2013-02-20 61 views
1

使用Scala 2.10,以下編譯沒有錯誤。爲什麼scala try塊允許重新定義封閉範圍的變量?

val test = 1 
try { 
    val test = 2 
} 

望着生成的字節碼,我看到:

int test = 1; 
int test = 2; 

這難道不奇怪嗎?還是我錯過了明顯的東西?

+0

它被稱爲陰影,可以在任何設置中通過在'{'braces'}'中包含一系列表達式來創建新的內部作用域。 – 2013-02-20 14:46:49

+0

我知道這不是真的,但是用Scala我假裝'{'和'}'定義了一個函數。這使得我個人更容易理解這些結構。 – EECOLOR 2013-02-20 21:55:28

回答

2

這有什麼好做try中存在。變量可以在任何影對方,你可以把塊基本上在任何地方:

val x = 0 
if ({val x = 1; x*3}==0) { 
    val x = 2; x + x + x 
} 
else x 

這使得代碼更容易移植:你可以自由走動塊,而不必擔心在外面的東西可能會發生衝突。 (好吧,並不完全正確:哪些隱含在範圍內仍然可能會導致問題,但這比重複的變量更不可能讓您受到影響。)

這是與Java不同的選擇; Java的態度是,你更可能忘記你的變量名稱,需要提醒,而斯卡拉的說法是,即使外部環境發生變化,你的意思可能就是你所說的。考慮到Java對可變操作的關注(遮蔽可變變量真的會導致問題!)和Scala的默認不變性(隱藏外部不可變變量可能甚至是可取的,因爲您可以重用像i和x這樣的短變量到你心中的內容)。

+0

謝謝!我會接受你的回答,因爲令我感到困惑的事情是scala和java之間的區別,我認爲你提供了一個合理的解釋。我在創建一個可變變量時遇到了這個問題,然後不小心將其映射到了我的try塊中,而不是將它分配給它。我想我應該看一些處理異常的更習慣的scala模式,:P – zakvdm 2013-02-21 10:01:56

3

局部變量可以始終與具有較寬範圍的名稱相同。通過將它聲明在括號內,可以有效防止意外地使用/覆蓋別處使用的變量。不奇怪 - 但有用!

+0

感謝您的回答。儘管如此,還是有一些東西讓我困惑......據我所知,這種行爲與Java(不同的代碼無法編譯)不同。爲什麼這種不一致?這是Scala關閉的自然後果嗎?然後就會產生奇怪的字節碼......這個字節碼如何等同於內部的「測試」實例和外部範圍的實例? – zakvdm 2013-02-20 13:58:30

+0

我同意字節碼很混亂,因爲它沒有顯示名爲「test」的變量的作用域 - 因此看着字節碼,如果它們是相同的變量,則無法判斷。它是否顯示他們有不同的地址? @korefn的例子是否如預測的那樣顯示「1 2 1」? – Floris 2013-02-20 15:07:49

2

也許你試試這個得到什麼在

val test = 1 
println(test) 
try{ 
    val test = 2 
    println(test) 
} 
println(test) 

範圍的事項要清晰的畫面。我希望你得到了121 第二test只有嘗試範圍