【发布时间】:2013-03-23 11:02:55
【问题描述】:
在 Racket 或 SML 等函数式语言中,我们通常在递归调用中执行列表操作(模式匹配、列表追加、列表连接......)。但是,我不确定这些操作在函数式语言中的一般实现。列表中的创建、更新或删除元素等操作是否会返回列表的全新副本?我曾经在一本书中读到一个关于函数式编程缺点的例子;也就是说,每次更新数据库时,都会返回一个全新的数据库副本。
我质疑这个例子,因为 FP 中的数据本质上是不可变的,因此从现有列表创建列表不应该创建一个全新的副本。相反,新列表只是基于过滤条件对其他列表中现有对象的不同引用集合。
例如,列表A = [a,b,c] 和列表B=[1,2,3],我创建了一个新列表,其中包含现有列表中的前两个元素,即C=[a,b,1,2]。这个新列表只包含来自A 的a,b, 和来自B 的1,2 的引用。它不应该是新副本,因为数据是不可变的。
所以,要更新列表中的元素,只需要线性时间在列表中找到一个元素,创建一个新值并创建一个新列表,其中包含与旧列表中相同的元素,除了更新的元素.要创建新列表,运行环境只需更新前一个元素的下一个指针。如果一个列表包含非原子元素(即列表、树...),并且只有一个非原子元素中的一个原子元素被更新,则此过程递归地应用于非原子元素,直到原子元素如上所述更新。 应该这样实现吗?
如果有人在每次从现有列表/添加/更新/删除/包含元素创建列表时创建列表的完整深层副本,那么他们做错了,不是吗?
另外一点是,当程序环境更新时(即为一个新变量添加一个新的键/值条目,以便我们以后可以参考),它并没有违反函数式编程的不可变属性是吗?
【问题讨论】:
-
您可以在这里找到部分问题的答案:stackoverflow.com/questions/1658887/…。