Thread overview | ||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
July 31, 2013 chunks equivalent with unpacking? | ||||
---|---|---|---|---|
| ||||
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 Re: chunks equivalent with unpacking? | ||||
---|---|---|---|---|
| ||||
Posted in reply to Andrej Mitrovic | 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 Re: chunks equivalent with unpacking? | ||||
---|---|---|---|---|
| ||||
Posted in reply to bearophile | 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 Re: chunks equivalent with unpacking? | ||||
---|---|---|---|---|
| ||||
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 Re: chunks equivalent with unpacking? | ||||
---|---|---|---|---|
| ||||
Posted in reply to Andrej Mitrovic | 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 Re: chunks equivalent with unpacking? | ||||
---|---|---|---|---|
| ||||
Posted in reply to Ali Çehreli | 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 Re: chunks equivalent with unpacking? | ||||
---|---|---|---|---|
| ||||
Posted in reply to bearophile | > 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 Re: chunks equivalent with unpacking? | ||||
---|---|---|---|---|
| ||||
Posted in reply to bearophile | > @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 Re: chunks equivalent with unpacking? | ||||
---|---|---|---|---|
| ||||
Posted in reply to bearophile | 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 Re: chunks equivalent with unpacking? | ||||
---|---|---|---|---|
| ||||
Posted in reply to Ali Çehreli | 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
|
Copyright © 1999-2021 by the D Language Foundation