Error initializing variable at declaration

Hi,

I'm having a very weird error and I have no clue of what's going on...

I have this piece of code:

import Toybox.Lang;
using Toybox.Application as App;
using Toybox.Background as Bg;
using Toybox.WatchUi as Ui;
using Toybox.System as Sys;
using Toybox.Time;
using Toybox.Weather;

//typedef Numeric as Number or Float or Long or Double;

//
//
//
var Location as Null or Array<Double> = null;

(:background)
class MyWFApp extends App.AppBase {

    var View;
	var FieldTypes as Array<Number> = new [6] as Array<Number>;
	var MeterTypes as Array<Number> = new [3] as Array<Number>;

	public static var HasOWMfield as Array<Boolean> = new [4] as Array<Boolean>;

When I compile with the option '--debug-log-level 2', I get the following error:

"Cannot find symbol ':HasOWMfield' on type 'self'. [Ln 23, Col 1]"

Without the above compiling option, everything works fine (even on the device).

Any Idea?

P.S.: using SDK version 4.1.7 and Type Check Level set to 'Gradual'

Top Replies

All Replies

  • It may be known 4.1.7 compiler bug related to static functions: 

    https://forums.garmin.com/developer/connect-iq/i/bug-reports/compiler-bug-cannot-compile-classes-with-static-functions

    Not sure whether it's also applicable to static fields though.

    You may try to compile with 4.1.6 SDK for sure.

  • Hello,

    Thanks a lot for the hint.

    I tried switching to 4.1.6 SDK but the problem remains. The only workaround I could find is to give up using a static variable. 

    Well, not a big deal. I was using a static variable to be able to access the variable as 'MyWFApp.HasOWMfield' instead of 'App.getApp().HasOWMfield' as I have to do now...

    Of course I can revert back to the previous coding once I'm done with '--debug-log-level 2' (I'm trying to figure out why my WF is crashing after updating my Enduro to fw 25.00).

  • Or you can move the variable outside of the class, then it's global, which is kind of static.

  • Yes, indeed.

    And this, declaring as global, points me to another question for which I haven't been able to find an answer yet: is there any significant performance / memory penalty in using globals?

    I understand that the lookup can be made more efficient by using '$.' in front of globals and I wonder if other than that local variables are accessed more efficiently than global ones.

    At present, I tend to avoid global variables and I rather use a lot of static variables, especially when they are frequently accessed within the class they belong to and, occasionally, elsewhere.

    (by the way, I'm definitely not a very experienced developer and I might be kind of naive)

  • What I can tell you that since you're talking about a variable that will anyway live the whole lifecycle of the app it doesn't matter in terms of memory usage. When you open the Memory View in the simulator then you can see the global variables, but in your case it's just a matter of where it is counted in the global or inside the app.

    As for efficiency  is the expert on that. IMHO local variable INSIDE a function is the best (both generates smaller code and faster), but you're not talking about function local, so I'm not sure. I guess that if you access it with $.hasOWMField then it'll be faster than if you just write hasOWMField, but adding the $ also adds some code (at least that was the case with the compiler 4.1.5, now I haven't test it with 4.1.7)

  • For me it's also a big riddle what does Monkey C do when you call an instance function without actual instance creation.
    When we call
    MyClass.myFunc()
    instead of
    new MyClass().myFunc()
    then does Monkey C implicitly create a new instance of MyClass on each function invocation, or does it implicitly treat such a function as static? Why not a compilation error? This definitely works if you omit static modifier declaration for function but why and how?

  • good question, but since I use MyApp.getProperty in a few places I can tell you that the constructor of MyApp is not called. However in this case getProperty is not even in MyApp, it's inherited. Though I guess if it was really a function in MyApp that would use self then there would be a crash.

  • For me it's also a big riddle what does Monkey C do when you call an instance function without actual instance creation

    I've filed some bugs against this.

    If you call an instance method as MyClass.myInstance() then it (mostly) gets the context it was called from.

    So if you call it from an instance method of MyClass, everything is good. If you call it from global, or module scope, it behaves as if it had been declared static.

    But if you call it from an instance method of OtherClass, "self instanceof OtherClass" will be true. If you try to call an instance method of MyClass, it will fail. If you try to call an instance method of OtherClass it will work! (although the type checker will of course think that calling a method of MyClass is fine, and calling a method of OtherClass is broken).

    There's a similar bug in reverse, that if you call a static method from an instance method, *without* qualifying it (ie just call myStaticMethod(), rather than MyClass.myStaticMethod()), then it will behave as if it were an instance method...

    So the answer is, no it doesn't create an instance. But if you try to do something in the function that requires an instance, it will fail (or maybe do something unexpected - eg if you try to call myOtherMethod(), and there happens to be a global function called myOtherMethod(), then you could end up calling that instead)

  • Though I guess if it was really a function in MyApp that would use self then there would be a crash

    This is what worries me about doing that. In fact the api says that there's a protected member, mProperties, which you might expect to hold the properties. And if it did, invoking getProperty statically would fail.

    But in every test I've tried, it doesn't (it's just null). But thats the simulator. I've only been able to test on two real devices (fr235 and fenix5xplus) and it works fine there...

  • I think many devs use MyApp.getProperty(), so if the fix to the compiler would break that than many apps would need to be adjusted.