执行功能直到某些条件成立

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)

但我正在寻找一个核心库函数(或某些函数组合),它们以相同的内存效率执行相同的操作.

sku*_*uro 5

你真正想要的是需要的时间:

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)


ama*_*loy 4

不确定你的意思是什么iterator- 你正在使用它,就好像它是一样iterate,我只是想确定这就是你的意思。无论如何,你的解决方案对我来说看起来很好,而且一点也不难看。内存也不是问题:iterate只要方便就可以随意丢弃中间结果,因为您没有保留对它们的任何引用,只是filter以“流”方式调用它。