Skip to content

Commit

Permalink
update tour
Browse files Browse the repository at this point in the history
  • Loading branch information
Yoorkin committed Dec 16, 2024
1 parent b147982 commit c0acce5
Show file tree
Hide file tree
Showing 23 changed files with 37 additions and 40 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

It's cumbersome to write a for loop and manually decide the end condition.

If you want to iterate over a collection, you can use the `for-in` loop.
If you want to iterate over a collection, you can use the `for .. in ... {}` loop.

In the first for-in loop, we iterate over an array. The loop will bind each
element to the variable `element` in each iteration.
Expand Down
11 changes: 6 additions & 5 deletions moonbit-tour/tour/chapter1_basic/lesson11_struct/index.md
Original file line number Diff line number Diff line change
@@ -1,17 +1,18 @@
# Struct

Structs are new types composed of other types.
Struct is a new type composed of other types.

In the example we define a struct `Point` with two fields, `x` and `y`, both of which are integers.
In the example we define a struct `Point` with two fields, `x` and `y`, both of which are integers.

We can create an instance of `Point` by using the `{ x: 3, y: 4}`. The structs name can be omitted since the compiler can infer it from the labels `x` and `y`.
We can create an instance of `Point` by using the `{ x: 3, y: 4 }`. The struct name can be omitted since the compiler can infer it from the labels `x` and `y`.

We can also add a `Point::` prefix to create an instance explicitly to disambiguate.

Analogous to tuples, we can access the fields of a struct using the syntax `point.x`.

The `derive(Show)` after the struct definition means that we can print the struct using the `println` function.
The `derive(Show)` after the struct definition means that we can print the struct using the `println` function.

The fields of a struct are immutable by default; they can't be changed after they are created. There is a syntax called _functional update_ that allows you to create a new struct with some fields updated.
The fields of a struct are immutable by default; they can't be changed after they are created. There is a syntax called *functional update* that allows you to create a new struct with some fields updated.

We will learn how to make the fields mutable in the next lesson.

4 changes: 2 additions & 2 deletions moonbit-tour/tour/chapter1_basic/lesson13_enum/index.md
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
# Enum

Enum used to define a type by enumerating its possible values. Unlike traditional enums, MoonBit enums can have data associated with each enumeration. We call each enumeration a *enum constructor*.
Enum used to define a type by enumerating its possible values. Unlike traditional enums, MoonBit enums can have data associated with each enumeration. We call each enumeration an *enum constructor*.

In this example, we define an enum `Color`, which has five enum constructors: `Red`, `Green`, `Blue`, `RGB`, and `CMYK`. The `Red`, `Green`, and `Blue` directly represent a color it described, while `RGB` and `CMYK` have data associated with them.

Expressions like `Red` and `RGB(255,255,255)` are both instances of the `Color` type. To create an instance more explicitly, you can use `Color::Red`, similar to creating an instance of a struct.
Values like `Red` and `RGB(255,255,255)` are both instances of the `Color` type. To create an instance more explicitly, you can use `Color::Red`, similar to creating an instance of a struct.

We use a bit of *pattern matching* to distinguish different *enum constructors* in `print_color`. It's a control flow similar to switch-case in C-like languages. Here is a slight difference: you can extract the associated data by giving them a name on the left of `=>`, and use them as variables on the right side.

Expand Down
2 changes: 1 addition & 1 deletion moonbit-tour/tour/chapter1_basic/lesson15_option/index.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# Option

`Option[Char]` represents a `Char` value that may or may not be present. It is a common way to handle exceptional cases.
`Option[Char]` is an enum represents a `Char` value that may or may not be present. It is a common way to handle exceptional case.

- `None` means the value is missing.
- `Some(e)` is a wrapper that contains the value `e`.
Expand Down
4 changes: 2 additions & 2 deletions moonbit-tour/tour/chapter1_basic/lesson16_result/index.md
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
# Result

Similar to `Option[Char]`, `Result[Char, String]` represents a `Char` value that may or may not be present. If not, it can contain an error message of type `String`.
Similar to `Option[Char]`, the enum `Result[Char, String]` represents a `Char` value that may or may not be present. Otherwise, it can contain an error message of type `String`.

