Skip to content

Commit

Permalink
docs: Recursive types (#4715)
Browse files Browse the repository at this point in the history
* Recursive types

* Update recursive-types.md

* Recursive types

* Update recursive-types.md

* Update recursive-types.md

* Update doc/md/writing-motoko/recursive-types.md

Co-authored-by: Gabor Greif <[email protected]>

* Update local-objects-classes.md

* Update recursive-types.md

---------

Co-authored-by: Gabor Greif <[email protected]>
  • Loading branch information
jessiemongeon1 and ggreif authored Oct 7, 2024
1 parent 00d60e4 commit 5ca3f22
Show file tree
Hide file tree
Showing 3 changed files with 75 additions and 3 deletions.
2 changes: 1 addition & 1 deletion doc/md/writing-motoko/async-star.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
---
sidebar_position: 27
sidebar_position: 28
---

# Abstracting asynchronous code
Expand Down
29 changes: 27 additions & 2 deletions doc/md/writing-motoko/local-objects-classes.md
Original file line number Diff line number Diff line change
Expand Up @@ -162,7 +162,32 @@ The `class` keyword syntax shown above is a shorthand for these two definitions

An object class defines a constructor function that may carry zero or more data arguments and zero or more type arguments.

The `Counter` example above has zero of each.
The `Counter` example above has zero of each. The example below takes two data arguments, `arg1` and `arg2`, with `Type1` and `Type2` as the types of these arguments, respectively.

``` motoko no-repl
class MyClass(arg1: Type1, arg2: Type2) {
// class body here
};
```

For example, you can write a `Counter` class that takes an argument of type `Nat` and an argument of type `Bool`:

``` motoko no-repl
import Nat "mo:base/Nat";
actor {
class Counter(init : Nat, flag : Bool) {
var c = init;
var f = flag;
public func inc() : Nat {
if f {
c += 1;
};
return c;
};
};
}
```

The type arguments, if any, parameterize both the type and the constructor function for the class.

Expand Down Expand Up @@ -324,4 +349,4 @@ extend existing objects with new functionality.

For more details, see the [language manual](../reference/language-manual#object-combinationextension).

<img src="https://github.com/user-attachments/assets/844ca364-4d71-42b3-aaec-4a6c3509ee2e" alt="Logo" width="150" height="150" />
<img src="https://github.com/user-attachments/assets/844ca364-4d71-42b3-aaec-4a6c3509ee2e" alt="Logo" width="150" height="150" />
47 changes: 47 additions & 0 deletions doc/md/writing-motoko/recursive-types.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
---
sidebar_position: 29
---

# Recursive types

## Overview

A recursive type is a type that contains the values of the same type. Recursive types enable you to create complex recursive data structures, such as linked lists or trees.

Motoko supports linked lists, a data structure that is an example of a recursive type.

## Recursive lists

``` motoko no-repl
type List<T> = ?(T, List<T>);
```

In this example, the generic type `List<T>` is defined with one type parameter. `List<T>` is a tuple with two components: the first component is the type parameter `T` , and the second component is `List<T>`. The second component is the recursive type, as the generic type `List<T>` contains a value of itself within its own definition.

`List` is a repeating pattern, where each repeated component is a tuple that contains a value of type `T` and a reference to the tail of `List<T>`.

## Recursive functions

A recursive function can be used to retrieve the last element of a given list:

```motoko no-repl
func last<T>(l : List<T>) : ?T {
switch l {
case null { null };
case (?(x, null)) { ?x };
case (?(_, t)) { last<T>(t) };
};
};
```

This generic function `last<T>` takes one argument `l` of type `List<T>`, which refers to the head of a list. If this function returns the last element of a list, it returns an optional value `?T`. If there isn't a last element, it will return `null`. The body of the function uses a `switch` statement to determine if the list passed as an argument is an empty list, the last element of a list, or if it is the tail of a list with a next value.

In this switch statement, the `last<T>` function is used recursively, since it is called within itself with `t` as the argument. The function is called again each time the case statement is satisfied, and the function receives a list head that it can switch on until the last element is returned.

:::info
Note that you will need to use recursive functions to access all data in a recursive type.
:::

## Resources

- [Recursive types](https://github.com/Web3NL/motoko-book/blob/main/src/advanced-types/recursive-types.md).

0 comments on commit 5ca3f22

Please sign in to comment.