-
Notifications
You must be signed in to change notification settings - Fork 57
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
fix(tour): update project structure and format code blocks (#298)
* fix(tour): outdated project structure and command * fix(tour): format codeblocks
- Loading branch information
Showing
2 changed files
with
56 additions
and
53 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 |
---|---|---|
|
@@ -39,18 +39,20 @@ To create a project (or module, more formally), run `moon new`. You will be gree | |
|
||
``` | ||
my-project | ||
├── LICENSE | ||
├── moon.mod.json | ||
├── README.md | ||
├── lib | ||
│ ├── hello.mbt | ||
│ ├── hello_test.mbt | ||
│ └── moon.pkg.json | ||
├── main | ||
│ ├── main.mbt | ||
│ └── moon.pkg.json | ||
└── moon.mod.json | ||
└── src | ||
├── lib | ||
│ ├── hello.mbt | ||
│ ├── hello_test.mbt | ||
│ └── moon.pkg.json | ||
└── main | ||
├── main.mbt | ||
└── moon.pkg.json | ||
``` | ||
|
||
This resembles a typical MoonBit module structure. Try running `moon run main`. | ||
This resembles a typical MoonBit module structure. Try running `moon run src/main`. | ||
|
||
Now, we can get started. | ||
|
||
|
@@ -66,7 +68,7 @@ Variables are defined with `let`: | |
```moonbit | ||
let e = 2.718281828459045 // double | ||
let int_min = -2147483648 // int | ||
let int_max: Int = 2147483647 // explicit type annotation | ||
let int_max : Int = 2147483647 // explicit type annotation | ||
let tuple = (1, 2) // 2-tuple | ||
``` | ||
|
||
|
@@ -91,7 +93,7 @@ By default, the `let` - binding creates an immutable reference to a value. That | |
Function is just a piece of code that takes some inputs and produce a result. We may define a function using the keyword `fn` (function name in MoonBit should not begin with uppercase letters A-Z): | ||
|
||
```moonbit | ||
fn identity[T](x: T) -> T { | ||
fn identity[T](x : T) -> T { | ||
// `Identity` won't work as it violates naming convention | ||
x | ||
} | ||
|
@@ -125,7 +127,7 @@ Languages nowadays have something called _lambda expression_. Most languages imp | |
```moonbit | ||
fn foo() -> Int { | ||
fn inc(x) { x + 1 } // named as `inc` | ||
fn (x) { x + inc(2) } (6) // anonymous, a so-called 'lambda expression' | ||
(fn (x) { x + inc(2) })(6) // anonymous, a so-called 'lambda expression' | ||
// function automatically captures the result of the last expression | ||
} | ||
``` | ||
|
@@ -159,27 +161,27 @@ Another datatype frequently used in MoonBit is our good old `Struct`, which work | |
|
||
```moonbit | ||
struct User { | ||
id: Int | ||
name: String | ||
id : Int | ||
name : String | ||
// by default the properties/fields of a struct is immutable. | ||
// the `mut` keyword works exactly the way we've mentioned before. | ||
mut email: String | ||
mut email : String | ||
} derive(Show) | ||
// a method of User is defined by passing a object of type User as self first. | ||
// just like what you would do in Python. | ||
// Note that methods may only be defined within the same package the type is in. | ||
// We may not define methods for foreign types directly | ||
fn greetUser(self: User) -> String{ // a method of struct/type/class `User` | ||
fn greetUser(self : User) -> String { // a method of struct/type/class `User` | ||
let id = self.id | ||
let name = self.name | ||
"Greetings, \{name} of id \{id}" // string interpolation | ||
} | ||
// construct a User object. | ||
let evan: User = {id:0,name:"Evan",email:"[email protected]"} | ||
let evan : User = { id: 0, name: "Evan", email: "[email protected]" } | ||
// we use a shorthand by duplicating evan's information | ||
// and replacing w/ someone elses' email. | ||
let listOfUser: List[User] = Cons(evan, Cons({..evan, email: "[email protected]"}, Nil)) | ||
let listOfUser : List[User] = Cons(evan, Cons({ ..evan, email: "[email protected]" }, Nil)) | ||
``` | ||
|
||
Another datatype is `type`, a specific case of `enum` type. `type` can be thought as a wrapper | ||
|
@@ -228,20 +230,20 @@ trait Printable { | |
} | ||
fn to_string(self : User) -> String { | ||
(self.id,self.name,self.email).to_string() | ||
(self.id, self.name, self.email).to_string() | ||
} // now `Printable` is implemented | ||
fn to_string[T: Printable](self : List[T]) -> String { | ||
fn to_string[T : Printable](self : List[T]) -> String { | ||
let string_aux = to_string_aux(self) | ||
// function arguments can have label | ||
"[" + string_aux.substring(end = string_aux.length() - 1) + "]" | ||
"[" + string_aux.substring(end=string_aux.length() - 1) + "]" | ||
} | ||
// polymorphic functions have to be toplevel. | ||
fn to_string_aux[T: Printable](self: List[T]) -> String{ | ||
fn to_string_aux[T : Printable](self : List[T]) -> String { | ||
match self { | ||
Nil => "" | ||
Cons(x,xs) => "\{x} " + to_string_aux(xs) | ||
Cons(x, xs) => "\{x} " + to_string_aux(xs) | ||
} | ||
} | ||
``` | ||
|
@@ -301,11 +303,11 @@ Pattern matching can be used in `let` as well. In `greetUser()`, instead of writ | |
2 `let`'s, we may write | ||
|
||
```moonbit | ||
fn greetUserAlt(self: User) -> String { | ||
fn greetUserAlt(self : User) -> String { | ||
// extract `id` `name` from `self` of type User. ignores email. | ||
let { id: id, name: name, email: _ } = self | ||
// equivalent, but ignores the rest. | ||
let {id,name,..} = self | ||
let { id, name, .. } = self | ||
"Greetings, \{name} of id \{id}" | ||
} | ||
``` | ||
|
@@ -321,13 +323,12 @@ Additionally, MoonBit provides a more interesting loop construct, the functional | |
For example the Fibonacci number can be calculated by | ||
|
||
```moonbit | ||
fn fib(n: Int) -> Int { | ||
fn fib(n : Int) -> Int { | ||
loop n, 0, 1 { // introduces 3 loop variables: `n` `a = 0` `b = 1` | ||
// pattern matching is available in `loop` | ||
0, a, b => a // what can be constructed from 0 -- Only 0 it self! | ||
// assign `b` to `a`, `(a + b)` to `b`, decrease counter `n` | ||
n, a, b => continue n - 1, b, a + b | ||
} | ||
} | ||
``` | ||
|
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 |
---|---|---|
|
@@ -38,18 +38,20 @@ MoonBit 目前处于活跃开发的阶段,尚不满足生产环境的需求。 | |
|
||
``` | ||
my-project | ||
├── LICENSE | ||
├── moon.mod.json | ||
├── README.md | ||
├── lib | ||
│ ├── hello.mbt | ||
│ ├── hello_test.mbt | ||
│ └── moon.pkg.json | ||
├── main | ||
│ ├── main.mbt | ||
│ └── moon.pkg.json | ||
└── moon.mod.json | ||
└── src | ||
├── lib | ||
│ ├── hello.mbt | ||
│ ├── hello_test.mbt | ||
│ └── moon.pkg.json | ||
└── main | ||
├── main.mbt | ||
└── moon.pkg.json | ||
``` | ||
|
||
这是一个很典型的项目结构,试试运行 `moon run main`。 | ||
这是一个很典型的项目结构,试试运行 `moon run src/main`。 | ||
|
||
现在可以开始我们的月兔之旅了。 | ||
|
||
|
@@ -65,7 +67,7 @@ my-project | |
```moonbit | ||
let e = 2.718281828459045 // double | ||
let int_min = -2147483648 // int | ||
let int_max: Int = 2147483647 // 显式类型标注 | ||
let int_max : Int = 2147483647 // 显式类型标注 | ||
let tuple = (1, 2) // 2-tuple | ||
``` | ||
|
||
|
@@ -90,7 +92,7 @@ MoonBit 是一个带类型推断的严格类型语言。在上方的例子中, | |
函数不过是一段接受某些输入并产生一个输出的一段代码。我们用关键词 `fn` 来定义一个函数(MoonBit 中的函数不应该由大写字母 A-Z 起头): | ||
|
||
```moonbit | ||
fn identity[T](x: T) -> T { // `Identity` 则不符合命名规范 | ||
fn identity[T](x : T) -> T { // `Identity` 则不符合命名规范 | ||
x | ||
} | ||
``` | ||
|
@@ -124,7 +126,7 @@ fn compose[S, T, U](f : (T) -> U, g : (S) -> T) -> (S) -> U { | |
```moonbit | ||
fn foo() -> Int { | ||
fn inc(x) { x + 1 } // 命名为 `inc` | ||
fn (x) { x + inc(2) } (6) // 匿名函数,即 lambda 表达式 | ||
(fn (x) { x + inc(2) })(6) // 匿名函数,即 lambda 表达式 | ||
// 函数会自动捕捉最后一个表达式的值并返回 | ||
} | ||
``` | ||
|
@@ -158,27 +160,27 @@ enum List[T] { | |
|
||
```moonbit | ||
struct User { | ||
id: Int | ||
name: String | ||
id : Int | ||
name : String | ||
// 默认情况下 Struct 的属性/字段是不可变的 | ||
// `mut` 关键字就和我们之前说的一样 | ||
mut email: String | ||
mut email : String | ||
} derive(Show) | ||
// 我们通过把函数第一个参数定义为 `self: User` 来给该 Struct 定义一个 method | ||
// 写法和 Python 类似 | ||
// 注意:只有类型所在的包能为其定义方法。 不能直接为外部类型定义方法。 | ||
fn greetUser(self: User) -> String{ // `User` 的一个方法 | ||
fn greetUser(self : User) -> String { // `User` 的一个方法 | ||
let id = self.id | ||
let name = self.name | ||
"Greetings, \{name} of id \{id}" // 字符串插值写法 | ||
} | ||
// 构造 User 对象的写法 | ||
let evan: User = {id:0,name:"Evan",email:"[email protected]"} | ||
let evan : User = { id: 0, name: "Evan", email: "[email protected]" } | ||
// 可以用一个语法糖将 evan 的属性复制一遍, | ||
// 并把其 email 换成其他的值,构造一个新对象 | ||
let listOfUser: List[User] = Cons(evan, Cons({..evan, email: "[email protected]"}, Nil)) | ||
let listOfUser : List[User] = Cons(evan, Cons({ ..evan, email: "[email protected]" }, Nil)) | ||
``` | ||
|
||
除了这两种数据类型之外,还有一种较为特殊的枚举类型:`type`. 可以看作其将已存在的类型包装起来, | ||
|
@@ -225,20 +227,20 @@ trait Printable { | |
} | ||
fn to_string(self : User) -> String { | ||
(self.id,self.name,self.email).to_string() | ||
(self.id, self.name, self.email).to_string() | ||
} // 这样就实现了 `Printable` | ||
fn to_string[T: Printable](self : List[T]) -> String { | ||
fn to_string[T : Printable](self : List[T]) -> String { | ||
let string_aux = to_string_aux(self) | ||
// 函数参数可以有标签 | ||
"[" + string_aux.substring(end = string_aux.length() - 1) + "]" | ||
"[" + string_aux.substring(end=string_aux.length() - 1) + "]" | ||
} | ||
// 多态函数一定是顶层函数 | ||
fn to_string_aux[T: Printable](self: List[T]) -> String{ | ||
fn to_string_aux[T : Printable](self : List[T]) -> String { | ||
match self { | ||
Nil => "" | ||
Cons(x,xs) => "\{x} " + to_string_aux(xs) | ||
Cons(x, xs) => "\{x} " + to_string_aux(xs) | ||
} | ||
} | ||
``` | ||
|
@@ -297,11 +299,11 @@ fn zip[T](self : List[T], other : List[T]) -> List[T] { | |
模式匹配也能够在 `let` 中使用。在 `greetUser()` 中,可以把两个 `let` 绑定改写为 | ||
|
||
```moonbit | ||
fn greetUserAlt(self: User) -> String { | ||
fn greetUserAlt(self : User) -> String { | ||
// 从 `self` 中提取 `id` `name` 字段,忽略 `email` | ||
let { id: id, name: name, email: _ } = self | ||
// 等价写法,但是忽略 `id `name` 之外的所有字段。 | ||
let {id,name,..} = self | ||
let { id, name, .. } = self | ||
"Greetings, \{name} of id \{id}" | ||
} | ||
``` | ||
|
@@ -315,7 +317,7 @@ MoonBit 本身是一个多范式语言, | |
除此之外,MoonBit 还提供了一种更有意思的写法:函数式循环。譬如斐波那契数就可以写成 | ||
|
||
```moonbit | ||
fn fib(n: Int) -> Int { | ||
fn fib(n : Int) -> Int { | ||
loop n, 0, 1 { // 引入 3 个循环变量: `n` `a = 0` `b = 1` | ||
// `loop` 中也可以使用 pattern matching | ||
0, a, _ => a // 只有 0 能从 0 构造出来。 | ||
|