January 30, 2013
On Wednesday, 30 January 2013 at 02:22:14 UTC, Jonathan M Davis wrote:
> On Wednesday, January 30, 2013 02:40:45 TommiT wrote:
>> I always thought that having public member variables is a bad
>> style of programming because of the lack of encapsulation. So, if
>> there's a language feature that enables you to write public
>> member variables, and later on, replace them with property
>> functions, wouldn't that mean that the language is encouraging
>> this particular kind of bad style of programming?
>
> Aside from the ability to take the variable's address, what really is the
> difference between
>
> struct S
> {
>  int prop;
> }
>
> and
>
> struct S
> {
>  @property int prop() @safe const pure nothrow
>  { return _prop; }
>
>  @property int prop(int value) @safe const pure nothrow
>  { return _prop = value; }
>
>  private int _prop;
> }
>
> At the moment, stuff like ++ and += wouldn't work with @property, but that
> could be fixed. But as far as access goes, there's no real difference. You have
> full read-write access in both cases. That being the case, why bother with the
> property functions? What you're supposed to be able to do (and C# let's you
> do, but we can't with our current implementation of properties), is start with
>
> struct S
> {
>  int prop;
> }
>
> The code's shorter and simpler. You don't need any checks on the data, and you
> don't need to do any operations when the property gets set. So, a variable is
> just fine. Then when you actually need to do something extra when the property
> is set, you change it to a property function.
>
> struct S
> {
>  @property int prop() @safe const pure nothrow
>  { return _prop; }
>
>  @property int prop(int value) @safe const pure nothrow
>  {
>  validate(value);
>  _prop = value;
>  doSomethingElseWhichCaresAboutPropChanging();
>  return _prop;
>  }
>
>  private int _prop;
> }
>
> And no code is broken. That works in C#, but it works there, because they
> actually have a good property implementation, and you can't take the address
> of a variable in C# like you can in D. If we want the same, we need to fix it
> so that the compiler does proper rewriting of code like s.prop++ and make it
> so that we can mark variables as properties (so that you can't take their
> address or pass them by ref or do anything else that you can't do with a
> property function). e.g.
>
> struct S
> {
>  @property int prop;
> }
>
> But a public variable isn't a problem if the language allows you to swap it
> out with a property function without breaking code.
>
> - Jonathan M Davis

Okay, I can see how that could work. But I still stand un-corrected by my previous post. Because 'public' means to me: "end-user has direct all-access". Therefore: "public @property int prop;" isn't really public given my definition. It's somewhere in the space between public and private.
January 30, 2013
On Wednesday, 30 January 2013 at 01:40:52 UTC, TommiT wrote:
> On Wednesday, 30 January 2013 at 00:25:41 UTC, Jonathan M Davis wrote:
>> On Wednesday, January 30, 2013 00:55:13 Rob T wrote:
>>> [..]
>>> You know a lot more about implementing compiler magic than I do, so I'll ask you if you think the effort is doable enough
>>> to justify having property functions that can act like a
>>> drop in replacement for existing variables?
>>
>> I believe that two main things are needed: [..]
>
> I always thought that having public member variables is a bad style of programming because of the lack of encapsulation. So, if there's a language feature that enables you to write public member variables, and later on, replace them with property functions, wouldn't that mean that the language is encouraging this particular kind of bad style of programming?

Belief is rarely a good thing.

public variable are an encapsulation problem if you don't have properties. Then, a bunch of boilerplate is written because in 1% of the cases, some logic will be hooked on the variable access.

Allowing properties allow the same level of encapsulation, without requiring boilerplate up-front.
January 30, 2013
On Wednesday, 30 January 2013 at 03:24:47 UTC, deadalnix wrote:
> public variable are an encapsulation problem if you don't have properties.

I don't agree. I think public variables are an encapsulation problem, period. And again, by 'public' I mean: "really, truly public, not kidding".
January 30, 2013
On Wednesday, 30 January 2013 at 03:52:22 UTC, TommiT wrote:
> On Wednesday, 30 January 2013 at 03:24:47 UTC, deadalnix wrote:
>> public variable are an encapsulation problem if you don't have properties.
>
> I don't agree. I think public variables are an encapsulation problem, period. And again, by 'public' I mean: "really, truly public, not kidding".

