January 30, 2013
On Tue, 29 Jan 2013 17:40:45 -0800, TommiT <tommitissari@hotmail.com> 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?

Not really, public fields ARE bad, but properties allow you to sanitize the data and throw exceptions if the data doesn't fit the spec. A field does not. In this way encapsulation is maintained.

-- 
Adam Wilson
IRC: LightBender
Project Coordinator
The Horizon Project
http://www.thehorizonproject.org/
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?

Well, the main reason why this was bad convention, is because the "." operator conceptually returns by reference, so you are operating directly on the encapsulated variable with no possibility of oversight through the encapsulation.

The @property method will restrict variable usage to non-ref and non-pointer uses only, which is a form of encapsulation through the "." operator, and it can later be replaced with a function call if required.

Even with @property restrictions, I still don't think it will work as expected. For example, if the variable is a struct, then you have to disallow operations on the struct from outside.

Example:

struct Y { int a; }

struct X{ @property Y y; }

X x;

x.y.a = 4; // <- this has to be illegal!

Reason?

struct X{

  Y _y;

  @property Y y{ return _y; }

}

// this won't change _y as it did before.
x.y.a = 4;

I figure if we're going to do something about properties, we may as well do something much more compelling and re-invent the property rather than attempt to partially emulate variables just because someone was in a hurry and left their encapsulated variables public and used them directly outside the struct or class.

--rt
January 30, 2013
On Tue, Jan 29, 2013 at 06:05:15PM -0800, Adam Wilson wrote:
> On Tue, 29 Jan 2013 17:32:20 -0800, H. S. Teoh <hsteoh@quickfur.ath.cx> wrote:
> 
> >On Wed, Jan 30, 2013 at 02:23:26AM +0100, Jonathan M Davis wrote:
> >>On Tuesday, January 29, 2013 17:06:32 H. S. Teoh wrote:
> >>> Why do you have to mark naked variables as @property? Isn't that redundant?
> >>
> >>In order to restrict what you can do with it to the subset of operations that you can do with a property function. In particular, taking its address would need to be illegal, as that won't work with a property function (or if it did, it would return a different type).
> >
> >I see.
> >
> >
> >>It would be impossible to replace a normal variable with a property function without risking breaking code, because there are operations that you can normally do on a variable that couldn't possibly be implemented with a function (such as taking its address). But if you mark it to restrict what it can do, then you could swap it out with a function later without the risk of breaking code (which is one of the main reasons for having properties in the first place). @property doesn't currently do this, but it could, and if we don't have something like that, then it'll never be safe to swap variables and property functions.
> >[...]
> >
> >If this is the case, then I would have to say that @property is fundamentally broken. The whole point of @property is to make functions behave like variables, but if this "variable emulation" isn't even complete, then it defeats the purpose of having it in the first place.
[...]
> 
> Indeed, but a better idea would be to fix it, throwing it out seems a bit extreme.
[...]

I'm not for throwing it out, actually. :) Just pointing out some problematic aspects of it.

One way to solve the '&' problem is to have the compiler lower that into a delegate that gives access to the setter/getter for that field. Then @property *would* indeed be a drop-in replacement for member variables.


T

-- 
In theory, there is no difference between theory and practice.
January 30, 2013
On Wednesday, January 30, 2013 02:40:45 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?

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
January 30, 2013
On 01/29/2013 08: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?

No, it means that style of programming is no longer bad.

It is already possible to write public member variables.  It's pretty much as dangerous to do so as the wisdom says.

We avoid using public member variables specifically because, in most languages, this makes it impossible to add hooks into the assignment/retrieval of the variable later without breaking the API. Now, in D, we might one day be able to add those assignment/retrieval hooks onto a variable without breaking API.  That makes it no longer necessary to avoid public variables, though you will probably have to mark them @property to get the safety.
January 30, 2013
On Tuesday, January 29, 2013 17:32:20 H. S. Teoh wrote:
> If this is the case, then I would have to say that @property is fundamentally broken. The whole point of @property is to make functions behave like variables, but if this "variable emulation" isn't even complete, then it defeats the purpose of having it in the first place.

