www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - Using unary expressions with property functions

reply Andrej Mitrovic <none none.com> writes:


class LibraryItem
{
    private int _numCopies;

    // Property
    public int NumCopies
    {
        get { return _numCopies; }
        set { _numCopies = value; }
    }
    
    public void BorrowItem(string name)
    {
        NumCopies--;
    }  
}

Apparently you can use the -- and ++ unary ops on property functions, which
might be convenient, I guess. But this won't work in D:

class LibraryItem
{
    private int _numCopies;

     property
    int NumCopies()
    {
        return _numCopies;
    }
    
     property
    void NumCopies(int value)
    {
        _numCopies = value;
    }
    
    public void BorrowItem(string name)
    {
        NumCopies--;
    }
}

void main()
{
}

I get this back: Error: this.NumCopies() is not an lvalue

So D tries to call the getter method "int NumCopies()" and apply -- on it. One
way around this is to make the getter method return by reference:

import std.stdio;

class LibraryItem
{
    private int _numCopies;

     property
    ref int NumCopies()
    {
        return _numCopies;
    }
    
     property
    void NumCopies(int value)
    {
        _numCopies = value;
    }
    
    public void BorrowItem(string name)
    {
        NumCopies--;
        writeln(NumCopies);     // writes -1 after the call
    }
}

void main()
{
    auto lib = new LibraryItem();
    lib.BorrowItem("TDPL");
}

So this works. But now the getter method acts both as a getter and a setter,
which contradicts the idea of having separate get/set methods, don't you agree?


for the -- op like in the last D example, or does it rewrite the whole
operation as "NumCopies(-1)"? Maybe we can have a functionality like that in D
without having to change the getter method to return a reference.. What do you
think?
Dec 13 2010
parent reply Jonathan M Davis <jmdavisProg gmx.com> writes:
On Monday, December 13, 2010 11:10:55 Andrej Mitrovic wrote:

 
 class LibraryItem
 {
     private int _numCopies;
 
     // Property
     public int NumCopies
     {
         get { return _numCopies; }
         set { _numCopies = value; }
     }
 
     public void BorrowItem(string name)
     {
         NumCopies--;
     }
 }
 
 Apparently you can use the -- and ++ unary ops on property functions, which
 might be convenient, I guess. But this won't work in D:
 
 class LibraryItem
 {
     private int _numCopies;
 
      property
     int NumCopies()
     {
         return _numCopies;
     }
 
      property
     void NumCopies(int value)
     {
         _numCopies = value;
     }
 
     public void BorrowItem(string name)
     {
         NumCopies--;
     }
 }
 
 void main()
 {
 }
 
 I get this back: Error: this.NumCopies() is not an lvalue
 
 So D tries to call the getter method "int NumCopies()" and apply -- on it.
 One way around this is to make the getter method return by reference:
 
 import std.stdio;
 
 class LibraryItem
 {
     private int _numCopies;
 
      property
     ref int NumCopies()
     {
         return _numCopies;
     }
 
      property
     void NumCopies(int value)
     {
         _numCopies = value;
     }
 
     public void BorrowItem(string name)
     {
         NumCopies--;
         writeln(NumCopies);     // writes -1 after the call
     }
 }
 
 void main()
 {
     auto lib = new LibraryItem();
     lib.BorrowItem("TDPL");
 }
 
 So this works. But now the getter method acts both as a getter and a
 setter, which contradicts the idea of having separate get/set methods,
 don't you agree?
 

 reference for the -- op like in the last D example, or does it rewrite the
 whole operation as "NumCopies(-1)"? Maybe we can have a functionality like
 that in D without having to change the getter method to return a
 reference.. What do you think?
I would think that it would be doable if something ++lib.NumCopies were lowered to lib.NumCopies(++lib.NumCopies()). If it were post-increment, it would then probably turn it into something more like this: auto toInc = lib.NumCopies(); auto temp = toInc; lib.NumCopies(++toInc); Of course, given that you could use pre and post-increment in the middle of an expression, that could get quite a bit more complicated, and a simple lowering could be rather difficult, but the basic idea should still hold. I don't see why it couldn't be done other than that figuring out the exact way to lower it in order to deal with the fact that it could be in the middle of an expression could be a bit entertaining. I say open an enhancement request for it. Perhaps someone else can point out why it would be a bad idea, but on the surface, it seems quite doable. - Jonathan M Davis
Dec 13 2010
parent "Robert Jacques" <sandford jhu.edu> writes:
On Mon, 13 Dec 2010 14:29:34 -0500, Jonathan M Davis <jmdavisProg gmx.com>  
wrote:
 On Monday, December 13, 2010 11:10:55 Andrej Mitrovic wrote:

 works:

 class LibraryItem
 {
     private int _numCopies;

     // Property
     public int NumCopies
     {
         get { return _numCopies; }
         set { _numCopies = value; }
     }

     public void BorrowItem(string name)
     {
         NumCopies--;
     }
 }

 Apparently you can use the -- and ++ unary ops on property functions,  
 which
 might be convenient, I guess. But this won't work in D:

 class LibraryItem
 {
     private int _numCopies;

      property
     int NumCopies()
     {
         return _numCopies;
     }

      property
     void NumCopies(int value)
     {
         _numCopies = value;
     }

     public void BorrowItem(string name)
     {
         NumCopies--;
     }
 }

 void main()
 {
 }

 I get this back: Error: this.NumCopies() is not an lvalue

 So D tries to call the getter method "int NumCopies()" and apply -- on  
 it.
 One way around this is to make the getter method return by reference:

 import std.stdio;

 class LibraryItem
 {
     private int _numCopies;

      property
     ref int NumCopies()
     {
         return _numCopies;
     }

      property
     void NumCopies(int value)
     {
         _numCopies = value;
     }

     public void BorrowItem(string name)
     {
         NumCopies--;
         writeln(NumCopies);     // writes -1 after the call
     }
 }

 void main()
 {
     auto lib = new LibraryItem();
     lib.BorrowItem("TDPL");
 }

 So this works. But now the getter method acts both as a getter and a
 setter, which contradicts the idea of having separate get/set methods,
 don't you agree?


 reference for the -- op like in the last D example, or does it rewrite  
 the
 whole operation as "NumCopies(-1)"? Maybe we can have a functionality  
 like
 that in D without having to change the getter method to return a
 reference.. What do you think?
I would think that it would be doable if something ++lib.NumCopies were lowered to lib.NumCopies(++lib.NumCopies()). If it were post-increment, it would then probably turn it into something more like this: auto toInc = lib.NumCopies(); auto temp = toInc; lib.NumCopies(++toInc); Of course, given that you could use pre and post-increment in the middle of an expression, that could get quite a bit more complicated, and a simple lowering could be rather difficult, but the basic idea should still hold. I don't see why it couldn't be done other than that figuring out the exact way to lower it in order to deal with the fact that it could be in the middle of an expression could be a bit entertaining. I say open an enhancement request for it. Perhaps someone else can point out why it would be a bad idea, but on the surface, it seems quite doable. - Jonathan M Davis
I know this concept has been extensively discussed before, i.e. the problem of a.b.c.d = 1, when b, c or d happen to be a method/property.
Dec 14 2010