Clojure에서 대를 let하자
문제
나는 자바의 로컬 인스턴스를 만들고 싶다 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 [s (foo whatever)] ;; s is bound here ) ;; but not here
(def s (foo whatever)) ;; s is bound here
올바른 구문 :
(let [s (Scanner. "a b c")] ...)
쉽게 한: 데프 글로벌 상수를위한 것입니다. 허락하다 로컬 변수입니다.
의미가 관련되어 있어도 그들에 대한 구문은 다릅니다.
a 바인딩 목록 (이름 값 쌍) 다음과 같은 바인딩의 맥락에서 평가하기위한 표현식이 뒤 따릅니다.
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