Is it possible to create a recursive function type in Kotlin?

与世无争的帅哥 提交于 2019-12-08 20:42:52

问题


I have functions that represent steps in a process. Each function also knows the next step, if there is one. I'd like to be able to do something like:

fun fooStep() : Step? {
    ... do something ...
    return ::barStep // the next step is barStep
}

These functions are called from a central dispatching function, which contains code a bit like this:

var step = startStep
while (step != null) {
    step = step()
}

Note that the logic in a particular step also determines the next step, if there even is one.

I thought I could define Step as:

typealias Step = () -> Step?

So a Step is a function that returns another Step, or null. However, this fails to compile with:

Kotlin: Recursive type alias in expansion: Step

I can work around this by wrapping the function in an object. eg:

data class StepWrapper(val step: () -> StepWrapper?)

and changing my function signatures accordingly.

Unfortunately, this means that I cannot just use function literals (eg: ::barStep), but instead have to wrap them in a StepWrapper:

fun fooStep() : StepWrapper? {
    ... do something ...
    return StepWrapper(::barStep)
}

(I also have to change my dispatch loop, accordingly.)

I'd like to avoid the need to create these wrapper objects, if possible. Is there any way to do this in Kotlin?


回答1:


You can define it by using some generic interface:

interface StepW<out T> : ()->T?

interface Step : StepW<Step>


class Step1 : Step {
    override fun invoke(): Step? = Step2()
}

class Step2 : Step {
    override fun invoke(): Step? = null
}

Where Step is your recursive function type.




回答2:


Here's how you can make it work though I'm really not sure what you're trying to achieve with it:

typealias Fun<T> = () -> T
typealias Step<T> = () -> (T)

typealias Step1 = Step<Fun<Step2>>
typealias Step2 = Step<Fun<Step3>>
typealias Step3 = Step<Unit>

fun step1(): Step1 {
    return {
        println("step 1")
        ::step2
    }
}

fun step2(): Step2 {
    return {
        println("step 2")
        ::step3
    }
}

fun step3(): Step3 {
    return { println("done") }
}



回答3:


Use an Enum to implement the state pattern with finite states and prefer returning non-null values. An enum can inherit from a function.

enum class Step : () -> Step {
    Step1 {
        override fun invoke() = Step2
    },
    Step2 {
        override fun invoke() = End
    },
    End {
        override fun invoke() = this
    }
}

fun work() {
    var step = Step.Step1
    while (step !== Step.End) {
        step = step()
    }
}


来源:https://stackoverflow.com/questions/44466716/is-it-possible-to-create-a-recursive-function-type-in-kotlin

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!