Как ссылаться на функцию, которая принимает varargs - PullRequest
8 голосов
/ 08 июля 2019

Если я определяю следующую функцию для возврата функции:

    def foo(): (Int*) => String = { is =>
        is.map(_.toString).mkString(", ")
    }

И затем пытаюсь ссылаться на нее:

    val bar = foo()
    bar(1, 2, 3)

Я получаю ошибку компилятора

Too many arguments (3) for method apply...

Но когда я явно определяю ссылочный тип, он прекрасно компилируется:

    val bar2: (Int*) => String = foo()
    bar2(4, 5, 6)

Можно ли как-то определить мою функцию foo() без необходимости использования этого явного ссылочного типа?

1 Ответ

10 голосов
/ 08 июля 2019

Это известная ошибка , которая была «исправлена» в Scala 2.13 , поскольку исключила возможность использовать * в типах вне сигнатур методов вообще.

Если вы заботитесь только о версиях Scala до 2.13, вы можете использовать определенный вами обходной путь - явно пометить переменную функции звездообразным типом.Если вам нужна поддержка 2.13, вы можете сделать что-то вроде этого, благодаря единственному абстрактному синтаксису метода Scala:

trait MyVarargsFunc[-A, +B] {
  def apply(is: A*): B
}

val f: MyVarargsFunc[Int, String] = is => is.map(_.toString).mkString(", ")

Или, если вы хотите по-настоящему выглядеть модно:

trait *=>[-A, +B] { def apply(is: A*): B }

val f: Int *=> String = is => is.map(_.toString).mkString(", ")

Изатем:

scala> f(1, 2, 3)
res0: String = 1, 2, 3

Это также будет работать на 2.12 (я проверял), и оно должно работать на 2.11 с -Xexperimental (и оно будет работать даже на 2.10 или vanilla 2.11, если вы создадите экземпляр MyVarargsFuncв явном виде - вы просто не получите красивый синтаксис литерала функции).

...