On 27 August 2012 01:41, Walter Bright <newshound2@digitalmars.com> wrote:
On 8/26/2012 3:26 PM, Manu wrote:
I just updated to 2.60 and found errors throughout my code where function
pointers default args no longer work.
_Every single project_ I've written in D, 5 projects, don't work anymore,

including my projects at work.

I found this discussion: http://d.puremagic.com/issues/show_bug.cgi?id=3866
It seems the change was just decided and implemented with basically no
discussion or argument at all :/

My use cases are dynamic linkage, and cross-language integration.
I can't manually interact with DLL's containing API's that expect to have
default arguments if function pointers no longer support them.
Also when receiving foreign language function pointers, they frequently need to
have default args too.

I also integrate with many C style API's (rendering engines and the like), which
involve registration of various callbacks, and lots of those have default args too.

I find this particularly surprising, since I recently motivated implementation
of new traits which could parse default args from parameter lists, and use that
to generation function pointers in templates which auto-magically clone
functions parameter lists verbatim, specifically including the default args...

The trouble is that, as 3866 shows, there is no design anyone could come up with that worked in a consistent manner. The only consistent way out was to make default arguments a characteristic of the declaration, not of the type.

To be fair, it's not a very lively discussion. Spans 1 day, and only 3 people comment :)
Is that really an exhaustive set of options? It seems the other possibility (including the default arg in the equivalence test) wasn't really considered.

The part that I don't understand is how the situation manifests in the first place:

    auto foo = (int a = 1) { return a;};
    auto bar = (int a) { return a;};
    writeln(foo()); // writes '1'
    writeln(bar()); // writes '1' also!
These are 2 distinct assignments. I would expect foo and bar would each take a type that is technically equivalent, but foo's type would have the bonus default arg in its type record, just as a function pointer that were declared explicitly.
At what point does the compiler become confused? They never interact... The expected behaviour seems obvious to me, foo and bar should effectively be:
   int function(int a = 1) foo = ..;
   int function(int a) bar = ...;

I presume if I typed that code, there would be no problem?

The discussion is obviously regarding implementation details...?


The trouble for function pointers, is that any default args would need to be part of the type, not the declaration.

I thought they were part of the type already? I would have thought that's where they should be. Why is their new home more 'proper'?


I know it broke code (for many others, too), and I'm very sorry about that, but I don't see another way out.

It's a rather major breakage. I've seen you reject far more important changes solely on the grounds that they are a breaking change before...


(Many uses of default arguments can be replaced with overloaded functions.)

Can you suggest how? I can't think of a feasible approach.

You can't overload function pointers (multiple instances of variables with the same name). And by definition of a function pointer, I don't own the target function to overload it.
I can't reasonably produce static wrappers either, unless the wrapper receives the function pointer I intend to call as an arg, which is super nasty.

I can probably address the global/static ones via wrappers, but I don't love redundant function calls, it reduces debug build performance (see: all my rants about __forceinline), but that would only address the problem in a few situations.
This also undoes all that good work recently with the parameter list traits >_<


As I see it, calling a function is possibly the single most important thing a programming language does. Flexibility in this regard is valuable. Default args in function pointers was a HUGE selling point of D to me, I've made extremely liberal use of this feature to great benefit throughout all my projects.
But perhaps most importantly, this change has a huge impact on my code at work... I don't really want to imagine telling my boss that I need to rewrite the engine bindings and integration code. I'll look like the biggest dick this side of the Baltic :/