当前位置: 首页>>代码示例 >>用法及示例精选 >>正文


Elixir Kernel.SpecialForms.<<args>>用法及代码示例


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"

utf8utf16utf32 类型用于 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的重复段数)。

类型默认单位
integer1 位
float1 位
binary8 位

类型的大小更细微。整数的默认大小为 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

此语法反映了通过将大小乘以单位来给出有效大小的事实。

修饰符

某些类型具有关联的修饰符以消除字节表示中的歧义。

修饰符相关类型
signedinteger
unsigned(默认)integer
littleinteger , float , utf16 , utf32
big(默认)integer , float , utf16 , utf32
nativeinteger , utf16 , utf32

符号

整数可以是 signedunsigned ,默认为 unsigned

iex> <<int::integer>> = <<-100>>
<<156>>
iex> int
156
iex> <<int::integer-signed>> = <<-100>>
<<156>>
iex> int
-100

signedunsigned 仅用于匹配二进制文件(见下文)并且仅用于整数。

iex> <<-100::signed, _rest::binary>> = <<-100, "foo">>
<<156, 102, 111, 111>>

字节序

Elixir 有三个字节序选项:biglittlenative。默认值为 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-lang.org大神的英文原创作品 Kernel.SpecialForms.<<args>>。非经特殊声明,原始代码版权归原作者所有,本译文未经允许或授权,请勿转载或复制。