Hi everyone,
while testing a function of mine I’ve stumbled upon a strange issue - when I make a mistake in an anonymous function it might try to call the parent function recursively and throw a confusing BadArityError
. Here is an example (can be pasted in a test file):
def external_fun(text) do
dummy_list = [[one: "1", two: "2"], [one: "3", two: "4"], [one: "5", two: "6"]]
text = Enum.reduce(dummy_list, text, fn(map, text) ->
text = text <> Keyword.get(map, :one)
text
end)
IO.inspect text
end
test "dev", %{conn: conn} do
external_fun("Test")
end
This should be green and give a “Test135” in console. Now when I make a mistake in the anonymous function by losing the second parameter like that:
text = Enum.reduce(dummy_list, text, fn(map) ->
text = text <> Keyword.get(map, :one)
text
end)
I get a ** (BadArityError) #Function ... external_fun/1> with arity 1 called with 2 arguments ([one: "1", two: "2"], "Test")
which is really confusing for such a “silly” mistake.
At first I thought it’s a parentheses issue (s. http://stackoverflow.com/questions/22591141/piping-maps-is-trying-to-call-the-original-function), but I already use parentheses almost all the time, so I seem to be unable to be more explicit in this case.
My questions are:
-
What actually happened? Why does reduce’s callback reaches to the parent function?
-
Is there a way to prevent such issues by changing my coding style (similar to using parentheses more often), should I maybe prefer named functions as callbacks? I’ve just spent about 20 minutes solving this issue and would like to make the most of it in the future