List("This","is","Scala").foreach(a => print(a+" "))
компилируется нормально, но
List("This","is","Scala").foreach(print(_+" "))
не может пожаловаться на отсутствующий тип параметра. Я не мог понять, почему это не помогает.
РЕДАКТИРОВАТЬ: я имел в виду печать, а не печать - не то, чтобы это имело логическое значение.
Проблема в том, что этот
List("This","is","Scala").foreach(print(_+" "))
не эквивалентен
List("This","is","Scala").foreach(a => print(a+" "))
, а
List("This","is","Scala").foreach(print(a => a+" "))
. Теперь давайте посмотрим на сигнатуру типа foreach
:
def foreach [B] (f: (A) ⇒ B) : Unit
где
- это параметр типа самого списка
. Поскольку у нас есть List [String]
, компилятор знает, что нужно передать foreach
функцию Function [String, B]
.
В a => print (a + "")
тогда уже известен тип a
: String
.
В print (a => a + "")
есть проблема, поскольку print
не является функцией
. Однако компилятор еще не учел это - он все еще пытается скомпилировать a => a + ""
. Итак, давайте посмотрим на тип Predef.print
:
def print (x: Any) : Unit
Итак, a => a + ""
должен иметь тип Any
, что, конечно же, значит это может быть что угодно. Это не помогает компилятору определить тип a
. Что на самом деле не имеет значения, потому что вы не хотели печатать Function
в первую очередь.
Scala читает (_ + "")
как x = > x + ""
. Но println
не содержит никакой информации о типе, чтобы помочь компилятору угадать, какой тип x
может быть, поэтому он выдает эту ошибку.
Что вы хотели, так это заметить, что println
не работает, и выполнить рекурсию в обратном направлении, а затем повторить попытку для foreach
. Но он не может этого сделать: println
может принимать любой аргумент, включая функцию, поэтому x => x + ""
- вполне допустимая вещь для println
попробовать напечатать.
(И даже в случае, когда он теоретически может вернуться назад, обычно этого не происходит.)