[erlang-questions] why is the the output not a list

Stefan Schmiedl <>
Sat Sep 26 19:37:38 CEST 2015


Roelof Wobben (26.09. 17:47):

> Still something is not working as expected and I do not see what it is,
> 
> I have this code now :
> 
> -module(number_parser).
> 
> -export([scan/1]).
> 
> scan(String) ->
>      scan(String, []).
> 
> scan([], List) ->
>      List;
> 
> scan([Head | Rest], List_parse) when Head >= $0, Head =< $9 ->
>       digits(Head, Rest, List_parse);
> 
> scan( [$+ | Rest], List_parse) ->
>     scan(Rest, [$+ | List_parse] );
> 
> scan([32 | Rest], List_parse) ->
>      scan(Rest, List_parse).
> 
> 
> digits(Number, [Head | Rest] , List_parse ) when Head >= $0 , Head =< $9 ->
>     io:format("Number: ~w", [Number]),
>     io:format("Head: ~w", [Head] ),
>     New_number = (Number - 48) * 10 + Head - 48,
>     digits(New_number, Rest, List_parse);

Danger, Roelof!

You're calling digits with arguments from different domains.

Assuming "10 + 1":
- scan calls it with digits(49, "0 + 1", []), i.e. "a character from the
  input domain" as first argument
- digits binds New_number to 1*10+0 and calls itself with digits(10," + 1", []),
  i.e. "a number from the output domain" as first argument

At that point I stopped reading and tried to build a parser according to
your approach:

    -module(number_parser).
    -export([scan/1]).

    scan(String) -> scan(String, []).

    scan([],           Parsed) -> Parsed;
    scan([32|R],       Parsed) -> scan(R, Parsed);
    scan([$+|R],       Parsed) -> scan(R, ['+' | Parsed]);
    scan([H|_]=String, Parsed)
      when H >= $0, H =< $9    -> digits(0, String, Parsed).

    digits(N, [], Parsed)      -> [N | Parsed];
    digits(N, [H|R], Parsed)
      when H >= $0, H =< $9    -> digits(N*10+(H-$0), R, Parsed);
    digits(N, String, Parsed)  -> scan(String, [N | Parsed]).

In fact, I just did and these are the results:

    1> c(number_parser).
    {ok,number_parser}
    2> number_parser:scan("1+1").
    [1,'+',1]
    3> number_parser:scan("10 + 1").
    [1,'+',10]

So you'd still need to reverse the list after finishing the parsing:

    scan(String) -> lists:reverse(scan(String, [])).

yep, this works:

    4> c(number_parser).
    {ok,number_parser}
    5> number_parser:scan("10 + 1").
    [10,'+',1]

HTH,
s.


More information about the erlang-questions mailing list