递归函数类型

Recursive function type

在Go的词法扫描Rob Pike's talk中,他定义了一个函数类型stateFn which returns another stateFn, like so:

type stateFn func() stateFn

为了尝试在 Rust 中做类似的事情,我尝试了这个:

type stateFn = fn() -> stateFn;

但编译器抱怨 "illegal recursive type; insert an enum or struct in the cycle, if this is desired"。

我可以在 Rust 中执行此操作吗?如果可以,怎么做?

您可以将函数类型包装在标称类型(即结构或枚举)中。这实际上是 Go 代码正在做的事情:type T U 定义了一个新的、不同的类型 T,它不能直接与 U 互换,而 Rust 的 type 只是一个别名,比如type 在 Haskell 和 typedef 在 C.

所以,可以这样写:

struct StateFn(fn() -> Option<StateFn>);

struct StateFn {
    f: fn() -> Option<StateFn>
}

(我必须添加 Option 因为 Go 的 func 可以为 nil,而 Rust 默认删除了可空性,使其可以选择加入。)

也就是说,我怀疑 func 在 Go 中是一个闭包(可以存储一些内部状态),而在 Rust 中 fn 只是一个函数指针(根本没有状态),所以您可能也希望在 Rust 中使用闭包。可以通过将 fn() -> Option<StateFn> 替换为 Box<<a href="http://doc.rust-lang.org/nightly/std/ops/trait.Fn.html">Fn</a>() -> Option<StateFn>> 并使用 Box::new(move || { /* code here */ }) 创建它来做到这一点。

也可以使用 FnMut instead of Fn which gives you more flexibility, or even FnOnce which represents a closure that can only be called once. Each of these places successively more restrictions on the caller, but gives the closure itself successively more flexibility. (However, "object safety" concerns mean that Box<FnOnce> doesn't work at the moment, "Purging proc" 有更多详细信息和解决方法。)

struct StateFn {
    f: Box<FnMut() -> Option<StateFn>>
}

任何这些情况的解析循环可能如下所示:

let mut state_fn = Some(initial_fn);
while let Some(mut f) = state_fn {
    state_fn = (*f.f)()
}