Rust 如何用未绑定的闭包替换proc?

Rust 如何用未绑定的闭包替换proc?,rust,Rust,我在替换proc方面有点困难。使用Invoke有效,但我必须指定生存期。为了能够将枚举发送到另一个线程,我必须使用'static和更高版本的mem::transmute来强制转换生存期。不太吸引人 另一方面,使用FnOnce会产生以下错误: <anon>:24:32: 24:33 error: cannot move a value of type for<'r> core::ops::FnOnce(&'r Type) + Send: the size of fo

我在替换proc方面有点困难。使用
Invoke
有效,但我必须指定生存期。为了能够将枚举发送到另一个线程,我必须使用
'static
和更高版本的
mem::transmute
来强制转换生存期。不太吸引人

另一方面,使用
FnOnce
会产生以下错误:

<anon>:24:32: 24:33 error: cannot move a value of type for<'r> core::ops::FnOnce(&'r Type) + Send: the size of for<'r> core::ops::FnOnce(&'r Type) + Send cannot be statically determined [E0161]
:24:32:24:33错误:无法移动f.invoke类型的值(不安全{mem::transmute(&a)})
}
火柴手柄2{
Message2::Handle(f)=>f(&a)
}
}

简单的答案是,使用:

Handle(Box<FnMut(&Type) + Send>)
手柄(盒)
更复杂的答案是,根据,您不能调用
,只能调用大小为F的F,其中F:fn一次

…不知道为什么,但我认为这是因为当特质消耗自我时,它会移动价值;很奇怪。

使用它怎么样

#![特征(标准杂项)]
使用std::thunk::thunk;
结构类型;
枚举消息f.invoke(&a))
};
普林顿!(“{}”,res);
}
()

为了能够将枚举发送到另一个线程,我必须使用“static and later mem::transmute”来强制转换生命周期

自从登陆后,可以接受具有非静态生存期的闭包(和
Fn*
traits)。需要注意的是,您必须确保线程在生存期到期之前退出—否则您将引用无效内存


使用
mem::transmute
可以忽略这一点,但当内存不再有效时,程序会崩溃。

在您的情况下,解决方案是使用
for
关键字,它允许您为输入参数指定“匿名”生存期

#![feature(box_syntax)]
#![feature(std_misc)]

use std::thunk::Invoke;

struct Type;

enum Message {
    Handle(Box<for <'r> Invoke<(&'r Type)> + Send>)
}

pub fn main() {
    let a = Type;
    let handler = Message::Handle(box move |_: &Type| {});
    match handler {
        Message::Handle(f) => f.invoke(&a)
    }
}
#![功能(方框语法)]
#![特征(标准杂项)]
使用std::thunk::Invoke;
结构类型;
枚举消息{
句柄(框+发送>)
}
pub fn main(){
设a=类型;
let handler=Message::Handle(框移动|{:&类型|{});
匹配处理程序{
Message::Handle(f)=>f.invoke(&a)
}
}

此外,我认为使用
transmute()
技巧时的主要问题是,如果函数返回或存储对输入结构一部分的引用:编译器会将“静态生存期”分配给该引用,而这显然是一个错误,并可能导致内存损坏


您可以找到更多关于闭包的信息以及中当前需要调用特性的原因(注意:关于显式指定闭包类型的部分现在已经过时,编译器现在可以推断出来)。

FnMut
不起作用,因为它借用的环境通常不是静态的,因此不可发送。我想我现在找到了一个更好的解决方案:
let handler:Box=safe{mem::transmute(handler)};调用(self)
,但我不知道这个cast有什么含义。我希望能很快打一次电话给
fn
。@Ferio:如果你需要变形,那就错了。它可能运行正常,但你肯定是自找麻烦,违反了规则。我不知道为什么我必须转变。原则上,它应该与
as
一起工作,但我想
FnOnce
仍然缺少一些支持…@Feno:如果你不知道你在从什么转变到什么,无论如何都不要这样做。在您的特定情况下,您正在从
&“uu型
转换为
&”静态型
,这可能导致在释放bug后使用。谢谢!但我认为这家伙还没有被记录在案……:(你可以在github上相应的RFC中找到关于for语法的一些信息(我还没有找到任何其他文档):构造闭包时必须注释参数类型也有点令人惊讶。Thunk的问题与我的解决方案相同。你必须提供一个生命周期,而我正在使用一个通道。请参见Vaeldens的答案。神秘的
for
就是解决方案。@Ferio我很高兴你的问题得到了解决!我必须承认,我我不明白为什么你不能提供一个生命周期,但我总有一天会遇到这个问题!^ ^^@Ferio Ah-channels!我认为这是一个足够重要的区别,足以补充你原来的问题。当你说“将枚举发送到另一个线程”时,我只是假设你是指启动线程时。
#![feature(std_misc)]

use std::thunk::Thunk;

struct Type;

enum Message<'a> { //'
    Handle(Thunk<'a, &'a Type, u8>)
}

pub fn main() {
    let a = Type;
    let handler = Message::Handle(Thunk::with_arg(move |_| 42));
    let res = match handler {
        Message::Handle(f) => f.invoke((&a))
    };
    println!("{}", res);
}
#![feature(box_syntax)]
#![feature(std_misc)]

use std::thunk::Invoke;

struct Type;

enum Message {
    Handle(Box<for <'r> Invoke<(&'r Type)> + Send>)
}

pub fn main() {
    let a = Type;
    let handler = Message::Handle(box move |_: &Type| {});
    match handler {
        Message::Handle(f) => f.invoke(&a)
    }
}