11

我已经有点沉迷于使用不可变集合(主要是在 Clojure 中,它称它们为“持久数据结构”),并且希望能够在 iOS 和 OS X 上的某些上下文中以这种方式编程。

这很有用的一个关键示例是能够通过创建修改后的副本来“更改”字典,并让更改侦听器能够查询旧值和新值之间的差异,而不是尝试将更改编码为属性更改事件。不可变数据结构也是并发编程的游戏规则改变者:不需要锁。

是的,您现在可以使用不可变NSArrayNSDictionary实例来执行此操作,但是当您拥有越来越大的集合和/或频繁进行更改时,复制它们以制作“更改”版本变得越来越低效:然后对大型数据结构进行小改动涉及不成比例的工作量。

我正在寻找一种在 Objective-C 中启用不可变数据编程的方法。为了澄清这可能是什么样子,以及它提供的更多优势,Phil Bagwell 在这个 SO 问题中引用的研究是高度相关的。

4

2 回答 2

3

请参阅 Ridiculous Fish 上的这篇文章(我相信,由 AppKit 团队的工程师兼 Fish shell 的创建者 Cory Doras 撰写):

数组:我们的数组不是. http://ridiculousfish.com/blog/posts/array.html

你已经回答了你的问题:

是的,您现在可以使用不可变的 NSArray 和 NSDictionary 实例来执行此操作...

Cocoa 框架的美妙之处在于它的简单性,尤其是在数据结构方面。这个想法是幕后代码应该决定如何实现结构,而不是你。在实践中,您只需要两种“类型”的数据结构:数组和字典(或映射,如果您来自其他语言)。当然,您需要许多“类型”的实现,但您实际上只需要两种访问数据的方式;如果您需要更多方法,那么这就是自定义类和组合发挥作用的地方。

至于您对效率的关注:不用担心。Cory (Ridiculous Fish) 的文章揭示了在幕后,Apple 已经满足了您对效率的要求。这毕竟只是指针,正如 Ian Murray 在评论中指出的那样:所有内容都被引用计数并且仅在必要时复制。当您“复制”或“mutableCopy”一个 NSArray 或 NSDictionary 时,最有可能的是底层数据实际上并未被复制。要了解如何实现这一点,请参阅 Rob Pike 关于 Go 语言的文章:http: //blog.golang.org/slices。我几乎可以肯定 Cocoa 遵循类似的模式,甚至可能在更远的程度上。

此外,随着Objective-C“块”的出现,现在以函数式编程方式(如LISP变体(例如Clojure))变得越来越可行。事实上,我强烈建议您这样做,并鼓励您继续走这条路。如果处理得当,它可以带来更稳定、更简洁的代码。

于 2013-10-15T16:40:15.517 回答
2

我认为这里没有捷径。

正如您所暗示的,Clojure 的持久数据结构与 Cocoa 提供的不可变集合类完全不同。

如果您想在 Obj-C 中使用 Clojure 的持久数据结构,唯一的方法就是在 Objective-C 中重新实现它们。我的理解是,其中许多在 Okasaki 的书Purely Functional Data Structures和Phil Bagwell的论文中都有描述。

这个其他答案有一些链接:Clojure 集合背后的数据结构是什么?.

于 2013-12-31T19:00:53.053 回答