binding - Clojure 中的 Let 与 Binding

标签 binding clojure let

我知道它们是不同的,因为一种可以设置 *compile-path* 而另一种则不能。但是,我需要帮助了解它们为何不同。

let 使用给定的绑定(bind)创建一个新作用域,但是 binding...?

最佳答案

let 为某个值创建一个词法作用域的不可变别名。 binding 为某些Var 创建动态范围的绑定(bind)。

动态绑定(bind)意味着 binding 表单内的代码以及该代码调用的任何代码(即使不在本地词法范围内)都将看到新的绑定(bind)。

给定:

user> (def ^:dynamic x 0)
#'user/x

binding 实际上为 Var 创建动态绑定(bind),但 let 仅使用本地别名隐藏 var:

user> (binding [x 1] (var-get #'x))
1
user> (let [x 1] (var-get #'x))
0

binding 可以使用限定名称(因为它在 Var 上运行),而 let 不能:

user> (binding [user/x 1] (var-get #'x))
1
user> (let [user/x 1] (var-get #'x))
; Evaluation aborted.
;; Can't let qualified name: user/x

let 引入的绑定(bind)是不可变的。 绑定(bind)引入的绑定(bind)是线程局部可变的:

user> (binding [x 1] (set! x 2) x)
2
user> (let [x 1] (set! x 2) x)
; Evaluation aborted.
;; Invalid assignment target

词法绑定(bind)与动态绑定(bind):

user> (defn foo [] (println x))
#'user/foo
user> (binding [x 1] (foo))
1
nil
user> (let [x 1] (foo))
0
nil

另请参阅Vars , let .

关于binding - Clojure 中的 Let 与 Binding,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1523240/

相关文章:

Clojure Luminus Migrations - 每个迁移文件只有一张表

unit-testing - 如何将单元测试添加到 Leiningen 项目?

clojure - 来自除 CL 之外的其他语言的 Clojure 功能概述

带有 let 的 JavaScript for 循环

binding - Clojure 中的变量作用域 + eval

android - 在kotlin中使用 'it'时我的变量名和 'let'有什么区别?

java - 将 java 类作为闭包绑定(bind)到 groovy 脚本中

c# - WPF Combobox Itemssource 是 Visibility Enum

objective-c - 手动绑定(bind) NSTableColumn(没有 NSArrayController)

forms - Spring 3 MVC 表单与 java.util.List 绑定(bind),包括表单错误和使用 bindingResult 进行验证