Methods
In MoonBit, methods are toplevel functions associated with a type.
There are two ways to declare a method:
fn method_name(self : T, ..) -> ..
. The name of the first parameter must beself
here. The declared method will be associated with the typeT
fn T::method_name(..) -> ..
, where the method is associated with typeT
Methods allow more flexible call syntax compared to regular functions:
- methods can always be invoked with the syntax
T::method_name(..)
- methods can also be invoked with the syntax
x.method_name(..)
, which is equivalent toT::method_name(x, ..)
, whereT
is the type ofx
- methods declared with
fn method_name(self : T, ..)
can be invoked usingmethod_name(..)
, just like regular function
There are already a lot of methods in previous lessons, such as Array::make(..)
and arr.length()
.
The difference between two ways to declare method, and guideline for choosing between them is:
- the
fn method_name(self : T, ..)
syntax declares a method in toplevel name space, just like regular function. So this kind of method can be called viamethod_name(..)
directly, and cannot have name clash with other regular functions. if the method is for a primary type of your package, and has no name clash with other regular functions, use thefn method_name(..)
syntax - the
fn T::method_name(..)
syntax declares a method in a small namespaceT
, so this kind of method can only be called viaT::method_name(..)
orx.method_name(..)
. But the benefit is, you can have multiple methods with the same name in this way, provided that the types of the methods are different. So, this syntax can be used to resolve ambiguity or make the scope of your package cleaner.
type MyInt Int
fn increment(self : MyInt) -> MyInt {
MyInt(self._ + 1)
}
fn MyInt::println(x : MyInt) -> Unit {
println("MyInt(\{x._})")
}
fn main {
let x = MyInt(39)
let y = x.increment() // call method via dot syntax
let z = increment(y) // `fn increment(..)` can be called directly
let w = MyInt::increment(z) // call methods using qualified syntax
w.println()
MyInt::println(w) // `fn MyInt::println` cannot be called via `println(..)` directly
}