Функция расширения Котлина функции с приемником - PullRequest
4 голосов
/ 07 ноября 2019

Я играю с функциями расширения Kotlin. Я хотел бы создать функцию расширения для функции, возвращающей логическое значение, с получателями, которые возвращают функцию дополнения.

Моя цель - иметь возможность написать:

val isEven: Int.() -> Boolean = { this % 2 == 0 }
val isOdd: Int.() -> Boolean = isEven.complement()

Я действительно понимаю, что тамлучше, более ясные способы делать то, что я делаю, я хочу лучше понять сам язык здесь, поэтому, пожалуйста, не говорите мне писать isOdd как { !isEven() }:)

Я хочу что-тонапример:

fun <I> (I.() -> Boolean).complement(): I.() -> Boolean = TODO()

Теперь,

fun <I> (I.() -> Boolean).complement(): I.() -> Boolean = this

компилируется правильно, поэтому синтаксис определенно имеет здесь смысл. Проблема в том, что this имеет тип I.() -> Boolean, и мне нужно было бы получить доступ к «внутреннему получателю» моей функции с помощью получателя, что-то вроде this@this, чтобы написать что-то вроде:

fun <I> (I.() -> Boolean).complement(): I.() -> Boolean = { !(this@this).this() }

где this@this будет типа I. Есть ли способ достичь этого эффекта?

Кроме того, я заметил, что я не знаю, как вызвать функцию с приемником, я пытался:

fun <I> (I.() -> Boolean).complement(innerthis: I): I.() -> Boolean = { !this(innerthis) }

Я получаю error: expression 'this' of type 'I' cannot be invoked as a function. The function 'invoke()' is not found.

Это звучит неправильно для меня! this должен иметь тип I.() -> Boolean, а не I! Я не могу обернуть голову вокруг этого сообщения об ошибке.

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

fun <I> (I.() -> Boolean).complement(innerthis: I): I.() -> Boolean = { !innerthis.this() }

Но я получаю то же самоеошибка. Меня это очень смущает, так как я ожидал innerthis типа I и this типа I.() -> Boolean. Кажется, мои ожидания подтверждаются безупречной компиляцией = this.

Может кто-нибудь объяснить мне ошибку, которую вызывает компилятор?

Спасибо!

1 Ответ

3 голосов
/ 07 ноября 2019

Вы можете устранить неоднозначность внешнего this по имени функции:

fun <I> (I.() -> Boolean).complement(): I.() -> Boolean = { !this@complement(this) }

Здесь this@complement - получатель функции complement, а обычный this - получатель лямбда-функциибуквальный. Для простоты this@complement вызывается как функция с одним аргументом, однако ее можно также назвать функцией расширения, используя более сложный синтаксис:

fun <I>  (I.() -> Boolean).complement(): I.() -> Boolean = { !this.(this@complement)() }
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...