July 20, 2022

On Wednesday, 20 July 2022 at 02:44:28 UTC, Steven Schveighoffer wrote:

>

version(a) version(b) accomplishes a && b. But a || b is just a complete pain to write.

Does this solve the issue?

version(a)
    version = a_or_b;
version(b)
    version = a_or_b;
version(a_or_b)
    // do whatever you need
> > >

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.

I don't see how raw numbers can be useful. Could you clarify your idea?

The proposal here (I think) is that if you define version MyLibrary.5 then version(MyLibrary.4) or version(MyLibrary.1) all are enabled.

What the current system does is worthless, because version(5) has no meaning. If we scope the numbers to be within a specific project, then that project has the ability to define what those things mean, and you can just define one version on the command line.

Scoping to a project doesn't always provide the meaning: if I have a library that does network communication then what is this version number - library version, protocol version or something else?

July 20, 2022

On Wednesday, 20 July 2022 at 03:18:15 UTC, Hipreme wrote:

>

It is virtually impossible to recreate the mess macros done. They were so messy because one could define AND undefine them, which made tracking a lot hard.

I agree, this is bad use case and I'm glad that D didn't allow it.

>

Even worse, macros were used for everything. Constants, inline functions, templates, syntax transformers, aliases, conditional compilation, importing.

D has already solved that by creating specific tool for each thing

Right and I believe that setting compile time constants in compiler command line would benefit everyone.

>

giving a way to define version as a namespaced number would hardly make anything more complex. If you take the use case i bring for example, you you actually check it would make it easier to understand

I think that version(V >= 5) is not harder to understand than version(V.5). But V >= 5 clearer defines that it's true when V==6 which is not obvious with V.5 - you need to get used to that.

July 20, 2022

On 7/19/22 11:54 PM, Andrey Zherikov wrote:

>

On Wednesday, 20 July 2022 at 02:44:28 UTC, Steven Schveighoffer wrote:

>

version(a) version(b) accomplishes a && b. But a || b is just a complete pain to write.

Does this solve the issue?

version(a)
     version = a_or_b;
version(b)
     version = a_or_b;
version(a_or_b)
     // do whatever you need

That's the pain I'm referring to.

> >

The proposal here (I think) is that if you define version MyLibrary.5 then version(MyLibrary.4) or version(MyLibrary.1) all are enabled.

What the current system does is worthless, because version(5) has no meaning. If we scope the numbers to be within a specific project, then that project has the ability to define what those things mean, and you can just define one version on the command line.

Scoping to a project doesn't always provide the meaning: if I have a library that does network communication then what is this version number - library version, protocol version or something else?

version(MyLibrary.5) ... // library version
version(MyLibrary_protocol.5) ... // protocol version.

-Steve

July 20, 2022

On Wednesday, 20 July 2022 at 13:49:40 UTC, Steven Schveighoffer wrote:

>

version(MyLibrary.5) ... // library version
version(MyLibrary_protocol.5) ... // protocol version.

What I don't like here is an assumption that MyLibrary.5 is compatible with MyLibrary.4,MyLibrary.3 etc. This might not be the case: versions might be backward incompatible so you will have to do version(MyLibrary.5 && !MyLibrary.4 && !MyLibrary.3 && !MyLibrary.2 && !MyLibrary.1). And here are the problems: we don't wave && (yes, you can substitute it with multiple version) and ! (you have to do version(bla) {} else {...}). All these workarounds keep me away from using version - the only thing I use is version(unittest).

July 20, 2022

On Wednesday, 20 July 2022 at 14:37:59 UTC, Andrey Zherikov wrote:

>

What I don't like here is an assumption that MyLibrary.5 is compatible with MyLibrary.4,MyLibrary.3 etc. This might not be the case: versions might be backward incompatible so you will have to do version(MyLibrary.5 && !MyLibrary.4 && !MyLibrary.3 && !MyLibrary.2 && !MyLibrary.1). And here are the problems: we don't wave && (yes, you can substitute it with multiple version) and ! (you have to do version(bla) {} else {...}). All these workarounds keep me away from using version - the only thing I use is version(unittest).

You can use version in conjunction with enums as I do in my bindbc packages, e.g. https://github.com/BindBC/bindbc-opengl/blob/master/source/bindbc/opengl/config.d.

Then you can use whichever logical operators you want on the enums with static if to test for library versions at compile time.

