Scala不可变vs可变。一个人应该去的方式是什么?

时间:2013-01-10 10:48:09

标签: oop scala coding-style functional-programming

我正在学习scala编程。 我在函数式编程方面有一些经验,就像面向对象编程一样。 我的问题很简单但很棘手:

Scala应该使用哪些结构?我们应该只坚持不变量,例如。通过迭代修改列表并将新的列表粘在一起,或者去寻找可变的列表?您对此有何看法,表现方面,记忆相关方面是什么......

我可能会以功能性的方式编程,但它通常会扩展到通过使用mutable轻松完成的事情。是依赖于情况,使用什么?

3 个答案:

答案 0 :(得分:3)

(我认为这必须是重复的,但不能轻易找到更早的类似的,所以我冒昧回答......)

这个问题没有一般答案。 Scala创建者提出的经验法则是从不可变的val和结构开始,只要它有意义就坚持使用它们。您几乎总能以这种方式为您的问题创建可行的解决方案。但如果没有,当然要务实并且使用可变性。

一旦你有了解决方案,你就可以调整它,测试它,测量它的性能等。如果你会发现它,例如它太慢或太复杂,找出它的关键部分,理解是什么使它成为问题,并且 - 如果需要 - 使用可变变量重新实现它,理想情况下使它与程序的其余部分隔离。请注意,在许多情况下,也可以在不可变领域内找到更好的解决方案,因此请先尝试查看。特别是像我这样的初学者,它仍然经常发生,我能想出的最好的解决方案看起来扭曲和复杂,没有明显的方法来改进它 - 直到在几行代码中看到一个简单而优雅的解决方案,由经验丰富的Scala开发人员创建,他负责控制语言及其库的更多功能。

答案 1 :(得分:3)

我通常遵守以下规则:

  • 绝不使用静态可变变量

  • 保持所有用户定义的数据类型(通常是案例类)不可变,除非复制起来非常昂贵。这将简化许多应用程序逻辑。

  • 如果数据结构/集合本质上是可变的(即它被设计为随时间变化),则使用可变数据结构/集合可能是合适的。一个例子可能是玩家移动时更新的大型游戏世界。记得(几乎)永远不要在线程之间共享这些数据结构。

  • 在方法

  • 中使用可变的本地变量是可以的
  • 对函数结果使用不可变集合。这些可以严格或延迟评估,具体取决于在使用的上下文中提供最佳性能的内容。如果使用依赖于可变集合的延迟评估结果,请小心。

答案 2 :(得分:3)

首选不可变状态。仅在绝对必要的地方使用可变状态。一些值得注意的原因包括:

  • 性能。标准库广泛使用vars和while循环,即使这不是惯用的Scala。但是,这不应该被模拟,除非您有 profiled 以确定修改代码更为必要的情况将带来显着的性能提升。

  • I / O。 I / O或与外部世界的交互本质上依赖于状态,因此必须以可变的方式处理。

这与所有主要语言中的推荐编码风格没有什么不同,无论是强制还是功能。例如,在Java中,最好使用仅包含private final个字段的数据对象。以不可变(和功能)方式编写的代码本质上更容易理解,因为当人们看到val时,他们知道它永远不会改变,减少任何特定对象或函数可能存在的状态数。

在许多情况下,它还允许自动并行执行,例如,Scala中的集合类都具有par函数,该函数将返回一个并行集合,该集合自动运行对map等函数的调用或reduce并行。