std.v2020.algorithm etc[ WAS: Is run.d going to be expand for runtime and the phobos library?]
Andrei Alexandrescu
SeeWebsiteForEmail at erdani.org
Mon Jun 22 02:52:57 UTC 2020
On 6/21/20 10:47 AM, Andrei Alexandrescu wrote:
> Was the better
> alternative to make input ranges noncopyable? It only takes a couple of
> hours of coding a bit of that up to see it's quite onerous.
To recap/put forth a few possible APIs for input ranges (that are not
forward):
bool fetchNext(ref T target);
Spec: As long as the range is nonempty, assigns the next element to
target and returns true. At end of range returns false without touching
target.
Pros: works naturally with actual input ranges such as files and sockets.
Cons: does not work if T is qualified. Creates a copy of each element
for forward ranges that exist in memory. That means essentially the API
is impaired and most algorithms that work with input ranges would need
to specialize for forward ranges, too. (FWIW this interface was first
discussed before D had qualifiers). Composes so-so, consider
implementations of filter (not bad) and map (not so nice).
T* fetchNext();
Spec: As long as the range is nonempty, returns a pointer to the next
element in the range. At end of range returns null.
Pros: Simple and efficient for many ranges. Doesn't compose too well.
Cons: Issues with escape analysis and safety. Sometimes the pointer is
scope, sometimes it's not depending on the range.
T fetchNext(ref bool done);
or
ref T fetchNext(ref bool done);
Spec: As long as the range is nonempty, sets done to false and returns
the next element in the range. At end of range sets done to true and
returns an arbitrary T.
Pros: works with qualified data.
Cons: inefficient or needs two versions depending on ref/value.
Complicates life of clients.
Flag!"each" each(alias fun);
Spec: calls fun(x) for each element in the range x - an efficient
generalization of opApply. If fun returns No.each, stops iteration (and
also returns No.each). Otherwise, returns Yes.each. See
https://dlang.org/library/std/algorithm/iteration/each.html.
Pros: works naturally and efficiently (assuming proper inlining) with
many range types. Composes quite well, picture e.g. implementations of
map and filter. Beautiful. Efficient implementation for forward ranges
is immediate. Jives well with Oleg's famous take on iteration
(http://okmij.org/ftp/papers/LL3-collections-talk.pdf).
Cons: ranges such as map, filter etc. would need to expose both each()
(for input ranges) and the existing interface (for better than input
ranges). A number of algorithms would need to be redone to take
advantage of the new interface. The language integration is not as nice
as with the (sadly inefficient) existing opApply.
At a point Sebastian Wilzbach and I discussed that several ranges should
get an each() member function, but that never got finalized. Once each()
is a member of prominent input range algos (can't hurt because people
already can call the less efficient each() global function) and we
accumulate experience with it, we can sanction it as a legit optional
primitive for ranges.
One more thing before I forget - we should drop classes that are ranges.
They add too much complication. The functionality would still be present
by wrapping a polymorphic implementation in a struct.
More information about the Digitalmars-d
mailing list