Clojure';s funcs don';通过列表发送时,似乎无法按预期工作
在Clojure REPL中,这个表达式Clojure';s funcs don';通过列表发送时,似乎无法按预期工作,clojure,Clojure,在Clojure REPL中,这个表达式 ( #(for [x %] (+ 100 (second x))) ['(+ 38) '(+ 48)] ) 按预期生产(138 148台) 但是这个 ( #(for [x %] ((first x) 100 (second x))) ['(+ 38) '(+ 48)] ) 生产(38 48),这似乎真的很奇怪 两个表达式真的应该产生相同的结果! 我错过了什么? 我会很感激任何能解开这个谜团的想法 顺便说一句,我尝试使用“apply(firstx)”
( #(for [x %] (+ 100 (second x))) ['(+ 38) '(+ 48)] )
按预期生产(138 148台)
但是这个
( #(for [x %] ((first x) 100 (second x))) ['(+ 38) '(+ 48)] )
生产(38 48),这似乎真的很奇怪
两个表达式真的应该产生相同的结果!
我错过了什么?
我会很感激任何能解开这个谜团的想法
顺便说一句,我尝试使用“apply(firstx)”并将其余参数打包到一个列表中,但这似乎并不重要。同样意想不到的结果又回来了
另外,为了验证+确实从输入中得到解析,我将以下内容提供给REPL
( #(for [x %] (resolve (first x) )) '((+ 38) (+ 48)) )
产生
(#'clojure.core/+ #'clojure.core/+) as expected.
在这种情况下,+
是一个符号,而不是一个函数,因为它已在列表中引用。但是,符号被定义为在作为函数调用时进行地图查找(与关键字相同)。所以('+10038)
与(get 100'+38)
相同。最后一个论点是“如果你在地图上找不到我想要的东西,就把它还给我”。由于100
不是映射,+
使用该参数作为返回值
要让它实现您想要的功能,您有两个选择:
+
得到适当的解析
( #(for [x %] ((first x) 100 (second x))) [[+ 38] [+ 48]] )
+
函数而不是+
符号
( #(for [x %] ((resolve (first x)) 100 (second x))) ['(+ 38) '(+ 48)] )
当您引用列表时,如
”(+38)
,列表中的任何项目都不会被计算。因此,+
只是一个符号,而不是对clojure.core中加法函数的引用
将此符号作为函数调用的结果有点混乱,特别是因为您恰好使用两个参数调用它。@mange已经解释了原因:将符号作为函数调用会尝试在第一个参数中查找符号,当查找失败时,将(可选)第二个参数作为默认参数返回:
('x) ; throws ArityException
('x 1) ;=> nil
('x 1 2) ;=> 2
('x 1 2 3) ; throws ArityException
您有几个选择:
[+38]
。向量的所有元素都会被计算(如在一个不带引号的列表中),但向量只是一个数据结构,而不是函数调用的语法(如列表)resolve
函数查找符号引用的函数。请注意,resolve
在当前名称空间中查找符号。因此,如果引用列表的构造和函数的调用发生在不同的名称空间中,这可能会导致令人惊讶的结果(如果您恰好在不同的名称空间中对同一符号有两个不同的定义)`(~+38)
+1.详细说明。由于问题实际上是在引用中,所以您实际上不需要更改数据结构,列表也可以工作。您只需删除文字形式,然后使用例如
(list+38)
谢谢您的精彩回答。我用作输入的列表列表是使用分区生成的,所以我更喜欢使用这种形式的输入本身。在我发布这个问题时,我确实转换成了向量,因为我注意到它生成了求值的func(REPL使用#^来显示它),但是解析(第一个x)的工作让我困惑,因为我预期(第一个x)调用会产生错误,但事实并非如此。(get 100'+38)帮助我解开了这一谜团。感谢您的深刻见解,尤其是语法引用示例。我用作输入的列表列表是使用分区生成的。在我发布这个问题时,我确实转换成了向量,因为我注意到它生成了求值的func(REPL使用#^来显示它),但是解析(第一个x)的工作让我困惑,因为我预期(第一个x)调用会产生错误,但事实并非如此。曼奇和你的回答帮我解决了这个问题。
('x) ; throws ArityException
('x 1) ;=> nil
('x 1 2) ;=> 2
('x 1 2 3) ; throws ArityException