- Feature Articles
- CodeSOD
- Error'd
- Forums
-
Other Articles
- Random Article
- Other Series
- Alex's Soapbox
- Announcements
- Best of…
- Best of Email
- Best of the Sidebar
- Bring Your Own Code
- Coded Smorgasbord
- Mandatory Fun Day
- Off Topic
- Representative Line
- News Roundup
- Editor's Soapbox
- Software on the Rocks
- Souvenir Potpourri
- Sponsor Post
- Tales from the Interview
- The Daily WTF: Live
- Virtudyne
Admin
If they were trying to work within a library, then they could have used the, already defined (via import), TRUE and FALSE. If this is not the case, then they might have defined them using these lines because they wished to use them as literals (not for comparison's sake which is just stupid in the first place) and, if using the version of C without bools, this would be OK. However, defining MAYBE in this way is just stupid. There is no valid reason for this. I reread my previous post. Didn't mean to flame you, I'm joking...sorry if I came across wrong.
Admin
What about 4: "My captcha is XXXXX, isn't that so funny!"
Admin
Now, implement a protocol. I'm given a list of numeric values that correspond to values that have meaning. Sounds like an enum to me. All of a sudden the ability to do this is REALLY nice:
enum foo { a = 0, b = 1, c = 2, d = 3, e = 3, };
(and the d==e isn't a typo).
All of a sudden you can now do a whole lot more than you could before.
Remember, C isn't a high-level programming language. C++ varies all over the place, depending on how you use it. But C is a high-level assembly language. It was principally designed to make it easier to code, to the machine. Which is why it has pointers and not objects.
When writing protocol implementations, being able to drop a C struct down on an incoming packet makes parsing the packets so much easier.
Admin
Been there, done that, many times. Enums are great for creating a small namespace of related constants.
Admin
I love this thedailywtf. The best part is the comments from people who supposedly should know better, saying this or that is not really a wtf, but perfectly reasonable.
In C (all the way back to K&R C) non-zero values are always true, that's the way the language is designed. Yes, having an unknown value is useful (particularly in databases), but it should never be added to true/false. Otherwise, somebody assuming that the code is halfway sane is going to do something like:
You want a 'maybe' value? Fine, but for God's sake come up with something other than true and false for the other values.
Admin
Firtly I too apologize as my post could have come off nicer. I was just getting frustrated as it feels as if some people here are just enjoying a little too much other people's screwups without trying to understand what could have lead the original author to write what they did.
What's funny is I myself have done things in a similar way including redefining certain values.
I've created smaller header files that duplicated certain definitions simply to avoid having to import the large header file. If this thing is written in C, there's a decent chance this part of it is also old and I remember working on limited resources and taking time out to speed up the compilation process as much as possible. It wasn't until much latter that we started to get more fine-grained compilation in C/C++. It used to be that if you compiled the program you compiled all of it even if you didn't have to because the compilers just weren't that sofisticated.
Admin
I'm familiar with K&R. And perhaps the point of this is that maybe and true are supposed to work the same way in 50% of the code and in some cases maybe should be treated specially.
And yes there's true and false and drum roll indeterminate.
If you have a treeview with checkboxes and you use rules: checking/unchecking the parent checks/unchecks the child checking/unchecking all children checks/unchecks the parent
you have to use an indeterminate state on the parent when the children are mixed. Indeterminate, Maybe, Undefined all work here, but none of them mean true or false.
Admin
should be sophisticated, not sofisticated. Teaches me to not rush.
Admin
Robin Hood: Blinkin! What are you doing? Blinkin: Guessing. I guess no one's coming.
Admin
Part of me wants to believe this is not as WTF-esque as it initially sounds, like there's some special reason for wanting to do this.
Perhaps it's used in some kind of branch-prediction hint to the compiler?
Admin
So you should not use True or False, as the other poster said. These are boolean values and whenever you need to use a third value you are no longer boolean but rather now in the realm of the enum.
Keep in mind this is how you use the data. As the data is saved yes you can have a third null value. If that Null value can be seen as one of the defined boolean values you can still use a boolean.
I've said it before but I will reiterate. A table field called IsValid can have True/False/Null values, but when reading it, it is safe to assume that Null=False. This makes it a bi-state value hence a boolean. A table field called Male may have True/False/Null values, but you can not safely assume that Null=False or Null=True. You have to go with Undertermined, this makes it an enumerator and should be properly listed as Gender with Male/Female/Undetermined as it's members.
Trying to make a tri-state boolean is simply a effort to fix a bad design with an even worse solution. Instead just go with a proper solution and use an enumerator.
Simple test if you need an boolean or an enum, can you do the following: if(!Value) If you can't you are using an enum, if you can you are using a boolean. With three states, you can't do it, period, end of story.
Anyone that thinks that booleans can be tri-state either didn't pay attention during basic CS theory or is simply an idiot, and I won't hesitate to say that to their face.
Admin
I would never do anything like that,
#define MAYBE 0.5
is just between FALSE and TRUE
or even better;
#define MAYBE (rand()%2)
for really easy debugging...
Admin
Oh this is nothing, at my previous job we had a situation where someone wrote, in Java: boolean test;
[...]
if( test == true ) { [...] } else if( test == false ) { [...] } else { [...] }
(with code that is not important in the [...], but suffice it to say did something meaningful).
Admin
The WTF is the real WTF:
"One would assume that "maybe" a plane hitting a box at least requires further testing."
Obviously you've never written geometric code. There are cases which are INDETERMINATE within the precision of a float or a double. That's what MAYBE means.
"there are definitely situations where it's safer to assume that a "maybe" is TRUE and not FALSE"
Yes, that's what the higher-level logic is there for. It is the first layer capable of deciding what to do when MAYBE is returned. It might want to pick TRUE, or it might want to pick FALSE, or it might want to run a fabulously expensive rational-bignum geometric intersection test that never returns MAYBE.
Absolutely the wrong thing to do would be for the API to return TRUE or FALSE arbitrarily when the situation is actually MAYBE.
"You should MAYBE turn left at the next intersection and go 5 miles, versus turning right and going approx. 23995 miles."
This is completely fatuous. MAYBE would be returned if the LEFT distance is 12,000.000000 and the RIGHT distance is 12,000.000000 and the error inherent in the calculation is O(0.000001). Why would it return MAYBE for something that is unambiguously TRUE or FALSE?
Sometimes the WTFs say more about the WTFer than the original coder.
Admin
Don't be silly, there's nothing wrong with specifying explicit values for enums. In fact, one of the most common reasons people do it is to AVOID careless with conversions: if you specify the starting value at 1, uninitialized ints (zero) won't map to any enum value. Instead of getting weird, unexpected, random behaviour, you get a conversion error.
(Disclaimer: this isn't true for EVERY language)
Admin
#define YES 1 #define NO 0 #define MAYBE 2 #define I_DONT_KNOW 3 #define CAN_YOU_REPEAT_THE_QUESTION 4
Admin
data Drool = False | Maybe | True data Fool = False | ProbablyNot | Maybe | Probably | True data Tool = False | ProbablyNot | Possibly | Maybe | Probably | True | NotSpecified | Unknown | FileNotFound | WhoCares
Admin
Admin
That's probably a good thing, at least that way his code will use that value and stay consistant with wherever that value was inherited from.
Admin
So he has an enum without the enum. The original code can be pretty much replaced with:
enum { FALSE = 0, TRUE = 1, MAYBE = 2 }
What a lot of people seem to be assuming is that the original coder was trying to create a boolean and not just a enum with number defines. They'll also probably use this a lot like a enum since they can't do negation operations against it safely.
While an enum would be preferrable in a new situation I'd not fault them for using #defines instead of enums as long as they knew what they were doing.
If we're going to have WTF's we should be a little more discriminating. As far as WTF's go this one's pretty weak -- as there are plenty of libraries out there including major platforms that do it this way. A lot of people say, "if the big boys do it, it must be ok".
Admin
Aren't macros unsafe as well due to the problems that can be caused due to incompatible types being passed?
inline functions / templates and const's are the way to go!
Besides, I was under the impression macros were deprecated in C++ anyhow...
Admin
Aren't macros unsafe as well due to the problems that can be caused due to incompatible types being passed?
inline functions / templates and const's are the way to go!
Besides, I was under the impression macros were deprecated in C++ anyhow...
captcha: WTF does captcha mean anyhow?
Admin
cute ;o)
oh, and the captcha is tesla - also fitting well, somehow...
Admin
FALSE != !TRUE
The logic is buggy...
Capcha: craaazy. I can't agree more...
Admin
Macros are very much a part of C++ -- at least last time I checked. They're fall to integral to existing code to be deprecated.
Macros are unsafe for a number of reasons however simple #defines likes this are about as safe as you can get with macros. One should avoid macros for things like
#define f(a) (a) + (a)
because this:
f(++i)
can turn into
++i + ++i
which isn't what you intended at all. And remember we don't know that all of this was intended for C++. Here with #define FALSE 0, #define TRUE 1 and #define MAYBE 2, you will get precisely the effects of an enum without the ability to use the enum as a type, but then again C doesn't really enforce enums that strictly.
So if I have
HRESULT = MyFunction(a, b, c) if (HRESULT == TRUE) DoSomethingElse()
the true will be translated to 1 and you'll get
HRESULT = MyFunction(a, b, c) if (HRESULT == 1) DoSomethingElse()
Unfortunately you can't use it like a true boolean, but given three states you can't use it as a boolean because its not one. And while one would assume that having something that looks like a boolean that isn't a boolean is a bad idea, unfortunately that's just the way it was done in a lot of places. C's lack of a true boolean type meant you either had to just forego it and use int, short, char or whatever and use #defines or enums to represent the values.
Here's the thing though: because Microsoft and a number of other major libraries in C used #defines for TRUE and FALSE, then if you want to use it too then you have use #defines or else you risk type incompatabilities with the enum in all the other code that's expecting #defines.
And yes enums and consts are preferable, especially in a good compiler, but one of the beauties of #defines is they have no binary overhead. There's no type involved so they just kind of melt away post-preprocessor. They just become the number. Now in a good compiler where you haven't externed anything you'll end up with much the same result, but remember that you can change a const in C/C++ either with a C-style cast () in C/C++ or with a const_cast in C++.
So after awhile you realize (at least to me) that its not so cut and dry. In any large program there's dozens of hacks and pseudohacks that are in place because there's just no better way once everything is taken into account. Now there are plently of actual WTF's out there performed by people like Paula who don't know what they're doing and that's great, but before we start getting knee-jerk in our reactions I suggest we allow for the possibility that maybe the original coders weren't stupid.
Admin
Correction: They're far to integral to existing code to be deprecated.
Admin
I can think of one example where this is "ok" (perhaps not absolutely correct, but ok) (and I haven't checked if it's already posted :p). In some games where collision detection occurs, objects can have two collision meshes: high detail, and low detail. high detail is generally more of a "shrunk wrap" and low detail more of a bounding box type thing.
On each tick, when testing a collision between a projectile and the object, you would first test if the projectile's movement vector will place it within (volumetrically) the outer (low detail) collision model, if it is queue it for high-detail collision detection, if not try the next object/projectile pair.
Thus the projectile could either: FALSE - Miss completely MAYBE - Be somewhere inside the outer one, and pending investigation could become: TRUE - it hits the high-detail one.
Which optimises it a bit (i.e. you can discard any computationally intense high detail calculations if the low detail one misses)
captcha: paint... like with numbers. or booleans.
Admin
um.. !1 != 0 etc..
technically... !0 == -1 !1 == -2 !2 == -3
Hence why VB uses -1 as it's internal true value, though with most systems the conditional logic simply says that 0 is false and anything else is true.
Admin
See Multi-valued Logic
http://en.wikipedia.org/wiki/Multi-valued_logic http://search.cpan.org/~summer/Math-Logic-1.19/Logic.pm#multi-degree_logic
As has been said, MAYBE is a perfectly valid truth value when doing macro/micro check logic. Once you get into heavy math on a computer, you start estimating to save CPU time.
If I remember correctly, Hindi originally had 4 truth values in daily logic, Navajos had 6 truth values, fuzzy logic has "infinite", etc. The world has not always ran on Greek logic.
Though there's a surprisingly strong correlation between the rise of categorical logic and monotheism. ;oP (please don't let that start anything)
Admin
Admin
WRONG!
!0 == 1 !1 == 0 !2 == 0 !3 == 0
For an int, PROBABLY;
~0 == -1 ~1 == -2 ~2 == -3
Admin
#define NOT_TONIGHT_I_HAVE_A_HEADACHE -1
Admin
Gosh ... why 3D geometric. What is the difference to 1D, 2D or 4D or 543D ? Always there are 3 states.
Can't you guys imagine alorithm which gives no concrete result ? For example some simple algorithm to determine ... let's say intersection of figures .. which is weak - thus very fast, so if it returns maybe the full featured slow version is used ...
I can't stand this lack of imagination which is typical to this crowd of FILE_NOT_FOUND bounded minds !
WTF ... as someone repeated 1000 times are those comments, and this CodeSDD is also a WTF, no the contents.
Admin
maybe is valid, little googleup
http://ai0.eu/start/cms.php?art=xnumbers
Admin
Nothing wrong with Maybe. It's used all the time in database systems (and elsewhere)... it's just known as NULL instead. If something cannot be irrevocably true, or false, i.e. there is no data entered then it is a NULL. This is the same as the Maybe.
No WTF here.
Admin
Admin
You might like to look at Intuitionism
Admin
Modern, standards-compliant C pre-processors generally don't substitute the "define" in "#define", even if you "#define define foo". (Apparently, older pre-processors did, though). There's a note about it in the IOCCC guidelines.
Admin
And you have just shown yourself wrong in your thinking.
With 3d calculations, yes you use a bounding box that is low resolution for initial checking of collisions. But you never MAYBE hit it, you either hit it or your didn't. If you didn't hit the low res version you don't check further. If you did hit it then you check the high res mesh, which you either hit or you didn't. There is no maybe in here. It is always true or false when working at the code level. The implications is that if you hit the low res, you maybe hit the high res, but the maybe is never seen as one. the test goes like this:
If(HitLowRes()) { If(HitHighRes()) WeHitIt = True; }
I admit this is a bit simplified, but no reason to add all the 3d checking code in here. Just note that there is no maybe.
Admin
It depends on the data.
If you have a field such as Validated that is boolean, yes the database can be True/False/Null but when using the data the Null values can safely be assumed to be False. If you have a field defined as boolean where the usage of that field can not safely assume either a true or false state then you have an enumerator with three states. The problem here is that by choosing a boolean in the database you have no limited yourself to three values when later you may need a fourth, this will invariably lead to problems as the software ages and many more cases arise during live usage.
Ultimately it comes down to if you have two strongly defined states, like the Validated state above, it either is or it isn't, and if the data is not specifically provided, you assume it isn't. The idea is simple.
Admin
I can't believe all of the people that are defending this as not being a WTF.
A boolean has two values, True and False. If you add a third value, it's no longer a boolean, plain and simple. Therefore, using TRUE and FALSE as names for the values of non-booleans is a WTF.
If you need three values, don't call either of them by boolean names. Use something else that makes sense in context. Using TRUE and FALSE inappropriately makes your code unreadable and unmaintainable by other people, and makes you look like a moron.
Admin
As I've said multiple times, there are times when you simply should do this small bad thing rather than deal with the headache of a bigger bad thing.
Let's say you're using a library with no third state, but you have to extend that state. You can either: a) simply add a third "Maybe" state and deal with tri-state pseudo-boolean OR b) rewrite your code to use new values so that code from the external library looks like:
int f(void) { return TRUE; }
but then in your code, you're comparing it like so:
if (f() == HIRES) DoSomething();
Either way you're screwed. Sometimes the right way to do something isn't feasible. Given the situation above I'd suggest simply adding the third state "Maybe".
Admin
The real wtf is the presence of NULL in the most used DBMSs.
Admin
Why not use ALWAYS, NEVER, and MAYBE?
#define ALWAYS 1 #define NEVER 0 #define MAYBE 2
Admin
I sometimes wonder about GUI programming -- it seems to be a cargo cult all of its own.
There are two separate state sets here: one represents the state of the checkbox (widget), and one represents the state of the (tied) variable.
It is either true or false that the widget is read-only. (Conceivably it could also be hidden, yes, but then there doesn't seem to be much point in painting the damn thing on the screen in the first place.)
The tied variable is also either in the true state or the false state.
There is no indeterminacy here at all. (Let alone a "maybe.") Smooshing state together like this is almost as bad as expressing a rich state set as a collection of apparently unconnected predicates. I have seen far too many implementations of comms protocols blow up on the latter, and heard far too many GUI programmers protest that their system is "just not practically testable: there are so many states to consider." Which is usually a consequence of the thinking here.
Admin
Exactly. To the people defending this code, please recognize that ~30 years of C tradition has TRUE and FALSE defined as 1 and 0 respectively, and that these have always represented a logical boolean value. There is no room for MAYBE.
If you want to define your own fuzzy logic, you don't override the boolean logic 99% of programmers are going to anticipate. You create a new enum (or other datatype) as an implicit note to new developers that they're going to have to go find out what it means.
Admin
No. There is no excuse for this.
Assuming you want to go with a tristate boolean, use this: enum tristate { MYTRUE = TRUE, MYFALSE = FALSE, MAYBE = 2 };
(first confirming that "2" isn't already taken as a "boolean" value in the external library)
The enum is exactly equivalent to the #defines, except that it avoids using TRUE/FALSE. Assignments can be done back and forth between any library that uses TRUE/FALSE. Of course, make sure that any MAYBEs are checked before calling any external library functions, since you've effectively defined a new data type that the library will not understand.
Admin
#define OUTLOOK_NOT_SO_GOOD 6
Admin
It wouldn't surprise me to learn that the "father" of Visual Basic, Alan Cooper, was traumatised as a child by a vicious and unprovoked attack by Martin Richards, the originator of BCPL. (Upon which, ironically, C was based. I can just see all the snopes-heads lining up now...)
Thing is, BCPL had 0 as true and -1 as false. This works very well with traditional logic-gate styled bitwise arithmetic: no matter what the word size (given 2s complement, of course), false AND false gives false, false XOR false gives true, etc.
Why K, R & P were pointy-headed enough to select a single bit for the determinant is beyond me. Maybe it was too much kool-aid that night, although I suspect the answer is, as usual, that there's some horrific cpu flag buried deep in a PDP-8 that saves three and a half cycles in the kernel during some really important operation like pretending that "everything is a file."
Oops, sorry, forgot to wrap that in <rant/>.
Admin
Except now you've added three extra symbols to the global namespace (remember C) when you only needed one.
Some questions I ask myself:
When reading a line of code will another programmer understand what I'm talking about? e.g.
if (Intersects()) return TRUE; if (Touches()) return MAYBE; if (DoesntTouch()) return FALSE;
there's a pretty good chance they'll know what I mean.
Once explained briefly will another program have difficultly using it in the right context?
Is it performant?
Does it create extraneous symbols in the global namespace that might prevent other uses of that name?
Is the scope appropriate (global, struct, class, local, file)?
Does it break precident?
MAYBE in this context passes most of these tests. What tests does maybe fail other than it's not the way it's done? As above breaking precident is an important consideration, but its not the only one.