返回 Skills 目錄
caffeinelabs/skills已通過檢查

SKILL DETAIL

writing-motoko

caffeinelabs/skills/writing-motoko

>-

安裝量 · 189查看來源

Installation

npx skills add https://github.com/caffeinelabs/skills --skill writing-motoko

技能檔案

SKILL.md

最近同步 · 2026年10月4日

api-reference.md›
# Core Library API Reference

Complete API signatures from `mo:core` library.

Use this as a reference when using contextual dot notation.

Generated from motoko-core's API lock by `scripts/generate-motoko-api-reference.mjs`.
Deprecated APIs are omitted — if a symbol is not here, do not write it.

## Array

- `func all<T>(self : [T], predicate : T -> Bool) : Bool`
- `func any<T>(self : [T], predicate : T -> Bool) : Bool`
- `func binarySearch<T>(self : [T], compare : (implicit : (T, T) -> Order.Order), element : T) : { #found : Nat; #insertionIndex : Nat }`
- `func compare<T>(self : [T], other : [T], compare : (implicit : (T, T) -> Order.Order)) : Order.Order`
- `func concat<T>(self : [T], other : [T]) : [T]`
- `func contains<T>(self : [T], equal : (implicit : (T, T) -> Bool), element : T) : Bool`
- `func empty<T>() : [T]`
- `func enumerate<T>(self : [T]) : Types.Iter<(Nat, T)>`
- `func equal<T>(self : [T], other : [T], equal : (implicit : (T, T) -> Bool)) : Bool`
- `func filter<T>(self : [T], f : T -> Bool) : [T]`
- `func filterMap<T, R>(self : [T], f : T -> ?R) : [R]`
- `func find<T>(self : [T], predicate : T -> Bool) : ?T`
- `func findIndex<T>(self : [T], predicate : T -> Bool) : ?Nat`
- `func flatMap<T, R>(self : [T], k : T -> Types.Iter<R>) : [R]`
- `func flatten<T>(self : [[T]]) : [T]`
- `func foldLeft<T, A>(self : [T], base : A, combine : (A, T) -> A) : A`
- `func foldRight<T, A>(self : [T], base : A, combine : (T, A) -> A) : A`
- `func forEach<T>(self : [T], f : T -> ())`
- `func indexOf<T>(self : [T], equal : (implicit : (T, T) -> Bool), element : T) : ?Nat`
- `func isEmpty<T>(self : [T]) : Bool`
- `func isSorted<T>(self : [T], compare : (implicit : (T, T) -> Order.Order)) : Bool`
- `func join<T>(self : Types.Iter<[T]>) : [T]`
- `func keys<T>(self : [T]) : Types.Iter<Nat>`
- `func lastIndexOf<T>(self : [T], equal : (implicit : (T, T) -> Bool), element : T) : ?Nat`
- `func map<T, R>(self : [T], f : T -> R) : [R]`
- `func mapEntries<T, R>(self : [T], f : (T, Nat) -> R) : [R]`
- `func nextIndexOf<T>(self : [T], equal : (implicit : (T, T) -> Bool), element : T, fromInclusive : Nat) : ?Nat`
- `func prevIndexOf<T>(self : [T], equal : (implicit : (T, T) -> Bool), element : T, fromExclusive : Nat) : ?Nat`
- `func range<T>(self : [T], fromInclusive : Int, toExclusive : Int) : Types.Iter<T>`
- `func repeat<T>(item : T, size : Nat) : [T]`
- `func reverse<T>(self : [T]) : [T]`
- `func singleton<T>(element : T) : [T]`
- `func size<T>(self : [T]) : Nat`
- `func sliceToArray<T>(self : [T], fromInclusive : Int, toExclusive : Int) : [T]`
- `func sliceToVarArray<T>(self : [T], fromInclusive : Int, toExclusive : Int) : [var T]`
- `func sort<T>(self : [T], compare : (implicit : (T, T) -> Order.Order)) : [T]`
- `func tabulate<T>(size : Nat, generator : Nat -> T) : [T]`
- `func toBlob(self : [Nat8]) : Blob`
- `func toText<T>(self : [T], f : (implicit : (toText : T -> Text))) : Text`
- `func toVarArray<T>(self : [T]) : [var T]`
- `func values<T>(self : [T]) : Types.Iter<T>`

## Blob

- `func compare(self : Blob, other : Blob) : Order.Order`
- `func empty() : Blob`
- `func equal(self : Blob, other : Blob) : Bool`
- `func greater(self : Blob, other : Blob) : Bool`
- `func greaterOrEqual(self : Blob, other : Blob) : Bool`
- `func hash(self : Blob) : Types.Hash`
- `func isEmpty(self : Blob) : Bool`
- `func less(self : Blob, other : Blob) : Bool`
- `func lessOrEqual(self : Blob, other : Blob) : Bool`
- `func notEqual(self : Blob, other : Blob) : Bool`
- `func size(self : Blob) : Nat`
- `func toArray(self : Blob) : [Nat8]`
- `func toVarArray(self : Blob) : [var Nat8]`
- `type Blob = Prim.Types.Blob`

## Bool

- `func allValues() : Iter.Iter<Bool>`
- `func compare(self : Bool, other : Bool) : Order.Order`
- `func equal(self : Bool, other : Bool) : Bool`
- `func logicalAnd(self : Bool, other : Bool) : Bool`
- `func logicalNot(self : Bool) : Bool`
- `func logicalOr(self : Bool, other : Bool) : Bool`
- `func logicalXor(self : Bool, other : Bool) : Bool`
- `func toText(self : Bool) : Text`
- `type Bool = Prim.Types.Bool`

## Char

- `func compare(self : Char, other : Char) : { #less; #equal; #greater }`
- `func equal(self : Char, other : Char) : Bool`
- `func greater(self : Char, other : Char) : Bool`
- `func greaterOrEqual(self : Char, other : Char) : Bool`
- `func isAlphabetic(self : Char) : Bool`
- `func isDigit(self : Char) : Bool`
- `func isLower(self : Char) : Bool`
- `func isUpper(self : Char) : Bool`
- `func isWhitespace(self : Char) : Bool`
- `func less(self : Char, other : Char) : Bool`
- `func lessOrEqual(self : Char, other : Char) : Bool`
- `func notEqual(self : Char, other : Char) : Bool`
- `func toNat32(self : Char) : Nat32`
- `func toText(self : Char) : Text`
- `type Char = Prim.Types.Char`

## Debug

- `func print(text : Text) : ()`
- `func todo() : None`

## Error

- `func code(self : Error) : ErrorCode`
- `func isCleanReject(self : Error) : Bool`
- `func isRetryPossible(self : Error) : Bool`
- `func message(self : Error) : Text`
- `func reject(message : Text) : Error`
- `type Error = Prim.Types.Error`
- `type ErrorCode = Prim.ErrorCode`

## Float

- `func abs(x : Float) : Float`
- `func add(x : Float, y : Float) : Float`
- `func arccos(x : Float) : Float`
- `func arcsin(x : Float) : Float`
- `func arctan(x : Float) : Float`
- `func arctan2(y : Float, x : Float) : Float`
- `func ceil(x : Float) : Float`
- `func compare(x : Float, y : Float) : Order.Order`
- `func copySign(x : Float, y : Float) : Float`
- `func cos(x : Float) : Float`
- `func div(x : Float, y : Float) : Float`
- `func equal(x : Float, y : Float, epsilon : Float) : Bool`
- `func exp(x : Float) : Float`
- `func floor(x : Float) : Float`
- `func format(self : Float, fmt : { #fix : Nat8; #exp : Nat8; #gen : Nat8; #exact }) : Text`
- `func fromInt64(x : Int64) : Float`
- `func greater(x : Float, y : Float) : Bool`
- `func greaterOrEqual(x : Float, y : Float) : Bool`
- `func isNaN(self : Float) : Bool`
- `func less(x : Float, y : Float) : Bool`
- `func lessOrEqual(x : Float, y : Float) : Bool`
- `func log(x : Float) : Float`
- `func max(x : Float, y : Float) : Float`
- `func min(x : Float, y : Float) : Float`
- `func mul(x : Float, y : Float) : Float`
- `func nearest(x : Float) : Float`
- `func neg(x : Float) : Float`
- `func notEqual(x : Float, y : Float, epsilon : Float) : Bool`
- `func pow(x : Float, y : Float) : Float`
- `func rem(x : Float, y : Float) : Float`
- `func sin(x : Float) : Float`
- `func sqrt(x : Float) : Float`
- `func sub(x : Float, y : Float) : Float`
- `func tan(x : Float) : Float`
- `func toFloat32(self : Float) : Prim.Types.Float32`
- `func toInt(self : Float) : Int`
- `func toInt64(self : Float) : Int64`
- `func toText(self : Float) : Text`
- `func trunc(x : Float) : Float`
- `let e : Float`
- `let pi : Float`
- `type Float = Prim.Types.Float`

## Int

- `func abs(x : Int) : Nat`
- `func add(x : Int, y : Int) : Int`
- `func compare(x : Int, y : Int) : Order.Order`
- `func div(x : Int, y : Int) : Int`
- `func equal(x : Int, y : Int) : Bool`
- `func fromText(text : Text) : ?Int`
- `func greater(x : Int, y : Int) : Bool`
- `func greaterOrEqual(x : Int, y : Int) : Bool`
- `func less(x : Int, y : Int) : Bool`
- `func lessOrEqual(x : Int, y : Int) : Bool`
- `func max(x : Int, y : Int) : Int`
- `func min(x : Int, y : Int) : Int`
- `func mul(x : Int, y : Int) : Int`
- `func neg(x : Int) : Int`
- `func notEqual(x : Int, y : Int) : Bool`
- `func pow(x : Int, y : Int) : Int`
- `func range(fromInclusive : Int, toExclusive : Int) : Iter.Iter<Int>`
- `func rangeBy(fromInclusive : Int, toExclusive : Int, step : Int) : Iter.Iter<Int>`
- `func rangeByInclusive(from : Int, to : Int, step : Int) : Iter.Iter<Int>`
- `func rangeInclusive(from : Int, to : Int) : Iter.Iter<Int>`
- `func rem(x : Int, y : Int) : Int`
- `func sub(x : Int, y : Int) : Int`
- `func toFloat(self : Int) : Float`
- `func toInt(self : Text) : ?Int`
- `func toInt16(self : Int) : Int16`
- `func toInt32(self : Int) : Int32`
- `func toInt64(self : Int) : Int64`
- `func toInt8(self : Int) : Int8`
- `func toNat(self : Int) : Nat`
- `func toText(self : Int) : Text`
- `type Int = Prim.Types.Int`

## Iter

- `func all<T>(self : Iter<T>, f : T -> Bool) : Bool`
- `func any<T>(self : Iter<T>, f : T -> Bool) : Bool`
- `func concat<T>(self : Iter<T>, other : Iter<T>) : Iter<T>`
- `func contains<T>(self : Iter<T>, equal : (implicit : (T, T) -> Bool), value : T) : Bool`
- `func drop<T>(self : Iter<T>, n : Nat) : Iter<T>`
- `func dropWhile<T>(self : Iter<T>, f : T -> Bool) : Iter<T>`
- `func empty<T>() : Iter<T>`
- `func enumerate<T>(self : Iter<T>) : Iter<(Nat, T)>`
- `func filter<T>(self : Iter<T>, f : T -> Bool) : Iter<T>`
- `func filterMap<T, R>(self : Iter<T>, f : T -> ?R) : Iter<R>`
- `func find<T>(self : Iter<T>, f : T -> Bool) : ?T`
- `func findIndex<T>(self : Iter<T>, predicate : T -> Bool) : ?Nat`
- `func flatMap<T, R>(self : Iter<T>, f : T -> Iter<R>) : Iter<R>`
- `func flatten<T>(self : Iter<Iter<T>>) : Iter<T>`
- `func foldLeft<T, R>(self : Iter<T>, initial : R, combine : (R, T) -> R) : R`
- `func foldRight<T, R>(self : Iter<T>, initial : R, combine : (T, R) -> R) : R`
- `func forEach<T>(self : Iter<T>, f : (T) -> ())`
- `func infinite<T>(item : T) : Iter<T>`
- `func map<T, R>(self : Iter<T>, f : T -> R) : Iter<R>`
- `func max<T>(self : Iter<T>, compare : (implicit : (T, T) -> Order.Order)) : ?T`
- `func min<T>(self : Iter<T>, compare : (implicit : (T, T) -> Order.Order)) : ?T`
- `func reduce<T>(self : Iter<T>, combine : (T, T) -> T) : ?T`
- `func repeat<T>(item : T, count : Nat) : Iter<T>`
- `func reverse<T>(self : Iter<T>) : Iter<T>`
- `func scanLeft<T, R>(self : Iter<T>, initial : R, combine : (R, T) -> R) : Iter<R>`
- `func scanRight<T, R>(self : Iter<T>, initial : R, combine : (T, R) -> R) : Iter<R>`
- `func singleton<T>(value : T) : Iter<T>`
- `func size<T>(self : Iter<T>) : Nat`
- `func sort<T>(self : Iter<T>, compare : (implicit : (T, T) -> Order.Order)) : Iter<T>`
- `func step<T>(self : Iter<T>, n : Nat) : Iter<T>`
- `func take<T>(self : Iter<T>, n : Nat) : Iter<T>`
- `func takeWhile<T>(self : Iter<T>, f : T -> Bool) : Iter<T>`
- `func toArray<T>(self : Iter<T>) : [T]`
- `func toVarArray<T>(self : Iter<T>) : [var T]`
- `func unfold<T, S>(initial : S, step : S -> ?(T, S)) : Iter<T>`
- `func zip3<A, B, C>(self : Iter<A>, other1 : Iter<B>, other2 : Iter<C>) : Iter<(A, B, C)>`
- `func zip<A, B>(self : Iter<A>, other : Iter<B>) : Iter<(A, B)>`
- `func zipWith3<A, B, C, R>(self : Iter<A>, other1 : Iter<B>, other2 : Iter<C>, f : (A, B, C) -> R) : Iter<R>`
- `func zipWith<A, B, R>(self : Iter<A>, other : Iter<B>, f : (A, B) -> R) : Iter<R>`
- `type Iter<T> = Types.Iter<T>`

## List

