yal*_*lis 8 functional-programming clojure
我想重复将某些函数应用于某个状态,直到条件成立为止.
函数f采用状态,修改它并返回它.再次将f应用于返回状态,依此类推.
我认为这会奏效.
(first (filter pred (iterate f x)))
Run Code Online (Sandbox Code Playgroud)
但它有点难看.加上内存消耗并不理想,因为迭代器将被强制评估并保持中间状态,直到返回pred保持为true的状态为止,此时中间状态应该被垃圾收集.
我知道你可以编写一个简单的递归函数:
(loop [f x p] (if (p x) x (recur f (f x) p))
Run Code Online (Sandbox Code Playgroud)
但我正在寻找一个核心库函数(或某些函数组合),它们以相同的内存效率执行相同的操作.
你真正想要的是需要的时间:
take-while
function
Usage: (take-while pred coll)
Returns a lazy sequence of successive items from coll while
(pred item) returns true. pred must be free of side-effects.
Run Code Online (Sandbox Code Playgroud)
编辑
使用高阶函数来实现所需结果的方法可能是将函数包装成要使用trampoline的函数,即将返回最终结果的函数或将执行下一步的其他函数.这是代码:
(defn iterable [f] ; wraps your function
(fn step [pred x] ; returns a new function which will accept the predicate
(let [y (f x)] ; calculate the current step result
(if (pred y) ; recursion stop condition
(fn [] (step pred y)) ; then: return a new fn for trampoline, operates on y
y)))) ; else: return a value to exit the trampoline
Run Code Online (Sandbox Code Playgroud)
迭代执行如下:
(trampoline (iterable dec) pos? 10)
Run Code Online (Sandbox Code Playgroud)
不确定你的意思是什么iterator- 你正在使用它,就好像它是一样iterate,我只是想确定这就是你的意思。无论如何,你的解决方案对我来说看起来很好,而且一点也不难看。内存也不是问题:iterate只要方便就可以随意丢弃中间结果,因为您没有保留对它们的任何引用,只是filter以“流”方式调用它。