新手问题,但我真的不明白为什么有很多操作来构建clojure中的地图.
你有conj,assoc和merge,但他们似乎或多或少做同样的事情?
(assoc {:a 1 :b 2} :c 3)
(conj {:a 1 :b 2} {:c 3})
(merge {:a 1 :b 2} {:c 3})
Run Code Online (Sandbox Code Playgroud)
真正的区别是什么,为什么所有这些方法在做或多或少相同的事情时都需要?
dby*_*rne 52
assoc并且conj对于其他数据结构的行为非常不同:
user=> (assoc [1 2 3 4] 1 5)
[1 5 3 4]
user=> (conj [1 2 3 4] 1 5)
[1 2 3 4 1 5]
Run Code Online (Sandbox Code Playgroud)
如果您正在编写一个可以处理多种集合的函数,那么您的选择将会产生很大的不同.
治疗merge作为唯一的地图功能(其类似于conj其他集合).
我的看法:
Mic*_*zyk 23
实际上,当与地图一起使用时,这些函数的行为完全不同.
conj:
首先,(conj {:a 1 :b 2} :c 3)问题文本中的示例根本不起作用(无论是1.1还是1.2; IllegalArgumentException都被抛出).只有少数类型可以conj编辑到地图上,即双元素向量,clojure.lang.MapEntrys(基本上相当于两元素向量)和映射.
请注意,seq地图包含一堆MapEntrys.因此你可以这样做
(into a-map (filter a-predicate another-map))
Run Code Online (Sandbox Code Playgroud)
(注意在内部into使用conj- 或者conj!,如果可能的话).既不merge也assoc不允许你这样做.
merge:
这几乎完全相同conj,但它nil用{}- 空哈希映射替换它的参数- 因此当链中的第一个"映射"碰巧时将返回一个映射nil.
(apply conj [nil {:a 1} {:b 2}])
; => ({:b 2} {:a 1}) ; clojure.lang.PersistentList
(apply merge [nil {:a 1} {:b 2}])
; => {:a 1 :b 2} ; clojure.lang.PersistentArrayMap
Run Code Online (Sandbox Code Playgroud)
请注意,没有任何东西(docstring除外)阻止程序员使用merge其他集合类型.如果一个人这样做,那么奇怪就会发生; 不建议.
assoc:
同样,问题文本中的例子(assoc {:a 1 :b 2} {:c 3})- 将不起作用; 相反,它会抛出一个IllegalArgumentException.assoc采用map参数后跟偶数个参数 - 奇数位置(假设地图位于0位置)是键,偶数位置是值.我发现我assoc的东西到地图往往比我conj,虽然我的时候conj,assoc会觉得累赘.;-)
merge-with:
为了完整起见,这是处理地图的最终基本功能.我发现它非常有用.它像docstring指示的那样工作; 这是一个例子:
(merge-with + {:a 1} {:a 3} {:a 5})
; => {:a 9}
Run Code Online (Sandbox Code Playgroud)
请注意,如果地图包含"新"键,该键未在其左侧的任何地图中出现,则不会调用合并功能.这有时令人沮丧,但在1.2中,聪明的人reify可以提供具有非nil"默认值" 的地图.
由于地图在Clojure中是一种普遍存在的数据结构,因此有多种工具可用于操作它们.在略微不同的情况下,各种不同的功能在语法上都很方便.
我个人对你提到的具体功能的看法:
| 归档时间: |
|
| 查看次数: |
5723 次 |
| 最近记录: |