- `func add<T>(self : List<T>, element : T)`
- `func addAll<T>(self : List<T>, iter : Types.Iter<T>)`
- `func addRepeat<T>(self : List<T>, initValue : T, count : Nat)`
- `func all<T>(self : List<T>, predicate : T -> Bool) : Bool`
- `func any<T>(self : List<T>, predicate : T -> Bool) : Bool`
- `func append<T>(self : List<T>, added : List<T>)`
- `func at<T>(self : List<T>, index : Nat) : T`
- `func binarySearch<T>(self : List<T>, compare : (implicit : (T, T) -> Types.Order), element : T) : { #found : Nat; #insertionIndex : Nat }`
- `func clear<T>(self : List<T>)`
- `func clone<T>(self : List<T>) : List<T>`
- `func compare<T>(self : List<T>, other : List<T>, compare : (implicit : (T, T) -> Types.Order)) : Types.Order`
- `func contains<T>(self : List<T>, equal : (implicit : (T, T) -> Bool), element : T) : Bool`
- `func deduplicate<T>(self : List<T>, equal : (implicit : (T, T) -> Bool))`
- `func empty<T>() : List<T>`
- `func enumerate<T>(self : List<T>) : Types.Iter<(Nat, T)>`
- `func equal<T>(self : List<T>, other : List<T>, equal : (implicit : (T, T) -> Bool)) : Bool`
- `func fill<T>(self : List<T>, value : T)`
- `func filter<T>(self : List<T>, predicate : T -> Bool) : List<T>`
- `func filterMap<T, R>(self : List<T>, f : T -> ?R) : List<R>`
- `func find<T>(self : List<T>, predicate : T -> Bool) : ?T`
- `func findIndex<T>(self : List<T>, predicate : T -> Bool) : ?Nat`
- `func findLastIndex<T>(self : List<T>, predicate : T -> Bool) : ?Nat`
- `func first<T>(self : List<T>) : ?T`
- `func flatMap<T, R>(self : List<T>, k : T -> Types.Iter<R>) : List<R>`
- `func flatten<T>(self : List<List<T>>) : List<T>`
- `func foldLeft<A, T>(self : List<T>, base : A, combine : (A, T) -> A) : A`
- `func foldRight<T, A>(self : List<T>, base : A, combine : (T, A) -> A) : A`
- `func forEach<T>(self : List<T>, f : T -> ())`
- `func forEachEntry<T>(self : List<T>, f : (Nat, T) -> ())`
- `func forEachInRange<T>(self : List<T>, f : T -> (), fromInclusive : Nat, toExclusive : Nat)`
- `func fromArray<T>(array : [T]) : List<T>`
- `func fromIter<T>(iter : Types.Iter<T>) : List<T>`
- `func fromVarArray<T>(array : [var T]) : List<T>`
- `func get<T>(self : List<T>, index : Nat) : ?T`
- `func indexOf<T>(self : List<T>, equal : (implicit : (T, T) -> Bool), element : T) : ?Nat`
- `func isEmpty<T>(self : List<T>) : Bool`
- `func isSorted<T>(self : List<T>, compare : (implicit : (T, T) -> Types.Order)) : Bool`
- `func join<T>(self : Types.Iter<List<T>>) : List<T>`
- `func keys<T>(self : List<T>) : Types.Iter<Nat>`
- `func last<T>(self : List<T>) : ?T`
- `func lastIndexOf<T>(self : List<T>, equal : (implicit : (T, T) -> Bool), element : T) : ?Nat`
- `func map<T, R>(self : List<T>, f : T -> R) : List<R>`
- `func mapEntries<T, R>(self : List<T>, f : (T, Nat) -> R) : List<R>`
- `func mapInPlace<T>(self : List<T>, f : T -> T)`
- `func mapResult<T, R, E>(self : List<T>, f : T -> Types.Result<R, E>) : Types.Result<List<R>, E>`
- `func max<T>(self : List<T>, compare : (implicit : (T, T) -> Types.Order)) : ?T`
- `func min<T>(self : List<T>, compare : (implicit : (T, T) -> Types.Order)) : ?T`
- `func nextIndexOf<T>(self : List<T>, equal : (implicit : (T, T) -> Bool), element : T, fromInclusive : Nat) : ?Nat`
- `func prevIndexOf<T>(self : List<T>, equal : (implicit : (T, T) -> Bool), element : T, fromExclusive : Nat) : ?Nat`
- `func put<T>(self : List<T>, index : Nat, value : T)`
- `func range<T>(self : List<T>, fromInclusive : Int, toExclusive : Int) : Types.Iter<T>`
- `func reader<T>(self : List<T>, start : Nat) : () -> T`
- `func removeLast<T>(self : List<T>) : ?T`
- `func repeat<T>(initValue : T, size : Nat) : List<T>`
- `func retain<T>(self : List<T>, predicate : T -> Bool)`
- `func reverse<T>(self : List<T>) : List<T>`
- `func reverseEnumerate<T>(self : List<T>) : Types.Iter<(Nat, T)>`
- `func reverseForEach<T>(self : List<T>, f : T -> ())`
- `func reverseForEachEntry<T>(self : List<T>, f : (Nat, T) -> ())`
- `func reverseInPlace<T>(self : List<T>)`
- `func reverseValues<T>(self : List<T>) : Types.Iter<T>`
- `func singleton<T>(element : T) : List<T>`
- `func size<T>(self : List<T>) : Nat`
- `func sliceToArray<T>(self : List<T>, fromInclusive : Int, toExclusive : Int) : [T]`
- `func sliceToVarArray<T>(self : List<T>, fromInclusive : Int, toExclusive : Int) : [var T]`
- `func sort<T>(self : List<T>, compare : (implicit : (T, T) -> Types.Order)) : List<T>`
- `func sortInPlace<T>(self : List<T>, compare : (implicit : (T, T) -> Types.Order))`
- `func tabulate<T>(size : Nat, generator : Nat -> T) : List<T>`
- `func toArray<T>(self : List<T>) : [T]`
- `func toList<T>(self : Types.Iter<T>) : List<T>`
- `func toText<T>(self : List<T>, toText : (implicit : T -> Text)) : Text`
- `func toVarArray<T>(self : List<T>) : [var T]`
- `func truncate<T>(self : List<T>, newSize : Nat)`
- `func values<T>(self : List<T>) : Types.Iter<T>`
- `type List<T> = Types.List<T>`

## Map

- `func add<K, V>(self : Map<K, V>, compare : (implicit : (K, K) -> Order.Order), key : K, value : V)`
- `func all<K, V>(self : Map<K, V>, predicate : (K, V) -> Bool) : Bool`
- `func any<K, V>(self : Map<K, V>, predicate : (K, V) -> Bool) : Bool`
- `func clear<K, V>(self : Map<K, V>)`
- `func clone<K, V>(self : Map<K, V>) : Map<K, V>`
- `func compare<K, V>(self : Map<K, V>, other : Map<K, V>, compareKey : (implicit : (compare : (K, K) -> Order.Order)), compareValue : (implicit : (compare : (V, V) -> Order.Order))) : Order.Order`
- `func containsKey<K, V>(self : Map<K, V>, compare : (implicit : (K, K) -> Order.Order), key : K) : Bool`
- `func empty<K, V>() : Map<K, V>`
- `func entries<K, V>(self : Map<K, V>) : Types.Iter<(K, V)>`
- `func entriesFrom<K, V>(self : Map<K, V>, compare : (implicit : (K, K) -> Order.Order), key : K) : Types.Iter<(K, V)>`
- `func equal<K, V>(self : Map<K, V>, other : Map<K, V>, compare : (implicit : (K, K) -> Types.Order), equal : (implicit : (V, V) -> Bool)) : Bool`
- `func filter<K, V>(self : Map<K, V>, compare : (implicit : (K, K) -> Order.Order), criterion : (K, V) -> Bool) : Map<K, V>`
- `func filterMap<K, V1, V2>(self : Map<K, V1>, compare : (implicit : (K, K) -> Order.Order), project : (K, V1) -> ?V2) : Map<K, V2>`
- `func foldLeft<K, V, A>(self : Map<K, V>, base : A, combine : (A, K, V) -> A) : A`
- `func foldRight<K, V, A>(self : Map<K, V>, base : A, combine : (K, V, A) -> A) : A`
- `func forEach<K, V>(self : Map<K, V>, operation : (K, V) -> ())`
- `func fromArray<K, V>(array : [(K, V)], compare : (implicit : (K, K) -> Order.Order)) : Map<K, V>`
- `func fromIter<K, V>(iter : Types.Iter<(K, V)>, compare : (implicit : (K, K) -> Order.Order)) : Map<K, V>`
- `func fromVarArray<K, V>(array : [var (K, V)], compare : (implicit : (K, K) -> Order.Order)) : Map<K, V>`
- `func get<K, V>(self : Map<K, V>, compare : (implicit : (K, K) -> Order.Order), key : K) : ?V`
- `func isEmpty<K, V>(self : Map<K, V>) : Bool`
- `func keys<K, V>(self : Map<K, V>) : Types.Iter<K>`
- `func map<K, V1, V2>(self : Map<K, V1>, project : (K, V1) -> V2) : Map<K, V2>`
- `func maxEntry<K, V>(self : Map<K, V>) : ?(K, V)`
- `func minEntry<K, V>(self : Map<K, V>) : ?(K, V)`
- `func remove<K, V>(self : Map<K, V>, compare : (implicit : (K, K) -> Order.Order), key : K)`
- `func replace<K, V>(self : Map<K, V>, compare : (implicit : (K, K) -> Order.Order), key : K, value : V) : ?V`
- `func reverseEntries<K, V>(self : Map<K, V>) : Types.Iter<(K, V)>`
- `func reverseEntriesFrom<K, V>(self : Map<K, V>, compare : (implicit : (K, K) -> Order.Order), key : K) : Types.Iter<(K, V)>`
- `func singleton<K, V>(key : K, value : V) : Map<K, V>`
- `func size<K, V>(self : Map<K, V>) : Nat`
- `func swap<K, V>(self : Map<K, V>, compare : (implicit : (K, K) -> Order.Order), key : K, value : V) : ?V`
- `func take<K, V>(self : Map<K, V>, compare : (implicit : (K, K) -> Order.Order), key : K) : ?V`
- `func toArray<K, V>(self : Map<K, V>) : [(K, V)]`
- `func toMap<K, V>(self : Types.Iter<(K, V)>, compare : (implicit : (K, K) -> Order.Order)) : Map<K, V>`
- `func toText<K, V>(self : Map<K, V>, keyFormat : (implicit : (toText : K -> Text)), valueFormat : (implicit : (toText : V -> Text))) : Text`
- `func toVarArray<K, V>(self : Map<K, V>) : [var (K, V)]`
- `func values<K, V>(self : Map<K, V>) : Types.Iter<V>`
- `type Map<K, V> = Types.Map<K, V>`

## Nat

- `func add(x : Nat, y : Nat) : Nat`
- `func allValues() : Iter.Iter<Nat>`
- `func bitshiftLeft(x : Nat, y : Nat32) : Nat`
- `func bitshiftRight(x : Nat, y : Nat32) : Nat`
- `func compare(x : Nat, y : Nat) : Order.Order`
- `func div(x : Nat, y : Nat) : Nat`
- `func equal(x : Nat, y : Nat) : Bool`
- `func fromText(text : Text) : ?Nat`
- `func greater(x : Nat, y : Nat) : Bool`
- `func greaterOrEqual(x : Nat, y : Nat) : Bool`
- `func less(x : Nat, y : Nat) : Bool`
- `func lessOrEqual(x : Nat, y : Nat) : Bool`
- `func max(x : Nat, y : Nat) : Nat`
- `func min(x : Nat, y : Nat) : Nat`
- `func mul(x : Nat, y : Nat) : Nat`
- `func notEqual(x : Nat, y : Nat) : Bool`
- `func pow(x : Nat, y : Nat) : Nat`
- `func range(fromInclusive : Nat, toExclusive : Nat) : Iter.Iter<Nat>`
- `func rangeBy(fromInclusive : Nat, toExclusive : Nat, step : Int) : Iter.Iter<Nat>`
- `func rangeByInclusive(from : Nat, to : Nat, step : Int) : Iter.Iter<Nat>`
- `func rangeInclusive(from : Nat, to : Nat) : Iter.Iter<Nat>`
- `func rem(x : Nat, y : Nat) : Nat`
- `func sub(x : Nat, y : Nat) : Nat`
- `func toFloat(self : Nat) : Float`
- `func toInt(self : Nat) : Int`
- `func toNat(self : Text) : ?Nat`
- `func toNat16(self : Nat) : Nat16`
- `func toNat32(self : Nat) : Nat32`
- `func toNat64(self : Nat) : Nat64`
- `func toNat8(self : Nat) : Nat8`
- `func toText(self : Nat) : Text`
- `type Nat = Prim.Types.Nat`

## Option

- `func apply<T, R>(self : ?T, f : ?(T -> R)) : ?R`
- `func chain<T, R>(self : ?T, f : T -> ?R) : ?R`
- `func compare<T>(self : ?T, other : ?T, compare : (implicit : (T, T) -> Types.Order)) : Types.Order`
- `func equal<T>(self : ?T, other : ?T, eq : (implicit : (equal : (T, T) -> Bool))) : Bool`
- `func flatten<T>(self : ??T) : ?T`
- `func forEach<T>(self : ?T, f : T -> ())`
- `func get<T>(self : ?T, default : T) : T`
- `func getMapped<T, R>(self : ?T, f : T -> R, default : R) : R`
- `func isNull(self : ?Any) : Bool`
- `func isSome(self : ?Any) : Bool`
- `func map<T, R>(self : ?T, f : T -> R) : ?R`
- `func some<T>(self : T) : ?T`
- `func toText<T>(self : ?T, toText : (implicit : T -> Text)) : Text`
- `func unwrap<T>(self : ?T) : T`

## Order

- `func allValues() : Types.Iter<Order>`
- `func equal(self : Order, other : Order) : Bool`
- `func isEqual(self : Order) : Bool`
- `func isGreater(self : Order) : Bool`
- `func isLess(self : Order) : Bool`
- `type Order = Types.Order`

## Principal

- `func anonymous() : Principal`
- `func compare(self : Principal, other : Principal) : { #less; #equal; #greater }`
- `func equal(self : Principal, other : Principal) : Bool`
- `func fromActor(a : actor {}) : Principal`
- `func fromBlob(blob : Blob) : Principal`
- `func fromText(t : Text) : Principal`
- `func greater(self : Principal, other : Principal) : Bool`
- `func greaterOrEqual(self : Principal, other : Principal) : Bool`
- `func hash(self : Principal) : Types.Hash`
- `func isAnonymous(self : Principal) : Bool`
- `func isCanister(self : Principal) : Bool`
- `func isController(self : Principal) : Bool`
- `func isReserved(self : Principal) : Bool`
- `func isSelfAuthenticating(self : Principal) : Bool`
- `func less(self : Principal, other : Principal) : Bool`
- `func lessOrEqual(self : Principal, other : Principal) : Bool`
- `func notEqual(self : Principal, other : Principal) : Bool`
- `func toActor<A <: actor {}>(p : Principal) : A`
- `func toBlob(self : Principal) : Blob`
- `func toLedgerAccount(self : Principal, subAccount : ?Blob) : Blob`
- `func toText(self : Principal) : Text`
- `type Principal = Prim.Types.Principal`

## Queue

