cnDenis http://cndenis.github.io 2013-04-26 (update:2013-09-12)

Erlang中的原子(Atom), 字符串(String)和二进制串(Binary)是有点容易让人糊涂 的东西, 这里归纳一下它们之间的区别与联系。

原子

原子是由小写字母开头, 后接大小写字母及数字及下划线的, 比方说abc, cDE, ff89, 或是由单引号’‘括起来的任意字符, 比方说’EXIT’, ‘!@#@!$sdaf’。 用过其他语言的话, 会觉得Erlang中没括起来的原子长得像变量, 括起来的 长得像字符串, 但其实都不是, 这点要特别注意。Erlang中的变量是以大写字母 开头的, 字符串是用双引号括起来的。

原子在Erlang中应用非常广, 模块名、函数名、记录名都是原子, 所以如果你够蛋疼的话, 可以用’!#@$#y3fdsa1’(包括两边的单引号)当做函数名。

原子顾名思义是“不可分割”的东西, 原子无论长短, 在内存中占用的空间都是一样的, 然而, 原子的名字也不是毫无意义的, 可以利用atom_to_binary把原子名转成二进制串, 也可以用atom_to_list把原子名转成字符串。 反过来也可以, 有binary_to_atomlist_to_atom可以用。

Erlang中是没有原生的原子连接方法, 真想要相连的话, 先要转成二进制串或是字符串.

字符串

Erlang中字符串是使用双引号括起来的一串字符, 例如”string”, “123”等等。 双引号其实只是一个简写形式, 其实并没有把“字符串”当作一种独立的数据类型, 而是用正整数的列表(List)作为字符串使用, 跟C里面的做法相似。以下三行是等价的:

    "hello"
    [$h, $e, $l, $l, $o]
    [104,101,108,108,111]

因此字符串转换成原子及二进制串的的函数名为list_to_atomlist_to_binary

Erlang中的有专门处理字符串的模块, string, 可以用以进行大小写变换、截断、 对齐、连接、分割、子字符串等等常用操作。由于字符串实质上是列表, 因此lists 模块里的方法也全都适用于字符串。

字符串是列表, 因此可以使用列表的连接运算符++进行连接。二进制串是不可以用++的。 虽然拿 字符串++二进制串 在语法上是允许的, 但得到的结果是一个 “非正规列表” (也有人翻译成 “非严格列表” ), 是不推荐这么做的。

二进制串

二进制串是Erlang的一项特色, 使用在代码中使用<< >>括起来(看起来有点像中文的 书名号, 其实是两个小于号和两个大于号)。括起来的内容可以用数字表示, 或是用对应 的字符串表示, 如下:

    << 97, 98, 99 >>
    << "abc" >>

这两者含义是相同的。但要注意的是, 和列表[ ]或元组{ }不一样的是, 双引号只是一种简记方式, 并不是说把一个字符串放到<< >>里就会变成二进制串的, 比方说以下的写法都是不对的。

    << [97, 98, 99] >>
    A = "abc", << A >>

正确的做法是:

    A = "abc",
    A1 = list_to_binary(A),
    << A1/binary >>,
    %% 或者
    << (list_to_binary(A))/binary >>,

记住, 在二进制串中使用函数的话, 必须要用括号括起来.

<< >>里可以接受数字和二进制串, 利用所谓的比特语法构造二进制串或进行模式匹配。 格式为 变量:大小/类型, 例如:

    X:4/little-signed-integer-unit:8  %% 把X存为有符号小端整数, 大小为 4*8 bit
    A:32/integer   %% 把A存储为32位整数
    B:15/binary    %% 要求B是长于或等于15字节的二进制串, 截取B的前15字节

变量:大小/类型 的格式中, 大小和类型是可以省略的, 因此可以有:

变量:大小
变量/类型
变量

当进行省略时, 会使用默认值:

  1. 缺省的类型是整数 ( 手册 上的例子是有点问题的, «3.14»这样的写法在 Erlang 16B 版上是非法的).

  2. 缺省的大小与类型有关:

    整数是8位, 溢出部分被截掉: 例如<< 257 >>等价于<< 257:8 >>, 值等于<< 1 >>

    浮点数是64位

    二进制串是整个串的长度: 例如<< A/binary >>会把整个A都存起来.

  3. 对于整数, 缺省是无符号的.

  4. 对于整数, 缺省是大端的(big-endian).

  5. 可以使用 -unit:长度 的方式来指定单位长度, 缺省的单位长度与类型有关.

    整数(integer)/浮点数(float)/字节串(bitstring) 的缺省长度是1.

    而binary类型缺省长度是8.

二进制的连接直接在<< >>中使用逗号放一起就可以了, 例如

    << A/binary, B/binary >>,

    << 1234:32, "String", "中文也可以", "引号的后面不能加/binary", <<"但是二进制串中括另一个二进制串要指定格式">>/binary >>

其它的二进制语法, 例如二进制中的模式匹配/二进制解析, 等等, 就不在这里讲了.

参考:

官方手册



blog comments powered by Disqus
头像

cnDenis

Email: 联系我

Fork me on GitHub