Когда точка с запятой обязательна в скале? - PullRequest
0 голосов
/ 25 августа 2018

Я учусь программировать в 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

Поэтому мне кажется, что точка с запятой на самом деле не является необязательнойи является обязательным в некоторых ситуациях.Могу ли я спросить, в какой ситуации точка с запятой является обязательной?

Ответы [ 2 ]

0 голосов
/ 25 августа 2018

Добавляя к ответу Андрея, вы редко пишете такой код в идиоматическом Scala, но когда вы это делаете, вы должны использовать locally:

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

Именно в этом случае и существует locally.

0 голосов
/ 25 августа 2018

Я постараюсь извлечь суть из вашего примера.

Рассмотрим следующий фрагмент кода:

{ 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 Символы новой строки ) (большинство частей перечислений опущено ([...]), выделено мое):

Грамматика Scala [...] содержит произведения, в которых необязательные nl токены, но не точки с запятой, принимаются. Это имеет эффект, что символ новой строки в одной из этих позиций не завершает выражение или утверждение . Эти позиции можно обобщить следующим образом:

[...]

  • перед открывающей скобкой ‘{’, , если эта скобка является законным продолжением текущего оператора или выражения ,

    [...]

Обратите внимание, что эта цитата охватывает только случай с одиночным необязательным переводом строки. Он не действует в течение двух или более последовательных разрывов строк, например,

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

допустимо, а { val y = 2 } анализируется как отдельное выражение.

I думаю мотивация состояла в том, чтобы разрешить встроенные DSL с синтаксическим сахаром, как это:

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

Было бы очень странно, если бы каждый из этих MY_WHILE операторов заключал в дополнительную пару круглых скобок, не так ли?

...