【问题标题】:Partial function application in KotlinKotlin 中的偏函数应用
【发布时间】:2018-04-21 05:35:10
【问题描述】:

部分函数应用程序的语法有问题。以下代码运行良好,并输出:two-three-four

import kotlin.coroutines.experimental.*

inline fun <T> Iterable<T>.forEachFrom(beg:Int, act:(T)->Unit) {
  var i=0;  if (beg>=0) for (e in this) if (i++ >= beg) act(e)
}    // sample function I am testing; please don't change this!

fun main(a:Array<String>) {
  val l = listOf("zero", "one", "two", "three", "four")
  fun test() = buildSequence { l.forEachFrom(2) { yield(it) } }.joinToString("-")
  println(test())
}

我想封装我的test(),所以它被称为: test(l.forEachFrom(2)) 但是,我似乎无法正确理解类型/语法。 我将如何重写 test() 函数定义以实现这一点?

【问题讨论】:

  • 但是你的act返回Unit,那yield怎么可能收集到东西?
  • 在您的情况下,阻止我找到简单解决方案的最大问题是 Kotlin 协程只能从内联的高阶函数执行挂起调用,因此您不能只创建部分应用的函数通过编写一个与最后一个参数一起工作的 lambda 并在那里传递 { yield(it) }:编译器需要你传递它的地方是一个内联函数。
  • @hotkey Inline 对于这些测试过程可能没问题,但我仍然不确定该语法会是什么样子。我试过了,但我认为我仍然没有得到正确的类型。如果所有内容都被内联,你能告诉我语法会是什么样子吗?

标签: kotlin partial-application


【解决方案1】:

您要达到的目标并不完全清楚。如果您提供更多详细信息,我们可以提供更好的答案。也就是说,以下代码有望为您指明正确的方向。

import kotlin.coroutines.experimental.*

inline fun <T,S> Iterable<T>.mapFrom(beg:Int, act:(T)->S) =
    drop(beg).map {act(it)}

fun main(a:Array<String>) {
    val l = listOf("zero", "one", "two", "three", "four")
    fun <T> test(values: List<T>) = values.joinToString("-")
    println(test(l.mapFrom(2) {it}))
}

forEachFrom 并没有真正用作forEach,而是用作map。这是主要问题,因为您使用 yield 来输出结果,而不仅仅是返回结果。如果forEachFrom 也将用于它的副作用,它仍然可以用于那个目的。

此外,test 没有理由将函数作为参数,而不仅仅是接受该函数的输出作为其参数。 buildSequence 调用也是多余的,因为您立即调用 joinToString 这是终端并强制对 buildSequence 内部的函数进行急切计算。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2014-04-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多