【问题标题】:Injecting variables into a quoted expression将变量注入引用的表达式
【发布时间】:2015-12-02 05:34:18
【问题描述】:

我有一个引用的表达式,比如这个:

ast = quote do
  IO.puts x
end

我希望在表达式中注入一个变量,以便 x 有一个值,并且表达式不会引发 CompileError,因为 x 在这样评估时未定义:

Code.eval_quoted ast, [x: "Hello, world!"]

此 AST 已传递给我,我无法更改生成它的代码。不过,通过后我可以修改 AST。

我想这样做我可以将 AST 转换为类似于这个引用的表达式:

ast = quote do
  x = var!(x)
  IO.puts x
end

尝试此操作后,我的 AST 看起来像这样:

{:__block__, [],
[{:=, [],
  [{:x, [], Elixir}, {:var!, [context: Check.Runner], [{:x, [], Elixir}]}]},
  {{:., [], [{:__aliases__, [alias: false], [:IO]}, :puts]}, [],
  [{:x, [], Check.RunnerTest}]}]}

这不起作用。我认为这可能是由于 var! 的上下文的值不正确。

解决方案:我现在意识到变量的范围不正确,我需要这样的 AST:

{:__block__, [],
[{:=, [],
  [{:x, [], Check.RunnerTest},
    {:var!, [context: Check.Runner], [{:x, [], Check.Runner}]}]},
  {{:., [], [{:__aliases__, [alias: false], [:IO]}, :puts]}, [],
  [{:x, [], Check.RunnerTest}]}]}

【问题讨论】:

    标签: macros metaprogramming elixir hygiene


    【解决方案1】:

    您的代码应该可以正常工作。事实上,你已经写了:

    ast = quote do
      x = var!(x)
      IO.puts x
    end
    

    但是您显示了其他代码的 AST,其中您将 1 分配给了 var!(x)。也就是说,上面的代码没有任何问题。

    【讨论】:

    • 啊,我贴错了。阅读下面的评论后,我意识到由于设置了不正确的上下文,我的变量范围不正确。我已经更新了上面的问题。
    • 现在您更新了问题,问题本身是错误的(示例确实有效)并且这个答案有些错误。 :P
    • 是的。这有点乱。现在可能最好走开!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-01-17
    相关资源
    最近更新 更多