3

我有一些可变的 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 回答 2

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=>x+1 来查看它的实际效果。

于 2010-05-13T19:21:50.583 回答
3

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

于 2010-05-13T18:12:56.370 回答