Operator Overloading
A struct can define how arithmetic and comparison operators behave for its instances. Name a method after the operator; it receives the right-hand operand, and @ is the left-hand one.
struct Vec2 fn new(x, y) @x = x @y = y end
fn +(other) Vec2.new(@x + other.x, @y + other.y) end
fn *(scalar) Vec2.new(@x * scalar, @y * scalar) end
fn ==(other) @x == other.x && @y == other.y end
fn to_string() "(${@x}, ${@y})" endend
a = Vec2.new(1, 2)b = Vec2.new(3, 4)
println (a + b).to_string() # (4, 6)println (a * 3).to_string() # (3, 6)println a == b # falseprintln a != b # trueWhich operators
Section titled “Which operators”| Category | Operators |
|---|---|
| Arithmetic | +, -, *, /, //, %, ** |
| Comparison | ==, !=, <, <=, >, >= |
| Bitwise | &, |, ^, <<, >>, >>> |
If you define == but not !=, != returns the opposite of your ==.
Logical operators (&&, ||, which short-circuit), unary operators, indexing and assignment can’t be overloaded.
- The left operand decides.
vec + 1callsVec2’s+, but1 + vecuses the built-in integer+. Put the struct on the left. - One parameter. An operator method takes exactly one parameter: the right-hand operand.
- Compound assignment follows.
a += buses your+. - Overloads are inherited. A child struct uses its parent’s operators unless it defines its own.
Accepting different right-hand types
Section titled “Accepting different right-hand types”Check the right operand’s type with typeof to support more than one kind:
struct Money fn new(cents) @cents = cents end
fn +(other) extra = typeof(other) == "Money" ? other.cents : other Money.new(@cents + extra) end
fn <(other) @cents < other.cents endend
total = Money.new(500) + Money.new(250) + 100println total.cents # 850
prices = [Money.new(300), Money.new(100), Money.new(200)]cheapest = prices.sort(do (a, b) => a < b).first()println cheapest.cents # 100Use typeof(value) == "Name" rather than value.is_a(Name) here: .is_a with a struct argument only works when value is itself a struct instance.
Since println doesn’t call to_string(), call it explicitly when printing results, as in the first example.