www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - foreach syntax, std.mixin

reply dsimcha <dsimcha yahoo.com> writes:
What are the chances that D gets auto tuple unpacking for foreach loops before
D2 goes gold?  In other words, it would be nice to write:

uint[] foo = [1,2,3,4,5];
uint[] bar = [6,7,8,9,10];

foreach(a, b; zip(foo, bar)) {
    // Does what you think it does.
}

Also, how about foreach over ranges with an index variable?  For example:

foreach(index, elem; chain(foo, bar)) {
   // Does what you think it does.
}

If these aren't going to happen, would it be worth having in Phobos a
std.mixin module (I've already considered such a thing a few times here) that
would allow someone writing a range to add goodies like these to structs and
classes with a single line of code?  For example:

struct MyRange {
    Tuple!(float, float) _front;
    bool _empty;

    typeof(_front) front() {
        return _front;
    }

    void popFront() {
        // do stuff.
    }

    bool empty() {
        return _empty;
    }

    mixin(UnpackTupleForeach);

    mixin(IndexForeach);
}

The mixin(UnpackTupleForeach) would make this work:
foreach(float float1, float float2; MyRange.init) {}

The mixin(IndexForeach) would make this work:
foreach(size_t index, float floatTuple; MyRange.init) {}

This would work via opApply, which some don't like for efficiency reasons.
It's been shown a while back that, while opApply does have some overhead, it's
pretty small and LDC actually optimizes it out.
Nov 08 2009
next sibling parent reply Bill Baxter <wbaxter gmail.com> writes:
On Sun, Nov 8, 2009 at 9:10 AM, dsimcha <dsimcha yahoo.com> wrote:
 What are the chances that D gets auto tuple unpacking for foreach loops b=

 D2 goes gold? =A0In other words, it would be nice to write:

 uint[] foo =3D [1,2,3,4,5];
 uint[] bar =3D [6,7,8,9,10];

 foreach(a, b; zip(foo, bar)) {
 =A0 =A0// Does what you think it does.
 }

Probably obvious, but if added, it should probably work by means of .tupleof on the iterated type, rather than by any particular knowledge of types used in std.range. And I guess just public members would be included. Main down side is that it could introduce ambiguities with explicitly specified opApply overloads. If you have an opApply that takes uint,uint already, which gets used? Or is it an error? I not sure what would be least likely to cause trouble. One the one hand the class author should be able to override the behavior, but on the other hand class users will assume that tuple unpacking works and may be surprised if it has been overriden to do something different. So either rule -- specifc opApply wins, or it's an error -- seems to have an argument for it.
 Also, how about foreach over ranges with an index variable? =A0For exampl=

 foreach(index, elem; chain(foo, bar)) {
 =A0 // Does what you think it does.
 }

This will create too many ambiguities if the tuple unpacking is also implemeted, so I'm agaist it: foreach(index,elem; zip(arrayOfInts, bar)) { // I don't know what this does } I think the index variant would better be done as an enumerate() function like in python. Which does something like zip(iota(1,bar.length),bar).
 If these aren't going to happen, would it be worth having in Phobos a
 std.mixin module (I've already considered such a thing a few times here) =

 would allow someone writing a range to add goodies like these to structs =

 classes with a single line of code? =A0For example:

These look less controversial, but I would like having foreach be able to tease apart structs/tuples. A further issue, and this may nuke the idea till we have tuple literals, is what to do about tuples of tuples. In python you can do for i,(f,b) in enumerate(zip(foo,bar)): I don't think we want to introduce the bad idea of automatic flattening yet again just to get this kind of thing to work: foreach(i,f,b; enumerate(zip(foo,bar))) It should really be something like: foreach(i,(f,b); enumerate(zip(foo,bar))) But that requires D get some tuple sytax. ... Or I suppose it could be a special syntax in "foreach" for now. Another approach to disambiguating tuple iteration vs opApply iteration could be to require tuple parens around the arguments: foreach((f,b); zip(foo,bar)) {} // tuple iteration foreach(f,b; zip(foo, bar)) {} // only works if zip returns something with the right kind of opApply --bb
Nov 08 2009
parent reply dsimcha <dsimcha yahoo.com> writes:
== Quote from Bill Baxter (wbaxter gmail.com)'s article
 On Sun, Nov 8, 2009 at 9:10 AM, dsimcha <dsimcha yahoo.com> wrote:
 What are the chances that D gets auto tuple unpacking for foreach loops b

 D2 goes gold?  In other words, it would be nice to write:

 uint[] foo = [1,2,3,4,5];
 uint[] bar = [6,7,8,9,10];

 foreach(a, b; zip(foo, bar)) {
    // Does what you think it does.
 }

.tupleof on the iterated type, rather than by any particular knowledge of types used in std.range. And I guess just public members would be included. Main down side is that it could introduce ambiguities with explicitly specified opApply overloads. If you have an opApply that takes uint,uint already, which gets used? Or is it an error? I not sure what would be least likely to cause trouble. One the one hand the class author should be able to override the behavior, but on the other hand class users will assume that tuple unpacking works and may be surprised if it has been overriden to do something different. So either rule -- specifc opApply wins, or it's an error -- seems to have an argument for it.
 Also, how about foreach over ranges with an index variable?  For exampl

 foreach(index, elem; chain(foo, bar)) {
   // Does what you think it does.
 }

implemeted, so I'm agaist it: foreach(index,elem; zip(arrayOfInts, bar)) { // I don't know what this does } I think the index variant would better be done as an enumerate() function like in python. Which does something like zip(iota(1,bar.length),bar).

