Julia体验 语言特性 元编程,宏

上接语言基础,个人感觉这门语言和自己心中的理想国相距较远,乘着热情还在,我挑一些有趣的东西再写写。

元编程

元编程即对代码进行处理的代码,可以使用Meta.parse()解析出参数代码的类AST表示,也可以使用quote ... end简化:

julia> multiStmt = Meta.parse(raw"a=1;b=2;t=a;a=b;b=t;println(a,b)") :($(Expr(:toplevel, :(a = 1), :(b = 2), :(t = a), :(a = b), :(b = t), :(println(a, b))))) julia> typeof(multiStmt) Expr julia> ast = quote x=1 y=2 res=x+y end quote #= REPL[21]:2 =# x = 1 #= REPL[21]:3 =# y = 2 #= REPL[21]:4 =# res = x + y end julia> typeof(ast) Expr

使用dump()获得更可读的表示:

julia> dump(multiStmt) Expr head: Symbol toplevel args: Array{Any}((6,)) 1: Expr head: Symbol = args: Array{Any}((2,)) 1: Symbol a 2: Int64 1 2: Expr head: Symbol = args: Array{Any}((2,)) 1: Symbol b 2: Int64 2 3: Expr head: Symbol = args: Array{Any}((2,)) 1: Symbol t 2: Symbol a 4: Expr head: Symbol = args: Array{Any}((2,)) 1: Symbol a 2: Symbol b 5: Expr head: Symbol = args: Array{Any}((2,)) 1: Symbol b 2: Symbol t 6: Expr head: Symbol call args: Array{Any}((3,)) 1: Symbol println 2: Symbol a 3: Symbol b

expr有两部分,expr.head表示出这个表达式的类型,expr.args表示出剩余的参数:

julia> multiStmt.head :toplevel julia> multiStmt.args 6-element Array{Any,1}: :(a = 1) :(b = 2) :(t = a) :(a = b) :(b = t) :(println(a, b))

如果我们typeof head会发现,它是一种名为Symbol的类型:

julia> typeof(multiStmt.head) Symbol

Symbol类型可以使用:name进行定义,也可以使用Symbol类型的构造创建:

julia> :str :str julia> typeof(:str) Symbol julia> Symbol("str2") :str2 julia> typeof(Symbol("str2"))==typeof(:str) true

最后我们使用eval()h函数传入Expr类型参数求值:

julia> eval(ast) 3 julia> eval(multiStmt) 21

这就给了我们一种使用代码操纵代码的方式:

julia> add = Expr(:call,:-,:a,:b) :(a - b) julia> a = 1 1 julia> b= 2 2 julia> eval(add) -1 宏

Julia的宏由macro ... end定义

julia> macro hello(name) return "hello,my name is "*name end @hello (macro with 1 method) julia> println(@hello("Andrew")) hello,my name is Andrew julia> println(@hello "Andrew") hello,my name is Andrew

使用宏可以像函数一样加括号也可以宏名 参数1 参数2 ...
类似C/C++的宏的概念,Julia的宏也是实施的替换操作
所以上述println(@hello "Andrew")会被替换为println("hello, my name is Andrew"),可以使用@macroexpand获得展开后的结果

julia> @macroexpand println(@hello "Andrew") :(println("hello,my name is Andrew"))

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/wssffy.html