LukasKnuth

LukasKnuth

How do I unquote a sigil parameter to a macro?

Consider the following simple example:

defmodule Test.Foo do
  defmacro foo(regex) do
    IO.inspect(regex)
  end
end

defmodule Test do
  require Test.Foo

  Test.Foo.foo(~r/test/)
end

{:sigil_r, [delimiter: "/", line: 10], [{:<<>>, [line: 10], ["test"]}, []]}
iex>

Here, the sigil passed to Test.Foo.foo becomes a quoted expression. When using the macro for code generation, one would simple call unquote/1 on arg and get the sigil representation again.

However, if I do this in the above example (IO.inspect(unquote(regex))), I get the following error:

warning: variable “regex” does not exist and is being expanded to “regex()”, please use parentheses to remove the ambiguity or change the variable name
macro_why.exs:3: Test.Foo
** (CompileError) macro_why.exs:3: undefined function regex/0 (there is no such import)

Note that I don’t have a quote block in my macro. The actual code I’m working on parses the AST directly into an internal representation, so there is no need to quote anything. This is whats kinda throwing me for a loop here.

Most Liked

benwilson512

benwilson512

Author of Craft GraphQL APIs in Elixir with Absinthe

Hey @LukasKnuth that isn’t how that works. You can think of quote and unquote as similar to "" and #{}. You can’t use #{} outside of a string "" it just doesn’t make any sense. And when you use unquote inside of quote it is not turning it “back into” a sigil, it’s still AST. AST is all there is at the macro level. It’s just interpolating that ast inside of other AST.

Can you show an example of the code you’re trying to get to work in general? Tangentially there is another thread about the use of ~p that is pretty similar Using `~p` dynamically inside a macro - #5 by 0xG it may have some useful pointers for you.

Last Post!

LukasKnuth

LukasKnuth

I’m contributing to the Goal library. They use a DSL to generate a schema to validate input against:

defparams :sigil do
 required :id, :string, format: ~r/testing/
end

This is then implemented as:

defmacro defparams(do: block) do
  quote do
    def schema do
      unquote(block |> generate_schema() |> Macro.escape())
    end
  end
end

defp generate_schema({:__block__, _lines, contents}), do: ...

defp generate_schema({:required, _lines, [field, type, options]}), do: ...

The problem is that the regex becomes the quoted string as above. Then later when I try to do the actual validation based on the schema created from the AST, I try to pattern match on the Regex:

{:format, %Regex{} = regex}, acc ->
  validate_format(acc, field, regex)

This won’t work, because the value of the :format option is a tuple (the quoted string representation of the sigil call).

The question now is:

  • Should I fix this call-site (e.g. in the DSL) - and if so, how?
  • Or is this something the generate_schema function needs to handle - and if so, how?

Where Next?

Popular in Questions Top

hariharasudhan94
lets say i have a sample like a = 20; b = 10; if (a &gt; b) do {:ok, "a"} end if (a &lt; b) do {:ok, b} end if (a == b) do {:ok, "equa...
New
jononomo
For some reason my phoenix channels are working for me in my local dev environment, but as soon as I deploy via Docker, I get a 403 error...
New
lessless
I believe there are people here who are dealing with CSV files import on the daily basis, and since Excel is a really popular tool there ...
New
aadeshere1
I have a another noob question about loop. Since elixir is immutable, while loop is not directly possible. total = 10 while total != 0 ...
New
jerry
Good day to you all. I have been struggling to get a query involving like and ilike to work. Can anyone assist me on this, please? pro...
New
WestKeys
Currently suffering from paralysis by [HTTP client] analysis. This is rather unusual in Elixirland as there tends to be consensus on the ...
New
Patoshizzle
After calling mix ecto.create I get this error: 17:00:32.162 [error] GenServer #PID&lt;0.412.0&gt; terminating ** (Postgrex.Error) FATAL...
New

Other popular topics Top

baxterw3b
Hi guys, i’m new in the Elixir world, and i have to say, that i love it! i’m having some problem to understand anonymous functions with ...
New
dogweather
I wrote this comment on r/haskell, and it’s not popular there. :wink: But I think I’m on to something… Haskell reminds me of Java, and e...
New
AstonJ
Seen any cool LiveView demos, sample apps or examples? Please post them here! :003:
New
shijith.k
I am trying to start a new phoenix project with elixir 1.9, but mix phx.new does not work. It says that ** (Mix) The task "phx.new" could...
New
SoCreat
i’m a new one to elixir which editor can i use vs code? or atom? Thanks! :smiley:
New
AstonJ
Posting this to see if we can make things easier for people to get into Neovim. If you use Neovim and have a favourite distro please let ...
New

We're in Beta

About us Mission Statement