Skip to content

Commit

Permalink
Update code examples to use no-repl (#4704)
Browse files Browse the repository at this point in the history
  • Loading branch information
jessiemongeon1 authored Sep 19, 2024
1 parent 8bfee2b commit 1219a50
Show file tree
Hide file tree
Showing 21 changed files with 48 additions and 50 deletions.
6 changes: 3 additions & 3 deletions doc/md/canister-maintenance/upgrades.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ sidebar_position: 3

One key feature of Motoko is its ability to automatically persist the program's state without explicit user instruction, called **orthogonal persistence**. This not only covers persistence across transactions but also includes canister upgrades. For this purpose, Motoko features a bespoke compiler and runtime system that manages upgrades in a sophisticated way such that a new program version can pick up the state left behind by a previous program version. As a result, Motoko data persistence is not simple but also prevents data corruption or loss, while being efficient at the same time. No database, stable memory API, or stable data structure is required to retain state across upgrades. Instead, a simple `stable` keyword is sufficient to declare an data structure of arbitrary shape persistent, even if the structure uses sharing, has a deep complexity, or contains cycles.

This is substantially different to other languages supported on the IC, which use off-the-shelf language implementations that are not designed for orthogonal persistence in mind: They rearrange memory structures in an uncontrolled manner on re-compilation or at runtime. As an alternative, in other languages, programmers have to explicilty use stable memory or special stable data structures to rescue their data between upgrades. Contrary to Motoko, this approach is not only cumbersome, but also unsafe and inefficient. Compared to using stable data structures, Motoko's orthogonal persistence allows more natural data modeling and significantly faster data access, eventually resulting in more efficient programs.
This is substantially different to other languages supported on the IC, which use off-the-shelf language implementations that are not designed for orthogonal persistence in mind: They rearrange memory structures in an uncontrolled manner on re-compilation or at runtime. As an alternative, in other languages, programmers have to explicitly use stable memory or special stable data structures to rescue their data between upgrades. Contrary to Motoko, this approach is not only cumbersome, but also unsafe and inefficient. Compared to using stable data structures, Motoko's orthogonal persistence allows more natural data modeling and significantly faster data access, eventually resulting in more efficient programs.

## Declaring stable variables

Expand Down Expand Up @@ -71,7 +71,7 @@ Unlike stable data structures in the Rust CDK, these modules do not use stable m

For example, the stable type `TemperatureSeries` covers the persistent data, while the non-stable type `Weather` wraps this with additional methods (local function types).

```motoko
```motoko no-repl
actor {
type TemperatureSeries = [Float];
Expand Down Expand Up @@ -121,7 +121,7 @@ You can emit the stable signature of the main actor or actor class to a `.most`
A stable signature `<stab-sig1>` is stable-compatible with signature `<stab-sig2>`, if for each stable field `<id> : T` in `<stab-sig1>` one of the following conditions hold:

- `<stab-sig2>` does not contain a stable field `<id>`.
- `<stab-sig>` has a matchng stable field `<id> : U` with `T <: U`.
- `<stab-sig>` has a matching stable field `<id> : U` with `T <: U`.

Note that `<stab-sig2>` may contain additional fields or abandon fields of `<stab-sig1>`. Mutability can be different for matching fields.

Expand Down
2 changes: 1 addition & 1 deletion doc/md/getting-started/basic-concepts.md
Original file line number Diff line number Diff line change
Expand Up @@ -199,7 +199,7 @@ Debug.trap("oops!");

**Assertions** allow you to conditionally trap when some Boolean test fails to hold, but continue execution otherwise:

``` motoko
``` motoko no-repl
let n = 65535;
assert n % 2 == 0; // traps when n not even
```
Expand Down
3 changes: 1 addition & 2 deletions doc/md/getting-started/quickstart.md
Original file line number Diff line number Diff line change
Expand Up @@ -61,8 +61,7 @@ Lastly, you can include extra features to be added to your project:
This hello world actor has a single function called `greet`. It is marked as `query` because it doesn't modify the state of the actor. The function accepts a name as input in type [`Text`](../base/Text.md) and returns a greeting of type [`Text`](../base/Text.md).


```motoko
//src/hello_backend/main.mo
```motoko title="src/hello_backend/main.mo"
actor {
public query func greet(name : Text) : async Text {
Expand Down
6 changes: 3 additions & 3 deletions doc/md/migration-guides/0.11.0-migration-guide.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ User-defined functions must now declare an explicit system pseudo-type parameter

For example, in previous Motoko versions the following could be used:

```motoko
```motoko no-repl
func splitCycles() {
let amount = ExperimentalCycles.balance() / 2;
ExperimentalCycles.add(amount); // new error
Expand All @@ -47,7 +47,7 @@ This code will now throw a compiler error such as:

For Motoko v0.11.0 and newer, the previous code should be rewritten to include the system type parameter:

```motoko
```motoko no-repl
func splitCycles<system>() {
let amount = ExperimentalCycles.balance() / 2;
ExperimentalCycles.add(amount); // warning
Expand All @@ -62,7 +62,7 @@ this function call implicitly requires `system` capability and may perform undes

This warning can be silenced by adding the pseudo-type argument `system` at the call-site:

```motoko
```motoko no-repl
func splitCycles<system>() {
let amount = ExperimentalCycles.balance() / 2;
ExperimentalCycles.add<system>(amount); // no warning or error
Expand Down
2 changes: 1 addition & 1 deletion doc/md/motoko-tools/mo-dev.md
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ mo-test --testmode wasi

To configure the runtime of an individual unit test, include the following comment within your test file (`*.test.mo`):

```motoko
```motoko no-repl
// @testmode wasi
```

Expand Down
2 changes: 1 addition & 1 deletion doc/md/motoko-tools/motoko-formatter.md
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ It is also compatible with the the [Prettier extension](https://marketplace.visu

You can set code to be skipped from formatting or being validated by using a `prettier-ignore` comment:

```motoko
```motoko no-repl
// prettier-ignore
func ignored<A>(a:A){a};
Expand Down
2 changes: 1 addition & 1 deletion doc/md/reference/generating-docs.md
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ $(dfx cache show)/mo-doc [options]

Doc comments can be used to provide explanations for functions, classes, types, modules, variables, and more. They can span multiple lines and may contain rich Markdown formatting:

```motoko
```motoko no-repl
/// Calculate the factorial of a given positive integer.
///
/// Example:
Expand Down
4 changes: 2 additions & 2 deletions doc/md/writing-motoko/actor-classes.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ The actor responsible for bucket `i` is obtained as an instance of the actor cla

`Buckets.mo`:

``` motoko name=Buckets file=../examples/Buckets.mo
``` motoko no-repl name=Buckets file=../examples/Buckets.mo
```

A bucket stores the current mapping of keys to values in a mutable `map` variable containing an imperative RedBlack tree, `map`, that is initially empty.
Expand All @@ -30,7 +30,7 @@ Both functions use the class parameters `n` and `i` to verify that the key is ap

Clients of the map can then communicate with a coordinating `Map` actor, implemented as follows:

``` motoko include=Buckets file=../examples/Map.mo
``` motoko no-repl include=Buckets file=../examples/Map.mo
```

As this example illustrates, the `Map` code imports the `Bucket` actor class as module `Buckets`.
Expand Down
2 changes: 1 addition & 1 deletion doc/md/writing-motoko/actors-async.md
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,7 @@ Like other modern programming languages, Motoko permits an ergonomic syntax for

In the case of Motoko, each communicating component is an actor. As an example of using actors, consider this three-line program:

```motoko
```motoko no-repl
let result1 = service1.computeAnswer(params);
let result2 = service2.computeAnswer(params);
finalStep(await result1, await result2)
Expand Down
4 changes: 2 additions & 2 deletions doc/md/writing-motoko/async-data.md
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,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`](../base/Nat.md), `n`:

``` motoko include=counter
``` motoko no-repl
let a : async Nat = Counter.read();
let n : Nat = await a;
```
Expand All @@ -61,7 +61,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 include=counter
``` motoko no-repl
let n : Nat = await Counter.read();
```

Expand Down
10 changes: 5 additions & 5 deletions doc/md/writing-motoko/async-star.md
Original file line number Diff line number Diff line change
Expand Up @@ -129,34 +129,34 @@ the computation each time.
For another example, suppose we define a
clap function with the side-effect of printing "clap".

``` motoko name=clap
``` motoko no-repl
import Debug "mo:base/Debug"
func clap() { Debug.print("clap") }
```

Now, using futures, this code will clap once:

``` motoko include=clap
``` motoko no-repl
let future = async { clap() };
```

This remains the case, no matter how often you await `future`.
For example:

``` motoko include=clap
``` motoko no-repl
let future = async { clap() };
await future;
await future;
```

Using computations, on the other hand, the following definition has no effect on its own:

``` motoko include=clap
``` motoko no-repl
let computation = async* { clap() };
```
But, the following example will clap twice:

``` motoko include=clap
``` motoko no-repl
let computation = async* { clap() };
await* computation;
await* computation;
Expand Down
8 changes: 4 additions & 4 deletions doc/md/writing-motoko/incomplete-code.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,13 +13,13 @@ To accommodate these situations, Motoko provides the `xxx`, `nyi` and `unreachab

Assuming that one has imported the prelude as follows:

``` motoko name=prelude
``` motoko no-repl
import P "mo:base/Prelude";
```

You can fill any missing expression with the following:

``` motoko include=prelude
``` motoko no-repl
P.xxx()
```

Expand All @@ -30,7 +30,7 @@ The expression `xxx()` has type `None`, which is a subtype of every other type.

By convention, longer-term holes can be considered "not yet implemented" (`nyi`) features, and marked as such with a similar function from the Prelude module:

``` motoko include=prelude
``` motoko no-repl
P.nyi()
```
Like `xxx()`, `nyi()` has type `None`, thus any other type, and will trap on execution.
Expand All @@ -41,7 +41,7 @@ Sometimes you will be required to provide code that they know will never be exec

To document unreachable code, you can use the `unreachable` function from the prelude:

``` motoko include=prelude
``` motoko no-repl
P.unreachable()
```

Expand Down
2 changes: 1 addition & 1 deletion doc/md/writing-motoko/intercanister-calls.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ This example will showcase a simple way to configure inter-canister calls that c

Consider the following code for `canister1`:

```motoko
```motoko no-repl
import Canister2 "canister:canister2";
actor {
Expand Down
6 changes: 3 additions & 3 deletions doc/md/writing-motoko/local-objects-classes.md
Original file line number Diff line number Diff line change
Expand Up @@ -109,7 +109,7 @@ In Motoko, an object encapsulates state, and an object `class` is a package of t

Consider this example `class` for counters that start at zero:

``` motoko name=counter
``` motoko no-repl
class Counter() {
var c = 0;
public func inc() : Nat {
Expand All @@ -121,14 +121,14 @@ class Counter() {

The value of this definition is that we can construct new counters, each starting with their own unique state, initially at zero:

``` motoko name=cinit include=counter
``` motoko no-repl
let c1 = Counter();
let c2 = Counter();
```

Each is independent:

``` motoko include=counter,cinit
``` motoko no-repl
let x = c1.inc();
let y = c2.inc();
(x, y)
Expand Down
4 changes: 2 additions & 2 deletions doc/md/writing-motoko/modules-and-imports.md
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,7 @@ For Vessel, edit the `vessel.dhall` file to include what packages your project w

Then, import the packages as you would import other packages in the Motoko source file:

```motoko
```motoko no-repl
import Vec "mo:vector";
import Vec "mo:vector/Class";
```
Expand All @@ -125,7 +125,7 @@ For example, a Motoko actor can import and instantiate the `Counter` class descr

`CountToTen.mo`:

``` motoko include=Counters file=../examples/CountToTen.mo
``` motoko no-repl file=../examples/CountToTen.mo
```

The call to `Counters.Counter(1)` installs a fresh counter on the network. Installation is asynchronous, so the caller must `await` the result.
Expand Down
14 changes: 7 additions & 7 deletions doc/md/writing-motoko/mutable-state.md
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ If you try to assign new values to either [`Text`](../base/Text.md) or `num` abo

You may freely update the value of mutable variables `pair` and `text2` using the syntax for assignment, written as `:=`, as follows:

``` motoko include=init
``` motoko no-repl
text2 := text2 # "xyz";
pair := (text2, pair.1);
pair
Expand All @@ -58,7 +58,7 @@ After the second line, the variable `num2` holds `42`, as one would expect.

Motoko includes other combinations as well. For example, we can rewrite the line above that updates `text2` more concisely as:

``` motoko include=init
``` motoko no-repl
text2 #= "xyz";
text2
```
Expand Down Expand Up @@ -114,7 +114,7 @@ Before discussing [mutable arrays](#mutable-arrays), we introduce immutable arra

### Allocate an immutable array of constants

``` motoko name=array
``` motoko
let a : [Nat] = [1, 2, 3] ;
```

Expand All @@ -124,7 +124,7 @@ The array `a` above holds three natural numbers, and has type `[Nat]`. In genera

You can read from an array using the usual bracket syntax of `[` and `]` around the index you want to access:

``` motoko include=array
``` motoko no-repl
let x : Nat = a[2] + a[0] ;
```

Expand All @@ -134,7 +134,7 @@ Every array access in Motoko is safe. Accesses that are out of bounds will not a

The Motoko standard library provides basic operations for immutable and mutable arrays. It can be imported as follows:

``` motoko name=import
``` motoko no-repl
import Array "mo:base/Array";
```

Expand All @@ -156,7 +156,7 @@ The function `gen` actually functions as the array during its initialization. It

For instance, you can first allocate `array1` consisting of some initial constants, then functionally update some of the indices by changing them in a pure, functional way, to produce `array2`, a second array that does not destroy the first.

``` motoko include=import
``` motoko no-repl
let array1 : [Nat] = [1, 2, 3, 4, 6, 7, 8] ;
let array2 : [Nat] = Array.tabulate<Nat>(7, func(i:Nat) : Nat {
Expand Down Expand Up @@ -195,7 +195,7 @@ func init<T>(size : Nat, x : T) : [var T]

For example:

``` motoko include=import
``` motoko no-repl
var size : Nat = 42 ;
let x : [var Nat] = Array.init<Nat>(size, 3);
```
Expand Down
4 changes: 2 additions & 2 deletions doc/md/writing-motoko/pattern-matching.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,13 +31,13 @@ The following table summarizes the different ways of pattern matching.

Consider the following function call:

``` motoko include=fullname
``` motoko no-repl
let name : Text = fullName({ first = "Jane"; mid = "M"; last = "Doe" });
```

This code constructs a record with three fields and passes it to the function `fullName`. The result of the call is named and brought into scope by binding it to the identifier `name`. The last, binding step is called pattern matching, and `name : Text` is one of the simplest forms of a pattern. For instance, in the following implementation of the callee:

``` motoko name=fullname
``` motoko
func fullName({ first : Text; mid : Text; last : Text }) : Text {
first # " " # mid # " " # last
};
Expand Down
2 changes: 1 addition & 1 deletion doc/md/writing-motoko/pipes.md
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ Note that using `_` as an expression outside of a pipe operation, where it is un

For example, the following example produces the compile-time error "type error [M0057], unbound variable _":

``` motoko
``` motoko no-repl
let x = _;
```

Expand Down
1 change: 0 additions & 1 deletion doc/md/writing-motoko/randomness.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,6 @@ The Random module features a class called `Finite` and a `*From` method. These c
To demonstrate randomness, consider the following example that shuffles a deck of cards then returns the cards in their shuffled order. The code is annotated with additional information:

```motoko
// Import the necessary modules, including the Random module:
import Random = "mo:base/Random";
import Char = "mo:base/Char";
Expand Down
Loading

0 comments on commit 1219a50

Please sign in to comment.