为什么 3.times 如果作为参数传递,则需要 .each,但在直接使用时不需要,如"3.times do xyz end"



这是一个简单的版本,可以像预期的一样工作

[15] pry(main)> def iter
[15] pry(main)*   3.times do
[15] pry(main)*     puts "Hello"
[15] pry(main)*   end  
[15] pry(main)* end  
=> nil
[16] pry(main)> iter
Hello
Hello
Hello
=> 3

但是,当我将枚举器作为参数传递时,它需要.each:

作品:

[17] pry(main)> def iter(enumerator)
[17] pry(main)*   enumerator.each do        # <-------- Here  
[17] pry(main)*     puts "Hello"
[17] pry(main)*   end  
[17] pry(main)* end  
=> nil
[18] pry(main)> iter(3.times)
Hello
Hello
Hello
=> 3

不起作用:

[13] pry(main)> def iter(enumerator)
[13] pry(main)*   enumerator do         # <-------- Here
[13] pry(main)*     puts "Hello"
[13] pry(main)*   end  
[13] pry(main)* end  
=> nil
[14] pry(main)> iter(3.times)
NoMethodError: undefined method `enumerator' for main:Object
from (pry):8:in `iter'

我可能错了,但Ruby似乎对"3.times"(又称句法糖)进行了一些特殊处理。是这样吗,还是我错了,这种行为可以从第一原则中预期/推断出来?

顺便说一句,这也有效,这让我怀疑这只是句法上的糖。

[19] pry(main)> def iter
[19] pry(main)*   3.times.each do
[19] pry(main)*     puts "Hello"
[19] pry(main)*   end  
[19] pry(main)* end  
=> nil
[20] pry(main)> iter
Hello
Hello
Hello
=> 3
[21] pry(main)> 

3.times被调用,该调用的结果(而不是可调用函数)被传递给iter函数。如果times在没有块的情况下被调用,它将返回迭代器。迭代器本身不接受块,但您可以在其上调用each

不是语法糖。由于Ruby 1.9的重复方法是这样构建的:

  • 如果有障碍,就向它屈服
  • 如果没有块,则返回一个枚举器(通过调用类似return to_enum(__method__) unless block_given?的东西)

小示例:

loop 
# => #<Enumerator: main:loop> 

相关内容

最新更新