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

I have functions that represent steps in a process. Each function also knows the next step, if any. I would 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 dispatch function that contains code similar to this:

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

Note that the logic at a particular step also determines the next step, if even one.

I thought I could determine Stephow:

typealias Step = () -> Step?

So, Stepthis is a function that returns another Stepor null. However, this cannot be compiled with:

Kotlin: Recursive type alias in expansion: Step

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

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

and accordingly changing the function signatures.

, , (: ::barStep), StepWrapper:

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

( , .)

-, . ?

+6
3

, - :

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
}

Step - .

+1

, , :

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") }
}
0

Use Enum to implement end state state patterns and prefer to return nonzero values. An enumeration 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()
    }
}
0
source

All Articles