Feedback Thread: DIP 1033--Implicit Conversion of Expressions to Delegates--Final Review
MD-39
39.m.delnis at gmail.com
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.
https://run.dlang.io/is/Nu6gct
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