Ruby语法

时间:2010-10-26 17:36:11

标签: ruby

有人为什么我可以写这个:

ruby-1.8.7-p302 > a = %w( a b c)
 => ["a", "b", "c"] 
ruby-1.8.7-p302 > while (i = a.shift) do; puts i ; end
a
b
c
 => nil 

这看起来像是将块传递给了。 而不是:

while(i = a.shift) { puts i; }

是因为while语法的“do”只是语法糖而且与块的“do”无关吗?

2 个答案:

答案 0 :(得分:13)

  

是因为do语法的while只是语法糖而与块的do无关吗?

或多或少,是的。这不是语法糖,它只是一个内置的语言结构,如defclass,正如@meagar已写的那样。

它与块的do无关,除了关键字很昂贵,因此重用关键字是有道理的。 (“昂贵”我的意思是他们限制了程序员的表现力。)

while循环中,有两种方法可以将块与条件分开:

  1. do关键字和
  2. 表达式分隔符。
  3. Ruby中有两个不同的表达式分隔符:

    1. 分号;
    2. 换行
    3. 因此,以下所有三项都是有效的:

      while i = a.shift do puts i end # do
      
      while i = a.shift; puts i end   # semicolon
      
      while i = a.shift
        puts i end                    # newline
      

      [显然,最后一个不会这样写,你会将end放在一个新行上,缩进以匹配while。我只是想证明分离while循环部分所需的最小值。]

      顺便说一句:将条件放在括号中是非常不恰当的。你的代码中还有很多多余的分号。变量名i通常保留给索引,而不是元素。 (我通常使用el作为通用元素,但我更喜欢更多的语义名称。)

      手动迭代集合也非常不恰当。您的代码将更好地编写为

      a.each(&method(:puts)).clear
      

      不仅更容易理解它的作用(打印数组的所有元素并从中删除所有项目),它也更容易编写(没有办法让终止条件错误,或者螺丝拧紧)任何作业)。它也恰好更有效:你的版本是Θ(n 2 ),这个是Θ(n)。

      实际上,这并不是你怎么写的,因为Kernel#puts已经实现了这种行为。那么,真正写的是

      puts a
      a.clear
      

      或者这个

      a.tap(&method(:puts)).clear
      

      [注意:这最后一个不是100%等效。它打印一个空数组的换行符,所有其他的都不打印。]

      简单。明确。简洁。表现力。快。

      将其与:

      进行比较
      while (i = a.shift) do; puts i ; end
      

      我实际上必须多次运行才能100%清楚它的作用。

答案 1 :(得分:7)

while没有阻止,它是一种语言结构。 do是可选的:

while (i = a.shift)
  puts i
end