Передача значений vargs в другую функцию с несколькими параметрами в Kotlin? - PullRequest
0 голосов
/ 20 марта 2019

У меня есть две функции расширения, объявленные в Kotin (1.3):

fun SomeClass.fooBuilder(vararg x: String, fn: ((String) -> Unit)? = null): Result.Builder = TODO()
fun SomeClass.foo(vararg x: String, fn: ((String) -> Unit)? = null): Result = fooBuilder(*x, fn).build()

Что я хочу сделать, это позвонить fooBuilder из foo и просто вызвать build() для результата, возвращенного изfooBuilder.

К сожалению, приведенный выше код не компилируется, поскольку вызов fooBuilder(*x, fn).build() завершается неудачно с:

Error:(28, 143) Kotlin: Type mismatch: inferred type is ((String) -> Unit)? but String was expected

Т.е. кажется, что компилятор считает, что я хочу передать дополнительную строку (x) аргументы, но на самом деле я хочу передать это функция.

Как я могу решить эту проблему, сохранив при этом возможность использовать скобки, чтобы пропустить скобки при указании fn, как в этом примере:

SomeClass().foo("x") { str -> println("Hello $str") }

Ответы [ 3 ]

2 голосов
/ 20 марта 2019

У вас есть два варианта:

1) vararg должен быть последним аргументом (но тогда вы не сможете использовать упрощенный лямбда-вызов)

2) использовать именованные параметры:

fun SomeClass.fooBuilder(vararg x: String, fn: ((String) -> Unit)? = null): Result.Builder = TODO()
fun SomeClass.foo(vararg x: String, fn: ((String) -> Unit)? = null): Result = fooBuilder(x = *x, fn = fn).build()

Ошибка, которую вы получили, очень логична - как компилятор может узнать, когда передача vararg argumnets закончена?

2 голосов
/ 20 марта 2019

Любые параметры, которые идут после vararg, должны быть переданы как именованные параметры.Попробуйте:

fun SomeClass.fooBuilder(vararg x: String, fn: ((String) -> Unit)? = null): Result.Builder = TODO()
fun SomeClass.foo(vararg x: String, fn: ((String) -> Unit)? = null): Result = fooBuilder(*x, fn = fn).build() // here I used named param

// it should work now:
SomeClass().foo("x") { str -> println("Hello $str") }
0 голосов
/ 20 марта 2019

Вот еще один вариант - он не такой четкий, короткий или эффективный, как использование именованного параметра, но я включил его для полноты.

Это должно пройти fn вне паренов, точно так же, как это должен сделать вызывающий. Я не думаю, что вы можете сделать это напрямую, но вы можете перевести вызов на fn так:

fun SomeClass.foo(vararg x: String, fn: ((String) -> Unit)? = null): Result
    = fooBuilder(*x){ fn?.invoke(it) }.build()
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...