Jump to page: 1 2
Thread overview
[Issue 19057] 2.079 changelog variadic template and default arguments
Jul 05, 2018
Mike Franklin
Jul 05, 2018
Seb
Jul 05, 2018
Jonathan M Davis
Jul 06, 2018
Jonathan M Davis
Jul 08, 2018
Jonathan M Davis
Dec 17, 2022
Iain Buclaw
July 04, 2018
https://issues.dlang.org/show_bug.cgi?id=19057

johanengelen@weka.io changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
           Keywords|                            |industry

--
July 05, 2018
https://issues.dlang.org/show_bug.cgi?id=19057

Steven Schveighoffer <schveiguy@yahoo.com> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
                 CC|                            |schveiguy@yahoo.com

--- Comment #1 from Steven Schveighoffer <schveiguy@yahoo.com> ---
IMO, this should either be reverted or go through a deprecation cycle.

I'm  not seeing what the pros/cons are of each mechanism. Is there a discussion somewhere?

--
July 05, 2018
https://issues.dlang.org/show_bug.cgi?id=19057

Mike Franklin <slavo5150@yahoo.com> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
                 CC|                            |slavo5150@yahoo.com

--- Comment #2 from Mike Franklin <slavo5150@yahoo.com> ---
It appears the PR that implemented this was https://github.com/dlang/dmd/pull/7831

The changelog was then amended in https://github.com/dlang/dmd/pull/7875

A spec change was also made in https://github.com/dlang/dlang.org/pull/2169

--
July 05, 2018
https://issues.dlang.org/show_bug.cgi?id=19057

--- Comment #3 from Steven Schveighoffer <schveiguy@yahoo.com> ---
So the use case for the new style is pretty well discussed and documented (and makes a lot of sense). The use cases for the old style are not discussed really.

Looks like the only times default parameters were used is when the number of parameters was less than the default (then the variadic template was inferred as an empty list). I can potentially see the benefit there.

Can that functionality be duplicated with the new mechanism? That is the main question we have to answer. If it can, then the deprecation period can be relatively short, with a nice message on how to rewrite. If not, then I don't know what the right path is. Clearly it's a hugely useful thing to be able to specify default parameters for line and file without doing it in the template list.

Johan, do you have some sample code to show a good use case for the old way?

--
July 05, 2018
https://issues.dlang.org/show_bug.cgi?id=19057

Steven Schveighoffer <schveiguy@yahoo.com> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
           See Also|                            |https://issues.dlang.org/sh
                   |                            |ow_bug.cgi?id=8687

--
July 05, 2018
https://issues.dlang.org/show_bug.cgi?id=19057

Seb <greensunny12@gmail.com> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
                 CC|                            |greensunny12@gmail.com

--
July 05, 2018
https://issues.dlang.org/show_bug.cgi?id=19057

--- Comment #4 from johanengelen@weka.io ---
My concern is not about use cases. It's about breaking old code (silently), and
also about strange (arguable) language behavior in the current situation.

Note that before 2.079, the default argument was never used: the template would
not match (in the testcase, `bar("a","b");` would not compile pre-2.079).
(which is probably why Timothee wrote that it now becomes possible to use
default args)

Breaking old code:
The fact that default argument was never used in pre-2079 is bad news: it means
that old code always specifies a value for the default value, and thus that
with the new compiler things are always broken (except when the caller is not
using IFTI, which is unlikely I think).

Strange new behavior:
Adding a default value for a parameter now changes the template instantiation
(if IFTI is used, which I think will happen in the majority of cases).
```
// Adding the default value will change behavior.
void bar(Args...)(Args _args, int timeout /* = 0 */) {
    writeln(_args, timeout);
}
void main() {
    bar("a", "b", 2); // used to print "ab2", but since 2.079 prints "ab20"
}
```
How many people would expect that to happen?


The use case of the new style does not discuss much about how to override the
default value (something that is trivially explained for normal functions).
Here, you need to disable IFTI, which is painful. I've mainly seen discussion
of the use case with __FILE__, but not for the general case.
Note: there is no old use case, because the default value itself didn't work
(syntax was allowed, but always need to specify value for the parameter at call
site).
A better fix for the __FILE__ use case would perhaps have been something like
this:
`void bar(Args...)(Args args, TypeThatIsNeverMatched =
TypeThatIsNeverMatched.init, string file = __FILE__)`, where default arguments
work but IFTI matching on callsite first matches the non-variadic parameters,
and then starts matching the variadic part.

