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

标签 julia

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()

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

其次,有没有一种方法可以在没有全局关键字的情况下在引用中定义 bar 和 bar2,并且在执行宏后仍然可用?

我想要 bar2 符号的动机是我可以用这种语法指定返回类型。

global bar3()::Void = begin end

不允许语法。

最佳答案

在 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

此功能称为 macro hygiene并避免在调用站点与变量发生意外冲突。

要避免这种行为,必须使用 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

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

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

有关详细信息,我建议阅读 corresponding section在手册中。

关于具有全局功能的 Julia 代码生成,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44268211/

相关文章:

regex - 如何在 Julia 中编写包含加号的正则表达式?

arrays - 矢量字符串替换为 Julia

julia - 如何使用julia的PackageCompiler搭建PlotStats的快速启动环境?

julia - Julia 相当于 R 的副本和代表什么?

matrix - 如何将矩阵中的偶数放入 Julia 中的单独向量中?

json - 在 Julia 中是否值得对 `JSON.parsefile` 返回的字典进行类型缩小

julia - 使用 julia 读取文本文件的最快方法是什么

csv - Julia - 重写 CSV

julia - 在 Julia 中广播数组和求和,无需临时矩阵分配

julia - 在 Julia 中创建长度为 n 的向量