February 06, 2013 Re: DIP23 Counter Proposal | ||||
---|---|---|---|---|
| ||||
Posted in reply to deadalnix | On 02/06/2013 04:31 AM, deadalnix wrote: > On Wednesday, 6 February 2013 at 00:39:55 UTC, Timon Gehr wrote: >> As my posts in the DIP23 thread have been left unanswered, I have >> prepared a counter proposal for DIP23 during the last hour. >> >> Everything DIP23 addresses is specified in the two short sub-sections >> "Optional parens" and "@property: basic design". >> >> Those in favour of what was called "semantic rewrites" in the DIP23 >> thread should probably read on further. >> >> All parts of this proposal are independent of DIP24 (which Andrei is >> preparing). >> >> http://wiki.dlang.org/DIP23_Counter_Proposal >> >> There are almost no examples yet, but in case it is not clear how some >> case would be handled, feel free to ask. >> > > I have to spend more time on the @property part. > > For the optional () part, I want to raise concern about point 2 (the > others make sense). > > In all other points, foo is either a call to function foo or the > function foo itself. In point 2, we introduce a 3rd meaning of foo, > identical to weird stuff we have in C/C++ (as we obviously aren't taking > the address either of the function or of its result when executed). This > object is an error of C and C++ we must get rid of. > 1. This would break a lot of code. 2. How to get a first-class function value (function pointer, delegate) from a function name otherwise? > Point 1, 4 and 5 make sense. > > Point 3 is nonsensial if we want to really be rigorous as : > returnType foo(TemplateArgs)(args) {} > > is equivalent to > > template foo(TemplateArgs) { > returnType foo(args) {} > } > > In this case foo is a template, Yes, a function template. Note that functions overload against function templates. > not a function. foo!args is the function > hen eponymous trick is used. I think you misunderstand. If we have eg: void foo(){ return 2; } void foo(int x)(){ return 2; } then we want: static assert(foo!2==2); Without rule 3, the code would be rewritten to static assert(foo()!2==2); And this would fail. |
February 06, 2013 Re: DIP23 Counter Proposal | ||||
---|---|---|---|---|
| ||||
Posted in reply to Timon Gehr | On Wednesday, 6 February 2013 at 03:43:28 UTC, Timon Gehr wrote: >> For the optional () part, I want to raise concern about point 2 (the >> others make sense). >> >> In all other points, foo is either a call to function foo or the >> function foo itself. In point 2, we introduce a 3rd meaning of foo, >> identical to weird stuff we have in C/C++ (as we obviously aren't taking >> the address either of the function or of its result when executed). This >> object is an error of C and C++ we must get rid of. >> > > 1. This would break a lot of code. > 2. How to get a first-class function value (function pointer, delegate) from a function name otherwise? > 2. I see no point in not making foo a first class function value. Not having it does complicate things for no benefit. Any complication should be properly motivated. This does not imply that optional () should be removed, as it is a mostly orthogonal problems (as scala shows). 1. As of backward compat, & can be kept and follow the usual deprecation process. >> Point 1, 4 and 5 make sense. >> >> Point 3 is nonsensial if we want to really be rigorous as : >> returnType foo(TemplateArgs)(args) {} >> >> is equivalent to >> >> template foo(TemplateArgs) { >> returnType foo(args) {} >> } >> >> In this case foo is a template, > > Yes, a function template. Note that functions overload against function templates. > >> not a function. foo!args is the function >> hen eponymous trick is used. > > I think you misunderstand. > > If we have eg: > > void foo(){ return 2; } > void foo(int x)(){ return 2; } > > then we want: > > static assert(foo!2==2); > > Without rule 3, the code would be rewritten to > > static assert(foo()!2==2); > > And this would fail. Well the thing that a function CANNOT be used before template parameter (so function will be removed from overload set and only template will remains). |
February 06, 2013 Re: DIP23 Counter Proposal | ||||
---|---|---|---|---|
| ||||
Posted in reply to Timon Gehr | On 2013-02-06 04:43, Timon Gehr wrote: > Yes, a function template. Note that functions overload against function > templates. Maybe I'm misunderstanding something there but since when? Example: void foo () {} void foo (T) (T t) {} void main () {} Error: template main.foo(T)(T t) conflicts with function main.foo at... -- /Jacob Carlborg |
February 06, 2013 Re: DIP23 Counter Proposal | ||||
---|---|---|---|---|
| ||||
Posted in reply to Timon Gehr | On 2013-02-06 01:39, Timon Gehr wrote: > As my posts in the DIP23 thread have been left unanswered, I have > prepared a counter proposal for DIP23 during the last hour. > > Everything DIP23 addresses is specified in the two short sub-sections > "Optional parens" and "@property: basic design". > > Those in favour of what was called "semantic rewrites" in the DIP23 > thread should probably read on further. > > All parts of this proposal are independent of DIP24 (which Andrei is > preparing). > > http://wiki.dlang.org/DIP23_Counter_Proposal > > There are almost no examples yet, but in case it is not clear how some > case would be handled, feel free to ask. > > > (Also feel free to fix the formatting.) +1 I would be nice with a couple of more examples. -- /Jacob Carlborg |
February 06, 2013 Re: DIP23 Counter Proposal | ||||
---|---|---|---|---|
| ||||
Posted in reply to Jacob Carlborg | On Wednesday, February 06, 2013 08:34:32 Jacob Carlborg wrote:
> On 2013-02-06 04:43, Timon Gehr wrote:
> > Yes, a function template. Note that functions overload against function templates.
>
> Maybe I'm misunderstanding something there but since when? Example:
>
> void foo () {}
> void foo (T) (T t) {}
>
> void main () {}
>
> Error: template main.foo(T)(T t) conflicts with function main.foo at...
They're _supposed_ to, but it's a long-standing bug that they don't, and AFAIK, it has yet to be fixed.
- Jonathan M Davis
|
February 06, 2013 Re: DIP23 Counter Proposal | ||||
---|---|---|---|---|
| ||||
Posted in reply to Jacob Carlborg | On Wednesday, 6 February 2013 at 07:34:33 UTC, Jacob Carlborg wrote:
> On 2013-02-06 04:43, Timon Gehr wrote:
>
>> Yes, a function template. Note that functions overload against function
>> templates.
>
> Maybe I'm misunderstanding something there but since when? Example:
>
> void foo () {}
> void foo (T) (T t) {}
>
> void main () {}
>
> Error: template main.foo(T)(T t) conflicts with function main.foo at...
That is dmd's implementation, but not what the spec says.
|
February 06, 2013 Re: DIP23 Counter Proposal | ||||
---|---|---|---|---|
| ||||
Posted in reply to deadalnix | On 2013-02-06 09:07, deadalnix wrote: > That is dmd's implementation, but not what the spec says. I can't see that the spec says anything about this. It doesn't say it's legal neither illegal. -- /Jacob Carlborg |
February 06, 2013 Re: DIP23 Counter Proposal | ||||
---|---|---|---|---|
| ||||
Posted in reply to Jacob Carlborg | On Wednesday, February 06, 2013 09:42:49 Jacob Carlborg wrote: > On 2013-02-06 09:07, deadalnix wrote: > > That is dmd's implementation, but not what the spec says. > > I can't see that the spec says anything about this. It doesn't say it's legal neither illegal. I don't know what the spec says (I'd have to go digging through it), but TDPL is quite clear on the matter. And it's still in bugzilla as a bug: http://d.puremagic.com/issues/show_bug.cgi?id=1528 I really don't think that there's any question that it's supposed to work. It's just that the implementation hasn't been fixed yet. - Jonathan M Davis |
February 06, 2013 Re: DIP23 Counter Proposal | ||||
---|---|---|---|---|
| ||||
Posted in reply to deadalnix | On 02/06/2013 06:12 AM, deadalnix wrote: > On Wednesday, 6 February 2013 at 03:43:28 UTC, Timon Gehr wrote: >>> For the optional () part, I want to raise concern about point 2 (the >>> others make sense). >>> >>> In all other points, foo is either a call to function foo or the >>> function foo itself. In point 2, we introduce a 3rd meaning of foo, >>> identical to weird stuff we have in C/C++ (as we obviously aren't taking >>> the address either of the function or of its result when executed). This >>> object is an error of C and C++ we must get rid of. >>> >> >> 1. This would break a lot of code. >> 2. How to get a first-class function value (function pointer, >> delegate) from a function name otherwise? >> > > 2. I see no point in not making foo a first class function value. > Not having it does complicate things for no benefit. Any > complication should be properly motivated. > > This does not imply that optional () should be removed, as it is > a mostly orthogonal problems (as scala shows). > So you would prefer Scala-like syntax? Scala uses suffix _ for what we use prefix &. Without something like that, type deduction is crippled. > 1. As of backward compat, & can be kept and follow the usual > deprecation process. > I think this language change is not part of the DIP that fixes optional parens and @property, but a separate improvement. >>> ... >>> Point 3 is nonsensial if we want to really be rigorous as : >>> returnType foo(TemplateArgs)(args) {} >>> >>> is equivalent to >>> >>> template foo(TemplateArgs) { >>> returnType foo(args) {} >>> } >>> >>> In this case foo is a template, >> >> Yes, a function template. Note that functions overload against >> function templates. >> >>> not a function. foo!args is the function >>> hen eponymous trick is used. >> >> I think you misunderstand. >> >> If we have eg: >> >> void foo(){ return 2; } >> void foo(int x)(){ return 2; } >> >> then we want: >> >> static assert(foo!2==2); >> >> Without rule 3, the code would be rewritten to >> >> static assert(foo()!2==2); >> >> And this would fail. > > Well the thing that a function CANNOT be used before template parameter > (so function will be removed from overload set and only template will > remains). foo _is_ the overload set. In order to decide whether to rewrite it to foo() or not, it is necessary to look at the context ("before template parameter"), which is what rule 3 states. My example is still valid if you make the first overload templated. The rewrites must happen before overload resolution. In fact, they may decide which overload is ultimately chosen. (You can be certain that my working implementation of optional parens would cease to work if I removed rule 3.) |
February 06, 2013 Re: DIP23 Counter Proposal | ||||
---|---|---|---|---|
| ||||
Posted in reply to Timon Gehr | On 2/5/13 7:39 PM, Timon Gehr wrote:
> As my posts in the DIP23 thread have been left unanswered, I have
> prepared a counter proposal for DIP23 during the last hour.
>
> Everything DIP23 addresses is specified in the two short sub-sections
> "Optional parens" and "@property: basic design".
>
> Those in favour of what was called "semantic rewrites" in the DIP23
> thread should probably read on further.
>
> All parts of this proposal are independent of DIP24 (which Andrei is
> preparing).
>
> http://wiki.dlang.org/DIP23_Counter_Proposal
>
> There are almost no examples yet, but in case it is not clear how some
> case would be handled, feel free to ask.
So syntactic case (2) prescribes that when foo is in address-taken position "&foo", that means take its address as opposed to evaluate foo. That makes the use of "&" here sheer punctuation, as opposed to operator.
There's also "(Note that redundant parentheses are assumed to be dropped in the parsing stage.)" It's unclear whether this makes &(foo) and &(((foo))) identical to &foo. If they don't, then "&" is not an operator in the expression "&foo" because an operator should be applicable to a parenthesized expression. If they do, in this context parens are also punctuation, not expression grouping; they don't enclose an expression, but instead define &(((...(foo)...))) as a sole syntactic unit (!).
This also leads to potential confusion, seeing as &(foo) takes the address of foo, but &( true ? foo : bar ) does, in fact, take the address of whatever foo returns. This makes the role of "&", "(", and ")" in the proposal as both punctuation and operator painfully visible.
This all makes DIP24 fail meet its own definition of success as far as I understand it, i.e. keeping "&" to mean operator and parens to mean grouping. In my opinion, it also makes DIP24 fail to improve over DIP23.
DIP23 has in fact /fewer/ such problems, because it clarifies that &foo and &expr.foo are indivisible syntactic units; thus parentheses are not ascribed a special meaning by DIP23. On the contrary, as soon as parens are used, as in &(foo) or &( true ? foo : bar ), the usual meaning of parens enters in action and give the expression inside the usual meaning.
I should point out that that's all okay, but we got to be clear about it. Tokens are used as both punctuation and operators all the time. For example, it may sound weird that (stuff) and ((stuff)) should ever mean distinct things, but writeln((1, 2)) does something different from writeln(1, 2). This is because the outer layer is punctuation and the inner layer is expression grouping. And nobody blinks an eye. The language just needs to be as clear as possible about which is which.
If DIP25 gets approved, taking the address of ref results will be banned, and therefore that potential meaning of "&" disappears, which simplifies things. But we'll still have to live with the reality that in the constructs "&foo" and "&expr.foo", "&" is not an operator. And that's okay.
Andrei
|
Copyright © 1999-2021 by the D Language Foundation