ToList на Range с суффиксной нотацией вызывает несоответствие типов

Я только начинаю со Scala и пробую некоторые вещи в Range и List, я получаю что-то очень странное с очень простым фрагментом. Я использую возвышенное, чтобы редактировать и выполнять эти фрагменты:

val a = 1 to 10
println(a)

доходность

Range(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)

в то время как

val a = 1 to 10
val b = a toList
println(a)

дает мне ошибку:

/home/olivier/Dropbox/Projects/ProjectEuler/misc/scala/ch05_ex02.scala:5:     error: type mismatch;
 found   : Unit
 required: Int
println(a)
       ^
one error found

В REPL, напротив, я не получаю никакой ошибки. Версия Scala 2.9.2

 Reactormonk20 июн. 2016 г., 23:34
Вы, вероятно, хотите Scala 2.11 или хотя бы 2.10. Многие библиотеки не кросс-скомпилированы в 2.9, поэтому вы устареете через несколько лет.

Ответы на вопрос(2)

использование-Xprint:parser,typer чтобы увидеть, как анализируется код и какие типы выводятся. Ответ объясняет взаимодействие постфикса и инфикса; но ошибка заставляет вас идти, "НоtoList даже не беретInt«.

$ scala -Xprint:parser,typer

scala> :pa
// Entering paste mode (ctrl-D to finish)

1 to 10 toList
println("hi")

// Exiting paste mode, now interpreting.

[[syntax trees at end of                    parser]] // <console>
package $line3 {
  object $read extends scala.AnyRef {
// ...
    val res0 = 1.to(10).toList(println("hi"))
// ...
[[syntax trees at end of                     typer]] // <console>
package $line3 {
  object $read extends scala.AnyRef {
//...
    private[this] val <res0: error>: <error> = scala.this.Predef.intWrapper(1).to(10).toList.apply(println("hi"));
//...
Решение Вопроса

Это вызвано тем, как компилятор анализируетСуффиксная запись (для методов арити 0). Он попытается разобрать это какИнфиксная нотация (если возможно). Это заставляет компилятор анализировать ваш код следующим образом:

val a = 1 to 10
val b = a toList println(a)

Или конкретно последняя строка с точечной нотацией:

val b = a.toList.apply(println(a))

List[A] имеетapply прием методапеременные аргументы типаA (в этом случаеInt) а такжеprintln возвращаетсяUnit, Вот причина этого конкретного сообщения об ошибке.

Этот стиль не одобряется, как указано вДокументация Scala:

Суффиксная запись

Scala позволяет вызывать методы arity-0, используя суффиксную нотацию:

names.toList
// is the same as
names toList // Unsafe, don't use!

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

names toList
val answer = 42   // will not compile!

В лучшем случае это может привести к неожиданным ошибкам компиляции, а в худшем - к счастью скомпилированным неисправным кодом. Хотя синтаксис используется некоторыми DSL, его следует считать устаревшим и его следует избегать.

Начиная с Scala 2.10, использование суффиксного обозначения оператора приведет к предупреждению компилятора.

Как рекомендуется, используйте точечную запись:

val b = a.toList

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

val b = a toList;

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

[warn] postfix operator toList should be enabled
[warn] by making the implicit value scala.language.postfixOps visible.
[warn] This can be achieved by adding the import clause 'import scala.language.postfixOps'
[warn] or by setting the compiler option -language:postfixOps.
[warn] See the Scaladoc for value scala.language.postfixOps for a discussion
[warn] why the feature should be explicitly enabled.
[warn]   val b = a toList;
[warn]             ^
[warn] one warning found

В REPL, напротив, я не получаю никакой ошибки.

Потому что REPL выполняется построчно. КакtoList выражение не сменяетсяprintln выражение, оно компилируется. Если вы входите в режим вставки (:paste) и скопируйте его как блок кода, вы увидите то же поведение.

Более подробную информацию можно найти в этомВопрос о группе пользователей Scala

 Olivier Georg21 июн. 2016 г., 10:52
Отлично, теперь все это имеет смысл! Урок выучен! Большое спасибо!
 Yuval Itzchakov21 июн. 2016 г., 11:01
@OliverGeorg Добро пожаловать.

Ваш ответ на вопрос