【问题标题】:Using Julia's external command interpolation inside macros?在宏中使用 Julia 的外部命令插值?
【发布时间】:2014-10-31 17:43:28
【问题描述】:

我一直在尝试编写一个 Julia 宏,它接受 Cmd 对象并在循环中运行它们。问题是我想在命令中使用局部循环变量进行插值。我会编写一个函数并使用 eval(),但 eval() 使用全局范围,因此看不到局部循环变量。

下面是一个简单的例子,演示了字符串插值是如何工作的,但是命令插值失败:

macro runcmd(cmdExpr)
    quote
        for i in 1:2
            println("i: $i")
            run($cmdExpr)
        end
    end
end
@runcmd(`echo $i`)

输出

i: 1
ERROR: i not defined
 in anonymous at none:5

如果我展开我得到的宏

quote  # none, line 3:
    for #261#i = 1:2 # line 4:
        println("i: $#261#i") # line 5:
        run(Base.cmd_gen((("echo",),(i,))))
    end
end

我猜测 cmd_gen 参数对 i 的引用中缺少的 #261# 部分与问题有关,但我不确定。

【问题讨论】:

  • 只是好奇......您想要这样做的用例和/或动机是什么?
  • 您是否阅读了手册的宏观卫生部分? quote 中的 i 在生成的代码中不会像 i 一样出现。
  • @rickhg12hs 我正在运行许多 shell 命令,每个命令都在一组可能的数据集上,并且这些命令需要引用数据集名称。
  • @IainDunning 谢谢!我阅读了宏部分,然后略读了卫生部分,因为当时我不明白它是如何应用的。现在我明白发生了什么。
  • 很微妙!我敢肯定,欢迎您提出任何手动改进建议。

标签: julia


【解决方案1】:

您说得对,问题是因为索引#261#i 与echo $i 中对它的引用不匹配。解决此问题的一种简单方法是转义索引中使用的i:

macro runcmd(cmdExpr)
    quote
        for $(esc(:i)) in 1:2
            println("i: $i")
            run($cmdExpr)
        end
    end
end

然后我们得到:

julia> @runcmd(`echo $i`)
i: 1
1
i: 2
2

Julia 的metaprogramming documentation 有更多讨论。

【讨论】:

  • 我现在看到#261#i 意味着宏扩展器将 i 设为局部变量以防止命名空间冲突。感谢您的回答和链接!
猜你喜欢
  • 1970-01-01
  • 2017-01-22
  • 2012-05-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-09-30
相关资源
最近更新 更多