我已经有点沉迷于使用不可变集合(主要是在Clojure中,它称之为#34;持久数据结构"),并且希望能够在iOS和某些上下文中以这种方式编程OS X。
这个有用的关键例子是能够改变"通过创建修改后的副本来创建字典,并使更改侦听器能够查询旧值和新值之间的差异,而不是尝试将更改编码为属性更改事件。不可变数据结构也是并发编程的游戏规则改变者:不需要锁定。
是的,您现在可以使用不可变的NSArray
和NSDictionary
实例执行此操作,但复制它们以使其变得越来越低效#34;版本,因为你有更大和更大的集合和/或经常进行更改:对大型数据结构的小改动则涉及不成比例的工作量。
我正在寻找一种在Objective-C中启用不可变数据编程的方法。为了澄清这可能是什么样子,以及它提供的更多优势,Phil Bagwell在this SO question中引用的研究具有高度相关性。
答案 0 :(得分:3)
请参阅Ridiculous Fish上的这篇文章(我相信,由AppKit团队的工程师Cory Doras编写,也是Fish shell的创建者):
数组:我们的数组不是 。 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“块”的出现,现在以函数式àla LISP变体(例如Clojure)进行编程变得越来越可行。事实上,我强烈推荐这一点,并鼓励你继续这条道路。如果做得好,它可以导致更稳定,更清晰的代码。
答案 1 :(得分:2)
我认为这里没有捷径。
就像你暗示的那样,Clojure的持久性数据结构与Cocoa提供的 immutable 集合类完全不同。
如果你想使用来自Obj-C的Clojure的持久数据结构,唯一的方法就是在Objective-C中重新实现它们。我的理解是,许多这些都在Okasaki的书Purely Functional Data Structures以及Phil Bagwell的papers中有所描述。
这个答案有一些链接:What is the data structure behind Clojure's sets?。