`File.enum_for (: readlines, ...)` не перечисляет - PullRequest
0 голосов
/ 14 декабря 2018

Почему этот перечислитель неожиданно возвращает пустой массив:

> File.enum_for(:readlines, '/usr/share/dict/words').take(1)
=> []

, а этот возвращает правильно:

File.enum_for(:readlines, "/usr/share/dict/words").each{}.take(1)
=> ["A\n"]

Для сравнения, другие перечислители будут работать без each:

> "abc".enum_for(:each_byte).take(1)
=> [97]

Что действительно странно в случае File.readlines, так это то, что тело each фактически не выполняется:

File.enum_for(:readlines, "/usr/share/dict/words").
     each{|e| p e; raise "stop" }.take(2)
=> ["A\n", "a\n"]

Это на ruby ​​2.5.3,Я пробовал код как в pry, так и в ruby -e однострочнике, с одинаковыми результатами.

1 Ответ

0 голосов
/ 15 декабря 2018

Видимо enum_for / to_enum работает только с методом, yield с.Автор благодарности @Anthony за то, что заставил меня осознать это.

Это эквивалент того, что я пытался сделать:

# whoops, `to_a` doesn't yield
[1,2,3].enum_for(:to_a).take(1)
=> []

# Works, but `enum_for` isn't really meant for this, and it's very possible this should be
#  considered undefined behavior.
# In this case, as in `File.readlines`, the `each` block isn't really executed.
> [1,2,3].enum_for(:to_a).each{}.take(1)
=> [1]

Другая интересная вещь - это вызов each{} на одном изэти "странные перечислители", кажется, действуют так, как будто перечислимый метод (например, to_a) был вызван напрямую.Но, конечно, это бессмысленно.

> arr = [1,2,3]
> arr.object_id
=> 70226978129700
> arr.to_a.object_id
=> 70226978129700
# same as calling `to_a` - doesn't create a new array!
> arr.enum_for(:to_a).each{}.object_id
=> 70226978129700

В случае File.readlines его реализация просто считывает строки и возвращает их в одном массиве;это не yield ничего.

...