本 EEP 描述了 Erlang 编程语言中位级二进制文件的引入。 它们可以使用位语法和一组新的 BIF 来构造和操作,这些 BIF 操作位级二进制文件。 引入这些新的 BIF 是为了不改变现有 BIF(操作二进制文件)的语义,而是使用新的 BIF 为位级二进制文件实现类似的操作。
本文档中称为位串的位级二进制文件是任意长度的位序列。 另一方面,二进制文件是位序列,其中位的数量可以被 8 整除。 这些定义意味着任何二进制文件也是位串。
位语法表达式
<<Seg1,...,SegN>>
计算结果为位串,如果表达式中所有段的大小之和可以被 8 整除,则结果也是二进制文件。 以前,此类表达式只能计算为二进制文件,如果不是这种情况,则会引发运行时错误。
通过此扩展,以前导致运行时错误的表达式 Bin = <<1:9>>
现在创建一个 9 位二进制文件。 为了能够使用此位串构建新的更大的位串,我们可以编写
<<Bin/bitstring, 0:1>>
请注意将 bitstring 用作类型。 这会扩展为 binary-unit:1,而 binary 类型会扩展为 binary-unit:8。 由于 bitstring 是在二进制模式中写入的长单词,因此有一个别名 bits 在本提案的其余部分中使用,类似地,对于 binary,有一个简写 bytes。
要匹配出一个位级二进制文件,我们还使用如下位串类型:
case Bin of
<<1:1,Rest/bits>> -> Rest;
<<0:1,_/bits>> -> 0
end
这使我们能够避免不得不计算填充的情况。
bitsize/1::bitstring() -> integer()
返回位串的大小(以位为单位)。 此 BIF 允许在保护子句中使用。
list_to_bitstring/1::bitstring_list() -> bitstr()
bitstring_list = cons(char() | bitstring()| bitstring_list(), bitstring() | bitstring_list) | nil()
连接 bitstring_list 中的位串和字符以创建一个位串,每个字符都成为一个 8 位位串。
is_bitstring/1::any() -> bool()
如果参数是位串,则返回 true,否则返回 false。 此 BIF 允许在保护子句中使用。
bitstring_to_list/1::bitstring() -> [char()|bitstring()]
将位串转换为字符列表,如果位串中的位数不能被 8 整除,则列表中的最后一个元素是一个由原始位串的最后 1-7 位组成的位串。
当前二进制文件的定义使得在格式不是面向字节时难以使用位语法进行解码,因为程序员总是被迫填充他正在使用的二进制文件以成为字节序列。 允许位级二进制文件可以缓解此问题。
此处提出的新 BIF 旨在为程序员提供与操作二进制文件时相同的工具来操作位级二进制文件,而无需更改现有 BIF 的语义并保持诸如此类属性,如果此语句
is_binary(X) andalso size(X) =:= 0
计算结果为 true,则意味着 X = <<>>
。
本文档中描述的扩展要么已经在 R11B-4 中实现,但受到编译器开关的保护,要么可以很容易地实现。
此更改并非完全向后兼容,例如:N=9, <<1:N>>
会在旧系统中引发错误,现在它将计算为位串。
新的 BIF 旨在为处理位级二进制文件提供与处理普通二进制文件相同的表达能力,而无需更改二进制文件(例如 size/1、binary_to_list/1、list_to_binary/1 等)的 BIF 的语义。 这意味着如果这些 BIF 的参数包含位串,则所有此类 BIF 都会抛出异常。