Why don't Ruby Enumerator
behave like Enumerator::Lazy
by default?
Is there any case where someone would want use a non-lazy Enumerator
?
Edited:
A comment to backward compatibility answers below, explaining why I'm not yet convinced:
Say we had added these 'breaking' changes to Ruby 2.0.0, which is a major version, you would test your code (especially if you're going to production) thoroughly before making the switch, no?
Edit#2
I suspected it has to do with efficiency (let me know if anything is wrong), so I did the following benchmark: (of course there are places where lazy is better. this is to demonstrate, potentially, why Ruby is not using lazy all the time?)
require 'fruity'
require 'prime'
compare do
lazy {
g = Prime::EratosthenesGenerator.new; 1000.times { g.lazy.take(100).to_a }
}
diligent {
g = Prime::EratosthenesGenerator.new; 1000.times { g.take(100).to_a }
}
end
I get the following: (maybe due to the calling of .lazy
method instead of using Enumerator::Lazy
from the beginning?)
diligent is faster than lazy by 19.999999999999996% ± 1.0%
Enumerator::Lazy is a special type of Enumerator , that allows constructing chains of operations without evaluating them immediately, and evaluating values on as-needed basis. In order to do so it redefines most of Enumerable methods so that they just construct another lazy enumerator.
Enumerator, specifically, is a class in Ruby that allows both types of iterations – external and internal. Internal iteration refers to the form of iteration which is controlled by the class in question, while external iteration means that the environment or the client controls the way iteration is performed.
Make laziness the default would be a breaking change for any code that expects/relies on side-effects.
Any previous usage of Enumerator would need to be examined and tested. The "safest"/"sane" approach is simply to keep the non-lazy behavior as the default - while providing a Lazy alternative.
Some fundamental/previous design decisions are not so easily discarded; Enumerators are supported as far back as Ruby 1.8.7.
Probably for compatibility. Lazy enumerators were introduced recently, and many code depend on enumerators being non-lazy.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With