www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - not an lvalue

reply "Steven Schveighoffer" <schveiguy yahoo.com> writes:
OK,

So I'm just finishing up porting dcollections into D2, and I came across  
this sucky problem:

     range opSlice(cursor b, cursor e)
     {
         // for hashmap, we only support ranges that begin on the first  
cursor,
         // or end on the last cursor.
         if((b == begin && belongs(e)) || (e == end && belongs(b)))
         {
             range result;
             result._begin = b.position;
             result._end = e.position;
             return result;
         }
         throw new RangeError("invalid slice parameters to " ~  
HashMap.stringof);
     }



line 500 is the if statement


dcollections/HashMap.d(500): Error: function  
dcollections.HashMap.HashMap!(uint,uint).HashMap.cursor.opEquals (ref  
const(cursor) it) const is not callable using argument types (cursor)
dcollections/HashMap.d(500): Error: this.begin() is not an lvalue
dcollections/HashMap.d(500): Error: function  
dcollections.HashMap.HashMap!(uint,uint).HashMap.cursor.opEquals (ref  
const(cursor) it) const is not callable using argument types (cursor)
dcollections/HashMap.d(500): Error: this.end() is not an lvalue

I originally made cursor.opEquals have this signature:

bool opEquals(cursor it) const

But the compiler complained it *must* have signature:

bool opEquals(const ref(cursor) it) const

It didn't even allow me this:

bool opEquals(const cursor it) const

So here is my dilemma.  I either do something like this, which I think is  
completely unnecessary and detracts from the beauty of the code:

     range opSlice(cursor b, cursor e)
     {
         // for hashmap, we only support ranges that begin on the first  
cursor,
         // or end on the last cursor.
         auto tmpb = begin;  // CRAP!
         auto tmpe = end;    // CRAP!
         if((b == tmpb && belongs(e)) || (e == tmpe && belongs(b)))
         {
             range result;
             result._begin = b.position;
             result._end = e.position;
             return result;
         }
         throw new RangeError("invalid slice parameters to " ~  
HashMap.stringof);
     }

Or I bitch and complain here until Walter changes his mind :)

So I'm going with option B.  Something's gotta give here, making me use  
ref, and then forcing me to declare superfluous temporaries is total BS.

---------

Here's a general test case that I can envision any custom value type that  
defines addition and equality being susceptible to:

if(a + b == c + d)

If that doesn't work, then the lvalue rules have to change, or D will have  
a huge wart.

-Steve
Apr 23 2010
parent SHOO <zan77137 nifty.com> writes:
Steven Schveighoffer さんは書きました:
 OK,
 
 So I'm just finishing up porting dcollections into D2, and I came across 
 this sucky problem:
 
     range opSlice(cursor b, cursor e)
     {
         // for hashmap, we only support ranges that begin on the first 
 cursor,
         // or end on the last cursor.
         if((b == begin && belongs(e)) || (e == end && belongs(b)))
         {
             range result;
             result._begin = b.position;
             result._end = e.position;
             return result;
         }
         throw new RangeError("invalid slice parameters to " ~ 
 HashMap.stringof);
     }
 
 
 
 line 500 is the if statement
 
 
 dcollections/HashMap.d(500): Error: function 
 dcollections.HashMap.HashMap!(uint,uint).HashMap.cursor.opEquals (ref 
 const(cursor) it) const is not callable using argument types (cursor)
 dcollections/HashMap.d(500): Error: this.begin() is not an lvalue
 dcollections/HashMap.d(500): Error: function 
 dcollections.HashMap.HashMap!(uint,uint).HashMap.cursor.opEquals (ref 
 const(cursor) it) const is not callable using argument types (cursor)
 dcollections/HashMap.d(500): Error: this.end() is not an lvalue
 
 I originally made cursor.opEquals have this signature:
 
 bool opEquals(cursor it) const
 
 But the compiler complained it *must* have signature:
 
 bool opEquals(const ref(cursor) it) const
 
 It didn't even allow me this:
 
 bool opEquals(const cursor it) const
 
 So here is my dilemma.  I either do something like this, which I think 
 is completely unnecessary and detracts from the beauty of the code:
 
     range opSlice(cursor b, cursor e)
     {
         // for hashmap, we only support ranges that begin on the first 
 cursor,
         // or end on the last cursor.
         auto tmpb = begin;  // CRAP!
         auto tmpe = end;    // CRAP!
         if((b == tmpb && belongs(e)) || (e == tmpe && belongs(b)))
         {
             range result;
             result._begin = b.position;
             result._end = e.position;
             return result;
         }
         throw new RangeError("invalid slice parameters to " ~ 
 HashMap.stringof);
     }
 
 Or I bitch and complain here until Walter changes his mind :)
 
 So I'm going with option B.  Something's gotta give here, making me use 
 ref, and then forcing me to declare superfluous temporaries is total BS.
 
 ---------
 
 Here's a general test case that I can envision any custom value type 
 that defines addition and equality being susceptible to:
 
 if(a + b == c + d)
 
 If that doesn't work, then the lvalue rules have to change, or D will 
 have a huge wart.
 
 -Steve
I completely agree to this opinion. "auto ref" may become the workaround, but by this method, we must mark it "auto ref" for all functions that return struct. It is stupid.
Apr 23 2010