August 23, 2023
On 8/22/2023 3:03 PM, ryuukk_ wrote:
> Since i got confused with ``version(linux)`` and ``version(Linux)``

For those who wonder why "linux", it is to match C's predefined identifier that serves the same purpose.

August 23, 2023
On 8/23/2023 5:37 AM, Nick Treleaven wrote:
> Walter already posted a sum type proposal. We do get it. He also mentioned that `match` would need a separate DIP:
> https://forum.dlang.org/post/tm4jr9$219h$1@digitalmars.com

Yes, and it's paused for the moment as we're working on fixing issues rather than adding new features.
August 23, 2023
On 8/23/2023 10:24 AM, Adam D Ruppe wrote:
> This kind of thing has happened even with Phobos.

Can you be more specific? I'm curious.


> D's `version` specifier is a major failure in real world code, leading to incomprehensible soup in addition to runtime corruption, porting trouble, and other problems.

C's #ifdef is not better in any way, and much much worse in many ways.

For library writers, there are indeed some things to watch out for. I recommend using the name of the library as a prefix on their version identifiers. For local versions, one can use private enums with static if.

Phobos has some head-scratchers, like this in std.stdio:

```
else version (CRuntime_DigitalMars)
{
    // Specific to the way Digital Mars C does stdio
    version = DIGITAL_MARS_STDIO;
}
```

https://github.com/dlang/phobos/pull/8802
August 23, 2023
I don't know how to design a language to force people to write better code, all I can do is make it harder to write worse code. Then try to lead by example:


https://github.com/dlang/phobos/pull/8803

https://github.com/dlang/phobos/pull/8802
August 24, 2023
On Monday, 21 August 2023 at 16:19:25 UTC, Walter Bright wrote:
> On 8/21/2023 8:39 AM, Basile B. wrote:
>> Like you pretend that `enum DEFAULTS` is not a workaround the limitations.
>
> I would not use the DEFAULTS, but would spell it out for each system. Then it looks like a table, with rows and columns, and makes it easy to see which setting is for which system.

I've been informed that you are not actually perfectly satisfied with D versions and that you personally use workarounds, for example here:

https://github.com/dlang/dmd/commit/80a62817f13a79d2d2d84cdb46697a2c1406a212
August 24, 2023
On Thursday, 24 August 2023 at 04:53:49 UTC, Walter Bright wrote:
> Can you be more specific? I'm curious.

version(unittest) made waves some time ago, making all kinds of random errors when user code was trying to be tested but still imported phobos modules.

> For library writers, there are indeed some things to watch out for. I recommend using the name of the library as a prefix on their version identifiers.

Yeah, that's what I tend to do too, but it is just a convention. The language probably could have defined versions to be specific to a module, even if given on the command line.

But name conflicts are one of the smallest problems with them. When a mismatch on compile and import lead to ABI mismatches are the worst.

I wrote at greater length about this here:
http://dpldocs.info/this-week-in-d/Blog.Posted_2022_11_14.html#redesign-for-template-emission-woes

> Phobos has some head-scratchers, like this in std.stdio:

This specific one doesn't seem to make sense, but this pattern comes up a lot because you might want to use a specific implementation from multiple triggers.

Easy to imagine there might be a CRuntime_DigitalMars and a CRuntime_DigitalMars64, for example, different predefined versions that share the implementation of this portion. But other parts of the module might branch differently on CRuntime_DigitalMars vs DM64, so you couldn't just find/replace all if you decided to add the other one.

So the author there is probably doing this to try to future-proof the code with some extra semantic tagging in case some other definition is added. I've done this a few times myself.

It actually isn't all bad, but it can get ugly when someone specifies `-version=DIGITAL_MARS_STDIO` on the command line when building against Microsoft C runtime... then what happens?

