上接语言基础,就release-1.1来看,个人感觉这门语言和自己心中的理想国相距较远。这门语言因为受众不仅仅是程序员有很多让人迷惑的设计,但是奇怪的是它的语法等表象设计虽然暗示这不是专门为程序员准备的,内在的却提供了大量非程序员不可用的高级特性,库。
乘着热情还在,我挑一些有趣的东西再写写。
元编程
元编程即对代码进行处理的代码,可以使用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)Exprjulia> ast = quote x=1 y=2 res=x+y endquote #= REPL[21]:2 =# x = 1 #= REPL[21]:3 =# y = 2 #= REPL[21]:4 =# res = x + yendjulia> 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:topleveljulia> multiStmt.args6-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:strjulia> typeof(:str)Symboljulia> Symbol("str2"):str2julia> typeof(Symbol("str2"))==typeof(:str)true
最后我们使用eval()
h函数传入Expr类型参数求值:
julia> eval(ast)3julia> eval(multiStmt)21
这就给了我们一种使用代码操纵代码的方式:
julia> add = Expr(:call,:-,:a,:b):(a - b)julia> a = 11julia> b= 22julia> 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 Andrewjulia> println(@hello "Andrew")hello,my name is Andrew
使用宏可以像函数一样加括号也可以宏名 参数1 参数2 ...
println(@hello "Andrew")
会被替换为println("hello, my name is Andrew")
,可以使用@macroexpand
获得展开后的结果 julia> @macroexpand println(@hello "Andrew"):(println("hello,my name is Andrew"))