RecipesBase.jl defines a macro @recipe that adds new methods to the RecipesBase.apply_recipe function. The catch is that RecipesBase might not be in scope at the macro call site, so the function RecipesBase.apply_recipe must be passed in directly.
I first tried interpolation
:($apply_recipe(x) = x+1)
But that failed because functions cannot be interpolated into function declarations. I thaught this was a bug and opened an issue, but apparently I’m supposed to be using GlobalRefs instead.
Why does the second approach above not work? How could it possibly be causing downstream segfaults? Is GlobalRef documented anywhere? What is a GlobalRef and how I use it?
I don’t know what a GlobalRef is and how it would help your problem. But here are (I think) a few ways to solve your problem:
module Foo
function foo end
# Does not work
macro new_foo_method_v0()
quote
$foo(::Val{0}) = 0
end
end
# Your workaround (IIUC), relying on the module knowing about itself
macro new_foo_method_v1()
quote
let M=$Foo
M.foo(::Val{1}) = 1
end
end
end
# The same as above, in a less convoluted way IMO
macro new_foo_method_v2()
quote
$Foo.foo(::Val{2}) = 2
end
end
# Another way, relying only the value of the function (not its name)
macro new_foo_method_v3()
quote
(::typeof($foo))(::Val{3}) = 3
end
end
end
Apart from v0, which fails as you already know, the other versions work as you’d expect (if I understood your problem correctly)
julia> Foo.@new_foo_method_v0
ERROR: syntax: invalid function name "Foo.foo" around REPL[1]:7
Stacktrace:
[1] top-level scope
@ REPL[2]:1
julia> Foo.@new_foo_method_v1
julia> Foo.@new_foo_method_v2
julia> Foo.@new_foo_method_v3
julia> methods(Foo.foo)
# 3 methods for generic function "foo":
[1] foo(::Val{1}) in Main at REPL[1]:15
[2] foo(::Val{2}) in Main at REPL[1]:23
[3] foo(::Val{3}) in Main at REPL[1]:30
As far as I know, GlobalRef is used by the compiler to make variables in local scope refer to objects from the containing global scope. I don’t think there’s too much to “use” here from the high level language, as Simeon mentioned in the issue - they’re emitted by the compiler and need a corresponding mapping in the scope it references.