Когда мне нужно обрабатывать мои методы как частично применяемые функции в Scala?
Я заметил, что когда я работаю с функциями, которые ожидают другие функции в качестве параметров, я иногда могу это сделать:
someFunction(firstParam,anotherFunction)
Но в других случаях компилятор дает мне ошибку, говоря мне, что я должен написать такую функцию, чтобы она рассматривала ее как частично примененную функцию:
someFunction(firstParam,anotherFunction _)
Например, если у меня есть это:
object Whatever {
def meth1(params:Array[Int]) = ...
def meth2(params:Array[Int]) = ...
}
import Whatever._
val callbacks = Array(meth1 _,meth2 _)
Почему я не могу использовать следующий код:
val callbacks = Array(meth1,meth2)
В каких обстоятельствах компилятор скажет мне добавить _
?
Ответы
Ответ 1
Правило на самом деле просто: вы должны написать _
всякий раз, когда компилятор явно не ожидает объект Function
.
Пример в REPL:
scala> def f(i: Int) = i
f: (i: Int)Int
scala> val g = f
<console>:6: error: missing arguments for method f in object $iw;
follow this method with `_' if you want to treat it as a partially applied function
val g = f
^
scala> val g: Int => Int = f
g: (Int) => Int = <function1>
Ответ 2
В Scala метод не является функцией. Компилятор может преобразовать метод неявно в функцию, но он должен знать, какой вид. Таким образом, либо вы используете _
для его преобразования явно, либо можете указать некоторые признаки того, какой тип функции использовать:
object Whatever {
def meth1(params:Array[Int]): Int = ...
def meth2(params:Array[Int]): Int = ...
}
import Whatever._
val callbacks = Array[ Array[Int] => Int ]( meth1, meth2 )
или
val callbacks: Array[ Array[Int] => Int ] = Array( meth1, meth2 )
Ответ 3
В дополнение к тому, что сказал Жан-Филипп Пелле, вы можете использовать частично прикладные функции при написании классов делегатов:
class ThirdPartyAPI{
def f(a: Int, b: String, c: Int) = ...
// lots of other methods
}
// You want to hide all the unnecessary methods
class APIWrapper(r: ThirdPartyAPI) {
// instead of writing this
def f(a: Int, b: String, c: Int) = r.f(a, b, c)
// you can write this
def f(a: Int, b: String, c: Int) = r.f _
// or even this
def f = r.f _
}
EDIT добавлена часть def f = r.f _
.