[英]block as argument to method in ruby is a mystery?
3.times {puts "Hello"}
输出:
你好
你好
你好
我们将其理解为times
是Integer
类中的一个函数,该函数以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.