Re: Another task

2011-01-20 Thread Simen kjaeraas

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

2011-01-20 Thread bearophile
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

2011-01-20 Thread spir

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

2011-01-20 Thread bearophile
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

2011-01-19 Thread Simen kjaeraas

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

2011-01-19 Thread bearophile
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

2011-01-19 Thread Simen kjaeraas
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

2011-01-19 Thread Simen kjaeraas
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

2011-01-19 Thread bearophile
> 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

2011-01-19 Thread bearophile
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

2011-01-19 Thread Simen kjaeraas

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

2011-01-19 Thread bearophile
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