Erlang地图中的非法模式

gee*_*ker 19 erlang map

代码如下:

-module(map_demo).
-export([count_characters/1]).

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

count_characters([H|T], #{ H => N } = X) ->
    count_characters(T, X#{ H := N+1 });
count_characters([H|T], X) ->
    count_characters(T, X#{ H => 1});
count_characters([], X) ->
    X.
Run Code Online (Sandbox Code Playgroud)

在Erlang shell中编译代码时,它报告了以下错误:

1> c(map_demo).
map_demo.erl:7: illegal pattern
map_demo.erl:8: variable 'N' is unbound
map_demo.erl:10: illegal use of variable 'H' in map
map_demo.erl:7: Warning: variable 'H' is unused
error
Run Code Online (Sandbox Code Playgroud)

我是Erlang的新手,我自己找不到任何错误.怎么纠正呢?

fen*_*llp 16

来自IRC的答案(#erlang @ freenode):

  1. 变量作为匹配项中的键尚不支持(版本17.0)
  2. 更普遍的问题会影响函数的匹配参数:第7行H匹配2次; 或曾经和以前用来匹配N. (此问题也出现在二进制文件中)

这应该在即将发布的版本中解决.

截至第17版,有效:

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

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

%% maps module functions cannot be used as guards (release 17)
%% or you'll get "illegal guard expression" error
count_characters([H|T], X) ->
    case maps:is_key(H,X) of
        false -> count_characters(T, maps:put(H,1,X));
        true  -> Count = maps:get(H,X),
                         count_characters(T, maps:update(H,Count+1,X))
    end;
count_characters([], X) ->
        X.
Run Code Online (Sandbox Code Playgroud)

这是另一个版本(仅在18上测试),与书中的版本略有不同:

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

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

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