Modern C++ Lamentations

Steven Schveighoffer schveiguy at gmail.com
Sun Dec 30 18:13:11 UTC 2018


On 12/30/18 7:27 AM, John Colvin wrote:
> On Saturday, 29 December 2018 at 22:01:58 UTC, Steven Schveighoffer wrote:
>> On 12/29/18 4:29 AM, Walter Bright wrote:
>>> http://aras-p.info/blog/2018/12/28/Modern-C-Lamentations/
>>>
>>> Time to show off your leet D skilz and see how good we can do it in D!
>>
>> Ugh, ranges really aren't a good fit for emulating nested loops, 
>> unless you write a specialized one.
>>
>> I tried my best, but it kind of sucks:
>>
>>     foreach(z, x, y;
>>     iota(size_t.max)
>>         .map!(a =>
>>              zip(StoppingPolicy.shortest, a.repeat, iota(1, a)))
>>         .joiner
>>         .map!(t =>
>>              zip(StoppingPolicy.shortest, t[0].repeat, t[1].repeat, 
>> iota(t[1], t[0])))
>>         .joiner
>>         .filter!(t => t[0]*t[0] == t[1]*t[1] + t[2]*t[2])
>>         .take(100))
>>     {
>>         writeln(x, " ", y, " ", z);
>>     }
> 
> Isn't "StoppingPolicy.shortest" the default?

Maybe :) I didn't spend a lot of time examining the details.

I also like your way, it's much more readable, but I still don't like 
the joiners. There has to be a way to just store the three ranges and 
iterate them properly, something like:

struct Triples(ZRange, alias r2func, alias r3func)
{
    ZRange z;
    typeof(r2func(z.front)) x;
    typeof(r3func(z.front, x.front)) y;

    auto front() { return tuple(z.front, x.front, y.front); }
    void popFront()
    {
       y.popFront;
       if(y.empty)
       {
          scope(exit) if(!x.empty) y = r3func(z.front, x.front)
          x.popFront;
          if(x.empty)
          {
             scope(exit) if(!z.empty) x = r2func(z.front);
             z.popFront;
          }
       }
    }
    bool empty() { return y.empty }
}

auto pythags = iota(size_t.max).triples!(z => iota(1 .. z), (z, x) => 
iota(x, z)).filter!(t => t[1]*t[1] + t[2]*t[2] == t[0]*t[0]);

Maybe split it out into something like withloop, maybe we can make this 
kind of thing work:

auto pythags = iota(size_t.max)
    .withLoop!(z => iota(1, z))
    .withLoop!((z, x) => iota(x, z))
    .filter!(t => t[1]*t[1] + t[2]*t[2] == t[0]*t[0]);

Which is really similar to the loop design.

-Steve


More information about the Digitalmars-d mailing list