Symbol lookup best practices?

Most of the time the simulator starts without a problem, but sometimes I get this when I start:

Error: Invalid Value

Details: Failed invoking <symbol>
Stack:
- onUpdate() at C:\Users\Andy\Desktop\Garmin-GIT\Annulus\source\AnnulusView.mc:735 0x10002514

Encountered app crash.
Kill app for run the app
Failed to run the app: Timeout

What's worse it's happening on the watch, after a day or so onUpdate will stop updating when awake, but it does keep updating every minute awake or not. I get something similar in a CIQ_LOG file. I reselect the watch face and it's fine, at least for a while.

Can I fix this by helping the lookup process? I don't have any globals beyond Toybox, so do I use self to say it's a variable or function in the same class? Does a symbol need to be looked up everytime that piece of code is run, or does it remember after the first time? It seems like if it was remembering where it was it wouldn't break the next day.

  • If that's the case I'm glad I didn't make my sunrise, sunset, high tide, low tide, moonrise and phase depend on the internet always being available.

  • I'm not disagreeing with you or Gavriel, I already have that same thing in code that's staying. But this is kinda like the voltmeter problem. The more code I put in my measurement the more it affects the measurement, so lighter and faster is better for now. When I'm a few milliseconds from 30 they all matter.

  • With sunrise/sunset, the thing to watch are the poles, where there may not be a sunrise or sunset.  I had a user contact me about that very case

  • result=(myDivisor==0) ? myValue : myValue/myDivisor;

    In *general* this is a flawed way to avoid divide by zero issues.

    If I opened a calculator app on any platform, typed in "3 / 0" and it returned "3", I would say that app was broken and I'd delete it right away. Same goes for Excel or Google Sheets. If google returned "3" when I type "3 / 0", I would immediately stop using it for math.

    This code "works" in the sense that it doesn't crash, but the value it returns when myDivisor is 0 would be wrong or misleading in almost every case. The only situations where this would be appropriate would be:

    - nobody cares about the actual value of result

    - we're actually pretty sure sure that myDivisor will never be 0, and if it is, we really don't care about result

    In general you want to specify a sensible default which depends on circumstances (where the divisor and dividend came from and what the quotient will be used for). It may even be something that is not a valid number (such as null), which will then be displayed to the user in a human-friendly way (such "--", a blank space or some text indicating that an error occurred.)

    In some cases you may actually want the system throw an error, if you're absolutely sure it doesn't make sense for the divisor to ever be zero.

    If the answer was really this simple, you'd think that computer science (and mathematics) would've already defined "x / 0" to equal "x".

  • The best approach is to figure out why it's zero in the first place,  The line I typed it cleaner code wise that using a tiny value  in place of zero.

  • The best approach is to figure out why it's zero in the first place

    Agreed, but I wasn't suggesting the best approach, I was talking about the code you actually posted.

    The line I typed it cleaner code wise that using a tiny value  in place of zero.

    Cleaner code-wise, but absolutely unsuitable for almost any real-world application.

    In the real world, you would do one of the following:

    1) figure out why the divisor is zero in the first place (as you said)

    2) if 0 is actually valid for the divisor:

    2a) use some sensible default numerical value which makes sense in context. It's not sensible to return x for x / 0.

    2b) display some non-numerical value to the end user, such as a blank space, "--" or an error

    Besides, pretty much everyone posting in this thread knows how to write something like:

    var z = (y == 0) ? defaultVal : x / y;

    (Someone else suggested something like this)

    If you're going to post obvious code, you may as well post something that could be plausibly used in the real world. I'd hate for someone who's learning to code (in general, not just monkey c) to read that code and think it's a good way to solve that problem in *general*.

  • In this particular case it's trying to calculate the ratio of awake time to uptime every time it's awake. Since it starts awake. It's starting from zero. It didn't used to start from zero because the rest of the code took long enough that it could get off of zero. I created this problem by making the rest of the code better, so I'm OK with that. The real problem is it's too soon to do the math, but then it would really need even more logic to say "don't check this for a while". The result itself is meaningless in this primordial state, so the fact that I hacked it in the non-canonical way so it wouldn't fault doesn't matter because the result won't be of much value until the next day anyway. At this moment uptime is 0.19 days, seconds awake is 650, and battery usage is 2.5% per day. But we all know that time is too short for those numbers to be reliable, so it needs to simmer a while longer. A week would be good, two would be better. That depends on whether or not I come up with some more optimizations to the rest of the code that makes me want to abort this test and try something smaller and/or faster. And the cycle continues.

  • If I get bored I might give that a try just to see what I get. I would think the azimuth would be the useful number.

  • I don't know why, but it just restarted again. From the log file on the watch, it looks like all is well, it's calculating the battery usage every hour, then whack:

    jday 2023-01-25 21:59:59  <- from onUpdate
    _batteryLevels [[8425.497922, 86.679688], [8425.667506, 86.265625], [8425.497928, 86.679688]]
    _batteryRate 2.441635
    starting AppBase  <- from appbase.initialize
    bYear 1964, age 59, _hrMax 161 <- from appview.initialize
    _jStart 2023-01-25 22:00:00  <- from onLayout, one second later

    I started from the Garmin analog watch. I thought I cleaned out all the cruft I didn't want. Is there something else it has I need to look for and get rid of?

  • Look at the world we live in: even when/where there's no sunrise there's internet ;)