【问题标题】:Efficiency of list operations in functional languages函数式语言中列表操作的效率
【发布时间】:2013-03-23 11:02:55
【问题描述】:

在 Racket 或 SML 等函数式语言中,我们通常在递归调用中执行列表操作(模式匹配、列表追加、列表连接......)。但是,我不确定这些操作在函数式语言中的一般实现。列表中的创建、更新或删除元素等操作是否会返回列表的全新副本?我曾经在一本书中读到一个关于函数式编程缺点的例子;也就是说,每次更新数据库时,都会返回一个全新的数据库副本。

我质疑这个例子,因为 FP 中的数据本质上是不可变的,因此从现有列表创建列表不应该创建一个全新的副本。相反,新列表只是基于过滤条件对其他列表中现有对象的不同引用集合。

例如,列表A = [a,b,c] 和列表B=[1,2,3],我创建了一个新列表,其中包含现有列表中的前两个元素,即C=[a,b,1,2]。这个新列表只包含来自Aa,b, 和来自B1,2 的引用。它不应该是新副本,因为数据是不可变的。

所以,要更新列表中的元素,只需要线性时间在列表中找到一个元素,创建一个新值并创建一个新列表,其中包含与旧列表中相同的元素,除了更新的元素.要创建新列表,运行环境只需更新前一个元素的下一个指针。如果一个列表包含非原子元素(即列表、树...),并且只有一个非原子元素中的一个原子元素被更新,则此过程递归地应用于非原子元素,直到原子元素如上所述更新。 应该这样实现吗?

如果有人在每次从现有列表/添加/更新/删除/包含元素创建列表时创建列表的完整深层副本,那么他们做错了,不是吗?

另外一点是,当程序环境更新时(即为一个新变量添加一个新的键/值条目,以便我们以后可以参考),它并没有违反函数式编程的不可变属性是吗?

【问题讨论】:

标签: functional-programming


【解决方案1】:

你完全正确!具有不可变数据的 FP 语言将从不进行深度复制(除非它们的实现真的很差)。由于数据不可变的,因此重用它永远不会有任何问题。它与所有其他结构的工作方式完全相同。因此,例如,如果您正在使用树结构,那么最多只会复制实际的树,而不会复制其中包含的数据。

因此,虽然复制听起来非常昂贵,但如果您来自命令式/OO 背景(您确实必须复制,因为您有可变数据),它比您最初想象的要少得多。拥有不可变数据有很多好处。

【讨论】:

    猜你喜欢
    • 2013-04-05
    • 1970-01-01
    • 2010-10-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多