Re: writing iterators without code duplication. inout?

2012-01-07 Thread Steven Schveighoffer

On Wed, 21 Dec 2011 11:34:18 -0500, pompei2 pomp...@gmail.com wrote:


On Wednesday, 21 December 2011 at 16:05:24 UTC, Trass3r wrote:

Can't really answer your original question, but
1. Why don't you use opApply?
2. Why do you use ref int even in the const version?
3. You could also use alias this to allow iteration, don't know if  
that's what you want in general though.


13: Because there are different things in my class to iterate over.  
Think foreach(p ; obj.properties()) and foreach(c ; obj.components()).  
(I know, I can make those @property so I don't need the ().)


2. Because if not, it says: Error: cannot implicitly convert expression  
(__foreachbody1315) of type int delegate(ref int) to int delegate(int)


Two of my most wished for bugs:

http://d.puremagic.com/issues/show_bug.cgi?id=2443
http://d.puremagic.com/issues/show_bug.cgi?id=2498

Looks like 2443 has been fixed in head!

-Steve


Re: writing iterators without code duplication. inout?

2012-01-07 Thread Steven Schveighoffer

On Wed, 21 Dec 2011 10:54:06 -0500, pompei2 pomp...@gmail.com wrote:


Hello.

I want to add the option to iterate objects of my class using foreach. I  
need them to be iterable as view-only const and as mutable too. I would  
prefer to iterate using the return a delegate but if that's not  
possible, ranges are fine too. Also, I'd prefer a template-less solution  
over a templated one.



This is what I have, which works but has severe code duplication. I  
hoped inout would help me here, but I just can't figure it out. I also  
gave a try to ranges, but same thing again: I can only get it to work if  
I define my things twice.


inout cannot be used here, because inout is const within an inout  
function.  This means you cannot modify data while in the context of the  
function, and the foreach delegate is called within the context of the  
function.


Having dealt with foreach in my container lib, I can tell you, it's not  
ideal.  I'm hoping to have some way to do tail-const ranges in the future,  
which should help with code duplication.


-Steve


writing iterators without code duplication. inout?

2011-12-21 Thread pompei2

Hello.

I want to add the option to iterate objects of my class using 
foreach. I need them to be iterable as view-only const and as 
mutable too. I would prefer to iterate using the return a 
delegate but if that's not possible, ranges are fine too. Also, 
I'd prefer a template-less solution over a templated one.



This is what I have, which works but has severe code duplication. 
I hoped inout would help me here, but I just can't figure it out. 
I also gave a try to ranges, but same thing again: I can only get 
it to work if I define my things twice.


(syntax highlight for the coming month: 
http://pastebin.com/TNmWWgsj)



   import std.conv, std.stdio;

   class Container
   {
   this(int from, int to)
   {
   while(from = to) {
   _arr ~= from;
   from++;
   }
   }

   // FIXME: severe code duplication for const/nonconst/ref
   //and I'm not even trying immutable yet
   int delegate(int delegate(ref int)) doIter()
   {
   writeln(calling non-const);

   int doTheIter(int delegate(ref int) dg)
   {
   int result = 0;
   foreach(ref i ; this._arr) {
   result = dg(i);
   if(result)
   break;
   }
   return result;
   }

   return doTheIter;
   }

   int delegate(int delegate(ref int)) doIter() const
   {
   writeln(calling const);

   int doTheIter(int delegate(ref int) dg)
   {
   int result = 0;
   foreach(i ; this._arr) {
   result = dg(i);
   if(result)
   break;
   }
   return result;
   }

   return doTheIter;
   }

   int[] _arr;
   }

   int main(string[] args)
   {
   Container c = new Container(1, 9);
   const Container cc = c;

   foreach(ref e ; c.doIter()) {
   writeln(e);
   e++;
   }

   foreach(e ; cc.doIter()) {
   writeln(e);
   }

   return 0;
   }



Re: writing iterators without code duplication. inout?

2011-12-21 Thread Trass3r

Can't really answer your original question, but
1. Why don't you use opApply?
2. Why do you use ref int even in the const version?
3. You could also use alias this to allow iteration, don't know if that's  
what you want in general though.


Re: writing iterators without code duplication. inout?

2011-12-21 Thread Timon Gehr

On 12/21/2011 04:54 PM, pompei2 wrote:

Hello.

I want to add the option to iterate objects of my class using foreach. I
need them to be iterable as view-only const and as mutable too. I would
prefer to iterate using the return a delegate but if that's not
possible, ranges are fine too. Also, I'd prefer a template-less solution
over a templated one.


This is what I have, which works but has severe code duplication. I
hoped inout would help me here, but I just can't figure it out. I also
gave a try to ranges, but same thing again: I can only get it to work if
I define my things twice.

(syntax highlight for the coming month: http://pastebin.com/TNmWWgsj)


import std.conv, std.stdio;

class Container
{
this(int from, int to)
{
while(from = to) {
_arr ~= from;
from++;
}
}

// FIXME: severe code duplication for const/nonconst/ref
// and I'm not even trying immutable yet
int delegate(int delegate(ref int)) doIter()
{
writeln(calling non-const);

int doTheIter(int delegate(ref int) dg)
{
int result = 0;
foreach(ref i ; this._arr) {
result = dg(i);
if(result)
break;
}
return result;
}

return doTheIter;
}

int delegate(int delegate(ref int)) doIter() const
{
writeln(calling const);

int doTheIter(int delegate(ref int) dg)
{
int result = 0;
foreach(i ; this._arr) {
result = dg(i);
if(result)
break;
}
return result;
}

return doTheIter;
}

int[] _arr;
}

int main(string[] args)
{
Container c = new Container(1, 9);
const Container cc = c;

foreach(ref e ; c.doIter()) {
writeln(e);
e++;
}

foreach(e ; cc.doIter()) {
writeln(e);
}

return 0;
}



Just remove the non-const overload. const member functions work with 
mutable, immutable and const receivers.


Re: writing iterators without code duplication. inout?

2011-12-21 Thread Jakob Ovrum

On Wednesday, 21 December 2011 at 16:31:01 UTC, Jakob Ovrum wrote:
On Wednesday, 21 December 2011 at 16:07:55 UTC, Timon Gehr 
wrote:
Just remove the non-const overload. const member functions 
work with mutable, immutable and const receivers.


The const version does not allow using 'ref' when iterating.


In light of pompei2's recent reply;

the const version *should not* allow using 'ref' when iterating.


Re: writing iterators without code duplication. inout?

2011-12-21 Thread pompei2

On Wednesday, 21 December 2011 at 16:05:24 UTC, Trass3r wrote:

Can't really answer your original question, but
1. Why don't you use opApply?
2. Why do you use ref int even in the const version?
3. You could also use alias this to allow iteration, don't know 
if that's what you want in general though.


13: Because there are different things in my class to iterate 
over. Think foreach(p ; obj.properties()) and foreach(c ; 
obj.components()). (I know, I can make those @property so I don't 
need the ().)


2. Because if not, it says: Error: cannot implicitly convert 
expression (__foreachbody1315) of type int delegate(ref int) to 
int delegate(int)




Re: writing iterators without code duplication. inout?

2011-12-21 Thread Jakob Ovrum

On Wednesday, 21 December 2011 at 16:07:55 UTC, Timon Gehr wrote:
Just remove the non-const overload. const member functions work 
with mutable, immutable and const receivers.


The const version does not allow using 'ref' when iterating.


Re: writing iterators without code duplication. inout?

2011-12-21 Thread Christophe
pompei2 , dans le message (digitalmars.D.learn:31164), a écrit :
 This is what I have, which works but has severe code duplication. 
 I hoped inout would help me here, but I just can't figure it out. 
 I also gave a try to ranges, but same thing again: I can only get 
 it to work if I define my things twice.


It's not optimal, and there is an ugly cast, but maybe this is a 
suitable workarrond for you :

  int delegate(int delegate(ref int)) doIter() const
{
  return (int delegate(ref int) dg)
{
  cast(typeof(this))(this).doIter()((ref int i) { int copy = i; 
dg(copy); });
}   
}


Until
  int delegate(ref inout int) opApply() inout;
and
  int delegate(int delegate(ref inout int)) doIter() inout;
are made to work. (I actually don't know if there is any obstacles to do 
this).