在Go中的词法扫描的Rob Pike's talk中,他定义了一个函数类型stateFn
,它返回另一个stateFn
,如下所示:
type stateFn func() stateFn
为了尝试在Rust中做类似的事情,我尝试了这个:
type stateFn = fn() -> stateFn;
但是编译器抱怨“非法递归类型;如果需要,可以在循环中插入枚举或结构”。
我可以在Rust中执行此操作,如果是,请执行此操作?
答案 0 :(得分:15)
您可以将函数类型包装为名义类型(即结构或枚举)。这实际上是Go代码正在做的事情:type T U
定义了一个新的,不同的类型T
,它不能与U
直接互换,而Rust' {{1} }只是一个别名,如Haskell中的type
和C中的type
。
所以,有人可能写道:
typedef
或
struct StateFn(fn() -> Option<StateFn>);
(我必须添加struct StateFn {
f: fn() -> Option<StateFn>
}
,因为Go的Option
可以为nil,而Rust默认删除可空性,使其选择加入。)
那就是说,我怀疑func
是Go中的闭包(可以存储一些内部状态),而Rust中的func
只是一个函数指针(根本没有状态),所以你可以我也希望在Rust中使用一个封口。可以通过将fn
替换为fn() -> Option<StateFn>
并使用Box<Fn() -> Option<StateFn>>
创建它来实现此目的。
也可以使用FnMut
代替Box::new(move || { /* code here */ })
,这样可以提供更大的灵活性,甚至FnOnce
代表一个只能调用一次的闭包。这些中的每一个都对呼叫者有了更多的限制,但是给予封闭本身更多的灵活性。 (但是,&#34;对象安全&#34;关注意味着Fn
目前无法正常工作,"Purging proc"有更多详细信息和解决方法。)
Box<FnOnce>
任何这些情况的解析循环可能如下所示:
struct StateFn {
f: Box<FnMut() -> Option<StateFn>>
}