Ruby 方法可以访问隐式块参数吗?

Com*_*ubh 1 ruby closures block

传递给 Ruby 方法的隐式块参数可以使用 来执行yield,或者可以使用 来检查它的存在block_given?。我试图将这个隐式块传递给另一个方法。

这可能吗?

(这是对我要问的隐式块参数的访问。用显式参数替换它不会削减它。)

Jör*_*tag 5

你可以 procify 它,更重要的是给它一个名字,以便你可以引用它&在方法的参数列表中使用&符号一元前缀符号,如下所示:

#implicit, anonymous, cannot be referenced:
def foo
  yield 23 if block_given?
end

foo {|i| puts i }
# 23

#explicit, named, can be referenced:
def bar(&blk)
  yield 23 if block_given? # still works

  blk.(42) if blk # but now it also has a name and is a `Proc`

  # since we have the block available as an object, we can inspect it
  p blk.arity, blk.parameters, blk.source_location, blk.binding

  b = blk.binding
  p b.local_variables.map {|var| [var, b.local_variable_get(var)] }.to_h
end

quux = "Hello"

bar { |a, b, c = nil, d: nil, &e| puts a }
# 23
# 42
# 2
# [[:opt, :a], [:opt, :b], [:opt, :c], [:key, :d], [:block, :e]]
# ["(irb)", 24]
# #<Binding:0x00007fb091051308>
# { :quux => "Hello" }
Run Code Online (Sandbox Code Playgroud)

这是你的两个选择:

  • 隐式,匿名,不是对象
  • 明确的,命名的, Proc

曾经有一个未公开的技巧,它实际上Proc::new是 MRI 中实现方式的意外副作用:Proc::new不检查您是否通过了一个块,它只是假设您通过了一个块并将第一个块从顶部移走内部 VM 堆栈。因此,如果您没有将块传递给Proc::new,它实际上最终会Proc为传递给该方法的隐式块创建一个(因为它恰好位于堆栈顶部)。

但是,这从来都不是可移植的,从来没有保证过,从来没有在所有 Ruby 实现中工作过,而且 AFAIK 也不再在 YARV 中工作。