- `Err("error message")` means the value is missing, and the error message is provided.
- `Ok('h')` is a wrapper that contains the value `'h'`.

The processing of `Option` and `Result` in examples so far is verbose and prone to bugs. To handle `Option` and `Result` values safely and cleanly, you can use pattern matching. It's recommended to use *error handling* to process errors effectively. These two topics will be covered in a later chapter.
The processing of `Option` and `Result` in examples so far is verbose and prone to bugs. To handle `Option` and `Result` values safely and cleanly, you can use *pattern matching*. It's recommended to use *error handling* to process errors effectively. These two topics will be covered in a later chapter.

2 changes: 1 addition & 1 deletion moonbit-tour/tour/chapter1_basic/lesson1_variable/index.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# Variables

The `let` keyword used to define a variables.
The `let` keyword used to define a variable.

The type of the variable can be annotated by using a colon followed by the type.
It is optional, if not provided the type will be inferred from the value.
Expand Down
2 changes: 1 addition & 1 deletion moonbit-tour/tour/chapter1_basic/lesson3_numbers/index.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# Numbers

integers and floats are the most common types in MoonBit, it can be represented in decimal, hexadecimal, octal, and binary, and you can use the underscore to separate digits for better readability.
Integers and floats are the most common types in MoonBit, it can be represented in decimal, hexadecimal, octal, and binary, and you can use the underscore to separate digits for better readability.
We call these *number literals*.

The `0xFFFF` is a hexadecimal number, `0o777` is an octal number, `0b1010` is a binary number,
Expand Down
4 changes: 2 additions & 2 deletions moonbit-tour/tour/chapter1_basic/lesson5_array/index.md
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
# Array

Array is a collection of elements, which have same type.
Array is a collection of elements that have the same type.

You can create an array by *array literal syntax*, which is a comma-separated list
of elements enclosed in square brackets: `[1,2,3]`.

You can also create an array by using the `Array::make` function, which takes a size and a element value,
You can also create an array by using the `Array::make` function, which takes a size and an element value,
as shown in the example, `Array::make(4,1)` creates an array equal to `[1,1,1,1]`.

The `arr3` is an array consists of elements in `arr1`, elements in `arr2` and a few more numbers.
Expand Down
8 changes: 4 additions & 4 deletions moonbit-tour/tour/chapter1_basic/lesson7_tuple/index.md
Original file line number Diff line number Diff line change
@@ -1,15 +1,15 @@
# Tuple

Tuple is a collection of values, which can have different types. It is immutable,
Tuple is a collection of values that can have different types. It is immutable,
which means that once it is created, it cannot be changed. It is created using
parentheses.

You can access the elements of tuple via the index: `tuple.0`, `tuple.1`, etc.

Tuple can be destructured via syntax like `let (a,b) = tuple`, the `tuple` in
Tuple can be destructed via syntax like `let (a,b) = tuple`, the `tuple` in
right side is a tuple with two elements, and `a` and `b` are the variables to
store the elements. This is a special use case of pattern matching. We will
introduce pattern matching in the later chapter.
store the elements. This is a special use case of *pattern matching*. We will
introduce *pattern matching* in the later chapter.

It's common to use tuple to return multiple values from a function.

8 changes: 2 additions & 6 deletions moonbit-tour/tour/chapter1_basic/lesson8_map/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,9 @@

A map is a collection of key-value pairs. Each key is unique in the map, and all keys are associated with a value. It is a mutable collection.

Expression like `{"key1": value1, "key2": value2}` represents a map, called a map
literal. If the key and value type of the map is basic type (`Int`, `String`,
`Bool`, `Double`, etc.), it can be written as map literal.
Expression like `{"key1": value1, "key2": value2}` represents a map, called a *map literal*. If the key and value type of the map is basic type (`Int`, `String`,`Bool`, `Double`, etc.), it can be written as *map literal*.

