为什么Julia宏名字混淆中变量可以以#开头?

5

我是一个刚开始学习宏的人,对于变量名称如何以#开头仍然感到困惑,但宏似乎确实可以成功地实现这一点。例如,如果我想将一个变量设置为4:

macro testMacro(sym)
  esym = esc(sym)
  quote
    temp = 4
    $esym = temp
    return
  end
end

那么

julia> macroexpand(:(@testMacro α))
quote  # none, line 4:
    #132#temp = 4 # line 5:
    α = #132#temp # line 6:
    return
end

julia> @testMacro α

julia> α
4

请注意,临时变量被命名为#132#temp,我理解它将像这样在REPL中评估。然而,这似乎是不可能的,因为整行现在在技术上应该是一个注释。

如果我查看宏内的第一个表达式,我会得到一些无法复制的东西。

julia> macroexpand(:(@testMacro α)).args[2]
:(#132#temp = 4)

julia> ex = :(#132#temp = 4)


ERROR: syntax: incomplete: premature end of input

这里发生了什么?我有两个基本问题。1.) 如果可能的话,如何定义以#开头的变量(甚至在表达式中)?2.) 假设存在这样的变量,julia如何不将其视为注释?

1个回答

12

这里在进行什么操作?

这里的名称修改是为了保持宏卫生,以使在宏内定义的名称不会与环境中的其他名称发生冲突。(可以使用esc覆盖此行为)

1.) 如果可能的话,我如何定义一个以#开头的变量(即使在表达式中)?

我不确定你为什么想要这样做,因为访问这个变量会很麻烦。但是这是可能的:

julia> eval(Expr(:(=), symbol("#s"), 1))
1

julia> whos()
#s                            Int64
Base                          Module
Core                          Module
LastMain                      Module
Main                          Module
ans                           Int64

julia> eval(symbol("#s"))
1

2.) 如果假设这样的变量存在,Julia 是如何避免将其视为注释的?

注释在解析器级别被忽略,因此系统的其他部分实际上永远不会看到它们。正如上面所示,一个 Symbol 可以从包含 # 的任意字符串中创建,这正是宏代码在内部执行的操作。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接