January 31, 2013
On Thu, 31 Jan 2013 17:54:21 -0500, Steven Schveighoffer <schveiguy@yahoo.com> wrote:


> Also note that structs are not meant to have internal pointers.  So a "property" struct with an internal pointer

Forgot to finish this sentence before I hit send.

So a "property" struct with an internal pointer would have to be modified when a copy of the struct is made.  But this is bad, structs are supposed to be movable WITHOUT updating anything.

-Steve
January 31, 2013
On Thursday, 31 January 2013 at 23:05:14 UTC, Steven Schveighoffer wrote:
> On Thu, 31 Jan 2013 17:54:21 -0500, Steven Schveighoffer <schveiguy@yahoo.com> wrote:
>
>
>> Also note that structs are not meant to have internal pointers.  So a "property" struct with an internal pointer
>
> Forgot to finish this sentence before I hit send.
>
> So a "property" struct with an internal pointer would have to be modified when a copy of the struct is made.  But this is bad, structs are supposed to be movable WITHOUT updating anything.

 Except when postblit is defined...? Or opAssign?
January 31, 2013
On Thu, 31 Jan 2013 18:48:18 -0500, Era Scarecrow <rtcvb32@yahoo.com> wrote:

> On Thursday, 31 January 2013 at 23:05:14 UTC, Steven Schveighoffer wrote:
>> On Thu, 31 Jan 2013 17:54:21 -0500, Steven Schveighoffer <schveiguy@yahoo.com> wrote:
>>
>>
>>> Also note that structs are not meant to have internal pointers.  So a "property" struct with an internal pointer
>>
>> Forgot to finish this sentence before I hit send.
>>
>> So a "property" struct with an internal pointer would have to be modified when a copy of the struct is made.  But this is bad, structs are supposed to be movable WITHOUT updating anything.
>
>   Except when postblit is defined...? Or opAssign?

I'm pretty sure structs are forbidden to have internal pointers.  They must be able to be moved without any post-processing.

-Steve
February 01, 2013
On Thursday, 31 January 2013 at 01:26:19 UTC, Steven Schveighoffer wrote:
> On Tue, 29 Jan 2013 23:57:14 -0500, Jesse Phillips <Jessekphillips+d@gmail.com> wrote:
>
>> Sorry I have to oppose this. It is in no way a compromise as it is completely different from everything suggested. I'm going to take this opportunity to highjack your thread.
>
> You are welcome to it!  I don't know if there is a thread on this newsgroup about properties that hasn't been hijacked.

Thank you.

> I should explain that my reasoning behind this is:
>
> 1. Walter wants to get rid of @property

I can't really speak to what Walter wants, but I think there is more to it than removing a keyword.

> 2. Dispite 4 years of assuming @property will be implemented, the old D1-style crap is still in place.

Yep, I thought its introduction meant things were going to break, and also that other things would work.

> The compromise is: OK, you want to ditch @property?  I can live with that as long as we have some way to designate properties.  How about this?

I don't think that is a compromise as i don't believe it is @property that is slated for removal, it is designating something a property.

>> Can an pro-@property members claim that the current behavior is what you want? I believe this answer is no.
>
> The answer is no, but only because what we asked for was never implemented.  What was ORIGINALLY designed with @property (enforcement of parentheses on functions, enforcement against parentheses on properties) is what we wanted.

Yep, totally thought that was coming. I'd still be ok with it, but I'm still partial to not having it enforced, would rather see field -> property a seamless transition.

>> It seems at least some members for @property feel that currently functions are being annotated with @property that shouldn't be.
>
> This is unavoidable.  It's like saying I feel some functions are incorrectly named.  @property has nothing to do with it.  There is no "right" answer to whether something should be a @property or not, just like there is no "right" name for a function.

Yes, but I was thinking more on the degree of wrongness that is currently acceptable. Something to think on for what my proposal would be. But again, I don't care about the appearance, only behavior.

>> It also seems those for @property aren't fighting optional parens as much? Can we discuss fixing the issues we have with this. I think a good change is to require parens if returning a callable (opposite of Walters suggestion).
>
> Yes, if the choice is between having the previous implementation (D1) and optional parentheses with a way to designate properties, I'll choose the latter.

Walter's suggestion isn't (D1) implementation it address some concerns with the existing behavior, but doesn't give you a way to declare properties.

