[英]Storing a closure in a structure — cannot infer an appropriate lifetime
我正在尝试在Rust中实现State monad( State
实际上是一个函数的包装器,它接受原始状态并返回修改后的状态和一些结果)。 这就是人们如何在Haskell中实现State
(monad操作,为简单起见重命名为unit
和bind
):
data State s u = State { run :: s -> (u, s) }
-- return
unit :: u -> State s u
unit u = State $ \s -> (u, s)
-- (>>=)
bind :: State s u -> (u -> State s a) -> State s a
bind m f = State $ \s ->
let (u, s') = run m s
in run (f u) s'
所以我尝试在Rust中重写它:
pub struct State<'r, S, U> {
priv run: 'r |S| -> (U, S)
}
pub fn unit<'r, S, U>(value: U) -> State<'r, S, U> {
State {
run: |state| (value, state)
}
}
(实际上我不确定run
字段的定义是否合法 - 它被认为是一个错误)。
此代码无法编译:
/some/path/lib.rs:31:12: 31:36 error: cannot infer an appropriate lifetime due to conflicting requirements
/some/path/lib.rs:31 run: |state| (value, state)
^~~~~~~~~~~~~~~~~~~~~~~~
/some/path/lib.rs:29:52: 33:2 note: first, the lifetime cannot outlive the block at 29:51...
/some/path/lib.rs:29 pub fn unit<'r, S, U>(value: U) -> State<'r, S, U> {
/some/path/lib.rs:30 State {
/some/path/lib.rs:31 run: |state| (value, state)
/some/path/lib.rs:32 }
/some/path/lib.rs:33 }
/some/path/lib.rs:31:12: 31:36 note: ...so that closure does not outlive its stack frame
/some/path/lib.rs:31 run: |state| (value, state)
^~~~~~~~~~~~~~~~~~~~~~~~
/some/path/lib.rs:29:52: 33:2 note: but, the lifetime must be valid for the lifetime &'r as defined on the block at 29:51...
/some/path/lib.rs:29 pub fn unit<'r, S, U>(value: U) -> State<'r, S, U> {
/some/path/lib.rs:30 State {
/some/path/lib.rs:31 run: |state| (value, state)
/some/path/lib.rs:32 }
/some/path/lib.rs:33 }
/some/path/lib.rs:30:5: 30:10 note: ...so that types are compatible (expected `State<'r,S,U>` but found `State<,S,U>`)
/some/path/lib.rs:30 State {
^~~~~
error: aborting due to previous error
好像我需要在unit
实例化State
时显式指定闭包表达式的生命周期,但我只是不知道如何,所以我需要帮助。 谢谢。
编辑 :不幸的是,我不能使用proc
(如弗拉基米尔所建议的那样),因为一个State
可以被执行任意次数。
该错误完全合法。 目前,完全不可能返回可以从函数中多次调用的闭包(除非它们作为参数传递给这些函数)。
当您查找终身注释位置时,您可以很容易地发现您在生命周期中使用了一个错误。 当lifetime参数仅用于参数或仅用于返回值时,则代码中存在错误。 这正是你的情况 - unit
有'r
lifetime参数,但它仅用于返回值。
您的代码无法编译,因为您正在创建堆栈闭包并尝试将其存储在将返回给调用者的对象中。 但是闭包是在堆栈上创建的,当你从函数返回时,该堆栈空间无效,即你的闭包被破坏了。 借用检查器阻止了这一点。
目前在Rust中只有两种闭包 - 堆栈盒装闭包和一次性堆盒装闭包(过程)。 你可以用proc做你想做的事,但你只能调用一次。 我不确定这是否适合您的需求,但是你去了:
pub struct State<S, U> {
priv run: proc(S) -> (U, S)
}
pub fn unit<S: Send, U: Send>(value: U) -> State<S, U> {
State {
run: proc(state) (value, state)
}
}
我不得不添加Send
kind,因为procs需要他们的环境可以发送。
将来,当(或者如果)动态大小的类型着陆时,您将能够创建常规的盒装闭包,可以多次调用并拥有其环境。 但DST仍处于设计和开发阶段。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.