Sounds like religious reasoning.
January 30, 2013
On 1/29/13 8:40 PM, TommiT wrote:
> On Wednesday, 30 January 2013 at 00:25:41 UTC, Jonathan M Davis wrote:
>> On Wednesday, January 30, 2013 00:55:13 Rob T wrote:
>>> [..]
>>> You know a lot more about implementing compiler magic than I do, so
>>> I'll ask you if you think the effort is doable enough
>>> to justify having property functions that can act like a
>>> drop in replacement for existing variables?
>>
>> I believe that two main things are needed: [..]
>
> I always thought that having public member variables is a bad style of
> programming because of the lack of encapsulation. So, if there's a
> language feature that enables you to write public member variables, and
> later on, replace them with property functions, wouldn't that mean that
> the language is encouraging this particular kind of bad style of
> programming?

The thing here is that properties offer control over changing the variable, which makes all the difference.

Andrei
January 30, 2013
On Wednesday, 30 January 2013 at 02:29:12 UTC, Jonathan M Davis wrote:
> But if we can do something like
>
> struct S
> {
>     @property int prop;
> }
>
> then that fixes the problem.

I had a thought. What if we use this opportunity to also fix the problem with transient ranges. So... what if, instead of using the attribute @property for the purpose you suggest, we added a new attribute, let's say @noref, and that's what it would mean:

struct S
{
    @noref int value; // #1

    @noref ref const(float) front() const; // #2
}

S s;

#1: Can't take the address/reference of s.value

#2: Can't take the address/reference of s.front()

Transient ranges could notate their front method with @noref, which would prevent all incorrect use of them, and would enable their front to return by ref or const ref, instead of by value.
January 30, 2013
On Wednesday, 30 January 2013 at 04:06:02 UTC, deadalnix wrote:
>> I don't agree. I think public variables are an encapsulation problem, period. And again, by 'public' I mean: "really, truly public, not kidding".
>
> Sounds like religious reasoning.

I don't understand you. According to wikipedia, encapsulation is:

"A language mechanism for restricting access to some of the object's components."

Member variable is a component of an object. Public access means un-restricted access. Therefore, public member variable is not encapsulated. Therefore, public member variable is a problem in encapsulation, by definition. I dare you to find a single religious cell in me.
January 30, 2013
There's times when a member variable manages its own invariant and any of its values is valid for the containing class, in which case the container doesn't need to further restrict access to it; a public struct doesn't need to be wrapped in a get function or anything.
January 30, 2013
On Wednesday, 30 January 2013 at 04:39:13 UTC, Adam D. Ruppe wrote:
> There's times when a member variable manages its own invariant and any of its values is valid for the containing class, in which case the container doesn't need to further restrict access to it; a public struct doesn't need to be wrapped in a get function or anything.

Okay, so we have this:

struct Foo
{
    Bar bar;
}

Assume that all data in Bar is stack allocated and we can't change it. What if I later on realize, that I should have really allocated bar on the heap, because its size is too great and it makes Foo inconvenient in every-day use because of stack overflow problems. Now that everybody has already been using foo.bar directly, I feel really bad for not encapsulating it.

Note: that's not a problem if we have a way of saying that bar should behave like a property function, something like:

struct Foo
{
    @property Bar bar;
}

...and if we can create that property function later on.
January 30, 2013
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.

Can an pro-@property members claim that the current behavior is what you want? I believe this answer is no.

It seems at least some members for @property feel that currently functions are being annotated with @property that shouldn't be.

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).

--------------------

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.

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.

Granted I'm not concerned if it doesn't ever come back. I believe it has a legitimate role in allowing a change from field to function without harming usage that can not be achieved without an annotation. However it seems we can't achieve this with the combination of features D employs.

I don't agree with the argument that properties provide a convince to identify low overhead access. While I'm not experienced in this area, profile code should indicate where performance is poor, it would be bad to assume "that looks like a field, so it must not be where the performance is bad."

---------------------

So let us decide to keep optional (), fix what we can there.

Define what is desired of properties, but for now get rid of what we currently know as @property. Then with a complete proposal, we can say it must meet these goals or it won't exist. Since optional () remain, introducing @property again will not break code and we will only deal with broken code now (and there would be some just to fix the current behavior and its disconnect with -property)