www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - property-like data members

reply spir <denis.spir gmail.com> writes:
Hello,

Using properties allows travesting a method call into direct data access. W=
hat if the underlying member actually is plain data? Would it be possible t=
o provide a real data member where the language expects a property (for ins=
tance as range empty & front properties)?
Is there any difficulty for the compiler to check whether a data member of =
the same name and correct type exists? To help it, we could mark said data =
member with an  property hint. For instance:

struct String {
    char[] cs;
    private uint index =3D 0;     // for traversal
     property char front;
     property bool empty;
    this (string characters) {
        this.cs =3D characters.dup;
        this.empty =3D (this.cs.length =3D=3D 0);
        if (this.cs.length > 0)
            this.front =3D this.cs[0];
    }
     property void popFront () {
        ++ this.index;
        this.empty =3D (this.index >=3D this.cs.length);
        if (this.index < this.cs.length)
            this.front =3D this.cs[this.index];
    }
}
unittest {
    auto s =3D String("abc");
    // works fine
    while (! s.empty) {
        auto c =3D s.front;
        write(c,' ');
        s.popFront;
    }
    writeln();
    // works not
//~     foreach (char c ; s) write(c,' ');
     writeln();
}

Here, popFront does not only advance, it correctly sets empty and front, so=
 that a single method is needed. But the language expects a method-property=
 (actually, it complains for missing opApply *).
I'm a bit troubled to implement methods where plain data does the job and c=
onceptually better matches my model (maybe it's only me: I wish the code to=
 mirror my views).

[Note: I do not mean at all the current imput-range model is overkill or an=
ything similar. It is certainly more general as is, and I do not have enoug=
h various use cases to give any opinion on that! The given example is just =
that: an example.]

Denis

(*) Would be good to update the error message:
	Error: no property 'opApply' for type 'String'
	Error: opApply() function for String must return an int
-->
	Error: type String does not provide any iteration method.
-- -- -- -- -- -- --
vit esse estrany =E2=98=A3

spir.wikidot.com
Jan 02 2011
next sibling parent =?UTF-8?B?QWxpIMOHZWhyZWxp?= <acehreli yahoo.com> writes:
spir wrote:
 Using properties allows travesting a method call into direct data 
access. What if the underlying member actually is plain data? Would it be possible to provide a real data member where the language expects a property (for instance as range empty & front properties)? There has been a lot of discussions on properties and their syntax. There is a complexity in your proposal: should we allow write access to property members? We would need to come up with a way to limit write access.
 Is there any difficulty for the compiler to check whether a data 
member of the same name and correct type exists? To help it, we could mark said data member with an property hint. For instance:
 struct String {
     char[] cs;
     private uint index = 0;     // for traversal
      property char front;
      property bool empty;
     this (string characters) {
         this.cs = characters.dup;
         this.empty = (this.cs.length == 0);
         if (this.cs.length > 0)
             this.front = this.cs[0];
     }
      property void popFront () {
         ++ this.index;
         this.empty = (this.index >= this.cs.length);
         if (this.index < this.cs.length)
             this.front = this.cs[this.index];
     }
 }
 unittest {
     auto s = String("abc");
     // works fine
     while (! s.empty) {
         auto c = s.front;
         write(c,' ');
         s.popFront;
     }
     writeln();
     // works not
 //~     foreach (char c ; s) write(c,' ');
      writeln();
 }

 Here, popFront does not only advance, it correctly sets empty and 
front, so that a single method is needed. But the language expects a method-property (actually, it complains for missing opApply *). Phobos is happy with 'empty' being a static member. The following member would make an infinite range: static enum bool empty = false; But I know that you don't want that. :) The actual problem in your example is the missing front() function.
 I'm a bit troubled to implement methods where plain data does the job 
