2010-10-26 77 views
8

有誰爲什麼我可以這樣寫: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語法的「做」只是syntaxic糖和沒有與塊「做」嗎?

+0

偉大的問題! – 2010-10-27 09:47:51

回答

12

是不是因爲while語法的do只是syntaxic糖,如無與塊的do辦?

或多或少,是的。它不是語法糖,它只是一個內置的語言結構,如defclass,就像@meagar已經寫過的那樣。

它與塊的do無關,只是關鍵字很貴,所以重複使用關鍵字是有意義的。 (所謂「昂貴的」我的意思是,他們限制了他的表現程序員。)

while循環,有兩種方法來塊從條件分開:

  1. do關鍵字和
  2. 表達式分隔符。

有,反過來,兩個不同的表達在Ruby中分離:

  1. 分號;
  2. 換行符

因此,所有三個以下是有效的:

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 

[Obvi最後一個不會這樣寫,你會把end放在一個新的行上,縮進以匹配while。我只是想證明分離while環路的部分所需的最低要求是多少。]

順便說一下:將條件放在括號內是非常不習慣的。你的代碼中還有很多多餘的分號。變量名稱i通常爲索引而不是元素保留。 (我通常對通用元素使用el,但我更喜歡更多的語義名稱。)

手動迭代集合也非常不習慣。您的代碼將更好地被多寫成

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

它不僅是更容易理解這樣做(打印數組的所有元素,並刪除其中的所有項目),也更容易編寫(有是沒有辦法讓終止條件錯誤,或搞砸任何分配)。它也碰巧更有效率:您的版本是Θ(n ),這個是Θ(n)。

實際上,這也不是你怎麼寫的,因爲Kernel#puts已經實現了這種行爲。所以,你會真的寫就是這個

puts a 
a.clear 

或者也許這

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

[注:最後一個是不等價的100%。它打印一個空行的換行符,所有其他打印都沒有。]

簡單。明確。簡潔。表現力。快速。

與此相比,:

while (i = a.shift) do; puts i ; end 

其實我不得不運行多次,以100%的清楚它做什麼。

+0

輝煌。我必須收藏並研究這一個。 :) – 2010-10-27 01:41:31

+1

方法#to_proc ...我想我只是愛上了你一點點jorg – 2010-10-27 01:47:57

+0

偉大的答案,非常感謝Jörg! – marcgg 2010-10-27 09:13:45

6

while不佔用塊,它是一種語言結構。該do是可選的:

while (i = a.shift) 
    puts i 
end