Macros can be fantastic (if not strictly necessary) for eliminating boilerplate, e.g. in BaseDirs.jl
I have
@setxdg DATA_HOME "~/.local/share"
@setxdgs DATA_DIRS ["/usr/local/share", "/usr/share"]
@setxdg CONFIG_HOME "~/.config"
@setxdgs CONFIG_DIRS ["/etc/xdg"]
@setxdg STATE_HOME "~/.local/state"
@setxdg BIN_HOME "~/.local/bin"
@setxdg CACHE_HOME "~/.cache"
Each invocation of @setxdg
is saving 3 lines (4 → 1) and improving code clarity. There are 49 uses of this macro across the codebase, IMO this is well worth it.
In DataToolkit.jl
, I define a few macros such as @addpkg
, @require
, and @advise
.
These could all be removed in favor of functions, but once again clarity and readability would suffer. Manually passing in @__MODULE__
every time you invoke a function (when it’s a commonly called function) is also just a bit of a pain.
String macros are also rather handy, as an example I’d pick the IMO indispensable ~500 line (yes, it’s that big) string macro in StyledStrings.jl
.
styled"{bold,(bg=yellow):hey} {green:there $you}"
# The above expands to (cleaned up):
annotatedstring(
AnnotatedString("hey there ",
[(1:3, :face => :bold),
(1:3, :face => Face(background=:yellow)),
(5:10, :face => :green)]),
let you_str = string(you)
you_len = ncodeunits(you_str)
if you_str isa AnnotatedString && !(isempty(you_str))
AnnotatedString(String(you_str),
vcat([1:you_len, :face => :green],
annotations(you_str)))
else
if isempty(you_str)
""
else
AnnotatedString(you_str, [(1:you_len, :face => :green)])
end
end
end) |> annotatedstring_optimize!
Maybe I’m missing something, but I would find it hard to classify the above as “unnecessary and regrettable”.