以下代码基本上是从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岁,想知道事情是否已经改变了?但是哪些事情呢?
感谢您的时间。
答案 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.
上的文档
使用列表更短: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.