February 04, 2013
On Monday, 4 February 2013 at 04:45:27 UTC, Jonathan M Davis wrote:
> On Sunday, February 03, 2013 03:16:08 Andrei Alexandrescu wrote:
>> Destroy.
>
> Another thing to consider would be to allow putting @property on a variable
> with the idea that variables marked as such would not be usable in any
> situation where a property function wouldn't be - such as taking their address
> or passing them by ref. [..]

If we consider a variable marked as @property as a variable whose access is restricted, then the following should be also illegal uses of it:
1) calling its non-const method
2) mutating its data field

If we consider a variable marked as @property as lowered to getter and setter properties, then it doesn't have those restrictions. This is what I would advocate.
February 04, 2013
On 2/3/13 11:00 PM, David Nadlinger wrote:
> The problem I see is that usually, one can insert grouping pairs of
> parentheses into an expression according to the operator
> precedence/associativity rules at will without changing the result. This
> isn't merely a theoretical exercise, but the way (well, in the form of
> trees) I tend to reason about source code intuitively.

Well this is going to sound bad, but you either use reason or intuition. I don't see how one can reason intuitively.

> Now, grouping the expression »&a.b« according to the precedence rules
> yields »&(a.b)« – but in your proposal, they mean completely different
> things.

I agree they mean different things. I'm unclear that's a problem. All your examples stop here, there's no propagation of the issue. To take the address of a property, one writes &obj.prop. To take the address of a property's result, one writes &(obj.prop). And that's that. It all works with typeof.

> You could argue that &<expression>.<identifier> is a special construct
> different from the normal address-of operator. But where do you mentally
> draw the line? What about &a.b.c <-> &(a.b).c <-> &((a.b).c)? &(a + b).c
> <-> &((a + b).c)?

That argument is easily destroyed. In a.b.c, a.b is the expression and c is the property name.

> Again, from an user's perspective the change in behavior seems to be
> completely at odds with the usual rule in C-family languages that
> grouping parens can be added without changing the meaning of an
> expression.

I think we avoid much more bizarre things that way, such that expr and &expr meaning sometimes the same exact thing. Or that we have expressions without a type. And nobody blinks an eye. I just think we're better off.

> Thus, this part of the proposed syntax strikes me as being
> extremely misleading, which is especially bad because the situation with
> the two possible meanings is confusing enough to start out with already.
> And how often do you think you'll find yourself in the situation of
> needing to get a delegate from a property anyway? Can't we just make
> »@property getter expressions are always equivalent to their return
> value« a hard (simple!) rule and add something like
> __traits(propertyGetter, ...) for the rare cases where you really need
> to get hold of the underlying function?

I don't see where the trouble is. If I thought the trait is necessary, I'd make it part of the proposal. Currently I don't see it as necessary, but I definitely can be convinced.


Andrei
February 04, 2013
On 2/3/13 11:17 PM, BLM768 wrote:
> On Monday, 4 February 2013 at 04:00:28 UTC, David Nadlinger wrote:
>> On Monday, 4 February 2013 at 03:15:51 UTC, David Nadlinger wrote:
>>
>> And how often do you think you'll find yourself in the situation of
>> needing to get a delegate from a property anyway? Can't we just make
>> »@property getter expressions are always equivalent to their return
>> value« a hard (simple!) rule and add something like
>> __traits(propertyGetter, ...) for the rare cases where you really need
>> to get hold of the underlying function?
>>
>> David
>
> I like this solution; it follows the Principle of Least Surprise
> quite well. The syntax may be a bit longer, but it's immediately
> obvious even to a beginning/intermediate D user what's going on
> without having to worry about too many nuances.

This is a good point, and __traits make all possible syntactic confusion go away.

Andrei
February 04, 2013
On 2/3/13 11:31 PM, Jonathan M Davis wrote:
> I tend to agree that making the parens change the nature of the expression is
> a bad idea.

I think there's some misunderstanding here. Parens change the nature of expressions ALL the time.

There is a weird rule in C++11 that makes sometimes typeof(expr) and typeof((expr)) mean different things. That is arguably an example to avoid. But introducing parens among parts of an expression is expected to affect meaning.


Andrei
February 04, 2013
2013/2/4 Andrei Alexandrescu <SeeWebsiteForEmail@erdani.org>

> On 2/3/13 11:00 PM, David Nadlinger wrote:
>
>>
>>  Now, grouping the expression »&a.b« according to the precedence rules
>> yields »&(a.b)« – but in your proposal, they mean completely different
>> things.
>>
>
> I agree they mean different things. I'm unclear that's a problem. All your examples stop here, there's no propagation of the issue. To take the address of a property, one writes &obj.prop. To take the address of a property's result, one writes &(obj.prop). And that's that. It all works with typeof.


If the expression is generated from string mixin, might have a problem.

