Today’s Ruby Tuesday is on Enumerable#flat_map.
Enumerable#flat_map
became this week’s topic, because yesterday I was doing some exercises in Elixir, and was thinking I could use the flat_map that is defined in Elixir to solve the solution, but it wasn’t working the way I thought it should.
I was getting confused with why it was failing, and I went to check my assumptions of how flatmap
works in Erlang, and it behaved the same way. Which, after seeing it, is unsurprising given their common runtime, but I couldn’t figure out where my mental model of flat_map
was coming from, other than the name alone.
It was time to pull up a Ruby REPL, and see if Ruby was behaving the way I thought it “should” be behaving.
[1, [[2], 3]].flat_map {|x| x * x} # TypeError: no implicit conversion of Array into Integer # from (pry):11:in `*'
No! It failed in Ruby as well.
I had myself convinced that flat_map
was the equivalent of doing a Array#flatten
, and then calling Enumerable#map
on the result.
[1, [[2], 3]].flatten.map {|x| x * x} # [1, 4, 9]
This is the equivalent of what I was trying to get, and flat_map
wasn’t working for me, and obviously, it is not the way Enumerable#flat_map
behaves either.
After looking deeper, I realized that somehow, I had the application of the conceptual flatten
and map
methods swapped.
The way Enumerable#flat_map
actually behaves is as if you called map
on the Enumerable
, and then called flatten
on the results.
[[:a, 1], [:b, 2], [:c, 3]].flat_map {|item, count| Array.new(count, item) } # [:a, :b, :b, :c, :c, :c] [[:a, 1], [:b, 2], [:c, 3]].map {|item, count| Array.new(count, item) } # [[:a], [:b, :b], [:c, :c, :c]] [[:a, 1], [:b, 2], [:c, 3]].map {|item, count| Array.new(count, item) }.flatten # [:a, :b, :b, :c, :c, :c]
And if an Enumerable
is not returned by the map block passed to Enumerable#flat_map
, it behaves the same as if you just called Enumerable#map
.
[1, 2, 3].flat_map {|x| x * x} # [1, 4, 9] [1, 2, 3].map {|x| x * x} # [1, 4, 9]
Here is hoping that this saves you some confusion as well.
–Proctor
Pingback: Erlang Thursday – lists:flatmap/2Proctor It | Proctor It