Функциональный эквивалент параллельной мультикарты - PullRequest
5 голосов
/ 22 марта 2012

В другой вопрос , я задал вопрос о параллельных мультикартах для Java.

Существует ли какой-либо шаблон функционального (неизменяемого) программирования, который можно использовать вместо этого в программе Scala или Clojure?Я представляю, что в решении Scala, вероятно, будут задействованы актеры, а в ближайшем будущем - atom, ref или agent, но, возможно, найдется лучший способ.Поскольку оба языка допускают «откат» к взаимодействию Java и просто используют решение Java, я могу использовать любой ответ, который получу на свой первый вопрос, но он не будет придерживаться парадигмы функционального программирования.Как программисты на Haskell решают эту проблему?

Ответы [ 3 ]

7 голосов
/ 22 марта 2012

Стандартные карты и наборы Clojure являются неизменными (и постоянными) [1], поэтому они работают так же хорошо в параллельных программах. Вы можете сохранить их в ref / agent / var / atom в зависимости от ваших требований, и вы можете просто обновить ref / agent / var / atom, как всегда.

Вы можете иметь более изменчивую карту, если значения на самом деле являются ссылками, например:

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

В этом случае вы сможете фактически добавить значения к уже существующему ключу (конечно, в транзакции). Добавление и удаление ключей будет по-прежнему возвращать новые карты, которые будут иметь те же ссылки, что и исходные карты, и поэтому изменения одной из них будут видны другим:

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] То есть добавление / удаление / изменение ключей и значений фактически возвращает новую карту без изменения оригинала.

3 голосов
/ 22 марта 2012

Функциональная структура данных является неизменной структурой данных. Неизменяемые структуры данных не имеют проблем с параллелизмом, потому что они не могут быть изменены.

0 голосов
/ 26 марта 2014

В Scala есть реализация в библиотеке Akka

https://github.com/akka/akka/blob/v2.3.0/akka-actor/src/main/scala/akka/util/Index.scala

...