Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

illegal pattern in map of Erlang

Tags:

map

erlang

The code is below:

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

when compiling the code in the Erlang shell, it reported the following errors:

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

I'm new in Erlang, and just can't find anything wrong by myself. How to correct it?

like image 605
geeker Avatar asked Apr 16 '14 10:04

geeker


1 Answers

The answers from IRC (#erlang@freenode):

  1. variables as keys in matches are not supported yet (release 17.0)
  2. A more general issue affects matching arguments of a function: line 7's H is matched 2 times; or once and used to match N then. (This issue also appears with binaries)

This should be solved in the coming releases.

As of release 17 this works:

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

Here is another version (only tested on 18) that is slightly more similar to the one in the book:

-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.
like image 147
fenollp Avatar answered Oct 05 '22 19:10

fenollp