Methods
Methods are functions on structs. These have special properties that are slightly different than functions. The main one being automatic referencing.
Defining a basic method
import stdlib::*;
struct MyStructure {
x: i32,
y: i32;
// defining a struct FUNCTION
// "Self" is a special type that exists inside of structs.
// In this case, it refers to "MyStructure"
define new(x: i32, y: i32) -> Self {
return Self {
x: x,
y: y
};
}
// defining a struct METHOD
// self is just the first argument, when we don't define a type,
// it is assumed we want a method. "self" can be named anything you want
// "self" is just common convention. Sometimes this argument is called "this",
// in other languages
define get_x(self) -> i32 {
return self.x;
}
}
define main() {
my_instance = MyStructure::new(10, 20); // use a struct function
// ^^
// accessed with the namespace operator
println(my_instance.get_x()); // use the struct method
// ^
// accessed with the member access operator
}
Trying to access struct methods without an instance
You cannot do this. The language only lets you access these methods when you have an instance to use them with. That is another thing that makes them different than methods.
Mutable Methods
Mutable methods let you modify the instance that you are working with. These are very helpful.
import stdlib::*;
struct MyStructure {
x: i32,
y: i32;
// defining a struct FUNCTION
// "Self" is a special type that exists inside of structs.
// In this case, it refers to "MyStructure"
define new(x: i32, y: i32) -> Self {
return Self {
x: x,
y: y
};
}
// defining a struct METHOD
// "&self" is used to define a mutable method. Names other than "self"
// can be used here too!
define set_x(&self, value: i32) {
self.x = value; // has side-effects
}
}
define main() {
my_instance = MyStructure::new(10, 20); // use a struct function
// ^^
// accessed with the namespace operator
my_instance.set_x(22); // call mutable method
println(my_instance.x);
}
Method Chaining
Method chaining is where you have mutable methods that return a reference to the instance.
This is useful if you have a “builder pattern”.
import stdlib::*;
struct Student {
grade_level: i8, // could be wise to use an enum!
classes: i8, // number of classes
GPA: f32;
define new() -> Self {
return Self {
grade_level: 0,
classes: 0,
GPA: 4.0
};
}
define set_classes(&self, count: i8) -> &Self {
self.classes = count;
return self;
}
define set_GPA(&self, new_gpa: f32) -> &Self {
self.GPA = new_gpa;
return self;
}
define set_grade_level(&self, new_level: i8) -> &Self {
self.grade_level = new_level;
return self;
}
}
define main() {
my_student = Student::new();
// use method chaining
my_student.set_classes(8)
.set_GPA(3.2)
.set_grade_level(11);
// alternatively, we could do this:
my_student = *(Student::new() // dereference with `*`
.set_classes(8)
.set_GPA(3.2)
.set_grade_level(11));
}