digitalmars.D - version(number) is completely useless
- Hipreme (20/20) Jul 19 2022 version(number) actually contains something really nice on it.
- Andrey Zherikov (27/48) Jul 19 2022 IMO it is completely useless: what does "3" mean? what is
- Andrey Zherikov (5/5) Jul 19 2022 I actually have a question since this topic is brought up:
- Steven Schveighoffer (13/18) Jul 19 2022 version is specifically a replacement for #defines as in C. They are
- Andrey Zherikov (15/36) Jul 19 2022 It's not a full replacement because it doesn't support
- jfondren (15/22) Jul 19 2022 And that works, right? When you definitely need the feature,
- Steven Schveighoffer (14/38) Jul 19 2022 Yes, and actually, this is not something I miss terribly. One place
- Andrey Zherikov (15/32) Jul 19 2022 Does this solve the issue?
- Steven Schveighoffer (5/31) Jul 20 2022 version(MyLibrary.5) ... // library version
- Andrey Zherikov (11/13) Jul 20 2022 What I don't like here is an assumption that `MyLibrary.5` is
- Mike Parker (6/15) Jul 20 2022 You can use version in conjunction with enums as I do in my
- Andrey Zherikov (9/15) Jul 20 2022 I'm not saying that it's impossible, there is a workaround. But
- Andrey Zherikov (32/32) Jul 20 2022 Don't get me wrong, I understand why Walter doesn't want to bring
- Hipreme (12/25) Jul 20 2022 That's why I said about SDL.2.5
- Andrey Zherikov (5/11) Jul 20 2022 I see one issue with this: you assume semver notion of versions.
- Walter Bright (3/6) Jul 20 2022 echo "enum V = `git version`;" > version.d
- Kagamin (15/17) Jul 20 2022 You can already do it:
- Walter Bright (4/4) Jul 23 2022 This is very clever, thanks for posting it! I would never have thought o...
- Walter Bright (18/23) Jul 20 2022 I know what will happen if that is allowed, and it is not pretty.
- Ola Fosheim =?UTF-8?B?R3LDuHN0YWQ=?= (9/11) Jul 20 2022 Seems like you have encouraged people to avoid using ‘version’
- James Blachly (4/7) Jul 22 2022 I find this very insightful; the practical consequences of well-meaning
- Walter Bright (6/9) Jul 22 2022 It brings it into the forum where I can explain how to achieve better re...
- Andrey Zherikov (17/23) Jul 22 2022 Unfortunately as you know people don't care about what you
- Walter Bright (11/28) Jul 23 2022 `defined` doesn't work in D.
- Andrey Zherikov (13/27) Jul 26 2022 Sorry, I didn't think that I had to provide fully working example
- H. S. Teoh (12/20) Jul 26 2022 static if (__VERSION__ == 2098L) {
- Steven Schveighoffer (4/24) Jul 26 2022 Ironic that DMD's provided meta doesn't feel the burden of dealing with
- Andrey Zherikov (2/22) Jul 26 2022 This is discouraged usage according to Walter, isn't it?
- H. S. Teoh (11/23) Jul 26 2022 I guess so. :-D
- jmh530 (12/21) Jul 26 2022 The bottom two are a bit separate. It makes perfect sense to add
- Walter Bright (2/4) Jul 26 2022 And a little more obvious.
- Paul Backus (22/24) Jul 26 2022 You can use introspection to check for features and bug fixes
- Walter Bright (28/30) Jul 26 2022 Create a single "configuration module", which has a section for each ver...
- Andrey Zherikov (4/34) Jul 27 2022 What's your recommendation about how I should check for a
- Walter Bright (4/7) Jul 27 2022 __VERSION__ is certainly more convenient.
- Andrey Zherikov (4/13) Jul 28 2022 Did I get you right that you discourage using `static if` for
- Walter Bright (6/10) Jul 28 2022 Yes, you did.
- Andrey Zherikov (4/13) Jul 29 2022 I'm just trying to clarify your recommendations as a language
- Dennis (3/5) Jul 26 2022 They are now deprecated:
- Kagamin (8/13) Apr 16 2023 You misquoted, and debug(number) wasn't discussed. If
- jfondren (42/48) Jul 19 2022 Consider:
- Andrey Zherikov (6/28) Jul 19 2022 I'd like build system to not generate any files with compile-time
- Hipreme (12/61) Jul 19 2022 It is virtually impossible to recreate the mess macros done. They
- Andrey Zherikov (8/20) Jul 19 2022 Right and I believe that setting compile time constants in
- Kagamin (2/5) Jul 20 2022 `version` is faster, `static if` has more features.
- Andrey Zherikov (2/8) Jul 20 2022 Do you have performance benchmark to share?
- apz28 (17/32) Jul 20 2022 D Version is very limit. It should expand to include the version
- Andrey Zherikov (13/15) Jul 20 2022 I don't thins that this is good example. The bug is actually
- Andrey Zherikov (13/28) Jul 20 2022 The interesting thing is that only top-level `static if` fails.
- Walter Bright (36/42) Jul 20 2022 This kind of thing is indeed terrible. Fortunately, there are better way...
- Hipreme (22/69) Jul 22 2022 Okay, so what I asked is not exactly doing as people here thought
- Mike Parker (3/15) Jul 22 2022 Then what happens when you *don't* want old versions together
- Hipreme (11/27) Jul 22 2022 I'm thinking about newer versions with incremental additions.
- Mike Parker (3/13) Jul 22 2022 And then you're baking a library versioning scheme into the
- Walter Bright (2/6) Jul 22 2022 The reader has no idea what actual feature is being turned on or off.
- Hipreme (22/29) Jul 22 2022 I understand your point. But there exists a problem. The reason
- Mike Parker (20/35) Jul 22 2022 What is a version? Linux version, Windows version, free version,
- Walter Bright (7/12) Jul 22 2022 New versions are not just numbers. They are an arbitrary collection of n...
- H. S. Teoh (20/51) Jul 22 2022 [...]
- Walter Bright (2/21) Jul 23 2022 Awkward since you cannot import versions from other modules.
- rikki cattermole (4/5) Jul 23 2022 Perhaps we should be changing that.
- Walter Bright (6/13) Jul 23 2022 1. then you can't tell which versions are active
- Max Samukha (2/5) Jul 24 2022 Choosing a different set of problems never results in no problems.
- Walter Bright (11/34) Jul 22 2022 !version is something I try to destroy. Versions should be positive
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: ```d version(V1_3) version = V1_2; version(V1_2) version = V1_1; version(V1_1) version = V1_0; ``` I need to do this. **per file**. This is such a boilerplate code that could get a lot nicer if we had some kind of versioning syntax. For example `version(V.1.3)`. We could even get: `version(SDL.2.5)`. Which would declare everything down to SDL.2.0 Obviously this feature is meaningless to small projects
Jul 19 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).IMO it is completely useless: what does "3" mean? what is relationship between "3" in my package and "3" in dependency? what is relationship between "3" in different sources within the same package?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: ```d version(V1_3) version = V1_2; version(V1_2) version = V1_1; version(V1_1) version = V1_0; ```I don't like it - why can't we just write this instead? ```d version(V1 >= 3) pragma(msg, "newest version"); else version(V1 >= 2) pragma(msg, "old version"); else pragma(msg, "obsolete version"); ``` But having this would mean that D has two ways to express the same things: `version` and `static if` because that code is the same as: ```d static if(V1 >= 3) pragma(msg, "newest version"); else static if(V1 >= 2) pragma(msg, "old version"); else pragma(msg, "obsolete version"); ```I need to do this. **per file**. This is such a boilerplate code that could get a lot nicer if we had some kind of versioning syntax. For example `version(V.1.3)`. We could even get: `version(SDL.2.5)`. Which would declare everything down to SDL.2.0Again, why can't it be `version(V >= 1.3)` or `static if(SDL >= 2.5)`?
Jul 19 2022
I actually have a question since this topic is brought up: What is conceptual difference between `version(FOO)` and `static if(FOO)`? I see `version` is a very limited comparing to `static if` - the former checks for "boolean" result (whether an ID is defined) while the latter evaluates condition expression.
Jul 19 2022
On 7/19/22 9:22 PM, 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)`? I see `version` is a very limited comparing to `static if` - the former checks for "boolean" result (whether an ID is defined) while the latter evaluates condition expression.version is specifically a replacement for #defines as in C. They are specified mostly on the command line. But also, a version cannot be detected from an imported file -- every module starts with the compilation versions, and that's it. Walter was very averse to the mess that is C preprocessor defines, and wanted something more hygienic. 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. 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. -Steve
Jul 19 2022
On Wednesday, 20 July 2022 at 01:34:00 UTC, Steven Schveighoffer wrote:On 7/19/22 9:22 PM, Andrey Zherikov wrote:It's not a full replacement because it doesn't support `-DSOME_DEFINE=5` or `-DANOTHER_DEFINE="some string"`. One of the features which I really miss in D is inability to do these things. This is very largely used in software development for setting compile-time constants from command line. D doesn't support this out of the box (I have to dump a `.d` file with set of `enums` and then include it into the build).I actually have a question since this topic is brought up: What is conceptual difference between `version(FOO)` and `static if(FOO)`? I see `version` is a very limited comparing to `static if` - the former checks for "boolean" result (whether an ID is defined) while the latter evaluates condition expression.version is specifically a replacement for #defines as in C. They are specified mostly on the command line.But also, a version cannot be detected from an imported file -- every module starts with the compilation versions, and that's it. Walter was very averse to the mess that is C preprocessor defines, and wanted something more hygienic.I'm totally for simple and clean solution here but whatever D offers right now is half-baked IMHO.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 don't think that `version1 or version2` is any different than allowing complete conditional expression.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?
Jul 19 2022
On Wednesday, 20 July 2022 at 02:10:21 UTC, Andrey Zherikov wrote:It's not a full replacement because it doesn't support `-DSOME_DEFINE=5` or `-DANOTHER_DEFINE="some string"`. One of the features which I really miss in D is inability to do these things. This is very largely used in software development for setting compile-time constants from command line. D doesn't support this out of the box (I have to dump a `.d` file with set of `enums` and then include it into the build).And that works, right? When you definitely need the feature, enough to live with a build-system burden like this, then you can have it. And when you don't definitely need it, D's `version` feature doesn't let you casually, effortlessly, create an impossible to understand version soup. Meanwhile, D makes it trivially easy to add a unit test whenever you want, and in some other languages unit testing is a feature that requires you to bear the burden of a more complex build system. You can see the opinions of the language designers. Testing is so important that even a throwaway function posted to this forum can have a unittest{} with it. Elaborate build-time configuration is so detested that you have to ignore the relevant language feature and roll your own alternative to it.
Jul 19 2022
On 7/19/22 10:10 PM, Andrey Zherikov wrote:On Wednesday, 20 July 2022 at 01:34:00 UTC, Steven Schveighoffer wrote:Yes, and actually, this is not something I miss terribly. 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.On 7/19/22 9:22 PM, Andrey Zherikov wrote:It's not a full replacement because it doesn't support `-DSOME_DEFINE=5` or `-DANOTHER_DEFINE="some string"`.I actually have a question since this topic is brought up: What is conceptual difference between `version(FOO)` and `static if(FOO)`? I see `version` is a very limited comparing to `static if` - the former checks for "boolean" result (whether an ID is defined) while the latter evaluates condition expression.version is specifically a replacement for #defines as in C. They are specified mostly on the command line.`version(a) version(b)` accomplishes a && b. But a || b is just a complete pain to write.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 don't think that `version1 or version2` is any different than allowing complete conditional expression.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. -SteveBut 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?
Jul 19 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? ```d version(a) version = a_or_b; version(b) version = a_or_b; version(a_or_b) // do whatever you need ```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?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.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?
Jul 19 2022
On 7/19/22 11:54 PM, Andrey Zherikov wrote:On Wednesday, 20 July 2022 at 02:44:28 UTC, Steven Schveighoffer wrote:That's the pain I'm referring to.`version(a) version(b)` accomplishes a && b. But a || b is just a complete pain to write.Does this solve the issue? ```d version(a) version = a_or_b; version(b) version = a_or_b; version(a_or_b) // do whatever you need ```version(MyLibrary.5) ... // library version version(MyLibrary_protocol.5) ... // protocol version. -SteveThe 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?
Jul 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)`.
Jul 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.
Jul 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).
Jul 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: ```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.
Jul 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: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 hygienicversion(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)`.
Jul 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.
Jul 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!)
Jul 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{} ```
Jul 20 2022
This is very clever, thanks for posting it! I would never have thought of it. I always enjoy the discovery of these kinds of gems. But I can't recommend this particular usage, because it isn't the right way to do versioning :-)
Jul 23 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.
Jul 20 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.)
Jul 20 2022
On 7/21/22 1:51 AM, Ola Fosheim Grøstad wrote: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.I find this very insightful; the practical consequences of well-meaning policies are often surprising and frequently the complete opposite of the original policy's intent.
Jul 22 2022
On 7/22/2022 6:31 PM, James Blachly wrote:I find this very insightful; the practical consequences of well-meaning policies are often surprising and frequently the complete opposite of the original policy's intent.It brings it into the forum where I can explain how to achieve better results than the same old chaotic way C does it. I've lived with the C way for a loooong time. Just take a look at the C system .h files on your system. I know people will treat the version way skeptically at first, but give it a try.
Jul 22 2022
On Thursday, 21 July 2022 at 03:57:31 UTC, Walter Bright wrote: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 :-)Unfortunately as you know people don't care about what you discourage or encourage. People just try to express their intent using those language structs that are the best for their needs and nothing prevents them from writing this right now: ```d static if (defined(_MSC_VER) && (_MSC_VER > 600) && !defined(__INTERIX)) { static if(defined(_WIN32_WCE)) alias fdopen = (fd,mode) {}; /* No fdopen() */ else alias fdopen = _fdopen; } ``` (I took this example from [zlib](https://github.com/madler/zlib/blob/master/zutil.h#L177))
Jul 22 2022
On 7/22/2022 9:24 PM, Andrey Zherikov wrote:Unfortunately as you know people don't care about what you discourage or encourage. People just try to express their intent using those language structs that are the best for their needs and nothing prevents them from writing this right now: ```d static if (defined(_MSC_VER) && (_MSC_VER > 600) && !defined(__INTERIX)) { static if(defined(_WIN32_WCE)) alias fdopen = (fd,mode) {}; /* No fdopen() */ else alias fdopen = _fdopen; } ``` (I took this example from [zlib](https://github.com/madler/zlib/blob/master/zutil.h#L177))`defined` doesn't work in D. The idea is to make the wrong way unattractive and clumsy enough that people will look for a better way, which we provide. BTW, I've been through the zlib .h files, in the course of dogfooding it with ImportC. Every ugly practice I complain about with #if's is in full display there. Here's another gem from your link: #if defined(STDC) && !defined(HAVE_MEMCPY) && !defined(NO_MEMCPY) #endif It's just madness.
Jul 23 2022
On Saturday, 23 July 2022 at 20:12:29 UTC, Walter Bright wrote:`defined` doesn't work in D.Sorry, I didn't think that I had to provide fully working example to illustrate an idea ;)The idea is to make the wrong way unattractive and clumsy enough that people will look for a better way, which we provide. BTW, I've been through the zlib .h files, in the course of dogfooding it with ImportC. Every ugly practice I complain about with #if's is in full display there. Here's another gem from your link: ``` #if defined(STDC) && !defined(HAVE_MEMCPY) && !defined(NO_MEMCPY) #endif ``` It's just madness.I totally understand you and your intentions with this. But I'd like to get your recommendation on the following situation. As a library developer I want to provide some SLA to the users: I guarantee that my library will be successfully built by all versions of all compilers (ldc,gdc,dmd) that are one year old or newer. The thing is that compilers evolve (they got new features, bug fixes etc) and I want my codebase evolve with them. I can easily check what compiler is used by `version(DigitalMars)` e.g.. But how should I check that a specific feature is added to compiler/phobos or a specific bug is fixed?
Jul 26 2022
On Tue, Jul 26, 2022 at 10:52:29AM +0000, Andrey Zherikov via Digitalmars-d wrote: [...]As a library developer I want to provide some SLA to the users: I guarantee that my library will be successfully built by all versions of all compilers (ldc,gdc,dmd) that are one year old or newer. The thing is that compilers evolve (they got new features, bug fixes etc) and I want my codebase evolve with them. I can easily check what compiler is used by `version(DigitalMars)` e.g.. But how should I check that a specific feature is added to compiler/phobos or a specific bug is fixed?static if (__VERSION__ == 2098L) { ... // 2.098-specific code } static if (__VERSION__ == 2100L) { ... // 2.100-specific code } // and so on T -- There are 10 kinds of people in the world: those who can count in binary, and those who can't.
Jul 26 2022
On 7/26/22 9:27 AM, H. S. Teoh wrote:On Tue, Jul 26, 2022 at 10:52:29AM +0000, Andrey Zherikov via Digitalmars-d wrote: [...]Ironic that DMD's provided meta doesn't feel the burden of dealing with the crippled version system. -SteveAs a library developer I want to provide some SLA to the users: I guarantee that my library will be successfully built by all versions of all compilers (ldc,gdc,dmd) that are one year old or newer. The thing is that compilers evolve (they got new features, bug fixes etc) and I want my codebase evolve with them. I can easily check what compiler is used by `version(DigitalMars)` e.g.. But how should I check that a specific feature is added to compiler/phobos or a specific bug is fixed?static if (__VERSION__ == 2098L) { ... // 2.098-specific code } static if (__VERSION__ == 2100L) { ... // 2.100-specific code } // and so on
Jul 26 2022
On Tuesday, 26 July 2022 at 13:27:55 UTC, H. S. Teoh wrote:On Tue, Jul 26, 2022 at 10:52:29AM +0000, Andrey Zherikov via Digitalmars-d wrote: [...]This is discouraged usage according to Walter, isn't it?As a library developer I want to provide some SLA to the users: I guarantee that my library will be successfully built by all versions of all compilers (ldc,gdc,dmd) that are one year old or newer. The thing is that compilers evolve (they got new features, bug fixes etc) and I want my codebase evolve with them. I can easily check what compiler is used by `version(DigitalMars)` e.g.. But how should I check that a specific feature is added to compiler/phobos or a specific bug is fixed?``` static if (__VERSION__ == 2098L) { ... // 2.098-specific code } static if (__VERSION__ == 2100L) { ... // 2.100-specific code } // and so on ```
Jul 26 2022
On Tue, Jul 26, 2022 at 03:19:44PM +0000, Andrey Zherikov via Digitalmars-d wrote:On Tuesday, 26 July 2022 at 13:27:55 UTC, H. S. Teoh wrote:[...]I guess so. :-D So maybe we need a DIP to add feature-based version identifiers, e.g.: version(fixed12345) { ... /* bug 12345 is fixed */ } version(dip1000) { ... } version(intpromote) { ... } and so on. T -- He who sacrifices functionality for ease of use, loses both and deserves neither. -- Slashdotter``` static if (__VERSION__ == 2098L) { ... // 2.098-specific code } static if (__VERSION__ == 2100L) { ... // 2.100-specific code } // and so on ```This is discouraged usage according to Walter, isn't it?
Jul 26 2022
On Tuesday, 26 July 2022 at 17:06:17 UTC, H. S. Teoh wrote:[snip] I guess so. :-D So maybe we need a DIP to add feature-based version identifiers, e.g.: version(fixed12345) { ... /* bug 12345 is fixed */ } version(dip1000) { ... } version(intpromote) { ... } and so on. TThe bottom two are a bit separate. It makes perfect sense to add predefined versions for preview statements (it may even make sense to include even more than that, e.g. version statement for other D features that people may want to disable, but that's neither here nor there and a bit beyond the scope). I don't think it needs a DIP for that. Bug fixes are a bit more annoying because there are thousands of them. I would still need to look up what bug 12345 was, even though it is at least more specific than the specific a DMD version. I think checking whether the buggy code is fixed with a traits _compiles is a little more obvious.
Jul 26 2022
On 7/26/2022 10:33 AM, jmh530 wrote:I think checking whether the buggy code is fixed with a traits _compiles is a little more obvious.And a little more obvious.
Jul 26 2022
On Tuesday, 26 July 2022 at 10:52:29 UTC, Andrey Zherikov wrote:But how should I check that a specific feature is added to compiler/phobos or a specific bug is fixed?You can use introspection to check for features and bug fixes directly: ```d static if (__traits(compiles, { import std.whatever: someSymbol; })) { // std.whatever.someSymbol exists } private bool hasBug() { // test case for bug } static if (hasBug) { // workaround for bug } else { // code without the workaround } ```
Jul 26 2022
On 7/26/2022 3:52 AM, Andrey Zherikov wrote:But how should I check that a specific feature is added to compiler/phobos or a specific bug is fixed?Create a single "configuration module", which has a section for each version: -------- module config; version (DigitalMars) { import digitalmars; } else version (LDC) { import ldc; } else version (GDC) { import gdc; } else { static assert(0, "unsupported system"); } --------- Now, in digitalmars.d and ldc.d and gdc.d, do what it takes to make that configuration work for your code. This makes it really easy to concentrate, say, in ldc.d, just on ldc's characteristics. Rather than having to constantly confuse yourself with which configuration is compiling what code. It also immediately points out when the code is being built for a version you have not anticipated.
Jul 26 2022
On Wednesday, 27 July 2022 at 03:42:07 UTC, Walter Bright wrote:On 7/26/2022 3:52 AM, Andrey Zherikov wrote:What's your recommendation about how I should check for a specific feature/bugfix? Should I use `static if(__VERSION__ ...)`, `static if(__traits(compiles, { ... }))` or something else?But how should I check that a specific feature is added to compiler/phobos or a specific bug is fixed?Create a single "configuration module", which has a section for each version: ```d module config; version (DigitalMars) { import digitalmars; } else version (LDC) { import ldc; } else version (GDC) { import gdc; } else { static assert(0, "unsupported system"); } ``` Now, in digitalmars.d and ldc.d and gdc.d, do what it takes to make that configuration work for your code. This makes it really easy to concentrate, say, in ldc.d, just on ldc's characteristics. Rather than having to constantly confuse yourself with which configuration is compiling what code.
Jul 27 2022
On 7/27/2022 7:24 AM, Andrey Zherikov wrote:What's your recommendation about how I should check for a specific feature/bugfix? Should I use `static if(__VERSION__ ...)`, `static if(__traits(compiles, { ... }))` or something else?__VERSION__ is certainly more convenient. Though, since upgrades to the compiler are free, a simpler strategy would be to just require a __VERSION__ past a certain point.
Jul 27 2022
On Wednesday, 27 July 2022 at 17:16:30 UTC, Walter Bright wrote:On 7/27/2022 7:24 AM, Andrey Zherikov wrote:Did I get you right that you discourage using `static if` for versioning the code (according to [this post](https://forum.dlang.org/post/tbair7$2ltc$1 digitalmars.com)) with an exception for `static if(__VERSION__ ...)`?What's your recommendation about how I should check for a specific feature/bugfix? Should I use `static if(__VERSION__ ...)`, `static if(__traits(compiles, { ... }))` or something else?__VERSION__ is certainly more convenient. Though, since upgrades to the compiler are free, a simpler strategy would be to just require a __VERSION__ past a certain point.
Jul 28 2022
On 7/28/2022 7:57 AM, Andrey Zherikov wrote:Did I get you right that you discourage using `static if` for versioning the code (according to [this post](https://forum.dlang.org/post/tbair7$2ltc$1 digitalmars.com)) with an exception for `static if(__VERSION__ ...)`?Yes, you did. Mainly, because the compiler doesn't generate a predefined version for every change, which is impractical. Frankly, what you're trying to do is hopeless, hence the suggestion to simply pick a minimum __VERSION__ to support.
Jul 28 2022
On Friday, 29 July 2022 at 01:04:42 UTC, Walter Bright wrote:On 7/28/2022 7:57 AM, Andrey Zherikov wrote:I'm just trying to clarify your recommendations as a language author. Whether I like it or not is different question but making things clear is important IMO. Thanks for your answers!Did I get you right that you discourage using `static if` for versioning the code (according to [this post](https://forum.dlang.org/post/tbair7$2ltc$1 digitalmars.com)) with an exception for `static if(__VERSION__ ...)`?Yes, you did. Mainly, because the compiler doesn't generate a predefined version for every change, which is impractical. Frankly, what you're trying to do is hopeless, hence the suggestion to simply pick a minimum __VERSION__ to support.
Jul 29 2022
On Thursday, 21 July 2022 at 03:57:31 UTC, Walter Bright wrote:Yes, the numbers are a failed idea of mine. I'd endorse deprecating them.They are now deprecated: https://github.com/dlang/dmd/pull/14330
Jul 26 2022
On Tuesday, 26 July 2022 at 19:25:14 UTC, Dennis wrote:On Thursday, 21 July 2022 at 03:57:31 UTC, Walter Bright wrote:You misquoted, and debug(number) wasn't discussed. If dependencies can't use numbers, it doesn't mean that nothing can use numbers. All version statements don't work for dependencies, because those can be compiled in a different way, which manifested for phobos in practice. In case of debug statement it can mean debugging fidelity, which is meaningful and can span dependencies, if they are compiled with the same settings.Yes, the numbers are a failed idea of mine. I'd endorse deprecating them.They are now deprecated: https://github.com/dlang/dmd/pull/14330
Apr 16 2023
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)`? I see `version` is a very limited comparing to `static if` - the former checks for "boolean" result (whether an ID is defined) while the latter evaluates condition expression.Consider: ```d enum Test = true; void main() { import std.stdio : writeln; version(Test) { writeln("true"); } else { writeln("false"); } } ``` And this output: ``` $ dmd -run example.d false $ dmd -version=Test -run example.d true ``` A few seconds of hacking with a build system though, and static if seems to be enough: ```d import mbs = magic_buildsystem_definitions; enum Test = true; void main() { import std.stdio : writeln; static if (mbs.Test) { writeln("true"); } else { writeln("false"); } } ``` with that module generated of course by the build system, and any logic you like now capable. version's limited expressiveness is due to experience with `#ifdef` abuse in C, much like (I imagine) limitations like "the code won't even compile if you're not using an import" exists in Go. You could positively say that such limitations are lessons learned and you could negatively say that they're expressions of trauma.
Jul 19 2022
On Wednesday, 20 July 2022 at 01:38:41 UTC, jfondren wrote:A few seconds of hacking with a build system though, and static if seems to be enough: ```d import mbs = magic_buildsystem_definitions; enum Test = true; void main() { import std.stdio : writeln; static if (mbs.Test) { writeln("true"); } else { writeln("false"); } } ``` with that module generated of course by the build system, and any logic you like now capable.I'd like build system to not generate any files with compile-time constants.version's limited expressiveness is due to experience with `#ifdef` abuse in C, much like (I imagine) limitations like "the code won't even compile if you're not using an import" exists in Go. You could positively say that such limitations are lessons learned and you could negatively say that they're expressions of trauma.I'm not sure I got what `#ifdef` issue is referenced. Is it something like the one described in https://www.usenix.org/legacy/publications/library/proceedings/sa92/spencer.pdf?
Jul 19 2022
On Wednesday, 20 July 2022 at 01:38:41 UTC, jfondren wrote:On Wednesday, 20 July 2022 at 01:22:00 UTC, Andrey Zherikov 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. 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, 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 understandI actually have a question since this topic is brought up: What is conceptual difference between `version(FOO)` and `static if(FOO)`? I see `version` is a very limited comparing to `static if` - the former checks for "boolean" result (whether an ID is defined) while the latter evaluates condition expression.Consider: ```d enum Test = true; void main() { import std.stdio : writeln; version(Test) { writeln("true"); } else { writeln("false"); } } ``` And this output: ``` $ dmd -run example.d false $ dmd -version=Test -run example.d true ``` A few seconds of hacking with a build system though, and static if seems to be enough: ```d import mbs = magic_buildsystem_definitions; enum Test = true; void main() { import std.stdio : writeln; static if (mbs.Test) { writeln("true"); } else { writeln("false"); } } ``` with that module generated of course by the build system, and any logic you like now capable. version's limited expressiveness is due to experience with `#ifdef` abuse in C, much like (I imagine) limitations like "the code won't even compile if you're not using an import" exists in Go. You could positively say that such limitations are lessons learned and you could negatively say that they're expressions of trauma.
Jul 19 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 thingRight 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 understandI 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.
Jul 19 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.
Jul 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:Do you have performance benchmark to share?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
Jul 20 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:`static if` can evaluate arbitrarily complex code, it has no upper complexity bound.On Wednesday, 20 July 2022 at 01:22:00 UTC, Andrey Zherikov wrote:Do you have performance benchmark to share?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
Jul 21 2022
On Wednesday, 20 July 2022 at 18:34:49 UTC, Andrey Zherikov wrote:Do you have performance benchmark to share?Feel free to benchmark this: ``` bool run(int seed) { int a=seed, b=10; while(a!=0) { a+=b; b^=a<<8; b+=a; a^=b>>8; if(b==0)return true; } return false; } static if(run(2)); ```
Jul 21 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: ```d 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
Jul 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=16666I don't thins that this is good example. The bug is actually about that `static if` doesn't work with forward declaration: ```d 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.
Jul 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:The interesting thing is that only top-level `static if` fails. This works: ```d void func(A.S s) {} struct A { version (WORKING) struct S {} else static if (true) struct S {} } ```Anyway, "static if" construct is not same as version https://issues.dlang.org/show_bug.cgi?id=16666I don't thins that this is good example. The bug is actually about that `static if` doesn't work with forward declaration: ```d 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.
Jul 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.
Jul 20 2022
On Thursday, 21 July 2022 at 04:11:57 UTC, Walter Bright wrote:On 7/19/2022 3:30 PM, Hipreme wrote:Okay, so what I asked is not exactly doing as people here thought like: ```d version(SDL > 2) ``` What I asked is basically, for maintaining the same behaviour we have right now, when defining like SDL.2.5, it would define: ```d version(SDL.2.5) //Ok version(SDL.2.4) //Ok version(SDL.2.3) //Ok version(SDL.2.2) //Ok version(SDL.2.1) //Ok version(SDL.2.0) //Ok version(SDL.1.9) //Not ok ``` It would basically just insert all possible versions when defining with a number like that, I'm not expecting to use those kind of operators with `version`. I have discussed and many people agree that doing many logical operators (besides `!version` (I do a lot of version(){}else{}) ) is bad.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.
Jul 22 2022
On Friday, 22 July 2022 at 10:36:39 UTC, Hipreme wrote:```d version(SDL.2.5) //Ok version(SDL.2.4) //Ok version(SDL.2.3) //Ok version(SDL.2.2) //Ok version(SDL.2.1) //Ok version(SDL.2.0) //Ok version(SDL.1.9) //Not ok ``` It would basically just insert all possible versions when defining with a number like that, I'm not expecting to use those kind of operators with `version`. IThen what happens when you *don't* want old versions together with the new one?
Jul 22 2022
On Friday, 22 July 2022 at 10:43:03 UTC, Mike Parker wrote:On Friday, 22 July 2022 at 10:36:39 UTC, Hipreme wrote:I'm thinking about newer versions with incremental additions. When I was looking into directx-d bindings, most of newer version depends on older version unless they change its major. The same thing could be applied to: ```d version(SDL.2.5.5) ... version(SDL.2.5.0) //Ok version(SDL.2.4) //not ok ``````d version(SDL.2.5) //Ok version(SDL.2.4) //Ok version(SDL.2.3) //Ok version(SDL.2.2) //Ok version(SDL.2.1) //Ok version(SDL.2.0) //Ok version(SDL.1.9) //Not ok ``` It would basically just insert all possible versions when defining with a number like that, I'm not expecting to use those kind of operators with `version`. IThen what happens when you *don't* want old versions together with the new one?
Jul 22 2022
On Friday, 22 July 2022 at 13:36:37 UTC, Hipreme wrote:I'm thinking about newer versions with incremental additions. When I was looking into directx-d bindings, most of newer version depends on older version unless they change its major. The same thing could be applied to: ```d version(SDL.2.5.5) ... version(SDL.2.5.0) //Ok version(SDL.2.4) //not ok ```And then you're baking a library versioning scheme into the language. Not sure about that.
Jul 22 2022
On 7/22/2022 6:36 AM, Hipreme wrote:version(SDL.2.5.5) ... version(SDL.2.5.0) //Ok version(SDL.2.4) //not okThe reader has no idea what actual feature is being turned on or off.
Jul 22 2022
On Friday, 22 July 2022 at 18:22:52 UTC, Walter Bright wrote:On 7/22/2022 6:36 AM, Hipreme wrote:I understand your point. But there exists a problem. The reason why version was been created seems basically: ```d version(FeatureA){} version(FeatureB){} ``` Trying to use numbers on version doesn't seem to be what you have planned. I believe the naming could be `feature(A)` instead of version because it would make a lot more sense. In my case, I have been coding a game engine which you can turn off or on a lot of features like: `version(JSONParsing)` `version(XMLParsing)`, which it is easy to understand exactly what is happening, but it actually does not really reflect what a version is. But, how one would approach when the feature is version dependent? This becomes a lot harder to reason about, the version number could mean anything. Specially approaching bindings, which other languages already has that convention of making/not making available functions based on version, it becomes even harder when this function can be enabled/disabled and is even build version dependentversion(SDL.2.5.5) ... version(SDL.2.5.0) //Ok version(SDL.2.4) //not okThe reader has no idea what actual feature is being turned on or off.
Jul 22 2022
On Saturday, 23 July 2022 at 00:33:36 UTC, Hipreme wrote:Trying to use numbers on version doesn't seem to be what you have planned. I believe the naming could be `feature(A)` instead of version because it would make a lot more sense. In my case, I have been coding a game engine which you can turn off or on a lot of features like: `version(JSONParsing)` `version(XMLParsing)`, which it is easy to understand exactly what is happening, but it actually does not really reflect what a version is.What is a version? Linux version, Windows version, free version, licensed version, alpha version, beta version, gold version... `version` is about more than just individual features and is broader than "project version number".But, how one would approach when the feature is version dependent? This becomes a lot harder to reason about, the version number could mean anything.You can use the approach I already recommended with static if and enums. Then you get to define exactly what a version number represents (e.g., only features from 2.5.2 or all features from 2.x). I know Walter doesn't like it, but it works great. You can also use your build system to set up specific configurations of version combinations.Specially approaching bindings, which other languages already has that convention of making/not making available functions based on version, it becomes even harder when this function can be enabled/disabled and is even build version dependentConsider again my bindbc bindings. SDL remains backwards compatible on ever minor version, so the API of 2.5 is still available in 2.10. Then there's Lua, which removes or renames C API functions in almost every minor release. Static if + enums allows me to handle both cases with `version(SDL_NNNN)` and `version(LUA_NNNN)`. `version` is very simple and easy to understand. Why would you want to add complexity to it when you can already do what you want to do?
Jul 22 2022
On 7/22/2022 5:33 PM, Hipreme wrote:But, how one would approach when the feature is version dependent? This becomes a lot harder to reason about, the version number could mean anything. Specially approaching bindings, which other languages already has that convention of making/not making available functions based on version, it becomes even harder when this function can be enabled/disabled and is even build version dependentNew versions are not just numbers. They are an arbitrary collection of new features and modified features. Nobody, not even the author, will remember which feature goes with which version number. My recommendation is to use version identifiers for each of those features that changed that matter to your program. It's rarely more than a handful. It'll make your code a pleasure to read, too.
Jul 22 2022
On Sat, Jul 23, 2022 at 12:33:36AM +0000, Hipreme via Digitalmars-d wrote:On Friday, 22 July 2022 at 18:22:52 UTC, Walter Bright wrote:[...] Maybe something like this? version(build1234) { version = FeatureA; version = FeatureB; // etc. } version(build1235) { version = FeatureA; version = FeatureC; // etc. } ... version(FeatureA) { ... /* feature A implementation here */ } version(FeatureB) { ... /* feature B implementation here */ } // etc. T -- What's an anagram of "BANACH-TARSKI"? BANACH-TARSKI BANACH-TARSKI.On 7/22/2022 6:36 AM, Hipreme wrote:I understand your point. But there exists a problem. The reason why version was been created seems basically: ```d version(FeatureA){} version(FeatureB){} ``` Trying to use numbers on version doesn't seem to be what you have planned. I believe the naming could be `feature(A)` instead of version because it would make a lot more sense. In my case, I have been coding a game engine which you can turn off or on a lot of features like: `version(JSONParsing)` `version(XMLParsing)`, which it is easy to understand exactly what is happening, but it actually does not really reflect what a version is. But, how one would approach when the feature is version dependent? This becomes a lot harder to reason about, the version number could mean anything. Specially approaching bindings, which other languages already has that convention of making/not making available functions based on version, it becomes even harder when this function can be enabled/disabled and is even build version dependentversion(SDL.2.5.5) ... version(SDL.2.5.0) //Ok version(SDL.2.4) //not okThe reader has no idea what actual feature is being turned on or off.
Jul 22 2022
On 7/22/2022 8:06 PM, H. S. Teoh wrote:Maybe something like this? version(build1234) { version = FeatureA; version = FeatureB; // etc. } version(build1235) { version = FeatureA; version = FeatureC; // etc. } ... version(FeatureA) { ... /* feature A implementation here */ } version(FeatureB) { ... /* feature B implementation here */ } // etc.Awkward since you cannot import versions from other modules.
Jul 23 2022
On 24/07/2022 7:53 AM, Walter Bright wrote:Awkward since you cannot import versions from other modules.Perhaps we should be changing that. It does seem to be a unnecessary limitation given that an enum can be used in its place.
Jul 23 2022
On 7/23/2022 1:08 PM, rikki cattermole wrote:On 24/07/2022 7:53 AM, Walter Bright wrote:1. then you can't tell which versions are active 2. circular imports become hellAwkward since you cannot import versions from other modules.Perhaps we should be changing that.It does seem to be a unnecessary limitation given that an enum can be used in its place.Yes, and when that was done in druntime it produced baffling issues because of circular imports. The problems got dumped in my lap. I yanked it all out and did it right. No problems since.
Jul 23 2022
On Sunday, 24 July 2022 at 02:24:39 UTC, Walter Bright wrote:Yes, and when that was done in druntime it produced baffling issues because of circular imports. The problems got dumped in my lap. I yanked it all out and did it right. No problems since.Choosing a different set of problems never results in no problems.
Jul 24 2022
On 7/22/2022 3:36 AM, Hipreme wrote:Okay, so what I asked is not exactly doing as people here thought like: ```d version(SDL > 2) ``` What I asked is basically, for maintaining the same behaviour we have right now, when defining like SDL.2.5, it would define: ```d version(SDL.2.5) //Ok version(SDL.2.4) //Ok version(SDL.2.3) //Ok version(SDL.2.2) //Ok version(SDL.2.1) //Ok version(SDL.2.0) //Ok version(SDL.1.9) //Not ok ``` It would basically just insert all possible versions when defining with a number like that, I'm not expecting to use those kind of operators with `version`.I know, this is an 'OR' operation. My proposal is a better way of doing this.I have discussed and many people agree that doing many logical operators (besides `!version` (I do a lot of version(){}else{}) ) is bad.!version is something I try to destroy. Versions should be positive affirmations, not negative ones. For example, version(DEMO) ... do demo stuff... !version(DEMO) ... do release stuff ... Better is to have `version(RELEASE)`. Even better, version the feature itself that you're turning on. Rationale: I've seen endless `#if CompilerVersion > 6` in C with all kinds of versions, and the poor reader has no idea what features are being turned on and off with them.
Jul 22 2022