This is good to think about, though I think writing `&mut || foo`
feels like a nonstarter to me.
I still feel that `&my` -- meaning, a pointer that gives ownership of
the referent but not the memory where the referent lives -- is the
right approach here. Basically, the type of `|| ...` would be `&my T`
where `T` is some fresh type that implements `Fn<U,R>`.
Now, the consumer of the closure could be any of:
- `fn foo(x: |U| -> R)`: In this case, the type `|U| -> R`
is equivalent to `&mut Fn<U,R>`. This is an automatic
object coercion and also an automatic reborrow. That is,
written out very explicitly, `foo(|u| r)` would be
equivalen to `foo((&mut *(&my T { ... })) as &mut Fn<U,R>)`,
where again `T` is the anonymous closure type.
- `fn foo<T:Fn<U,R>>(x: &my T) -> T`: Now `foo` takes ownership of the
value `T`. Because it's an `&my` pointer, `foo()` can move the
referent around.
- `fn foo<T:Fn<U,R>>(x: &mut T) -> T`: `foo` does not take ownership
of the closure, but does avoid virtual dispatch.
This can be extended to "once closures" in a pretty straightforward
way:
- `fn foo(x: once |U| -> R)`
- `fn foo<T:OnceFn<U,R>>(x: &my T)`
As a bonus, `&my` is perfect for the `drop` trait. And (I think)
fairly straightforwad to implement.
(The semantics of `&my`: when an `&my` value is dropped, it would
cause the referent to be dropped as well)
Niko
On Mon, Dec 30, 2013 at 07:31:45PM -0800, Patrick Walton wrote:
> Yes, it would need to be &mut, you're right.
>
> I think the underlying type syntax would be something like `Fn<int,&int>` for
> the unboxed version, and `&mut Fn<int,&int>` for the boxed version. The type
> syntax with the bars is just syntactic sugar for the latter (and, in trait
> bound position, for the former).
>
> It's somewhat unfortunate but I don't see a particularly good alternative if
> we want boxed and unboxed closures alike to have nice-looking APIs. The
> alternative, I guess, is to block 1.0 on unboxed closures, convert all our
> APIs to unboxed closures where possible, and just say that if you want a
> boxed closure you have to write `&mut |x| x + 1` at each closure construction
> site...
>
> Patrick
>
> "Gábor Lehel" <[email protected]> wrote:
> >Wouldn't it have to be `&mut` rather than `&` to fit the semantics of |
> >|,
> >which is affine and can mutate its environment?
> >
> >And wouldn't this lead to divergence between the type- and value
> >syntax,
> >with | | as a type being a boxed closure (`&mut FnMut`), and an unboxed
> >closure as a value? This was one of the nicer points of the recent
> >closure
> >overhaul, and it would be a shame to lose it so soon.
> >
> >
> >On Mon, Dec 30, 2013 at 10:11 PM, Patrick Walton
> ><[email protected]>wrote:
> >
> >> I've been thinking that to future-proof unboxed closures in the
> >future we
> >> should maybe limit `|x| x+1` lambda syntax to either (a) require `&`
> >in
> >> front or (b) in function position.
> >>
> >> So today you would write:
> >>
> >> let f = |x| x+1;
> >>
> >> But tomorrow you would write:
> >>
> >> let f = &|x| x+1;
> >>
> >> But it would always work here:
> >>
> >> v.map(|&x| x+1);
> >>
> >> The reason is simply that we'd like `|x| x+1` to become an unboxed
> >closure
> >> in the future and it's easier in the language semantics to
> >future-proof for
> >> it this way: we simply special-case the function argument position.
> >>
> >> Alternatively we can do it with assignability: say that `|x| x+1` is
> >an
> >> anonymous type (an error today) that is assignable to the type
> >> `|int|->int`. That might be cleaner than special-casing the function
> >> argument position.
> >>
> >> Patrick
> >> _______________________________________________
> >> Rust-dev mailing list
> >> [email protected]
> >> https://mail.mozilla.org/listinfo/rust-dev
> >>
>
> --
> Sent from my Android phone with K-9 Mail. Please excuse my brevity.
> _______________________________________________
> Rust-dev mailing list
> [email protected]
> https://mail.mozilla.org/listinfo/rust-dev
_______________________________________________
Rust-dev mailing list
[email protected]
https://mail.mozilla.org/listinfo/rust-dev