6
6
Elixir是一门动态类型语言,Elixir中所有数据类型都是在运行时动态推定的。
7
7
然而,Elixir还提供了** typespecs** 标记,用来:
8
8
9
- 1 . 声明自定义数据类型
10
- 2 . 声明含有显式类型说明的函数签名(即函数的规格说明)
9
+ 1 . 声明自定义数据类型
10
+ 2 . 声明含有显式类型说明的函数签名(即函数的规格说明)
11
11
12
12
###函数的规格说明(spec)
13
13
14
- 默认地,Elixir提供了一些基础数据类型,比如 ` integer ` 或者` pid ` 。还有其它一些复杂的:
15
- 如函数` round/1 ` ,它对一个float类型的数值四舍五入。
14
+ 默认地,Elixir提供了一些基础数据类型,表示为 ` integer ` 或者` pid ` 。
15
+ 还有一些复杂情形: 如函数` round/1 ` 为例 ,它对一个float类型的数值四舍五入。
16
16
它以一个` number ` (一个` integer ` 或` float ` )作为参数,返回一个` integer ` 。
17
17
18
- [ round函数的文档] ( http://elixir-lang.org/docs/stable/elixir/Kernel.html#round/1 )
19
- 里面描述 ` round/1 ` 的函数签名为 :
18
+ 那么,它在 [ round函数的文档] ( http://elixir-lang.org/docs/stable/elixir/Kernel.html#round/1 )
19
+ 里面记载的函数签名为 :
20
20
21
21
```
22
22
round(number) :: integer
23
23
```
24
24
25
- ` :: ` 表示其左边的函数* 返回* 一个其右面声明的类型的值。
26
- 函数的规格说明写在函数定义的前面、以` @spec ` 指令打头。
27
- 比如` round/1 ` 函数可以这么写:
25
+ ` :: ` 表示其左边的函数* 返回* 一个其右面声明的类型的值。函数名后面括号中是参数类型的列表。
26
+
27
+ 如果想特别注明某个函数的参数类型及返回值类型,那么可以在定义函数的时候,
28
+ 在函数前面使用` @spec ` 指令附加上函数的规格说明(spec)。
29
+
30
+ 比如,在函数库源码中,函数` round/1 ` 是这么写的:
28
31
29
32
``` elixir
30
33
@spec round (number):: integer
@@ -33,32 +36,34 @@ def round(number), do: # 具体实现 ...
33
36
34
37
Elixir还支持组合类型。例如,整数的列表,它的类型表示为` [integer] ` 。
35
38
可以阅读[ typespecs的文档] ( http://elixir-lang.org/docs/stable/elixir/typespecs.html )
36
- 查看Elixir提供的所有内建类型 。
39
+ 查看Elixir提供的所有内建类型的表示方法 。
37
40
38
41
###定义自定义类型
39
42
40
- Elixir提供了许多有用的内建类型,而且也很方便去创建自定义类型应用于合适的场景 。
41
- 在定义模块的时候,通过加上 ` @type ` 指令就可以实现 。
43
+ Elixir提供了许多有用的内建类型,而且也方便创建自定义类型应用于特定场景 。
44
+ 方法是在定义的时候,加上 ` @type ` 指令 。
42
45
43
- 比方我们有个模块叫做` LuosyCalculator ` ,可以执行常见的算术计算(如求和、计算乘积等)。
44
- 但是,它不是返回数值,而是返回一个元祖,该元祖第一个元素是计算结果,第二个是随机的文字记号。
46
+ 比如我们有个模块叫做` LuosyCalculator ` ,可以执行常见的算术计算(如求和、计算乘积等)。
47
+ 但是,它的函数不是返回结果数值,而是返回一个元祖,
48
+ 该元祖第一个元素是计算结果,第二个是随机的文字记号。
45
49
46
50
``` elixir
47
51
defmodule LousyCalculator do
48
52
@spec add (number, number):: {number,String .t }
49
- def add (x, y),do: {x+ y," 你用计算器算这个?!" }
53
+ def add (x, y),do: { x+ y," 你用计算器算这个?!" }
50
54
51
55
@spec multiply (number, number):: {number,String .t }
52
- def multiply (x, y),do: {x* y," 老天,不是吧?!" }
56
+ def multiply (x, y),do: { x* y," 老天,不是吧?!" }
53
57
end
54
58
```
55
59
56
60
从例子中可以看出,元组是复合类型。每个元组都定义了其具体元素类型。
57
- 至于为何是` String.t ` 而不是` string ` ,可以参考
58
- [ 这篇文章] ( http://elixir-lang.org/docs/stable/elixir/typespecs.html#Notes ) 。
61
+ 至于为何是` String.t ` 而不是` string ` 的原因,可以参考
62
+ [ 这篇文章] ( http://elixir-lang.org/docs/stable/elixir/typespecs.html#Notes ) ,
63
+ 此处不多说明。
59
64
60
65
像这样定义函数规格说明是没问题,但是一次次重复写这种复合类型的
61
- 样式名称 ` {number, String.t} ` ,很快会厌烦 。
66
+ 表示方法 ` {number, String.t} ` ,很快会厌烦的吧 。
62
67
我们可以使用` @type ` 指令来声明我们自定义的类型:
63
68
64
69
``` elixir
@@ -76,9 +81,9 @@ defmodule LousyCalculator do
76
81
end
77
82
```
78
83
79
- 指令` @typedoc ` ,和` @doc ` 或` @moduledoc ` 指令类似,被用来记录自定义类型 。
84
+ 指令` @typedoc ` ,和` @doc ` 或` @moduledoc ` 指令类似,用来解释说明自定义的类型,放在 ` @type ` 前面 。
80
85
81
- 自定义类型通过 ` @type ` 定义,可以从其定义的模块导出并被外界访问 :
86
+ 另外,通过 ` @type ` 定义的自定义类型,实际上也是模块的成员,可以被外界访问 :
82
87
83
88
``` elixir
84
89
defmodule QuietCalculator do
94
99
95
100
###静态代码分析
96
101
97
- Typespecs的作用不仅仅是被用来作为程序文档说明 。举个例子,
102
+ 给函数等元素标记类型或者签名的作用,不仅仅是被用来作为程序文档说明 。举个例子,
98
103
Erlang工具[ Dialyzer] [ Dialyzer ] (http://www.erlang.org/doc/man/dialyzer.html )
99
- 使用typespecs来进行代码静态分析 。
104
+ 通过这些类型或者签名标记,进行代码静态分析 。
100
105
这就是为什么我们在` QuiteCalculator ` 例子中,
101
106
即使` make_quite/1 ` 是个私有函数,也写了函数规格说明。
102
107