【问题标题】:When is semicolon mandatory in scala?scala中何时强制使用分号?
【发布时间】:2019-01-31 17:11:28
【问题描述】:

我正在学习如何在 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

因此,在我看来,分号并不是真正的可选,在某些情况下是强制性的。请问在什么情况下分号是必填的?

【问题讨论】:

  • @Bergi 你在说什么?这里是a typical piece of Scala code。它每 177 行包含三个分号,恰好在 {} 中包含多个表达式的情况下(无缘无故,在这种情况下,所有这些分号都可以省略,但是作者懒得输入换行符,显然)。
  • @AndreyTyukin,你的意思是我错误的结果是由于缺少换行符?
  • 大多数时候(我估计大约 99.5% 左右),只有当没有分号的表达式没有任何意义时,分号才是强制性的。例如,{val b = a * 2 { val c = b + 4 ; c }} 没有任何意义,因为2 没有可以将块{ val c = b + 4; c } 作为参数的apply 方法。将其与例如Future 伴随对象,您可以在其中毫无问题地编写 Future { val c = b + 4; c },因为与 2 不同,对象 Future确实提供适当的 apply 方法。
  • @AndreyTyukin,感谢您的解释。我认为在这种情况下将语句放在多行就足够了。

标签: scala syntax semicolon-inference


【解决方案1】:

我会试着从你的例子中提取精髓。

考虑以下代码sn-p:

{ 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 现在确实有一个apply 方法。

为了更容易区分这两种情况,编译器需要在第一种情况下使用分号。

现在人们可能想知道为什么val x = 1{ 之间的换行符没有转换为推断的分号。我认为规范中的相关引用是这样的(1.2 Newline Characters)(大部分枚举部分省略([...]),强调我的):

Scala 语法 [...] 包含产生式,其中 接受可选的nl 标记,但不接受分号。这有 效果是这些位置之一中的 换行符不会终止 表达或陈述。这些职位可以总结如下:

[...]

  • 在左大括号之前'{',如果该大括号是当前语句或表达式的合法延续

    [...]

请注意,此引用仅涵盖带有 single 可选换行符的情况。它不适用于两个或多个连续换行符,例如

scala> {
     |   val x = 1
     | 
     |   { val y = 2 }
     | }

有效,{ val y = 2 } 被解析为单独的表达式。

的动机是允许嵌入式 DSL 的语法糖是这样的:

MY_WHILE(x >= 0)
{
  println(x)
  x -= 1
}

如果必须将每个这样的MY_WHILE-语句括在一对额外的圆括号中,那真的很奇怪,不是吗?

【讨论】:

    【解决方案2】:

    除了 Andrey 的回答之外,您很少使用惯用的 Scala 编写这样的代码,但是,当您这样做时,您应该使用 locally

    {
      val a = 1
      locally {
        val b = a * 2
        locally {
          val c = b + 4
          c
        }
      }
    }
    

    这种情况正是locally 存在的原因。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2011-09-15
      • 2011-12-17
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-02-09
      相关资源
      最近更新 更多