作者热门文章
- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
请原谅标题中任何混淆的术语,但想象一下我想要一个小宏来标记我创建的结构可用于某些邪恶目的。我写了这个小模块:
module Usable
export @usable, isusable
isusable(::Type{T}) where T = false
macro usable(expr::Expr)
name = expr.args[2]
return quote
$expr
Usable.isusable(::Type{$name}) = true # This in't working
end
end
end
但是,尝试使用我的宏
julia> include("Usable.jl")
Main.Usable
julia> using Main.Usable
julia> @usable struct Foo
bar::String
end
结果
ERROR: UndefVarError: Foo not defined
结构显然定义得很好
julia> Foo("soup")
Foo("soup")
所以看来定义比我预期的要早。我显然遗漏了什么,但我不知道是什么。
最佳答案
始终查看宏的输出:
julia> @macroexpand @usable struct Foo
bar::String
end
quote
#= REPL[1]:11 =#
struct Foo
#= REPL[4]:2 =#
bar::Main.Usable.String
end
#= REPL[1]:13 =#
(Main.Usable.Usable).isusable(::Main.Usable.Type{Main.Usable.Foo}) = begin
#= REPL[1]:13 =#
true
end
end
问题是宏输出在它定义的模块内扩展,这混淆了名称的含义。在这种情况下,我们希望 Foo
引用定义它的 namespace :
quote
#= REPL[1]:11 =#
struct Foo
#= REPL[10]:2 =#
bar::String
end
#= REPL[1]:13 =#
Usable.isusable(::Type{Foo}) = begin
#= REPL[1]:13 =#
true
end
end
实际上很简单——只需转义输出即可:
macro usable(expr::Expr)
name = expr.args[2]
return esc(quote
$expr
$Usable.isusable(::Type{$name}) = true
end)
end
但是请再次阅读宏文档。 esc
非常复杂,您不想盲目地将它应用于您编写的所有内容。
另一件事(我希望做对)是拼接模块本身 -- $Usable
-- 而不是按名称引用它。否则,如果您在外部重命名模块名称,您可能会遇到问题。
关于macros - 如何使结构的宏生成在结构上匹配的函数方法?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/65002459/
我是一名优秀的程序员,十分优秀!