I think his suggestions need implemented regardless of what we do with @property. I think Walter just felt this would appease the pro-property.

>> If I have my above claims mostly correct, then I'd say @property needs to be put back in the drawing board and re-implemented.
>
> If you want to replace @property, we need a replacement.  @property still serves a purpose, even in it's currently crippled form.

What purpose is that? Isn't it a no-op by default, and barely enforce () with -property?

>> I'd be for removing it from the language and if we decide on what in needs to enforce and should be part of the language, then its implementation is completed in a feature branch and remains out of the language until it meets the needed enforcement and behavior.
>
> Fine, but leave @property in until you have completed the replacement feature.

I'm not sure if we are going to have a complete replacement, but your right, we can leave it in until such a choice is finalized, but let us get rid of -property.

> Ah, your subtle bias shines through ;)

:)

> The real fact of the matter is, if D never had the "hack" properties it did, I actually wouldn't care.  Calling functions instead of setting or getting properties is not that horrible.  But writeln = "hi" is horrible.

Yep, introducing properties would have been easy, because no one would have fallen for the joys of optional parens.

writeln = "hi" would not compile with Walters suggested changes.

> In general, the idea is to implement fields without having to create storage for them.  It will never perform as well as a field.

I know, but you can't trust when reading code that is what happens. And having that convention was being argued for, I like Walter's position of having the compiler make guarantees and not conventions (I'm sure I've got some exception I'd want but can't think of one).

> In other words, go back to D1 properties.  No thanks.

Again, it wouldn't be D1, and we aren't going back because that is what we currently have. We need to fix it.

>
> -Steve

Thanks for the feedback.
February 01, 2013
On Thursday, 31 January 2013 at 23:57:59 UTC, Steven Schveighoffer wrote:
> On Thu, 31 Jan 2013 18:48:18 -0500, Era Scarecrow <rtcvb32@yahoo.com> wrote:
>> On Thursday, 31 January 2013 at 23:05:14 UTC, Steven Schveighoffer wrote:
>>>
>>>
>>> Also note that structs are not meant to have internal pointers.  So a "property" struct with an internal pointer
>>>
>>> So a "property" struct with an internal pointer would have to be modified when a copy of the struct is made.  But this is bad, structs are supposed to be movable WITHOUT updating anything.
>>
>>  Except when postblit is defined...? Or opAssign?
>
> I'm pretty sure structs are forbidden to have internal pointers.  They must be able to be moved without any post-processing.

 Hmmm... Well I threw out an idea about not returning inner structs (outside the controlling parent). If that were followed, the reference to the parent could silently be added to the function call rather than the struct itself; Then the data can be moved freely.

February 01, 2013
On 1/31/13 7:01 PM, Jesse Phillips wrote:
> I don't think that is a compromise as i don't believe it is @property
> that is slated for removal, it is designating something a property.

FWIW we want to keep a means to define properties.

Andrei

February 01, 2013
On Thursday, 31 January 2013 at 22:54:21 UTC, Steven Schveighoffer wrote:
> C# has properties like this:
>
> property int foo {
>   get {return _foo;}
>   set {_foo = value;}
> }
>
> Your proposal looks like this:
>
> foo struct {
>    int opGet() {return _foo;}
>    void opSet(int value) {_foo = value;}
> }
>
> What I see is that the getter and setter are assigned specific contextual keywords (opGet vs. get, and opSet vs. set). It seems like a very similar (albeit more verbose) solution.
>
> What I had originally suggested for properties is this:
>
> property int foo {
>    int get() {return _foo;} // only one getter allowed
>    void set(int v) {_foo = v;}
>    void set(float v) {_foo = (int)v;} // more than one setter allowed
> }
>
> I think these are all along the same line of solutions.  I don't think they are bad, but clearly they weren't used 4 years ago, so it may be difficult to convince Walter to use them now.
>
>> My opGet is just another opXXX definable for all structs, not just properties.
>
> I didn't see that, but I also don't really see the point of that.  What value does opGet have unless it's a getter for a property?
>
>> I had said it was necessary to achieve structs as properties, but I think I was wrong. It's just the equivalent of:
>>
>> int __someRandomFunction() { return _propValue; }
>> alias __someRandomFunction this;
>>
>> But it would be syntactically nicer, much like Highlander structs are syntactically nicer. Therefore, the only language change absolutely required would be making non-static structs nested in structs behave like non-static structs nested in functions, which they arguably should do anyway. Also under the hood, some important optimizations getting rid of pointers for data-less structs.
>
> This is a VERY bad idea.  A struct is POD.  For example, consider a range type for a container.  You may not NEED to have a pointer to the container, so that is wasted bytes.
>
> Also note that structs are not meant to have internal pointers.
>  So a "property" struct with an internal pointer
>
> The strange case for a struct type inside a function kind of makes sense, because of the ability to access the function's variables, and because you can't really move the stack frame.
>
> -Steve

