How can I specify a lifetime for closure arguments?

…衆ロ難τιáo~ 提交于 2019-12-12 01:52:06

问题


Playpen link: http://is.gd/EpX6lM

I have a closure that takes a slice and returns a subslice of it. Compiling the following code on rust-1.0.0-beta-2 fails:

trait OptionalFirst {
    fn optional_first<'a>(&self, x: &'a [usize]) -> &'a [usize];
}

impl<F> OptionalFirst for F where F: Fn(&[usize]) -> &[usize] {
    fn optional_first<'a>(&self, x: &'a [usize]) -> &'a [usize] {
        (*self)(x)
    }
}

fn main() {
    let bc: Box<OptionalFirst> = Box::new(
        |x: &[usize]| -> &[usize] {
            if x.len() != 0 {
                &x[..1]
            }
            else {
                &x[..0]
            }
        }) as Box<OptionalFirst>;

    let a: [usize; 3] = [1, 2, 3];
    let b: &[usize] = bc.optional_first(&a);
    println!("{:?}", b);
}

I know how to define a lifetime in a closure's type (using for <'a>), but I don't know how to specify it in the closure's implementation.


回答1:


Your implementation impl<F> OptionalFirst for F where F: Fn(&[usize]) -> &[usize] is expecting a bound lifetime parameter, for the constraint F: Fn(&[usize]) -> &[usize] is, expanded to full form: F: for<'a> Fn(&'a [usize]) -> &'a [usize].

That is, at the time you call the function, it will determine what values to select for the lifetime (they are generics).

A closure, however, cannot have any bound lifetime parameters; they are by stuck using concrete lifetime parameters. They lack the facility to wire output lifetimes to input lifetimes generically as you want: they are by very design concrete and not generic. I haven’t thought about this in great depth, but it might be possible to counteract this for generic lifetime parameters; it is not, however, something that is implemented as far as I am aware.

If you want something like this, try using a function rather than a closure. When you’re not using any of the environment there’s no benefit to using closures beyond the typically lower verbosity.

Here’s what you end up with:

fn bc(x: &[usize]) -> &[usize] {
    if x.len() != 0 {
        &x[..1]
    } else {
        &x[..0]
    }
}

Playpen




回答2:


You can create a closure with bound lifetime parameters, you just have to get the compiler to infer that type correctly. It can be done like this:

fn main() {
    let bc: Box<Fn(&[usize]) -> &[usize]> = Box::new(
        |x| {
            if x.len() != 0 {
                &x[..1]
            }
            else {
                &x[..0]
            }
        });

    let a: [usize; 3] = [1, 2, 3];
    let b: &[usize] = bc(&a);
    println!("{:?}", b);
}

However, what I don't know is how to cast it further into Box<OptionalFirst>.



来源:https://stackoverflow.com/questions/29714934/how-can-i-specify-a-lifetime-for-closure-arguments

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!