最佳功能方法

发布于 2024-09-01 14:40:55 字数 849 浏览 6 评论 0原文

我有一些可变的 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. 想出一种新方法。

我想我真正想要的是一个延迟评估的序列,我可以在处理完这些值后丢弃它们。有什么建议吗?

I have some mutable scala code that I am trying to rewrite in a more functional style. It is a fairly intricate piece of code, so I am trying to refactor it in pieces. My first thought was this:

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

iterate(2000000,initialValue)

This didn't seem functional at all to me, since I still have side effects mixed throughout my code. My second thought was this:

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
}

This seemed like a better solution to me, because at least I've isolated my functional value-generation code from the mutable value-processing code. However, this is much less memory efficient because I am generating a large list that I don't really need to store.

This leaves me with 3 choices:

  1. Write a tail-recursive function, bite the bullet and refactor the value-processing code
  2. Use a lazy list. This is not a memory sensitive app (although it is performance sensitive)
  3. Come up with a new approach.

I guess what I really want is a lazily evaluated sequence where I can discard the values after I've processed them. Any suggestions?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

昔梦 2024-09-08 14:40:55

请记住,对性能至关重要的算法在可变时通常效果更好。所以要小心过早的去优化!

在 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 来查看它的实际效果。

Bear in mind that performance-critical algorithms often work better when mutable. So beware of premature de-optimization!

In Scala 2.8 you can use Iterator.iterate to create an infinite sequence without stored values. But I'm not sure that alone will be the key step to refactoring the code to be more functional. It's that "process data with side effects" part that is tricky.

You might put the whole thing into the iterate block:

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

where you now have defined an infinite processing stream by sequentially modifying your initial state. You throw away the first 2000000 values (one of which is the initial value), then get the next one (which is the 2000000'th generated value). Try it out with 0 and x=>x+1 to see it in action.

乞讨 2024-09-08 14:40:55

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

I'm thinking you want to use Range if all you're doing is creating a Seq of ints from 0 to 2000000. It's nice and lazy, in 2.7 at least.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文