Skip to content
Sword

Methods and interfaces

A method is a function with a receiver:

struct Counter {
hits u64
}
func (c *Counter) Value() u64 {
return c.hits
}
func (mut c *Counter) Bump(by u64) {
c.hits += by
}
func main() int {
mut c := Counter{hits: 1}
c.Bump(20)
c.Bump(c.Value())
return int(c.Value())
}

mut on the receiver means the same thing it means on any parameter, and only a mutable binding can call such a method.

A receiver is always a struct, so a value that was just computed already lives somewhere and can be used directly — which is what makes a fluent API read the way it should:

import "std/io"
import "std/time"
func main() !int {
start := time.Now()
time.Sleep(time.Millis(10))
try io.Printf("took {}ms\n", time.Since(start).AsMillis())
return 0
}

A method that writes through its receiver is the exception: there is nowhere for the change to go, so bind the value first.

An interface is a set of method signatures, satisfied structurally — nothing is declared to implement anything:

interface Shape {
Area() i64
}
struct Square {
side i64
}
func (s *Square) Area() i64 {
return s.side * s.side
}
func describe(s Shape) i64 {
return s.Area()
}
func main() int {
mut sq := Square{side: 6}
return int(describe(&sq)) + 6
}

Note the &. Only pointers satisfy an interface. Boxing a value would mean allocating, and nothing in Sword allocates on its own, so the pointer is explicit. An interface value is two words — the data and a table of methods — and costs nothing to pass.