Edit: Since I wrote the question with a wrong example and didn't describe my issues, I'll do it again!
It seems to me that #flat_map, even though part of the Enumerator::Lazy class, is not very enumerable itself.
This example correctly works:
(1..Float::INFINITY).flat_map { |s| [s,s] }.take(4).to_a
The lazy implementation will also work:
(1..Float::INFINITY).flat_map { |s| [s,s] }.take(4).to_a
This will only take into account that the array generated within the block are finite. But they will also be fully evaluated before the take(4) call takes place. Which is not very lazyable.
Hence, this will fail:
(1..Float::INFINITY).lazy.flat_map { |i| (i..Float::INFINITY).map(&:to_i) }.take(4).force
Because the "infinity range to array" will be fully evaluated before the lazy call takes place. I would expect it to be "lazy by default", though. I mean, I do understand where the conundrum lies, but I'd expect it to happen this way: flat_map evaluates each instance lazy, knows that the result will be an array (or enumerable, at least), and will apply the lazy mechanism on it. hence, (i..Float::INFINITY).map(&:to_i) would be lazified (which doesn't seem very compatible, since the map(&:to_i) call will "force" it to be calculated).