- `func all<T>(self : Queue<T>, predicate : T -> Bool) : Bool`
- `func any<T>(self : Queue<T>, predicate : T -> Bool) : Bool`
- `func clear<T>(self : Queue<T>)`
- `func clone<T>(self : Queue<T>) : Queue<T>`
- `func compare<T>(self : Queue<T>, other : Queue<T>, compare : (implicit : (T, T) -> Order.Order)) : Order.Order`
- `func contains<T>(self : Queue<T>, equal : (implicit : (T, T) -> Bool), element : T) : Bool`
- `func empty<T>() : Queue<T>`
- `func equal<T>(self : Queue<T>, other : Queue<T>, equal : (implicit : (T, T) -> Bool)) : Bool`
- `func filter<T>(self : Queue<T>, criterion : T -> Bool) : Queue<T>`
- `func filterMap<T, U>(self : Queue<T>, project : T -> ?U) : Queue<U>`
- `func forEach<T>(self : Queue<T>, operation : T -> ())`
- `func fromArray<T>(array : [T]) : Queue<T>`
- `func fromIter<T>(iter : Iter.Iter<T>) : Queue<T>`
- `func fromVarArray<T>(array : [var T]) : Queue<T>`
- `func isEmpty<T>(self : Queue<T>) : Bool`
- `func map<T, U>(self : Queue<T>, project : T -> U) : Queue<U>`
- `func peekBack<T>(self : Queue<T>) : ?T`
- `func peekFront<T>(self : Queue<T>) : ?T`
- `func popBack<T>(self : Queue<T>) : ?T`
- `func popFront<T>(self : Queue<T>) : ?T`
- `func pushBack<T>(self : Queue<T>, element : T)`
- `func pushFront<T>(self : Queue<T>, element : T)`
- `func reverseValues<T>(self : Queue<T>) : Iter.Iter<T>`
- `func singleton<T>(element : T) : Queue<T>`
- `func size<T>(self : Queue<T>) : Nat`
- `func toArray<T>(self : Queue<T>) : [T]`
- `func toQueue<T>(self : Iter.Iter<T>) : Queue<T>`
- `func toText<T>(self : Queue<T>, format : (implicit : (toText : T -> Text))) : Text`
- `func toVarArray<T>(self : Queue<T>) : [var T]`
- `func values<T>(self : Queue<T>) : Iter.Iter<T>`
- `type Queue<T> = Types.Queue.Queue<T>`

## Result

- `func assertErr(self : Result<Any, Any>)`
- `func assertOk(self : Result<Any, Any>)`
- `func chain<Ok1, Ok2, Err>(self : Result<Ok1, Err>, f : Ok1 -> Result<Ok2, Err>) : Result<Ok2, Err>`
- `func compare<Ok, Err>(self : Result<Ok, Err>, other : Result<Ok, Err>, compareOk : (implicit : (compare : (Ok, Ok) -> Order.Order)), compareErr : (implicit : (compare : (Err, Err) -> Order.Order))) : Order.Order`
- `func equal<Ok, Err>(self : Result<Ok, Err>, other : Result<Ok, Err>, equalOk : (implicit : (equal : Ok, Ok) -> Bool), equalErr : (implicit : (equal : (Err, Err) -> Bool))) : Bool`
- `func flatten<Ok, Err>(self : Result<Result<Ok, Err>, Err>) : Result<Ok, Err>`
- `func forErr<Ok, Err>(self : Result<Ok, Err>, f : Err -> ())`
- `func forOk<Ok, Err>(self : Result<Ok, Err>, f : Ok -> ())`
- `func fromOption<Ok, Err>(x : ?Ok, err : Err) : Result<Ok, Err>`
- `func fromUpper<Ok, Err>(result : { #Ok : Ok; #Err : Err }) : Result<Ok, Err>`
- `func isErr(self : Result<Any, Any>) : Bool`
- `func isOk(self : Result<Any, Any>) : Bool`
- `func mapErr<Ok, Err1, Err2>(self : Result<Ok, Err1>, f : Err1 -> Err2) : Result<Ok, Err2>`
- `func mapOk<Ok1, Ok2, Err>(self : Result<Ok1, Err>, f : Ok1 -> Ok2) : Result<Ok2, Err>`
- `func toOption<Ok, Err>(self : Result<Ok, Err>) : ?Ok`
- `func toUpper<Ok, Err>(self : Result<Ok, Err>) : { #Ok : Ok; #Err : Err }`
- `type Result<Ok, Err> = Types.Result<Ok, Err>`

## Runtime

- `func envVar<system>(name : Text) : ?Text`
- `func envVarNames<system>() : [Text]`
- `func trap(errorMessage : Text) : None`
- `func unreachable() : None`

## Set

- `func add<T>(self : Set<T>, compare : (implicit : (T, T) -> Order.Order), element : T)`
- `func addAll<T>(self : Set<T>, compare : (implicit : (T, T) -> Order.Order), iter : Types.Iter<T>)`
- `func all<T>(self : Set<T>, predicate : T -> Bool) : Bool`
- `func any<T>(self : Set<T>, predicate : T -> Bool) : Bool`
- `func clear<T>(self : Set<T>)`
- `func clone<T>(self : Set<T>) : Set<T>`
- `func compare<T>(self : Set<T>, other : Set<T>, compare : (implicit : (T, T) -> Order.Order)) : Order.Order`
- `func contains<T>(self : Set<T>, compare : (implicit : (T, T) -> Order.Order), element : T) : Bool`
- `func deleteAll<T>(self : Set<T>, compare : (implicit : (T, T) -> Order.Order), iter : Types.Iter<T>) : Bool`
- `func difference<T>(self : Set<T>, other : Set<T>, compare : (implicit : (T, T) -> Order.Order)) : Set<T>`
- `func empty<T>() : Set<T>`
- `func equal<T>(self : Set<T>, other : Set<T>, compare : (implicit : (T, T) -> Types.Order)) : Bool`
- `func filter<T>(self : Set<T>, compare : (implicit : (T, T) -> Order.Order), criterion : T -> Bool) : Set<T>`
- `func filterMap<T1, T2>(self : Set<T1>, compare : (implicit : (T2, T2) -> Order.Order), project : T1 -> ?T2) : Set<T2>`
- `func flatten<T>(self : Set<Set<T>>, compare : (implicit : (T, T) -> Order.Order)) : Set<T>`
- `func foldLeft<T, A>(self : Set<T>, base : A, combine : (A, T) -> A) : A`
- `func foldRight<T, A>(self : Set<T>, base : A, combine : (T, A) -> A) : A`
- `func forEach<T>(self : Set<T>, operation : T -> ())`
- `func fromArray<T>(array : [T], compare : (implicit : (T, T) -> Order.Order)) : Set<T>`
- `func fromIter<T>(iter : Types.Iter<T>, compare : (implicit : (T, T) -> Order.Order)) : Set<T>`
- `func insertAll<T>(self : Set<T>, compare : (implicit : (T, T) -> Order.Order), iter : Types.Iter<T>) : Bool`
- `func intersection<T>(self : Set<T>, other : Set<T>, compare : (implicit : (T, T) -> Order.Order)) : Set<T>`
- `func isEmpty<T>(self : Set<T>) : Bool`
- `func isSubset<T>(self : Set<T>, other : Set<T>, compare : (implicit : (T, T) -> Order.Order)) : Bool`
- `func join<T>(setIterator : Types.Iter<Set<T>>, compare : (implicit : (T, T) -> Order.Order)) : Set<T>`
- `func map<T1, T2>(self : Set<T1>, compare : (implicit : (T2, T2) -> Order.Order), project : T1 -> T2) : Set<T2>`
- `func max<T>(self : Set<T>) : ?T`
- `func min<T>(self : Set<T>) : ?T`
- `func remove<T>(self : Set<T>, compare : (implicit : (T, T) -> Order.Order), element : T) : ()`
- `func retainAll<T>(self : Set<T>, compare : (implicit : (T, T) -> Order.Order), predicate : T -> Bool) : Bool`
- `func reverseValues<T>(self : Set<T>) : Types.Iter<T>`
- `func reverseValuesFrom<T>(self : Set<T>, compare : (implicit : (T, T) -> Order.Order), element : T) : Types.Iter<T>`
- `func singleton<T>(element : T) : Set<T>`
- `func size<T>(self : Set<T>) : Nat`
- `func toArray<T>(self : Set<T>) : [T]`
- `func toSet<T>(self : Types.Iter<T>, compare : (implicit : (T, T) -> Order.Order)) : Set<T>`
- `func toText<T>(self : Set<T>, toText : (implicit : T -> Text)) : Text`
- `func union<T>(self : Set<T>, other : Set<T>, compare : (implicit : (T, T) -> Order.Order)) : Set<T>`
- `func values<T>(self : Set<T>) : Types.Iter<T>`
- `func valuesFrom<T>(self : Set<T>, compare : (implicit : (T, T) -> Order.Order), element : T) : Types.Iter<T>`
- `type Set<T> = Types.Set.Set<T>`

## Stack

- `func all<T>(self : Stack<T>, predicate : T -> Bool) : Bool`
- `func any<T>(self : Stack<T>, predicate : T -> Bool) : Bool`
- `func clear<T>(self : Stack<T>)`
- `func clone<T>(self : Stack<T>) : Stack<T>`
- `func compare<T>(self : Stack<T>, other : Stack<T>, compare : (implicit : (T, T) -> Order.Order)) : Order.Order`
- `func contains<T>(self : Stack<T>, equal : (implicit : (T, T) -> Bool), element : T) : Bool`
- `func empty<T>() : Stack<T>`
- `func equal<T>(self : Stack<T>, other : Stack<T>, equal : (implicit : (T, T) -> Bool)) : Bool`
- `func filter<T>(self : Stack<T>, predicate : T -> Bool) : Stack<T>`
- `func filterMap<T, U>(self : Stack<T>, project : T -> ?U) : Stack<U>`
- `func find<T>(self : Stack<T>, predicate : T -> Bool) : ?T`
- `func findIndex<T>(self : Stack<T>, predicate : T -> Bool) : ?Nat`
- `func forEach<T>(self : Stack<T>, operation : T -> ())`
- `func fromArray<T>(array : [T]) : Stack<T>`
- `func fromIter<T>(iter : Types.Iter<T>) : Stack<T>`
- `func fromVarArray<T>(array : [var T]) : Stack<T>`
- `func get<T>(self : Stack<T>, position : Nat) : ?T`
- `func isEmpty<T>(self : Stack<T>) : Bool`
- `func map<T, U>(self : Stack<T>, project : T -> U) : Stack<U>`
- `func peek<T>(self : Stack<T>) : ?T`
- `func pop<T>(self : Stack<T>) : ?T`
- `func push<T>(self : Stack<T>, value : T)`
- `func reverse<T>(self : Stack<T>)`
- `func reverseValues<T>(self : Stack<T>) : Iter.Iter<T>`
- `func singleton<T>(element : T) : Stack<T>`
- `func size<T>(self : Stack<T>) : Nat`
- `func tabulate<T>(size : Nat, generator : Nat -> T) : Stack<T>`
- `func toArray<T>(self : Stack<T>) : [T]`
- `func toStack<T>(self : Types.Iter<T>) : Stack<T>`
- `func toText<T>(self : Stack<T>, format : (implicit : (toText : T -> Text))) : Text`
- `func toVarArray<T>(self : Stack<T>) : [var T]`
- `func values<T>(self : Stack<T>) : Types.Iter<T>`
- `type Stack<T> = Types.Stack<T>`

## Text

- `func compare(self : Text, other : Text) : Order.Order`
- `func compareWith(self : Text, other : Text, compare : (Char, Char) -> Order.Order) : Order.Order`
- `func concat(self : Text, other : Text) : Text`
- `func contains(self : Text, p : Pattern) : Bool`
- `func decodeUtf8(self : Blob) : ?Text`
- `func encodeUtf8(self : Text) : Blob`
- `func endsWith(self : Text, p : Pattern) : Bool`
- `func equal(self : Text, other : Text) : Bool`
- `func flatMap(self : Text, f : Char -> Text) : Text`
- `func foldLeft<A>(self : Text, base : A, combine : (A, Char) -> A) : A`
- `func fromArray(a : [Char]) : Text`
- `func fromIter(cs : Iter.Iter<Char>) : Text`
- `func fromVarArray(a : [var Char]) : Text`
- `func greater(self : Text, other : Text) : Bool`
- `func greaterOrEqual(self : Text, other : Text) : Bool`
- `func isEmpty(self : Text) : Bool`
- `func join(self : Iter.Iter<Text>, sep : Text) : Text`
- `func less(self : Text, other : Text) : Bool`
- `func lessOrEqual(self : Text, other : Text) : Bool`
- `func map(self : Text, f : Char -> Char) : Text`
- `func notEqual(self : Text, other : Text) : Bool`
- `func replace(self : Text, p : Pattern, r : Text) : Text`
- `func reverse(self : Text) : Text`
- `func size(self : Text) : Nat`
- `func split(self : Text, p : Pattern) : Iter.Iter<Text>`
- `func startsWith(self : Text, p : Pattern) : Bool`
- `func stripEnd(self : Text, p : Pattern) : ?Text`
- `func stripStart(self : Text, p : Pattern) : ?Text`
- `func toArray(self : Text) : [Char]`
- `func toIter(self : Text) : Iter.Iter<Char>`
- `func toLower(self : Text) : Text`
- `func toText(self : Text) : Text`
- `func toUpper(self : Text) : Text`
- `func toVarArray(self : Text) : [var Char]`
- `func tokens(self : Text, p : Pattern) : Iter.Iter<Text>`
- `func trim(self : Text, p : Pattern) : Text`
- `func trimEnd(self : Text, p : Pattern) : Text`
- `func trimStart(self : Text, p : Pattern) : Text`
- `type Pattern = Types.Pattern`
- `type Text = Prim.Types.Text`

## Time

- `func now() : Time`
- `func toNanoseconds(duration : Duration) : Nat`
- `type Duration = Types.Duration`
- `type Time = Types.Time`
- `type TimerId = Nat`

> No `Time.compare` — use `Int.compare` to compare times.

## Timer

- `func cancelTimer(TimerId) : ()`
- `func recurringTimer<system>(duration : Time.Duration, job : () -> async ()) : TimerId`
- `func setTimer<system>(duration : Time.Duration, job : () -> async ()) : TimerId`
- `type TimerId = Nat`
examples.md›
# Motoko Development Examples

Complete working examples demonstrating Motoko patterns and features.

## Complete Actor Example

A full-featured actor using modern Motoko patterns:

```motoko project=complete-actor filepath=src/backend/main.mo
import Map "mo:core/Map";
import List "mo:core/List";
import Queue "mo:core/Queue";
import Stack "mo:core/Stack";
import Array "mo:core/Array";
import Iter "mo:core/Iter";
import Nat "mo:core/Nat";
import Text "mo:core/Text";
import Principal "mo:core/Principal";

actor {
  // Stable state — types only, values come from the migration chain
  let inventory : Map.Map<Nat, Text>;
  let orders : List.List<Nat>;
  let taskQueue : Queue.Queue<Text>;
  let history : Stack.Stack<Text>;
  let scores : [var Nat];

  // Private helpers
  func formatItem(key : Nat, item : Text) : Text {
    "Item " # key.toText() # ": " # item;
  };

  // Update function with caller
  public shared ({ caller }) func initialize() : async () {
    inventory.add(0, "Init by: " # caller.toText());
    inventory.add(1, "Apple");
    inventory.add(2, "Banana");
    orders.add(100);
    orders.add(200);
    taskQueue.pushBack("task1");
    taskQueue.pushBack("task2");
    history.push("action1");
    scores[0] := 10;
    scores[1] := 20;
  };

  // Query function
  public shared query func getData() : async Text {
    var result = "";

    // Iterate map
    for ((key, value) in inventory.entries()) {
      result := result # formatItem(key, value) # "\n";
    };

    // Process list with chaining
    let largeOrders = orders.values().filter(func x = x > 150).map(func x = x * 2).toArray();
    result := result # "Large orders: " # largeOrders.toText() # "\n";

    result;
  };
};

```

