[erlang-questions] count_characters example from Programming Erlang

zxq9 zxq9@REDACTED
Fri Feb 5 05:58:19 CET 2016


On 2016年2月4日 木曜日 20:59:47 Mark Bucciarelli wrote:
> Hi,
> 
> I'm trying to compile the count_characters example from Programming Erlang
> book.
> But I get an error, and I can't see a typo.
> 
> -module(t).
> -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.
> 
> 1> c(t).
> t.erl:7: variable 'H' is unbound
> error
> 2>
> 
> This behavior contradicts the point made in the text:
> 
>         There are two things to note about count_characters/2.
>         In the first clause, the variable H inside the map is also
>         defined outside the map and thus is bound (as required).
>         In the second clause, we use map_extend to add a new
>         key to the map.

Someone will be along to sharpshoot this statement, but I'm pretty sure
that the book was written based on the proposed map implementation, and
the actual implementation turned out to not allow match-assignment on keys.

I believe variable map keys are permitted in R18, but not sure about this
particular case.

A working version can be built this way, though:

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

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

  count_characters([Char | Rest], Counts) ->
      Count = maps:get(Char, Counts, 0),
      count_characters(Rest, maps:put(Char, Count + 1, Counts));
  count_characters([], Counts) ->
      Counts.

Same principle, just slightly different way of going about it.

The difficulty of writing a book against an unimplemented and still
shifting standard is daunting. I'm amazed he was even able to!

-Craig



More information about the erlang-questions mailing list