是否可以在 Kotlin 中创建递归函数类型?
Is it possible to create a recursive function type in Kotlin?
我有代表流程中步骤的函数。每个函数也知道下一步,如果有的话。我希望能够做类似的事情:
fun fooStep() : Step? {
... do something ...
return ::barStep // the next step is barStep
}
这些函数是从一个中央调度函数调用的,它包含的代码有点像这样:
var step = startStep
while (step != null) {
step = step()
}
请注意,如果有下一步,特定步骤中的逻辑也会决定下一步。
我想我可以将 Step
定义为:
typealias Step = () -> Step?
所以 Step
是 returns 另一个 Step
的函数,否则为空。但是,这无法编译:
Kotlin: Recursive type alias in expansion: Step
我可以通过将函数包装在一个对象中来解决这个问题。例如:
data class StepWrapper(val step: () -> StepWrapper?)
并相应地更改我的函数签名。
不幸的是,这意味着我不能只使用函数文字(例如:::barStep
),而是必须将它们包装在 StepWrapper
:
中
fun fooStep() : StepWrapper? {
... do something ...
return StepWrapper(::barStep)
}
(我还必须相应地更改我的调度循环。)
如果可能,我想避免创建这些包装器对象。在 Kotlin 中有什么方法可以做到这一点吗?
您可以使用一些通用接口来定义它:
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
是您的递归函数类型。
尽管我真的不确定您想要用它实现什么,但您可以通过以下方式让它发挥作用:
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") }
}
使用 Enum 来实现具有有限状态的状态模式并且更喜欢返回非空值。枚举可以继承自函数。
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()
}
}
我有代表流程中步骤的函数。每个函数也知道下一步,如果有的话。我希望能够做类似的事情:
fun fooStep() : Step? {
... do something ...
return ::barStep // the next step is barStep
}
这些函数是从一个中央调度函数调用的,它包含的代码有点像这样:
var step = startStep
while (step != null) {
step = step()
}
请注意,如果有下一步,特定步骤中的逻辑也会决定下一步。
我想我可以将 Step
定义为:
typealias Step = () -> Step?
所以 Step
是 returns 另一个 Step
的函数,否则为空。但是,这无法编译:
Kotlin: Recursive type alias in expansion: Step
我可以通过将函数包装在一个对象中来解决这个问题。例如:
data class StepWrapper(val step: () -> StepWrapper?)
并相应地更改我的函数签名。
不幸的是,这意味着我不能只使用函数文字(例如:::barStep
),而是必须将它们包装在 StepWrapper
:
fun fooStep() : StepWrapper? {
... do something ...
return StepWrapper(::barStep)
}
(我还必须相应地更改我的调度循环。)
如果可能,我想避免创建这些包装器对象。在 Kotlin 中有什么方法可以做到这一点吗?
您可以使用一些通用接口来定义它:
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
是您的递归函数类型。
尽管我真的不确定您想要用它实现什么,但您可以通过以下方式让它发挥作用:
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") }
}
使用 Enum 来实现具有有限状态的状态模式并且更喜欢返回非空值。枚举可以继承自函数。
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()
}
}