Elixir 数据类型
学习一门语言,最重要的就是了解它由哪些类型,比如有没有整形,有没有浮点数,浮点数分不分单精度浮点数和双精度浮点数,有没有字符概念,还是字符和字符串都是一个概念。
Elixir 语言有 八 种基础类型。他们分别是
类型 | 说明 | 范例 |
---|---|---|
integer |
整数 | 1、0x1F |
float |
浮点数 | 1.0 |
bool |
布尔值 | true、false |
:atom |
原子 | :atom |
string |
字符串 | "简单教程" |
[] |
列表 | ["简","单","教","程"] |
() |
元组 | {"简", "单", "教", "程"} |
nil |
空类型 | nil 只有这个一个值 |
你可以尝试在 iex 里输入下面的内容试一试
iex(1)> 1 1 iex(2)> 0x1F 31 iex(3)> 1.0 1.0 iex(4)> 1.000 1.0 iex(5)> true true iex(6)> :atom :atom iex(7)> "简单教程" "简单教程" iex(8)> ["简","单","教","程"] ["简", "单", "教", "程"] iex(9)> {"简","单","教","程"} {"简", "单", "教", "程"} iex(10)> ```` ### 数学运算符 对于整数和浮点数,Elixir 支持数学四则运算符。你可以打开 iex 并键入以下表达式试一试
iex(13)> 5 + 2 7 iex(14)> 5 * 6 30 iex(15)> 10 / 2 5.0 iex(16)> 5 - 2 3 iex(17)>
需要注意的是,Elixir 中的除法 `/` 是基于 **浮点数** 的除法。这可能和其它的语言不一样,总之,你要记住: **Elixir 中的 `/` 运算符始终返回浮点数**。 ### 整数除法 如果你想做整数除法或得到除法余数,则必须调用 `div()` 函数和 `rem()` 函数
iex(20)> div(10,2) 5 iex(21)> div 10,2 5 iex(22)> rem(10,4) 2 iex(23)> rem 10,4 2 iex(24)>
你应该注意到了,Elixir 中的函数调用时的 **小括号是可选的**。 > 习惯了使用其它有括号的语言,这个的确有点难结束,不过后面我们在学习声明和控制流结构时,就回发现,没有括号,感觉语法更清晰。 > > 当然了,这个仁者见人,智者见治。 ### 二进制整数 Elixir 除了支持十进制整数外,还支持 **二进制**、**八进制**、和 **十六进制** 。
iex(34)> 10 10 iex(35)> 0b1010 10 iex(36)> 0o12 10 iex(37)> 0x1F 31
二进制以 `0b` 开头,八进制以 `0o` 开头,十六进制以 `0x` 开头。 ### 浮点数 Elixir 中的浮点数是 **64 位双精度** ,且浮点数必须存在一个 **点号(`.` )**,比如 `10.0` 写如果写成 `10` 则会被判断为整数
iex(41)> 10.233 10.233 iex(42)> 10.0 10.0 iex(43)> 10 10
Elixir 中的浮点数还支持 `e` 科学记数法
iex(44)> 10.0e-2 0.1 iex(45)> 10.123e-2 0.10123
### 浮点数转化为整数 Elixir 提供了 `round()` 函数将浮点数转化为 **最接近的整数**
iex(48)> round(3.4) 3 iex(49)> round(3.5) 4 iex(50)> round(-1.5) -2 iex(51)> round(-1.1) -1 iex(52)> round(-1.8) -2
注意负数部分,按照范例给的结果,`round()` 应该是先取绝对值,然后找最接近的整数。 Elixir 同时也提供了 **trunc()** 函数截断浮点的小数部分只保留整数部分。
iex(55)> trunc(3.4) 3 iex(56)> trunc(3.8) 3 iex(57)> trunc(3.5) 3 iex(58)> trunc(-1.1) -1 iex(59)> trunc(-1.5) -1 iex(60)> trunc(-1.8) -1
从范例中可以看出,`trunc()` 是直接抛弃小数部分的。 ### 定义函数 Elixir 中的函数由它们的 **函数名称** 和 **携带参数数量**来确定。 也就是说某个函数是否重复定义,号判断函数名和参数数量。如果函数名不同,肯定不是同一个函数,但如果函数名相同,且参数数量相同,那就是同一个函数了,而不管参数名是否不一样。 这种特殊性,是 Elixir 从 Erlang 中继承而来的。因为这种特殊性,Elixir 和 Erlang 使用函数名称和参数个数描述整个文档中的函数。比如: 1. `round/1` 定义了函数名字为 `round`,并且携带了1个参数 2. `round/2` 定义了一个和 `round` 名字相同的函数,但是参数的个数却是2个。 ### 布尔类型 bool 跟其它大多数语言一样,Elixir 支持布尔类型 (`bool`),且值只有两个 `true` 和 `false`。 而且,最重要的是,`true` 和 `false` 都是小写字母,任何一个字母变大些,都不是布尔类型。
iex(62)> True True iex(63)> False False iex(64)> true true iex(65)> false false iex(66)> true == false false
### 谓词函数 因为布尔类型如此重要,Elixir 还内置了一个函数 `is_boolean/1` 来检查某个值是否布尔值。 > 对了,这种函数,就是返回 true 或 false 的函数,程序界有个说法,叫 **谓词函数**。
iex(67)> is_boolean(true) true iex(68)> is_boolean(True) false iex(69)> is_boolean(False) false iex(70)> is_boolean(1==2) true
其实,不仅仅有布尔谓词函数,其它类型也有对应的谓词函数,比如: |函数|说明| |:---|:---| |`is_integer/1` |用于检查参数是否整数| |`is_float/1` | 用于检查参数是否浮点数| |`is_number/1`| 用于检查参数是否浮点数或整数| ### 显示函数或语法帮助信息 在交互式 shell `iex` 中,我们可以输入 `h()` 来打印有关如何使用 shell 的信息。
iex(73)> h()
IEx.Helpers
Welcome to Interactive Elixir. You are currently seeing the documentation for the module IEx.Helpers which provides many helpers to make Elixir's shell more joyful to work with.
This message was triggered by invoking the helper h(), usually referred to as h/0 (since it expects 0 arguments).
You can use the h/1 function to invoke the documentation for any Elixir module or function:
iex> h(Enum) iex> h(Enum.map) iex> h(Enum.reverse/1)
You can also use the i/1 function to introspect any value you have in the shell:
iex> i("hello")
There are many other helpers available, here are some examples:
• b/1 - prints callbacks info and docs for a given module • c/1 - compiles a file • c/2 - compiles a file and writes bytecode to the given path • cd/1 - changes the current directory • clear/0 - clears the screen • exports/1 - shows all exports (functions + macros) in a module • flush/0 - flushes all messages sent to the shell • h/0 - prints this help message • h/1 - prints help for the given module, function or macro • i/0 - prints information about the last value • i/1 - prints information about the given term • ls/0 - lists the contents of the current directory • ls/1 - lists the contents of the specified directory • open/1 - opens the source for the given module or function in your editor • pid/1 - creates a PID from a string • pid/3 - creates a PID with the 3 integer arguments passed • port/1 - creates a port from a string • port/2 - creates a port with the 2 non-negative integers passed • ref/1 - creates a reference from a string • ref/4 - creates a reference with the 4 integer arguments passed • pwd/0 - prints the current working directory • r/1 - recompiles the given module's source file • recompile/0 - recompiles the current project • runtime_info/0 - prints runtime info (versions, memory usage, stats) • v/0 - retrieves the last value from the history • v/1 - retrieves the nth value from the history
Help for all of those functions can be consulted directly from the command line using the h/1 helper itself. Try:
iex> h(v/0)
To list all IEx helpers available, which is effectively all exports (functions and macros) in the IEx.Helpers module:
iex> exports(IEx.Helpers)
This module also includes helpers for debugging purposes, see IEx.break!/4 for more information.
To learn more about IEx as a whole, type h(IEx).
iex(74)>
但 `h()` 函数的作用远不在此 ,它帮助程序也可用于访问任何函数或功能的文档。例如,输入 `h( is_integer/1)` 将打印该 `is_integer/1` 函数的文档。
iex(74)> h( is_integer/1)
def is_integer(term)
@spec is_integer(term()) :: boolean()
guard: true
Returns true if term is an integer; otherwise returns false.
Allowed in guard tests. Inlined by the compiler.
`h()` 函数还可以显示操作符和其它构造的文档,比如 `h ==/2` 用于显示 `==` 符号的文档。
iex(75)> h ==/2
def left == right
@spec term() == term() :: boolean()
guard: true
Equal to operator. Returns true if the two terms are equal.
This operator considers 1 and 1.0 to be equal. For stricter semantics, use ===/2 instead.
All terms in Elixir can be compared with each other.
Allowed in guard tests. Inlined by the compiler.
Examples
iex> 1 == 2 false iex> 1 == 1.0 true
### 原子 `atom` Elixir 支持一种特殊的单词,对,也就是没有双引号或单引号或反引号包裹的单词,且这些单词以 **冒号(`:`) 开头**。 这些单词,我们统称为 **原子** `atom`。在其它语言中,有的称之为 **符号(`symbol`)**。 **原子是一个常数,其名称是它自己的值**。
iex(85)> :hello
:hello
iex(86)> :world
:world
iex(87)> :hello == :world
false
iex(88)> hello
** (CompileError) iex:88: undefined function hello/0
iex(89)> :hello == :hello
true
你不能给原子赋值,否则会引发错误
iex(90)> :hello = 1 ** (MatchError) no match of right hand side value: 1
其实, 布尔 `true` 和 `false` 实际上是也是原子,一种不以冒号开头的内置的原子。 > 但我们仍然可以以冒号开头用它,哈哈。
iex(90)> true == :true true
Elixir 提供了谓词 `is_atom()` 来判断参数是否为原子。
iex(91)> is_atom(true) true iex(92)> is_atom(:false) true
最后,Elixir 有一个名为别名的构造,我们将在后面进行探讨。以**大写字母开头的别名** 也是原子
iex(93)> is_atom(Hello) true ```
所以,这个世界还蛮好玩的。