Первый случай ,
save(throw new RuntimeException("boom!")) _
Согласно "Scala Reference" (§6.7), вместо списка аргументов используется завершающее подчеркивание, ивыражение преобразуется в
val f: (Boolean) => Unit = save(throw new RuntimeException("boom!"))
, где первый аргумент def save
немедленно вычисляется.
Выражение e _ корректно сформировано, если e имеет тип метода или еслиe является параметром вызова по имени.Если e - метод с параметрами, e _ представляет e, преобразованный в тип функции путем расширения eta (§6.26.5).Если e является параметром без параметров или параметром вызова по имени типа => T, e _ представляет функцию типа () => T, которая оценивает e при применении к пустому списку параметров ().
Чтобы все работало так, как вы ожидаете, требуются некоторые модификации:
scala> def save(f:() => Any)(run:Boolean) { if (run) { println("running f"); f() } else println("not running f") }
save: (f: () => Any)(run: Boolean)Unit
scala> val f = save(() => throw new RuntimeException("boom!")) _
f: (Boolean) => Unit = <function1>
scala> f(true)
running f
java.lang.RuntimeException: boom!
at $anonfun$1.apply(<console>:6)
Второй случай ,
save(throw new RuntimeException("boom!"))(_)
Согласно «Scala Reference» (§6.23), когда в качестве замены аргумента используется заполнитель, выражение преобразуется в
val f: (Boolean) => Unit = save(throw new RuntimeException("boom!"))(_)