表达式和Proc.new在方法中做了什么?

时间:2014-01-31 13:46:52

标签: ruby-on-rails ruby

我在rails来源中发现&Proc.new的使用情况:

# rails/railties/lib/rails/engine.rb
def routes
  @routes ||= ActionDispatch::Routing::RouteSet.new
  @routes.append(&Proc.new) if block_given?
  @routes
end

我不明白表达式&Proc.new是如何工作的。

我写了类似的代码而失败了:

def method_name
  &Proc.new if block_given?
end
proc = method_name{ puts 'Hello world!' }
proc.call

我收到语法错误:

syntax error, unexpected &
    &Proc.new if block_given?
  • 表达式&Proc.new在方法中的作用是什么?

3 个答案:

答案 0 :(得分:4)

首先,您应该了解并了解哪些块和过程是什么。基本上它们是ruby提供闭包的方式。 Here是一个很好的链接。

ruby​​中的一元&符号运算符有3种用法(所有这些都与块和过程相关):

  • 如果应用于方法定义中的参数,则隐式块参数将使用参数名称存储为Proc。

  • 如果在方法调用中应用于Proc,则Proc中包含的块将作为隐式块参数传递。它保留Proc是否是lambda。方法总是lambdas。

  • 如果在方法调用中应用于其他对象,则调用方法#to_proc,并按照第二种情况传递生成的Proc。

The & Operator in Ruby详细解释了这一点。

答案 1 :(得分:3)

&在参数列表中有特殊含义 - 当用作Proc对象的前缀时,它将其作为块传递给被调用的方法。在方法体内,它只是一个二元运算符。

答案 2 :(得分:0)

如果从方法内部调用Proc.new而没有自己的任何参数,它将返回一个新的Proc,其中包含赋予其周围方法的块。

def foo
  Proc.new.call
end

foo { puts "hello world" }
# hello world

这意味着现在可以在不使用& block参数的情况下在方法之间传递块:

class C
  def bar
    puts "called bar..."
    baz &Proc.new
  end

  def baz
    puts "called baz..."
    yield
  end
end

C.new.bar { puts "called block..." }
# called bar...
# called baz...
# called block...

这个技巧被Rails用于

# File railties/lib/rails/engine.rb, line 533
def routes
  @routes ||= ActionDispatch::Routing::RouteSet.new_with_config(config)
  @routes.append(&Proc.new) if block_given?
  @routes
end

的更多详情