In MoonScript you call a method with a backslash: obj\method args compiles
to obj:method(args) in Lua. The dot, obj.method args, looks up a field
and calls it without passing the object as self. Inside a method, @
refers to self, so @method args calls another method on the same object.
Quick reference
| MoonScript | Lua | Meaning |
|---|---|---|
obj\method a, b | obj:method(a, b) | Call a method, passing obj as self |
obj\method! | obj:method() | Call a method with no arguments |
obj.func a | obj.func(a) | Call a function stored in a field, no self |
@name | self.name | Read a field on self |
@method a | self:method(a) | Call a method on self |
f = obj\method | (a closure) | Create a function bound to obj |
Calling a method with \
Lua uses : to call a method. MoonScript uses \ instead.
Arguments can be written without parentheses, and ! calls a method with no
arguments:
MoonScript
|
Lua
|
Chained calls work as you would expect, as do calls on the result of an index or on a literal:
MoonScript
|
Lua
|
All of Lua’s string methods work this way, since strings use the string
table as their metatable:
MoonScript
|
Lua
|
Why Lua’s : doesn’t work
The colon is already used in MoonScript to write key and value pairs in tables. Writing a Lua-style method call does not cause a compile error. It creates a table instead:
MoonScript
|
Lua
|
The code compiles, and fails when it runs. The compiled Lua calls a global
function named read, which doesn’t exist:
lua5.4: notes.lua:1: attempt to call a nil value (global 'read')
On Lua 5.1 and LuaJIT the same error is worded differently:
luajit: notes.lua:1: attempt to call global 'read' (a nil value)
If you see attempt to call a nil value (global '...') for something that
looks like a method name, look for a : that should be a \.
The difference between \ and .
The dot accesses a field and calls whatever is there as an ordinary function.
No self is passed. This is correct for module functions and for functions
stored in a table:
MoonScript
|
Lua
|
Using a dot to call a method is a mistake. The method receives no self, and
fails as soon as it reads a field:
MoonScript
|
Lua
|
Running this gives:
lua5.4: person.lua:6: attempt to index a nil value (local 'self')
On Lua 5.1 and LuaJIT:
luajit: person.lua:6: attempt to index local 'self' (a nil value)
The fix is person\greet!.
Using @ inside methods
A method is a function defined with the fat arrow, =>. The fat arrow adds a
self argument, and inside the method @ is shorthand for self:
MoonScript
|
@count reads a field, and @report! calls a method, compiling to
self:report(). When @ is followed by a name and then arguments, it is a
method call:
MoonScript
|
To call a function stored on self without passing self, index it with a
dot: @.callback value compiles to self.callback(value).
=> vs ->
A function defined with the thin arrow, ->, gets no self argument. Using
-> for a method, and then calling it with \, shifts every
argument by one position, because the object fills the first parameter:
MoonScript
|
Lua
|
Here @name refers to a self that the function never defines. Use => for
anything that will be called as a method, including new.
Getting a method as a function
Sometimes you need to pass a method somewhere that expects a plain function,
such as a callback. Writing obj\method without calling it creates a new
function with obj bound as self:
MoonScript
|
Lua
|
The same works with import. Prefixing a name with \ imports
it as a function bound to the object:
MoonScript
|
Lua
|
Calling MoonScript methods from Lua
MoonScript classes compile to ordinary Lua tables and metatables, so Lua code
calls their methods with the normal : syntax:
local Person = require("person")
local p = Person("Ada")
p:greet()