Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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 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?

like image 949
Laurence Gonsalves Avatar asked Jun 09 '17 21:06

Laurence Gonsalves


People also ask

How do you define a recursive type?

In computer programming languages, a recursive data type (also known as a recursively-defined, inductively-defined or inductive data type) is a data type for values that may contain other values of the same type. Data of recursive types are usually viewed as directed graphs.

Can datatype definitions be recursive?

Any datatype, the definition of which somehow involves a reference to itself, is considered a recursive datatype. Most commonly, however, (in C, at least) such references to itelf are pointers to elements of the same type. You have already seen the most common example of recursive types: linked lists.


1 Answers

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.

like image 189
Logain Avatar answered Jan 03 '23 01:01

Logain