I think my suggestion goes far beyond what you suspect. It goes way beyond mere getting and setting of variables. Here is basically how you implement a basic int as a property, assuming my new syntax and language adjustments. You need: 1) a struct to have the property in, which is just a normal struct. 2) An actual integer which will be indirectly accessed by using the properties. Let's call it "_n" and the property "n". 3) a struct to hold all of the property functions which access _n. THIS STRUCT CONTAINS NO DATA OF ITS OWN. 4) A bunch of methods implementing all the operators you want. For int, that's quite a lot, so I'll shorten it to a getter, a setter, and an adder. I'll even leave out opGet and use an alias to what might as well be opGet. I'll give the adder a little personality because what's the point of properties if they don't do something different from a basic type?

struct myStruct
{
  int _n;
  n struct
  {
    int __mightAsWellBeOpGet() { return _n; }
    alias __mightAsWellBeOpGet this;

    int opAssign(int newN) { _n = newN; return _n; }
    int opBinary(string op) (int rhs)
    {
      static if (op == "+")
      {
        writeln("You sure are adding a funky int, my friend...");
        return _n + rhs;
      }
      else static assert(0, "Operator "~op~" not implemented");
    }
  }
}

This is not some kind of special property implementation. n is a struct. It has no data and therefore is a very peculiar kind of struct. A struct with no data needs only one instance, ever. Copying it is pointless. Taking its address is pointless. Creating a new instance is pointless. Passing it by ref is pointless. All operations which require more than one instance are pointless, which is why it doesn't need a separately defined type. The type and the instance can therefore use the same name, n in this case.

Note that n uses the new rule which allows it access to its parent's scope, the same way it would in a nested function. The only pointer it needs is the same pointer used for myStruct, since myStruct actually stores some data.

Using the int is as simple as:
myStruct foo;
foo.n = 4; // Calls opAssign
writeln(foo.n); // uses alias this to call __mightAsWellBeOpGet
writeln(foo.n + 4); // Calls opBinary. Prints:

You sure are adding a funky int, my friend...
8

There's literally nothing these properties can't do that a full-fledged struct type couldn't do.
February 01, 2013
On Friday, 1 February 2013 at 00:59:47 UTC, Zach the Mystic wrote:
> writeln(foo.n); // uses alias this to call __mightAsWellBeOpGet

No it won't. It will print "n()".

And that exactly (passing to a templated parameter) is the insurmountable problem in using a variable to represent a property.
February 01, 2013
On Friday, 1 February 2013 at 01:53:05 UTC, TommiT wrote:
> On Friday, 1 February 2013 at 00:59:47 UTC, Zach the Mystic wrote:
>> writeln(foo.n); // uses alias this to call __mightAsWellBeOpGet
>
> No it won't. It will print "n()".
>
> And that exactly (passing to a templated parameter) is the insurmountable problem in using a variable to represent a property.

On Friday, 1 February 2013 at 01:53:05 UTC, TommiT wrote:
> And that exactly (passing to a templated parameter) is the insurmountable problem in using a variable to represent a property.

And here's another example of why it is as big of a problem as I make it sound to be:

import std.concurrency;

struct Array
{
    int _len;

    length struct // Using Zach's syntax
    {
        @property get() { return _len; }
        alias this = get;
        void opAssign(int rhs) { _len = rhs; }
    }
}

void func(T)(T t)
{
    auto v = t;
    v = 10;
}

void main()
{
    Array arr;
    spawn(&func!int, arr.length);
    arr.length = 20; // And here we have a data-race.
                     // Good luck trying to find these
                     // kinds of bugs.
}
February 01, 2013
On Friday, 1 February 2013 at 02:27:30 UTC, TommiT wrote:
> [..] as big of a problem as I make it sound to be:

...make it out to be...