Why version() ?

Steven Schveighoffer schveiguy at yahoo.com
Tue Feb 10 18:32:18 PST 2009


"Andrei Alexandrescu" wrote
> Steven Schveighoffer wrote:
>> "Walter Bright" wrote
>> Think of code that is versioned around architecture that would look 
>> horrendous if you have to do version statements that have all different 
>> combinations of stuff.  If I have 5 different architectures to support, I 
>> don't want to have to define a module that has 2^5 different version 
>> combinations.  On top of that, the way versioning works, you need 2^4 * 5 
>> different statements:
>>
>> version(A)
>> {
>>    version = AorB;
>>    version = AorC;
>>    version = AorD;
>>    version = AorE;
>>    version = AorBorC;
>>    version = AorBorD;
>>    // ad nauseum.
>> }
>> version(B)
>> {
>>    // oh fun! let's do it again!!!!
>>    version = AorB;
>>    version = BorC;
>>    version = BorD;
>>    ...
>> }
>>
>> When I add another architecture, *gasp* I have to double the statements 
>> (to do them now with and without version(F) ), and now I have to do 
>> another 2^5 statements for the version(F) block.  Wheee!
>
> But this is clearly the wrong way of cutting the pie. What you need is 
> define features that are supported by some of the versions. You don't need 
> to judge in terms of logical operators between versions.
>
> version (A) version = canBeUsedToPickupChicks;
> version (C) version = canBeUsedToPickupChicks;
> // version (B) no good
>

Sometimes, coming up with a better identifier than this || that is not easy.

For example, in Tango, there is a version for Posix, which is defined if 
linux or darwin or bsd is defined, but we sometimes get people arguing that 
Windows is posix compliant too!

Not only that, but are you going to want to define a special identifier in 
the header file that is used exactly ONCE in your code?  Often times, I see 
this in source files:

version(linux)
  version = specialWay;
version(darwin)
  version = specialWay;

Because they need that combination of linux || darwin in one spot, but 
nowhere else.  I see no reason why this is more readable than

version(linux || darwin)

in that one spot.  I do not have to go looking for specialWay in this file, 
or some other header file, or simply have to read through useless repetitive 
statements.  It's perfectly clear what it means.  How does this promote 
confusing versioning?  Many people have pointed out the possibility of 
spelling mistakes now more likely because you have to repetitively specify 
the same version under other version branches.

I see allowing version(x || y) as something that has absolutely no 
drawbacks.  None of the arguments against it have had any merit, because the 
examples of how bad it would be are not bad because of the existance of that 
construct.  They are simply complicated examples of versioned code, which 
would probably benefit from allowing ||.

It would even make code more maintainable in your example:

version(A || C) version = canBeUsedToPickUpChicks;

Note no duplication of the long token you chose ;)

-Steve 





More information about the Digitalmars-d mailing list