Erlang地图中的非法模式

时间:2014-04-16 10:18:22

标签: map erlang

代码如下:

-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.

在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

我是Erlang的新手,我自己也找不到任何错误。如何纠正?

7 个答案:

答案 0 :(得分:15)

IRC(#erlang @ freenode)的回答:

  1. 不支持匹配项中的变量(版本17.0)
  2. 更常见的问题会影响函数的匹配参数:第7行H匹配2次;或曾经和以前用来匹配N. (此问题也出现在二进制文件中)
  3. 这应该在即将发布的版本中解决。

    截至第17版this有效:

    -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.
    

    这是另一个版本(仅在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.
    

答案 1 :(得分:2)

引自OTP 17.0 Release Notes

  

OTP-11616 == erts stdlib hipe dialyzer编译器typer ==

    EEP43: New data type - Maps

    With Maps you may for instance:

    -- M0 = #{ a => 1, b => 2}, % create associations

    -- M1 = M0#{ a := 10 }, % update values

    -- M2 = M1#{ "hi" => "hello"}, % add new associations

    -- #{ "hi" := V1, a := V2, b := V3} = M2. % match keys with
    values

    For information on how to use Maps please see the Reference
    Manual.

    The current implementation is without the following features:

    -- No variable keys

    -- No single value access

    -- No map comprehensions

    Note that Maps is experimental during OTP 17.0.

目前,您可以使用maps模块来实施count_characters

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

count_characters([H|T], X) -> 
    count_characters(T, maps:put(H, maps:get(H, X, 0) + 1, X));
count_characters([], X) ->
    X.

答案 2 :(得分:1)

如果你想匹配地图,你需要这样:

#{key1 := Pattern1, key2 := Pattern2, ...} = VarContainingAMap.

你可以阅读这篇论文: http://joearms.github.io/2014/02/01/big-changes-to-erlang.html

答案 3 :(得分:1)

@EWit,Felipe Mafra:

地图确实应该做的事情;这里缺少的是减少部分:

count(Str) -> M = count_chars(Str, maps:new()), % maps part, bad naming
    L = maps:to_list(M),                        % to be able to sum
    N = [X || {_,X} <- L],                      % strip the numbers
    lists:sum(N).                               % sum them up

count_chars([H|T], Map) when is_map(Map)->
    N = maps:get(H, Map, 0),
    count_chars(T, maps:put(H, N + 1, Map));
count_chars([], Map) -> Map.

答案 4 :(得分:-1)

匹配语法中的问题。

匹配使用:=。实施例

test(#{ key := Test }) -> Test.

对于相关的键和值使用=>。例: M = #{ keynew => 123 }

答案 5 :(得分:-1)

我猜您使用的是R17,因为此功能仅适用于此版本。

看一些文档,我的理解是你应该编写代码(我无法测试它,我仍在使用R15:o)

-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.

答案 6 :(得分:-2)

  

- 模(count_chars)。

     

%% API

     

-export([计数/ 1])。

     

count(Str) - &gt; count_chars(Str,maps:new())。

     当is_map(地图) - &gt;

时,

count_chars([H | T],Map)

N = maps:get(H, Map, 0),
count_chars(T, maps:put(H, N + 1, Map));
     

count_chars([],Map) - &gt;地图。