递归很酷,但是当你被更高阶的库函数包围时,它的级别很低.我试图避免为依赖于生成的最后一个值的进程编写递归函数.
我通常会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的迭代更难以包裹我的大脑.
这是你在找什么?它与iterate
Clojure 基本相同:
List.iterate(1, 5) { _ + 1 }
// res1: List[Int] = List(1, 2, 3, 4, 5)
Run Code Online (Sandbox Code Playgroud)
我认为iterate
for 的定义List
来自GenTraversableFactory
.
唯一的缺点是第二个参数len
是你想要的参数数量,所以它不像iterate
Clojure 那样返回无限序列.
更新:
刚学到新东西!该Stream
对象也有一个iterate
方法,这可以让你创建无限的懒惰流:
(Stream.iterate(1) { _ * 2 } take 5).toList
// res1: List[Int] = List(1, 2, 4, 8, 16)
Run Code Online (Sandbox Code Playgroud)
听起来你想要的高阶函数是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
会为您保留中间值。
归档时间: |
|
查看次数: |
473 次 |
最近记录: |