Syntax 如何指定选项的生存期<;关闭>;?

Syntax 如何指定选项的生存期<;关闭>;?,syntax,rust,lifetime,Syntax,Rust,Lifetime,我试图在结构上放置一个字段,该字段应包含一个选项 然而,Rust对我大喊大叫,说我必须指定生命周期(并不是说我真的会这么做)。我正在尽我最大的努力去做,但是Rust对我的想法从来都不满意。请查看我的内联注释,以查找我得到的编译错误 struct Floor{ handler: Option<|| ->&str> //this gives: missing lifetime specifier //handler: Option<||: 'a>

我试图在结构上放置一个字段,该字段应包含一个
选项

然而,Rust对我大喊大叫,说我必须指定生命周期(并不是说我真的会这么做)。我正在尽我最大的努力去做,但是Rust对我的想法从来都不满意。请查看我的内联注释,以查找我得到的编译错误

struct Floor{
    handler: Option<|| ->&str> //this gives: missing lifetime specifier 
    //handler: Option<||: 'a> // this gives: use of undeclared lifetime name `'a`
}

impl Floor {
    // I guess I need to specify life time here as well 
    // but I can't figure out for the life of me what's the correct syntax
    fn get(&mut self, handler: || -> &str){
        self.handler = Some(handler);
    }
}
结构层{
handler:Option&str>//这给出了:缺少生存期说明符
//处理程序:选项(&str){
self.handler=Some(handler);
}
}

这有点棘手

一般来说,当您在数据结构中存储借用的引用(即
&
类型)时,您需要命名其生存期。在本例中,您使用的
'a
是正确的,但必须在当前范围中引入该
'a
。这与引入类型变量的方式相同。因此,要定义您的
楼层
结构:

struct Floor<'a> {
    handler: Option<|| -> &'a str>
}

从技术上讲,您可以将其缩短为一个生命周期,并使用
|:'a->&'a str
,但这意味着返回的
&str
始终与闭包本身具有相同的生命周期,我认为这是一个错误的假设。

回答当前生锈版本
1.x

有两种可能得到您想要的结果:一种是未装箱的闭包,另一种是装箱的闭包。未绑定的闭包速度非常快(大多数情况下,它们是内联的),但它们向结构添加了一个类型参数。盒式闭包在这里增加了一点自由度:它们的类型被一级间接删除,遗憾的是速度有点慢

我的代码有一些示例函数,因此有点长,请原谅;)

无框闭包 完整代码:

struct Floor<F>
    where F: for<'a> FnMut() -> &'a str 
{
    handler: Option<F>,
}


impl<F> Floor<F> 
    where F: for<'a> FnMut() -> &'a str
{
    pub fn with_handler(handler: F) -> Self {
        Floor {
            handler: Some(handler),
        }
    }

    pub fn empty() -> Self {
        Floor {
            handler: None,
        }
    }

    pub fn set_handler(&mut self, handler: F) {
        self.handler = Some(handler);
    }

    pub fn do_it(&mut self) {
        if let Some(ref mut h) = self.handler {
            println!("Output: {}", h());
        }
    }
}

fn main() {
    let mut a = Floor::with_handler(|| "hi");
    a.do_it();

    let mut b = Floor::empty();
    b.set_handler(|| "cheesecake");
    b.do_it();
}
type HandlerFun = Box<for<'a> FnMut() -> &'a str>;

struct Floor {
    handler: Option<HandlerFun>,
}

impl Floor {
    pub fn with_handler(handler: HandlerFun) -> Self {
        Floor {
            handler: Some(handler),
        }
    }

    pub fn empty() -> Self {
        Floor {
            handler: None,
        }
    }

    pub fn set_handler(&mut self, handler: HandlerFun) {
        self.handler = Some(handler);
    }

    pub fn do_it(&mut self) {
        if let Some(ref mut h) = self.handler {
            println!("Output: {}", h());
        }
    }
}

fn main() {
    let mut a = Floor::with_handler(Box::new(|| "hi"));
    a.do_it();

    let mut b = Floor::empty();
    b.set_handler(Box::new(|| "cheesecake"));
    b.do_it();
}
这有点慢,因为我们对每个闭包都有一个堆分配,当调用一个装箱闭包时,大多数时候都是间接调用(CPU不喜欢间接调用…)


但是
Floor
struct没有类型参数,因此您可以拥有其中的
Vec
。您还可以删除
b.set_处理程序(Box::new(| |“cheesecake”)它仍然可以工作。

哦,哇,这让我头晕目眩。人们应该习惯这种疯狂吗-S@Christoph:如果你认为这很疯狂,试着实际使用你的
楼层
结构……是的,我已经遇到了下一个麻烦。:)我做错了吗?喜欢不写惯用的锈代码吗?@Christoph,希望在什么时候登陆,闭包的情况会变得更好。例如,您可以在一个结构中存储一个堆装箱闭包,而不需要指定生存期。@shaman.sir,您可能想就此提出一个单独的问题,但简而言之,可以存储在结构中的一种类型的自有装箱闭包可以如下所示,例如:
Box String+'static>
struct Floor<F>
    where F: for<'a> FnMut() -> &'a str 
{
    handler: Option<F>,
}


impl<F> Floor<F> 
    where F: for<'a> FnMut() -> &'a str
{
    pub fn with_handler(handler: F) -> Self {
        Floor {
            handler: Some(handler),
        }
    }

    pub fn empty() -> Self {
        Floor {
            handler: None,
        }
    }

    pub fn set_handler(&mut self, handler: F) {
        self.handler = Some(handler);
    }

    pub fn do_it(&mut self) {
        if let Some(ref mut h) = self.handler {
            println!("Output: {}", h());
        }
    }
}

fn main() {
    let mut a = Floor::with_handler(|| "hi");
    a.do_it();

    let mut b = Floor::empty();
    b.set_handler(|| "cheesecake");
    b.do_it();
}
type HandlerFun = Box<for<'a> FnMut() -> &'a str>;

struct Floor {
    handler: Option<HandlerFun>,
}

impl Floor {
    pub fn with_handler(handler: HandlerFun) -> Self {
        Floor {
            handler: Some(handler),
        }
    }

    pub fn empty() -> Self {
        Floor {
            handler: None,
        }
    }

    pub fn set_handler(&mut self, handler: HandlerFun) {
        self.handler = Some(handler);
    }

    pub fn do_it(&mut self) {
        if let Some(ref mut h) = self.handler {
            println!("Output: {}", h());
        }
    }
}

fn main() {
    let mut a = Floor::with_handler(Box::new(|| "hi"));
    a.do_it();

    let mut b = Floor::empty();
    b.set_handler(Box::new(|| "cheesecake"));
    b.do_it();
}