Ошибка с литералом с плавающей запятой в Scala REPL

#scala #floating-point #literals #read-eval-print-loop #scala-repl

#scala #с плавающей запятой #литералы #чтение-оценка-печать-цикл #scala-repl

Вопрос:

Определение литерала с плавающей запятой в Scala

 floatingPointLiteral  ::=  digit {digit} ‘.’ digit {digit} [exponentPart] [floatType]
                        |  ‘.’ digit {digit} [exponentPart] [floatType]
                        |  digit {digit} exponentPart [floatType]
                        |  digit {digit} [exponentPart] floatType
exponentPart          ::=  (‘E’ | ‘e’) [‘ ’ | ‘-’] digit {digit}
floatType             ::=  ‘F’ | ‘f’ | ‘D’ | ‘d’
  

Когда я пытаюсь ввести литерал с плавающей запятой, который начинается с точки, я получаю сообщение об ошибке:

 scala> .123
        ^
   error: ';' expected but double literal found.
  

Если присвоить такой литерал какой-либо переменной, все в порядке

 scala> val x = .123
x: Double = 0.123
  

Почему он так себя ведет?

Комментарии:

1. Зачем вам нужно записывать любое число в консоль Scala без какого-либо назначения или возврата? У этого числа просто нет средств.

2. Или используйте ammonite, который намного лучше Scala REPL, чем vanilla REPL. Он обрабатывает этот случай правильно.

3. Вы тоже хотите digit {digit} ‘.’ [exponentPart] [floatType] ? Является ли «123.e45» недопустимым?

Ответ №1:

Вероятно, вставленная вами цитата взята из сводки синтаксиса.

Прежде чем мы ответим на ваш вопрос, давайте обратим внимание на следующее:

 scala> 1.213
res1: Double = 1.213
  

Итак, проблема здесь не в плавающей запятой, а в том факте, что выражение начинается с точки. Это заставляет консоль, как и обычную программу Scala, вычислять выражение для последнего вычисленного объекта.

Давайте рассмотрим пример:

 scala> val d = 1.123
d: Double = 1.123

scala> .equals(1.123)
res10: Boolean = true

scala> .equals(1.123)
res11: Boolean = false

scala> .toString
res12: String = false
  

Как вы можете видеть, каждая новая строка является продолжением предыдущей. Вы можете вернуться назад, например:

 scala> res10
res13: Boolean = true
  

Но объект в кэше является последним результатом.

В вашем примере, вероятно, последним успешным запуском вашей консоли был val x = .123 , который помещал последнее res как Double . При .123 запуске вы запускаете другой BlockStat . Лексер определяет, что это a Block , и, следовательно, ожидает a semi (который является a ; ) между разными BlockStat s.

При запуске новой консоли она работает так, как ожидалось:

 scala> .123
res0: Double = 0.123