DF optimization: should I check every time for info has :currentHeartRate in compute?

Currently my DF's cumpute() starts with:

var hr = (info != null && info has :currentHeartRate && info.currentHeartRate != null)
  ? info.currentHeartRate
  : "--";

Should I check info has :currentHeartRate in every call to compute() or can I cache it:

if (mHasCurrentHR == null && info != null) {
  mHasCurrentHR = info has :currentHeartRate;
}
var hr = mHasCurrentHR == true && info != null && info.currentHeartRate != null ? info.currentHeartRate : "--";

Or in other words: does info always have :currentHeartRate on a specific device, even when there won't be HR for a while or can it "surprise me" that sometimes it'll have a non-null info that doesn't even has a null info.currentHeartRate?

Or do I even need to bother with the has? Can I just write:
var hr = (info != null && info.currentHeartRate != null)
  ? info.currentHeartRate
  : "--";

Or even better: can I move this to initialize somehow?
function initialize() {
    var info = ActivityMonitor.getInfo();
    mHasCurrentHR = info has :currentHeartRate;
}
Can I be sure that the info I get this way indicates regarding has :currentHeartRate what will the info sent to compute(info) be like?

  • Regarding: "assumed that "has" had some way of checking a type that literally could not change without upgrading firmware" that might probably be the case for my original question that is basically about Activity.Info, but not in general, because let's say I have some barrel code that generates some data, then you in your code can't know (of course depending on the circumstances". Like I could have:

    class A {
       function foo() {}
    }

    class B extends A {
       function bar() {}
    }

    and I'm producing A-s. Now you could use item instanceof B which might probably be the right approch in this case, but if you happen to use item has :bar then it'll only be true for that item, I can still produce the next item that is "only" an A.
    But probably this is too theoretical anyway for real world usage.

  • Great point! I meant for CIQ API stuff, not has in general. But it was def a bad assumption and a hasty generalization.

  • If type checking is off, the type doesn't matter.  As type checking is only a pre-compile thing the actual compiler desn't care. "has" just is checking for the symbol (that's why a symbol is used with has)

  • If type checking is off, the type doesn't matter.  As type checking is only a pre-compile thing the actual compiler desn't care. "has" just is checking for the symbol (that's why a symbol is used with has)

    When I said "type" I wasn't referring to compile-time type checking as in Monkey C types, I was referring to runtime types as in Activity.Info and its members that are available at runtime.

    My point was I assumed that "X has Y" (where X is a "standard CIQ type" in the API) would always return the same value for a given device and firmware version, but it seems I was wrong about that, as  pointed out.

    Again, my point was about how I thought has would behave for standard CIQ types like Activity.Info, not its implementation, but I was wrong per usual.

  • I've seen it on all data from sensors but it only happens a few minutes after reboot.

    HAS sensorXXXhistory returns false

    I've made some modification in code after reading Jim notice about HAS and my icons was grey to time I quit and return to WF (HAS was moved to view.initilase so in  next run HAS return true).

  • I still feel we're just guessing. Garmin should include specific information about these kind of things in the docs (at least if they're intentional or even if not but known)

  • Never seen this and I use has a fair amount - in initialize.  There are a few odd cases of things with watch faces, where some things are only available in a background service, or only some things are available in the main app.

  • I still feel we're just guessing.

    That's the trouble with all things Garmin. There's no spec for anything.

    But note that generally, caching something is going to increase code size. I suppose if you're doing the has check in lots of places, caching the result *could* save code... but refactoring the code to only do the check in one place could probably save you more...

  • But I've seen it after I changed code following your advise (code is still changed, I believe it saving energy especially if HAS has to look in something that has a lot of 'members') 

    But first false doesn't make problem it is worse if in initialise I have true and in onUpdate checking Boolean instead of HAS (never have an error yet but waiting... :-)). In WF it's not problem because to make any change you have to exit from WF. But in DF? User starts activity, go to watch's settings and switch off all sensors and nobody knows if sensor history exist or not or iterator will be null.

    So was can assume that initialise is good place to use HAS and change it to Boolean but we're have to observe ERA :-)