簡體   English   中英

向Scala添加“case”關鍵字背后的原因是什么?

[英]What's the reasoning behind adding the “case” keyword to Scala?

除了:

case class A

......非常有用的案例

為什么我們需要在match使用case 豈不:

x match {
  y if y > 0 => y * 2
  _ => -1
}

... 漂亮和簡潔?

或者為什么我們需要在函數取元組時使用case 說,我們有:

val z = List((1, -1), (2, -2), (3, -3)).zipWithIndex

現在,不是:

z map { case ((a, b), i) => a + b + i }

...... 方式不僅僅是:

z map (((a, b), i) => a + b + i)

...?

首先,正如我們所知,可以為同一個案例場景放置幾個語句,而不需要一些分離符號,只需一行跳轉,如:

x match {
       case y if y > 0 => y * 2
                          println("test")
                          println("test2")  // these 3 statements belong to the same "case"
}

如果不需要case ,編譯器必須找到一種方法來了解下一個案例場景何時涉及到一行。

例如:

x match {
   y if y > 0 => y * 2
   _ => -1
}

編譯器如何知道_ => -1屬於第一種情況還是代表下一種情況?

此外,編譯器如何知道=>符號不代表文字函數,而是當前case的實際代碼?

編譯器當然需要一種這樣的代碼允許案例隔離:(使用花括號或其他任何東西)

x match {
    {y if y > 0 => y * 2}
    {_ => -1}  // confusing with literal function notation
}

當然,使用case關鍵字的解決方案(目前由scala提供)比在我的示例中使用像花括號這樣的分離方式更具可讀性和可理解性。

添加到@ Mik378的答案:

當你寫這個: (a, b) => something ,你正在定義一個匿名的Function2 - 一個帶有兩個參數的函數。

當你寫這個: case (a, b) => something ,你正在定義一個匿名的PartialFunction ,它接受一個參數並將它與一對匹配。

所以你需要case關鍵字來區分這兩者。

第二個問題是避免這種case匿名函數,這是一個有爭議的問題:

https://groups.google.com/d/msg/scala-debate/Q0CTZNOekWk/z1eg3dTkCXoJ

另外: http//www.scala-lang.org/old/node/1260

對於第一個問題,選擇是您是否允許箭頭的RHS上的塊或表達式。

在實踐中,我發現通常更喜歡較短的盒體,所以我當然可以想象你的替代語法會產生更清晰的代碼。

考慮一行方法。 你寫:

def f(x: Int) = 2 * x

那么你需要添加一個聲明。 我不知道IDE是否能夠自動添加parens。

def f(x: Int) = { val res = 2*x ; res }

這似乎並不比要求案例主體使用相同的語法更糟糕。

要查看,案例子句是case Pattern Guard => body

目前, body是一個塊,或一系列語句和一個結果表達式。

如果body是一個表達式,那么你需要多個語句的大括號,比如函數。

我不認為=>導致歧義,因為函數文字不符合模式,不像1"foo"這樣的文字。

一個障礙可能是: { case foo => ??? } { case foo => ??? }是“模式匹配匿名函數”(SLS 8.5)。 顯然,如果案例是可選的或被刪除,那么{ foo => ??? } { foo => ??? }是模糊的。 你必須來區分匿名玩意兒情況的條款(其中case是必需的)和條款的情況下在match

當前語法的一個反駁論點是,在源自C的直覺中,你總是暗地希望你的匹配將編譯到切換表。 在那個比喻中,案例是跳轉到的標簽,標簽只是一系列語句的地址。

替代語法可能會鼓勵更內聯的方法:

x match {
  C => c(x)
  D => d(x)
  _ => ???
}
@inline def c(x: X) = ???
//etc

在這種形式中,它看起來更像是一個調度表,並且匹配體回憶Map語法Map(a -> 1, b -> 2) ,即整理關聯的簡化。

代碼可讀性的一個關鍵方面是引起你注意的詞。 例如,當你看到它時, return引起你的注意,因為你知道它是一個如此決定性的動作(打破了函數並可能將值發送回調用者)。

另一個例子是break不是我喜歡break ,但它引起了你的注意。

我同意@ Mik378,Scala中的case比其他case更具可讀性。 除了他提到的編譯混淆之外,它引起了你的注意。

我全都是為了簡潔的代碼,但簡潔和難以辨認之間有一條界限。 我很樂意進行4n個字符的交易(其中n是個案數量),以獲得我得到的實質性可讀性。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM