在scala中clojure迭代等效?

5 scala clojure

递归很酷,但是当你被更高阶的库函数包围时,它的级别很低.我试图避免为依赖于生成的最后一个值的进程编写递归函数.

我通常会iterate在Clojure中使用函数而不是最后一个值和当前参数的"压缩"列表.Scala的集合API中是否存在等效函数?

这是在一些疯狂的伪代码中尝试抽象的例子:

说你有

  • 输入列表: Seq(1,2,3)
  • 您对生成的最后一个值以及列表中的下一个项执行的某些操作:

    lastValue ^ 2 + nextInt(i)

并且您希望累积生成的所有值.

我正在努力避免写一些类似的东西:

def f(ls:Seq[Int]):Seq[Float] = {

  def g(pos:Int, lastGen:Float):Seq[Float] = { 
    val v = gen(lastGen, ls(pos))
    if( end(v) )
      Seq(v)
    else
      Seq(v) ++ g(pos+1, v)
  }

  f(0, 1)
}
Run Code Online (Sandbox Code Playgroud)

我已经在Haskell中看到了类似于定义一个懒惰流版本的Fibonacci的东西,所以假设我可以使用一个引用它的懒惰流,但是这比Clojure的迭代更难以包裹我的大脑.

Dao*_*Wen 6

这是你在找什么?它与iterateClojure 基本相同:

List.iterate(1, 5) { _ + 1 }
// res1: List[Int] = List(1, 2, 3, 4, 5)
Run Code Online (Sandbox Code Playgroud)

我认为iteratefor 的定义List来自GenTraversableFactory.

唯一的缺点是第二个参数len是你想要的参数数量,所以它不像iterateClojure 那样返回无限序列.

更新:

刚学到新东西!该Stream对象也有一个iterate方法,这可以让你创建无限的懒惰流:

(Stream.iterate(1) { _ * 2 } take 5).toList
// res1: List[Int] = List(1, 2, 4, 8, 16)
Run Code Online (Sandbox Code Playgroud)

  • 我建议使用`Iterator`而不是`Stream`,因为它不会缓存计算值(这里不需要). (2认同)

Tra*_*own 0

听起来你想要的高阶函数是scanLeft,它就像一个记住其中间步骤的折叠。例如,假设您有以下内容:

val ls = Seq(1, 2, 3)
def gen(lastValue: Double, n: Int) = math.pow(lastValue, 2) + n
Run Code Online (Sandbox Code Playgroud)

然后你可以像这样将它们与scanLeft

scala> ls.scanLeft(1.0)(gen)
res0: Seq[Double] = List(1.0, 2.0, 6.0, 39.0)
Run Code Online (Sandbox Code Playgroud)

这或多或少相当于 Apocalisp 的 公式foldLeft,只不过它scanLeft会为您保留中间值。