Enumerate is a great idea. It's probably much better than requiring every range struct to mix something in to enable this behavior. Thanks. I guess the same thing could be applied to unpack(). Instead of making the range implementer mixin something to enable this (he/she will probably forget and it could lead to ambiguities), do it on the caller end. Makes me wonder why noone thought of this until now, or maybe someone did and I forgot. How's: foreach(fooElem, barElem; unpack(zip(foo, bar))) {}, or: foreach(i, elem; enumerate(chain(foo, bar))) {} ?
Nov 08 2009
parent reply dsimcha <dsimcha yahoo.com> writes:
== Quote from Philippe Sigaud (philippe.sigaud gmail.com)'s article
 dsimcha wrote:
 Makes me wonder why noone thought of this until now, or maybe someone did
 and I
 forgot.  How's:

 foreach(fooElem, barElem; unpack(zip(foo, bar))) {}, or:

 foreach(i, elem; enumerate(chain(foo, bar))) {} ?

deligthed to have that.

Hot off the press and VERY prototype-ish: Code: http://pastebin.com/m2087e524 Docs: http://cis.jhu.edu/~dsimcha/unpackEnumerate.html Does this look like a good addition to std.range? The elegance of it is it solves the problem of providing syntactic sugar to ranges w/ zero ripple effects either in the compiler or in the rest of Phobos. I'll file it somewhere more official after people review it a little and refine the idea, but I definitely think something similar to this has a legit place in std.range. If you're wondering how unpack works and don't want to grovel through all the code, it's tons of string mixin magic. That's about the only way I was able to make it work.
Nov 08 2009
next sibling parent reply dsimcha <dsimcha yahoo.com> writes:
== Quote from Bill Baxter (wbaxter gmail.com)'s article
 On Sun, Nov 8, 2009 at 1:43 PM, dsimcha <dsimcha yahoo.com> wrote:
 == Quote from Philippe Sigaud (philippe.sigaud gmail.com)'s article
 dsimcha wrote:
 Makes me wonder why noone thought of this until now, or maybe someone



 and I
 forgot.  How's:

 foreach(fooElem, barElem; unpack(zip(foo, bar))) {}, or:

 foreach(i, elem; enumerate(chain(foo, bar))) {} ?

deligthed to have that.

Hot off the press and VERY prototype-ish: Code: http://pastebin.com/m2087e524 Docs: http://cis.jhu.edu/~dsimcha/unpackEnumerate.html Does this look like a good addition to std.range?  The elegance of it i

 the problem of providing syntactic sugar to ranges w/ zero ripple effects

 in the compiler or in the rest of Phobos.  I'll file it somewhere more

 after people review it a little and refine the idea, but I definitely thi

 something similar to this has a legit place in std.range.

 If you're wondering how unpack works and don't want to grovel through all

 code, it's tons of string mixin magic.  That's about the only way I was

 make it work.

from using unpack or enumerate. As Andrei is fond of saying "expensive abstractions are a dime a dozen". If it's not too bad then this sounds like a decent solution to me. --bb