Or when someone again tries to figure proof and puts `else static assert(0)` at the end, making incremental porting impossible. (which i also wrote about in the last year: http://dpldocs.info/this-week-in-d/Blog.Posted_2023_02_20.html#static-assert-patterns-arguably-harmful-for-porting )


C's ifdef is a big mess.

D's version is a different big mess, but still a mess.
August 24, 2023
On 8/24/2023 7:37 AM, Basile B. wrote:
> I've been informed that you are not actually perfectly satisfied with D versions and that you personally use workarounds, for example here:
> 
> https://github.com/dlang/dmd/commit/80a62817f13a79d2d2d84cdb46697a2c1406a212

I'm always experimenting with better ways to do things.
August 24, 2023
On Wednesday, 23 August 2023 at 17:24:24 UTC, Adam D Ruppe wrote:
>
>> You can also create a config.d file with a list of enum declarations in them, import that, and use whatever algebra you want with static if.
>
> This is *significantly* better than using D's failed `version` specifier.

We have the ability to declare information (`enum`s and so on) & branch on it at compile time (`static if`), we have a package & module system to handle who can and does read that data. Beyond that, it's the author & build system’s problem imo.

I get the problem that `version` tries to solve, but I reckon if it didn’t already exist then it wouldn’t get added now.
August 24, 2023
On 8/24/2023 8:30 AM, Adam D Ruppe wrote:
> On Thursday, 24 August 2023 at 04:53:49 UTC, Walter Bright wrote:
>> Can you be more specific? I'm curious.
> 
> version(unittest) made waves some time ago, making all kinds of random errors when user code was trying to be tested but still imported phobos modules.

That was something different.


> I wrote at greater length about this here:
> http://dpldocs.info/this-week-in-d/Blog.Posted_2022_11_14.html#redesign-for-template-emission-woes

I'll read it, thanks.


>> Phobos has some head-scratchers, like this in std.stdio:
> 
> This specific one doesn't seem to make sense, but this pattern comes up a lot because you might want to use a specific implementation from multiple triggers.
> 
> Easy to imagine there might be a CRuntime_DigitalMars and a CRuntime_DigitalMars64, for example,

I wouldn't set it up that way. I'd version on IA64 within CRuntime_DigitalMars. I.e. overlapping version declarations are not a good plan, for precisely the reason you mention. Better to version along orthogonal axes.

> different predefined versions that share the implementation of this portion. But other parts of the module might branch differently on CRuntime_DigitalMars vs DM64, so you couldn't just find/replace all if you decided to add the other one.
> 
> So the author there is probably doing this to try to future-proof the code with some extra semantic tagging in case some other definition is added. I've done this a few times myself.

Back in the 80s, everyone knew that 32 bits was inevitable. So the professionals future-proofed their code so it would be portable from 16 to 32 bits. (A classic example of this is Windows with their forest of typedefs like BYTE.) But when 32 bits arrived, people discovered that their future-proofing did not work at all. It failed because none of them had ever ported code from 16 to 32 before, and so the future-proof solutions were all the wrong solutions.

The same thing happened to me.

But I learned how to make code 16->32 portable, and it was pretty simple. Just not at all like what I or anyone else presumed it would be.

Have you noticed how darned easy it is to port D code between 32 and 64 bit? That's the result of my experience porting 16 to 32.

The point is, future-proofing is a pretty hard thing to do, because we simply don't know what the future will be.

This is why I don't really try to future-proof with versions, instead relying on enumerating the known cases, and leaving the default with `static assert(0);`


> It actually isn't all bad, but it can get ugly when someone specifies `-version=DIGITAL_MARS_STDIO` on the command line when building against Microsoft C runtime... then what happens?

At some point, you're just going to have to run:

    grep -r version *

Fortunately (by design!) you can grep for such simple patterns. I learned that long ago when Matthew Wilson suggested I extend the DMC++ compiler to use a keyword for casting rather than (type) which is ungreppable, even with a regex. I put it in, but he refused to use it because no other C++ compiler did that and it wouldn't be portable.

I learned two things:

1. nobody wants local C++ extensions

2. the idea behind a keyword for cast was sound, and hence the D syntax which is easily greppable


> Or when someone again tries to figure proof and puts `else static assert(0)` at the end, making incremental porting impossible. (which i also wrote about in the last year: http://dpldocs.info/this-week-in-d/Blog.Posted_2023_02_20.html#static-assert-patterns-arguably-harmful-for-porting )

I'll have a look at that.

> C's ifdef is a big mess.
> 
> D's version is a different big mess, but still a mess.

A much smaller one. I have a lot of experience with the C one. It's often essentially impossible to tell which path through the tangle is being taken unless one dumps the preprocessor output and examines it.

Even if one is faced with such a tangle in D, a strategic:
```
pragma(msg, "xyzzy");
```
will let you know which branch is happening. I sometimes resort to that with templates.

August 24, 2023
On 8/24/2023 8:30 AM, Adam D Ruppe wrote:
> Or when someone again tries to figure proof and puts `else static assert(0)` at the end, making incremental porting impossible. (which i also wrote about in the last year: http://dpldocs.info/this-week-in-d/Blog.Posted_2023_02_20.html#static-assert-patterns-arguably-harmful-for-porting )

Not impossible, just initially a mite tedious. One can still incrementally port to AdrOS by adding:

```
version (Windows)
{
     enum x = 7;
}
else version (AdrOS)
{
     enum x = 0; // FIXME
}
else
     static assert(0);
```

and at least the compiler will tell you were all these places are. Then, a grep for FIXME will find every place you overlooked.

You wrote that this is in hundreds of places in druntime. Great! If this technique wasn't used, I guarantee that any port to AdrOS will miss more than a few, and it will be hell to figure out what is going wrong. I guarantee it because it always happened when defaults were used for unknown systems.

I prefer a bit of tedium to debugging hell.

This is also why the `default` case is required for D switches.