What is the need for using var! in Phoenix.Template?

What is the need for using var! in the following code snippet from Phoenix.Template module?

Since assigns is set up the caller, shouldn’t this function work without the call to var! in both function header and as well as in the body?

answering my own question, it looks to me the _ = var!(assigns) is used only to avoid warnings on unused variable during compilation.

However, it’s not clear why var!(assigns) is required while it’s not required for another function defined in the macro the very next line:


1 Like

Macros and Meta programming in Elixir isn’t a topic I’ve learned yet but I did find this. Hopefully it is of use to you.

It is used to make assigns available in quoted.

The following code is directly from Phoenix.Template. As you can see, render_template didn’t use var!(assigns). It doesn’t trigger compilation error without it. However, if I remove var! from dynamic function created above, I get compilation error.

{name, quote do
      @file unquote(path)
      @external_resource unquote(path)

      defp unquote(defp)(var!(assigns)) do
        _ = var!(assigns)

      defp render_template(unquote(name), assigns) do

My question is in what ways these two function differ which requires var! in one and not in another?

This defines a function with the name of whatever the value of defp is. This function has a single argument, assigns. var!/1 is used here that one cann use assigns inside of quoted.

defp render_template(unquote(name), assigns) do

This defines a function, which calls the function which we defined earlier, passing in through assigns, as they have been given to this function when called.

In render_template assigns is known to be used, therefore there cannot ever be a warning. The other created function compiles the AST of the actual template into the module, so it‘s unknown if the template actually makes use of assigns or not. That‘s why the line with var! is added to ensure no warnings will happen, as each case is equaly valid and there‘s no way for the user to silence the warning as well.