Erlang中的地图模式匹配,意外错误(未绑定)

时间:2017-05-29 17:25:38

标签: hashmap erlang

以下代码基本上是从J.A。的书中复制的:

-module(mapz).
-export([count_chars/1]).

count_chars(Str) ->
    count_chars(Str, #{}).

count_chars([H|T], #{H := N}=X) -> % line that throws
    count_chars(T, X#{H := N+1});
count_chars([H|T], X) ->
    count_chars(T, X#{H => 1});
count_chars([], X) -> X.

但是,在shell中编译它会给我

151> c(mapz).
mapz.erl:7: variable 'H' is unbound
error
152>

我理解在H可以用于匹配地图中的键之前绑定H的重要性;并且,据我所知,它与第一个参数中的列表(字符串)的头部匹配,因此受到第二个参数(与地图匹配)的评估时间的约束。更重要的是,这个例子来自书中,我怀疑它是正确的。这本书似乎正在使用OTP17,而我现在已经20岁,想知道事情是否已经改变了?但是哪些事情呢?

感谢您的时间。

2 个答案:

答案 0 :(得分:2)

在子句count_chars([H|T], #{H := N}=X) -> ...中,编译器不认为H在第一个参数的模式匹配期间已被绑定:[H|T],因此它无法模式匹配第二个参数#{H := N}(我认为可以通过实际装配,见my answer to this topic

但是地图库中还有你需要的功能:

count_chars(Str) ->
    count_chars(Str, #{}).

count_chars([H|T],X) ->
    count_chars(T, maps:update_with(H,fun(V) -> V+1 end, 1,X));
count_chars([], X) ->
    X.

请参阅Maps erlang doc

上的文档

使用列表更短:foldl / 3

count_chars(Str) -> 
    lists:foldl(fun(C,Map) ->  maps:update_with(C,fun(Count) -> Count+1 end, 1,Map) end, #{},Str).

答案 1 :(得分:1)

您不能在地图上进行模式匹配(至少现在还没有),其中键是变量,例如:

count_chars([H|T], #{H := N}=X)

但这可行:

count_chars([H|T], #{"MyKey" := N}=X)

您可以将代码更新为:

-module(mapz).
-export([count_chars/1]).

count_chars(Str) ->
  count_chars(Str, #{}).

count_chars([H|T], X) ->
  case maps:is_key(H,X) of
    false -> count_chars(T, X#{ H => 1 });
    true  -> #{ H := Count } = X,
             count_chars(T, X#{ H := Count+1 })
    end;
count_chars([], X) ->
  X.