14

除了:

case class A

...案例哪一个很有用?

为什么我们需要使用casein match?不会:

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)

...?

4

4 回答 4

12

首先,我们知道,可以为同一个案例场景放置多个语句,而不需要一些分隔符号,只需一个行跳转,例如:

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 提供)比在我的示例中使用花括号等某种分隔方式更具可读性和可理解性。

于 2013-10-19T22:17:10.047 回答
9

添加到@Mik378 的答案:

当你写这个:(a, b) => something时,你定义了一个匿名Function2函数——一个接受两个参数的函数。

当你写这个:case (a, b) => something时,你定义了一个匿名的PartialFunction,它接受一个参数并将它与一对匹配。

所以你需要case关键字来区分这两者。

于 2013-10-19T22:31:19.773 回答
3

第二个问题,避免 的匿名函数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 是否能够自动添加括号。

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

这似乎并不比要求案例主体使用相同的语法更糟糕。

回顾一下,case 子句是case Pattern Guard => body.

目前,body是一个块,或一个语句序列和一个结果表达式。

如果body是表达式,则需要大括号用于多个语句,例如函数。

我认为不会=>导致歧义,因为函数文字不符合模式的条件,不像1or之类的文字"foo"

一个障碍可能是:{ case foo => ??? }是“模式匹配匿名函数”(SLS 8.5)。显然,如果案例是可选的或消除的,那么{ foo => ??? }是模棱两可的。您必须区分 anon funs 中的 case 子句(case需要的地方)和 a 中的 case 子句match

对当前语法的一个反驳是,在从 C 派生的直觉中,您总是暗中希望您的匹配项能够编译为切换表。在那个比喻中,案例是要跳转到的标签,而标签只是一系列语句的地址。

替代语法可能会鼓励更内联的方法:

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

在这种形式下,它看起来更像是一个调度表,匹配体让人想起 Map 语法,Map(a -> 1, b -> 2)即对关联的整洁简化。

于 2013-10-20T00:53:59.090 回答
2

代码可读性的关键方面之一是引起您注意的单词。例如, return当您看到它时会引起您的注意,因为您知道这是一个决定性的动作(打破函数并可能将值发送回调用者)。

另一个例子是break--not that I like break,但它引起了你的注意。

我同意@Mik378 的观点,即case在 Scala 中比替代方案更具可读性。除了他提到的编译器混乱之外,它还引起了你的注意。

我完全赞成简洁的代码,但简洁和难以辨认之间有一条线。我很乐意用 4n 个字符(其中n是案例的数量)来换取我获得的大量可读性作为回报。

于 2013-10-19T22:34:23.597 回答