In "Programming Elixir 1.6", there is this example:
authors = [
%{name: "José", language: "Elixir"},
%{name: "Matz", language: "Ruby"},
%{name: "Larry", language: "Perl"}
]
languages_with_an_r = fn (:get, collection, next_fn) ->
for row <- collection do
if String.contains?(row.language, "r") do
next_fn.(row)
end
end
end
IO.inspect get_in(authors, [languages_with_an_r, :name])
#=> ["José", nil, "Larry"]
I have some questions about the example:
The function that you pass to
get_in()is called by Elixir and the first argument that Elixir passes to the function is the atom:get. How is that useful?The third argument that Elixir passes to the function is a function that gets bound to
next_fn. Where in the docs does it say how many arguments that function takes? What does that function do? How are we supposed to usenext_fn? It seems to me that theforconstruct is already iterating over each map in the list, so what does the namenext_fneven mean? Isnext_fnused to somehow tag a row for further consideration?Where does nil in the result list come from?
And, I'll say this: that example is one of the poorest examples I've seen in any programming book--because there's not adequate discussion of the example, and the docs for get_in() suck. That means there are at least three people who don't understand get_in(): me, Dave Thomas, and whoever wrote the docs--because if you can't explain something, they you don't understand it yourself.
Edit: I found this in the source code:
def get_in(data, [h | t]) when is_function(h),
do: h.(:get, data, &get_in(&1, t))
What does &1 refer to there? data? Why not just use data, then?