Announcement

Collapse
No announcement yet.

Monkey C: 0.0 treated as true value

Collapse
X
  • Time
  • Show
Clear All
new posts

  • Monkey C: 0.0 treated as true value

    Environment: CIQ 3.0.5
    (Tested in both CIQ1 and CIQ2+ watches in simulator. Known to happen on real CIQ2+ watch)

    Unlike C, Javascript and probably every other programming language in the world, 0.0 is treated as a true value.

    Also, 0.0 is treated as true, but "0 == 0.0" is true (as it should be), which is logically incoherent. If x == y, one can't be true while the other is false.

    I can't even post the code to the forums (as per usual), so it's all on pastebin:
    https://pastebin.com/KKZGUu3m

    Output:
    Code:
    0 == 0.0: PASSED....
    0.0 is truthy: FAILED....
    0 is falsey: PASSED....

    All I can say is that Monkey C and Connect IQ have really laudable design goals and great potential, but I think stuff like this is a huge disincentive to devs. There's no substitute for testing, but we shouldn't have to test obvious language constructs to see if they work the same way as expected.

    Furthermore, we still can't post code in the forums.... A huge disincentive to participate in the community. The amount of effort I had to expend just to post this bug report is ridiculous.

    I get that Garmin has higher priorities, like promoting the Spider-Man watchface (hey, I liked Spider-Man: Homecoming) and not updating the Uber/Lyft apps.
    Last edited by Marianne.ConnectIQ; 12-06-2018, 02:28 PM.

  • #2
    This means to implement a simple division function "x / y" it's not enough to test "if [y]", you have to test that y is not null and not zero.

    [Where y could be an integer, float or null, which is plausible if you are doing math on ActivityInfo.]

    On a side note, it looks the language design bug I posted last year where logical OR is treated like bitwise OR is still not fixed. Guessing it never will. (I understand that you don't want to break existing code in the field.)
    https://pastebin.com/M9q9Vcda

    Output:
    Code:
    x = null
    y = 0
    
    Trying if [x]...
      if [x] works
    Trying if [y]...
      if [y] works
    Trying if [x && y]...
      if [x && y] works
    Trying if [x || y]...
    Unhandled Exception
    Last edited by FlowState; 12-05-2018, 07:30 PM.

    Comment


    • #3
      I can provide some information here, but I can only comment on the way things are, and not why they are that way.

      Regarding your new issue. As best I can tell, floats just simply are not allowed to be interpreted as true/false values. You should definitely avoid attempting to do so. Based on what I can see, I would really expect some sort of exception or failure in the case where you attempt to evaluate if( 0.0 ). As far as I can tell, it is not considered to be true or false, so behavior here is probably a bit undefined. Some sort of ticket is probably in order since the system appears to just be ignoring this type of evaluation instead of producing an error.

      Your prior issue is similar, but I think there is more going on than you tested for. The handling of AND and OR is a bit unique in Monkey C. Logical OR/AND will be applied in any case where a boolean value is involved, and bitwise or will be used in cases involving only Number and/or Long. Again any other types are not valid for this operator. this includes null. It actually isn't allowed in the && case either, and I suspect your test is only passing due to short circuit evaluation. If you tried "var foo = x && y; if(foo);", I think you would see the same exception.


      The key to avoiding these types of issues appears to be keeping all your null checking separate from other logic.

      Comment


      • #4
        Brian.ConnectIQ Thanks for the quick and patient response. Sorry for the tone of my original post.

        I guess my problem is that in the limited memory space of CIQ1 and even CIQ2 datafields, sometimes a handful of null checks will make the difference between a datafield that runs and a datafield that crashes. I've actually rewritten some logic to initialize with negative numbers instead of nulls to reduce the number of null checks and save memory. (To be fair, in that case it wouldn't have mattered if null could be used with logical AND/OR).

        I think it's possible that the thing with logical/bitwise AND and OR may have been explained last year (when I probably posted a much more extensive test case), but I think at the time it was a surprise to even some regulars (e.g. Travis). But it is the way it is. I guess it probably has something to do with efficiency (size of VM), or perhaps it's a safety net for new coders. I guess I'll never know and I guess it doesn't matter.

        I guess I bring these issues on to myself by:
        - Not doing adequate unit testing
        - Trying to pack too many features into tiny data fields (less is more)

        Originally posted by Brian.ConnectIQ View Post
        The key to avoiding these types of issues appears to be keeping all your null checking separate from other logic.
        Yeah, I guess I sort of learned that the hard way, but the thing with 0.0 was sort of a new wrinkle.

        As I probably commented before, I guess I just sort of wish this kind of thing was documented somewhere. Maybe in an appendix, so it doesn't scare off noobs, but at least it would be there for people who could appreciate that kind of information.

        Guess I will have to stop assuming that Monkey C is like C or Javascript, when there is no reason to do so.

        Thanks again!
        Last edited by FlowState; 12-06-2018, 02:09 PM.

        Comment


        • #5
          You definitely found a bug worth reporting here, so it is a good find. For your own amusement, try this out:
          Code:
          var x = 0.0f;
          do {
              Sys.println( "is 0.0f truthy?" );
          } while( x );
          
          Sys.println( "nope, I guess 0.0f is false" );
          In some cases Monkey C is trying to be everything. In some cases it makes things easy because it just works the way you expected it to based on that other thing you know, but in other cases, it works like that other thing you don't know.

          This case can be compared to Java, which does not allow you to test things that are not boolean. However, Monkey C allows integers, which isn't fully consistent with Java... and it is not producing an error for floats, and a number of other things that it should be producing an error for.



          Last edited by Brian.ConnectIQ; 12-06-2018, 03:20 PM.

          Comment


          • #6
            Brian.ConnectIQ thanks for the explanation. I've coded in a lot of languages, but I have to admit I probably think in terms of C/C++/C# and Javascript most often, although I like a lot of things about other languages.

            Ironically, I can (almost) relate to the difficulty of designing a language, since I wrote a data field that implements a simplified programming language on top of Monkey C >_>. That's obviously why I so found so many quirks in Monkey C (at least they seemed like quirks to me.)

            There's so many things to think about, like how to handle comparisons/arithmetic on null.... And sometimes it seems like there's no one good answer to every decision you have to make. I decided to say that "5 - null = null" but maybe I should've said that "5 - null = 5", like Javascript. Oh well, too late now.

            So I don't really envy the people who have to make these decisions and are stuck with them forever. I can sort of relate to that, too. (The difference is I have a tiny userbase....)
            Last edited by FlowState; 12-06-2018, 05:42 PM.

            Comment

            Working...
            X