在clojure中让vs

我想在clojure程序中创build一个Java Scanner类的本地实例。 为什么这不起作用:

;gives me: count not supported on this type: Symbol (let s (new Scanner "abc")) 

但它会让我创build一个像这样的全局实例:

 (def s (new Scanner "abc")) 

我的印象是,唯一的区别是范围,但显然不是。 let和def有什么区别?

问题是你使用let是错误的。

让这样的作品:

 (let [identifier (expr)]) 

所以你的例子应该是这样的:

 (let [s (Scanner. "abc")] (exprs)) 

你只能使用在let的范围内(let的开始和结束的parens)所做的词法绑定。 只需创build一组词汇绑定。 我使用def来进行全局绑定,并且只允许在let的范围内绑定我想要的东西,因为它使事情保持干净。 他们都有他们的用途。

注意:(类)与(新类)相同,只是语法上的糖。

LET不是“在当前范围内进行词汇绑定”,而是“以下面的绑定形成新的词汇范围”。

 (让[s(foo无论)]
   ;; 这里是绑定的
   )
 ;; 但不在这里
 (def s(foo whatever))
 ;; 这里是绑定的

正确的语法:

 (let [s (Scanner. "abc")] ...) 

简化: def是全局常量, let是局部variables。

它们的语法是不同的,即使意义是相关的。

让我们获取绑定 (名称值对)后跟expression式来评估这些绑定的上下文。

def只需要一个绑定,而不是一个列表,并将其添加到全局上下文中。

你可以考虑let语法糖当作fn创build一个新的词法作用域,然后马上应用:

 (let [a 3 b 7] (* ab)) ; 21 ; vs. ((fn [ab] (* ab)) 3 7) ; 21 

所以你可以实现let一个简单的macros和fn

 (defmacro fnlet [bindings & body] ((fn [pairs] `((fn [~@(map first pairs)] ~@body) ~@(map last pairs))) (partition 2 bindings))) (fnlet [a 3 b 7] (* ab)) ; 21