erlang 字符串函数子句匹配

wbgh16ku  于 2022-12-08  发布在  Erlang
关注(0)|答案(3)|浏览(235)

I'm running into a problem when writing some simple erlang code for an old Advent of Code task.
The following program is supposed to read lines, group characters in a string by occurrence and then count the number of lines that have a repeat of three characters.

count_occurrences([], Map) -> Map;
count_occurrences([H | T], Map) ->
    count_occurrences(T, maps:put(H, maps:get(H, Map, 0) + 1, Map)).

count(Line, Count) ->
    Map = count_occurrences(Line, #{}),
    case lists:member(3, maps:values(Map)) of
        true -> Count + 1;
        false -> Count
    end.

run() ->
    {ok, Binary} = file:read_file("data.txt"),
    Lines = binary:split(Binary, <<"\n">>, [global]),
    Result = lists:foldl(fun count/2, 0, Lines),
    Result.

However, I get this error message:

10> c(day2).   
{ok,day2}
11> day2:run().
** exception error: no function clause matching day2:count_occurrences(<<"bpacnmelhhzpygfsjoxtvkwuor">>,#{}) (day2.erl, line 5)
     in function  day2:count/2 (day2.erl, line 10)
     in call from lists:foldl/3 (lists.erl, line 1263)

I don't understand why <<"bpacnmelhhzpygfsjoxtvkwuor">>,#{} doesn't match the second "count_occurrences" function clause - a string is the same as a list, right? Why doesn't it match [H | T]?

qij5mzcb

qij5mzcb1#

看看这个例子:

-module(a).
-compile(export_all).

go([_H|_T], _X) ->
    "First arg was a list";
go("a", _X) ->
    "First arg was a string";
go(<<"a">>, _X) -> 
    "First arg was a binary".

在 shell 中:

5> a:go(<<"a">>, #{a=>1, b=>2}).
"First arg was a binary"

以及:

6> a:go("a", #{a=>1, b=>2}).    
"First arg was a list"

字符串和列表是一样的,对吧
是的,双引号字符串是创建整数列表的快捷方式,其中列表中的整数是字符的ascii代码。因此,上面的第二个函数子句永远不会匹配:
a. erl:6:警告:此子句不能匹配,因为第4行的前一个子句始终匹配
但是......二进制,比如<<"abc">>不是字符串,因此二进制不是创建整数列表的快捷方式。

8> "a" =:= [97].
true

好吧,你知道的。但是,现在:

9> "a" =:= <<"a">>.
false

10> <<"a">> =:= <<97>>.
true

11> "a" =:= <<97>>.
false

最后:

13> <<"abc">> =:= <<97, 98, 99>>.
true

最后一个例子表明,在二进制文件中指定双引号字符串只是在二进制文件中指定逗号分隔的整数列表的一种快捷方式--然而,在二进制文件中指定双引号字符串并不会以某种方式将二进制文件转换为列表。

wlzqhblo

wlzqhblo2#

请注意,您也可以使用稍微不同的语法来逐一查看二进制档:

count_occurrences(<<>>, Map) -> Map;
count_occurrences(<<H, T/binary>>, Map) ->
    count_occurrences(T, maps:put(H, maps:get(H, Map, 0) + 1, Map)).

默认情况下,H假定为字节,但您可以添加修饰符以指定要选择的位数等。有关位语法,请参阅文档。

h4cxqtbf

h4cxqtbf3#

出现此错误的原因是函数count_occurrences/2的第一个参数应为list-[<<"bpacnmelhhzpygfsjoxtvkwuor">>]"bpacnmelhhzpygfsjoxtvkwuor",但实际上是binary-<<"bpacnmelhhzpygfsjoxtvkwuor">>。请仔细检查第10行模块day2.erl的函数count/2中的输入数据Line

1> is_list([]).
true
2> is_list("").
true
3> is_list(<<"">>).
false
4> is_list(binary_to_list(<<"">>)).
true

相关问题