21-Erlang库
正如前文所言,Elixir是基于Erlang实现的编程语言。
对于Erlang语言库,Elixir提供了完善的交互能力。
而且,实际上,Elixir不只是简单地对Erlang库功能进行语言上的包装(是的,没有Elixir版本的对应Erlang库函数),
而是直接连接Erlang代码(因为同源,Elixir以特定语法来直接调用Erlang库函数)。
本章将展示一些Elixir中没有,但是常用(常见+有用)的Erlang功能函数。
随着对Elixir更加深入的学习和使用,你可能会更多地阅读参考Erlang的
标准库手册。
二进制串模块
内建的Elixir字符串模块用来处理UTF-8编码过的二进制串(binaries)。
而Erlang的二进制串模块可能对你更加有用,
因为它可以处理的二进制串不一定非要是UTF-8编码的:
iex> String.to_char_list "Ø"
[216]
iex> :binary.bin_to_list "Ø"
[195, 152]
从上面的例子你就能看出一些区别来了;String
模块返回UTF-8的字符码,
而:binary
是原始的数据字节。
Elixir引用Erlang的库函数十分简单。正如这个例子所示,在Erlang库模块名称前面加上冒号,
就可以直接调用Erlang的库函数了。
格式化的字符串输出
Elixir中并没有类似于C中的printf
函数。作为一个可选项,你可以使用字符串插值来完成同样的功能:
iex> f = Float.to_string(:math.pi, decimals: 3) |> String.rjust(10)
iex> str = "Pi is approximately given by: #{f}"
"Pi is approximately given by: 3.142"
另外,还可以用Erlang标准库中的:io.format/2
和:io_lib.format/2
函数。
第一个格式化后输出到终端,而第二个输出到一个iolist。具体格式化的语法和pringf
略有区别,
详见Erlang文档:
iex> :io.format("Pi is approximately given by:~10.3f~n", [:math.pi])
Pi is approximately given by: 3.142
:ok
iex> to_string :io_lib.format("Pi is approximately given by:~10.3f~n", [:math.pi])
"Pi is approximately given by: 3.142\n"
另外需要注意的是Erlang的格式化函数中对Unicode的处理。
日历模块
日历模块 包含本地时间和标准时间的转换函数,
以及其它一些时间函数。
iex> :calendar.day_of_the_week(1980, 6, 28)
6
iex> {date, time} = :calendar.now_to_local_time(:erlang.timestamp)
iex> date
{2016, 2, 17}
iex> time
{22, 4, 55}
加密模块
加密模块 包含哈希方法,数字签名,
加密等功能函数:
iex> Base.encode16(:crypto.hash(:sha256, "Elixir"))
"3315715A7A3AD57428298676C5AE465DADA38D951BDFAC9348A8A31E9C7401CB"
:crypto
模块不是Erlang的标准库,但是包含在了Erlang发行包中。
这要求你必须在项目的配置文件中列出:crypto
模块作为依赖项。
通过修改mix.exs
来加载该模块:
def application do
[applications: [:crypto]]
end
有向图模块
有向图模块 (以及
有向图模块工具)
包含了处理有向图(有丁点和边构成)的函数。
创建了一个图实例之后,模块的算法即可帮助找寻顶点最短路径、图中的环等。
给出三个顶点,找寻从第一个到最后一个顶点的最短路径:
iex> digraph = :digraph.new()
iex> coords = [{0.0, 0.0}, {1.0, 0.0}, {1.0, 1.0}]
iex> [v0, v1, v2] = (for c <- coords, do: :digraph.add_vertex(digraph, c))
iex> :digraph.add_edge(digraph, v0, v1)
iex> :digraph.add_edge(digraph, v1, v2)
iex> :digraph.get_short_path(digraph, v0, v2)
[{0.0, 0.0}, {1.0, 0.0}, {1.0, 1.0}]
ETS(Erlang Term Storage):Erlang的“Term存储”机制
模块ets
以及dets
分别处理在内存中、磁盘上存储大型数据结构。
ETS创建一个表来存储元祖。默认情况下,ETS表是受保护的:只有owner进程才能写表,
其它进程只可以读。ETS提供了一些功能,可被当做简单的数据库、键值存储或cache机制使用。
作为副作用,ets
模块中的函数会修改表的状态。
iex> table = :ets.new(:ets_test, [])
# Store as tuples with {name, population}
iex> :ets.insert(table, {"China", 1_374_000_000})
iex> :ets.insert(table, {"India", 1_284_000_000})
iex> :ets.insert(table, {"USA", 322_000_000})
iex> :ets.i(table)
<1 > {"USA", 322000000}
<2 > {"China", 1_374_000_000}
<3 > {"India", 1_284_000_000}
数学模块
数学模块 包含了常用数学操作,
如三角函数、指数或底数函数等等。
iex> angle_45_deg = :math.pi() * 45.0 / 180.0
iex> :math.sin(angle_45_deg)
0.7071067811865475
iex> :math.exp(55.0)
7.694785265142018e23
iex> :math.log(7.694785265142018e23)
55.0
队列(queue)模块
队列 queue
是一种数据结构
实现了双向先进先出的高效率队列:
iex> q = :queue.new
iex> q = :queue.in("A", q)
iex> q = :queue.in("B", q)
iex> {value, q} = :queue.out(q)
iex> value
{:value, "A"}
iex> {value, q} = :queue.out(q)
iex> value
{:value, "B"}
iex> {value, q} = :queue.out(q)
iex> value
:empty
随机值(rand)模块
rand
模块函数 可以返回随机值或是设置随机seed:
iex> :rand.uniform()
0.8175669086010815
iex> _ = :rand.seed(:exs1024, {123, 123534, 345345})
iex> :rand.uniform()
0.5820506340260994
iex> :rand.uniform(6)
6
zip和zlib模块
zip
模块 可以让你读写磁盘或内存中的zip文件,
以及提取其文件信息等。
以下代码计算了zip压缩包中的文件数量:
iex> :zip.foldl(fn _, _, _, acc -> acc + 1 end, 0, :binary.bin_to_list("file.zip"))
{:ok, 633}
zlib
模块 处理zlib格式的数据压缩
(如gzip中用的):
iex> song = "
...> Mary had a little lamb,
...> His fleece was white as snow,
...> And everywhere that Mary went,
...> The lamb was sure to go."
iex> compressed = :zlib.compress(song)
iex> byte_size song
110
iex> byte_size compressed
99
iex> :zlib.uncompress(compressed)
"\nMary had a little lamb,\nHis fleece was white as snow,\nAnd everywhere that Mary went,\nThe lamb was sure to go."