Skip to content

Coming from Go

Every section below is a Go pattern with a Lisette equivalent.

count := 5
total := 0
total += count
bindings.go
let count = 5
let mut total = 0
total += count
bindings.lis

See Bindings

func add(a int, b int) int {
return a + b
}
add.go
fn add(a: int, b: int) -> int {
a + b
}
add.lis

See Functions

sort.Slice(scores, func(i, j int) bool {
return scores[i] < scores[j]
})
sort.go
sort.Slice(scores, |i, j| scores[i] < scores[j])
sort.lis

See Lambdas

trimmed := strings.TrimSpace(" Hello World ")
lowered := strings.ToLower(trimmed)
result := strings.ReplaceAll(lowered, " ", "-")
slug.go
let result = " Hello World "
|> strings.TrimSpace
|> strings.ToLower
|> strings.ReplaceAll(" ", "-")
slug.lis

See Operators

for i := 0; i < 10; i++ {
fmt.Println(i)
}
for _, line := range lines {
fmt.Println(line)
}
for {
if queue.IsEmpty() { break }
}
loops.go
for i in 0..10 {
fmt.Println(i)
}
for line in lines {
fmt.Println(line)
}
loop {
if queue.is_empty() { break }
}
loops.lis

See Control flow

type User struct {
Name string
email string
}
u := User{Name: "Alice", email: "a@b.com"}
user.go
struct User {
pub name: string,
email: string,
}
let u = User { name: "Alice", email: "a@b.com" }
user.lis

See Structs

func rename(u *User, name string) {
u.Name = name
}
user := User{Name: "Alice", email: "a@b.com"}
rename(&user, "Bob")
pointer.go
fn rename(u: mut Ref<User>, name: string) {
u.name = name
}
let mut user = User { name: "Alice", email: "a@b.com" }
rename(&user, "Bob")
pointer.lis

See References

type Severity int
const (
Low Severity = iota
High
Critical
)
severity.go
enum Severity { Low, High, Critical }
severity.lis

A match on an enum must cover every variant.

switch s {
case Low, High:
fmt.Println("ignore")
case Critical:
fmt.Println("alert")
}
severity.go
match s {
Low | High => fmt.Println("ignore"),
Critical => fmt.Println("alert"),
}
severity.lis

See Enums and Pattern matching

nums := []int{1, 2, 3}
nums = append(nums, 4)
buf := make([]byte, 1024)
ages := make(map[string]int)
ages["Alice"] = 20
age, ok := ages["Bob"]
collections.go
let nums = [1, 2, 3]
let nums = nums.append(4)
let buf = Slice.make<byte>(1024)
let mut ages = Map.new<string, int>()
ages["Alice"] = 20
let age = ages.get("Bob")Option<int>
collections.lis

See Slice, Map and Array

func (r Rectangle) Area() float64 {
return r.Width * r.Height
}
func (r *Rectangle) Scale(factor float64) {
r.Width *= factor
r.Height *= factor
}
rectangle.go
impl Rectangle {
fn area(self) -> float64 {
self.width * self.height
}
fn scale(self: mut Ref<Rectangle>, factor: float64) {
self.width *= factor
self.height *= factor
}
}
rectangle.lis

See Methods

type Reader interface {
Read(p []byte) (n int, err error)
}
reader.go
interface Reader {
fn Read(p: mut Slice<byte>) -> Partial<int, error>
}
reader.lis

See Interfaces

bytes, err := os.ReadFile(path)
if err != nil {
return Config{}, err
}
return parseConfig(bytes)
handle.go
let bytes = os.ReadFile(path)?
parse_config(bytes)
handle.lis

The ? operator unwraps Ok or returns early with Err. Functions returning (T, error) in Go become Result<T, error> in Lisette.

See Failures

var user *Userpointer can be nil
if user != nil {
fmt.Println(user.Name)
}
lookup.go
let user = get_user(id)Option<Ref<User>>
if let Some(u) = user {
fmt.Println(u.name)
}
lookup.lis

Ref<T> is guaranteed non-nil. Nilable pointers become Option<Ref<T>>.

See Option and Safety

ch := make(chan int)
go func() {
ch <- 42
}()
v := <-ch
worker.go
let ch = Channel.new<int>()
task ch.send(42)
let v = ch.receive()Option<int>
worker.lis

See Concurrency