繁体   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