Скорочений запис для передачі методу як блоку в Ruby

У 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 виконує два важливі кроки:

  1. :method_name (наприклад, :upcase) – це символ, що представляє ім’я методу.
  2. &: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, коли це підходить, щоб зробити код компактнішим!