D needs a type expression syntax
Quirin Schroll
qs.il.paperinik at gmail.com
Sat May 6 16:20:56 UTC 2023
On Friday, 5 May 2023 at 15:11:50 UTC, Nick Treleaven wrote:
> On Thursday, 4 May 2023 at 15:40:20 UTC, Quirin Schroll wrote:
>> ```d
>> ref int refId (ref int i) => i;
>> ref int function(ref int i) refIdPtr = &refId; // Doesn’t
>> parse!
>> ```
>> You can declare `refIdPtr` with `auto` because the type of
>> `&refId` is 100 % well-formed, it’s just a syntax issue
>> spelling it out in code; if you `pragma(msg,
>> typeof(refIdPtr))` you get:
>> ```d
>> int function(ref int i) ref
>> ```
>> Interesting where the `ref` is, isn’t it? Go ahead, try using
>> *that* instead of `auto`. It doesn’t parse! And frankly, it
>> shouldn’t; it’s confusing to read.
>
> It could be trailing return type syntax:
> ```d
> function(ref int i) -> ref int refIdPtr;
> ```
> Then we don't need the `alias A = ref T` rule, and we can keep
> parentheses for expressions (including tuples in future).
I agree that trailing return types (TRT) are really well readable
– in a language designed around them, which D isn’t. I find it
irritating that the `-> Type` is followed by the variable name.
In languages that have them, variables are declared by a keyword,
then follows the name, then a separator and then comes the type.
In that order, TRT makes sense.
> Trailing return is much easier to read, when you read a
> function signature the return type is not as salient as the
> name or the parameter list (particularly as there's no
> overloading by return type). The return type gets in the way,
> especially when its a complex type:
> ```
> some_package.Foo!(const(ElementType!R)[]) oh_hi(long parameter,
> list following)
> ```
> Some people also recommend putting attributes after the
> parameter list rather than before the declaration for this
> reason.
I do that. I’ll never understand why people use them in front.
And why `unittest` don’t work with trailing attributes. It’s
inconsistent and annoying.
I put parts of a declaration in their own line when they’re
getting big: Big return type → own line. 1 big (template)
parameter or lots of them → each its own line. Constraints and
contracts → own line (always). It’s another thing what a
documentation generator makes of them.
```d
some_package.Foo!(const(ElementType!R)[])
oh_hi(R, T)(
T parameter,
...
)
const @safe pure
if (T.sizeof > 0)
in (true)
out(r; true)
{
…
}
```
> Imagine in an IDE seeing a list of function overloads, if they
> were shown with trailing return syntax it would be much easier
> to find the overload you want.
Could be. When looking through overloads, the important part is
the parameters.
TRT are are a much greater language change, though, compared to
making a token at a very specific place optional. Their grammar
must really be implemented and maintained separately. Also, we
get the same as C++: Two ways to declare a function.
>> ```d
>> const Object function() f0; // Make this an error …
>> const (Object function()) f1; // … and require this!
>> (const Object) function() f2; // To differentiate from this.
>> const(Object) function() f3; // (Same type as f2)
>> ```
>
> I don't get what the issue is with f0 and f3, aren't they clear
> enough?
With `f0`: Does `const` apply to the return value or the variable
`f0`? I’m quite adept with D and I’m only 95% sure it applies to
`f0`. 95 is not 100, and frankly, when it comes to syntax, it
should be 100.
With `f3`: Less of an issue, but basically the same. To someone
new to D, it might be odd that `const` applies to something
different if a parenthesis follows.
`f1` and `f2` are beyond misapprehension. If you show any
programmer what `const` applies to (return type or the declared
variable), they’ll assume it’s a trick question because the
answer is plain obvious.
More information about the Digitalmars-d
mailing list