Вопрос

Я хочу создать локальный экземпляр класса 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
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top