Skip to content

Cheat sheet

Lyth syntax next to the Go it compiles to. The tour explains each row with runnable examples, and the language reference has the exact rules.

Lyth Go
x := 1, x = 2, lo, hi := 0, n, a, b = b, a + b the same
x: int64 = 0, x: int64 (zero value) var x int64 = 0, var x int64
var Default = "x", const Max = 10 (package level) the same
func add(a: int, b: int): int = a + b func add(a int, b int) int { return a + b }
func square(n: int) = n * n (unexported) func square(n int) int { return n * n }
func dial(host: string, port: int = 5432) func dial(host string, port int); calls fill in 5432
func Add(...) (capitalized: exported) the same
func parse(s: string): int throws func parse(s string) (int, error)
struct User { Name: string } type User struct { Name string `json:"name"` }
struct Circle : Shape { R: float64 } type Circle struct { ... } and var _ Shape = Circle{}
secret: string (lower-case field) secret string (unexported, no json tag)
func User.Hello(): string (the receiver is self) func (u User) Hello() string
func *User.rename(n: string) (pointer receiver) func (u *User) rename(n string)
interface Shape { Area(): float64 } type Shape interface { Area() float64 }
typealias Handler = (Ctx) -> unit throws type Handler = func(Ctx) error
func maxOf[T: cmp.Ordered](a: T, b: T): T func maxOf[T cmp.Ordered](a T, b T) T
struct Page[T] { Items: []T }, func Page[T].First(): T type Page[T any] struct { ... }, func (p Page[T]) First() T
func string.Shout(): string (extension), "hi".Shout() func Shout(s string) string, Shout("hi")
enum Color { Red, Green } type Color int, const ( ColorRed Color = iota; ColorGreen ), and a String method
sealed interface Shape { ... } and struct Circle : Shape an interface with an unexported isShape() that only declared members have
import "net/http" as h import h "net/http"
Lyth Go
int, int64, float64, bool, string, byte, rune, any, error the same
[]T, []User? (slice of nullable users) []T, []*User
map[K]V, [4]int, *T, chan T, chan<- T, <-chan T the same
(A, B) -> R, (A) -> unit func(A, B) R, func(A)
(A) -> R throws func(A) (R, error)
User? (nullable struct) *User
*User? (nullable pointer), Shape? *User, Shape (nil allowed)
T! (in diagnostics) a Go value of unknown nullability
Lyth Go
"Hi ${name}, ${n + 1}" "Hi " + name + ", " + strconv.Itoa(n+1)
User(Name = "a", Age = 3) User{Name: "a", Age: 3}
dial("db", timeout = time.Second) dial("db", 5432, time.Second) (defaults filled in)
code in 200..299, code !in 200..<300 code >= 200 && code <= 299, code < 200 || code >= 300
x in xs, k in m, "@" in email slices.Contains(xs, x), _, ok := m[k], strings.Contains(email, "@")
&User(Name = "a") &User{Name: "a"}
[1, 2, 3], ["a": 1], [:] []int{1, 2, 3}, map[string]int{"a": 1}, map[K]V{}
[]int64{1, 2}, map[string]any{"ok": true}, [3]int{1, 2} (typed literals) the same
[][]int{[1, 2]}, []Point{Point(1, 2)} [][]int{{1, 2}}, []Point{{X: 1, Y: 2}}
if c { a } else { b } (as a value) an if statement assigning (or returning) the value
when x { 1, 2 -> a; else -> b } switch x { case 1, 2: ...; default: ... }
{ x -> x * 2 }, { it + 1 } func(x int) int { return x * 2 }
f(a) { x -> ... } (trailing lambda) f(a, func(x T) { ... })
int64(x), string(bytes), []byte(s), make(map[string]int) the same
errors.AsType[*E](https://github.com/lyth-lang/lyth/tree/main/docs/guide/err), maxOf[int](a, b) (when inference cannot bind) the same
Lyth Go
n := parse(s)? n, err := parse(s); if err != nil { return ..., err }
throw errors.New("bad") return ..., errors.New("bad")
parse(s) catch { 0 } n, err := parse(s); if err != nil { n = 0 }
parse(s) catch (err) { log(err); 0 } the same, with code in the if
f() catch {} if err := f(); err != nil {}
find(id) catch (_: *NotFound) { guest }? if _, ok := errors.AsType[*NotFound](https://github.com/lyth-lang/lyth/tree/main/docs/guide/err); ok { u = guest } else { return ..., err }
return w.Write(b) (in a throws function) return w.Write(b)
err.wrap("loading ${path}") fmt.Errorf("loading %v: %w", path, err)
n, err := strconv.Atoi(s) the same
func main() throws main that prints the error and exits with status 1
Lyth Go
if u != null { u.Name } if u != nil { u.Name }
u?.Name var name *string; if u != nil { name = new(u.Name) }
u?.Name ?: "anon" name := "anon"; if u != nil { name = u.Name }
u := find(id) ?: return u := find(id); if u == nil { return }
u!! u, with a nil check that panics with the .lyth position
x is Circle _, ok := x.(Circle)
if x is Circle { x.R } if c, ok := x.(Circle); ok { c.R }
x as Circle, x as? *Circle x.(Circle), c, _ := x.(*Circle) (a value type is boxed: Circle? is *Circle)
when x { is A -> ...; is B -> ... } switch x := x.(type) { case A: ...; case B: ... }
Color.Red; when c { Red -> ...; Green -> ... } (every entry, no else) ColorRed; a switch with a panicking default
Lyth Go
for x in xs, for i, x in xs for _, x := range xs, for i, x := range xs
for k, v in m for k, v := range m
for i in 0..<n, for i in 1..n for i := range n, for i := 1; i <= n; i++
while c { ... }, while true { ... } for c { ... }, for { ... }
break inside when break with a loop label (Lyth’s break always exits the loop)
outer@ for x in xs { ... break@outer } outer: for ... { ... break outer }
when code { in 200..299 -> a; else -> b } if code >= 200 && code <= 299 { ... } else { ... }
go { ... }, defer { ... } go func() { ... }(), defer func() { ... }()
make(chan int, 10) the same
ch.send(v), ch.receive(), ch.close() ch <- v, <-ch, close(ch)
v, ok := ch.receive() v, ok := <-ch
job := jobs.receive() ?: break job := <-jobs; if job == nil { break }
select { v := ch.receive() -> ...; else -> ... } select { case v := <-ch: ...; default: ... }
defer f.Close() catch {} defer func() { if err := f.Close(); err != nil {} }()
Lyth Go
lyth run file.lyth, lyth run ./cmd/api go run
lyth build, lyth test, lyth vet go build, go test, go vet (through an overlay)
lyth check type-check only, no build
lyth gen -stdout print the generated Go
lyth mod tidy go mod tidy that also sees imports in .lyth files

See tooling for flags and the build layout.