在Clojure中,函数、引用函数和井号引用函数之间的区别

22
在Clojure中,我想知道以下三者之间的区别。
(println (map + '(1 2 3) '(4 5 6))) 

(println (map '+ '(1 2 3) '(4 5 6))) 

(println (map #'+ '(1 2 3) '(4 5 6))) 

结果是

(5 7 9) 

(4 5 6) 

(5 7 9) 

我不理解第二个的行为。

我感觉第一个和第三个在Clojure中是相同的,这是Lisp-1,并且不区分评估变量和同名函数。

这可能是一个基础问题,但似乎没有足够的信息。请教一下我。

谢谢。


2
顺便提一下,在Clojure中,用向量来描述文字序列是惯用法,而不是引用列表。 - Alex Taggart
1个回答

35

关于第三种情况,与通用 Lisp 不同的是,#'+ 不能被理解为 (function +) 并且不指向函数命名空间中符号 + 的值,因为 Clojure 没有函数命名空间。相反,它被理解为 (var +) 并且指向被称作 +var。应用一个 var 和应用存储在该 var 中的值是一样的。

在第二种情况中,你反复将一个符号应用于一对数字。这是偶然有效的。将一个符号应用于一个映射相当于索引该映射:

user> ('a {'a 1, 'b 2, 'c 3, '+ 4})
1
user> ('+ {'a 1, 'b 2, 'c 3, '+ 4})
4
如果你提供第二个参数,那么它将被用作默认值,以防在地图中找不到匹配的键:
user> ('+ {'a 1, 'b 2, 'c 3} 4)
4

每次迭代中,您都将符号 + 应用于一对数字,由于数字不是映射,因此不包含 + 作为键,因此第二个参数将作为失败匹配的默认值返回。

user> ('+ 'foo 4)
4
user> ('+ {} 4)
4
user> ('+ 1 4)
4

1
很棒的答案。对于不太明显的行为进行了清晰的解释。谢谢。 - sw1nn
1
非常感谢你,马蒂亚斯。我现在明白了#'的含义。我之前没有意识到Var,也忽略了它,但这次我能更深入地理解它。我也能理解第二段代码的行为。谢谢。 - jolly-san

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