kerryb
How do unquote sigils?
I have some AST rewriting code (using Sourceror) that has started failing in Elixir 1.18 – I believe because unquote has become stricter about valid AST, whereas in earlier versions it was only an issue within macros.
The issue is that it’s trying to generate code containing a ~D[...] sigil. It works in Elixir 1.17:
iex(1)> quote do: unquote(~D[2025-01-07])
~D[2025-01-07]
But not in 1.18:
iex(1)> quote do: unquote(~D[2025-01-07])
** (ArgumentError) tried to unquote invalid AST: ~D[2025-01-07]
Did you forget to escape term using Macro.escape/1?
(elixir 1.18.1) src/elixir_quote.erl:542: :elixir_quote.argument_error/1
iex:1: (file)
I can use Macro.escape as suggested, but this inserts the date as a raw map instead of a sigil. This works, but doesn’t look great in the generated code:
iex(2)> quote do: unquote(Macro.escape(~D[2025-01-07]))
{:%{}, [],
[__struct__: Date, calendar: Calendar.ISO, day: 7, month: 1, year: 2025]}
Is there some way to end up with a call to the ~D macro in the generated code, rather than the resulting struct/map?
Marked As Solved
LostKobrakai
The quote/unquote has nothing to do with how the final generated code looks like. They’re just means of generating AST/injecting given AST in the resulting AST. You’d need to figure out the correct AST you want to return for sourceror:
iex(1)> quote do: ~D[2024-12-12]
{:sigil_D, [delimiter: "[", context: Elixir, imports: [{2, Kernel}]],
[{:<<>>, [], ["2024-12-12"]}, []]}
Depending on what input you actually have you can build that AST for the return value.
iex(1)> quote do: unquote(~D[2025-01-07])
~D[2025-01-07]
This here is basically a noop. It does/did nothing.
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








