3.times {puts "Hello"}
输出:
您好
你好
你好
我们理解为times
是Integer
类中的一个函数,它以block
为参数。
我试图深入挖掘并发现它并非那么简单。
如果times
是一个函数并且方法调用中的括号是可选的,我尝试使用以下方法验证它:
3.times({puts "Hello"})
它显然犯了一个错误:
SyntaxError:(irb):3:语法错误,意外tSTRING_BEG,期待keyword_do或'{'或'('' 3次({puts“你好”}) ^ (irb):3:语法错误,意外'}',期待输入结束 3次({puts“你好”}) ^ 来自/home/ashish/.rvm/rubies/ruby-2.0.0-p353/bin/irb:12:in`'
进一步调查:
a = 3.times
puts a.class
输出Enumerator
,表示3次是Enumerator
类对象。
有人可以用这个背后的确切概念解释整个事情吗?
答案 0 :(得分:3)
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
关键字调用该块。
答案 1 :(得分:2)
块不是参数,它甚至不是对象。将它括在括号中是没有意义的,因为它不是一个对象。
答案 2 :(得分:0)
Block是一个位置(总是最后一个,如果已定义)参数,带有一个传递值的特殊规则,times
可以定义为:
def times(&block)
block.call(...)
end
要调用它,你需要一个可以转换为Proc
类实例的对象,你应该在&
之前添加它:
3.times(&Proc.new { puts "Hello" })
调用times
之类的
3.times { puts "Hello" }
只是上述形式的语法糖。
更新:我不得不承认它不是语法糖,块速度更快,只需向&block
添加times
参数即使从未调用它也会减慢速度