Home AMX User Forum AMXForums Archive Threads Tips and Tricks

== TRUE trap

Occasionally you may have a line like if(sTP_Session[GET_LAST(arrTP)].r4 == false){ and you decide to reverse your logic and say if(sTP_Session[GET_LAST(arrTP)].r4 == true){.

WARNING!

In NetLinx, comparing something to TRUE does not check for inequality to 0 (FALSE). Comparing something to TRUE is simply a comparison to the number 1. TRUE is a NetLinx constant for 1. If you compare to TRUE you had better be sure that the data is a 1 or 0, if some other number sneaks in there you will get an unexpected result since values like 2, 3, 99 evaluate to TRUE in other languages.

In the example above better would have been:
if(sTP_Session[GET_LAST(arrTP)].r4 != false){
or just
if(sTP_Session[GET_LAST(arrTP)].r4){

Comments

  • a_riot42a_riot42 Posts: 1,624
    mpullin wrote: »
    In NetLinx, comparing something to TRUE does not check for inequality to 0 (FALSE). Comparing something to TRUE is simply a comparison to the number 1. TRUE is a NetLinx constant for 1.

    That isn't a 'trap'.

    From the help files:

    True
    This keyword is a CHAR constant contains the value 1.

    While NetLinx does not support a BOOLEAN data type, an non-zero value is consider true for conditional expressions.

    What is stupid is writing code like this:
    if (something == true)
    {
      do this
    }
    else if (something == false)
    {
      do that
    }
    

    when it should be written:
    if (something)
    {
      do this
    }
    else 
    {
      do that
    }
    
    


    I hate seeing this as well:
    if (something == false)
    {
      return false
    }
    else if (something == true)
    {
      return true
    }
    

    when it should be written:
    return something
    
  • mpullinmpullin Posts: 949
    I disagree. It is a trap in the sense that the behavior is nonstandard, and, while documented, not many people would think to look this up.

    Your first example is indeed silly, but your second one... keep in mind "return something" will return whatever something is, but the block will return either a 0 or 1 (false or true). It depends on how the value returned is being treated whether or not this is appropriate. Maybe RETURN !(something == FALSE) would be more accurate (if less human-readable).
  • a_riot42a_riot42 Posts: 1,624
    mpullin wrote: »
    I disagree. It is a trap in the sense that the behavior is nonstandard, and, while documented, not many people would think to look this up.

    Perhaps. I never use true and false so I haven't encountered the problem. I don't think there is a standard per-se. In C (pre-C99) for instance, true and false are not defined.
    mpullin wrote: »
    Your first example is indeed silly, but your second one... keep in mind "return something" will return whatever something is, but the block will return either a 0 or 1 (false or true). It depends on how the value returned is being treated whether or not this is appropriate. Maybe RETURN !(something == FALSE) would be more accurate (if less human-readable).

    It's the same thing, so RETURN !(something == FALSE) is just redundant and difficult to read. Can you write some code where 'return something' doesn't work but 'RETURN !(something == FALSE)' does?
    Paul
  • a_riot42a_riot42 Posts: 1,624
    Hedberg wrote: »
    You should write the code to do what you want it to do.

    this:[code]
    if (n = 0)
    {

    What is it that you want this code to do?
    Paul
  • HedbergHedberg Posts: 671
    You should write the code to do what you want it to do.

    this:
    if (n = 1)
    {
      do this
    }
    else if (n = 0)
    {
      do that
    }
    

    Is not the same as this:
    if (n)
    {
      do this
    }
    else
    {
      do that
    }
    

    That they are different is pretty obvious and if you want the behavior in the first, it's not stupid to prefer it to the second.

    Likewise the second code example.
    if(n = 0)
    {
      return 0
    }
     else if (n=1)
    {
      return 1
    }
    

    is not the same as
    return n
    


    Seems to me that if you avoid the constants TRUE and FALSE that you avoid the trap.
  • HedbergHedberg Posts: 671
    a_riot42 wrote: »
    Perhaps. I never use true and false so I haven't encountered the problem. I don't think there is a standard per-se. In C (pre-C99) for instance, true and false are not defined.



    It's the same thing, so RETURN !(something == FALSE) is just redundant and difficult to read. Can you write some code where 'return something' doesn't work but 'RETURN !(something == FALSE)' does?
    Paul


    I think so.

    compare
    something = 99
    
    return something
    
    

    to
    something = 99
    
    return !(something =0)
    
    

    If I understand correctly, the first will return 99 and the second will return 1. Which one "works" depends on the behavior desired. It's possible that both "work", but not necessary.
  • a_riot42a_riot42 Posts: 1,624
    Hedberg wrote: »
    You should write the code to do what you want it to do.

    this:
    if (n = 1)
    {
      do this
    }
    else if (n = 0)
    {
      do that
    }
    

    Is not the same as this:
    if (n)
    {
      do this
    }
    else
    {
      do that
    }
    

    That they are different is pretty obvious and if you want the behavior in the first, it's not stupid to prefer it to the second.

    They are the same if n is a boolean which is what we were talking about (true, false). If n is some integer that can have many values that you need to test against, that is a different thing altogether.
    Hedberg wrote: »
    if(n = 0)
    {
      return 0
    }
     else if (n=1)
    {
      return 1
    }
    

    That is dangerous code in my opinion since it is ambiguous. It looks like you are just testing for a boolean but you really testing an integer value.
  • a_riot42a_riot42 Posts: 1,624
    Hedberg wrote: »
    I think so.

    compare
    something = 99
    return something
    

    to
    something = 99
    return !(something =0)
    

    If I understand correctly, the first will return 99 and the second will return 1. Which one "works" depends on the behavior desired. It's possible that both "work", but not necessary.

    I understand your reasoning but it makes no sense to me. If you are returning a boolean that is true, then returning either 1 or 99 will work. If you are returning an integer, then you would return 'something' to get the value of it. I can't foresee any situation when I would want to return !(something == 0).

    You can return 'something' as a boolean and also get its value which I do often enough, but its still a boolean. Writing ambiguous code that confuses a boolean with an integer will create some hard to find bugs as the OP has discovered.
    Paul
  • HedbergHedberg Posts: 671
    a_riot42 wrote: »
    They are the same if n is a boolean which is what we were talking about (true, false). If n is some integer that can have many values that you need to test against, that is a different thing altogether.

    But there is no boolean in Netlinx and that's the source of the "trap" which this thread is about. TRUE = 1 and FALSE = 0/ If you think that an integer value has to be either TRUE or FALSE, you're wrong.

    That is dangerous code in my opinion since it is ambiguous. It looks like you are just testing for a boolean but you really testing an integer value.

    I see no reason why testing an integer value is dangerous code. What's dangerous is thinking that an integer value must be either 0 or 1.
  • a_riot42a_riot42 Posts: 1,624
    Hedberg wrote: »
    But there is no boolean in Netlinx and that's the source of the "trap" which this thread is about. TRUE = 1 and FALSE = 0/ If you think that an integer value has to be either TRUE or FALSE, you're wrong.

    I don't follow. Can an integer in Netlinx be neither true nor false? I haven't tested it, but I can't think of any integer that wouldn't print something using this code:
    if (aNumber)
    {
      print("'Its not a zero'")
    }
    else if (! aNumber)
    {
      print("'Its a zero'")
    }
    

    In Netlinx, at least according to the help file, zero is considered a false conditional expression, and a non-zero value is considered true for conditional expressions.
    Hedberg wrote: »
    If you think that an integer value has to be either TRUE or FALSE, you're wrong.

    What integer are you referring to that isn't either true or false? I am pretty sure that 0 and !0 pretty much cover all the integers unless there is some bug in the compiler that can be fooled with +0 or some other trick.
    Hedberg wrote: »
    I see no reason why testing an integer value is dangerous code. What's dangerous is thinking that an integer value must be either 0 or 1.


    Testing an integer isn't dangerous code, but ambiguous code is always potentially dangerous and usually easily avoided. I don't think anyone is claiming that an integer must be either 0 or1, that would be rather silly.
    Paul
  • HedbergHedberg Posts: 671
    I suppose I should have known better than to get involved in this. Oh, well.
    a_riot42 wrote: »

    What integer are you referring to that isn't either true or false? I am pretty sure that 0 and !0 pretty much cover all the integers unless there is some bug in the compiler that can be fooled with +0 or some other trick.

    I think we went down the !0 trail a couple months back.

    Consider the following:
    nn = 99
    ii = (nn = !0)
    

    what value do you suppose ii turns out to be? Clearly nn is not zero, but it's not !0 either.

    Testing an integer isn't dangerous code, but ambiguous code is always potentially dangerous and usually easily avoided. I don't think anyone is claiming that an integer must be either 0 or1, that would be rather silly.
    Paul

    Well, if you claim that an integer must be either 0 or !0, you are claiming that it must be either 0 or 1. If you are claiming that it must be equal to either true or false, you are also claiming it must be 0 or 1 as true is a constant equal to 1 and false is a constant equal to 0.

    I've never considered something like
    if(aNumber)
    

    to be a test of whether or not aNumber is either true or false. I've always considered it to be short hand for
    if(anumber <> 0)
    

    which is different from
    if(anumber = true)
    

    which is the same as
    if(anumber = 1)
    

    I think this horse is dead and I'm getting off.
  • travtrav Posts: 188
    Checks the horse for a pulse...

    I like cheese.....
  • a_riot42a_riot42 Posts: 1,624
    Hedberg wrote: »

    Consider the following:
    nn = 99
    ii = (nn = !0)
    

    what value do you suppose ii turns out to be? Clearly nn is not zero, but it's not !0 either.

    I wouldn't write code that way. According to the docs ii should be true.
    Hedberg wrote: »
    Well, if you claim that an integer must be either 0 or !0, you are claiming that it must be either 0 or 1. If you are claiming that it must be equal to either true or false, you are also claiming it must be 0 or 1 as true is a constant equal to 1 and false is a constant equal to 0.

    I don't get what your driving at here. I am making no claim beyond what the docs say, and according to the docs, any non zero number is considered true. Are you saying its a typo?
  • I remember this routine...
    Who's on first,
    What's on second,
    I Don't Know is on third...
    :)
    a_riot42 wrote: »
    I am making no claim beyond what the docs say, and according to the docs, any non zero number is considered true. Are you saying its a typo?

    I think the trap mentioned by mpullin initially is that the keyword/constant "TRUE" = 1, but any non-zero value will evaluate as true in a comparator, so....
    If nValue = 99 and you run the following statements, Example 1 will evaluate as false, Example 2 will evaluate as true:

    Example 1:
    IF(nValue == TRUE)
    {
      //do something (*this will evaluate as false since nValue = 99 and not 1)
    }
    


    Example 2:
    IF(nValue)
    {
      //Do something (*this will evaluate as true since nValue is a non-zero number)
    }
    

    The trap is, don't forget that TRUE has a literal value of 1, not any non-zero number.


    --John
  • a_riot42a_riot42 Posts: 1,624
    The trap is, don't forget that TRUE has a literal value of 1, not any non-zero number.

    I guess I don't see that as a trap. True has to be defined as some value since there are no macros in Netlinx, so 1 makes as much sense as anything. When you write
    if (something == true)
    
    you are essentially asking if (something == 1) since that is how true is defined. My point was that if you didn't write code in that redundant way these problems don't occur. The OP was maintaining that you had to write
    if(sTP_Session[GET_LAST(arrTP)].r4)
    
    to get around a trap, when in fact that is actually the correct syntax and that
    if(sTP_Session[GET_LAST(arrTP)].r4 == true)
    
    is redundant and bug-prone.
    Paul
  • True or False

    Man - Is this the right room for an argument?
    Mr Vibrating - I've told you once.
    Man - No you haven't.
    Mr Vibrating - Yes I have.
    Man - When?
    Mr Vibrating - Just now!
    Man - No you didn't.
    Mr Vibrating - Yes I did!
    Man - Didn't.
    Mr Vibrating - Did.
    Man - Didn't.
    Mr Vibrating - I'm telling you I did!
    Man - You did not!
    Mr Vibrating - I'm sorry, is this a five minute argument, or the full half hour?
    Man Oh ... Just a five-minute one.

    http://www.youtube.com/watch?v=teMlv3ripSM
  • DHawthorneDHawthorne Posts: 4,584
    I appreciate the heads-up ... I would have assumed it evaluated to anything non-zero as well. I think the only reason it never bit me was that before they added TRUE and FALSE as keywords, I defined them as constants myself and knew I had that limitation. So I was inclined to write my tests with that in mind. As a result, I'm much more likely to test the variable itself, IF(nValue).
  • travtrav Posts: 188
    He's not the messiah, he's just a very naughty boy...
    B_Clements wrote: »
    Man - Is this the right room for an argument?
    Mr Vibrating - I've told you once.
    Man - No you haven't.
    Mr Vibrating - Yes I have.
    Man - When?
    Mr Vibrating - Just now!
    Man - No you didn't.
    Mr Vibrating - Yes I did!
    Man - Didn't.
    http://www.youtube.com/watch?v=teMlv3ripSM

    Look, strange women lying in ponds distributing swords is no basis for a system of government.
  • PhreaKPhreaK Posts: 966
    Perhaps we need to start a new thread / section on the forum for monty python appreication. Either that or I may have to start posting "NOBODY EXPECTS THE SPANISH INQUISITION" in random threads.
  • How about simplifying further?

    switch(sTP_Session[GET_LAST(arrTP)].r4)
    {
    case 0://do this
    case 1://do that
    }
Sign In or Register to comment.