Why version() ?

Nick Sabalausky a at a.a
Tue Feb 10 18:43:52 PST 2009


"Walter Bright" <newshound1 at digitalmars.com> wrote in message 
news:gmt8t7$1042$1 at digitalmars.com...
> Derek Parnell wrote:
>> On Tue, 10 Feb 2009 14:01:29 -0800, Walter Bright wrote:
>>
>> My apology. The problem is more than run-time performance issues. The 
>> more
>> pressing problem, IMHO, is the one of maintenance costs. Duplicated code 
>> is
>> a significant cost burden. Not only may each duplication require 
>> updating,
>> but there is extra effort in analyizing every duplicate to see if it 
>> *does*
>> need updating. And every act of updating increases the opportunity for
>> introducing bugs.
>
> Let's take an example, like the enum for O_XXXX in std.c.linux.linux. Some 
> of those values are common between platforms, and some are unique to 
> particular platforms. So you might be tempted to write:
>
{snip}

I have to admit, that's a very compelling example. I hadn't thought of 
anything like that. I guess the moral is "DRY is normally great, but be very 
careful with it when using it across multiple builds." But I'm still not 
sure we should be going that far. For instance:

enum
{
    version(Linux || OSX)
    {
        O_RDONLY = 0,
        O_WRONLY = 1,
        O_RDWR = 2,
        O_CREAT = 0100,
    }
    version(Linux)
    {
        O_APPEND = 02000,
    }
    version(OSX)
    {
        O_APPEND = 8,
        O_SYMLINK = 0x200000,
    }
}

That seems reasonable to me. Granted, with a small enum like that, 
completely replicating the whole enum would be fine, but imagine if it were 
something much larger, like MS or Apple error codes (though that may not be 
an ideal example since they're platform-specific).

Unlike Walter's example, this method clearly allows for DRY, would would be 
quite an improvement on large enums. But I would argue that this method also 
provides for just as much robustness:

Scenario 1: Porting to Windows, BSD, or Joe's Embedded OS:
Walter's example results in an obvious compile-time failure at the enum. 
Mine might not do that (but maybe it *could* still do some sort of 
"version(Linux||OSX) {...} else fail" ), however mine does still cause an 
error anytime there's an attempt to call (or maybe even define) the "file 
open" function (Since there's no valid value for the paramater. Even the 
default value would be invalid).

Scenario 2: Linux User Joe wants to add an "O_PREPEND" (Yea, I know that's 
*very* contrived):
He's going to see three sections, Linux, Mac, and Both. The "Linux||OSX" 
part makes it clear to him that he should double-check the value of 
O_PREPEND on OSX if he wants to stick it in "Both", or else he knows he can 
just leave it in the Linux-only part or check with the project's manager. 
Later on, if Project Manager Suzy uses both systems and knows that O_PREPEND 
is the same on both, she can just move it to the "Both" section.

Besides, without expression-level version(), the project's author might just 
as likely think "Shoot, this is stupid that D doesn't let me make this 
nicely DRY. But I really like DRY, so I guess I'll just resort to an 
external C-like pre-processor".





More information about the Digitalmars-d mailing list