理解Clojure绑定语法

5

我正在学习Clojure,读到了关于doseq的内容,发现官方Clojure文档中有以下示例:

(doseq [x [-1 0 1]
        y [1  2 3]] 
  (prn (* x y)))

我的困惑在于表达式[x [-1 0 1] y [1 2 3]]。这是一个绑定表达式吗?我尝试了一些Google搜索,但没有找到任何描述这种形式的文档。能否有人帮助我理解Clojure中绑定表达式的各种语法表示?

2
clojuredocs.org并不是Clojure文档的官方来源。它是用户贡献的各种质量的示例。该页面上唯一官方的东西是doseq的docstring,它告诉你阅读for的docstring以了解它的工作原理。我同意如果doseq有自己全面的文档会更好,但至少它指向了正确的阅读材料。 - amalloy
2个回答

8
这是一个 "绑定表单",它将表达式的值依次绑定到名称x中。因此,俗称为将名称绑定到值的表达式。这是“解构绑定形式”的一部分,它将名称绑定到复合值(例如列表或映射)的部分。
术语“绑定”而不是“设置”有助于传达这样做与其他编程语言中设置变量之间的区别。该名称附加到该值,以使doseq内部的表单运行所需的时间,然后释放该名称以附加到另一个值。
Clojure提供任意结构绑定,在大多数分配名称(绑定符号)的语言中的任何值的任何部分上命名。
(doseq [[x1 x2] [[-1 -1] [0 0] [1 1]]
        y [1  2 3]] 
  (prn (* x1 x2 y)))

虽然它看起来更深入地查看数据并为第一个向量中的每个项目分配两个值的名称(并假定每个值都有两个数字),但它也是绑定表达式。我非常喜欢这篇关于解构/绑定的教程


"没错,我会将它转换为至少包含两个数字的序列嵌套序列。" - Arthur Ulfeldt
感谢您提供这么详细的解释,非常有帮助! - Prahalad Deshpande

2

这就像在Java中的嵌套for循环。您还可以手动进行嵌套:

(dotest
  (newline)
  (println "version 1")
  (doseq [x [1 2]
          y [:a :b :c]]
    (println  x y))

  (newline)
  (println "version 2")
  (doseq [x [1 2]]
    (doseq [y [:a :b :c]]
      (println x y))))

with results:
version 1
1 :a
1 :b
1 :c
2 :a
2 :b
2 :c

version 2
1 :a
1 :b
1 :c
2 :a
2 :b
2 :c

请注意,doseq总是返回nil,只适用于生成副作用(如向屏幕打印)。 for表达式的行为类似,但返回一个(惰性)值序列(请注意,在每个循环中我们生成一个向量[x y])。
(newline)
(println "For generates a (lazy) sequence:"
  (for [x [1 2]
        y [:a :b :c]]
    [x y]))

结果如下:

For generates a (lazy) sequence: ([1 :a] [1 :b] [1 :c] [2 :a] [2 :b] [2 :c])

+1 表示提供了其他形式。然而,这篇文章并没有真正回答我的问题。目前我更关心 Clojure 绑定语法而不是其他形式,因为我正在学习这门语言,理解语法是我的首要任务。 - Prahalad Deshpande

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接