2012-08-29 34 views
4

我必須對Scala'match'語義或編譯器邏輯有一些基本的誤解。此代碼:scala'match'編譯規則的誤解

val stageStart:Int = 0 
val stageShutDown:Int = Int.MaxValue 
val stageErrorReport:Int = Int.MinValue 

def stageString(stage:Int):String = stage match { 
    case stageStart  => "Start" 
    case stageShutDown => "End" 
    case stageErrorReport => "Error" 
    case _    => "Step " + String.valueOf(stage) 
} 

導致最後3個'case'語句中的「Unreachable Code」錯誤?如果不是用名稱來代替它編譯的實際值(0,Int.MaxValue,Int.MinValue),但是現在我已經使用硬編碼的值來引用它們的名稱(出於所有常見原因)。由於'val'永遠不會改變,所以第一個版本不應該起作用嗎?

+0

btw intellij突出顯示此爲警告http://gyazo.com/147de35d25071dafa8de1290b5d23e26 – OlegYch

+0

警告將不勝感激! Eclipse沒有提出警告。檢查編譯器的各種屬性,看看是否可以打開這種情況下的警告,但沒有發現任何東西。 – user1624503

回答

9

有一個微妙而重要的特性:如果case規則中的標識符以小寫字母開頭,則它們始終被視爲變量。因此,第一個case總是匹配(將stage存儲到變量stageStart中),其餘3個不可訪問。您需要定義一個大寫字母常量,

val StageStart:Int = 0 
val StageShutDown:Int = Int.MaxValue 
val StageErrorReport:Int = Int.MinValue 

def stageString(stage:Int):String = stage match { 
    case StageStart  => "Start" 
    case StageShutDown => "End" 
    case StageErrorReport => "Error" 
    case _    => "Step " + String.valueOf(stage) 
} 

然後,他們將不會被視爲變量,但爲常數對模式匹配。

this answerNaming convention for Scala constants?

8

的問題是,當你使用以小寫字符開頭的變量,模式匹配認爲你正試圖分配該變量。所以,你得到此行爲:

val stageStart = 0 
val stage = 5 
def stageString(stage: Int) = stage match { 
    case stageStart => println(startStage) // prints "5" 
} 

當然,這僅僅是一個分配的變量將匹配任何一個模式,所以任何後續case將無法​​訪問。

要解決這個問題,您需要使用「穩定標識符」。這可以通過將小寫變量反引號來完成:

val stageStart = 0 
def stageString(stage: Int) = stage match { 
    case `stageStart` => "Start" 
} 

或重命名變量,以便它以大寫字母開頭:

val StageStart = 0 
def stageString(stage: Int) = stage match { 
    case StageStart => "Start" 
} 

另外:String.valueOf(stage)應改寫爲stage.toString

+0

哇!感謝您的洞察力 - 從未猜到過。 – user1624503

+0

但這帶來了一個更嚴重的問題。你是否在第一個例子中暗示一個被聲明爲** val **的變量實際上可以被**這個匹配語句重新賦值**一個不同的值?這似乎真的很可怕!或者**案例stageStart **實際上被認爲是一個臨時變量 - 這是一種可怕的方式。 – user1624503

+0

一點研究來回答我自己的問題。 **案例stageStart **實際上是引入了一個新的** stageStart **變量,該變量隱藏了原始內容。沒有Eclipse/Scala環境發出警告。仍然認爲這是非常可怕的 - 閱讀這本書兩次封面覆蓋,以及許多其他部分多次,關於大寫字母和小寫字母變量名稱的一個是我的權利。對於新的Scala人員,或者任何試圖將一堆遺留Java遷移到Scala的人來說,這也可能會成爲一個主要問題。 – user1624503