I have two versions of __using__
, however, first version has different behaviour from one I've expected. This code does not work properly (actually, it does not import anything).
defmodule SomeModule do
defmacro __using__(opts \\ []) do
quote do
opts = unquote(opts)
if Keyword.has_key?(opts, :my_key) && opts[:my_key] == 3 do
import MyModuleOne
else
import MyModuleTwo
end
end
end
end
And this is the working version, however, I don't like having two separate quote
parts.
defmodule SomeModule do
defmacro __using__(opts \\ []) do
if Keyword.has_key?(opts, :my_key) && opts[:my_key] == 3 do
quote do
import MyModuleOne
end
else
quote do
import MyModuleTwo
end
end
end
end
How should the first one be rewritten for it to work properly?
That's a tricky one! Took me a while to work out the reason...
Before going into why, let me assure you that your macro is perfectly valid, and Elixir works precisely as you told it .
I tried to expand the two macros you posted and got the same result, ie the correct thing is being imported. But why does it not work as you expected?
Here is why,
It is important to notice that import/2 is lexical
from the docs for import
and let me show you 2 examples
iex(1)> import Enum, only: [into: 2]
Enum
iex(2)> into [a: 1], %{}
%{a: 1}
iex(3)>
and...
iex(1)> if true do
...(1)> import Enum, only: [into: 2]
...(1)> end
Enum
iex(2)> into [a: 1], %{}
** (CompileError) iex:2: undefined function into/2
the import only takes effect inside the clause that you wrote it :)
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.