2012-02-27 11 views
5

¿Existe la posibilidad de comprobar si alguna cosa es una función parcial en Clojure?¿Cómo puedo verificar si la función es parcial?

Sería mejor tener algo como (partial? (partial + 10))?

Gracias de antemano

+2

Simplemente curioso: ¿por qué lo necesitas? – viebel

+1

@Yehonathan Estoy implementando Shen en Clojure y allí necesito diferenciar entre funciones normales y funciones parciales. (Debido a decisiones de diseño). –

+0

¿Qué es Shen? Además, ¿qué ocurre con la función anónima creada a través de '#()'? – viebel

Respuesta

16

No, porque las funciones creadas por parciales son sólo funciones "normales". No obstante, usted podría utilizar algunos metadatos para que, de esta manera:

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

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

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

no he pensado en las consecuencias de este enfoque, aunque ...

Kotarak se le ocurrió una solución más agradable que funciona, pero no siempre. Por ejemplo tomar esta:

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

esto funciona:

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

con la cadena/split ser la función de división de clojure.string (1.3) o clojure.contrib.str-utils2 (1.2).

+0

clojure.string está en 1.2 también. –

+0

Probablemente deberías probar también para 'clojure.core', no solo' partial'. – kotarak

+0

Buen punto, lo arregló. –

2

Las funciones creadas por parcial son solo funciones normales, pero si está empeñado en ello, ¿podría ayudar algo como esto? :

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

Descargo de responsabilidad: No sé si algo así es a prueba de tontos.

5

Puedes hacerlo con un truco.

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: fija de acuerdo con el comentario de Michiel. Que tengas que saber las entrañas de partial confirma la naturaleza hacky.

Cuestiones relacionadas