pub fn up_to(limit: u64) -> impl Generator<Yield = u64, Return = u64> {
move || {
for x in 0..limit {
yield x;
}
return limit;
}
}
What does impl
mean? How might this be implemented in plain Rust or C++?
As Matthieu explained,
impl X
means "return a concrete implementation of traitX
". Without this you have the choice of returning a concrete type that implements the trait, e.g. anUpToImpl
, or erasing the type by returning aBox<Generator>
. The former requires exposing the type, while the latter carries the run-time cost of dynamic allocation and virtual dispatch. More importantly, and this is the clincher for the generator case, the former approach precludes returning a closure, because closures return values of anonymous types.If you mean how to implement
up_to
, and you want to do it without incurring allocation overhead, you have to give up using a closure and manually rewrite the generator into a state machine that implements theGenerator
trait:This kind of transformation is essentially what the Rust compiler does behind the scenes when given a closure that contains
yield
, except that the generated type equivalent toUpToImpl
is anonymous. (A similar but much simpler transformation is used to convert ordinary closures to values of anonymous types that implement one of theFn
traits.)There is another difference between returning
impl Generator
and a concrete type. When returningUpToImpl
, that type has to be public, and thus becomes part of the function signature. For example, a caller is allowed to do this:That code will break if
UpToImpl
is ever renamed, or if you decide to switch to using a generator closure.The
up_to
in this answer compiles even when changed to returnimpl Generator
, so once impl trait is made stable, that will be a better option for its return type. In that case, the caller cannot rely or refer to the exact return type, and it can be switched between any type that implements the trait, including the anonymous closure, without loss of source-level backward compatibility.See also:
This is the new
impl Trait
syntax which allows the programmer to avoid naming generic types. The feature is available as of Rust 1.26.Here, it is used in return position to say "the type returned will implement this trait, and that's all I'm telling you". In this case, note that all return paths of the function must return the exact same concrete type.
The syntax can also be used in argument position, in which case the caller decides what concrete type to pass.
See also: