vshesh
I’m trying to use one macro inside another macro and running into issues:
defmodule Test do
defmacro somemacro(arg1, do: block) do
quote do
defmodule unquote(arg1) do
def unquote(arg1), do: 1
unquote_splicing(elem(block, 2))
end
end
end
defmacro othermacro(arg2, arg1, do: block) do
__MODULE__.somemacro arg1, do: quote do
def unquote(arg2), do: 2
end
end
end
I get that I can’t unquote inside othermacro so how do I do this?
Another try:
defmodule Test do
defmacro somemacro(arg1, do: block) do
quote do
defmodule unquote(arg1) do
def unquote(arg1), do: 1
unquote_splicing(elem(block, 2))
end
end
end
defmacro othermacro(arg2, arg1, do: block) do
newblock = quote do
def unquote(arg2), do: 2
end
__MODULE__.somemacro arg1, do: newblock
end
end
ERROR: you must require Test before invoking the macro Test.somemacro/2
requiring Test within Test causes another error:
(CompileError) you are trying to use the module AEnum which is currently being defined.
This may happen if you accidentally override the module you want to use. For example:
defmodule MyApp do
defmodule Supervisor do
use Supervisor
end
end
In the example above, the new Supervisor conflicts with Elixir's Supervisor. This may be fixed by using the fully qualified name in the definition:
defmodule MyApp.Supervisor do
use Supervisor
end
Basically othermacro is the same as somemacro except it adds some extra functions to the module
I am trying to use the do block to make a composition of the bits of the module … any help welcome
Trending in Questions
Hello!
Suppose you are building workflow (order / task / payment) processing system with the following requirements:
Each workflow con...
New
I’m in search of an Elixir library that offers PDF generation capabilities similar to Ruby’s Prawn. While there have been discussions abo...
New
I’m looking to build a personal workflow to quickly deploy web applications written in elixir/phoenix, for local consumption (ie not on t...
New
Before I dive in myself, did anyone successfully sprinkle Hologram into their existing LiveView app?
Looking for hints regarding:
Addi...
New
Kia ora,
We have been using elixir-google-api to connect to Google Drive. However, with the updates to Tesla due to CVEs this is now bro...
New
Hi all, I wanted to ask how the community is dealing with post-release steps.
Today we have Ecto migrations, which make sure that the db...
New
Hello,
I have an Elixir backend that implements a custom protocol over TCP. I want to load test the backend and assess the performance o...
New
Other Trending Topics
Hey, I’m Jesse and I’m the main contributor behind Dexter, a full-featured, lightning-fast Elixir LSP optimized for large codebases. It s...
New
Beam Bots (or just BB for short) is a framework for building fault-tolerant robotics applications in Elixir using familiar OTP patterns. ...
New
Hello everyone. After busy few months I am happy to announce v0.1.0 of Emerge & Solve.
They are GUI (Emerge) and State management (S...
New
Corex is an accessible, unstyled UI component library for Phoenix that integrates Zag.js state machines using Vanilla JavaScript and Live...
New
Emily is an Elixir library that runs Nx computations on Apple’s MLX. Install it as the default Nx backend and Nx, defn, Axon, Nx.Serving,...
New
There are three potential reasons for members of this forum to have a look at https://vutuv.de
You are tired or annoyed of LinkedIn.
Yo...
New
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
- #blog-post
- #phoenix_html
- #iex
- #graphql
- #ai
- #genstage
- #elixirconf-us
- #websockets
- #supervisor
- #advent-of-code
- #distillery
- #processes
- #api
- #forms
- #metaprogramming
- #security
- #hex










First 4 of 4 Posts
al2o3cr
Removing the
__MODULE__.fromothermacrofixes the require issue, but exposes a bigger problem:which fails with:
This happens because when
othermacrocallssomemacro, the valuesomemacrosees inblockis{:newblock, [line: 17], nil}.One way to avoid this problem is to keep the
defmacroparts simple and depend on plain functions to generate the actual AST fragments:BUT BEWARE SOME GOTCHAS
The module defined by
Test.somemacrois not nested - so in the example, it generates a top-level module named:bar:This may not be what you want.
vshesh
Why doesn’t this work?
Is it because the unquote is evaluated after being passed into somemacro?
al2o3cr
It comes down to the difference between
defanddefmacro:defdefines a function that expects evaluated arguments and returns a valuedefmacrodefines a function that expects AST arguments and returns a value (that’s usually AST) that is then evaluatedQuick demo:
The “plain function” version returns this AST:
the “macro function” version returns this AST:
A key thing to observe: the argument to
macro_functionis an AST representing the arguments passed. For instance, extracting code to a variable does NOT work quite like you’d expect:Here
macro_functionreceives an AST representing “access the local variable namedquoted_block”.vshesh
Right this makes sense it’s about what’s there at compile time.
I guess when othermacro is compiled somemacro is already expanded so there’s no opportunity to evaluate the
unquote.In that case though, shouldn’t this work?
That should expand to an AST that has further unquote definitions in it which are evaluated in the context of othermacro, right? (this isn’t right, it throws an error). I guess what I want to do is quote an unquote operation, so that the expanded macro has an unquote operation in it? Not sure how to do that.
I don’t understand how using functions helps - it’s the same issue where I want to compose ASTs. So I want, ideally, to have a function that returns an AST and then another function that adds some extra stuff to that AST. because there is no way to do that directly (is there some AST function I don’t know about), I’m left with composing macros.
Is this what
Macro.escapeis for? I can define the value of the block andescapeit into the macro.I end up with an invalid quoted expression though