## Principled Architecture Example

Complete example following the architecture pattern:

### types.mo

```motoko project=architecture filepath=src/backend/types.mo
import List "mo:core/List";

module {
  // Entities
  public type UserId = Principal;

  public type User = {
    id : UserId; // Immutable field
    var username : Text; // Mutable field
    var bio : Text;
    var isActive : Bool;
  };

  public type Post = {
    id : Nat; // Immutable field
    author : User; // Immutable field
    var title : Text; // Mutable field
    var content : Text;
    var published : Bool;
  };

  // Shared (immutable) views for the API boundary.
  // User/Post hold `var` fields, so they are NOT shared — never return them directly.
  public type UserView = {
    id : UserId;
    username : Text;
    bio : Text;
    isActive : Bool;
  };

  public type PostView = {
    id : Nat;
    author : UserView;
    title : Text;
    content : Text;
    published : Bool;
  };

};

```

### lib/User.mo

```motoko project=architecture filepath=src/backend/lib/User.mo
import Types "../types";

module {
  public type User = Types.User;

  public func new(id : Types.UserId, username : Text) : User {
    {
      id = id;
      var username = username;
      var bio = "";
      var isActive = true;
    };
  };

  // Dot notation method
  public func updateBio(self : User, newBio : Text) {
    if (newBio.size() > 280) return;
    self.bio := newBio;
  };

  public func ban(self : User) {
    self.isActive := false;
  };

  public func isValid(self : User) : Bool {
    self.username.size() > 0 and self.isActive
  };

  // Immutable projection for the API boundary
  public func toView(self : User) : Types.UserView {
    { id = self.id; username = self.username; bio = self.bio; isActive = self.isActive };
  };
};

```

### lib/Post.mo

```motoko project=architecture filepath=src/backend/lib/Post.mo
import Types "../types";
import UserLib "User";

module {
  public type Post = Types.Post;

  public func new(id : Nat, author : Types.User, title : Text) : Post {
    {
      id;
      author;
      var title = title;
      var content = "";
      var published = false;
    };
  };

  public func publish(self : Post) {
    if (self.content.size() > 0) {
      self.published := true;
    };
  };

  public func setContent(self : Post, content : Text) {
    self.content := content;
  };

  // Immutable projection for the API boundary (UserLib import enables `self.author.toView()`)
  public func toView(self : Post) : Types.PostView {
    {
      id = self.id;
      author = self.author.toView();
      title = self.title;
      content = self.content;
      published = self.published;
    };
  };
};

```

### mixins/Auth.mo

```motoko project=architecture filepath=src/backend/mixins/Auth.mo
import Types "../types";
import UserLib "../lib/User";
import List "mo:core/List";

// In mixins, use {caller} destructuring in the function signature
mixin (users : List.List<Types.User>) {

  func findUser(p : Principal) : ?Types.User {
    users.find(func(u) { u.id == p });
  };

  public shared ({ caller }) func register(username : Text) : async Bool {
    switch (findUser(caller)) {
      case (?_) return false;
      case (null) {
        let newUser = UserLib.new(caller, username);
        users.add(newUser);
        return true;
      };
    };
  };

  public shared query ({ caller }) func getProfile() : async ?Types.UserView {
    switch (findUser(caller)) {
      case (?user) { ?user.toView() };
      case (null) { null };
    };
  };

  public shared ({ caller }) func updateBio(newBio : Text) : async Bool {
    switch (findUser(caller)) {
      case (null) false;
      case (?user) {
        user.updateBio(newBio); // Dot notation!
        true;
      };
    };
  };
};

```

### mixins/Blog.mo

```motoko project=architecture filepath=src/backend/mixins/Blog.mo
import Types "../types";
import PostLib "../lib/Post";
import Iter "mo:core/Iter";
import List "mo:core/List";
import Runtime "mo:core/Runtime";

mixin (
  users : List.List<Types.User>,
  posts : List.List<Types.Post>,
  state : { var nextPostId : Nat },
) {

  public shared ({ caller }) func createPost(title : Text) : async Nat {
    let author = users.find(func(u) { u.id == caller })
      ?? Runtime.trap("User not registered");

    let pid = state.nextPostId;
    state.nextPostId += 1;

    let newPost = PostLib.new(pid, author, title);
    posts.add(newPost);
    pid;
  };

  public shared ({ caller }) func publishPost(postId : Nat) : async Bool {
    let maybePost = posts.find(func(p) { p.id == postId });
    switch (maybePost) {
      case (null) { false };
      case (?post) {
        if (post.author.id != caller) { return false };
        post.publish(); // Dot notation!
        true;
      };
    };
  };

  public query func getAllPosts() : async [Types.PostView] {
    posts.values().map(func(p) { p.toView() }).toArray();
  };
};

```

### mixins/Admin.mo

```motoko project=architecture filepath=src/backend/mixins/Admin.mo
import Types "../types";
import UserLib "../lib/User";
import List "mo:core/List";
import Principal "mo:core/Principal";

mixin (users : List.List<Types.User>, posts : List.List<Types.Post>) {

  // Hardcoded admin (in production, use proper authorization)
  transient let ADMIN = Principal.fromText("aaaaa-aa"); // constant — `transient` keeps it out of stable state

  func isAdmin(caller : Principal) : Bool {
    caller == ADMIN;
  };

  public shared ({ caller }) func adminBanUser(targetId : Principal) : async Bool {
    if (not isAdmin(caller)) return false;

    let target = users.find(func(u) { u.id == targetId });
    switch (target) {
      case (?user) {
        user.ban(); // Dot notation!
        true;
      };
      case (null) { false };
    };
  };

  public query ({ caller }) func getStats() : async {
    userCount : Nat;
    postCount : Nat;
  } {
    if (not isAdmin(caller)) {
      return { userCount = 0; postCount = 0 };
    };
    {
      userCount = users.size();
      postCount = posts.size();
    };
  };
};

```

### main.mo

```motoko project=architecture filepath=src/backend/main.mo
import List "mo:core/List";
import Types "types";
import AuthMixin "mixins/Auth";
import BlogMixin "mixins/Blog";
import AdminMixin "mixins/Admin";

actor Main {

  let users : List.List<Types.User>;
  let posts : List.List<Types.Post>;
  let state : { var nextPostId : Nat };

  include AuthMixin(users);
  include BlogMixin(users, posts, state);
  include AdminMixin(users, posts);
};

```

### migrations/20260101_000000.mo

The first migration supplies the initial values. `OldActor = {}` because no prior version exists. Types are inlined — migration files may only import from `mo:core/...`. See `migrating-motoko-actors` for full rules.

```motoko
import List "mo:core/List";
import Principal "mo:core/Principal";

module {
  // Inlined copies of Types.User / Types.Post (migration files cannot import project types)
  type User = {
    id : Principal;
    var username : Text;
    var bio : Text;
    var isActive : Bool;
  };

  type Post = {
    id : Nat;
    author : User;
    var title : Text;
    var content : Text;
    var published : Bool;
  };

  type OldActor = {};

  type NewActor = {
    users : List.List<User>;
    posts : List.List<Post>;
    state : { var nextPostId : Nat };
  };

  public func migration(_ : OldActor) : NewActor {
    {
      users = List.empty();
      posts = List.empty();
      state = { var nextPostId = 0 };
    };
  };
};

```

## Iterator Examples

### Basic Iteration

```motoko project=iterators filepath=src/backend/main.mo
import Array "mo:core/Array";
import Iter "mo:core/Iter";
import Nat "mo:core/Nat";
import Bool "mo:core/Bool";

actor {
  let numbers : [Nat];

  public query func demonstrateIterators() : async Text {
    var output = "";

    // Map and filter with chaining
    let doubled = numbers.values().map(func x = x * 2).filter(func x = x > 10).toArray();
    output := output # "Doubled > 10: " # doubled.toText() # "\n";

    // Convert to iterator, chain, convert back
    let processed = numbers.values().map(func x = x * 3).filter(func x = x % 2 == 0).toArray();
    output := output # "Processed: " # processed.toText() # "\n";

    // Fold
    let sum = numbers.values().foldLeft(0, func(acc, x) = acc + x);
    output := output # "Sum: " # sum.toText() # "\n";

    // Find
    switch (numbers.find(func x = x > 5)) {
      case (?found) {
        output := output # "Found: " # found.toText() # "\n";
      };
      case (null) {};
    };

    // Any / All
    let hasLarge = numbers.any(func x = x > 8);
    let allPositive = numbers.all(func x = x > 0);
    output := output # "Has large: " # hasLarge.toText() # "\n";
    output := output # "All positive: " # allPositive.toText() # "\n";

    output;
  };
};

```

### Custom Iterator

```motoko project=custom-iterator filepath=src/backend/main.mo
import Iter "mo:core/Iter";

actor {
  // Fibonacci iterator
  func fibonacci(n : Nat) : Iter.Iter<Nat> {
    var count = 0;
    var prev = 0;
    var curr = 1;

    object {
      public func next() : ?Nat {
        if (count >= n) return null;
        count += 1;

        if (count == 1) return ?0;
        if (count == 2) return ?1;

        let next = prev + curr;
        prev := curr;
        curr := next;
        ?prev;
      };
    };
  };

  public query func getFibonacci() : async [Nat] {
    fibonacci(10).toArray();
  };
};

```

## Map Examples

### Complex Key Types

```motoko project=complex-key filepath=src/backend/main.mo
import Map "mo:core/Map";
import Order "mo:core/Order";
import Text "mo:core/Text";
import Int "mo:core/Int";
import Iter "mo:core/Iter";

actor {
  type Point = { x : Int; y : Int };

  // Module with compare for automatic inference
  module Point {
    public func compare(a : Point, b : Point) : Order.Order {
      switch (Int.compare(a.x, b.x)) {
        case (#equal) { Int.compare(a.y, b.y) };
        case (other) { other };
      };
    };
  };

  // Stable state — initial value comes from the migration chain
  let pointMap : Map.Map<Point, Text>;

  public func addPoint(x : Int, y : Int, pointLabel : Text) : async () {
    pointMap.add({ x = x; y = y }, pointLabel); // Point.compare inferred!
  };

  public query func getPoint(x : Int, y : Int) : async ?Text {
    pointMap.get({ x; y });
  };

  public query func getAllPoints() : async [(Point, Text)] {
    pointMap.entries().toArray();
  };
};

```

### Map Transformation

```motoko project=map-transform filepath=src/backend/main.mo
import Map "mo:core/Map";
import Nat "mo:core/Nat";
import Text "mo:core/Text";
import Iter "mo:core/Iter";
import Order "mo:core/Order";

actor {
  public type Score = {
    name : Text;
    score : Nat;
  };

  module Score {
    public func compare(score1 : Score, score2 : Score) : Order.Order {
      Nat.compare(score1.score, score2.score);
    };
  };

  // Stable state — initial value comes from the migration chain
  let scores : Map.Map<Text, Nat>;

  public func addScore(score : Score) : async () {
    scores.add(score.name, score.score);
  };

  public query func getTopScores(threshold : Nat) : async [Score] {
    let filteredScores = scores.entries().filterMap(
      func((name, score)) {
        if (score > threshold) {
          ?{ name; score };
        } else {
          null;
        };
      }
    );
    filteredScores.sort().toArray();
  };

  public query func doubleAllScores() : async [Score] {
    scores.entries().map(func((name, score)) { { name; score = score * 2 } }).toArray();
  };
};

```

### Safe Division Pattern

<!-- motoko-check:skip -->

```motoko
import Runtime "mo:core/Runtime";
import someModule "../lib/someModule";

actor {
  public func safeDivide(a : Nat, b : Nat) : async Nat {
    if (b == 0) {
      Runtime.trap("Division by zero is not defined");
    } else {
      (a / b);
    };
  };

  // Inter-canister calls that trap will cause the entire function to trap
  public func callOtherCanister() : async Text {
    try {
      // If someModule.method() traps, this will trap too, so you need to wrap it in try catch
      let result = await someModule.method();
    } catch (error) {
      "Canister call failed. ";
    };
  };
};

```

## Timer Example

```motoko project=timer filepath=src/backend/main.mo
import Timer "mo:core/Timer";
import Time "mo:core/Time";
import List "mo:core/List";

actor {
  // Stable state — initial values come from the migration chain
  let logs : List.List<(Int, Text)>;
  var timerId : Nat;

  func logEvent(message : Text) {
    logs.add((Time.now(), message));
  };

  public func startPeriodicCleanup() : async () {
    timerId := Timer.recurringTimer<system>(
      #seconds(3600), // Every hour
      func() : async () {
        let now = Time.now();
        let oneHourAgo = now - 3_600_000_000_000; // 1 hour in nanoseconds

        // Remove old logs
        let newLogs = logs.filter(func((timestamp, logText)) { timestamp > oneHourAgo });
        logs.clear();
        logs.addAll(newLogs.values());
        logEvent("Cleanup completed");
      },
    );
  };

  public func stopPeriodicCleanup() : async () {
    Timer.cancelTimer(timerId);
  };

  public query func getLogs() : async [(Int, Text)] {
    logs.toArray();
  };
};

```

These examples demonstrate real-world Motoko patterns and can be adapted for various use cases.

## Full-Stack Example: Motoko to Frontend

This example shows the complete round-trip from a Motoko backend to the generated TypeScript bindings to frontend usage. Always follow this pattern: write backend first, then use the generated `backend.d.ts` as the source of truth for frontend code.

### Motoko Backend (src/backend/main.mo)

```motoko project=fullstack filepath=src/backend/main.mo
import List "mo:core/List";
import Principal "mo:core/Principal";
import Time "mo:core/Time";

actor Main {

  type TodoItem = {
    id : Nat;
    title : Text;
    completed : Bool;
    createdAt : Int;
    owner : Principal;
  };

  // Stable state — initial values come from src/backend/migrations/*.mo
  let todos : List.List<TodoItem>;
  var nextId : Nat;

  public shared ({ caller }) func addTodo(title : Text) : async Nat {
    let id = nextId;
    nextId += 1;
    todos.add({
      id = id;
      title = title;
      completed = false;
      createdAt = Time.now();
      owner = caller;
    });
    id;
  };

  public shared query ({ caller }) func getMyTodos() : async [TodoItem] {
    todos.filter(func(t) { t.owner == caller }).toArray();
  };

  public shared ({ caller }) func toggleTodo(todoId : Nat) : async Bool {
    switch (todos.find(func(t) { t.id == todoId and t.owner == caller })) {
      case (?todo) {
        let idx = switch (todos.findIndex(func(t) { t.id == todoId })) {
          case (?i) { i };
          case (null) { return false };
        };
        todos.put(idx, { todo with completed = not todo.completed });
        true;
      };
      case (null) { false };
    };
  };
};

```

### Migration (src/backend/migrations/20260101_000000.mo)

```motoko
import List "mo:core/List";
import Principal "mo:core/Principal";

module {
  // Inlined copy of TodoItem — migration files cannot import project types
  type TodoItem = {
    id : Nat;
    title : Text;
    completed : Bool;
    createdAt : Int;
    owner : Principal;
  };

  type OldActor = {};

  type NewActor = {
    todos : List.List<TodoItem>;
    var nextId : Nat;
  };

  public func migration(_ : OldActor) : NewActor {
    {
      todos = List.empty();
      var nextId = 0;
    };
  };
};

```

