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.

Reply via email to