online - clojure vs scala
Clojure def vs defn para una funciĆ³n sin argumentos (4)
He escrito un programa en clojure pero algunas de las funciones no tienen argumentos. ¿Cuáles serían las ventajas de codificar funciones como "def" en lugar de "defn" sin argumentos?
(defn name ...) es simplemente una macro que se convierte en (def nombre (fn ...) de todos modos, no importa cuántos parámetros tenga. Así que es solo un atajo. Consulte (doc defn) para más detalles.
La forma especial def
crea un objeto Var identificado por un símbolo dado como su primer argumento. La identificación se crea asociando el símbolo dado con un Var en un mapa llamado espacio de nombres.
El Var contiene una referencia a algún valor , que podría expresarse (entre otros):
como una forma constante, que siempre evalúa su propio valor :
(def x 1) x ; => 1 ; x holds a reference to a number 1
como una forma de función, que al principio se evalúa a su valor resultante :
(def x (+ 2 2)) x ; => 4 ; x holds a reference to a number 4
como una forma de método Java, que al principio se evalúa a su valor resultante :
(def x (System/currentTimeMillis)) x ; => 1417811438904 ; x holds a reference to a number 1417811438904 x ; => 1417811438904 ; still the same number!
como una forma lambda (función anónima), que al principio se evalúa para un objeto de función :
(def x (fn [] (System/currentTimeMillis))) x ; => #<user$x user$x@4c2b1826> (x) ; function form, function evaluated ; => 1417811438904 (x) ; function form, function evaluated ; => 1417812565866
Hay una regla simple para todo lo anterior. En el caso de una forma especial def
una expresión S dada como su segundo argumento se evalúa recursivamente antes de crearse el enlace , de modo que el Var resultante se vincula al resultado de esta evaluación.
Incluso fn
se evalúa antes, pero su valor resultante es un objeto de función que contiene un código. Este código se ejecutará (y evaluará) cada vez que se llame a la función . Es por eso que hay diferentes resultados.
La macro defn
es como def
pero internamente crea una función anónima y luego le une un objeto Var. Su segundo argumento se convierte en un cuerpo de esta función y no se evalúa de una manera "regular". También se podría decir que se evalúa pero como una forma lambda: el resultado de la evaluación es un objeto de función, no el resultado de un cálculo instantáneo.
Entonces escribiendo:
(defn fun [] 1)
Es sinónimo de:
(def fun (fn [] 1))
def
s se evalúan una sola vez mientras que defn
s (con o sin argumentos) se evalúan (ejecutan) cada vez que se llaman. Entonces, si sus funciones siempre devuelven el mismo valor, puede cambiarlas a def
s, pero no de otra manera.
user=> (def t0 (System/currentTimeMillis))
user=> (defn t1 [] (System/currentTimeMillis))
user=> (t1)
1318408717941
user=> t0
1318408644243
user=> t0
1318408644243
user=> (t1)
1318408719361