如何在结构体上创建定长闭包或实现 Fn/FnMut/FnOnce?

10

基本上,我想编写一个返回闭包的函数。如何做到这一点而不必返回 Box<FnOnce(u32)>

从 Rust 书籍的闭包章节中,我了解到闭包只是结构体和 FnOnce 的实现的语法糖。以下是我的尝试:

#[derive(Debug)]
struct MyError {
    code: u32,
    location: &'static str,
}
// Here is my closure:
struct MyErrorPartial {
    location: &'static str,
}
impl FnOnce(u32) for MyErrorPartial {
    type Output = MyError;

    fn call_once(self, args: u32) -> MyError {
        MyError {
            code: args,
            location: self.location,
        }
    }
}
fn error_at(location: &'static str) -> MyErrorPartial {
    MyErrorPartial {location: location}
}

fn function_returning_code() -> Result<(), u32> {
    Err(123)
}
fn function_with_error() -> Result<(), MyError> {
    try!(function_returning_code().map_err(error_at("line1")));
    try!(function_returning_code().map_err(error_at("line2")));
    Ok(())
}
fn main() {
    function_with_error().unwrap();
}

目前它会给出一个错误:

<anon>:11:12: 11:17 error: associated type bindings are not allowed here [E0229]
<anon>:11 impl FnOnce(u32) for MyErrorPartial {
                     ^~~~~
1个回答

10
手动在结构体上实现 Fn* 特质的语法如下:
impl FnOnce<(Arg1,Arg2,Arg3,)> for MyStruct {
    type Output = MyOutput;
    extern "rust-call" fn call_once(args: (Arg1, Arg2, Arg3,)) -> MyOutput {
       // implementation here
    }
}

请注意,所有参数都作为单个元组给出。
此外,这种语法不稳定,需要使用 #![feature(core, unboxed_closures)],因此您无法在 beta 渠道中使用它,只能在 nightly 中使用。
对于您的情况,它将翻译成这样:
impl FnOnce<(u32,)> for MyErrorPartial {
    type Output = MyError;

    extern "rust-call" fn call_once(self, args: (u32,)) -> MyError {
        MyError {
            code: args.0,
            location: self.location,
        }
    }
}

6
稳定版是否无法实现 Fn* - Kapichu
1
@Kapichu 看起来是这样的:call_once 方法的文档链接到问题#29625,该问题仍然未解决。 - Sam Estep

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接