July 20, 2022

On Wednesday, 20 July 2022 at 01:34:00 UTC, Steven Schveighoffer wrote:

>

The thing I miss the most for versions is a version1 or version2 mechanism.

You can already do it:

struct Version
{
    template opDispatch(string s)
    {
        mixin(`version(`~s~`)enum opDispatch=true;else enum opDispatch=false;`);
    }
}

static if(Version.OSX || Version.linux){}
else{}
July 20, 2022

On Wednesday, 20 July 2022 at 01:22:00 UTC, Andrey Zherikov wrote:

>

I actually have a question since this topic is brought up:
What is conceptual difference between version(FOO) and static if(FOO)?

version is faster, static if has more features.

July 20, 2022

On Wednesday, 20 July 2022 at 17:55:20 UTC, apz28 wrote:

>

Anyway, "static if" construct is not same as version
https://issues.dlang.org/show_bug.cgi?id=16666

I don't thins that this is good example. The bug is actually about that static if doesn't work with forward declaration:

void func(S s) {}

version (WORKING)
    struct S {}
else static if (true)
    struct S {}

This fails with Error: undefined identifier 'S' and passes with dmd -version=WORKING.

Anyway this can be fixed.

July 20, 2022

On Wednesday, 20 July 2022 at 18:29:28 UTC, Kagamin wrote:

>

On Wednesday, 20 July 2022 at 01:22:00 UTC, Andrey Zherikov wrote:

>

I actually have a question since this topic is brought up:
What is conceptual difference between version(FOO) and static if(FOO)?

version is faster

Do you have performance benchmark to share?

July 20, 2022

On Wednesday, 20 July 2022 at 18:33:50 UTC, Andrey Zherikov wrote:

>

On Wednesday, 20 July 2022 at 17:55:20 UTC, apz28 wrote:

>

Anyway, "static if" construct is not same as version
https://issues.dlang.org/show_bug.cgi?id=16666

I don't thins that this is good example. The bug is actually about that static if doesn't work with forward declaration:

void func(S s) {}

version (WORKING)
    struct S {}
else static if (true)
    struct S {}

This fails with Error: undefined identifier 'S' and passes with dmd -version=WORKING.

Anyway this can be fixed.

The interesting thing is that only top-level static if fails. This works:

void func(A.S s) {}

struct A
{
  version (WORKING)
    struct S {}
  else static if (true)
    struct S {}
}
July 20, 2022
On 7/19/2022 6:34 PM, Steven Schveighoffer wrote:
> The thing I miss the most for versions is a `version1 or version2` mechanism. I doubt we will ever convince Walter this is a good idea.

I know what will happen if that is allowed, and it is not pretty.

The idea is to encourage people to work at teasing out just what should be a version and what shouldn't be, not have arithmetic decide what it is.

This can be faked with `static if` and some enums. Long ago, some users decided that druntime would be better served using `static if` arithmetic on enums instead of versions. Of course, what quickly emerged was the usual C snarl, and nobody knew what code was being compiled (it was made even worse by mutual dependencies). The problem was dropped in my lap, because nobody could figure it out. I didn't even try to figure it out, I figured out what the versions should be and removed all that `static if` nonsense.

If version arithmetic was added, it is guaranteed to produce a coding horror. But by then it will be too late to change our minds, and you and I will be stuck in hell.

At least using `static if` on enums as versioning I have managed to discourage, like using operator overloading for I/O. It's also why enums cannot be set on the command line :-)


> But in any case, we have the numeric versions, which are 100% useless (because, as you say, they are not scoped to any dependencies), it would make sense to at least make that feature useful.

Yes, the numbers are a failed idea of mine. I'd endorse deprecating them.
July 20, 2022
On 7/19/2022 3:30 PM, Hipreme wrote:
> version(V1_3)
>      version = V1_2;
> version(V1_2)
>      version = V1_1;
> version(V1_1)
>      version = V1_0;

This kind of thing is indeed terrible. Fortunately, there are better ways.

Let's say you've got FeatureX, and it exists in some versions and not in others.

Worse way:

    version (X) doX();

Better way:

    import X;
    doX();

Inside module X:

    module X;

    version (X)
        void X() { ... }
    else
        void X() {}

Now, let's say version Y and Z both rely on X being implemented:

    import X;
    doX();

module X:

    version (Y) import Ximpl : X;
    else version (Z) import Ximpl : Y;
    else void X() { }

module Ximpl:

    module Ximpl;

    void X() { ... }

Essentially, what you wind up with is, for each of the versions, there will be a straightforward list of which features are implemented for it. These manifests only appear once in your code, and are easy to maintain.

The complaint about this comes from the DRY principle, people do not want to duplicate a single line of code (in this case, the import lines). But once one gets past DRY, the readability of each version having its own list begins to look much more attractive.

Even better, when one adds a new version, the addition becomes straightforward rather than weaving it into a tangle of other conditional compilation sections.

I know you're not convinced. But I ask that you think about it, and give it a try. I bet you like the results. And you won't have that conditional compilation mess *per file* anymore.
July 20, 2022
On 7/19/2022 7:44 PM, Steven Schveighoffer wrote:
> One place where I do miss it is communicating something like git version information to the compiler. The only way to do this is to pre-build a module for it.

echo "enum V = `git version`;" > version.d

or something like that. (I didn't test it!)
July 21, 2022

On Thursday, 21 July 2022 at 03:57:31 UTC, Walter Bright wrote:

>

At least using static if on enums as versioning I have managed to discourage, like using operator overloading for I/O.

Seems like you have encouraged people to avoid using ‘version’ and inventing their own schemes. So you got a many different chaotic expressions of versioning instead of a singular one. How is this easier for library users to deal with?

Ideally the language versioning expressions should be the same as the package manager uses.

(There is nothing wrong with having operators for I/O and ranges, D would be better if it did provide such.)

July 21, 2022

On Wednesday, 20 July 2022 at 18:34:49 UTC, Andrey Zherikov wrote:

>

On Wednesday, 20 July 2022 at 18:29:28 UTC, Kagamin wrote:

>

On Wednesday, 20 July 2022 at 01:22:00 UTC, Andrey Zherikov wrote:

>

I actually have a question since this topic is brought up:
What is conceptual difference between version(FOO) and static if(FOO)?

version is faster

Do you have performance benchmark to share?

static if can evaluate arbitrarily complex code, it has no upper complexity bound.