Почему вывод 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 с точкой с запятой не работает на этой конкретной строке?
Ответы
Ответ 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
заставляет различную интерпретацию синтаксическим анализатором.