import std.stdio, std.perf; void main() { auto myRange = replicate(100_000_000, 0); scope pc = new PerformanceCounter; pc.start; foreach(i, num; enumerate(myRange)) {} pc.stop; writeln("Enumerate: ", pc.milliseconds); pc.start; foreach(num; myRange) {} pc.stop; writeln("Raw Range: ", pc.milliseconds); pc.start; foreach(i; 0..100_000_000) { int num = 0; } pc.stop; writeln("Plain old for loop: ", pc.milliseconds); } Enumerate: 1207 Raw Range: 940 Plain old for loop: 112 In other words, it's not a zero-cost abstraction, but it's not what you'd call expensive either, especially since in real-world code you'd actually have a loop body. Also, apparently LDC inlines opApply, proving that a sufficiently smart but realistically implementable compiler can make this a zero-cost abstraction. (Someone who uses LDC please confirm this.) To put this in perspective, ranges are not a free abstraction on DMD either, probably because DMD's inliner isn't sufficiently aggressive. Really, the raw range case shouldn't take nearly as long as it does either, as the plain old for loop test proves. IMHO the details of how DMD's optimizer currently works should not dictate the design of the standard library unless either performance is absurdly bad or we have good reason to believe that common implementations will never be any better. LDC proves that inlining opApply can be done. If you have something that absolutely must be as fast as possible now, you may not want to use this (or ranges either), but in the bigger picture I think it's efficient enough to have a legitimate place in Phobos.
Nov 08 2009
parent dsimcha <dsimcha yahoo.com> writes:
== Quote from Bill Baxter (wbaxter gmail.com)'s article
 I agree.  Those numbers don't seem so bad, particularly if inlining is
 possible in the future.
 But there's still the issue of how to get both an enumeration and an
 unpacked tuple together.
 --bb

Yeah, I thought about this, and I didn't have any good answer other than make an absurdly baroque enumerateUnpack function. I'd be open to suggestions here.
Nov 09 2009
prev sibling parent dsimcha <dsimcha yahoo.com> writes:
== Quote from Philippe Sigaud (philippe.sigaud gmail.com)'s article
 --0016e6d99ba70494130478196284
 Content-Type: text/plain; charset=ISO-8859-1
 On Sun, Nov 8, 2009 at 22:43, dsimcha <dsimcha yahoo.com> wrote:
 Hot off the press and VERY prototype-ish:

 Code:
 http://pastebin.com/m2087e524

 Docs:


 Cool! Thanks a lot.

I'll go and read this part of the docs. *test it* Hmm, I can get enumerate to work, but the Unpack part doesn't compile. It complains elem.at!(0) is not an lvalue.

Argh. That's because I was hacking around with Zip in my copy of Phobos right before I wrote this lib and forgot to change some stuff back to stock when testing. If you uncomment a /*ref*/ in there somewhere, which was leftover from a compiler bug a long time ago, it seems to work. The real problem is that that bit of cruft hasn't been removed from Phobos yet.
Nov 11 2009
prev sibling next sibling parent Philippe Sigaud <philippe.sigaud gmail.com> writes:
--0016e6d7842363bb2c0477e22024
Content-Type: text/plain; charset=ISO-8859-1

On Sun, Nov 8, 2009 at 21:14, dsimcha wrote:

 function like in python. Which does something like
 zip(iota(1,bar.length),bar).

 I think the index variant would better be done as an enumerate()

range struct to mix something in to enable this behavior. Thanks. FWIW, I coded enumerate and such for D2, and will post them on dsource as

Personally, I then use a 'tuplify' template which takes a standard function and transforms it into a tuple-accepting one: so if I have: int foo(int a, double b, string c) {...} tuplify!foo is : int tfoo(Tuple!(int, double, string) t) { /* extracts a,b & c from t, and returns foo(a,b,c) */ } so, as I can't unpack the tuple: foreach(a,b,c ; zip(range1, range2, range3) { /* do something with foo on (a,b,c) */ } I tuplify foo and do: foreach (tup; zip(range1, range2, range3) { /* do something with tuplify!foo(tup) */ } There is no real limit on the number of ranges that can be acted upon in parallel that way, though I admit the syntax is a bit cumbersome. I also use unzip!index( someZip) to get back the original range from inside zip.
 I guess the same thing could be applied to unpack().  Instead of making the
 range
 implementer mixin something to enable this (he/she will probably forget and
 it
 could lead to ambiguities), do it on the caller end.

 Makes me wonder why noone thought of this until now, or maybe someone did
 and I
 forgot.  How's:

 foreach(fooElem, barElem; unpack(zip(foo, bar))) {}, or:

 foreach(i, elem; enumerate(chain(foo, bar))) {} ?

