View mode: basic / threaded / horizontal-split · Log in · Help
January 02, 2011
property-like data members
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)?
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 *).
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).

[Note: I do not mean at all the current imput-range model is overkill or anything similar. It is certainly more general as is, and I do not have enough 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 ☣

spir.wikidot.com
January 02, 2011
Re: property-like data members
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
January 03, 2011
Re: property-like data members
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)
January 03, 2011
Re: property-like data members
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  
> > 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)

Thank you, Robert for the pointer. Actually, I know this principle a bit; but 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 & type coincidence are intended.)

Genis
-- -- -- -- -- -- --
vit esse estrany ☣

spir.wikidot.com
January 03, 2011
Re: property-like data members
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
January 03, 2011
Re: property-like data members
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).

Denis
-- -- -- -- -- -- --
vit esse estrany ☣

spir.wikidot.com
January 03, 2011
Re: property-like data members
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
January 03, 2011
Re: property-like data members
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:
> 
> > 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

All right. great that we can do that (provide a plain data member where a property is expected).

denis
-- -- -- -- -- -- --
vit esse estrany ☣

spir.wikidot.com
Top | Discussion index | About this forum | D home