Translate

sábado, 2 de enero de 2021

Primeros pasos con Clojure, parte 16

Seguimos con Clojure... 

 let vincula símbolos a valores en un "ámbito léxico". Un alcance léxico crea un nuevo contexto para los nombres, anidado dentro del contexto circundante. Los nombres definidos en un let tienen prioridad sobre los nombres en el contexto externo.


;;      bindings     name is defined here

;;    ------------  ----------------------

(let  [name value]  (code that uses name))


Cada let puede definir 0 o más enlaces y puede tener 0 o más expresiones en el cuerpo.


(let [x 1

      y 2]

  (+ x y))


Esta expresión let crea dos enlaces locales para x e y. La expresión (+ x y) está en el ámbito léxico de let y resuelve x en 1 ey en 2. Fuera de la expresión let, x e y no tendrán un significado continuo, a menos que ya estén vinculados a un valor.


(defn messenger [msg]

  (let [a 7

        b 5

        c (clojure.string/capitalize msg)]

    (println a b c)

  ) ;; end of let scope

) ;; end of function


La función  messenger toma un argumento msg. Aquí, defn también crea un alcance léxico para msg; solo tiene significado dentro de la función.

Dentro de ese alcance de función, let crea un nuevo alcance para definir a, b y c. Si intentáramos usar una expresión después de let, el compilador reportaría un error.

Clojure tiene clusuras, la expresión fn crea una "clausura". La clausura existe en  el ámbito léxico circundante (como msg, a, boc arriba) y captura sus valores más allá del ámbito léxico.


(defn messenger-builder [greeting]

  (fn [who] (println greeting who))) ; closes over greeting


;; greeting provided here, then goes out of scope

(def hello-er (messenger-builder "Hello"))


;; greeting value still available because hello-er is a closure

(hello-er "world!")

;; Hello world!