deligthed to have that. Philippe --0016e6d7842363bb2c0477e22024 Content-Type: text/html; charset=ISO-8859-1 Content-Transfer-Encoding: quoted-printable <div class=3D"gmail_quote">On Sun, Nov 8, 2009 at 21:14, dsimcha<span dir= =3D"ltr"></span> wrote:<br><blockquote class=3D"gmail_quote" style=3D"borde= r-left: 1px solid rgb(204, 204, 204); margin: 0pt 0pt 0pt 0.8ex; padding-le= ft: 1ex;"> <div class=3D"im"> &gt; function like in python. Which does something like<br> &gt; zip(iota(1,bar.length),bar).<br> <br> </div>&gt; I think the index variant would better be done as an enumerate()= <br>Enumerate is a great idea. =A0It&#39;s probably much better than requir= ing every range<br> struct to mix something in to enable this behavior. =A0Thanks.<br> <br></blockquote><div>FWIW, I coded enumerate and such for D2, and will pos= t them on dsource as soon as I can get my hands on svn. In a few days at mo= st, I hope.<br><br>Personally, I then use a &#39;tuplify&#39; template whic= h takes a standard function and transforms it into a tuple-accepting one:<b= r> so if I have:<br><br>int foo(int a, double b, string c) {...}<br>tuplify!fo= o is :<br>int tfoo(Tuple!(int, double, string) t) { /* extracts a,b &amp; c= from t, and returns foo(a,b,c) */=A0 }<br><br><br>so, as I can&#39;t unpac= k the tuple:<br> <br>foreach(a,b,c ; zip(range1, range2, range3) {<br>=A0=A0=A0=A0=A0 /* do = something with foo on (a,b,c) */<br>}<br><br>I tuplify foo and do:<br><br>f= oreach (tup; zip(range1, range2, range3) {<br>=A0=A0 /* do something with t= uplify!foo(tup) */<br> }<br>There is no real limit on the number of ranges that can be acted upon = in parallel that way, though I admit the syntax is a bit cumbersome.<br><br=
I also use unzip!index( someZip) to get back the original range from insid=

<br>=A0</div><blockquote class=3D"gmail_quote" style=3D"border-left: 1px so= lid rgb(204, 204, 204); margin: 0pt 0pt 0pt 0.8ex; padding-left: 1ex;"> I guess the same thing could be applied to unpack(). =A0Instead of making t= he range<br> implementer mixin something to enable this (he/she will probably forget and= it<br> could lead to ambiguities), do it on the caller end.<br> <br> Makes me wonder why noone thought of this until now, or maybe someone did a= nd I<br> forgot. =A0How&#39;s:<br> <br> foreach(fooElem, barElem; unpack(zip(foo, bar))) {}, or:<br> <br> foreach(i, elem; enumerate(chain(foo, bar))) {} ?<br> <br> </blockquote></div><br>Can that be done for more than two ranges? The synta= x is so nice, I&#39;d be deligthed to have that.<br><br><br>=A0 Philippe<br=
<br>

--0016e6d7842363bb2c0477e22024--
Nov 08 2009
prev sibling next sibling parent Bill Baxter <wbaxter gmail.com> writes:
On Sun, Nov 8, 2009 at 1:43 PM, dsimcha <dsimcha yahoo.com> wrote:
 =3D=3D Quote from Philippe Sigaud (philippe.sigaud gmail.com)'s article
 dsimcha wrote:
 Makes me wonder why noone thought of this until now, or maybe someone =



 and I
 forgot. =A0How's:

 foreach(fooElem, barElem; unpack(zip(foo, bar))) {}, or:

 foreach(i, elem; enumerate(chain(foo, bar))) {} ?

deligthed to have that.

Hot off the press and VERY prototype-ish: Code: http://pastebin.com/m2087e524 Docs: http://cis.jhu.edu/~dsimcha/unpackEnumerate.html Does this look like a good addition to std.range? =A0The elegance of it i=

 the problem of providing syntactic sugar to ranges w/ zero ripple effects=

 in the compiler or in the rest of Phobos. =A0I'll file it somewhere more =

 after people review it a little and refine the idea, but I definitely thi=

 something similar to this has a legit place in std.range.

 If you're wondering how unpack works and don't want to grovel through all=

 code, it's tons of string mixin magic. =A0That's about the only way I was=

 make it work.

