Why can't I combine a macro call with a comparison operator?

To save myself a bit of typing, I have created a wrapper macro around a function in my model, to be used in a specific context:

macro landcover()
    :(landcover($(esc(:pos)), $(esc(:model))))
end

I want to be able to use this macro in conditional statements. However, doing so throws an error:

julia> @macroexpand @landcover
:(MyModel.landcover(pos, model))

julia> landcover(pos, model) == 20
true

julia> @landcover == 20
ERROR: syntax: "==" is not a unary operator
Stacktrace:
 [1] top-level scope
   @ none:1

Why is that?

You need parentheses to keep the macro call from slurping up all the expressions to the right of it.

@landcover() == 20

or

(@landcover) == 20

or

20 == @landcover

See docs.

1 Like

True, I should have thought of that… My expectation was that since the macro doesn’t take any arguments, any expressions that followed its invocation would therefore not be considered possible arguments.

I take it that Julia has no equivalent to Common Lisp’s symbol macros / parameterless macros?

Julia has multiple dispatch for macros too, so you can define more macros with the same name that do take those arguments. That can’t be known at parse time, so what you want isn’t possible.

1 Like

To illustrate that macros are really just a special case of functions:

julia> function var"@foo"(_, _, arg)  QuoteNode(arg)  end
@foo (macro with 1 method)

julia> @foo Hello, world!
:((Hello, world!))

Edit: Note that this is not official API, and should probably not be relied upon in case it’s ever decided to prepend additional arguments into macro invocations.