`Julia宏中的UndervarError`

`Julia宏中的UndervarError`,julia,metaprogramming,Julia,Metaprogramming,帮助我调试(以及更好地理解Julia宏 我试图定义一个简单的宏,用它来查找代码块 “进入”和“离开”通知。以下是我到目前为止得出的结论: macro dbg(block_title, expr) quote title = $block_title println("Entering $title") $expr println("Leaving $title") end end 乍一看,它似乎符合我的要求: j

帮助我调试(以及更好地理解Julia宏 我试图定义一个简单的宏,用它来查找代码块 “进入”和“离开”通知。以下是我到目前为止得出的结论:

macro dbg(block_title, expr)
    quote
        title = $block_title
        println("Entering $title")
        $expr
        println("Leaving  $title")
    end
end
乍一看,它似乎符合我的要求:

julia> @dbg "first test" begin
           println("does it work?")
       end
Entering first test
does it work?
Leaving  first test
然而,一旦涉及到变量,就什么都不起作用了,我得到了答案
UndefVarError
用于所有变量访问。看起来像 宏内部和外部的作用域是不同的:

julia> @dbg "initialization" begin
           foo = rand(10)
           println("foo = ", foo)
       end
Entering initialization
foo = [0.9178016919066918, 0.6004694971609528, 0.5294790810682284, 0.04208146400653634, 0.09271603217172952, 0.2809448815925, 0.68236281020963, 0.8313876607106496, 0.07484095574744898, 0.14099531301938573]
Leaving  initialization

julia> foo
ERROR: UndefVarError: foo not defined

我做错了什么?

简言之,你错过了和的概念 特别是 功能

尽管文档的这一部分对于任何想要开发自己的宏的人来说都是很好的读物,但让我们试着在这个特定示例中扩展一下宏卫生学的功能,以及如何解决问题

调试宏的一种有用方法是 :

#=>中的所有注释放在一边=#标记,我们几乎可以看到我们需要的代码
想要得到:用户代码块被打印语句包围
“进入”和“离开”通知。然而,有一个值得注意的问题
差异:变量名如
foo
title
已被删除 替换为外观怪异的名称,如
var“#33#foo”
var“#32#title”
。这就是所谓的 “”并且它有助于避免两个用户之间可能发生的冲突 宏本身中使用的变量(如本例中的
title
),以及代码块中使用的变量 作为宏的参数提供(如这里的
foo
)。(举例来说,想想什么 如果在定义
标题
变量的代码块上使用
@dbg
,则会发生这种情况。)

Julia犯了谨慎的错误,并以这种方式保护所有变量 出现在宏中。如果要对选定的零部件禁用此功能 表达式,您可以将这些子表达式包装在 作用例如,在您的示例中,您应该转义用户提供的 表达方式:

macro dbg(block_title, expr)
    quote
        title = $block_title
        println("Entering $title")
        $(esc(expr))
        println("Leaving  $title")
    end
end
现在事情应该像他们希望的那样:

julia> @dbg "initialization" begin
           foo = rand(10)
           println("foo = ", foo)
       end
Entering initialization
foo = [0.2955287439482881, 0.8989053281359838, 0.27751430906108343, 0.4920810199867245, 0.7633806735297282, 0.34535540650110597, 0.7099231627594489, 0.39978144801175564, 0.9104888704503833, 0.1983996781283539]
Leaving  initialization

julia> @dbg "computation" begin
           foo .+= 1
       end
Entering computation
Leaving  computation

julia> foo
10-element Array{Float64,1}:
 1.295528743948288 
 1.8989053281359838
 1.2775143090610834
 1.4920810199867245
 1.7633806735297282
 1.345355406501106 
 1.709923162759449 
 1.3997814480117556
 1.9104888704503833
 1.198399678128354 

简而言之,您缺少和的概念 特别是 功能

尽管文档的这一部分对于任何想要开发自己的宏的人来说都是很好的读物,但让我们试着在这个特定示例中扩展一下宏卫生学的功能,以及如何解决问题

调试宏的一种有用方法是 :

#=>中的所有注释放在一边=#标记,我们几乎可以看到我们需要的代码
想要得到:用户代码块被打印语句包围
“进入”和“离开”通知。然而,有一个值得注意的问题
差异:变量名如
foo
title
已被删除 替换为外观怪异的名称,如
var“#33#foo”
var“#32#title”
。这就是所谓的 “”并且它有助于避免两个用户之间可能发生的冲突 宏本身中使用的变量(如本例中的
title
),以及代码块中使用的变量 作为宏的参数提供(如这里的
foo
)。(举例来说,想想什么 如果在定义
标题
变量的代码块上使用
@dbg
,则会发生这种情况。)

Julia犯了谨慎的错误,并以这种方式保护所有变量 出现在宏中。如果要对选定的零部件禁用此功能 表达式,您可以将这些子表达式包装在 作用例如,在您的示例中,您应该转义用户提供的 表达方式:

macro dbg(block_title, expr)
    quote
        title = $block_title
        println("Entering $title")
        $(esc(expr))
        println("Leaving  $title")
    end
end
现在事情应该像他们希望的那样:

julia> @dbg "initialization" begin
           foo = rand(10)
           println("foo = ", foo)
       end
Entering initialization
foo = [0.2955287439482881, 0.8989053281359838, 0.27751430906108343, 0.4920810199867245, 0.7633806735297282, 0.34535540650110597, 0.7099231627594489, 0.39978144801175564, 0.9104888704503833, 0.1983996781283539]
Leaving  initialization

julia> @dbg "computation" begin
           foo .+= 1
       end
Entering computation
Leaving  computation

julia> foo
10-element Array{Float64,1}:
 1.295528743948288 
 1.8989053281359838
 1.2775143090610834
 1.4920810199867245
 1.7633806735297282
 1.345355406501106 
 1.709923162759449 
 1.3997814480117556
 1.9104888704503833
 1.198399678128354