In other cases, you can create the map using the `Map::of` function. It takes a
array of two elements tuple, the first element is the key, and the second element
is the value.
In other cases, you can create the map using the `Map::of` function. It takes an array of two-element tuples, where the first element is the key and the second element is the value.

Values in a map can be accessed by the key using the `map[key]` syntax.

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,13 +13,9 @@ for init; condition; increment {
}
```

The loop initializes the variables in the `init` part before it starts. When the loop starts, it tests the `condition` and executes the loop body if the `condition` is true. After that, it runs the `increment` expression and repeats the process until the condition is false.

The loop initializes the variables `init` before it starts. When the loop starts,
it tests the `condition` and executes the loop body if the `condition` is true.
After that, it runs the `increment` expression and repeats the process until the
condition is false.

The for loop in MoonBit is more expressive than the C-style for loop. We will
In MoonBit, the for loop is more expressive than the C-style for loop. We will
explain it in the following chapters.

## While loop and if-else expression
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
We have seen pattern matching in the previous example.
It's a powerful feature in MoonBit that can be used in many places. It can help you test conditions conveniently and effectively, making your program more precise and robust.

In this example, we give some basic use cases of pattern matching. Some other languages call it "destructuring", a way to extract values from a complex data structure.
In this example, we give some basic use cases of pattern matching. Some other languages call it "destructuring" or "structured bindings", a way to extract values from a complex data structure.

"Destructuring" is just a subset of this feature.
In MoonBit, almost every type you can construct can have a form to "destruct", which we call a *pattern*.
Original file line number Diff line number Diff line change
Expand Up @@ -6,16 +6,17 @@ We defined a `Resource` type, it describes a file system. The `Resource` can be

## Pattern in let statement

In a let statement, the left side of `=` can be a pattern, we knowns that assets is a folder so just use `let Folder(top_level) = assets` to match it and extract the inside map.
In a let statement, the left side of `=` can be a pattern, we known that assets is a folder so just use `let Folder(top_level) = assets` to match it and extract the inside map.

You may notice that there is a partial match warning because the resource can also be `Image` or `TextFile`. **Partial match make the program more fragile: the pattern matching will fail in other cases and lead to the program aborting.** Practically, the match expression is used more frequently.

## Pattern in match expression

The `count` function traverse the input `res` recursively and return the count of `Image` and `TextFile`, using match expression.
The `count` function traverse the input `res` recursively and return the count of `Image` and `TextFile`, using match expression.

Match expression have _first match semantic_. It will try to find the first matched pattern from first case to last case, and execute the e
Match expressions have *first match semantics*. They will try to find the first matching pattern from the first case to the last case and execute the corresponding expression.

The match expression has a `Int` return value because all the case result in same value type `Int`.

Patterns can be nested. If you don't care about the data associated with the enum constructor, you can use the _any pattern_, written as `_`, instead of introducing a new variable. It means discarding that value.
Patterns can be nested. If you don't care about the data associated with the enum constructor, you can use the *any pattern*, written as `_`, instead of introducing a new variable. It means discarding that value.

Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@

Use tuple pattern to match multiple conditions at once.

This example simulates _logical and_ and _logical or_ operation via pattern matching.
This example simulates *logical and* and *logical or* operation via pattern matching.

In this scenario, the overhead of creating the tuple in the condition will be optimized out by the compiler.


Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
# Or Pattern
# Or Pattern

It's a little verbose if any two cases have common data and same way to handle them. For example, here is a enum `RGB` and a function `get_green` to get the green value from it.
It's a little verbose if any two cases have common data and same way to handle them. For example, here is a enum `RGB` and a function `get_green` to get the green value from it.

The `RGB` and `RGBA` cases can be combined as well. In an *or pattern*, the sub-patterns can introduce new variables, but they must be of the same type and have the same name in all sub-patterns. This restriction allows us to handle them uniformly.

The `RGB` and `RGBA` cases can be combined as well. In an _or pattern_, the sub-patterns can introduce new variables, but they must be of the same type and have the same name in all sub-patterns. This restriction allows us to handle them uniformly.

0 comments on commit c0acce5

Please sign in to comment.