Подтвердить что ты не робот

Генераторы Ruby против генераторов Python

Я изучал сходства/различия между генераторами Ruby и Python (известный как Enumerators в Ruby), и насколько я могу сказать, они в значительной степени эквивалентны.

Однако одно замечание, которое я заметил, это то, что генераторы Python поддерживают метод close(), тогда как Ruby Generators этого не делают. Из документов Python метод close(), как говорят, выполняет следующие действия:

Вызывает генератор Exit в точке, где функция генератора была приостановлена. Если функция генератора затем вызывает StopIteration (путем выхода из нормального состояния или из-за уже закрытого состояния) или GeneratorExit (если не поймать исключение), close возвращает его вызывающему.

Есть ли веская причина, почему Ruby Enumerators не поддерживает метод close()? Или это случайный упущение?

Я также обнаружил, что Ruby Enumerators поддерживает метод rewind(), но генераторы Python не... есть ли причина для этого тоже?

Спасибо

4b9b3361

Ответ 1

Эта документация для метода перемотки немного редка. Но для того, чтобы "начать", генератор должен был бы сделать одну из двух вещей:

  • запомнить его полный вывод, повторить этот вывод после перемотки, затем возобновить то, что он делал до
  • reset его внутреннее состояние таким образом, чтобы повторять один и тот же вывод без других нежелательных побочных эффектов.

Вторая из них не всегда возможна; например, если генератор испускает байт-буферы из сети, выход не является полностью функцией внутреннего состояния. Но любой генератор, который использует первый метод, должен обязательно создавать большой и больший буфер в памяти, поскольку он используется. Такие генераторы предлагают небольшое преимущество в производительности по спискам.

Поэтому я заключаю, что метод Ruby rewind должен быть необязательным и не всегда поддерживаться конкретным классом перечислителя. Поэтому, если дизайнеры Python оценивают принцип замены Лискова, это приведет к тому, что они не потребуют такого метода во всех генераторах.

Ответ 2

Генераторы основаны на стеках, Ruby Enumerators часто специализируются (на уровне интерпретатора), а не на основе стека.

Ответ 3

Ruby Enumerator использует класс StopIteration внутри, см. Как работают Enumerators в Ruby 1.9.1?

(он просто завернут, если вы используете его в для каждого вызова). Поэтому я бы сказал, что они довольно близки. Это, как говорится, я не уверен, что должен делать закрытый метод для перечислителя, точно... очистка, возможно? (Генераторы Python, вероятно, извлекли бы выгоду из перемотки - хорошо заметьте, что в Ruby некоторые счетчики не реагируют на перемотку, поэтому они вызывают исключение, когда вы вызываете этот метод).