рубиновые блоки не первоклассные - PullRequest
7 голосов
/ 14 июля 2011

С точки зрения языкового дизайна, почему рубиновые блоки не являются первоклассными?

Точно так же я думаю, что блоки должны быть на самом деле лямбдами, что избавляет от необходимости громоздкого синтаксиса, такого как proc {...}. Call или & proc или lambda или Proc.new. Это избавило бы и от необходимости доходности.

Ответы [ 2 ]

6 голосов
/ 14 июля 2011

С точки зрения языкового дизайна, почему рубиновые блоки не являются первоклассными?

Насколько я знаю, в основном из соображений производительности.Рассмотрим:

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.

2 голосов
/ 14 июля 2011

lambda и proc (и блок) имеют разную семантику.Procs / блоки имеют нелокальные возвращения и менее требовательны к арности;Лямбды более похожи на методы в своем поведении.На мой взгляд, это различие полезно, и procs / blocks / lambdas НЕ должны объединяться, как вы предлагаете.

...