Methods as Callbacks

I was wondering if a method could be used as a callback. Assume class MyClass, methods MyClass:load and MyClass:setup exist, and the latter contains the following statements. I tried:

parameter.action("Load", self.Load)

but when another method is called inside self.Load the system says “self” is nil.
And this:

parameter.action("Load", self:Load)

won’t even compile.
The following works:

parameter.action("Load", function(_) self:Load() end

but I was curious if one can somehow name the method directly and not be nested in another function.
Thanks.

See here

http://twolivesleft.com/Codea/Talk/discussion/2609/question-on-callback-functions/p1

http://twolivesleft.com/Codea/Talk/discussion/1210/why-one-callback-works-and-the-next-fails-on-self-reference/p1

So Lua has no concept of “method pointers”. I guess that means that methods can’t be store in variables, arrays, etc, which would have been handy. I suspected such but I wanted to verify with others more knowledgeable of Lua.

Both of those links are quite interesting, Ignatz, thanks. I’ll bookmark them for “advanced study” in Lua.

Sorry @starblue, I misunderstood your original question. As @damny says, in Lua methods and functions are the same thing.

The colon syntax for calling methods is a kind-of shorthand for passing the object itself as the first argument.

I think this does what you want. Or i misinterpreted?



--# Main
-- test method

-- Use this function to perform your initial setup
function setup()
    test = MyClass()
    parameter.action("load",function () test:load() end)
end

function draw()
end


--# MyClass
MyClass = class()

function MyClass:init(x)
    
end

function MyClass:load()
    print("i load myself")
end

there are various way to return or store methods is a table. The trick is to avoid the non-definition of ‘self’ by having it defined by the compiler, as an ‘up-value’ of the function returned (the up-value is a kind of hidden parameter, automatically managed by LUA)! Or, if the method had to be applied to various object, then you must provide the object as the first parameter. (method(object))

@starblue methods need to be bound to the object on which they will act. @Jmv38 has it right in that an instance can be bound to the function passed into parameter.action.

This is true for any language that allows method pointers (e.g. C++)

You can do this:

methodvar = "methodname"
objvar[methodvar](objvar, x)

If you don’t want methodvar to be a string, the only other option is a reference bound to a class, i.e. methodvar can’t evaluate to load only, it would evaluate to myclass.load:

methodvar = myclass.method
methodvar(objvar, x)

Essentially, obj:method(x) is the same as obj.method(obj, x). So if you have an object and a function, you can call that function as a method of your object. Useful for inheritance too because you can call superclass methods on your subclass instance (e.g. Superclass.init(self) and such).

@Jvm38, your example corresponds to my third example above, where you wrapped a function around the method call. To @Simeon, it’s been almost 20 years since I last worked with C++, but as I remember, you could store method pointers in variables and arrays (if they’re appropriately typed) without needing to wrap them inside functions. My example described method MyClass:setup(), where inside it was a call to MyClass:load() that I hoped could be put into a variable so that I could do dynamic dispatch from an array–Lua has all the information it needed to do it, if it was possible. Evidentally, it’s not possible.

Being a beginner at Lua I don’t really understand all its possibilities (and limitations) yet. Yet Perl has the ability to call methods from an array. Perl has no method pointers, but it can evaluate both parts of a method call; the results are effectively the same.

So let me explicitly ask the following question. Given this expression:

objvar:methodvar()

could “objslot” and “methodslot” both be variables, where “objslot” evaluates to an instance of myClass, “methodslot” evaluates to “load”, and so the result is effectively a call to “myClass:load()”?

Thanks, @damny and @Simeon.