Generate AST for string with interpolation

I had to write a macro helper which I wanted to return the ast corresponding to a string with the interpolation for a parameter:

def example(some_ast, value)
  quote do
    "...#{unquote(some_ast)}...#{unquote(value)}!"
  end
end

example(quote do foo() end, :bar) # => quote do "...#{foo()}...#{:bar}!" end

This works but I was wondering if there was a simple way to modify the implementation so it returns quote do "...#{foo()}...bar!" end instead?

It’s really just curiosity, as I wouldn’t be surprised if the second interpolation was optimized away.

2 Likes

The AST for a string with interpolation is the AST for string concatenation. The interpolation syntax doesn’t exist in the AST - its syntactic sugar. For example (as you’ve probably seen):

iex> quote do
...> "This is #{some} string"
...> end
{:<<>>, [],
 [
   "This is ",
   {:"::", [],
    [
      {{:., [], [Kernel, :to_string]}, [], [{:some, [], Elixir}]},
      {:binary, [], Elixir}
    ]},
   " string"
 ]}

I’d therefore be structuring my returned AST that way, rather than trying to recreate what is human-readable-only format (the interpolation syntax).

3 Likes

So you want to partially evaluate the AST. This is just not possible in elixir out of the box.

1 Like

Thanks to you both, that’s what I thought, thanks for the confirmations.