Macro compilation error

Please help me understand why we get this compilation error.

Created a new phoenix project and created this macro

defmodule TestMacro do
  defmacro __using__(_options) do
    quote do
      use Test.Web, :controller
      plug :scrub_params, "page" when action in [:create, :update]
    end
  end
end

Inside a controller, use the macro

defmodule Test.Web.PageController do
 
  use TestMacro

  def index(conn, _params) do
    render conn, "index.html"
  end
end

Compile. We get this error

test $ mix compile
Compiling 2 files (.ex)

== Compilation error on file lib/test/web/controllers/page_controller.ex ==
** (CompileError) lib/test/web/controllers/page_controller.ex:4: unknown variable action or cannot invoke local action/0 inside guard
    (stdlib) lists.erl:1354: :lists.mapfoldl/3
    (stdlib) lists.erl:1354: :lists.mapfoldl/3
    (stdlib) lists.erl:1354: :lists.mapfoldl/3
    (stdlib) lists.erl:1354: :lists.mapfoldl/3
    (stdlib) lists.erl:1355: :lists.mapfoldl/3

Macros are hygienic, so it doesn’t see any variables from the outside. Passing in action as an option should work guaranteed.

Another possibility is to use var!/2.

@NobbZ - Thank you.

Doesn’t the quoted expression simply return without evaluation. When the macro is expanded, because of the, the action variable should be available right?

For example, instead of

plug :scrub_params, "page" when action in [:create, :update]

If I instead have

a = 1

It compiles fine. So how does this work?

I’ll read up more on macro hygiene.

@NobbZ - I think I get it. Thanks