#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