Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Preface

Overview

import {
    std { compare.Ordering, io.stdin },
    random { Random, thread_rng },
};

func read_number(buffer: $String) -> Result<U32, ParseError> {
    buffer.clear;
    stdin().read_line($buffer).expect;
    buffer.trim.parse
}

func main() {
    let mut buffer = String.new;

    print("Please enter a number: ");

    let number = while_failing {
        read_number($buffer)
    } {
        print("Input must be a number.");
    };

    let correct = 0.to(number).random(thread_rng());
    print("Guess a number 0 to \(number): ");

    loop continue!{
        let guess = read_number($buffer).catch {
            print("Input must be a number.");
            continue!();
        };

        correct.compare(&guess).match {
            Ordering.Greater -> print("Higher..."),
            Ordering.Less -> print("Lower..."),
            Ordering.Equal -> {
                print("Correct!");
                return!();
            },
        };
    };
};

Inspirations

Major Inspirations

LanguageInspiration
Rustphilosophy, syntax, features
Gleamphilosophy, syntax, features
Smalltalkphilosophy, features
Swiftsyntax, ergonomics

Gleam was only discovered by me after significant design work for Sonance was already complete. Still, they two languages are very similar! That is why Gleam is listed as a major inspiration.

Minor Inspirations

LanguageInspiration
Kotlin
Inko
Kokabackpassing
Rubyblocks

Strings

Escape Codes

See Rust lol.

String Interpolation

Interpolation can be done with a special escape sequence \(...) where the ... is an arbitrary expression.

print("\(a) plus \(b) is \(a + b)");

Multiline Strings

Both after the opening quote and before closing quote must be only whitespace, which is stripped. Starting whitespace of the closing quote is commonly stripped from all middle lines, syntax error if a line has less starting whitespace. Newlines can be escaped using \ at the end of the line.

let example = "
    foo\
    bar
    ";

assert_equal(example, "foobar");

Raw Strings

Raw strings are created by prefixing the opening quote and suffixing the closing quote with a set number of # characters. Within raw strings, normal special characters are interpreted literally, including sequences of lesser amounts of #. To use escape sequences, prefix the \ character with the same amount of # as the opening and closing quotes.

let example ###"
    "you can put whatever here"
    ##" not affected
    ###\n escape codes
    ###\(value) interpolation works
"###;

Functions

func add(x: U32, y: U32) -> U32 {
    x + y
}

Modules

module my_module {}

File Module

module;

Imports

import {
    library1.foo,
    library2.bar,
};

Types

Custom Types

type MyType {
    VariantA,
    VariantB,
}

Records

type MyRecord(foo: U32, bar: Boolean);

Anonymous Records

fn sincos(x: F64) -> type(F64, F64) {
    type(x.sin, x.cos)
}

Type Modules

module type MyType {
    ...
}

Type Aliases

type Alias = MyType;

Blocks

Example: scope

func scope<T>(body: block() -> T) -> T {
    body!()
}

Example: Option<T>

condition
    .then { print("was true") }
    .else { print("was false") }
func then<T>(self: Boolean, body: block() -> T) -> Option<T> {
    match(self) {
        True -> Some(body!()),
        False -> None,
    }
}

func else<T>(self: Option<T>, body: block() -> T) -> T {
    match(self) {
        Some(value) -> value,
        None -> body!(),
    }
}

Example: while

let mut i = 1;

while { i < 6 } {
    print(i);
    i = i + 1;
}
func while(condition: block() -> Boolean, body: block()) {
    loop {
        condition!().then {
            body!();
        };
    };
}

Labels

Backpassing

Function based

Monad based

Uses With Containers

func maybe_sum(x: Option<U32>, y: Option<U32>) -> Option<U32> {
    x.flat_map do(i) {
        y.flat_map do(j) {
            Some(i + j)
        }
    }
}
func maybe_sum(x: Option<U32>, y: Option<U32>) -> Option<U32> {
    let i = x.flat_map?;
    let j = y.flat_map?;

    Some(i + j)
}

Backpassing match Special Form

match(foo) {
  True?,
  False -> print("nope"),
};

print("yep");

Expression returns a tuple.

With values

match(foo) {
  Pass(value)?,
  Fail(error) -> print("oh no: \(error)"),
};

print("yippee: \(value)");

Traits

Trait Modules

module type MyType -> MyTrait {
    ...
}

Advanced Modules

Named Type Modules

module my_module MyType {}

Named Trait Modules

module my_module MyType -> MyTrait {}

Language Reference

Keywords

ContextKeywordDescription
ModulesmoduleDeclare modules or implementations
ModulesimportImport items from other modules
ModulesexportMake item available to rest of current package
ModulespublicMake item available to external packages
TypesstructDeclare struct type
TypesenumDeclare enum types
TypestypeAlias types
TypestraitDeclare traits
FunctionsfuncDeclare functions
FunctionsdoDeclare arguments in a block literal
FunctionsblockBlock type literal
PatternsletDeclare variables
PatternsmutMake place mutable
PatternssetAssign value to place
PatternsmatchPattern match an value

Punctuation

NameSymbolDescription
=Assignment, labeled parameters
.Pipeline
;Statement ending
,General purpose separator
:Type ascription
()Parameters, arguments, grouped expressions
{}Code blocks
<>Type generic
!Label declaration, label call
?Implicit argument, backpassing
->Return type ascription, match branches
&Shared references
$Unique References