Ruby块和过程。使用Proc时,您不需要指定第二个参数吗?

时间:2016-10-28 16:30:19

标签: ruby

我读过Ruby Procs:

class Monkey

  # Monkey.tell_ape { "ook!" }
  # ape: ook!
  #  => nil
  def self.tell_ape
    tell("ape", &Proc.new)
  end

  def self.tell(name)
    puts "#{name}: #{yield}"
  end
end

在上面的例子中......块被传递给.tell_apeProc.new正在将块转换为proc权限?但是...... .tell方法是否需要在其方法签名中接受&block参数?我们将Proc作为参数传递给.tell方法吧?如果是这样...... .tell方法是否需要有第二个参数?

2 个答案:

答案 0 :(得分:2)

所有方法总是只使用一个可选的块参数:

puts('Hello') { I.can.write.whatever.i.want.here.because.the.block.is.never.ran }
# Hello

def foo; end
foo { same.here }

块的重点在于它们在语法和语义上都是轻量级的,并且实现这一点的方法之一是它们是匿名的:

def bar; yield if block_given? end
# Note how I didn't need to say where to yield to and what block to check since 
# there can only ever be at most one anyway.

bar { puts 'Hello' }
# Hello

它们也不是对象。

但是如果它没有名字而且甚至不是一个对象,那你怎么能引用它呢?好吧,那就是&参数的来源:它们告诉Ruby将块转换为正确的Proc对象并将其绑定到参数:

def baz(&blk) p blk end
baz { again.we.are.not.calling.the.block }
# #<Proc:0xdeadbeef081542@(pry):42>
# ^^^^^^^ Debugging representation of a Proc object

Proc有一个call方法执行它们(还有一段用于调用call的语法糖):

def quux(grault, &blk)
  blk.(grault)
  yield grault
end

quux('Hello') {|garply| puts garply }
# Hello
# Hello

答案 1 :(得分:1)

当你有一个接收块的方法时,yield关键字将执行块,你不必将它作为参数显式传递。

def foo
 yield 1
end

相当于:

def foo(&block)
  block.call(1)
end