我目前正在阅读“Clojure 的乐趣”一书,第 2 版。 在第 7 章“函数式编程”中,我遇到了以下用于描述函数组合的函数。
(defn fnth [n]
(apply comp
(cons first
(take (dec n) (repeat rest)))))
((fnth 5) '[a b c d e])
;=> e
我不完全了解该函数的机制。
尝试在不使用 comp
的情况下重现内部作用域,该函数会生成一个重复列表:
(take (dec 5) (repeat (rest '[a b c d e])))
;=> ((b c d e) (b c d e) (b c d e) (b c d e))
使用 first
将 comp
附加到重复列表有什么意义?
这也是输入 comp
的函数列表的最后一部分吗?
(first (take (dec 5) (repeat (rest '[a b c d e]))))
=> (b c d e)
先谢谢你!
答案 0 :(得分:5)
fnth
函数的工作原理是构造 (first rest rest ... rest)
形式的序列,即 first
后跟 n - 1 rest
s。然后通过 apply
ing comp
将它们组合成一个函数。对于(fnth 5)
,这是
(apply comp (first rest rest rest rest))
当在向量 [a b c d e]
上调用结果函数时,结果应用程序是
(first (rest (rest (rest (rest [a b c d e])))))
即输入序列第 4 个尾部的第一个元素。
您尝试的重建只调用 rest
一次,然后 reapeat
返回返回的序列。
答案 1 :(得分:5)
这个 fnth
不(本身)返回集合的第 n 个项目,而是生成一个函数来这样做。
它应该产生什么函数来获得第一个项目?
(defn nth-1 [coll]
(first coll))
它应该产生什么函数来获得第二个项目?
(defn nth-2 [coll]
(first (rest coll)))
它应该产生什么函数来获得第三个项目?
(defn nth-3 [coll]
(first (rest (rest coll))))
所以有一个模式!但是嵌套对于 fnth
来说是一个挑战。
(first (rest (rest x)))
的等效公式是 ((comp first rest rest) x)
。现在我们可以将 nth-3 写成
(defn nth-3 [coll]
((comp first rest rest) coll))
使用这种方法 fnth
更容易编写。但是如果我们将 (comp first rest rest)
改写为 (apply comp [first rest rest])
会更容易。那里!现在 fnth
需要列出第一个 + 正确数量的休息列表,并将 comp 应用到该列表。