пусть против def в ближайшем будущем
Вопрос
Я хочу создать локальный экземпляр класса 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
?
Решение
Проблема в том, что вы используете let
неправильно.
Пусть работает так:
(let [identifier (expr)])
Итак, ваш пример должен выглядеть примерно так:
(let [s (Scanner. "a b c")]
(exprs))
Вы можете использовать только лексические привязки, сделанные с помощью let, в области let (открывающая и закрывающая части). Пусть просто создает множество лексических привязок. Я использую def для создания глобальной привязки, а let - для привязки чего-то, что мне нужно, только в области действия let, поскольку она сохраняет чистоту. У них обоих есть свое применение.
ПРИМЕЧАНИЕ. (Класс.) такой же, как (новый класс), это просто синтаксический сахар.
Другие советы
LET не «создает лексическую привязку в текущей области видимости», но «создает новую лексическую область видимости со следующими привязками».
(let [s (foo whatever)] ;; s is bound here ) ;; but not here
(def s (foo whatever)) ;; s is bound here
Правильный синтаксис:
(let [s (Scanner. "a b c")] ...)
Упрощено: def для глобальных констант, let для локальных переменных.
Синтаксис для них различен, даже если значения связаны.
let принимает список привязок (пары имя-значение), за которыми следуют выражения для оценки в контексте этой привязки.
def просто берет одну привязку, а не список, и добавляет ее в глобальный контекст.
Вы можете думать о 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 [~@(map first pairs)] ~@body) ~@(map last pairs)))
(partition 2 bindings)))
(fnlet [a 3 b 7] (* a b)) ; 21