简体   繁体   English

功能等效于并发多重映射

[英]Functional equivalent to the concurrent multimap

In another question , I asked about concurrent multimaps for Java. 另一个问题中 ,我询问了Java的并发多图。

Is there some functional programming (immutable) pattern that can be used instead in a Scala or Clojure program? 是否有一些函数式编程(不可变)模式可以在Scala或Clojure程序中使用? I image that the Scala solution will probably involve actors and the clojure one an atom , ref or agent , but there may be a better way. 我认为Scala解决方案可能涉及演员和clojure一个atomrefagent ,但可能有更好的方法。 Since both languages allow "falling back" to Java interop and just using a Java solution, I can use whatever answer I get to my first question, but that will not adhere to the functional programming paradigm. 由于两种语言都允许“回退”到Java互操作并只使用Java解决方案,我可以使用我在第一个问题中得到的任何答案,但这不符合函数式编程范例。 How do Haskell programmers solve this? Haskell程序员如何解决这个问题?

Standard Clojure maps and sets are immutable (and persistent)[1], so they work just as well in concurrent programs. 标准Clojure映射和集合是不可变的(和持久的)[1],因此它们在并发程序中也能正常工作。 You may want to store them in a ref/agent/var/atom depending on your requirements, and you can just update the ref/agent/var/atom as ever. 您可能希望将它们存储在ref / agent / var / atom中,具体取决于您的要求,您可以像以前一样更新ref / agent / var / atom。

You can have a more mutable map, if the values are actually refs, like this: 如果值实际为refs,则可以使用更可变的映射,如下所示:

{:a (ref #{1 2 3})
 :b (ref #{4 5 6})}

In this case, you'll be able to actually add values to already existing key (in transaction of course). 在这种情况下,您将能够实际向现有密钥添加值(当然在事务中)。 Addition and removal of keys will still return new maps, which would share the same refs as the original maps, and so changes to one of them will be visible to the others: 添加和删​​除键仍将返回新的地图,这些地图将与原始地图共享相同的引用,因此其他地图的更改将对其他地方可见:

user=> (def mmap {:a (ref #{1 2 3}) :b (ref #{4 5 6})})
#'user/mmap
user=> mmap
{:a #<Ref@be0446: #{1 2 3}>, :b #<Ref@10aa282: #{4 5 6}>}
user=> (def mmap2 (assoc mmap :c (ref #{7 8 9})))
#'user/mmap2
user=> mmap2
{:c #<Ref@405f6: #{7 8 9}>, :a #<Ref@be0446: #{1 2 3}>, :b #<Ref@10aa282: #{4 5 6}>}
user=> mmap
{:a #<Ref@be0446: #{1 2 3}>, :b #<Ref@10aa282: #{4 5 6}>}
user=> (dosync (alter (:a mmap2) conj 0))
#{0 1 2 3}
user=> mmap
{:a #<Ref@be0446: #{0 1 2 3}>, :b #<Ref@10aa282: #{4 5 6}>}
user=> mmap2
{:c #<Ref@405f6: #{7 8 9}>, :a #<Ref@be0446: #{0 1 2 3}>, :b #<Ref@10aa282: #{4 5 6}>}

[1] That is, adding/removing/modifying keys, and values actually return a new map, without changing the original. [1]也就是说,添加/删除/修改键,值实际上返回一个新地图,而不更改原始地图。

A functional data structure is an immutable data structure. 功能数据结构是不可变的数据结构。 Immutable data structures do not have problems with concurrency because they cannot be modified. 不可变数据结构没有并发问题,因为它们无法修改。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM