Jump to page: 1 2
Thread overview
chunks equivalent with unpacking?
Jul 31, 2013
Andrej Mitrovic
Jul 31, 2013
bearophile
Jul 31, 2013
Andrej Mitrovic
Jul 31, 2013
Andrej Mitrovic
Jul 31, 2013
Ali Çehreli
Jul 31, 2013
bearophile
Jul 31, 2013
bearophile
Jul 31, 2013
bearophile
Jul 31, 2013
Ali Çehreli
Jul 31, 2013
Ali Çehreli
Jul 31, 2013
bearophile
Jul 31, 2013
Andrej Mitrovic
Jul 31, 2013
Andrej Mitrovic
Jul 31, 2013
Andrej Mitrovic
July 31, 2013
std.range.chunks is useful for iterating through a range like so:

-----
import std.range;
import std.stdio : writeln;

void main()
{
    float[] arr = [
         0.0,   0.15, 0.0, 1.0,
         0.25, -0.25, 0.0, 1.0,
        -0.25, -0.25, 0.0, 1.0,
    ];

    foreach (xyzw; arr.chunks(4))
    {
        writeln(xyzw[0]);  // write 'x'
    }
}
-----

But instead of having to use indexing for each element in the chunk, I'd like to use separate arguments instead, like so:

    // nicer API
    foreach (x, y, z, w; arr.chunks(4))
    {
        writeln(x);
    }

Is there a function in Phobos that does this?
July 31, 2013
Andrej Mitrovic:

>     foreach (x, y, z, w; arr.chunks(4))
>     {
>         writeln(x);
>     }
>
> Is there a function in Phobos that does this?

Those four variables x y z w influence the type of the foreach, while 4 is a run-time argument. This API can be used:

foreach (x, y, z, w; arr.chunks!4)

A forward range like that seems easy to implement.

Bye,
bearophile
July 31, 2013
On 7/31/13, bearophile <bearophileHUGS@lycos.com> wrote:
> Those four variables x y z w influence the type of the foreach, while 4 is a run-time argument. This API can be used:
>
> foreach (x, y, z, w; arr.chunks!4)

Yeah it will have to be CT.

> A forward range like that seems easy to implement.

Can it? I've tried alternatively with opApply but it's problematic to support both ref/non-ref argument versions.

I know there's been some sort of automatic unpacking feature recently introduced (in 2.063 maybe?). Got an idea how you'd implement this range?
July 31, 2013
On 7/31/13, Andrej Mitrovic <andrej.mitrovich@gmail.com> wrote:
> Can it? I've tried alternatively with opApply but it's problematic to support both ref/non-ref argument versions.

Ajh nevermind there's no issue with ref-ness, I just had a bug in my code. So this is easily implementable with opApply but I'm not sure how it can be done with a range type.
July 31, 2013
On 07/31/2013 10:58 AM, Andrej Mitrovic wrote:
> On 7/31/13, Andrej Mitrovic <andrej.mitrovich@gmail.com> wrote:
>> Can it? I've tried alternatively with opApply but it's problematic to
>> support both ref/non-ref argument versions.
>
> Ajh nevermind there's no issue with ref-ness, I just had a bug in my
> code. So this is easily implementable with opApply but I'm not sure
> how it can be done with a range type.
>

Once the element type is a tuple, 'tuple foreach' will expand them.

    foreach (x, y, z, w; /* a range that returns tuple of four */)

Ali

July 31, 2013
Ali Çehreli:

> Once the element type is a tuple, 'tuple foreach' will expand them.
>
>     foreach (x, y, z, w; /* a range that returns tuple of four */)

That part of the D design is not yet formalized, it's a special case, and maybe it will need to be removed :-( It's a significant design mistake introduced recently in D.


This is a first nonworking try:


import std.range: chunks, Chunks;
import std.stdio : writeln;
import std.string: format, join;
import std.typecons: tuple;
import std.typetuple: TypeTuple;

template Iota(int stop) {
    static if (stop <= 0)
        alias TypeTuple!() Iota;
    else
        alias TypeTuple!(Iota!(stop-1), stop-1) Iota;
}

struct TupleChunks(size_t n, CR) {
    CR cr;

    @property bool empty() { return cr.empty; }

    void popFront() { cr.popFront; }

    @property front() {
        static string gen() {
            string[] result;
            foreach (i; Iota!n)
                result ~= format("cr.front[%d]", i);
            return result.join(", ");
        }

        mixin("return tuple(" ~ gen ~ ");");
    }
}

TupleChunks!(n, Chunks!R) tupleChunks(size_t n, R)(R r) {
    return typeof(return)(chunks(r, n));
}


void main() {
   float[] arr = [ 0.0,   0.15, 0.0, 1.0,
                   0.25, -0.25, 0.0, 1.0,
                  -0.25, -0.25, 0.0, 1.0];

    foreach (x, y, z, w; arr.tupleChunks!4)
        x.writeln;
}


Bye,
bearophile
July 31, 2013
> template Iota(int stop) {
>     static if (stop <= 0)
>         alias TypeTuple!() Iota;
>     else
>         alias TypeTuple!(Iota!(stop-1), stop-1) Iota;
> }

Silly me, that Iota is not needed:


import std.stdio : writeln;
import std.range: chunks, Chunks, iota;
import std.string: format, join;
import std.typecons: tuple;
import std.algorithm: map;

struct TupleChunks(size_t n, CR) {
    CR cr;

    @property bool empty() { return cr.empty; }

    void popFront() { cr.popFront; }

    @property front() {
        mixin("return tuple(" ~
              n.iota.map!(i => format("cr.front[%d]", i)).join(", ") ~
              ");");
    }
}

TupleChunks!(n, Chunks!R) tupleChunks(size_t n, R)(R r) {
    return typeof(return)(chunks(r, n));
}

void main() {
   float[] arr = [ 0.0,   0.15, 0.0, 1.0,
                   0.25, -0.25, 0.0, 1.0,
                  -0.25, -0.25, 0.0, 1.0];

    foreach (x, y, z, w; arr.tupleChunks!4)
        x.writeln;
}


(It still doesn't work, but it doesn't work in a better way).

Bye,
bearophile
July 31, 2013
>     @property front() {
>         mixin("return tuple(" ~
>               n.iota.map!(i => format("cr.front[%d]", i)).join(", ") ~
>               ");");
>     }

That TupleChunks is doing kind of the opposite of this older enhancement request of mine:
http://d.puremagic.com/issues/show_bug.cgi?id=9871

Bye,
bearophile
July 31, 2013
On 07/31/2013 11:19 AM, bearophile wrote:
>> template Iota(int stop) {
>>     static if (stop <= 0)
>>         alias TypeTuple!() Iota;
>>     else
>>         alias TypeTuple!(Iota!(stop-1), stop-1) Iota;
>> }
>
> Silly me, that Iota is not needed:
>
>
> import std.stdio : writeln;
> import std.range: chunks, Chunks, iota;
> import std.string: format, join;
> import std.typecons: tuple;
> import std.algorithm: map;
>
> struct TupleChunks(size_t n, CR) {
>      CR cr;
>
>      @property bool empty() { return cr.empty; }
>
>      void popFront() { cr.popFront; }
>
>      @property front() {
>          mixin("return tuple(" ~
>                n.iota.map!(i => format("cr.front[%d]", i)).join(", ") ~
>                ");");
>      }
> }
>
> TupleChunks!(n, Chunks!R) tupleChunks(size_t n, R)(R r) {
>      return typeof(return)(chunks(r, n));
> }
>
> void main() {
>     float[] arr = [ 0.0,   0.15, 0.0, 1.0,
>                     0.25, -0.25, 0.0, 1.0,
>                    -0.25, -0.25, 0.0, 1.0];
>
>      foreach (x, y, z, w; arr.tupleChunks!4)
>          x.writeln;
> }
>
>
> (It still doesn't work, but it doesn't work in a better way).
>
> Bye,
> bearophile

Fixed magically :) by a line that should have no effect:

    pragma(msg, ElementType!(typeof(arr.tupleChunks!4)));

Of course one must also import ElementType:

import std.range: chunks, Chunks, iota, ElementType;

Ali

July 31, 2013
On 07/31/2013 11:36 AM, Ali Çehreli wrote:

> Fixed magically :) by a line that should have no effect:
>
>      pragma(msg, ElementType!(typeof(arr.tupleChunks!4)));

And only when inserted before the foreach statement.

Ali

« First   ‹ Prev
1 2