我正在做一个项目,我可能会在其中编写大量以下形式的代码:
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}])
并自动生成必要的结构、typedef 和解包函数,用于固定大小的任意命名字段。甚至可以扩展它,在元组中添加第三个字段来传递一个函数来处理可变大小的类型。不幸的是,当我尝试做一个更简单的版本时(只取一个大小的字段,并且只匹配 1 ):
defmodule Unpack do
defmacro testmacro({name, kind}) do
quote do
<<unquote(name)::unqote(kind)>> = 1
end
end
end
系统告诉我它有无效的参数quote/1
。我认为这是因为位串模式匹配中使用的“类型”是一种特殊形式,一般而言,位串文字也是如此,并且这些特定项目不会在其他任何地方使用。
那么,我该如何解决呢?我有十几种打包结构要解包,每种都有五到二十个不同的字段。如果我不这样做,我可能会求助于 Vim 宏来至少节省我的双手……但这对于维护大量极其重复的代码并没有真正的帮助。