shahryarjb

shahryarjb

How to alias a module in __using__

Hello, I want to load a alias under my __using__, but with opts help like this:

defmacro __using__(opts) do
  quote(bind_quoted: [opts: opts]) do
    behaviour = Keyword.get(opts, :behaviour)
    alias behaviour
  end
end

It shows me invalid argument for alias, expected a compile time atom or alias, got: behaviour error, if I use alias unquote(behaviour), it shows me unquote called outside quote.

It should be noted, for @behaviour it works if I do like this, @behaviour behaviour but for alias doesn’t work.
How can I fix this? Thanks

Most Liked

LostKobrakai

LostKobrakai

One thing people usually have a hard time to grok is that macros only deal with AST – or “code”. Even if things look like a variable they don’t really represent the value assigned to the variable.

defmacro __using__(opts) do
  quote(bind_quoted: [opts: opts]) do
    behaviour = Keyword.get(opts, :behaviour)
    alias behaviour
  end
end

Doing this means alias (also a macro) will receive the AST for the behaviour variable (something like this: {:behaviour, [], Elixir}). So it has no idea what module it’s supposed to alias.

defmacro __using__(opts_ast) do
  behaviour = select_module_from_opts(opts_ast)
  quote do
    alias unquote(behaviour)
  end
end

This on the other hand pulls out the module out of the AST your macro received and creates AST (again a representation of code), where alias receives the module as an argument instead of a variable.

The tricky part here is select_module_from_opts, because again opts is AST not necessarily a plain value to consume. Some values represent themselves in AST – no difference between the AST and the value represented – so they’re rather easy to deal with (e.g. many keyword lists with simple values) , but others are not as simple, e.g. maps or anything containing other variables.

LostKobrakai

LostKobrakai

You‘ll need to pull out the module in the macro body and not in the quoted return. It needs to look like this:

alias unquote(module)

Anything where the alias macro doesn‘t receive the module name directly, but e.g. the ast of a variable won‘t work.

shahryarjb

shahryarjb

Thank you for your complete explanation. The subject is beyond my comprehension, and I’ve refrained from using alias. :rose:

Where Next?

Popular in Questions Top

vonH
In asking this question I am more interested about the expressiveness of the language itself and less concerned about the availability of...
New
gshaw
What is the idiomatic way of matching for not nil in Elixir? E.g., First way: defp halt_if_not_signed_in(conn, signed_in_account) when...
New
LegitStack
I’m hoping you guys can give me some general advice and perhaps code examples if you’re feeling up to it. I’m very interested in Elixir,...
New
openscript
Hello! Sorry for this astonishing simple question, but I’m really stuck. I try to set up the intellij-elixir plugin, but I don’t know ho...
New
aalberti333
As the title describes, I’m trying to run Enum.map() over a list of key/value pairs, where the value is a map. My data looks like this: ...
New
pgiesin
This should be a simple problem but I just can’t seem to figure it out. I have a standalone Elixir app that won’t find the database. Dep...
New
sacepums
Hey guys. I'm new to elixir and im really stocked about it. But I ran into a bit of problem - I need to convert a date sting, for examp...
New
Mooodi
Given a string, how can I get access to its character by index? Enum.at("my_string", 2) doesn't work. Or rather, not char, but a substr...
New
skosch
To my knowledge, put_in, Map.update etc. all have the one limitation of not automatically creating intermediate keys when needed (for exa...
New
idi527
I’ve been re-reading swift book again and noticed that multiline strings there don’t have a trailing line break, unlike in elixir iex(2)...
New

Other popular topics Top

albydarned
Hello all! I am typing this post from my new MacBook Pro with the M1 chip. I’m loving it so far, and will probably use it as my daily dr...
New
openscript
Hello! Sorry for this astonishing simple question, but I’m really stuck. I try to set up the intellij-elixir plugin, but I don’t know ho...
New
AstonJ
You’re a programmer, so you don’t need spoon feeding with the conventional drivel about “this is an integer.” No. You need to know what’s...
New
jononomo
I am trying to figure out how Mix knows whether the environment is test, dev, or prod -- where is this set? Thanks.
New
polypush135
As many of you may have realized by now (sorry for all the posts here) I’ve been working on a db problem where I’m trying to aggregate a ...
New
lastday4you
I wanted to check elixir version in phoenix because i found that my elixir is 1.5 but when i use Enum.chunk_by it said the function is un...
New
alice
Hey, Just curious what are the main benefits of Elixir compared to Clojure? When is Elixir more useful than Clojure and vice versa? Th...
New
msaraiva
Surface is an experimental library built on top of Phoenix LiveView and its new LiveComponent API that aims to provide a more declarative...
564 42633 214
New
Patoshizzle
After calling mix ecto.create I get this error: 17:00:32.162 [error] GenServer #PID<0.412.0> terminating ** (Postgrex.Error) FATAL...
New
Qqwy
Original source of discussion: This topic on the Pragmatic Programmers' Functional Web Development with Elixir, OTP, and Phoenix forum. ...
New

We're in Beta

About us Mission Statement