宏的卫生很奇怪

时间:2014-10-05 17:30:46

标签: macros julia hygiene

假设我在模块中有这个宏定义:

module Example

export @example_macro

macro example_macro(a)
    quote
        local r = RemoteRef()
        put!(r, $(esc(a)))
        remotecall_fetch(2, (r) -> fetch(r), r)
    end
end

end

这是它的扩展:

julia> include("Example.jl")

julia> using Example

julia> macroexpand(quote @example_macro a end)
quote  # none, line 1:
    begin  # /.../Example.jl, line 7:
        local #121#r = Example.RemoteRef() # line 8:
        Example.put!(#121#r,a) # line 9:
        Example.remotecall_fetch(2,(r) -> Example.fetch(r),#121#r)
    end
end

全局可用函数中的每一个(例如put!fetch)都以模块名称为前缀。据我所知,这需要宏来保持卫生 - 例如,如果fetch在调用@example_macro的模块中重新定义,并且fetch被插入到扩展中,那么,它无法正常工作。

但是,这还需要Example模块不仅可以在主进程中使用,还可以在第二个工作程序上使用(因为remotecall_fetch需要在其上执行Example.fetch)。我不想要它 - 毕竟,fetch是默认情况下所有工作人员都可以使用的基本功能。

那么,有没有办法禁用所有带有当前模块名称的标识符的前缀?我认为这意味着将宏视为非卫生,因为在宏扩展阶段无法确定某些标识符(如fetch)的定义,这对我来说很好。

1 个答案:

答案 0 :(得分:1)

由于这是一个非常深刻的问题,我认为你应该通过询问julia-users给朱莉娅开发者自己一个回答它的机会。

目前,您可以通过将quote块中的整个esc(...)块包裹在esc中来完全规避宏观卫生(不要忘记带走a {{1}}周围{{} 1}}),但我一般会建议反对它 - 那么你就是靠自己。