On Sun, 10 Feb 2013 11:52:47 -0500, Robert <jfanati...@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 <jfanati...@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

Reply via email to