(data:Any)=> println(data)与data:Any => println(data)

时间:2018-09-24 07:15:40

标签: scala language-lawyer

我遇到了以下Scala代码:

val x = 10 match {
  case _: Int => data: Any => println(data) // no issue
}

val y = data: Any => println(data) //compiling error

在区分大小写子句中,我不必将data: Any => println(data)写为 (data: Any) => println(data)

但是在val y = data: Any => println(data)中,我必须写为val y = (data: Any) => println(data)。为什么?

2 个答案:

答案 0 :(得分:3)

相关规则是

  

If an anonymous function (x: T) => e with a single typed parameter appears as the result expression of a block, it can be abbreviated to x: T => e.

第一种情况(case _: Int => data: Any => println(data))满足此条件,第二种情况不满足。但是您可以将其重写为

val y = { data: Any => println(data) }

答案 1 :(得分:2)

其中一个区别是大小写匹配的case语句,另一个是赋值语句。在第一种情况下,我们实质上是将=>右侧的值(结果)返回为语句块,如下所示。

scala> {data: Any => println(data)}
res0: Any => Unit = $$Lambda$1141/1699449247@71468613

scala> data: Any => println(data)
<console>:1: error: ';' expected but '=>' found.
       data: Any => println(data)
scala> val x = 10 match {
     |   case _: Int => val y = 56;data: Any => println(data) // no issue
     | }
x: Any => Unit = $$Lambda$1171/115016870@8f374de

以上语句认为=>之后的所有内容都将被视为statement block语句中的case,但在第二种情况下(赋值-即分配函数值)则不是。因此,必须在参数声明两边加上括号。

编辑:

尽管我已经在scala REPL中给出了以上答案,但我进一步认为 那将不会清楚地回答为什么?问了一部分问题。我进一步做了一些 在调查了键入

时得到的确切错误消息后,跟踪了scala编译器的行为
val y = data:Int => println(data)

scala> val y = data:Int => println(data)
<console>:1: error: ';' expected but '(' found.
       val y = data:Int => println(data)

这似乎是由于scala具有val y类型推断的功能。

在Scala中type可以在需要的任何地方显式指定,并且Scala编译器可以在任何可能的地方隐式infer type进行指定。这里的type of y首先要由scala编译器推断出来,因为这里没有明确声明。正是由于编译器的这种尝试,导致出现了以上错误消息。

现在,如果我们要显式声明type,则在scala中将有two ways

第一种方式val y : Int = 5

第二种方式val y = 5:Int

以上两个赋值语句均在scala中为valid

因为在我们的具体分配声明中,

val y = data:Any => println(data)

我们正在强制scala以上面显示的 第二种方式 推断type of y

要推断type of y,scala编译器将按照以下说明进行尝试:

在这里,编译器假设data是在此代码行之前某处定义的函数,并且该函数的类型为Int=>println(data)。然后,它正在检查这种类型的有效性。编译器确定Int是有效类型,而println(data)不是有效类型,因为有效类型名称不能包含括号('(' char),这就是上述error message的原因。

如果将上述赋值语句的右侧插入到一个块中,即;卷曲之间 大括号或将参数声明放在括号中,则推断type of y不会有问题。

或者使用 第一种方法 ,我们可以这样做,而无需使用花括号

val y : Any => Unit = data =>println(data)


scala> val y : Any => Unit = data =>println(data)
y: Any => Unit = $$Lambda$1059/1854873748@799c8758

希望这可以解释问题的部分原因。