Как получить размер клонированного ленивого перечислителя
У нас есть объект Enumerator::Lazy
a = [1,2,3].lazy.map {} #=> <Enumerator::Lazy: #<Enumerator::Lazy: [1, 2, 3]>:map>
a.size #=> 3
a.clone.size #=> nil
У кого-нибудь есть правильное объяснение такого поведения? я знаю это size
возвращает размер перечислителя или ноль, если он не может быть вычислен лениво. Когда мы клонируем объект, он возвращается
a.clone #=> <Enumerator::Lazy:<Enumerator::Generator:0x00007fdaa80218d8>:each>
1 ответ
Я знаю, что размер возвращает размер перечислителя или ноль, если его нельзя вычислить лениво.
size
для Enumerator
не обязательно реальная вещь (или, по крайней мере, не то, что можно было бы подумать), что может быть причиной того, что это изменение было осуществлено.
Например
[1,2,3].to_enum.size
#=> nil
[1,2,3].to_enum(:each) { 1 }.size #=> 1
#=> 1
или еще лучше
[1,2,3].to_enum(:each) { "A" }.size
#=> "A"
Когда мы клонируем объект, он возвращается
a.clone #=> <Enumerator::Lazy<Enumerator::Generator:0x00007fdaa80218d8>:each>
Похоже, что это изменение в 2.4, когда кажется, что он возвращается к: каждый метод (возможно, через enum_for
) потому что в 2.3 ссылка на map
сохраняется как размер. Очевидно, что из-за реверсии не произошло итерации, и размер не может быть определен "ленивым" образом и, таким образом, nil