是否可以通过应用参数将Kotlin KFunction1转换为KFunction0?

时间:2019-02-12 12:32:23

标签: reflection kotlin

我引用了需要参数的函数。

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 :(得分:1)

希望它可以帮助您

fun foo(x: Int) = 2 * x
val f1 = ::foo
val f0 = { -> f1(42) }
f0() //84

答案 1 :(得分:1)

f2旨在表示在Kotlin代码中明确取消的功能,但是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())

然后使用它:

[{                                                                   
  firstname: "John",lastname:"Peter",department:"wsed4"                      
},{                                                                  
   firstname: "Daniel",lastname:"McGregor",department:"asdf2"           
}]

答案 2 :(得分:0)

可以部分申请。

您可以只声明一个用于部分应用程序的函数,并将其用于::引用。

因此,该名称将不是原始功能。另一种方法-创建自己的类/接口

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() 
} 

现在定义路线:

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

(它也可以是成员函数)