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

时间:2012-01-12 06:29:09

标签: ruby

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

示例:

foo.send(:a_method) { bar.another_method }

4 个答案:

答案 0 :(得分: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

答案 1 :(得分: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

希望这有帮助!

答案 2 :(得分:5)

是的,它会的。在方法内,您可以使用block_given?进行检查,然后使用yield

调用该块

代码

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"}

输出

before yield
after yield

before yield
yield
after yield

答案 3 :(得分:1)

TL; DR:是的, Volume Date Open High Low Close Adj Date 2009 0 2009-12-31 31.709999 31.840000 31.299999 1957700 23.547892 2010 1 2010-01-04 31.480000 31.840000 31.330000 3472500 23.668222 2010 4 2010-01-07 31.549999 31.700001 31.049999 7232100 23.487726 方法会将闭包传递给它调用的方法。

在幕后,提供给方法调用的闭包将作为附加参数(尽管是一个特殊的参数)隐式传递给该方法。您可以使用send ...

显式使用闭包
call

...或隐式包含> def do_it(&block) > block.call > end => :do_it > do_it { puts 'apples' } apples => nil

yield

您可以将闭包传递给任何方法,包括> def do_it_with_yield > yield if block_given? > end => :do_it_with_yield > do_it_with_yield { puts 'bananas' } bananas => nil :send等,尽管取决于是否使用闭包。

:public_send等人的情况下,他们按照我们希望和期望的方式忠实地通过了闭包。

send

例如,在实现> self.public_send(:do_it) { puts 'cherries' } cherries => nil > self.send(:do_it_with_yield) { puts 'dates' } dates => nil 方法时,这一点很重要。

method_missing

参考: