Присвоение возвращаемых значений блоков метода в ruby - PullRequest
0 голосов
/ 09 февраля 2020

Принимая объяснение документации ruby API для String # each_char , он предлагает получить строку при вызове этого метода вместе с данным блоком.

each_char {|cstr| block } → str

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

irb(main):001:0> v = "foobar".each_char { |c| c + "." }
=> "foobar"

Проблема, которую это вызывает, состоит в том, что назначение этого вызова метода довольно обманчиво, поскольку оно не возвращает ожидаемый результат, а просто строку, с которой мы начали:

irb(main):002:0> puts v
foobar
=> nil

Использование инструкции break - единственный способ вернуть значение из блока во время присвоения переменной.

irb(main):003:0> v = "foobar".each_char { |c| break c + "." }
=> "f."

Вопросы:

Почему методы, вызываемые с помощью блока, не возвращают вычисленные ими значения? Является ли это просто особым случаем с этой реализацией, поскольку я уверен, что Array # каждый возвращает новый массив. Но опять же, String # each_byte также ничего не возвращает. Что здесь происходит?

Какой самый элегантный способ присвоения обработанных значений из блока? Является ли обезьяна исправлениями вариант?

Дополнительная информация: я использую ruby 2.6.3

(Примечание: я видел [этот вопрос от Эда], но в 2017 году был сделан вывод, что использование оператор присваивания приводит к синтаксическим ошибкам, ruby явно не ведет себя так в случае Array#each.)

1 Ответ

1 голос
/ 09 февраля 2020

Прежде всего, #each не возвращает новый массив. Каждый означает, что он будет обрабатывать каждый элемент массива, но в конце концов он вернет свой получатель.

Чтобы напечатать что-то из блока, вам нужно использовать print или puts.

Есть несколько способов присвоить результат каждому:

Первый: использование # with_object

=> v = "foobar".each_char.with_object('') { |c, obj| obj << c + '.'  }
=> v
=> "f.o.o.b.a.r."

Еще один: использование #chars и #join

=> v = "foobar".chars.join('.')
=> v
=> "f.o.o.b.a.r"
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...