October 02, 2017
Andrei suggests we take a closer look at alternatives to DIP 1011 (extern(delegate)) that can be implemented in a library.  In the past I've failed to come up with anything good, however, my last attempt seemed to be less horrible than before.  I'm inviting anyone to view/modify my feeble attempt at a solution here https://github.com/marler8997/externdelegate

A good library solution would be great but my current solution has problems.  It doesn't really support template parameters yet and I'm not sure if it can be solved in the general case without pulling in a fair chunk of the language grammar into the library. Assuming that can be fixed, the bigger concern is that the API to define a "delegate function" looks very awkward.  It provides a template mixin that you can use to create a delegate function by passing in your function definition as a string.

With the current solution I believe its very unlikely that applications would use the library. Keep in mind that this feature is something that a library could use on most or all of it's functions.  If it has to use such an awkward syntax it's highly unlikely it would be used at that scale.  Not to mention that when you start pushing the limits of the language like this you almost always run into bugs and end up having to go with a different solution.  Also I haven't measured it but I'm almost certain this would greatly increase compile time as more functions start using it.

October 03, 2017
On Monday, 2 October 2017 at 07:48:54 UTC, Jonathan Marler wrote:
> Andrei suggests we take a closer look at alternatives to DIP 1011 (extern(delegate)) that can be implemented in a library.  In the past I've failed to come up with anything good, however, my last attempt seemed to be less horrible than before.  I'm inviting anyone to view/modify my feeble attempt at a solution here https://github.com/marler8997/externdelegate
>
> A good library solution would be great but my current solution has problems.  It doesn't really support template parameters yet and I'm not sure if it can be solved in the general case without pulling in a fair chunk of the language grammar into the library. Assuming that can be fixed, the bigger concern is that the API to define a "delegate function" looks very awkward.  It provides a template mixin that you can use to create a delegate function by passing in your function definition as a string.
>
> With the current solution I believe its very unlikely that applications would use the library. Keep in mind that this feature is something that a library could use on most or all of it's functions.  If it has to use such an awkward syntax it's highly unlikely it would be used at that scale.  Not to mention that when you start pushing the limits of the language like this you almost always run into bugs and end up having to go with a different solution.  Also I haven't measured it but I'm almost certain this would greatly increase compile time as more functions start using it.

I've improved the solution.  I've gotten templates to work, however, template parameter deduction won't work because I'm currently defining the delegate functions as structs.  I'm including a bit of code to demonstrate the solution.  The example will demonstrate how to define a "delegate function" that uses a File object for it's context.  The function is called "importantWriteln" which simply calls writeln with a prefix of "Important: ".  Here's how you would define that function:

    mixin delegateFunctionImpl!("importantWriteln", "(T...)", "File", "file", "T args",
    q{
        file.writeln("Important: ", args);
    });

This is the code that the mixin would generate:

    struct importantWriteln(T...)
    {
        File file;
        auto opCall(T args)
        {
            file.writeln("Important: ", args);
        }
        pragma(inline) static auto opCall(ref File file, T args)
        {
            return (cast(importantWriteln*)&file).opCall(args);
        }
        // NOTE: this doesn't quite work yet if there are template parameters
        pragma(inline) static auto createDelegate(T...)(ref File file)
        {
            return &(cast(importantWriteln*)&file).opCall;
        }
    }

And here's how you would use it:

    // call like a normal function
    importantWriteln!(string,string)(stdout, "Hello, ", "World!");
    // NOTE: template type deduction doesn't work since importantWriteln is a struct

    // call like a delegate
    auto dg = importantWriteln!(string,string).createDelegate(stdout);
    dg("Hello, ", "again");

The worst part about this solution is how you define the function.  The way I evaluate the solution is I think about ALL the functions in phobos that could use this feature (most functions that would normally be called using UFCS are good candidates) then think about whether I could create a pull request to make them all delegate functions.  Given this solution, I don't think that it would be accepted.