关于map、apply函数与引用表达式向量的求值逻辑困惑求解
Clojure中
apply println与引用表达式的求值逻辑解析 第一个例子的问题根源
你执行的代码(map #(apply println %) ['(+ 1 1)])输出+ 1 1而非预期的2,核心是对apply和println的行为理解偏差,拆解求值步骤如下:
- 先求值向量
['(+ 1 1)]:其中'(+ 1 1)是引用表达式,它的作用就是阻止内部表达式求值,直接返回列表数据(+ 1 1)——也就是符号+、数字1、数字1组成的列表,而不是计算结果2。 map遍历这个向量,把列表(+ 1 1)传给匿名函数#(apply println %)。apply println的作用是把传入的序列展开成println的参数列表,也就是等同于调用(println '+ 1 1)。而println的本质是输出参数的字面形式,它根本不会对传入的参数做求值计算——所以就直接把+、1、1打印出来了。
你之前误以为apply会让列表再次求值,但实际上apply只是帮你把序列拆成参数,求值逻辑和直接调用println是一样的。如果想要得到2,需要显式调用eval来触发表达式求值,比如:
(map #(println (eval %)) ['(+ 1 1)])
这段代码里eval会把列表(+ 1 1)当成表达式求值得到2,再传给println打印。
补充示例的逻辑验证
再看你给出的第二个例子:(map #(apply println %) [(list "a" "b") (list "c" "d")]),它的求值流程完全符合上面的逻辑:
(list "a" "b")求值后得到列表("a" "b"),(list "c" "d")求值后得到("c" "d")。apply println把这两个列表分别展开成(println "a" "b")和(println "c" "d"),println直接打印参数本身,所以输出a b和c d。
关键知识点总结
- 引用
'的核心作用:将表达式转为数据,阻止其被求值。 apply的核心作用:把序列展开为目标函数的参数列表,不会触发额外的求值操作——所有参数的求值在传入apply之前就完成了。println的行为:仅输出参数的字符串表示,不对参数做任何求值计算。
内容的提问来源于stack exchange,提问作者mpettis
相关产品推荐
相关产品推荐

