У Ruby можна передавати методи як блоки за допомогою скороченого запису &:method_name
. Це зручний спосіб викликати один і той самий метод для всіх елементів колекції без написання повного блоку { |x| x.method_name }
.
Як це працює?
Звичайний запис із блоком
Зазвичай, якщо потрібно викликати метод на кожному елементі масиву, ми пишемо блок:
array = ["apple", "banana", "cherry"]
result = array.map { |fruit| fruit.upcase }
puts result
Вивід:
["APPLE", "BANANA", "CHERRY"]
Скорочений запис за допомогою &:method_name
Те саме можна записати компактніше:
result = array.map(&:upcase)
puts result
&:upcase
автоматично розгортається у { |fruit| fruit.upcase }
Що відбувається під капотом?
Ruby виконує два важливі кроки:
:method_name
(наприклад,:upcase
) – це символ, що представляє ім’я методу.&:method_name
перетворює символ у Proc-об’єкт за допомогою методуSymbol#to_proc
.
Еквівалентний запис:
proc_object = :upcase.to_proc
result = array.map(&proc_object)
Обмеження &:method_name
Не можна передавати аргументи
Якщо метод потребує аргументів, &:method_name
не спрацює.
Наприклад, це НЕ ПРАЦЮВАТИМЕ:
numbers = [1, 2, 3]
numbers.map(&:+(10)) # Помилка!
Рішення: Використовуємо блок:
numbers.map { |n| n + 10 }
Не працює з нестандартними викликами
Метод повинен бути без аргументів і викликатися без додаткових параметрів.
hash = { a: 1, b: 2, c: 3 }
hash.keys.map(&:to_sym) # ✅ Працює
hash.map(&:first) # ❌ Помилка, бо `.first` не метод окремих елементів
hash.map { |k, v| k } # ✅ Правильний варіант
Ітого
&:method_name
– це короткий запис для передачі методу об’єкта у блок.
Використовується, коли потрібно викликати один метод без аргументів.
Покращує читабельність коду, але не підходить для методів із параметрами.
Приклад порівняння:
# Довгий варіант
array.map { |x| x.method_name }
# Скорочений варіант
array.map(&:method_name)
Використовуйте &:method_name
, коли це підходить, щоб зробити код компактнішим!