我正在学习scala编程。 我在函数式编程方面有一些经验,就像面向对象编程一样。 我的问题很简单但很棘手:
Scala应该使用哪些结构?我们应该只坚持不变量,例如。通过迭代修改列表并将新的列表粘在一起,或者去寻找可变的列表?您对此有何看法,表现方面,记忆相关方面是什么......
我可能会以功能性的方式编程,但它通常会扩展到通过使用mutable轻松完成的事情。是依赖于情况,使用什么?
答案 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
并行。