What's the overhead like? That would be the thing that would keep me from using unpack or enumerate. As Andrei is fond of saying "expensive abstractions are a dime a dozen". If it's not too bad then this sounds like a decent solution to me. --bb
Nov 08 2009
prev sibling next sibling parent Bill Baxter <wbaxter gmail.com> writes:
On Sun, Nov 8, 2009 at 5:13 PM, dsimcha <dsimcha yahoo.com> wrote:
 =3D=3D Quote from Bill Baxter (wbaxter gmail.com)'s article
 On Sun, Nov 8, 2009 at 1:43 PM, dsimcha <dsimcha yahoo.com> wrote:
 =3D=3D Quote from Philippe Sigaud (philippe.sigaud gmail.com)'s articl=



 dsimcha wrote:
 Makes me wonder why noone thought of this until now, or maybe someo=





 did
 and I
 forgot. =A0How's:

 foreach(fooElem, barElem; unpack(zip(foo, bar))) {}, or:

 foreach(i, elem; enumerate(chain(foo, bar))) {} ?





 deligthed to have that.

Hot off the press and VERY prototype-ish: Code: http://pastebin.com/m2087e524 Docs: http://cis.jhu.edu/~dsimcha/unpackEnumerate.html Does this look like a good addition to std.range? =A0The elegance of i=



 s it solves
 the problem of providing syntactic sugar to ranges w/ zero ripple effe=



 =A0either
 in the compiler or in the rest of Phobos. =A0I'll file it somewhere mo=



 official
 after people review it a little and refine the idea, but I definitely =



 nk
 something similar to this has a legit place in std.range.

 If you're wondering how unpack works and don't want to grovel through =



 =A0the
 code, it's tons of string mixin magic. =A0That's about the only way I =



 =A0able to
 make it work.

from using unpack or enumerate. =A0As Andrei is fond of saying "expensive abstractions are a dime a dozen". =A0If it's not too bad then this sounds like a decent solution to me. --bb

import std.stdio, std.perf; void main() { =A0 =A0auto myRange =3D replicate(100_000_000, 0); =A0 =A0scope pc =3D new PerformanceCounter; =A0 =A0pc.start; =A0 =A0foreach(i, num; enumerate(myRange)) {} =A0 =A0pc.stop; =A0 =A0writeln("Enumerate: =A0", pc.milliseconds); =A0 =A0pc.start; =A0 =A0foreach(num; myRange) {} =A0 =A0pc.stop; =A0 =A0writeln("Raw Range: =A0", pc.milliseconds); =A0 =A0pc.start; =A0 =A0foreach(i; 0..100_000_000) { =A0 =A0 =A0 =A0int num =3D 0; =A0 =A0} =A0 =A0pc.stop; =A0 =A0writeln("Plain old for loop: =A0", pc.milliseconds); } Enumerate: =A01207 Raw Range: =A0940 Plain old for loop: =A0112 In other words, it's not a zero-cost abstraction, but it's not what you'd=

 expensive either, especially since in real-world code you'd actually have=

 body. =A0Also, apparently LDC inlines opApply, proving that a sufficientl=

 realistically implementable compiler can make this a zero-cost abstractio=

 (Someone who uses LDC please confirm this.)

 To put this in perspective, ranges are not a free abstraction on DMD eith=

 probably because DMD's inliner isn't sufficiently aggressive. =A0Really, =

 range case shouldn't take nearly as long as it does either, as the plain =

 loop test proves.

 IMHO the details of how DMD's optimizer currently works should not dictat=

 design of the standard library unless either performance is absurdly bad =

 have good reason to believe that common implementations will never be any=

 =A0LDC proves that inlining opApply can be done. =A0If you have something=

 absolutely must be as fast as possible now, you may not want to use this =

 ranges either), but in the bigger picture I think it's efficient enough t=

 legitimate place in Phobos.

