As we override more and more try_fold implementations on iterators, I’ve been thinking that .next() can always be implemented as x.try_for_each(Err).err() (or .find(|_| true), or a variety of other equivalent things), so long as try_fold has been overridden. And it looks like it’s pretty often optimal. Once the paths are folded, things like Chain look pretty much the same between the two.
So it’d be nice to let people not have to provide an implementation for next if they have one for try_fold.
Any thoughts on a nice way to allow that to work? I assume it’ll need language support, since just overriding both is a stack overflow hazard.
Yes, this sounds great. I think this is called “minimal complete definition” in Haskell, and is suppored by GHC compiler using {-# MINIMAL #-}. I think we can mostly copy the design.
GHC MINIMAL pragma is documented in GHC Users Gude 9.31.5.
The list inside #[minimal(..)] constitutes a disjunction.
Like with #[cfg(..)], we can also use any(..) to embed a disjunction anywhere we want. all(..) can be used to require a conjunction of items. Optionally, not(..) could also be supported but that requires deeper thinking wrt. semantics when combined with specialization.
Seems like you could do this with default impls (if/whenever they’re supported). If someone implements TryFold (supplying the body of Iterator::try_fold as a static method), they get a default implementation of Iterator where Iterator::try_fold and Iterator::next are defined in terms of TryFold::try_fold.
trait Foo {
fn foo(&self);
fn bar(&self);
fn quux(&self);
#[requires(foo,quux)]
default fn bar(&self) {
/* implement on top of foo and quux */
}
#[requires(bar)]
default fn foo(&self) {
/* implement on top of bar */
}
}
Or even
trait Foo {
fn foo(&self);
fn bar(&self);
fn quux(&self);
#[requires(foo)]
default {
fn bar(&self) {
/* implement on top of foo */
}
fn quux(&self) {
/* implement on top of foo */
}
}
}
Of course, there’s the problem of what to do when we have