Currently, APIs are often forced to either (1) expose a concrete return type or (2) return trait objects, which come with several downsides.
For example, the iter
function for Vec<T>
currently has the signature
fn iter<'a>(&'a self) -> Items<'a, T>
where Items
is a struct defined purely for iterating over a slice. The struct has no public fields; the only interesting thing about it is that it implements various traits, such as Iterator<&'a T>
.
This API is revealing more than it might have to: the type Items
should not have to be exposed at all. Instead, we should be able to give iter
a signature like:
fn iter<'a>(&'a self) -> impl Iterator<&'a T>
where impl Iterator<&'a T>
is hypothetical syntax for "some statically-known type that implements Iterator<&'a T>
." That's the contract you really want: not the name of a specific type, but just that there is some type that implements Iterator
that you are going to return.
Of course, we can use trait objects to get something close to this:
fn iter<'a>(&'a self) -> Box<Iterator<&'a T>>
but this has several disadvantages. It means that we're returning a fat pointer (with a v-table). It also precludes using generic traits for return types.
The situation for input is much better: you can decide to either write a generic function like
fn <I: Iterator<uint>>sum(it: I) { ... }
and get static dispatch, or use trait objects like
fn sum(it: Box<Iterator<uint>>) { ... }
and get dynamic dispatch.
It would be nice to be able to make the analogous choices for return types.