Why would drawPoint(x,y) give "Invalid Value"?

drawPoint(x,y) in the code below is infrequently giving error "Error: Invalid Value
Details: 'Failed invoking <symbol>'".
Any thoughts as to why?
This isn't happening very often - in fact, only once so far, on a real device.
The only thought I've had so far is perhaps x or y was NaN or Inf somehow.  I supposed A or B could possibly by NaN or Inf (shouldn't be, but could) and if so, that would descend to x & y.
Any thoughts welcome!
CODE -------------------------------------------


//type = :low or :high; swidth & sheight are the screen width & height of myDc
// xc, yc are the center points of myDc
drawFuzzyEllipse (myDc, swidth, sheight, xc, yc, A, B, type) {


      if (A> swidth && B > sheight) { return; }

      var step =  A/2.0;  

      var start = 0;

      if (type == :low) {
step = (Math.rand()%150)/100.0 + 0.5;
start = (Math.rand()%314).toFloat();
}

      if (step<25 && A > 3  && type == :high) { step = 25; }

      for (var theta = start; theta < 2 * Math.PI;theta += Math.PI * 2.0 / step) {

         var adder = 0;
         if (type == :low) {adder = Math.rand()%1000/1000.0 * Math.PI * 2;

         var ran = Math.rand()%1000;
         var addme = 0.95f + ran/10000000.0f;

         var x = xc + (A*addme) * Math.cos(theta);
         var y = yc + (B*addme) * Math.sin(theta);

       

CODE -------------------------------------------
  • The code you posted doesn't get to drawPoint(x,y).

  • Sorry, I could have sworn the line was in when I posted, and then yesterday after seeing your response, I went & added it to the post again, and for some reason it's still not showing up. 

    Anyway, the missing lines are is simply checking the point lies within the graphics area and plotting it.

    Just add these lines to what is above

    
    
       if (x<0|| y<0 || x>swidth || y>sheight ) {continue;}
       myDc.drawPoint(x,y);

    } //end function
  • One feature of duck typing I've noticed is that you have to be careful about what touches. Any math where one of the values is null returns null unless you do ternary check, same for a bunch of integers and a float returns float, etc. Invalid value is what happens when you divide by zero, which is I always prefer to multiply when I can rearrange the terms or use a reciprocal of a constant. Most errors are not "catchable", so you need to do your own sanity checking.

  • One feature of duck typing I've noticed is that you have to be careful about what touches

    The following points aren't limited to duck typed languages.

    Any math where one of the values is null returns null unless you do ternary check

    This isn't true at all. Consider the following Monkey C code (compile with type checking disabled):

    var x = 0.5;
    var y = null;
    System.println(x*y);

    The 3rd line will throw an exception at runtime:

    Error: Unhandled Exception
    Exception: UnexpectedTypeException: Expected Number/Float/Long/Double, given null/Float

    Java will throw a null pointer exception in a similar situation.

    same for a bunch of integers and a float returns float,

    C and Java (for example) also promote integers to floats when arithmetic is performed with an integer and a float.

    Invalid value is what happens when you divide by zero

    Most implementations of C will crash if you divide by zero. Java will throw an exception if you divide an integer by 0, but it will return a special value if you divide a float by 0.

    Out of those 3 examples, the only way Monkey C (a duck-typed language) significantly differs from Java (a strongly-typed language) is that division by zero is an uncatchable fatal error in Monkey C ("Invalid Value" as you said) but a catchable exception or special value in Java.

  • I'm pretty sure this is a Monkey C forum. I'm not sure why references to other languages keep coming up or even matter.

    If it were possible I would use strict typing, but I don't know how to set the type of a global variable to a class that I'm going to instantiate later. I also don't know how I would get around a function parameter defined as Array<Numeric>? then later in the function after I determine that the parameter is not null I try to get the size and the compiler says there's no size method for null. I would have to do the null checking first before I call the function, which means a lot of null checks when one in the function should suffice. The idea that a variable could be null breaks about everything in type checking.

  • I'm pretty sure this is a Monkey C forum. I'm not sure why references to other languages keep coming up or even matter.

    Because you insinuated that the things you brought up are issues with duck typed languages ["One feature of duck typing I've noticed is that you have to be careful about what touches..."], which implies that they are not issues with non-duck typed languages. Otherwise there would be no reason to bring up duck typing in the first place.

    To recap:

    - "Any math where one of the values is null returns null unless you do ternary check"

    Not true. Arithmetic where one or more of the values is null results in an exception. Same with certain comparisons.

    - "same for a bunch of integers and a float returns float,"

    True, but other popular [non duck typed] languages are the same, so what's your point?

    - "Invalid value is what happens when you divide by zero"

    Sure and the invalid value error can be caused by other things, as well.

    More to the point, none of these things has anything at all to do with duck typing. That was my point - I should've made that clear.

    I'm not sure why references to other languages keep coming up or even matter.

    If you implicitly or explicitly say that something is unexpected, tricky or even buggy in Monkey C, as in this discussion or other discussions, there's always the implicit question of "compared to *what*?" Monkey C doesn't exist in a vacuum.

    By mentioning duck typing in the first place, you are placing the discussion in a larger context [by implicitly comparing it to other languages, duck typed or not].

    If it were possible I would use strict typing, but I don't know how to set the type of a global variable to a class that I'm going to instantiate later.

    class TestClass {}
    var x as TestClass or Null = null;

    inb4 "I want x to be TestClass but not null." Unfortunately x has to have *some* value before you set it to an instance of TestClass, and that value will be null by default [I made it explicit here, but you could also omit "= null"].

    I also don't know how I would get around a function parameter defined as Array<Numeric>? then later in the function after I determine that the parameter is not null I try to get the size and the compiler says there's no size method for null. I would have to do the null checking first before I call the function, which means a lot of null checks when one in the function should suffice. The idea that a variable could be null breaks about everything in type checking.

    This code compiles for me without error, with typechecking at the max level [3].

    The idea that a variable could be null breaks about everything in type checking.

    Again, simply not true at all. If there is an issue with handling null checks in Monkey Types, that would be a bug, not an inherent flaw in the idea of type checking.

  • Given this code snippet, it's pretty crazy that you're getting an Invalid Value at drawPoint[].

    If x or y were null, you should get an error or exception at the if-statement, so that's obviously ruled out [without even looking at the rest of the code].

    Normal negative values and normal values greater than the screen width/height are also ruled out.

    The only thing I can think of some kind of special value like NaN [as you said], which might possibly fail all of those checks.

    If you are looking for a way to test whether a value is not Nan or -NaN, you can use this workaround:

    [https://forums.garmin.com/developer/connect-iq/f/discussion/338071/testing-for-nan/1637853#1637853]

    It's not clear to me what's actually happening in your case, though.

  • inb4 "I want x to be TestClass but not null." Unfortunately x has to have *some* value before you set it to an instance of TestClass, and that value will be null by default [I made it explicit here, but you could also omit "= null"].

    This is exactly what makes strict impossible:

    public var newClass as myClass; fails if you don't instantiate it in the initialize function because it can't be null.

    public var newClass as myClass?; fails because any use of it as a path is not allowed because it could be null.

    And apparently even though the documentation says that any test of a value will be false if it is null, it only works if you don't check it strictly:

    	private function fillOrb(drawDc as Dc, orbColor as ColorValue, flatOrb as oneDim?) as Void {
    		if (flatOrb) {
    			var z = flatOrb.size();
    

    But change it to this:

    	private function fillOrb(drawDc as Dc, orbColor as ColorValue, flatOrb as oneDim?) as Void {
    		if (flatOrb != null) {
    			var z = flatOrb.size();
    

    and it is happier. I'm not convinced that strict type checking has arrived yet, so we stuck with ambiguity which brings it's own issues.

  • Try using println to see what x and y actually are. The graphics methods like fillPolygon, drawPoint, drawLine and some others don't care if the point is off the screen, they will just silently not draw that part so there isn't really any benefit to checking for that. Some care that it has to be an integer, some will take any numeric, and fillPolygon has it's own special type.

  • This is exactly what makes strict impossible:

    public var newClass as myClass; fails if you don't instantiate it in the initialize function because it can't be null.

    public var newClass as myClass?; fails because any use of it as a path is not allowed because it could be null.

    Right, I already anticipated this response above.

    You are asking for the impossible [or impractical]: to leave a variable uninitialized, but to not have a default value [null].

    public var newClass as myClass; // you want this to be uninitialized

    What do you expect to happen if newClass is accessed before it's initialized? Recall that your original statement referred to global variables [and you have now switched to using an example with a class member].

    Sure, if it actually is a class member, the compiler could try to statically forbid access to the variable until it's initialized. That could be pretty tricky if the initialization is triggered by a timer, random event, or user input. I'm gonna assume this isn't possible in general.

    What's the alternative? The variable has to have *some* value when you access it.

    I know you don't like talking about other languages, but:

    - C handles uninitialized variables by simply leaving their value undetermined [except for globals, which are set to 0]

    - Other languages either forbid uninitialized variables and/or provide a default value for uninitialized variables

    If you want Monkey C to support uninitialized variables without a default value of null, then you have to answer the question of what should happen if that variable is accessed before it's initialized?

    What you are actually asking for is the ability to leave a variable uninitialized with no default value [not even null]. which is not possible in Monkey C. This is not strictly an issue with strict type checking. Strict type checking only exposes the fact that there is a default value in the first place. To be fair, it probably would not be possible to implement strict type checking if you allowed the initial type of a variable to be "indeterminate". So I think you have it backwards. It's not that "strict is impossible" (for your use case), it's that your use case (uninitialized variables [without default values]) is not a good idea

    public var newClass as myClass; fails if you don't instantiate it in the initialize function because it can't be null.

    This is not a bug or conceptual problem, because it's working exactly as expected.

    public var newClass as myClass?; fails because any use of it as a path is not allowed because it could be null.

    I'm not sure exactly what you mean by "as a path" here. I assume you mean that every usage of newClass will have to be wrapped with null checks, and that will make for ugly, hard-to-maintain code?

    Simple solution: