Reputation: 1202
I have a function that matches against some binary value:
def parse(<<timestamp::binary-size(4)>>) do
IO.inspect timestamp
end
Unfortunately, my real "pattern" is MUCH longer than this. Would it be possible to store that pattern and match on it later?
@pattern <<timestamp::binary-size(4)>>
def parse(@pattern) do
IO.inspect timestamp
end
Obviously, this doesn't work as I've written. And, no matter what I do with quote
and unquote
I can't seem to get this to work.
Upvotes: 3
Views: 574
Reputation: 222448
You cannot store the pattern in a variable, but you can create a macro:
defmodule A do
defmacro pattern do
quote do
<<var!(timestamp)::binary-size(4)>>
end
end
def parse(pattern()) do
IO.inspect timestamp
end
end
A.parse("abcd")
A.parse("abcde")
Output:
"abcd"
** (FunctionClauseError) no function clause matching in A.parse/1
a.exs:8: A.parse("abcde")
(elixir) lib/code.ex:370: Code.require_file/2
Note that I had to use var!(timestamp)
in the pattern. This is to disable Elixir's Macro Hygiene feature so that you can access that variable with the same name in the caller. You'll have to add var!()
around each variable name in the pattern.
Edit: You can store a quoted pattern in a module attribute and then unquote it in the function argument:
defmodule A do
@pattern quote do: <<var!(timestamp)::binary-size(4)>>
def parse(unquote(@pattern)) do
IO.inspect timestamp
end
end
The output is identical to the macro code above.
Upvotes: 3