2011-10-17 9 views
5

Defino una función, que toma dos parámetros: mapa y una clave. La clave se hace referencia a partir de la descomposición de parámetros mapadefn vs. let respecto a la descomposición

(defn myfunc [{v k} k] 
    v) 

cuando llamo:

(myfunc {:a 10} :a) 

Sorprendentemente produce esperado resultado: 10

cosa similar en el let:

(let [{v k} {:a 10} k :a] v) 

falla, porque k no está definido en momento, cuando se evalúa la primera parte

Mi pregunta es: ¿por qué la descomposición dentro de los parámetros de función se comporta de manera diferente en comparación con la descomposición en let expresiones?

Respuesta

3

Macroexpanding forma defn consigo el equivalente de esta (cosas .withMeta eliminado y volver a formatear):

(def myfunc 
    (fn* myfunc 
     ([p__11393 k] 
      (let* [map__11394 p__11393 
       map__11394 (if (seq? map__11394) 
           (apply hash-map map__11394) 
           map__11394) 
       v   (get map__11394 k)] 
       v)))) 

Así que aquí podemos ver que el mapa {v k} es, de hecho, la primera asignada a una variable local p__11393. Luego, la declaración if prueba si esa variable es de hecho una secuencia y la convierte en un hash-map si es así, de lo contrario la deja tal como está. Es importante destacar que el valor asignado a k se busca en el mapa después de todo esto sucede, por lo tanto, esto funciona sin error (y también si :a no estaba en el mapa, get devuelve nil en ese caso).

Por otro lado macroexpanding forma let me sale

(let* 
    [map__11431 
    {:a 10} 
    map__11431 
    (if (seq? map__11431) (apply hash-map map__11431) map__11431) 
    v 
    (get map__11431 k) 
    k 
    :a] 
    v) 

y aquí podemos ver que v obtiene el resultado de (get map__11431 k), pero k no está definido en este punto, sin embargo, de ahí el error.

+0

Ahora la pregunta es, si tal diferencia tiene que ser considerada como un error o como una característica ... – aav

+0

diría si uno sabe que la desestructuración ocurre dentro del cuerpo de la función, no es sorprendente, por lo tanto, no es un error. Pero creo que este hecho debería explicarse mejor en los lugares apropiados; si mal no recuerdo, la Alegría de Clojure, por ejemplo, no consigue entrar realmente en esto. – Paul

+0

lo que es interesante (pero no sorprendente) que su voluntad no funcione: (defn myfunc [{v k} {k: k1}] v) – aav

0

Ésta no es una respuesta completa, pero el siguiente sí funciona:

user=> (defn myfunc [{v k} k] v) 
#'user/myfunc 
user=> (myfunc {:a 10} :a) 
10 
user=> (let [k :a {v k} {:a 10}] v) 
10 
user=> 
+0

esto, por supuesto, funcionará, porque * k * se define antes que cualquier otra cosa – aav

Cuestiones relacionadas