🎓 A1Learner
🔍
0 of 46 lessons completed

Elixir Compile-Time Code Generation

Compile-time code generation builds function definitions from a list while the code is being prepared. One list can produce many functions, each named from one list item.

One list makes two functions

The list holds red and blue. Each name becomes a function.

defmodule Palette do
  for name <- [:red, :blue] do
    def unquote(name)(), do: Atom.to_string(unquote(name))
  end
end
IO.puts(Palette.red())
IO.puts(Palette.blue())

Names and values come from pairs

Each pair holds a name and a message. Each pair becomes one function.

defmodule Words do
  for {name, message} <- [hello: "Hello!", bye: "Goodbye!"] do
    def unquote(name)(), do: unquote(message)
  end
end
IO.puts(Words.hello())
IO.puts(Words.bye())

Generated functions return numbers too

The same pattern works for numbers, not only for words.

defmodule Scores do
  for {name, value} <- [one: 1, two: 2, three: 3] do
    def unquote(name)(), do: unquote(value)
  end
end
IO.puts(Scores.one())
IO.puts(Scores.two())
IO.puts(Scores.three())

Example

defmodule AnimalSounds do
  for {name, sound} <- [cat: "Meow", dog: "Woof", cow: "Moo"] do
    def unquote(name)(), do: unquote(sound)
  end
end
IO.puts(AnimalSounds.cat())
IO.puts(AnimalSounds.dog())
IO.puts(AnimalSounds.cow())

Key points

  • Code generation: code generation builds definitions from data instead of writing each one by hand.
  • List: a list of names drives how many functions are made.
  • Use def unquote(name) to define a function whose name comes from a variable.
  • Use unquote inside the body to put the list value into the function.
  • For: a for loop inside a module runs once per list item and defines one function each time.

In this example, a list of three name and sound pairs drives a for loop, each pair defines one function, and each function returns its own sound.

Note

the generated functions are ordinary functions once they exist.

Try it Yourself

Edit the code, then press Run.

Running is simulated

Exercise

What does def unquote(name) do inside a module?