Re: Another task
bearophile wrote: I think for a newcomer the most difficult part is related to tuples: * find them (in std.typecons!!!) * catch after much time, pains, research, they should not even try to construct a tuple using Tuple!, but using the convenience tuple() func instead. I agree that like dynamic arrays, tuples are better as built-ins, in D too. Another very useful thing is tuple unpacking syntax: http://d.puremagic.com/issues/show_bug.cgi?id=4579 And if not necessarily being built-ins, they are useful enough to warrant inclusion in object.d rather than std.typecons. -- Simen
Re: Another task
spir: > Yes, this is the only nice looking, high-level, and D-style solution. I have added: http://d.puremagic.com/issues/show_bug.cgi?id=5466 > While I by far prefer avoiding stringcode: > auto r = map!((p) (tuple(p[0]*10, p[1]~p[1])) (aa.byPair()); > where p means pair; should be correct, should'nt it? If you use a lambda template you need braces and the return statement: auto r = map!((p){ return tuple(p[0]*10, p[1]~p[1]); })(aa.byPair()); > I think for a newcomer the most difficult part is related to tuples: > * find them (in std.typecons!!!) > * catch after much time, pains, research, they should not even try to > construct a tuple using Tuple!, but using the convenience tuple() func > instead. I agree that like dynamic arrays, tuples are better as built-ins, in D too. Another very useful thing is tuple unpacking syntax: http://d.puremagic.com/issues/show_bug.cgi?id=4579 > And also that map expects a range, which an AA is not according to my > trials (code rejected at link time until I used byKey). Or am I wrong? You aren't wrong. > PS: sh*t, I cannot have this work, what's wrong? > > auto pairs = map! > ((int i) {return tuple(10*i, aa[i]~aa[i]);}) > (aa.byKey()); Look at the answers by Simen kjaeraas in this thread, he has explained the situation. Bye, bearophile
Re: Another task
On 01/20/2011 11:12 AM, bearophile wrote: > And I suggest to add a third associative array member function that returns a range of key,value tuples, as in Python3. This allows to solve the task like this: > auto r = map!q{ tuple(a[0]*10, a[1]~a[1]) }(aa.byPair()); Yes, this is the only nice looking, high-level, and D-style solution. While I by far prefer avoiding stringcode: auto r = map!((p) (tuple(p[0]*10, p[1]~p[1])) (aa.byPair()); where p means pair; should be correct, should'nt it? I think for a newcomer the most difficult part is related to tuples: * find them (in std.typecons!!!) * catch after much time, pains, research, they should not even try to construct a tuple using Tuple!, but using the convenience tuple() func instead. And also that map expects a range, which an AA is not according to my trials (code rejected at link time until I used byKey). Or am I wrong? PS: sh*t, I cannot have this work, what's wrong? auto pairs = map! ((int i) {return tuple(10*i, aa[i]~aa[i]);}) (aa.byKey()); Denis _ vita es estrany spir.wikidot.com
Re: Another task
Simen kjaeraas: > byKey is essentially an opApply. You have to wrap it in a fiber to make it > work with the range interface: Thank you for all your code and work. I have found a bug (it's not a bug of yours): if I compile your code with -release, DMD prints: test.d(45): Error: function D main is a nested function and cannot be accessed from array test.d(45): Error: function D main is a nested function and cannot be accessed from array Where the line 45 is the one that starts with: auto o = map!(... I use D associative arrays often (it comes from my Python practice), I suggest to modify AAs to change byKey() and byValue() into ranges usable with std.algorithm. AAs may become iterable with zero method calls too (this is equivalent to byKey or byValue): map!q{a*10}([1:2, 3:4]) And I suggest to add a third associative array member function that returns a range of key,value tuples, as in Python3. This allows to solve the task like this: auto r = map!q{ tuple(a[0]*10, a[1]~a[1]) }(aa.byPair()); Bye, bearophile
Re: Another task
bearophile wrote: D AAs have byKey and byValue that return a lazy iterator. So if we add a "byItem" or "byPair" or "byKeyValue" you are able to read pairs lazily :-) byKey is essentially an opApply. You have to wrap it in a fiber to make it work with the range interface: import std.algorithm; import std.range; import std.stdio; import std.typecons; import core.thread; class opApplyRange( T ) { alias int delegate( int delegate( ref T ) ) dgType; Fiber fib; T value; dgType dg; void fibFun( ) { dg( ( ref T t ){ value = t; Fiber.yield(); return 0; } ); } this( dgType _dg ) { dg = _dg; fib = new Fiber( &fibFun ); popFront( ); } @property T front( ) { return value; } @property bool empty() { return fib.state == Fiber.State.TERM; } void popFront( ) { if ( !empty ) { fib.call( ); } } } opApplyRange!T toRange( T )( int delegate( int delegate( ref T ) ) dg ) { return new opApplyRange!T( dg ); } void main( ) { auto aa = [1:"a", 2:"b", 3:"c"]; auto o = map!((a){return tuple(a*10,aa[a]~aa[a]);})( toRange( aa.byKey() ) ); writeln(typeof(o).stringof); writeln(array(o)); } Ugly, but it works. -- Simen
Re: Another task
Simen kjaeraas: > Soz, I read a bit too fast. It /is/ lazy, though perhaps not the way > you meant. This returns the right thing, but does not *read* lazily > from the AA, a task I am unsure how, if at all possible, one should > perform. In the task was written: > If possible read things lazily from the associative array. D AAs have byKey and byValue that return a lazy iterator. So if we add a "byItem" or "byPair" or "byKeyValue" you are able to read pairs lazily :-) > import std.algorithm; > import std.range; > > void main( ) { > auto aa = [1:"a", 2:"b", 3:"c"]; > auto result = map!"tuple(a[0]*10,a[1]~a[1])"( zip( aa.keys, aa.values > ) ); > } This is a nice solution I didn't think about, thank you :-) It doesn't read data lazily from the AA as requested, but it's not bad looking. Bye and thank you, bearophile
Re: Another task
On Thu, 20 Jan 2011 02:44:39 +0100, bearophile wrote: That result is not the requested one: [(10,"aa"), (30,"bb"), (50,"cc")] Sorry, the last tuple is (30,"cc"). And the second is (20,"bb"), I hope. :p -- Simen
Re: Another task
On Thu, 20 Jan 2011 02:40:29 +0100, bearophile wrote: Simen kjaeraas: Why use map()? The correct solution for this looks like so: import std.range; void main( ) { auto aa = [1:"a", 2:"b", 3:"c"]; auto result = zip( aa.keys, aa.values ); } That result is not the requested one: [(10,"aa"), (30,"bb"), (50,"cc")] And that result is not generated by lazily as the task asks (keys and values return true arrays). Soz, I read a bit too fast. It /is/ lazy, though perhaps not the way you meant. This returns the right thing, but does not *read* lazily from the AA, a task I am unsure how, if at all possible, one should perform. import std.algorithm; import std.range; void main( ) { auto aa = [1:"a", 2:"b", 3:"c"]; auto result = map!"tuple(a[0]*10,a[1]~a[1])"( zip( aa.keys, aa.values ) ); } -- Simen
Re: Another task
> That result is not the requested one: > [(10,"aa"), (30,"bb"), (50,"cc")] Sorry, the last tuple is (30,"cc"). Bye, bearophile
Re: Another task
Simen kjaeraas: > Why use map()? The correct solution for this looks like so: > > > import std.range; > > void main( ) { > auto aa = [1:"a", 2:"b", 3:"c"]; > auto result = zip( aa.keys, aa.values ); > } That result is not the requested one: [(10,"aa"), (30,"bb"), (50,"cc")] And that result is not generated by lazily as the task asks (keys and values return true arrays). Bye, bearophile
Re: Another task
bearophile wrote: Now and then I like to test Phobos with simple tasks, to see how it's going. This simple task is to create a dynamic array of pairs (tuples) like: [(10,"aa"), (30,"bb"), (50,"cc")] from the associative array: [1:'a', 2:'b', 3:'c'] If possible read things lazily from the associative array. - Idiomatic Python2 solution (iteritems is lazy): d = {1:'a', 2:'b', 3:'c'} [(k*10, v*2) for k,v in d.iteritems()] [(10, 'aa'), (20, 'bb'), (30, 'cc')] - D2 lazy solution without map(): import std.stdio, std.typecons; void main() { auto aa = [1:'a', 2:'b', 3:'c']; Tuple!(int, string)[] r; foreach (k, v; aa) r ~= tuple(k*10, ""~v~v); writeln(r); } - Alternative D2 lazy solution without append and map(): import std.stdio, std.typecons; void main() { auto aa = [1:"a", 2:"b", 3:"c"]; auto r = new Tuple!(int, string)[aa.length]; int count = 0; foreach (k, v; aa) r[count++] = tuple(k*10, v~v); writeln(r); } - Now to test Phobos a little, is it easy to write a D2 lazy version that uses map()? Are you able to write it? How many tries needs a D2 programmer with about a month of D2 programming experience to write a correct version that uses map()? Why use map()? The correct solution for this looks like so: import std.range; void main( ) { auto aa = [1:"a", 2:"b", 3:"c"]; auto result = zip( aa.keys, aa.values ); } -- Simen
Another task
Now and then I like to test Phobos with simple tasks, to see how it's going. This simple task is to create a dynamic array of pairs (tuples) like: [(10,"aa"), (30,"bb"), (50,"cc")] from the associative array: [1:'a', 2:'b', 3:'c'] If possible read things lazily from the associative array. - Idiomatic Python2 solution (iteritems is lazy): >>> d = {1:'a', 2:'b', 3:'c'} >>> [(k*10, v*2) for k,v in d.iteritems()] [(10, 'aa'), (20, 'bb'), (30, 'cc')] - D2 lazy solution without map(): import std.stdio, std.typecons; void main() { auto aa = [1:'a', 2:'b', 3:'c']; Tuple!(int, string)[] r; foreach (k, v; aa) r ~= tuple(k*10, ""~v~v); writeln(r); } - Alternative D2 lazy solution without append and map(): import std.stdio, std.typecons; void main() { auto aa = [1:"a", 2:"b", 3:"c"]; auto r = new Tuple!(int, string)[aa.length]; int count = 0; foreach (k, v; aa) r[count++] = tuple(k*10, v~v); writeln(r); } - Now to test Phobos a little, is it easy to write a D2 lazy version that uses map()? Are you able to write it? How many tries needs a D2 programmer with about a month of D2 programming experience to write a correct version that uses map()? Bye, bearophile