【问题标题】:Is this Erlang code idiomatic? [closed]这个 Erlang 代码是惯用的吗? [关闭]
【发布时间】:2016-03-01 20:48:09
【问题描述】:

我正在对 Erlang、Haskell、Elixir 和 ES6 进行比较,我对 Erlang 和 Elixir 不太熟悉,但我想公平地表示所有这些语言,那么这样的 Erlang 代码好吗?

-module(mapreduce).
-export([map_reduce/1]).

add_to_key(KV, Sum) -> {Key, Value} = KV,
                       Tmp = proplists:get_value(Key, Sum, 0),
                       Newlist = proplists:delete(Key, Sum),
                       lists:append([{Key, Value + Tmp}], Newlist).

map_reduce(Pl) -> lists:foldl(fun add_to_key/2, [], Pl).

- 谢谢大家!

顺便说一句,如果你们想看,这里是 Haskell 版本:

module MapReduce where
import qualified Data.Map as M

mapReduce :: [(String, Int)] -> [(String, Int)]
mapReduce = foldl addToKey []
    where addToKey hl (k, v) = M.toList . M.insertWith (+) k v $ M.fromList hl

【问题讨论】:

  • 你有什么理由想在 erlang 中使用列表?为什么不是dictupdate 似乎是最经济的方式。
  • 请不要在 Stack Overflow 上要求代码审查。
  • 我投票结束这个问题,因为它是关于代码审查的。
  • 对不起,伙计们。我对 StackOverflow 还是比较陌生,我不知道你没有在这里做代码审查。我会转移问题。
  • @ChristopherDumas 发布指向新版本问题的链接,可能在此处的 erlang 聊天室中(不确定将问题移至此处是否会使它们消失)。 Erlang 社区非常小,我想我只见过 Erlang 问题在主要问题上真正处理过。

标签: haskell erlang idioms


【解决方案1】:

我会这样写(在版本 >= 17 的 shell 中测试),以限制列表创建/复制的数量:

1> F = fun F([],L,_)-> L; F([{K,V}|T],[{K,V1}|T1],Func) -> F(T,[{K,Func(V,V1)}|T1],Func); F([{K,V}|T],L,Func) -> F(T,[{K,V}|L],Func) end.
#Fun<erl_eval.42.54118792>
2> MR = fun(L,Func) -> F(lists:sort(L),[],Func) end.                                                                                     
#Fun<erl_eval.12.54118792>
3> MR([{1,2},{2,5},{1,6},{8,5},{2,1}],fun(A,B)-> A+B end).                                                                               
[{8,5},{2,6},{1,8}]
4> MR([{1,2},{2,5},{1,6},{8,5},{2,1}],fun(A,B)-> A*B end).
[{8,5},{2,5},{1,12}]
5> MR([{1,2},{2,5},{1,6},{8,5},{2,1}],fun(A,B)-> max(A,B) end).
[{8,5},{2,5},{1,6}]
10>

【讨论】:

  • 哇。那是疯狂的编码。
  • 我同意我没有花很多时间来编写漂亮的代码 :o)。尽管如此,我认为如果输入 proplist 足够大(需要一些基准来验证它),它应该会更高效。
【解决方案2】:

更惯用的 Erlang 会在函数子句头 add_to_key({Key, Value}, Sum) 中使用模式匹配,但是当您在 Haskell 中使用 Data.Map 时,您也应该在 Erlang 中使用类似的键/值存储。在 R17 之前的版本中,它主要是 dict,但现在我们也有地图。像add_to_key/2 那样做额外的功能也不常见(我个人更喜欢它,但它不是惯用的。):

map_reduce(L) ->
    F = fun({K, V}, M) ->
            maps:put(K, V + maps:get(K, M, 0), M)
        end,
    maps:to_list(lists:foldl(F, #{}, L)).

无论如何,使用Pascalanswer中的排序列表的方法并不罕见:

map_reduce(L) ->
    F = fun({K, V1}, [{K, V2}|Acc]) ->
            [{K, V1 + V2}|Acc];
           ({K, V}, Acc) ->
            [{K, V}|Acc]
        end,
    lists:foldl(F, [], lists:sort(L)).

【讨论】:

    猜你喜欢
    • 2021-03-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多