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

Top | Discussion index | About this forum | D home