F#列表是否持久?

F#列表是否持久?,f#,performance,immutability,persistent,F#,Performance,Immutability,Persistent,我是一名C#开发人员,不熟悉F#,我知道在.net中字符串是不可变的。换句话说,每次修改字符串时,都会得到一个新的字符串实例 对于像我这样的非功能性思维来说,第一个问题是效率,我理解C#可变对象不是持久的。因为在大多数应用程序中,字符串操作通常是微不足道的 我的问题是,F#列表也是这样吗?F#会克隆每一个变化的列表吗?例如,在筛选列表时,我是否创建一个包含较少项目的新列表 更新:我没有比较.net字符串和列表。我将string命名为不可变对象的一个示例,并想知道F#是否对它的列表进行了特殊处理

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

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

我的问题是,F#列表也是这样吗?F#会克隆每一个变化的列表吗?例如,在筛选列表时,我是否创建一个包含较少项目的新列表

更新:我没有比较.net字符串和列表。我将string命名为不可变对象的一个示例,并想知道F#是否对它的列表进行了特殊处理

这就是我所说的“.

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

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

(我认为任何语言中的所有不可变对象都是这样工作的。)

见例

请提供一个很好的描述以及一些图片来说明共享是如何工作的。

我认为在解释列表不变性方面做得非常出色

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

在这一点上,你们当中更怀疑的人可能会说,“嗯, 这是一个非常有趣的理论,但你能证明它吗?”

没问题

利用F#列表是递归的知识,我们可以检索 通过取 尾巴,它的尾巴,它的尾巴。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框架的一流公民,我们 具有对所有基类库的完全访问权限。所以,我们可以使用
Object.ReferenceEquals
方法来测试是否为最后一半 第二种情况确实相同

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

val it : bool = true
就在这里。信不信由你,加上两个不变的 列表实际上可以比追加更快、更节省内存 可变列表,因为需要复制的节点较少


理解函数式语言列表的最佳方法是理解

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

  • 介绍F#列表并展示如何在C#中实现相同的概念,这是了解列表如何工作(以及哪些操作是有效的)的一个很好的方法

  • 提供更多关于F#中不变性的背景信息-它不会直接回答您的问题,但也可能是一个有用的资源


.Net字符串是不可变的,它与C无关。C#、VB.Net和任何其他.Net语言都将具有不可变的字符串,因为它是相同的代码库,最终是相同的IL,而不管使用哪种语言。抱歉,我编辑了标题,因为不可变的数据结构是通常用于函数式编程列表、映射等的术语,而持久对象在数据库意义上还有第二层含义。我同意,但它是数据结构实现术语中的标准术语。我完全理解您的好奇心。在编写代码时,效率应该是您最不担心的事情。您可以重新实现运行速度比原来慢一倍的东西,但它可以同时在4个处理器上运行。现在它的速度是原来的两倍。我非常同意,但最好知道幕后发生了什么。我对“可能分享”部分非常感兴趣。你能解释一下什么时候可以吗?在一篇文章中添加了一个链接,其中包含有用的漂亮图片。对于列表,因为它们只是链接列表,当你添加一个元素时,会创建一个新列表,但实际上,只有head设置为指向新值,tail设置为指向现有列表。其他操作,如筛选器和映射,需要重新创建列表。需要明确的是,@emaster意味着,当您在列表的前面添加cons和element时,您可以与原始列表共享整个“尾部”。(添加到列表末尾需要完整副本。)遗憾的是,您提供的链接已失效:(使用internet archive更新建议: