递归函数类型 [英] Recursive function type
问题描述
在 Rob Pike 关于 Go 词法扫描的演讲中,他定义了一个函数类型 stateFn
返回另一个 stateFn
,如下所示:
In Rob Pike's talk on lexical scanning in Go, he defines a function type stateFn
which returns another stateFn
, like so:
type stateFn func() stateFn
为了在 Rust 中做类似的事情,我尝试了这个:
In an attempt to do something similar in Rust, I tried this:
type stateFn = fn() -> stateFn;
但编译器抱怨非法递归类型;如果需要,请在循环中插入枚举或结构".
but the compiler complains "illegal recursive type; insert an enum or struct in the cycle, if this is desired".
我可以在 Rust 中执行此操作吗?如果可以,如何执行?
Can I do this in Rust, and if so, how?
推荐答案
您可以将函数类型包装在名义类型(即结构体或枚举)中.这实际上是 Go 代码所做的:type TU
定义了一个新的、独特的类型 T
,它不能与 U
直接互换,而 Rust 的 type
只是一个别名,就像 Haskell 中的 type
和 C 中的 typedef
一样.
You can wrap the function type in a nominal type (i.e. a struct or enum). This is actually what the Go code is doing: type T U
defines a new, distinct type T
that's not directly interchangable with U
, while Rust's type
is just an alias, like type
in Haskell and typedef
in C.
所以,可以这样写:
struct StateFn(fn() -> Option<StateFn>);
或
struct StateFn {
f: fn() -> Option<StateFn>
}
(我不得不添加 Option
因为 Go 的 func
可以为 nil,而 Rust 默认删除可空性,使其成为可选.)
(I've had to add the Option
because Go's func
can be nil, while Rust removes nullability by default, making it opt-in.)
也就是说,我怀疑 func
在 Go 中是一个闭包(可以存储一些内部状态),而在 Rust 中 fn
只是一个函数指针(在all),所以你可能也希望在 Rust 中使用闭包.可以通过替换 fn() ->带有
,并使用 BoxFn 的选项
() -> Option<StateFn>>Box::new(move || {/* code here */})
创建它.
That said, I suspect that func
is a closure in Go (can store some internal state), while fn
in Rust is just a function pointer (no state at all), so you may wish to use a closure in Rust too. One might do this by replacing fn() -> Option<StateFn>
with a Box<Fn() -> Option<StateFn>>
, and creating it with Box::new(move || { /* code here */ })
.
也可以使用 FnMut
代替Fn
给你更多的灵活性,甚至 FnOnce
表示只能调用一次的闭包.这些中的每一个都对调用者施加了更多的限制,但依次为闭包本身提供了更多的灵活性.(但是,对象安全"问题意味着 Box
目前不起作用,"Purging proc" 有更多细节和解决方法.)
One might also use 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" has more details and a work-around.)
struct StateFn {
f: Box<FnMut() -> Option<StateFn>>
}
任何这些情况的解析循环可能如下所示:
The parsing loop for any of these situations might look like:
let mut state_fn = Some(initial_fn);
while let Some(mut f) = state_fn {
state_fn = (*f.f)()
}
这篇关于递归函数类型的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!