Могу ли я преобразовать Kotlin KFunction1 в KFunction0, применив аргумент? - PullRequest
0 голосов
/ 12 февраля 2019

У меня есть ссылка на функцию, которой нужен параметр.

fun foo(x: Int) = 2 * x
val f: KFunction1<Int, Int> = ::foo

Можно ли написать applyArgument где

val f2: KFunction0<Int> = f1.applyArgument(42) 
assertEquals("foo", f2.name)
assertEquals(84, f2())

Я не хочу использоватьвызываемая ссылка, так как мне нужен доступ к свойству name.

Ответы [ 3 ]

0 голосов
/ 12 февраля 2019

Возможно частичное применение.

Вы можете просто объявить функцию для частичного применения и использовать ее для ссылки ::.

Следовательно, имя не будет исходной функцией.Другой подход - создать свои собственные классы / интерфейсы

data class MyFunction1<T, R>(val name: String, val f: (T) -> R) { 
  operator fun invoke(t: T) = f(t) 
} 

data class MyFunction0<R>(val name: String, val f: () -> R) { 
  operator fun invoke() = f() 
} 

Теперь определите curring:

fun MyFunction1<T, R>.curry(t: T) = MyFunction0(name){ f(t) } 

(это тоже может быть функция-член)

0 голосов
/ 12 февраля 2019

KFunction s предназначены для представления функций, которые явно объявлены в коде Kotlin, но f2 не объявлено нигде в коде.Кроме того, KFunction имеет множество свойств и функций отражения, которые не относятся к применяемой функции f2.Поэтому, даже если это возможно, это не рекомендуется.

Если вы все равно хотите это сделать, вы можете просто написать функцию applyArgument следующим образом:

fun <T, R> KFunction1<T, R>.applyArgument(value: T): KFunction0<R> {
    return object : KFunction<R> by this, KFunction0<R> {
        override fun invoke(): R {
            return this@applyArgument(value)
        }
    }
}

Но, если вам нужно сохранить имя, я бы сделалэто безопасным способом.Одним из способов может быть:

data class Named<out T>(val name: String, val value: T)

fun <T, R> Named<T>.map(transform: (T) -> R): Named<R> = Named(name, transform(value))

val <F : KFunction<*>> F.named: Named<F>
    get() = Named(name, this)

Тогда используйте его:

fun foo(x: Int) = 2 * x
val f: Named<(Int) -> Int> = ::foo.named

val f2: Named<() -> Int> = f.map { fValue -> { fValue(42) } }
assertEquals("foo", f2.name)
assertEquals(84, f2.value())
0 голосов
/ 12 февраля 2019

надеюсь, это поможет вам:

fun foo(x: Int) = 2 * x
val f1 = ::foo
val f0 = { -> f1(42) }
f0() //84
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...