Частичное применение функции Scala
Я пытаюсь понять, как функция частичного приложения работает в Scala.
Для этого я построил этот простой код:
object Test extends App {
myCustomConcat("General", "Public", "License") foreach print
GeneralPublicLicenceAcronym(myCustomConcat(_)) foreach print
def myCustomConcat(strings: String*): List[Char] = {
val result = for (s <- strings) yield {
s.charAt(0)
}
result.toList
}
def GeneralPublicLicenceAcronym (concatFunction: (String*) => List[Char] ) = {
myCustomConcat("General", "Public", "License")
}
}
Функция myCostumConcat принимает на вход массив String и возвращает список, содержащий первую букву каждой строки.
Итак, код
myCustomConcat("General", "Public", "License") foreach print
напечатает на консоли: GPL
Предположим теперь, что я хочу написать функцию для генерации аббревиатуры GPL, используя (в качестве входного параметра) мою предыдущую функцию, извлекающую первую букву каждой строки:
def GeneralPublicLicenceAcronym (concatFunction: (String*) => List[Char] ): List[Char] = {
myCustomConcat("General", "Public", "License")
}
Запуск этой новой функции с частичным применением:
GeneralPublicLicenceAcronym(myCustomConcat(_)) foreach print
Я получаю эту ошибку:
Ошибка:(8, 46) несоответствие типов; найдено: Seq[String] требуется: String GeneralPublicLicenceAcronym(myCustomConcat(_)) foreach print
Зачем? Могу ли я использовать частичную заявку в этом случае?
1 ответ
Все, что вам нужно сделать, это изменить myCustomConcat(_)
в myCustomConcat _
или просто myCustomConcat
То, что вы делаете, не является частичным приложением - оно просто использует метод в качестве значения функции.
В некоторых случаях (когда ожидается значение функции) компилятор решит, что вы имеете в виду, но в других контекстах вам часто приходится сообщать компилятору о своем намерении, используя _
суффикс.
"частичное применение" означает, что мы предоставляем некоторые, но не все, аргументы функции, чтобы создать новую функцию, например:
def add(x: Int, y: Int) = x + y //> add: (x: Int, y: Int)Int
val addOne: Int => Int = add(1, _) //> addOne : Int => Int = <function1>
addOne(2) //> res0: Int = 3
Я предполагаю, что ваш случай может рассматриваться как частичное применение, но не применяя ни один из аргументов - вы можете использовать здесь частичный синтаксис приложения, но вам нужно дать _*
подсказка компилятору из-за повторяющихся параметров (String*
), что в конечном итоге немного некрасиво:
myCustomConcat(_:_*)
См. Также: Атрибут типа Scala для varargs, использующих _* причиной ошибки