Clojure 中的 let 与 def

发布于 2024-07-14 21:08:25 字数 338 浏览 8 评论 0原文

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

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

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

(def s (new Scanner "a b c"))

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

I want to make a local instance of a Java Scanner class in a clojure program. Why does this not work:

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

but it will let me create a global instance like this:

(def s (new Scanner "a b c"))

I was under the impression that the only difference was scope, but apparently not. What is the difference between let and def?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(6

淡淡の花香 2024-07-21 21:08:25

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

let 的工作方式如下:

(let [identifier (expr)])

因此,您的示例应该如下所示:

(let [s (Scanner. "a b c")]
  (exprs))

您只能在 let 范围内使用由 let 进行的词法绑定(左括号和右括号)。 让我们创建一组词法绑定。 我使用 def 来进行全局绑定,并使用 let 来绑定我只想要在 let 范围内的东西,因为它可以保持事物的干净。 它们都有各自的用途。

注意: (Class.) 与 (new Class) 相同,它只是语法糖。

The problem is that your use of let is wrong.

let works like this:

(let [identifier (expr)])

So your example should be something like this:

(let [s (Scanner. "a b c")]
  (exprs))

You can only use the lexical bindings made with let within the scope of let (the opening and closing parens). Let just creates a set of lexical bindings. I use def for making a global binding and lets for binding something I want only in the scope of the let as it keeps things clean. They both have their uses.

NOTE: (Class.) is the same as (new Class), it's just syntactic sugar.

染年凉城似染瑾 2024-07-21 21:08:25

LET 不是“在当前范围内创建词法绑定”,而是“使用以下绑定创建新的词法范围”。

(let [s (foo whatever)]
  ;; s is bound here
  )
;; but not here
(def s (foo whatever))
;; s is bound here

LET is not "make a lexical binding in the current scope", but "make a new lexical scope with the following bindings".

(let [s (foo whatever)]
  ;; s is bound here
  )
;; but not here
(def s (foo whatever))
;; s is bound here
原谅我要高飞 2024-07-21 21:08:25

简化:def用于全局常量,let用于局部变量。

Simplified: def is for global constants, let is for local variables.

吻安 2024-07-21 21:08:25

正确的语法:

(let [s (Scanner. "a b c")] ...)

Correct syntax:

(let [s (Scanner. "a b c")] ...)
无悔心 2024-07-21 21:08:25

即使含义相关,它们的语法也不同。

let 接受一个绑定列表(名称值对),后跟要在这些绑定的上下文中计算的表达式。

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

The syntax for them is different, even if the meanings are related.

let takes a list of bindings (name value pairs) followed by expressions to evaluate in the context of those binding.

def just takes one binding, not a list, and adds it to the global context.

留一抹残留的笑 2024-07-21 21:08:25

您可以将 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

You could think of let as syntactic sugar for creating a new lexical scope with fn then applying it immediately:

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

So you could implement let with a simple macro and 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
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文