references/control-flow.md›
# Control Flow

Reference for Motoko control flow patterns. Load when you need `??`, `do ?`, switch, or loop syntax.

## Null Coalesce (`??`) — prefer this for `?T`

`e1 ?? e2` unwraps `e1` when it is `?v`, otherwise evaluates `e2` (lazily). Prefer it over a two-arm `switch` that only unwraps or supplies a default.

Requires `moc >= 1.7.0`.

```motoko
// Default when absent
let name = optName ?? "anonymous";

// Trap when null means a bug / invariant break
let value = map.get(key) ?? Runtime.trap("Key not found");

// Nested options — chain instead of nested switches
let start = event.start.dateTime ?? event.start.date ?? "";

// A block on the RHS needs `do`
let n = opt ?? do { let x = 1; x };

// A record literal on the RHS needs parens
let rec = opt ?? ({ x = 0 });
```

Do **not** use `??` when the `?v` arm transforms the value, runs side effects, or matches variants — keep `switch` for those.

## Option Chaining (`do ? { ... }`)

Inside a `do ? { ... }` block, postfix `!` unwraps an option. If any `!` hits `null`, the **whole block** short-circuits to `null`. Use it when several lookups must all succeed and you want one combined result — `??` only handles a single option at a time.

```motoko
// Every step must succeed; any null makes cityOf return null
func cityOf(id : Text) : ?Text {
  do ? { users.get(id)!.city! }
};

// `!` composes with ordinary computation inside the block
func nameAndCity(id : Text) : ?Text {
  do ? { nick.get(id)! # " of " # cityOf(id)! }
};
```

`!` is only legal inside `do ? { ... }`. Using it anywhere else is an error:

```text
type error [M0064], misplaced '!' (no enclosing 'do ? { ... }' expression)
```

Reach for `do ?` over nested `switch`es when unwrapping several options; reach for `??` when there is one option and a default.

## Switch Statements

Use `switch` for variants, multi-way matches, and option arms that are not plain unwrap/default:

```motoko
// Variant matching
type Status = { #active; #inactive; #pending : Text };
switch (status) {
  case (#active) { "User is active" };
  case (#inactive) { "User is inactive" };
  case (#pending(reason)) { "Pending: " # reason };
};

// Value matching
switch (statusCode) {
  case (200) { "OK" };
  case (404) { "Not Found" };
  case _ { "Unknown" };
};

// Option with a transform or side effect on the Some arm — keep switch
switch (users.get(caller)) {
  case (?u) { u.isAdmin };
  case null { false };
};
```

## For Loops

```motoko
// Iterate Map entries
for ((key, value) in map.entries()) {
  // use key and value
};

// Iterate List
for (item in list.values()) {
  // use item
};

// Iterate Array
for (score in scores.values()) {
  total += score;
};
// Most of the time for Arrays you can use .foldLeft() or .map() instead.

```

## Break and Continue

`break` and `continue` work as in most other languages: `break` leaves the enclosing loop, `continue` skips to its next iteration. Both are available in `for`, `while`, and `loop`:

```motoko
for (item in items.values()) {
  if (item.archived) { continue };
  if (item.id == targetId) {
    result := ?item;
    break;
  };
};

while (true) {
  switch (iter.next()) {
    case (?item) { total += item.score };
    case null { break };
  };
};
```

Alternatively, refactor to a helper function with early `return` when that reads better than a loop with an early exit.
references/equality.md›
# Equality and Comparison

Load when choosing between `==`, `equal`, and `compare`, or when a `.equal(...)` call fails with M0070.

## `==` vs `equal`

**`==` compares two values; `equal` and `compare` are functions you can pass.** Collections need the function form, so write it for the records and variants you use as keys or elements. For a direct comparison of primitives or shared fields, `==` is fine — and on `Nat`, `Int`, `Float`, and the sized int types it is the only receiver form available, where `a == b` is shorter than `Nat.equal(a, b)` and needs no import.

`==` is compiler-generated structural equality, and it only exists for **shared** types. That is the catch: a single `var` field takes a record out of shared, and `==` stops compiling:

```motoko
type Todo = { id : Nat; var completed : Bool };
a == b
// type error [M0060], operator is not defined for operand types
```

Internal state records routinely have `var` fields, so code written around `==` breaks the moment a field becomes mutable. `equal`/`compare` functions do not have that failure mode, which is why record and variant comparisons belong in them rather than in `==`.

`equal` and `compare` are also what **collections** take, as implicit arguments: `Map`, `Set`, `contains`, and the collection-level `equal`/`compare` helpers. The compiler infers them, so you rarely name them:

```motoko
let map = Map.empty<Nat, Text>(); // compare resolved at add/get, from the imported Nat
numbers.contains(3);              // likewise Nat.equal
```

Inference finds `equal`/`compare` in the module imported for the element type, so the import is what makes it work — without `import Nat`, you get M0230. Passing the module's own function explicitly is redundant and warns:

```motoko
friends.contains(p);                  // CORRECT
friends.contains(Principal.equal, p); // WRONG (M0237)
```

Name a function only when you want **different** behaviour from the module default — a case-insensitive match, a reversed order:

```motoko
names.contains(func (x, y) = x.toLower() == y.toLower(), q);
```

## Which types allow receiver `.equal` / `.compare`

The general dot-notation rule applies: a receiver call works only when the module declares the function with a `self` parameter. `Text.equal` is `(self : Text, other : Text)`, so `a.equal(b)` resolves. `Nat.equal` is `(x : Nat, y : Nat)` — no `self`, so it does **not**.

| Type | `a.equal(b)` | `a.compare(b)` | Module form |
|---|---|---|---|
| `Text`, `Principal`, `Bool`, `Char`, `Blob` | yes | yes | also fine |
| `Order` | yes | **no such function** | `Order.equal(a, b)` only |
| `Nat`, `Int`, `Float` | **no** | **no** | `Nat.equal(a, b)` |
| `Nat8`…`Nat64`, `Int8`…`Int64` | **no** | **no** | `Nat64.equal(a, b)` |

`mo:core/Order` has no `compare` in any form — `Order.compare(a, b)` is M0072 (`field compare does not exist`), not just a missing receiver.

Calling the receiver form on a numeric type fails:

```motoko
myNat.equal(other)   // WRONG
// type error [M0070], expected object type, but expression produces type Nat

Nat.equal(myNat, other)  // CORRECT — or just: myNat == other
```

This is the one place where "always use dot notation" does not hold, and it is worth remembering: numeric types **do** support other receiver methods (`myNat.toText()` is correct), just not `equal` and `compare`.

## Your own records, tuples, and variants

Nothing is derived for them. A record or variant used as a `Map`/`Set` key needs a `compare` the compiler can find, or you get:

```text
type error [M0230], Cannot determine implicit argument `compare`
```

**Record `compare` must be an explicit function.** There is no sensible default — which field dominates, and in what direction, is a decision only you can make. Write it out and be deliberate about the tie-breaking:

```motoko
type Point = { x : Nat; y : Nat };
module Point {
  public func compare(a : Point, b : Point) : Order.Order {
    switch (Nat.compare(a.x, b.x)) {
      case (#equal) { Nat.compare(a.y, b.y) }; // x first, then y
      case other { other };
    }
  };
};
```

Put it in the module named after the type and inference will find it, exactly as it finds `Nat.compare`.

**Custom variants need both `equal` and `compare` written out.** `mo:core` types are the exception — `Result` already ships them:

```motoko
a.equal(b, Nat.equal, Text.equal); // Result.equal, sub-functions for Ok and Err
```

For a one-off equality check on an immutable record, tuple, or variant, `==` still works and is fine — the guidance above is about the functions collections need, and about not building on `==` for types whose fields may become `var`.
references/project-setup.md›
# Project Setup: Compiler Flags

**Read this only when you are setting up a Motoko project yourself.** These are one-time `mops.toml` settings, not something to revisit while writing code.

**If your platform manages `mops.toml` for you, skip this file entirely** — do not inspect, add, or change `[moc] args`. The flags below are already set on your behalf, and editing them is not yours to do. This is the normal case for hosted platforms; it is only self-managed projects that need anything here.

## Persistence

Enhanced orthogonal persistence is `moc`'s default, so a top-level `let`/`var` in an actor is stable without the `stable` keyword. What is **not** default is letting a plain `actor { ... }` be persistent:

```toml
[moc]
args = ["--default-persistent-actors"]
```

Every actor example in this skill assumes that flag. Without it a plain `actor` fails to compile, with one of two errors depending on whether it holds state:

```text
// actor { var count = 0 }
type error [M0219], this declaration is currently implicitly transient, please declare it explicitly `transient`

// actor { public func f() : async Nat { 1 } }  — no stable declaration to complain about
type error [M0220], this actor or actor class should be declared `persistent`
```

If you cannot set the flag, write `persistent actor { ... }` instead — same semantics, declared per actor. (`persistent` is transitional; actors become persistent-by-default in a future major `moc` release.) `--default-persistent-actors` is not listed in `moc --help`, but it is supported.

## Style warnings

The style rules this skill enforces are compiler warnings that are **off by default**. Enabling them makes `moc` flag violations for you, and `mops check --fix` then auto-corrects all three:

```toml
[moc]
args = ["--default-persistent-actors", "-W", "M0236,M0237,M0223"]
```

`M0236` non-dot-notation calls, `M0237` redundant explicit implicit arguments, `M0223` redundant type instantiation.

Without `-W` in `[moc] args` these never fire, so `mops check --fix` has nothing to correct — the rules still hold, you just have to follow them unaided.
references/reserved-keywords.md›
# Reserved Keywords

Motoko's reserved words. **None** of these may be used as an identifier — not as a variable, parameter, function, type, field, or label name. Check a name against this list before declaring it, especially when a domain term happens to collide (`query`, `label`, `system`, `object`, `class`, `type`, and `in` are the ones that bite most often).

```text
actor        and          assert       async        await
break        case         catch        class        composite
continue     debug        debug_show   do           else
false        finally      flexible     for          from_candid
func         if           ignore       implicit     import
in           include      label        let          loop
mixin        module       not          null         object
or           persistent   private      public       query
return       shared       stable       switch       system
throw        to_candid    transient    true         try
type         var          while        with
```

`async*`, `await*`, and `await?` are also reserved. They cannot collide with an identifier anyway, since `*` and `?` are not identifier characters.

Using a reserved word as an identifier is a parse error at the declaration:

```text
syntax error [M0001], unexpected token '<name>', expected one of token or <phrase> sequence: ...
```

Rename the colliding term rather than relying on position or inferred meaning — there is no escaping or quoting mechanism. Conventional renames: `query` → `request` / `searchTerm`, `label` → `caption` / `tag`, `type` → `kind` / `category`, `object` → `item` / `entity`, `class` → `group` / `kind`.

## Not reserved

These read like keywords but are ordinary identifiers in Motoko — several are Candid keywords rather than Motoko ones, which is the usual source of confusion:

```text
blob    bool    char    int     nat     opt     record  service
struct  variant vec     enum    match   state   result  status
```
references/type-conversions.md›
# Type Conversions

Reference for Motoko numerical type conversions. Load when you need to convert between `Nat`, `Int`, and their sized variants.

**Every conversion is spelled `to`, on the source value.** Widening and narrowing are both receiver calls; `Module.fromX` is deprecated. Do not write `Nat8.fromNat64(n)` even where it still compiles — write `n.toNat8()`.

## Nat to Int

```motoko
let natValue = 42;
let intValue = natValue.toInt();
let backToNat = Int.abs(intValue); // Only if non-negative

```

## Nat Size Conversions

```motoko
let nat8 : Nat8 = 255;
let nat16 = nat8.toNat16();
let nat32 = nat16.toNat32();
let nat64 = nat32.toNat64();
let backToNat8 = nat64.toNat8(); // Narrow — traps on overflow

```

Conversion chain: `Nat8 → Nat16 → Nat32 → Nat64` (widen) and back (narrow). Both directions are `toXX` on the value.

## Int Size Conversions

```motoko
let int8 : Int8 = -128;
let int16 = int8.toInt16();
let int32 = int16.toInt32();
let int64 = int32.toInt64();
let backToInt8 = int64.toInt8(); // Narrow — traps on overflow

```

Conversion chain: `Int8 → Int16 → Int32 → Int64` (widen) and back (narrow). Both directions are `toXX` on the value.

## Common Conversion Patterns

```motoko
// Nat to Text
let text = myNat.toText(); // dot notation

// Int to Text
let text = myInt.toText(); // dot notation

// Text to Nat/Int (returns optional) — receiver form on the Text
let maybeNat = "42".toNat(); // ?Nat
let maybeInt = "-5".toInt(); // ?Int

// Nat to Float
let f = myNat.toFloat();

// Int to Float
let f = myInt.toFloat();

// Time is Int — use Int conversions
let timestamp = Time.now(); // Int (nanoseconds)
let milliseconds = timestamp / 1_000_000;

```
SKILL.md›
---
name: writing-motoko
description: >-
  Motoko language reference, architecture patterns, and dependency tooling
  (mops). Load when writing or modifying backend .mo files.
version: 0.2.9
compatibility:
  toolchain:
    moc: ">=1.11.2"
    mops: "3.x"
  mops:
    core: ">=2.6.0"
caffeineai-subscription: [none]
---

# Writing Motoko

Motoko is an under-represented language for the Internet Computer Protocol, so your pre-training data is likely to be outdated — always favour this skill and its documentation for the most up-to-date information.

## Critical Requirements

**NEVER use these:**

- `stable` keyword -- Not needed in enhanced orthogonal persistence mode
- `mo:base` library -- Deprecated. Use `mo:core` instead
- `.vals()` -- The deprecated `mo:base` iterator name. Always `.values()`. On arrays `.vals()` still compiles, so nothing flags it; on core collections it fails with M0072
- `system func preupgrade/postupgrade` -- Not needed with enhanced orthogonal persistence
- `(with migration = ...)` actor-attached migration syntax -- Use the mops-managed migration chain in `migrations/`
- Inline initializers on stable actor fields -- Initial values come from the migration chain (see `migrating-motoko-actors`)
- Module function style for `self` parameters -- Don't write `List.add(list, item)` or `Map.get(map, key)`
- Manual field-by-field record copying for immutable records -- Use record spread (`{ self with ... }`). For records with `var` fields, do not use record spread; mutate the `var` field directly or rebuild the record explicitly.
- Single-file monolithic actors -- Use the multi-file architecture: types.mo, lib/, mixins/, main.mo
- Stable state in a `mixin` block -- a bare `let`/`var` is silently stable and traps at runtime (`IC0503`). Pass state in as a parameter and keep constants in a module
- Any Motoko reserved keyword as a declared identifier -- Before writing, check parameter, variable, function, type, field, and label names against the full list in [references/reserved-keywords.md](references/reserved-keywords.md). `query` and `label` are reserved and must never be identifiers. Rename a colliding domain term instead of relying on its position or inferred meaning.
- Type annotations on an inline `func` passed as a **call argument** -- write `xs.filter(func x = x > 1)`, not `xs.filter(func(x : Nat) : Bool { x > 1 })`. The call supplies the types. If a generic cannot be inferred, instantiate the call (`map<In, Out>`), never the lambda. This applies only in argument position — named declarations still carry full signatures. **One exception:** keep `: async ()` on an async callback (`func() : async () { ... }`) — it is what makes the body async, and removing it fails with M0096