I agree. Those numbers don't seem so bad, particularly if inlining is possible in the future. But there's still the issue of how to get both an enumeration and an unpacked tuple together. --bb
Nov 09 2009
prev sibling next sibling parent Bill Baxter <wbaxter gmail.com> writes:
On Mon, Nov 9, 2009 at 6:46 AM, dsimcha <dsimcha yahoo.com> wrote:
 =3D=3D Quote from Bill Baxter (wbaxter gmail.com)'s article
 I agree. =A0Those numbers don't seem so bad, particularly if inlining is
 possible in the future.
 But there's still the issue of how to get both an enumeration and an
 unpacked tuple together.
 --bb

Yeah, I thought about this, and I didn't have any good answer other than =

 absurdly baroque enumerateUnpack function. =A0I'd be open to suggestions =

unpack2nd(enumerate(zip(foo,bar))) ? :-P or more seriously, you could have a flatten() type of HOF, which flattens any tuples at the top level. So (1, Tuple(a,Tuple(b,c))) becomes (1,a,Tuple(b,c)). --bb
Nov 09 2009
prev sibling next sibling parent Philippe Sigaud <philippe.sigaud gmail.com> writes:
--0016e6d99ba70494130478196284
Content-Type: text/plain; charset=ISO-8859-1

On Sun, Nov 8, 2009 at 22:43, dsimcha <dsimcha yahoo.com> wrote:

 Hot off the press and VERY prototype-ish:

 Code:
 http://pastebin.com/m2087e524

 Docs:
 http://cis.jhu.edu/~dsimcha/unpackEnumerate.html<http://cis.jhu.edu/%7Edsimcha/unpackEnumerate.html>

 Cool! Thanks a lot.

I looked at opApply for D1 maybe two years ago, but never used it myself. I'll go and read this part of the docs. *test it* Hmm, I can get enumerate to work, but the Unpack part doesn't compile. It complains elem.at!(0) is not an lvalue. You know, the Proxy part of std.range.zip is really annoying. I'd prefer zip to return std.typecons.Tuples, even if that means stopping at the shortest range. That's what other languages do and it seems enough for most uses. Does this look like a good addition to std.range? The elegance of it is it
 solves
 the problem of providing syntactic sugar to ranges w/ zero ripple effects
 either
 in the compiler or in the rest of Phobos.  I'll file it somewhere more
 official
 after people review it a little and refine the idea, but I definitely think
 something similar to this has a legit place in std.range.

 If you're wondering how unpack works and don't want to grovel through all
 the
 code, it's tons of string mixin magic.  That's about the only way I was
 able to
 make it work.

I'll read it with pleasure(!). I'm there to learn anyway.Heck, I can't read my own string mixins a week after writing them, so it'll be a good exercise. As to making it an addition to std.range, I'm all for it. If people don't want to use it because they are leery of using opApply, too bad for them. Your small benchmark was interesting: overhead exists, but it's not awful. Philippe --0016e6d99ba70494130478196284 Content-Type: text/html; charset=ISO-8859-1 Content-Transfer-Encoding: quoted-printable <br><br><div class=3D"gmail_quote">On Sun, Nov 8, 2009 at 22:43, dsimcha <s= pan dir=3D"ltr">&lt;<a href=3D"mailto:dsimcha yahoo.com">dsimcha yahoo.com<= /a>&gt;</span> wrote:<br><blockquote class=3D"gmail_quote" style=3D"border-= left: 1px solid rgb(204, 204, 204); margin: 0pt 0pt 0pt 0.8ex; padding-left= : 1ex;"> <br> Hot off the press and VERY prototype-ish:<br> <br> Code:<br> <a href=3D"http://pastebin.com/m2087e524" target=3D"_blank">http://pastebin= .com/m2087e524</a><br> <br> Docs:<br> <a href=3D"http://cis.jhu.edu/%7Edsimcha/unpackEnumerate.html" target=3D"_b= lank">http://cis.jhu.edu/~dsimcha/unpackEnumerate.html</a><br> <br></blockquote><div>Cool! Thanks a lot.<br>=A0<br>I looked at opApply for= D1 maybe two years ago, but never used it myself. I&#39;ll go and read thi= s part of the docs.<br><br>*test it*<br><br>Hmm, I can get enumerate to wor= k, but the Unpack part doesn&#39;t compile. It complains <a href=3D"http://= elem.at">elem.at</a>!(0) is not an lvalue.<br> <br>You know, the Proxy part of std.range.zip is really annoying. I&#39;d p= refer zip to return std.typecons.Tuples, even if that means stopping at the= shortest range. That&#39;s what other languages do and it seems enough for= most uses.<br> <br><br></div><blockquote class=3D"gmail_quote" style=3D"border-left: 1px s= olid rgb(204, 204, 204); margin: 0pt 0pt 0pt 0.8ex; padding-left: 1ex;"> Does this look like a good addition to std.range? =A0The elegance of it is = it solves<br> the problem of providing syntactic sugar to ranges w/ zero ripple effects e= ither<br> in the compiler or in the rest of Phobos. =A0I&#39;ll file it somewhere mor= e official<br> after people review it a little and refine the idea, but I definitely think= <br> something similar to this has a legit place in std.range.<br> <br> If you&#39;re wondering how unpack works and don&#39;t want to grovel throu= gh all the<br> code, it&#39;s tons of string mixin magic. =A0That&#39;s about the only way= I was able to<br> make it work.<br> </blockquote></div><br>I&#39;ll read it with pleasure(!). I&#39;m there to = learn anyway.Heck, I can&#39;t read my own string mixins a week after writi= ng them, so it&#39;ll be a good exercise.<br><br>As to making it an additio= n to std.range, I&#39;m all for it. If people don&#39;t want to use it beca= use they are leery of using opApply, too bad for them. Your small benchmark= was interesting: overhead exists, but it&#39;s not awful.<br> <br>=A0 Philippe<br><br> --0016e6d99ba70494130478196284--
Nov 11 2009
prev sibling next sibling parent Philippe Sigaud <philippe.sigaud gmail.com> writes:
--0016e6d64441292a4004781b2388
Content-Type: text/plain; charset=ISO-8859-1

