什么时候分号在scala中是强制性的?
When is semicolon mandatory in scala?
我正在学习如何在 Scala 中编程,并被告知分号在 Scala 中是可选的。因此,考虑到这一点,我尝试使用以下没有分号的嵌套代码块。但是,它会在 Scala REPL
中引发错误
scala> { val a = 1
| {val b = a * 2
| {val c = b + 4
| c}
| }
| }
<console>:17: error: Int(1) does not take parameters
{val b = a * 2
带分号的样本工作得很好。
scala> { val a = 1;
| { val b = a*2;
| { val c = b+4; c}
| }
| }
res22: Int = 6
因此在我看来,分号并不是真正可选的,在某些情况下是强制性的。请问分号在什么情况下是必须的?
我将尝试从您的示例中提取精华。
考虑以下代码片段:
{ val x = 1 { val y = 2 } }
对于编译器来说,它看起来像是
的语法糖
{ val x = 1.apply({ val y = 2 }) }
但是对象 1
没有 apply
接受块的方法,因此编译器产生错误:
error: Int(1) does not take parameters
{ val x = 1 { val y = 2 } }
^
对比
object I { def apply(a: => Any): Unit = () }
{ val x = I { val y = 2 } }
这行得通,因为 I
现在 有一个 apply
方法。
为了更容易区分这两种情况,编译器要求在第一种情况下使用分号。
现在有人可能想知道为什么 val x = 1
和 {
之间的换行符没有转换为推断的分号。我认为规范中的相关引用是这样的(1.2 Newline Characters)(省略了大部分枚举([...]
),重点是我的):
The Scala grammar [...] contains productions where
optional nl
tokens, but not semicolons, are accepted. This has the
effect that a newline in one of these positions does not terminate an
expression or statement. These positions can be summarized as follows:
[...]
in front of an opening brace ‘{’, if that brace is a legal continuation of the current statement or expression,
[...]
请注意,此引用仅涵盖带有 单个 可选换行符的情况。它不适用于两个或多个连续的换行符,例如
scala> {
| val x = 1
|
| { val y = 2 }
| }
有效,{ val y = 2 }
被解析为单独的表达式。
我 猜测 其动机是允许嵌入式 DSL 具有如下语法糖:
MY_WHILE(x >= 0)
{
println(x)
x -= 1
}
如果必须将每个这样的 MY_WHILE
语句括在一对额外的圆括号中,那真的很奇怪,不是吗?
添加到 Andrey 的回答中,您很少在惯用的 Scala 中编写这样的代码,但是,当您这样做时,您应该使用 locally
:
{
val a = 1
locally {
val b = a * 2
locally {
val c = b + 4
c
}
}
}
这种情况正是 locally
存在的原因。
我正在学习如何在 Scala 中编程,并被告知分号在 Scala 中是可选的。因此,考虑到这一点,我尝试使用以下没有分号的嵌套代码块。但是,它会在 Scala REPL
中引发错误scala> { val a = 1
| {val b = a * 2
| {val c = b + 4
| c}
| }
| }
<console>:17: error: Int(1) does not take parameters
{val b = a * 2
带分号的样本工作得很好。
scala> { val a = 1;
| { val b = a*2;
| { val c = b+4; c}
| }
| }
res22: Int = 6
因此在我看来,分号并不是真正可选的,在某些情况下是强制性的。请问分号在什么情况下是必须的?
我将尝试从您的示例中提取精华。
考虑以下代码片段:
{ val x = 1 { val y = 2 } }
对于编译器来说,它看起来像是
的语法糖{ val x = 1.apply({ val y = 2 }) }
但是对象 1
没有 apply
接受块的方法,因此编译器产生错误:
error: Int(1) does not take parameters
{ val x = 1 { val y = 2 } } ^
对比
object I { def apply(a: => Any): Unit = () }
{ val x = I { val y = 2 } }
这行得通,因为 I
现在 有一个 apply
方法。
为了更容易区分这两种情况,编译器要求在第一种情况下使用分号。
现在有人可能想知道为什么 val x = 1
和 {
之间的换行符没有转换为推断的分号。我认为规范中的相关引用是这样的(1.2 Newline Characters)(省略了大部分枚举([...]
),重点是我的):
The Scala grammar [...] contains productions where optional
nl
tokens, but not semicolons, are accepted. This has the effect that a newline in one of these positions does not terminate an expression or statement. These positions can be summarized as follows:[...]
in front of an opening brace ‘{’, if that brace is a legal continuation of the current statement or expression,
[...]
请注意,此引用仅涵盖带有 单个 可选换行符的情况。它不适用于两个或多个连续的换行符,例如
scala> {
| val x = 1
|
| { val y = 2 }
| }
有效,{ val y = 2 }
被解析为单独的表达式。
我 猜测 其动机是允许嵌入式 DSL 具有如下语法糖:
MY_WHILE(x >= 0)
{
println(x)
x -= 1
}
如果必须将每个这样的 MY_WHILE
语句括在一对额外的圆括号中,那真的很奇怪,不是吗?
添加到 Andrey 的回答中,您很少在惯用的 Scala 中编写这样的代码,但是,当您这样做时,您应该使用 locally
:
{
val a = 1
locally {
val b = a * 2
locally {
val c = b + 4
c
}
}
}
这种情况正是 locally
存在的原因。