具有全局功能的Julia代码生成

Noz*_*rum 3 julia

朱莉娅0.5.1

我想在引用中创建一个函数,可以在使用指定的宏之后使用.这是我的意思的一个例子

macro wat()
  quote
    type Foo end
    global bar() = begin end
    global function bar2()
    end
    type Baaz end
  end
end

@wat
Foo()
Baaz()
bar()
bar2()
Run Code Online (Sandbox Code Playgroud)

现在当我运行它时,最后一行崩溃,因为bar2未定义.我不明白为什么因为在我的理解中bar()和bar2()应该相等而bar只是bar2的语法糖.但他们显然不平等,我不明白为什么一个有效,另一个无效.

其次有没有一种方法可以在没有global-keyword的情况下在引号内定义bar和bar2,并且在执行宏之后仍然可用?

我想要bar2表示法的动机是我可以用这种语法指定一个返回类型.

global bar3()::Void = begin end
Run Code Online (Sandbox Code Playgroud)

不允许使用语法.

tim*_*tim 5

在返回的Julia宏表达式中,局部变量的名称将替换为唯一符号:

julia> macro foo()
        quote
            x = 1
            global y = 2
        end
    end
@foo (macro with 1 method)

julia> macroexpand(:(@foo))
quote  # REPL[1], line 4:
    #1#x = 1
    global y = 2
end
Run Code Online (Sandbox Code Playgroud)

此功能称为宏观卫生,可避免在呼叫站点与变量发生意外冲突.

要逃避此行为,必须使用esc:

julia> macro bar()
                quote
                    x = 1
                end |> esc
            end
@bar (macro with 1 method)

julia> macroexpand(:(@bar))
quote  # REPL[1], line 3:
    x = 1
end
Run Code Online (Sandbox Code Playgroud)

通常,人们不想逃避整个返回的表达式,而只是它的特定部分:

julia> macro myshow(expr)
        quote
            x = $(esc(expr))
            println($(string(expr)), " = ", x)
            x
        end
    end
@myshow (macro with 1 method)

julia> x = pi/2
1.5707963267948966

julia> macroexpand(:(@myshow sin(x)))
quote  # REPL[1], line 3:
    #1#x = sin(x) # REPL[1], line 4:
    (Main.println)("sin(x)", " = ", #1#x) # REPL[1], line 5:
    #1#x
end

julia> @myshow sin(x)
sin(x) = 1.0
1.0

julia> x
1.5707963267948966
Run Code Online (Sandbox Code Playgroud)

有关详细信息,建议您阅读手册中的相应部分.