**ALWAYS use:**

- `mo:core` library version 2.6.0+ (compiler `moc` 1.11.2+)
- Contextual dot notation -- `list.add(item)`, `map.get(key)`
- An import of the key type's module in every file that operates on a `Map`/`Set` -- the implicit `compare` is resolved from the imported module (`import Nat "mo:core/Nat"` for a `Map.Map<Nat, _>`), never from the type alone. A missing key-module import is the usual cause of M0230; a record or variant key needs its own module with a `compare` (see Implicit Parameters)
- Null coalesce `??` for unwrap-or-default and unwrap-or-trap (`opt ?? default`, `opt ?? Runtime.trap(...)`) -- prefer over a two-arm `switch` on `?T` (requires `moc >= 1.7.0`)
- Plain `break` / `continue` to exit or skip a loop iteration -- they work inside `for`, `while`, and `loop` just like in other languages
- Enhanced orthogonal persistence (state persists without `stable` keyword)
- Principled Motoko Architecture -- `types.mo` (types), `lib/` (domain logic), `mixins/` (API endpoints), `main.mo` (composition root, NO public methods)
- **API reference for uncertain APIs**: Use [api-reference.md](api-reference.md) to verify exact method signatures when you are about to use an unfamiliar `mo:core` API or when a compile diagnostic points at an API mismatch. It lists only non-deprecated APIs — a symbol that is not there should not be written. Do NOT guess API shapes — a targeted lookup of a symbol you are unsure about is always worth the step; skipping it to save steps ships hallucinated APIs and costs far more in compile repair.

**When encountering compilation errors:** Re-check [api-reference.md](api-reference.md) for exact method signatures.

**Before changing actor state shape, introducing new stable fields, or upgrading canisters:** load `migrating-motoko-actors`. This guidance assumes the **mops-managed migration chain** — when a change requires a migration, it goes in the pending migration file, or a new one in `src/backend/migrations/` if none is pending. Introducing stable state for the first time always needs one (no inline initializers); trivial stable-compatible upgrades do not. See the skill. If a migration or compatibility diagnostic still does not match what the source says, or a migration file cannot be written, load `troubleshooting-motoko-migrations`.

## Toolchain (mops)

All configuration is in `mops.toml`. Only consult https://docs.mops.one/ if you encounter an unfamiliar mops error.

### Dependency management

- Never hand-edit dependency entries in `mops.toml`, and never touch `mops.lock`; use the `mops` CLI so dependency metadata and the lockfile stay atomic. (`[toolchain]` has a CLI too: `mops toolchain use <tool> [version]`.)
- Leave `[moc] args` alone. Compiler flags are a one-time project-setup concern, and many platforms own `mops.toml` and set them for you — do not inspect or change them while writing code. If you are setting up a project yourself, see [references/project-setup.md](references/project-setup.md).
- `mops add <pkg>` installs and exact-pins a published package. Use `@x.y.z` for a specific version, `<url>[#ref]` for GitHub, `./path` for a local package, and `--dev` for development dependencies.
- `mops add` accepts exactly one package name. To install several packages, chain one-package commands with `&&`; never run multiple `mops add` invocations in parallel — they race on `mops.toml` and `mops.lock`.
- `mops update [pkg]` updates a package and rewrites its exact pin.
- `mops sync` reconciles imports after bulk `.mo` changes by adding missing dependencies and removing unused ones.
- `mops.lock` is rewritten only by `mops add`, `mops update`, `mops sync`, `mops install`, and related supported mops commands.
- On a lock or integrity failure, run `mops install` — it regenerates a `mops.lock` that is missing, stale, or inconsistent with `mops.toml`. `mops verify` reports a file-hash mismatch it cannot repair; `mops cache clean` forces a verified re-download. Never `chmod`, remove, or text-edit `mops.lock`.

### Check and build

- **`mops install`** — Install dependencies and reconcile `mops.lock`, regenerating it when it is missing or no longer matches `mops.toml`.
- **`mops check --fix`** (fast — use for iteration) — Reports compile errors and auto-fixes the style warnings, where the project has them enabled (dot-notation, redundant type instantiation, redundant implicit arguments). Follow this skill's rules whether or not `--fix` enforces them. Exit 0 = success. Error format: `file:startLine.startCol-endLine.endCol: severity [code], message`. Iterate on this until it passes.
- **`mops build`** (slow — run ONCE at the end) — Produces the compiled `.wasm` and the candid interface file `.did`. Use only as final verification after `mops check --fix` passes; never put `mops build` inside the fix loop. The `.did` file drives generated client bindings — never edit it manually.

If `mops check --fix` fails: read stderr first. Do NOT call `moc` directly. Fix `.mo` source and rerun the check.

## Modern Motoko Features

### Contextual Dot Notation

**RULE:** When a function has a `self` parameter, ALWAYS use dot notation.
Dot notation is still type-specific: it only applies to APIs that the value's
module actually defines — verify against [api-reference.md](api-reference.md)
rather than inferring JavaScript-style helpers. `.some(...)` and `.every(...)`
do not exist in Motoko; the `mo:core` names are `.any(...)` and `.all(...)`.

The module a dot call resolves against is the module that **defines** the
function — usually the receiver's type's module (`map.get`, `list.add`), but
sometimes a different one: `arr.values().toList()` resolves against `List` (the
target), not the array's module. The import needed (if any) is the defining
module's, not the receiver's.

```motoko
map.get(key);
list.add(item);
array.filter(func x = x > 0); // CORRECT
Map.get(map, key);
List.add(list, item); // WRONG (M0236)

// Chaining
let doubled = numbers.map(func x = x * 2).filter(func x = x > 10);

```

Conversions are receiver calls too, but the `toX` functions are split across
modules: some are defined on the **source** module (`Nat8.toNat`), others on the
**target** (`"42".toNat()` and `"-5".toInt()` are defined by `Nat` and `Int`,
not `Text`). So `Text`-receiver conversions need the target imported (`import
Nat "mo:core/Nat"`, `import Int "mo:core/Int"`); without it, moc reports
M0070/M0072 and the call does not compile:

```motoko project=dot-notation filepath=src/backend/main.mo
import Principal "mo:core/Principal";
import Nat "mo:core/Nat";
import Text "mo:core/Text";

func conversions(caller : Principal, myNat : Nat) {
  ignore caller.toText();            // CORRECT
  ignore myNat.toText();             // CORRECT
  ignore "42".toNat();               // CORRECT (defined by Nat, imported above)
  ignore "hello".concat(" world");   // CORRECT
  ignore Principal.toText(caller);   // WRONG (M0236)
  ignore Nat.toText(myNat);          // WRONG (M0236)
};
```

**`equal` / `compare` vs `==`.** Collections take `equal` and `compare` as implicit arguments, so those are the functions to write for your own records and variants. `==` is compiler-generated structural equality and exists only for **shared** types — one `var` field takes a record out of shared and `==` stops compiling (M0060) — so do not build record comparisons on it. Comparing primitives and shared fields directly with `==` is fine, and on `Nat`, `Int`, `Float`, and the sized int types it is the only form: those declare `equal(x, y)` without a `self` parameter, so `myNat.equal(other)` fails with M0070. Other receiver methods on those types (`myNat.toText()`) are fine.

Your own records and variants get nothing derived — a record `compare` must be an explicit function, and custom variants need both `equal` and `compare` written out. See [references/equality.md](references/equality.md).

### Mixins

Composable actor services with granular state injection. Each mixin lives in its own file as a top-level `mixin` block:

```motoko project=mixin filepath=src/backend/types.mo
module {
  public type User = {
    principal : Principal;
    username : Text;
  };
};
```

```motoko project=mixin filepath=src/backend/mixins/Auth.mo
import List "mo:core/List";
import Principal "mo:core/Principal";
import Types "../types";

mixin (users : List.List<Types.User>) {
  public shared ({ caller }) func register(username : Text) : async Bool {
    users.add({ principal = caller; username });
    true
  };

  public query func listUsers() : async [Types.User] {
    users.toArray()
  };
};
```

```motoko project=mixin filepath=src/backend/main.mo
import List "mo:core/List";
import Types "types";
import AuthMixin "mixins/Auth";

actor {
  let users : List.List<Types.User>;
  include AuthMixin(users);
};
```

**Mixin Anti-Patterns — NEVER generate these:**

```motoko
// WRONG — mixin is NOT a function inside a module; wrapping in module {} is invalid
module {
  public func createMixin(state : ...) : actor { ... } { // M0001: unexpected token 'actor'
    actor { public func foo() { ... }; };
  };
}

// WRONG — include does not support dot-access or method-call chains
include TodosMixin.createMixin(state); // M0001: unexpected token '.'

// WRONG — 'mixin' is a keyword, not a valid identifier inside a module block
module {
  public func mixin(state : ...) { ... }; // M0001: unexpected token 'mixin'
}
```

Rules:
- A mixin file contains a bare `mixin (params) { ... };` block at the **top level** — not inside `module {}`, not returned from a function.
- `include` takes a bare name followed by arguments: `include MixinName(args)` — no dot-access, no chained calls.

**No stable state in Mixins.** Every top-level `let`/`var` in a `mixin` is implicitly **stable**. Only `transient` is ever allowed, but prefer putting static definitions (like literals) into modules instead!

**Sharing state between mixins — pass it as a parameter.** To share state between two or more mixins, declare that state once as an actor field and pass that same binding to each `include`. Every mixin that gets it reads and writes the same value. A mixin can take several parameters, so it can receive shared state plus its own private state.

```motoko
// types.mo:  public type GoogleState = { var connection : ?Conn; var config : ?Cfg };
let google : Types.GoogleState;          // declared once; initialized in the migration function
let bookings : Map.Map<Nat, Booking>;    // BookingsApi's own state
include GoogleApi(google);               // gets `google`
include BookingsApi(google, bookings);   // gets the SAME `google`, plus its own bookings
```

Pass the same binding to each mixin. Never build a new record at the `include` — that gives each mixin its own separate copy, so one mixin's writes never reach the others:

```motoko
include GoogleApi({ var connection = google.connection });   // WRONG: NEVER DO THIS!
```

### Null Coalesce (`??`)

Prefer `??` over a two-arm `switch` that only unwraps an option or supplies a default / trap. Requires `moc >= 1.7.0`.

```motoko
// Default when absent
let name = optName ?? "anonymous";

// Fail-fast unwrap — null means a bug / missing invariant
let user = users.find(func u = u.id == caller)
  ?? Runtime.trap("User not found");

// Nested options — chain instead of nested switches
let start = event.start.dateTime ?? event.start.date ?? "";

// RHS is lazy. A block needs `do`; a record literal needs parens:
let n = opt ?? do { let x = 1; x };
let rec = opt ?? ({ x = 0 });
```

**Use `switch` instead** when the `?v` arm transforms the value, runs side effects, or you are matching variants / multiple cases — `??` only unwraps or substitutes.

```motoko
// Keep switch: Some arm transforms / branches on the inner value
switch (users.get(caller)) {
  case (?u) { u.isAdmin };
  case null { false };
};

switch (result) {
  case (#ok value) { value };
  case (#err e) { Runtime.trap(e) };
};
```

See [references/control-flow.md](references/control-flow.md).

### Implicit Parameters

`Map` and `Set` operations take the comparison function as an **implicit** argument. `Map.empty()` itself takes no arguments — the comparator is resolved at the operations that need it (`add`, `get`, `remove`, …), not at construction.

Inference works by finding a `compare` in the module imported **for the key type**. So the import is what makes it work:

```motoko
import Map "mo:core/Map";
import Nat "mo:core/Nat"; // this import is what supplies Nat.compare

let map = Map.empty<Nat, Text>();
map.add(5, "hello"); // compare resolved from the imported Nat
```

Without `import Nat`, the same code fails — the type is known, but there is no module to take `compare` from:

```text
type error [M0230], Cannot determine implicit argument `compare` of type (Nat, Nat) -> Order
note: Did you mean to import mo:core/Int or mo:core/Nat?
```

Do **not** pass the comparator explicitly when it can be inferred; that is M0237, which `mops check --fix` removes:

```motoko
let ages = Map.empty<Text, Nat>();   // Text.compare resolved at add, from the imported Text
ages.add("Alice", 30);               // CORRECT
ages.add(Text.compare, "Alice", 30); // WRONG (M0237)
```

A custom key type works the same way — give its module a `compare` and it is inferred:

```motoko
type Point = { x : Nat; y : Nat };
module Point {
  public func compare(a : Point, b : Point) : Order.Order { ... };
};
let points = Map.empty<Point, Text>();
points.add({ x = 1; y = 2 }, "A"); // Point.compare inferred
```

Type instantiation on `empty()` follows the usual rule — needed only when the binding is unannotated. `let m : Map.Map<Nat, Text> = Map.empty();` infers it, and `Map.empty<Nat, Text>()` there would be M0223.

## Architecture Pattern

```text
backend/
├── types.mo         # Central schema, state definitions
├── lib/             # Domain logic (stateless modules with self pattern)
├── mixins/          # Service layer (stateless, state injected via parameters)
├── types/           # Type definitions for mixins and lib modules
├── migrations/      # Mops-managed migration chain. See migrating-motoko-actors.
│                    #   Each file is YYYYMMDD_HHMMSS.mo (a UTC timestamp, not a feature name); applied files are FROZEN.
└── main.mo          # Composition root (state owner, NO public methods)
```

## Import Path Conventions

Paths are **relative to the importing file**. No `.mo` extension, no `/lib.mo` suffix.

```motoko
// From main.mo
import Types "types";
import AuthMixin "mixins/Auth";
import UserLib "lib/User";
// From lib/*.mo or mixins/*.mo
import Types "../types";
import UserLib "../lib/User";
// Core library — always absolute
import Map "mo:core/Map";

// WRONG — these all cause M0009
import Types "types.mo";
import Types "types/lib.mo";
import Types "backend/types";

```

**Migration files** (`migrations/*.mo`) must be self-contained — they may only import from `mo:core/...`, never from `../types` or any project module. See `migrating-motoko-actors` for the full rules.

### The Actor Must Come Last

Imports and `type`/`let` declarations may precede the actor. Nothing may follow it — the actor is the file's result, so a trailing declaration makes the actor a non-`()` statement and fails with M0096 (`expression of type actor {...} cannot produce expected type ()`). Prefer keeping shared types in `types.mo` regardless.

### Import Hygiene

Add an import only to the file that uses the imported identifier. `Time.now()` usually belongs in a domain `lib/*.mo` implementation file, so `import Time "mo:core/Time";` belongs in that file, not `main.mo`, unless `main.mo` itself calls `Time.now()`. Every capitalized namespace call must have a matching import in the same file: if a mixin calls `TodosLib.listTodos(...)`, the file must import `TodosLib "../lib/todos"` (or use the alias it actually imported). Treat unused-import warnings as failures: remove stale `Debug`, `Time`, or helper-module imports before finishing.

## Query Functions

`query` marks a public function as a read-only call: it executes fast and unreplicated, and **every state change it makes is silently discarded when the call completes** — a write inside a query compiles, runs, and vanishes with no error or warning. Declare pure reads as `query func`; any function that must persist a change is a plain update func (no `query`). `public query func` is shorthand for `public shared query func`; both forms take `({ caller })` the same way.

