我将尝试从您的示例中提取本质。
考虑以下代码片段:
{ val x = 1 { val y = 2 } }
对于编译器来说,它看起来像是语法糖
{ val x = 1.apply({ val y = 2 }) }
但对象1
没有apply
方法需要块,因此编译器会产生错误:
错误:Int(1) 不带参数
{ val x = 1 { val y = 2 } }
^
将此对比
object I { def apply(a: => Any): Unit = () }
{ val x = I { val y = 2 } }
这有效,因为I
now does有一个apply
method.
为了更容易区分这两种情况,编译器在第一种情况下需要一个分号。
现在人们可能想知道为什么之间要换行val x = 1
和{
不转换为推断的分号。我认为规范中的相关引用是这样的(1.2 换行符 https://scala-lang.org/files/archive/spec/2.12/01-lexical-syntax.html#newline-characters)(省略了大部分枚举([...]
),强调我的):
Scala 语法 [...] 包含产生式,其中
选修的nl
接受标记,但不接受分号。这有
效果是一个这些位置之一的换行符不会终止
表达或陈述。这些立场可概括如下:
[...]
请注意,此引用仅涵盖带有single可选换行符。它不适用于两个或多个连续换行符,例如
scala> {
| val x = 1
|
| { val y = 2 }
| }
是有效的,并且{ val y = 2 }
被解析为单独的表达式。
I guess动机是允许嵌入带有语法糖的 DSL,如下所示:
MY_WHILE(x >= 0)
{
println(x)
x -= 1
}
如果必须将这样的每一个都包含起来,那就真的很奇怪了MY_WHILE
- 语句放入一对额外的圆括号中,不是吗?