Julia體驗 語言特性 超程式設計,巨集
阿新 • • 發佈:2019-02-18
上接語言基礎,個人感覺這門語言和自己心中的理想國相距較遠,乘著熱情還在,我挑一些有趣的東西再寫寫。
超程式設計
超程式設計即對程式碼進行處理的程式碼,可以使用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"))