简单参数模式匹配中的头部不匹配

时间:2015-01-18 13:33:28

标签: erlang pattern-matching head mismatch

我有这段代码:

-module(info).
-export([map_functions/0]).
-author("me").



map_functions() ->
    {Mod,_} = code:all_loaded(),
    map_functions(Mod,#{});
map_functions([H|Tail],A) ->
    B = H:mod_info(exports),
    map_functions(Tail,A#{H => B});
map_functions([],A) -> A.

然而,每当我编译它时,我在第10行就会出现头部不匹配,即

map_funtions([H|Tail],A) ->

我确定这是一个非常基本的错误,但我无法理解为什么这不会运行。它是一个正确的模式匹配语法[H|Tail],具有相同名称但不同arities的三个函数用逗号分隔。

2 个答案:

答案 0 :(得分:2)

您的功能定义应为

map_functions() ->
    {Mod,_} = code:all_loaded(),
    map_functions(Mod, #{}).

map_functions([], A)       -> A;
map_functions([H|Tail], A) ->
    B = H:mod_info(exports),
    map_functions(Tail, A#{H => B}).

名称map_functions是相同的,但arity不是。在Erlang世界中,这意味着这两个功能完全不同:map_functions/0map_functions/2

另外,请注意我放了"基本情况"首先在map_functions/2(并使第一个条款' s返回值突然出现 - 将其分为两行更常见,但无论如何)。这有三个原因:清晰,养成先写基础案例的习惯(所以你不要意外地写出无限循环),而且经常有必要这样做,这样你就不会意外地掩盖通过匹配更高优先级子句中的每个参数来获得基本情况。

关于这个主题的一些扩展讨论在这里(针对Elixir和Erlang):Specify arity using only or except when importing function on Elixir

答案 1 :(得分:1)

具有相同名称但不同arity的函数不同,它们用点分隔。

代码:all_loaded返回一个列表,因此应该写第一个函数:

map_functions() ->
    Mods = code:all_loaded(),
    map_functions(Mods, #{}).

结果列表Mods是{ModName,BeamLocation}形式的元组列表,因此应编写第二个函数:

map_functions([], A)       -> A;
map_functions([{ModName,_}|Tail], A) ->
    B = ModName:module_info(exports),
    map_functions(Tail, A#{ModName => B}).

请注意,你应该深入研究erlang库并尝试使用更多惯用形式的代码,整个函数,使用列表理解,可以写成:

map_functions() ->
     maps:from_list([{X,X:module_info(exports)} || {X,_} <- code:all_loaded()]).