November 28, 2006
Walter Bright wrote:
> Anders F Björklund wrote:
> 
>>> (is there a way to do version(!NOMAIN)?)
> 
> 
> "Not no-how, not no-way!" -- the Cowardly Lion

> 
>  > A patch to do so has been rejected several times,
>  > it's apparently "against the spirit" of version...
>  > (it is supposed to be "positive" and not negative,
>  > see Walter's earlier newsgroup posts* on the topic)
> 
> "Sir, you are employing a double negative." -- Mr. Spock

Yeh, ok, "not no main" is not a great example.

And actually I think if such a think existed the 'not' should be on the 'version' instead of the identifier,
more like #ifndef VAR than #if !VAR

 !version(LeanAndMean) {
    // do some fatty stuff here
 }

The bottom line is, just because D doesn't have negative version checks, doesn't mean the need for them will go away.  It just means that
  "version(X){}else"
becomes the spelling of "!version".  I'd personally rather see !version(X) or not_version(X) than version(X){}else.

But either way it's not a big deal.  Just an odd thing to get all principled over.

--bb
November 28, 2006
Bill Baxter wrote:
> 
> Looks interesting.  Thanks for the link.  The one thing I was most curious about was whether it uses emulation or wrapping of native widgets.  But I can't find that mentioned anywhere.  All the screen shots seem to show a winXP kind of look and some clearly non-native widgets (like the color picker), so I'm thinking it's emulated with winXP look everywhere?  Is it themeable?
> 
> Whoa, though, that QTF is crazy!
> http://www.ultimatepp.org/srcdoc$RichText$QTF$en-us.html
> "WTF" is more what comes to mind... it seems so out of place in a toolkit that puts a priority on simplicity and clarity.
> 
> They should make T-Shirts:
>   Got "{{1:2 A1::l40/60R6@3 A2::! B1:: B2}}"?
> 


Ultimate++ is a window less GUI toolkit. Everything is written from "scratch" and only the TopWindow has a native handle. They are working on skinning in the latest dev releases (which btw have some nice features and are pretty stable).

Harmonia seems to do some of the same things Ultimate++ does.

And yeah QTF is insane :P
November 29, 2006
Anders F Björklund wrote:
> Walter Bright wrote:
> 
>> "Sir, you are employing a double negative." -- Mr. Spock
> 
> "Nobody helps nobody but himself." --Oxmyx
> 
> So are you saying that we should *not* write
> "version(whatever) {} else" for D's #ifndef ?

No, I'm saying one should not have properties that contain a negative, such as NOTMAIN or NOALIAS.
November 29, 2006
Bill Baxter wrote:
> The bottom line is, just because D doesn't have negative version checks, doesn't mean the need for them will go away.  It just means that
>   "version(X){}else"
> becomes the spelling of "!version".  I'd personally rather see !version(X) or not_version(X) than version(X){}else.

Or perhaps rethink why there is a negative version called X in the first place. For example, if you want:

	version (!FULL) { }

it would perhaps be better to redo the version as:

	version (EMPTY) { }

I've been through this with my own code, and it definitely improves the readability to think in positive features rather than negative features. Something about how human perception works. Long ago I read that there's some research to back this up.

For example,

	version (NOFLOAT) => version (INTONLY)
	version (NOTWINDOWS) => version (LINUX)
November 29, 2006
Tomas Lindquist Olsen wrote:
> Bill Baxter wrote:
>>
>> Looks interesting.  Thanks for the link.  The one thing I was most curious about was whether it uses emulation or wrapping of native widgets.  But I can't find that mentioned anywhere.  All the screen shots seem to show a winXP kind of look and some clearly non-native widgets (like the color picker), so I'm thinking it's emulated with winXP look everywhere?  Is it themeable?
>>
>> Whoa, though, that QTF is crazy!
>> http://www.ultimatepp.org/srcdoc$RichText$QTF$en-us.html
>> "WTF" is more what comes to mind... it seems so out of place in a toolkit that puts a priority on simplicity and clarity.
>>
>> They should make T-Shirts:
>>   Got "{{1:2 A1::l40/60R6@3 A2::! B1:: B2}}"?
>>
> 
> 
> Ultimate++ is a window less GUI toolkit. Everything is written from "scratch" and only the TopWindow has a native handle. They are working on skinning in the latest dev releases (which btw have some nice features and are pretty stable).

Thanks.  I think both approaches have merit.  Sometimes you really just want to make a custom widget that draws itself and will work immediately on every platform (then emulation==good).  But other times you really want to have the native look-and-feel (then wrapping==good).  Other times you just want to have a consistent look or theme across all platforms (then emulation==good).  But some particular things like file dialogs tend to easier on users if they are native (then wrapping==good).

> Harmonia seems to do some of the same things Ultimate++ does.

Harmonia seems an interesting beastie.  Not quite my cup of tea, but some interesting ideas there to be sure.

> And yeah QTF is insane :P

The only thing I can figure is that Ultimate++ must have been created by some BBS hackers who wrote ANSI graphics in their sleep back in the day.

--bb
November 29, 2006
Walter Bright wrote:
> Bill Baxter wrote:
>> The bottom line is, just because D doesn't have negative version checks, doesn't mean the need for them will go away.  It just means that
>>   "version(X){}else"
>> becomes the spelling of "!version".  I'd personally rather see !version(X) or not_version(X) than version(X){}else.
> 
> Or perhaps rethink why there is a negative version called X in the first place. For example, if you want:
> 
>     version (!FULL) { }
> 
> it would perhaps be better to redo the version as:
> 
>     version (EMPTY) { }
> 
> I've been through this with my own code, and it definitely improves the readability to think in positive features rather than negative features. Something about how human perception works. Long ago I read that there's some research to back this up.
> 
> For example,
> 
>     version (NOFLOAT) => version (INTONLY)
>     version (NOTWINDOWS) => version (LINUX)

Yeh, makes sense.  So putting a positive spin on it, the thing I want is something like version("LIBRARY") or version("CONSOLE")

But that doesn't change the fact that the version basically involves leaving out code, so I still will want to do:

      !version(LIBRARY)
      {
            int WinMain(...
      }

In this case what I really want, though, is to have a version(MAIN) that's the default, i.e. it's what you get without specifying any -version flags to dmd.


--bb
November 29, 2006
Walter Bright wrote:
> Bill Baxter wrote:
>> The bottom line is, just because D doesn't have negative version checks, doesn't mean the need for them will go away.  It just means that
>>   "version(X){}else"
>> becomes the spelling of "!version".  I'd personally rather see !version(X) or not_version(X) than version(X){}else.
> 
> Or perhaps rethink why there is a negative version called X in the first place. For example, if you want:
> 
>     version (!FULL) { }
> 
> it would perhaps be better to redo the version as:
> 
>     version (EMPTY) { }
> 
> I've been through this with my own code, and it definitely improves the readability to think in positive features rather than negative features. Something about how human perception works. Long ago I read that there's some research to back this up.
> 
> For example,
> 
>     version (NOFLOAT) => version (INTONLY)
version (BIGNUMONLY)
version (MATHUNSUPPORTED)
version (COMPLEXONLY)

>     version (NOTWINDOWS) => version (LINUX)

I hate to say this, but that example just plain stupid. All it will ever do is limit your code to work on only certain operating systems. That's hindering portability, and that's no good.

As it turns out, it's often the case that such-and-such does work on every sane operating system, and therefore version (!Windows) makes sense.

I know I've ran into instances where $WEIRD_SOCKET_FEATURE_X crashes horribly on a certain operating system, so I was forced to #ifndef __APPLE__. The same feature worked fine on literally every other system I tested it on, so it would be ridiculous to do an #ifdef for everything BUT Apple.

version (darwin)
version (BSD)
version (Solaris)
version (SkyOS)
version (DJGPP)
version (HURD)
version (ObscureOS)
version (OSYetToBeInvented)


Thinking in positives is great, but so unrealistic as to be completely valueless. version statements in reality are used like indexes into sets. The set of operating systems, the set of C libraries, the set of compielrs. And it's unrealistic and ignorant to try to index EVERY member except for whichever one you like, especially since the list is always growing.

Not everything has a positive opposite. In fact, most everything doesn't.

 - Gregor Richards
November 29, 2006
Gregor Richards wrote:
>>     version (NOTWINDOWS) => version (LINUX)
> I hate to say this, but that example just plain stupid. All it will ever do is limit your code to work on only certain operating systems. That's hindering portability, and that's no good.
> 
> As it turns out, it's often the case that such-and-such does work on every sane operating system, and therefore version (!Windows) makes sense.

I've seen a lot of code that did that, and it was nearly always broken. That's one motivation for operating system versions should be positives, not "this is for not windows" or "this is for not linux". Such fundamentally are wrong, and will bite you or the maintainer sooner or later.

> I know I've ran into instances where $WEIRD_SOCKET_FEATURE_X crashes horribly on a certain operating system, so I was forced to #ifndef __APPLE__. The same feature worked fine on literally every other system I tested it on, so it would be ridiculous to do an #ifdef for everything BUT Apple.
> 
> version (darwin)
> version (BSD)
> version (Solaris)
> version (SkyOS)
> version (DJGPP)
> version (HURD)
> version (ObscureOS)
> version (OSYetToBeInvented)

What I'd do is have APPLE_SOCKET_BUG with the workaround, and the default for the else. That way, you can search for the workarounds for that bug, and they won't be confused with other apple features or other apple bugs. Furthermore, if apple fixes that bug, you can update your code much easier with a targeted update than if you painted the entire apple os that way.

It's common practice (such as in STL) to target specific bugs with specific identifiers, and then have a configuration file which sets up the bugs for each system.

> Thinking in positives is great, but so unrealistic as to be completely valueless. version statements in reality are used like indexes into sets. The set of operating systems, the set of C libraries, the set of compielrs. And it's unrealistic and ignorant to try to index EVERY member except for whichever one you like, especially since the list is always growing.
> 
> Not everything has a positive opposite. In fact, most everything doesn't.

I don't agree, and as an example I suggest the socket bug approach above.
November 29, 2006
Walter Bright wrote:
> Gregor Richards wrote:
>>>     version (NOTWINDOWS) => version (LINUX)
>> I hate to say this, but that example just plain stupid. All it will ever do is limit your code to work on only certain operating systems. That's hindering portability, and that's no good.
>>
>> As it turns out, it's often the case that such-and-such does work on every sane operating system, and therefore version (!Windows) makes sense.
> 
> I've seen a lot of code that did that, and it was nearly always broken. That's one motivation for operating system versions should be positives, not "this is for not windows" or "this is for not linux". Such fundamentally are wrong, and will bite you or the maintainer sooner or later.
> 
>> I know I've ran into instances where $WEIRD_SOCKET_FEATURE_X crashes horribly on a certain operating system, so I was forced to #ifndef __APPLE__. The same feature worked fine on literally every other system I tested it on, so it would be ridiculous to do an #ifdef for everything BUT Apple.
>>
>> version (darwin)
>> version (BSD)
>> version (Solaris)
>> version (SkyOS)
>> version (DJGPP)
>> version (HURD)
>> version (ObscureOS)
>> version (OSYetToBeInvented)
> 
> What I'd do is have APPLE_SOCKET_BUG with the workaround, and the default for the else. That way, you can search for the workarounds for that bug, and they won't be confused with other apple features or other apple bugs. Furthermore, if apple fixes that bug, you can update your code much easier with a targeted update than if you painted the entire apple os that way.
> 
> It's common practice (such as in STL) to target specific bugs with specific identifiers, and then have a configuration file which sets up the bugs for each system.
> 
>> Thinking in positives is great, but so unrealistic as to be completely valueless. version statements in reality are used like indexes into sets. The set of operating systems, the set of C libraries, the set of compielrs. And it's unrealistic and ignorant to try to index EVERY member except for whichever one you like, especially since the list is always growing.
>>
>> Not everything has a positive opposite. In fact, most everything doesn't.
> 
> I don't agree, and as an example I suggest the socket bug approach above.

This discussion has made me remember something I though about a while ago...
While I understand the reasoning for disallowing negated version identifiers / version statements from the above, I dont understand why we can't use logical operators with versions:

version(Windows)
{
    writefln("I know your OS");
}
else version(linux)
{
    writefln("I know your OS");
}
else version(darwin)
{
    writefln("I know your OS");
}
else
{
    writefln("I don't know your OS");
}

VS.

version(Windows || linux || darwin)
{
    writefln("I know your OS");
}
else
{
    writefln("I don't know your OS");
}

This genuinely reduces code duplication and is thus according to standard D mentality: less prone to be buggy, easier to maintain, and faster to write.
Though if something like this was to be allowed, && and ! probably should be as well.
IIRC the reason I wanted something like this was for a demo where I use a proprietary library that only supports win32 and linux, and thus those two versions wants a single implementation, all other will not use it at all.

I realise this can be done with something like:

version(Windows) version=OK;
else version(linux) version=OK;
version(OK)
{
	...
}
else
{
	...
}

but just:

version(Windows || linux)
{
	...
}
else
{
	...
}

is clearer IMHO.
November 29, 2006
Tomas Lindquist Olsen wrote:
> Walter Bright wrote:
>> Gregor Richards wrote:
>>>>     version (NOTWINDOWS) => version (LINUX)
>>> I hate to say this, but that example just plain stupid. All it will ever do is limit your code to work on only certain operating systems. That's hindering portability, and that's no good.
>>>
>>> As it turns out, it's often the case that such-and-such does work on every sane operating system, and therefore version (!Windows) makes sense.
>>
>> I've seen a lot of code that did that, and it was nearly always broken. That's one motivation for operating system versions should be positives, not "this is for not windows" or "this is for not linux". Such fundamentally are wrong, and will bite you or the maintainer sooner or later.
>>
>>> I know I've ran into instances where $WEIRD_SOCKET_FEATURE_X crashes horribly on a certain operating system, so I was forced to #ifndef __APPLE__. The same feature worked fine on literally every other system I tested it on, so it would be ridiculous to do an #ifdef for everything BUT Apple.
>>>
>>> version (darwin)
>>> version (BSD)
>>> version (Solaris)
>>> version (SkyOS)
>>> version (DJGPP)
>>> version (HURD)
>>> version (ObscureOS)
>>> version (OSYetToBeInvented)
>>
>> What I'd do is have APPLE_SOCKET_BUG with the workaround, and the default for the else. That way, you can search for the workarounds for that bug, and they won't be confused with other apple features or other apple bugs. Furthermore, if apple fixes that bug, you can update your code much easier with a targeted update than if you painted the entire apple os that way.
>>
>> It's common practice (such as in STL) to target specific bugs with specific identifiers, and then have a configuration file which sets up the bugs for each system.
>>
>>> Thinking in positives is great, but so unrealistic as to be completely valueless. version statements in reality are used like indexes into sets. The set of operating systems, the set of C libraries, the set of compielrs. And it's unrealistic and ignorant to try to index EVERY member except for whichever one you like, especially since the list is always growing.
>>>
>>> Not everything has a positive opposite. In fact, most everything doesn't.
>>
>> I don't agree, and as an example I suggest the socket bug approach above.
> 
> This discussion has made me remember something I though about a while ago...
> While I understand the reasoning for disallowing negated version identifiers / version statements from the above, I dont understand why we can't use logical operators with versions:
> 
> version(Windows)
> {
>     writefln("I know your OS");
> }
> else version(linux)
> {
>     writefln("I know your OS");
> }
> else version(darwin)
> {
>     writefln("I know your OS");
> }
> else
> {
>     writefln("I don't know your OS");
> }
> 
> VS.
> 
> version(Windows || linux || darwin)
> {
>     writefln("I know your OS");
> }
> else
> {
>     writefln("I don't know your OS");
> }
> 
> This genuinely reduces code duplication and is thus according to standard D mentality: less prone to be buggy, easier to maintain, and faster to write.
> Though if something like this was to be allowed, && and ! probably should be as well.
> IIRC the reason I wanted something like this was for a demo where I use a proprietary library that only supports win32 and linux, and thus those two versions wants a single implementation, all other will not use it at all.
> 
> I realise this can be done with something like:
> 
> version(Windows) version=OK;
> else version(linux) version=OK;
> version(OK)
> {
>     ...
> }
> else
> {
>     ...
> }
> 
> but just:
> 
> version(Windows || linux)
> {
>     ...
> }
> else
> {
>     ...
> }
> 
> is clearer IMHO.


Agreed.  'version' is basically just an emasculated special case of 'static if'.  'static if' didn't exist when 'version' was created, but now that it does, I think it would make more sense if version became a kind of static if with access to a special version namespace.  'Windows' should be treated like an alias for true if it is indeed defined, otherwise false, and you should be allowed to do boolean ops with any constant values in your program inside the version statement.

--bb