Implicit conversion to mutable if no indirections?
Quirin Schroll
qs.il.paperinik at gmail.com
Tue Sep 6 10:06:59 UTC 2022
On Sunday, 4 September 2022 at 14:45:15 UTC, Meta wrote:
> On Sunday, 4 September 2022 at 12:33:37 UTC, Mathias LANG wrote:
>> On Sunday, 4 September 2022 at 11:03:53 UTC, Nick Treleaven
>> wrote:
>>> On Friday, 2 September 2022 at 18:58:43 UTC, Ali Çehreli
>>> wrote:
>>>> But I am aware that we can't deduce T to be 'int' because we
>>>> would be losing that qualifier and further template
>>>> deductions would be wrong. :/
>>>
>>> Another feature that would be interesting is if an `auto`
>>> declaration stripped const/immutable where possible. After
>>> all, if the user didn't want that they could've used `const`
>>> or `immutable`.
>>>
>>> ```d
>>> const i = 4; // const int
>>> auto v = i; // int
>>> const a = [0]; // const(int[])
>>> auto s = a; // const(int)[]
>>> ```
>>
>> This has been discussed in another thread and Walter approved
>> it. Just need to implement it.
>
> He did? This is straight out of Scott Myers' "The Last Thing D
> Needs" talk. He uses almost the same code as an example too.
I ran into this while writing a DIP that “abused” `const`. In
C++, `const` is a far lower guarantee and it’s more like a
convention than actual compiler checking. I really dislike the
fact that Walter made `const(int*)` become `const(int)*` as well
as `const(int[])` become `const(int)[]` when an object of the
former types is passed to a function template as an argument
which has its type inferred:
```D
void f(T)(T x) { pragma(msg, "parameter: ", T); }
void main()
{
const int[] xs;
pragma(msg, "argument : ", typeof(xs));
f(xs);
const int* p;
pragma(msg, "argument : ", typeof(p));
f(p);
}
```
What I started to love about C# is that you feel almost no
difference between built-in stuff and user-defined stuff. (One
notable exception to this is C#’s `const`.)
In C++, there’s has been lot of work put in to give user-defined
types the same possibilities that built-in types have.
In D, there’s much more special casing around built-in types that
make meta-programming tedious. Some examples:
* Value-range propagation: Given `int x`, `x & 0x7FFF` converts
to `short` (but `x` alone requires `cast(int)`. Nice for concrete
code, but in meta-programming code, it opens the door for
hard-to-understand errors appearing.
* Aforementioned `const(int*)` becoming `const(int)*`. That does
not happen with custom `struct S(T)` automatically even in cases
where it is provably correct, and there is no way to tell the D
compiler that copies of `const(S!int)` are better understood to
be `S!(const int)`.
* Types are keywords: With `alias` we could have `alias int =
__traits(signed_integer_type, 32);` etc. There were a lot of
issues in the parser that could be avoided. If you think this
leads to problems, note that `string` is such an alias already.
* Type constructors are hard-wired: If templates want to
deconstruct a type, a lot of special cases have to be written
because in `int*`, `int[]`, `int[10]`, and `int[string]`, the
`*`, `[]`, `[N]`, `[T]` is not syntactic sugar for (hypothetical)
`Ptr!int`, `Slice!int`, `Array!(int, 10)`, and
`AssocArray!(string, int)`, respectively, so those would be
matched by `void f(alias TT, T)(TT!T value)`. Technically
speaking, `const`, `immutable` etc. and `function`/`delegate` are
type constructors as well, but those have additional things going
on: e.g. `const` methods and a function’s parameters have more on
them than their type (e.g., `ref`). As in the bullet above:
`alias Ptr = __traits(pointer_type_ctor);`, etc.
The Last Thing D Needs is the opposite of streamlining.
More information about the Digitalmars-d
mailing list