Mox*_*Mox 2 syntax scala semicolon-inference
我正在学习如何在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
Run Code Online (Sandbox Code Playgroud)
半结肠的样本工作得非常好.
scala> { val a = 1;
| { val b = a*2;
| { val c = b+4; c}
| }
| }
res22: Int = 6
Run Code Online (Sandbox Code Playgroud)
因此,在我看来,半结肠不是真正可选的,在某些情况下是强制性的.请问在什么情况下半结肠是强制性的?
我将尝试从你的例子中提取精华.
请考虑以下代码段:
{ val x = 1 { val y = 2 } }
Run Code Online (Sandbox Code Playgroud)
对于编译器来说,它看起来像语法糖
{ val x = 1.apply({ val y = 2 }) }
Run Code Online (Sandbox Code Playgroud)
但是该对象1没有apply采用块的方法,因此编译器会产生错误:
错误:Int(1)不接受参数
Run Code Online (Sandbox Code Playgroud){ val x = 1 { val y = 2 } } ^
对比这个
object I { def apply(a: => Any): Unit = () }
{ val x = I { val y = 2 } }
Run Code Online (Sandbox Code Playgroud)
这是有效的,因为I现在确实有一个apply方法.
为了使这两种情况之间的区别更容易一些,编译器在第一种情况下需要分号.
现在有人可能想知道为什么它之间val x = 1的{换行和未转换为推断的分号.我认为规范中的相关引用将是这个(1.2换行符)(枚举的大多数部分省略([...]),强调我的):
Scala语法[...]包含可选
nl令牌但不接受分号的作品.这导致其中一个位置的换行不终止表达式或语句.这些职位可归纳如下:[...]
在开口括号 '{' 前面,如果该括号是当前陈述或表达的合法延续,
[...]
请注意,此引用仅涵盖具有单个可选换行符的情况.它不适用于两个或多个连续的换行符,例如
scala> {
| val x = 1
|
| { val y = 2 }
| }
Run Code Online (Sandbox Code Playgroud)
是有效的,并被{ val y = 2 }解析为单独的表达式.
我想动机是允许嵌入式DSL使用这样的语法糖:
MY_WHILE(x >= 0)
{
println(x)
x -= 1
}
Run Code Online (Sandbox Code Playgroud)
如果一个人必须将每个这样的MY_WHILE陈述括在另外一对圆括号中,那真的很奇怪,不是吗?
添加到 Andrey 的答案中,您很少在惯用的 Scala 中编写这样的代码,但是,当您这样做时,您应该使用locally:
{
val a = 1
locally {
val b = a * 2
locally {
val c = b + 4
c
}
}
}
Run Code Online (Sandbox Code Playgroud)
这个案例正是locally存在的原因。