Julia神奇的元编程

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

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

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

julia> e1 = Meta.parse("2 * 3")
:(2 * 3)

julia> typeof(e1)
Expr

julia> e1.head
:call

julia> e1.args
3-element Array{Any,1}:
  :*
 2
 3

julia> dump(e1)
Expr
  head: Symbol call
  args: Array{Any}((3,))
    1: Symbol *
    2: Int64 2
    3: Int64 3

julia> ex2 = Expr(:call,:*,2,3)
:(2 * 3)

julia> e3 = :(2*3)
:(2 * 3)

julia> e1 == ex2
true

julia> e1 == e3
true

julia> Meta.show_sexpr(e1)
(:call, :*, 2, 3)
julia> var_x = :x
:x

julia> typeof(var_x)
Symbol

julia> var_y = Symbol("y")
:y

julia> var_z = Symbol("var",'_',"z")
:var_z

julia> typeof(e1)
Expr

julia> exq = quote
       x = 1
       y = 3
       sin(x)+y
       end
quote
    #= REPL[34]:2 =#
    x = 1
    #= REPL[34]:3 =#
    y = 3
    #= REPL[34]:4 =#
    sin(x) + y
end

julia> typeof(exq)
Expr

julia> eval(exq)
3.8414709848078967

julia> eval(:(2 * 3))
6

julia> x = 2
2

julia> ex = :($x+sin($x))
:(2 + sin(2))

julia> eval(ex)
2.909297426825682

julia> ex = :(x in $:((1,2,3)))
:(x in (1, 2, 3))

julia> eval(ex)
true

julia> 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)
3

julia> e = dump(Meta.parse(":x"))
QuoteNode
  value: Symbol x

 从上述代码示例中可知,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> macro sayhello(name)
                  return :( println("Hello, ", $name) )
              end
@sayhello (macro with 1 methods)

julia> @sayhello("julia")
Hello, julia

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

julia> function myf(x,y)
       x + y + 1
       end
myf (generic function with 1 method)

julia> ex = :(myf(1,2))
:(myf(1, 2))

julia> eval(ex)
4

julia> ex = Meta.parse("myf(1,2)+3")
:(myf(1, 2) + 3)

julia> eval(ex)
7

julia> A = [ 1 2 3 ; 4 5 6]
2×3 Array{Int64,2}:
 1  2  3
 4  5  6

julia> A'
3×2 LinearAlgebra.Adjoint{Int64,Array{Int64,2}}:
 1  4
 2  5
 3  6

julia> ex = Meta.parse("A= [ 1 2 3 ; 4 5 6]")
:(A = [1 2 3; 4 5 6])

julia> eval(ex)
2×3 Array{Int64,2}:
 1  2  3
 4  5  6

julia> ex = Meta.parse("A2= [ 1 2 3 ; 4 5 6]")
:(A2 = [1 2 3; 4 5 6])

julia> A2
ERROR: UndefVarError: A2 not defined

julia> eval(ex)
2×3 Array{Int64,2}:
 1  2  3
 4  5  6

julia> A2
2×3 Array{Int64,2}:
 1  2  3
 4  5  6

julia> ex = Meta.parse("A3 = A2'")
:(A3 = A2')

julia> eval(ex)
3×2 LinearAlgebra.Adjoint{Int64,Array{Int64,2}}:
 1  4
 2  5
 3  6

julia> A3
3×2 LinearAlgebra.Adjoint{Int64,Array{Int64,2}}:
 1  4
 2  5
 3  6

julia> 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

【版权声明】本文为华为云社区用户原创内容,转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息, 否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。