Isn't `each` too much of a good thing?

Andrei Alexandrescu SeeWebsiteForEmail at erdani.org
Thu Sep 17 16:18:18 UTC 2020


The implementation of each in std.algorithm.iteration sets out a lofty 
goal: whatever can be iterated, must be iterated with each.

Problem is, there are way too many things that can be iterated in D and 
too many ways to iterate them. This leads to a veritable gallop of checks:

     alias BinaryArgs = AliasSeq!(fun, "i", "a");

     enum isRangeUnaryIterable(R) =
         is(typeof(unaryFun!fun(R.init.front)));

     enum isRangeBinaryIterable(R) =
         is(typeof(binaryFun!BinaryArgs(0, R.init.front)));

     enum isRangeIterable(R) =
         isInputRange!R &&
         (isRangeUnaryIterable!R || isRangeBinaryIterable!R);

     enum isForeachUnaryIterable(R) =
         is(typeof((R r) {
             foreach (ref a; r)
                 cast(void) unaryFun!fun(a);
         }));

     enum isForeachUnaryWithIndexIterable(R) =
         is(typeof((R r) {
             foreach (i, ref a; r)
                 cast(void) binaryFun!BinaryArgs(i, a);
         }));

     enum isForeachBinaryIterable(R) =
         is(typeof((R r) {
             foreach (ref a, ref b; r)
                 cast(void) binaryFun!fun(a, b);
         }));

     enum isForeachIterable(R) =
         (!isForwardRange!R || isDynamicArray!R) &&
         (isForeachUnaryIterable!R || isForeachBinaryIterable!R ||
          isForeachUnaryWithIndexIterable!R);

Does this pass the laugh test? How can one explain a colleague "yep, 
here are the conditions under which you can iterate over an object in 
the D language".

I don't contest the correctness of this code. I contest its being 
sensible. There's just too much of a good thing.

For example: static arrays are supported. Why? This creates a dangerous 
precedent whereby we'd need to support static arrays with other 
primitives, such as map or reduce. (We don't, and we shouldn't. Let them 
add a "[]" to the array.) Where do you stop?

We support opApply with one, two, or more arguments. Built-in hashtables 
(when was the last time you were in a place in your life where 
hashtable.each was useful?). You name it - we support it.

This is in the same league with supporting enums that use string as a 
base, as "some kinda sorta string thing".

Too much!

I have no idea how to improve this code because it will break one of the 
suitably overspecialized unittests. But this kind of stuff has no place 
in stdv2021.


More information about the Digitalmars-d mailing list