本文介绍了在匿名块中屈服的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我没有理解以下行为(另请参阅此 SO 线程中的 ):

I'm not making sense of the following behavior (see also in this SO thread):

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 变量并直接调用它,但我更希望弄清楚为什么我最终需要这样做.>

I don't mind resorting to explicitly declaring the &block variable and calling it directly, but I'd more ideally like to make some sense of why I end up needing to.

推荐答案

lambda 是一个闭包,它似乎正在捕获 block_given? 并阻止其外部范围.这种行为确实有意义,因为块或多或少是外部方法的隐含参数;如果需要,您甚至可以在命名参数中捕获块:

The lambda is a closure and it seems to be capturing the block_given? and block from its outer scope. This behavior does make sense as the block is, more or less, an implied argument to the outer method; you can even capture the block in a named argument if desired:

def def_test(&block)
    frobnicate &block
end

所以即使块没有命名,它也是参数列表的一部分.

So the block is part of the argument list even when it isn't named.

考虑这段简单的代码:

def f
    lambda do
        puts "\tbefore block"
        yield if block_given?
        puts "\tafter block"
    end
end

puts 'Calling f w/o block'
x = f; x.call
puts

puts 'Calling f w/ block'
x = f { puts "\t\tf-block" }; x.call
puts

puts 'Calling f w/o block but x with block'
x = f; x.call { puts "\t\tx-block" }
puts

puts 'Calling f w/ block and x with block'
x = f { puts "\t\tf-block" }; x.call { puts "\t\tx-block" }

这会为我在 1.9.2 中生成以下内容:

This produces the following for me with 1.9.2:

Calling f w/o block
    before block
    after block

Calling f w/ block
    before block
        f-block
    after block

Calling f w/o block but x with block
    before block
    after block

Calling f w/ block and x with block
    before block
        f-block
    after block

此外,Proc#call(AKA proc ===) 不需要一个块:

Furthermore, Proc#call (AKA proc ===) doesn't take a block:

prc === obj → result_of_proc
调用块,使用 obj 作为块的参数.就是让一个proc对象成为case语句中when子句的目标.

将第一行与 Enumerable#chunk(例如):

Compare the first line with the documentation for Enumerable#chunk (for example):

enum.chunk {|elt|... } → an_enumerator

{...} 表示 chunk 被记录为占用一个块,Proc#call 缺少这样的符号表示Proc#call 不需要一个块.

The {...} indicates that chunk is documented to take a block, the lack of such notation for Proc#call indicates that Proc#call does not take a block.

这不完全是一个权威的答案,但也许它会稍微澄清一些事情.

This isn't exactly an authoritative answer but maybe it clears things up a little bit.

这篇关于在匿名块中屈服的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

08-23 04:27