Clojure字符串到符号评估错误的结果

时间:2016-02-21 20:56:22

标签: clojure

user=> ((symbol "or") true false)
false
user=> (or true false)
true

为什么第一个表单评估为false?我想这两种输入形式是等价的。

奇怪的是,颠倒参数的顺序是有效的:

user=> ((symbol "or") false true)
true
user => (or false true)
true

1 个答案:

答案 0 :(得分:4)

评估列表(or true false)时,Clojure首先评估第一项。在这种情况下,第一个项目是一个命名宏的符号,因此Clojure扩展宏并评估结果数据结构(在这种情况下为let形式)。

另一方面,当您评估列表((symbol "or") true false)时,Clojure会再次首先评估第一个项目,但在这种情况下,第一个项目是另一个列表! 列表的第一个元素是符号symbol,它命名一个函数,因此Clojure使用参数"or"调用该函数,再次生成符号or 。换句话说,您基本上在评估('or true false)

这里有一个问题:Clojure不接受它刚刚评估的东西,然后再去评估它。相反,因为它首先不是符号,所以Clojure会对它进行评估,然后假设它必须是一个函数。这是一个功能吗?的确,答案是肯定的!

user> (ifn? 'do)
;=> true

这里有点棘手。 invoke类上Symbol的实现与invoke类上Keyword的实现相同:它假设第一个参数是一个地图并试图查看本身在那张地图上。如果您提供第二个参数,它将使用它作为默认值。

现在,很明显,如果您尝试将true视为地图并在该地图中查找符号or,您将找不到任何内容。所以Clojure有助于返回您提供的默认值:false。您可以在第二个参数点中添加任何您想要的值,只要您的符号在第一个参数中不作为键存在,您将始终返回默认值。