Macros 朱莉娅:宏、表达式和Meta.parse

Macros 朱莉娅:宏、表达式和Meta.parse,macros,julia,metaprogramming,Macros,Julia,Metaprogramming,以下所有代码行都是Julia表达式: x = 10 1 + 1 println("hi") 如果要将表达式传递给宏,它的工作方式如下。宏foo仅返回给定的表达式,该表达式将被执行: macro foo(ex) return ex end @foo println("yes") # prints yes x = @foo 1+1 println(x) # prints 2 如果要将字符串转换为表达式,可以使用Meta.parse: string = "1+1" expr = Meta.

以下所有代码行都是Julia表达式:

x = 10
1 + 1
println("hi")
如果要将表达式传递给宏,它的工作方式如下。宏foo仅返回给定的表达式,该表达式将被执行:

macro foo(ex)
  return ex
end

@foo println("yes") # prints yes

x = @foo 1+1
println(x) # prints 2
如果要将字符串转换为表达式,可以使用Meta.parse:

string = "1+1"
expr = Meta.parse(string)
x = @foo expr
println(x) # prints 1 + 1
但是,很明显,宏将expr视为一个符号。我这里出了什么错

提前谢谢

宏卫生很重要宏必须确保它们在返回表达式中引入的变量不会意外地与它们展开到的周围代码中的现有变量冲突。这本书里有一个章节。最简单的方法是展示一个简单的案例:

macro foo(x)
    return :($x)
end
在REPL中输入普通表达式时,将立即对其求值。若要禁止该计算,请在表达式周围加上:

因此,Meta.parse将适当的字符串转换为表达式。如果对结果求值,将对表达式求值。请注意,打印简单表达式会删除外部表达式:

通常,宏用于在表达式的常规求值之前操作事物;它们主要是语法转换。宏是在编译/计算/执行其他源代码之前执行的

与其寻找一个对字符串求值的宏,就好像它是在REPL中直接键入的,而不带引号,不如使用此函数

evalstr(x::AbstractString) = eval(Meta.parse(x))
虽然我不推荐使用下一个宏,但了解该技术还是很好的。 名为_str的宏的使用方式如下:

p、 不要将基函数名重新用作变量名,请使用str而不是string

如果有什么问题我还没有解决,请告诉我。

宏卫生很重要。宏必须确保它们在返回表达式中引入的变量不会意外地与它们扩展到的周围代码中的现有变量冲突。这本书里有一个章节。最简单的方法是展示一个简单的案例:

macro foo(x)
    return :($x)
end
在REPL中输入普通表达式时,将立即对其求值。若要禁止该计算,请在表达式周围加上:

因此,Meta.parse将适当的字符串转换为表达式。如果对结果求值,将对表达式求值。请注意,打印简单表达式会删除外部表达式:

通常,宏用于在表达式的常规求值之前操作事物;它们主要是语法转换。宏是在编译/计算/执行其他源代码之前执行的

与其寻找一个对字符串求值的宏,就好像它是在REPL中直接键入的,而不带引号,不如使用此函数

evalstr(x::AbstractString) = eval(Meta.parse(x))
虽然我不推荐使用下一个宏,但了解该技术还是很好的。 名为_str的宏的使用方式如下:

p、 不要将基函数名重新用作变量名,请使用str而不是string


如果有什么问题我还没有解决,请告诉我。

谢谢你,杰弗里,但我还是不确定我是否收到了!把我的问题归结为:表达式1+1和Meta.parse1+1之间有什么区别?因为@foo 1+1和@foo Meta.parse1+1不会给出相同的结果。如果我将printlntypeofex放入宏中,在这两种情况下,它都会打印Expr…hm,ok Expr=Meta.eval1+1@foo-epxr与@foo-Meta不同。eval1+1.Meta.eval确实不是您想要的。eval基本上做了相同的事情,而且更清晰。用它代替。str=1+1;evalstr==str;expr=Meta.parsestr;val=evalexpr;所以@foostr==str@fooexpr==expr@fooval==应该是val。啊,对不起,这是个打字错误!我的意思是:expr=Meta.parse1+1@foo epxr与@foo Meta.parse1+1不同。我不确定我们是否只是出于不同的目的而交谈。我再次尝试更清楚地说明我的问题:我必须对字符串应用什么操作,以便它将被视为与1+1完全相同的普通表达式?谢谢Jeffrey,但我仍然不确定我是否得到了它!把我的问题归结为:表达式1+1和Meta.parse1+1之间有什么区别?因为@foo 1+1和@foo Meta.parse1+1不会给出相同的结果。如果我将printlntypeofex放入宏中,在这两种情况下,它都会打印Expr…hm,ok Expr=Meta.eval1+1@foo-epxr与@foo-Meta不同。eval1+1.Meta.eval确实不是您想要的。eval基本上做了相同的事情,而且更清晰。用它代替。str=1+1;evalstr==str;expr=Meta.parsestr;val=evalexpr;所以@foostr==str@fooexpr==expr@fooval==应该是val。啊,对不起,这是个打字错误!我的意思是:expr=Meta.parse1+1@foo epxr与@foo Meta.parse1+1不同。我不确定我们是否只是出于不同的目的而交谈。我再次尝试更清楚地说明我的问题:我必须对字符串应用什么操作,以便它将被视为与1+1完全相同的普通表达式?
julia> macro eval_str(x)
          :(eval(Meta.parse($x)))
      end

julia> eval"1 + 1"
2