Julia神奇的元编程

简介: 元编程(Meta-Programming)是指某类程序编写或者操纵其他程序(或者自身)作为它们的数据,或者在运行时完成部分本应在编译时完成的工作。换句话说,具有元编程能力的语言,可以自己来编写自己,即Julia语言代码中可以包含Julia语言代码,这样可以在运行期间动态的执行一些业务逻辑,因此其功能非常强大。

     根据百度百科的定义,元编程(Meta-Programming)是指某类程序编写或者操纵其他程序(或者自身)作为它们的数据,或者在运行时完成部分本应在编译时完成的工作。编写元程序的语言称之为元语言,被操作的语言称之为目标语言。一门语言同时也是自身的元语言的能力称之为反射。换句话说,具有元编程能力的语言,可以自己来编写自己,即Julia语言代码中可以包含Julia语言代码,这样可以在运行期间动态的执行一些业务逻辑,因此其功能非常强大。

    下面将重点介绍一下Julia语言的元编程用法:

julia>e1=Meta.parse("2 * 3")
:(2*3)
julia>typeof(e1)
Exprjulia>e1.head:calljulia>e1.args3-elementArray{Any,1}:
  :*23julia>dump(e1)
Exprhead:Symbolcallargs:Array{Any}((3,))
1: Symbol*2: Int6423: Int643julia>ex2=Expr(:call,:*,2,3)
:(2*3)
julia>e3= :(2*3)
:(2*3)
julia>e1==ex2truejulia>e1==e3truejulia>Meta.show_sexpr(e1)
(:call, :*, 2, 3)
julia>var_x= :x:xjulia>typeof(var_x)
Symboljulia>var_y=Symbol("y")
:yjulia>var_z=Symbol("var",'_',"z")
:var_zjulia>typeof(e1)
Exprjulia>exq=quotex=1y=3sin(x)+yendquote#=REPL[34]:2=#x=1#=REPL[34]:3=#y=3#=REPL[34]:4=#sin(x) +yendjulia>typeof(exq)
Exprjulia>eval(exq)
3.8414709848078967julia>eval(:(2*3))
6julia>x=22julia>ex= :($x+sin($x))
:(2+sin(2))
julia>eval(ex)
2.909297426825682julia>ex= :(xin$:((1,2,3)))
:(xin (1, 2, 3))
julia>eval(ex)
truejulia>args= [:x, :y, :m];
julia>ex= :(f(1, $(args...)))
:(f(1, x, y, m))
julia>Meta.quot(Expr(:$, :(1+2)))
:($(Expr(:quote, :($(Expr(:$, :(1+2)))))))
julia>mq=Meta.quot(Expr(:$, :(1+2)))
:($(Expr(:quote, :($(Expr(:$, :(1+2)))))))
julia>eval(mq)
3julia>e=dump(Meta.parse(":x"))
QuoteNodevalue:Symbolx

从上述代码示例中可知,Julia提供了一个Meta类,其中可以用 Meta.parse(str)来对一个字符串进行解析,并返回 :(2 * 3) , 这个返回的值有一个冒号,由于后面是一个表达式,用typeof(e1)返回Expr。而表达式e1有head属性和args属性,可以返回操作和参数信息。同样的, ex2 = Expr(:call,:*,2,3) 也可以用来定义一个表达式,而最简单的定义方式为 e3 = :(2*3) 。这三种方式定义的表达式是相同的,通过逻辑比较则是相同的。

另外,var_x = :x 也可以定义符号对象,即 Symbol , 即typeof(var_x) 返回 Symbol 。而Symbol("var",'_',"z") 定义了一个:var_zSymbol 。对于多行的表达式定义,可以通过quote ... end进行定义。而表达式可以通过 eval(exq)函数求值。

最后,表达式中还可以用符号$进行变量插值操作,即将变量替换成值。 如 x = 2 , ex = :($x+sin($x)) 返回 :(2 + sin(2)) 。且定义中还支持语句,如 ex = :(x in $:((1,2,3)))  ,由于x = 2 ,因此x是属于 (1,2,3) 内的,eval返回true 。

Julia还支持宏,宏用macro声明,调用时用@函数名进行调用:

julia>macrosayhello(name)
return :( println("Hello, ", $name) )
end@sayhello (macrowith1methods)
julia>@sayhello("julia")
Hello, julia

元编程中也可以引用自定义的函数等,这将大大提高了灵活性:

