gpt4 book ai didi

macros - 如何使结构的宏生成在结构上匹配的函数方法?

转载 作者:行者123 更新时间:2023-12-01 23:40:44 27 4
gpt4 key购买 nike

请原谅标题中任何混淆的术语,但想象一下我想要一个小宏来标记我创建的结构可用于某些邪恶目的。我写了这个小模块:

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/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com