С точки зрения языкового дизайна, почему рубиновые блоки не являются первоклассными?
Насколько я знаю, в основном из соображений производительности.Рассмотрим:
def test_yield
yield
end
def test_block &block
block.call
end
la = lambda {}
def test_lambda l
l.call
end
Затем сравните результаты с пустым блоком для первых двух, по сравнению с третьим - с новым la
на вызов или с тем же la
, и обратите внимание, насколько быстрее идет доходностьв каждом случае.Причина в том, что явная переменная & block создает объект Proc, как это делает лямбда, в то время как простая отдача - нет.
Побочный эффект (который я фактически нашел, использует для рекурсивной передачи пропущенных блоков черезиспользование объекта proc), вы не можете уступить в proc или lambda вне какой-либо области видимости:
foo = proc { yield if block_given? }
foo.call { puts 'not shown' }
def bar
baz = proc { yield if block_given? }
baz.call
end
bar { puts 'should show' }
Это потому, что, как я понял, (я потерял многоволос из-за этого, пока не галочка), block_given?отправляется main, когда foo вызывает его, и bar, а не baz, когда он оценивается в bar.