1 day ago
On Wednesday, 22 January 2025 at 07:12:08 UTC, Walter Bright wrote:
> On 1/20/2025 7:43 PM, Paul Backus wrote:
>> Would you be open to using a helper function if it had a shorter, less ugly name?
>
> The shorter the name, and the less ugly it is, the more it risks breaking code. Overloading keywords is commonplace in languages, and D, to avoid that problem.

I am confident that, if we put our minds to it, we can find a name which both satisfies your aesthetic sensibilities and carries minimal risk of breaking existing code.

For example:

* x.typePaint!T
* x.bytesAs!T
* x.transmute!T (from Rust [1])

All of these are as short as, or shorter than, `cast(ref T) x`, and none of them seem likely to break existing code.

Personally, I'm a fan of the name typePaint for this operation, since it's a term that's already used in the language specification ([2], [3], [4]).

[1] https://doc.rust-lang.org/std/mem/fn.transmute.html
[2] https://dlang.org/spec/expression.html#cast_class
[3] https://dlang.org/spec/expression.html#cast_array
[4] https://dlang.org/spec/expression.html#cast_static_array

> Consider the builtin associative arrays. These have been a big success. All attempts at making it a template foundered on it being less convenient to use.

Associative arrays are an extremely versatile and widely-used data structure, so there is a lot of value in making them as convenient as possible.

Reinterpreting casts, on the other hand, are a relatively niche, low-level operation. Most code never needs to use them at all, so there is not a lot of value in making them maximally convenient.

> One of the problems of relying on templates for basic things is they aren't in the language specification, so people don't realize they are there.

Just the other day, in the community Discord, I showed Steven Schvieghoffer--a long-time contributor to D--the section in the language spec about how `cast(S) expr` can be rewritten to `S(expr)` if S is a struct. [5] His exact reply was, "Oh wow. That isn't something I knew or expected."

Burying this feature in the specification for cast expressions would be, IMHO, a great way to ensure that hardly anybody ever finds out about it.

[5] https://dlang.org/spec/expression.html#cast_struct
21 hours ago
On Wednesday, 22 January 2025 at 19:17:06 UTC, Paul Backus wrote:

> language spec about how `cast(S) expr` can be rewritten to `S(expr)` if S is a struct. [5]

> Burying this feature in the specification for cast expressions would be, IMHO, a great way to ensure that hardly anybody ever finds out about it.
>
> [5] https://dlang.org/spec/expression.html#cast_struct

I would use this much more often, if only it would work also with basic types. But I tend to write as-generic-as-possible code. If something works only for some types, it's most often completely useless. I'm much better off remembering only the way that works for every type.
19 hours ago

On Tuesday, 21 January 2025 at 13:28:48 UTC, ryuukk_ wrote:

>

On Tuesday, 21 January 2025 at 03:43:02 UTC, Paul Backus wrote:

>

On Monday, 20 January 2025 at 22:55:29 UTC, Walter Bright wrote:

>

On 1/19/2025 9:33 AM, Paul Backus wrote:

>

Why not just add a simple reinterpretCast!T helper function to Phobos or druntime?

Great question.

reinterpretcast!T is just ugly. I never liked it in C++. cast(ref T), on the other hand, looks nice.

Would you be open to using a helper function if it had a shorter, less ugly name?

please stop trying to kill D improvement proposals by suggesting Yet Another Template

nobody, literally, nobody ever thought of using a template TO CAST, this is ridiculous, stop

[…]

Generally, I somewhat agree. A good idea that died this death is dependency-carrying declarations aka. imports in function declarations, because you can make Import!"std.conv".text work.

However, in this particular case, I’m on the templaters’ side. A reinterpret cast is so rare, you can be bothered to import some module for it, especially because it’s an expert tool. It’s not like an import which virtually every D program has.

To be honest, requiring reinterpretCast!int(someLong) and allowing cast(string)someLong makes more sense than the reverse. Currently, both require an import, but what would naïve users expect to have as a core-language feature? If I were new to D, to get from a long to a string, I’d try someLong.toString() and the cast, possibly string(someLong). Then, I’ll try to look it up with an annoyed mood to find the template.

C++ made reinterpret_cast<…>(…) purposefully annoying to type. And I know the critique, C++ bad, we different. But C++ got some things right, and one was making reinterpret-casts annoying to type and obvious to spot. D seriously lacks discipline in making dangerous constructs look dangerous.

There at least these three levels of cast. An implicit cast is a safe cast where data can’t be lost, e.g. casting a ushort to uint or uint* to const(uint)*. An explicit cast is a safe cast where data can be lost, e.g. casting uint to ushort. A dangerous cast is one that could incur undefined behavior, e.g. casting const(uint)* to uint*.

Kind C++ D
Implicit T{…} T(…)
Explicit static_cast<T>(…) cast(T)…
Dangerous reinterpret_cast<T>(…) cast(T)…

Some static_cast are dangerous, and of course there are more dangerous C++ casts such as C-style casts, T(…), and const_cast<T>(…), it’s a mess, but many dangerous casts are easily spotted. However, D only ever offers two syntaxes, and one is consistently used for explicit casts and dangerous casts. As a rule of thumb, if the argument to cast involves casting to a pointer, it’s dangerous. If it were up to me, cast should only ever do @safe casts, and be required for stuff like cast(ushort) myInt. For const(uint)* to uint*, D should require something like, __traits(unsafeCast, uint*, &myConstInt). Of course, I’m aware this ship has sailed.

The bottom line is: It’s way more reasonable having to write import std.conv; such that reinterpretCast is available than you presume. It is much more reasonable than having to write import std.conv; to use myInt.to!string instead of myInt.toString() working without any import whatsoever.

2 hours ago

On Thursday, 23 January 2025 at 01:56:32 UTC, Quirin Schroll wrote:

>

cast should only ever do @safe casts, and be required for stuff like cast(ushort) myInt.

For this, I wish ushort(myInt) would work. This would safe a LOT of unneccessary text and keep cast() for the more dangerous things.

But at the moment the compiler rejects that: "cannot implicitly cast myInt of type int to ushort". I would never consider ushort(x) "implicit". It really doesn't get any more explicit than this :-(

Allowing explicitly calling the constructor of a smaller type to truncate values could easily get allowed without breaking any existing code.
Especially because working with small types requires this cast over and over because every operation extends them to int.

1 2 3
Next ›   Last »