diff --git a/.docs-plan/motoko-repo-sync-proposal.md b/.docs-plan/motoko-repo-sync-proposal.md deleted file mode 100644 index 61de5b70..00000000 --- a/.docs-plan/motoko-repo-sync-proposal.md +++ /dev/null @@ -1,1070 +0,0 @@ -# Proposal: Transform-free Motoko docs sync - -**Context:** `docs.internetcomputer.org` syncs Motoko language documentation from -`caffeinelabs/motoko` as a git submodule. Currently a 200-line bash script -(`sync-motoko.sh`) plus a 300-line Node.js post-processor (`postprocess-motoko.mjs`) -are needed on every release to: flatten numbered directories, strip numeric prefixes, -convert Docusaurus-specific syntax to Starlight syntax, rewrite relative links to -match the flattened structure, and expand file-embed code blocks. - -The goal is to reach a state where syncing is just a file copy: no structural -transformation, no syntax conversion, no link rewriting needed. - ---- - -## Problems with the current setup - -### 1. Numbered directories and files - -``` -fundamentals/ - 1-basic-syntax/ - 1-defining-an-actor.md - 8-functions.md ← same slug as types/3-functions.md after stripping - 3-types/ - 3-functions.md ← collision! both flatten to "functions.md" -``` - -Numeric prefixes encode ordering in Docusaurus (which uses `_category_.yml`). -Starlight uses `sidebar: { order: N }` frontmatter instead, so the prefix -serves no purpose once the files are in Starlight. Removing the prefixes and -using frontmatter order avoids the collision problem and removes the need to -strip prefixes during sync. - -### 2. Docusaurus-specific frontmatter - -```yaml -sidebar_position: 8 # Docusaurus -``` - -Starlight uses: - -```yaml -sidebar: - order: 8 -``` - -`sidebar_position` is silently ignored by Starlight, leaving all pages in -undefined (alphabetical) order until the consuming site explicitly enumerates -them in its sidebar config. - -### 3. Docusaurus file-embed syntax - -```` -```motoko file=../examples/counter.mo#L1-L30 -``` -```` - -This site has a `remark-include-file` plugin that runs at build time and handles -`file=` syntax. Both historical gaps have been resolved on the developer-docs -side: - -- **Line-range slicing**: the plugin now supports `#L-L` suffixes. Of - the file-embed blocks in the Motoko source, roughly 9 use line ranges and 38 - embed whole files — both forms now work. -- **Path incompatibility**: synced files land in `docs/languages/motoko/...` while - examples stay in `.sources/motoko/doc/md/examples/`. The `` - placeholder bridges this: `postprocess-motoko.mjs` rewrites `../examples/` → - `/` at sync time, and `remark-include-file` resolves the - placeholder to the examples directory inside the pinned submodule at build time. - -The upstream change (Proposed Change §3 below) makes this bridge permanent by -adopting `` paths directly in the source, after which the sync-time -rewrite becomes a no-op. - -### 4. Links to retired portal URLs - -Many files reference `internetcomputer.org/docs/...`, which is the retired -DFINITY portal. The sync post-processor maintains a rewrite table to map these -to internal developer-docs paths, but that table needs manual updates with -every Motoko release. - -### 5. `base/` and `core/` library links - -Several files link to `./base/.md` or `./core/.md` — both -excluded sections. These are post-processed to `https://mops.one/core/docs/` -because `mo:base` is deprecated in favour of `mo:core`. Using the mops.one URL -directly in the source removes the need for this rewrite. - -The `core/` directory (49 files: `Array.md`, `Map.md`, etc.) is auto-generated -from `caffeinelabs/motoko-core` using `mo-doc` as a separate CI step in the -motoko repo. Once all `./core/.md` links are replaced with mops.one -URLs, the generated `doc/md/core/` directory is no longer needed in the docs -tree and the CI generation step can be dropped from the motoko repo. - -### 6. Docusaurus-specific aside types - -``` -:::info ← ~21 occurrences in synced sections (60+ across full doc/md tree) -:::warn ← 1 occurrence in synced sections -:::info [Link](url) ← link in aside title (Starlight titles are plain text) -``` - -Starlight supports `:::note`, `:::tip`, `:::caution`, `:::danger`, and -`:::warning` (the full word). It does NOT support `:::info` (renders as plain -text) or `:::warn` (the shortened form — also renders as plain text). The -post-processor maps `:::info` → `:::note` and `:::warn` → `:::caution`. Aside -titles that are markdown links (`:::info [Iter](url)`) are also rewritten to -strip the URL (Starlight titles cannot contain links). - -**Important distinction:** `:::warning` (full word) IS a valid Starlight type -(rendered as `:::caution`). Only `:::warn` (three-letter shorthand) is invalid -in Starlight. The source currently uses both — `:::warn` appears once -(`fundamentals/3-types/12-advanced-types.md:235`) and `:::warning` appears twice -(`fundamentals/3-types/9-mutable-arrays.md:89`, `12-base-core-migration.md:31`). -Only `:::warn` needs to be replaced; `:::warning` is already valid. - -Docusaurus supports all four Starlight types natively, so switching `:::info` → -`:::note` and `:::warn` → `:::caution` in the upstream source is a safe change -with no effect on the Docusaurus site. - -### 7. Docusaurus REPL meta flags - -The old DFINITY developer portal (`internetcomputer.org/docs`) wrapped Docusaurus's -`CodeBlock` component with a custom React component that embedded the `moc` -interpreter in the browser. It added the following code-fence meta flags: - -| Flag | Docusaurus behaviour | -|---|---| -| `` ```motoko `` (bare, no flag) | Syntax highlighting + **Run** button; output shown on click | -| `` ```motoko run `` | Same as bare but auto-runs on page load | -| `` ```motoko no-repl `` | Syntax highlighting only; no button | -| `` ```motoko name=X `` | Saves block as `X.mo` so other blocks can `include=X` it | -| `` ```motoko include=X,Y `` | Runs `X.mo`, `Y.mo` as context before executing this block | -| `` ```motoko _include=X `` | Like `include=X` but the included code is not shown | - -This site uses Astro + Starlight with the Expressive Code syntax highlighter. -**No REPL or interpreter exists on this site.** Expressive Code silently ignores -all unrecognised meta flags. This has been verified in the built HTML output: -the `figcaption` for a `name=int` block is empty, no Run button is injected, and -the code renders as plain syntax-highlighted Motoko — indistinguishable from a -`no-repl` block. - -**Distribution in the sections this site syncs** (counted against the source): - -| Section | `no-repl` | bare `motoko` | `name=X` | `_include=X` | `run` / `include=` | -|---|---|---|---|---|---| -| `fundamentals/` | 216 | 97 | ~15 (8 files) | ~5 (2 files) | 0 | -| `icp-features/` | 20 | 8 | 0 | 0 | 0 | -| `language-manual.md` | 1 | 19 | 0 | 0 | 0 | -| **Total synced** | **237** | **124** | **~15** | **~5** | **0** | - -The `run` and `include=` (without underscore) flags — the most REPL-intensive — do -not appear in any of the synced sections. They exist only in `core/` (35 files), -`base/` (25 files), and `old/` — all of which are deliberately excluded from sync. - -**The `name=` blocks that appear in `fundamentals/`** are standalone, complete -examples that each make sense on their own. The `name=` label was only meaningful -to the REPL cross-reference mechanism; on this site it does nothing. Examples: -`name=int` labels the `Int.toText` snippet, `name=List` labels a recursive list -type definition, `name=max` labels a generic max function. - -**The `_include=X no-repl` blocks** show a usage example of a named block without -re-executing it. The `_include=` part is a no-op without the REPL; `no-repl` is -already the correct flag for this site. - -**The bare `` ```motoko `` blocks** (97 in `fundamentals/`, 8 in `icp-features/`, -19 in `language-manual.md`) implicitly had a Run button in the portal. On this -site they render identically to `no-repl` blocks — Expressive Code ignores the -missing flag. However, they signal intent incorrectly to anyone reading the source. - -### 8. Internal relative links use numeric-prefixed paths - -Every relative cross-reference in the source uses the current numeric-prefixed -directory and file names. For example, from `fundamentals/3-types/14-subtyping.md`: - -```markdown -[immutable arrays (`[T]`)](../3-types/8-immutable-arrays.md) -[mutable arrays](../3-types/9-mutable-arrays.md) -[functions](../3-types/3-functions.md) -``` - -And from top-level fundamentals files like `0-hello-world.md`: - -```markdown -[actor](../fundamentals/2-actors/1-actors-async.md) -[stable variable](../fundamentals/3-types/13-stable-types.md) -``` - -After the directory and file renames in Proposed Change §1, all of these paths -become invalid. The consuming site's post-processor (`postprocess-motoko.mjs`) -currently rewrites every relative link by stripping numeric prefixes and doing a -slug-index lookup. For a transform-free sync, the upstream must update all -relative links to reflect the post-rename paths. - -In the sections this site syncs, **~146 relative links across ~20 files** use -numeric-prefixed paths. The affected files are concentrated in `fundamentals/` -(subdirs `types/`, `actors/`, `declarations/`, `control-flow/`, `basic-syntax/` -and top-level standalone files) and `reference/1-error-codes.md`. - -**Content quality issue to fix during this pass:** `fundamentals/1-basic-syntax/3-printing-values.md` -links to `../3-types/3-functions.md` (post-rename: `types/function-types.md`) using -the link text "pure functions". However, `function-types.md` has no heading or -anchor for "pure functions" — the concept is only implicit in the "## Local functions" -section. When updating this link's path in Change §8, also fix the link destination: -either add a `{#pure-functions}` anchor inside `function-types.md` (preferred — makes -the concept explicit) or point to `function-types.md#local-functions` and adjust the -link text to "local functions". Without this fix, readers who click "pure functions" -land at the top of `function-types.md` with no indication where the concept is. - -### 9. `changelog.mdx` contains a Docusaurus `md reference` block - -`doc/md/reference/3-changelog.mdx` contains: - -```` -```md reference -https://github.com/caffeinelabs/motoko/blob/master/Changelog.md -``` -```` - -This is a Docusaurus-specific directive that fetches the content of -`Changelog.md` from GitHub at build time. It has no equivalent in Starlight or -standard Markdown — the page renders blank on this site (except for the title) -unless the post-processor inlines the content at sync time. - -The post-processor currently reads `Changelog.md` from the pinned submodule -(`./sources/motoko/Changelog.md`) and inlines it. This works but creates a -dependency on postprocess-motoko.mjs for what should be a simple file copy. - -`Changelog.md` is 2474 lines and grows with every release. The consumer site -is pinned to a specific submodule commit. If the changelog content lived -directly in `doc/md/reference/changelog.md` at the same commit, there can be -no drift: the file always reflects exactly the entries up to that release. - -### 10. `motoko-tooling` links in `comments.md` - -`doc/md/fundamentals/1-basic-syntax/10-comments.md` links to the `motoko-tooling/` -section (excluded from sync) via two relative paths: - -```markdown -[mo-doc](../../motoko-tooling/3-mo-doc.md) -``` - -The `motoko-tooling/` section covers: Canpack, dev containers, mo-doc, and the -Motoko VS Code extension. It is excluded from sync because it uses `dfx` commands -(banned in developer-docs) and contains Docusaurus JSX (`import Tabs`). - -The post-processor previously rewrote these links to `https://docs.motoko.org`, -which does not exist. This is now fixed: the postprocessor redirects both -`motoko-tooling/` relative paths and the `docs.motoko.org` domain to the -internal developer-docs page at `/developer-tools/#mo-doc`. - ---- - -## Proposed changes to `caffeinelabs/motoko` - -### 1. Remove numeric prefixes from all directories and files - -> **Optional for the current sync.** `sync-motoko.sh` already strips numeric -> prefixes via `strip_num()` and handles the one slug collision -> (`types/functions.md` → `function-types.md`) with an explicit rename rule. -> §1 is only *required* if the goal is a fully transform-free rsync with no -> post-processing at all. If the Motoko team prefers to keep numbers for local -> navigation clarity, they can skip §1 and §8 entirely — the sync handles both -> automatically. The remaining 9 changes (§2–§7, §9–§11) are independent of -> whether files are numbered. - -Change the directory structure from: - -``` -doc/md/ - 12-base-core-migration.md - 14-style.md - 15-compiler-ref.md - 16-language-manual.md - fundamentals/ - 0-hello-world.md - 1-basic-syntax/ - 1-defining-an-actor.md - 8-functions.md - 3-types/ - 3-functions.md ← rename to function-types.md to resolve slug collision - ... -``` - -to: - -``` -doc/md/ - base-core-migration.md - style-guide.md ← also rename style.md → style-guide.md for clarity - compiler-ref.md - language-manual.md - fundamentals/ - hello-world.md - basic-syntax/ - defining-an-actor.md - functions.md - types/ - function-types.md ← renamed to avoid collision with basic-syntax/functions.md - ... -``` - -Files that currently share a basename after prefix-stripping need distinct names -(the one collision today is `types/functions.md` vs `basic-syntax/functions.md`; -proposed rename: `types/function-types.md`). - -`fundamentals/2-actors/6-orthogonal-persistence/index.md` must be renamed to -`overview.md` (not just stripped of its prefix). Unlike the other `index.md` files -in `fundamentals/` subdirs — which are Docusaurus navigation pages replaced by -metadata stubs in §11 — this file contains real overview content comparing both -persistence modes. Renaming it to `overview.md` distinguishes it as a content page -rather than an ordering stub. - -### 2. Replace `sidebar_position` with Starlight-native `sidebar.order` - -In every file, replace: - -```yaml ---- -sidebar_position: 8 ---- -``` - -with: - -```yaml ---- -sidebar: - order: 8 ---- -``` - -This allows `icp-features/` and `reference/` to use Starlight `autogenerate`. -`fundamentals/` must stay as an explicitly listed sidebar (see below for why). - -**Section-specific notes:** - -`icp-features/` — flat structure, autogenerate works. `sidebar_position` maps -directly to `sidebar.order` 1–1. `icp-features/7-view-queries.md` has no -`sidebar_position`; add `sidebar: { order: 7 }` to fix. - -`reference/` — after the rename, all six files share one directory but come from -two different legacy position namespaces (reference/ subdir had 1–3; top-level -files had 14–16). Mechanical substitution gives the wrong order. The six files -must be renumbered to match the desired display order: - -| File (post-rename) | Old `sidebar_position` | Correct `sidebar.order` | -|---|---|---| -| `language-manual.md` | 16 | 1 | -| `error-codes.md` | 1 | 2 | -| `motoko-grammar.md` | 2 | 3 | -| `style-guide.md` | 14 | 4 | -| `compiler-ref.md` | 15 | 5 | -| `changelog.md` | 3 | 6 | - -`fundamentals/` — **cannot use autogenerate** without the subdir `index.md` -ordering stubs from Change §11. After removing numeric prefixes, subdirectory -names sort alphabetically: `actors`, `basic-syntax`, `control-flow`, `declarations`, -`types` — but the desired display order is `basic-syntax`, `actors`, `types`, -`declarations`, `control-flow`. Starlight overrides alphabetical directory order -only via `sidebar.order` in a directory's `index.md`. Change §11 adds these -stubs; the new sync uses `--exclude='/index.md'` (anchored to the transfer root), -which keeps the subdir stubs while dropping only the top-level -`fundamentals/index.md` section landing page. - -**Without Change §11:** keep the explicit `sidebar-motoko.mjs` enumeration. -**With Change §11 (recommended):** switch `fundamentals/` to `autogenerate` and -delete `sidebar-motoko.mjs`. - -`actors/` duplicate values — both `4-compatibility.md` and `5-messaging.md` -carry `sidebar_position: 4`. Fix so values are unique and match the numeric -filename order. - -**Add `title:` and `description:` frontmatter to every file, and remove the H1 -heading from the body.** Starlight requires `title:` as a schema field — without -it the build fails. All 68 synced upstream files currently carry `# Title` as an -H1 heading (Docusaurus convention) but have no `title:` in frontmatter. The -developer-docs postprocessor currently bridges this by extracting the H1 as -`title:` and adding a generic `description: "Motoko language documentation"` -fallback. Moving this into the upstream source eliminates that extraction step and -is a prerequisite for the symlink approach. - -The `title:` value is derived from the existing H1 heading. `description:` should -be a genuine one-line summary for each page; the postprocessor's generic fallback -is acceptable as a placeholder during the transition. - -After adding `title:` frontmatter, remove the `# Title` H1 from the body — Starlight -renders the page heading from `title:` frontmatter and would show it twice otherwise. - -Three files have no frontmatter at all: - -- `fundamentals/2-actors/7-mixins.md` — add `title`, `description`, and `sidebar: { order: 7 }` -- `fundamentals/10-contextual-dot.md` — add `title`, `description`, and `sidebar: { order: N }` -- `fundamentals/11-implicit-parameters.md` — add `title`, `description`, and `sidebar: { order: N }` - -### 3. Use `` paths for file-embed blocks - -Replace Docusaurus-relative paths in file-embed blocks: - -```` -```motoko file=../examples/counter.mo -```motoko file=../../examples/todo-error.mo#L49-L58 -``` -```` - -with the `` placeholder: - -```` -```motoko file=/counter.mo -```motoko file=/todo-error.mo#L49-L58 -``` -```` - -`` is a path placeholder recognised by the `remark-include-file` -build plugin on `docs.internetcomputer.org`. It resolves to -`.sources/motoko/doc/md/examples/` — the examples directory inside the pinned -`caffeinelabs/motoko` submodule — at Astro build time. This means: - -- Examples are always live: the plugin reads from the pinned submodule at build - time, so a submodule bump automatically picks up updated examples. -- No sync-time processing: the path rewrite that `postprocess-motoko.mjs` - currently performs (`../examples/` → `/`) will become a - no-op once the upstream source uses `` paths directly, and - can then be removed from the postprocess script. -- `#L-L` line-range suffixes are supported as-is; the plugin slices - the specified lines and raises a hard build error if the range is out of bounds. - -This is a mechanical search-and-replace in the upstream source: -```bash -# In caffeinelabs/motoko — replace all relative example paths -find doc/md -name '*.md' -o -name '*.mdx' | \ - xargs sed -i 's|file=\(\.\./\)*examples/|file=/|g' -``` - -### 4. Replace `./core/` and `./base/` links with mops.one URLs, then remove those directories - -A core maintainer confirmed: "I'd honestly prefer that. Mops docs should be the -single source of truth." — mops.one is the intended canonical home for `mo:core` -library docs. This makes the link replacement + directory removal the actively -desired outcome, not just a side-effect. - -**Step 1 — replace links:** Replace all `./base/.md` and -`./core/.md` links with `https://mops.one/core/docs/`. The -module name matches the source file name exactly; the mapping is mechanical. - -```markdown -[Map](./core/Map.md) → [Map](https://mops.one/core/docs/Map) -[Bool](./base/Bool.md) → [Bool](https://mops.one/core/docs/Bool) -``` - -**Step 2 — remove `doc/md/core/` and its CI generation step:** Once all -`./core/.md` links are replaced, the auto-generated `doc/md/core/` -directory (49 files) is no longer needed and should be deleted. The CI step -that runs `mo-doc` to generate those files from `caffeinelabs/motoko-core` can -be dropped at the same time. This removes a CI dependency and keeps the doc tree -clean. - -**Step 3 — consider removing `doc/md/base/`:** `mo:base` is deprecated in -favour of `mo:core`. Once `./base/.md` links are replaced with mops.one -URLs, the `doc/md/base/` directory is also redundant and can be removed. - -The mops.one URL pattern uses the exact module name: `https://mops.one/core/docs/Map`, -`https://mops.one/core/docs/List`, etc. The module name matches the source file -name in `caffeinelabs/motoko-core/src/.mo` exactly, so the mapping is -mechanical and stable across releases. - -### 5. Use `docs.internetcomputer.org` internal paths - -Replace all `internetcomputer.org/docs/...` links with the canonical -developer-docs paths (relative or absolute using `docs.internetcomputer.org`). -The mapping for common links: - -All `internetcomputer.org/docs/...` URLs currently in the synced source files -(verified against source at time of writing), with specific section anchors -wherever the target page has a matching section: - -| Old portal URL | Current developer-docs path | -|---|---| -| `building-apps/essentials/canisters` | `/concepts/canisters` | -| `building-apps/essentials/message-execution` | `/references/message-execution-properties` | -| `building-apps/interact-with-canisters/update-calls` | `/concepts/canisters#update-calls` | -| `building-apps/interact-with-canisters/query-calls` | `/concepts/canisters#query-calls` | -| `building-apps/interact-with-canisters/query-calls#composite-queries` | `/concepts/canisters#composite-queries` | -| `building-apps/interact-with-canisters/candid/candid-concepts` | `/guides/canister-calls/candid` | -| `building-apps/interact-with-canisters/candid/using-candid` | `/guides/canister-calls/candid` | -| `building-apps/interact-with-canisters/agents/overview` | `/guides/canister-calls/calling-from-clients` | -| `building-apps/canister-management/upgrade` | `/guides/canister-management/lifecycle#upgrade-a-canister` | -| `building-apps/canister-management/snapshots` | `/guides/canister-management/snapshots` | -| `building-apps/canister-management/storage` | `/concepts/orthogonal-persistence` | -| `building-apps/canister-management/storage#heap-memory` | `/concepts/orthogonal-persistence#heap-wasm-linear-memory` | -| `building-apps/canister-management/storage#stable-memory` | `/concepts/orthogonal-persistence#stable-memory` | -| `building-apps/canister-management/storage#motoko-storage-handling` | `/concepts/orthogonal-persistence#motoko-true-orthogonal-persistence` | -| `building-apps/canister-management/resource-limits` | `/guides/canister-management/large-wasm` | -| `building-apps/network-features/periodic-tasks-timers` | `/guides/backends/timers` | -| `building-apps/network-features/periodic-tasks-timers#timers` | `/guides/backends/timers#recurring-timers` | -| `building-apps/network-features/randomness` | `/guides/backends/randomness` | -| `references/async-code` | `/references/message-execution-properties` | -| `references/ic-interface-spec` | `/references/ic-interface-spec/` | -| `references/ic-interface-spec#ic-raw_rand` | `/references/ic-interface-spec/management-canister#ic-raw_rand` | -| `references/ic-interface-spec#global-timer` | `/references/ic-interface-spec/canister-interface#global-timer` | -| `references/ic-interface-spec#system-api-inspect-message` | `/references/ic-interface-spec/canister-interface#system-api-inspect-message` | -| `references/ic-interface-spec#heartbeat` | `/references/ic-interface-spec/canister-interface#heartbeat` | -| `references/candid-ref` | `/references/candid-spec` | -| `references/system-canisters/management-canister` | `/references/management-canister` | - -Notes on anchored entries: -- The ic-interface-spec is split across multiple pages on developer-docs. Old - portal anchors map to specific sub-files. `#heartbeat` has no explicit - `{#heartbeat}` attribute in `canister-interface.md` — Starlight auto-generates - the slug `heartbeat` from the `#### Heartbeat` heading, so the link resolves. -- `building-apps/canister-management/storage` (with and without fragments) maps - to `/concepts/orthogonal-persistence`. The old portal anchors differ: `#heap-memory` - → `#heap-wasm-linear-memory`, `#motoko-storage-handling` → `#motoko-true-orthogonal-persistence`, - `#stable-memory` is an exact match. The postprocessor handles these with explicit - anchored entries in the rewrite map and tries the full URL (with anchor) before - stripping — entries without anchors act as a fallback for bare URLs. -- `building-apps/canister-management/logs` and `building-apps/security/iam/` - appeared in an earlier version of the source but are no longer present. No - action needed for those two. - -**developer-docs side — postprocessor update when §5 lands:** the current -`externalToInternal` map in `postprocess-motoko.mjs` handles the old -`internetcomputer.org/docs/...` pattern. After §5 replaces those with -`docs.internetcomputer.org/...` paths, add a general prefix rule to the map: -```javascript -['docs.internetcomputer.org/', '/'] -``` -This single entry rewrites all `docs.internetcomputer.org/` links to -root-relative `/` internal paths, replacing the entire set of specific -entries above. Remove the `internetcomputer.org/docs/...` entries at the same -time — they will no longer appear in the upstream source. - -### 6. Use Starlight-native aside types - -Replace Docusaurus-only aside types with their Starlight equivalents: - -- `:::info` → `:::note` (both are supported by Docusaurus; no effect on the Docusaurus site) -- `:::warn` → `:::caution` (same: Docusaurus supports both). **Do not change `:::warning`** (full word) — it is already a valid Starlight type and renders correctly on both sites. -- `:::info [LinkText](url)` → `:::note[LinkText]` (strip URL from title; link text becomes plain-text title) - -### 7. Normalize REPL meta flags to `no-repl` - -The REPL meta flags are Docusaurus-specific and have no effect on this site (see -Problem §7). Cleaning them up makes the source readable without assuming any -REPL infrastructure: - -- **Bare `` ```motoko ``** → `` ```motoko no-repl ``: the implicit Run button - no longer exists; `no-repl` makes the intent explicit. Scope: all files in the - sections this site syncs (`fundamentals/`, `icp-features/`, `language-manual.md`). - This is safe for the Docusaurus site too — Docusaurus renders bare `motoko` - and `no-repl` identically when no REPL component is mounted. - -- **`` ```motoko name=X ``** → `` ```motoko no-repl ``: the `name` label has no - purpose without the REPL. The code itself is a self-contained example and - should render as a static block. Applies to all `name=X` blocks in the synced - sections (~15 occurrences in 8 files under `fundamentals/`). - -- **`` ```motoko name=X no-repl ``** → `` ```motoko no-repl ``: strip the unused - `name=X` attribute, keep `no-repl`. - -- **`` ```motoko _include=X no-repl ``** → `` ```motoko no-repl ``: strip the - `_include=X` attribute (it was a no-op display hint for the REPL; the block - already carries `no-repl`). Applies to ~5 occurrences in `fundamentals/`. - -- **`` ```motoko run ``**: not present in any synced section — no action needed. - Only appears in `core/` and `base/` which are excluded from sync. - -- **`` ```motoko include=X ``** (without underscore): not present in any synced - section — no action needed. - -**Important:** a significant portion of code fences in the source use -`` ``` motoko `` (with a space between the backticks and the language name), -not `` ```motoko ``. This space variant must be normalised first, otherwise -the subsequent `sed` commands that anchor to `^```motoko` will miss those blocks. - -This cleanup can be done with the following targeted commands, scoped to the -sections this site syncs: - -```bash -# In caffeinelabs/motoko — scoped to synced sections only -# (do NOT apply to core/, base/, old/ — they have active REPL usage) - -SYNCED_DIRS="doc/md/fundamentals doc/md/icp-features doc/md/reference" -SYNCED_TOP="doc/md/16-language-manual.md doc/md/14-style.md doc/md/15-compiler-ref.md doc/md/12-base-core-migration.md" - -# Step 1: normalise the space-before-language variant (``` motoko → ```motoko) -# This is required first so the patterns below can match consistently. -for dir in $SYNCED_DIRS; do - find "$dir" \( -name '*.md' -o -name '*.mdx' \) \ - | xargs sed -i 's/^``` motoko/```motoko/g' -done -sed -i 's/^``` motoko/```motoko/g' $SYNCED_TOP - -# Step 2: bare ```motoko → ```motoko no-repl -for dir in $SYNCED_DIRS; do - find "$dir" \( -name '*.md' -o -name '*.mdx' \) \ - | xargs sed -i 's/^```motoko$/```motoko no-repl/' -done -sed -i 's/^```motoko$/```motoko no-repl/' $SYNCED_TOP - -# Step 3: strip name=X attribute (with or without no-repl) -for dir in $SYNCED_DIRS; do - find "$dir" \( -name '*.md' -o -name '*.mdx' \) \ - | xargs sed -i 's/^```motoko\(.*\) name=[^ ]*/```motoko\1/g' -done - -# Step 4: strip _include=X attribute (always paired with no-repl) -for dir in $SYNCED_DIRS; do - find "$dir" \( -name '*.md' -o -name '*.mdx' \) \ - | xargs sed -i 's/ _include=[^ ]*//g' -done -``` - -`no-repl` is already recognised by both Docusaurus (disables the Run button) and -this site (syntax highlighting only). The cleanup is a safe no-op for the -Docusaurus site. - -### 8. Update all internal relative links to use post-rename paths - -> **Only needed if §1 is done.** If numeric prefixes are kept, skip this -> section — `postprocess-motoko.mjs` already rewrites all numeric-prefixed -> relative links via its `syncRenames` map and slug-index lookup. - -After the directory and file renames in Change §1, every relative cross-reference -in the source that uses numeric-prefixed path components must be updated. This -applies to ~146 links across ~20 files in the synced sections. - -The pattern is mechanical: strip the numeric prefix from each path component in -relative links, and apply the special renames from Change §1 (`3-functions.md` → -`function-types.md`, `index.md` → `overview.md`, `14-style.md` → `style-guide.md`). - -Examples of required rewrites: - -| Before | After | -|---|---| -| `../3-types/8-immutable-arrays.md` | `../types/immutable-arrays.md` | -| `../2-actors/1-actors-async.md` | `../actors/actors-async.md` | -| `../fundamentals/3-types/13-stable-types.md` | `./types/stable-types.md` | -| `../fundamentals/2-actors/6-orthogonal-persistence/enhanced.md` | `./actors/orthogonal-persistence/enhanced.md` | -| `../5-control-flow/5-switch.md` | `../control-flow/switch.md` | - -This step **must be completed alongside Change §1** — the renames and link -updates form one atomic change. A broken intermediate state (files renamed but -links not yet updated) would prevent the Docusaurus site from building. - -There is no single `sed` command for this — the correct replacement depends on -each link's context (depth in the tree, target file, special renames). The -recommended approach is to run the renames first, then use a link-checker to -enumerate broken links, and update each one. The consuming site's -`postprocess-motoko.mjs` contains the full mapping table in `syncRenames` and -the slug index logic, which can serve as a reference for the expected post-rename -paths. - -### 9. Replace the `changelog.mdx` Docusaurus `md reference` block - -`doc/md/reference/3-changelog.mdx` (after prefix removal: `reference/changelog.mdx`) -contains the following Docusaurus-specific directive that has no standard Markdown -equivalent: - -```` -```md reference -https://github.com/caffeinelabs/motoko/blob/master/Changelog.md -``` -```` - -Docusaurus fetches the content of `Changelog.md` from GitHub and renders it -inline. Starlight and standard Markdown processors ignore this block entirely, -leaving the changelog page blank except for the frontmatter title. - -The post-processor currently handles this by reading `Changelog.md` from the -pinned submodule (`.sources/motoko/Changelog.md`) and inlining its full contents. - -There is no need to copy `Changelog.md` — it already exists at exactly the right -version in the submodule root at the pinned commit. The fix has two parts: - -**developer-docs side (already done with this PR):** `remark-include-file` now -supports inline markdown inclusion. A code fence with language `md` and a `file=` -attribute is replaced with the parsed AST of the referenced file, so the content -renders as prose (headings, lists, etc.), not as a code block. The new -`` placeholder resolves to `.sources/motoko/` at build time. - -**Upstream fix:** replace the `md reference` block with a single inline include -directive and rename the file from `changelog.mdx` to `changelog.md`: - -```markdown ---- -title: "Changelog" -description: "Motoko compiler changelog" -sidebar: - order: 3 ---- - -```md file=/Changelog.md -``` -``` - -(The `` placeholder is developer-docs-specific and is a no-op on -the Docusaurus site — Docusaurus ignores unknown code fence attributes and will -render this as an empty fenced block. The Docusaurus site can keep its `md reference` -block separately, or the two directives can coexist in the same file since only one -will be processed at a time depending on the build environment.) - -The post-processor's changelog inlining step can be removed once the upstream -adopts this. The `changelog.mdx` file can be renamed `changelog.md` at the same -time (the MDX extension was only needed for the `md reference` directive). - -### 10. Replace `motoko-tooling` links with a valid URL - -`doc/md/fundamentals/1-basic-syntax/10-comments.md` (after rename: -`fundamentals/basic-syntax/comments.md`) contains two links to the -`motoko-tooling/` section, which is excluded from sync: - -```markdown -[mo-doc](../../motoko-tooling/3-mo-doc.md) -``` - -These appear twice: once inline in the text (line 17) and once in a "See also" -list (line 49). - -The post-processor previously rewrote these to `https://docs.motoko.org`, which -does not exist. This is now fixed: both `motoko-tooling/` relative paths and the -`docs.motoko.org` domain redirect to `/developer-tools/#mo-doc`. - -**Upstream fix:** replace both occurrences with the developer-docs mo-doc page: - -```markdown -[mo-doc](https://docs.internetcomputer.org/developer-tools/#mo-doc) -``` - -**developer-docs side (done):** `docs/developer-tools/index.md` now has a -dedicated `### mo-doc` section covering what it does, how to install it from the -Motoko compiler tarball, and usage examples. The `motoko-tooling/` section -remains excluded from sync because it still contains `dfx` commands and -Docusaurus JSX — see the note on `dfx` references below. - ---- - -## Known content issues — outside the sync scope - -The items below are content quality issues found in synced files. They are upstream -problems that cannot be fixed on the developer-docs side (synced files must not be -edited directly). They should be addressed in a separate upstream PR, independent -of the sync reorganization effort. - -### `dfx` references in prose - -Several synced files contain `dfx` and `dfx.json` references in prose and code -examples: `compatibility.md`, `data-persistence.md`, -`orthogonal-persistence/classical.md`, `orthogonal-persistence/enhanced.md`, -`modules-imports.md`, and `reference/changelog.md` (historical entries). - -Upstream PR [caffeinelabs/motoko#6069](https://github.com/caffeinelabs/motoko/pull/6069) -is a first attempt at replacing these. **It should not be merged before the sync -reorganization PR (§1–§11) lands**: §1 renames files, so #6069's branch needs to -be rebased on the post-reorganization state and extended with any remaining `dfx` -references before merging. Em-dash fixes (see below) can be included in the same -follow-up PR. - -### Em-dashes in prose - -`enhanced-multi-migration.md` and `compatibility.md` contain em-dashes in body -prose. Em-dashes are banned in developer-docs content. These should be replaced -with colons, semicolons, or commas in the upstream source. - ---- - -## What the sync becomes after these changes - -With the above changes in place, `sync-motoko.sh` reduces to a plain file copy: - -```bash -rsync -r --delete .sources/motoko/doc/md/fundamentals/ docs/languages/motoko/fundamentals/ -rsync -r --delete .sources/motoko/doc/md/icp-features/ docs/languages/motoko/icp-features/ -rsync -r --delete .sources/motoko/doc/md/reference/ docs/languages/motoko/reference/ -cp .sources/motoko/doc/md/language-manual.md docs/languages/motoko/reference/language-manual.md -cp .sources/motoko/doc/md/style-guide.md docs/languages/motoko/reference/style-guide.md -cp .sources/motoko/doc/md/compiler-ref.md docs/languages/motoko/reference/compiler-ref.md -cp .sources/motoko/doc/md/base-core-migration.md docs/languages/motoko/base-core-migration.md -``` - -No exclude flags needed: upstream deletes `_category_.yml` files (§11) and the -top-level section `index.md` nav pages as part of the Docusaurus cleanup. - -### Symlink alternative - -Once all upstream changes are in place, the copy step could be replaced entirely -with committed symlinks: - -``` -docs/languages/motoko/fundamentals → ../../.sources/motoko/doc/md/fundamentals -docs/languages/motoko/icp-features → ../../.sources/motoko/doc/md/icp-features -docs/languages/motoko/reference → ../../.sources/motoko/doc/md/reference -``` - -Astro follows symlinks (the site already uses them for `src/content/docs/`), so -this works. Bumping the submodule is the entire update — no sync script runs. - -**The copy approach is preferred.** Three reasons: - -1. **Internal links**: the postprocessor converts `docs.internetcomputer.org/` - absolute URLs to root-relative `/` internal paths. Internal paths are - validated at Astro build time, work in local dev (`npm run dev`), and work in - preview deployments. Symlinks leave these as absolute external URLs, which skip - build-time validation and always point to production regardless of environment. -2. **Anchor routing**: the postprocessor maps old portal anchor slugs to the - correct developer-docs sub-page (e.g. `#global-timer` → - `canister-interface#global-timer`). Upstream cannot encode this mapping — - it requires knowledge of the developer-docs structure that lives here. -3. **Auditability**: every submodule bump produces a reviewable `git diff` showing - exactly what changed in the docs. With symlinks, content changes are invisible - in this repo. - -`postprocess-motoko.mjs` can be deleted entirely once §2 is fully completed -upstream, including adding `title:` and `description:` frontmatter to every file -and removing the `# Title` H1 heading from the body. Without `title:` in the -upstream frontmatter, Starlight's build schema validation fails; this is a hard -prerequisite for the symlink approach. - -Once §2 lands, the postprocessor's H1-extraction step becomes a no-op and the -remaining tasks split by approach: - -- **Copy approach (preferred for auditability):** the postprocessor rewrites - `docs.internetcomputer.org/` links to root-relative `/` internal - links. Every submodule bump produces a reviewable `git diff`. -- **Symlink approach:** `docs.internetcomputer.org/` links remain as absolute - external URLs pointing to the consumer site itself (self-referential but - acceptable). Bumping the submodule is the entire update. - -In both cases, `` paths are handled by `remark-include-file` at -build time — no sync-time file expansion is needed. - -`sidebar.mjs` changes after the upstream PR: -- `icp-features/` — switch to `autogenerate: { directory: "languages/motoko/icp-features" }`. - Already autogenerated today; no change to this block. -- `reference/` — switch to `autogenerate: { directory: "languages/motoko/reference" }`. - Correct because all six files will have sequential `sidebar.order` 1–6. -- `fundamentals/` — switch to `autogenerate: { directory: "languages/motoko/fundamentals" }` - once Change §11 lands. The subdir `index.md` stubs copied by the anchored - `--exclude='/index.md'` carry the `sidebar.order` values Starlight needs to - override alphabetical sort. Delete `sidebar-motoko.mjs` at the same time. - ---- - -## Migration path - -**developer-docs side (already done):** -- `remark-include-file` supports `` and `#L-L` ranges. -- `postprocess-motoko.mjs` rewrites `../examples/` → `/` at - sync time as a bridge until the upstream adopts the placeholder directly. - -**upstream side (one PR in `caffeinelabs/motoko`):** - -**Required (fix rendering/content bugs in the consumer site):** §2, §3, §4, §5, §6, §9, §10 -**Required for `fundamentals/` autogenerate (eliminates manual sidebar maintenance):** §11 -**Optional — only needed for a fully transform-free rsync:** §1 + §8 (do both or neither) -**Optional cleanup (silently handled today):** §7 -_(Note: §4 also includes removing `doc/md/core/`, `doc/md/base/`, and the CI generation step once links are replaced — confirmed as desired by a core maintainer.)_ - -1. Remove numeric prefixes from all directories and files (including top-level - `14-style.md` → `style-guide.md`, `15-compiler-ref.md` → `compiler-ref.md`, - `16-language-manual.md` → `language-manual.md`, - `12-base-core-migration.md` → `base-core-migration.md`). - Rename `fundamentals/2-actors/6-orthogonal-persistence/index.md` → - `overview.md` to distinguish it as a content page from the ordering stubs - added in step 11. -2. Replace `sidebar_position: N` with `sidebar: { order: N }` in every file. - Fix duplicate `sidebar_position` values in `2-actors/`. Add `sidebar_position` - to `icp-features/7-view-queries.md` (currently missing). Add complete - frontmatter (`title`, `description`, `sidebar_position`) to `7-mixins.md`, - `10-contextual-dot.md`, and `11-implicit-parameters.md` (currently have none). -3. Replace `file=../examples/` (and `file=../../examples/`) with - `file=/` throughout — one `sed` command covers all cases. -4. Replace `./base/.md` and `./core/.md` links with - `https://mops.one/core/docs/`. -5. Replace `internetcomputer.org/docs/...` links using the mapping table above. -6. Replace `:::info` → `:::note` and `:::warn` → `:::caution` throughout. - Do NOT change `:::warning` (full word) — it is already valid in Starlight. - Strip URLs from aside titles that use a markdown link as the title - (`:::info [LinkText](url)` → `:::note[LinkText]`). -7. Normalize REPL meta flags in `fundamentals/`, `icp-features/`, `reference/`, - and the four top-level synced files: normalise space variant - (`` ``` motoko `` → `` ```motoko ``); bare `` ```motoko `` → `` ```motoko no-repl ``; - strip `name=X` and `_include=X` attributes (use `no-repl` instead). -8. Update all ~146 internal relative links to use the post-rename paths (no - numeric prefixes, apply the special renames from step 1). Do this atomically - with the renames — the Docusaurus site must not have broken links at any - intermediate commit. -9. Replace the `md reference` block in `reference/changelog.mdx` with - `` ```md file=/Changelog.md ``` `` plus frontmatter. - Rename `changelog.mdx` → `changelog.md` (MDX was only needed for the - Docusaurus directive). No release automation needed — the file is a static - stub; `Changelog.md` at the same commit is always the correct version. -10. Replace the two `../../motoko-tooling/3-mo-doc.md` links in - `fundamentals/basic-syntax/comments.md` with - `https://docs.internetcomputer.org/developer-tools/#mo-doc`. -11. Replace the `index.md` files in each `fundamentals/` subdirectory with a - metadata-only version containing just `sidebar.order` and `sidebar.label` - frontmatter (no content). Also add a new `fundamentals/actors/index.md` - which currently does not exist. Add `sidebar: { hidden: true }` to - `base-core-migration.md`. These three changes are what allow developer-docs - to switch `fundamentals/` from an explicit sidebar list to `autogenerate`. - See the table below. Without this step, developer-docs must maintain an - explicit fundamentals page list in `sidebar-motoko.mjs` and update it - manually every time a fundamentals page is added or removed. - - | Subdir | Action | `sidebar.order` | - |---|---|---| - | `fundamentals/basic-syntax/` | replace `index.md` with metadata stub | 1 | - | `fundamentals/actors/` | add new `index.md` (currently missing) | 2 | - | `fundamentals/types/` | replace `index.md` with metadata stub | 3 | - | `fundamentals/declarations/` | replace `index.md` with metadata stub | 4 | - | `fundamentals/control-flow/` | replace `index.md` with metadata stub | 5 | - | `base-core-migration.md` | add `sidebar: { hidden: true }` | n/a | - - The metadata stub format: - ```yaml - --- - sidebar: - order: 1 - label: "Basic syntax" - --- - ``` - - The `fundamentals/index.md` (top-level section landing page) is still - excluded by the sync — only subdir `index.md` files are kept. - -**developer-docs side (done in PR 261 — `docs/motoko-sync-fixes`):** -- `remark-include-file` supports `` placeholder and inline markdown - inclusion (`md` language code fence → rendered prose, not a code block). -- `remark-include-file` supports `` and `#L-L` ranges. -- `postprocess-motoko.mjs` rewrites `../examples/` → `/` at - sync time as a bridge until the upstream adopts the placeholder directly. -- `sidebar-motoko.mjs` contains the explicit Motoko sidebar as a transitional - file. It is deleted in the step below once step 11 above lands. - -**developer-docs side (separate PR — do after upstream PR merges):** - -The following changes must NOT be merged until the upstream reorganization PR -has landed and the submodule has been bumped. Merging them early permanently -breaks the automated weekly sync CI (`sync-motoko.yml` runs `npm run sync:motoko` -weekly; it would fail on the structure guard with every new Motoko release until -the upstream changes are in place). - -1. Replace `sync-motoko.sh` with the simplified rsync version shown above. Add a - structure guard at the top: if `$SOURCE_DIR/fundamentals/1-basic-syntax` still - exists (old numeric-prefix layout), exit with a clear error. Once upstream - deletes the top-level section `index.md` files, the `--exclude='index.md'` flags - become no-ops and can be removed. Remove the postprocess call. -2. Delete `postprocess-motoko.mjs`. -3. Delete `sidebar-motoko.mjs`. Replace its import in `sidebar.mjs` with: - ```js - export const motokoSidebar = { - label: "Motoko", - collapsed: true, - autogenerate: { directory: "languages/motoko" }, - }; - ``` - New pages in any section appear automatically. No sidebar config to maintain. - -The Docusaurus site in `caffeinelabs/motoko` is unaffected: Docusaurus ignores -`sidebar.order` and continues to use `_category_.yml` position values. -Both `sidebar_position` and `sidebar.order` can coexist in the same frontmatter -during the transition period. - ---- - -## Appendix: additional decisions - -### If Docusaurus is dropped from the upstream repo - -The motoko team is considering moving away from Docusaurus in `caffeinelabs/motoko`. -If that happens, some of the changes above become simpler or can be deferred: - -- **§2 (sidebar.order)**: If Docusaurus is dropped, `sidebar_position` can be - removed entirely rather than migrated. `sidebar.order` in Starlight frontmatter - remains the right replacement. -- **§6 (aside types)**: Without Docusaurus compatibility to maintain, `:::info` can - simply become `:::note` with no concern about backward breakage on the docs site. -- **§7 (REPL flags)**: `no-repl` is Docusaurus-specific. Without Docusaurus, REPL - flags can be removed entirely rather than normalized. Bare `` ```motoko `` is the - correct form for a static site. -- **§9 (changelog)**: The `md reference` block is Docusaurus-specific and would - need replacing regardless of which framework replaces it. -- **§1, §3, §4, §5, §8, §10**: Framework-independent — required regardless of - which docs tool the upstream uses. - -In practice: proceed with this plan without waiting for a Docusaurus decision. The -changes are safe whether Docusaurus stays or goes. - -### Upstream agent instructions: `_category_.yml` and `index.md` - -The upstream `caffeinelabs/motoko` currently uses two Docusaurus-specific -constructs for sidebar navigation that have no equivalent in Starlight. Both -must be replaced as part of the reorganization (or removed if Docusaurus is -dropped). - -#### `_category_.yml` files - -Each `_category_.yml` defines the label, position, and collapsed state for a -directory in the Docusaurus sidebar. In Starlight, this information goes into -an `index.md` file in the same directory with `sidebar.order` and -`sidebar.label` frontmatter. - -**Mapping for all `_category_.yml` files in the synced sections:** - -| Directory (post-rename) | `_category_.yml` | Action | -|---|---|---| -| `fundamentals/` | `position: 3, label: 'Fundamentals'` | Delete — label comes from `sidebar.mjs` in developer-docs, not from upstream | -| `fundamentals/basic-syntax/` | `position: 2, label: 'Basic syntax'` | Create `index.md` stub with `sidebar: { order: 1, label: "Basic syntax" }` | -| `fundamentals/actors/` | `position: 3, label: 'Actors'` | Create `index.md` stub with `sidebar: { order: 2, label: "Actors" }` | -| `fundamentals/types/` | `position: 4, label: 'Types'` | Create `index.md` stub with `sidebar: { order: 3, label: "Types" }` | -| `fundamentals/declarations/` | `position: 5, label: 'Declarations'` | Create `index.md` stub with `sidebar: { order: 4, label: "Declarations" }` | -| `fundamentals/control-flow/` | `position: 6, label: 'Control flow'` | Create `index.md` stub with `sidebar: { order: 5, label: "Control flow" }` | -| `icp-features/` | `position: 4, label: 'ICP features'` | Delete — label comes from `sidebar.mjs` | -| `reference/` | `position: 13, label: 'Motoko references'` | Delete — label comes from `sidebar.mjs` | - -Note: the Starlight `sidebar.order` values (1–5) for fundamentals subdirs do -not match the Docusaurus `position` values (2–6). The difference is that -Docusaurus counts `hello-world.md` (position 1) as a sibling, while Starlight -uses the subdir `index.md` order only among subdirs. What matters is the -relative order among the five subdirs, not the absolute number. - -The metadata stub format: -```yaml ---- -sidebar: - order: 1 - label: "Basic syntax" ---- -``` -No title, description, or body content. This is a Starlight navigation -control file only. - -After creating the `index.md` stubs, delete every `_category_.yml` in the repo -(they have no meaning outside Docusaurus). - -#### `index.md` files in `fundamentals/` subdirs - -The current `index.md` files in `fundamentals/1-basic-syntax/`, -`fundamentals/3-types/`, `fundamentals/4-declarations/`, and -`fundamentals/5-control-flow/` are Docusaurus section landing pages. Their -content is a numbered list of links to pages in the section — useful in -Docusaurus where the section heading is a clickable link. In Starlight, the -sidebar handles navigation automatically; these pages are not needed. - -**Replace** each of these `index.md` files with the metadata stub described -above (matching the `_category_.yml` values for that directory). The existing -list content is Docusaurus navigation scaffold and can be discarded. - -`fundamentals/2-actors/` currently has no `index.md`. **Create** one with the -stub for order 2 / label "Actors" (the `_category_.yml` position and label). - -**Do NOT touch** `fundamentals/2-actors/6-orthogonal-persistence/index.md` — -this file contains real conceptual content comparing both persistence modes. -It must be **renamed** to `overview.md` (Change §1) to distinguish it as a -content page from the ordering stubs. - -The top-level `fundamentals/index.md`, `icp-features/index.md`, and -`reference/index.md` are Docusaurus section landing pages (nav scaffold with -no Starlight equivalent). **Delete them** as part of the Docusaurus cleanup. - -### `base-core-migration.md` in the sidebar - -`base-core-migration.md` is currently excluded from the sidebar and linked from -the Motoko overview (`docs/languages/motoko/index.md`) only. This is the right -call: `mo:base` has been deprecated for a while and most new developers will never -need the migration guide. Keeping it off the sidebar avoids adding a dead-weight -entry that implies the base library is still relevant. The guide remains fully -discoverable via site search and via the overview link for developers who do need -it. No change recommended. diff --git a/.sources/motoko b/.sources/motoko index 75c4123f..1fc25e95 160000 --- a/.sources/motoko +++ b/.sources/motoko @@ -1 +1 @@ -Subproject commit 75c4123f4d117f334d174656d049423efe6dcaab +Subproject commit 1fc25e951b417ec0e3e98bbfa05cd96d81e1e44f diff --git a/docs/languages/motoko/base-core-migration.md b/docs/languages/motoko/base-core-migration.md index 6185e780..70bf783b 100644 --- a/docs/languages/motoko/base-core-migration.md +++ b/docs/languages/motoko/base-core-migration.md @@ -1,11 +1,13 @@ --- -sidebar_position: 12 -description: "Motoko language documentation" title: "Motoko `base` to `core` migration guide" +description: "Comprehensive guide for migrating from the Motoko base package to the new core package." +sidebar: + order: 12 + hidden: true --- -* [GitHub repository](https://github.com/dfinity/motoko-core) -* [Documentation](https://mops.one/core) +* [GitHub repository](https://github.com/caffeinelabs/motoko-core) +* [Documentation](https://mops.one/core/docs/) The `core` package is a new and improved standard library for Motoko, focusing on: * AI-friendly design patterns. @@ -28,7 +30,7 @@ If you are migrating an existing project, you can keep the `base` import and gra ### Important considerations -:::warning[Version requirements] +:::caution[Version requirements] The `core` package depends on new language features, so make sure to update to the latest dfx (0.28+) or Motoko compiler (0.15+) before migrating. ::: @@ -40,9 +42,9 @@ When updating to the `core` package: - Hash-based data structures are no longer included in the standard library. It is encouraged to use ordered maps and sets for improved security. - In some cases, it won't be possible to fully migrate to `core` due to removal of some features in `base`. In these cases, you can continue using both packages side-by-side or search for [Mops packages](https://mops.one/) built by the community. -For details on function signatures, please refer to the official [documentation](https://mops.one/core). +For details on function signatures, please refer to the official [documentation](https://mops.one/core/docs/). -Also, feel free to ask for help by posting on the [ICP developer forum](https://forum.dfinity.org/c/developers) or opening a GitHub issue on the [`dfinity/motoko-core`](https://github.com/dfinity/motoko-core/issues) repository. +Also, feel free to ask for help by posting on the [ICP developer forum](https://forum.dfinity.org/c/developers) or opening a GitHub issue on the [`caffeinelabs/motoko-core`](https://github.com/caffeinelabs/motoko-core/issues) repository. ## Module changes @@ -158,7 +160,7 @@ The `core` package brings significant changes to data structures, making a clear - `sortInPlace()` - Use `VarArray.sortInPlace()` instead - `tabulateVar()` - Use `VarArray.tabulate()` instead -### [`Blob`](https://mops.one/core/docs/Blob) +### [`Blob`](https://mops.one/core/docs/Blo) #### Modified functions - `fromArrayMut()` → `fromVarArray()` @@ -187,7 +189,7 @@ The `core` package brings significant changes to data structures, making a clear - `isLowercase()` → `isLower()` - `isUppercase()` → `isUpper()` -### [`Debug`](https://mops.one/core/docs/Debug) +### [`Debug`](https://mops.one/core/docs/Deug) #### Added functions - `todo()` - Replaces `Prelude.nyi()` @@ -258,7 +260,7 @@ Helper functions have been added, such as `allValues()`, for each finite type in - `rangeBy()`, `rangeByInclusive()` - Range with step - `toInt()` - Convert to Int -### [`Int8`, `Int16`, `Int32`, `Int64`, `Nat8`, `Nat16`, `Nat32`, `Nat64`](https://mops.one/core) +### [`Int8`, `Int16`, `Int32`, `Int64`, `Nat8`, `Nat16`, `Nat32`, `Nat64`](https://mops.one/core/docs/) #### Renamed fields @@ -293,7 +295,7 @@ Helper functions have been added, such as `allValues()`, for each finite type in The `Random` module has been completely redesigned in the core package with a new API that provides better control over random number generation and supports both pseudo-random and cryptographic random number generation. -```motoko +```motoko no-repl import Random "mo:core/Random"; persistent actor { @@ -370,7 +372,7 @@ The new migration pattern allows you to automatically convert existing stable da The `with migration` syntax follows this structure: -```motoko +```motoko no-repl ( with migration = func( state : { @@ -389,7 +391,7 @@ persistent actorApp { It's also possible to use a function defined in an imported module: -```motoko +```motoko no-repl import { migrate } "Migration"; (with migration = migrate) @@ -404,7 +406,7 @@ This pattern ensures that existing stable data is preserved and converted to the #### Original (`base`) -```motoko +```motoko no-repl import Buffer "mo:base/Buffer"; persistent actor{ @@ -433,7 +435,7 @@ persistent actor{ #### Updated (`core`) -```motoko +```motoko no-repl import List "mo:core/List"; ( @@ -466,7 +468,7 @@ persistent actorApp { #### Original (`base`) -```motoko +```motoko no-repl import Deque "mo:base/Deque"; persistent actor{ @@ -492,7 +494,7 @@ persistent actor{ #### Updated (`core`) -```motoko +```motoko no-repl import Deque "mo:base/Deque"; // For migration import Queue "mo:core/Queue"; @@ -537,7 +539,7 @@ import Queue "mo:core/Queue"; #### Original (`base`) -```motoko +```motoko no-repl import HashMap "mo:base/HashMap"; import Text "mo:base/Text"; import Iter "mo:base/Iter"; @@ -570,7 +572,7 @@ persistent actor{ #### Updated (`core`) -```motoko +```motoko no-repl import Map "mo:core/Map"; import Text "mo:core/Text"; import Iter "mo:core/Iter"; @@ -607,7 +609,7 @@ persistent actor{ #### Original (`base`) -```motoko +```motoko no-repl import OrderedMap "mo:base/OrderedMap"; import Text "mo:base/Text"; import Iter "mo:base/Iter"; @@ -634,7 +636,7 @@ persistent actor{ #### Updated (`core`) -```motoko +```motoko no-repl import OrderedMap "mo:base/OrderedMap"; // For migration import Map "mo:core/Map"; import Text "mo:core/Text"; @@ -675,7 +677,7 @@ persistent actor{ #### Original (`base`) -```motoko +```motoko no-repl import OrderedSet "mo:base/OrderedSet"; import Text "mo:base/Text"; import Iter "mo:base/Iter"; @@ -704,7 +706,7 @@ persistent actor{ #### Updated (`core`) -```motoko +```motoko no-repl import OrderedSet "mo:base/OrderedSet"; // For migration import Set "mo:core/Set"; import Text "mo:core/Text"; @@ -747,7 +749,7 @@ persistent actorApp { #### Original (`base`) -```motoko +```motoko no-repl import Trie "mo:base/Trie"; import Text "mo:base/Text"; import Iter "mo:base/Iter"; @@ -778,7 +780,7 @@ persistent actor{ #### Updated (`core`) -```motoko +```motoko no-repl import Trie "mo:base/Trie"; // For migration import Map "mo:core/Map"; import Text "mo:core/Text"; @@ -816,7 +818,7 @@ persistent actor{ #### Original (`base`) -```motoko +```motoko no-repl import TrieMap "mo:base/TrieMap"; import Text "mo:base/Text"; import Iter "mo:base/Iter"; @@ -849,7 +851,7 @@ persistent actor{ #### Updated (`core`) -```motoko +```motoko no-repl import Map "mo:core/Map"; import Text "mo:core/Text"; import Iter "mo:core/Iter"; @@ -886,7 +888,7 @@ persistent actor{ #### Original (`base`) -```motoko +```motoko no-repl import TrieSet "mo:base/TrieSet"; import Text "mo:base/Text"; @@ -913,7 +915,7 @@ persistent actor{ #### Updated (`core`) -```motoko +```motoko no-repl import Set "mo:core/Set"; import Text "mo:core/Text"; import Iter "mo:core/Iter"; diff --git a/docs/languages/motoko/fundamentals/actors/actors-async.md b/docs/languages/motoko/fundamentals/actors/actors-async.md index a1594095..3388e0b9 100644 --- a/docs/languages/motoko/fundamentals/actors/actors-async.md +++ b/docs/languages/motoko/fundamentals/actors/actors-async.md @@ -1,10 +1,11 @@ --- -sidebar_position: 1 -description: "Motoko language documentation" title: "Actors & async data" +description: "The actor programming model was designed to solve concurrency issues by encapsulating state and computation within independent units called actors." +sidebar: + order: 1 --- -The actor programming model was designed to solve concurrency issues by encapsulating [state](/languages/motoko/fundamentals/actors/state) and computation within independent units called **actors**. +The actor programming model was designed to solve concurrency issues by encapsulating [state](./state.md) and computation within independent units called **actors**. The actor model is built on four key principles: @@ -105,7 +106,7 @@ To access the result of an `async` value, the receiver of the future uses an `aw For example, to use the result of `Counter.read()` above, we can first bind the future to an identifier `a`, and then `await a` to retrieve the underlying [`Nat`](https://mops.one/core/docs/Nat), `n`: -``` motoko no-repl +```motoko no-repl let a : async Nat = Counter.read(); let n : Nat = await a; ``` @@ -116,7 +117,7 @@ The second line `await`s this future and extracts the result, a natural number. Typically, one rolls the two steps into one and just awaits an asynchronous call directly: -``` motoko no-repl +```motoko no-repl let n : Nat = await Counter.read(); ``` @@ -130,7 +131,7 @@ An `await` will always suspend execution and commit state, even if its future is When several futures are issued in parallel and racing to complete, it can be more efficient to opt out of the unconditional behavior of `await` and immediately continue with a result when it is available: -``` motoko no-repl +```motoko no-repl let a : async Nat = CounterA.read(); let b : async Nat = CounterB.read(); let sum : Nat = (await a) + (await? b); @@ -177,7 +178,7 @@ A function that does not use `await` runs atomically, meaning nothing else can c For example, the implementation of `bump()` above is guaranteed to increment and read the value of `count`, in one atomic step. The following alternative implementation does not have the same semantics and allows another client of the actor to interfere with its operation. -``` motoko no-repl +```motoko no-repl public shared func bump() : async Nat { await inc(); await read(); @@ -216,7 +217,7 @@ In other languages without these features, developers often need to use advanced To demonstrate how asynchronous actors work, consider the following example. -Customers place orders at a pizza restaurant, but the chef can only make one pizza at a time. Orders are taken **[asynchronously](/languages/motoko/fundamentals/actors/actors-async#async--await)**, meaning customers do not have to wait for previous orders to be completed before placing their own. However, each pizza is prepared sequentially. This is representative of an asynchronous actor. +Customers place orders at a pizza restaurant, but the chef can only make one pizza at a time. Orders are taken **[asynchronously](./actors-async.md#async--await)**, meaning customers do not have to wait for previous orders to be completed before placing their own. However, each pizza is prepared sequentially. This is representative of an asynchronous actor. ```motoko no-repl import Array "mo:core/Array"; @@ -287,7 +288,7 @@ Use `async*` and `await*` carefully. In Motoko, a regular `await` is a commit po ### Example -``` motoko no-repl +```motoko no-repl persistent actor class (Logger : actor { log : Text -> async () }) { var logging = true; @@ -376,6 +377,3 @@ When `catch` is used, the `finally` clause is optional. The `catch` block only c 1. Local traps. 2. Pre-await traps in async functions. 3. Traps after `await`. - - -Logo diff --git a/docs/languages/motoko/fundamentals/actors/compatibility.md b/docs/languages/motoko/fundamentals/actors/compatibility.md index bb918ff8..382ff27d 100644 --- a/docs/languages/motoko/fundamentals/actors/compatibility.md +++ b/docs/languages/motoko/fundamentals/actors/compatibility.md @@ -1,18 +1,17 @@ --- -sidebar_position: 4 -description: "Motoko language documentation" title: "Verifying upgrade compatibility" +description: "When upgrading a canister, it is important to verify that the upgrade can proceed without:" +sidebar: + order: 4 --- - - When upgrading a canister, it is important to verify that the upgrade can proceed without: - Introducing an incompatible change in stable declarations. - Breaking clients due to a Candid interface change. `dfx` checks these properties statically before attempting the upgrade. -Moreover, with [enhanced orthogonal persistence](/languages/motoko/fundamentals/actors/orthogonal-persistence/enhanced), Motoko rejects incompatible changes of stable declarations. +Moreover, with [enhanced orthogonal persistence](./orthogonal-persistence/enhanced.md), Motoko rejects incompatible changes of stable declarations. ## Upgrade example @@ -52,12 +51,12 @@ You can think of this as the interior interface of the actor, that it presents t For example, `v1`'s stable types: -```motoko no-repl file=/count-v1.most +```motoko no-repl title="count-v1.most" file=/count-v1.most ``` An upgrade from `v1` to `v2`'s stable types consumes a [`Nat`](https://mops.one/core/docs/Nat) as an [`Int`](https://mops.one/core/docs/Nat), which is valid because `Nat <: Int`, that is, `Nat` is a subtype of `Int`. -```motoko no-repl file=/count-v2.most +```motoko no-repl title="count-v2.most" file=/count-v2.most ``` ## Evolving the Candid interface @@ -74,38 +73,38 @@ An upgrade is safe provided that both the Candid interface and stable type signa does not involve promotion to `Any` or dropping object fields. * The Candid interface evolves to a subtype. -Consider the following four versions of the counter example: +Consider the following four versions of the counter example. The `// Version: 1.0.0` comment at the top of each `.most` file is the stable signature format version, not the application version. See [Stable signature versions](#stable-signature-versions) below for the full taxonomy. Version `v0` with Candid interface `v0.did` and stable type interface `v0.most`: -```candid file=/count-v0.did +``` candid file=/count-v0.did ``` -```motoko no-repl file=/count-v0.most +```motoko no-repl title="count-v0.most" file=/count-v0.most ``` Version `v1` with Candid interface `v1.did` and stable type interface `v1.most`, -```candid file=/count-v1.did +``` candid file=/count-v1.did ``` -```motoko no-repl file=/count-v1.most +```motoko no-repl title="count-v1.most" file=/count-v1.most ``` Version `v2` with Candid interface `v2.did` and stable type interface `v2.most`, -```candid file=/count-v2.did +``` candid file=/count-v2.did ``` -```motoko no-repl file=/count-v2.most +```motoko no-repl title="count-v2.most" file=/count-v2.most ``` Version `v3` with Candid interface `v3.did` and stable type interface `v3.most`: -```candid file=/count-v3.did +``` candid file=/count-v3.did ``` -```motoko no-repl file=/count-v3.most +```motoko no-repl title="count-v3.most" file=/count-v3.most ``` ## Incompatible upgrade @@ -121,7 +120,7 @@ This version is neither compatible to stable type declarations, nor to the Candi - The change in the return type of `read` is also not safe. If the change were accepted, then existing clients of the `read` method, that still expect to receive integers, would suddenly start receiving incompatible floats. -With [enhanced orthogonal persistence](/languages/motoko/fundamentals/actors/orthogonal-persistence/enhanced), Motoko actively rejects any upgrades that require type-incompatible state changes. +With [enhanced orthogonal persistence](./orthogonal-persistence/enhanced.md), Motoko actively rejects any upgrades that require type-incompatible state changes. This is to guarantee that the stable state is always kept safe. @@ -134,7 +133,7 @@ In addition to Motoko's runtime check, `dfx` raises a warning message for these Motoko tolerates Candid interface changes, since these are more likely to be intentional, breaking changes. :::danger -Versions of Motoko using [classical orthogonal persistence](/languages/motoko/fundamentals/actors/orthogonal-persistence/classical) will drop the state and reinitialize the counter with `0.0`, if the `dfx` warning is ignored. +Versions of Motoko using [classical orthogonal persistence](./orthogonal-persistence/classical.md) will drop the state and reinitialize the counter with `0.0`, if the `dfx` warning is ignored. For this reason, users should always heed any compatibility warnings issued by `dfx`. ::: @@ -232,7 +231,7 @@ The stable signature of an actor with a migration function now consists of two o For example, this is the combined signature of the previous example: -```motoko no-repl file=/count-v9.most +```motoko no-repl title="count-v9.most" file=/count-v9.most ``` The second signature is determined solely by the actor's stable variable declarations. @@ -244,7 +243,7 @@ The migration function can be deleted or adjusted on the next upgrade. ## Enhanced stable signatures -When using [enhanced multi-migration](/languages/motoko/fundamentals/actors/enhanced-multi-migration), the compiler produces an **enhanced stable signature** that records the entire migration chain alongside the actor's final stable fields. This extended signature enables the tooling to verify upgrade compatibility across the full history of migrations. +When using [enhanced multi-migration](./enhanced-multi-migration.md), the compiler produces an **enhanced stable signature** that records the entire migration chain alongside the actor's final stable fields. This extended signature enables the tooling to verify upgrade compatibility across the full history of migrations. ### Stable signature versions @@ -252,12 +251,12 @@ Motoko uses three versions of the stable signature format, each corresponding to **Version 1.0.0: Single.** The original format, listing the actor's stable fields. Used when the actor has no migration function. -```motoko no-repl file=/count-v1.most +```motoko no-repl title="count-v1.most" file=/count-v1.most ``` **Version 3.0.0: Pre/Post.** Used when the actor declares a single migration function via `(with migration = ...)`. The signature contains a pre-signature (the fields the migration function consumes from the old actor) and a post-signature (the new actor's stable fields): -```motoko no-repl file=/count-v9.most +```motoko no-repl title="count-v9.most" file=/count-v9.most ``` Fields marked `in` are required inputs that must be present in the previous actor. Fields marked `stable` are carried through or newly declared. @@ -368,10 +367,10 @@ cannot be consumed at new type var Float ``` -With [enhanced orthogonal persistence](/languages/motoko/fundamentals/actors/orthogonal-persistence/enhanced), compatibility errors of stable variables are always detected in the runtime system and if failing, the upgrade is safely rolled back. +With [enhanced orthogonal persistence](./orthogonal-persistence/enhanced.md), compatibility errors of stable variables are always detected in the runtime system and if failing, the upgrade is safely rolled back. :::danger -With [classical orthogonal persistence](/languages/motoko/fundamentals/actors/orthogonal-persistence/classical), however, an upgrade attempt from `v2.wasm` to `v3.wasm` is unpredictable and may lead to partial or complete data loss if the `dfx` warning is ignored. +With [classical orthogonal persistence](./orthogonal-persistence/classical.md), however, an upgrade attempt from `v2.wasm` to `v3.wasm` is unpredictable and may lead to partial or complete data loss if the `dfx` warning is ignored. ::: ## Adding record fields @@ -403,8 +402,8 @@ cannot be consumed at new type Do you want to proceed? yes/No ``` -It is recommended not to continue, as you will lose the state in older versions of Motoko that use [classical orthogonal persistence](/languages/motoko/fundamentals/actors/orthogonal-persistence/classical). -Upgrading with [enhanced orthogonal persistence](/languages/motoko/fundamentals/actors/orthogonal-persistence/enhanced) will trap and roll back, keeping the old state. +It is recommended not to continue, as you will lose the state in older versions of Motoko that use [classical orthogonal persistence](./orthogonal-persistence/classical.md). +Upgrading with [enhanced orthogonal persistence](./orthogonal-persistence/enhanced.md) will trap and roll back, keeping the old state. Adding a new record field to the type of existing stable variable is not supported. The reason is simple: the upgrade would need to supply values for the new field out of thin air. In this example, the upgrade would need to conjure up some value for the `description` field of every existing `card` in `map`. Moreover, allowing adding optional fields is also a problem, as a record can be shared from various variables with different static types, some of them already declaring the added field or adding a same-named optional field with a potentially different type (and/or different semantics). diff --git a/docs/languages/motoko/fundamentals/actors/data-persistence.md b/docs/languages/motoko/fundamentals/actors/data-persistence.md index 598e812f..b97eed2c 100644 --- a/docs/languages/motoko/fundamentals/actors/data-persistence.md +++ b/docs/languages/motoko/fundamentals/actors/data-persistence.md @@ -1,7 +1,8 @@ --- -sidebar_position: 3 -description: "Motoko language documentation" title: "Data persistence" +description: "One key feature of Motoko is its ability to automatically persist the program's state without explicit user instruction." +sidebar: + order: 3 --- One key feature of Motoko is its ability to automatically persist the program's state without explicit user instruction. This is called **orthogonal persistence**. Data persists across transactions and canister upgrades. @@ -80,7 +81,7 @@ __Discouraged and not recommended__: [Pre- and post-upgrade hooks](#preupgrade-a The collection of stable variable declarations in an actor can be summarized in a stable signature. The textual representation of an actor’s stable signature resembles the internals of a Motoko actor type. It specifies the names, types, and mutability of the actor’s stable fields, possibly preceded by relevant Motoko type declarations. -``` motoko no-repl +```motoko no-repl actor { stable x : Nat; stable var y : Int; @@ -120,7 +121,7 @@ When upgrading a canister, it is important to verify that the upgrade can procee - Introducing an incompatible change in stable declarations. - Breaking clients due to a Candid interface change. -With [enhanced orthogonal persistence](/languages/motoko/fundamentals/actors/orthogonal-persistence/enhanced), Motoko rejects incompatible changes of stable declarations during an upgrade attempt. +With [enhanced orthogonal persistence](./orthogonal-persistence/enhanced.md), Motoko rejects incompatible changes of stable declarations during an upgrade attempt. Moreover, `dfx` checks the two conditions before attempting the upgrade and warns users as necessary. A Motoko canister upgrade is safe provided: @@ -129,7 +130,7 @@ A Motoko canister upgrade is safe provided: - The canister’s Motoko stable signature evolves to a stable-compatible one. :::danger -With [classical orthogonal persistence](/languages/motoko/fundamentals/actors/orthogonal-persistence/classical), the upgrade can still fail due to resource constraints. This is problematic as the canister can then not be upgraded. It is therefore strongly advised to test the scalability of upgrades extensively. This does not apply to enhanced orthogonal persistence. +With [classical orthogonal persistence](./orthogonal-persistence/classical.md), the upgrade can still fail due to resource constraints. This is problematic as the canister can then not be upgraded. It is therefore strongly advised to test the scalability of upgrades extensively. This does not apply to enhanced orthogonal persistence. ::: @@ -178,8 +179,8 @@ A cleaner, more maintainable solution, is to declare an explicit migration expre Both of these data migration paths are supported by static and dynamic checks that prevent data loss or corruption. A user may still lose data due to coding errors, so should tread carefully. -For more information, see the [example of explicit migration](/languages/motoko/fundamentals/actors/compatibility#explicit-migration-using-a-migration-function) and the -reference material on [migration expressions](/languages/motoko/reference/language-manual#migration-expressions). +For more information, see the [example of explicit migration](./compatibility.md#explicit-migration-using-a-migration-function) and the +reference material on [migration expressions](../../language-manual.md#migration-expressions). ## Legacy features diff --git a/docs/languages/motoko/fundamentals/actors/enhanced-multi-migration.md b/docs/languages/motoko/fundamentals/actors/enhanced-multi-migration.md index 3d6340a6..1275b77a 100644 --- a/docs/languages/motoko/fundamentals/actors/enhanced-multi-migration.md +++ b/docs/languages/motoko/fundamentals/actors/enhanced-multi-migration.md @@ -1,12 +1,13 @@ --- -sidebar_position: 8 -description: "Motoko language documentation" title: "Enhanced multi-migration" +description: "Enhanced multi-migration lets you manage canister state changes over time through a series of migration modules, each stored in its own file." +sidebar: + order: 8 --- Enhanced multi-migration lets you manage canister state changes over time through a series of migration modules, each stored in its own file. Instead of writing a single inline migration function, one builds up a chain of small, self-contained migrations that the compiler and runtime apply in order. -This approach is especially useful for long-lived canisters whose data shape evolves across many deployments. Each migration captures one logical change: adding a field, renaming a field, changing a type: and the compiler verifies that the entire chain is consistent. +This approach is especially useful for long-lived canisters whose data shape evolves across many deployments. Each migration captures one logical change (adding a field, renaming a field, or changing a type), and the compiler verifies that the entire chain is consistent. ## Overview @@ -17,10 +18,10 @@ With enhanced multi-migration you: 3. Each migration module exports a `public func migration({...}) : {...}` that transforms a subset of stable fields. 4. Pass `--enhanced-migration ./migrations` to `moc` when compiling. -The compiler reads all migration modules in lexicographic order, checks that they compose correctly, and compiles them into the actor. At runtime, only migrations that have not yet been applied are executed: already-applied migrations are skipped automatically. +The compiler reads all migration modules in lexicographic order, checks that they compose correctly, and compiles them into the actor. At runtime, only migrations that have not yet been applied are executed; already-applied migrations are skipped automatically. :::note -Enhanced multi-migration requires enhanced orthogonal persistence. It cannot be combined with the inline `(with migration = ...)` syntax used for [single migration functions](/languages/motoko/fundamentals/actors/compatibility#explicit-migration-using-a-migration-function). +Enhanced multi-migration requires enhanced orthogonal persistence. It cannot be combined with the inline `(with migration = ...)` syntax used for [single migration functions](./compatibility.md#explicit-migration-using-a-migration-function). ::: ## Getting started @@ -52,7 +53,7 @@ module { } ``` -The input record describes which stable fields this migration reads from the current state. The output record describes which fields this migration produces. The input field types must be compatible with the state at that point in the chain, and the output field types must ultimately be compatible with the new actor's declared stable fields. A migration only needs to mention the fields it cares about: all other stable fields are carried through unchanged. +The input record describes which stable fields this migration reads from the current state. The output record describes which fields this migration produces. The input field types must be compatible with the state at that point in the chain, and the output field types must ultimately be compatible with the new actor's declared stable fields. A migration only needs to mention the fields it cares about; all other stable fields are carried through unchanged. ### The actor @@ -71,7 +72,7 @@ actor { } ``` -The initial value of each uninitialized variable is determined entirely by the migration chain. When the canister is first deployed, every migration runs in order and the final state provides the values. On subsequent upgrades, only newly added migrations execute, but the result is the same: the migration chain: not the actor source: is the single source of truth for stable variable values. +The initial value of each uninitialized variable is determined entirely by the migration chain. When the canister is first deployed, every migration runs in order and the final state provides the values. On subsequent upgrades, only newly added migrations execute, but the result is the same: the migration chain (not the actor source) is the single source of truth for stable variable values. The compiler rejects any stable variable that carries an initializer when `--enhanced-migration` is enabled. This prevents ambiguity about whether the value comes from the migration chain or from the inline expression. @@ -256,7 +257,7 @@ Migrations can perform arbitrary computation. For example, splitting a full name ```motoko no-repl // migrations/20250601_000000_SplitName.mo -import Text "mo:base/Text"; +import Text "mo:core/Text"; module { public func migration(old : { name : Text }) : { firstName : Text; lastName : Text } { @@ -412,6 +413,6 @@ moc --enhanced-orthogonal-persistence \ ## See also -- [Data persistence](/languages/motoko/fundamentals/actors/data-persistence) -- [Verifying upgrade compatibility](/languages/motoko/fundamentals/actors/compatibility) -- [Enhanced orthogonal persistence](/languages/motoko/fundamentals/actors/orthogonal-persistence/enhanced) +- [Data persistence](./data-persistence.md) +- [Verifying upgrade compatibility](./compatibility.md) +- [Enhanced orthogonal persistence](./orthogonal-persistence/enhanced.md) diff --git a/docs/languages/motoko/fundamentals/actors/index.md b/docs/languages/motoko/fundamentals/actors/index.md new file mode 100644 index 00000000..9e74ca31 --- /dev/null +++ b/docs/languages/motoko/fundamentals/actors/index.md @@ -0,0 +1,7 @@ +--- +title: "Actors" +sidebar: + order: 3 + label: "Actors" + hidden: true +--- diff --git a/docs/languages/motoko/fundamentals/actors/messaging.md b/docs/languages/motoko/fundamentals/actors/messaging.md index c3c057bd..6810a3e1 100644 --- a/docs/languages/motoko/fundamentals/actors/messaging.md +++ b/docs/languages/motoko/fundamentals/actors/messaging.md @@ -1,14 +1,15 @@ --- -sidebar_position: 4 -description: "Motoko language documentation" title: "Messaging" +description: "ICP enforces rules on when and how canisters communicate." +sidebar: + order: 5 --- ICP enforces rules on when and how [canisters](/concepts/canisters) communicate. Motoko includes static (compile-time) messaging restrictions to help prevent certain execution errors. For example, a canister cannot send messages during installation, which helps avoid errors during deployment. Query functions cannot send messages either, because they run locally and do not trigger updates. Additionally, shared functions cannot be called in a synchronous context since shared calls require asynchronous execution. -Only async contexts support [error handling](/languages/motoko/fundamentals/error-handling) with `try/catch` because messaging errors only occur asynchronously. +Only async contexts support [error handling](../error-handling.md) with `try/catch` because messaging errors only occur asynchronously. In Motoko, an expression is considered to be in an async context if it appears inside an `async` function. Query functions are read-only, so they do not create an async context and therefore cannot use `await` or send messages. diff --git a/docs/languages/motoko/fundamentals/actors/mixins.md b/docs/languages/motoko/fundamentals/actors/mixins.md index cd8b9800..0d677846 100644 --- a/docs/languages/motoko/fundamentals/actors/mixins.md +++ b/docs/languages/motoko/fundamentals/actors/mixins.md @@ -1,6 +1,8 @@ --- title: "Mixins" -description: "Motoko language documentation" +description: "Using mixins to compose reusable actor components in Motoko." +sidebar: + order: 7 --- Mixins allow defining parts of actors in separate re-usable files that can be combined/included into a complete actor. diff --git a/docs/languages/motoko/fundamentals/actors/orthogonal-persistence/classical.md b/docs/languages/motoko/fundamentals/actors/orthogonal-persistence/classical.md index 5d87d27b..efd2e311 100644 --- a/docs/languages/motoko/fundamentals/actors/orthogonal-persistence/classical.md +++ b/docs/languages/motoko/fundamentals/actors/orthogonal-persistence/classical.md @@ -1,7 +1,8 @@ --- -sidebar_position: 3 -description: "Motoko language documentation" title: "Classical orthogonal persistence" +description: "Classical orthogonal persistence is the legacy implementation of Motoko's orthogonal persistence." +sidebar: + order: 3 --- Classical orthogonal persistence is the legacy implementation of Motoko's orthogonal persistence. Classical persistence is deprecated in favor of enhanced orthogonal persistence. @@ -20,7 +21,7 @@ Therefore, it is absolutely necessary to thoroughly test how much data an upgrad Moreover, it is ideal to have a backup plan to rescue data even if upgrades fail, e.g. by controller-privileged data query calls. Another option is to [snapshot](/guides/canister-management/snapshots) the canister before attempting the upgrade. ::: -These issues are solved by [enhanced orthogonal persistence](/languages/motoko/fundamentals/actors/orthogonal-persistence/enhanced). +These issues are solved by [enhanced orthogonal persistence](./enhanced.md). :::note diff --git a/docs/languages/motoko/fundamentals/actors/orthogonal-persistence/enhanced.md b/docs/languages/motoko/fundamentals/actors/orthogonal-persistence/enhanced.md index ba4c49be..ee739b68 100644 --- a/docs/languages/motoko/fundamentals/actors/orthogonal-persistence/enhanced.md +++ b/docs/languages/motoko/fundamentals/actors/orthogonal-persistence/enhanced.md @@ -1,7 +1,8 @@ --- -sidebar_position: 2 -description: "Motoko language documentation" title: "Enhanced orthogonal persistence" +description: "Enhanced orthogonal persistence implements the vision of efficient and scalable orthogonal persistence in Motoko that combines:" +sidebar: + order: 2 --- Enhanced orthogonal persistence implements the vision of efficient and scalable orthogonal persistence in Motoko that combines: @@ -19,8 +20,8 @@ Moreover, it is advised to have a backup possibility for rescuing data even when ::: :::note -[Classical orthogonal persistence](/languages/motoko/fundamentals/actors/orthogonal-persistence/classical) with 32-bit main memory and Candid stabilization was the previous default compilation mode for `moc`. If necessary, it can be re-enabled with compiler flag `--legacy-persistence`. -See [orthogonal persistence modes](/languages/motoko/fundamentals/actors/orthogonal-persistence/overview) for a comparison. +[Classical orthogonal persistence](./classical.md) with 32-bit main memory and Candid stabilization was the previous default compilation mode for `moc`. If necessary, it can be re-enabled with compiler flag `--legacy-persistence`. +See [orthogonal persistence modes](./index.md) for a comparison. ::: ## Design @@ -53,7 +54,7 @@ Compatible changes for immutable types are largely analogous to the allowed Moto The runtime system checks migration compatibility on upgrade, and if not fulfilled, rolls back the upgrade. This compatibility check serves as an additional safety measure on top of the `dfx` warning that can be bypassed by users. -Any more complex change can be performed with programmatic instruction, see [explicit migration](/languages/motoko/fundamentals/actors/data-persistence#explicit-migration). +Any more complex change can be performed with programmatic instruction, see [explicit migration](../data-persistence.md#explicit-migration). ### Migration path When migrating from the old serialization-based stabilization to the new persistent heap, the old data is deserialized one last time from stable memory and then placed in the new persistent heap layout. Once operating on the persistent heap, the system should prevent downgrade attempts to the old serialization-based persistence. diff --git a/docs/languages/motoko/fundamentals/actors/orthogonal-persistence/index.md b/docs/languages/motoko/fundamentals/actors/orthogonal-persistence/index.md new file mode 100644 index 00000000..1373d649 --- /dev/null +++ b/docs/languages/motoko/fundamentals/actors/orthogonal-persistence/index.md @@ -0,0 +1,7 @@ +--- +title: "Orthogonal persistence" +sidebar: + order: 6 + label: "Orthogonal persistence" + hidden: true +--- diff --git a/docs/languages/motoko/fundamentals/actors/orthogonal-persistence/overview.md b/docs/languages/motoko/fundamentals/actors/orthogonal-persistence/overview.md index 51b7da82..b3ebb7cf 100644 --- a/docs/languages/motoko/fundamentals/actors/orthogonal-persistence/overview.md +++ b/docs/languages/motoko/fundamentals/actors/orthogonal-persistence/overview.md @@ -1,7 +1,8 @@ --- -sidebar_position: 1 -description: "Motoko language documentation" title: "What is orthogonal persistence?" +description: "Orthogonal persistence is the ability to for a program to automatically preserve its state across transactions and canister upgrades without requiring manual..." +sidebar: + order: 1 --- Orthogonal persistence is the ability to for a program to automatically preserve its state across transactions and canister upgrades without requiring manual intervention. This means that data persists seamlessly, without the need for a database, stable memory APIs, or specialized stable data structures. @@ -12,9 +13,9 @@ In contrast, other canister development languages like Rust require explicit han Motoko features two implementations for orthogonal persistence: -* [Enhanced orthogonal persistence](/languages/motoko/fundamentals/actors/orthogonal-persistence/enhanced) provides very fast upgrades, scaling independently of the heap size. This is realized by retaining the entire Wasm main memory on an upgrade and simply performing a type-driven upgrade safety check. By using 64-bit address space, it is designed to scale beyond 4 GiB and in the future, offer the same capacity like stable memory. +* [Enhanced orthogonal persistence](./enhanced.md) provides very fast upgrades, scaling independently of the heap size. This is realized by retaining the entire Wasm main memory on an upgrade and simply performing a type-driven upgrade safety check. By using 64-bit address space, it is designed to scale beyond 4 GiB and in the future, offer the same capacity like stable memory. -* [Classical orthogonal persistence](/languages/motoko/fundamentals/actors/orthogonal-persistence/classical) is the old implementation of orthogonal persistence that is superseded by enhanced orthogonal persistence. On an upgrade, the runtime system first serializes the persistent data to stable memory and then deserializes it back again to main memory. While this is both inefficient and unscalable, it exhibits problems on shared immutable data (potentially leading to state explosion), deep structures (call stack overflow) and larger heaps (the implementation limits the stable data to at most 2 GiB). +* [Classical orthogonal persistence](./classical.md) is the old implementation of orthogonal persistence that is superseded by enhanced orthogonal persistence. On an upgrade, the runtime system first serializes the persistent data to stable memory and then deserializes it back again to main memory. While this is both inefficient and unscalable, it exhibits problems on shared immutable data (potentially leading to state explosion), deep structures (call stack overflow) and larger heaps (the implementation limits the stable data to at most 2 GiB). :::note diff --git a/docs/languages/motoko/fundamentals/actors/state.md b/docs/languages/motoko/fundamentals/actors/state.md index dbbf59a9..edf112a9 100644 --- a/docs/languages/motoko/fundamentals/actors/state.md +++ b/docs/languages/motoko/fundamentals/actors/state.md @@ -1,8 +1,8 @@ --- -sidebar_position: 2 -description: "Motoko language documentation" title: "Mutable state" -hide_table_of_contents: true +description: "In Motoko, each actor can use internal mutable state but cannot share it directly with other actors." +sidebar: + order: 2 --- In Motoko, each actor can use internal mutable state but cannot share it directly with other actors. Immutable data, however, can be shared among actors and accessed via their external entry points, which act as shareable functions. diff --git a/docs/languages/motoko/fundamentals/basic-syntax/characters-text.md b/docs/languages/motoko/fundamentals/basic-syntax/characters-text.md index 10260012..0810cbfc 100644 --- a/docs/languages/motoko/fundamentals/basic-syntax/characters-text.md +++ b/docs/languages/motoko/fundamentals/basic-syntax/characters-text.md @@ -1,14 +1,15 @@ --- -sidebar_position: 5 -description: "Motoko language documentation" title: "Characters & text" +description: "The Char type in Motoko represents a single Unicode character delimited with a single quotation mark (')." +sidebar: + order: 5 --- ## Characters The `Char` type in Motoko represents a single Unicode character delimited with a single quotation mark (`'`). -```motoko +```motoko no-repl let letter : Char = 'A'; let symbol : Char = '✮'; @@ -20,7 +21,7 @@ let symbol : Char = '✮'; :::note[Iter] An `Iter` is an object that sequentially produces values of specified type `T` until no more values remain. ::: -``` motoko +```motoko no-repl import Char "mo:core/Char"; func reverse(t: Text) : Text { @@ -36,7 +37,7 @@ reverse("Motoko"); The operator `#` concatenates two `Text` values. -```motoko +```motoko no-repl import Text "mo:core/Text"; import Iter "mo:core/Iter"; import Char "mo:core/Char"; @@ -81,13 +82,13 @@ persistent actor Alternator { Strings of characters, familiar from other languages, are called **text** in Motoko, and represented using the [`Text`](https://mops.one/core/docs/Text) type. A text value is an immutable sequence of Unicode characters delimited with a double quotation mark (`"`). -```motoko +```motoko no-repl let greeting : Text = "Hello, world!"; ``` The `#` operator concatenates two `Text` values: -``` motoko +```motoko no-repl // Concatenating text "ICP " # "❤️" # " Motoko" // "ICP ❤️ Motoko" @@ -95,13 +96,13 @@ The `#` operator concatenates two `Text` values: `t.size()` can be used to return the number of characters in the text `t`. -```motoko +```motoko no-repl "abc".size() == 3 ``` `t.chars()` returns an iterator enumerating the characters in `t`. For example: -```motoko +```motoko no-repl import Char "mo:core/Char"; import Debug "mo:core/Debug"; diff --git a/docs/languages/motoko/fundamentals/basic-syntax/comments.md b/docs/languages/motoko/fundamentals/basic-syntax/comments.md index 27332c67..a2aa6f78 100644 --- a/docs/languages/motoko/fundamentals/basic-syntax/comments.md +++ b/docs/languages/motoko/fundamentals/basic-syntax/comments.md @@ -1,7 +1,8 @@ --- -sidebar_position: 10 -description: "Motoko language documentation" title: "Comments" +description: "Motoko supports single-line, multi-line, and nested comments." +sidebar: + order: 10 --- Motoko supports single-line, multi-line, and nested comments. @@ -44,7 +45,7 @@ Multi-line comments can be nested within each other. ## Resources -- [Comment style guide](/languages/motoko/reference/style-guide#comments) +- [Comment style guide](../../style-guide.md#comments) - [Generating Motoko documentation](/developer-tools/#mo-doc) diff --git a/docs/languages/motoko/fundamentals/basic-syntax/defining-an-actor.md b/docs/languages/motoko/fundamentals/basic-syntax/defining-an-actor.md index 5410897d..a8a95001 100644 --- a/docs/languages/motoko/fundamentals/basic-syntax/defining-an-actor.md +++ b/docs/languages/motoko/fundamentals/basic-syntax/defining-an-actor.md @@ -1,13 +1,13 @@ --- -sidebar_position: 1 -description: "Motoko language documentation" title: "Defining an actor" -hide_table_of_contents: true +description: "In Motoko, an actor is a computational process with its own state and behavior." +sidebar: + order: 1 --- -In Motoko, an **actor** is a computational process with its own [state](/languages/motoko/fundamentals/actors/state) and behavior. Actors are declared with the `actor` keyword. +In Motoko, an **actor** is a computational process with its own [state](../actors/state.md) and behavior. Actors are declared with the `actor` keyword. -Unlike traditional functions or objects in other programming languages, actors operate independently and communicate via [asynchronous](/languages/motoko/fundamentals/actors/actors-async#async--await) messaging. Each actor maintains its own message queue, enabling concurrent execution. +Unlike traditional functions or objects in other programming languages, actors operate independently and communicate via [asynchronous](../actors/actors-async.md#async--await) messaging. Each actor maintains its own message queue, enabling concurrent execution. An actor's state is defined by its private variables, while its behavior is defined by the public functions it exposes to other actors. @@ -28,7 +28,7 @@ Each actor maintains separate queues of incoming messages, one per sender. Messa Since actors process messages independently, multiple actors can handle messages in parallel, enabling concurrent execution across actors. -```motoko name=Main +```motoko no-repl // Declares an actor named Main. persistent actor Main { // Define a private variable called 'count' to track the number of greetings. @@ -53,7 +53,7 @@ persistent actor Main { This code defines an actor that can be deployed on ICP. The actor is declared as `persistent` so that its state, `count`, will be preserved when the actor is upgraded. -Learn more about [persistence](/languages/motoko/fundamentals/actors/data-persistence). +Learn more about [persistence](../actors/data-persistence.md). ::: Another actor can call `Main.greet()` with an argument and await the result: @@ -62,7 +62,7 @@ Another actor can call `Main.greet()` with an argument and await the result: await Main.greet("Programmer"); ``` -A Motoko actor always presents its interface as a suite of named [functions](/languages/motoko/fundamentals/basic-syntax/functions) (also called methods) with defined argument and return types. When Motoko code is compiled, this interface is automatically translated to [Candid](/guides/canister-calls/candid), an interface description language. The Candid description can be consumed by other canisters, including canisters written in another language such as Rust. +A Motoko actor always presents its interface as a suite of named [functions](./functions.md) (also called methods) with defined argument and return types. When Motoko code is compiled, this interface is automatically translated to [Candid](/guides/canister-calls/candid), an interface description language. The Candid description can be consumed by other canisters, including canisters written in another language such as Rust. The above example's corresponding Candid interface can be found below. @@ -76,5 +76,5 @@ service : { ## Resources -- [Actors](/languages/motoko/fundamentals/actors/actors-async) +- [Actors](../actors/actors-async.md) diff --git a/docs/languages/motoko/fundamentals/basic-syntax/functions.md b/docs/languages/motoko/fundamentals/basic-syntax/functions.md index a0bee145..03be2c2d 100644 --- a/docs/languages/motoko/fundamentals/basic-syntax/functions.md +++ b/docs/languages/motoko/fundamentals/basic-syntax/functions.md @@ -1,13 +1,13 @@ --- -sidebar_position: 8 -description: "Motoko language documentation" title: "Functions" -hide_table_of_contents: true +description: "Functions in Motoko can have various attributes, the most fundamental being whether they are public or private." +sidebar: + order: 8 --- Functions in Motoko can have various attributes, the most fundamental being whether they are public or private. Public functions can be called by users or other [canisters](/concepts/canisters), while private functions are only accessible within the program that defines them. -The most basic Motoko [function declaration](/languages/motoko/fundamentals/declarations/function-declarations) is: +The most basic Motoko [function declaration](../declarations/function-declarations.md) is: ```motoko no-repl func exampleFunction() : () {}; @@ -15,7 +15,7 @@ func exampleFunction() : () {}; In objects, modules, and actors, all functions are private by default unless explicitly declared as `public`. -```motoko +```motoko no-repl object Counter { var value = 0; func reset() { value := 0 }; @@ -48,13 +48,13 @@ Shared functions come in several forms: - `shared composite query` functions, which behave like queries but can also call other queries. All shared function, unlike ordinary functions, provide access to the identity of their caller, for applications like access control. -[Learn more about function types](/languages/motoko/fundamentals/types/function-types). +[Learn more about function types](../types/function-types.md). ::: For example, you can rewrite the object above as an actor: -``` motoko +```motoko no-repl persistent actor Digit { var value = 0; func reset() { value := 0 }; @@ -70,7 +70,7 @@ persistent actor Digit { Since the public functions of an actor must be `shared`, you can omit the `shared` keyword: -``` motoko +```motoko no-repl persistent actor Digit { var value = 0; func reset() { value := 0 }; diff --git a/docs/languages/motoko/fundamentals/basic-syntax/identifiers.md b/docs/languages/motoko/fundamentals/basic-syntax/identifiers.md index 739e3cd2..e8b32dd8 100644 --- a/docs/languages/motoko/fundamentals/basic-syntax/identifiers.md +++ b/docs/languages/motoko/fundamentals/basic-syntax/identifiers.md @@ -1,8 +1,8 @@ --- -sidebar_position: 7 -description: "Motoko language documentation" title: "Identifiers" -hide_table_of_contents: true +description: "Identifiers are names used for variables, functions, types, and other entities." +sidebar: + order: 7 --- Identifiers are names used for variables, functions, types, and other entities. They must start with a letter or an underscore and can contain letters, digits, and underscores. @@ -16,4 +16,4 @@ let snake_case_identifier = "for compatibility with other languages"; ## Reserved syntax keywords -Motoko reserves [keywords](/languages/motoko/reference/language-manual#keywords) for its syntax and they cannot be used as identifiers. +Motoko reserves [keywords](../../language-manual.md#keywords) for its syntax and they cannot be used as identifiers. diff --git a/docs/languages/motoko/fundamentals/basic-syntax/imports.md b/docs/languages/motoko/fundamentals/basic-syntax/imports.md index c0cb12a7..5f8a807d 100644 --- a/docs/languages/motoko/fundamentals/basic-syntax/imports.md +++ b/docs/languages/motoko/fundamentals/basic-syntax/imports.md @@ -1,8 +1,8 @@ --- -sidebar_position: 2 -description: "Motoko language documentation" title: "Imports" -hide_table_of_contents: true +description: "In Motoko, related code modules are organized into packages." +sidebar: + order: 2 --- In Motoko, related code modules are organized into packages. Modules can be imported either from named packages or from the local file system using relative paths. The compiler locates packages on the file system based on a command line argument specifying their location. @@ -48,4 +48,4 @@ import { compare } "mo:core/Nat"; import { type Result; mapOk } "mo:core/Result"; ``` -Learn more about [modules and imports](/languages/motoko/fundamentals/basic-syntax/imports). +Learn more about [modules and imports](./imports.md). diff --git a/docs/languages/motoko/fundamentals/basic-syntax/index.md b/docs/languages/motoko/fundamentals/basic-syntax/index.md new file mode 100644 index 00000000..43cc2f78 --- /dev/null +++ b/docs/languages/motoko/fundamentals/basic-syntax/index.md @@ -0,0 +1,7 @@ +--- +title: "Basic syntax" +sidebar: + order: 2 + label: "Basic syntax" + hidden: true +--- diff --git a/docs/languages/motoko/fundamentals/basic-syntax/literals.md b/docs/languages/motoko/fundamentals/basic-syntax/literals.md index eec4035c..94eb047a 100644 --- a/docs/languages/motoko/fundamentals/basic-syntax/literals.md +++ b/docs/languages/motoko/fundamentals/basic-syntax/literals.md @@ -1,8 +1,8 @@ --- -sidebar_position: 6 -description: "Motoko language documentation" title: "Literals" -hide_table_of_contents: true +description: "Literals are constant expressions that require no further evaluation:" +sidebar: + order: 6 --- Literals are constant expressions that require no further evaluation: @@ -19,11 +19,11 @@ Literals are constant expressions that require no further evaluation: You can use literals directly in expressions. -```motoko +```motoko no-repl 100 + 50 ``` ## Resources -- [Literals](/languages/motoko/reference/language-manual#literals) +- [Literals](../../language-manual.md#literals) diff --git a/docs/languages/motoko/fundamentals/basic-syntax/numbers.md b/docs/languages/motoko/fundamentals/basic-syntax/numbers.md index 0e105829..ac63f784 100644 --- a/docs/languages/motoko/fundamentals/basic-syntax/numbers.md +++ b/docs/languages/motoko/fundamentals/basic-syntax/numbers.md @@ -1,7 +1,8 @@ --- -sidebar_position: 4 -description: "Motoko language documentation" title: "Numbers" +description: "The Nat type represents natural numbers, which are all non-negative integers (i.e., 0 and positive numbers)." +sidebar: + order: 4 --- ## Natural numbers @@ -16,7 +17,7 @@ let zero : Nat = 0; Defining a `Nat` with a negative value is a compile time error: -``` motoko +```motoko no-repl let negative : Nat = -1; // Error: Cannot assign a negative value to Nat ``` @@ -47,7 +48,7 @@ let trappingNat8 : Nat8 = 255+1; // trap: arithmetic overflow [`Int`](https://mops.one/core/docs/Int) represents all integers, both positive and negative (e.g., -2, -1, 0, 1, 2). -For scenarios requiring fixed-size integers, Motoko offers bounded variants with specific bit-widths ([`Int8`](https://mops.one/core/docs/Int8), [`Int16`](https://mops.one/core/docs/Int16), [`Int32`](https://mops.one/core/docs/Int32), [`Int64`](https://mops.one/core/docs/Int64)). These types can overflow if their limits are exceeded, resulting in a [runtime error](/languages/motoko/fundamentals/error-handling). +For scenarios requiring fixed-size integers, Motoko offers bounded variants with specific bit-widths ([`Int8`](https://mops.one/core/docs/Int8), [`Int16`](https://mops.one/core/docs/Int16), [`Int32`](https://mops.one/core/docs/Int32), [`Int64`](https://mops.one/core/docs/Int64)). These types can overflow if their limits are exceeded, resulting in a [runtime error](../error-handling.md). ```motoko no-repl let a : Int = -42; @@ -70,7 +71,7 @@ let bigNumber : Int = 999_999_999_999_999; - [`Int32`](https://mops.one/core/docs/Int32) (32-bit signed integer) - [`Int64`](https://mops.one/core/docs/Int64) (64-bit signed integer) -Arithmetic on bounded integers can overflow if their limits are exceeded, resulting in a [runtime error](/languages/motoko/fundamentals/error-handling). +Arithmetic on bounded integers can overflow if their limits are exceeded, resulting in a [runtime error](../error-handling.md). ```motoko no-repl let trappingInt8 : Int8 = 127+1; // trap: arithmetic overflow diff --git a/docs/languages/motoko/fundamentals/basic-syntax/operators.md b/docs/languages/motoko/fundamentals/basic-syntax/operators.md index ac97c665..a422c989 100644 --- a/docs/languages/motoko/fundamentals/basic-syntax/operators.md +++ b/docs/languages/motoko/fundamentals/basic-syntax/operators.md @@ -1,7 +1,8 @@ --- -sidebar_position: 9 -description: "Motoko language documentation" title: "Operators" +description: "Motoko provides various operators for working with numbers, text, and boolean values." +sidebar: + order: 9 --- Motoko provides various operators for working with numbers, text, and boolean values. They can be categorized as follows: @@ -170,13 +171,13 @@ Operators follow precedence rules, meaning that, in the absence of explicit pare For example: -```motoko +```motoko no-repl let result = 10 + 5 * 2; // result = 20 ``` Use parentheses to enforce a different order. -```motoko +```motoko no-repl let result = (10 + 5) * 2; // result = 30 ``` @@ -184,7 +185,7 @@ let result = (10 + 5) * 2; // result = 30 Pipes (`|>`) chain together function calls in a readable way. Instead of nesting function calls, pipes pass the result of one expression as an argument to the next function. The value of the left side of the pipe is referenced on the right side using an underscore (`_`). -```motoko +```motoko no-repl func double(n : Int) : Int { n * 2 }; func increment(n : Int) : Int { n + 1 }; diff --git a/docs/languages/motoko/fundamentals/basic-syntax/printing-values.md b/docs/languages/motoko/fundamentals/basic-syntax/printing-values.md index b59379e7..1d59cd50 100644 --- a/docs/languages/motoko/fundamentals/basic-syntax/printing-values.md +++ b/docs/languages/motoko/fundamentals/basic-syntax/printing-values.md @@ -1,15 +1,15 @@ --- -sidebar_position: 3 -description: "Motoko language documentation" title: "Printing values" -hide_table_of_contents: true +description: "Motoko uses Debug.print to output text to the terminal or a canister's log depending on execution context." +sidebar: + order: 3 --- Motoko uses `Debug.print` to output text to the terminal or a canister's log depending on execution context. It takes a [`Text`](https://mops.one/core/docs/Text) value and returns `()`. `()` is the empty tuple and represents a token or trivial return value. -```motoko +```motoko no-repl import Debug "mo:core/Debug"; Debug.print("Hello, world!"); @@ -17,7 +17,7 @@ Debug.print("Hello, world!"); For debugging purposes, `debug_show` converts most Motoko types into [`Text`](https://mops.one/core/docs/Text). The operator handles most types well, but may not work with cyclic data structures or types containing functions or type parameters. -```motoko +```motoko no-repl import Debug "mo:core/Debug"; Debug.print(debug_show {life = 42} ); // "{life = 42}" @@ -25,7 +25,7 @@ Debug.print(debug_show {life = 42} ); // "{life = 42}" Functions like `Debug.print("Hello, World!")` are considered **impure functions** because they cause a side effect by printing to the console or log. -In contrast, [**pure functions**](/languages/motoko/fundamentals/types/function-types) return values that do not modify output or have other side effects like sending messages. For example `Nat.toText(42)` is pure because it always returns `"42"` with no other effect. +In contrast, [**pure functions**](../types/function-types.md#pure-functions) return values that do not modify output or have other side effects like sending messages. For example `Nat.toText(42)` is pure because it always returns `"42"` with no other effect. ## Resources diff --git a/docs/languages/motoko/fundamentals/basic-syntax/traps.md b/docs/languages/motoko/fundamentals/basic-syntax/traps.md index aa013d68..75b1b11e 100644 --- a/docs/languages/motoko/fundamentals/basic-syntax/traps.md +++ b/docs/languages/motoko/fundamentals/basic-syntax/traps.md @@ -1,21 +1,21 @@ --- -sidebar_position: 12 -description: "Motoko language documentation" title: "Assertions" -hide_table_of_contents: true +description: "An assertion checks a condition at runtime and traps if it fails." +sidebar: + order: 12 --- An assertion checks a condition at runtime and traps if it fails. -```motoko +```motoko no-repl let n = 10; assert n % 2 == 1; // Traps ``` -```motoko +```motoko no-repl let n = 10; assert n % 2 == 0; // Succeeds ``` -Assertions help catch logic errors early, but should not be used for regular [error handling](/languages/motoko/fundamentals/error-handling). +Assertions help catch logic errors early, but should not be used for regular [error handling](../error-handling.md). diff --git a/docs/languages/motoko/fundamentals/basic-syntax/whitespace.md b/docs/languages/motoko/fundamentals/basic-syntax/whitespace.md index 0e0ade53..5cc36c0f 100644 --- a/docs/languages/motoko/fundamentals/basic-syntax/whitespace.md +++ b/docs/languages/motoko/fundamentals/basic-syntax/whitespace.md @@ -1,20 +1,21 @@ --- -sidebar_position: 11 -description: "Motoko language documentation" title: "Whitespace" +description: "Whitespace characters (spaces, tabs, newlines) are generally ignored in Motoko, but are essential for separating syntax components like keywords and identifi..." +sidebar: + order: 11 --- Whitespace characters (spaces, tabs, newlines) are generally ignored in Motoko, but are essential for separating syntax components like keywords and identifiers. Proper use of whitespace enhances code readability. ### Incorrect use of whitespace -```motoko +```motoko no-repl persistent actor Counter{var x : Nat = 0; public func inc(): async Int{x+1; }}; ``` ### Proper whitespace usage -```motoko +```motoko no-repl persistent actor Counter { var x : Nat = 0; public func inc() : async Int { @@ -25,5 +26,5 @@ persistent actor Counter { ## Resources -- [Motoko style guide](/languages/motoko/reference/style-guide) +- [Motoko style guide](../../style-guide.md) diff --git a/docs/languages/motoko/fundamentals/contextual-dot.md b/docs/languages/motoko/fundamentals/contextual-dot.md index fd0b0437..da3bb87e 100644 --- a/docs/languages/motoko/fundamentals/contextual-dot.md +++ b/docs/languages/motoko/fundamentals/contextual-dot.md @@ -1,6 +1,8 @@ --- title: "Contextual dot notation" -description: "Motoko language documentation" +description: "Using contextual dot notation to call module functions with method-like syntax in Motoko." +sidebar: + order: 10 --- Contextual dot notation is a language feature that allows you to call functions from modules using object-oriented style syntax, where a value appears as the receiver of a method call. This feature bridges the gap between Motoko's procedural and object-oriented programming styles. @@ -13,7 +15,7 @@ In Motoko, there are two main approaches to organizing and calling related funct Consider a common operation on data structures. Without contextual dot notation, you would write: -```motoko +```motoko no-repl import Array "mo:core/Array"; let numbers = [1, 2, 3, 4, 5]; @@ -30,7 +32,7 @@ This functional style, while powerful, has some drawbacks: With contextual dot notation, you can rewrite the same code as: -```motoko +```motoko no-repl import Array "mo:core/Array"; let numbers = [1, 2, 3, 4, 5]; @@ -57,7 +59,7 @@ The self parameter is indicated by its position as the first parameter and its t Here's a more comprehensive example using the `Array` module: -```motoko +```motoko no-repl import Array "mo:core/Array"; import Nat "mo:core/Nat"; @@ -121,7 +123,7 @@ While any function can use contextual dot notation based on its first parameter Contextual dot notation works seamlessly with generic types: -```motoko +```motoko no-repl import Array "mo:core/Array"; // These work with any type T @@ -162,4 +164,4 @@ Contextual dot notation has some intentional limitations: ## See also - [Modules and imports](modules-imports) -- [Language reference](/languages/motoko/reference/language-manual#dotted-function-calls) \ No newline at end of file +- [Language reference](../language-manual#dotted-function-calls) \ No newline at end of file diff --git a/docs/languages/motoko/fundamentals/control-flow/basic-control-flow.md b/docs/languages/motoko/fundamentals/control-flow/basic-control-flow.md index e8b852e4..563988f8 100644 --- a/docs/languages/motoko/fundamentals/control-flow/basic-control-flow.md +++ b/docs/languages/motoko/fundamentals/control-flow/basic-control-flow.md @@ -1,7 +1,8 @@ --- -sidebar_position: 1 -description: "Motoko language documentation" title: "Basic control flow" +description: "In Motoko, code normally executes sequentially, evaluating expressions and declarations in order." +sidebar: + order: 1 --- In Motoko, code normally executes sequentially, evaluating expressions and declarations in order. @@ -14,7 +15,7 @@ However, certain constructs can alter the flow of control, such as exiting a blo | `return` | Exits a function and returns a value. | | `if` | Executes a block if the condition is `true`. | | `if/else` | Executes different blocks based on a condition. | -| `switch` | [Pattern matching](/languages/motoko/fundamentals/pattern-matching) for variants, options, results, etc. | +| `switch` | [Pattern matching](../pattern-matching.md) for variants, options, results, etc. | | `let-else` | Destructure a pattern and handle the failure case inline. | | `option block` | Evaluates an expression and wraps the result in an option type, allowing scoped handling of `null` values. | | `label/break` | Allows exiting loops early. | @@ -134,7 +135,7 @@ let o4 = addOpt(null, null); // null Instead of having to switch on the options `n` and `m` in a verbose manner the use of the postfix operator `!` makes it easy to unwrap their values but exit the block with `null` when either is `null`. -A more interesting example of option blocks can be found at the end of the section on [switch](/languages/motoko/fundamentals/control-flow/switch). +A more interesting example of option blocks can be found at the end of the section on [switch](./switch.md). ## `label` and `break` @@ -245,7 +246,7 @@ A `continue` expression skips the remainder of the current iteration in a loop a For example, computing the product we can skip a multiplication when the number is `1`: -``` motoko no-repl +```motoko no-repl func product(numbers : [Int]) : Int { var prod : Int = 1; for (number in numbers.vals()) { @@ -258,7 +259,7 @@ func product(numbers : [Int]) : Int { When you have nested loops and need to continue a specific outer loop, you can use a label: -``` motoko no-repl +```motoko no-repl func product(numbers : [Int]) : Int { var prod : Int = 1; label l for (number in numbers.vals()) { @@ -278,7 +279,7 @@ You can also exit any loop in a function using `return` or (in an asynchronous f ## Function calls -A function call executes a function by passing arguments and receiving a result. In Motoko, function calls can be synchronous (executing immediately within the same [canister](/concepts/canisters)) or [asynchronous](/languages/motoko/fundamentals/actors/actors-async#async--await) (message passing between canisters). Asynchronous calls use `async`/`await` and are essential for inter-canister communication. +A function call executes a function by passing arguments and receiving a result. In Motoko, function calls can be synchronous (executing immediately within the same [canister](/concepts/canisters)) or [asynchronous](../actors/actors-async.md#async--await) (message passing between canisters). Asynchronous calls use `async`/`await` and are essential for inter-canister communication. ```motoko no-repl persistent actor { diff --git a/docs/languages/motoko/fundamentals/control-flow/blocks.md b/docs/languages/motoko/fundamentals/control-flow/blocks.md index f83f630f..ff6ac39e 100644 --- a/docs/languages/motoko/fundamentals/control-flow/blocks.md +++ b/docs/languages/motoko/fundamentals/control-flow/blocks.md @@ -1,7 +1,8 @@ --- -sidebar_position: 4 -description: "Motoko language documentation" title: "Block expressions" +description: "A block expression in Motoko is a sequence of declarations enclosed in { ..." +sidebar: + order: 4 --- A block expression in Motoko is a sequence of declarations enclosed in `{ ... }`. diff --git a/docs/languages/motoko/fundamentals/control-flow/conditionals.md b/docs/languages/motoko/fundamentals/control-flow/conditionals.md index 5a5122cf..8c5f50d3 100644 --- a/docs/languages/motoko/fundamentals/control-flow/conditionals.md +++ b/docs/languages/motoko/fundamentals/control-flow/conditionals.md @@ -1,7 +1,8 @@ --- -sidebar_position: 3 -description: "Motoko language documentation" title: "Conditionals" +description: "Conditionals in Motoko come in two forms: if-expressions and if-statements." +sidebar: + order: 3 --- Conditionals in Motoko come in two forms: **if-expressions** and **if-statements**. @@ -34,7 +35,7 @@ let identity : Text = The result of the `if-else` is assigned to `identity`. Here, both branches have the same type ([`Text`](https://mops.one/core/docs/Text) in this case) as does the entire `if-else`. -``` motoko no-repl +```motoko no-repl let n : Nat = 0; let parity = if (n % 2 == 0) #even else #odd; ``` @@ -42,7 +43,7 @@ Here, the first branch has type `{#even}` and the second branch has type `{#odd} Motoko will infer the common supertype for you, choosing the most specific one possible. If the types are inconsistent and only have the useless common supertype `Any`, Motoko will issue a warning: -``` motoko +```motoko no-repl let n : Nat = 0; let oops = if (n % 2 == 0) #even else 0; ``` diff --git a/docs/languages/motoko/fundamentals/control-flow/index.md b/docs/languages/motoko/fundamentals/control-flow/index.md new file mode 100644 index 00000000..76813607 --- /dev/null +++ b/docs/languages/motoko/fundamentals/control-flow/index.md @@ -0,0 +1,7 @@ +--- +title: "Control flow" +sidebar: + order: 6 + label: "Control flow" + hidden: true +--- diff --git a/docs/languages/motoko/fundamentals/control-flow/loops.md b/docs/languages/motoko/fundamentals/control-flow/loops.md index 5a851a1a..58ed6e91 100644 --- a/docs/languages/motoko/fundamentals/control-flow/loops.md +++ b/docs/languages/motoko/fundamentals/control-flow/loops.md @@ -1,7 +1,8 @@ --- -sidebar_position: 2 -description: "Motoko language documentation" title: "Loops" +description: "In Motoko, loops provide flexible control over repetition, such as iterating over collections, looping while some condition holds, or just looping until an e..." +sidebar: + order: 2 --- @@ -52,7 +53,7 @@ label countLoop loop { A `loop-while` executes the loop body at least once, then repeats as long as the condition remains true. -``` motoko no-repl +```motoko no-repl import Debug "mo:core/Debug"; var count = 0; diff --git a/docs/languages/motoko/fundamentals/control-flow/switch.md b/docs/languages/motoko/fundamentals/control-flow/switch.md index 66c1f54f..34b22ac6 100644 --- a/docs/languages/motoko/fundamentals/control-flow/switch.md +++ b/docs/languages/motoko/fundamentals/control-flow/switch.md @@ -1,13 +1,13 @@ --- -sidebar_position: 5 -description: "Motoko language documentation" title: "Switch" -hide_table_of_contents: true +description: "A switch expression is a control flow construct that, given a value, selects a control flow path based on the pattern or shape of the value." +sidebar: + order: 5 --- A `switch` expression is a control flow construct that, given a value, selects a control flow path based on the pattern or shape of the value. -A switch is constructed from an expression and a sequence of cases. Each case consists of a [pattern](/languages/motoko/fundamentals/pattern-matching) guarding an expression or block that defines a possible branch of execution. +A switch is constructed from an expression and a sequence of cases. Each case consists of a [pattern](../pattern-matching.md) guarding an expression or block that defines a possible branch of execution. Switch evaluates its expression and based on its value, selects the first case whose pattern matches the value. Any identifiers bound by the pattern are available in the selected branch, allowing you to access case-specific data in the branch. @@ -24,7 +24,7 @@ Only the first case of a `switch` expression that matches will execute. The wild The simplest use of switch is to emulate an `if-else` expression: -``` motoko +```motoko no-repl func toText(b : Bool) : Text { switch b { case true "true"; @@ -35,7 +35,7 @@ func toText(b : Bool) : Text { If you add a second case for `true`, Motoko issues a warning that it will never be matched and is unreachable or dead code: -``` motoko +```motoko no-repl func toText(b : Bool) : Text { switch b { case true "true"; @@ -47,7 +47,7 @@ func toText(b : Bool) : Text { If you forget the case for `false`, Motoko will also issue a warning that `false is not covered by any case`: -``` motoko +```motoko no-repl func toText(b : Bool) : Text { switch b { case true "true"; @@ -77,7 +77,7 @@ Above, the example `switch` expressions have only matched against simple constan Here's a simple example of matching against an option: -``` motoko no-repl +```motoko no-repl func value(option : ?T, default : T) : T { switch option { case null default; @@ -92,7 +92,7 @@ If either case is omitted, Motoko will warn that the switch does not cover the ` Here's an example of a nested pattern: -``` motoko no-repl +```motoko no-repl type List = ?(T, List); func size(list : List) : Nat { @@ -111,7 +111,7 @@ In this example, the branches are enclosed in blocks to demonstrate that it is s A more complex example can be found below: -``` motoko no-repl +```motoko no-repl type Exp = {#Lit : Nat; #Div : (Exp, Exp); #If : (Exp, Exp, Exp)}; func eval(e : Exp) : ? Nat { switch e { @@ -146,7 +146,7 @@ eval(expr); Using option blocks this code can be rewritten to reduce the need for nested switches, if that's preferred: -``` motoko no-repl +```motoko no-repl type Exp = {#Lit : Nat; #Div : (Exp, Exp); #If : (Exp, Exp, Exp)}; func eval(e : Exp) : ? Nat { do ? { diff --git a/docs/languages/motoko/fundamentals/declarations/class-declarations.md b/docs/languages/motoko/fundamentals/declarations/class-declarations.md index 72f04a4e..0438118b 100644 --- a/docs/languages/motoko/fundamentals/declarations/class-declarations.md +++ b/docs/languages/motoko/fundamentals/declarations/class-declarations.md @@ -1,10 +1,11 @@ --- -sidebar_position: 4 -description: "Motoko language documentation" title: "Class declarations" +description: "A class in Motoko serves as a blueprint for creating objects that encapsulate both state and behavior." +sidebar: + order: 4 --- -A class in Motoko serves as a blueprint for creating [objects](/languages/motoko/fundamentals/declarations/object-declaration) that encapsulate both [state](/languages/motoko/fundamentals/actors/state) and behavior. It defines fields to hold data and methods to operate on that data. Unlike records and plain objects, classes support constructors, allowing developers to initialize each instance with unique values at creation time. +A class in Motoko serves as a blueprint for creating [objects](./object-declaration.md) that encapsulate both [state](../actors/state.md) and behavior. It defines fields to hold data and methods to operate on that data. Unlike records and plain objects, classes support constructors, allowing developers to initialize each instance with unique values at creation time. Classes in Motoko are not the same as classes in other object oriented programming languages, but they serve the same purpose. Motoko also doesn’t have a `this` or `self` keyword because you can simply call other methods directly by name or name the entire object using an identifier of your choice. @@ -165,5 +166,5 @@ Using this `system` syntax, developers can: - Manually install, upgrade, or reinstall canisters. - Access lower-level canister management features provided by ICP. -[Learn more about actor class management](/languages/motoko/reference/language-manual#actor-class-management). +[Learn more about actor class management](../../language-manual.md#actor-class-management). diff --git a/docs/languages/motoko/fundamentals/declarations/expression-declarations.md b/docs/languages/motoko/fundamentals/declarations/expression-declarations.md index 7e82f078..38bcd4db 100644 --- a/docs/languages/motoko/fundamentals/declarations/expression-declarations.md +++ b/docs/languages/motoko/fundamentals/declarations/expression-declarations.md @@ -1,7 +1,8 @@ --- -sidebar_position: 6 -description: "Motoko language documentation" title: "Expression declarations" +description: "An expression declaration is a declaration that consists of a single expression." +sidebar: + order: 6 --- An expression declaration is a declaration that consists of a single expression. The expression is evaluated solely for its value and side effects. Unlike other declarations, it does not declare any new names. @@ -31,7 +32,7 @@ In Motoko, expressions of type `()` play the role of statements in other languag ## Basic usage -Expression declarations are commonly used for functions or operations that produce side effects, such as printing or modifying [state](/languages/motoko/fundamentals/actors/state). +Expression declarations are commonly used for functions or operations that produce side effects, such as printing or modifying [state](../actors/state.md). ```motoko no-repl Debug.print("Hello, Motoko!"); @@ -65,7 +66,7 @@ The expression `x * 2;` returns a value of type `Nat`, but since it is not assig Motoko supports anonymous functions as a type of expression. -``` motoko no-repl +```motoko no-repl func applyFunction(f : Int -> Int, value : Int) : Int { f(value) }; applyFunction( func (x : Int) : Int { x * 2 } , 2); ``` @@ -75,6 +76,6 @@ This is just an anonymous version of the function named `double` above. The compiler can infer the argument and result types of anonymous functions, when the types are determined from the context, so you can even just write: -``` motoko no-repl +```motoko no-repl applyFunction( func x { x * 2 } , 2); ``` diff --git a/docs/languages/motoko/fundamentals/declarations/function-declarations.md b/docs/languages/motoko/fundamentals/declarations/function-declarations.md index 0255de7e..85e45d1f 100644 --- a/docs/languages/motoko/fundamentals/declarations/function-declarations.md +++ b/docs/languages/motoko/fundamentals/declarations/function-declarations.md @@ -1,7 +1,8 @@ --- -sidebar_position: 2 -description: "Motoko language documentation" title: "Function declarations" +description: "A function in Motoko is a reusable block of code that accepts inputs, performs computations or actions, and optionally returns a result." +sidebar: + order: 2 --- A function in Motoko is a reusable block of code that accepts inputs, performs computations or actions, and optionally returns a result. Functions can be either named or anonymous and may explicitly define the types of their parameters and return values for clarity and type safety. @@ -98,7 +99,7 @@ assert echoTwice("Hello") == "Hello!!"; ## Shared functions in actors -In actors, functions can be marked as `shared` to allow [asynchronous](/languages/motoko/fundamentals/actors/actors-async#async--await) [inter-canister](/references/message-execution-properties) communication. +In actors, functions can be marked as `shared` to allow [asynchronous](../actors/actors-async.md#async--await) [inter-canister](/references/message-execution-properties) communication. ```motoko no-repl actor Counter { @@ -120,7 +121,7 @@ await Counter.getCount(); One key advantage of shared functions in Motoko is that they have access to the caller's Principal, which uniquely identifies the entity (user or another canister) that made the request. This capability allows actors to implement access control by verifying the caller’s identity before performing sensitive operations. -```motoko +```motoko no-repl actor Example { // msg.caller retrieves the Principal of the caller. public shared(msg) func whoAmI() : async Principal { diff --git a/docs/languages/motoko/fundamentals/declarations/index.md b/docs/languages/motoko/fundamentals/declarations/index.md new file mode 100644 index 00000000..8ca6fbd5 --- /dev/null +++ b/docs/languages/motoko/fundamentals/declarations/index.md @@ -0,0 +1,7 @@ +--- +title: "Declarations" +sidebar: + order: 5 + label: "Declarations" + hidden: true +--- diff --git a/docs/languages/motoko/fundamentals/declarations/module-declarations.md b/docs/languages/motoko/fundamentals/declarations/module-declarations.md index 09070099..4f246aaa 100644 --- a/docs/languages/motoko/fundamentals/declarations/module-declarations.md +++ b/docs/languages/motoko/fundamentals/declarations/module-declarations.md @@ -1,12 +1,13 @@ --- -sidebar_position: 7 -description: "Motoko language documentation" title: "Module declarations" +description: "In Motoko, a module is a collection of related types, values, and functions grouped under a single namespace." +sidebar: + order: 7 --- In Motoko, a **module** is a collection of related types, values, and functions grouped under a single namespace. Unlike actors and objects, modules cannot declare mutable state or have side effects during their construction. This restriction makes them ideal for defining code libraries, since you don’t need to worry about the side effects or state implications of importing the same library multiple times or removing an unused one. -Modules are mainly used to build libraries, such as those in the [core package](https://mops.one/core) or packages available through [Mops, the Motoko package manager](https://mops.one). +Modules are mainly used to build libraries, such as those in the [core package](https://mops.one/core/docs/index) or packages available through [Mops, the Motoko package manager](https://mops.one). A module in Motoko can define: @@ -90,7 +91,7 @@ A module can declare classes that use state, provided it doesn't instantiate tho For example, a module can define a class of stateful `Counters` : -``` motoko no-repl +```motoko no-repl module Counters { public class Counter() { var count : Nat = 0; @@ -133,7 +134,7 @@ If you'd prefer to avoid dot notation, you can also import individual values dir This allows you to bind specific names from the module into your local scope, making the code more concise and readable when those values are used frequently. -``` motoko no-repl +```motoko no-repl import {init; identity} "Matrix"; let zero = init(3, 3, 0); diff --git a/docs/languages/motoko/fundamentals/declarations/object-declaration.md b/docs/languages/motoko/fundamentals/declarations/object-declaration.md index ac82e228..71879e0f 100644 --- a/docs/languages/motoko/fundamentals/declarations/object-declaration.md +++ b/docs/languages/motoko/fundamentals/declarations/object-declaration.md @@ -1,20 +1,22 @@ --- -sidebar_position: 3 -description: "Motoko language documentation" title: "Object declarations" +description: "In Motoko, records and objects are both used to group related values using named fields." +sidebar: + order: 3 --- In Motoko, records and objects are both used to group related values using named fields. Record and objects have the same types, but differ in the way they are created and used. The types of record and objects are both described using object types, which are unordered sequences of named fields describing the content and mutability of each public field. Both record and object fields can be accessed by either dot notation or by pattern matching on the names of the fields. While records expressions are ideal for lightweight data representation, objects expressions are more verbose. Object expressions can define full objects in the sense of object-oriented programming where an object is a collection of named fields and methods acting on private state. In Motoko, the private declarations define the encapsulated state, while the public definitions define the object's visible members. -Record and object both use the `var` keyword to define [mutable](/languages/motoko/fundamentals/declarations/variable-declarations) and declarations. Both records and objects support `and` and `with` for merging and updating object fields to create new records and objects. +Record and object both use the `var` keyword to define [mutable](./variable-declarations.md) and declarations. Both records and objects support `and` and `with` for merging and updating object fields to create new records and objects. **Record expressions** are used to construct simple data structures that consist of named fields holding values. The fields can be mutable or immutable. The fields of a record cannot refer to each other by name and are mainly used to store plain data, like the records in a database. Record values can only be declared using `let`: -```motoko name=record no-repl +```motoko no-repl + let Motoko = { name : Text = "Motoko"; var age : Nat = 25; @@ -60,7 +62,8 @@ This defines an object with three public members, the field `name` and the metho Motoko also supports object declarations, which stress the definition of an object by using the `object` keyword in place of `let`: -```motoko name=Object no-repl +```motoko no-repl + object Motoko = { public let name = "Motoko"; var age = 6; diff --git a/docs/languages/motoko/fundamentals/declarations/type-declarations.md b/docs/languages/motoko/fundamentals/declarations/type-declarations.md index 528e11a8..85634a61 100644 --- a/docs/languages/motoko/fundamentals/declarations/type-declarations.md +++ b/docs/languages/motoko/fundamentals/declarations/type-declarations.md @@ -1,7 +1,8 @@ --- -sidebar_position: 5 -description: "Motoko language documentation" title: "Type declarations" +description: "Type declarations are used for defining custom types that improve readability, reusability, and structure of the code." +sidebar: + order: 5 --- Type declarations are used for defining custom types that improve readability, reusability, and structure of the code. They can represent records, variants, objects, or parameterized (generic) types. Motoko enforces productivity and non-expansiveness in type declarations to ensure well-formed, valid types. @@ -34,7 +35,7 @@ type Person = { username : Username; age : Age}; Given a similar type `User`: -``` motoko no-repl +```motoko no-repl type User = { age : Nat; username : Text }; ``` @@ -42,7 +43,7 @@ Structural typing means that the types `User` and `Person` are interchangeable b ## Record types -In Motoko, a type can define a structured [record](/languages/motoko/fundamentals/types/records) with labeled fields. Each field has a specific type, and you can access them using dot notation. Records are useful for organizing related data clearly and safely. +In Motoko, a type can define a structured [record](../types/records.md) with labeled fields. Each field has a specific type, and you can access them using dot notation. Records are useful for organizing related data clearly and safely. ```motoko no-repl // A reusable record @@ -145,8 +146,8 @@ type Seq = ?(T, Seq<[T]>); ## Resources -- [`Record`](/languages/motoko/fundamentals/types/records) -- [`Variant`](/languages/motoko/fundamentals/types/variants) +- [`Record`](../types/records.md) +- [`Variant`](../types/variants.md) diff --git a/docs/languages/motoko/fundamentals/declarations/variable-declarations.md b/docs/languages/motoko/fundamentals/declarations/variable-declarations.md index c852e20d..b40186c0 100644 --- a/docs/languages/motoko/fundamentals/declarations/variable-declarations.md +++ b/docs/languages/motoko/fundamentals/declarations/variable-declarations.md @@ -1,7 +1,8 @@ --- -sidebar_position: 1 -description: "Motoko language documentation" title: "Variable declarations" +description: "In Motoko, variables are declared using:" +sidebar: + order: 1 --- In Motoko, variables are declared using: @@ -25,7 +26,7 @@ The left hand side of a `let` can be also be a more general pattern, naming the For example, the declaration: -``` motoko +```motoko no-repl let (fst, snd) = (1, 2); ``` @@ -56,7 +57,7 @@ Motoko provides special assignment operators that combine assignment with a bina For example, numbers permit a combination of assignment and addition: -``` motoko +```motoko no-repl var count = 2; count += 40; ``` @@ -65,7 +66,7 @@ After the second line, the variable `count` holds `42`. Motoko includes other compound assignments as well, such as `#=`: -``` motoko +```motoko no-repl var text = "Motoko"; text #= " Ghost" ``` diff --git a/docs/languages/motoko/fundamentals/error-handling.md b/docs/languages/motoko/fundamentals/error-handling.md index 43bd0625..e6f34ad3 100644 --- a/docs/languages/motoko/fundamentals/error-handling.md +++ b/docs/languages/motoko/fundamentals/error-handling.md @@ -1,7 +1,8 @@ --- -sidebar_position: 9 -description: "Motoko language documentation" title: "Error handling" +description: "Using Option or Result is the preferred way of signaling errors in Motoko." +sidebar: + order: 9 --- Using `Option` or `Result` is the preferred way of signaling errors in Motoko. They work in both synchronous and asynchronous contexts and make your APIs safer to use by encouraging clients to consider the error cases as well as the success cases. Exceptions should only be used to signal unexpected error states. @@ -33,7 +34,7 @@ For this reason, option types should only be used for errors when there's just o While options are a built-in type, the `Result` is defined as a variant type like so: -``` motoko no-repl +```motoko no-repl type Result = { #ok : Ok; #err : Err } ``` @@ -70,7 +71,7 @@ With a `Result` type, you can use pattern matching to handle both success and er Sometimes you need to convert between `Option` and `Result` types. For example, a HashMap lookup returns `null` on failure (an `Option`), but if the caller has more context, they can turn that failure into a meaningful `Result` with an error message. On the other hand, sometimes you don’t need the extra detail from a `Result` and just want to convert any error (`#err`) into `null`. -The [core](https://github.com/dfinity/motoko-core) package provides `fromOption` and `toOption` functions in the `Result` module that make converting between these two types easy. +The [core](https://github.com/caffeinelabs/motoko-core) package provides `fromOption` and `toOption` functions in the `Result` module that make converting between these two types easy. ## Error reporting with `Error` (asynchronous errors) @@ -94,7 +95,7 @@ Function callsite: ## Traps -Traps immediately stop execution and roll back [state](/languages/motoko/fundamentals/actors/state). They are used for fatal errors that cannot be recovered. +Traps immediately stop execution and roll back [state](./actors/state.md). They are used for fatal errors that cannot be recovered. ```motoko no-repl import Runtime "mo:core/Runtime"; diff --git a/docs/languages/motoko/fundamentals/hello-world.md b/docs/languages/motoko/fundamentals/hello-world.md index 2576ae72..d910eea2 100644 --- a/docs/languages/motoko/fundamentals/hello-world.md +++ b/docs/languages/motoko/fundamentals/hello-world.md @@ -1,15 +1,15 @@ --- -sidebar_position: 1 -description: "Motoko language documentation" title: "Hello, world!" -hide_table_of_contents: true +description: "\"Hello, world!\" is a common starting point used to showcase a programming language's basic syntax." +sidebar: + order: 1 --- "Hello, world!" is a common starting point used to showcase a programming language's basic syntax. Below is an example of "Hello, world!" written in Motoko: -```motoko +```motoko no-repl // If an actor is declared with the persistent keyword, all private declarations are considered stable by default persistent actor HelloWorld { // We store the greeting in a stable variable such that it gets persisted over canister upgrades. @@ -29,12 +29,12 @@ persistent actor HelloWorld { In this example: -1. The code begins by defining an [actor](/languages/motoko/fundamentals/actors/actors-async) named `HelloWorld`. In Motoko, an actor is an object capable of maintaining state and communicating with other entities via message passing. +1. The code begins by defining an [actor](./actors/actors-async.md) named `HelloWorld`. In Motoko, an actor is an object capable of maintaining state and communicating with other entities via message passing. -2. It then declares the variable `greeting`. This is a [stable variable](/languages/motoko/fundamentals/types/stable-types) because the actor is declared with the keyword `persistent`. Stable variables are used to store data that persists across canister upgrades. [Read more about canister upgrades.](/guides/canister-management/lifecycle) +2. It then declares the variable `greeting`. This is a [stable variable](./types/stable-types.md) because the actor is declared with the keyword `persistent`. Stable variables are used to store data that persists across canister upgrades. [Read more about canister upgrades.](/guides/canister-management/lifecycle#upgrade-a-canister) -3. An [update method](/concepts/canisters) named `setGreeting` is used to modify the canister’s state. This method specifically updates the value stored in `greeting`. +3. An [update method](/concepts/canisters#update-calls) named `setGreeting` is used to modify the canister’s state. This method specifically updates the value stored in `greeting`. -4. Finally, a [query method](/concepts/canisters) named `greet` is defined. Query methods are read-only and return information from the canister without changing its state. This method returns the current `greeting` value, followed by the input text. The method body produces a response by concatenating `"Hello, "` with the input `name`, followed by an exclamation point. +4. Finally, a [query method](/concepts/canisters#query-calls) named `greet` is defined. Query methods are read-only and return information from the canister without changing its state. This method returns the current `greeting` value, followed by the input text. The method body produces a response by concatenating `"Hello, "` with the input `name`, followed by an exclamation point. -[Learn more about actors and basic syntax](/languages/motoko/fundamentals/basic-syntax/defining-an-actor). \ No newline at end of file +[Learn more about actors and basic syntax](./basic-syntax/defining-an-actor.md). \ No newline at end of file diff --git a/docs/languages/motoko/fundamentals/implicit-parameters.md b/docs/languages/motoko/fundamentals/implicit-parameters.md index 1339f1a8..c3935854 100644 --- a/docs/languages/motoko/fundamentals/implicit-parameters.md +++ b/docs/languages/motoko/fundamentals/implicit-parameters.md @@ -1,6 +1,8 @@ --- title: "Implicit parameters" -description: "Motoko language documentation" +description: "Using implicit parameters to pass values to functions without explicit arguments in Motoko." +sidebar: + order: 11 --- ## Overview @@ -27,7 +29,7 @@ The `implicit` marker on the type of parameter `compare` indicates the call-site A function can declare more than one implicit parameter, even of the same name. -```motoko +```motoko no-repl func show( self: (T, U), toTextT : (implicit : (toText : T -> Text)), @@ -44,7 +46,7 @@ The inner name (under `implicit`) overrides the local name of the parameter in t When calling a function with implicit parameters, you can omit the implicit arguments if the compiler can infer them: -```motoko +```motoko no-repl import Map "mo:core/Map"; import Nat "mo:core/Nat"; @@ -69,13 +71,13 @@ An ambiguous call can always be disambiguated by supplying the explicit argument ### Contextual dot notation -Implicit parameters dovetail nicely with [contextual dot notation](/languages/motoko/fundamentals/contextual-dot). +Implicit parameters dovetail nicely with [contextual dot notation](contextual-dot.md). The dot notation and implicit arguments can be used in conjunction to shorten code. For example, since the first parameter of `Map.add` is called `self`, we can both use `map` as the receiver of `add` "method" calls and omit the tedious `compare` argument: -```motoko +```motoko no-repl import Map "mo:core/Map"; import Nat "mo:core/Nat"; @@ -95,7 +97,7 @@ The primary use case for implicit arguments is simplifying code that uses maps a ### Map Example -```motoko +```motoko no-repl import Map "mo:core/Map"; import Nat "mo:core/Nat"; @@ -120,7 +122,7 @@ let item2 = inventory.get(102); ### Set example The core `Set` type also takes advantage of implicit `compare` parameters. -```motoko +```motoko no-repl import Set "mo:core/Set"; import Text "mo:core/Text"; @@ -141,7 +143,7 @@ let hasTag2 = tags.contains("urgent"); Implicit arguments make imperative collection operations much cleaner: -```motoko +```motoko no-repl import Map "mo:core/Map"; import Text "mo:core/Text"; @@ -215,7 +217,7 @@ module MyArray { With derivation, the compiler handles this automatically. It recognizes that `Array.compare`, after removing its implicit `compare` parameter and instantiating `T := Nat`, has the right type. It then recursively resolves the inner implicit (`Nat.compare`) and synthesizes the wrapper for you. -This works transitively: a `compare` for `[[Nat]]` is derived via `Array.compare<[Nat]>`, which needs `[Nat]` compare, which is derived via `Array.compare`, which needs `Nat.compare`: all resolved automatically. +This works transitively: a `compare` for `[[Nat]]` is derived via `Array.compare<[Nat]>`, which needs `[Nat]` compare, which is derived via `Array.compare`, which needs `Nat.compare`, all resolved automatically. The resolution depth is bounded to guarantee termination. If you encounter a depth limit, you can increase it with `--implicit-derivation-depth` or provide the argument explicitly. @@ -239,7 +241,7 @@ Other implicit parameters declared by the core library are `equals : (implicit : You can always provide implicit arguments explicitly when needed: -```motoko +```motoko no-repl import Map "mo:core/Map"; import Nat "mo:core/Nat"; import {type Order} "mo:core/Order"; @@ -264,7 +266,7 @@ This is useful when: To use implicit arguments with your own custom types, define a comparison function: -```motoko +```motoko no-repl import Map "mo:core/Map"; import Text "mo:core/Text"; import {type Order} "mo:core/Order"; @@ -306,7 +308,7 @@ let email = directory.get({ name = "Alice"; age = 30 }); Existing code with explicit comparison functions will continue to work. You can adopt implicit arguments gradually: -```motoko +```motoko no-repl import Map "mo:core/Map"; import Nat "mo:core/Nat"; @@ -328,4 +330,4 @@ Implicit arguments are resolved at compile time. ## See also -- [Language reference](/languages/motoko/reference/language-manual#function-calls) +- [Language reference](../language-manual#function-calls) diff --git a/docs/languages/motoko/fundamentals/modules-imports.md b/docs/languages/motoko/fundamentals/modules-imports.md index 33fb18b9..d2adaccb 100644 --- a/docs/languages/motoko/fundamentals/modules-imports.md +++ b/docs/languages/motoko/fundamentals/modules-imports.md @@ -1,7 +1,8 @@ --- -sidebar_position: 7 -description: "Motoko language documentation" title: "Modules and imports" +description: "Motoko minimizes built-in types and operations, relying on a core package of modules to provide essential functionality." +sidebar: + order: 7 --- Motoko minimizes built-in types and operations, relying on a core package of modules to provide essential functionality. This modular approach keeps the language simple. @@ -28,7 +29,7 @@ The `mo:` prefix identifies a Motoko module. The declaration does not include th You can also selectively import and rename a subset of named values and types from a module by using the object pattern syntax: -``` motoko +```motoko no-repl import { type List; get; foldLeft = fold } "mo:core/List"; ``` @@ -48,7 +49,7 @@ In this scenario, you might place all three files in the same directory and use For example, the `main.mo` contains the following lines to reference the modules in the same directory: -``` motoko no-repl +```motoko no-repl import Types "types"; import Utils "utils"; ``` @@ -61,7 +62,7 @@ You can also import modules from other packages or from directories other than t For example, the following lines import modules from a `redraw` package that is defined as a dependency: -``` motoko no-repl +```motoko no-repl import Render "mo:redraw/Render"; import Mono5x5 "mo:redraw/glyph/Mono5x5"; ``` @@ -146,7 +147,7 @@ When importing from another canister, the canister must be listed as a dependenc ## Importing actor classes -When imported, an [actor](/languages/motoko/fundamentals/actors/actors-async) class provides a type definition describing the class interface and a function that returns an instance of the class. +When imported, an [actor](./actors/actors-async.md) class provides a type definition describing the class interface and a function that returns an instance of the class. For example, if you define the following actor class: @@ -183,7 +184,7 @@ persistent actor CountToTen { }; ``` -`Counters.Counter(1)` installs a new counter on the network. Installation is [asynchronous](/languages/motoko/fundamentals/actors/actors-async#async--await), so the result is awaited. If the actor class is not named, it will result in a bad import error because actor class imports cannot be anonymous. +`Counters.Counter(1)` installs a new counter on the network. Installation is [asynchronous](./actors/actors-async.md#async--await), so the result is awaited. If the actor class is not named, it will result in a bad import error because actor class imports cannot be anonymous. ## Importing `Blob` values diff --git a/docs/languages/motoko/fundamentals/pattern-matching.md b/docs/languages/motoko/fundamentals/pattern-matching.md index d8d5bf67..891e004a 100644 --- a/docs/languages/motoko/fundamentals/pattern-matching.md +++ b/docs/languages/motoko/fundamentals/pattern-matching.md @@ -1,7 +1,8 @@ --- -sidebar_position: 8 -description: "Motoko language documentation" title: "Pattern matching" +description: "Pattern matching in Motoko is a language feature that makes it easy to test and break down complex data structures." +sidebar: + order: 8 --- Pattern matching in Motoko is a language feature that makes it easy to test and break down complex data structures. It is commonly used in `switch` expressions to extract and work with parts of a value. @@ -44,7 +45,7 @@ To prevent runtime errors when no `switch` case matches, the Motoko compiler per Consider the following function call: -```motoko +```motoko no-repl let name : Text = fullName({ first = "Motoko"; mid = "X"; last = "Ghost" }); ``` @@ -52,7 +53,7 @@ This creates a record with three fields and passes it to the `fullName` function Now, look at the function itself: -```motoko +```motoko no-repl func fullName({ first : Text; mid : Text; last : Text }) : Text { first # " " # mid # " " # last }; @@ -60,7 +61,7 @@ func fullName({ first : Text; mid : Text; last : Text }) : Text { Here, the input record is*destructured. Its fields are matched and their values are assigned to the variables `first`, `mid`, and `last`, which are then used in the function body. This example uses name punning, where the field name (e.g., `first`) is reused as the variable name. A more flexible pattern lets you give the value a different name, like this: -```motoko +```motoko no-repl mid = m : Text ``` diff --git a/docs/languages/motoko/fundamentals/types/advanced-types.md b/docs/languages/motoko/fundamentals/types/advanced-types.md index 47aa3982..eed45d7a 100644 --- a/docs/languages/motoko/fundamentals/types/advanced-types.md +++ b/docs/languages/motoko/fundamentals/types/advanced-types.md @@ -1,16 +1,17 @@ --- -sidebar_position: 12 -description: "Motoko language documentation" title: "Advanced types" +description: "Advanced type features enable more flexible and expressive type definitions, including structural equality, generic types, subtyping, recursive types, and ty..." +sidebar: + order: 12 --- Advanced type features enable more flexible and expressive type definitions, including structural equality, generic types, subtyping, recursive types, and type bounds. ## Structural equality -Structural equality determines whether two values are equal based on their contents. This applies to immutable data structures, such as [records](/languages/motoko/fundamentals/types/records) and [variants](/languages/motoko/fundamentals/types/variants), but does not apply to mutable structures for safety reasons. +Structural equality determines whether two values are equal based on their contents. This applies to immutable data structures, such as [records](./records.md) and [variants](./variants.md), but does not apply to mutable structures for safety reasons. -```motoko +```motoko no-repl type Point = { x : Int; y : Int }; let p1 : Point = { x = 1; y = 2 }; @@ -23,7 +24,7 @@ Even though `p1` and `p2` are distinct objects, they are considered equal becaus This remains true even if different fields are added to the point values, since the `==` on `Point` values only considers the `x` and `y` fields and ignores other fields. -```motoko +```motoko no-repl type Point = { x : Int; y : Int }; let p1 : Point = { x = 1; y = 2; z = 3 }; @@ -34,9 +35,9 @@ p1 == p2; // true (structural equality at type `Point`) ## Generic types -Generic types are used to define type parameters that work with multiple data types, commonly used in [functions](/languages/motoko/fundamentals/types/function-types), [classes](/languages/motoko/fundamentals/types/objects-classes), and data structures. +Generic types are used to define type parameters that work with multiple data types, commonly used in [functions](./function-types.md), [classes](./objects-classes.md), and data structures. -```motoko +```motoko no-repl // Generic function func identity(x : T) : T { return x; @@ -47,7 +48,7 @@ identity(42); // num is Nat A generic class can store any type while maintaining type safety: -```motoko +```motoko no-repl class Box(value : T) { public func open() : T { value }; }; @@ -70,7 +71,7 @@ This defines a recursive type for representing a linked list of natural number. - `?(head, tail)`, where `head` is a `Nat` and `tail` is another `List`. -```motoko +```motoko no-repl ?(1, ?(2, ?(3, null))) // A list: 1 → 2 → 3 ``` @@ -88,7 +89,7 @@ Reversing a linked list involves iterating through the list and prepending each Non-parameterized type: -```motoko name=List +```motoko no-repl // Lists of naturals type List = ?(Nat, List); @@ -111,14 +112,14 @@ func reverseNat(l : List) : List { }; ``` -```motoko _include=List no-repl +```motoko no-repl let numbers : List = ?(1, ?(2, ?(3, null))); reverseNat(numbers); // ?(3, ?(2, ?(1, null))) ``` Parameterized: -```motoko name=GenList +```motoko no-repl // Lists of naturals type List = ?(T, List); @@ -144,13 +145,13 @@ These type and function definitions generalize the previous code to work not jus You can reverse a list of numbers. -``` motoko _include=GenList no-repl +```motoko no-repl let numbers : List = ?(1, ?(2, ?(3, null))); reverse(numbers); // ?(3, ?(2, ?(1, null))) ``` But you can also reverse a list of characters: -```motoko _include=GenList no-repl +```motoko no-repl let chars : List = ?('a', ?('b', ?('c', null))); reverse(numbers); // ?('c', ?('b', ?('a', null))) @@ -171,7 +172,7 @@ This approach balances the flexibility of generic programming with the safety of The following examples illustrate this behavior: -```motoko +```motoko no-repl func printName(x : T): Text { debug_show(x.name); }; @@ -180,13 +181,13 @@ let ghost = { name = "Motoko"; age = 30 }; printName(ghost); // Allowed since 'ghost' has a 'name' field. ``` -In the example above, `T <: { name : Text }` requires that any type used for `T` must be a subtype of the [record](/languages/motoko/fundamentals/types/records) `{ name : Text }`, that is, it must have at least a `name` field of type [`Text`](https://mops.one/core/docs/Text). Extra fields are permitted, but the `name` field is mandatory. +In the example above, `T <: { name : Text }` requires that any type used for `T` must be a subtype of the [record](./records.md) `{ name : Text }`, that is, it must have at least a `name` field of type [`Text`](https://mops.one/core/docs/Text). Extra fields are permitted, but the `name` field is mandatory. Type bounds are not limited to records. In general, the notation `T <: A` in a parameter declaration mandates that any type provided for type parameter `T` must be a subtype of the specified type `A`. For example, it is possible to constrain a generic type to be a subtype of a primitive type. -```motoko name=max +```motoko no-repl func max(x : T, y : T) : T { if (x <= y) y else x }; @@ -197,7 +198,7 @@ Here, `T <: Int` constrains `T` to be a subtype of [`Int`](https://mops.one/core But the function can also be used to return the maximum of two `Nat`s and still produce a `Nat` (not an `Int`). -```motoko _include=max no-repl +```motoko no-repl max(5, 10); // returns 10 : Nat ``` @@ -208,7 +209,7 @@ The *actor reference* expression `actor ` compute a reference to an actor f A simple example of using actor references is to access the management canister with textual address `"aaaaa-aa"`. Amongst other things, it has a method `raw_rand` for generating cryptographically random bytes as a `Blob`. -```motoko +```motoko no-repl persistent actor Coin { public func flip() : async Bool { let managementCanister = actor "aaaaa-aa" : actor { raw_rand : () -> async Blob }; @@ -220,7 +221,7 @@ persistent actor Coin { A variation computes the textual canister identifier from a given principal. A call to `flipWith(p)` will succeed is called with `Principal.fromBlob("aaaaa-aa")`, but may fail with another argument, if the canister does not exist or does not have a `raw_rand` function: -```motoko +```motoko no-repl import Principal "mo:core/Principal"; persistent actor Coin { diff --git a/docs/languages/motoko/fundamentals/types/function-types.md b/docs/languages/motoko/fundamentals/types/function-types.md index 2d2fdb0d..3c73ab2e 100644 --- a/docs/languages/motoko/fundamentals/types/function-types.md +++ b/docs/languages/motoko/fundamentals/types/function-types.md @@ -1,7 +1,8 @@ --- -sidebar_position: 3 -description: "Motoko language documentation" title: "Function types" +description: "Functions are reusable chunks of code that perform a specific task." +sidebar: + order: 3 --- Functions are reusable chunks of code that perform a specific task. A function is defined with a name and optional parameters, then returns a defined result. A function can also specify a return type for the value it produces. @@ -29,12 +30,12 @@ Motoko provides different types of functions based on where in the program they | Keyword | Function | |-------------|--------------| | `shared` | Used to enable async communication between actors. Exposes the caller’s identity. | -| `async` | Runs the function [asynchronously](/languages/motoko/fundamentals/actors/actors-async#async--await) and returns its result in a future. | -| `query` | Optimized for reading data but cannot modify [state](/languages/motoko/fundamentals/actors/state). | +| `async` | Runs the function [asynchronously](../actors/actors-async.md#async--await) and returns its result in a future. | +| `query` | Optimized for reading data but cannot modify [state](../actors/state.md). | ## Function comparison -| Function type | Mutates [state](/languages/motoko/fundamentals/actors/state) | Calls updates | Calls queries | Asynchronous | External calls | +| Function type | Mutates [state](../actors/state.md) | Calls updates | Calls queries | Asynchronous | External calls | |------------------------------|---------------|------------------|------------------|---------------|---------------| | Local (synchronous) | Yes | No | No | No | No | | Local (asynchronous) | Yes | Yes | Yes | Yes | No | @@ -42,11 +43,11 @@ Motoko provides different types of functions based on where in the program they | Shared query | No | No | No | Yes | Yes | | Shared composite query | No | No | Yes | Yes | Yes | -## Local functions +## Local functions {#pure-functions} -Local functions run within the canister's [actor](/languages/motoko/fundamentals/actors/actors-async). They cannot call other [canisters](/concepts/canisters). Local functions are cheap to call and execute synchronously. +Local functions run within the canister's [actor](../actors/actors-async.md). They cannot call other [canisters](/concepts/canisters). Local functions are cheap to call and execute synchronously. -```motoko +```motoko no-repl persistent actor CommonDivisor{ func gcd(a : Nat, b : Nat) : Nat { var x = a; @@ -72,7 +73,7 @@ The type of `gcd` is `(Nat, Nat) -> Nat` indicating that it expects a pair of na Generic functions allow the use of type parameters, making them more flexible for using different data types. -```motoko name=swap +```motoko no-repl func swap(t : T, u : U) : (U, T) { (u, t) }; @@ -163,7 +164,7 @@ persistent actor Account { The deposit function has type `: shared Nat -> async Nat`. Consider this code: -``` motoko +```motoko no-repl let b1 = await Account.deposit(50); let b2 = await Account.deposit(50); (b1,b2) @@ -173,7 +174,7 @@ The second call increments the balance from `50` to `100`, returning `100`. Since `Account.deposit` is asynchronous, its results are returned in futures of type `async Nat`. Calling `await` on each future extracts the results of the calls when they become available (so `b1` is `50` and `b2` is `100`). -**Example use case**: Transactions, user [state](/languages/motoko/fundamentals/actors/state) updates, or anything that modifies persistent data. +**Example use case**: Transactions, user [state](../actors/state.md) updates, or anything that modifies persistent data. ### One-way functions @@ -193,7 +194,7 @@ persistent actor Account { Calling `Account.credit(100)` updates the balance by `100`; -``` motoko +```motoko no-repl Account.credit(100); ``` @@ -204,7 +205,7 @@ Again, the shared keyword is optional. Note that `Account.credit(100` just retur ## Query functions -[Query](/concepts/canisters) functions are designed for retrieving data. They cannot permanently update [state](/languages/motoko/fundamentals/actors/state) and execute faster than [update](/concepts/canisters) functions because they do not go through consensus. Query functions are identified with the `query` keyword. Any function without the `query` keyword is an [update](/concepts/canisters) function. +[Query](/concepts/canisters#query-calls) functions are designed for retrieving data. They cannot permanently update [state](../actors/state.md) and execute faster than [update](/concepts/canisters#update-calls) functions because they do not go through consensus. Query functions are identified with the `query` keyword. Any function without the `query` keyword is an [update](/concepts/canisters#update-calls) function. ```motoko no-repl public query func greet(name : Text) : async Text { @@ -236,7 +237,7 @@ persistent actor Account { The `getBalance` function has function type `shared query () -> async Nat`. -**Example use case:** Fetching data quickly without modifying the canister [state](/languages/motoko/fundamentals/actors/state). +**Example use case:** Fetching data quickly without modifying the canister [state](../actors/state.md). ### Composite queries @@ -305,7 +306,7 @@ Functions can accept multiple arguments and return multiple results by enclosing ### Using a record as an argument -Multiple values can be passed as a single argument by encapsulating them within a [record](/languages/motoko/fundamentals/types/records) type. +Multiple values can be passed as a single argument by encapsulating them within a [record](./records.md) type. ```motoko no-repl func userName(user: { name : Text; age : Nat }) : Text { diff --git a/docs/languages/motoko/fundamentals/types/immutable-arrays.md b/docs/languages/motoko/fundamentals/types/immutable-arrays.md index 7366bdc4..92a58371 100644 --- a/docs/languages/motoko/fundamentals/types/immutable-arrays.md +++ b/docs/languages/motoko/fundamentals/types/immutable-arrays.md @@ -1,10 +1,11 @@ --- -sidebar_position: 8 -description: "Motoko language documentation" title: "Immutable arrays" +description: "Immutable arrays are fixed-size, read-only data structures that allow efficiently storing elements of the same type." +sidebar: + order: 8 --- -Immutable arrays are fixed-size, read-only data structures that allow efficiently storing elements of the same type. Unlike [mutable arrays](/languages/motoko/fundamentals/types/mutable-arrays), they cannot be modified after creation, ensuring data integrity and predictable behavior. +Immutable arrays are fixed-size, read-only data structures that allow efficiently storing elements of the same type. Unlike [mutable arrays](./mutable-arrays.md), they cannot be modified after creation, ensuring data integrity and predictable behavior. ## When to use immutable arrays @@ -20,7 +21,7 @@ If the number of elements may change, collections like `List` is a better choice Immutable arrays are declared using square brackets `[T]`. The type of the array is specified within the square brackets, e.g., `[Nat]` declares an immutable array of natural numbers. -```motoko +```motoko no-repl let arr : [Nat] = [1, 2, 3, 4, 5]; ``` @@ -30,9 +31,9 @@ The size of an array `a` is available as `a.size()`, a `Nat`. Array elements are zero-indexed, allowing indices `0` up to `a.size() - 1`. -Attempting to access an array's index that does not exist will cause a [trap](/languages/motoko/fundamentals/basic-syntax/traps). Attempting to modify an immutable array will result in an error `expected mutable assignment target(M0073)`. +Attempting to access an array's index that does not exist will cause a [trap](../basic-syntax/traps.md). Attempting to modify an immutable array will result in an error `expected mutable assignment target(M0073)`. -```motoko +```motoko no-repl import Debug "mo:core/Debug"; let numbers : [Nat] = [10, 20, 30]; @@ -64,7 +65,7 @@ The `array.keys()` function returns an iterator that is used to iterate over the A `for` loop can also be used to iterate over an array by accessing elements via their index. -```motoko +```motoko no-repl import Debug "mo:core/Debug"; let arr : [Nat] = [1, 2, 3, 4, 5]; @@ -89,7 +90,7 @@ mutableCopy[0] := 10; Motoko supports passing collections to a function, ensuring that all arguments are handled as a collection rather than individual parameters. -```motoko +```motoko no-repl import Debug "mo:core/Debug" func printAllStrings(strings : [Text]) { @@ -134,7 +135,7 @@ Unlike some languages, Motoko does not compare arrays by reference; instead, it The [`Array`](https://mops.one/core/docs/Array) module in Motoko's core package contains built-in functions for mapping over elements, filtering values, and summing numerical arrays. -```motoko +```motoko no-repl import Array "mo:core/Array"; func transformArray() : [Nat] { @@ -148,7 +149,7 @@ transformArray(); To demonstrate nested immutable arrays, consider the following: -A chessboard is a fixed `8×8` grid. Using immutable arrays to represent the initial [state](/languages/motoko/fundamentals/actors/state) of the board ensures that the setup remains unchanged, preventing accidental modifications. This is useful because the starting position of pieces in chess is fixed, and any changes should be intentional, such as when making a move. Immutable arrays provide stability and help maintain the integrity of the initial board [state](/languages/motoko/fundamentals/actors/state). +A chessboard is a fixed `8×8` grid. Using immutable arrays to represent the initial [state](../actors/state.md) of the board ensures that the setup remains unchanged, preventing accidental modifications. This is useful because the starting position of pieces in chess is fixed, and any changes should be intentional, such as when making a move. Immutable arrays provide stability and help maintain the integrity of the initial board [state](../actors/state.md). ```motoko no-repl import Array "mo:core/Array"; diff --git a/docs/languages/motoko/fundamentals/types/index.md b/docs/languages/motoko/fundamentals/types/index.md new file mode 100644 index 00000000..b9acc74b --- /dev/null +++ b/docs/languages/motoko/fundamentals/types/index.md @@ -0,0 +1,7 @@ +--- +title: "Types" +sidebar: + order: 4 + label: "Types" + hidden: true +--- diff --git a/docs/languages/motoko/fundamentals/types/mutable-arrays.md b/docs/languages/motoko/fundamentals/types/mutable-arrays.md index c4580146..45dbd793 100644 --- a/docs/languages/motoko/fundamentals/types/mutable-arrays.md +++ b/docs/languages/motoko/fundamentals/types/mutable-arrays.md @@ -1,10 +1,11 @@ --- -sidebar_position: 9 -description: "Motoko language documentation" title: "Mutable arrays" +description: "Mutable arrays allow direct modification of elements, making them suitable for scenarios where data needs to be updated frequently." +sidebar: + order: 9 --- -Mutable arrays allow direct modification of elements, making them suitable for scenarios where data needs to be updated frequently. Unlike [immutable arrays](/languages/motoko/fundamentals/types/immutable-arrays), which require creating a new array to reflect changes, mutable arrays support in place modifications, improving performance in some cases. +Mutable arrays allow direct modification of elements, making them suitable for scenarios where data needs to be updated frequently. Unlike [immutable arrays](./immutable-arrays.md), which require creating a new array to reflect changes, mutable arrays support in place modifications, improving performance in some cases. ## Creating a mutable array @@ -12,7 +13,7 @@ Mutable array types are written with square brackets `[var T]`. The `var` keywor A mutable array is created using a mutable array expression: - ``` motoko + ```motoko no-repl [var 1, 2, 3, 4, 5]; ``` @@ -22,13 +23,13 @@ Its type is inferred to be `[var Nat]`. If you want to update the array with negative elements, use a type annotation: - ```motoko + ```motoko no-repl [var 1, 2, 3, 4, 5] : [var Int] ``` A named array can be declared using either `let` or `var`: -```motoko +```motoko no-repl let digits = ["0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "10"]; ``` @@ -36,7 +37,7 @@ The function `Array.tabulateVar(size, f)` creates a mutable array of `size` elem Example: -```motoko +```motoko no-repl import Nat "mo:core/Nat"; import Array "mo:core/Array"; @@ -53,7 +54,7 @@ Each element is mutable and can be updated later. To initialize a large array where every element starts with the same value, use `Array.init(size, value)`: -```motoko +```motoko no-repl import Array "mo:core/Array"; let optArr = Array.repeat(null, 10); @@ -86,7 +87,7 @@ Mutable arrays are beneficial when: | Conversion | Can be converted to mutable with `Array.thaw`. | Can be converted to immutable with `Array.freeze`. | | Use case | Tabular fixed, data | Iterative algorithms | -:::warning +:::caution Unlike some other programming languages that support resizable arrays, Motoko's arrays (both mutable and immutable) are fixed-size. Motoko arrays cannot shrink or grow in length, and operations like `Array.concat` always construct new arrays. For dynamically-sized, array-like data structures, consider using modules in `core` (e.g. `List`) or other `mops` packages (e.g. [`vector`](https://mops.one/vector)). @@ -97,7 +98,7 @@ For dynamically-sized, array-like data structures, consider using modules in `co Mutable arrays use the `var` keyword inside the square brackets `[var T]`. The type of the array is also specified within the square brackets, e.g., `[var Nat]` declares a mutable array of natural numbers. In place element modification is supported in mutable arrays. -```motoko +```motoko no-repl let mutableArray : [var Nat] = [var 1, 2, 3, 4, 5]; mutableArray[0] := 10; // Updates the first element to 10 @@ -107,9 +108,9 @@ mutableArray; ## Accessing and modifying elements -Mutable array elements can be read and modified using indexed access. Attempting to access an index that does not exist will result in a [trap](/languages/motoko/fundamentals/basic-syntax/traps). +Mutable array elements can be read and modified using indexed access. Attempting to access an index that does not exist will result in a [trap](../basic-syntax/traps.md). -```motoko +```motoko no-repl let numbers : [var Nat] = [var 10, 20, 30]; numbers[0] := 100; // updating first element @@ -119,7 +120,7 @@ debug_show(numbers[0]); // 100 The size of an array `a` is available as `a.size()`, a `Nat`. Array elements are zero-indexed, allowing indices `0` up to `a.size() - 1`. -Attempting to access an array's index that does not exist will cause a [trap](/languages/motoko/fundamentals/basic-syntax/traps). +Attempting to access an array's index that does not exist will cause a [trap](../basic-syntax/traps.md). ```motoko no-repl let numbers : [var Nat] = [var 10, 20, 30]; @@ -157,7 +158,7 @@ for (i in arr.keys()) { ## Converting a mutable array to an immutable array -You can convert a mutable array into an immutable array using `Array.freeze`, ensuring that the contents cannot be modified after conversion. Since mutable arrays are not [sharable](/languages/motoko/fundamentals/types/shared-types), freezing them is useful when passing data across [functions](/languages/motoko/fundamentals/types/function-types) or [actors](/languages/motoko/fundamentals/actors/actors-async) to ensure immutability. +You can convert a mutable array into an immutable array using `Array.freeze`, ensuring that the contents cannot be modified after conversion. Since mutable arrays are not [sharable](./shared-types.md), freezing them is useful when passing data across [functions](./function-types.md) or [actors](../actors/actors-async.md) to ensure immutability. ```motoko no-repl import Array "mo:core/Array"; @@ -175,7 +176,7 @@ A Tic-tac-toe board is a `3x3` grid that requires updates as players take turns. `VarArray.tabulate` is used to create a mutable board initialized with `"_"` (empty space). -```motoko +```motoko no-repl import VarArray "mo:core/VarArray"; import Debug "mo:core/Debug"; @@ -237,7 +238,7 @@ To see why, suppose the following was allowed: `[var Nat] <: [var Int]` (since ` Then, consider the following code: -```motoko +```motoko no-repl let ns : [var Nat] = [var 0]; let is : [var Int] = ns; // only allowed if [var Nat] <: [var Int] is[0] := -1; // [var Nat] is not a subtype of [var Int] — even though Nat <: Int. diff --git a/docs/languages/motoko/fundamentals/types/objects-classes.md b/docs/languages/motoko/fundamentals/types/objects-classes.md index 6cc9c6f9..d76d35d3 100644 --- a/docs/languages/motoko/fundamentals/types/objects-classes.md +++ b/docs/languages/motoko/fundamentals/types/objects-classes.md @@ -1,7 +1,8 @@ --- -sidebar_position: 6 -description: "Motoko language documentation" title: "Objects & classes" +description: "In Motoko, an object is a collection of named fields that hold values." +sidebar: + order: 6 --- ## Objects @@ -9,14 +10,14 @@ title: "Objects & classes" In Motoko, an object is a collection of named fields that hold values. These values can be plain data or functions. Each field can be either **mutable** or **immutable** depending on whether it's declared with `var` or not. A simple object containing just fields of data is like a record in a database. -Motoko's light-weight [record](/languages/motoko/fundamentals/types/records) syntax makes it easy to construct such objects. +Motoko's light-weight [record](./records.md) syntax makes it easy to construct such objects. When fields contain function values, Motoko objects can represent traditional objects with methods, familiar from object-oriented programming (OOP). From an OOP perspective, an object is an abstraction, defined by the behavior of its methods. Methods are typically used to modify or observe some encapsulated (i.e. hidden) state of an object. In addition to the record syntax, Motoko let's you define an object from a block of declarations. The declarations in the block can be `public` or `private`, with `private` the default. Public declarations become accessible fields of the object, while private declarations remain hidden and inaccessible from outside the object. -```motoko +```motoko no-repl object Account { var balance : Nat = 1000; @@ -34,9 +35,9 @@ object Account { ## Classes -An object declaration just declares a single object. To declare a function that generates objects of a similar type, Motoko offer classes. A class acts as a blueprint for creating multiple objects with independent [state](/languages/motoko/fundamentals/actors/state). +An object declaration just declares a single object. To declare a function that generates objects of a similar type, Motoko offer classes. A class acts as a blueprint for creating multiple objects with independent [state](../actors/state.md). -```motoko +```motoko no-repl class Account(initialBalance : Nat) { var balance = initialBalance; @@ -60,7 +61,7 @@ let account2 = Account(1000); An object class defines a blueprint for multiple objects. The above is just short-hand for an `object` class. Motoko also support module and actor classes. -```motoko +```motoko no-repl object class Account(initialBalance : Nat) { var balance = initialBalance; @@ -91,7 +92,7 @@ Objects with fewer fields are more general, while objects with additional fields Below are example objects for each account type, demonstrating subtyping in practice: -```motoko name=accounts +```motoko no-repl type BasicAccount = { getBalance : () -> Nat; }; @@ -189,5 +190,5 @@ withdrawFromAccount(_premiumAccount); // withdrawFromAccount(_basicAccount); // type error: (missing withdraw) ``` -[Learn more about subtyping](/languages/motoko/fundamentals/types/subtyping). +[Learn more about subtyping](./subtyping.md). diff --git a/docs/languages/motoko/fundamentals/types/options.md b/docs/languages/motoko/fundamentals/types/options.md index 844c1ac9..1e16ff86 100644 --- a/docs/languages/motoko/fundamentals/types/options.md +++ b/docs/languages/motoko/fundamentals/types/options.md @@ -1,7 +1,8 @@ --- -sidebar_position: 10 -description: "Motoko language documentation" title: "Options" +description: "Options provide a structured way to represent values that may or may not be present." +sidebar: + order: 10 --- | Type | Syntax | Purpose | Application | @@ -12,7 +13,7 @@ Options provide a structured way to represent values that may or may not be pres An option is defined using `?` followed by the type of the value it can hold. -```motoko name=user +```motoko no-repl var username : ?Text = null; username; ``` @@ -27,7 +28,7 @@ The constant `null` is the sole value of Motoko’s trivial `Null` type. It also When a Motoko value has type `?T`, it is either `null` or contains a value, written as `?value` (note the leading `?`). The fundamental way to access this value is by using a `switch` expression, which explicitly handles both cases: -``` motoko no-repl +```motoko no-repl func displayName(option : ?Text) : Text { switch option { case (?user) { user }; @@ -43,7 +44,7 @@ Sometimes, the verbosity of a `switch` expression can make code harder to read. To determine if an option contains a value, function `Option.isSome` returns `true` if its argument is not `null`. -```motoko +```motoko no-repl import Option "mo:core/Option"; import Debug "mo:core/Debug"; @@ -53,11 +54,11 @@ if (Option.isSome(value)) { } ``` -By leveraging the `Option` module, handling optional values becomes more concise and expressive, reducing the need for explicit [`switch`](/languages/motoko/fundamentals/control-flow/switch) statements. +By leveraging the `Option` module, handling optional values becomes more concise and expressive, reducing the need for explicit [`switch`](../control-flow/switch.md) statements. ### Providing default values -Instead of manually handling `null` cases with [pattern matching](/languages/motoko/fundamentals/pattern-matching), `Option.get` allows for cleaner fallback logic to ensure that missing values are safely replaced with a default. +Instead of manually handling `null` cases with [pattern matching](../pattern-matching.md), `Option.get` allows for cleaner fallback logic to ensure that missing values are safely replaced with a default. ```motoko no-repl import Option "mo:core/Option"; @@ -67,9 +68,9 @@ Option.get(username, "Guest"); // "Guest" if username is null ### Using options for error handling -Options can be used to catch expected failures instead of calling a [`trap`](/languages/motoko/fundamentals/basic-syntax/traps), making a function return `null` when it encounters an invalid input. +Options can be used to catch expected failures instead of calling a [`trap`](../basic-syntax/traps.md), making a function return `null` when it encounters an invalid input. -```motoko +```motoko no-repl func safeDivide(a : Int, b : Int) : ?Int { if (b == 0) null else ?(a / b); }; @@ -96,7 +97,7 @@ The `let` statement matches the option against the pattern `?value`, extracting The same logic can be expressed using a `switch`, though the result is more verbose and introduces an additional level of nesting: -``` motoko no-repl +```motoko no-repl func get(option : ?T, defaultValue : T) : T { switch option { case null defaultValue; @@ -111,7 +112,7 @@ Although convenient for option patterns, `let-else` also works with other types The `Option.map` function applies a transformation only if the value is present. -```motoko +```motoko no-repl import Option "mo:core/Option"; let number : ?Nat = ?10; @@ -124,7 +125,7 @@ In this example, if `number` is `null`, `map` ensures the result remains `null` Sometimes, both the function and value are optional. `Option.apply` calls a function only if both are present. This is useful when chaining optional operations that may return `null`. -```motoko +```motoko no-repl import Option "mo:core/Option"; let maybeIncrement : ?(Nat -> Nat) = ?(func x: Nat = x + 1); @@ -139,7 +140,7 @@ If either `maybeFunction` or `maybeValue` is `null`, the result remains `null`. When working with multiple optional values, using `Option.chain` processes them safely without unnecessary `switch` statements. -```motoko +```motoko no-repl import Option "mo:core/Option"; let firstName : ?Text = ?"Motoko"; @@ -164,7 +165,7 @@ Within a `do ? `, the `!` operator is used to unwrap values of unrelated The `do ? ` construct is similar to the `?` operator in Rust, providing a concise and expressive way to propagate `null` values. -```motoko +```motoko no-repl // Returns the sum of optional values `n` and `m` or `null`, if either is `null` func addOpt(n : ?Nat, m : ?Nat) : ?Nat { do ? { @@ -175,7 +176,7 @@ func addOpt(n : ?Nat, m : ?Nat) : ?Nat { The following example defines a simple function that evaluates expressions built from natural numbers, division, and a zero test, encoded as a variant type: -```motoko +```motoko no-repl type Exp = {#Lit : Nat; #Div : (Exp, Exp); #If : (Exp, Exp, Exp)}; func eval(e : Exp) : ? Nat { do ? { diff --git a/docs/languages/motoko/fundamentals/types/primitive-types.md b/docs/languages/motoko/fundamentals/types/primitive-types.md index fad81793..f84b81cf 100644 --- a/docs/languages/motoko/fundamentals/types/primitive-types.md +++ b/docs/languages/motoko/fundamentals/types/primitive-types.md @@ -1,7 +1,8 @@ --- -sidebar_position: 1 -description: "Motoko language documentation" title: "Primitive types" +description: "Motoko provides several primitive types that form the foundation of all computations." +sidebar: + order: 1 --- Motoko provides several primitive types that form the foundation of all computations. These include numeric types, characters and text, booleans, and floating-point numbers. @@ -12,7 +13,7 @@ More esoteric functions, not supported by dedicated operators, can be found in t For example, the library function `Int.toText: Int -> Text`, declared in core package `Int`, returns the textual representation of its argument. -```motoko name=int +```motoko no-repl import Int "mo:core/Int"; Int.toText(0); // returns "0" ``` @@ -32,7 +33,7 @@ This means that every expression of type [`Nat`](https://mops.one/core/docs/Nat) An [`Int`](https://mops.one/core/docs/Int) cannot be directly assigned to a [`Nat`](https://mops.one/core/docs/Nat) since it may be a negative number and the [`Nat`](https://mops.one/core/docs/Nat) type only contains non-negative numbers. -```motoko +```motoko no-repl let x : Int = -5; let y : Nat = x; // Error ``` @@ -46,7 +47,7 @@ let y : Nat = Int.abs(x); // Allowed, y = 5 Fixed-size numeric types ([`Int8`](https://mops.one/core/docs/Int8), [`Nat32`](https://mops.one/core/docs/Nat32), etc.) support additional operations, including bitwise shifts. -```motoko +```motoko no-repl let x : Nat32 = 0xA; // 10 in hexadecimal let y = x << 2; // 0x28 (40 in decimal) ``` @@ -55,7 +56,7 @@ let y = x << 2; // 0x28 (40 in decimal) `Char` represents a single Unicode scalar value, while [`Text`](https://mops.one/core/docs/Text) represents a sequence of characters. -```motoko +```motoko no-repl import Char "mo:core/Char"; import Text "mo:core/Text"; @@ -76,7 +77,7 @@ The [`Bool`](https://mops.one/core/docs/Bool) type represents boolean values, `t The logical operators `and` and `or` will only evaluate their second operand if necessary. -```motoko +```motoko no-repl let flag : Bool = true or false; // true let opposite = not flag; // false @@ -87,7 +88,7 @@ let isEqual = true == false ; // false [`Float`](https://mops.one/core/docs/Float) is a 64-bit floating-point type that provides mathematical operations. -```motoko +```motoko no-repl import Float "mo:core/Float"; let pi = Float.pi; let radius : Float = 2.5; @@ -107,7 +108,7 @@ single-precision values. Values are written as float literals with a `Float32` type ascription, or produced by arithmetic on `Float32` operands, or by explicit conversion from `Float`: -```motoko +```motoko no-repl let a : Float32 = 3.14; // literal rounded to single precision at compile time let b : Float32 = a * 2.0; // arithmetic stays in Float32 let c : Float32 = floatToFloat32 3.14; // explicit conversion from Float diff --git a/docs/languages/motoko/fundamentals/types/records.md b/docs/languages/motoko/fundamentals/types/records.md index fbd7d65f..d9b81557 100644 --- a/docs/languages/motoko/fundamentals/types/records.md +++ b/docs/languages/motoko/fundamentals/types/records.md @@ -1,18 +1,19 @@ --- -sidebar_position: 5 -description: "Motoko language documentation" title: "Records" +description: "Records allow you to group related values using named fields, with each field potentially having a different type." +sidebar: + order: 5 --- Records allow you to group related values using named fields, with each field potentially having a different type. -Unlike [tuples](/languages/motoko/fundamentals/types/tuples), which use positional access, records provide field-based access, improving readability and maintainability. +Unlike [tuples](./tuples.md), which use positional access, records provide field-based access, improving readability and maintainability. Records also support **mutable fields**, declared using the `var` keyword. In contrast, all fields in a tuple are always **immutable**. ## Defining a record -```motoko +```motoko no-repl let person = { name : Text = "Motoko"; age : Nat = 25; @@ -26,7 +27,7 @@ Without an explicit annotation, the compiler might infer a more specific type th Example: -```motoko +```motoko no-repl let account = { name = "Motoko"; var balance = 0 }; // Inferred as { name : Text; var balance : Nat } account.balance := -100; // Rejected, -100 is an Int not a Nat @@ -53,7 +54,7 @@ Unlike tuples, the order of record fields is immaterial and all record types wit Fields in a record can be accessed using the dot (`.`) notation. -```motoko +```motoko no-repl let person = { name : Text = "Motoko"; age : Nat = 25; @@ -71,7 +72,7 @@ Attempting to access a field that isn't available in the type of the record is a By default, record fields are immutable. To create a mutable field, use `var`. -```motoko +```motoko no-repl let person = { var name : Text = "Motoko"; var age : Nat = 25; @@ -82,7 +83,7 @@ This `person` has type `{var age : Nat; var name : Text}`. `var name` and `var age` allow the values to be updated later. -```motoko +```motoko no-repl let person = { var name : Text = "Motoko"; var age : Nat = 25; @@ -100,7 +101,7 @@ Attempting to update an immutable field is a compile-time type error. Records can contain other records, allowing for hierarchical data structures that maintain organization while ensuring type safety and clarity. -```motoko +```motoko no-repl type Address = { city : Text; street : Text; @@ -120,9 +121,9 @@ let individual : Individual = { ## Pattern matching on records -Records can be destructured using [`switch`](/languages/motoko/fundamentals/control-flow/switch), allowing selective extraction of fields. This approach makes accessing deeply nested fields more explicit and readable. +Records can be destructured using [`switch`](../control-flow/switch.md), allowing selective extraction of fields. This approach makes accessing deeply nested fields more explicit and readable. -```motoko +```motoko no-repl type Address = { city : Text; street : Text; @@ -149,7 +150,7 @@ The field pattern `name` is just shorthand for `name = name`: it binds the conte Records are commonly used in arrays and other collections for structured data storage, allowing efficient data organization and retrieval. -```motoko +```motoko no-repl type Product = { name : Text; price : Float; @@ -187,7 +188,7 @@ debug_show(profile); The `with` keyword modifies, overrides, or adds fields when combining records. -```motoko +```motoko no-repl let person = { name : Text = "Motoko"; age : Nat = 25; }; // age = 26; updates the existing age field. // city = "New York" adds a new field to the record. @@ -205,7 +206,7 @@ If `person` contained a mutable (`var`) field, `with` must redefine it, preventi ### Combining `and` and `with` -```motoko +```motoko no-repl let person = {name : Text = "Motoko"; age : Nat = 25}; let contact = {email : Text = "motoko@example.com"}; diff --git a/docs/languages/motoko/fundamentals/types/results.md b/docs/languages/motoko/fundamentals/types/results.md index 3504ced2..b8df6e4b 100644 --- a/docs/languages/motoko/fundamentals/types/results.md +++ b/docs/languages/motoko/fundamentals/types/results.md @@ -1,7 +1,8 @@ --- -sidebar_position: 11 -description: "Motoko language documentation" title: "Results" +description: "While options are a built-in type, the Result is defined as a variant type:" +sidebar: + order: 11 --- | Type | Syntax | Purpose | Application | @@ -10,7 +11,7 @@ title: "Results" While options are a built-in type, the `Result` is defined as a variant type: -``` motoko no-repl +```motoko no-repl type Result = { #ok : Ok; #err : Err } ``` @@ -18,7 +19,7 @@ Because of the second type parameter `Err`, the `Result` type lets you select th Here’s a simple function that validates a username. If it's non-empty, it will return a greeting of type `Text`. If not, it will return an error of type `Text`. -```motoko +```motoko no-repl import Result "mo:core/Result"; func greet(name : Text) : Result.Result { @@ -32,7 +33,7 @@ When a Motoko value has type `Result`, it is either a success, written `#o ### `switch` -```motoko +```motoko no-repl import Result "mo:core/Result"; func greet(name : Text) : Result.Result { @@ -56,7 +57,7 @@ The verbosity of `switch` expressions can make code harder to read, so Motoko al Values can be extracted from `Result` using the `let ... else` pattern. This can be preferable to a `switch` expression when only the success `case` is needed, and the else branch can cleanly handle or exit on failure. It allows concise early returns or alternative flows when the result is `#err`. -```motoko +```motoko no-repl import Result "mo:core/Result"; func greet(name : Text) : Result.Result { diff --git a/docs/languages/motoko/fundamentals/types/shared-types.md b/docs/languages/motoko/fundamentals/types/shared-types.md index 52252024..fdcd54a8 100644 --- a/docs/languages/motoko/fundamentals/types/shared-types.md +++ b/docs/languages/motoko/fundamentals/types/shared-types.md @@ -1,10 +1,11 @@ --- -sidebar_position: 2 -description: "Motoko language documentation" title: "Shared types" +description: "All Motoko types are divided into sets." +sidebar: + order: 2 --- -All Motoko types are divided into sets. The smallest is the set of shared types. Shared types are part of the larger set of [stable types](/languages/motoko/fundamentals/types/stable-types). +All Motoko types are divided into sets. The smallest is the set of shared types. Shared types are part of the larger set of [stable types](./stable-types.md). A shared type's value can be easily exchanged with other actors. To prevent issues associated with sharing mutable state across actors, **all shared types are immutable**. This immutability allows values to be transmitted safely by copying data, avoiding the complexity and risks of sharing stateful or mutable objects. @@ -29,7 +30,7 @@ Shareability is essential for several reasons: ### Primitive types -Most [primitive types](/languages/motoko/fundamentals/types/primitive-types) are shared by default. +Most [primitive types](./primitive-types.md) are shared by default. ```motoko no-repl // Numbers, text, and booleans are shared @@ -40,7 +41,7 @@ let flag : Bool = true; ### Immutable collections -Collections that cannot be modified after creation are shared, including [immutable arrays](/languages/motoko/fundamentals/types/immutable-arrays) and [tuples](/languages/motoko/fundamentals/types/tuples). +Collections that cannot be modified after creation are shared, including [immutable arrays](./immutable-arrays.md) and [tuples](./tuples.md). ```motoko no-repl // Immutable arrays are shared @@ -52,7 +53,7 @@ let person : (Text, Nat) = ("Motoko", 25); ### Records with immutable fields -Objects with immutable fields containing shared types are shared, including [records](/languages/motoko/fundamentals/types/records). +Objects with immutable fields containing shared types are shared, including [records](./records.md). ```motoko no-repl // Records with immutable fields are shared @@ -65,7 +66,7 @@ let user = { ### Variants with shared type tags -[Variant types](/languages/motoko/fundamentals/types/variants) are shared when their tags contain shared types. +[Variant types](./variants.md) are shared when their tags contain shared types. ```motoko no-repl // Variant types with shared tags are shared @@ -80,7 +81,7 @@ let failure : Result = #error("Operation failed"); ### Option types -[Option types](/languages/motoko/fundamentals/types/options) are shared when they contain shared types. +[Option types](./options.md) are shared when they contain shared types. ```motoko no-repl // Option types with shared inner types are shared @@ -90,7 +91,7 @@ let nothing : ?Nat = null; ### Actor references -References to [actors](/languages/motoko/fundamentals/actors/actors-async) are shared, allowing [canisters](/concepts/canisters) to call each other. +References to [actors](../actors/actors-async.md) are shared, allowing [canisters](/concepts/canisters) to call each other. ```motoko no-repl // Actor types are shared @@ -102,7 +103,7 @@ type CounterActor = actor { ### Shared functions -[Function types](/languages/motoko/fundamentals/types/function-types) marked as `shared` are sharable. +[Function types](./function-types.md) marked as `shared` are sharable. ```motoko no-repl // Shared function types are shared diff --git a/docs/languages/motoko/fundamentals/types/stable-types.md b/docs/languages/motoko/fundamentals/types/stable-types.md index 96e71762..ef35c579 100644 --- a/docs/languages/motoko/fundamentals/types/stable-types.md +++ b/docs/languages/motoko/fundamentals/types/stable-types.md @@ -1,10 +1,11 @@ --- -sidebar_position: 13 -description: "Motoko language documentation" title: "Stable types" +description: "Stable types include all shared types and represent the kinds of values that can be stored in the stable declarations of a Motoko actor." +sidebar: + order: 13 --- -**Stable types** include all [shared types](/languages/motoko/fundamentals/types/shared-types) and represent the kinds of values that can be stored in the `stable` declarations of a Motoko actor. +**Stable types** include all [shared types](./shared-types.md) and represent the kinds of values that can be stored in the `stable` declarations of a Motoko actor. Storing a value in a `stable` declaration ensures that it persists across canister upgrades. This enables state preservation without the need for an external file system or database. The set of stable types defines the kinds of values that can be transferred from an actor to its future upgraded versions. @@ -55,7 +56,7 @@ Non-shared functions and futures (`async T`) and computations (`async* T`) depen ### Primitive types -Most [primitive types](/languages/motoko/fundamentals/types/primitive-types) in Motoko are stable. +Most [primitive types](./primitive-types.md) in Motoko are stable. ```motoko no-repl persistent actor { @@ -83,7 +84,7 @@ persistent actor { ### Records with mutable or immutable fields -[Records](/languages/motoko/fundamentals/types/records) that contain only stable types remain stable, regardless of whether their fields are mutable or immutable. +[Records](./records.md) that contain only stable types remain stable, regardless of whether their fields are mutable or immutable. ```motoko no-repl persistent actor { @@ -104,7 +105,7 @@ persistent actor { ### Variants with stable type tags -[Variants](/languages/motoko/fundamentals/types/variants) are stable when their tags contain only stable types. +[Variants](./variants.md) are stable when their tags contain only stable types. ```motoko no-repl persistent actor { @@ -122,7 +123,7 @@ persistent actor { ### Option types -[Option](/languages/motoko/fundamentals/types/options) types are stable when they contain stable types. +[Option](./options.md) types are stable when they contain stable types. ```motoko no-repl persistent actor { @@ -145,7 +146,7 @@ persistent actor { ### Actor references -References to [actors](/languages/motoko/fundamentals/actors/actors-async) are stable, allowing stable canister-to-canister interactions. +References to [actors](../actors/actors-async.md) are stable, allowing stable canister-to-canister interactions. ```motoko no-repl persistent actor { diff --git a/docs/languages/motoko/fundamentals/types/subtyping.md b/docs/languages/motoko/fundamentals/types/subtyping.md index d7586feb..f4a02947 100644 --- a/docs/languages/motoko/fundamentals/types/subtyping.md +++ b/docs/languages/motoko/fundamentals/types/subtyping.md @@ -1,7 +1,8 @@ --- -sidebar_position: 14 -description: "Motoko language documentation" title: "Subtyping" +description: "Subtyping is a fundamental concept in type systems that allows values of one type to be used wherever values of another type are expected, p" +sidebar: + order: 14 --- Subtyping is a fundamental concept in type systems that allows values of one type to be used wherever values of another type are expected, provided @@ -73,12 +74,12 @@ In this table: [`Nat`](https://mops.one/core/docs/Nat) is a subtype of [`Int`](https://mops.one/core/docs/Int) (`Nat <: Int`), meaning a [`Nat`](https://mops.one/core/docs/Nat) value can be used where an `Int` is expected. This works because every [`Nat`](https://mops.one/core/docs/Nat) is an `Int`, but not every `Int` is a [`Nat`](https://mops.one/core/docs/Nat) (as negative numbers exist in `Int`). -```motoko +```motoko no-repl let n : Nat = 5; let i : Int = n; // Allowed, since `Int <: Nat` ``` -```motoko +```motoko no-repl let i : Int = -5; let n : Nat = i; // Not allowed, since `Int = ok; // Allowed, since `{#ok : Nat} <: {#ok : Int; ## Immutable arrays -[Immutable arrays (`[T]`)](/languages/motoko/fundamentals/types/immutable-arrays) support covariant subtyping, meaning if `T <: U`, then `[T] <: [U]`. +[Immutable arrays (`[T]`)](./immutable-arrays.md) support covariant subtyping, meaning if `T <: U`, then `[T] <: [U]`. If `T <: U`, then an (immutable) array of type `[T]` can be used as an array of type `[U]`. @@ -238,7 +239,7 @@ let ints : [Int] = nats; // Allowed, since `Nat <: Int` we also have `[Nat] <: ## Mutable arrays -[Mutable arrays](/languages/motoko/fundamentals/types/mutable-arrays) of the form `[var T]` do not support interesting subtyping. +[Mutable arrays](./mutable-arrays.md) of the form `[var T]` do not support interesting subtyping. The mutable array constructor `[var T]` is invariant in `T`. This means that `[var T]` is a subtype of `[var U]` only if `T` and `U` are equivalent types, that is, both `T <: U` and `U <: T` must hold. @@ -252,7 +253,7 @@ let ints : [var Int] = nats; // Not allowed, because `[var Nat] T2` is a subtype of another function type `U1 -> U2` provided that: 1. The argument types are related in the opposite direction (`U1 <: T1` ). @@ -266,7 +267,7 @@ This ensures safety because the function will never be passed arguments it can As a simple example, consider the `magnitude` function that returns the absolute value, or magnitude, of an integer. -```motoko no-repl name=magnitude +```motoko no-repl import Int "mo:core/Int" func magnitude(i : Int) : Nat { Int.abs(i) }; ``` @@ -274,7 +275,7 @@ func magnitude(i : Int) : Nat { Int.abs(i) }; Its most precise type is `Int -> Nat`, but, due to subtyping, it also has types `Nat -> Nat` (making the argument more specific), `Int -> Int` (making the result more general) and `Int -> Int` (doing both). -``` motoko no-repl _include=magnitude +```motoko no-repl let i2n : Int -> Nat = magnitude; let n2n : Nat -> Nat = magnitude; let i2i : Int-> Int = magnitude; @@ -298,11 +299,11 @@ In the case of actors, which can only contain shared functions as fields, this m ## Recursive and generic types -[Recursive and generic types](/languages/motoko/fundamentals/types/advanced-types) can be subtypes of each other when their definitions allow it. +[Recursive and generic types](./advanced-types.md) can be subtypes of each other when their definitions allow it. Consider the following recursive point types, where the second extends the first by adding a color field: -```motoko no-repl name=Point +```motoko no-repl type Point = { x : Int; move: Int -> Point @@ -317,7 +318,7 @@ type ColorPoint = { `ColorPoint` is a subtype of `Point`: -``` motoko no-repl _include=Point +```motoko no-repl let cp : ColorPoint = { color = #red; x = 0; diff --git a/docs/languages/motoko/fundamentals/types/tuples.md b/docs/languages/motoko/fundamentals/types/tuples.md index b9ecddc2..7a417995 100644 --- a/docs/languages/motoko/fundamentals/types/tuples.md +++ b/docs/languages/motoko/fundamentals/types/tuples.md @@ -1,7 +1,8 @@ --- -sidebar_position: 4 -description: "Motoko language documentation" title: "Tuples" +description: "A tuple is a fixed-size, ordered collection of values, where each element can have a different type." +sidebar: + order: 4 --- A tuple is a fixed-size, ordered collection of values, where each element can have a different type. Tuples provide a way to group values by position, without the overhead of defining a record of named fields. @@ -14,13 +15,13 @@ Unit values are typically used as placeholder arguments or return values for fun ## Defining a tuple -```motoko +```motoko no-repl let ghost = ("Motoko", 25); ``` The tuple's type is automatically inferred as `(Text, Nat)`, since `"Motoko"` is of type [`Text`](https://mops.one/core/docs/Text) and `25` is of type [`Nat`](https://mops.one/core/docs/Nat). -```motoko +```motoko no-repl let ghost : (Text, Nat) = ("Motoko", 25); ``` @@ -32,7 +33,7 @@ Motoko **does not** support length-one tuples. This is in contrast to languages Elements are accessed using `.n` where `n` is the index (0-based indexing). -```motoko +```motoko no-repl // Ghost is a tuple of length 2 let ghost : (firstName : Text, age : Nat) = ("Motoko", 25); let first = ghost.0; // "Motoko" @@ -43,7 +44,7 @@ let second = ghost.1; // 25 Tuples are useful for returning multiple values from a function without requiring a separate data structure. -```motoko +```motoko no-repl func getUserInfo() : (Text, Nat) { ("Ghost", 30); }; @@ -55,17 +56,17 @@ getUserInfo(); Tuples can be stored in arrays or other data structures. Tuples can be constructed with named types, improving readability. By naming the types in the tuple in the collection, the intent of each component is clarified, reducing ambiguity. -```motoko +```motoko no-repl let users : [(Text, Nat)] = [("Motoko", 25), ("Ghost", 30)]; ``` -This structure efficiently represents a collection of key-value pairs without requiring a dedicated [record](/languages/motoko/fundamentals/types/records) type. +This structure efficiently represents a collection of key-value pairs without requiring a dedicated [record](./records.md) type. ## Pattern matching on tuples In addition to dot notation, tuples can be decomposed using tuple patterns. When combined with `let` or `switch`, this allows you to access the components of a tuple through simple pattern matching. -```motoko +```motoko no-repl let users : [(Text, Nat)] = [("Motoko", 25), ("Ghost", 30)]; let (firstUserName, _) = users[0] // "Motoko" @@ -85,7 +86,7 @@ $$ Using nested tuples, this can be implemented in Motoko as follows: -```motoko +```motoko no-repl // Point is a tuple of coordinate floats type Point = (Float, Float); // Line is a tuple of points, that is, a nested tuple diff --git a/docs/languages/motoko/fundamentals/types/type-conversions.md b/docs/languages/motoko/fundamentals/types/type-conversions.md index 5626f5f6..de5b9220 100644 --- a/docs/languages/motoko/fundamentals/types/type-conversions.md +++ b/docs/languages/motoko/fundamentals/types/type-conversions.md @@ -1,7 +1,8 @@ --- -sidebar_position: 15 -description: "Motoko language documentation" title: "Type conversions" +description: "Conversions are used to transform values between different types to ensure compatibility and ease of manipulation." +sidebar: + order: 15 --- Conversions are used to transform values between different types to ensure compatibility and ease of manipulation. Common conversions include numeric transformation, such as converting [`Float`](https://mops.one/core/docs/Float) or [`Int`](https://mops.one/core/docs/Int) to [`Nat`](https://mops.one/core/docs/Nat), and text manipulation, like converting [`Text`](https://mops.one/core/docs/Text) to [`Float`](https://mops.one/core/docs/Float) or encoding [`Text`](https://mops.one/core/docs/Text) as a [`Blob`](https://mops.one/core/docs/Blob). Arrays and tuples can be converted into structured types, such as records or hashmaps, for better organization. Additionally, time conversions enable transforming `Time.now()` (nanoseconds since 1970) into human-readable date formats, with optional timezone adjustments. These conversions provide flexibility when working with different data types. @@ -14,7 +15,7 @@ Motoko provides methods for converting both [`Float`](https://mops.one/core/docs A [`Float`](https://mops.one/core/docs/Float) can be converted to [`Nat`](https://mops.one/core/docs/Nat) using `Float.toInt`, followed by `Int.abs` to ensure a non-negative value. -```motoko +```motoko no-repl import Float "mo:core/Float"; import Int "mo:core/Int"; @@ -30,7 +31,7 @@ let result2 = floatToNat(-15.6); // 15 (absolute value is taken) [`Int`](https://mops.one/core/docs/Int) can be directly converted to [`Nat`](https://mops.one/core/docs/Nat) using `Int.abs`, which removes any negative sign. -```motoko +```motoko no-repl import Int "mo:core/Int"; func intToNat(i : Int) : Nat { @@ -162,7 +163,7 @@ assert arrayOfNatToText([1, 2, 3]) == "1 2 3"; ### `Array` of tuples to an object -Motoko lacks support for dynamic objects, so an array of tuples is converted into a [record](/languages/motoko/fundamentals/types/records) or a structured representation. +Motoko lacks support for dynamic objects, so an array of tuples is converted into a [record](./records.md) or a structured representation. ```motoko no-repl import HashMap "mo:core/HashMap"; @@ -181,7 +182,7 @@ persistent actor MapConverter { arrayToMap([("Motoko", 4), ("Ghost", 21)]); ``` -To convert an array of tuples `[(Text, Nat)]` into a custom [record](/languages/motoko/fundamentals/types/records) type, such as `User`, `Array.map` is used to transform each tuple into a structured [record](/languages/motoko/fundamentals/types/records). +To convert an array of tuples `[(Text, Nat)]` into a custom [record](./records.md) type, such as `User`, `Array.map` is used to transform each tuple into a structured [record](./records.md). ```motoko no-repl import Array "mo:core/Array"; diff --git a/docs/languages/motoko/fundamentals/types/variants.md b/docs/languages/motoko/fundamentals/types/variants.md index 175378a1..75eda882 100644 --- a/docs/languages/motoko/fundamentals/types/variants.md +++ b/docs/languages/motoko/fundamentals/types/variants.md @@ -1,14 +1,15 @@ --- -sidebar_position: 7 -description: "Motoko language documentation" title: "Variants" +description: "Variant type describe values that take on one of several forms, each labeled with a distinct tag." +sidebar: + order: 7 --- -Variant type describe values that take on one of several forms, each labeled with a distinct tag. Unlike [records](/languages/motoko/fundamentals/types/records), where all fields exist at once, a value of a variant type holds exactly one of the type's possible values. This makes variants useful for representing mutually exclusive alternatives such as states, enumerations, categories and even trees. +Variant type describe values that take on one of several forms, each labeled with a distinct tag. Unlike [records](./records.md), where all fields exist at once, a value of a variant type holds exactly one of the type's possible values. This makes variants useful for representing mutually exclusive alternatives such as states, enumerations, categories and even trees. ## Defining a variant -```motoko no-repl name=status +```motoko no-repl type Status = { #Active; #Inactive; @@ -22,14 +23,14 @@ type Status = { To assign a variant value, use one of the defined tags. -```motoko +```motoko no-repl let activeUser = #Active; let bannedUser = #Banned("Violation of rules"); ``` ## Accessing a variant's value -To work with a variant, use a [`switch`](/languages/motoko/fundamentals/control-flow/switch) expression to match each possible case. +To work with a variant, use a [`switch`](../control-flow/switch.md) expression to match each possible case. ```motoko no-repl import Debug "mo:core/Debug"; @@ -59,11 +60,11 @@ A traffic light cycles between three distinct states: - Yellow: Vehicles should prepare to stop. - Green: Vehicles may proceed. -Since the traffic light can only be in one of these states at a time, a variant is well-suited to model it. There is no invalid [state](/languages/motoko/fundamentals/actors/state), as every possible value is explicitly defined. The transitions are controlled and predictable. +Since the traffic light can only be in one of these states at a time, a variant is well-suited to model it. There is no invalid [state](../actors/state.md), as every possible value is explicitly defined. The transitions are controlled and predictable. ### Defining the traffic light state -```motoko no-repl name=lights +```motoko no-repl type TrafficLight = { #red; #yellow; @@ -73,7 +74,7 @@ type TrafficLight = { ### Transitioning between states -A function can define how the traffic light cycles from one [state](/languages/motoko/fundamentals/actors/state) to the next. +A function can define how the traffic light cycles from one [state](../actors/state.md) to the next. ```motoko no-repl func nextState(light : TrafficLight) : TrafficLight { @@ -113,7 +114,7 @@ for (_ in Iter.range(0, 5)) { A binary tree is a data structure where each node has up to two child nodes. A variant can be used to represent this structure since a node can either contain a value with left and right children or be an empty leaf. This tree type is recursive as it refers to itself in its definition. -```motoko no-repl name=tree +```motoko no-repl type Tree = { #node : { value : Nat; @@ -183,7 +184,7 @@ traverseInOrder(tree); ### Using generic types -Currently, the example tree only supports [`Nat`](https://mops.one/core/docs/Nat) values. To allow it to store any type of data, a [generic type](/languages/motoko/fundamentals/types/advanced-types#generic-types) can be used. A generic type allows a data structure to work with multiple types by using a placeholder type `T`, which is replaced with a specific type when used. +Currently, the example tree only supports [`Nat`](https://mops.one/core/docs/Nat) values. To allow it to store any type of data, a [generic type](./advanced-types.md#generic-types) can be used. A generic type allows a data structure to work with multiple types by using a placeholder type `T`, which is replaced with a specific type when used. ```motoko no-repl type Tree = { diff --git a/docs/languages/motoko/icp-features/caller-identification.md b/docs/languages/motoko/icp-features/caller-identification.md index 10391907..5e929988 100644 --- a/docs/languages/motoko/icp-features/caller-identification.md +++ b/docs/languages/motoko/icp-features/caller-identification.md @@ -1,8 +1,8 @@ --- +title: "Caller identification" +description: "On ICP, every user and canister has a unique principal identifier." sidebar: order: 3 -description: "Motoko language documentation" -title: "Caller identification" --- On ICP, every user and canister has a unique **principal** identifier. When a canister receives a message, such as a function call, the principal identifying the caller of the function is included in the message. @@ -13,7 +13,7 @@ Motoko’s `shared` keyword is used to declare a shared function. Shared functio For example, when a shared function is called by a user or another canister, the caller's principal can be captured with `msg.caller`: -``` motoko no-repl +```motoko no-repl shared(msg) func inc() : async () { // ... msg.caller ... } @@ -23,7 +23,7 @@ In this example, the shared function `inc()` specifies a `msg` parameter, a reco To access the caller of an actor class constructor, you use the same syntax on the actor class declaration: -``` motoko +```motoko no-repl shared(msg) persistent actor class Counter(init : Nat) { // ... msg.caller ... } diff --git a/docs/languages/motoko/icp-features/candid-serialization.md b/docs/languages/motoko/icp-features/candid-serialization.md index 64f7f700..287d64df 100644 --- a/docs/languages/motoko/icp-features/candid-serialization.md +++ b/docs/languages/motoko/icp-features/candid-serialization.md @@ -1,8 +1,8 @@ --- +title: "Candid serialization" +description: "Candid is an interface description language and serialization format designed specifically for the Internet Computer Protocol." sidebar: order: 4 -description: "Motoko language documentation" -title: "Candid serialization" --- Candid is an interface description language and serialization format designed specifically for the Internet Computer Protocol. Candid serves as the standard communication protocol between canisters. When one canister calls another, the arguments are serialized to Candid, transmitted, and then deserialized by the receiving canister. This standardization enables developers to create frontends in languages like JavaScript that can easily interact with backend canisters written in Motoko or Rust. Candid uses strong typing to guarantee accurate data interpretation and an efficient binary format for encoding data, making it ideal for network transmission. Importantly, Candid's design allows for backwards-compatible upgrades of canister interfaces. @@ -102,7 +102,7 @@ Dynamic calls are particularly useful when working with canisters or services th In this example, use the imported `call` function to make a dynamic call on the actor: -``` motoko no-repl +```motoko no-repl import Principal "mo:core/Principal"; import { call } "mo:core/InternetComputer"; diff --git a/docs/languages/motoko/icp-features/randomness.md b/docs/languages/motoko/icp-features/randomness.md index aaedd55d..92a8cbbe 100644 --- a/docs/languages/motoko/icp-features/randomness.md +++ b/docs/languages/motoko/icp-features/randomness.md @@ -1,8 +1,8 @@ --- +title: "Randomness" +description: "Randomness is used for generating unique identifiers, ensuring fairness in games, cryptographic protocols, and much more." sidebar: order: 1 -description: "Motoko language documentation" -title: "Randomness" --- [Randomness](/guides/backends/randomness) is used for generating unique identifiers, ensuring fairness in games, cryptographic protocols, and much more. On ICP, all computations, including [randomness](/guides/backends/randomness), must be **verifiable and reproducible** across the network's nodes. diff --git a/docs/languages/motoko/icp-features/stable-memory.md b/docs/languages/motoko/icp-features/stable-memory.md index 2b1363df..5c414f44 100644 --- a/docs/languages/motoko/icp-features/stable-memory.md +++ b/docs/languages/motoko/icp-features/stable-memory.md @@ -1,8 +1,8 @@ --- +title: "Stable memory and regions" +description: "Canisters have two types of storage: Wasm memory and stable memory." sidebar: order: 5 -description: "Motoko language documentation" -title: "Stable memory and regions" --- Canisters have two types of storage: Wasm memory and stable memory. The Wasm memory is often referred to as the [heap memory](/concepts/orthogonal-persistence#heap-wasm-linear-memory). It is automatically used for heap-allocated objects and has a maximum size limitation of 4 GiB or 6 GiB respective to whether you are using 32-bit or 64-bit heap storage without enhanced orthogonal persistence. When a canister is upgraded, the heap memory is cleared, only retaining data stored in stable variables. @@ -12,7 +12,7 @@ Stable memory has a maximum size of 500 GiB and is preserved across canister upg The system automatically commits all memory modifications, both Wasm and stable, after the successful execution of a message. If a message execution fails, the changes are not committed. :::caution -The `Regions` library should only be used if [enhanced orthogonal persistence](/languages/motoko/fundamentals/actors/orthogonal-persistence/enhanced) does not fit your use case. +The `Regions` library should only be used if [enhanced orthogonal persistence](../fundamentals/actors/orthogonal-persistence/enhanced.md) does not fit your use case. ::: ## What is a `Region`? diff --git a/docs/languages/motoko/icp-features/system-functions.md b/docs/languages/motoko/icp-features/system-functions.md index a1beb372..78e5da31 100644 --- a/docs/languages/motoko/icp-features/system-functions.md +++ b/docs/languages/motoko/icp-features/system-functions.md @@ -1,25 +1,25 @@ --- +title: "System functions" +description: "ICP supports five system functions that canisters can call to interact with the ICP runtime environment:" sidebar: order: 6 -description: "Motoko language documentation" -title: "System functions" --- ICP supports five system functions that canisters can call to interact with the ICP runtime environment: -- [`timer`](/references/ic-interface-spec/canister-interface#global-timer) +- [`timer`](#timer) - [`preupgrade`](#preupgrade) - [`postupgrade`](#postupgrade) - [`lowmemory`](#lowmemory) -- [`inspect`](/references/ic-interface-spec/canister-interface#system-api-inspect-message) -- [`heartbeat`](/references/ic-interface-spec/canister-interface#heartbeat) +- [`inspect`](#inspect) +- [`heartbeat`](#heartbeat) Declaring any other system function will result in an error. Canisters can use these functions to efficiently manage state transitions, automate tasks, or handle system-level operations. ## `timer()` -The [`timer()` system function](/guides/backends/timers#timers) lets canisters schedule a task to execute after a specified delay. To make the timer repeat, the function must explicitly call `setGlobalTimer()` within its body to reset the timer. It accepts a single argument to set the global timer and returns `async ()`. +The [`timer()` system function](/guides/backends/timers#recurring-timers) lets canisters schedule a task to execute after a specified delay. To make the timer repeat, the function must explicitly call `setGlobalTimer()` within its body to reset the timer. It accepts a single argument to set the global timer and returns `async ()`. Unlike `heartbeat()`, which runs automatically every subnet round, `timer()` requires manual rescheduling after each execution. This design gives canisters precise control over whether the timer runs once or continuously, depending on if and when `setGlobalTimer()` is called again. diff --git a/docs/languages/motoko/icp-features/timers.md b/docs/languages/motoko/icp-features/timers.md index 1b7a6d4b..e6a447cd 100644 --- a/docs/languages/motoko/icp-features/timers.md +++ b/docs/languages/motoko/icp-features/timers.md @@ -1,8 +1,8 @@ --- +title: "Timers" +description: "Canisters can set recurring timers that execute a piece of code after a specified period of time or regular interval." sidebar: order: 2 -description: "Motoko language documentation" -title: "Timers" --- Canisters can set recurring timers that execute a piece of code after a specified period of time or regular interval. Timers in Motoko are implemented using the [`Timer.mo`](https://mops.one/core/docs/Timer) module and return a `TimerId`. `TimerId`s are unique for each timer instance. A canister can contain multiple active timers. @@ -26,7 +26,7 @@ If the `timer` system method is declared, the [`Timer.mo`](https://mops.one/core The following example of a global timer expiration callback gets called immediately after the canister starts, i.e. after install, and periodically every twenty seconds thereafter: -``` motoko no-repl +```motoko no-repl system func timer(setGlobalTimer : Nat64 -> ()) : async () { let next = Nat64.fromIntWrap(Time.now()) + 20_000_000_000; setGlobalTimer(next); // absolute time in nanoseconds diff --git a/docs/languages/motoko/icp-features/view-queries.md b/docs/languages/motoko/icp-features/view-queries.md index 6053659b..e51c4efe 100644 --- a/docs/languages/motoko/icp-features/view-queries.md +++ b/docs/languages/motoko/icp-features/view-queries.md @@ -1,6 +1,8 @@ --- -title: "Stable Variable Inspection with `--generate-view-queries`" -description: "Motoko language documentation" +title: "Stable variable inspection" +description: "Using --generate-view-queries to auto-generate query methods that expose stable variable contents in Motoko." +sidebar: + order: 7 --- The `--generate-view-queries` compiler flag instructs `moc` to auto-generate **query methods** that expose the contents of an actor's stable variables for inspection at runtime. This enables tooling, dashboards, and generic front-end UIs to browse canister state without writing boilerplate accessor code. @@ -26,7 +28,7 @@ When generation proceeds, the compiler chooses one of two strategies: If the expression `id.view()` resolves to a function with shared argument types `(T1, ..., TN)` and shared result type `R`, the compiler generates: -```motoko +```motoko no-repl public shared ({ caller }) query func __id(arg1 : T1, ..., argN : TN) : async R { ; id.view()(arg1, ..., argN) @@ -39,7 +41,7 @@ The `.view()` call may rely on implicit arguments (such as `compare`) provided t If no `.view()` method is available but `` is a shared type, the compiler generates a simple accessor: -```motoko +```motoko no-repl public shared ({ caller }) query func __id() : async { ; id @@ -72,7 +74,7 @@ A `.view()` method is a function resolved via contextual dot syntax on a stable ### Signature pattern -```motoko +```motoko no-repl module MyView { public func view<...>(self : , ...) : (arg1 : T1, ..., argN : TN) -> R = ... } @@ -82,7 +84,7 @@ Implicit arguments (like `compare` for ordered collections) are supported and re ### Example: paginated map view -```motoko +```motoko no-repl module MapView { public func view( self : Map.Map, @@ -103,13 +105,13 @@ module MapView { Given a stable variable: -```motoko +```motoko no-repl let customers : Map.Map = Map.empty(); ``` The compiler generates a query with the Motoko signature: -```motoko +```motoko no-repl public shared query func __customers(ko : ?Text, count : ?Nat) : async [(Text, Customer)] ``` @@ -123,7 +125,7 @@ __customers : (ko : opt text, count : opt nat) -> (vec record { text; Customer } View modules for common core data structures (`Map`, `Set`, arrays, `List`, `Stack`, `Queue`, and their pure counterparts) can be collected into a **mixin** and included in any actor: -```motoko +```motoko no-repl import Views "views"; persistent actor { @@ -136,7 +138,7 @@ persistent actor { ## Example: full actor -```motoko +```motoko no-repl //MOC-FLAG --generate-view-queries import Array "mo:core/Array"; diff --git a/docs/languages/motoko/index.md b/docs/languages/motoko/index.md index 704705c3..2b9c3347 100644 --- a/docs/languages/motoko/index.md +++ b/docs/languages/motoko/index.md @@ -1,17 +1,17 @@ --- title: "Motoko" -description: "A language designed for the Internet Computer with built-in actor model and orthogonal persistence" +description: "A programming language designed for the Internet Computer with built-in actor model, orthogonal persistence, and native WebAssembly compilation." sidebar: order: 1 --- -Motoko is a next-generation, high-level programming language designed to empower AI agents building backends for apps and services on the Internet Computer cloud network. While it channels several popular modern languages, it introduces groundbreaking new features such as actor-based concurrency, orthogonal persistence, and seamless WebAssembly integration. +Motoko is a high-level programming language designed for AI agents building backends for apps and services on the Internet Computer. It combines a familiar syntax with platform-native features: actor-based concurrency, orthogonal persistence, and direct WebAssembly compilation. ## Key features -**Actor model.** Every Motoko canister is an actor — an isolated unit of state and behavior that communicates with other actors through asynchronous messages. This maps directly to how canisters work on ICP: each canister has private state and a public interface. +**Actor model.** Every Motoko canister is an actor: an isolated unit of state and behavior that communicates with other actors through asynchronous messages. This maps directly to how canisters work on ICP: each canister has private state and a public interface. -**Orthogonal persistence.** Variables declared in a `persistent actor` survive canister upgrades automatically. There is no database layer, no serialization code, and no pre/post-upgrade hooks needed for most use cases. See [Orthogonal persistence](../../concepts/orthogonal-persistence.md) for how this works at the platform level. +**Orthogonal persistence.** Variables declared in a `persistent actor` survive canister upgrades automatically. There is no database layer, no serialization code, and no pre/post-upgrade hooks needed for most use cases. See [Orthogonal persistence](/concepts/orthogonal-persistence) for how this works at the platform level. **Async/await messaging.** Inter-canister calls use `async`/`await`, making sequential message flows read like synchronous code. The compiler and runtime handle the underlying callback mechanics. @@ -37,37 +37,6 @@ persistent actor Counter { }; ``` -The `persistent actor` declaration means `count` survives canister upgrades. The `query` keyword marks `get` as a fast, read-only call. The `increment` function is an update call that modifies state and goes through consensus. - -## Getting started - -Create a new Motoko project with icp-cli: - -```bash -icp new my-project --subfolder motoko -``` - -This generates a Motoko canister project with an `icp.yaml` build configuration and a source file. The build configuration uses the Motoko recipe: - -```yaml -canisters: - - name: backend - recipe: - type: "@dfinity/motoko@" - configuration: - main: src/main.mo - shrink: true -``` - -Start a local network and deploy: - -```bash -icp network start -d -icp deploy -``` - -For a guided walkthrough, see the [Quickstart](../../getting-started/quickstart.md). - ## Standard library: `core` The **`core`** package ([mops.one/core](https://mops.one/core)) is the standard library for Motoko. It supersedes the older `base` library with a cleaner API, consistent naming conventions, and data structures that work directly with stable memory. @@ -76,10 +45,10 @@ Add it to your project's `mops.toml`: ```toml [dependencies] -core = "2.2.0" # Check the latest version at https://mops.one/core +core = "2.5.0" # Check the latest version at https://mops.one/core [toolchain] -moc = "1.3.0" # Check the latest version at https://github.com/caffeinelabs/motoko/releases +moc = "1.8.0" # Check the latest version at https://github.com/caffeinelabs/motoko/releases ``` Then import modules: @@ -103,9 +72,7 @@ If you have an existing project using `base`, you can migrate incrementally; bot ## Further reading -- [Quickstart](../../getting-started/quickstart.md): create and deploy your first canister +- [Quickstart](/getting-started/quickstart): create and deploy your first canister - [core library API docs](https://mops.one/core/docs): standard library reference -- [Orthogonal persistence](../../concepts/orthogonal-persistence.md): how persistent memory works at the platform level +- [Orthogonal persistence](/concepts/orthogonal-persistence): how persistent memory works at the platform level - [Motoko GitHub](https://github.com/caffeinelabs/motoko): compiler source and issue tracker - - diff --git a/docs/languages/motoko/reference/changelog.md b/docs/languages/motoko/reference/changelog.md index 7a1269d7..b275c85b 100644 --- a/docs/languages/motoko/reference/changelog.md +++ b/docs/languages/motoko/reference/changelog.md @@ -1,26 +1,24 @@ --- -sidebar_position: 3 -description: "Motoko language documentation" -title: "Motoko changelog" +title: "Changelog" +description: "Motoko compiler changelog." +sidebar: + order: 6 + label: "Motoko changelog" --- -This section reproduces the changelog of Motoko up until this release. +# Motoko compiler changelog -More recent `moc` releases may be available on the [release page](https://github.com/dfinity/motoko/releases/). +## Next -:::tip -You can determine the version of your `moc` installation using -```bash -moc --version -``` +* motoko (`moc`) -If using `moc` via `dfx`, you can determine the version of moc bundled with `dfx` using: -```bash -$(dfx cache show)/moc --version -``` -::: + * bugfix: M0236 dot-notation suggestion no longer fires when the receiver argument is not already a postfix expression (e.g. `Nat.toText((x * a + b) % c)`). The compiler used to print the suggestion as `().toText(...)` but emit no machine-applicable edits, leaving `mops check --fix` with nothing to do; suggesting `(complex).f()` over `Module.f(complex)` is also a debatable style change. Trivial-receiver cases (variables, literals, calls) are unaffected. -# Motoko compiler changelog +## 1.8.1 (2026-05-20) + +* motoko (`moc`) + + * bugfix: Split stable-signature compatibility error M0169: the "previous version does not contain the stable variable required by the migration function" case now reports as new code **M0263**, leaving M0169 strictly for the "stable variable would be implicitly discarded" (data-loss) case. The two scenarios have different fixes and now have distinct codes (#6134). ## 1.8.0 (2026-05-15) @@ -866,7 +864,7 @@ $(dfx cache show)/moc --version inspected on the IC replica dashboard as they are internal to the Motoko runtime system. This query is only authorized to the canister controllers and self-calls of the canister. - ``` Motoko + ```motoko __motoko_runtime_information : () -> { compilerVersion : Text; rtsVersion : Text; @@ -1144,7 +1142,7 @@ $(dfx cache show)/moc --version * Allow identifiers in `or`-patterns (#3807). Bindings in alternatives must mention the same identifiers and have compatible types: - ``` Motoko + ```motoko let verbose = switch result { case (#ok) "All is good!"; case (#warning why or #error why) "There is some problem: " # why; @@ -1368,14 +1366,14 @@ $(dfx cache show)/moc --version This is a frequently asked-for feature that allows to change the control-flow of programs when pattern-match failure occurs, thus providing a means against the famous "pyramid of doom" issue. A common example is look-ups: - ``` Motoko + ```motoko shared func getUser(user : Text) : async Id { let ?id = Map.get(users, user) else { throw Error.reject("no such user") }; id } ``` Similarly, an expression like - ``` Motoko + ```motoko (label v : Bool { let = else break v false; true }) ``` evaluates to a `Bool`, signifying whether `` matches ``. @@ -1553,7 +1551,7 @@ $(dfx cache show)/moc --version * motoko (`moc`) * Add new primitives for a default timer mechanism (#3542). These are - ``` Motoko + ```motoko setTimer : (delayNanos : Nat64, recurring : Bool, job : () -> async ()) -> (id : Nat) cancelTimer : (id : Nat) -> () ``` @@ -2504,5 +2502,3 @@ $(dfx cache show)/moc --version ## 0.1 (2020-07-20) * Beginning of the changelog. Released with dfx-0.6.0. - - diff --git a/docs/languages/motoko/reference/compiler-ref.md b/docs/languages/motoko/reference/compiler-ref.md index 46505522..ed4ccf87 100644 --- a/docs/languages/motoko/reference/compiler-ref.md +++ b/docs/languages/motoko/reference/compiler-ref.md @@ -1,7 +1,8 @@ --- -sidebar_position: 15 -description: "Motoko language documentation" title: "Compiler reference" +description: "The Motoko compiler (moc) is the primary tool for compiling Motoko programs into executable WebAssembly (Wasm) modules." +sidebar: + order: 5 --- The Motoko compiler (`moc`) is the primary tool for compiling Motoko programs into executable WebAssembly (Wasm) modules. The compiler runs in the background when you build projects using the [IC SDK](https://github.com/dfinity/sdk). If you invoke the compiler directly on the command-line, you can press CTRL-C to exit. @@ -52,7 +53,7 @@ You can use the following options with the `moc` command. | `--incremental-gc` | Use incremental GC (default, works with both enhanced orthogonal persistence and legacy/classical persistence). | | `--idl` | Compile binary and emit Candid IDL specification to `.did` file. | | `-i` | Runs the compiler in an interactive read–eval–print loop (REPL) shell so you can evaluate program execution (implies -r). | -| `--implicit-derivation-depth ` | Maximum recursion depth for [implicit](/languages/motoko/fundamentals/implicit-parameters) argument derivation (default 100). Raise if a complex derivation is rejected as depth-limited. | +| `--implicit-derivation-depth ` | Maximum recursion depth for [implicit](./fundamentals/11-implicit-parameters.md) argument derivation (default 100). Raise if a complex derivation is rejected as depth-limited. | | `--legacy-persistence` | Use legacy (classical) persistence. This also enables the usage of --copying-gc, --compacting-gc, and --generational-gc. Deprecated in favor of the new enhanced orthogonal persistence, which is default. Legacy persistence will be removed in the future.| | `--map` | Outputs a JavaScript source map. | | `--max-stable-pages ` | Set maximum number of pages available for library `ExperimentStableMemory.mo` (default 65536). | diff --git a/docs/languages/motoko/reference/error-codes.md b/docs/languages/motoko/reference/error-codes.md index cab2c229..3dcfd960 100644 --- a/docs/languages/motoko/reference/error-codes.md +++ b/docs/languages/motoko/reference/error-codes.md @@ -1,7 +1,8 @@ --- -sidebar_position: 1 -description: "Motoko language documentation" title: "Error code reference" +description: "Reference for Motoko compiler error codes with examples and explanations." +sidebar: + order: 2 --- @@ -17,7 +18,7 @@ title: "Error code reference" | M0030 | Type field does not exist in type. | ```type Person = { name : Text }; func getName(p : Person) : Nat { p.age }``` | The field `age` doesn't exist in the `Person` type. | | M0031 | Shared function has non-shared parameter type. | ```public shared func process(obj : { var count : Nat }) { ... }``` | Shared functions cannot have mutable types as parameters. | | M0032 | Shared function has non-shared return type. | ```public shared func getData() : { var data : [Nat] } { ... }``` | Shared functions cannot return mutable types. | -| M0033 | Async has non-shared content type. | ```async { var counter = 0 }``` | Async blocks cannot contain mutable [state](/languages/motoko/fundamentals/actors/state). | +| M0033 | Async has non-shared content type. | ```async { var counter = 0 }``` | Async blocks cannot contain mutable [state](../fundamentals/actors/state.md). | | M0036 | Invalid return type for shared query function. | ```public shared query func getUsers() : async [User] { ... }``` | Query functions cannot return async types. | | M0038 | Misplaced await. | ```func compute() { let x = await promise; }``` | `await` can only be used in an async function or block. | | M0045 | Wrong number of type arguments. | ```func process(x : Array) { ... }``` | `Array` type expects one type parameter, not two. | @@ -33,7 +34,7 @@ title: "Error code reference" | M0082 | Expected iterable type. | ```for (item in 42) { ... }``` | The value `42` is not an iterable type for a for-loop. | | M0088 | Expected async type. | ```let result = await 42;``` | Cannot `await` on a non-async value. | | M0089 | Redundant ignore. | ```ignore (5);``` | The `ignore` is unnecessary for a value that doesn't need to be ignored. | -| M0090 | Actor reference must have an [actor](/languages/motoko/fundamentals/actors/actors-async) type .| ```let a = actor { ... }; a.someMethod();``` | The variable `a` must have an explicit [actor](/languages/motoko/fundamentals/actors/actors-async) type to call its methods. | +| M0090 | Actor reference must have an [actor](../fundamentals/actors/actors-async.md) type .| ```let a = actor { ... }; a.someMethod();``` | The variable `a` must have an explicit [actor](../fundamentals/actors/actors-async.md) type to call its methods. | | M0096 | Expression can't produce expected type. | ```func getValue() : Bool { return "true"; }``` | String cannot be returned where a [`Bool`](https://mops.one/core/docs/Bool) is expected. | | M0097 | Expected function type. | ```let x = 5; x();``` | Cannot call a non-function value. | | M0098 | Cannot instantiate function type. | ```type Func = (Nat) -> Nat; let f = Func();``` | Function types cannot be instantiated directly. | @@ -44,8 +45,8 @@ title: "Error code reference" | M0139 | Inner actor classes are not supported. | ```class Outer() { actor class Inner() { ... } }``` | Actor classes cannot be nested inside other classes. | | M0141 | Forbidden declaration in program. | ```import Prim "mo:prim";``` | Certain imports/declarations are not allowed in normal user code. | | M0145 | Pattern does not cover value. | ```switch (option) { case (null) { ... } };``` (missing `?some` case) | Switch statement doesn't handle all possible values. | -| M0149 | An immutable [record](/languages/motoko/fundamentals/types/records) field (declared without `var`) was supplied where a mutable [record](/languages/motoko/fundamentals/types/records) field (specified with `var`), was expected. | ```type Mutable = { var x : Nat }; func set(r : Mutable) { ... }; set({ x = 10 });``` | Immutable [record](/languages/motoko/fundamentals/types/records) provided where mutable was expected. | -| M0150 | A mutable [record](/languages/motoko/fundamentals/types/records) field (declared with `var`) was supplied where an immutable [record](/languages/motoko/fundamentals/types/records) field (specified without `var`) was expected. | ```type Immutable = { x : Nat }; let record : Immutable = { var x = 10 };``` | Mutable field provided where immutable was expected. | +| M0149 | An immutable [record](../fundamentals/types/records.md) field (declared without `var`) was supplied where a mutable [record](../fundamentals/types/records.md) field (specified with `var`), was expected. | ```type Mutable = { var x : Nat }; func set(r : Mutable) { ... }; set({ x = 10 });``` | Immutable [record](../fundamentals/types/records.md) provided where mutable was expected. | +| M0150 | A mutable [record](../fundamentals/types/records.md) field (declared with `var`) was supplied where an immutable [record](../fundamentals/types/records.md) field (specified without `var`) was expected. | ```type Immutable = { x : Nat }; let record : Immutable = { var x = 10 };``` | Mutable field provided where immutable was expected. | | M0151 | A object literal is missing some fields. | ```type Person = { name : Text; age : Nat }; let p : Person = { name = "John" };``` | The `age` field is missing from the object literal. | | M0153 | An imported Candid file (.did) mentions types that cannot be represented in Motoko. | ```import Types from "types.did";``` (where `types.did` contains incompatible types) | The imported Candid file contains types that don't map to Motoko types. | | M0154 | Deprecation annotation. | ```@deprecated("Use newFunction instead") func oldFunction() { ... }``` | Using a deprecated function or feature that has been marked with `@deprecated`. | diff --git a/docs/languages/motoko/reference/language-manual.md b/docs/languages/motoko/reference/language-manual.md index d4364f0b..a73c193a 100644 --- a/docs/languages/motoko/reference/language-manual.md +++ b/docs/languages/motoko/reference/language-manual.md @@ -1,7 +1,8 @@ --- -sidebar_position: 16 -description: "Motoko language documentation" title: "Language reference" +description: "Complete Motoko language reference covering syntax, types, expressions, declarations, and built-in operations." +sidebar: + order: 1 ---