matteosister
Creating a variable with a macro, and then use it in its body
I’m trying to do something similar to wath ecto does when defining schemas. Basically the idea is:
defmodule Test do
use TableBuilder
row "test" do
field "field1"
field "field2"
end
end
row and field are macros defined in the TableBuilder module, what I’m trying to achieve is a DSL that underneath builds a Row struct, that has a fields collection of Field structs
here is what I’m doing right now:
defmodule TableBuilder do
defmacro __using__(_opts) do
quote do
import unquote(__MODULE__)
Module.register_attribute __MODULE__, :rows, accumulate: true
@before_compile unquote(__MODULE__)
end
end
defmacro __before_compile__(_env) do
quote do
def get_table do
inspect @rows
end
end
end
defmacro row(name, do: fields) do
row = %Row{name: name}
quote do
@rows {unquote(row), unquote(fields)}
end
end
defmacro field(name) do
quote do
%Field{name: unquote(name)}
end
end
end
the problem is:
when the field macro is called, I need to access the row variable created in the row macro.
But I can’t find a solution.
What’s the problem with this approach? Am I doing it wrong? Do you see better approaches to the problem?
Many thanks in advance!
Most Liked
Qqwy
By default, Macros in Elixir are unable to access variables outside of their definition. This is called ‘hygienic’. It is also possible to create unhygienic macros, which are what you are looking for here. Saša Jurić’s guide on Macros has some great information on this subject.
matteosister
yes! And this is exactly what I’m doing right now.
But this approach do not work perfectly for me for two reasons:
-
I need to define multiple rows in a single module (and right now I’m using the
fieldsattribute and then wipe it right after the macro body invocation to be empty for the next row) -
the fact that you are not forced in any way to use field inside a row macro, so weird things could happen. But maybe this is also a problem for ecto…and with a good documentation should be ok.
I’d really love to create a struct in the row macro and than pass it (like var!) when unquoting the body, but as far as I know it’s impossible…
matteosister
thanks for pointing me there…after many attempts I found a nice solution. Not so clean, but it’s working. ![]()
Popular in Questions
Other popular topics
Categories:
Sub Categories:
Forums
Popular Tags
- #ecto
- #liveview
- #troubleshooting
- #learning-elixir
- #deployment
- #library
- #erlang
- #testing
- #genserver
- #mix
- #absinthe
- #remote-other
- #otp
- #plug
- #how-to-question
- #macros
- #postgres
- #channels
- #elixirconf
- #exunit
- #discussion
- #code-sync
- #javascript
- #podcasts
- #onsite
- #dialyzer
- #docker
- #authentication
- #umbrella
- #full-time-contract
- #podcasts-by-brainlid
- #ecto-query
- #elixir-ls
- #phoenix_html
- #iex
- #blog-post
- #graphql
- #genstage
- #ai
- #websockets
- #supervisor
- #advent-of-code
- #elixirconf-us
- #distillery
- #processes
- #forms
- #api
- #metaprogramming
- #security
- #performance









