Elixir piping output to an anonymous function

685 views Asked by At

I'm currently learning elixir and i'm trying to print functions and their arity

print = fn ({function , arity}) ->
        IO.puts "#{function}/#{arity}" 
        end

Enum.__info__(:functions) |> Enum.each(print.())

this returns

** (BadArityError) #Function<0.60149952 in file:learn.exs> with arity 1 called with no arguments
    learn.exs:5: (file)
    (elixir) lib/code.ex:767: Code.require_file/2
2

There are 2 answers

2
Paweł Obrok On BEST ANSWER

Your issue is how you pass print to Enum.each. The variable print is already bound to a function. When you do print.() you're calling that function with no arguments and passing the result to Enum.each. What you want instead is to pass the print function itself as an argument to Enum.each. So:

Enum.__info__(:functions) |> Enum.each(print)
0
Adam Millerchip On

To add to what Paweł Obrok said, the reason this returns BadArityError is because print.() calls your print function with no arguments, but it expects a tuple as its argument.

That's actually masking the real problem - that you're calling the function instead of passing it as an argument. If you pass the print.() function call a tuple, thus resolving the BadArityError, you get the real error:

Enum.__info__(:functions) |> Enum.each(print.({:foo, :bar}))

foo/bar
** (BadFunctionError) expected a function, got: :ok
(elixir) lib/enum.ex:769: Enum."-each/2-lists^foreach/1-0-"/2
(elixir) lib/enum.ex:769: Enum.each/2

The print function is executed, performing the IO.puts "#{function}/#{arity}" as you can see from the foo/bar output, then returns the result of IO.puts/1, which is:ok, and passes that as the second argument to Enum.each. That causes BadFunctionError because Enum.each expects a function as its second argument, but you gave the result of executing the function - the atom :ok.