julia>functionmyf(x,y)
x+y+1endmyf (genericfunctionwith1method)
julia>ex= :(myf(1,2))
:(myf(1, 2))
julia>eval(ex)
4julia>ex=Meta.parse("myf(1,2)+3")
:(myf(1, 2) +3)
julia>eval(ex)
7julia>A= [ 123 ; 456]
2×3Array{Int64,2}:
123456julia>A'3×2LinearAlgebra.Adjoint{Int64,Array{Int64,2}}:
142536julia>ex=Meta.parse("A= [ 1 2 3 ; 4 5 6]")
:(A= [123; 456])
julia>eval(ex)
2×3Array{Int64,2}:
123456julia>ex=Meta.parse("A2= [ 1 2 3 ; 4 5 6]")
:(A2= [123; 456])
julia>A2ERROR:UndefVarError:A2notdefinedjulia>eval(ex)
2×3Array{Int64,2}:
123456julia>A22×3Array{Int64,2}:
123456julia>ex=Meta.parse("A3 = A2'")
:(A3=A2')julia>eval(ex)
3×2LinearAlgebra.Adjoint{Int64,Array{Int64,2}}:
142536julia>A33×2LinearAlgebra.Adjoint{Int64,Array{Int64,2}}:
142536julia>ex=Meta.parse("a=1;b=2;z=sin(a)*b")
:($(Expr(:toplevel, :(a=1), :(b=2), :(z=sin(a) *b))))
julia>eval(ex)
1.682941969615793

从上述示例中可知,我们可以定义自己的函数,并可以作为字符串中进行表达式逻辑编写,通过Meta.parse方法进行解析,同时,文本中可以进行变量的定义,当通过Eval执行后,在外部可以进行变量的访问。如 ex = Meta.parse("A= [ 1 2 3 ; 4 5 6]") 在未执行 eval(ex)时,外部访问A则抛出错误:ERROR: UndefVarError: A2 not defined 。而执行eval(ex)后,外部访问A则返回 [ 1 2 3 ; 4 5 6 ] 。

Meta.parse方法也支持多行语句,中间用;分割,如ex = Meta.parse("a=1;b=2;z=sin(a)*b") ,它返回:($(Expr(:toplevel, :(a = 1), :(b = 2), :(z = sin(a) * b)))) ,当执行eval时,返回1.682941969615793

相关文章
|
缓存 运维 监控
10分钟带你了解 Linux 系统中的 Top 命令
`top`命令是Linux系统中用于实时监控系统资源利用率的工具,展示CPU、内存使用情况及进程状态。启动`top`只需在终端输入`top`。默认按CPU使用率排序,可通过`P`、`M`、`T`键改变排序。使用`k`键可结束进程,`d`键调整刷新率,`q`键退出。输出信息包括系统负载、进程状态、内存使用等。通过进程列表,可以观察到每个进程的CPU和内存占用、用户、运行时间等。了解`top`能帮助测试工程师排查性能问题。
|
供应链 搜索推荐 安全
唯品会Vip商品详情 API 接口:开发应用与收益深度剖析
唯品会Vip商品详情API接口,作为电商数据交互的枢纽,提供详尽的商品信息与动态数据,助力开发者、商家及市场分析者洞察市场趋势、优化商品推荐、提升用户体验,从而实现销售额增长、利润空间拓展及用户忠诚度加固,推动电商行业创新发展。
702 16
|
机器学习/深度学习 编解码 计算机视觉
YOLOv11改进策略【注意力机制篇】| CVPR-2023 FSAS 基于频域的自注意力求解器 结合频域计算和卷积操作 降低噪声影响
YOLOv11改进策略【注意力机制篇】| CVPR-2023 FSAS 基于频域的自注意力求解器 结合频域计算和卷积操作 降低噪声影响
590 1
YOLOv11改进策略【注意力机制篇】| CVPR-2023 FSAS 基于频域的自注意力求解器 结合频域计算和卷积操作 降低噪声影响
|
11月前
|
SQL 数据采集 资源调度
【SQL 周周练】爬取短视频发现数据缺失,如何用 SQL 填充
爬虫爬取抖音和快手的短视频数据时,如果遇到数据缺失的情况,如何使用 SQL 语句完成数据的补全。
398 5
|
人工智能 自然语言处理 搜索推荐
阿里云携手叫叫,共创儿童学习AI新体验
阿里云携手叫叫,共创儿童学习AI新体验
|
安全 数据安全/隐私保护
解释 TCSEC 和 ITSEC
【8月更文挑战第31天】
1221 1
|
JavaScript
vue-router路由实现页面的跳转
该博客文章介绍了如何在Vue.js应用程序中使用Vue Router 4实现页面跳转,包括项目结构、组件定义、路由配置以及首页设置,并附有效果展示。
vue-router路由实现页面的跳转
|
传感器
基于51单片机的车辆倒车雷达报警系统
该文描述了一个基于51单片机的超声波倒车雷达系统设计,要求包括:2cm至4m的测量范围,3mm精度,集成DS18B20温度传感器以校准声速,使用LCD1602显示距离和温度,具备按键设置预警距离及蜂鸣器报警功能。系统由AT89C51单片机、HC-SR04超声波模块、DS18B20温度模块、报警电路和LCD显示电路组成。文中还展示了Proteus仿真电路图和部分仿真结果分析,包括LCD显示示例和预警距离设置操作。
484 4
MBProgressHUD和SVProgressHUD各自的缺点及解决方案
MBProgressHUD和SVProgressHUD各自的缺点及解决方案
343 0
|
存储 NoSQL 搜索推荐
详解:图数据库 GDB五大应用场景
图数据库GDB针对高度互联数据的存储和查询场景进行设计,并在内核层面进行了大量优化,非常适合社交网络、欺诈检测、推荐引擎、知识图谱、网络/IT运营等高密互连数据集的场景。
3660 0

热门文章

最新文章