功能编程:不变性应该走多远?

Qua*_*One 3 functional-programming immutability

我意识到这可能是一个非常主观的问题,但我正在寻找一些比我在函数式编程方面更有经验的人的见解.

我的理解是,保持一切不可变的主要动力是让事情更容易理解,并阻止错误蔓延到并行任务.这样做的缺点是,每次要对数据结构进行更改时,都必须将整个数据结构复制到一个新对象中,但需要进行所需的更改.据推测,这样做有一些性能成本:虽然对于一个小对象我不会这么做三次,如果你正在研究大型矩阵或张量,或类似的大型数据结构,那肯定会变得非常慢?

简而言之:

  1. 复制不可变数据结构会有性能损失吗?它有多重要?
  2. 如果是这样,你能举例说明你(个人)在制作不可变的东西和使它变得可变之间的界限吗?

Wil*_*sem 5

我的理解是,保持一切不可变的主要动力是让事情更容易理解,并阻止错误蔓延到并行任务.

这可能是主要动机.但还有其他优点.但它可以带来性能提升.例如,lockfreewaitfree数据结构是一种处理并行处理的方法,旨在减少锁定的开销.

这样做的缺点是,每次要对数据结构进行更改时,都必须将整个数据结构复制到一个新对象中,但需要进行所需的更改.

这是不正确的.您无需复制整个数据结构.例如,手指树是功能编程中的典型数据结构.它在O(d)中插入(带有d)树的深度.所以它具有完全相同的性能.

使用不可变对象可能在很多/大多数情况下导致相同的时间复杂度,尽管算法通常以不同方式编写(例如,列表通常是链表,因此列表处理通常是为了避免随机索引查找而完成的).

此外,数据结构不可变的事实也可以提高效率.例如,在许多编程语言中,字符串是不可变对象.某些编程语言具有实现flyweight模式的字符串存储.如果构造一个新字符串,它会检查字符串是否已经存在,如果是这种情况,则获取指向该字符串的指针.优点是减少了内存占用,而且由于可以缓存这些对象,因此它还可以提高性能.

会在制作不可变的东西和使它变得可变之间划清界限吗?

有像Haskell这样的编程语言,其中一切都是不可变的.在这种情况下,可变性通过使用monad完成,从而通过该过程传递新版本的对象.Haskell编译器往往做得很好,有时可以达到与命令式对应程序相同的速度.