I'm trying to get my app strict typing compliant. Already hit the wall with a simple array:
...
var showList = [0, 0, 0] as Lang.Array<Lang.Number>;
...
showList[0] = 4;
I'm trying to get my app strict typing compliant. Already hit the wall with a simple array:
The following compiles fine for me:
class abc { private var _flcDataSets as Array<Array> = new [6] as Array<Array>; private var _flcDataSet as Array<Number> = new [5] as Array<Number>; …
_displayString += (_data.FLdata[FL_temperature] as Number / 10.0).format("%.1f").toString() + "°C";
Couple of things here, not directly related to the problem.
You shouldn…
Seems safe but a little bit of overkill. You def don't want to cast v to a Number after you've determined it's not a Number, but in the given code it's harmless.
I would probably do something…
I don't think there is anything wrong with the code snippet you've added, what I think is causing the issue is all the other code in your project that isn't strict. You can test this by just adding Toybox.Lang and seeing if all of these errors appear.
When I converted my datafield to strict I eventually gave up on trying to retrofit it to an existing project, just too many errors generated, and instead created a new strict project and moved the code over piece by piece a making each bit compliant as I went.
If it's any use you can see the result on GitHub: MBOCountdown
Hi CYBERMAN54, I was able to compile both of these with strict typing - no errors / warnings:
using Toybox.Lang; var showList as Lang.Array<Lang.Number> = [0, 0, 0] as Lang.Array<Lang.Number>; function foo(x as Lang.Number) as Void { showList[0] = 4; }
and
using Toybox.Lang; function foo(x as Lang.Number) as Void { var showList = [0, 0, 0] as Lang.Array<Lang.Number>; showList[0] = 4; }
From the error you were getting, I suspect you were trying to define a member variable like the first set of code that I listed above. The 'as' keyword can be used in different ways when it comes to Monkey Types - you can define a type for a member variable / function parameter:
var showList as Lang.Array<Lang.Number> = ...; ... function foo(x as Lang.Number) as Void {...}
or you can cast a value:
... = [0, 0, 0] as Lang.Array<Lang.Number>;
Strict typing is going to be somewhat annoying since it is STRICT. If you want a slightly less restrictive type check, you can use Informative typing. I have created a documentation ticket to better explain member typing vs. value typing.
Strict typing is going to be somewhat annoying since it is STRICT
Patient: "Doctor, it hurts when I do this!"
Doctor: "Stop doing that!"
folks really shouldn't jump from -l0 to -l3 and not expect pain. Use -l1 and -l2 before trying -l3!
Doctor: "I'm gonna recommend this trendy low-carb diet and cardio regimen for you to lose weight. If you wanna get even more fit, I suggest adding crossfit"
Patient: "I tried crossfit and I almost died"
Doctor: "That sounds like a you problem"
Seriously, the actual point of the "it hurts when I do this!" joke is that the patient is doing something crazy that the doctor would *never* recommend doing. What's the point of implementing strict typing (and the type system in general) if the recommendation is not to use it?
Having said that, if the goal is just to create a working app as fast as possible, using strict typing is probably not a great idea. Personally I think informative typing isn't much better, since you just get a bunch of warnings instead of errors. If you ignore all of those warnings, that turns into a bad habit where you start to ignore warnings that are significant. (That's why it's a fairly common practice to treat warnings -- or certain classes of warnings -- as errors.)
Also, not to state the obvious, but the following code is redundant from the POV of a dev:
var showList as Lang.Array<Lang.Number> = [0, 0, 0] as Lang.Array<Lang.Number>;
The type system should be smart enough to accept something like this instead:
var showList as Lang.Array<Lang.Number> = [0, 0, 0];
If I'm not mistaken, it's a known limitation that the compiler doesn't know that [0, 0, 0] is an Array<Number> unless you do an explicit cast.
Thanks for all the answers. I will start to refactor my app step by step.
Next funny problem:
parity ^= b;
produces a compiler crash with error
ERROR: Unsupported operation xor
com.garmin.monkeybrains.compiler2.CompilerException: Unsupported operation xor
at com.garmin.monkeybrains.compiler2.typechecker.ExpressionTypeTest.getTypeFor(ExpressionTypeTest.java:386
...
private var_parity as Number = 0,b as Number = 10;parity ^= b;
produces a compiler crash with error
ERROR: Unsupported operation xor
com.garmin.monkeybrains.compiler2.CompilerException: Unsupported operation xor
at com.garmin.monkeybrains.compiler2.typechecker.ExpressionTypeTest.getTypeFor(ExpressionTypeTest.java:386
This is a known issue. I tried it in SDK 4.1.4 (non-beta) and it fails to compile. The issue seems to be fixed in SDK 4.1.4 Compiler 2 Beta tho.
You could use this suggested workaround in the meantime:
workaround: fooNumber ^ barNumber is identical to fooNumber & ~barNumber | ~fooNumber & barNumber
You should type the declaration as well, not only the RHS:
var showList as Lang.Array<Lang.Number> = [0, 0, 0] as Lang.Array<Lang.Number>;
Thank you all for your answers. Meanwhile, i went down all the way to get my app strict typing compliant. That was some more pain at the beginning, but after a while i got used to this paved by cobblestones road. Would be better to have native C# imho ...
It's me again... -
now struggling with the declaration of a simple two-dimensional 6 x 5 Array of Numbers, while strictly sticking to strict typing.
After several trials i gave up and would like to ask here, what's wrong with
class abc {
...
private var
_flcDataSets as Array<Array> = new [6] Array<Array>,
_flcDataSet as Array<Number> = new [5] Array<Number>;
}
and subscription as e.g.
The following compiles fine for me:
class abc { private var _flcDataSets as Array<Array> = new [6] as Array<Array>; private var _flcDataSet as Array<Number> = new [5] as Array<Number>; function test() as Void { _flcDataSets[0].add(_flcDataSet); } }
Note that if you want to say _flcDataSets is an Array<Array<Number>> that currently doesn't work due to a compiler bug, but you can use a typedef as a workaround:
typedef ArrayOfNumbers as Array<Number>; class abc { private var _flcDataSets as Array<Array> = new [6] as Array<ArrayOfNumbers>; private var _flcDataSet as Array<Number> = new [5] as Array<Number>; function test() as Void { _flcDataSets[0].add(_flcDataSet); } }
Array.add() accepts Object or null in any case. (Although that seems like a big hole in the type checking system.)
EDIT: I found that the argument to Array.add() is indeed type-checked properly.