Почему я получаю "отсутствующий параметр для расширенной функции" в одном случае, а не в другом?
Дело в этом:
Seq(fromDir, toDir) find (!_.isDirectory) foreach (println(_))
Если это не так:
Seq(fromDir, toDir) find (!_.isDirectory) foreach (throw new Exception(_.toString))
Компиляция заканчивается этой ошибкой:
error: missing parameter type for expanded function ((x$4) => x$4.toString)
Теперь, если я напишу его таким образом, он снова скомпилируется:
Seq(fromDir, toDir) find (!_.isDirectory) foreach (s => throw new Exception(s.toString))
Я уверен, что есть разумное объяснение;)
Ответы
Ответ 1
Это уже рассмотрено в связанном вопросе. Подчеркивания расширяются к ближайшему закрытию Expr
: выражения верхнего уровня или выражения в круглых скобках.
(_.toString)
- выражение в круглых скобках. Таким образом, аргумент, который вы передаете Exception
в случае ошибки, после расширения - это полная анонимная функция (x$1) => x$1.toString
типа A <: Any => String
, а Exception
ожидает String
.
В случае println
_
сам по себе не имеет синтаксической категории Expr
, но (println (_))
есть, поэтому вы получаете ожидаемый (x$0) => println(x$0)
.
Ответ 2
Разница заключается в том, означает ли _
весь параметр или является частью выражения. В зависимости от того, он попадает в одну из двух следующих категорий:
Частично примененная функция
Seq(fromDir, toDir) find (!_.isDirectory) foreach (println(_))
означает
Seq(fromDir, toDir) find (!_.isDirectory) foreach ((x$1) => println(x$1))
Анонимный функциональный параметр
Seq(fromDir, toDir) find (!_.isDirectory) foreach (throw new Exception(_.toString))
означает
Seq(fromDir, toDir) find (!_.isDirectory) foreach (throw new Exception((x$1) => x$1.toString))