1

I have this code:

-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.

However whenever I compile it I get a head mismatch on line 10 which is the

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

I'm sure this is a very basic error but I just cannot get my head around why this does not run. It is a correct pattern match syntax [H|Tail] and the three functions with the same name but different arities are separated by commas.

Bula
  • 2,398
  • 5
  • 28
  • 54
  • First `map_function` is function of zero arity so it should end with a dot, not comma. It's different [function](http://erlang.org/doc/reference_manual/functions.html) in erlang. Btw. [code:all_loaded()](http://erlang.org/doc/man/code.html#all_loaded-0) returns a list, not tuple. – Łukasz Ptaszyński Jan 18 '15 at 13:51
  • possible duplicate of [What does the "head mismatch" compiler error mean?](http://stackoverflow.com/questions/1802680/what-does-the-head-mismatch-compiler-error-mean) – Steve Vinoski Jan 18 '15 at 14:58

2 Answers2

2

Your function definition should be

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}).

The name map_functions is the same, but the arity is not. In the Erlang world that means these are two entirely different functions: map_functions/0 and map_functions/2.

Also, note that I put the "base case" first in map_functions/2 (and made the first clause's return value stick out -- breaking that to two lines is more common, but whatever). This is for three reasons: clarity, getting in the habit of writing the base case first (so you don't accidentally write infinite loops), and very often it is necessary to do this so you don't accidentally mask your base case by matching every parameter in a higher-precedence clause.

Some extended discussion on this topic is here (addressing Elixir and Erlang): Specify arity using only or except when importing function on Elixir

Community
  • 1
  • 1
zxq9
  • 13,020
  • 1
  • 43
  • 60
1

Function with same name but different arity are different, they are separated by dots.

code:all_loaded returns a list, so the first function should be written:

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

The resulting list Mods is a list of tuples of the form {ModName,BeamLocation} so the second function should be written:

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

Note that you should dig into erlang libraries and try to use more idiomatic forms of code, the whole function, using list comprehension, can be written:

map_functions() ->
     maps:from_list([{X,X:module_info(exports)} || {X,_} <- code:all_loaded()]).
Pascal
  • 13,977
  • 2
  • 24
  • 32