let vs def en clojure


Quiero hacer una instancia local de una clase Java Scanner en un programa clojure. Por qué esto no funciona:

; gives me:  count not supported on this type: Symbol 
(let s (new Scanner "a b c"))

Pero me permitirá crear una instancia global como esta:

(def s (new Scanner "a b c"))

Tenía la impresión de que la única diferencia era el alcance, pero aparentemente no. ¿Cuál es la diferencia entre let y def?

Author: Micah Elliott, 2009-03-08

6 answers

El problema es que su uso de let es incorrecto.

Que funcione así:

(let [identifier (expr)])

Así que tu ejemplo debería ser algo como esto:

(let [s (Scanner. "a b c")]
  (exprs))

Solo puede usar las encuadernaciones léxicas hechas con let dentro del alcance de let (los paréntesis de apertura y cierre). Let acaba de crear un conjunto de enlaces léxicos. Uso def para hacer un enlace global y lets para vincular algo que quiero solo en el alcance del let, ya que mantiene las cosas limpias. Ambos tienen sus usos.

NOTA: (Clase.) es lo mismo que (nueva clase), es solo azúcar sintáctico.

 51
Author: Rayne,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2011-12-29 01:07:19

LET no es "hacer un enlace léxico en el ámbito actual", sino "hacer un nuevo ámbito léxico con los siguientes enlaces".

(let [s (foo whatever)]
  ;; s is bound here
  )
;; but not here
(def s (foo whatever))
;; s is bound here
 32
Author: Svante,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2009-03-09 15:58:27

Sintaxis correcta:

(let [s (Scanner. "a b c")] ...)
 11
Author: ayrnieu,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2009-03-08 00:29:06

Simplificado: defes para constantes globales, let es para variables locales.

 9
Author: Marko,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2009-03-11 17:33:57

La sintaxis para ellos es diferente, incluso si los significados están relacionados.

Let toma una lista de enlaces (pares de valores de nombre) seguida de expresiones para evaluar en el contexto de esos enlaces.

Def solo toma un enlace, no una lista, y lo agrega al contexto global.

 3
Author: MarkusQ,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2009-03-08 00:30:26

Se podría pensar en let como azúcar sintáctico para crear un nuevo ámbito léxico con fn y luego aplicarlo inmediatamente:

(let [a 3 b 7] (* a b))  ; 21
; vs.
((fn [a b] (* a b)) 3 7) ; 21

Por lo que podría implementar let con una macro simple y fn:

(defmacro fnlet [bindings & body]
  ((fn [pairs]
    `((fn [~@(map first pairs)] ~@body) ~@(map last pairs)))
   (partition 2 bindings)))

(fnlet [a 3 b 7] (* a b)) ; 21
 1
Author: d11wtq,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-12-08 07:56:47