Let vs def в clojure
Я хочу создать локальный экземпляр класса Java Scanner в программе clojure. Почему это не работает:
;gives me: count not supported on this type: Symbol
(let s (new Scanner "a b c"))
но он позволит мне создать глобальный экземпляр, подобный этому:
(def s (new Scanner "a b c"))
У меня создалось впечатление, что единственное различие было сфера, но, по-видимому, нет. В чем разница между let и def?
Ответы
Ответ 1
Проблема в том, что использование let
неверно.
Позволяет работать следующим образом:
(let [identifier (expr)])
Итак, ваш пример должен быть примерно таким:
(let [s (Scanner. "a b c")]
(exprs))
Вы можете использовать только лексические привязки, сделанные с помощью let в пределах области let (открывающий и закрывающий parens). Пусть просто создает набор лексических привязок. Я использую def для создания глобальной привязки и позволяет привязывать что-то, что я хочу, только в области let, поскольку он сохраняет чистоту. Они оба используют свои возможности.
ПРИМЕЧАНИЕ: (класс.) совпадает с (новый класс), это просто синтаксический сахар.
Ответ 2
LET не "делает лексическую привязку в текущей области", а "создает новую лексическую область со следующими связями".
(let [s (foo whatever)]
;; s is bound here
)
;; but not here
(def s (foo whatever))
;; s is bound here
Ответ 3
Правильный синтаксис:
(let [s (Scanner. "a b c")] ...)
Ответ 4
Упрощенный: def предназначен для глобальных констант, let для локальных переменных.
Ответ 5
Синтаксис для них различен, даже если значения связаны.
let отображает список привязок (пары значений имени), за которыми следуют выражения для оценки в контексте этих привязок.
def просто берет одну привязку, а не список, и добавляет ее в глобальный контекст.
Ответ 6
Вы можете придумать let
как синтаксический сахар для создания новой лексической области с помощью fn
, а затем применить ее немедленно:
(let [a 3 b 7] (* a b)) ; 21
; vs.
((fn [a b] (* a b)) 3 7) ; 21
Итак, вы можете реализовать let
с помощью простого макроса и fn
:
(defmacro fnlet [bindings & body]
((fn [pairs]
`((fn [[email protected](map first pairs)] [email protected]) [email protected](map last pairs)))
(partition 2 bindings)))
(fnlet [a 3 b 7] (* a b)) ; 21