Thread overview
property-like data members
Jan 02, 2011
spir
Jan 02, 2011
Ali Çehreli
Jan 03, 2011
Robert Jacques
Jan 03, 2011
spir
Jan 03, 2011
spir
Jan 03, 2011
spir
January 02, 2011
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
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
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
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
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
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
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
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