Черт возьми, что за хрень эти свободно плавающие фрагменты кода, смежные с этим #методом, который вызывается (чешет затылок). Хм, я уверен, что должен был видеть что-то подобное раньше .. где-то; ах, но, конечно же, Array#each не имеет смежного кода после вызова метода?

Блоки Ruby можно найти в каждом приложении или скрипте Ruby. Скорее всего, вы использовали блоки Ruby, даже не подозревая об этом — при условии, что вы использовали такие методы, как Array#each.

доказательство 1

Мы углубимся в этот фрагмент кода по мере продвижения в этой статье. Но пока важно понимать, что у нас есть массив из 5 целых чисел: [1, 2, 3, 4, 5]; этот экземпляр класса Array вызывает метод #each; Рядом с методом #each мы находим... звук труб … блок Ruby. Вот и все. Были сделаны! Тем не менее, вы можете продолжить чтение, если хотите — я вас умоляю.

Что такое блоки Ruby?

  • Вкратце: блоки Ruby — это анонимные функции, которые вызываются при вызове метода.
  • В приведенном выше примере (пример 1) с использованием Array#each соседний блок Ruby принял форму (пример 2):

доказательство 2

  • В приведенном выше фрагменте кода обратите внимание на синтаксис блока — это одна из форм выражения блока (обычно используется, когда логика блока занимает несколько строк) — альтернативноблок можно создать с помощью фигурных скобок (например, видно ниже). Оба блока по сути одинаковы.

доказательство 3

  • Между «do/end» или «{ }» находится логика блока.
  • Ruby полон синтаксического сахара, и блоки Ruby не являются исключением. Блоки Ruby являются частью синтаксиса Ruby — когда синтаксический анализатор Ruby читает блок, он автоматически связывает его с вызываемым методом (#each) в нашем примере выше.

Основной пример

  • Вот базовый пример использования блока Ruby.
  • Здесь определен метод с именем #pass_a_block. Затем вызывается метод и передается соседний блок. Затем блок выполняется из тела вызываемого метода.
  • Обратите внимание, что ключевое слово yield отвечает за выполнение логики блока.

доказательство 4

Как вызывается блок внутри тела метода?

  • Хорошо, теперь, когда мы создали метод и передали этому методу блок при вызове, вы можете спросить себя: как блок был выполнен?
  • Как упоминалось выше, как только синтаксический анализатор Ruby распознает блок рядом с вызываемым методом, он свяжет этот блок с выполняемым методом.
  • Если в теле выполняемого метода есть ключевое слово yield, yield будет действовать как связующее звено и выполнять блок в контексте метода.
  • Короче говоря, при выполнении метода ключевое слово yield заменяется логикой связанного блока.
  • По сути, вы предоставляете изменяемый код определенному методу — примерно как в приведенном ниже примере, хотя исходный метод не переопределяется.

доказательство 5

  • Примечание. Блок всегда можно передать или привязать к методу, хотя, если ключевое слово yield отсутствует в теле соответствующего метода, блок не будет использоваться (см. ниже).

приложение 6

Возвращаемое значение блока

  • Внутри блока ключевое слово возврата явно не используется.
  • Возвращаемое значение блока является неявным.
  • Последняя строка выполнения внутри блока будет возвращаемым значением.
  • Если yield является последней строкой, выполняемой в методе, то возвращаемое значение метода будет возвращаемым значением блока.
  • Вы также можете присвоить возвращаемое значение yield (или выполнение блока) переменной и в дальнейшем использовать его в последовательной логике в теле вашего метода (см. ниже).

приложение 6

Блоки и их аргументы

Я намеренно опустил эту тему в нескольких последних разделах, чтобы предоставить знакомый пример (Array#each).

Но время пришло — спорить бесполезно 😉.

  • Блоки могут быть записаны либо с включением аргументов или без них. Лучше всего это продемонстрировать на примере (см. ниже).

доказательство 7

доказательство 8

  • Блокам можно передавать несколько аргументов.
  • Ожидаемые аргументы блока определяются в списке, разделенном запятыми, между набором каналов т.е. |argument_one, argument_two|
  • Аргументы, переданные для получения , т.е. yield(my_block_arg) соответствуют аргументам блока, определенным между его каналами, т.е. |my_block_arg|
  • Давайте объединим часть полученной информации и напишем собственный метод Array#each.

доказательство 9

  • Сначала мы открываем класс Array и переопределяем метод Ruby Array#each нашим собственным упрощенным методом #each.
  • В этом методе мы просто создаем индексную переменную, объявленную как i.
  • Затем мы перебираем self (экземпляр Array).
  • В цикле мы вызываем yield — последовательно передавая каждый элемент по мере того, как мы перебираем экземпляр Array.
  • Когда мы вызываем наш метод #each для экземпляра Array т.е.[1, 2, 3, 4, 5].each — мы передаем в #each блок, который принимает аргумент (который будет элементом массива, переданным для yield из тела метода).
  • Оттуда мы просто выводим каждый элемент массива * 10 .

Лексическое окружение блока

  • Блоки имеют доступ ко всем переменным из среды, в которой они определены (см. ниже).

приложение 10

Неявные блоки и доходность

  • Во всех наших примерах мы передаем блоки методам неявно, т.е. никогда в наших методах мы явно не определяли наш метод для ожидания блока.
  • Это связано с тем, что yield является специальным ключевым словом Ruby, оно находит и вызывает блок, который был передан методу.
  • Мы можем явно передавать блоки методам — ну вроде того. Я расскажу об этом в одном из будущих руководств — или не стесняйтесь продолжить исследование блоков и процессов, если вы просто не можете ждать.

Сделать «доходность» необязательным в наших методах

  • Ключевое слово yield будет искать и выполнять логику блоков И если yield присутствует в теле метода — и этот метод вызывается без блока, вам лучше в это поверить.. урожай будет жаловаться.
  • Чтобы предотвратить ошибку, вы можете написать метод для вызова yield только в том случае, если метод вызывается с блоком (см. ниже).

приложение 11

Явные блоки и процедуры

  • Вот краткий обзор для тех, кто интересуется методами, вызываемыми с явными блоками:

  • Я углублюсь в предмет Procs в следующем уроке.

примечание: если вы вызываете метод без круглых скобок, вы столкнетесь со странным поведением, если используете синтаксис блока ‘{ }’; поскольку блок будет привязан к последнему аргументу, противоположному вызываемому методу. Менее важные — и почти нет необходимости упоминать об этом в данный момент. Не стесняйтесь игнорировать этот пункт.

Спасибо, что нашли время прочитать мою статью! Я Full Stack Developer из Торонто, Канада🇨🇦 . В настоящее время я работаю в Swift Medical, ведущем приложении MedTech.