Taking address of properties

Steven Schveighoffer schveiguy at yahoo.com
Sun Feb 10 16:18:52 PST 2013


On Sun, 10 Feb 2013 11:52:47 -0500, Robert <jfanatiker at gmx.at> wrote:

> On Sun, 2013-02-10 at 10:43 -0500, Steven Schveighoffer wrote:
>> On Sun, 10 Feb 2013 07:09:52 -0500, Robert <jfanatiker at gmx.at> wrote:
>>
>> > Ok, at the very first I have to make clear that my DIP is about  
>> changing
>> > the actual specification, not trying to make the implementation to  
>> match
>> > the specification, because in my view of things, the specification is
>> > the problem.
>> >
>> > Properties in my proposal are no longer about optional parentheses ore
>> > forbidden parentheses. Properties are a concept hat benefits from the
>> > fact, that parentheses are optional, but would work either way.
>>
>> We don't need a feature to implement encapsulation, it's quite possible
>> without property specification.  And your proposal does not guarantee
>> encapsulation anyway.
>
> We don't need it. -> Yes.
> Would it be nice to have. -> Discuss-able.
> Does it solve the issues we have. -> Yes.
> Properties as such do guarantee encapsulation, if you access the fields
> through the property methods. There is no way to forbid the programmer
> to break it by other members, alias this, or what ever. But as you said
> D is a systems programming language.

It does not.  @property as you have designed it does not "solve" any  
issues.  It does not enforce or guarantee encapsulation.  Only the author  
can do that.

One thing I have learned from D's design philosophies is that a guarantee  
is not a guarantee unless the compiler guarantees it.  Like const.  Walter  
constantly derides C++ const as convention, not enforced.  This would be  
the same thing, if someone uses @property, then you assume they have  
encapsulated.  Unless they haven't, in which case, the compiler still  
happily compiles, and your guarantee is gone.

How is your DIP any different from a statement that non-ref returning  
@properties guarantee encapsulation?  Answer: it's no different.  And  
neither statement is true.

> Why do we need properties to be radically different than functions? This
> breaks templates, except we try to make almost everything a property,
> what DIP23 seems to do. All I do is strive for a clean concept what a
> property actually is, instead of making everything a property just so
> that templates work, but by giving up any meaning property could have.

They aren't *radically* different from functions, the syntax is  
different.  Under the hood, they are identical to functions.  Well, a  
certain form of functions.

>> And who says what good design is?  What if good design means low
>> performance?  What if performance is more important?  How can you say  
>> you
>> know the goals of every possible implementable object and whether
>> encapsulation is entirely necessary for it?  You are holding hostage a
>> syntax feature on the concession that it play nice with your "requiring
>> function call" rules.
>
> I believe the principles of OOP are very well established and accepted.
> And once again, you don't have to use properties if they don't match
> your requirements. Also performance does not suffer from a trivial
> get/set functions. (For classes make them final if needed)

It is true that properties are mostly in OOP languages. But D is not  
strictly OOP.  structs are not OOP, and you can have properties on them.   
Static properties can exist, and they have absolutely nothing to do with  
OOP.  It is a syntax modification.  Encapsulation, an OOP design, does not  
require a special property syntax to implement them.

>>
>> I don't think D should be dictating everything about how you write your
>> properties and methods.  This is a systems language, not a nanny  
>> language.
> It does not dictate anything. You do accept that you can not do floating
> point arithmetic with an integer? What's the difference with properties?
> If the tool does not fit your need, don't use it.

Actually, floating point is 2 integers.  And yes, you can do floating  
point math with integers.  I do it all the time to avoid the issues with  
floating point.

But beside that point, your properties bring nothing to the table, so I  
can actually do without them completely.  They are a tool that fixes  
problems that are already fixed.

