Блоки — одна из ключевых концепций в Ruby, без которой практически не обходится ни один кусок кода. Они очень похожи на обычные лямбда-функции, но имеют свои особые черты. Для хорошего понимания языка и происходящего в коде нужно понимать, как они устроены. Здесь мы немного копнем вглубь.
С одной стороны, у блоков есть особый синтаксис создания и передачи в функции как особого параметра.
# Открытие файла на запись и добавление туда строки
File.open('log.txt', 'w') { |f| f.write "[hexlet] #{Time.now} - User logged in\n" }
С другой стороны, сам блок — это объект, как и всё остальное в языке.
Его можно как создать независимо от функции, так и использовать. За
блоки в Ruby отвечает класс Proc
:
# Немного взрывает мозг то, что блок определяется через свой же синтаксис
square = Proc.new { |x| x**2 }
# Альтернативный синтаксис — proc { |x| x**2 }
square.call(4) # 16
С объектом-блоком можно делать всё то же самое, что и с другими объектами. В этом смысле он ведет себя как анонимная функция в любом языке. Однако, если мы захотим этот объект использовать как блок при передаче в функцию, то ничего не получится:
[1, 2].map square
# ArgumentError (wrong number of arguments (given 1, expected 0))
Хотя мы и имеем дело с блоком, всё же в примере выше он передается в
функцию как обычный объект первым параметром. Но метод map()
не
принимает на вход ничего, кроме блока, поэтому код завершается с
ошибкой. Блок, созданный как объект, невозможно напрямую использовать в
методах, ожидающих на вход блоки. Для этого нужен специальный синтаксис:
[1, 2].map &square # [1, 4]
Амперсанд, добавленный в начале переменной, содержащей блок, передает этот блок в функцию не как параметр, а как блок. Но тут нас ждет сюрприз:
# Завершится с ошибкой
[1, 2].map() &square
# Сработает
[1, 2].map(&square)
Это поведение не должно вас вводить в заблуждение. Выше мы видим
исключительно особенности синтаксиса. Блок выше не передается как
параметр, это легко увидеть, если посмотреть на определение метода
map()
. Он не принимает на вход никаких параметров.
Остались вопросы? Задайте их в разделе «Обсуждение»
Вам ответят команда поддержки Хекслета или другие студенты
Для полного доступа к курсу нужен базовый план
Базовый план откроет полный доступ ко всем курсам, упражнениям и урокам Хекслета, проектам и пожизненный доступ к теории пройденных уроков. Подписку можно отменить в любой момент.