• (cs) in reply to Orion Adrian
    Orion Adrian:
    I'm not saying that there isn't a better solution. My point was to say that many rules are bent and broken for compatibilities'[fixed] sake. When I read this I see someone as importing another library that has these defined already (not MAYBE, but TRUE AND FALSE). My guess is the library in question is windef.h or something that itself uses windef.h.

    So the question is, did they screw up because they didn't know they shouldn't do it? Or were they simply not trying to, excuse the pun, redefine TRUE and FALSE but rather use what was already there.

    A lot of things that look like WTFs aren't. They are instead people trying to simplify their lives by working within the libraries and technical realities of the systems and libraries they were given.

    That's what I mean by "Don't presume."

    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.

  • Scottford (unregistered) in reply to Winter
    Winter:
    3 things I've noticed and stop me from wanting to register to post here:

    "FIRST POST!!11!" occurring for three quarters of the first page of any public discussion

    "The REAL WTF is ____" followed by some extremely dodgy code (usually)

    and then the template posts. (What no FILE_NOT_FOUND?!, Man that sounds like job for PAULA BEAN! etc etc)

    captcha is stinky. Damn right!

    What about 4: "My captcha is XXXXX, isn't that so funny!"

  • Woody (unregistered) in reply to mkb
    2.) enums don't have a set value. If you are using them this way (eg enum { FOO = 2, BAR, BAZ}) or casting enums to ints, STOP.

    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.

  • Woody (unregistered) in reply to EvanED
    enum FlagSet { FLAG_A = 1, FLAG_B = 2, FLAG_C = 4, FLAG_D = 8, FLAG_E = 16 };

    foo( FLAG_A | FLAG_B | FLAG_D );

    Been there, done that, many times. Enums are great for creating a small namespace of related constants.

  • anonymous guy (unregistered)

    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:

    result = MAYBE;
    // later somebody does this:
    if (result) {
      ; // true
      }
    else {
      ; // false
      }
    

    You want a 'maybe' value? Fine, but for God's sake come up with something other than true and false for the other values.

  • Orion Adrian (unregistered) in reply to Edowyth
    Edowyth:
    Orion Adrian:
    I'm not saying that there isn't a better solution. My point was to say that many rules are bent and broken for compatibilities'[fixed] sake. When I read this I see someone as importing another library that has these defined already (not MAYBE, but TRUE AND FALSE). My guess is the library in question is windef.h or something that itself uses windef.h.

    So the question is, did they screw up because they didn't know they shouldn't do it? Or were they simply not trying to, excuse the pun, redefine TRUE and FALSE but rather use what was already there.

    A lot of things that look like WTFs aren't. They are instead people trying to simplify their lives by working within the libraries and technical realities of the systems and libraries they were given.

    That's what I mean by "Don't presume."

    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.

    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.

  • Orion Adrian (unregistered) in reply to anonymous guy
    anonymous guy:
    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:

    result = MAYBE;
    // later somebody does this:
    if (result) {
      ; // true
      }
    else {
      ; // false
      }
    

    You want a 'maybe' value? Fine, but for God's sake come up with something other than true and false for the other values.

    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.

  • Orion Adrian (unregistered) in reply to Orion Adrian
    Orion Adrian:
    because the compilers just weren't that sofisticated.

    should be sophisticated, not sofisticated. Teaches me to not rush.

  • mnature (unregistered)

    Robin Hood: Blinkin! What are you doing? Blinkin: Guessing. I guess no one's coming.

  • Anonymous Coward (unregistered)

    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?

  • (cs) in reply to Orion Adrian
    Orion Adrian:
    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.

    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.

  • Paxinum (unregistered)

    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...

  • Miauen (unregistered)

    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).

  • Eddie Pedant (unregistered)

    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.

  • Aaron (unregistered) in reply to mkb
    mkb:
    There are things you can do to ints that you can't do to enums.
    You mean like, store it in a database? Or combine them into a bitmask?

    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)

  • Glenn Lasher (unregistered)

    #define YES 1 #define NO 0 #define MAYBE 2 #define I_DONT_KNOW 3 #define CAN_YOU_REPEAT_THE_QUESTION 4

  • Jon (unregistered) in reply to Peter Antoine
    Peter Antoine:
    Ed Heil:
    Dude should be programming Haskell!

    http://www.haskell.org/onlinelibrary/maybe.html

    Lightweights!

    VHDL std_logic, 9 different values for a bit. Two types of maybe, '-' = dont_care and 'X' = unknown.

    Doable in Haskell in one line. Here're some examples:

    data Drool = False | Maybe | True data Fool = False | ProbablyNot | Maybe | Probably | True data Tool = False | ProbablyNot | Possibly | Maybe | Probably | True | NotSpecified | Unknown | FileNotFound | WhoCares

  • (cs) in reply to Winter
    Winter:
    3 things I've noticed and stop me from wanting to register to post here:

    "FIRST POST!!11!" occurring for three quarters of the first page of any public discussion

    "The REAL WTF is ____" followed by some extremely dodgy code (usually)

    and then the template posts. (What no FILE_NOT_FOUND?!, Man that sounds like job for PAULA BEAN! etc etc)

    captcha is stinky. Damn right!

    You just exemplified the fourth DWTF annoyance while complaining about the first three...Nobody cares what anyone's captcha is! Yes, they are sometimes funny when compared to the article, but that's because someone typed in the list of already funny words to use for the captcha, and--surprise, surprise--they have to do with the theme of the site! Get over it!

    </rant>
  • (cs) in reply to akatherder
    akatherder:
    I like the fact that someone else could define FALSE as 1 or 50 and his code won't even fix that.

    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.

  • Orion Adrian (unregistered) in reply to KattMan
    KattMan:
    Orion Adrian:
    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.

    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.

    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".

  • BitBabe (unregistered) in reply to mkb

    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...

  • (cs) in reply to mkb
    mkb:
    kro:
    #define's are just plain unsafe use enums, enums, enums, enums

    #defines, enums, typedefs, and consts all have their pros and cons: 1.) You can only take the address of a const 2.) enums don't have a set value. If you are using them this way (eg enum { FOO = 2, BAR, BAZ}) or casting enums to ints, STOP. 3.) consts and enums cannot be used for macros. 4.) defines don't have a type, which is more risky than const int, const short, const unsigned int64_t 5.) #define where a typedef should be used is just stupid. I've never seen this, though.

    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?

  • woohoo (unregistered) in reply to skztr
    skztr:
    It's forwards-compatible with quantum computers. No WTF here.

    cute ;o)

    oh, and the captcha is tesla - also fitting well, somehow...

  • Cheong (unregistered)

    FALSE != !TRUE

    The logic is buggy...

    Capcha: craaazy. I can't agree more...

  • Orion Adrian (unregistered) in reply to BitBabe
    BitBabe:
    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...

    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.

  • Orion Adrian (unregistered) in reply to Orion Adrian

    Correction: They're far to integral to existing code to be deprecated.

  • Peter (unregistered)

    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.

  • (cs) in reply to Jeremy Bettis

    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.

  • (cs)

    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)

  • NotARobot (unregistered) in reply to steven22
    steven22:
    If he had called it UNKNOWN instead of MAYBE, would you guys be okay with it?
    MAYBE
  • (cs) in reply to jokeyxero

    WRONG!

    !0 == 1 !1 == 0 !2 == 0 !3 == 0

    For an int, PROBABLY;

    ~0 == -1 ~1 == -2 ~2 == -3

    jokeyxero:
    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.

  • (cs)

    #define NOT_TONIGHT_I_HAVE_A_HEADACHE -1

  • zbigg (unregistered) in reply to JamesKilton

    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.

  • Omg (unregistered)

    maybe is valid, little googleup

    http://ai0.eu/start/cms.php?art=xnumbers

  • valerion (unregistered)

    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.

  • f@ (unregistered) in reply to Zylon
    Zylon:
    You forgot:

    People who obsessively post their captcha for no discernable reason.

    My captcha, ironically enough, is muhahaha.

  • (cs) in reply to webdev101
    webdev101:
    There can be many valid reasons for MAYBE. E.g. Is there life in galaxy outside milkyway? If you say Yes: How can you tell? Did you see it? If you say NO: How can you tell? Did you visit each and every planet in each and every galaxy and verified? If you say NULL (No status): Not true the fact is the value is going to be TRUE or FALSE even if you do not know.

    You might like to look at Intuitionism

  • (cs) in reply to snoofle
    snoofle:
    As I recall, this was late 70's/early 80's-ish, and we were working with some crappy VAX/VMS system on a military contract. For some reason, without something that it recognized after the "#", the pre-processor ignored the intervening spaces, and took the directive as "#<whatever came after the original 'define'>", didn't recognize it, and puked.

    Per your, and other examples, the "define" in "#define" seems to be effectively ignored (implied?) in current compilers.

    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.

  • (cs) in reply to zbigg

    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.

  • (cs) in reply to valerion

    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.

  • (cs) in reply to KattMan

    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.

  • Orion Adrian (unregistered) in reply to KenW
    KenW:
    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.

    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".

  • Milen (unregistered)

    The real wtf is the presence of NULL in the most used DBMSs.

  • Eric (unregistered)

    Why not use ALWAYS, NEVER, and MAYBE?

    #define ALWAYS 1 #define NEVER 0 #define MAYBE 2

  • real_aardvark (unregistered) in reply to Orion Adrian
    Orion Adrian:
    anonymous guy:
    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:

    result = MAYBE;
    // later somebody does this:
    if (result) {
      ; // true
      }
    else {
      ; // false
      }
    

    You want a 'maybe' value? Fine, but for God's sake come up with something other than true and false for the other values.

    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.

    No, I have to disagree.

    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.

  • Guything McThingGuy (unregistered) in reply to merreborn's nemesis
    merreborn's nemesis:
    Seriously, using #define to redefine true and false is just stupid. The programmer should just have to return true, false, or (as seems to be needed here) an enum value.

    enum { Intersects, Tangent, Disjoint };

    CAPTCHA: tesla...as in shockingly bad code

    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.

  • Guything McThingGuy (unregistered) in reply to Orion Adrian
    Orion Adrian:
    KenW:
    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.

    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".

    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.

  • Anon (unregistered)

    #define OUTLOOK_NOT_SO_GOOD 6

  • (cs) in reply to jokeyxero
    jokeyxero:
    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.

    Maybe. (Captcha'ed!)

    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/>.

  • Orion Adrian (unregistered) in reply to Guything McThingGuy
    Guything McThingGuy:
    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.

    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.

Leave a comment on “Rarely Just TRUE or FALSE”

Log In or post as a guest

Replying to comment #:

« Return to Article