I have a macro that in some circumstances must throw an error. Is there a recommended way of doing that?
For example, I can throw the error directly from the macro, or return code that throws the error.
macro A()
if true
error("Error message")
else
return :(1 + 1)
end
end
macro B()
if true
return quote
error("Error message")
end
else
return :(1 + 1)
end
end
If I understand it correctly, macro @A would cause an error during compile time, while macro @B would cause an error during run time. I don’t think this would make any difference to the user who calls my macro in their code. However, it makes a difference for me in my unit tests. In particular, I can do
I’m hoping to have discussion about this. Would you recommend one versus the other and why? Am I thinking about this correctly? Are there other considerations that I should take into account?
That does make a difference for users too. Let’s imagine that the macro is not used interactively or in global scope, but inside a function. Then @A would throw the error in the moment of defining the function (it does not even need to be compiled), but @B would let the function exist, which would fail in the moment of calling it.
You have to decide if you need one thing or the other.
If the error can be thrown at compile-time, I’d say it’s best to fail during macro expansion. Examples of early macro expansion failure include the Test macros themselves:
julia> using Test
julia> @macroexpand @test true unsupported_kwarg=nothing
ERROR: invalid test macro call: @test true unsupported_kwarg = nothing
This example also illustrates how @macroexpand allows to clearly separate the macro expansion stage from the runtime, which allows testing for errors that happen during macro expansion:
julia> macro A()
error("ko")
end
@A (macro with 1 method)
julia> @test_throws ErrorException @macroexpand @A
Test Passed
Thrown: ErrorException
Another way of thinking about it is that macros are basically syntax transformations. So it makes sense to throw errors as soon as possible (like syntax errors)