patrón ilegal en el mapa de Erlang
(7)
-módulo (count_chars).
%% API
-exportación ([contar / 1]).
count (Str) -> count_chars (Str, maps: new ()).
count_chars ([H | T], Mapa) cuando is_map (Mapa) ->
N = maps:get(H, Map, 0), count_chars(T, maps:put(H, N + 1, Map));
count_chars ([], Mapa) -> Mapa.
El código está abajo:
-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.
al compilar el código en el shell de Erlang, se informaron los siguientes errores:
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
Soy nuevo en Erlang, y simplemente no puedo encontrar nada malo. ¿Cómo corregirlo?
@EWit, Felipe Mafra:
los mapas hacen exactamente lo que se supone que deben hacer; lo que falta aquí es la parte de reducción:
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.
Citado de OTP 17.0 Notas de la versión :
OTP-11616 == erts stdlib hipe dialy compilador 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.
Actualmente puedes usar el módulo de maps
para implementar 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.
Cuando quieras hacer coincidir un mapa, necesitas lo siguiente:
#{key1 := Pattern1, key2 := Pattern2, ...} = VarContainingAMap.
Puedes leer el artículo: http://joearms.github.io/2014/02/01/big-changes-to-erlang.html
Las respuestas de IRC (# erlang @ freenode):
- Las variables como claves en coincidencias no son compatibles todavía (versión 17.0)
- Un problema más general afecta a los argumentos coincidentes de una función: la línea 7 de
H
se compara 2 veces; o una vez y solía coincidir con N entonces. (Este problema también aparece con binarios)
Esto debería ser resuelto en los próximos lanzamientos.
A partir del lanzamiento 17 this funciona:
-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.
Aquí hay otra versión (solo probada en 18) que es ligeramente más parecida a la del libro:
-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.
Problema en la sintaxis de coincidencia.
Para el uso del partido :=
. Ejemplo
test(#{ key := Test }) -> Test.
Y para clave asociada y uso de valor =>
. Ejemplo: M = #{ keynew => 123 }
Supongo que está utilizando R17, ya que esta función solo está disponible desde esta versión.
Mirando un documento, entiendo que debes escribir el código de esa manera (no puedo probarlo, todavía estoy usando 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.