在Julia宏中评估本地变量

3
我正在编写一个Julia宏,用于接收表达式并将其序列化,以便在其他地方运行。因此,该宏会接收表达式并替换所有符号为变量。然后将表达式序列化并在其他地方进行评估。
我的问题与评估不在全局范围内的变量有关。也就是说,以下内容可以正常工作,因为a在全局范围内定义:
macro myprintf(ex)
    print(eval(ex))
end

# works 
a = 2
@myprintf a

当宏在新会话中运行时,由于它无法看到局部循环作用域中定义的a,因此会引发错误:

macro myprintf(ex)
    print(eval(ex))
end

# UndefVarError: a not defined
for j=1:3
    a = 2
    @myprintf a
end

如果a在局部作用域中定义,比如在循环中,有没有办法在宏内部访问它?我知道我可能没有按照宏的意图使用它,因为我在宏定义内部调用了eval。 总体思路是,我想序列化传递给宏的表达式,并在以后的某个地方(例如不同的Julia会话)中评估它。

1个回答

1

eval 只能在全局作用域中使用。但我不认为将变量替换为求值后的字面量有多大用处,结果只是一个由字面量组成的表达式。

无论如何,解决原始问题的另一种方法可能是类似于 R 的方法:在调用它的地方,利用表达式及其环境构建thunks。要在Julia中重新创建它,您需要:

  1. 找出表达式中的自由变量
  2. 创建其值的环境数据结构
  3. 将原始表达式包装在闭包中,使其从环境中获取本地变量
  4. 将所有内容放入新对象中

例如:

for j=1:3
    a = 2
    @saveexpr a + 2
end

应该扩展为类似以下内容:
for j=1:3
    a = 2
    SerializedExpr(
      (; a),
      function (env)
          let (a,) = env
              a + 2
          end
      end,
      :(a + 2))
end

如果在您的用例中无法保存关闭,则我猜您要么必须实现自己的评估器,要么使用类似于JuliaInterpreter.jl的东西。

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