F#列表是否持久存在?

时间:2011-08-09 21:29:45

标签: f# performance immutability persistent

我是F#的C#开发人员,我明白.net中的字符串是不可变的。换句话说,每次修改字符串时,都会得到一个新的字符串实例。

对于像我这样的非功能性思维,第一个问题就是效率,我理解C#可变对象不是持久性的。因为字符串操作在大多数应用程序中通常是微不足道的。

我的问题是,这也是F#列表的情况吗?F#克隆每个列表的变化吗?例如,在过滤列表时,我是否创建了一个包含较少项目的新列表?

更新:我不是在比较.net字符串和列表。我将string命名为不可变对象的一个​​例子,并想知道F#是否为它的List提供了任何特殊处理。

这就是我所说的“persistent”。

5 个答案:

答案 0 :(得分:4)

我认为Dustin Campbell's introduction在解释列表不变性方面做得非常出色。

  

在功能世界中,列表是不可变的。这意味着节点共享是可能的,因为原始列表永远不会改变。因为第一个列表以空列表结束,所以必须复制其节点才能将其最后一个节点指向第二个列表。在追加操作之后,我们的列表如下所示:

     

enter image description here

     

此时,你们中间可能会更加怀疑,“嗯,   这是一个非常有趣的理论,但你可以证明吗?“

     

没问题。

     

使用F#列表递归的知识,我们可以检索   结合的后半部分(内部列表从4开始)取   尾巴,尾巴,尾巴。 List.tl是F#的功能   提供了提取列表的尾部。

> let lastHalf = List.tl (List.tl (List.tl combined));;

val lastHalf : int list

> lastHalf;;

val it : int list = [4; 5; 6]
     

最后,因为F#是.NET Framework的一等公民,我们   可以完全访问所有基类库。所以,我们可以使用   用于测试lastHalf的Object.ReferenceEquals方法   第二个确实是同一个例子。

> System.Object.ReferenceEquals(lastHalf, second);;

val it : bool = true
     

你有它。信不信由你,附加两个不可变的   列表实际上比附加更快,内存效率更高   可变列表,因为必须复制的节点更少。

答案 1 :(得分:1)

F#列表是不可变的。没有API来“修改”F#列表,因此不涉及克隆。像List.filter这样的操作会创建一个新列表(如果可能的话,可能与原始列表共享一些结构)。

(我认为这就是所有语言中所有不可变对象的工作原理。)

参见例如

http://en.wikipedia.org/wiki/Persistent_data_structure

有一个很好的描述以及建议共享如何工作的图片。

答案 2 :(得分:1)

我认为Dan和Brian的引用应该直接回答你的问题。如果您想了解更多信息,还可以查看以下材料(本周在MSDN上发布),这些材料是为了向.NET开发人员解释F#和功能概念而编写的:

答案 3 :(得分:0)

F#列表是链接列表。因此,当您创建新列表时,它只是将项目添加到现有列表并指向包含新项目的头部。原始列表仍指向创建列表时头部的项目。换句话说,它们都指向列表中不同位置的相同列表。

答案 4 :(得分:0)

理解函数式语言列表以理解Cons Cells

的最佳方式