科学计算语言Julia及MWORKS实践 课件 15-元编程_第1页
科学计算语言Julia及MWORKS实践 课件 15-元编程_第2页
科学计算语言Julia及MWORKS实践 课件 15-元编程_第3页
科学计算语言Julia及MWORKS实践 课件 15-元编程_第4页
科学计算语言Julia及MWORKS实践 课件 15-元编程_第5页
已阅读5页,还剩21页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

四、Julia语言进阶4.3元编程元编程是指编程语言可以通过编写程序生成满足用户需求的程序。Julia语言把代码表示为语言中的数据结构,支持元编程。在程序运行时和编译时,元编程可以修改对象和添加方法等,使得编程更灵活。元编程的程序表示创建表达式并求值生成代码利用宏实现元编程生成函数运行时反射四、Julia语言进阶4.3.1程序表示Julia代码的执行过程分为两个阶段:第一将字符串解析为抽象语法树结构解析原始代码阶段和第二执行已解析代码阶段。利用元编程可以在代码执行之前,对已解析的代码进行修改。修改后的结果类型为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#表达式参数数组3-elementVector{Any}::+12四、Julia语言进阶4.3.1程序表示Expr类型包含符号对象和表达式,表达式可能包含符号、其它表达式或字面量。julia>typeof(expr1.args[1])#判断表达式参数类型Symboljulia>typeof(expr1.args[2])Int64julia>typeof(expr1.args[3])Int64julia>dump(expr1)#使用dump函数查看Expr对象Exprhead:Symbolcallargs:Array{Any}((3,))1:Symbol+2:Int6413:Int642四、Julia语言进阶4.3.1程序表示使用Expr函数构造表达式,与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函数构造等价。四、Julia语言进阶4.3.1程序表示使用Symbol函数将多个字符串联。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标识符“_”串联字符串无效标识符“.”需要用双引号。四、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函数构造简单。四、Julia语言进阶4.3.2表达式与求值使用符号$将数插入表达式,称为插值。未被引用的表达式不能被插值。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表达式与求值将多个表达式变成另一个表达式的参数时,可以使用$(name…)构造。例如,将数组中的表达式插入到函数f的输入参数位置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;#在全局作用域内对表达式的变量赋值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语言中,使用插值和求值来实现代码生成。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)用符号:和和插值实现连加用关键词引用和插值实现连加四、Julia语言进阶4.3.3代码生成当需要编写重复的代码、样板形式代码时,可以使用元编程大幅度提升编程效率。在Julia语言中,使用插值和求值来实现代码生成。julia>forop=(:+,:-,:*,:/,:&&,:||)#需要多个不同的操作时,用for循环。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宏宏可以实现表达式的替换,不需要使用eval就可以返回表达式。用关键词macro构造宏,声明语法:macromac_name(para_name)…end构造宏,mac_name为宏名称,para_name为输入参数。julia>macromac1()#构造无输入参数的宏。return:(println("MWORKS.Syslab"))end@mac1(macrowith1method)julia>macromac2(str)#构造有输入参数的宏。return:(println("MWORKS.Syslabbasedon",$str))end@mac2(macrowith1method)四、Julia语言进阶4.3.4宏调用宏的2种方法@mac_namepara_name1para_name2…#使用空格分开参数名称。@mac_name(para_name1,para_name2…)#使用逗号分开参数名称。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宏数组做参数时,先将数组代入宏计算并返回值,再执行剩余表达式。julia>macromac4(para)return:($para.+1)end@mac4(macrowith1method)julia>@mac4[12]*2#第一种调用方式,宏名和数组之间没有空格。1×2Matrix{Int64}:46#先计算[12].+1,再计算返回值*2。julia>@mac4([12])*2#第二种调用方式,宏名和括号之间没有空格。1×2Matrix{Int64}:46#先计算[12].+1,再计算返回值*2。julia>@mac4[12]*2#先计算[12]*2,再计算返回值.+1。1×2Matrix{Int64}:35注意:有空格时,整体做为宏的输入参数。四、Julia语言进阶4.3.4宏使用show函数可导出宏的参数,但show函数必须在宏内部。julia>macromac5(para)show(para)end@mac5(macrowith1method)julia>@mac5(x):xjulia>@mac5(2*3):(2*3)四、Julia语言进阶4.3.4宏卫生宏,又称为干净宏,可避免展开后的表达式中变量与全局变量名称冲突的问题。宏内部只可使用关键词local声明局部变量,不能使用eval,可使用关键词esc转义以避免宏变大。例如计算时间的宏:macromac7(ex)returnquotelocalt0=time_ns()localval=$(esc(ex))localt1=time_ns()println("elapsedtime:",(t1-t0)/1e9,"seconds")valendend四、Julia语言进阶4.3.4宏宏的派发,同一个宏可以有多个方法,调用宏时可以实现多重派发。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"调用宏@r_str创建正则表达式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函数实现插值并构造正则表达式。四、Julia语言进阶4.3.6生成函数宏@generated定义生成函数。生成函数与普通函数不同,调用生成函数返回的是表达式,普通函数返回的是值。定义和调用生成函数julia>@generatedfunctionfun1(x)return:(x*x)endfun1(genericfunctionwith1method)julia>fun1(5)25julia>fun1("Syslab")"SyslabSyslab"在普通函数关键词function前加@generated宏。四、Julia语言进阶4.3.6生成函数向普通函数中添加新方法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的元编程支持运行时反射,例如可以查看类型字段、类型的类型、类型的亚型,还可查看函数所包含的方法和函数内部检查。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. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论