gpt4 book ai didi

scala - 内置无副作用模拟 while 循环的方法

转载 作者:行者123 更新时间:2023-12-04 12:26:36 24 4
gpt4 key购买 nike

通常 while 循环的样板看起来像(r 是我想要的结果,p 是预测器:

var r, p;
while(p()) {
(r, p) = compute(r)
}

我可以将其转换为递归以摆脱 var:

def f(r) = {
val (nr, p) = compute(r)
if(p()) nr
else f(nr)
}

有没有内置的方法来实现这样的逻辑?我知道 Iterator.continually,但它似乎仍然需要一个 var 来存储副作用。

最佳答案

def compute(i: Int): (Int, () => Boolean) =
(i - 1) -> { () => i > 1 }

要创建不可变的while,您需要迭代 - 一个接受state 并返回新的state 的函数> 相同类型加上退出条件。

Iterator.continually

这不是最好的解决方案 - 在我看来这段代码很难阅读,但既然你提到了它:

val (r, p) = Iterator.continually(()).
scanLeft( 13 -> { () => true } ){
case ((r, p), _) => compute(r)
}.dropWhile{ case (r, p) => p() }.
next
// r: Int = 0
// p: () => Boolean = <function0>

你可以使用 val (r, _) = 因为你不需要 p

如果您想要使用Iterator 的解决方案,请参阅this answer使用 Iterator.iterate

尾递归

我想这是一个惯用的解决方案。您始终可以将 while 循环重写为具有显式状态类型的尾递归:

@annotation.tailrec
def lastWhile[T](current: T)(f: T => (T, () => Boolean)): T = {
val (r, p) = f(current)
if (p()) lastWhile(r)(f)
else r
}

lastWhile(13){ compute }
// Int = 0

鳞片展开

如果您使用 scalaz已经有这样的方法了。它生成一个 Stream,因此您应该获取最后一个元素。

在迭代结束时,您应该生成一个 Option(None 是退出条件)和 Pair 流元素(r) 和下一个状态 (r, p()):

unfold(13 -> true) { case (r0, p0) =>
val (r, p) = compute(r0)
p0.option(r -> (r, p()))
}.last
// Int = 0

关于scala - 内置无副作用模拟 while 循环的方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20726236/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com