doc: update docs/elixir.md #587
This commit is contained in:
parent
8d60181b96
commit
3fdfa19b74
358
docs/elixir.md
358
docs/elixir.md
@ -6,20 +6,22 @@ Elixir 备忘清单
|
||||
入门
|
||||
------
|
||||
|
||||
### 安装Elixir
|
||||
### 安装 Elixir
|
||||
<!--rehype:wrap-class=row-span-2-->
|
||||
|
||||
> 每个操作系统的安装说明可以在 elixir-lang.org 网站上 [Installing Elixir](http://elixir-lang.org/install.html) 部分找到。
|
||||
> Elixir 自带了`iex`这样一个交互 shell,可以随时计算 Elixir 表达式的值,运行`iex`命令,继续输入几个简单的表达式试试:
|
||||
Elixir 自带了 `iex` 这样一个交互 shell,可以随时计算 Elixir 表达式的值,运行`iex`命令,继续输入几个简单的表达式试试:
|
||||
|
||||
```shell
|
||||
iex 2+3
|
||||
5
|
||||
iex 2+3 == 5
|
||||
true
|
||||
iex String.length("The quick brown fox jumps over the lazy dog")
|
||||
iex String.length("快速的狐狸跳过了懒惰的狗")
|
||||
43
|
||||
```
|
||||
|
||||
每个操作系统的文档可以在[官网](https://elixir-lang.org)网站上 [Installing Elixir](http://elixir-lang.org/install.html) 部分找到
|
||||
|
||||
### hello.exs
|
||||
|
||||
```elixir
|
||||
@ -33,21 +35,128 @@ $ elixir hello.exs
|
||||
```
|
||||
|
||||
### 基本类型
|
||||
>
|
||||
> Elixir 支持多种基本类型:整数、浮点、布尔值、原子和字符串。其他数据类型,如列表和元组
|
||||
<!--rehype:wrap-class=row-span-3-->
|
||||
|
||||
Elixir 支持多种基本类型:整数、浮点、布尔值、原子和字符串。其他数据类型,如列表和元组
|
||||
|
||||
```elixir
|
||||
iex> 1 # integer
|
||||
iex> 0x1F # integer(支持二进制、八进制和十六进制的整数)
|
||||
iex> 1.0 # float
|
||||
iex> true # boolean
|
||||
iex> :atom # atom / symbol
|
||||
iex> "elixir" # string
|
||||
iex> [1, 2, 3] # list
|
||||
iex> {1, 2, 3} # tuple
|
||||
# integer 整数
|
||||
iex> 1
|
||||
# integer(支持2进制、8进制和16进制的整数)
|
||||
iex> 0x1F
|
||||
# float
|
||||
iex> 1.0
|
||||
# boolean
|
||||
iex> true
|
||||
# atom / symbol
|
||||
iex> :atom
|
||||
# string
|
||||
iex> "elixir"
|
||||
# list
|
||||
iex> [1, 2, 3]
|
||||
# tuple
|
||||
iex> {1, 2, 3}
|
||||
```
|
||||
|
||||
### 注释
|
||||
|
||||
```elixir
|
||||
# 这是一个单行注释
|
||||
```
|
||||
|
||||
### 字符串插值与拼接
|
||||
|
||||
```elixir
|
||||
iex> name = "Sean"
|
||||
iex> "Hello #{name}"
|
||||
"Hello Sean"
|
||||
|
||||
iex> "Hello " <> "world!"
|
||||
"Hello world!"
|
||||
```
|
||||
|
||||
### 变量和模式匹配
|
||||
|
||||
```elixir
|
||||
x = 1
|
||||
# => x 现在等于 1
|
||||
|
||||
{a, b} = {1, 2}
|
||||
# => a 等于 1,b 等于 2
|
||||
```
|
||||
|
||||
在 Elixir 中,使用 `=` 来进行赋值操作,但实际上是模式匹配。左边是模式,右边是值
|
||||
|
||||
### 原子(Atoms)
|
||||
|
||||
```elixir
|
||||
:ok
|
||||
```
|
||||
|
||||
原子是常量,它们的名称就是它们的值
|
||||
|
||||
### 列表(Lists)
|
||||
|
||||
```elixir
|
||||
list = [1, 2, 3]
|
||||
```
|
||||
|
||||
### 元组(Tuples)
|
||||
|
||||
```elixir
|
||||
tuple = {:ok, "value"}
|
||||
```
|
||||
|
||||
### 函数定义
|
||||
|
||||
```elixir
|
||||
defmodule MyModule do
|
||||
def my_function(parameter) do
|
||||
# 函数体
|
||||
end
|
||||
end
|
||||
```
|
||||
|
||||
### 匿名函数
|
||||
|
||||
```elixir
|
||||
add = fn a, b -> a + b end
|
||||
```
|
||||
|
||||
### 控制结构
|
||||
<!--rehype:wrap-class=row-span-2-->
|
||||
|
||||
`if/else`
|
||||
|
||||
```elixir
|
||||
if x > 0 do
|
||||
"Positive"
|
||||
else
|
||||
"Non-positive"
|
||||
end
|
||||
```
|
||||
|
||||
`case`
|
||||
|
||||
```elixir
|
||||
case {1, 2} do
|
||||
{1, x} -> "Matched #{x}"
|
||||
_ -> "Not matched"
|
||||
end
|
||||
```
|
||||
|
||||
`cond`
|
||||
|
||||
```elixir
|
||||
cond do
|
||||
x > 2 -> "Greater than 2"
|
||||
x == 2 -> "Equal to 2"
|
||||
true -> "Less than 2"
|
||||
end
|
||||
```
|
||||
|
||||
### 基本算术
|
||||
<!--rehype:wrap-class=row-span-4-->
|
||||
|
||||
```elixir
|
||||
iex> 1 + 2
|
||||
@ -58,18 +167,23 @@ iex> 10 / 2
|
||||
5.0
|
||||
```
|
||||
|
||||
> 运算符`/`总是返回一个float。如果你想做整数除法或得到除法余数,你可以调用div和rem函数:
|
||||
运算符`/`总是返回一个 float。如果你想做整数除法或得到除法余数,你可以调用 div 和 rem 函数:
|
||||
|
||||
```elixir
|
||||
iex> div(10, 2)
|
||||
5
|
||||
iex> div 10, 2 # Elixir允许在调用需要一个或多个参数的函数时删除括号
|
||||
```
|
||||
|
||||
允许在调用需要一个或多个参数的函数时删除括号
|
||||
|
||||
```elixir
|
||||
iex> div 10, 2
|
||||
5
|
||||
iex> rem 10, 3
|
||||
1
|
||||
```
|
||||
|
||||
> 可以调用round函数来获取与给定浮点数最接近的整数,或者调用trunc函数来获取浮点数的整数部分
|
||||
可以调用 round 函数来获取与给定浮点数最接近的整数,或者调用 trunc 函数来获取浮点数的整数部分
|
||||
|
||||
```elixir
|
||||
iex> round(3.58)
|
||||
@ -78,7 +192,7 @@ iex> trunc(3.58)
|
||||
3
|
||||
```
|
||||
|
||||
> 可以使用is_integer、is_float或is_number分别检查参数是否为integer、float或number类型
|
||||
可以使用 is_integer、is_float 或 is_number 分别检查参数是否为 integer、float 或 number 类型
|
||||
|
||||
```elixir
|
||||
iex> is_integer(1)
|
||||
@ -90,8 +204,9 @@ false
|
||||
```
|
||||
|
||||
### 布尔算术
|
||||
>
|
||||
> Elixir 提供了 `||`、`&&` 和 `!` 布尔操作符,它们支持任何类型的操作:
|
||||
<!--rehype:wrap-class=row-span-4-->
|
||||
|
||||
Elixir 提供了 `||`、`&&` 和 `!` 布尔操作符,它们支持任何类型的操作:
|
||||
|
||||
```elixir
|
||||
iex> -20 || true
|
||||
@ -110,7 +225,7 @@ iex> !false
|
||||
true
|
||||
```
|
||||
|
||||
> 还有三个操作符(and、or、not),它们的第一个参数**必须是布尔类型**(true 和 false):
|
||||
还有三个操作符(and、or、not),它们的第一个参数**必须是布尔类型**(true 和 false):
|
||||
|
||||
```elixir
|
||||
iex> true and 42
|
||||
@ -125,9 +240,25 @@ iex> not 42
|
||||
** (ArgumentError) argument error
|
||||
```
|
||||
|
||||
### 模块和函数导入
|
||||
|
||||
```elixir
|
||||
import List, only: [duplicate: 2]
|
||||
```
|
||||
|
||||
### 管道操作符
|
||||
|
||||
```elixir
|
||||
result = data
|
||||
|> process1()
|
||||
|> process2()
|
||||
```
|
||||
|
||||
`|>` 用于链式调用函数,将前一个函数的结果作为下一个函数的第一个参数
|
||||
|
||||
### 比较运算符
|
||||
>
|
||||
> 比较运算符 :`==`, `!=`, `===`, `!==`, `<=`, `>=`, `<` 和 `>`
|
||||
|
||||
比较运算符 :`==`, `!=`, `===`, `!==`, `<=`, `>=`, `<` 和 `>`
|
||||
|
||||
```elixir
|
||||
iex> 1 > 2
|
||||
@ -140,23 +271,14 @@ iex> 2 <= 3
|
||||
true
|
||||
```
|
||||
|
||||
### 字符串插值与拼接
|
||||
|
||||
```elixir
|
||||
iex> name = "Sean"
|
||||
iex> "Hello #{name}"
|
||||
"Hello Sean"
|
||||
|
||||
iex> "Hello " <> "world!"
|
||||
"Hello world!"
|
||||
```
|
||||
|
||||
集合
|
||||
------
|
||||
>
|
||||
> 列表(list)、元组(tuple)、关键字列表(keyword list)、映射(map)。
|
||||
>
|
||||
|
||||
### 列表(List)
|
||||
<!--rehype:wrap-class=row-span-2-->
|
||||
|
||||
```elixir
|
||||
iex> [3.14, :pie, "Apple"]
|
||||
@ -164,14 +286,34 @@ iex> [3.14, :pie, "Apple"]
|
||||
|
||||
iex> list = [3.14, :pie, "Apple"]
|
||||
iex> [3.14, :pie, "Apple"]
|
||||
iex> ["π" | list] # 列表的开头添加元素
|
||||
```
|
||||
|
||||
列表的开头添加元素
|
||||
|
||||
```elixir
|
||||
iex> ["π" | list]
|
||||
["π", 3.14, :pie, "Apple"]
|
||||
iex> list ++ ["Cherry"] # 列表的尾部添加元素/列表拼接
|
||||
```
|
||||
|
||||
列表的尾部添加元素/列表拼接
|
||||
|
||||
```elixir
|
||||
iex> list ++ ["Cherry"]
|
||||
[3.14, :pie, "Apple", "Cherry"]
|
||||
|
||||
iex> hd [3.14, :pie, "Apple"] # 获取列表的头部元素
|
||||
```
|
||||
|
||||
获取列表的头部元素
|
||||
|
||||
```elixir
|
||||
iex> hd [3.14, :pie, "Apple"]
|
||||
3.14
|
||||
iex> tl [3.14, :pie, "Apple"] # 获取列表的尾部元素
|
||||
```
|
||||
|
||||
获取列表的尾部元素
|
||||
|
||||
```elixir
|
||||
iex> tl [3.14, :pie, "Apple"]
|
||||
[:pie, "Apple"]
|
||||
```
|
||||
|
||||
@ -191,17 +333,17 @@ iex> [{:foo, "bar"}, {:hello, "world"}]
|
||||
[foo: "bar", hello: "world"]
|
||||
```
|
||||
|
||||
> 关键字列表非常重要,它有以下的特性:
|
||||
关键字列表非常重要,它有以下的特性:
|
||||
|
||||
- 键(key)都是原子(atom)
|
||||
- 键(key)是有序的(定义后,顺序不会改变)
|
||||
- 键(key)不必是唯一的
|
||||
|
||||
> 因为这些原因,关键字列表最常见的用法是作为参数传递给函数。
|
||||
因为这些原因,常见的用法是作为参数传递给函数
|
||||
|
||||
### 映射(Map)
|
||||
|
||||
> Elixir 的映射(maps)是键值对结构的第一选择,和关键字列表(keywords)不同,映射允许任意类型的数据作为键,而且数据并不严格排序。 你可以使用 %{} 来定义映射:
|
||||
Elixir 的映射(maps)是键值对结构的第一选择,和关键字列表(keywords)不同,映射允许任意类型的数据作为键,而且数据并不严格排序。 你可以使用 %{} 来定义映射:
|
||||
|
||||
```elixir
|
||||
iex> map = %{:foo => "bar", "hello" => :world}
|
||||
@ -214,26 +356,34 @@ iex> map["hello"]
|
||||
|
||||
模式匹配
|
||||
------
|
||||
|
||||
>
|
||||
> 模式匹配是 Elixir 很强大的特性,它允许我们匹配简单值、数据结构、甚至函数。
|
||||
>
|
||||
### 匹配操作符
|
||||
|
||||
### 匹配元组
|
||||
|
||||
```elixir
|
||||
# 匹配元组
|
||||
iex> {a, b, c} = {:hello, "world", 42}
|
||||
{:hello, "world", 42}
|
||||
iex> a
|
||||
:hello
|
||||
iex> b
|
||||
"world"
|
||||
```
|
||||
|
||||
# 匹配列表
|
||||
### 匹配列表
|
||||
|
||||
```
|
||||
iex> [a, b, c] = [1, 2, 3]
|
||||
[1, 2, 3]
|
||||
iex> a
|
||||
1
|
||||
# 匹配列表的头部元素
|
||||
```
|
||||
|
||||
### 匹配列表的头部元素
|
||||
|
||||
```
|
||||
iex> [head | tail] = [1, 2, 3]
|
||||
[1, 2, 3]
|
||||
iex> head
|
||||
@ -242,17 +392,20 @@ iex> tail
|
||||
[2, 3]
|
||||
```
|
||||
|
||||
### Pin操作符
|
||||
### Pin 操作符
|
||||
|
||||
> pin 操作符,就是用已经绑定的值去匹配,而不是重新绑定一个新值。
|
||||
pin 操作符,就是用已经绑定的值去匹配,而不是重新绑定一个新值。
|
||||
|
||||
```elixir
|
||||
iex> {x, ^x} = {2, 1}
|
||||
{2, 1}
|
||||
iex> x
|
||||
2
|
||||
```
|
||||
|
||||
# 使用下划线_忽略匹配的值
|
||||
### 使用下划线 `_` 忽略匹配的值
|
||||
|
||||
```elixir
|
||||
iex> [head | _] = [1, 2, 3]
|
||||
[1, 2, 3]
|
||||
iex> head
|
||||
@ -261,37 +414,89 @@ iex> head
|
||||
|
||||
控制语句
|
||||
------
|
||||
>
|
||||
> case, cond, and if
|
||||
>
|
||||
|
||||
### if/else/end
|
||||
|
||||
```elixir
|
||||
if condition do
|
||||
# 条件成立时执行的代码
|
||||
else
|
||||
# 条件不成立时执行的代码
|
||||
end
|
||||
```
|
||||
|
||||
### case/end
|
||||
|
||||
```elixir
|
||||
case expression do
|
||||
pattern1 -> # 匹配 pattern1 时执行的代码
|
||||
pattern2 -> # 匹配 pattern2 时执行的代码
|
||||
_ -> # 其他情况执行的代码
|
||||
end
|
||||
```
|
||||
|
||||
### cond/end
|
||||
|
||||
```elixir
|
||||
cond do
|
||||
condition1 -> # 条件1成立时执行的代码
|
||||
condition2 -> # 条件2成立时执行的代码
|
||||
true -> # 如果没有任何条件成立,执行这里的代码
|
||||
end
|
||||
```
|
||||
|
||||
### unless/do/end
|
||||
|
||||
```elixir
|
||||
unless condition do
|
||||
# 条件为假时执行的代码
|
||||
end
|
||||
```
|
||||
|
||||
### try/rescue/end
|
||||
|
||||
```elixir
|
||||
try do
|
||||
# 可能会引发异常的代码
|
||||
rescue
|
||||
pattern1 -> # 匹配 pattern1 的异常处理代码
|
||||
pattern2 -> # 匹配 pattern2 的异常处理代码
|
||||
_ -> # 其他异常处理代码
|
||||
end
|
||||
```
|
||||
|
||||
### case
|
||||
>
|
||||
> case允许我们将一个值与许多模式进行比较,直到找到匹配的模式:
|
||||
<!--rehype:wrap-class=row-span-2-->
|
||||
|
||||
允许将一个值与许多模式进行比较,直到找到匹配的模式:
|
||||
|
||||
```elixir
|
||||
iex> case {1, 2, 3} do
|
||||
{4, 5, 6} ->
|
||||
"This clause won't match"
|
||||
{1, x, 3} ->
|
||||
"This clause will match and bind x to 2 in this clause"
|
||||
"该子句将匹配并绑定 x 到该子句中的 2"
|
||||
_ ->
|
||||
"This clause would match any value"
|
||||
end
|
||||
"This clause will match and bind x to 2 in this clause"
|
||||
"该子句将匹配并绑定 x 到该子句中的 2"
|
||||
```
|
||||
|
||||
# 还可以使用when指定额外的条件
|
||||
还可以使用when指定额外的条件
|
||||
|
||||
```elixir
|
||||
iex> case {1, 2, 3} do
|
||||
{1, x, 3} when x > 0 ->
|
||||
"Will match"
|
||||
_ ->
|
||||
"Would match, if guard condition were not satisfied"
|
||||
"如果不满足保护条件,将匹配"
|
||||
end
|
||||
"Will match"
|
||||
```
|
||||
|
||||
### cond
|
||||
|
||||
> 当我们需要匹配条件而不是值的时候,可以使用 cond,这和其他语言的 else if 或者 elsif 相似
|
||||
当我们需要根据条件进行匹配而不是值时,类似于其他语言的 `else if` 或 `elsif`,可以使用 `cond` 控制结构。
|
||||
|
||||
```elixir
|
||||
iex> cond do
|
||||
@ -303,41 +508,27 @@ iex> cond do
|
||||
"But this will"
|
||||
end
|
||||
"But this will"
|
||||
```
|
||||
|
||||
# 如果所有的条件都返回nil或false,则会引发一个错误(CondClauseError)。因此,需要添加一个final条件,等于true,它将始终匹配:
|
||||
如果所有的条件都返回 `nil` 或 `false`,则会引发一个错误(CondClauseError)。因此,需要添加一个 `final` 条件,等于 `true`,它将始终匹配:
|
||||
|
||||
```elixir
|
||||
iex> cond do
|
||||
2 + 2 == 5 ->
|
||||
"This is never true"
|
||||
2 * 2 == 3 ->
|
||||
"Nor this"
|
||||
true ->
|
||||
"This is always true (equivalent to else)"
|
||||
"这始终为真(等同于 else)"
|
||||
end
|
||||
"This is always true (equivalent to else)"
|
||||
"这始终为真(等同于 else)"
|
||||
```
|
||||
|
||||
### if/unless
|
||||
### 变量的作用域
|
||||
|
||||
如果在if、case和类似的构造中声明或更改了任何变量,则声明和更改将只在构造中可见。
|
||||
|
||||
```elixir
|
||||
iex> if true do
|
||||
"This works!"
|
||||
end
|
||||
"This works!"
|
||||
|
||||
iex> unless true do
|
||||
"This will never be seen"
|
||||
end
|
||||
nil
|
||||
|
||||
# if...else...
|
||||
iex> if nil do
|
||||
"This won't be seen"
|
||||
else
|
||||
"This will"
|
||||
end
|
||||
"This will"
|
||||
|
||||
# 关于Elixir中变量的作用域:如果在if、case和类似的构造中声明或更改了任何变量,则声明和更改将只在构造中可见。
|
||||
iex> x = 1
|
||||
1
|
||||
if true do
|
||||
@ -346,8 +537,11 @@ end
|
||||
2
|
||||
iex> x
|
||||
1
|
||||
```
|
||||
|
||||
# 如果要更改值,则必须从if返回值:
|
||||
如果要更改值,则必须从if返回值:
|
||||
|
||||
```elixir
|
||||
iex> x = 1
|
||||
1
|
||||
iex> x = if true do
|
||||
|
Loading…
x
Reference in New Issue
Block a user