// This is much simple case. Real example might be more complicated.
template AddressOf(string exp)
{
    enum AddressOf = "&" ~ exp;
}
struct S {
    @property int prop() { return 1; }
}
void main() {
    S s;
    assert(s.prop == 1);
    int* p = mixin(AddressOf!("s.prop"));  // &s.prop returns delegate
}

I think that parenthesis-dependent syntax is not good.

Kenji Hara


February 04, 2013
On Monday, 4 February 2013 at 05:36:10 UTC, Andrei Alexandrescu wrote:
> On 2/3/13 11:31 PM, Jonathan M Davis wrote:
>> I tend to agree that making the parens change the nature of the expression is
>> a bad idea.
>
> I think there's some misunderstanding here. Parens change the nature of expressions ALL the time.
>
> There is a weird rule in C++11 that makes sometimes typeof(expr) and typeof((expr)) mean different things. That is arguably an example to avoid. But introducing parens among parts of an expression is expected to affect meaning.
>

Weird behaviors of C++ are a very good reason to have D in the first place.
February 04, 2013
On Monday, 4 February 2013 at 05:32:39 UTC, Andrei Alexandrescu
wrote:
> On 2/3/13 11:00 PM, David Nadlinger wrote:
>> The problem I see is that usually, one can insert grouping pairs of
>> parentheses into an expression according to the operator
>> precedence/associativity rules at will without changing the result. This
>> isn't merely a theoretical exercise, but the way (well, in the form of
>> trees) I tend to reason about source code intuitively.
>
> Well this is going to sound bad, but you either use reason or intuition. I don't see how one can reason intuitively.
>

Yes, that is why, ideally, you want to close the gap as much as
possible.
February 04, 2013
On Monday, 4 February 2013 at 05:32:39 UTC, Andrei Alexandrescu wrote:
> On 2/3/13 11:00 PM, David Nadlinger wrote:
>> The problem I see is that usually, one can insert grouping pairs of
>> parentheses into an expression according to the operator
>> precedence/associativity rules at will without changing the result. This
>> isn't merely a theoretical exercise, but the way (well, in the form of
>> trees) I tend to reason about source code intuitively.
>
> Well this is going to sound bad, but you either use reason or intuition. I don't see how one can reason intuitively.
>
>> Now, grouping the expression »&a.b« according to the precedence rules
>> yields »&(a.b)« – but in your proposal, they mean completely different
>> things.
>
> I agree they mean different things. I'm unclear that's a problem. All your examples stop here, there's no propagation of the issue. To take the address of a property, one writes &obj.prop. To take the address of a property's result, one writes &(obj.prop). And that's that. It all works with typeof.
>
> [SNIP]
>
> Andrei

It was my understanding that once a function is declared a property, it is meant to emulate a field. In such circumstance, there were talks about plain and simply not allowing taking the address of an @property function.

2 questions:

1. Was this proposal rejected, or have we just forgotten about it?
2. What are the actual use cases for taking the address of a property function?

Unless I'm mistaken, the "entire mess" of &a.b would be solved if we simply recognized it as "but you aren't allowed to take the address of the function b, so why have a syntax to support it anyways"? In such circumstance, "&a.b" == "&(a.b)" == "the address of the thing obtaining by running a.b"
February 04, 2013
Am Mon, 04 Feb 2013 04:24:46 +0100
schrieb "TommiT" <tommitissari@hotmail.com>:

> On Monday, 4 February 2013 at 02:36:41 UTC, Timon Gehr wrote:
> > On 02/04/2013 03:23 AM, kenji hara wrote:
> >> Unfortunately, I can present a counterexample.
> >>
> >> struct S {
> >>     static int value;
> >>     static @property int foo() { return value; }
> >>     static @property void foo(int n) { value = n; }
> >>
> >> }
> >> void main() {
> >>     int n = S.foo;
> >>     S.foo = 1;
> >> }
> >>
> >> Should they be disallowed, as like module level properties?
> >>
> >> Kenji Hara
> >
> > Probably. (static essentially means module-level, but in a potentially nested name space.)
> 
> I disagree. Static properties can be allowed because they're not
> ambiguous. The problem with module-level:
> @property void foo(int n) {}
> ...are the two interpretations of foo as either a setter taking
> an int or a getter property of int type. So, one of those
> interpretations must be disallowed. But, with static member
> properties, there aren't multiple interpretations.

"getter property of int type"

But a getter shouldn't return void, right? So it's actually not ambiguous?
February 04, 2013
On 2013-02-03 17:11, Andrei Alexandrescu wrote:

> It's dangerous to get too clever about that. Anyhow, such rewrites are
> possible:
>
> ++a.p ----> { auto v = a.p; ++v; a.p = v; return v; }()
> a.p++ ----> { auto v = a.p; ++a.p; return v; }()
>
> and so on.

Is that part of the proposal or not?

-- 
/Jacob Carlborg