--
July 05, 2018
https://issues.dlang.org/show_bug.cgi?id=19057

Jonathan M Davis <issues.dlang@jmdavisProg.com> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
                 CC|                            |issues.dlang@jmdavisProg.co
                   |                            |m

--- Comment #5 from Jonathan M Davis <issues.dlang@jmdavisProg.com> ---
Honestly, I would guess that far more code has been written to take advantage of the new behavior since it was released than was ever purposefully written to use the old behavior. I think that many (most?) of us had no clue that there was any way to use default arguments with variadic templates and IFTI prior to the 2.079 release, and many were very interested in the new behavior, because it fixes the file and line problem. So, changing the behvior back (as would have to be done to deprecate it) would definitely break existing code (whereas I question that much code was broken with the change in 2.079), and we've now had three major releases with the new behvior. So, I don't think that it makes any sense to try and deprecate the old behavior at this point.

Clearly, the fact that this was a breaking change was not properly caught, and we should have deprecated the old behavior before introducing the new. But while that was definitely a screw-up, I don't see how it makes much sense to backtrack now.

The new behavior has been out for three releases and is something that enough folks were looking for that I expect that there are quite a few folks using it now. So, if anything, if we were to decide that the current behavior is undesirable, then we arguably need a deprecation warning for that, not the old behavior.

--
July 05, 2018
https://issues.dlang.org/show_bug.cgi?id=19057

--- Comment #6 from Steven Schveighoffer <schveiguy@yahoo.com> ---
OK, I misunderstood. So essentially, any function that uses variadic parameters AND a normal parameter with a default value was EXACTLY the same as a function which takes the varargs parameter and a normal parameter WITHOUT a default value prior to 2.079.

i.e. ALL code that uses default parameters after varargs parameters can be rewritten to simply remove the default parameter, and the same behavior occurred

But in addition, there is a strange new behavior that has default parameters NEVER match the parameters unless you disable IFTI.

Indeed I find it odd that this would be the case:

void foo(A...)(A a, int timeout) {}
void bar(A...)(A a, int timeout = 0) {}

foo(1); // equivalent to foo!()(1)
bar(1); // equivalent to bar!(int)(1, 0) ???

Given the use case of file and line parameters, this makes sense, as you almost never want to pass those parameters. But in the general case it makes very little sense.

I'm pretty sure phobos was changed to take advantage of this immediately. So reverting would be really painful, right?

If I were to start over before 2.079, this is the path I would have taken:

1. Make default parameters in these cases actually work in the way we would
expect (i.e. they match if they are the right type, otherwise they go to the
variadic).
2. Fix issue 18919
3. Create a new type `Location`, which accepts a filename and line number, and
use THAT as the final parameter for such functions, with a default value of
Location loc = Location(__FILE__, __LINE__). Now, you would never
"accidentally" pass in a file or line number.

I don't know the path forward now...

--
July 05, 2018
https://issues.dlang.org/show_bug.cgi?id=19057

--- Comment #7 from johanengelen@weka.io ---
Thanks for the support Steven.

<rant>
I hope this helps put the message across to be _very careful_ in making
language additions / changes. This should have been a DIP. And not a PR that
gets merged after a single (!) day.
It's not a good story at all for industrial use of D. Note that with the
current high-paced release cycle, testing of new compilers is guaranteed to
happen only after 2 new releases have happened, as I've argued before. Proof
given again in this bug report.
This did break code at Weka, luckily in non-silent way, but now I probably will
have to modify the old compiler to error on these things, to not cause trouble
with silently broken code.

Regardless of breakage, the new behavior is also one more special case to learn about in the language. I can already see style guides telling people to never use this functionality, except for __FILE__.

This is a bit of a rant, I know, my apologies for that, but it seems my message has not gotten through yet and I don't know how else than to just repeat it. </rant>

--
« First   ‹ Prev
1 2