2010-04-28 23 views
15

試圖解開元組到瓦爾斯時,我注意到在斯卡拉以下行爲:Scala的元組解包的細微差別

scala> val (A, B, C) = (1, 2, 3) 
<console>:5: error: not found: value A 
     val (A, B, C) = (1, 2, 3) 
      ^
<console>:5: error: not found: value B 
     val (A, B, C) = (1, 2, 3) 
      ^
<console>:5: error: not found: value C 
     val (A, B, C) = (1, 2, 3) 
       ^

scala> val (u, v, w) = (1, 2, 3) 
u: Int = 1 
v: Int = 2 
w: Int = 3 

是不是因爲Scala的模式匹配機制自動假定與首都開始的所有標識符範圍內的圖案是常數,還是由於其他原因?

謝謝!

回答

20

是的,事情變得更糟糕:

val (i, j) : (Int, Int) = "Hello" -> "World" 

以上將編譯並在運行時用一個ClassCastException失敗。很容易忘記(i, j)聲明是模式

EDIT:用於ziggystar,Scala的分配規則規定在聲明:

val p = expr //or var 

p可以是一個標識符或圖案(見15.7的編程Scala中,第284頁)。因此,例如,以下是有效的:

val x :: y :: z :: rest = List(1, 2, 3, 4) 

的事實,圖案被刪除(即參數類型信息沒有被選中),意味着我原來的例子編譯在一起考慮這一點。

+0

這就是interessting。但我在這裏沒有得到你的意思。你能再解釋一下嗎? – ziggystar 2010-04-28 09:27:01

+0

我修改了我的答案 – 2010-04-28 10:42:12

+5

有趣的錯誤...也許你應該指出它失敗,因爲這相當於'Tuple2 [Int,Int]',它被類型擦除爲'Tuple2 [Any,Any]'? – 2010-04-28 15:51:40

13

[scala] Question about naming conventions您可以閱讀

的首字母大寫有優勢時,模式匹配。帶有首字母大寫字母的標識符被認爲是要匹配的值,而不是要綁定的變量。

+0

感謝裁判aioobe! – 2010-04-28 18:52:58

1

如果您需要初始化大量常量並且希望避免爲每個常量寫入val =或者您正在達到元組大小限制(22),則存在解決方法。

從部的The Scala Language Specification 4.1:

值德音響nition VAL X:T =È德音響內斯x作爲值的名稱,從e的評價 結果。值定義val p1,...,pn = e是值定義序列val p1 = e的簡寫。 ...; val pn = e。

按照規範,可以通過在右側指定一個表達式來按照順序返回每個值來初始化所有名稱都以名稱開頭的值序列。

val iter = Iterator(1, 2, 3) 
val A, B, C = iter.next() 

又如:

val next = { var n = 0;() => { n = n + 1; n } } 
val A, B, C, D, E, F, G, H = next() 

在這些簡單的情形這種方法上面沒有非常有用的。下面是初始化常數爲每個棋盤的64個平方的更有用的例子(參見Square.scala#L31源):

val squareIter = squares.iterator 
val A1, A2, A3, A4, A5, A6, A7, A8, 
    B1, B2, B3, B4, B5, B6, B7, B8, 
    C1, C2, C3, C4, C5, C6, C7, C8, 
    D1, D2, D3, D4, D5, D6, D7, D8, 
    E1, E2, E3, E4, E5, E6, E7, E8, 
    F1, F2, F3, F4, F5, F6, F7, F8, 
    G1, G2, G3, G4, G5, G6, G7, G8, 
    H1, H2, H3, H4, H5, H6, H7, H8 = squareIter.next() 
+0

謝謝。好想法。第一個例子可以更短:val A,B,C =(Iterator(1,2,3).next _)() – 2014-03-24 11:40:03

+1

謝謝,但縮短版本不等同於第一個示例。表達式'(Iterator(1,2,3).next _)()'評估爲'1',然後'A','B'和'C'被設置爲'1'。 – 2014-03-24 22:40:41