最佳功能方法

时间:2010-05-13 18:03:08

标签: scala functional-programming scala-2.8 lazy-evaluation tail-recursion

我有一些可变的scala代码,我试图以更实用的方式重写。这是一段相当复杂的代码,所以我试图将它重构成碎片。我的第一个想法是:

def iterate(count:Int,d:MyComplexType) = {
  //Generate next value n
  //Process n causing some side effects
  return iterate(count - 1, n)
}

iterate(2000000,initialValue)

这对我来说似乎没有任何功能,因为我的代码中仍然存在混合副作用。我的第二个想法是:

def generateStream(d:MyComplexType):Stream[MyComplexType] = {
  //Generate next value n
  return Stream.cons(n, generateStream(n))
}

for (n <- generateStream(initialValue).take(2000000)) {
  //process n causing some side effects
}

这对我来说似乎是一个更好的解决方案,因为至少我已经从可变的值处理代码中分离出了我的功能价值生成代码。但是,这样的内存效率要低得多,因为我生成了一个我不需要存储的大型列表。

这给我留下了3个选择:

  1. 编写一个尾递归函数,咬住子弹并重构值处理代码
  2. 使用懒惰列表。这不是一个对内存敏感的应用程序(虽然它对性能敏感)
  3. 想出一个新的方法。
  4. 我想我真正想要的是一个懒惰的评估序列,我可以在处理它们之后丢弃这些值。有什么建议吗?

2 个答案:

答案 0 :(得分:6)

请记住,性能关键算法在可变时通常效果更好。所以要注意过早的去优化!

在Scala 2.8中,您可以使用Iterator.iterate创建无存储值的无限序列。但我不确定单独将是重构代码以使其更具功能性的关键步骤。这是“带有副作用的过程数据”部分,这很棘手。

您可以将整个事情放入迭代块:

Iterator.iterate(initialState)(x => {
  // create a new state based upon state x
}).drop(2000000).next

您现在通过顺序修改初始状态来定义无限处理流。你扔掉前2000000个值(其中一个是初始值),然后得到下一个值(这是第2000000个生成的值)。尝试使用0和x =&gt; x + 1来查看它的实际效果。

答案 1 :(得分:3)

我想你想要使用Range,如果你所做的只是从0到2000000创建一个整数的seq。它很好而且很懒,至少在2.7中。