Acknowledged
CIQQA-3088

bug: method() and new Method() issues. Cannot find symbol ':method' on type 'self'

import Toybox.Lang;
import Toybox.Position;

function onPosition(info as Position.Info) as Void {
    // log("onPosition");
}

function initLocationEvents1(config as Number) as Void {
    Position.enableLocationEvents(Position.LOCATION_CONTINUOUS, method(:onPosition));
}

// (:typecheck(false))
function initLocationEvents2(config as Number) as Void {
    Position.enableLocationEvents(Position.LOCATION_CONTINUOUS, new Method($, :onPosition));
}

function initLocationEvents3(config as Number) as Void {
    Position.enableLocationEvents(Position.LOCATION_CONTINUOUS, new Method($, :onPosition)  as Method(loc as $.Toybox.Position.Info) as Void);
}

In the 1st case I get:

Cannot find symbol ':method' on type 'self'

It looks like method() only works in classes? I'm not sure why, this really should work, but at least it should be documented.

In the 2nd case I get:

Passing '$.Toybox.Lang.Method' as parameter 2 of poly type 'PolyType<Null or ($.Toybox.Lang.Method(loc as $.Toybox.Position.Info) as Void)>'.

This at least can be worked around by adding the typecheck false annotation (or new Method($, :onPosition2as Method(loc as Position.Info) as Void), but I feel like this shouldn't be needed,  method() and the compiler should be clever enough to work it out.

SDK 8.1.0, typecheck:3, I tried it on fr955 in the simulator

  • I do agree the docs aren't great here.

  • To be clear, I think method(someSymbol) is more or less equivalent to new Method(self, someSymbol), where someSymbol is the symbol for a non-static function on the current class.

    (Maybe it would work for static functions too? idk)

  • "Monkey C api" => "Connect IQ API"

  • > It looks like method() only works in classes? I'm not sure why, this really should work, but at least it should be documented.

    Yes that's by design. method() actually only works with instances of classes. Note that method() is a method on Object, which all CIQ API classes inherit from. Not sure why you would expect method() to randomly work in other contexts. It's not a global function - i.e. it's not $.method(), it's Object.method() - and afaik, there are no such global functions in the Monkey C api.

    developer.garmin.com/.../Object.html

    developer.garmin.com/.../

    The main difference between JavaScript or Lua and Monkey C is that functions in Monkey C are not first class. In JavaScript, a function can be passed to handle a callback:

    Neither of these techniques works in Monkey C, because functions are bound to the object they are created in.

    In Lua, to create an object, you bind functions to a hash table:

    To create a callback in Monkey C, create a Method object. Method objects are a combination of the function and the object instance or module they originate from.

    The above docs as well as the docs for Method.initiallize() do imply that you can create a new Method object with a function that in a module, or a static function on a class.

    https://developer.garmin.com/connect-iq/api-docs/Toybox/Lang/Method.html#initialize-instance_function

    > Passing '$.Toybox.Lang.Method' as parameter 2 of poly type 'PolyType<Null or ($.Toybox.Lang.Method(loc as $.Toybox.Position.Info) as Void)>'.

    Yes this seems like a limitation of the type checker.

    It seems that the type checker is only able to infer the type of a callback created from a symbol in the current class via method(someSymbol1). If you use new Method(moduleOrClassdef, someSymbol2), the type checker cannot infer the type of the callback.