-
Notifications
You must be signed in to change notification settings - Fork 93
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
1 changed file
with
133 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,133 @@ | ||
# Moonbit/Core List | ||
|
||
## Overview | ||
|
||
List is implemented as a **linked list**, supporting O(1) head access. | ||
- Moonbit list is **homogenous** list, which means all elements in the list must be of the same type. | ||
- Moonbit list does not support random access well, you can only access elements by iterating through the list. If you need randomly access the nth element, you should use `Vec` instead. | ||
|
||
## Usage | ||
|
||
### Building lists | ||
You can create a list manually via the `new()` or construct it using the `from_array()`. | ||
```moonbit | ||
let list0 : List[Int] = List::new() | ||
let list1 = List::[1, 2, 3, 4, 5] | ||
let list2 = List::from_array([1, 2, 3, 4, 5]) | ||
``` | ||
|
||
Or use `Cons` constructor directly (Adds a single element to the beginning of a list): | ||
```moonbit | ||
let list = Cons(1, Cons(2, Cons(3, Nil))) | ||
``` | ||
|
||
Build a repeated list by using the `repeat()` method: | ||
```moonbit | ||
let list = repeat(3, 1) // List::[1, 1, 1] | ||
``` | ||
|
||
### Patten matching | ||
You can use pattern matching to destructure a list: | ||
```moonbit | ||
let list = List::[1, 2, 3, 4, 5] | ||
match list { | ||
Cons(head, tail) => print(head) | ||
Nil => print("Empty list") | ||
} | ||
``` | ||
|
||
### Iterating over a list | ||
The standard library provides a lot of tools for iterating over a list, such as `iter()`, `iteri()`, etc. (For details check the API documentation) | ||
```moonbit | ||
let list = List::[1, 2, 3, 4, 5] | ||
let list1 = list.iter(fn (ele) { print(ele) }) | ||
``` | ||
|
||
### Appending / Joining lists | ||
To simply concatenate two lists, you can use the `concat()` method (or `+` operator): | ||
```moonbit | ||
let list1 = List::[1, 2, 3] | ||
let list2 = List::[4, 5, 6] | ||
let list3 = list1.concat(list2) // List::[1, 2, 3, 4, 5, 6] | ||
let list4 = list1 + list2 // List::[1, 2, 3, 4, 5, 6] | ||
``` | ||
|
||
For concatenating multiple lists (especially the length is unknown), you can use the `flatten()` method: | ||
```moonbit | ||
let list1 = List::[1, 2, 3] | ||
let list2 = List::[4, 5, 6] | ||
let list3 = List::[7, 8, 9] | ||
let list4 = List::flatten([list1, list2, list3]) // List::[1, 2, 3, 4, 5, 6, 7, 8, 9] | ||
``` | ||
|
||
To concatenate a list with a delimiter, `intercalate()` is useful: | ||
```moonbit | ||
let list = List::[List::[1, 2, 3], List::[4, 5, 6], List::[7, 8, 9]] | ||
let list1 = list.intercalate(List::[0]) // List::[1, 2, 3, 0, 4, 5, 6, 0, 7, 8, 9] | ||
``` | ||
|
||
### Filtering / Rejecting / Selecting elements | ||
There are three ways to filter / reject / select multiple elements from a list: | ||
- Go through the entire list and decide whether the element should be present in the resultant list or not. Use `filter` for this. | ||
- To extract the first (or last) N elements of a list (and N is independent of the contents of the list). Use `take` or `drop` in this case. | ||
- To stop selecting elements (terminate the iteration) as soon as a condition is met, using `take_while` or `drop_while` | ||
|
||
```moonbit | ||
let ls = List::[1, 2, 3, 4, 5] | ||
ls.filter(fn (ele) { ele % 2 == 0 }) // List::[2, 4] | ||
ls.take(2) // List::[1, 2] | ||
ls.drop(2) // List::[3, 4, 5] | ||
ls.take_while(fn (ele) { ele < 3 }) // List::[1, 2] | ||
ls.drop_while(fn (ele) { ele < 3 }) // List::[3, 4, 5] | ||
``` | ||
|
||
### Accessing elements / sub-lists | ||
You can access the head of the list using the `head()` (O(1)) method, and the last element in list using the `last()` (O(n)) method. | ||
These two functions will panic if the list is empty. | ||
```moonbit | ||
let list = List::[1, 2, 3, 4, 5] | ||
list.head() // 1 | ||
list.last() // 5 | ||
``` | ||
|
||
For randomly accessing, you can use the `nth()` method, which returns the nth element in the list (O(n)). | ||
This method will panic if the index is out of bounds. For a safe alternative, use `nth_option()` method. | ||
```moonbit | ||
let list = List::[1, 2, 3, 4, 5] | ||
list.nth(2) // 3 | ||
list.nth_option(2) // Some(3) | ||
``` | ||
|
||
To get a sub-list from the list, you can use the `init_()` method for getting all elements except the last one, and `tail()` for getting all elements except the first one. | ||
```moonbit | ||
let list = List::[1, 2, 3, 4, 5] | ||
list.init_() // List::[1, 2, 3, 4] | ||
list.tail() // List::[2, 3, 4, 5] | ||
``` | ||
|
||
### Reducing Lists | ||
You can reduce (fold) a list to a single value using the `fold()` method. | ||
```moonbit | ||
let list = List::[1, 2, 3, 4, 5] | ||
list.fold(0, fn(acc, x) { acc + x }) // 15 | ||
``` | ||
|
||
#### Special folds | ||
- `any` returns true if any element in the list satisfies the predicate. | ||
- `all` returns true if all elements in the list satisfy the predicate. | ||
- `sum` returns the sum of all elements in the list. | ||
- `maximum` returns the maximum element in the list. | ||
- `minimum` returns the minimum element in the list. | ||
|
||
### List transformations | ||
To transform list elements, you can use the `map()` method. | ||
```moonbit | ||
let list = List::[1, 2, 3, 4, 5] | ||
list.map(fn (ele) { ele * 2 }) // List::[2, 4, 6, 8, 10] | ||
``` | ||
|
||
The `reverse` method reverses the list. | ||
```moonbit | ||
let list = List::[1, 2, 3, 4, 5] | ||
list.reverse() // List::[5, 4, 3, 2, 1] | ||
``` |