Clojure中为何(map ff `(inc))返回(nil)而非预期的1?
问题根因
你遇到的问题核心是语法引号(反引号)的求值特性导致的,具体差异如下:
- 单独执行
(ff inc)时,inc会被Clojure的reader直接求值为clojure.core下对应的函数值,传入ff后执行(f 0)等价于(inc 0),正常返回1 - 执行
(map ff(inc))时,语法引号包裹的列表不会对内部元素求值,你传入的列表元素不是inc函数,而是*符号类型的clojure.core/inc`*
你可以通过以下代码验证两类值的差异:
;; 直接调用inc的类型为函数 user=> (type inc) clojure.core$inc ;; 语法引号列表的第一个元素类型为符号 user=> (type (first `(inc))) clojure.lang.Symbol
当符号作为函数调用时,Clojure会默认将其当做属性查找函数,执行(符号 0)等价于查找目标对象0上对应符号的属性,最终找不到匹配结果返回nil,所以map的执行结果是(nil)。
修复方法
要拿到预期的返回结果,可以选择以下任意一种写法:
- 直接构造包含函数值的列表,不需要用语法引号包裹
user=> (map ff (list inc)) (1) - 在语法引号内用
~对inc强制求值user=> (map ff `(~inc)) (1) - 先对符号求值拿到函数再执行
user=> (map #(ff (eval %)) `(inc)) (1)
内容的提问来源于stack exchange,提问作者aQua
相关产品推荐
相关产品推荐

