Подтвердить что ты не робот

Почему вывод Scala с запятой заканчивается?

При компиляции следующего кода с Scala 2.7.3,

package spoj

object Prime1 {
  def main(args: Array[String]) {
    def isPrime(n: Int) = (n != 1) && (2 to n/2 forall (n % _ != 0))
    val read = new java.util.Scanner(System.in)
    var nTests = read nextInt // [*]
    while(nTests > 0) {
      val (start, end) = (read nextInt, read nextInt)
      start to end filter(isPrime(_)) foreach println
      println
      nTests -= 1
    }
  }
}

Я получаю следующую ошибку времени компиляции:

PRIME1.scala:8: error: illegal start of simple expression
    while(nTests > 0) {
    ^
PRIME1.scala:14: error: block must end in result expression, not in definition
  }
  ^
two errors found

Когда я добавляю точку с запятой в конце строки, прокомментированную как [*], программа компилируется в порядке. Может кто-нибудь объяснить, почему вывод Scala с точкой с запятой не работает на этой конкретной строке?

4b9b3361

Ответ 1

Это потому, что scala предполагает, что вы используете синтаксис a foo b (эквивалентно a.foo(b)) при вызове readInt. То есть предполагается, что цикл while является аргументом readInt (напомним, что каждое выражение имеет тип), и, следовательно, последний оператор является объявлением:

var ntests = read nextInt x

где x - ваш блок while.

Я должен сказать, что в качестве предпочтительного варианта я вернулся к использованию обычного синтаксиса a.foo(b) над a foo b, если специально не работать с DSL, который был разработан с учетом этого (например, t29 > ). Это делает вещи намного яснее в целом, и вы не укусаетесь такими странными вещами, как это!

Ответ 2

Дополнительный комментарий к вопросу от oxbow_lakes...

var ntests = read nextInt()

Должны исправить вещи для вас в качестве альтернативы точкам с запятой

Ответ 3

Чтобы добавить немного больше о выводе с запятой, Scala делает это в два этапа. Сначала он отображает специальный токен под названием nl по спецификации языка. Парсер позволяет использовать nl как разделитель операторов, а также точки с запятой. Тем не менее, nl также разрешено в нескольких других местах по грамматике. В частности, один единственный nl разрешен после операторов infix, когда первый токен на следующей строке может начать выражение - и while может начать выражение, поэтому он интерпретирует его таким образом. К сожалению, хотя while может начать выражение, оператор while не может использоваться в выражении инфикса, следовательно, ошибка. Лично для парсера это кажется довольно причудливым способом, но там вполне правдоподобно разумное обоснование за все, что я знаю!

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