July 21, 2006 Re: More powerful foreach statements | ||||
---|---|---|---|---|
| ||||
Posted in reply to Oskar Linde | Oskar Linde wrote: > Python style ranges: > > foreach(x; range(5)) > ... x is 0,1,2,3,4 > foreach(x; range(1, 6)) > ... x is 1,2,3,4,5 > foreach(x; range(1.5, 0, -0.25)) // bad idea to support doubles? > ... x is 1.5, 1.25, 1.0, 0.75, 0.5, 0.25 > For what it's worth, writing a Python 'xrange'-style construct in D isn't that hard. I've posted one previously to the group: http://www.digitalmars.com/drn-bin/wwwnews?digitalmars.D/38808 Some follow-ups to that post had templated versions. -- Kirk McDonald Pyd: Wrapping Python with D http://dsource.org/projects/pyd/wiki |
July 21, 2006 Re: More powerful foreach statements | ||||
---|---|---|---|---|
| ||||
Posted in reply to pragma | pragma wrote: > In article <e9qe1i$1m5c$3@digitaldaemon.com>, Oskar Linde says... >> I've not found a good iterator design yet though. Only supporting foreach style iteration is a bit too limited. >> >> I would also like array views to work as iterators and also support common array operations without having to generate temporary arrays. >> >> Currently: >> >> double pensionCosts = employees >> .filter((Employee e) { return e.age >= 28; }) >> .map((Employee e) { return e.salary * 0.04; }) >> .sum(); >> >> Will generate a temporary Employee[] array and a temporary double[] array. >> >> Using array views one could get around the temporaries: >> >> // give all employees over 55 a 3 % raise: >> >> employees.select((Employee e) { return e.age >= 55; }) >> .update((Employee e) { e.salary *= 1.03; }); >> >> //(No temporaries created.) >> >> /Oskar > > IMO, I think it's all *very* worth it. It kind of fills this gap between what > phobos gives us and what STL's iterators and algorithms has to offer. > > I think that if you have an 'array view' widget/template that supports > opApply(), length(), and opIndex() for all the view types you return, then > you're pretty much set. That will cover both the random-access and > sequential-access modes that arrays already enjoy. That way, you can support > for() iteration as well, and still not need any temporaries. ;) Yes, that is probably the right way do to it. If the views support the same operations as arrays do, they will be usable just as arrays, and views-of-views and similar would work transparently. > As for ranges, I wouldn't throw those out. Ruby also has them, and thanks to > Rails, prototype.js now supports them now too. I'd be willing to bet that > someone will come along to the DNG and say "Where's the range support?!" - and > we can all just point them to your library. > > I'd imagine ranges being an extension of your 'array view' concept. Yes, ideally, a range should work just like a (read only) array, but without allocating any memory. Silly example: range(100).select((int x) { return x % 5 == 0 }).sum() //returns 950 > I think something like the following would be workable: > > /**/ struct ReverseArrayView(ArrayT){ > /**/ ElemType!(ArrayT) opIndex(uint idx); > /**/ ArrayT opSlice(uint start,uint end); //creates temporary or another view? > /**/ int opApply(int delegate(inout ElemType!(ArrayT)) dg); > /**/ uint length(); > /**/ static opCall(ArrayT arr); > /**/ } > /**/ > /**/ template reverse(ArrayT){ > /**/ ReverseArrayView!(ArrayT) reverse(ArrayT arr){ /**/ return ReverseArrayView!(ArrayT)(arr); > /**/ } > /**/ } > > The trick is to get ArrayView instances to jive with your templates like > ElemType!() such that they get treated like first-class arrays where possible. I > think static if() could be used to check for a static property on ArrayViews > like "isArrayView=true", such that standard arrays will fail the test. Yes, that is definitely doable. The only problem is that there is no way to "inject" methods for anything but built-in arrays. I'd have to add wrappers to all views for all functions (a mixin will probably be enough), or live with calling them as ordinary functions: update(select(employees, (Employee e) { return e.age >= 55; }), (Employee e) { e.salary *= 1.03; }); instead of: employees.select((Employee e) { return e.age >= 55; }) .update((Employee e) { e.salary *= 1.03; }); It would be nice to have a way to inject methods/define extension methods for other types than arrays. Maybe something like what has been proposed before: int squared(this int x) { return x*x; } and called: 5.squared(); Just add ifti template support to this and the array functions would be applicable as methods of any type that implements the needed iterator semantics (opApply or opIndex and length()). /Oskar |
Copyright © 1999-2021 by the D Language Foundation