|
> For example, the return of map could provide indexing, You can provide more interfaces in Rust: fn map(...) -> impl Iterator<Item=U> + Index<Target=U>
but you can't provide "conditional" interfaces (for most interfaces at least), e.g., this won't work: fn map(...) -> impl Iterator<Item=U> + ?Index<Target=U>
where `?Index` reads as "maybe implements Index".To allow that you would essentially need to say that "if the input implements `Index`, the output implements `Index`": fn map<U, T, F, I, O>(it: I) -> O
where I: Iterator<Item=T>, U: From<T>,
O: impl Iterator<Item=U>,
I:?Index<Target=T> -> O:?Index<Target=U>
{
it.map(|t| From::from(t))
}
The type system implementation already supports these types of constraints, but there isn't a language extension that exposes that. I don't see any fundamental reasons that make this impossible, but there are many trade-offs involved.Notice that, for example, the output Range does not implement the same interfaces as the input range, e.g., the input Range implements an `Index` interface over a range of `T`s, but the output Range implements an `Index` interface over a range of `U`s. In D this is super implicit in the implementation details (body) of an equivalent `map` function, but in Rust it needs to be part of the type signature to avoid changes to a function body to silently cause API breaking changes. In D, you could change the body of map to map only from Range(T) -> Range(T), without changing its interface, and that would break all code using it to map a Range(T)->Range(U). |