>> Because then I have to do:
>>
>> id.front()();
>>
>> To call the delegate.  Not what I wanted to design.  You are calling  
>> into
>> question my design because it doesn't suit your DIP.  Why is your DIP  
>> more
>> important than my design?
>
> You are questioning my DIP, because it does not match your design. How
> is that better? Seriously this is just my point of view, you can agree
> or not, all I am trying is to make sure that you understand why I think
> it is good and to find possible flaws in it, by discussing it.

The issue is, my design is limited to MY library, your DIP affects EVERY  
library (or would if implemented).  The bar is much higher that you have  
to pass, since everyone will have to play by your rules.

Without your DIP, I can have my library, and others can have their  
libraries which might require you to use id.front()().  Freedom of design  
is definitely not something to take away lightly.

> It establishes some semantics for properties, instead of simply making
> basically everything a property, just so that templates work somehow.
> The DIP increases uniformity among language features, instead of
> decreasing it. Also I am obviously convinced that my DIP is a good
> solution, otherwise I would not have proposed it.

All the property proposals establish semantics for properties.  Nobody is  
making everything a property, save perhaps your DIP, which mostly equates  
functions and properties, so I don't really get that.  Your dip makes  
things much less uniform IMO, since properties should syntactically be  
more like fields than functions.  With your DIP, I am forced to require  
"property or function" in a template, I can't require "field or  
property".  Seeing as how properties are actually functions, I don't see  
the point.  I feel this takes the major draw of properties away.

>
>> > which would still work just the same, if you removed @property.
>>
>> Right, the setter is not the reason we need @property on this, it's the
>> getter.  And only for delegate arrays.  I should not have brought this
>> example as a reason for UFCS setter properties.
>
> Not if we simply accept: front()(); as the syntax to go. It might not
> look as beautiful as front(), so if you think the syntax for this corner
> case is just so utterly ugly that it has to be fixed, well then my
> proposal is rubbish.

It's not about the beauty.  A field that is a delegate does not require  
two sets of parentheses.  In this case, properties would behave like  
functions, and we already HAVE functions that execute arbitrary code, we  
don't need another language construct that executes arbitrary code and is  
called exactly like a function.  So in your DIP, properties are pretty  
much redundant.

>>  import std.stdio;
>> > int i;
>> >
>> > void main() {
>> >     int i;
>> >     i=8;
>> >     writeln(".i: ", .i);
>> >     writeln(".i: ", testglobal.i);
>> > }
>> >
>> > Prints 0 both times. (The file was named testglobal.d)
>>
>> I don't know what this example is trying to prove.  I don't see any
>> properties here.
> Hmm, maybe I misunderstood your argument against module level
> properties. (The example works the same if i was a property)
> So what did you mean by:
> 	So the point is, a global property could possibly be obscured
> 	if you declared a local variable with the same name.

The original text this was in reply to made this confusing.

What I was saying is that struct static fields/properties do not interfere  
with UFCS, and are as global as global fields/properties.

>> >> A ref property pretty much behaves EXACTLY like a field.
>> >
>> > Exactly that is why I don't consider it a property. :-)
>>
>> If it's not a property, it does not behave like a field.  If it is a
>> function, then it can behave like a field for all cases except for the
>> delegate case.
> right, so its behaviour is uniform with properties.

Again, we have fields, we have functions.  If you want to make a *new  
type* of function, it needs to justify its existence.  I don't see  
anything compelling for @properties as you see them, they act just like  
functions.

>> Your design dictates that if you want field-like syntax, you have to  
>> agree
>> to arbitrary rules regarding ref, and you can't do it with UFCS.  Such
>> rules are pretty much arbitrary, because there is no hidden meaning to a
>> property, they are just functions.  The only benefit is the readability
>> and the 'human' meaning.  Because instead of calling my function setX, I
>> can just call it x, and you have to use the x = ... to call it.
>
> The most important thing the DIP does, is giving "property" an actual
> meaning. Also readability is a valid goal, otherwise we could all code
> in machine code.

Right, a meaning that is not true.

>
>>
>> But you want to assign some guarantees that really aren't guarantees,  
>> they
>> are conventions.  In the end, they just get in the way, and your
>> requirements can't achieve the type of guarantees you want.
>
> So you basically say that OOP does not work? (No offense here, but it is
> hard to understand for me to understand this statement in any other way)