```motoko
public query func getPosts() : async [Types.PostView] { ... };          // read: query
public shared ({ caller }) func addPost(t : Text) : async Nat { ... };  // persists: update
public query func resetAll() : async () { posts.clear() };              // WRONG: compiles, but the clear is discarded
```

### When await is allowed

A plain `query func` cannot call any other canister function, whether that callee is a query or an update. Writing `await someCall()` inside one fails with a paired `M0038` (misplaced await) + `M0188` (send capability required: "cannot call a `shared` function from a `query` function"), always on the same statement. Pick the function kind by what the body must call:

| Body must call                          | Declare                                 | Can `await`                              |
| --------------------------------------- | --------------------------------------- | ---------------------------------------- |
| another canister's `query`/`composite query` | `public shared composite query func` | those query callees                     |
| an update (`shared` func) or oneway     | a normal `public shared func`           | that update                              |
| nothing across canisters                | `public shared query func`              | nothing                                  |

A `composite query` is a read-only function that can `await` other canisters' queries. Loop over callees and `await` each:

```motoko
public shared composite query func sum(counters : [Counter]) : async Nat {
  var total = 0;
  for (counter in counters.values()) {
    total += await counter.peek();
  };
  total
};
```

A `composite query` can call `query` and `composite query` callees but not updates or other `shared` functions; awaiting an update there is `M0187` ("send capability required ... only calls to `query` and `composite query` functions are allowed"). If the body must `await` an update, no flavor of query works — make it an update func.

A composite query can only be initiated as an ingress call, e.g. from a frontend — calling one from an update or oneway func is `M0186`, from a plain `query func` `M0188`. Within the call tree it composes: it may call other canisters' `query`/`composite query` functions.

## Shared Types

Public functions accept/return only **shared types** (serializable):

- Shared: `Nat`, `Int`, `Text`, `Bool`, `Principal`, `Blob`, `Float`, `[T]`, `?T`, records, variants
- **Not shared**: Functions, `var` fields, objects, `Map`, `Set`, `List`, `Queue`, `Stack`

If internal state uses mutable containers, define a separate immutable public type for the API boundary:

```motoko
public type PostInternal = { id : Nat; likedBy : Set.Set<Principal> }; // internal
public type Post = { id : Nat; likedBy : [Principal] }; // shared

public func toPublic(self : Types.PostInternal) : Types.Post {
  { self with likedBy = self.likedBy.toArray() };
};

```

## Collections

For full API signatures, read [api-reference.md](api-reference.md).

```motoko
import Map "mo:core/Map";
import List "mo:core/List";
import Queue "mo:core/Queue";
import Stack "mo:core/Stack";
import Array "mo:core/Array";
import Set "mo:core/Set";

```

**Map** (B-tree, O(log n)): `Map.empty<K, V>()`, `.add(k, v)`, `.get(k) → ?V`, `.remove(k)`, `.entries()`
**List** (growable array, O(1) access): `List.empty<T>()`, `.add(item)`, `.get(i) → ?T`, `.at(i) → T` (traps on OOB)
**Queue** (FIFO): `Queue.empty<T>()`, `.pushBack(item)`, `.popFront() → ?T`
**Stack** (LIFO): `Stack.empty<T>()`, `.push(item)`, `.pop() → ?T`
**Array**: `[var 0, 0, 0]` (mutable), `[1, 2, 3]` (immutable)
**Set** (B-tree, O(log n)): `Set.empty<T>()`, `.add(item)`, `.contains(item)`, `.remove(item)`

**Warning**: Never call `list.add()` inside a `retain` callback. Use `mapInPlace` to update items in place.

```motoko
todos.mapInPlace(
  func(todo) {
    if (todo.id == targetId) { { todo with completed = not todo.completed } } else {
      todo;
    };
  }
);

```

**Important**: Always use opaque type aliases (`List.List<T>`, `Map.Map<K, V>`, `Set.Set<T>`) in type declarations. Never use raw internal structure or `.filter`, `.map()` won't resolve (M0072).

When a domain helper receives a core collection, type the parameter as the concrete opaque collection type (e.g. `todos : List.List<Types.Todo>`) and import that module in the helper file. Do not use structural method-record parameters such as `{ add : (Types.Todo) -> (); toArray : () -> [Types.Todo] }` for core collection values. A compiler error saying `List.List<T>` cannot produce an expected type with fields like `add`, `toArray`, or `clear` means the helper signature is wrong; fix the signature to `List.List<T>` and keep the collection — do not switch to an invented module such as `mo:core/Buffer`, and do not regress to module-function calls like `List.toArray(todos)` or `List.add(todos, todo)`.

### Arrays vs Core Collections

Core collections (`List.List<T>`, `Map.Map<K, V>`, `Set.Set<T>`, `Queue.Queue<T>`, `Stack.Stack<T>`) have receiver helpers because their modules define self-parameter APIs. A value of type `[T]` or `[var T]` is an array snapshot, not a `List.List<T>`.

- After `let snapshot = list.toArray()`, only use array operations whose exact signatures are shown here or verified in the API reference — with receiver dot notation: `snapshot.filter(pred)`, `snapshot.map(mapper)`, `snapshot.sort(comparator)`, `snapshot.concat([item])`. Do not call those as module functions such as `Array.filter<T>(snapshot, pred)` or `Array.append(snapshot, [item])`.
- If a value is an array (`[T]`) or came from `.toArray()` / `.filter(...)`, then `.map(...)` already returns an array; do not append `.toArray()` to that array-map result. (`List.List<T>.map(...)` returns a `List`, so it still needs `.toArray()` when the caller expects an array.)
- Arrays DO support predicate search: `.find(predicate) : ?T`, `.findIndex(predicate) : ?Nat`, `.any(predicate)`, and `.all(predicate)` are all in `mo:core/Array` (see the API reference). The JS spellings `.some(...)` / `.every(...)` do not exist — use `.any` / `.all`.
- Arrays DO have `.contains(element)` (`equal` is implicit, so pass only the element). Reach for `.indexOf(element)` when you need the position — it returns `?Nat`, so keep the option and use it; and for `.any(pred)` when membership is decided by a predicate rather than equality:

```motoko
// Overlap between two tag arrays
let matched = leftTags.any(func left = rightTags.any(func right = left == right));
```

- Do not copy a collection just to search it: prefer `templates.find(func ...)` on the original `List.List<T>` over `templates.toArray().find(func ...)` — the intermediate array is a wasted copy.
- Use `.values()` when iterating array snapshots. Do not write `.vals()` in new Motoko code.

**CRUD List patterns:** Do not invent helpers on `List`. There is no `filterInPlace`, and record spread fails on records with `var` fields.

**An inline `func` passed as a call argument takes no type annotations.** The call already fixes the parameter and result types, so annotating repeats them and lets them drift as the code changes. Use the expression form `func x = <expr>`:

```motoko
todos.find(func todo = todo.id == targetId);            // CORRECT
todos.find(func(todo : Types.Todo) : Bool { todo.id == targetId }); // WRONG: annotated
```

This is about **argument position only**. A named declaration still carries its full signature, and a lambda bound on its own has nothing to infer from — `let f = func x = x > 1` fails with M0103 (`cannot infer type of variable`).

```motoko
public func toView(t : Types.Todo) : Types.TodoView { ... }; // annotated, as always
```

When the types are not obvious to a reader, or a generic cannot be inferred, say it **on the call** rather than on the lambda — it reads better and keeps one source of truth:

```motoko
photos.map(func p = { id = p.id; url = p.url.toText() }); // inferred — preferred
photos.map<PhotoInternal, Photo>(func p = { ... });       // when M0098 demands it
```

Add `<In, Out>` only when the compiler actually reports M0098; adding it when inference already succeeded is M0223 (redundant type instantiation).

The one exception is a callback that must return `async`. There `: async ()` is load-bearing — it is what makes the body async, and there is no unannotated form (`func() = async { ... }` does not work either). Without it the lambda infers `() -> ()` and the call fails with M0096:

```motoko
Timer.recurringTimer<system>(#seconds(3600), func() : async () { cleanup() });
```

```motoko
// Toggle a mutable field by finding the record and mutating the var field.
switch (todos.find(func todo = todo.id == targetId)) {
  case (?todo) {
    todo.completed := not todo.completed;
    ?toView(todo);
  };
  case null { null };
};

// Delete from List by rebuilding from an array snapshot.
var removed = false;
let snapshot = todos.toArray();
todos.clear();
for (todo in snapshot.values()) {
  if (todo.id == targetId) {
    removed := true;
  } else {
    todos.add(todo);
  };
};
removed;

// To change an immutable field on a record that also has var fields, rebuild it.
let updated : Types.Todo = {
  id = todo.id;
  text = newText;
  var completed = todo.completed;
  createdAt = todo.createdAt;
};
let snapshot = todos.toArray();
todos.clear();
for (todo in snapshot.values()) {
  if (todo.id == targetId) {
    todos.add(updated);
  } else {
    todos.add(todo);
  };
};
```

For delete-style operations that return whether a record was removed, prefer a `var removed = false` flag while rebuilding from the array snapshot. Do not call `todos.size()` unless the parameter type explicitly exposes `size()`, such as `List.List<T>`.

### Iteration and Chaining

```motoko
let doubled = numbers.map(func x = x * 2).filter(func x = x > 10);
let sum = scores.filter(func s = s > 15).foldLeft(0, func(acc, s) = acc + s);
switch (numbers.find(func n = n > 5)) {
  case (?found) { /* use */ };
  case null {};
};

```

### Sorting Arrays

`Array`/array receiver helpers such as `.sort(...)` return a value. Do not use them as standalone sequenced statements; Motoko rejects sequencing a non-`()` expression.

```motoko
let all = todos.toArray();
let sorted = all.sort(func (a, b) =
  if (a.createdAt > b.createdAt) { #less }
  else if (a.createdAt < b.createdAt) { #greater }
  else { #equal }
);
sorted.map(func todo = {
  id = todo.id; text = todo.text; completed = todo.completed; createdAt = todo.createdAt
});

// WRONG: `.sort(...)` returns an array, so this is not a valid statement.
all.sort(func (a, b) = Int.compare(b.createdAt, a.createdAt));
all.map(func todo = { ... });
```

### `contains` vs `find`

- **`contains(element)`** -- equality check on `List`/`Set`/etc. Does NOT take a predicate.
- **`find(predicate)`** -- predicate search on `List.List<T>` and `[T]`. Returns `?T`.
- Both `List.List<T>` and `[T]` have `contains`. Use `.any(func x = ...)` when the test is a predicate, not equality.

```motoko
numbers.contains(3); // equal inferred from the imported Nat
friends.contains(p); // likewise from Principal — passing Principal.equal here is M0237
todos.find(func todo = todo.id == targetId); // returns ?Todo
// WRONG: friends.contains(func(f) { f == p })  → M0096/M0103

```

### Text Search and Case Folding

Motoko `Text` uses contextual receiver methods for case folding and substring checks. Do not use JavaScript spellings such as `.toLowerCase()` or `.toLowercase()`, and do not call `Text.contains(...)` for ordinary substring search.

```motoko
let term = searchTerm.toLower();
textValue.toLower().contains(#text term)
```

### Joining Text

`join` takes the **iterator as its receiver and the separator as its argument** — easy to invert. Use dot notation; the module form is an M0236 violation that `mops check --fix` rewrites for you.

```motoko
["a", "b"].values().join(", ");     // CORRECT → "a, b"
Text.join(["a", "b"].values(), ", "); // WRONG (M0236)
```

Note the receiver is an **iterator**, not an array: call `.values()` on an array first.

### Variant Tag Arguments

Always parenthesize a variant tag's argument. A tag binds only to the atom immediately after it, tighter than any operator, so an unparenthesized argument silently loses everything past the first term:

```motoko
#tag(n + 1) // CORRECT
#tag n + 1  // WRONG: parses as (#tag n) + 1 → M0060, operator is not defined for operand types
```

### Explicit Type Instantiation

Let inference work first. With unannotated lambdas the compiler resolves `.map()` to a different type on its own, so write the plain call:

```motoko
let photos = internalPhotos.map(
  func p = { id = p.id; url = p.url; uploadedBy = p.uploadedBy.toText() }
);
```

Add explicit type parameters **only** when the compiler reports M0098 (`no best choice for type parameter`):

```motoko
let photos = internalPhotos.map<PhotoInternal, Photo>(func p = { ... });
```

Adding them when inference already succeeded is a warning of its own — M0223, redundant type instantiation — which `mops check --fix` strips. Annotating the lambda instead of instantiating the call is always wrong.

### Function Literals as Arguments

Do NOT put a semicolon after a function body passed as an argument:

```motoko
list.filter(func(item) { item.id != targetId }) // CORRECT
list.filter(func(item) { item.id != targetId; }) // WRONG: trailing semicolon makes the block return `()`

```

Do not inline imperative statement blocks as boolean operands:

```motoko
// WRONG: parser can treat the block after `or` as an invalid expression shape.
let matches = titleMatches or {
  var found = false;
  for (tag in tags.values()) {
    if (tag == q) { found := true };
  };
  found
};

// CORRECT: compute the loop result before the final boolean expression.
var tagMatches = false;
for (tag in tags.values()) {
  if (tag == q) { tagMatches := true };
};
let matches = titleMatches or tagMatches;
```

Every `switch` case must be separated with a semicolon before the next `case`, even in compact one-line switches:

```motoko
switch (pricing) { case (#free) { true }; case (#paid(_)) { false }; } // CORRECT
switch (pricing) { case (#free) { true } case (#paid(_)) { false } } // WRONG
```

### Declaration Terminators

Top-level and nested function declarations inside `module`, `actor`, and `mixin` blocks must end with `;`. A missing `};` after a function commonly surfaces as a syntax error near the next declaration, e.g. `unexpected token 'public'`.

### Local Mutability

Use `let` for local bindings unless the variable is reassigned with `:=`. Never use `var` for a local binding only because the value it references is mutable. Mutating an object through methods such as adding to a collection does not require the binding itself to be `var`; use `let` for collection builders and other accumulator objects unless the binding is later reassigned.

### Safe Nat Arithmetic

Avoid `Nat` subtraction unless the compiler can prove the result is non-negative at the operation itself. `a - b` traps when `b > a`, and the compiler can still warn when safety depends on a previous branch. Prefer bounds checks, bounded addition, loop counters, or helper branches that do not subtract one `Nat` from another.

## Option Handling

**Prefer `??` for unwrap-or-default and unwrap-or-trap.** Do not write a nested `switch` solely to peel `?T`.

```motoko
// Unwrap with trap when null means something is wrong
let user = users.find(func u = u.id == caller)
  ?? Runtime.trap("User not found");

// Default when absence is fine
let caption = optLabel ?? "(untitled)"; // not `label` — reserved word

// Only return ?T when absence is a normal, expected outcome
public query func findUserByName(name : Text) : async ?User {
  users.find(func u = u.name == name);
};

// Keep switch when the Some arm maps / mutates / has side effects
switch (todos.find(func todo = todo.id == targetId)) {
  case (?todo) {
    todo.completed := not todo.completed;
    ?toView(todo);
  };
  case null { null };
};
```

