Thanks for the feedback!
One thing I do like about my Sequential proposal: the terminology of the
callback function seek/2 makes it very clear that only linear access is
promised, and the necessity of fully seeking a Sequence before negative
access becomes an emergent implication.
The parts you seem to favor are:
2. Enforcing explicit handling of countable collections.
The only way I can think of to do this within the existing Enum framework
is to add a new Enumerable.seek callback.
3. Consistent failure modes around negative index access of interminable
sequences.
The easiest way to handle this within the existing Enum framework would be
by adding some sort of terminable flag to to Enumerable and having
dependent functions check this first.
Both changes necessitate some ultimate breakage in existing behaviour of
Enum––either eventually the functions that need to know this need be moved
to a new protocol, or the Enumerable protocol need change, at least to
introduce new failure modes previous not emitted.
Currently, both Enumerable.count/1 and Enumerable.member?/2 can return
{:error, __MODULE__} to fall back on a naive linear implementation that
takes neither countability nor exhaustibility into account––factors that
Enumerable.reduce/3 doesn't entirely rely on. If we want to group these
changes into the Enumerable module, this seem to me to be the place of
leverage for breaking API changes.
How does this proposal sound? I can reformulate this as a new proposal to
the mailing list in a second pass with your tentative blessing:
Iteration 1: two new functions to Enumerable
- Enumerable.seek/2
Falls back to reduce/3 if not implemented, via a counter, re-implements
Enum.at/{2, 3} and dependents, return {:error, __MODULE__} to fall back on
reduce/3.
- Enumerable.exhaustible?/1
Pure opt-in to denote non-negative access: raises if implemented as {:ok,
false} in relevant functions, proceeds if {:ok, true} is returned, defaults
to {:error, __MODULE__} for existing infinite loop behaviour. Uses the
default for existing core types.
Iteration 2: re-implement Enumerable.count/1 and Enumerable.member?/2 in
terms of the above
Again maintaining existing behaviour, but responses of {:error, __MODULE__}
warn about future deprecation.
Iteration 3: Fully re-define Enumerable interface
- Enumerable.reduce/3
Fully maintains existing behaviour as continuable Enumerables can halt at
any time to abort seeking or interminable behaviour when they reach their
bounds.
- Enumerable.seek/2
Fully takes on all responsibilities of integer access within the Enum
module.
- Enumerable.exhaustible?/1
Appears within any seek/2 dependent implementation to error early on
negative integer access.
- Enumerable.member?/2
Fully optional in favor of dependent functions erroring if not terminable,
and falling back on linear access if not implemented. Useful to override
for Set-type data structures.
- Enumerable.count/1
Fully deprecated in favor of dependent functions erroring if not
terminable. Still seeks by default.
Thanks again for your time! Thoughts?
--
You received this message because you are subscribed to the Google Groups
"elixir-lang-core" group.
To unsubscribe from this group and stop receiving emails from it, send an email
to [email protected].
To view this discussion on the web visit
https://groups.google.com/d/msgid/elixir-lang-core/dfd6a516-b1f1-440c-8673-cb057641f20c%40googlegroups.com.
For more options, visit https://groups.google.com/d/optout.