【问题标题】:Clojure example: I cannot comprehend what are the values of "%2" and "%1" in "(str %2 %1)"Clojure 示例:我无法理解 "(str %2 %1)" 中 "%2" 和 "%1" 的值是什么
【发布时间】:2014-12-07 21:30:31
【问题描述】:
我正在做一些关于clojure(初学者)的研究,我发现了一个例子,问题是我无法理解“(str %2 %1)”中“%2”和“%1”的值是什么。完整示例如下:
(defn my-reverse [s]
(let [lst (list)]
(reduce #(str %2 %1)
(mapcat #(conj lst %1) s))))
我知道 %2 指的是第二个参数,但我只看到 "#(str %2 %1)" 之后的一个参数值,它是 mapcat 表达式,应该是 %1。
感谢您的帮助。希望我已经清楚了。
【问题讨论】:
标签:
clojure
functional-programming
lisp
【解决方案1】:
#(str %2 %1) 是reduce 的第一个参数:
(减少 f coll)
f 应该是 2 个参数的函数...返回应用的结果
f 应用于 coll 中的前 2 个项目,然后将 f 应用于该结果和
第三项等。
所以f 的一个参数是要处理的当前值(集合coll 中的当前项),另一个是到目前为止的累积结果。
在这种情况下,(mapcat #(conj lst %1) s) 的结果是集合。在第一次调用#(str %2 %1) 时,参数%1 和%2 将是该集合中的前两个值。下次将使用该结果和集合中的第三个值调用它。从而构建一个包含(mapcat #(conj lst %1) s) 产生的所有值的字符串。
【解决方案2】:
符号#(...) 是创建匿名函数的简写。
创建匿名函数的较长方法是 lambda 表达式,由 clojure 中的符号 fn 引入:
(fn [arg1 arg2]
(do-something-with arg1 arg2))
简写可以让您省略 fn 和参数列表,而使用默认参数名称:
#(do-something-with %1 %2)
所以,你的例子扩展了:
#(str %2 %1)
扩展到
(fn [thing1 thing2]
(str thing2 thing1))
和
#(conj lst %1)
扩展到
(fn [thing]
(conj lst thing))