向Object.send添加一个块是否将它传递给被调用的方法?

问题描述 投票:18回答:3

我刚刚完成了Ruby Koans,使用Object.send调用方法的单元和方法上的Ruby文档都没有提供有关在send方法中使用块的任何信息。将附加到send方法的块传递给它调用的方法,还是块会丢失?

例:

foo.send(:a_method) { bar.another_method }
ruby
3个回答
21
投票

documentation对此有点不清楚:

发送(符号[,args ...])→obj

调用由symbol标识的方法,并将指定的任何参数传递给它。

但请注意指定部分的任何参数。您为方法提供的块实际上是一个有趣的隐式参数类型,因此您可以执行以下操作:

def m(&b)
  @a.each(&b)
end
m { |e| puts e }

将块作为Proc实例传递。但是,您也可以这样做:

def m
  yield
end
m { puts 'pancakes' }

因此,就参数列表而言,该块是特殊的,但即使有时是隐式的,该块仍然表现为参数。

鉴于上面的“块是一种论证”漫无目的以及Ruby中块的重要性,send通过该块是合理的。你也可以尝试一下,但是你必须小心使用“试一试”方法进行偶然和无证的行为:

class C
  def m
    yield
  end
end
o = C.new
o.send(:m) { puts 'pancakes' }
# "pancakes" comes out

14
投票

是。考虑以下:

class A
  def explicit(&b); b; end
  def implicit; yield "hello"; end
end

>> A.new.send(:explicit) { }
=> #<Proc:0x0000000000000000@(irb):19>
>> A.new.send(:implicit) { |greeting| puts greeting }
hello
=> nil

希望这可以帮助!


5
投票

是的,它会的。在方法内部,您可以使用block_given?进行检查,并使用yield调用块

Code

class Foo
  def bar
    puts "before yield"
    yield if block_given?
    puts "after yield"
  end
end

f = Foo.new
f.send(:bar)
puts ""
f.send(:bar) { puts "yield"}

Output

before yield
after yield

before yield
yield
after yield
© www.soinside.com 2019 - 2024. All rights reserved.