DIP23 Counter Proposal

Steven Schveighoffer schveiguy at yahoo.com
Fri Feb 8 09:46:10 PST 2013


On Thu, 07 Feb 2013 23:22:45 -0500, deadalnix <deadalnix at gmail.com> wrote:

> On Thursday, 7 February 2013 at 13:56:17 UTC, Steven Schveighoffer wrote:
>> On Wed, 06 Feb 2013 21:53:25 -0500, deadalnix <deadalnix at gmail.com>  
>> wrote:
>>
>>> On Wednesday, 6 February 2013 at 21:30:10 UTC, Timon Gehr wrote:
>>>>> &(fun, fun)
>>>>>
>>>>
>>>> Agh, comma strikes again. It should be handled analogous to the  
>>>> ternary expression. i.e. the expression above evaluates fun and then  
>>>> returns the function pointer. The DIP now states this. (the second  
>>>> fun is in address-taken position.) This is in agreement to how lvalue  
>>>> positions propagate into comma expressions.
>>>>
>>>
>>> Adding more special cases are not gonna create a good DIP.
>>
>> I don't they are so much a special case, as they are a clarification.
>>
>> The two "exceptions" are simply explaining that because ternary  
>> operator and comma operators evaluate to an lvalue, it is equivalent to  
>> putting the & on the resulting lvalue.
>>
>
> You have the following behavior :
>   - & take the address of what is before.
>   - foo is call to function foo.
>   - special case : &foo is the first class function foo. (here  
> expression foo have a new meaning).
>   - In a comma expression, if the last item is a function, it is  
> evaluated, unless the comma expression is in an address of context, in  
> which case the function pointer is returned.

I think it's consistent, and no special cases.

foo is treated as a fucntion name, until it is evaluated without any  
adornments, in which case it becomes a function call, or when the address  
operator is applied to it.

In other words:

&(foo, foo); => foo(); &(foo); => foo(); &foo;

(foo, foo); => foo(); foo; => foo(); foo();

Let's note here that by opting on the side of NOT adding optional parens  
by default, both cases are possible:

&(foo, foo());
and
&(foo, foo);

Under DIP23 (and the current implementation), both are equivalent, and  
expressive power is less.

>   - Same goes for ternary, except that both branches are evaluated in  
> that context.

I would see the expression the same way, foo's meaning is not evaluated  
until the ternary expression is resolved.  For example:

condition ? foo : foo; => foo; => foo();

&(condition ? foo : foo) => &(foo); => &foo;

> This is exactly how special case (3) turtle down to definition of many  
> other languages constructs. For instance,
>
> int a;
> int foo() { return a }
>
> static assert(is(typeof(foo) == typeof(a))); // Pass

I'm unsure whether this should pass or fail.  It seems disingenuous to  
make typeof(foo) equivalent to typeof(foo()), since foo is NOT an  
integer.  If we err on the side of expressiveness, typeof(foo) should be  
the function type, not an int.

> condition ? foo : a; // OK.

I would say not ok.  you have to do:

condition ? foo() : a;

> &(condition ? foo : a); // Type error between foo of unexpressible type

Same, also not ok.

This all seems consistent to me.  It is more consistent than either the  
current dmd implementation, or the proposed DIP23.

I can see however, that no matter what, there is going to be confusion.   
The simple rule is that optional parentheses only apply after all other  
reductions do not consider the function name as a function.  The meaning  
of foo could be explicitly considered as a function call by including the  
parentheses.

-Steve


More information about the Digitalmars-d mailing list