当前位置:K88软件开发文章中心编程语言非主流编程语言Julia → 文章内容

Julia 模块

减小字体 增大字体 作者:佚名  来源:网上搜集  发布时间:2019-1-15 16:28:16

由 陈 创建, 最后一次修改 2016-08-12 模块Julia 的模块是一个独立的全局变量工作区。它由句法限制在 module Name ... end 之间。在模块内部,你可以控制其他模块的命名是否可见(通过 import ),也可以指明本模块的命名是否为 public(通过 export)。下面的例子展示了模块的主要特征。这个例子仅为演示: module MyModule using Lib using BigLib: thing1, thing2 import Base.show importall OtherLib export MyType, foo type MyType x end bar(x) = 2x foo(a::MyType) = bar(a.x) + 1 show(io, a::MyType) = print(io, "MyType $(a.x)") end注意上述例子没有缩进模块体的代码,因为整体缩进没有必要。这个模块定义了类型 MyType 和两个函数。foo 函数和 MyType 类型被 export ,因此可以被 import 进其他模块使用。 bar 是 MyModule 的私有函数。语句 using Lib 表明,Lib 模块在需要时可用来解析命名。若一个全局变量在当前模块中没有被定义,系统会在 Lib export 的变量中搜索,并在找到后把它 import 进来。在当前模块中凡是用到这个全局变量时,都会去找 Lib 中变量的定义。语句 using BigLib: thing1, thing2 是 using BigLib.thing1, BigLib.thing2 的缩写。import 关键字支持与 using 所有相同的语法,但只能在一个时间上对一个名称进行操作。它不像 using 那样会添加用于搜索的模块。import 与 using 的不同之处还在于导入这一功能时必须使用新的方法扩展后的 import。 在上述的 MyModule 中我们想向标准的 show 功能增加一个方法,所以我们必须写下 import Base.show。 那些函数名只有通过 using 功能才能看到的函数是不能被扩展的。 importall 关键字显式地导入导出指定模块的所有名称,其效果就像 import 单独使用在它们的所有名称一样。 一旦一个变量是通过 using 或 import 使其可见的,一个模块就可能无法创建它自己的同名的变量了。输入变量必须是只读的;对全局变量赋值总是会影响当前模块所拥有的变量,否则就会引发错误。模块使用方法的总结我们要加载一个模块时,可以使用两个主要关键字:using 和 import。要了解他们的差异,可以考虑下面的例子: module MyModule export x, y x() = "x" y() = "y" p() = "p" end在这个模块中我们(使用关键字 export )导出 x 和 y 功能,也包含了非导出函数 p 。我们有几个不同的方法来加载该模块及其内部功能到当前工作区,具体如下:导入命令导入变量方法扩展可用项using MyModuleAll export ed names (x and y), MyModule.x, MyModule.y and MyModule.p MyModule.x, MyModule.y and MyModule.pusing MyModule .x, MyModule.px and pusing MyModule: x, px and pimport MyModuleMyModule.x, MyModule.y and MyModule.pMyModule.x, MyModule.y and MyModule.pimport MyModule.x, MyModule.px and px and pimport MyModule: x, px and px and pimportall MyModuleAll export ed names (x and y)x and y模块和文件大多数情况下,文件和文件名与模块无关;模块只与模块表达式有关。一个模块可以有多个文件,一个文件也可以有多个模块: module Foo include("file1.jl") include("file2.jl") end在不同的模块中包含同样的代码,会带来类似 mixin 的特征。可以利用这点,在不同的环境定义下运行同样的代码,例如运行一些操作的“安全”版本来进行代码测试: module Normal include("mycode.jl") end module Testing include("safe_operators.jl") include("mycode.jl") end标准模块有三个重要的标准模块:Main, Core, 和 Base。Main 是顶级模块,Julia 启动时将 Main 设为当前模块。提示符模式下,变量都是在 Main 模块中定义,whos() 可以列出 Main 中的所有变量。Core 包含“内置”的所有标志符,例如部分核心语言,但不包括库。每个模块都隐含地调用了 using Core,因为没有这些声明,什么都做不了。Base 是标准库( 在 base/ 文件夹下)。所有的模块都隐含地调用了 using Base,因为大部分情况下都需要它。默认顶级声明和裸模块除了 using Base,模块显式引入了所有的运算符。模块还自动包含 eval 函数的定义,这个函数对本模块中的表达式求值。如果不想要这些定义,可以使用 baremodule 关键字来定义模块。使用 baremodule 时,一个标准的模块有如下格式: baremodule Mod using Base importall Base.Operators eval(x) = Core.eval(Mod, x) eval(m,x) = Core.eval(m, x) ... end模块的相对和绝对路径输入指令 using foo, Julia 会首先在 Main 名字空间中寻找 Foo。如果模块未找到, Julia 会尝试 require("Foo")。通常情况下, 这会从已安装的包中载入模块。然而,有些模块还有子模块,也就是说,有时候不能从 Main 中直接引用一些模块。有两种方法可以解决这个问题:方法一,使用绝对路径,如 using Base.Sort。方法二,使用相对路径,这样可以方便地载入当前模块的子模块或者嵌套的模块: module Parent module Utils ... end using .Utils ... end模块 Parent 包含子模块 Utils。如果想要 Utils 中的内容对 Parent 可见, 可以使用 using 加上英文句号。更多的句号表示在更下一层的命名空间进行搜索。例如,using ..Utils 将会在 Parent 模块的子模块内寻找 Utils 。模块文件路径全局变量 LOAD_PATH 包含了调用 require 时 Julia搜索模块的目录。可以用 push! 进行扩展 : push!(LOAD_PATH, "/Path/To/My/Module/")将这一段代码放在 ~\.juliarc.jl 里能够在每次 Julia启动时对 LOAD_PATH 扩展。此外,还可以通过定义环境变量JULIA_LOAD_PATH 来扩展 Julia 的模块路径。小提示如果一个命名是有许可的(qualified)(如 Base.sin),即使它没被 export ,仍能被外部读取。这在调试时非常有用。import 或 export 宏时,要在宏名字前添加 @ 符号,例如 import Mod.@mac 。在其他模块中的宏可以被调用为 Mod.@mac 或 @Mod.mac 。形如 M.x = y 的语法是错的,不能给另一个模块中的全局变量赋值;全局变量的赋值都是在变量所在的模块中进行的。直接在顶层声明为 global x,可以将变量声明为“保留”的。这可以用来防止加载时,全局变量初始化遇到命名冲突。

Julia 模块