July 20, 2022

Don't get me wrong, I understand why Walter doesn't want to bring #define/#ifdef/#if/#undef into D and I agree with him. Let's take a look at them:

#undef:
There is no such a thing in D - you can't undef a symbol. This effectively removes the mess referenced in this thread (at least one of its flavor).

#define:
It's used to define macroses and compile-time constants. D offers template engine for the former and enums for the latter. They work perfectly except that I'm not able to set compile-time constants from compiler command line (as I mentioned earlier).

#ifdef/#if:
These are used for conditional compilation. D offers version and static if for these. To be precise: #ifdef == version and #if == static if.
Since version checks whether a symbol is defined only and this can be done with static if(is(typeof(VERSION_ID))), the latter has all the features that version has making it useless IMHO.

There is also another #ifdef mess allowed in C:

void func(
#ifdef FOO_INT_PARAM
    int param
#else
    double param
#endif
  )

This is not allowed in D due to its syntax - you can use static if inside function definition. This is also great (IMHO) decision.

July 20, 2022

On Wednesday, 20 July 2022 at 14:37:59 UTC, Andrey Zherikov wrote:

>

On Wednesday, 20 July 2022 at 13:49:40 UTC, Steven Schveighoffer wrote:

>

version(MyLibrary.5) ... // library version
version(MyLibrary_protocol.5) ... // protocol version.

What I don't like here is an assumption that MyLibrary.5 is compatible with MyLibrary.4,MyLibrary.3 etc. This might not be the case: versions might be backward incompatible so you will have to do version(MyLibrary.5 && !MyLibrary.4 && !MyLibrary.3 && !MyLibrary.2 && !MyLibrary.1). And here are the problems: we don't wave && (yes, you can substitute it with multiple version) and ! (you have to do version(bla) {} else {...}). All these workarounds keep me away from using version - the only thing I use is version(unittest).

That's why I said about SDL.2.5
It will be compatible to all version until SDL.2.0
That is more than enough for that, specially because breaking changes you could put under a new major versions, and if they're not compatible, you will be declaring another version rather than a number. The problem is exactly that which the best solution right now is doing like Mike has done.

I'm only suggesting that because trying to replicate newer version has access to older versions is painful and have lots of boilerplate code which could be solved with metaprogramming. But importing a module for doing this hack doesn't feel very hygienic

July 20, 2022

On Wednesday, 20 July 2022 at 14:46:40 UTC, Mike Parker wrote:

>

You can use version in conjunction with enums as I do in my bindbc packages, e.g. https://github.com/BindBC/bindbc-opengl/blob/master/source/bindbc/opengl/config.d.

Then you can use whichever logical operators you want on the enums with static if to test for library versions at compile time.

I'm not saying that it's impossible, there is a workaround. But why should we have workarounds if we can have better support from the language and compiler?

Regarding your example, IMHO there is no difference for your users to do dmd -version GL_46 or dmd -define GLSupport.gl46 but the ability to set GLSupport.gl46 constant from command line will simplify your code (your simply won't need config.d at all).

July 20, 2022

On Wednesday, 20 July 2022 at 16:26:28 UTC, Hipreme wrote:

>

That's why I said about SDL.2.5
It will be compatible to all version until SDL.2.0
That is more than enough for that, specially because breaking changes you could put under a new major versions, and if they're not compatible, you will be declaring another version rather than a number.

I see one issue with this: you assume semver notion of versions. This might not work for everyone - there are a lot of software that have <year> as a major version which has nothing to do with breaking changes.

July 20, 2022

On Tuesday, 19 July 2022 at 22:30:28 UTC, Hipreme wrote:

>

version(number) actually contains something really nice on it. But it is useless.

For example: version(3) would actually declare version(2) and version(1).

The problem is that these doesn't mean anything at all, but they have this property of waterfall. Which is totally missing in D right now. Take this as an example:


version(V1_3)
    version = V1_2;
version(V1_2)
    version = V1_1;
version(V1_1)
    version = V1_0;

D Version is very limit. It should expand to include the version number
version(string-part.float-part)
ex: version = foo.1.3
string-part = foo
float-part = 1.3
true usage =
version(foo >= 1) {with version check}
version(foo) {without version check}
false usage
version(foo >= 2) {never compiled block}

ex: version = foo
string-part = foo
float-part = 0.0

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