Частичное применение функции 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, использующих _* причиной ошибки

Другие вопросы по тегам