Conditionally defining a macro

I want to be able to modify a bunch of definitions depending on whether another file is included. In the parlance of Aspect Oriented programming, that file would implement an aspect which I could optionally include. I would use a macro to explicityly identify the cutpoints where the aspect has effect.

To minimize the change in my original source file, I’d just wrap each expression to be affected with a macro. That macro would be the identity macro if it has no other definition.

To this end, I want to conditionally define a macro to an identity macro if the macro is not otherwise defined:

try
    @mymacro()
catch e
    if e isa UndefVarError
        macro mymacro(e)
            e
        end
    end
end

but this fails with

ERROR: syntax: macro definition not allowed inside a local scope

In CommonLisp, top levelexpressions are evaluated at both compile time and load time, unless explicity wrapped in EVAL-WHEN. I’ve not seen explicit documentation of Julia’s semantics for top level expressions, but it appears that only certain top level expressions have compile time effect: macro definitions, and possibly const declarations. Is my assumption on-track?

What is the right way to conditionally define a macro if it is not yet defined?

Thanks.

Maybe just use isdefined:

julia> module M
           macro m() :() end
       end
Main.M

julia> isdefined(M, Symbol("@m"))
true

so:

if !isdefined(@__MODULE__, Symbol("@mymacro"))
    macro mymacro(ex)
        esc(ex)
    end
end
1 Like