On Wed, Nov 11, 2009 at 16:48, dsimcha <dsimcha yahoo.com> wrote:


 *test it*
 Hmm, I can get enumerate to work, but the Unpack part doesn't compile. It
 complains elem.at!(0) is not an lvalue.

Argh. That's because I was hacking around with Zip in my copy of Phobos right before I wrote this lib and forgot to change some stuff back to stock when testing.

How do you deal with successive version of DMD? Do you have parallel installations? I know I hacked around Zip, Chain and such a few times, forgot about it, only to have it crushed by my next download :-(
  If you uncomment a /*ref*/ in there somewhere, which was leftover from a
 compiler bug a long time ago, it seems to work.  The real problem is that
 that bit
 of cruft hasn't been removed from Phobos yet.

OK, thanks. I get the impression that ref is viral... Either you have it everywhere or it'll block some compositions (chain(map() ...) . I'm wrong? Thanks again for your code, I'll test it and tell you how it went. Philippe --0016e6d64441292a4004781b2388 Content-Type: text/html; charset=ISO-8859-1 Content-Transfer-Encoding: quoted-printable <div class=3D"gmail_quote">On Wed, Nov 11, 2009 at 16:48, dsimcha <span dir= =3D"ltr">&lt;<a href=3D"mailto:dsimcha yahoo.com">dsimcha yahoo.com</a>&gt;= </span> wrote:<br><div>=A0</div><blockquote class=3D"gmail_quote" style=3D"= border-left: 1px solid rgb(204, 204, 204); margin: 0pt 0pt 0pt 0.8ex; paddi= ng-left: 1ex;"> &gt; *test it*<br><div class=3D"im"> &gt; Hmm, I can get enumerate to work, but the Unpack part doesn&#39;t comp= ile. It<br> &gt; complains <a href=3D"http://elem.at" target=3D"_blank">elem.at</a>!(0)= is not an lvalue.<br> <br> </div>Argh. =A0That&#39;s because I was hacking around with Zip in my copy = of Phobos right<br> before I wrote this lib and forgot to change some stuff back to stock when<= br> testing. </blockquote><div><br>How do you deal with successive version of D= MD? Do you have parallel installations? I know I hacked around Zip, Chain a= nd such a few times, forgot about it, only to have it crushed by my next do= wnload :-(<br> =A0</div><blockquote class=3D"gmail_quote" style=3D"border-left: 1px solid = rgb(204, 204, 204); margin: 0pt 0pt 0pt 0.8ex; padding-left: 1ex;">=A0If yo= u uncomment a /*ref*/ in there somewhere, which was leftover from a<br> compiler bug a long time ago, it seems to work. =A0The real problem is that= that bit<br> of cruft hasn&#39;t been removed from Phobos yet.<br> </blockquote></div><br>OK, thanks.<br>I get the impression that ref is vira= l... Either you have it everywhere or it&#39;ll block some compositions (ch= ain(map() ...) . I&#39;m wrong? <br><br>Thanks again for your code, I&#39;l= l test it and tell you how it went.<br> <br>=A0 Philippe<br><br> --0016e6d64441292a4004781b2388--
Nov 11 2009
prev sibling parent Philippe Sigaud <philippe.sigaud gmail.com> writes:
--0016e6d7eea08e126d04781fc7e2
Content-Type: text/plain; charset=ISO-8859-1

On Wed, Nov 11, 2009 at 17:44, Philippe Sigaud <philippe.sigaud gmail.com>wrote:

 On Wed, Nov 11, 2009 at 16:48, dsimcha <dsimcha yahoo.com> wrote:

  If you uncomment a /*ref*/ in there somewhere, which was leftover from a
 compiler bug a long time ago, it seems to work.  The real problem is that
 that bit
 of cruft hasn't been removed from Phobos yet.


Strangely, on my computer it's frequently faster to use your enumerate than a raw range (re: your speed tests). Is there something I don't get? I thought (ie: read here) that opApply was slower than other means of iteration? My own enumerate, which produces a tuple(uint, T) as a lazy range is thrice as slow :( And, I just discovered that I can simply unpack a tuple with .field or .expand. auto t = tuple('a',1, 2.0); int foo(char a, int b, double c) { return to!int(a) * b * to!int(c);} foo(t.expand) ; // works. Is that common knowledge? It'd be nice addition to the std.typecons docs. Gosh, when I think of the time I spent to find a way to extract this information with template recursion, to map a n-ary function on tuple-producing ranges. And all this time, I could have done tuple-mapping as a simple map on "foo(a.expand)". Time for some heavy refactoring... Philippe --0016e6d7eea08e126d04781fc7e2 Content-Type: text/html; charset=ISO-8859-1 Content-Transfer-Encoding: quoted-printable <br><br><div class=3D"gmail_quote">On Wed, Nov 11, 2009 at 17:44, Philippe = Sigaud <span dir=3D"ltr">&lt;<a href=3D"mailto:philippe.sigaud gmail.com">p= hilippe.sigaud gmail.com</a>&gt;</span> wrote:<br><blockquote class=3D"gmai= l_quote" style=3D"border-left: 1px solid rgb(204, 204, 204); margin: 0pt 0p= t 0pt 0.8ex; padding-left: 1ex;"> <div class=3D"gmail_quote"><div>On Wed, Nov 11, 2009 at 16:48, dsimcha <spa= n dir=3D"ltr">&lt;<a href=3D"mailto:dsimcha yahoo.com" target=3D"_blank">ds= imcha yahoo.com</a>&gt;</span> wrote:=A0</div><div class=3D"im"><blockquote= class=3D"gmail_quote" style=3D"border-left: 1px solid rgb(204, 204, 204); = margin: 0pt 0pt 0pt 0.8ex; padding-left: 1ex;"> =A0If you uncomment a /*ref*/ in there somewhere, which was leftover from a= <br> compiler bug a long time ago, it seems to work. =A0The real problem is that= that bit<br> of cruft hasn&#39;t been removed from Phobos yet.<br></blockquote></div></d= iv></blockquote><div><br>So, it works. Thanks! <br><br>Strangely, on my com= puter it&#39;s frequently faster to use your enumerate than a raw range (re= : your speed tests). Is there something I don&#39;t get? I thought (ie: rea= d here) that opApply was slower than other means of iteration?<br> My own enumerate, which produces a tuple(uint, T) as a lazy range is thrice= as slow :(<br><br><br>And, I just discovered that I can simply unpack a tu= ple with .field or .expand.<br><br>auto t =3D tuple(&#39;a&#39;,1, 2.0);<br=

o(t.expand) ; // works.<br><br>Is that common knowledge? It&#39;d be nice a= ddition to the std.typecons docs.<br><br>=A0Gosh, when I think of the time = I spent to find a way to extract this information with template recursion, = to map a n-ary function on tuple-producing ranges. And all this time, I cou= ld have done tuple-mapping as a simple map on &quot;foo(a.expand)&quot;.<br=

--0016e6d7eea08e126d04781fc7e2--
Nov 11 2009