No, I have no idea how you get that.  Whether or not you *can* encapsulate  
with @properties is a different statement than whether @properties  
*guarantee* encapsulation.  What you have is something that is  
unnecessarily strict, in exchange for a false guarantee.  That's all I  
said.  It had nothing to do with whether encapsulation is good practice,  
or if OOP works.

>
>>
>> Your concept of property is that they are just functions.  But we  
>> already
>> HAVE functions.  There is no reason to have a language feature that says
>> "this is a property" unless it dictates the *syntax*.  It is up to the
>> designer of the type to decide how it's parts are called, it should not  
>> be
>> up to the caller.  Leaving it up to the caller results in unnecessary
>> obfuscation, and hidden meanings where none was intended.
>>
>> There is actually no real need for properties, they are functions, they
>> can be called like functions.  We can get along just fine if we have to
>> write:
>>
>> setFoo(x);
>>
>> instead of
>>
>> foo = x;
>
> Agreed, if we started from scratch and did not want this syntactic
> sugar. The problem is we do not start from scratch and we would
> basically break every single D program out there.

Well, we actually are starting from pretty much what you are proposing.   
Your proposal adds complexity for no gain.

>>
>> If there is any reason to have a @property language feature, it's for
>> syntax, not for design.
>
> At the moment. And I am criticizing this very fact. But if you consider
> this a good thing, than I understand your position completely. Because
> this way you don't need a meaning of property, you just adopt the rules,
> until templates work.

Your counter proposal is to make @property essentially a no-op.  If you  
want to criticize, that is fine.  If you want to establish a convention  
that using @property to encapsulate really requires not returning ref, or  
using them with UFCS (which is in fact incorrect), that is fine too.

But in order to have a reason to have @property stay in the language, it  
has to be a feature that isn't easily done otherwise.  It needs to pull  
it's weight.  Having it just be another function isn't worth it.

>>  ref, don't use @property.
>> >
>> > So there will be guaranteed to have a proper encapsulated field, the
>> > moment they see @property, but what is more important is, that the
>> > provider of the code can be sure that he/she got encapsulation right  
>> as
>> > long as he/she does qualifies something with @property.
>>
>> But they don't see property:
>>
>> auto x = obj.y; // no @property in sight.
>
> Sure, but how important is this for the caller? The provider of the API
> has to ensure compatibility. (Also the caller sees it, if she looked at
> the documentation.)

I don't think it is important.  That is why your whole DIP is needless.   
As an object author, I can easily ensure encapsulation whether @properties  
are used or not.  @properties as you define them give me no extra bonuses  
or features, they are simply functions.

If your DIP is implemented, and any programmer looks at a @property method  
and says "aha! that field is entirely encapsulated because it has  
@property on it," I would call that programmer foolish.  Any guarantees  
that you have to double check yourself are not guarantees.

>>
>> "guarantees" of encapsulation are easily thwarted:
>>
>> struct NotEncapsulated
>> {
>>     int x;
>>     @property int y() { return x;}
>> }
>>
> Well no language feature in as systems programming language can prevent
> you from stupidity. But then, why not get rid of private too, as this is
> also possible:
>
> struct {
> private int i;
> public int* u=&i;
> }

Again, when you say "guarantees", that is a strong term.  If @property  
claims to guarantee encapsulation, it better ensure the above doesn't  
compile, because otherwise it's not guaranteed.

The rule in D is that if it guarantees something, the only way to get  
around it is to cast.  This way, you can use cast as a red flag to  
indicate some guarantee may be broken.

private does not guarantee that others cannot access it through other  
references.  It simply is a tool with which you CAN guarantee others  
cannot access it.  @properties are no different, they do not guarantee  
encapsulation, with or without your DIP, they only provide a mechanism to  
be able to provide that guarantee.

-Steve


More information about the Digitalmars-d mailing list