Передача аргумента типа карты в функцию в Erlang жалуется на ошибку

Вот мой фрагмент кода.

%% test.erl
-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.

%% ErShell
1> c(test).
test.erl:19: illegal use of variable 'H' in map
test.erl:20: illegal use of variable 'H' in map
test.erl:20: variable 'N' is unbound
test.erl:22: illegal use of variable 'H' in map
error

Я просто не знаю, почему он жалуется на такую ​​​​ошибку, так как следующий код просто отработал нормально:

%% test2.erl
birthday(#{age := N} = Person) ->
    Person#{age := N+1}.

%% ErShell
1> c(test2).
2> test2:birthday(#{age => 333}).
#{age => 334}

Заранее спасибо.


person Judking    schedule 14.05.2015    source источник


Ответы (2)


Причина проста: карта еще не полностью реализована. Взгляните на: http://learnyousomeerlang.com/maps.

Кроме того, вы можете подумать об альтернативных реализациях, используя то, что уже возможно с картами:

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

count_characters([H|T], Map) ->
    N = maps:get(H, Map, 0),
    count_characters(T, maps:put(H, N + 1, Map));
count_characters([], Map) -> Map.
person Marc Lambrichs    schedule 14.05.2015
comment
Просто как дополнение: вы, вероятно, нашли свой код в книге Джо по программированию на Erlang, 2-е изд., а? Он уже в списке опечаток. Когда-нибудь в будущем это сработает. - person Marc Lambrichs; 14.05.2015

На сегодняшний день (2021 г.) эта функция все еще не реализована. Однако для больших ключей рекомендуется использовать функцию update из соображений эффективности:

count_characters([H|T], Map) ->
    case N = maps:get(H, Map, 0) of
       0 -> count_chars(T, Map#{H => 1});
       _ -> count_chars(T, Map#{H := N+1}) % update function maps:udpate(...)
    end;
person VladiC4T    schedule 23.03.2021