2012-02-27 10 views
5

Esiste la possibilità di verificare se qualcosa è una funzione parziale in Clojure?Come posso verificare se la funzione è parziale?

Sarebbe meglio avere qualcosa come (partial? (partial + 10))?

Grazie in anticipo

+2

Solo curioso: perché ne hai bisogno? – viebel

+1

@Yehonathan Sto implementando Shen in Clojure e lì devo distinguere tra funzioni normali e funzioni parziali. (A causa di decisioni di progettazione). –

+0

Che cos'è Shen? Inoltre, che dire della funzione anonima creata tramite '#()'? – viebel

risposta

16

No, perché le funzioni create da parziale sono solo le funzioni "normali". Si potrebbe comunque utilizzare alcuni metadati per esso, come questo:

(defn partial2 [f & more] 
    (with-meta (apply partial f more) {:partial true})) 

(def partial-plus (partial2 + 1 2)) 

(meta partial-plus) ;;=> {:partial true} 

non hanno veramente pensato alle conseguenze di questo approccio anche se ...

Kotarak si avvicinò con una soluzione più bello che funziona, ma non sempre. Ad esempio prendere questo:

(partial? (partial + 1)) ;;=> true 
(partial? (partial + 1 2)) ;;=> false 

funziona:

(defn partial? [f] 
    (let [[fst snd] (-> (class f) (.getName) (string/split #"\$"))] 
    (= ["clojure.core" "partial"] [fst snd]))) 

con stringa/split essendo la funzione split da clojure.string (1.3) o clojure.contrib.str-utils2 (1.2).

+0

clojure.string è anche in 1.2. –

+0

Probabilmente dovresti testare anche per 'clojure.core', non solo' partial'. – kotarak

+0

Buon punto, risolto. –

2

Le funzioni create da partial sono solo funzioni normali, ma se si è decisi a farlo, forse qualcosa del genere potrebbe essere d'aiuto? :

(defn partial? 
    [f] 
    (clojure.contrib.string/substring? "partial" (str (class f)))) 

Disclaimer: Non so se qualcosa del genere sia infallibile.

5

È possibile con un hack.

user=> (let [partial-classes (map class [(partial + 1) 
             (partial + 1 2) 
             (partial + 1 2 3) 
             (partial + 1 2 3 4)])] 
     (defn partial? 
      [x] 
      (some #(instance? % x) partial-classes))) 
#'user/partial? 
user=> (partial? (partial - 1)) 
true 
user=> (partial? (partial - 1 2)) 
true 
user=> (partial? (partial - 1 2 3)) 
true 
user=> (partial? (apply partial - 1 2 [3 4 5])) 
true 

EDIT: fissato in base al commento di Michiel. Che devi sapere le viscere di partial conferma la natura hacky.

Problemi correlati