[英]Elixir macros, quoting bitstring patternmatch types
我正在做一个项目,其中我可能会编写很多形式的代码:
defmodule Kind
defstruct [name1, name2, name3]
@type t :: %Kind{name1: integer(), name2: integer(), name3: binary()}
def unpack(input) do
with <<name1::integer-8>> <- Enum.take(input, 1),
<<name2::integer-little-32>> <- Enum.take(input, 4),
<<name3::binary-10>> <- Enum.take(input, 10),
do: %Kind{name1: name1, name2: name2, name3: name3>>
end
end
(对于任意输入名称和类型集, input
是一次生成一个字节的二进制流)
能够在宏中进行处理将非常有用,这样我就可以简单地编写(例如) use Unpack quote([{name1, integer-8}, {name2, integer-little-32}, {name3, binary-10}])
,并为固定大小的任意命名字段自动生成必要的struct,typedef和拆包函数。 甚至可以对其进行扩展,在元组中添加第三个字段以传递用于处理大小可变的类型的函数。 不幸的是,当我尝试做一个更简单的版本时(仅采用一个大小的字段,并且仅将其匹配1):
defmodule Unpack do
defmacro testmacro({name, kind}) do
quote do
<<unquote(name)::unqote(kind)>> = 1
end
end
end
系统告诉我, quote/1
参数无效。 我认为这是因为在位串模式匹配中使用的“类型”是一种特殊形式,通常在位串文字中也是如此,并且这些特定项在其他任何地方都没有使用。
那么,我该如何解决呢? 我要解压缩的打包结构有十几种,每种都有五到二十个不同的字段。 如果我不这样做,我可能会求助于Vim宏,至少可以省掉我的手...但是,这对于维护大量极其重复的代码并没有真正的帮助。
两件事情:您在unquote
有一个错字,RHS必须是二进制的,以便模式匹配。 经过这些更改,您的代码对我有用:
defmodule Unpack do
defmacro unpack({name, kind}) do
quote do
<<unquote(name)::unquote(kind)>> = "a"
end
end
end
defmodule Main do
import Unpack
def main do
unpack({foo, integer-8})
IO.inspect foo
end
end
Main.main
输出:
97
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.