首页
技术小册
AIGC
面试刷题
技术文章
MAGENTO
云计算
视频课程
源码下载
PDF书籍
「涨薪秘籍」
登录
注册
Julia简介
Julia 语言安装
Julia 交互式命令
Julia 基本语法
Julia 数组
Julia 元组
Julia 数据类型
Julia 复数和有理数
Julia 基本运算符
Julia 数学函数
Julia 字符串
Julia 正则表达式
Julia 函数
Julia 流程控制
Julia 字典和集合
Julia 日期和时间
Julia 文件读写
Julia元编程
当前位置:
首页>>
技术小册>>
Julia入门教程
小册名称:Julia入门教程
Julia 把自己的代码表示为语言中的数据结构,这样我们就可以编写操纵程序的程序。 元编程也可以简单理解为编写可以生成代码的代码。 元编程(英语:Metaprogramming),是指某类计算机程序的编写,这类计算机程序编写或者操纵其它程序(或者自身)作为它们的资料,或者在编译时完成部分本应在运行时完成的工作。多数情况下,与手工编写全部代码相比,程序员可以获得更高的工作效率,或者给与程序更大的灵活度去处理新的情形而无需重新编译。 编写元程序的语言称之为元语言。被操纵的程序的语言称之为"目标语言"。一门编程语言同时也是自身的元语言的能力称之为"反射"或者"自反"。 ###Julia 源代码执行阶段 1、解析原始 Julia 代码: Julia 解析器首先将解析字符串以获得抽象语法树(AST),AST 是一种结构,它以易于操作的格式包含所有代码。 2、执行已解析的 Julia 代码:: 在这个阶段,执行已解析的 Julia 代码。 当我们在交互式编程环境(REPL)中输入代码并按回车键时,会执行以上两个阶段。 使用元编程工具,我们就可以访问这两个阶段之间的 Julia 代码,即在源代码解析之后,但在执行之前。 程序表示 Julia 提供了一个 Meta 类,其中可以用 Meta.parse(str) 来对一个字符串进行解析,用 typeof(e1) 返回 Expr: 实例 ``` julia> prog = "1 + 1" "1 + 1" julia> ex1 = Meta.parse(prog) :(1 + 1) julia> typeof(ex1) ``` ###Expr 返回 :(1 + 1) , 这个返回的值由一个冒号和后面的表达式组成,用 typeof(ex1) 返回 Expr。 Expr 对象包含两个部分(ex1 包含了 head 和 args 属性): 一个标识表达式类型的符号对象。 实例 ``` julia> ex1.head :call ``` 另一个是表达式的参数,可能是符号、其他表达式或字面量: 实例 ``` julia> ex1.args 3-element Vector{Any}: :+ 1 1 ``` 表达式也可能直接用 Expr 构造: 实例 ``` julia> ex2 = Expr(:call, :+, 1, 1) :(1 + 1) ``` 上面构造的两个表达式:一个通过解析构造,一个通过直接构造,两个是等价的: 实例 ``` julia> ex1 == ex2 true ``` Expr 对象也可以嵌套: 实例 ``` julia> ex3 = Meta.parse("(4 + 4) / 2") :((4 + 4) / 2) ``` 我们也可以使用 Meta.show_sexpr 查看表达式,以下实例展示了嵌套的 Expr: 实例 ``` julia> Meta.show_sexpr(ex3) (:call, :/, (:call, :+, 4, 4), 2) ``` ###符号 我们可以通过冒号 : 前缀运算符存储一个未计算但已解析的表达式。 实例 ``` julia> ABC = 100 100 julia> :ABC :ABC ``` 引用下面的整个表达式: 实例 ``` julia> :(100-50) :(100 - 50) ``` ###引用算数表达式: 实例 ``` julia> ex = :(a+b*c+1) :(a + b * c + 1) julia> typeof(ex) Expr ``` 注意等价的表达式也可以使用 Meta.parse 或者直接用 Expr 构造: 实例 ``` julia> :(a + b*c + 1) == Meta.parse("a + b*c + 1") == Expr(:call, :+, :a, Expr(:call, :*, :b, :c), 1) true ``` 引用多个表达式也可以在 quote ... end 中包含代码块。 实例 ``` julia> ex = quote x = 1 y = 2 x + y end quote #= none:2 =# x = 1 #= none:3 =# y = 2 #= none:4 =# x + y end julia> typeof(ex) Expr ``` ###执行表达式 表达式解析后,我们可以使用 eval() 函数来执行: 实例 ``` julia> ex1 = :(1 + 2) :(1 + 2) julia> eval(ex1) 3 julia> ex = :(a + b) :(a + b) julia> eval(ex) ERROR: UndefVarError: b not defined [...] julia> a = 1; b = 2; julia> eval(ex) 3 ``` ###抽象语法树 (AST) 抽象语法树 (AST) 是一种结构,是源代码语法结构的一种抽象表示。 它以树状的形式表现编程语言的语法结构,树上的每个节点都表示源代码中的一种结构。 我们可以在 dump() 函数查看表达式的层次结构: 实例 ``` julia> dump(:(1 * cos(pi/2))) Expr head: Symbol call args: Array{Any}((3,)) 1: Symbol * 2: Int64 1 3: Expr head: Symbol call args: Array{Any}((2,)) 1: Symbol cos 2: Expr head: Symbol call args: Array{Any}((3,)) 1: Symbol / 2: Symbol pi 3: Int64 2 ``` ###插值 使用值参数直接构造 Expr 对象虽然很强大,但与 Julia 语法相比,Expr 构造函数可能让人觉得乏味。作为替代方法,Julia 允许将字面量或表达式插入到被引用的表达式中。表达式插值由前缀 $ 表示。 在此示例中,插入了变量 a 的值: 实例 ``` julia> a = 1; julia> ex = :($a + b) :(1 + b) ``` 对未被引用的表达式进行插值是不支持的,这会导致编译期错误: ``` julia> $a + b ERROR: syntax: "$" expression outside quote ``` 在此示例中,元组 (1,2,3) 作为表达式插入到条件测试中: ``` julia> ex = :(a in $:((1,2,3)) ) :(a in (1, 2, 3)) ``` 在表达式插值中使用 $ 是有意让人联想到字符串插值和命令插值。表达式插值使得复杂 Julia 表达式的程序化构造变得方便和易读。 ###宏 宏提供了一种机制,可以将生成的代码包含在程序的最终主体中。 宏将一组参数映射到返回的 表达式,并且生成的表达式被直接编译,而不需要运行时 eval 调用。 宏参数可能包括表达式、字面量和符号。 这是一个非常简单的宏: 实例 ``` julia> macro sayhello() return :( println("Hello, world!") ) end @sayhello (macro with 1 method) ``` 宏在Julia的语法中有一个专门的字符 @ (at-sign),紧接着是其使用 macro NAME ... end 形式来声明的唯一的宏名。在这个例子中,编译器会把所有的 @sayhello 替换成: ``` :( println("Hello, world!") ) ``` 当 @sayhello 在REPL中被输入时,解释器立即执行,因此我们只会看到计算后的结果: ``` julia> @sayhello() Hello, world! ``` 现在,考虑一个稍微复杂一点的宏: 实例 ``` julia> macro sayhello(name) return :( println("Hello, ", $name) ) end @sayhello (macro with 1 method) ``` 这个宏接受一个参数 name。当遇到 @sayhello 时,quoted 表达式会被展开并将参数中的值插入到最终的表达式中: 实例 ``` julia> @sayhello("human") Hello, human ``` 我们可以使用函数 macroexpand 查看引用的返回表达式: 实例 ``` julia> ex = macroexpand(Main, :(@sayhello("human")) ) :(Main.println("Hello, ", "human")) julia> typeof(ex) Expr ``` 我们可以看到 "human" 字面量已被插入到表达式中了。 还有一个宏 @ macroexpand,它可能比 macroexpand 函数更方便: 实例 ``` julia> @macroexpand @sayhello "human" :(println("Hello, ", "human")) ```f
上一篇:
Julia 文件读写
该分类下的相关小册推荐:
暂无相关推荐.