Macros can totally change the code that you see. If they were not opt-in, you could monkey patch the whole codebase like in Ruby or do JavaScript-like prototype fiddling. While this is still possible, it’s limited to a specific module and has to be explicitly requested by using use (“please inject some code here”), require (“I’m going to use macros from this module”) or import (make all/selected functions and macros available).
That is not exactly true. The main reason why you need require or import (use is just wrapper over require) is that you need to compile module with macro definition to happen before your module will be compiled, otherwise the compiler do not know what macro should expand to. The reason why it cannot be done automatically is that there is no way to know whether given construct is a macro or just regular function without first compiling the another module. Theoretically it shouldn’t be required for Logger, as this module is almost always already compiled when you compile your project, but for sake of the consistency it is better to have it there.
Following is the code (from Elixir for Programmers course by Dave Thomas):
defmodule Example do
def read_file({:ok, file}) do
file
|> IO.read(:line)
end
def read_file({:error, reason}) do
Logger.error("File.error: #{reason}")
[]
end
end
Then use it like,
iex(1)> ".gitignore" |> File.open |> Example.read_file
"# The directory Mix will write compiled artifacts to.\n"
Suppose you want to use Logger all over your application (which I think makes sense but not sure how others do it). Does this mean you have to require Logger at the top of each file? Is there some way to modify the AppWeb config so that Logger is always included and I don’t have to worry about this anymore?
I tried adding it into “view_helpers” macro but it didn’t work. I also tried adding it into the app_web.ex file alone but that didn’t work either. Frankly, I’m not well versed on macro development or how this part of the infrastructure works, so probably missing something, but i you have thoughts as to how to set this up or best practices advice for what you normally do, would be appreciated. For now, I’ll just require logger everywhere…