Блоки (blocks) — это одна из фундаментальных возможностей Ruby, позволяющая передавать код в методы. Рассмотрим все способы передачи блоков и их особенности.
Самый распространённый способ — использование do...end
или {...}
:
# Способ 1: с do...end (для многострочных блоков)
[1, 2, 3].each do |num|
puts num * 2
end
# Способ 2: с {...} (для однострочных блоков)
[1, 2, 3].each { |num| puts num * 2 }
Можно явно указать параметр блока через &
:
def process_items(items, &block)
items.each(&block)
end
process_items([1, 2, 3]) { |n| puts n * 3 }
Особенности:
block_given?
block.call
Метод может получать блок неявно и вызывать его через yield
:
def print_twice
yield if block_given?
yield if block_given?
end
print_twice { puts "Hello!" }
# Выведет "Hello!" два раза
Можно передать уже созданный объект Proc или lambda:
doubler = Proc.new { |x| x * 2 }
[1, 2, 3].map(&doubler) # => [2, 4, 6]
tripler = lambda { |x| x * 3 }
[1, 2, 3].map(&tripler) # => [3, 6, 9]
Способ | Доступ через | Можно проверить наличие? | Становится Proc? |
---|---|---|---|
{...} /do...end | yield | block_given? | Нет |
Явный &block | block.call | Да (через block ) | Да |
Proc/Lambda | call | Всегда есть | Да |
Ruby не поддерживает напрямую, но можно использовать хитрости:
def two_blocks(default1, default2, &main_block)
block1 = Proc.new { default1 }
block2 = Proc.new { default2 }
[main_block, block1, block2]
end
def calculate(a, b)
yield(a, b)
end
result = calculate(5, 3) { |x, y| x * y } # => 15
do...end
для многострочных блоков, {...}
для однострочныхblock_given?
, если блок опционален&block
def repeat(times)
times.times { yield } if block_given?
end
repeat(3) { puts "Ruby!" }
def transform(array)
array.map { |item| yield(item) }
end
transform([1, 2, 3]) { |x| x**2 } # => [1, 4, 9]
Резюмируем: в Ruby есть несколько способов передачи блоков в методы — от неявного использования yield
до явного объявления параметра с &
. Выбор конкретного способа зависит от потребностей: для простых случаев достаточно yield
, для более сложных сценариев лучше использовать явное объявление блока как Proc. Блоки — мощный инструмент Ruby, делающий код более выразительным и гибким.