## Error Handling: `Result`

Use `mo:core/Result` to return a failure a caller can act on. `Result<Ok, Err>` is `{ #ok : Ok; #err : Err }`, so it crosses the API boundary as Candid whenever `Ok` and `Err` are themselves shared, which for `Ok` usually means the view type, not the internal record.

**Pick the return type by what the failure means:**

| The call can fail because…                          | Return                 |
| --------------------------------------------------- | ---------------------- |
| the caller did something the caller can fix         | `Result<Ok, Err>`      |
| the thing simply is not there, and that is normal   | `?T`                   |
| an invariant this code is responsible for is broken | trap (`Runtime.trap`)  |

```motoko
import Result "mo:core/Result";

public type BookingError = {
  #slotTaken : { until : Time.Time };
  #notAuthorized;
  #unknownRoom : Nat;
};

public shared ({ caller }) func book(roomId : Nat, at : Time.Time) : async Result.Result<Booking, BookingError> {
  // ...
};
```

**Never launder an error into `Text`.** `Result<Booking, Text>` forces every caller — including the frontend — to string-match to tell "slot taken" from "not authorized". Make `Err` a variant; put the data each failure needs inside its own tag. A `Text` payload is fine *inside* a tag when it is a message for a human, not a discriminator.

**Do not trap on caller error.** A trap rolls back the whole message and reaches the frontend as an opaque reject — the caller cannot branch on it and the user gets no actionable message. Reserve traps for "this cannot happen" (see `?? Runtime.trap(...)` above).

**Chain, do not nest.** `mapOk`, `mapErr`, and `chain` take `self`, so they are dot notation like every other self-parameter API and a pipeline stays flat. `Result.fromOption` has no `self` — it is the module-call bridge from `?T` at the edge where absence becomes a caller-visible error.

```motoko project=result-chain filepath=src/backend/main.mo
import Result "mo:core/Result";
import Map "mo:core/Map";
import Nat "mo:core/Nat";

actor {
  type Room = { id : Nat; name : Text };
  type RoomView = { name : Text };
  type BookingError = { #unknownRoom : Nat; #notAuthorized };

  let rooms : Map.Map<Nat, Room>;

  func toView(room : Room) : RoomView = { name = room.name };
  func reserve(room : Room) : Result.Result<Room, BookingError> = #ok(room);

  public shared ({ caller }) func book(roomId : Nat) : async Result.Result<RoomView, BookingError> {
    Result.fromOption(rooms.get(roomId), #unknownRoom(roomId))
      .chain(func room = reserve(room))
      .mapOk(toView);
  };
};
```

Use `switch` on `#ok` / `#err` when the arms do different work; do not write `isOk`/`isErr` followed by an unwrap — that discards the payload the type was carrying.

## Common Patterns

### Module with Self Pattern

```motoko
// lib/User.mo
module {
  public type User = Types.User;
  public func new(id : Principal, name : Text) : User {
    { id; var name; var isActive = true };
  };
  public func ban(self : User) { self.isActive := false };
};
// Usage: user.ban(); -- dot notation!

```

### Record Spread with `with`

**RULE:** Use record spread for immutable records. Never use record spread on a record type that contains `var` fields; Motoko rejects that with `base has non-aliasable var field`.

```motoko
{ self with newField = "" }; // CORRECT for immutable records

// CORRECT for a record type containing var fields:
let updated : Types.Todo = {
  id = todo.id;
  text = newText;
  var completed = todo.completed;
  createdAt = todo.createdAt;
};

{ todo with text = newText }; // WRONG if Todo contains any var field

```

### State Definition

Entity types live in `types.mo`. State fields as direct actor bindings — no `AppState` wrapper.

Stable actor fields are declared with **types only — no initializers** (initial values come from the migration chain). Transient fields use initializers as usual.

```motoko
// types.mo
module {
  public type User = {
    id : Principal;
    var username : Text;
    var isActive : Bool;
  };
};
```

```motoko
// main.mo
actor {
  let users : List.List<Types.User>;
  let state : { var nextPostId : Nat };
  include AuthMixin(users);
};

```

### Mutable State for Mixins

Never declare `var` actor-fields (e.g. `var nextPostId : Nat`) you intend to share with mixins — `var` parameters are passed by value, so the mixin's mutations don't propagate back. Wrap mutables in a record and pass the record; records are shared by reference. In the actor, declare the record type-only (`let state : { var nextPostId : Nat };`) — its initial value (e.g. `{ var nextPostId = 0 }`) comes from the migration chain, like every stable field.

Preserve the exact field names on shared mutable state records across actor, mixin, and helper modules. If the actor declares `let state : { var nextId : Nat }` and the mixin receives `state`, helper parameters must accept `{ var nextId : Nat }` and update `state.nextId`. Do not rename the field to `val` or `counter` in helper signatures, and do not create wrapper copies like `{ var val = state.nextId }`; the copy mutates only itself and leaves actor state unchanged.

### Transient State & Static/Module Fields

Enhanced orthogonal persistence makes every top-level `let`/`var` in an actor or mixin **stable** (persisted across upgrades) by default — there is no `stable` keyword. Prefix a binding with `transient` to keep it OUT of stable storage; it is re-initialized on every (re)start instead of being persisted. Use it for anything that isn't durable state — caches, capability handles, and constants.

**Constants** — Motoko has no `const`, and a bare `let X = ...` in an actor or mixin is stable state. Put a fixed value in a **module** when its right-hand side is a **static** expression (namespaced, reusable, never state); otherwise keep it as `transient let` in the actor/mixin:

```motoko
transient let admin = Principal.fromText("..."); // non-static (a call) — can't be a module `let`
transient let cache = Map.empty<Text, User>();   // derived; rebuilt after each upgrade
```

**Static** (what a module `let` field allows) = literals, variant tags (`#x`), options (`?x`), tuples, immutable arrays and records, function values, and imported/variable names — plus `.field` projection over those. **Non-static** = function calls, operators (`+`, `==`, `#`), control flow (`if`/`switch`/loops), and array indexing (`a[i]`).

## Numeric Conversion Hygiene

Treat deprecation warnings as failures. **Every conversion is spelled `to`, on the source value** — never a `Module.fromX` call, and never a chain through the sized numeric modules. A conversion is one receiver call:

```motoko
import Nat "mo:core/Nat";

let average = sum.toFloat() / count.toFloat(); // Nat.toFloat
```

| Instead of                | write             |
| ------------------------- | ----------------- |
| `Float.fromInt(i)`        | `i.toFloat()`     |
| `Float.fromInt64(i)`      | `i.toFloat()`     |
| `Nat.fromNat64(n)`        | `n.toNat()`       |
| `Int.fromNat(n)`          | `n.toInt()`       |
| `Nat64.fromNat(n)`        | `n.toNat64()`     |
| `Blob.fromArray(bytes)`   | `bytes.toBlob()`  |
| `Iter.fromArray(a)`       | `a.values()`      |

A conversion that needs several hops is a sign the wrong function was picked: verify the exact `mo:core` signature in [api-reference.md](api-reference.md), which lists only non-deprecated APIs.

## Security and Authorization

Every public update function MUST verify the caller via `{caller}` destructuring. Enforce authorization on the backend — never trust client-side checks.

Attaching cycles to an inter-canister call (`await (with cycles = ...) <call>`) hands them to the callee, so treat any endpoint that can trigger one as spend authority: gate it on the caller, bound the amount, and never let an unauthenticated path reach it. Some platforms forbid outbound cycles entirely — follow the hosting platform's own guidance where it applies.

## Common Compile Error Patterns

| Error pattern                                          | Cause                        | Fix                                         |
| ------------------------------------------------------ | ---------------------------- | ------------------------------------------- |
| `field append does not exist`                          | Array.append removed         | receiver `.concat(...)`                     |
| `field put does not exist`                             | Map.put renamed              | `.add()`                                    |
| `field delete is deprecated`                           | Map.delete renamed           | `.remove()`                                 |
| `field toLowerCase does not exist`                     | JS Text API spelling         | `.toLower()`                                |
| `field toLowercase does not exist`                     | JS Text API spelling         | `.toLower()`                                |
| `You can use the dot notation ... contains`            | Wrong Text contains shape    | `text.toLower().contains(#text term)`       |
| `operator may trap for inferred type Nat`              | Potentially unsafe Nat math  | Avoid `Nat` subtraction; use bounds/loops   |
| `Int cannot produce expected type Nat`                 | Int/Nat mismatch             | `.toNat()`                                  |
| `field fromX is deprecated`                            | Deprecated `fromX` conversion | The `toX` counterpart on the source value: `n.toFloat()`, `bytes.toBlob()` |
| `syntax error, unexpected token '.'`                   | Missing parens               | `#text (searchTerm.toLower())`              |
| `syntax error, unexpected token ','`                   | Missing parens in for        | `for ((key, value) in map.entries())`       |
| `Compatibility error [M0170]`                          | Missing migration            | Load `migrating-motoko-actors`            |
| `M0250` initialized stable field                       | Initializer on a stable actor field | Declare it type-only; move the value into the migration's `NewActor` |
| `M0254` / `M0267` initial actor requires field         | Stable field no migration supplies | Add it to the pending migration's `NewActor` |
| `M0255` stable signature downgrade                     | Chain or migrations config removed | Restore it — enhanced migration is one-way; load `troubleshooting-motoko-migrations` |
| `shared function has non-shared parameter/return type` | Mutable type in API          | Return `[T]` not `List<T>`, no `var` fields |
| `send capability required`                             | Async in non-async (`async*`/local non-shared target) | Add `<system>` capability                   |
| M0038 misplaced await + M0188 send capability (paired) | `await <call>` inside a plain `query func` | Make it a `composite query func` (queries) or a plain update func (updates) |
| `M0187` send capability in a composite query           | calling/awaiting an update from a `composite query func` | Make it a plain update func                |
| `M0186` composite send capability required             | calling a `composite query func` from a non-composite func | Only ingress calls initiate composite queries; call it from the frontend, or make the callee a plain `query` |
| `unexpected token '<name>'` at an identifier declaration | Reserved word used as an identifier | Rename it consistently across its contract and callers; see [references/reserved-keywords.md](references/reserved-keywords.md) |
| `unexpected token 'public'` after a function           | Missing declaration `;`      | End function declarations with `};`         |
| `M0219` implicitly transient                           | Actor not persistent         | Write `persistent actor`; see [references/project-setup.md](references/project-setup.md) |
| `M0220` actor should be declared `persistent`          | Actor not persistent         | Write `persistent actor`; see [references/project-setup.md](references/project-setup.md) |
| `M0218` redundant `stable` keyword                     | `stable` under EOP           | Remove `stable` — a plain `let`/`var` is already stable |
| `M0064` misplaced `'!'`                                | `!` outside an option block  | Wrap in `do ? { ... }`                      |
| `M0145` `does not cover value`                         | Non-exhaustive switch        | Add the missing cases or a `case _`         |
| `M0060` operator not defined for `{#tag : T}`          | Unparenthesized variant tag  | `#tag(x)`, never `#tag x`                   |
| `M0060` operator not defined, on `==`                  | `==` on a record with a `var` field (not shared) | Use an `equal` function instead |
| `M0230` cannot determine implicit argument `compare`   | Key type's module not in scope | Usually a missing import: `import` the key type's module (`Nat`, `Text`, …) in that file. For a record/variant key, add `compare` to the type's own module |
| `M0070` expected object type, produces `Nat`           | Receiver `.equal`/`.compare` on a number | Use `==` or `Nat.equal(a, b)`   |
| `M0096` actor cannot produce expected type `()`        | Declaration after the actor  | The actor must be the last declaration in the file |
| `field compare does not exist` on Time                 | No Time.compare              | Use `Int.compare`                           |
| `unexpected token ';'` in function call                | Semicolon after func literal | Remove `;` before `)`                       |
| `unbound variable X`                                   | Missing import               | `import X "mo:core/X"`                      |
| `M0098` no best choice for type param                  | Generic needs explicit types | `list.map<In, Out>(...)`                    |
| `M0096` on `contains` callback                         | Predicate passed to contains | `contains` takes an element; for a predicate use `.any(pred)` for a Bool, `.find(pred)` for the element |
| `M0009` import file does not exist                     | Wrong path                   | Relative, no `.mo` extension                |
| `M0244 variable ... is never reassigned`               | Unneeded `var` binding       | Use `let` unless reassigned with `:=`       |

## Quick Reference

**Basic Types:** `Nat` `Int` `Text` `Bool` `Principal` `?T` `[T]` `[var T]` `Blob` `Float` — `Time.now()` returns `Int` (nanoseconds)

**Common Operations:** `debug_show(value)` → Text | `assert condition` | `# "text"` concatenation | `break` / `continue` inside `for`, `while`, `loop`

| Structure | Use Case         | Key Operations     | Complexity  |
| --------- | ---------------- | ------------------ | ----------- |
| Map       | Key-value pairs  | get, add, remove   | O(log n)    |
| List      | Growable array   | add, get, at       | O(1) access |
| Queue     | FIFO processing  | pushBack, popFront | O(1)        |
| Stack     | LIFO processing  | push, pop          | O(1)        |
| Array     | Fixed collection | index, map, filter | O(1) access |
| Set       | Unique values    | contains, add      | O(log n)    |

## Best Practices

1. Always `mo:core`, never `mo:base`
2. No `stable` keyword — enhanced orthogonal persistence handles state
3. Dot notation for all `self`-parameter functions
4. Unwrap with `??` (`opt ?? Runtime.trap(...)` or `opt ?? default`); reserve `switch` for transforms/side effects/variants; `?T` only when absence is expected
5. types.mo / lib/ / mixins/ / main.mo structure
6. Mixins receive only needed state slices
7. Queries for read-only, updates for state changes
8. Iterator chaining to avoid intermediate collections
9. Record spread `{ self with ... }` for immutable records; mutate or rebuild records that contain `var` fields
10. No inline initializers on stable actor fields — initial values come from the migration chain
11. Inline `func` arguments carry no type annotations (except `: async ()` on async callbacks); instantiate the call instead, and only when the compiler reports M0098

## Additional Resources

- **Control flow**: [references/control-flow.md](references/control-flow.md) — `??`, `do ? { ... }` option chaining, switch statements, loops, `break` / `continue`
- **Reserved keywords**: [references/reserved-keywords.md](references/reserved-keywords.md) — full list to check identifiers against
- **Equality & comparison**: [references/equality.md](references/equality.md) — which types support receiver `.equal`, and when `==` differs from `equal`
- **Type conversions**: [references/type-conversions.md](references/type-conversions.md) — Nat/Int size conversions
- **Project setup**: [references/project-setup.md](references/project-setup.md) — one-time `[moc] args` flags. Skip this if your platform manages `mops.toml`
- **Design review**: Load `reviewing-motoko` when reviewing, auditing, or refactoring existing `.mo` files — type-encoded invariants, state/persistence discipline, and file structure
- **Actor migrations**: Load `migrating-motoko-actors` when upgrading canisters or changing actor state shape
- **Migration failures**: Load `troubleshooting-motoko-migrations` for unexplained compatibility diagnostics, frozen migration files, or converted legacy projects
- **API signatures**: [api-reference.md](api-reference.md) — complete function signatures
- **Complete examples**: [examples.md](examples.md) — full working code samples