We can use the function Code.eval_quoted to evaluate code fragments, such as those returned by quote.
| iex> fragment = quote do: IO.puts("hello") |
| {{:.,[],[{:__aliases__,[alias: false],[:IO]},:puts]},[],["hello"]} |
| iex> Code.eval_quoted fragment |
| hello |
| {:ok,[]} |
By default, the quoted fragment is hygienic, and so does not have access to variables outside its scope. Using var!(:name), we can disable this feature and allow a quoted block to access variables in the containing scope. In this case, we pass the binding to eval_quoted as a keyword list.
| iex> fragment = quote do: IO.puts(var!(a)) |
| {{:., [], [{:__aliases__, [alias: false], [:IO]}, :puts]}, [], |
| [{:var!, [context: Elixir, import: Kernel], [{:a, [], Elixir}]}]} |
| iex> Code.eval_quoted fragment, [a: "cat"] |
| cat |
| {:ok,[a: "cat"]} |
Code.string_to_quoted converts a string containing code to its quoted form, and Macro.to_string converts a code fragment back into a string.
| iex> fragment = Code.string_to_quoted("defmodule A do def b(c) do c+1 end end") |
| {:ok,{:defmodule,[line: 1],[{:__aliases__,[line: 1],[:A]}, |
| [do: {:def,[line: 1],[{:b,[line: 1],[{:c,[line: 1],nil}]}, |
| [do: {:+,[line: 1],[{:c,[line: 1],nil},1]}]]}]]}} |
| iex> Macro.to_string(fragment) |
| "{:ok, defmodule(A) do\n def(b(c)) do\n c + 1\n end\nend}" |
We can also evaluate a string directly using Code.eval_string.
| iex> Code.eval_string("[a, a*b, c]", [a: 2, b: 3, c: 4]) |
| {[2,6,4],[a: 2, b: 3, c: 4]} |