屈服于一个匿名的块
我没有理解以下行为(另请参见此SO线程 ):
def def_test puts 'def_test.in' yield if block_given? puts 'def_test.out' end def_test do puts 'def_test ok' end block_test = proc do |&block| puts 'block_test.in' block.call if block puts 'block_test.out' end block_test.call do puts 'block_test' end proc_test = proc do puts 'proc_test.in' yield if block_given? puts 'proc_test.out' end proc_test.call do puts 'proc_test ok' end
输出:
def_test.in def_test ok def_test.out block_test.in block_test ok block_test.out proc_test.in proc_test.out
我不介意明确声明&block变量并直接调用它,但我更理想地想了解为什么我最终需要它。
lambda
是一个闭包,它似乎捕获了block_given?
并阻止其外部范围。 这种行为确实有意义,因为块或多或少是外部方法的隐含参数; 如果需要,您甚至可以在命名参数中捕获块:
def def_test(&block) frobnicate &block end
所以即使没有命名,该块也是参数列表的一部分。
考虑一下这段简单的代码:
def f lambda do puts "\tbefore block" yield if block_given? puts "\tafter block" end end puts 'Calling fw/o block' x = f; x.call puts puts 'Calling fw/ block' x = f { puts "\t\tf-block" }; x.call puts puts 'Calling fw/o block but x with block' x = f; x.call { puts "\t\tx-block" } puts puts 'Calling fw/ block and x with block' x = f { puts "\t\tf-block" }; x.call { puts "\t\tx-block" }
这为1.9.2产生了以下内容:
Calling fw/o block before block after block Calling fw/ block before block f-block after block Calling fw/o block but x with block before block after block Calling fw/ block and x with block before block f-block after block
此外, Proc#call
(AKA proc ===
)不会阻止:
prc === obj→result_of_proc
调用块,使用obj作为块的参数。 它允许proc对象成为case语句中when子句的目标。
将第一行与Enumerable#chunk
的文档进行比较(例如):
enum.chunk {| elt | ……}→an_enumerator
{...}
表示chunk
被记录为占用块,缺少Proc#call
的这种表示法表示Proc#call
不占用块。
这不是一个权威的答案,但也许它可以解决一些问题。
block_given?
考虑def
范围,而不是lambda
范围:
def test l = lambda do yield if block_given? end l.call end test { puts "In block" }