scala – 功能编程中是否有“折叠折叠”或“找到累加器”的概念?

标题真的是这样说的迭代收集,同时保持循环之间的状态和基于终止条件的完成迭代,除了简单地运行元素之外,也可能是在命令式编程中完成任何事情的最常见的模式.不过,在我看来,这是一个功能性很强的程序员同意不要谈论的东西,或者至少我从来没有遇到一个成语,或者是一个半标点的名字,如地图,折叠,缩小等.

我经常在scala中使用followinig代码:

implicit class FoldWhile[T](private val items :Iterable[T]) extends AnyVal {
    def foldWhile[A](start :A)(until :A=>Boolean)(op :(A, T)=>A) :A = {
        if (until(start)) start
        else {
            var accumulator = start
            items.find{ e => accumulator = op(accumulator, e); until(accumulator) }
            accumulator
        }

    }

}

但它是丑陋的每当我尝试一个更具声明性的方法时,我会有更长的时间,几乎肯定较慢的代码,类似于:

Iterator.iterate((start, items.iterator)){
    case (acc, i) if until(acc) => (acc, i)
    case (acc, i) if i.hasNext => (op(acc, i.next()), i)
    case x => x
}.dropWhile {
    case (acc, i) => !until(acc) && i.hasNext
}.next()._1

(一个更多功能的变体将使用Lists或Streams,但迭代器可以说比将数据转换为Stream更少的开销,因为后者的默认实现方式使用下面的迭代器).

我的问题是:

1)这个概念在函数式编程中是否有一个名称,如果是这样,与实现有关的模式是什么?

2)什么是最好的(即简洁,通用,懒惰和最少的开销)的方法来实现它在scala?

最佳答案
这是由scala纯粹主义者皱起眉头,但你可以使用这样的return语句:

 def foldWhile[A](zero: A)(until:A => Boolean)(op:  (A,T) => A): A = items.fold(zero) {
      case (a, b) if until(a) => return a
      case (a,b) => op(a, b)
}

或者,如果你是一个皱眉头的人,并且想要一个纯粹的功能性解决方案,没有肮脏的命令式的技巧,你可以使用一些懒惰,像迭代器或流:

items
  .toStream // or .iterator - it doesn't really matter much in this case
  .scanLeft(zero)(op)
  .find(until)

转载注明原文:scala – 功能编程中是否有“折叠折叠”或“找到累加器”的概念? - 代码日志