Erlang в отличие от Haskell не является pure функциональным языком программирования. Как следствие, он не накладывает ограничений на функции с точки зрения того, могут ли они иметь побочные эффекты или нет. В Haskell даже подсистема ввода-вывода не может нарушить свою чистоту, и поэтому существует различие на уровне типов между Traversable
и Functor
(traverse
и fmap
), где первое может воздействовать на каждого элемент контейнера, а последний не может. В Erlang нет такого четкого различия, и, как следствие, у вас может быть функция execute(Container) ->
, и вы не знаете, будет ли она запускать эффекты, просто глядя на свою подпись. Вот почему наличие в Эрланге map
и smap
(или traverse
, или как бы вы это ни называли) не имеет смысла и не приносит никакой ценности вообще. Но это правда, что использование lists:map
для такого рода операций нарушает контракт map
, который должен быть чистой функцией. В такой ситуации я могу порекомендовать вам использовать понимание списка, которое, на мой взгляд, является более идиоматическим:
[begin
Pids = [spawn_link(fun() ->
% Side-effect operation which worker performs
end) || Id <- Ids],
[receive {received_data, Data} -> Data end || _Pid <- Pids]
end || Ids <- JobChunks].
Опять же , с моей точки зрения, . Побочные эффекты - это существенная разница между пониманием списка и lists:map()
. Когда они используются вышеупомянутым способом, я обычно думаю о них как о монадских пониманиях Хаскелла.