Closed
Description
Using generic functions with trait bounds results in efficient code generation, at the cost of syntactic simplicity (compared to using trait objects).
Consider this snippet:
fn stringify<T: ToStr>(x: T) -> ~str {
x.to_str()
}
// Making use of a hypothetical Fn trait.
fn map2fn<T, U, V, F1: Fn<T, U>, F2: Fn<U, V>>(x: T, f1: F1, f2: F2) -> V {
f2(f1(x))
}
Now with trait bounds moved to argument types (creating implicit generic type parameters):
fn stringify(x: ToStr) -> ~str {
x.to_str()
}
// Making use of a hypothetical Fn trait.
fn map2fn<T, U, V>(x: T, f1: Fn<T, U>, f2: Fn<U, V>) -> V {
f2(f1(x))
}
// Or closures as sugar for Fn (unboxed!).
fn map2fn<T, U, V>(x: T, f1: |T| -> U, f2: |U| -> V) -> V {
f2(f1(x))
}
Note that this would be limited to values as references or pointers would conflict with current syntax for trait objects.
However, optimizing &Trait
in an argument type (or even a structure field? there is room for discussion here) to a generic (<T: Trait> ... &T
) wouldn't cause any serious issues AFAICT.
And it would mean we can make the closure syntax be sugar for &Fn
without losing backwards compatibility while allowing compile-time monomorphization.
Metadata
Metadata
Assignees
Labels
No labels