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.
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.
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.