¿Es posible crear un tipo de function recursiva en Kotlin?

Tengo funciones que representan pasos en un process. Cada function también conoce el siguiente paso, si hay uno. Me gustaría poder hacer algo como:

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

Estas funciones se llaman desde una function central de despacho, que contiene un código como este:

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

Tenga en count que la lógica en un paso particular también determina el siguiente paso, si es que hay uno.

Pensé que podría definir Step como:

 typealias Step = () -> Step? 

Entonces un Step es una function que devuelve otro Step o nulo. Sin embargo, esto no se puede comstackr con:

 Kotlin: Recursive type alias in expansion: Step 

Puedo evitar esto envolviendo la function en un object. p.ej:

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

y cambiando mis firmas de funciones en consecuencia.

Desafortunadamente, esto significa que no puedo usar ::barStep funciones (por ej .: ::barStep ), sino que tengo que envolverlas en un StepWrapper :

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

(También tengo que cambiar mi ciclo de envío, en consecuencia).

Me gustaría evitar la necesidad de crear estos objects de envoltura, si es posible. ¿Hay alguna manera de hacer esto en Kotlin?

Puede definirlo utilizando una interfaz genérica:

 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 } 

Donde Step es su tipo de function recursiva.

Así es cómo puedes hacer que funcione, aunque realmente no estoy seguro de lo que intentas lograr con él:

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

Use un Enum para implementar el patrón de estado con estados finitos y prefiera devolver valores que no sean nulos. Una enumeración puede henetworkingar de una 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() } } 
  • Usar con autoclose en Kotlin
  • ¿Puede un object de class creado "sobre la marcha" en Kotlin tener un constructor?
  • kotlin android - Diálogo personalizado con patrón de construcción y Java 8 lambda
  • split kotlin de arguments nullable
  • Cómo importar un directory / package completo en Intellij para fines de testing
  • Conversión de methods de estilo de procedimiento a estilo funcional
  • Mi propia solución para la ausencia de Try-with-Resources de Kotlin
  • Kotlin valor negativo negativo de retorno de modul
  • propiedad de delegado kotlin, en un método get () cómo puedo acceder al valor?
  • ¿Cómo funciona el ejemplo de los numbers primos de la documentation de Corotines de Kotlin?
  • Kolin Spek Framework se bloquea con Gradle