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.
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
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>
.