digitalmars.D - proposal to disambiguate &a.fun: disable optional parenthesis INSIDE
- timotheecour (42/42) Feb 04 2013 There's current disagreement regarding the syntax &a.fun, as it
- deadalnix (2/11) Feb 04 2013 MOAR special cases !
- monarch_dodra (15/59) Feb 04 2013 As I asked in the other thread: What is the point of even
- FG (19/29) Feb 04 2013 Yes, but this is not just about properties but also normal functions:
- Andrei Alexandrescu (3/12) Feb 04 2013 Hah! I swear I posted before seeing this :o).
- Timon Gehr (4/8) Feb 04 2013 The entire optional parens/@property thing is about (limited)
- FG (22/30) Feb 04 2013 Indeed, currently there isn't and, considering the use of optional paren...
There's current disagreement regarding the syntax &a.fun, as it makes &a.fun be different from &(a.fun): &a.fun : address of member function &(a.fun) : address of return value of a.fun This breaks the usual rules of scoping and makes the expression &a.fun special. More complex cases can arise, eg: &a.b.c, &(a+b).c, etc as pointed out by others, plus who knows what else might come up in practice. Here's a very simple proposal: for anything INSIDE &() operator, optional parenthesis are NOT allowed: &(fun) : address of function fun &(a.fun) : address of member function fun (different from DIP23) &(a.fun()) : address of element returned by a.fun() &fun : same as &(fun) Now when fun is a property: I would propose to break one rule to make everything else more consistent: treat properties as normal functions inside the &() operator, so that we can distinguish as above the address of property vs adress of return type. This is the only time a property can be called with parens: eg &(a.fun) : address of property fun &(a.fun()) : address of return type of property fun The last point of this proposal is what to do with the expression without parens: &a.fun : current behavior in DIP23: address of member function fun proposed behavior: there are 3 options, please chime in: A1) disallow this with compile time error, forcing user to disambiguate as: - (&a).fun - &(a.fun) - &(a.fun()) A2) interpret it as : (&a).fun, which would make the rule for "&" consistent with the rule for template "!" operator: B!double.x <=> (B!(double)).x) ---- template B(T){ T x; } void main(){assert(is(typeof(B!double.x) == double)); //same as (B!(double)).x) } ---- A3) decide whether to interpret it as address of function or of return type, but again, the user can disambiguate with the preferred &() syntax.
Feb 04 2013
On Monday, 4 February 2013 at 10:09:09 UTC, timotheecour wrote:There's current disagreement regarding the syntax &a.fun, as it makes &a.fun be different from &(a.fun): &a.fun : address of member function &(a.fun) : address of return value of a.fun This breaks the usual rules of scoping and makes the expression &a.fun special. More complex cases can arise, eg: &a.b.c, &(a+b).c, etc as pointed out by others, plus who knows what else might come up in practice. Here's a very simple proposal:MOAR special cases !
Feb 04 2013
On Monday, 4 February 2013 at 10:09:09 UTC, timotheecour wrote:There's current disagreement regarding the syntax &a.fun, as it makes &a.fun be different from &(a.fun): &a.fun : address of member function &(a.fun) : address of return value of a.fun This breaks the usual rules of scoping and makes the expression &a.fun special. More complex cases can arise, eg: &a.b.c, &(a+b).c, etc as pointed out by others, plus who knows what else might come up in practice. Here's a very simple proposal: for anything INSIDE &() operator, optional parenthesis are NOT allowed: &(fun) : address of function fun &(a.fun) : address of member function fun (different from DIP23) &(a.fun()) : address of element returned by a.fun() &fun : same as &(fun) Now when fun is a property: I would propose to break one rule to make everything else more consistent: treat properties as normal functions inside the &() operator, so that we can distinguish as above the address of property vs adress of return type. This is the only time a property can be called with parens: eg &(a.fun) : address of property fun &(a.fun()) : address of return type of property fun The last point of this proposal is what to do with the expression without parens: &a.fun : current behavior in DIP23: address of member function fun proposed behavior: there are 3 options, please chime in: A1) disallow this with compile time error, forcing user to disambiguate as: - (&a).fun - &(a.fun) - &(a.fun()) A2) interpret it as : (&a).fun, which would make the rule for "&" consistent with the rule for template "!" operator: B!double.x <=> (B!(double)).x) ---- template B(T){ T x; } void main(){assert(is(typeof(B!double.x) == double)); //same as (B!(double)).x) } ---- A3) decide whether to interpret it as address of function or of return type, but again, the user can disambiguate with the preferred &() syntax.As I asked in the other thread: What is the point of even allowing taking the address of a property function? If a property is designed as something that can encapsulate and emulate a field, then it makes to sense to get the address of the getter (As far as I can tell). If we already have optional parenthesis, then why even bother having property getters? They would end up being exactly the same thing as a normal function... I say that if "b" is a property, then "a.b" should mean "the thing returned by b", *regardless of context*. Simple as that: "&a.b" => address of what is gotten with "a.b" "&(a.b)" => address of what is gotten with "a.b" Simple, no? As for "how do I take the address of the function b": "You can't".
Feb 04 2013
On 2013-02-04 11:20, monarch_dodra wrote:As I asked in the other thread: What is the point of even allowing taking the address of a property function? If a property is designed as something that can encapsulate and emulate a field, then it makes to sense to get the address of the getter (As far as I can tell).Yes, but this is not just about properties but also normal functions: foo; // calling foo &foo; // delegate of foo &foo(); // calling and taking address of ref return &(foo());// calling and taking address of ref return &(foo); // OLD: delegate of foo &(foo); // NEW: calling foo and taking address of ref return The change in behavior of &(expr) makes sense in the light that "expr" should behave the same in every context, not just in &(...), i.e. call foo(). As for properties, they will never be truly exchangeable with variables, therefore being able to pass around their function pointers is useful. Naturally taking their address doesn't have to follow the same rules, but why shouldn't they behave like other functions in "typeof(&prop)"?If we already have optional parenthesis, then why even bother having property getters? They would end up being exactly the same thing as a normal function...Indeed, their existence is not essential. They may be more useful when the operator rewriting is done. The biggest problem is with the amount of code that uses "prop = x" syntax, which doesn't play well with optional parentheses.if "b" is a property, then "a.b" should mean "the thing returned by b", *regardless of context*. Simple as that: "&a.b" => address of what is gotten with "a.b" "&(a.b)" => address of what is gotten with "a.b"For me only "&(a.b)" is about the context of "a.b". "&a.b" is something completely different from "a.b", hence doesn't have to produce same output.
Feb 04 2013
On 2/4/13 8:37 AM, FG wrote:On 2013-02-04 11:20, monarch_dodra wrote:Hah! I swear I posted before seeing this :o). AndreiAs I asked in the other thread: What is the point of even allowing taking the address of a property function? If a property is designed as something that can encapsulate and emulate a field, then it makes to sense to get the address of the getter (As far as I can tell).Yes, but this is not just about properties but also normal functions:
Feb 04 2013
On 02/04/2013 02:37 PM, FG wrote:... The change in behavior of &(expr) makes sense in the light that "expr" should behave the same in every context, not just in &(...), i.e. call foo(). ...The entire optional parens/ property thing is about (limited) context-dependent behaviour! This line of reasoning is simply wrong. There is no difference whatsoever between &expr and &(expr).
Feb 04 2013
On 2013-02-04 15:42, Timon Gehr wrote:On 02/04/2013 02:37 PM, FG wrote:Indeed, currently there isn't and, considering the use of optional parentheses for delimiting and grouping, it also makes sense to treat &expr as &(expr). Oh, wait, no -- this leads straight to the OP's idea, which is: Rule of optional parentheses omission doesn't work in the context of '&'. Properties on the other hand need a different kind of treatment here. Forcing properties to also use parentheses here is a bad idea: &obj.prop; // a delegate? &obj.prop(); // address of the returned referenced data? Bad! This would make some typical code awkward: void* p1 = &someRange.retro.front; // suddenly it's a function pointer, not pointer to the element :( void* p2 = &someRange.retro.front(); // but having to add () just feels wrong. Therefore it's better for &prop to become the address of return data and to use some __traits or special member (like prop.__delegate) for taking address of the property: auto a = &someRange.retro.front; // address of element, yay auto b = someRange.retro.front.__delegate; // a delegate of front Simple enough? To specify exactly which prop we want it could even become: prop.__delegate(RetType, FirstArgType, SecondArgType)... The change in behavior of &(expr) makes sense in the light that "expr" should behave the same in every context, not just in &(...), i.e. call foo(). ...The entire optional parens/ property thing is about (limited) context-dependent behaviour! This line of reasoning is simply wrong. There is no difference whatsoever between &expr and &(expr).
Feb 04 2013