Victor Björklund

Elixir: Understanding the difference between "require" and "use"

Published: Jun 18 2023

If you’ve delved into the world of Elixir, chances are you’ve encountered the concept of metaprogramming through macros. Even if you haven’t written macros yourself or explored libraries that explicitly employ macros (like Ecto), you’ve unknowingly used them. Surprisingly, a significant portion of Elixir itself and its standard library is constructed using macros, which is quite mind-boggling when you stop to think about it.

Now, you might be pondering the significance of two frequently encountered keywords: “require” and “use.” These keywords often come up when working with libraries that heavily leverage macros. It’s essential to understand when to use each keyword and the distinctions between them. In this article, we’ll unravel these concepts to help beginners like you gain clarity.

In Elixir, “require” and “use” are two different directives used in metaprogramming, but they serve distinct purposes.

Require

The require directive is used to load and make available external modules within the current module. When you require a module, you gain access to its functionality and can use its functions, macros, and types. It’s similar to importing modules in other programming languages. require is typically used at the top of a module to specify dependencies. Here’s an example of using require:

defmodule MyModule do
  require Logger

  def log_message(message) do
    Logger.info(message)
  end
end

In the above example, require Logger allows you to use the Logger module and its info/1 function within the MyModule module.

Use

The use directive is used to invoke a set of predefined code transformations, called macros, provided by a module. When you use a module, it typically injects code or modifies the current module’s behavior.

For example, the use GenServer directive is often used to create a GenServer process. It automatically injects boilerplate code and defines callbacks required by the GenServer behavior.

Here’s an example of using use:

defmodule MyServer do
  use GenServer

  def init(_) do
    # Initialization logic
  end

  # Callback functions defined by GenServer
  def handle_cast(message, state) do
    # Handling cast messages
  end

  def handle_info(message, state) do
    # Handling info messages
  end
end

In the above example, use GenServer injects the necessary code to implement the GenServer behavior, such as setting up message handling callbacks and managing the server’s state.

To summarize, require is used to import external modules and make their functionality available, while use is used to apply code transformations or inject predefined functionality into the current module.