and conceptually better matches my model (maybe it's only me: I wish the code to mirror my views). Having never used a language that had properties, I am very happy how D handles them. Having to write a one-liner doesn't bother me. Ali
Jan 02 2011
prev sibling next sibling parent reply "Robert Jacques" <sandford jhu.edu> writes:
On Sun, 02 Jan 2011 05:29:48 -0500, spir <denis.spir gmail.com> wrote:
 Hello,

 Using properties allows travesting a method call into direct data  
 access. What if the underlying member actually is plain data? Would it  
 be possible to provide a real data member where the language expects a  
 property (for instance as range empty & front properties)?
Yes, see the Uniform access principle (http://en.wikipedia.org/wiki/Uniform_access_principle). (Though UAP hasn't been discussed much on the newsgroup)
Jan 02 2011
parent spir <denis.spir gmail.com> writes:
On Mon, 03 Jan 2011 00:55:47 -0500
"Robert Jacques" <sandford jhu.edu> wrote:

 On Sun, 02 Jan 2011 05:29:48 -0500, spir <denis.spir gmail.com> wrote:
 Hello,

 Using properties allows travesting a method call into direct data =20
 access. What if the underlying member actually is plain data? Would it =
=20
 be possible to provide a real data member where the language expects a =
=20
 property (for instance as range empty & front properties)?
=20 Yes, see the Uniform access principle =20 (http://en.wikipedia.org/wiki/Uniform_access_principle). (Though UAP =20 hasn't been discussed much on the newsgroup)
Thank you, Robert for the pointer. Actually, I know this principle a bit; b= ut would it be hard to implement it for d: * maybe for properties only, * if the data member is marked as (pseudo)property ? (The latter condition to give a hint to the compiler that member name & typ= e coincidence are intended.) Genis -- -- -- -- -- -- -- vit esse estrany =E2=98=A3 spir.wikidot.com
Jan 03 2011
prev sibling parent reply "Steven Schveighoffer" <schveiguy yahoo.com> writes:
On Sun, 02 Jan 2011 05:29:48 -0500, spir <denis.spir gmail.com> wrote:

 Hello,

 Using properties allows travesting a method call into direct data  
 access. What if the underlying member actually is plain data? Would it  
 be possible to provide a real data member where the language expects a  
 property (for instance as range empty & front properties)?
Yes, just use a data member: struct MyRange { int front; bool empty; void popFront(); } A property is actually supposed to work just like a field. There is no need for new syntax. -Steve
Jan 03 2011
parent reply spir <denis.spir gmail.com> writes:
On Mon, 03 Jan 2011 08:34:42 -0500
"Steven Schveighoffer" <schveiguy yahoo.com> wrote:

 Yes, just use a data member:
=20
 struct MyRange {
     int front;
     bool empty;
     void popFront();
 }
=20
 A property is actually supposed to work just like a field.
=20
 There is no need for new syntax.
Hum, does not work by me (else I would not have posted ;-) The compiler rejects the code complaining for missing opApply (which I inte= rpret as meaning it does not recognize a range in such an interface). indee= d, it works if manually implement iteration like for instance: while (! coll.empty) { auto element =3D coll.front; use(element); coll.popFront(); } But then there no property in play (I mean the compiler does not expect a p= roperty set implementing a range). Denis -- -- -- -- -- -- -- vit esse estrany =E2=98=A3 spir.wikidot.com
Jan 03 2011
parent reply "Steven Schveighoffer" <schveiguy yahoo.com> writes:
On Mon, 03 Jan 2011 09:56:30 -0500, spir <denis.spir gmail.com> wrote:

 On Mon, 03 Jan 2011 08:34:42 -0500
 "Steven Schveighoffer" <schveiguy yahoo.com> wrote:

 Yes, just use a data member:

 struct MyRange {
     int front;
     bool empty;
     void popFront();
 }

 A property is actually supposed to work just like a field.

 There is no need for new syntax.
Hum, does not work by me (else I would not have posted ;-) The compiler rejects the code complaining for missing opApply (which I interpret as meaning it does not recognize a range in such an interface). indeed, it works if manually implement iteration like for instance: while (! coll.empty) { auto element = coll.front; use(element); coll.popFront(); } But then there no property in play (I mean the compiler does not expect a property set implementing a range).
That's a bug. isInputRange!S returns true. There's nothing in the spec that says foreach requires those elements to be functions. In fact, empty *does* work as a normal field, i.e. this struct is foreachable: struct S { property int front() {return 0;} bool empty; void popFront() {empty = true;} } Filed: http://d.puremagic.com/issues/show_bug.cgi?id=5403 -Steve
Jan 03 2011
parent spir <denis.spir gmail.com> writes:
On Mon, 03 Jan 2011 10:27:17 -0500
"Steven Schveighoffer" <schveiguy yahoo.com> wrote:

 On Mon, 03 Jan 2011 09:56:30 -0500, spir <denis.spir gmail.com> wrote:
=20
 On Mon, 03 Jan 2011 08:34:42 -0500
 "Steven Schveighoffer" <schveiguy yahoo.com> wrote:

 Yes, just use a data member:

 struct MyRange {
     int front;
     bool empty;
     void popFront();
 }

 A property is actually supposed to work just like a field.

 There is no need for new syntax.
Hum, does not work by me (else I would not have posted ;-) The compiler rejects the code complaining for missing opApply (which I =
=20
 interpret as meaning it does not recognize a range in such an =20
 interface). indeed, it works if manually implement iteration like for =
=20
 instance:
 	while (! coll.empty) {
 	    auto element =3D coll.front;
 	    use(element);
 	    coll.popFront();
 	}
 But then there no property in play (I mean the compiler does not expect=
=20
 a property set implementing a range).
=20 That's a bug. isInputRange!S returns true. =20 There's nothing in the spec that says foreach requires those elements to =
=20
 be functions.  In fact, empty *does* work as a normal field, i.e. this =20
 struct is foreachable:
=20
 struct S
 {
      property int front() {return 0;}
     bool empty;
     void popFront() {empty =3D true;}
 }
=20
 Filed:
=20
 http://d.puremagic.com/issues/show_bug.cgi?id=3D5403
=20
 -Steve
All right. great that we can do that (provide a plain data member where a p= roperty is expected). denis -- -- -- -- -- -- -- vit esse estrany =E2=98=A3 spir.wikidot.com
Jan 03 2011