我正在进行一个项目,在这个项目中,我可能会编写大量的表单代码:
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、ty清晰度和unpacking函数。甚至可以扩展它,在元组中添加第三个字段来传递一个函数来处理不同大小的类型。不幸的是,当我尝试做一个更简单的版本时(只使用一个大小的字段,并且只匹配1):
defmodule Unpack do
defmacro testmacro({name, kind}) do
quote do
<<unquote(name)::unqote(kind)>> = 1
end
end
end系统告诉我,quote/1的参数无效。我认为这是因为在位字符串模式匹配中使用的“类型”是一种特殊的形式,与一般的位字符串文本一样,而这些特定项在其他任何地方都不使用。
那我怎么才能绕开呢?我有十几种打包的结构,每一种都有五到二十个不同的字段。如果我不这么做,我可能会求助于Vim宏,至少拯救我的手.但是,这并不能真正帮助维护大量非常重复的代码。
发布于 2017-12-15 11:09:39
两件事:您在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输出:
97https://stackoverflow.com/questions/47784615
复制相似问题