2013-02-27 26 views
3

我無法確定什麼是錯用下面的Ruby內聯救援碼爲什麼a = b解救一個錯誤但救援stmt不是?

def test_check() 
p "first st" 
t = 5 * lsdj rescue return false 
p "second" 
end 

p test_check 

這是給一個錯誤消息syntax error, unexpected kFALSE, expecting kEND 但如果我刪除賦值語句它會正常工作(返回false)。

def test_check() 
    p "first st" 
    5 * lsdj rescue return false 
    p "second" 
    end 

如果出了什麼問題紅寶石內嵌救援的正確語法是什麼?

+0

+1。一個非常好的問題。人們會希望修飾符規則在兩種情況下都能得到相同的解析,並且對此的回答會遇到很多關於Ruby爲什麼會這樣的問題。也許只有馬茨知道完整的答案,但我已經在下面貢獻了我的理解。 – DigitalRoss 2013-02-27 22:52:58

回答

12

嵌入式rescue在分配中使用它時不會將語句當作參數1,2 - 它只是希望得到一個表達式的值,以獲取它被救出的情況。

但要小心,你認爲這會返回什麼?

def q 
    return 5 * lsdj rescue false 
    true 
end 

假,返回。這樣做,而不是救援只適用於表達式。

def q 
    return (5 * lsdj rescue false) 
    true 
end 

此人返回false。


注意事項:
1.這實際上是一個很好的問題。重述:
          爲什麼A = B救援語句一個錯誤,但語句救援語句是不是?
而膚淺的答案是,在分配的情況下RHS和救援語句是ARG非終結符在Ruby語法,而不是完整的語句,而在聲明的情況下的語法簡單的搶救後解析一個完整的語句規則。這只是它定義的方式。現在,如果你問爲什麼呢? ......好吧...... Ruby的複雜語法生活在yacc(1)有能力的邊緣。在我看來,在很多情況下,Matz詳細闡述了在某些情況下究竟會接受什麼,而不僅僅是使用單個非終端,如expr,我想象的原因是保留語法LALR(1)並將不可避免的shift/reduce conflicts限制在可容忍的範圍內。 Check out parse.y在Ruby源碼分發中進行了一個有趣的閱讀。
2.這裏是一個例子:def q; (t = 5 * lsdj) rescue return false; true; end
這可以像你想的那樣工作,因爲它只是恰好符合其他語法規則。我聽說爲了支持詩歌模式存在一些這些限制。

+1

我搜索了很多文檔,但是找不到任何好的文檔。最後的解釋很好,謝謝@DigitalRoss。 – 2013-03-01 12:23:27

2

您的代碼將被解釋爲:

def test_check() 
p "first st" 
t = (5 * lsdj rescue return) false 
p "second" 
end 

這使得false無效狀態圖。爲了解決這個問題,在圓括號中加上:

def test_check() 
p "first st" 
t = 5 * lsdj rescue (return false) 
p "second" 
end 
+3

爲了迂迴,具體的問題是救援修飾符的參數(當應用於賦值時)是非終端'arg',並且不能解析以'keyword_return.'開頭的語句。但是,添加' (...)'會導致語法解析一個'primary'表達式,它恰好包含* return *語句。 – DigitalRoss 2013-02-27 18:21:23