Подтвердить что ты не робот

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?

4b9b3361

Ответ 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