Elixir语言中 Kernel.SpecialForms.<<args>>
相关用法介绍如下。
用法:
<<args>>
(宏)
定义一个新的位串。
例子
iex> <<1, 2, 3>>
<<1, 2, 3>>
类型
一个位串由许多段组成,每个段都有一个类型。位串中使用了 9 种类型:
integer
float
bits
(bitstring
的别名)bitstring
binary
bytes
(binary
的别名)utf8
utf16
utf32
未指定类型时,默认为 integer
:
iex> <<1, 2, 3>>
<<1, 2, 3>>
Elixir 还默认接受段为文字字符串或文字字符列表,默认情况下扩展为整数:
iex> <<0, "foo">>
<<0, 102, 111, 111>>
二进制文件需要明确标记为 binary
:
iex> rest = "oo"
iex> <<102, rest::binary>>
"foo"
utf8
、 utf16
和 utf32
类型用于 Unicode 代码点。它们也可以应用于文字字符串和字符列表:
iex> <<"foo"::utf16>>
<<0, 102, 0, 111, 0, 111>>
iex> <<"foo"::utf32>>
<<0, 0, 0, 102, 0, 0, 0, 111, 0, 0, 0, 111>>
否则我们在构建二进制文件时会得到一个
:ArgumentError
rest = "oo"
<<102, rest>>
** (ArgumentError) argument error
选项
使用-
作为分隔符可以给出许多选项。顺序是任意的,所以以下都是等价的:
<<102::integer-native, rest::binary>>
<<102::native-integer, rest::binary>>
<<102::unsigned-big-integer, rest::binary>>
<<102::unsigned-big-integer-size(8), rest::binary>>
<<102::unsigned-big-integer-8, rest::binary>>
<<102::8-integer-big-unsigned, rest::binary>>
<<102, rest::binary>>
单位和大小
匹配的长度等于unit
(位数)乘以size
(长度为unit
的重复段数)。
类型 | 默认单位 |
---|---|
integer | 1 位 |
float | 1 位 |
binary | 8 位 |
类型的大小更细微。整数的默认大小为 8。
对于浮点数,它是 64。对于浮点数,size * unit
必须产生 16、32 或 64,分别对应于 IEEE 754 binary16、binary32 和 binary64。
对于二进制文件,默认值是二进制文件的大小。只有匹配中的最后一个二进制文件可以使用默认大小。所有其他人必须明确指定其大小,即使匹配是明确的。例如:
iex> <<name::binary-size(5), " the ", species::binary>> = <<"Frank the Walrus">>
"Frank the Walrus"
iex> {name, species}
{"Frank", "Walrus"}
大小可以是一个变量:
iex> name_size = 5
iex> <<name::binary-size(name_size), " the ", species::binary>> = <<"Frank the Walrus">>
iex> {name, species}
{"Frank", "Walrus"}
并且可以在匹配本身中定义变量(在使用之前):
iex> <<name_size::size(8), name::binary-size(name_size), " the ", species::binary>> = <<5, "Frank the Walrus">>
iex> {name, species}
{"Frank", "Walrus"}
但是,大小不能在二进制/位串匹配之外的匹配中定义:
{name_size, <<name::binary-size(name_size), _rest::binary>>} = {5, <<"Frank the Walrus">>}
** (CompileError): undefined variable "name_size" in bitstring segment
未能指定 non-last 的大小会导致编译失败:
<<name::binary, " the ", species::binary>> = <<"Frank the Walrus">>
** (CompileError): a binary field without size is only allowed at the end of a binary pattern
快捷方式语法
传递整数值时,也可以使用语法快捷方式指定大小和单位:
iex> x = 1
iex> <<x::8>> == <<x::size(8)>>
true
iex> <<x::8*4>> == <<x::size(8)-unit(4)>>
true
此语法反映了通过将大小乘以单位来给出有效大小的事实。
修饰符
某些类型具有关联的修饰符以消除字节表示中的歧义。
修饰符 | 相关类型 |
---|---|
signed | integer |
unsigned (默认) | integer |
little | integer , float , utf16 , utf32 |
big (默认) | integer , float , utf16 , utf32 |
native | integer , utf16 , utf32 |
符号
整数可以是 signed
或 unsigned
,默认为 unsigned
。
iex> <<int::integer>> = <<-100>>
<<156>>
iex> int
156
iex> <<int::integer-signed>> = <<-100>>
<<156>>
iex> int
-100
signed
和 unsigned
仅用于匹配二进制文件(见下文)并且仅用于整数。
iex> <<-100::signed, _rest::binary>> = <<-100, "foo">>
<<156, 102, 111, 111>>
字节序
Elixir 有三个字节序选项:big
、little
和 native
。默认值为 big
:
iex> <<number::little-integer-size(16)>> = <<0, 1>>
<<0, 1>>
iex> number
256
iex> <<number::big-integer-size(16)>> = <<0, 1>>
<<0, 1>>
iex> number
1
native
由 VM 在启动时确定,并将取决于主机操作系统。
二进制/位串匹配
二进制匹配是 Elixir 中的一项强大函数,可用于从二进制文件中提取信息以及模式匹配。
二进制匹配本身可以用来从二进制文件中提取信息:
iex> <<"Hello, ", place::binary>> = "Hello, World"
"Hello, World"
iex> place
"World"
或者作为模式匹配的函数定义的一部分:
defmodule ImageTyper do
@png_signature <<137::size(8), 80::size(8), 78::size(8), 71::size(8),
13::size(8), 10::size(8), 26::size(8), 10::size(8)>>
@jpg_signature <<255::size(8), 216::size(8)>>
def type(<<@png_signature, _rest::binary>>), do: :png
def type(<<@jpg_signature, _rest::binary>>), do: :jpg
def type(_), do: :unknown
end
性能与优化
Erlang 编译器可以在二进制创建和匹配方面提供许多优化。要查看优化输出,请设置 bin_opt_info
编译器选项:
ERL_COMPILER_OPTIONS=bin_opt_info mix compile
要了解有关特定优化和性能注意事项的更多信息,请查看Erlang 效率指南的“构建和匹配二进制文件”一章.
相关用法
- Elixir Kernel.SpecialForms.case用法及代码示例
- Elixir Kernel.SpecialForms.%{}用法及代码示例
- Elixir Kernel.SpecialForms.for用法及代码示例
- Elixir Kernel.SpecialForms.quote用法及代码示例
- Elixir Kernel.SpecialForms.require用法及代码示例
- Elixir Kernel.SpecialForms.&expr用法及代码示例
- Elixir Kernel.SpecialForms.{args}用法及代码示例
- Elixir Kernel.SpecialForms.unquote_splicing用法及代码示例
- Elixir Kernel.SpecialForms.receive用法及代码示例
- Elixir Kernel.SpecialForms.%struct{}用法及代码示例
- Elixir Kernel.SpecialForms.import用法及代码示例
- Elixir Kernel.SpecialForms.left . right用法及代码示例
- Elixir Kernel.SpecialForms.alias用法及代码示例
- Elixir Kernel.SpecialForms.try用法及代码示例
- Elixir Kernel.SpecialForms.fn用法及代码示例
- Elixir Kernel.SpecialForms.cond用法及代码示例
- Elixir Kernel.SpecialForms.__aliases__用法及代码示例
- Elixir Kernel.SpecialForms.left :: right用法及代码示例
- Elixir Kernel.SpecialForms.unquote用法及代码示例
- Elixir Kernel.SpecialForms.with用法及代码示例
- Elixir Kernel.SpecialForms.__block__用法及代码示例
- Elixir Kernel.SpecialForms.^var用法及代码示例
- Elixir Kernel.round用法及代码示例
- Elixir Kernel.left / right用法及代码示例
- Elixir Kernel.put_in用法及代码示例
注:本文由纯净天空筛选整理自elixir-lang.org大神的英文原创作品 Kernel.SpecialForms.<<args>>。非经特殊声明,原始代码版权归原作者所有,本译文未经允许或授权,请勿转载或复制。