Feedback Thread: DIP 1033--Implicit Conversion of Expressions to Delegates--Final Review

MD-39 39.m.delnis at
Sat Nov 21 00:40:48 UTC 2020

There's a few problems and some things I don't really agree with. 
I'll start with the most obvious problem regarding the example 
with absolutePath.

> pure @safe string absolutePath(string path, string delegate() 
> base = getcwd());

This becomes (per the DIP):

pure @safe string absolutePath(string path, string delegate() 
base = () @trusted { return getcwd() });

Which would still give an error, though the delegate 
encapsulating getcwd() is auto inferred, the actually parameter 
isn't auto inferred according to existing rules.

The parameter `base` is both impure and @unsafe. Unless there is 
some auto inference happening here this would fail to compile. It 
wouldn't be used the same way, the implementation would have to 
change to assume `base` is pure and @safe.

If there is auto inference of parameter types, the DIP needs to 
outline the details for this. Again, it would still be impure 
even if it auto inferred to be @trusted from `getcwd`. So again, 
the implementation would have to change to assume `base` is pure.

In either case, the code is broken and/or is giving the illusion 
that the problem at hand is simpler than it actually is by 
masking implementation details.

The DIP also doesn't go over one of the common discussions 
regarding lazy that is brought up from time to time; in regards 
to readability. This would be a good case to implement it. For 
example in C# at the call site the keyword `ref` has to be added 
when passing an argument to a ref parameter. Similarly you would 
just use a lambda `() =>` in C#, there is no special case to 
implicitly convert to a delegate.

> int delegate() dg = () { return 3; };
> int delegate() dg = () => 3;
> int delegate() dg = { return 3; };
> int delegate() dg = 3;

When you have 4 ways to express the exact same thing, there is an 
obvious design problem. You shouldn't need 4 different ways to 
express the same thing.

The existing Lambda syntax already has a lot of confusion, it 
isn't uncommon for individuals to mistakenly do the following:

     auto dg = x => { return x * x; };

Which doesn't do what it appears to do.

This would introduce syntax that can be similarly misunderstood. 
AS follows, the similar syntax can be used today. This code may 
not be common but it illustrates the commonality in the syntax, 
as calling a function doesn't require the `()` parenthesis.

     alias FooDelegate = int delegate();
     struct A {
         FooDelegate a() { return null; }

     void main()
         A a;
         int delegate() t = a.a;

In summation, this is just replacing something that already was 
and is repeating past mistake*s*. Ultimately this is just syntax 
sugar to avoid 4 characters `() =>`. The justification is flimsy 
(along with errors in the DIP) and the benefit isn't outweighed 
by the hit to readability and the potential for that improvement 
by requiring to just define a delegate.

I really hope this DIP is at least delayed, as once it is added 
it won't be removed. If the implicit conversion does end up being 
needed for some reason, a better justification could be 
formulated with that reason and then be additively introduced at 
a later date.

More information about the Digitalmars-d mailing list