【问题标题】:let vs def in clojure在clojure中让vs def
【发布时间】:2010-10-11 23:43:31
【问题描述】:

我想在 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有什么区别?

【问题讨论】:

    标签: lisp clojure let function


    【解决方案1】:

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

    let 是这样工作的:

    (let [identifier (expr)])
    

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

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

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

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

    【讨论】:

      【解决方案2】:

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

      (让 [s (foo 随便)] ;; s 绑定在这里 ) ;;但不是在这里 (def s (foo 随便)) ;; s 绑定在这里

      【讨论】:

      • 我明白了,有点像 C# 的 using 或 Python 的 with 但没有任何破坏(无论如何,这将是一种愚蠢的不可变状态)。
      【解决方案3】:

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

      【讨论】:

      • 不,这过于简单化了,而这恰恰导致了原始提问者的困惑。 LET 创建一个带有词法绑定的 new_block,而 DEF 只创建一个新的“全局”绑定。
      • 对我来说听起来不对。 Def 总是绑定到 Var,因此不是常量。命名空间绑定也可以更改,因此它们甚至不是一个常量。 Let 是一个常数,它根本无法更改或重新绑定。所以至少我会说:“def 用于全局变量,let 用于局部常量。
      【解决方案4】:

      正确的语法:

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

      【讨论】:

        【解决方案5】:

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

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

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

        【讨论】:

          【解决方案6】:

          您可以将let 视为使用fn 创建新词法范围然后立即应用它的语法糖:

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

          所以你可以用一个简单的宏和fn来实现let

          (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
          

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 2011-05-26
            • 2023-03-20
            • 1970-01-01
            • 2015-01-31
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2022-11-15
            相关资源
            最近更新 更多