版權說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權,請進行舉報或認領
文檔簡介
四、Julia語言進階4.3元編程元編程是指編程語言可以通過編寫程序生成滿足用戶需求的程序。Julia語言把代碼表示為語言中的數(shù)據(jù)結構,支持元編程。在程序運行時和編譯時,元編程可以修改對象和添加方法等,使得編程更靈活。元編程的程序表示創(chuàng)建表達式并求值生成代碼利用宏實現(xiàn)元編程生成函數(shù)運行時反射四、Julia語言進階4.3.1程序表示Julia代碼的執(zhí)行過程分為兩個階段:第一將字符串解析為抽象語法樹結構解析原始代碼階段和第二執(zhí)行已解析代碼階段。利用元編程可以在代碼執(zhí)行之前,對已解析的代碼進行修改。修改后的結果類型為Expr類型。julia>str1="1+2""1+2"julia>expr1=Meta.parse(str1) #使用Meta.parse解析字符串:(1+2)julia>typeof(expr1) #解析輸出的結果類型為表達式類型Expr四、Julia語言進階4.3.1程序表示Expr類型包含符號對象和表達式,表達式可能包含符號、其它表達式或字面量。julia>fieldnames(typeof(expr1))(:head,:args)julia>s1=expr1.head#標識表達式類型的Symbol:calljulia>typeof(s1)Symboljulia>expr1.args#表達式參數(shù)數(shù)組3-elementVector{Any}::+12四、Julia語言進階4.3.1程序表示Expr類型包含符號對象和表達式,表達式可能包含符號、其它表達式或字面量。julia>typeof(expr1.args[1])#判斷表達式參數(shù)類型Symboljulia>typeof(expr1.args[2])Int64julia>typeof(expr1.args[3])Int64julia>dump(expr1)#使用dump函數(shù)查看Expr對象Exprhead:Symbolcallargs:Array{Any}((3,))1:Symbol+2:Int6413:Int642四、Julia語言進階4.3.1程序表示使用Expr函數(shù)構造表達式,與parse所解析的表達式等價。julia>expr1=Meta.parse(str1) :(1+2)julia>expr2=Expr(:call,:+,1,2):(1+2)julia>expr1==expr2truejulia>s2=:sym1:sym1julia>typeof(s2)Symboljulia>s2==Symbol("sym1")true使用使用:構造與使用Symbol函數(shù)構造等價。四、Julia語言進階4.3.1程序表示使用Symbol函數(shù)將多個字符串聯(lián)。julia>Symbol("MWORKS","_","Syslab"):MWORKS_Syslabjulia>Symbol(:MWORKS,"_","Syslab"):MWORKS_Syslabjulia>:MWORKS_Syslab:MWORKS_Syslabjulia>s3=Symbol("MWORKS",".","Syslab")Symbol("MWORKS.Syslab")julia>dump(s3)SymbolMWORKS.Syslab標識符“_”串聯(lián)字符串無效標識符“.”需要用雙引號。四、Julia語言進階4.3.2表達式與求值通過符號:構造表達式,稱為引用。復雜表達式通過引用符號、其它表達式和字面量值構造。julia>expr3=:(a+b/c-3):((a+b/c)-3)julia>expr3==Expr(:call,:-,Expr(:call,:+,:a,Expr(:call,:/,:b,:c)),3)true用符號:構造復雜表達式比Expr函數(shù)構造簡單。四、Julia語言進階4.3.2表達式與求值使用符號$將數(shù)插入表達式,稱為插值。未被引用的表達式不能被插值。julia>c=11julia>expr4=:(a+b/$c-3)#向被引用表達式插值:((a+b/1)-3)julia>a+b/$c-3#向未被引用表達式插值ERROR:syntax:"$"expressionoutsidequotearoundREPL[61]:1Stacktrace:[1]top-levelscope@REPL[61]:1四、Julia語言進階4.3.2表達式與求值將多個表達式變成另一個表達式的參數(shù)時,可以使用$(name…)構造。例如,將數(shù)組中的表達式插入到函數(shù)f的輸入?yún)?shù)位置julia>arry1=[:a,:b,:c,:d];julia>:(f(1,$(arry1:(f(1,a,b,c,d))四、Julia語言進階4.3.2表達式與求值引用多個表達式,用關鍵詞quote構造新的表達式。julia>expr5=quotex=1y=4x-yendquote#=REPL[57]:2=#x=1#=REPL[57]:3=#y=4#=REPL[57]:4=#x-yendjulia>expr6=quotequotex=1y=4x-yendendquote#=REPL[79]:2=#$(Expr(:quote,quote#=REPL[79]:3=#x=1#=REPL[79]:4=#y=4#=REPL[79]:5=#x-yend))endqutoe支持嵌套引用四、Julia語言進階4.3.2表達式與求值用關鍵詞eval求取表達式的值。julia>expr7=:(2-9):(2-9)julia>eval(expr7)-7julia>expr8=:(a*b)#含未賦值變量的表達式:(a*b)julia>eval(expr8)ERROR:UndefVarError:bnotdefinedjulia>a=6;b=3;#在全局作用域內(nèi)對表達式的變量賦值julia>eval(expr8)18julia>a=3;julia>eval(expr8)9注意:未賦值的表達式不能求值。四、Julia語言進階4.3.2表達式與求值先賦值的變量,用Expr構造表達式后,變量值不可修改。julia>a9=8;julia>expr9=Expr(:call,:-,a9,:b9):(8-b9)julia>a9=0;b9=3;julia>eval(expr9)5julia>b9=4;eval(expr9)4a9值在構造表達式之前賦值修改a9值表達式的值未改變未賦值的變量值可修改四、Julia語言進階4.3.3代碼生成當需要編寫重復的代碼、樣板形式代碼時,可以使用元編程大幅度提升編程效率。在Julia語言中,使用插值和求值來實現(xiàn)代碼生成。julia>op=:+;julia>quote($op)(a,b,c)=($op)(($op)(a,b),c)endquote#=REPL[28]:2=#a+b+c=begin#=REPL[28]:2=#(a+b)+cendendjulia>eval(quote($op)(a,b,c)=($op)(($op)(a,b),c)end)+(genericfunctionwith1method)用符號:和和插值實現(xiàn)連加用關鍵詞引用和插值實現(xiàn)連加四、Julia語言進階4.3.3代碼生成當需要編寫重復的代碼、樣板形式代碼時,可以使用元編程大幅度提升編程效率。在Julia語言中,使用插值和求值來實現(xiàn)代碼生成。julia>forop=(:+,:-,:*,:/,:&&,:||)#需要多個不同的操作時,用for循環(huán)。eval(quote($op)(a,b,c)=($op)(($op)(a,b),c)end)end
julia>forop=(:+,:-,:*,:/,:&&,:||)#使用符號:構造,程序更簡潔。eval(:(($op)(a,b,c)=($op)(($op)(a,b),c)))endjulia>forop=(:+,:-,:*,:/,:&&,:||)#使用@eval宏。@eval($op)(a,b,c)=($op)(($op)(a,b),c)end四、Julia語言進階4.3.4宏宏可以實現(xiàn)表達式的替換,不需要使用eval就可以返回表達式。用關鍵詞macro構造宏,聲明語法:macromac_name(para_name)…end構造宏,mac_name為宏名稱,para_name為輸入?yún)?shù)。julia>macromac1()#構造無輸入?yún)?shù)的宏。return:(println("MWORKS.Syslab"))end@mac1(macrowith1method)julia>macromac2(str)#構造有輸入?yún)?shù)的宏。return:(println("MWORKS.Syslabbasedon",$str))end@mac2(macrowith1method)四、Julia語言進階4.3.4宏調(diào)用宏的2種方法@mac_namepara_name1para_name2…#使用空格分開參數(shù)名稱。@mac_name(para_name1,para_name2…)#使用逗號分開參數(shù)名稱。julia>macromac3(para1,para2,para3)return:(println($para1,$para2,$para3))end@mac3(macrowith1method)julia>@mac3"MWORKS.Syslab"2023"a"MWORKS.Syslab2023ajulia>@mac3("MWORKS.Syslab",2023,"a")MWORKS.Syslab2023a注意:宏名與()之間不能有空格四、Julia語言進階4.3.4宏數(shù)組做參數(shù)時,先將數(shù)組代入宏計算并返回值,再執(zhí)行剩余表達式。julia>macromac4(para)return:($para.+1)end@mac4(macrowith1method)julia>@mac4[12]*2#第一種調(diào)用方式,宏名和數(shù)組之間沒有空格。1×2Matrix{Int64}:46#先計算[12].+1,再計算返回值*2。julia>@mac4([12])*2#第二種調(diào)用方式,宏名和括號之間沒有空格。1×2Matrix{Int64}:46#先計算[12].+1,再計算返回值*2。julia>@mac4[12]*2#先計算[12]*2,再計算返回值.+1。1×2Matrix{Int64}:35注意:有空格時,整體做為宏的輸入?yún)?shù)。四、Julia語言進階4.3.4宏使用show函數(shù)可導出宏的參數(shù),但show函數(shù)必須在宏內(nèi)部。julia>macromac5(para)show(para)end@mac5(macrowith1method)julia>@mac5(x):xjulia>@mac5(2*3):(2*3)四、Julia語言進階4.3.4宏衛(wèi)生宏,又稱為干凈宏,可避免展開后的表達式中變量與全局變量名稱沖突的問題。宏內(nèi)部只可使用關鍵詞local聲明局部變量,不能使用eval,可使用關鍵詞esc轉(zhuǎn)義以避免宏變大。例如計算時間的宏:macromac7(ex)returnquotelocalt0=time_ns()localval=$(esc(ex))localt1=time_ns()println("elapsedtime:",(t1-t0)/1e9,"seconds")valendend四、Julia語言進階4.3.4宏宏的派發(fā),同一個宏可以有多個方法,調(diào)用宏時可以實現(xiàn)多重派發(fā)。julia>macromac8(para1)println("FirstMethod")return:(println($para1))end@mac8(macrowith1methods)julia>macromac8(para1,para2)println("SecondMethod")return:(println($para1,$para2))end@mac8(macrowith2methods)julia>@mac8("Syslab")FirstMethodSyslabjulia>@mac8(9)FirstMethod9julia>@mac8("MWORKS","Syslab")SecondMethodMWORKSSyslabSyslab程序運行結果為:四、Julia語言進階4.3.5非標準字符串字面量以標識符為前綴的字符串字面量被稱為非標準字符串字面量。以r為前綴的正則表達式,并非是字符串。例如:r"\\Qx\\E"調(diào)用宏@r_str創(chuàng)建正則表達式julia>@r_str("\\Qx\\E")r"\Qx\E"julia>x=3;julia>@r_str("\\Q$x\\E")ERROR:MethodError:nomethodmatchingRegex(::Expr)julia>Regex("\\Q$x\\E")r"\Q3\E"不能利用宏直接插值,用Regex函數(shù)實現(xiàn)插值并構造正則表達式。四、Julia語言進階4.3.6生成函數(shù)宏@generated定義生成函數(shù)。生成函數(shù)與普通函數(shù)不同,調(diào)用生成函數(shù)返回的是表達式,普通函數(shù)返回的是值。定義和調(diào)用生成函數(shù)julia>@generatedfunctionfun1(x)return:(x*x)endfun1(genericfunctionwith1method)julia>fun1(5)25julia>fun1("Syslab")"SyslabSyslab"在普通函數(shù)關鍵詞function前加@generated宏。四、Julia語言進階4.3.6生成函數(shù)向普通函數(shù)中添加新方法julia>fun2(x)="MWORKS";julia>@generatedfun3(x)=fun2(x);#不允許向fun2()添加新方法julia>@generatedfun4(x)=:(fun2(x));#允許向fun2()添加新方法julia>a1=fun3(1)"MWORKS"julia>b1=fun4(1)"MWORKS"julia>fun2(x::Int64)="Syslab"#添加新方法fun2(genericfunctionwith2methods)julia>a2=fun3(1)"MWORKS"julia>b2=fun4(1)"Syslab"四、Julia語言進階4.3.7運行時反射Julia的元編程支持運行時反射,例如可以查看類型字段、類型的類型、類型的亞型,還可查看函數(shù)所包含的方法和函數(shù)內(nèi)部檢查。julia>structMytypex::Int64yendjulia>typeof(Mytype)#查看Mytype的類型DataTypejulia>fieldnames(Mytype)#查看類型字段(:x,:y)julia>Mytype.types#字段類型儲存在types變量中svec(Int64,Any)查看類型字段和類型的類型julia>subtypes(AbstractFloat)6-elementVector{An
溫馨提示
- 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預覽,若沒有圖紙預覽就沒有圖紙。
- 4. 未經(jīng)權益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負責。
- 6. 下載文件中如有侵權或不適當內(nèi)容,請與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
最新文檔
- 企業(yè)并購招投標委托協(xié)議
- 咨詢服務廣告施工合同文本格式
- 校園廣播系統(tǒng)升級:學校施工合同
- 農(nóng)家樂廚師長錄用合同
- 商業(yè)街區(qū)租賃合同模板
- 2025高壓電安裝合同范本
- 城市景觀工程土建施工合同范本
- 2025代理汽車飾品經(jīng)銷合同
- 城市道路改造混凝土路面施工合同
- 校門安全員招聘協(xié)議
- 2025學年人教新版英語七下Unit1隨堂小測
- 2024年汽車抵押貸款提前還款合同范例3篇
- 《項目溝通管理培訓》課件
- 2024版教育培訓機構店面轉(zhuǎn)讓及課程合作協(xié)議3篇
- GB/T 44916-2024船舶和海上技術船用超低溫閘閥設計與試驗要求
- 《BL急性腎盂腎炎》課件
- 夢想在路上 高二上學期期中家長會
- 2024-2025學年上學期上海小學語文六年級期末模擬試卷
- 【MOOC】中國文化概論-華南師范大學 中國大學慕課MOOC答案
- 2024-2025學年二年級數(shù)學上冊期末樂考非紙筆測試題(二 )(蘇教版)
- 2025年蛇年年會匯報年終總結大會模板
評論
0/150
提交評論