It works if you can restrict a variable to a reasonable subset of its normal operations (which primarily means that you can't take its address or pass it by ref). You just can't fix that. Not with a systems language like D. Variables and functions are just fundamentally different. C# manages it because you don't have as much low-level control over variables (like taking their address). But if we can do something like

struct S
{
    @property int prop;
}

then that fixes the problem.

- Jonathan M Davis
January 30, 2013
On Tuesday, January 29, 2013 18:13:41 H. S. Teoh wrote:
> I'm not for throwing it out, actually. :) Just pointing out some problematic aspects of it.
> 
> One way to solve the '&' problem is to have the compiler lower that into a delegate that gives access to the setter/getter for that field. Then @property *would* indeed be a drop-in replacement for member variables.

But the type would be different. You wouldn't be able to do stuff like

int* p = &s.prop;

And what happens with a delegate is fundamentally different when you take the address of a variable. The property function may not even be returning a value associated with a variable. It could be calculated. I believe that you're trying to take the abstraction farther than is possible. All abstractions break at some point, and taking the address of a property is one place that property functions break as an abstraction for variables.

- Jonathan M Davis
January 30, 2013
On 01/29/2013 09:13 PM, H. S. Teoh wrote:
>
> I'm not for throwing it out, actually. :) Just pointing out some
> problematic aspects of it.
>
> One way to solve the '&' problem is to have the compiler lower that into
> a delegate that gives access to the setter/getter for that field. Then
> @property *would* indeed be a drop-in replacement for member variables.
>
>
> T
>

I hate to be a bringer of bad news, but I don't think getter/setter proxies will ever be an invisible replacement for pointers.

Getter/setter proxies cannot be incremented/decremented, and you can't use them in conjunction with the container's pointer to get the offset to the field.  Pointers have very specific semantics.

I think it's much easier to just restrict variables from being addressable in cases where they will eventually become properties.

I would argue though, that pointers are a getter/setter proxy.  The relationship is just not commutative.  What this means is that we can treat getter/setter proxies as an algorithmic structure, right alongside things like ranges, iterators, containers, etc.  They are the most general form of their class: anything that supports assignment and retrieval (ex: pointers) is a kind of getter/setter proxy.

I think that we would eventually want a (library-defined) getter/setter proxy type.  It will be the only way to defer getting/setting of an @property into called code, which is what pointers are currently used for in many cases.  Such a type should be possible to construct from plain variables, pointers, (hash table + key) pairs, certain functions (ex: foo(int getOrSet, void **value)), and anything else you could concoct that satisfies the "is a" relationship.

</dream>
January 30, 2013
On Wednesday, 30 January 2013 at 00:26:11 UTC, q66 wrote:
> It deeply disturbs me that people even take the original post seriously.

Well, you may give some arguments instead of no, just no, to convince people.
January 30, 2013
On Tue, Jan 29, 2013 at 09:44:36PM -0500, Chad Joan wrote:
> On 01/29/2013 09:13 PM, H. S. Teoh wrote:
> >
> >I'm not for throwing it out, actually. :) Just pointing out some problematic aspects of it.
> >
> >One way to solve the '&' problem is to have the compiler lower that into a delegate that gives access to the setter/getter for that field. Then @property *would* indeed be a drop-in replacement for member variables.
[...]
> 
> I hate to be a bringer of bad news, but I don't think getter/setter proxies will ever be an invisible replacement for pointers.
> 
> Getter/setter proxies cannot be incremented/decremented,

This is easy to fix in the compiler.


> and you can't use them in conjunction with the container's pointer to get the offset to the field.  Pointers have very specific semantics.

If you write code that is specific to a particular implementation of a field, then it's no surprise that you can't use drop-in abstract replacements. I don't see that as a major issue.


> I think it's much easier to just restrict variables from being addressable in cases where they will eventually become properties.

You're right, there is some merit to this idea.


> I would argue though, that pointers are a getter/setter proxy.  The relationship is just not commutative.  What this means is that we can treat getter/setter proxies as an algorithmic structure, right alongside things like ranges, iterators, containers, etc.  They are the most general form of their class: anything that supports assignment and retrieval (ex: pointers) is a kind of getter/setter proxy.

I like this line of reasoning.

Pointer arithmetic is @unsafe anyway, and in general don't interact well with abstraction, so I don't see lack of pointer support as a major problem. As long as you treat pointers as opaque handles to some value (abstract or otherwise), you can replace them with a getter/setter proxy.


> I think that we would eventually want a (library-defined) getter/setter proxy type.  It will be the only way to defer getting/setting of an @property into called code, which is what pointers are currently used for in many cases.  Such a type should be possible to construct from plain variables, pointers, (hash table + key) pairs, certain functions (ex: foo(int getOrSet, void **value)), and anything else you could concoct that satisfies the "is a" relationship.
[...]

I think if we can address the various issues of Rob T's struct-as-variable idea, it might be possible to turn it into a template in Phobos (maybe in std.typecons or something).


T

-- 
"I speak better English than this villain Bush" -- Mohammed Saeed al-Sahaf, Iraqi Minister of Information