繁体   English   中英

块作为红宝石方法的参数是一个谜吗?

[英]block as argument to method in ruby is a mystery?

3.times {puts "Hello"}

输出:

你好
你好
你好

我们将其理解为timesInteger类中的一个函数,该函数以block作为参数。

我试图深入研究,发现它不是那么简单。

如果情况是times是一个函数,并且方法调用中的括号是可选的,我尝试使用以下方法对其进行验证:

3.times({puts "Hello"})

它显然引发了一个错误:

语法错误:(irb):3:语法错误,意外的tSTRING_BEG,期望keyword_do或'{'或'('3.times({puts“ Hello”}))^(irb):3:语法错误,意外的'}',预期来自/home/ashish/.rvm/rubies/ruby-2.0.0-p353/bin/irb:12:in`'中的输入时间3.times({puts“ Hello”})^

进一步调查:

a = 3.times
puts a.class

输出Enumerator ,其言下之意是3.times是一个Enumerator类对象。

有人可以用这背后的确切概念来解释整个事情吗?

正如Sawa所说,块不是对象,因此不会作为参数传递。 块是Ruby中的特殊事物。 它们具有特殊的语法(仅允许我们将一个块传递给方法)和专用于调用它们的特殊关键字。 这是Ruby中times的示例实现:

def times
  if block_given?
    i = 0
    while i < self
      yield i
      i += 1
    end
    # times returns the number that was executing times,
    # so we need to return self here
    self
  else
    enum_for :times
    # ^^ This is where the Enumerator comes from if
    #    you don't pass a block.
  end
end

块给block_given? 方法测试是否有与当前方法关联的块,并且yield关键字调用该块。

块不是参数,甚至不是对象。 将其放在括号中是没有意义的,因为它不是对象。

Block是一个位置参数(如果已定义,则总是最后一个参数),具有用于传递值的特殊规则, times可以定义为:

def times(&block)
  block.call(...)
end

要调用它,您需要一个可以转换为Proc类实例的对象,并且应该在&加上它:

3.times(&Proc.new { puts "Hello" })

像这样的通话times

3.times { puts "Hello" }

只是上述形式的语法糖。

更新 :我不得不承认,它不是一个语法糖,块是速度更快,只需添加&block参数times确实慢下来的东西,即使它永远不会被调用。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM