clojure - clojure 如何绑定可变参数?
问题描述
我是 Clojure 的新手。我曾经检查过以下源代码时出现了问题conj
:
(def conj
(fn ^:static conj
([] [])
([coll] coll)
([coll x] (clojure.lang.RT/conj coll x));4
([coll x & xs] ;1
(if xs ;2
(recur (clojure.lang.RT/conj coll x) (first xs) (next xs)) ;3
(clojure.lang.RT/conj coll x)))))
的源代码conj
显示它使用recur来实现该功能。这个源代码看起来很简单。我感到困惑的是它在确定递归是否需要继续时使用的条件。看起来它检查变量参数是否是nil
,但如果变量参数是nil
,它很快就会等同于conj
?的第三个“arity” 然后我尝试评估以下表达式:
user=> (conj [] 1 (next []))
[1 nil]
user=>
它正常工作并成功添加nil
到向量中。我知道clojure实际上包装nil
在一个列表中并将其传递给函数,但我不明白为什么recur
可以传递一个实数nil
?为什么clojure会识别并匹配正确的“arity”?
user=> (def my_conj
(fn [coll x & xs]
(println "xs is" xs)
(if xs
(recur (clojure.lang.RT/conj coll x) (first xs) (next xs))
(clojure.lang.RT/conj coll x))))
#'user/my_conj
user=> (my_conj [] 1 (next []))
xs is (nil)
xs is nil
[1 nil]
解决方案
好的,我很抱歉没有更早地意识到您遇到了我以前从未见过的 Clojure 行为的一个方面。今天我学到了一些关于 Clojure 的新东西,并且用了 10 年,这让我感到惊讶。
这是在官方 Clojure 文档的几句话中提到的 recur,这里:https ://clojure.org/reference/special_forms#recur
这是一个社区编写的示例和文档页面(因此不是“官方”),描述了具有可变参数的函数的这种递归行为:https ://clojuredocs.org/clojure.core/recur#example-55ff3cd4e4b08e404b6c1c7f
推荐阅读
- c# - 将 VirtualizingStackPanel 与 ScrollViewer 内的多个 ListBox 一起使用
- php - Mysqli 连接查询返回错误的 COUNT?
- excel - 在excel公式中按顺序用数字替换字母
- sonarqube - 代码覆盖率未在 Sonar Qube 中上传
- sql - 如何统计表中每一列的数据量
- elasticsearch - 按查询平均和分组 ElasticSearch
- react-native - React Native 组件意外卸载
- python - “numpy.ndarray”对象没有属性“add_patch”
- android-studio - 无法使用 gradle 插件 3.3 覆盖清单
- qt - 是否可以在没有 Mac 的情况下将 Qt 应用程序部署到 Mac OS?