Part 1 - Ordinary Functions (the rewrite rules)
--------------------------
Not strictly the discussion topic, but it was a big issue and is related, so:

Q: Do you think the "property" rewrite rules (ie optional opCall operators) are a bad idea.
A: Yes I do
Q: Why?
A1: Look at all the confusion its caused!
A2: Because I have shot myself in the foot too many times because of this to be convinced otherwise. Judging from the posts, I am not the only one hopping around on one foot.
Q: Accepting that it's here to stay, what can you do about it?
A: Pretend they don't exist and always write expressions the "correct" way.

Basically If you're having problems with the "property" rewrite rules, then stop trying to use them. Adopt the habit of always writing your function calls verbosely (even with UFCS) and your problems should go away.

Unless they are going to be gotten rid of entirely, the rewrite rules should not be changed. All of the suggestions I've seen (including Walter's original one) will only lead to more complexity, more special cases, more inconsistency, more confusion, and more problems.

Part 2 - @property
--------------------------

A big problem with @property is that people are thinking of them as functions, no small part due to the "property" rewrite rules discussed above. Even people who suggest that @properties should not use opCall still talk about calling properties, as though they are functions.

The trick is to stop thinking of properties in terms of functions, and to think of them as variables. To "call" a property should make as much sense as calling a variable.

Some have mentioned this, and others have hinted at it, but I think that it has not been made fully clear.

To illustrate, consider this:

   int v;

v is a reference to a block of memory which is accessed by a machine code getter and setter. So

   int a;

is really

@property { int a() { fetch from memory }; int a(int) { write to memory } }

When you're declaring a true property, you're still declaring a variable, but you're simply providing the complier with altertives to the traditional fetch/write instructions.

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

Here is another (admittedly more complex) way to look at it.

struct {
  int opAssign(int) { ... };
  int opCast!(int) { ... } ;
} Property

Property prop;

You will need to imagine the opCast as an implicit cast for it to work, but hopefully you will get what I mean.

Here prop is a variable, so it would be parsed like one by the compiler.

The expression "prop = 3" would assign 3 to the contents of prop, Which would result in the opAssign (the setter) being called.

In the expression "y = prop++", we get the contents of prop (via opCast, the getter), apply the ++ operator to it, and assign the result to y.

If prop were an actual integer, the above expressions would work exactly the same way.

Using struct for this is a little ugly, so you could say instead:

@property { int prop(int) { ... }; int prop() { ... }; }

A little neater, but would work the same way.

Part 3 - functions returning delegates.
---------------------------------------

When it comes to delegate properties (ie the getter returns a delegate), I'm sensing that people are having trouble getting their heads around it, always needing to treat it like a special case. Let's try to see it in a way that it is not special.

Lets have

    delegate int() f1;

and

    @property delegate int() f2() { ... };

In the eyes of the greater world f1 and f2 should work the same way.

In the expression y = f1(), we get the contents of f1 (the delegate), apply the "()" operator to it, and assign the result to y;

In the expression y = f2(), we get the contents of f2 (via the getter, which gives us the delegate), apply the "()" operator to it, and assign the result to y;

In both cases y is an int.

Recall an eariler statement:

In the expression "y = prop++", we get the contents of prop (via opCast, the getter), apply the ++ operator to it, and assign the result to y.

Note the similarity. () is like other operators and is no longer special.

How does this work for ordinary functions?

    int func()

can be seen as

    auto func = function int()

func is a variable and its contents is the function. The expression func() means "get the contents of func (the function) an apply () to it (gives int)".

For

    delegate int() delg()

which can be seen as

    auto delg = function (delegate int())()

The expression delg() means "get the contents of delg (the function) and apply () to it (gives delegate)", and delg()() would apply () to whatever delg() gives and, ultimately, give us an int.

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

How come people are getting confused about it? That damn optional opCall rewrite rule.

Some people probably think that, for functions returning delegates, if
   f becomes f()
then
   f() becomes f()()

THIS DOES NOT HAPPEN! Nor should it. Remember that and you should be OK. Otherwise consider my suggestion in Part 1.

Part 4 - Answering the original question.
----------------------------------------

Should @property be shot?

No, but it should be reworked

Regards
Jason

Reply via email to