Essentials
Introduction
Julia Base 包含一系列适合进行科学和数值计算的函数和宏,但其范围也与许多通用编程语言一样广泛。 额外的功能来自于一个不断增长的集合 available packages。 函数按主题分组如下。
一些一般性备注:
- 要使用模块函数,请使用
import Module
导入模块,并使用Module.fn(x)
来使用这些函数。 - 或者,
using Module
将把所有导出的Module
函数导入到当前命名空间。 - 根据约定,以感叹号(
!
)结尾的函数名称会修改其参数。一些函数同时具有修改版本(例如,sort!
)和非修改版本(sort
)。
Base
和标准库的行为是稳定的,如 SemVer 中定义的,前提是它们是有文档记录的;即,包含在 Julia documentation 中,并且没有标记为不稳定。有关更多信息,请参见 API FAQ。
Getting Around
Base.exit
— Functionexit(code=0)
使用退出代码停止程序。默认退出代码为零,表示程序成功完成。在交互式会话中,可以使用键盘快捷键 ^D
调用 exit()
。
Base.atexit
— Functionatexit(f)
注册一个零或一个参数的函数 f()
,在进程退出时调用。atexit()
钩子以后进先出 (LIFO) 的顺序调用,并在对象终结器之前运行。
如果 f
为一个整数参数定义了一个方法,它将被作为 f(n::Int32)
调用,其中 n
是当前的退出代码,否则将被作为 f()
调用。
一参数形式需要 Julia 1.9
退出钩子可以调用 exit(n)
,在这种情况下,Julia 将以退出代码 n
退出(而不是原始退出代码)。如果多个退出钩子调用 exit(n)
,则 Julia 将以最后一个调用 exit(n)
的退出钩子的退出代码退出。(因为退出钩子是以 LIFO 顺序调用的,“最后调用”等同于“最先注册”。)
注意:一旦所有退出钩子被调用,就不能再注册更多的退出钩子,任何在所有钩子完成后调用 atexit(f)
的操作将抛出异常。如果您在后台任务中注册退出钩子,而这些任务在关闭期间可能仍在并发执行,则可能会发生这种情况。
Base.isinteractive
— Functionisinteractive() -> Bool
确定Julia是否在交互式会话中运行。
Base.summarysize
— FunctionBase.summarysize(obj; exclude=Union{...}, chargeall=Union{...}) -> Int
计算从参数可达的所有唯一对象所使用的内存量(以字节为单位)。
关键字参数
exclude
:指定在遍历中要排除的对象类型。chargeall
:指定始终计算其所有字段大小的对象类型,即使这些字段通常会被排除。
另请参见 sizeof
。
示例
julia> Base.summarysize(1.0)
8
julia> Base.summarysize(Ref(rand(100)))
848
julia> sizeof(Ref(rand(100)))
8
Base.__precompile__
— Function__precompile__(isprecompilable::Bool)
指定调用此函数的文件是否可预编译,默认为 true
。如果模块或文件不安全地可预编译,则应调用 __precompile__(false)
以便在 Julia 尝试预编译时抛出错误。
Base.include
— FunctionBase.include([mapexpr::Function,] m::Module, path::AbstractString)
在模块 m
的全局作用域中评估输入源文件的内容。每个模块(除了使用 baremodule
定义的模块)都有自己的 include
定义,省略 m
参数,这会在该模块中评估文件。返回输入文件最后评估的表达式的结果。在包含期间,任务本地的包含路径被设置为包含文件的目录。嵌套调用 include
将相对于该路径进行搜索。此函数通常用于交互式加载源代码,或将分成多个源文件的包中的文件组合在一起。
可选的第一个参数 mapexpr
可用于在评估之前转换包含的代码:对于 path
中的每个解析表达式 expr
,include
函数实际上评估 mapexpr(expr)
。如果省略,则 mapexpr
默认为 identity
。
需要 Julia 1.5 才能传递 mapexpr
参数。
include
— Functioninclude([mapexpr::Function,] path::AbstractString)
在包含模块的全局作用域中评估输入源文件的内容。每个模块(除了使用 baremodule
定义的模块)都有自己的 include
定义,该定义在该模块中评估文件。返回输入文件最后评估的表达式的结果。在包含期间,任务本地的包含路径被设置为包含文件的目录。嵌套调用 include
将相对于该路径进行搜索。此函数通常用于交互式加载源代码,或将分成多个源文件的包中的文件组合在一起。参数 path
使用 normpath
进行规范化,这将解析相对路径标记,例如 ..
并将 /
转换为适当的路径分隔符。
可选的第一个参数 mapexpr
可用于在评估之前转换包含的代码:对于 path
中的每个解析表达式 expr
,include
函数实际上评估 mapexpr(expr)
。如果省略,则 mapexpr
默认为 identity
。
使用 Base.include
将文件评估到另一个模块中。
需要 Julia 1.5 才能传递 mapexpr
参数。
Base.include_string
— Functioninclude_string([mapexpr::Function,] m::Module, code::AbstractString, filename::AbstractString="string")
与 include
类似,但从给定的字符串中读取代码,而不是从文件中读取。
可选的第一个参数 mapexpr
可用于在评估之前转换包含的代码:对于 code
中的每个解析表达式 expr
,include_string
函数实际上会评估 mapexpr(expr)
。如果省略,则 mapexpr
默认为 identity
。
需要 Julia 1.5 才能传递 mapexpr
参数。
Base.include_dependency
— Functioninclude_dependency(path::AbstractString; track_content::Bool=true)
在一个模块中,声明由 path
指定的文件、目录或符号链接(相对或绝对)是预编译的依赖项;也就是说,如果 track_content=true
,则如果 path
的内容发生变化,模块将需要重新编译(如果 path
是一个目录,则内容等于 join(readdir(path))
)。如果 track_content=false
,则在 path
的修改时间 mtime
发生变化时触发重新编译。
只有在您的模块依赖于未通过 include
使用的路径时,这才是必要的。它在编译之外没有影响。
关键字参数 track_content
至少需要 Julia 1.11。如果 path
不可读,则会抛出错误。
__init__
— Keyword__init__
__init__()
函数在模块首次运行时加载后立即执行。它在模块中所有其他语句执行完毕后被调用一次。由于它是在完全导入模块后被调用的,因此子模块的 __init__
函数会首先执行。__init__
的两个典型用途是调用外部 C 库的运行时初始化函数和初始化涉及外部库返回的指针的全局常量。有关更多详细信息,请参见 manual section about modules。
示例
const foo_data_ptr = Ref{Ptr{Cvoid}}(0)
function __init__()
ccall((:foo_init, :libfoo), Cvoid, ())
foo_data_ptr[] = ccall((:foo_data, :libfoo), Ptr{Cvoid}, ())
nothing
end
Base.which
— Methodwhich(f, types)
返回将为给定 types
的参数调用的 f
的方法(一个 Method
对象)。
如果 types
是一个抽象类型,则返回 invoke
将调用的方法。
另请参见:parentmodule
,@which
,和 @edit
。
Base.methods
— Functionmethods(f, [types], [module])
返回 f
的方法表。
如果指定了 types
,则返回类型匹配的方法数组。如果指定了 module
,则返回在该模块中定义的方法数组。模块列表也可以作为数组指定。
至少需要 Julia 1.4 才能指定模块。
另请参见: which
, @which
和 methodswith
.
Base.@show
— Macro@show exs...
将一个或多个表达式及其结果打印到 stdout
,并返回最后一个结果。
示例
julia> x = @show 1+2
1 + 2 = 3
3
julia> @show x^2 x/2;
x ^ 2 = 9
x / 2 = 1.5
Base.MainInclude.ans
— Constantans
一个指向最后计算值的变量,自动导入到交互提示中。
Base.MainInclude.err
— Constanterr
一个变量,指向最后抛出的错误,自动导入到交互提示符中。抛出的错误被收集在一个异常栈中。
Base.active_project
— Functionactive_project()
返回活动 Project.toml
文件的路径。另见 Base.set_active_project
。
Base.set_active_project
— Functionset_active_project(projfile::Union{AbstractString,Nothing})
将活动的 Project.toml
文件设置为 projfile
。另见 Base.active_project
。
此函数至少需要 Julia 1.8。
Keywords
这是Julia中保留关键字的列表:baremodule
,begin
,break
,catch
,const
,continue
,do
,else
,elseif
,end
,export
,false
,finally
,for
,function
,global
,if
,import
,let
,local
,macro
,module
,quote
,return
,struct
,true
,try
,using
,while
。这些关键字不能用作变量名。
以下两个词序列是保留的:abstract type
,mutable struct
,primitive type
。但是,您可以创建名为:abstract
,mutable
,primitive
和 type
的变量。
最后:where
被解析为用于编写参数化方法和类型定义的中缀运算符;in
和 isa
被解析为中缀运算符;public
在开始顶层语句时被解析为关键字;outer
在用于修改 for
循环的迭代规范中的变量作用域时被解析为关键字;而 as
被用作关键字,以重命名通过 import
或 using
引入作用域的标识符。不过,允许创建名为 where
、in
、isa
、outer
和 as
的变量。
module
— Keyword模块
module
声明一个 Module
,这是一个独立的全局变量工作空间。在模块内,您可以控制从其他模块可见的名称(通过导入),并指定您的名称中哪些是公开的(通过 export
和 public
)。模块允许您创建顶级定义,而无需担心在与其他人的代码一起使用时出现名称冲突。有关更多详细信息,请参见 关于模块的手册部分。
示例
module Foo
import Base.show
export MyType, foo
struct MyType
x
end
bar(x) = 2x
foo(a::MyType) = bar(a.x) + 1
show(io::IO, a::MyType) = print(io, "MyType $(a.x)")
end
export
— Keywordexport
export
用于模块中,告诉 Julia 哪些名称应该对用户可用。例如:export foo
使名称 foo
在 using
模块时可用。有关详细信息,请参见 manual section about modules。
public
— Keywordpublic
public
用于模块中,以告诉 Julia 哪些名称是模块的公共 API 的一部分。例如:public foo
表示名称 foo
是公共的,但在 using
模块时并不可用。有关详细信息,请参见 manual section about modules。
public 关键字是在 Julia 1.11 中添加的。在此之前,公共性的概念不够明确。
import
— Keywordimport
import Foo
将加载模块或包 Foo
。可以使用点语法访问导入的 Foo
模块中的名称(例如,使用 Foo.foo
访问名称 foo
)。有关详细信息,请参见 manual section about modules。
using
— Keywordusing
using Foo
将加载模块或包 Foo
并使其 export
的名称可供直接使用。名称也可以通过点语法使用(例如 Foo.foo
来访问名称 foo
),无论它们是否被 export
。有关详细信息,请参见 手册中关于模块的部分。
当两个或多个包/模块导出一个名称,并且该名称在每个包中并不指代相同的事物时,如果通过 using
加载这些包而没有明确列出名称,则引用该名称而不进行限定将会出错。因此,建议编写旨在与其依赖项和 Julia 的未来版本向前兼容的代码,例如,已发布包中的代码,列出它从每个加载的包中使用的名称,例如 using Foo: Foo, f
而不是 using Foo
。
as
— Keywordas
as
被用作关键字,以重命名通过 import
或 using
引入作用域的标识符,目的是为了处理名称冲突以及缩短名称。 (在 import
或 using
语句之外,as
不是关键字,可以作为普通标识符使用。)
import LinearAlgebra as LA
将导入的 LinearAlgebra
标准库引入作用域,命名为 LA
。
import LinearAlgebra: eigen as eig, cholesky as chol
将 LinearAlgebra
中的 eigen
和 cholesky
方法引入作用域,分别命名为 eig
和 chol
。
as
仅在单个标识符被引入作用域时与 using
一起使用。例如,using LinearAlgebra: eigen as eig
或 using LinearAlgebra: eigen as eig, cholesky as chol
是有效的,但 using LinearAlgebra as LA
是无效的语法,因为将 LinearAlgebra
中的 所有 导出名称重命名为 LA
是没有意义的。
baremodule
— Keywordbaremodule
baremodule
声明一个不包含 using Base
或 eval
和 include
的局部定义的模块。它仍然导入 Core
。换句话说,
module Mod
...
end
等价于
baremodule Mod
using Base
eval(x) = Core.eval(Mod, x)
include(p) = Base.include(Mod, p)
...
end
function
— Keyword函数
函数是用 function
关键字定义的:
function add(a, b)
return a + b
end
或者使用简写形式:
add(a, b) = a + b
使用 return
关键字的方式与其他语言完全相同,但通常是可选的。没有显式 return
语句的函数将返回函数体中的最后一个表达式。
macro
— Keyword宏
宏
定义了一种将生成的代码插入程序的方法。宏将一系列参数表达式映射到返回的表达式,结果表达式直接替换到调用宏的程序中的位置。宏是一种运行生成代码而不调用 eval
的方式,因为生成的代码简单地成为周围程序的一部分。宏参数可以包括表达式、字面值和符号。可以为可变数量的参数(varargs)定义宏,但不接受关键字参数。每个宏还隐式地接收参数 __source__
,它包含宏被调用的行号和文件名,以及 __module__
,它是宏展开的模块。
有关如何编写宏的更多信息,请参见手册中的 元编程 部分。
示例
julia> macro sayhello(name)
return :( println("Hello, ", $name, "!") )
end
@sayhello (宏有 1 个方法)
julia> @sayhello "Charlie"
Hello, Charlie!
julia> macro saylots(x...)
return :( println("Say: ", $(x...)) )
end
@saylots (宏有 1 个方法)
julia> @saylots "hey " "there " "friend"
Say: hey there friend
return
— Keywordreturn
return x
使得封闭的函数提前退出,将给定的值 x
返回给调用者。单独使用 return
而不带值等同于 return nothing
(参见 nothing
)。
function compare(a, b)
a == b && return "equal to"
a < b ? "less than" : "greater than"
end
一般来说,你可以在函数体内的任何位置放置 return
语句,包括深度嵌套的循环或条件中,但要小心 do
块。例如:
function test1(xs)
for x in xs
iseven(x) && return 2x
end
end
function test2(xs)
map(xs) do x
iseven(x) && return 2x
x
end
end
在第一个例子中,返回在遇到偶数时立即退出 test1
,因此 test1([5,6,7])
返回 12
。
你可能期望第二个例子的行为相同,但实际上那里的 return
仅仅是退出 内部 函数(在 do
块内),并将值返回给 map
。因此 test2([5,6,7])
返回 [5,12,7]
。
当在顶层表达式中使用时(即在任何函数外部),return
会导致整个当前的顶层表达式提前终止。
do
— Keyworddo
创建一个匿名函数并将其作为第一个参数传递给函数调用。例如:
map(1:10) do x
2x
end
等价于 map(x->2x, 1:10)
。
使用多个参数,如下所示:
map(1:10, 11:20) do x, y
x + y
end
begin
— Keywordbegin
begin...end
表示一段代码块。
begin
println("Hello, ")
println("World!")
end
通常情况下,begin
是不必要的,因为像 function
和 let
这样的关键字会隐式地开始代码块。另见 ;
。
begin
也可以在索引时使用,表示集合的第一个索引或数组某个维度的第一个索引。例如,a[begin]
是数组 a
的第一个元素。
将 begin
作为索引的使用需要 Julia 1.4 或更高版本。
示例
julia> A = [1 2; 3 4]
2×2 Array{Int64,2}:
1 2
3 4
julia> A[begin, :]
2-element Array{Int64,1}:
1
2
end
— Keywordend
end
标志着一组表达式的结束,例如 module
, struct
, mutable struct
, begin
, let
, for
等。
end
也可以在索引时使用,表示集合的最后一个索引或数组某个维度的最后一个索引。
示例
julia> A = [1 2; 3 4]
2×2 Array{Int64, 2}:
1 2
3 4
julia> A[end, :]
2-element Array{Int64, 1}:
3
4
let
— Keywordlet
let
块创建一个新的硬作用域,并可选地引入新的局部绑定。
就像 其他作用域构造 一样,let
块定义了新引入的局部变量可访问的代码块。此外,语法对以逗号分隔的赋值和可能出现在与 let
同一行的变量名具有特殊含义:
let var1 = value1, var2, var3 = value3
code
end
在这一行引入的变量是 let
块的局部变量,赋值按顺序求值,每个右侧的值在不考虑左侧名称的作用域中求值。因此,写出 let x = x
这样的代码是有意义的,因为两个 x
变量是不同的,左侧的 x
在局部作用域中遮蔽了外部作用域的 x
。这甚至可以成为一个有用的习惯用法,因为每次进入局部作用域时都会新创建局部变量,但这仅在通过闭包存活于其作用域的变量的情况下可观察到。没有赋值的 let
变量,例如上面示例中的 var2
,声明了一个尚未绑定到值的新局部变量。
相比之下, begin
块也将多个表达式组合在一起,但不引入作用域或具有特殊的赋值语法。
示例
在下面的函数中,有一个单一的 x
被 map
迭代更新三次。返回的闭包都引用了那个 x
的最终值:
julia> function test_outer_x()
x = 0
map(1:3) do _
x += 1
return ()->x
end
end
test_outer_x (generic function with 1 method)
julia> [f() for f in test_outer_x()]
3-element Vector{Int64}:
3
3
3
然而,如果我们添加一个引入 新 局部变量的 let
块,我们将得到三个不同的变量被捕获(每次迭代一个),即使我们选择使用(遮蔽)相同的名称。
julia> function test_let_x()
x = 0
map(1:3) do _
x += 1
let x = x
return ()->x
end
end
end
test_let_x (generic function with 1 method)
julia> [f() for f in test_let_x()]
3-element Vector{Int64}:
1
2
3
所有引入新局部变量的作用域构造在重复运行时都表现得如此;let
的独特特征是其能够简洁地声明新的 local
,这些 local
可能遮蔽同名的外部变量。例如,直接使用 do
函数的参数同样捕获了三个不同的变量:
julia> function test_do_x()
map(1:3) do x
return ()->x
end
end
test_do_x (generic function with 1 method)
julia> [f() for f in test_do_x()]
3-element Vector{Int64}:
1
2
3
if
— Keywordif/elseif/else
if
/elseif
/else
执行条件评估,这允许根据布尔表达式的值来评估或不评估代码的某些部分。以下是 if
/elseif
/else
条件语法的结构:
if x < y
println("x 小于 y")
elseif x > y
println("x 大于 y")
else
println("x 等于 y")
end
如果条件表达式 x < y
为真,则相应的代码块被评估;否则,条件表达式 x > y
被评估,如果它为真,则相应的代码块被评估;如果两个表达式都不为真,则评估 else
块。elseif
和 else
块是可选的,可以使用任意数量的 elseif
块。
与某些其他语言相比,条件必须是 Bool
类型。条件不能仅仅转换为 Bool
。
julia> if 1 end
ERROR: TypeError: non-boolean (Int64) used in boolean context
for
— Keywordfor
for
循环在遍历一系列值时重复评估一组语句。
迭代变量始终是一个新变量,即使在封闭作用域中存在同名变量。使用 outer
来重用现有的局部变量进行迭代。
示例
julia> for i in [1, 4, 0]
println(i)
end
1
4
0
while
— Keywordwhile
while
循环重复评估条件表达式,并在表达式保持为真时继续评估 while 循环的主体。如果在第一次到达 while 循环时条件表达式为假,则主体永远不会被评估。
示例
julia> i = 1
1
julia> while i < 5
println(i)
global i += 1
end
1
2
3
4
break
— Keywordbreak
立即跳出循环。
示例
julia> i = 0
0
julia> while true
global i += 1
i > 5 && break
println(i)
end
1
2
3
4
5
continue
— Keyword继续
跳过当前循环迭代的其余部分。
示例
julia> for i = 1:6
iseven(i) && continue
println(i)
end
1
3
5
try
— Keywordtry/catch
try
/catch
语句允许拦截由 throw
抛出的错误(异常),以便程序执行可以继续。例如,以下代码尝试写入一个文件,但如果文件无法写入,则警告用户并继续执行,而不是终止执行:
try
open("/danger", "w") do f
println(f, "Hello")
end
catch
@warn "Could not write file."
end
或者,当文件无法读取到变量中时:
lines = try
open("/danger", "r") do f
readlines(f)
end
catch
@warn "File not found."
end
语法 catch e
(其中 e
是任何变量)将抛出的异常对象分配给 catch
块中的给定变量。
try
/catch
结构的强大之处在于能够立即将深度嵌套的计算展开到调用函数栈中的更高层次。
finally
— Keywordfinally
在给定代码块退出时运行一些代码,无论它是如何退出的。例如,以下是我们如何确保打开的文件被关闭:
f = open("file")
try
operate_on_file(f)
finally
close(f)
end
当控制离开try
块时(例如,由于return
或正常完成),close(f)
将被执行。如果try
块由于异常而退出,异常将继续传播。catch
块也可以与try
和finally
结合使用。在这种情况下,finally
块将在catch
处理完错误后运行。
quote
— Keywordquote
quote
在一个块中创建多个表达式对象,而不使用显式的 Expr
构造函数。例如:
ex = quote
x = 1
y = 2
x + y
end
与其他引用方式 :( ... )
不同,这种形式在表达式树中引入了 QuoteNode
元素,在直接操作树时必须考虑这些元素。出于其他目的,:( ... )
和 quote .. end
块被视为相同。
local
— Keywordlocal
local
引入一个新的局部变量。有关更多信息,请参见 manual section on variable scoping。
示例
julia> function foo(n)
x = 0
for i = 1:n
local x # 引入一个循环局部 x
x = i
end
x
end
foo (generic function with 1 method)
julia> foo(10)
0
global
— Keywordglobal
global x
使得当前作用域及其内部作用域中的 x
引用同名的全局变量。有关更多信息,请参见 manual section on variable scoping。
示例
julia> z = 3
3
julia> function foo()
global z = 6 # 使用在 foo 外部定义的 z 变量
end
foo (generic function with 1 method)
julia> foo()
6
julia> z
6
outer
— Keywordfor outer
在 for
循环中重用现有的局部变量进行迭代。
有关更多信息,请参见变量作用域手册部分。
另请参见for
。
示例
julia> function f()
i = 0
for i = 1:3
# empty
end
return i
end;
julia> f()
0
julia> function f()
i = 0
for outer i = 1:3
# empty
end
return i
end;
julia> f()
3
julia> i = 0 # 全局变量
for outer i = 1:3
end
ERROR: syntax: no outer local variable declaration exists for "for outer"
[...]
const
— Keywordconst
const
用于声明全局变量,其值不会改变。在几乎所有代码中(尤其是性能敏感的代码),全局变量应该以这种方式声明为常量。
const x = 5
可以在单个 const
中声明多个变量:
const y, z = 7, 11
请注意,const
仅适用于一个 =
操作,因此 const x = y = 1
声明 x
为常量,但不声明 y
。另一方面,const x = const y = 1
声明 x
和 y
都为常量。
请注意,“常量性”并不扩展到可变容器;只有变量与其值之间的关联是常量。如果 x
是一个数组或字典(例如),您仍然可以修改、添加或删除元素。
在某些情况下,改变 const
变量的值会发出警告而不是错误。然而,这可能会产生不可预测的行为或破坏程序的状态,因此应该避免。这一特性仅用于交互使用时的便利。
struct
— Keywordstruct
在Julia中最常用的类型是结构体,指定为一个名称和一组字段。
struct Point
x
y
end
字段可以有类型限制,这些限制可以是参数化的:
struct Point{X}
x::X
y::Float64
end
结构体还可以通过<:
语法声明一个抽象超类型:
struct Point <: AbstractPoint
x
y
end
struct
默认是不可变的;这些类型的实例在构造后不能被修改。请使用mutable struct
来声明一个可以修改其实例的类型。
有关更多详细信息,例如如何定义构造函数,请参见手册中的复合类型部分。
mutable struct
— Keyword可变结构体
mutable struct
类似于 struct
,但额外允许在构造后设置类型的字段。
可变结构体的单个字段可以标记为 const
以使其不可变:
mutable struct Baz
a::Int
const b::Float64
end
可变结构体字段的 const
关键字需要至少 Julia 1.8。
有关更多信息,请参阅手册中的 复合类型 部分。
Base.@kwdef
— Macro@kwdef typedef
这是一个辅助宏,它自动为在表达式 typedef
中声明的类型定义基于关键字的构造函数,该类型必须是 struct
或 mutable struct
表达式。默认参数通过声明形式为 field::T = default
或 field = default
的字段来提供。如果没有提供默认值,则关键字参数在生成的类型构造函数中变为必需的关键字参数。
内部构造函数仍然可以定义,但至少一个应该接受与默认内部构造函数相同形式的参数(即每个字段一个位置参数),以便与关键字外部构造函数正确配合使用。
对于参数化结构体和具有超类型的结构体,Base.@kwdef
至少需要 Julia 1.1。
从 Julia 1.9 开始,该宏被导出。
示例
julia> @kwdef struct Foo
a::Int = 1 # 指定的默认值
b::String # 必需的关键字
end
Foo
julia> Foo(b="hi")
Foo(1, "hi")
julia> Foo()
ERROR: UndefKeywordError: 关键字参数 `b` 未分配
Stacktrace:
[...]
abstract type
— Keyword抽象类型
抽象类型
声明一个不能被实例化的类型,仅作为类型图中的一个节点,从而描述一组相关的具体类型:那些具体类型是它们的子类。抽象类型形成了概念层次结构,使得 Julia 的类型系统不仅仅是对象实现的集合。例如:
abstract type Number end
abstract type Real <: Number end
primitive type
— Keyword原始类型
原始类型
声明一个具体类型,其数据仅由一系列位组成。原始类型的经典示例是整数和浮点值。一些内置原始类型声明的示例:
primitive type Char 32 end
primitive type Bool <: Integer 8 end
名称后面的数字表示该类型所需的存储位数。目前,仅支持8位的倍数大小。Bool
声明显示了如何将原始类型可选地声明为某个超类型的子类型。
where
— Keywordwhere
where
关键字创建一个 UnionAll
类型,可以被视为对某个变量的所有值进行的其他类型的迭代联合。例如 Vector{T} where T<:Real
包含所有元素类型为某种 Real
数字的 Vector
。
如果省略变量绑定,默认绑定为 Any
:
Vector{T} where T # 简写为 `where T<:Any`
变量也可以有下界:
Vector{T} where T>:Int
Vector{T} where Int<:T<:Real
对于嵌套的 where
表达式,还有一种简洁的语法。例如,这个:
Pair{T, S} where S<:Array{T} where T<:Number
可以简化为:
Pair{T, S} where {T<:Number, S<:Array{T}}
这种形式通常出现在方法签名中。
请注意,在这种形式中,变量按外层优先的顺序列出。这与使用语法 T{p1, p2, ...}
将类型“应用”到参数值时变量的替换顺序相匹配。
...
— Keyword“展开”运算符 `...` 表示一系列参数。`...` 可以在函数定义中使用,以指示该函数接受任意数量的参数。`...` 还可以用于将函数应用于一系列参数。
# 示例
jldoctest julia> add(xs...) = reduce(+, xs) add (generic function with 1 method)
julia> add(1, 2, 3, 4, 5) 15
julia> add([1, 2, 3]...) 6
julia> add(7, 1:100..., 1000:1100...) 111107
;
— Keyword;
;
在 Julia 中的作用与许多 C 类语言相似,用于分隔前一个语句的结束。
;
在行末并不是必需的,但可以用于在单行中分隔语句或将语句连接成一个表达式。
在 REPL 中,在行末添加 ;
将抑制该表达式结果的打印。
在函数声明中,以及在调用中可选地,;
用于分隔常规参数和关键字参数。
在数组字面量中,用分号分隔的参数其内容会被连接在一起。由单个 ;
组成的分隔符会垂直连接(即沿着第一个维度),;;
会水平连接(第二维度),;;;
会沿着第三维度连接,等等。这样的分隔符也可以在方括号的最后位置使用,以添加长度为 1 的尾随维度。
在括号内的首个位置的 ;
可以用于构造命名元组。相同的 (; ...)
语法在赋值的左侧允许进行属性解构。
在标准 REPL 中,在空行上输入 ;
将切换到 shell 模式。
示例
julia> function foo()
x = "Hello, "; x *= "World!"
return x
end
foo (generic function with 1 method)
julia> bar() = (x = "Hello, Mars!"; return x)
bar (generic function with 1 method)
julia> foo();
julia> bar()
"Hello, Mars!"
julia> function plot(x, y; style="solid", width=1, color="black")
###
end
julia> A = [1 2; 3 4]
2×2 Matrix{Int64}:
1 2
3 4
julia> [1; 3;; 2; 4;;; 10*A]
2×2×2 Array{Int64, 3}:
[:, :, 1] =
1 2
3 4
[:, :, 2] =
10 20
30 40
julia> [2; 3;;;]
2×1×1 Array{Int64, 3}:
[:, :, 1] =
2
3
julia> nt = (; x=1) # 如果没有 `;` 或尾随逗号,这将赋值给 x
(x = 1,)
julia> key = :a; c = 3;
julia> nt2 = (; key => 1, b=2, c, nt.x)
(a = 1, b = 2, c = 3, x = 1)
julia> (; b, x) = nt2; # 使用属性解构设置变量 b 和 x
julia> b, x
(2, 1)
julia> ; # 输入 `;` 后,提示符(就地)更改为: shell>
shell> echo hello
hello
=
— Keyword=
=
是赋值运算符。
- 对于变量
a
和表达式b
,a = b
使a
指向b
的值。 - 对于函数
f(x)
,f(x) = x
定义了一个新的函数常量f
,或者如果f
已经定义,则向f
添加一个新方法;这种用法等同于function f(x); x; end
。 a[i] = v
调用setindex!
(a,v,i)
。a.b = c
调用setproperty!
(a,:b,c)
。- 在函数调用内部,
f(a=b)
将b
作为关键字参数a
的值传递。 - 在带逗号的括号内,
(a=1,)
构造一个NamedTuple
。
示例
将 a
赋值为 b
并不会创建 b
的副本;相反,使用 copy
或 deepcopy
。
julia> b = [1]; a = b; b[1] = 2; a
1-element Array{Int64, 1}:
2
julia> b = [1]; a = copy(b); b[1] = 2; a
1-element Array{Int64, 1}:
1
传递给函数的集合也不会被复制。函数可以修改(变更)其参数所指向对象的内容。(执行此操作的函数名称通常以 '!' 结尾。)
julia> function f!(x); x[:] .+= 1; end
f! (generic function with 1 method)
julia> a = [1]; f!(a); a
1-element Array{Int64, 1}:
2
赋值可以并行操作多个变量,从可迭代对象中获取值:
julia> a, b = 4, 5
(4, 5)
julia> a, b = 1:3
1:3
julia> a, b
(1, 2)
赋值可以串行操作多个变量,并将返回最右侧表达式的值:
julia> a = [1]; b = [2]; c = [3]; a = b = c
1-element Array{Int64, 1}:
3
julia> b[1] = 2; a, b, c
([2], [2], [2])
在越界索引处的赋值不会扩展集合。如果集合是 Vector
,则可以使用 push!
或 append!
来扩展。
julia> a = [1, 1]; a[3] = 2
ERROR: BoundsError: attempt to access 2-element Array{Int64, 1} at index [3]
[...]
julia> push!(a, 2, 3)
4-element Array{Int64, 1}:
1
1
2
3
赋值 []
不会从集合中删除元素;相反,使用 filter!
。
julia> a = collect(1:3); a[a .<= 1] = []
ERROR: DimensionMismatch: tried to assign 0 elements to 1 destinations
[...]
julia> filter!(x -> x > 1, a) # in-place & thus more efficient than a = a[a .> 1]
2-element Array{Int64, 1}:
2
3
?:
— Keyworda ? b : c
条件的简写形式;读作“如果 a
,则计算 b
,否则计算 c
”。也称为三元运算符。
这种语法等价于 if a; b else c end
,但通常用于强调作为更大表达式一部分的值 b
或 c
,而不是计算 b
或 c
可能产生的副作用。
有关更多详细信息,请参见手册中的控制流部分。
示例
julia> x = 1; y = 2;
julia> x > y ? println("x is larger") : println("x is not larger")
x is not larger
julia> x > y ? "x is larger" : x == y ? "x and y are equal" : "y is larger"
"y is larger"
Standard Modules
Main
— Module主模块
主模块
是顶级模块,Julia 从 主模块
开始并将其设置为当前模块。在提示符下定义的变量放在 主模块
中,varinfo
列出 主模块
中的变量。
julia> @__MODULE__
主模块
Core
— ModuleCore
Core
是包含所有被认为是“内置”的标识符的模块,即核心语言的一部分,而不是库。每个模块隐式地指定 using Core
,因为没有这些定义你无法做任何事情。
Base
— ModuleBase
Julia的基础库。Base
是一个包含基本功能的模块(base/
的内容)。所有模块隐式地包含using Base
,因为在绝大多数情况下这是必需的。
Base Submodules
Base.Broadcast
— ModuleBase.Broadcast
包含广播实现的模块。
Base.Docs
— ModuleBase.Iterators
— Module处理迭代器的方法。
Base.Libc
— Modulelibc 的接口,C 标准库。
Base.Meta
— Module元编程的便利函数。
Base.StackTraces
— Module用于收集和处理堆栈跟踪的工具。主要用于构建错误。
Base.Sys
— Module提供检索有关硬件和操作系统信息的方法。
Base.Threads
— Module多线程支持。
Base.GC
— ModuleBase.GC
具有垃圾回收工具的模块。
All Objects
Core.:===
— Function===(x,y) -> Bool
≡(x,y) -> Bool
确定 x
和 y
是否相同,意思是没有程序能够区分它们。首先比较 x
和 y
的类型。如果类型相同,则可变对象通过内存地址进行比较,而不可变对象(例如数字)则通过位级内容进行比较。这个函数有时被称为 "egal"。它总是返回一个 Bool
值。
示例
julia> a = [1, 2]; b = [1, 2];
julia> a == b
true
julia> a === b
false
julia> a === a
true
Core.isa
— Functionisa(x, type) -> Bool
确定 x
是否为给定的 type
。也可以用作中缀运算符,例如 x isa type
。
示例
julia> isa(1, Int)
true
julia> isa(1, Matrix)
false
julia> isa(1, Char)
false
julia> isa(1, Number)
true
julia> 1 isa Number
true
Base.isequal
— Functionisequal(x, y) -> Bool
类似于 ==
,但在处理浮点数和缺失值时有所不同。isequal
将所有浮点 NaN
值视为相等,将 -0.0
视为不等于 0.0
,并将 missing
视为等于 missing
。始终返回一个 Bool
值。
isequal
是一种等价关系 - 它是自反的(===
意味着 isequal
),对称的(isequal(a, b)
意味着 isequal(b, a)
)和传递的(isequal(a, b)
和 isequal(b, c)
意味着 isequal(a, c)
)。
实现
isequal
的默认实现调用 ==
,因此一个不涉及浮点值的类型通常只需要定义 ==
。
isequal
是哈希表(Dict
)使用的比较函数。isequal(x,y)
必须意味着 hash(x) == hash(y)
。
这通常意味着,对于存在自定义 ==
或 isequal
方法的类型,必须实现相应的 hash
方法(反之亦然)。集合通常通过对所有内容递归调用 isequal
来实现 isequal
。
此外,isequal
与 isless
相关联,它们共同定义了一个固定的全序关系,其中 isequal(x, y)
、isless(x, y)
或 isless(y, x)
中恰好有一个必须为 true
(其他两个为 false
)。
标量类型通常不需要单独实现 isequal
,除非它们表示的浮点数可以实现比作为通用后备提供的更高效的实现(基于 isnan
、signbit
和 ==
)。
示例
julia> isequal([1., NaN], [1., NaN])
true
julia> [1., NaN] == [1., NaN]
false
julia> 0.0 == -0.0
true
julia> isequal(0.0, -0.0)
false
julia> missing == missing
missing
julia> isequal(missing, missing)
true
isequal(x)
创建一个函数,该函数使用 isequal
将其参数与 x
进行比较,即一个等价于 y -> isequal(y, x)
的函数。
返回的函数类型为 Base.Fix2{typeof(isequal)}
,可用于实现专门的方法。
Base.isless
— Functionisless(x, y)
测试 x
是否小于 y
,根据固定的全序(与 isequal
一起定义)。isless
并未为所有类型的对 (x, y)
定义。然而,如果它被定义,则期望满足以下条件:
- 如果
isless(x, y)
被定义,则isless(y, x)
和isequal(x, y)
也被定义,并且这三者中恰好有一个返回true
。 isless
定义的关系是传递的,即isless(x, y) && isless(y, z)
意味着isless(x, z)
。
通常无序的值,如 NaN
,在常规值之后排序。 missing
值排在最后。
这是 sort!
使用的默认比较。
实现
具有全序的非数值类型应实现此函数。数值类型仅在具有特殊值(如 NaN
)时需要实现它。具有部分序的类型应实现 <
。有关如何定义可用于排序和相关函数的替代排序方法,请参见 Alternate Orderings 的文档。
示例
julia> isless(1, 3)
true
julia> isless("Red", "Blue")
false
Base.isunordered
— Functionisunordered(x)
如果 x
是一个无法根据 <
排序的值,例如 NaN
或 missing
,则返回 true
。
使用此谓词评估为 true
的值可能在其他排序(例如 isless
)中是可排序的。
此函数需要 Julia 1.7 或更高版本。
Base.ifelse
— Functionifelse(condition::Bool, x, y)
如果 condition
为 true
,则返回 x
,否则返回 y
。这与 ?
或 if
的不同之处在于它是一个普通函数,因此所有参数都会先被求值。在某些情况下,使用 ifelse
而不是 if
语句可以消除生成代码中的分支,并在紧密循环中提供更高的性能。
示例
julia> ifelse(1 > 2, 1, 2)
2
Core.typeassert
— Functiontypeassert(x, type)
除非 x isa type
,否则抛出一个 TypeError
。语法 x::type
调用此函数。
示例
julia> typeassert(2.5, Int)
ERROR: TypeError: in typeassert, expected Int64, got a value of type Float64
Stacktrace:
[...]
Core.typeof
— Functiontypeof(x)
获取 x
的具体类型。
另见 eltype
。
示例
julia> a = 1//2;
julia> typeof(a)
Rational{Int64}
julia> M = [1 2; 3.5 4];
julia> typeof(M)
Matrix{Float64} (alias for Array{Float64, 2})
Core.tuple
— Functiontuple(xs...)
构造给定对象的元组。
另见 Tuple
, ntuple
, NamedTuple
。
示例
julia> tuple(1, 'b', pi)
(1, 'b', π)
julia> ans === (1, 'b', π)
true
julia> Tuple(Real[1, 2, pi]) # 接受一个集合
(1, 2, π)
Base.ntuple
— Functionntuple(f, n::Integer)
创建一个长度为 n
的元组,计算每个元素为 f(i)
,其中 i
是元素的索引。
示例
julia> ntuple(i -> 2*i, 4)
(2, 4, 6, 8)
ntuple(f, ::Val{N})
创建一个长度为 N
的元组,计算每个元素为 f(i)
,其中 i
是元素的索引。通过传递 Val(N)
参数,这个版本的 ntuple 可能生成比将长度作为整数的版本更高效的代码。但是在 N
不能在编译时确定的情况下,ntuple(f, N)
比 ntuple(f, Val(N))
更可取。
示例
julia> ntuple(i -> 2*i, Val(4))
(2, 4, 6, 8)
Base.objectid
— Functionobjectid(x) -> UInt
根据对象身份获取 x
的哈希值。
如果 x === y
,则 objectid(x) == objectid(y)
,通常当 x !== y
时,objectid(x) != objectid(y)
。
Base.hash
— Functionhash(x[, h::UInt]) -> UInt
计算一个整数哈希码,使得 isequal(x,y)
意味着 hash(x)==hash(y)
。可选的第二个参数 h
是另一个哈希码,用于与结果混合。
新类型应该实现两参数形式,通常通过递归调用两参数 hash
方法来混合内容的哈希与 h
。通常,任何实现 hash
的类型也应该实现其自己的 ==
(因此 isequal
),以保证上述属性。
当启动一个新的 Julia 进程时,哈希值可能会改变。
julia> a = hash(10)
0x95ea2955abd45275
julia> hash(10, a) # 仅使用另一个哈希函数的输出作为第二个参数
0xd42bad54a8575b16
Base.finalizer
— Functionfinalizer(f, x)
注册一个函数 f(x)
,当没有程序可访问的对 x
的引用时调用,并返回 x
。x
的类型必须是 mutable struct
,否则该函数将抛出异常。
f
不能导致任务切换,这排除了大多数 I/O 操作,例如 println
。使用 @async
宏(将上下文切换推迟到最终器外部)或 ccall
直接调用 C 中的 I/O 函数可能对调试有帮助。
请注意,执行 f
时没有保证的世界年龄。它可能在注册最终器的世界年龄或任何后来的世界年龄中被调用。
示例
finalizer(my_mutable_struct) do x
@async println("Finalizing $x.")
end
finalizer(my_mutable_struct) do x
ccall(:jl_safe_printf, Cvoid, (Cstring, Cstring), "Finalizing %s.", repr(x))
end
可以在对象构造时注册最终器。在以下示例中,请注意我们隐式依赖于最终器返回新创建的可变结构体 x
。
mutable struct MyMutableStruct
bar
function MyMutableStruct(bar)
x = new(bar)
f(t) = @async println("Finalizing $t.")
finalizer(f, x)
end
end
Base.finalize
— Functionfinalize(x)
立即运行为对象 x
注册的终结器。
Base.copy
— FunctionBase.deepcopy
— Functiondeepcopy(x)
创建 x
的深拷贝:所有内容都被递归复制,结果是一个完全独立的对象。例如,深拷贝一个数组会创建它所包含的所有对象的深拷贝,并生成一个具有一致关系结构的新数组(例如,如果原始数组的前两个元素是同一个对象,则新数组的前两个元素也将是相同的 deepcopy
ed 对象)。对一个对象调用 deepcopy
通常应该具有与序列化然后反序列化它相同的效果。
虽然通常不需要,但用户定义的类型可以通过定义函数 deepcopy_internal(x::T, dict::IdDict)
的专门版本来覆盖默认的 deepcopy
行为(该函数不应被其他方式使用),其中 T
是要专门化的类型,dict
用于跟踪在递归过程中已复制的对象。在定义中,deepcopy_internal
应该替代 deepcopy
使用,并且在返回之前应适当地更新 dict
变量。
Base.getproperty
— Functiongetproperty(value, name::Symbol)
getproperty(value, name::Symbol, order::Symbol)
语法 a.b
调用 getproperty(a, :b)
。语法 @atomic order a.b
调用 getproperty(a, :b, :order)
,而语法 @atomic a.b
调用 getproperty(a, :b, :sequentially_consistent)
。
示例
julia> struct MyType{T <: Number}
x::T
end
julia> function Base.getproperty(obj::MyType, sym::Symbol)
if sym === :special
return obj.x + 1
else # fallback to getfield
return getfield(obj, sym)
end
end
julia> obj = MyType(1);
julia> obj.special
2
julia> obj.x
1
只有在必要时才应重载 getproperty
,因为如果语法 obj.f
的行为不寻常,可能会造成困惑。还要注意,使用方法通常更可取。有关更多信息,请参见此风格指南文档:Prefer exported methods over direct field access。
另请参见 getfield
,propertynames
和 setproperty!
。
Base.setproperty!
— Functionsetproperty!(value, name::Symbol, x)
setproperty!(value, name::Symbol, x, order::Symbol)
语法 a.b = c
调用 setproperty!(a, :b, c)
。语法 @atomic order a.b = c
调用 setproperty!(a, :b, c, :order)
,而语法 @atomic a.b = c
调用 setproperty!(a, :b, c, :sequentially_consistent)
。
在模块上使用 setproperty!
至少需要 Julia 1.8。
另请参见 setfield!
, propertynames
和 getproperty
。
Base.replaceproperty!
— Functionreplaceproperty!(x, f::Symbol, expected, desired, success_order::Symbol=:not_atomic, fail_order::Symbol=success_order)
对 x.f
执行比较并交换操作,将其从 expected
更改为 desired
,按照平等原则。可以使用语法 @atomicreplace x.f expected => desired
来代替函数调用形式。
Base.swapproperty!
— Functionswapproperty!(x, f::Symbol, v, order::Symbol=:not_atomic)
语法 @atomic a.b, _ = c, a.b
返回 (c, swapproperty!(a, :b, c, :sequentially_consistent))
,其中两边必须有一个共同的 getproperty
表达式。
另请参见 swapfield!
和 setproperty!
。
Base.modifyproperty!
— Functionmodifyproperty!(x, f::Symbol, op, v, order::Symbol=:not_atomic)
语法 @atomic op(x.f, v)
(及其等效形式 @atomic x.f op v
)返回 modifyproperty!(x, :f, op, v, :sequentially_consistent)
,其中第一个参数必须是 getproperty
表达式,并且是以原子方式修改的。
调用 op(getproperty(x, f), v)
必须返回一个可以默认存储在对象 x
的字段 f
中的值。特别地,与 setproperty!
的默认行为不同,convert
函数不会被自动调用。
另请参见 modifyfield!
和 setproperty!
。
Base.setpropertyonce!
— Functionsetpropertyonce!(x, f::Symbol, value, success_order::Symbol=:not_atomic, fail_order::Symbol=success_order)
对 x.f
执行比较并交换操作,如果之前未设置,则将其设置为 value
。可以使用语法 @atomiconce x.f = value
来代替函数调用形式。
另请参见 setfieldonce!
, setproperty!
, replaceproperty!
.
此函数需要 Julia 1.11 或更高版本。
Base.propertynames
— Functionpropertynames(x, private=false)
获取对象 x
的属性(x.property
)的元组或向量。这通常与 fieldnames(typeof(x))
相同,但重载 getproperty
的类型通常也应该重载 propertynames
以获取该类型实例的属性。
propertynames(x)
可能只返回作为 x
文档接口一部分的“公共”属性名称。如果您希望它还返回用于内部使用的“私有”属性名称,请将可选的第二个参数设置为 true
。在 x.
上的 REPL 标签补全仅显示 private=false
属性。
另请参见:hasproperty
,hasfield
。
Base.hasproperty
— Functionhasproperty(x, s::Symbol)
返回一个布尔值,指示对象 x
是否将 s
作为其自身的属性之一。
此函数至少需要 Julia 1.2。
另请参见: propertynames
, hasfield
.
Core.getfield
— Functiongetfield(value, name::Symbol, [order::Symbol])
getfield(value, i::Int, [order::Symbol])
通过名称或位置从复合 value
中提取字段。可以选择性地为操作定义一个排序。如果字段被声明为 @atomic
,则强烈建议该规范与该位置的存储兼容。否则,如果未声明为 @atomic
,则如果指定,则此参数必须为 :not_atomic
。另请参见 getproperty
和 fieldnames
。
示例
julia> a = 1//2
1//2
julia> getfield(a, :num)
1
julia> a.num
1
julia> getfield(a, 1)
1
Core.setfield!
— Functionsetfield!(value, name::Symbol, x, [order::Symbol])
setfield!(value, i::Int, x, [order::Symbol])
将 x
赋值给可组合类型 value
中的命名字段。value
必须是可变的,x
必须是 fieldtype(typeof(value), name)
的子类型。此外,可以为此操作指定一个顺序。如果字段被声明为 @atomic
,则此规范是强制性的。否则,如果未声明为 @atomic
,则如果指定,必须为 :not_atomic
。另请参见 setproperty!
。
示例
julia> mutable struct MyMutableStruct
field::Int
end
julia> a = MyMutableStruct(1);
julia> setfield!(a, :field, 2);
julia> getfield(a, :field)
2
julia> a = 1//2
1//2
julia> setfield!(a, :num, 3);
ERROR: setfield!: immutable struct of type Rational cannot be changed
Core.modifyfield!
— Functionmodifyfield!(value, name::Symbol, op, x, [order::Symbol]) -> Pair
modifyfield!(value, i::Int, op, x, [order::Symbol]) -> Pair
原子性地执行操作以获取和设置字段,应用函数 op
。
y = getfield(value, name)
z = op(y, x)
setfield!(value, name, z)
return y => z
如果硬件支持(例如,原子递增),这可能会优化为适当的硬件指令,否则将使用循环。
此函数需要 Julia 1.7 或更高版本。
Core.replacefield!
— Functionreplacefield!(value, name::Symbol, expected, desired,
[success_order::Symbol, [fail_order::Symbol=success_order]) -> (; old, success::Bool)
replacefield!(value, i::Int, expected, desired,
[success_order::Symbol, [fail_order::Symbol=success_order]) -> (; old, success::Bool)
原子性地执行操作以获取并有条件地将字段设置为给定值。
y = getfield(value, name, fail_order)
ok = y === expected
if ok
setfield!(value, name, desired, success_order)
end
return (; old = y, success = ok)
如果硬件支持,这可能会优化为适当的硬件指令,否则将使用循环。
此函数需要 Julia 1.7 或更高版本。
Core.swapfield!
— Functionswapfield!(value, name::Symbol, x, [order::Symbol])
swapfield!(value, i::Int, x, [order::Symbol])
原子性地执行操作以同时获取和设置字段:
y = getfield(value, name)
setfield!(value, name, x)
return y
此函数需要 Julia 1.7 或更高版本。
Core.setfieldonce!
— Functionsetfieldonce!(value, name::Union{Int,Symbol}, desired,
[success_order::Symbol, [fail_order::Symbol=success_order]) -> success::Bool
原子地执行操作,将字段设置为给定值,仅在之前未设置的情况下。
ok = !isdefined(value, name, fail_order)
if ok
setfield!(value, name, desired, success_order)
end
return ok
此函数需要 Julia 1.11 或更高版本。
Core.isdefined
— Functionisdefined(m::Module, s::Symbol, [order::Symbol])
isdefined(object, s::Symbol, [order::Symbol])
isdefined(object, index::Int, [order::Symbol])
测试全局变量或对象字段是否已定义。参数可以是一个模块和一个符号,或者一个复合对象和字段名称(作为符号)或索引。可选地,可以为操作定义一个顺序。如果字段被声明为 @atomic
,则强烈建议该规范与对该位置的存储兼容。否则,如果未声明为 @atomic
,则如果指定,此参数必须为 :not_atomic
。
要测试数组元素是否已定义,请使用 isassigned
代替。
另请参见 @isdefined
。
示例
julia> isdefined(Base, :sum)
true
julia> isdefined(Base, :NonExistentMethod)
false
julia> a = 1//2;
julia> isdefined(a, 2)
true
julia> isdefined(a, 3)
false
julia> isdefined(a, :num)
true
julia> isdefined(a, :numerator)
false
Base.@isdefined
— Macro@isdefined s -> Bool
测试变量 s
是否在当前作用域中定义。
另请参见 isdefined
以获取字段属性,以及 isassigned
以获取数组索引或 haskey
以获取其他映射。
示例
julia> @isdefined newvar
false
julia> newvar = 1
1
julia> @isdefined newvar
true
julia> function f()
println(@isdefined x)
x = 3
println(@isdefined x)
end
f (generic function with 1 method)
julia> f()
false
true
Base.convert
— Functionconvert(T, x)
将 x
转换为类型 T
的值。
如果 T
是 Integer
类型,当 x
不能被 T
表示时,将引发 InexactError
,例如如果 x
不是整数值,或者超出了 T
支持的范围。
示例
julia> convert(Int, 3.0)
3
julia> convert(Int, 3.5)
ERROR: InexactError: Int64(3.5)
Stacktrace:
[...]
如果 T
是 AbstractFloat
类型,则它将返回最接近 x
的 T
可表示的值。对于确定最近值的目的,Inf 被视为比 floatmax(T)
大一个 ulp。
julia> x = 1/3
0.3333333333333333
julia> convert(Float32, x)
0.33333334f0
julia> convert(BigFloat, x)
0.333333333333333314829616256247390992939472198486328125
如果 T
是集合类型,而 x
是一个集合,则 convert(T, x)
的结果可能与 x
的全部或部分别名。
julia> x = Int[1, 2, 3];
julia> y = convert(Vector{Int}, x);
julia> y === x
true
另请参见: round
, trunc
, oftype
, reinterpret
. ```
Base.promote
— Functionpromote(xs...)
将所有参数转换为一个共同类型,并将它们全部返回(作为一个元组)。如果没有参数可以转换,则会引发错误。
另请参见: promote_type
, promote_rule
.
示例
julia> promote(Int8(1), Float16(4.5), Float32(4.1))
(1.0f0, 4.5f0, 4.1f0)
julia> promote_type(Int8, Float16, Float32)
Float32
julia> reduce(Base.promote_typejoin, (Int8, Float16, Float32))
Real
julia> promote(1, "x")
ERROR: promotion of types Int64 and String failed to change any arguments
[...]
julia> promote_type(Int, String)
Any
Base.oftype
— Functionoftype(x, y)
将 y
转换为 x
的类型,即 convert(typeof(x), y)
。
示例
julia> x = 4;
julia> y = 3.;
julia> oftype(x, y)
3
julia> oftype(y, x)
4.0
Base.widen
— Functionwiden(x)
如果 x
是一个类型,返回一个“更大”的类型,定义为算术运算 +
和 -
保证不会溢出或失去精度,适用于类型 x
可以容纳的任何值组合。
对于小于 128 位的固定大小整数类型,widen
将返回一个位数是原来的两倍的类型。
如果 x
是一个值,它将被转换为 widen(typeof(x))
。
示例
julia> widen(Int32)
Int64
julia> widen(1.5f0)
1.5
Base.identity
— Functionidentity(x)
恒等函数。返回其参数。
另见:one
、oneunit
和 LinearAlgebra
的 I
。
示例
julia> identity("Well, what did you expect?")
"Well, what did you expect?"
Core.WeakRef
— TypeWeakRef(x)
w = WeakRef(x)
构造一个对 Julia 值 x
的 弱引用:尽管 w
包含对 x
的引用,但它并不阻止 x
被垃圾回收。w.value
要么是 x
(如果 x
尚未被垃圾回收),要么是 nothing
(如果 x
已被垃圾回收)。
julia> x = "a string"
"a string"
julia> w = WeakRef(x)
WeakRef("a string")
julia> GC.gc()
julia> w # 通过 `x` 维护一个引用
WeakRef("a string")
julia> x = nothing # 清除引用
julia> GC.gc()
julia> w
WeakRef(nothing)
Properties of Types
Type relations
Base.supertype
— Functionsupertype(T::DataType)
返回数据类型 T
的超类型。
示例
julia> supertype(Int32)
Signed
Core.Type
— TypeCore.Type{T}
Core.Type
是一个抽象类型,其所有类型对象都是它的实例。单例类型 Core.Type{T}
的唯一实例是对象 T
。
示例
julia> isa(Type{Float64}, Type)
true
julia> isa(Float64, Type)
true
julia> isa(Real, Type{Float64})
false
julia> isa(Real, Type{Real})
true
Core.DataType
— TypeDataType <: Type{T}
DataType
表示显式声明的具有名称的类型、显式声明的超类型,以及可选的参数。系统中的每个具体值都是某个 DataType
的实例。
示例
julia> typeof(Real)
DataType
julia> typeof(Int)
DataType
julia> struct Point
x::Int
y
end
julia> typeof(Point)
DataType
Core.:<:
— Function<:(T1, T2)
子类型运算符:仅当类型 T1
的所有值也属于类型 T2
时返回 true
。
示例
julia> Float64 <: AbstractFloat
true
julia> Vector{Int} <: AbstractArray
true
julia> Matrix{Float64} <: Matrix{AbstractFloat}
false
Base.:>:
— Function>:(T1, T2)
超类型运算符,相当于 T2 <: T1
。
Base.typejoin
— Functiontypejoin(T, S, ...)
返回类型 T
和 S
的最近公共祖先,即它们都继承的最窄类型。对额外的可变参数进行递归。
示例
julia> typejoin(Int, Float64)
Real
julia> typejoin(Int, Float64, ComplexF32)
Number
Base.typeintersect
— Functiontypeintersect(T::Type, S::Type)
计算一个包含 T
和 S
交集的类型。通常这将是最小的这样的类型或接近它的一个类型。
一个保证精确行为的特殊情况:当 T <: S
时,typeintersect(S, T) == T == typeintersect(T, S)
。
Base.promote_type
— Functionpromote_type(type1, type2, ...)
提升指的是将混合类型的值转换为单一的公共类型。promote_type
表示 Julia 中默认的提升行为,当运算符(通常是数学运算)接收到不同类型的参数时。promote_type
通常尝试返回一种类型,该类型至少可以近似表示任一输入类型的大多数值,而不会过度扩展。某些损失是可以容忍的;例如,promote_type(Int64, Float64)
返回 Float64
,即使严格来说,并非所有 Int64
值都可以精确表示为 Float64
值。
另请参见:promote
,promote_typejoin
,promote_rule
。
示例
julia> promote_type(Int64, Float64)
Float64
julia> promote_type(Int32, Int64)
Int64
julia> promote_type(Float32, BigInt)
BigFloat
julia> promote_type(Int16, Float16)
Float16
julia> promote_type(Int64, Float16)
Float16
julia> promote_type(Int8, UInt16)
UInt16
要为您自己的类型重载提升,您应该重载 promote_rule
。promote_type
在内部调用 promote_rule
来确定类型。直接重载 promote_type
可能会导致歧义错误。
Base.promote_rule
— Functionpromote_rule(type1, type2)
指定在给定类型为 type1
和 type2
的值时,promote
应使用的类型。此函数不应直接调用,但应根据需要为新类型添加定义。
Base.promote_typejoin
— Functionpromote_typejoin(T, S)
计算一个包含 T
和 S
的类型,这可能是两个类型的父类型,或者在适当的情况下是一个 Union
。回退到 typejoin
。
另见 promote
, promote_type
。
示例
julia> Base.promote_typejoin(Int, Float64)
Real
julia> Base.promote_type(Int, Float64)
Float64
Base.isdispatchtuple
— Functionisdispatchtuple(T)
确定类型 T
是否为元组“叶类型”,这意味着它可以作为调度中的类型签名出现,并且没有可以出现在调用中的子类型(或超类型)。如果 T
不是一个类型,则返回 false
。
Declared structure
Base.ismutable
— Functionismutable(v) -> Bool
仅当值 v
是可变的时返回 true
。有关不可变性的讨论,请参见 Mutable Composite Types。请注意,此函数作用于值,因此如果您给它一个 DataType
,它会告诉您该类型的值是可变的。
出于技术原因,ismutable
对某些特殊类型的值(例如 String
和 Symbol
)返回 true
,尽管它们不能以允许的方式被修改。
另请参见 isbits
,isstructtype
。
示例
julia> ismutable(1)
false
julia> ismutable([1,2])
true
此函数至少需要 Julia 1.5。
Base.isimmutable
— Functionisimmutable(v) -> Bool
考虑使用 !ismutable(v)
,因为 isimmutable(v)
将在未来的版本中被 !ismutable(v)
替代。 (自 Julia 1.5 起)
返回 true
当且仅当值 v
是不可变的。有关不可变性的讨论,请参见 Mutable Composite Types。请注意,此函数作用于值,因此如果您给它一个类型,它会告诉您 DataType
的值是可变的。
示例
julia> isimmutable(1)
true
julia> isimmutable([1,2])
false
Base.ismutabletype
— Functionismutabletype(T) -> Bool
确定类型 T
是否被声明为可变类型(即使用 mutable struct
关键字)。如果 T
不是一个类型,则返回 false
。
此函数至少需要 Julia 1.7。
Base.isabstracttype
— Functionisabstracttype(T)
确定类型 T
是否被声明为抽象类型(即使用 abstract type
语法)。请注意,这并不是 isconcretetype(T)
的否定。如果 T
不是一个类型,则返回 false
。
示例
julia> isabstracttype(AbstractArray)
true
julia> isabstracttype(Vector)
false
Base.isprimitivetype
— Functionisprimitivetype(T) -> Bool
确定类型 T
是否被声明为原始类型(即使用 primitive type
语法)。如果 T
不是一个类型,则返回 false
。
Base.issingletontype
— FunctionBase.issingletontype(T)
确定类型 T
是否只有一个可能的实例;例如,一个除了其他单例值外没有字段的结构类型。如果 T
不是一个具体类型,则返回 false
。
Base.isstructtype
— Functionisstructtype(T) -> Bool
确定类型 T
是否被声明为结构类型(即使用 struct
或 mutable struct
关键字)。如果 T
不是一个类型,则返回 false
。
Base.nameof
— Methodnameof(t::DataType) -> Symbol
获取(可能被 UnionAll
包裹的)DataType
的名称(不包括其父模块),作为符号。
示例
julia> module Foo
struct S{T}
end
end
Foo
julia> nameof(Foo.S{T} where T)
:S
Base.fieldnames
— Functionfieldnames(x::DataType)
获取一个元组,包含 DataType
的字段名称。
另见 propertynames
, hasfield
。
示例
julia> fieldnames(Rational)
(:num, :den)
julia> fieldnames(typeof(1+im))
(:re, :im)
Base.fieldname
— Functionfieldname(x::DataType, i::Integer)
获取 DataType
的字段 i
的名称。
示例
julia> fieldname(Rational, 1)
:num
julia> fieldname(Rational, 2)
:den
Core.fieldtype
— Functionfieldtype(T, name::Symbol | index::Int)
确定复合数据类型 T
中字段(由名称或索引指定)的声明类型。
示例
julia> struct Foo
x::Int64
y::String
end
julia> fieldtype(Foo, :x)
Int64
julia> fieldtype(Foo, 2)
String
Base.fieldtypes
— Functionfieldtypes(T::Type)
复合数据类型 T
中所有字段的声明类型,作为一个元组。
此函数至少需要 Julia 1.1。
示例
julia> struct Foo
x::Int64
y::String
end
julia> fieldtypes(Foo)
(Int64, String)
Base.fieldcount
— Functionfieldcount(t::Type)
获取给定类型的实例将具有的字段数量。如果类型过于抽象以至于无法确定,则会抛出错误。
Base.hasfield
— Functionhasfield(T::Type, name::Symbol)
返回一个布尔值,指示 T
是否将 name
作为其自身字段之一。
另请参见 fieldnames
, fieldcount
, hasproperty
.
此函数至少需要 Julia 1.2。
示例
julia> struct Foo
bar::Int
end
julia> hasfield(Foo, :bar)
true
julia> hasfield(Foo, :x)
false
Core.nfields
— Functionnfields(x) -> Int
获取给定对象中的字段数量。
示例
julia> a = 1//2;
julia> nfields(a)
2
julia> b = 1
1
julia> nfields(b)
0
julia> ex = ErrorException("我做了一件坏事");
julia> nfields(ex)
1
在这些示例中,a
是一个 Rational
,它有两个字段。b
是一个 Int
,它是一个没有任何字段的原始位类型。ex
是一个 ErrorException
,它有一个字段。
Base.isconst
— Functionisconst(m::Module, s::Symbol) -> Bool
确定在给定模块 m
中全局变量是否被声明为 const
。
isconst(t::DataType, s::Union{Int,Symbol}) -> Bool
确定字段 s
在给定类型 t
中是否被声明为 const
。
Base.isfieldatomic
— Functionisfieldatomic(t::DataType, s::Union{Int,Symbol}) -> Bool
确定字段 s
在给定类型 t
中是否被声明为 @atomic
。
Memory layout
Base.sizeof
— Methodsizeof(T::DataType)
sizeof(obj)
给定的 DataType
T
的规范二进制表示的大小(以字节为单位),如果有的话。或者对象 obj
的大小(以字节为单位),如果它不是 DataType
。
另请参见 Base.summarysize
。
示例
julia> sizeof(Float32)
4
julia> sizeof(ComplexF64)
16
julia> sizeof(1.0)
8
julia> sizeof(collect(1.0:10.0))
80
julia> struct StructWithPadding
x::Int64
flag::Bool
end
julia> sizeof(StructWithPadding) # 由于填充,不是字段的 `sizeof` 之和
16
julia> sizeof(Int64) + sizeof(Bool) # 与上面不同
9
如果 DataType
T
没有特定的大小,将抛出错误。
julia> sizeof(AbstractArray)
ERROR: 抽象类型 AbstractArray 没有确定的大小。
Stacktrace:
[...]
Base.isconcretetype
— Functionisconcretetype(T)
确定类型 T
是否为具体类型,这意味着它可以有直接实例(值 x
使得 typeof(x) === T
)。请注意,这并不是 isabstracttype(T)
的否定。如果 T
不是一个类型,则返回 false
。
另请参见:isbits
, isabstracttype
, issingletontype
。
示例
julia> isconcretetype(Complex)
false
julia> isconcretetype(Complex{Float32})
true
julia> isconcretetype(Vector{Complex})
true
julia> isconcretetype(Vector{Complex{Float32}})
true
julia> isconcretetype(Union{})
false
julia> isconcretetype(Union{Int,String})
false
Base.isbits
— Functionisbits(x)
如果 x
是 isbitstype
类型的实例,则返回 true
。
Base.isbitstype
— Functionisbitstype(T)
如果类型 T
是一种“简单数据”类型,则返回 true
,这意味着它是不可变的,并且不包含对其他值的引用,仅包含 primitive
类型和其他 isbitstype
类型。典型示例包括数字类型,如 UInt8
、Float64
和 Complex{Float64}
。这一类类型是重要的,因为它们可以作为类型参数,可能不跟踪 isdefined
/ isassigned
状态,并且具有与 C 兼容的定义布局。如果 T
不是类型,则返回 false
。
另请参见 isbits
、isprimitivetype
、ismutable
。
示例
julia> isbitstype(Complex{Float64})
true
julia> isbitstype(Complex)
false
Base.fieldoffset
— Functionfieldoffset(type, i)
字段 i
的字节偏移量相对于数据开始。例如,我们可以以以下方式使用它来总结有关结构的信息:
julia> structinfo(T) = [(fieldoffset(T,i), fieldname(T,i), fieldtype(T,i)) for i = 1:fieldcount(T)];
julia> structinfo(Base.Filesystem.StatStruct)
13-element Vector{Tuple{UInt64, Symbol, Type}}:
(0x0000000000000000, :desc, Union{RawFD, String})
(0x0000000000000008, :device, UInt64)
(0x0000000000000010, :inode, UInt64)
(0x0000000000000018, :mode, UInt64)
(0x0000000000000020, :nlink, Int64)
(0x0000000000000028, :uid, UInt64)
(0x0000000000000030, :gid, UInt64)
(0x0000000000000038, :rdev, UInt64)
(0x0000000000000040, :size, Int64)
(0x0000000000000048, :blksize, Int64)
(0x0000000000000050, :blocks, Int64)
(0x0000000000000058, :mtime, Float64)
(0x0000000000000060, :ctime, Float64)
Base.datatype_alignment
— FunctionBase.datatype_alignment(dt::DataType) -> Int
此类型实例的内存分配最小对齐。可以在任何 isconcretetype
上调用,尽管对于内存,它将给出元素的对齐,而不是整个对象的对齐。
Base.datatype_haspadding
— FunctionBase.datatype_haspadding(dt::DataType) -> Bool
返回此类型实例的字段是否在内存中打包,没有中间的填充位(定义为其值不唯一影响应用于结构字段的相等测试的位)。可以在任何 isconcretetype
上调用。
Base.datatype_pointerfree
— FunctionBase.datatype_pointerfree(dt::DataType) -> Bool
返回此类型的实例是否可以包含对 gc 管理内存的引用。可以在任何 isconcretetype
上调用。
Special values
Base.typemin
— Functiontypemin(T)
给定的(实数)数值数据类型 T
可表示的最小值。
示例
julia> typemin(Int8)
-128
julia> typemin(UInt32)
0x00000000
julia> typemin(Float16)
-Inf16
julia> typemin(Float32)
-Inf32
julia> nextfloat(-Inf32) # 最小的有限 Float32 浮点数
-3.4028235f38
Base.typemax
— Functiontypemax(T)
给定的(实)数值 DataType
可表示的最高值。
示例
julia> typemax(Int8)
127
julia> typemax(UInt32)
0xffffffff
julia> typemax(Float64)
Inf
julia> typemax(Float32)
Inf32
julia> floatmax(Float32) # 最大的有限 Float32 浮点数
3.4028235f38
Base.floatmin
— Functionfloatmin(T = Float64)
返回浮点类型 T
可表示的最小正正规数。
示例
julia> floatmin(Float16)
Float16(6.104e-5)
julia> floatmin(Float32)
1.1754944f-38
julia> floatmin()
2.2250738585072014e-308
Base.floatmax
— Functionfloatmax(T = Float64)
返回浮点类型 T
可表示的最大有限数。
示例
julia> floatmax(Float16)
Float16(6.55e4)
julia> floatmax(Float32)
3.4028235f38
julia> floatmax()
1.7976931348623157e308
julia> typemax(Float64)
Inf
Base.maxintfloat
— Functionmaxintfloat(T=Float64)
在给定的浮点类型 T
(默认为 Float64
)中,精确表示的最大连续整数值浮点数。
也就是说,maxintfloat
返回最小的正整数值浮点数 n
,使得 n+1
在类型 T
中不能被精确表示。
当需要 Integer
类型的值时,请使用 Integer(maxintfloat(T))
。
maxintfloat(T, S)
在给定的浮点类型 T
中可表示的最大连续整数,同时不超过整数类型 S
可表示的最大整数。等价地,它是 maxintfloat(T)
和 typemax(S)
的最小值。
Base.eps
— Methodeps(::Type{T}) where T<:AbstractFloat
eps()
返回浮点类型 T
的 机器精度(默认 T = Float64
)。这被定义为 1 和 typeof(one(T))
可表示的下一个最大值之间的间隔,并且等同于 eps(one(T))
。 (由于 eps(T)
是 T
的 相对误差 的界限,它是一个“无量纲”的量,如 one
所示。)
示例
julia> eps()
2.220446049250313e-16
julia> eps(Float32)
1.1920929f-7
julia> 1.0 + eps()
1.0000000000000002
julia> 1.0 + eps()/2
1.0
Base.eps
— Methodeps(x::AbstractFloat)
返回 x
的 最后一位单位 (ulp)。这是在 x
处连续可表示浮点值之间的距离。在大多数情况下,如果 x
两侧的距离不同,则取两者中较大的一个,即
eps(x) == max(x-prevfloat(x), nextfloat(x)-x)
这个规则的例外是最小和最大有限值(例如 Float64
的 nextfloat(-Inf)
和 prevfloat(Inf)
),它们会舍入到较小的值。
这种行为的理由是 eps
界定了浮点舍入误差。在默认的 RoundNearest
舍入模式下,如果 $y$ 是一个实数,而 $x$ 是离 $y$ 最近的浮点数,则
\[|y-x| \leq \operatorname{eps}(x)/2.\]
另请参见: nextfloat
, issubnormal
, floatmax
.
示例
julia> eps(1.0)
2.220446049250313e-16
julia> eps(prevfloat(2.0))
2.220446049250313e-16
julia> eps(2.0)
4.440892098500626e-16
julia> x = prevfloat(Inf) # 最大有限 Float64
1.7976931348623157e308
julia> x + eps(x)/2 # 向上舍入
Inf
julia> x + prevfloat(eps(x)/2) # 向下舍入
1.7976931348623157e308
Base.instances
— Functioninstances(T::Type)
返回给定类型的所有实例的集合(如果适用)。主要用于枚举类型(见 @enum
)。
示例
julia> @enum Color red blue green
julia> instances(Color)
(red, blue, green)
Special Types
Core.Any
— TypeAny::数据类型
Any
是所有类型的并集。它具有定义属性 isa(x, Any) == true
对于任何 x
。因此,Any
描述了所有可能值的整个宇宙。例如,Integer
是 Any
的一个子集,包括 Int
、Int8
和其他整数类型。
Core.Union
— TypeUnion{类型...}
Union
类型是一个抽象类型,它包含其任何参数类型的所有实例。这意味着 T <: Union{T,S}
和 S <: Union{T,S}
。
与其他抽象类型一样,它不能被实例化,即使它的所有参数都是非抽象的。
示例
julia> IntOrString = Union{Int,AbstractString}
Union{Int64, AbstractString}
julia> 1 isa IntOrString # Int 的实例包含在联合中
true
julia> "Hello!" isa IntOrString # String 也包含在内
true
julia> 1.0 isa IntOrString # Float64 不包含,因为它既不是 Int 也不是 AbstractString
false
扩展帮助
与大多数其他参数化类型不同,联合在其参数中是协变的。例如,Union{Real, String}
是 Union{Number, AbstractString}
的子类型。
空联合 Union{}
是 Julia 的底层类型。
Union{}
— KeywordUnion{}
Union{}
,空的 Union
类型,是没有值的类型。也就是说,对于任何 x
,它具有定义属性 isa(x, Union{}) == false
。Base.Bottom
被定义为它的别名,Union{}
的类型是 Core.TypeofBottom
。
示例
julia> isa(nothing, Union{})
false
Core.UnionAll
— TypeUnionAll
一个类型参数的所有值的类型的并集。UnionAll
用于描述参数化类型,其中某些参数的值是未知的。请参阅手册中关于 UnionAll Types 的部分。
示例
julia> typeof(Vector)
UnionAll
julia> typeof(Vector{Int})
DataType
Core.Tuple
— TypeTuple{Types...}
元组是一个固定长度的容器,可以容纳不同类型的任何值,但不能被修改(它是不可变的)。可以通过索引访问这些值。元组字面量用逗号和括号表示:
julia> (1, 1+1)
(1, 2)
julia> (1,)
(1,)
julia> x = (0.0, "hello", 6*7)
(0.0, "hello", 42)
julia> x[2]
"hello"
julia> typeof(x)
Tuple{Float64, String, Int64}
长度为1的元组必须用逗号书写,即(1,)
,因为(1)
只是一个带括号的值。()
表示空(长度为0)元组。
可以通过使用Tuple
类型作为构造函数从迭代器构造元组:
julia> Tuple(["a", 1])
("a", 1)
julia> Tuple{String, Float64}(["a", 1])
("a", 1.0)
元组类型在其参数中是协变的:Tuple{Int}
是Tuple{Any}
的子类型。因此,Tuple{Any}
被视为抽象类型,只有当其参数是具体的时,元组类型才是具体的。元组没有字段名称;字段只能通过索引访问。元组类型可以有任意数量的参数。
请参阅手册中关于Tuple Types的部分。
另请参阅Vararg
、NTuple
、ntuple
、tuple
、NamedTuple
。
Core.NTuple
— TypeNTuple{N, T}
一种紧凑的方式来表示长度为 N
的元组类型,其中所有元素都是类型 T
。
示例
julia> isa((1, 2, 3, 4, 5, 6), NTuple{6, Int})
true
另见 ntuple
.
Core.NamedTuple
— Type命名元组
NamedTuple
是命名 Tuple
的集合。也就是说,它们是一个类似元组的值集合,其中每个条目都有一个唯一的名称,表示为 Symbol
。与 Tuple
一样,NamedTuple
是不可变的;构造后,名称和数值都不能就地修改。
可以通过带有键的元组字面量创建命名元组,例如 (a=1, b=2)
,或者通过在开括号后加分号的元组字面量,例如 (; a=1, b=2)
(这种形式也接受下面描述的程序生成的名称),或者使用 NamedTuple
类型作为构造函数,例如 NamedTuple{(:a, :b)}((1,2))
。
可以使用字段访问语法访问命名元组中与名称相关联的值,例如 x.a
,或使用 getindex
,例如 x[:a]
或 x[(:a, :b)]
。可以使用 keys
获取名称的元组,使用 values
获取值的元组。
对 NamedTuple
的迭代会产生 值 而不包含名称。(见下面的示例。)要迭代名称-值对,请使用 pairs
函数。
@NamedTuple
宏可用于方便地声明 NamedTuple
类型。
示例
julia> x = (a=1, b=2)
(a = 1, b = 2)
julia> x.a
1
julia> x[:a]
1
julia> x[(:a,)]
(a = 1,)
julia> keys(x)
(:a, :b)
julia> values(x)
(1, 2)
julia> collect(x)
2-element Vector{Int64}:
1
2
julia> collect(pairs(x))
2-element Vector{Pair{Symbol, Int64}}:
:a => 1
:b => 2
以与程序化定义关键字参数类似的方式,可以通过在元组字面量内的分号后给出成对的 name::Symbol => value
来创建命名元组。可以混合使用这种和 name=value
语法:
julia> (; :a => 1, :b => 2, c=3)
(a = 1, b = 2, c = 3)
名称-值对也可以通过展开命名元组或任何生成两个值集合的迭代器来提供,每个集合的第一个值为符号:
julia> keys = (:a, :b, :c); values = (1, 2, 3);
julia> NamedTuple{keys}(values)
(a = 1, b = 2, c = 3)
julia> (; (keys .=> values)...)
(a = 1, b = 2, c = 3)
julia> nt1 = (a=1, b=2);
julia> nt2 = (c=3, d=4);
julia> (; nt1..., nt2..., b=20) # 最后的 b 会覆盖 nt1 中的值
(a = 1, b = 20, c = 3, d = 4)
julia> (; zip(keys, values)...) # zip 生成的元组如 (:a, 1)
(a = 1, b = 2, c = 3)
与关键字参数一样,标识符和点表达式隐含名称:
julia> x = 0
0
julia> t = (; x)
(x = 0,)
julia> (; t.x)
(x = 0,)
从标识符和点表达式隐含的名称自 Julia 1.5 起可用。
使用多个 Symbol
的 getindex
方法自 Julia 1.7 起可用。
Base.@NamedTuple
— Macro@NamedTuple{key1::Type1, key2::Type2, ...}
@NamedTuple begin key1::Type1; key2::Type2; ...; end
这个宏提供了一种更方便的语法来声明 NamedTuple
类型。它返回一个具有给定键和类型的 NamedTuple
类型,相当于 NamedTuple{(:key1, :key2, ...), Tuple{Type1,Type2,...}}
。如果省略 ::Type
声明,则默认为 Any
。begin ... end
形式允许将声明分布在多行(类似于 struct
声明),但在其他方面是等效的。NamedTuple
宏在打印 NamedTuple
类型时使用,例如在 REPL 中。
例如,元组 (a=3.1, b="hello")
的类型是 NamedTuple{(:a, :b), Tuple{Float64, String}}
,也可以通过 @NamedTuple
声明为:
julia> @NamedTuple{a::Float64, b::String}
@NamedTuple{a::Float64, b::String}
julia> @NamedTuple begin
a::Float64
b::String
end
@NamedTuple{a::Float64, b::String}
该宏自 Julia 1.5 起可用。
Base.@Kwargs
— Macro@Kwargs{key1::Type1, key2::Type2, ...}
这个宏提供了一种方便的方式来构造关键字参数的类型表示,语法与 @NamedTuple
相同。例如,当我们有一个函数调用像 func([positional arguments]; kw1=1.0, kw2="2")
时,我们可以使用这个宏将关键字参数的内部类型表示构造为 @Kwargs{kw1::Float64, kw2::String}
。该宏的语法专门设计用于简化关键字方法的签名类型,以便在堆栈跟踪视图中打印时更清晰。
julia> @Kwargs{init::Int} # 关键字参数的内部表示
Base.Pairs{Symbol, Int64, Tuple{Symbol}, @NamedTuple{init::Int64}}
julia> sum("julia"; init=1)
ERROR: MethodError: no method matching +(::Char, ::Char)
函数 `+` 存在,但没有为这种参数类型组合定义方法。
最接近的候选者是:
+(::Any, ::Any, ::Any, ::Any...)
@ Base operators.jl:585
+(::Integer, ::AbstractChar)
@ Base char.jl:247
+(::T, ::Integer) where T<:AbstractChar
@ Base char.jl:237
堆栈跟踪:
[1] add_sum(x::Char, y::Char)
@ Base ./reduce.jl:24
[2] BottomRF
@ Base ./reduce.jl:86 [内联]
[3] _foldl_impl(op::Base.BottomRF{typeof(Base.add_sum)}, init::Int64, itr::String)
@ Base ./reduce.jl:62
[4] foldl_impl(op::Base.BottomRF{typeof(Base.add_sum)}, nt::Int64, itr::String)
@ Base ./reduce.jl:48 [内联]
[5] mapfoldl_impl(f::typeof(identity), op::typeof(Base.add_sum), nt::Int64, itr::String)
@ Base ./reduce.jl:44 [内联]
[6] mapfoldl(f::typeof(identity), op::typeof(Base.add_sum), itr::String; init::Int64)
@ Base ./reduce.jl:175 [内联]
[7] mapreduce(f::typeof(identity), op::typeof(Base.add_sum), itr::String; kw::@Kwargs{init::Int64})
@ Base ./reduce.jl:307 [内联]
[8] sum(f::typeof(identity), a::String; kw::@Kwargs{init::Int64})
@ Base ./reduce.jl:535 [内联]
[9] sum(a::String; kw::@Kwargs{init::Int64})
@ Base ./reduce.jl:564 [内联]
[10] 顶级作用域
@ REPL[12]:1
这个宏自 Julia 1.10 起可用。
Base.Val
— TypeVal(c)
返回 Val{c}()
,其中不包含运行时数据。像这样的类型可以用来通过值 c
在函数之间传递信息,c
必须是一个 isbits
值或一个 Symbol
。这个构造的意图是能够直接在常量上进行调度(在编译时),而不必在运行时测试常量的值。
示例
julia> f(::Val{true}) = "Good"
f (generic function with 1 method)
julia> f(::Val{false}) = "Bad"
f (generic function with 2 methods)
julia> f(Val(true))
"Good"
Core.Vararg
— ConstantVararg{T,N}
元组类型 Tuple
的最后一个参数可以是特殊值 Vararg
,表示任意数量的尾随元素。 Vararg{T,N}
精确对应 N
个类型为 T
的元素。最后, Vararg{T}
对应零个或多个类型为 T
的元素。 Vararg
元组类型用于表示 varargs 方法接受的参数(请参见手册中关于 Varargs Functions 的部分。)
另见 NTuple
。
示例
julia> mytupletype = Tuple{AbstractString, Vararg{Int}}
Tuple{AbstractString, Vararg{Int64}}
julia> isa(("1",), mytupletype)
true
julia> isa(("1",1), mytupletype)
true
julia> isa(("1",1,2), mytupletype)
true
julia> isa(("1",1,2,3.0), mytupletype)
false
Core.Nothing
— TypeBase.isnothing
— Functionisnothing(x)
如果 x === nothing
,则返回 true
,否则返回 false
。
此函数至少需要 Julia 1.1。
Base.notnothing
— Functionnotnothing(x)
如果 x === nothing
,则抛出错误;如果不是,则返回 x
。
Base.Some
— TypeSome{T}
在 Union{Some{T}, Nothing}
中使用的包装类型,用于区分缺少值(nothing
)和存在一个 nothing
值(即 Some(nothing)
)。
使用 something
来访问 Some
对象包装的值。
Base.something
— Functionsomething(x...)
返回参数中第一个不等于 nothing
的值(如果有的话)。否则抛出错误。类型为 Some
的参数会被解包。
另请参见 coalesce
, skipmissing
, @something
。
示例
julia> something(nothing, 1)
1
julia> something(Some(1), nothing)
1
julia> something(Some(nothing), 2) === nothing
true
julia> something(missing, nothing)
missing
julia> something(nothing, nothing)
ERROR: ArgumentError: No value arguments present
Base.@something
— Macro@something(x...)
something
的短路版本。
示例
julia> f(x) = (println("f($x)"); nothing);
julia> a = 1;
julia> a = @something a f(2) f(3) error("无法找到 `a` 的默认值")
1
julia> b = nothing;
julia> b = @something b f(2) f(3) error("无法找到 `b` 的默认值")
f(2)
f(3)
错误: 无法找到 `b` 的默认值
[...]
julia> b = @something b f(2) f(3) Some(nothing)
f(2)
f(3)
julia> b === nothing
true
此宏自 Julia 1.7 起可用。
Base.Enums.Enum
— TypeEnum{T<:Integer}
由 @enum
定义的所有枚举类型的抽象超类型。
Base.Enums.@enum
— Macro@enum EnumName[::BaseType] value1[=x] value2[=y]
创建一个名为 EnumName
的 Enum{BaseType}
子类型,枚举成员值为 value1
和 value2
,可选的赋值为 x
和 y
。EnumName
可以像其他类型一样使用,枚举成员值可以作为常规值使用,例如
示例
julia> @enum Fruit apple=1 orange=2 kiwi=3
julia> f(x::Fruit) = "I'm a Fruit with value: $(Int(x))"
f (generic function with 1 method)
julia> f(apple)
"I'm a Fruit with value: 1"
julia> Fruit(1)
apple::Fruit = 1
值也可以在 begin
块内指定,例如
@enum EnumName begin
value1
value2
end
BaseType
默认为 Int32
,必须是 Integer
的原始子类型。成员值可以在枚举类型和 BaseType
之间转换。read
和 write
会自动执行这些转换。如果枚举是使用非默认的 BaseType
创建的,Integer(value1)
将返回类型为 BaseType
的整数 value1
。
要列出枚举的所有实例,请使用 instances
,例如
julia> instances(Fruit)
(apple, orange, kiwi)
可以从枚举实例构造符号:
julia> Symbol(apple)
:apple
Core.Expr
— TypeExpr(head::Symbol, args...)
一个表示解析的 Julia 代码(ASTs)中复合表达式的类型。每个表达式由一个 head
Symbol
组成,用于标识它是哪种类型的表达式(例如,调用、for 循环、条件语句等),以及子表达式(例如,调用的参数)。子表达式存储在一个名为 args
的 Vector{Any}
字段中。
请参阅手册章节 元编程 和开发者文档 Julia ASTs。
示例
julia> Expr(:call, :+, 1, 2)
:(1 + 2)
julia> dump(:(a ? b : c))
Expr
head: Symbol if
args: Array{Any}((3,))
1: Symbol a
2: Symbol b
3: Symbol c
Core.Symbol
— Type符号
用于表示解析的 julia 代码 (ASTs) 中标识符的对象类型。也常用作名称或标签来标识实体(例如,作为字典键)。可以使用 :
引用运算符输入 Symbol
:
julia> :name
:name
julia> typeof(:name)
Symbol
julia> x = 42
42
julia> eval(:x)
42
Symbol
还可以通过调用构造函数 Symbol(x...)
从字符串或其他值构造。
Symbol
是不可变的,其实现为所有具有相同名称的 Symbol
复用相同的对象。
与字符串不同,Symbol
是“原子”或“标量”实体,不支持对字符的迭代。
Core.Symbol
— MethodSymbol(x...) -> Symbol
通过将参数的字符串表示连接在一起来创建一个 Symbol
。
示例
julia> Symbol("my", "name")
:myname
julia> Symbol("day", 4)
:day4
Core.Module
— Type模块
模块
是一个独立的全局变量工作区。有关详细信息,请参见module
和关于模块的手册部分。
Module(name::Symbol=:anonymous, std_imports=true, default_names=true)
返回一个具有指定名称的模块。baremodule
对应于Module(:ModuleName, false)
可以使用Module(:ModuleName, false, false)
创建一个完全不包含任何名称的空模块。此模块将不导入Base
或Core
,并且不包含对自身的引用。
Generic Functions
Core.Function
— Type函数
所有函数的抽象类型。
示例
julia> isa(+, Function)
true
julia> typeof(sin)
typeof(sin) (函数 sin 的单例类型,Function 的子类型)
julia> ans <: Function
true
Base.hasmethod
— Functionhasmethod(f, t::Type{<:Tuple}[, kwnames]; world=get_world_counter()) -> Bool
确定给定的泛型函数是否具有与给定的 Tuple
参数类型匹配的方法,并且该方法的世界年龄上限由 world
给出。
如果提供了一个关键字参数名称的元组 kwnames
,这也会检查与 t
匹配的 f
的方法是否具有给定的关键字参数名称。如果匹配的方法接受可变数量的关键字参数,例如使用 kwargs...
,则 kwnames
中给出的任何名称都被视为有效。否则,提供的名称必须是该方法的关键字参数的子集。
另请参见 applicable
。
提供关键字参数名称需要 Julia 1.2 或更高版本。
示例
julia> hasmethod(length, Tuple{Array})
true
julia> f(; oranges=0) = oranges;
julia> hasmethod(f, Tuple{}, (:oranges,))
true
julia> hasmethod(f, Tuple{}, (:apples, :bananas))
false
julia> g(; xs...) = 4;
julia> hasmethod(g, Tuple{}, (:a, :b, :c, :d)) # g 接受任意关键字参数
true
Core.applicable
— Functionapplicable(f, args...) -> Bool
确定给定的泛型函数是否有适用于给定参数的方法。
另见 hasmethod
。
示例
julia> function f(x, y)
x + y
end;
julia> applicable(f, 1)
false
julia> applicable(f, 1, 2)
true
Base.isambiguous
— FunctionBase.isambiguous(m1, m2; ambiguous_bottom=false) -> Bool
确定两个方法 m1
和 m2
是否可能在某些调用签名中产生歧义。此测试是在同一函数的其他方法的上下文中进行的;在孤立情况下,m1
和 m2
可能是模糊的,但如果定义了一个解决歧义的第三个方法,则返回 false
。或者,在孤立情况下,m1
和 m2
可能是有序的,但如果无法与它们排序的第三个方法存在,它们可能会一起导致歧义。
对于参数化类型,ambiguous_bottom
关键字参数控制 Union{}
是否被视为类型参数的模糊交集——当 true
时,它被视为模糊,当 false
时则不是。
示例
julia> foo(x::Complex{<:Integer}) = 1
foo (generic function with 1 method)
julia> foo(x::Complex{<:Rational}) = 2
foo (generic function with 2 methods)
julia> m1, m2 = collect(methods(foo));
julia> typeintersect(m1.sig, m2.sig)
Tuple{typeof(foo), Complex{Union{}}}
julia> Base.isambiguous(m1, m2, ambiguous_bottom=true)
true
julia> Base.isambiguous(m1, m2, ambiguous_bottom=false)
false
Core.invoke
— Functioninvoke(f, argtypes::Type, args...; kwargs...)
调用给定泛型函数 f
的方法,匹配指定类型 argtypes
和指定参数 args
,并传递关键字参数 kwargs
。参数 args
必须符合 argtypes
中指定的类型,即不自动执行转换。此方法允许调用与最特定匹配方法不同的方法,这在明确需要更一般定义的行为时非常有用(通常作为同一函数的更特定方法实现的一部分)。
在使用 invoke
调用你未编写的函数时要小心。对于给定的 argtypes
使用哪个定义是一个实现细节,除非该函数明确声明使用某些 argtypes
调用是公共 API 的一部分。例如,下面示例中 f1
和 f2
之间的变化通常被认为是兼容的,因为这种变化在正常(非 invoke
)调用中对调用者是不可见的。然而,如果使用 invoke
,这种变化是可见的。
示例
julia> f(x::Real) = x^2;
julia> f(x::Integer) = 1 + invoke(f, Tuple{Real}, x);
julia> f(2)
5
julia> f1(::Integer) = Integer
f1(::Real) = Real;
julia> f2(x::Real) = _f2(x)
_f2(::Integer) = Integer
_f2(_) = Real;
julia> f1(1)
Integer
julia> f2(1)
Integer
julia> invoke(f1, Tuple{Real}, 1)
Real
julia> invoke(f2, Tuple{Real}, 1)
Integer
Base.@invoke
— Macro@invoke f(arg::T, ...; kwargs...)
提供了一种方便的方式来调用 invoke
,通过将 @invoke f(arg1::T1, arg2::T2; kwargs...)
扩展为 invoke(f, Tuple{T1,T2}, arg1, arg2; kwargs...)
。当参数的类型注释被省略时,它会被替换为 Core.Typeof
该参数。要调用一个参数未类型化或显式类型为 Any
的方法,请使用 ::Any
注释该参数。
它还支持以下语法:
@invoke (x::X).f
扩展为invoke(getproperty, Tuple{X,Symbol}, x, :f)
@invoke (x::X).f = v::V
扩展为invoke(setproperty!, Tuple{X,Symbol,V}, x, :f, v)
@invoke (xs::Xs)[i::I]
扩展为invoke(getindex, Tuple{Xs,I}, xs, i)
@invoke (xs::Xs)[i::I] = v::V
扩展为invoke(setindex!, Tuple{Xs,V,I}, xs, v, i)
示例
julia> @macroexpand @invoke f(x::T, y)
:(Core.invoke(f, Tuple{T, Core.Typeof(y)}, x, y))
julia> @invoke 420::Integer % Unsigned
0x00000000000001a4
julia> @macroexpand @invoke (x::X).f
:(Core.invoke(Base.getproperty, Tuple{X, Core.Typeof(:f)}, x, :f))
julia> @macroexpand @invoke (x::X).f = v::V
:(Core.invoke(Base.setproperty!, Tuple{X, Core.Typeof(:f), V}, x, :f, v))
julia> @macroexpand @invoke (xs::Xs)[i::I]
:(Core.invoke(Base.getindex, Tuple{Xs, I}, xs, i))
julia> @macroexpand @invoke (xs::Xs)[i::I] = v::V
:(Core.invoke(Base.setindex!, Tuple{Xs, V, I}, xs, v, i))
此宏需要 Julia 1.7 或更高版本。
此宏自 Julia 1.9 起被导出。
从 Julia 1.10 开始支持额外的语法。
Base.invokelatest
— Functioninvokelatest(f, args...; kwargs...)
调用 f(args...; kwargs...)
,但保证将执行 f
的最新方法。这在某些特殊情况下非常有用,例如长时间运行的事件循环或可能调用过时版本的回调函数 f
。(缺点是 invokelatest
的速度比直接调用 f
稍慢,并且结果的类型无法被编译器推断。)
在 Julia 1.9 之前,此函数未被导出,称为 Base.invokelatest
。
Base.@invokelatest
— Macro@invokelatest f(args...; kwargs...)
提供了一种方便的方式来调用 invokelatest
。 @invokelatest f(args...; kwargs...)
将简单地扩展为 Base.invokelatest(f, args...; kwargs...)
。
它还支持以下语法:
@invokelatest x.f
扩展为Base.invokelatest(getproperty, x, :f)
@invokelatest x.f = v
扩展为Base.invokelatest(setproperty!, x, :f, v)
@invokelatest xs[i]
扩展为Base.invokelatest(getindex, xs, i)
@invokelatest xs[i] = v
扩展为Base.invokelatest(setindex!, xs, v, i)
julia> @macroexpand @invokelatest f(x; kw=kwv)
:(Base.invokelatest(f, x; kw = kwv))
julia> @macroexpand @invokelatest x.f
:(Base.invokelatest(Base.getproperty, x, :f))
julia> @macroexpand @invokelatest x.f = v
:(Base.invokelatest(Base.setproperty!, x, :f, v))
julia> @macroexpand @invokelatest xs[i]
:(Base.invokelatest(Base.getindex, xs, i))
julia> @macroexpand @invokelatest xs[i] = v
:(Base.invokelatest(Base.setindex!, xs, v, i))
此宏需要 Julia 1.7 或更高版本。
在 Julia 1.9 之前,此宏未被导出,并被称为 Base.@invokelatest
。
额外的 x.f
和 xs[i]
语法需要 Julia 1.10。
new
— Keywordnew, or new{A,B,...}
特殊函数可用于内部构造函数,它创建该类型的新对象。形式 new{A,B,...} 明确指定参数类型的参数值。有关更多信息,请参见手册中关于 Inner Constructor Methods 的部分。
Base.:|>
— Function|>(x, f)
中缀运算符,将函数 f
应用到参数 x
。这允许将 f(g(x))
写成 x |> g |> f
。当与匿名函数一起使用时,通常需要在定义周围加上括号以获得预期的链式调用。
示例
julia> 4 |> inv
0.25
julia> [2, 3, 5] |> sum |> inv
0.1
julia> [0 1; 2 3] .|> (x -> x^2) |> sum
14
Base.:∘
— Functionf ∘ g
组合函数:即 (f ∘ g)(args...; kwargs...)
意味着 f(g(args...; kwargs...))
。在 Julia REPL(以及大多数适当配置的编辑器)中,可以通过输入 \circ<tab>
来输入 ∘
符号。
函数组合也可以以前缀形式工作:∘(f, g)
与 f ∘ g
相同。前缀形式支持多个函数的组合:∘(f, g, h) = f ∘ g ∘ h
和展开 ∘(fs...)
用于组合一个可迭代的函数集合。∘
的最后一个参数首先执行。
多重函数组合至少需要 Julia 1.4。
组合一个函数 ∘(f) 至少需要 Julia 1.5。
使用关键字参数至少需要 Julia 1.7。
示例
julia> map(uppercase∘first, ["apple", "banana", "carrot"])
3-element Vector{Char}:
'A': ASCII/Unicode U+0041 (category Lu: Letter, uppercase)
'B': ASCII/Unicode U+0042 (category Lu: Letter, uppercase)
'C': ASCII/Unicode U+0043 (category Lu: Letter, uppercase)
julia> (==(6)∘length).(["apple", "banana", "carrot"])
3-element BitVector:
0
1
1
julia> fs = [
x -> 2x
x -> x-1
x -> x/2
x -> x+1
];
julia> ∘(fs...)(3)
2.0
另请参见 ComposedFunction
, !f::Function
.
Base.ComposedFunction
— TypeComposedFunction{Outer,Inner} <: Function
表示两个可调用对象 outer::Outer
和 inner::Inner
的组合。也就是说
ComposedFunction(outer, inner)(args...; kw...) === outer(inner(args...; kw...))
构造 ComposedFunction
实例的首选方式是使用组合运算符 ∘
:
julia> sin ∘ cos === ComposedFunction(sin, cos)
true
julia> typeof(sin∘cos)
ComposedFunction{typeof(sin), typeof(cos)}
组合的部分存储在 ComposedFunction
的字段中,可以通过以下方式检索:
julia> composition = sin ∘ cos
sin ∘ cos
julia> composition.outer === sin
true
julia> composition.inner === cos
true
ComposedFunction 至少需要 Julia 1.6。在早期版本中,∘
返回一个匿名函数。
另见 ∘
.
Base.splat
— Functionsplat(f)
等价于
my_splat(f) = args->f(args...)
即,给定一个函数,返回一个新的函数,该函数接受一个参数并将其展开到原始函数中。这在将多参数函数作为期望单个参数的上下文中的适配器时非常有用,但将元组作为该单个参数传递。
示例
julia> map(splat(+), zip(1:3,4:6))
3-element Vector{Int64}:
5
7
9
julia> my_add = splat(+)
splat(+)
julia> my_add((1,2,3))
6
Base.Fix1
— TypeBase.Fix2
— TypeFix2(f, x)
一个类型,表示将两个参数的函数 f
的部分应用版本,第二个参数固定为值 "x"。换句话说,Fix2(f, x)
的行为类似于 y->f(y, x)
。
Syntax
Core.eval
— FunctionCore.eval(m::Module, expr)
在给定模块中评估一个表达式并返回结果。
eval
— Functioneval(expr)
在包含模块的全局范围内评估一个表达式。每个 Module
(除了那些用 baremodule
定义的)都有自己的 1 个参数的 eval
定义,该定义在该模块中评估表达式。
Base.@eval
— Macro@eval [mod,] ex
使用 eval
评估一个表达式,并将值插入其中。如果提供了两个参数,第一个是要评估的模块。
Base.evalfile
— Functionevalfile(path::AbstractString, args::Vector{String}=String[])
将文件加载到一个匿名模块中,使用 include
,评估所有表达式,并返回最后一个表达式的值。可选的 args
参数可用于设置脚本的输入参数(即全局 ARGS
变量)。请注意,定义(例如方法、全局变量)在匿名模块中被评估,不会影响当前模块。
示例
julia> write("testfile.jl", """
@show ARGS
1 + 1
""");
julia> x = evalfile("testfile.jl", ["ARG1", "ARG2"]);
ARGS = ["ARG1", "ARG2"]
julia> x
2
julia> rm("testfile.jl")
Base.esc
— FunctionBase.@inbounds
— Macro@inbounds(blk)
消除表达式中的数组边界检查。
在下面的示例中,跳过对数组 A
的元素 i
的范围检查以提高性能。
function sum(A::AbstractArray)
r = zero(eltype(A))
for i in eachindex(A)
@inbounds r += A[i]
end
return r
end
使用 @inbounds
可能会对越界索引返回不正确的结果/崩溃/损坏。用户有责任手动检查。仅在从本地可用信息中确定所有访问都在边界内时使用 @inbounds
。特别是,在像上面这样的函数中使用 1:length(A)
而不是 eachindex(A)
是 不 安全的,因为 A
的第一个索引对于所有子类型 AbstractArray
的用户定义类型可能不是 1
。
Base.@boundscheck
— Macro@boundscheck(blk)
将表达式 blk
注释为边界检查块,允许通过 @inbounds
省略它。
编写 @boundscheck
的函数必须被内联到其调用者中,以便 @inbounds
生效。
示例
julia> @inline function g(A, i)
@boundscheck checkbounds(A, i)
return "accessing ($A)[$i]"
end;
julia> f1() = return g(1:2, -1);
julia> f2() = @inbounds return g(1:2, -1);
julia> f1()
ERROR: BoundsError: attempt to access 2-element UnitRange{Int64} at index [-1]
Stacktrace:
[1] throw_boundserror(::UnitRange{Int64}, ::Tuple{Int64}) at ./abstractarray.jl:455
[2] checkbounds at ./abstractarray.jl:420 [inlined]
[3] g at ./none:2 [inlined]
[4] f1() at ./none:1
[5] top-level scope
julia> f2()
"accessing (1:2)[-1]"
@boundscheck
注释允许您作为库作者选择允许 其他代码 使用 @inbounds
删除您的边界检查。如上所述,调用者必须使用他们可以访问的信息验证他们的访问是有效的,然后才能使用 @inbounds
。例如,对于索引到您的 AbstractArray
子类,这涉及到检查索引是否与其 axes
相符。因此,只有在您确定其行为是正确的情况下,才应将 @boundscheck
注释添加到 getindex
或 setindex!
实现中。
Base.@propagate_inbounds
— Macro@propagate_inbounds
告诉编译器在保留调用者的边界上下文的同时内联一个函数。
Base.@inline
— Macro@inline
给编译器一个提示,表明这个函数值得进行内联。
小函数通常不需要 @inline
注解,因为编译器会自动处理。通过在较大的函数上使用 @inline
,可以给编译器一个额外的推动力来进行内联。
@inline
可以在函数定义之前或函数体内立即应用。
# 注解长形式定义
@inline function longdef(x)
...
end
# 注解短形式定义
@inline shortdef(x) = ...
# 注解 `do` 块创建的匿名函数
f() do
@inline
...
end
在函数体内的使用至少需要 Julia 1.8。
@inline block
给编译器一个提示,表明 block
内的调用值得进行内联。
# 编译器将尝试内联 `f`
@inline f(...)
# 编译器将尝试内联 `f`、`g` 和 `+`
@inline f(...) + g(...)
调用点注解总是优先于应用于被调用函数定义的注解:
@noinline function explicit_noinline(args...)
# body
end
let
@inline explicit_noinline(args...) # 将被内联
end
当存在嵌套的调用点注解时,最内层的注解具有优先权:
@noinline let a0, b0 = ...
a = @inline f(a0) # 编译器将尝试内联此调用
b = f(b0) # 编译器将不会尝试内联此调用
return a, b
end
尽管调用点注解将尝试强制内联,无论成本模型如何,但仍然有可能无法成功。特别是,递归调用即使被注解为 @inline
也无法进行内联。
调用点注解至少需要 Julia 1.8。
Base.@noinline
— Macro@noinline
给编译器一个提示,表明它不应该内联一个函数。
小函数通常会自动被内联。通过在小函数上使用 @noinline
,可以防止自动内联。
@noinline
可以在函数定义之前或在函数体内使用。
# 注释长形式定义
@noinline function longdef(x)
...
end
# 注释短形式定义
@noinline shortdef(x) = ...
# 注释一个 `do` 块创建的匿名函数
f() do
@noinline
...
end
在函数体内的使用需要至少 Julia 1.8。
@noinline block
给编译器一个提示,表明它不应该内联 block
内的调用。
# 编译器将尝试不内联 `f`
@noinline f(...)
# 编译器将尝试不内联 `f`、`g` 和 `+`
@noinline f(...) + g(...)
调用位置注释总是优先于应用于被调用函数定义的注释:
@inline function explicit_inline(args...)
# body
end
let
@noinline explicit_inline(args...) # 将不会被内联
end
当存在嵌套的调用位置注释时,最内层的注释具有优先权:
@inline let a0, b0 = ...
a = @noinline f(a0) # 编译器将不会尝试内联此调用
b = f(b0) # 编译器将尝试内联此调用
return a, b
end
调用位置注释需要至少 Julia 1.8。
如果函数是微不足道的(例如返回一个常量),它可能仍然会被内联。
Base.@nospecialize
— Macro@nospecialize
应用于函数参数名称时,提示编译器该方法实现不应针对该参数的不同类型进行特化,而应使用该参数声明的类型。它可以应用于正式参数列表中的参数,或在函数体内。当应用于参数时,宏必须包裹整个参数表达式,例如 @nospecialize(x::Real)
或 @nospecialize(i::Integer...)
,而不是仅仅包裹参数名称。当在函数体内使用时,宏必须出现在语句位置,并且在任何代码之前。
在没有参数的情况下,它适用于父作用域的所有参数。在局部作用域中,这意味着包含函数的所有参数。在全局(顶层)作用域中,这意味着当前模块中随后定义的所有方法。
通过使用 @specialize
可以将特化重置为默认值。
function example_function(@nospecialize x)
...
end
function example_function(x, @nospecialize(y = 1))
...
end
function example_function(x, y, z)
@nospecialize x y
...
end
@nospecialize
f(y) = [x for x in y]
@specialize
@nospecialize
影响代码生成,但不影响推断:它限制了生成的本机代码的多样性,但并不对类型推断施加任何限制(超出标准限制)。使用 Base.@nospecializeinfer
结合 @nospecialize
以额外抑制推断。
示例
julia> f(A::AbstractArray) = g(A)
f (generic function with 1 method)
julia> @noinline g(@nospecialize(A::AbstractArray)) = A[1]
g (generic function with 1 method)
julia> @code_typed f([1.0])
CodeInfo(
1 ─ %1 = invoke Main.g(_2::AbstractArray)::Float64
└── return %1
) => Float64
在这里,@nospecialize
注解的结果等同于
f(A::AbstractArray) = invoke(g, Tuple{AbstractArray}, A)
确保只会为 g
生成一个版本的本机代码,该版本对任何 AbstractArray
都是通用的。然而,g
和 f
的具体返回类型仍然被推断,并且这仍然用于优化 f
和 g
的调用者。
Base.@specialize
— Macro@specialize
将参数的特化提示重置为默认值。有关详细信息,请参见 @nospecialize
。
Base.@nospecializeinfer
— MacroBase.@nospecializeinfer function f(args...)
@nospecialize ...
...
end
Base.@nospecializeinfer f(@nospecialize args...) = ...
告诉编译器使用 @nospecialize
参数的声明类型来推断 f
。这可以用来限制推断期间编译器生成的特化数量。
示例
julia> f(A::AbstractArray) = g(A)
f (generic function with 1 method)
julia> @noinline Base.@nospecializeinfer g(@nospecialize(A::AbstractArray)) = A[1]
g (generic function with 1 method)
julia> @code_typed f([1.0])
CodeInfo(
1 ─ %1 = invoke Main.g(_2::AbstractArray)::Any
└── return %1
) => Any
在这个例子中,f
将针对 A
的每个特定类型进行推断,但 g
只会使用声明的参数类型 A::AbstractArray
进行一次推断,这意味着编译器不太可能在其上看到过多的推断时间,因为它无法推断其具体的返回类型。如果没有 @nospecializeinfer
,f([1.0])
将推断 g
的返回类型为 Float64
,这表明尽管禁止了特化代码生成,推断仍然针对 g(::Vector{Float64})
进行了。
使用 Base.@nospecializeinfer
需要 Julia 版本 1.10。
Base.@constprop
— MacroBase.@constprop 设置 [ex]
控制注释函数的跨过程常量传播模式。
支持两种 setting
:
Base.@constprop :aggressive [ex]
:积极地应用常量传播。对于返回类型依赖于参数值的方法,这可以在增加编译时间的代价下产生更好的推断结果。Base.@constprop :none [ex]
:禁用常量传播。这可以减少 Julia 可能认为值得进行常量传播的函数的编译时间。常见情况是对于具有Bool
或Symbol
值参数或关键字参数的函数。
Base.@constprop
可以在函数定义之前立即应用,或在函数体内应用。
# 注释长形式定义
Base.@constprop :aggressive function longdef(x)
...
end
# 注释短形式定义
Base.@constprop :aggressive shortdef(x) = ...
# 注释 `do` 块创建的匿名函数
f() do
Base.@constprop :aggressive
...
end
在函数体内的使用需要至少 Julia 1.10。
Base.gensym
— Functiongensym([tag])
生成一个符号,该符号不会与其他变量名(在同一模块中)冲突。
Base.@gensym
— Macro@gensym
为变量生成一个 gensym 符号。例如,@gensym x y
被转换为 x = gensym("x"); y = gensym("y")
。
var"name"
— Keywordvar
语法 var"#example#"
指的是一个名为 Symbol("#example#")
的变量,即使 #example#
不是一个有效的 Julia 标识符名称。
这对于与具有不同有效标识符构造规则的编程语言的互操作性非常有用。例如,要在你的 Julia 代码中引用 R
变量 draw.segments
,你可以使用 var"draw.segments"
。
它也用于 show
经过宏卫生处理或包含无法正常解析的变量名称的 Julia 源代码。
请注意,这种语法需要解析器支持,因此它是由解析器直接扩展的,而不是作为普通字符串宏 @var_str
实现的。
这种语法至少需要 Julia 1.3。
Base.@goto
— Macro@goto name
@goto name
无条件跳转到位置 @label name
的语句。
@label
和 @goto
不能创建跳转到不同的顶级语句。尝试会导致错误。要仍然使用 @goto
,请将 @label
和 @goto
包含在一个块中。
Base.@label
— Macro@label name
将语句标记为符号标签 name
。该标签标记了与 @goto name
的无条件跳转的终点。
Base.SimdLoop.@simd
— Macro@simd
注释一个 for
循环,以允许编译器采取额外的自由度来允许循环重排序
!!! 警告 此功能是实验性的,可能会在未来的 Julia 版本中发生变化或消失。错误使用 @simd
宏可能会导致意外结果。
在 @simd for
循环中迭代的对象应该是一个一维范围。通过使用 @simd
,您正在断言循环的几个属性:
- 在任意或重叠顺序中执行迭代是安全的,特别考虑到归约变量。
- 对归约变量的浮点操作可以被重排序或收缩,可能导致与没有
@simd
时不同的结果。
在许多情况下,Julia 能够在不使用 @simd
的情况下自动向量化内部 for 循环。使用 @simd
给编译器提供了一些额外的余地,使其在更多情况下成为可能。在任何情况下,您的内部循环应具有以下属性以允许向量化:
- 循环必须是最内层循环
- 循环体必须是直线代码。因此,当前所有数组访问都需要
@inbounds
。如果安全地无条件评估所有操作数,编译器有时可以将短的&&
、||
和?:
表达式转换为直线代码。如果安全,可以考虑在循环中使用ifelse
函数代替?:
。 - 访问必须具有步幅模式,不能是“聚集”(随机索引读取)或“散布”(随机索引写入)。
- 步幅应为单位步幅。
!!! 注意 默认情况下,@simd
并不断言循环完全没有循环携带的内存依赖关系,这是在通用代码中很容易被违反的假设。如果您正在编写非通用代码,可以使用 @simd ivdep for ... end
还可以断言:
- 不存在循环携带的内存依赖关系
- 没有迭代会等待先前的迭代以取得前进进展。
Base.@polly
— Macro@polly
告诉编译器对一个函数应用多面体优化器 Polly。
Base.@generated
— Macro@generated f
@generated
用于注解将要生成的函数。在生成的函数体内,只能读取参数的类型(而不是值)。该函数返回一个在调用函数时评估的引用表达式。@generated
宏不应在改变全局作用域或依赖可变元素的函数上使用。
有关更多详细信息,请参见 Metaprogramming。
示例
julia> @generated function bar(x)
if x <: Integer
return :(x ^ 2)
else
return :(x)
end
end
bar (generic function with 1 method)
julia> bar(4)
16
julia> bar("baz")
"baz"
Base.@assume_effects
— MacroBase.@assume_effects 设置... [ex]
覆盖编译器的效果建模。此宏可以在几种上下文中使用:
- 在方法定义之前立即使用,以覆盖应用方法的整个效果建模。
- 在没有任何参数的函数体内使用,以覆盖封闭方法的整个效果建模。
- 应用于代码块,以覆盖应用代码块的局部效果建模。
示例
julia> Base.@assume_effects :terminates_locally function fact(x)
# 用法 1:
# 这个 :terminates_locally 允许 `fact` 被常量折叠
res = 1
0 ≤ x < 20 || error("bad fact")
while x > 1
res *= x
x -= 1
end
return res
end
fact (generic function with 1 method)
julia> code_typed() do
fact(12)
end |> only
CodeInfo(
1 ─ return 479001600
) => Int64
julia> code_typed() do
map((2,3,4)) do x
# 用法 2:
# 这个 :terminates_locally 允许这个匿名函数被常量折叠
Base.@assume_effects :terminates_locally
res = 1
0 ≤ x < 20 || error("bad fact")
while x > 1
res *= x
x -= 1
end
return res
end
end |> only
CodeInfo(
1 ─ return (2, 6, 24)
) => Tuple{Int64, Int64, Int64}
julia> code_typed() do
map((2,3,4)) do x
res = 1
0 ≤ x < 20 || error("bad fact")
# 用法 3:
# 使用这个 :terminates_locally 注释,编译器跳过在这个 `while` 块内的污点
# `:terminates` 效果,允许父级匿名函数被常量折叠
Base.@assume_effects :terminates_locally while x > 1
res *= x
x -= 1
end
return res
end
end |> only
CodeInfo(
1 ─ return (2, 6, 24)
) => Tuple{Int64, Int64, Int64}
使用 Base.@assume_effects
需要 Julia 版本 1.8。
在函数体内的使用至少需要 Julia 1.10。
代码块注释至少需要 Julia 1.11。
不当使用此宏会导致未定义行为(包括崩溃、错误答案或其他难以追踪的错误)。请谨慎使用,并仅在绝对必要时作为最后手段使用。即使在这种情况下,您也应该采取一切可能的步骤来最小化效果断言的强度(例如,如果 :nothrow
足够,则不要使用 :total
)。
一般来说,每个 setting
值对函数的行为做出断言,而不要求编译器证明这种行为确实为真。这些断言适用于所有世界年龄。因此,建议限制使用可能在以后扩展以使假设无效的通用函数(这将导致未定义行为)。
支持以下 setting
。
:consistent
:effect_free
:nothrow
:terminates_globally
:terminates_locally
:notaskstate
:inaccessiblememonly
:noub
:noub_if_noinbounds
:nortcall
:foldable
:removable
:total
扩展帮助
:consistent
:consistent
设置断言对于相等 (===
) 的输入:
- 终止的方式(返回值、异常、非终止)将始终相同。
- 如果方法返回,结果将始终相等。
这特别意味着该方法不得返回新分配的可变对象。多次分配可变对象(即使内容相同)也不相等。
:consistent
-cy 断言是按世界年龄进行的。更正式地说,写 $fᵢ$ 为在世界年龄 $i$ 中对 $f$ 的评估,则此设置要求:
\[∀ i, x, y: x ≡ y → fᵢ(x) ≡ fᵢ(y)\]
然而,对于两个世界年龄 $i$ 和 $j$,使得 $i ≠ j$,我们可能有 $fᵢ(x) ≢ fⱼ(y)$。
进一步的含义是 :consistent
函数不得使其返回值依赖于堆的状态或任何其他在给定世界年龄下不恒定的全局状态。
:consistent
-cy 包括优化器执行的所有合法重写。例如,浮点快速数学操作不被视为 :consistent
,因为优化器可能重写它们,导致输出在相同世界年龄下不 :consistent
(例如,因为一个在解释器中运行,而另一个被优化了)。
如果 :consistent
函数通过抛出异常终止,则该异常本身不需要满足上述的相等性要求。
:effect_free
:effect_free
设置断言该方法没有外部语义可见的副作用。以下是外部语义可见副作用的不完整列表:
- 改变全局变量的值。
- 变更堆(例如数组或可变值),除非如下所述
- 改变方法表(例如通过调用 eval)
- 文件/网络等 I/O
- 任务切换
然而,以下内容显然不是语义可见的,即使它们可能是可观察的:
- 内存分配(可变和不可变)
- 经过的时间
- 垃圾收集
- 对于生命周期不超过方法的对象的堆变更(即在方法中分配且不逃逸的对象)。
- 返回值(虽然是外部可见的,但不是副作用)
这里的经验法则是,外部可见的副作用是任何会影响程序其余部分执行的内容,如果该函数未被执行。
:effect_free
断言适用于方法本身以及方法执行的任何代码。请记住,该断言必须对所有世界年龄有效,并相应地限制使用此断言。
:nothrow
:nothrow
设置断言该方法不会抛出异常(即将始终返回一个值或永不返回)。
允许 :nothrow
注释的方法在内部使用异常处理,只要异常不在方法本身中重新抛出。
如果方法的执行可能引发 MethodError
和类似异常,则该方法不被视为 :nothrow
。但是,请注意,像 StackOverflowError
或 InterruptException
这样的环境依赖错误不被此效果建模,因此可能导致 StackOverflowError
的方法不一定需要 !:nothrow
(尽管通常也应该是 !:terminates
)。
:terminates_globally
:terminates_globally
设置断言该方法最终会终止(无论是正常还是异常),即不会无限循环。
此 :terminates_globally
断言涵盖任何被注释方法调用的其他方法。
编译器将视此为该方法相对快速终止的强烈指示,并且可能(如果其他合法)在编译时调用此方法。即在一个技术上终止但实际上不终止的方法上注释此设置是个坏主意。
:terminates_locally
:terminates_locally
设置类似于 :terminates_globally
,但仅适用于注释方法内的语法控制流。因此,这是一个更弱(因此更安全)的断言,允许在方法调用其他不终止的方法时可能出现非终止的情况。
:terminates_globally
隐含 :terminates_locally
。
:notaskstate
:notaskstate
设置断言该方法不使用或修改本地任务状态(任务本地存储、随机数生成器状态等),因此可以安全地在任务之间移动而不会产生可观察的结果。
异常处理的实现使用存储在任务对象中的状态。然而,目前此状态不被视为 :notaskstate
的范围,并且使用 :nothrow
效果单独跟踪。
:notaskstate
断言涉及当前运行任务的状态。如果通过其他方式获得对 Task
对象的引用,而不考虑哪个任务是当前运行的,则 :notaskstate
效果不需要被污染。即使该任务对象恰好与当前运行的任务相等,这也是如此。
访问任务状态通常还会导致其他效果的污染,例如 :effect_free
(如果修改了任务状态)或 :consistent
(如果在计算结果时使用了任务状态)。特别是,代码不是 :notaskstate
,但同时是 :effect_free
和 :consistent
的代码仍然可能被消除死代码,因此提升为 :total
。
:inaccessiblememonly
:inaccessiblememonly
设置断言该方法不访问或修改外部可访问的可变内存。这意味着该方法可以访问或修改新分配对象的可变内存,该内存在返回方法之前对其他方法或顶级执行不可访问,但不能访问或修改任何可变全局状态或其参数指向的可变内存。
以下是使此假设无效的不完整示例:
- 访问可变全局变量的全局引用或
getglobal
调用 - 对非常量全局变量执行赋值的全局赋值或
setglobal!
调用 - 改变全局可变变量字段的
setfield!
调用
此 :inaccessiblememonly
断言涵盖任何被注释方法调用的其他方法。
:noub
:noub
设置断言该方法不会执行任何未定义行为(对于任何输入)。请注意,未定义行为在技术上可能导致该方法违反任何其他效果断言(例如 :consistent
或 :effect_free
),但我们不对其建模,并假设不存在未定义行为。
:nortcall
:nortcall
设置断言该方法不调用 Core.Compiler.return_type
,并且该方法可能调用的任何其他方法也不调用 Core.Compiler.return_type
。
精确地说,当在运行时未调用 Core.Compiler.return_type
时,可以使用此断言;即,当 Core.Compiler.return_type
的结果在编译时已知并且调用被优化器消除时。然而,由于 Core.Compiler.return_type
的结果是否在编译时折叠在很大程度上取决于编译器的实现,因此如果相关方法以任何形式使用 Core.Compiler.return_type
,则通常很危险地断言这一点。
:foldable
此设置是编译器要求保证在编译时常量折叠调用的效果集合的便捷快捷方式。它目前等同于以下 setting
:
:consistent
:effect_free
:terminates_globally
:noub
:nortcall
此列表特别不包括 :nothrow
。编译器仍将尝试常量传播并在编译时注意任何抛出的错误。然而,请注意,根据 :consistent
-cy 的要求,任何此类注释调用必须在给定相同参数值时一致地抛出。
函数内部的显式 @inbounds
注释也将禁用常量折叠,并且不会被 :foldable
覆盖。
:removable
此设置是编译器要求保证在编译时删除未使用结果的调用的效果集合的便捷快捷方式。它目前等同于以下 setting
:
:effect_free
:nothrow
:terminates_globally
:total
此 setting
是可能的最大效果集合。它目前隐含以下其他 setting
:
:consistent
:effect_free
:nothrow
:terminates_globally
:notaskstate
:inaccessiblememonly
:noub
:nortcall
:total
是一个非常强的断言,并且在未来的 Julia 版本中可能会获得额外的语义(例如,如果添加了额外的效果并包含在 :total
的定义中)。因此,应该谨慎使用。尽可能地,优先使用特定应用所需的最小效果断言集合。在适用大量效果覆盖的函数集的情况下,建议使用自定义宏,而不是使用 :total
。
否定效果
效果名称可以通过 !
前缀来表示该效果应从先前的元效果中移除。例如,:total !:nothrow
表示虽然调用通常是完全的,但它可能会抛出。
Managing deprecations
Base.@deprecate
— Macro@deprecate old new [export_old=true]
弃用方法 old
并指定替代调用 new
,同时定义一个具有指定签名的新方法 old
。
要防止 old
被导出,将 export_old
设置为 false
。
另见 Base.depwarn()
。
从 Julia 1.5 开始,当 julia
在未设置 --depwarn=yes
标志的情况下运行时,通过 @deprecate
定义的函数不会打印警告,因为 --depwarn
选项的默认值为 no
。 警告是通过 Pkg.test()
运行的测试打印的。
示例
julia> @deprecate old(x) new(x)
old (generic function with 1 method)
julia> @deprecate old(x) new(x) false
old (generic function with 1 method)
没有显式类型注释的 @deprecate
调用将定义接受任意数量位置参数和关键字参数类型为 Any
的弃用方法。
从 Julia 1.9 开始,当没有显式类型注释时,关键字参数会被转发。对于旧版本,您可以通过 @deprecate old(args...; kwargs...) new(args...; kwargs...)
手动转发位置参数和关键字参数。
要将弃用限制为特定签名,请注释 old
的参数。例如,
julia> new(x::Int) = x;
julia> new(x::Float64) = 2x;
julia> @deprecate old(x::Int) new(x);
julia> methods(old)
# 1 method for generic function "old" from Main:
[1] old(x::Int64)
@ deprecated.jl:94
将定义并弃用一个方法 old(x::Int)
,该方法与 new(x::Int)
相对应,但不会定义或弃用方法 old(x::Float64)
。
Base.depwarn
— FunctionBase.depwarn(msg::String, funcsym::Symbol; force=false)
打印 msg
作为弃用警告。符号 funcsym
应该是调用函数的名称,用于确保弃用警告仅在每个调用位置第一次打印。设置 force=true
以强制始终显示警告,即使 Julia 是以 --depwarn=no
启动的(默认情况下)。
另见 @deprecate
。
示例
function deprecated_func()
Base.depwarn("Don't use `deprecated_func()`!", :deprecated_func)
1 + 1
end
Missing Values
Base.Missing
— TypeBase.missing
— ConstantBase.coalesce
— Functioncoalesce(x...)
返回参数中第一个不等于 missing
的值(如果有的话)。否则返回 missing
。
另请参见 skipmissing
, something
, @coalesce
。
示例
julia> coalesce(missing, 1)
1
julia> coalesce(1, missing)
1
julia> coalesce(nothing, 1) # 返回 `nothing`
julia> coalesce(missing, missing)
missing
Base.@coalesce
— Macro@coalesce(x...)
coalesce
的短路版本。
示例
julia> f(x) = (println("f($x)"); missing);
julia> a = 1;
julia> a = @coalesce a f(2) f(3) error("`a` 仍然是缺失的")
1
julia> b = missing;
julia> b = @coalesce b f(2) f(3) error("`b` 仍然是缺失的")
f(2)
f(3)
ERROR: `b` 仍然是缺失的
[...]
此宏自 Julia 1.7 起可用。
Base.ismissing
— FunctionBase.skipmissing
— Functionskipmissing(itr)
返回一个迭代器,遍历 itr
中的元素,跳过 missing
值。返回的对象可以使用 itr
的索引进行索引,如果后者是可索引的。对应于缺失值的索引是无效的:它们被 keys
和 eachindex
跳过,并且在尝试使用它们时会抛出 MissingException
。
使用 collect
来获取一个包含 itr
中非 missing
值的 Array
。请注意,即使 itr
是一个多维数组,结果始终是一个 Vector
,因为在保留输入的维度的同时无法删除缺失值。
另见 coalesce
,ismissing
,something
。
示例
julia> x = skipmissing([1, missing, 2])
skipmissing(Union{Missing, Int64}[1, missing, 2])
julia> sum(x)
3
julia> x[1]
1
julia> x[2]
ERROR: MissingException: the value at index (2,) is missing
[...]
julia> argmax(x)
3
julia> collect(keys(x))
2-element Vector{Int64}:
1
3
julia> collect(skipmissing([1, missing, 2]))
2-element Vector{Int64}:
1
2
julia> collect(skipmissing([1 missing; 2 missing]))
2-element Vector{Int64}:
1
2
Base.nonmissingtype
— Functionnonmissingtype(T::Type)
如果 T
是一个包含 Missing
的类型的联合体,则返回一个去除 Missing
的新类型。
示例
julia> nonmissingtype(Union{Int64,Missing})
Int64
julia> nonmissingtype(Any)
Any
从 Julia 1.3 开始导出了此函数。
System
Base.run
— Functionrun(command, args...; wait::Bool = true)
运行一个命令对象,该对象使用反引号构造(请参见手册中的 Running External Programs 部分)。如果出现任何问题,包括进程以非零状态退出(当 wait
为 true 时),则会抛出错误。
args...
允许您将文件描述符传递给命令,并且按常规 unix 文件描述符的顺序排列(例如 stdin, stdout, stderr, FD(3), FD(4)...
)。
如果 wait
为 false,进程将异步运行。您可以稍后等待它并通过在返回的进程对象上调用 success
来检查其退出状态。
当 wait
为 false 时,进程的 I/O 流被定向到 devnull
。当 wait
为 true 时,I/O 流与父进程共享。使用 pipeline
来控制 I/O 重定向。
Base.devnull
— Constantdevnull
用于流重定向,以丢弃写入其中的所有数据。基本上等同于 Unix 上的 /dev/null
或 Windows 上的 NUL
。用法:
run(pipeline(`cat test.txt`, devnull))
Base.success
— Functionsuccess(command)
运行一个命令对象,该对象使用反引号构造(请参见手册中的 Running External Programs 部分),并告知其是否成功(以代码 0 退出)。如果无法启动该进程,将引发异常。
Base.process_running
— Functionprocess_running(p::Process)
确定一个进程是否当前正在运行。
Base.process_exited
— Functionprocess_exited(p::Process)
确定一个进程是否已退出。
Base.kill
— Methodkill(p::Process, signum=Base.SIGTERM)
向进程发送信号。默认情况下是终止该进程。如果进程已经退出,则成功返回,但如果由于其他原因(例如权限不足)导致无法终止进程,则会抛出错误。
Base.Sys.set_process_title
— FunctionSys.set_process_title(title::AbstractString)
设置进程标题。在某些操作系统上无操作。
Base.Sys.get_process_title
— FunctionSys.get_process_title()
获取进程标题。在某些系统上,将始终返回一个空字符串。
Base.ignorestatus
— Functionignorestatus(command)
标记一个命令对象,以便运行它时,如果结果代码为非零,则不会抛出错误。
Base.detach
— Functiondetach(command)
标记一个命令对象,使其在一个新的进程组中运行,从而允许它超出 julia 进程的生命周期,并且不会将 Ctrl-C 中断传递给它。
Base.Cmd
— TypeCmd(cmd::Cmd; ignorestatus, detach, windows_verbatim, windows_hide, env, dir)
Cmd(exec::Vector{String})
构造一个新的 Cmd
对象,表示一个外部程序及其参数,来自 cmd
,同时更改可选关键字参数的设置:
ignorestatus::Bool
:如果为true
(默认为false
),则Cmd
在返回代码非零时不会抛出错误。detach::Bool
:如果为true
(默认为false
),则Cmd
将在一个新的进程组中运行,允许它超出julia
进程的生命周期,并且不会将 Ctrl-C 传递给它。windows_verbatim::Bool
:如果为true
(默认为false
),则在 Windows 上,Cmd
将以不进行引号或转义参数的方式将命令行字符串发送给进程,即使参数包含空格。(在 Windows 上,参数作为单个“命令行”字符串发送给程序,程序负责将其解析为参数。默认情况下,空参数和包含空格或制表符的参数在命令行中用双引号"
引起来,并且\
或"
前面有反斜杠。windows_verbatim=true
对于启动以非标准方式解析其命令行的程序非常有用。)对非 Windows 系统没有影响。windows_hide::Bool
:如果为true
(默认为false
),则在 Windows 上执行Cmd
时不会显示新的控制台窗口。如果已经打开控制台或在非 Windows 系统上,则没有影响。env
:设置运行Cmd
时使用的环境变量。env
可以是一个将字符串映射到字符串的字典,一个形式为"var=val"
的字符串数组,或一对"var"=>val
的数组或元组。为了修改(而不是替换)现有环境,使用copy(ENV)
初始化env
,然后根据需要设置env["var"]=val
。要在Cmd
对象中添加环境块而不替换所有元素,请使用addenv()
,它将返回一个具有更新环境的Cmd
对象。dir::AbstractString
:指定命令的工作目录(而不是当前目录)。
对于未指定的任何关键字,将使用 cmd
的当前设置。
请注意,Cmd(exec)
构造函数不会创建 exec
的副本。对 exec
的任何后续更改将反映在 Cmd
对象中。
构造 Cmd
对象的最常见方法是使用命令字面量(反引号),例如:
`ls -l`
然后可以将其传递给 Cmd
构造函数以修改其设置,例如:
Cmd(`echo "Hello world"`, ignorestatus=true, detach=false)
Base.setenv
— Functionsetenv(command::Cmd, env; dir)
设置在运行给定 command
时使用的环境变量。env
可以是一个将字符串映射到字符串的字典,一个形式为 "var=val"
的字符串数组,或者零个或多个 "var"=>val
对参数。为了修改(而不是替换)现有环境,可以通过 copy(ENV)
创建 env
,然后根据需要设置 env["var"]=val
,或者使用 addenv
。
dir
关键字参数可用于指定命令的工作目录。dir
默认为 command
当前设置的 dir
(如果未指定,则为当前工作目录)。
Base.addenv
— Functionaddenv(command::Cmd, env...; inherit::Bool = true)
将新的环境映射合并到给定的 Cmd
对象中,返回一个新的 Cmd
对象。重复的键会被替换。如果 command
中尚未设置任何环境值,则在 inherit
为 true
时,它会继承 addenv()
调用时的当前环境。值为 nothing
的键会从环境中删除。
此函数需要 Julia 1.6 或更高版本。
Base.withenv
— Functionwithenv(f, kv::Pair...)
在一个临时修改(而不是像 setenv
那样替换)环境中执行 f
,通过零个或多个 "var"=>val
参数 kv
。withenv
通常通过 withenv(kv...) do ... end
语法使用。可以使用 nothing
的值来临时取消设置环境变量(如果已设置)。当 withenv
返回时,原始环境已被恢复。
更改环境不是线程安全的。对于使用与父进程不同的环境运行外部命令,建议使用 addenv
而不是 withenv
。
Base.setcpuaffinity
— Functionsetcpuaffinity(original_command::Cmd, cpus) -> command::Cmd
通过一组 CPU ID(基于 1 的索引)cpus
设置 command
的 CPU 亲和性。传递 cpus = nothing
意味着如果 original_command
有任何 CPU 亲和性,则取消设置。
此功能仅在 Linux 和 Windows 中受支持。在 macOS 中不受支持,因为 libuv 不支持亲和性设置。
此功能至少需要 Julia 1.8。
示例
在 Linux 中,可以使用 taskset
命令行程序查看 setcpuaffinity
的工作原理。
julia> run(setcpuaffinity(`sh -c 'taskset -p $$'`, [1, 2, 5]));
pid 2273's current affinity mask: 13
请注意,掩码值 13
反映出第一个、第二个和第五个位(从最低有效位开始计数)被打开:
julia> 0b010011
0x13
Base.pipeline
— Methodpipeline(from, to, ...)
创建一个从数据源到目的地的管道。源和目的地可以是命令、I/O 流、字符串或其他 pipeline
调用的结果。至少一个参数必须是命令。字符串指的是文件名。当使用超过两个参数调用时,它们会从左到右链接在一起。例如,pipeline(a,b,c)
等价于 pipeline(pipeline(a,b),c)
。这提供了一种更简洁的方式来指定多阶段管道。
示例:
run(pipeline(`ls`, `grep xyz`))
run(pipeline(`ls`, "out.txt"))
run(pipeline("out.txt", `grep xyz`))
Base.pipeline
— Methodpipeline(command; stdin, stdout, stderr, append=false)
将输入/输出重定向到给定的 command
。关键字参数指定应重定向命令的哪个流。append
控制文件输出是否追加到文件。这是 2 个参数的 pipeline
函数的更一般版本。当 from
是命令时,pipeline(from, to)
等价于 pipeline(from, stdout=to)
,当 from
是另一种数据源时,等价于 pipeline(to, stdin=from)
。
示例:
run(pipeline(`dothings`, stdout="out.txt", stderr="errs.txt"))
run(pipeline(`update`, stdout="log.txt", append=true))
Base.Libc.gethostname
— Functiongethostname() -> String
获取本地机器的主机名。
Base.Libc.getpid
— Functiongetpid() -> Int32
获取 Julia 的进程 ID。
getpid(process) -> Int32
获取子进程 ID,如果它仍然存在。
此函数至少需要 Julia 1.1。
Base.Libc.time
— Methodtime() -> Float64
获取自纪元以来的系统时间(以秒为单位),具有相当高的(通常是微秒级)分辨率。
Base.time_ns
— Functiontime_ns() -> UInt64
获取以纳秒为单位的时间。对应于0的时间是未定义的,并且每5.8年会循环一次。
Base.@time
— Macro@time expr
@time "描述" expr
一个宏,用于执行一个表达式,打印执行所花费的时间、分配的数量以及执行导致的总字节数的分配,然后返回表达式的值。任何花费在垃圾收集(gc)、编译新代码或重新编译失效代码上的时间以百分比形式显示。任何需要等待的 ReentrantLock
的锁冲突以计数形式显示。
可选地提供一个描述字符串,在时间报告之前打印。
在某些情况下,系统会在 @time
表达式内部查看并在顶层表达式执行开始之前编译一些被调用的代码。当发生这种情况时,一些编译时间将不会被计算。要包括这段时间,可以运行 @time @eval ...
。
另请参见 @showtime
、@timev
、@timed
、@elapsed
、@allocated
和 @allocations
。
对于更严肃的基准测试,考虑使用 BenchmarkTools.jl 包中的 @btime
宏,该宏在多次评估函数以减少噪声等方面表现出色。
添加描述的选项是在 Julia 1.8 中引入的。
编译时间与重新编译时间分开显示是在 Julia 1.8 中引入的。
在 Julia 1.11 中添加了任何锁冲突的报告。
julia> x = rand(10,10);
julia> @time x * x;
0.606588 秒 (2.19 M 分配: 116.555 MiB, 3.75% gc 时间, 99.94% 编译时间)
julia> @time x * x;
0.000009 秒 (1 分配: 896 字节)
julia> @time begin
sleep(0.3)
1+1
end
0.301395 秒 (8 分配: 336 字节)
2
julia> @time "一秒的睡眠" sleep(1)
一秒的睡眠: 1.005750 秒 (5 分配: 144 字节)
julia> for loop in 1:3
@time loop sleep(1)
end
1: 1.006760 秒 (5 分配: 144 字节)
2: 1.001263 秒 (5 分配: 144 字节)
3: 1.003676 秒 (5 分配: 144 字节)
Base.@showtime
— Macro@showtime expr
类似于 @time
,但还会打印出被评估的表达式以供参考。
此宏是在 Julia 1.8 中添加的。
另见 @time
。
julia> @showtime sleep(1)
sleep(1): 1.002164 seconds (4 allocations: 128 bytes)
Base.@timev
— Macro@timev expr
@timev "description" expr
这是 @time
宏的详细版本。它首先打印与 @time
相同的信息,然后打印任何非零的内存分配计数器,最后返回表达式的值。
可选地提供一个描述字符串,在时间报告之前打印。
添加描述的选项是在 Julia 1.8 中引入的。
另请参见 @time
、@timed
、@elapsed
、@allocated
和 @allocations
。
julia> x = rand(10,10);
julia> @timev x * x;
0.546770 seconds (2.20 M allocations: 116.632 MiB, 4.23% gc time, 99.94% compilation time)
elapsed time (ns): 546769547
gc time (ns): 23115606
bytes allocated: 122297811
pool allocs: 2197930
non-pool GC allocs:1327
malloc() calls: 36
realloc() calls: 5
GC pauses: 3
julia> @timev x * x;
0.000010 seconds (1 allocation: 896 bytes)
elapsed time (ns): 9848
bytes allocated: 896
pool allocs: 1
Base.@timed
— Macro@timed
一个宏,用于执行一个表达式,并返回该表达式的值、经过的时间(以秒为单位)、总分配的字节数、垃圾回收时间、一个包含各种内存分配计数器的对象、编译时间(以秒为单位)和重新编译时间(以秒为单位)。任何需要等待的 ReentrantLock
的锁冲突将以计数的形式显示。
在某些情况下,系统会查看 @timed
表达式内部,并在顶层表达式执行开始之前编译一些被调用的代码。当发生这种情况时,一些编译时间将不会被计算。要包括这段时间,您可以运行 @timed @eval ...
。
另请参见 @time
、@timev
、@elapsed
、@allocated
、@allocations
和 @lock_conflicts
。
julia> stats = @timed rand(10^6);
julia> stats.time
0.006634834
julia> stats.bytes
8000256
julia> stats.gctime
0.0055765
julia> propertynames(stats.gcstats)
(:allocd, :malloc, :realloc, :poolalloc, :bigalloc, :freecall, :total_time, :pause, :full_sweep)
julia> stats.gcstats.total_time
5576500
julia> stats.compile_time
0.0
julia> stats.recompile_time
0.0
此宏的返回类型在 Julia 1.5 中从 Tuple
更改为 NamedTuple
。
lock_conflicts
、compile_time
和 recompile_time
字段在 Julia 1.11 中添加。
Base.@elapsed
— Macro@elapsed
一个宏,用于评估一个表达式,丢弃结果值,而是返回执行所需的秒数,作为浮点数。
在某些情况下,系统会查看 @elapsed
表达式内部,并在顶层表达式执行开始之前编译一些被调用的代码。当发生这种情况时,一些编译时间将不会被计算在内。要包括这段时间,可以运行 @elapsed @eval ...
。
另请参见 @time
、@timev
、@timed
、@allocated
和 @allocations
。
julia> @elapsed sleep(0.3)
0.301391426
Base.@allocated
— Macro@allocated
一个宏,用于评估一个表达式,丢弃结果值,而是返回在评估该表达式期间分配的总字节数。
另见 @allocations
,@time
,@timev
,@timed
和 @elapsed
。
julia> @allocated rand(10^6)
8000080
Base.@allocations
— Macro@allocations
一个宏,用于评估一个表达式,丢弃结果值,而是返回在评估表达式期间的总分配次数。
另见 @allocated
, @time
, @timev
, @timed
, 和 @elapsed
。
julia> @allocations rand(10^6)
2
这个宏是在 Julia 1.9 中添加的。
Base.@lock_conflicts
— Macro@lock_conflicts
一个宏,用于评估一个表达式,丢弃结果值,而是返回评估期间锁冲突的总数,其中对ReentrantLock
的锁尝试由于锁已被持有而导致等待。
julia> @lock_conflicts begin
l = ReentrantLock()
Threads.@threads for i in 1:Threads.nthreads()
lock(l) do
sleep(1)
end
end
end
5
此宏是在Julia 1.11中添加的。
Base.EnvDict
— TypeEnvDict() -> EnvDict
此类型的单例提供了一个哈希表接口来访问环境变量。
Base.ENV
— ConstantENV
对单例 EnvDict
的引用,提供了一个字典接口来访问系统环境变量。
(在 Windows 上,系统环境变量不区分大小写,因此 ENV
相应地将所有键转换为大写以便于显示、迭代和复制。可移植的代码不应依赖于通过大小写区分变量的能力,并应注意设置一个表面上是小写的变量可能会导致大写的 ENV
键。)
修改环境不是线程安全的。
示例
julia> ENV
Base.EnvDict with "50" entries:
"SECURITYSESSIONID" => "123"
"USER" => "username"
"MallocNanoZone" => "0"
⋮ => ⋮
julia> ENV["JULIA_EDITOR"] = "vim"
"vim"
julia> ENV["JULIA_EDITOR"]
"vim"
Base.Sys.STDLIB
— ConstantSys.STDLIB::String
一个包含 stdlib
包所在目录的完整路径的字符串。
Base.Sys.isunix
— FunctionSys.isunix([os])
用于测试操作系统是否提供类Unix接口的谓词。请参阅处理操作系统变异中的文档。
Base.Sys.isapple
— FunctionSys.isapple([os])
用于测试操作系统是否是 Apple Macintosh OS X 或 Darwin 的衍生版本的谓词。请参阅 处理操作系统变体 中的文档。
Base.Sys.islinux
— FunctionSys.islinux([os])
用于测试操作系统是否是 Linux 的衍生版本的谓词。请参阅 处理操作系统变异 中的文档。
Base.Sys.isbsd
— FunctionSys.isbsd([os])
用于测试操作系统是否是BSD的衍生版本的谓词。请参阅处理操作系统变体中的文档。
Darwin内核源自BSD,这意味着在macOS系统上Sys.isbsd()
为true
。要从谓词中排除macOS,请使用Sys.isbsd() && !Sys.isapple()
。
Base.Sys.isfreebsd
— FunctionSys.isfreebsd([os])
用于测试操作系统是否是 FreeBSD 的派生版本的谓词。请参阅 处理操作系统变体 中的文档。
不要与 Sys.isbsd()
混淆,后者在 FreeBSD 上为 true
,但在其他基于 BSD 的系统上也为 true
。Sys.isfreebsd()
仅指 FreeBSD。
此函数至少需要 Julia 1.1。
Base.Sys.isopenbsd
— FunctionSys.isopenbsd([os])
用于测试操作系统是否是 OpenBSD 的派生版本的谓词。请参阅 处理操作系统变体 中的文档。
不要与 Sys.isbsd()
混淆,后者在 OpenBSD 上为 true
,但在其他基于 BSD 的系统上也为 true
。Sys.isopenbsd()
仅指 OpenBSD。
此函数至少需要 Julia 1.1。
Base.Sys.isnetbsd
— FunctionSys.isnetbsd([os])
用于测试操作系统是否是 NetBSD 的派生版本的谓词。请参阅 处理操作系统变异 中的文档。
不要与 Sys.isbsd()
混淆,后者在 NetBSD 上为 true
,但在其他基于 BSD 的系统上也为 true
。Sys.isnetbsd()
仅指 NetBSD。
此函数至少需要 Julia 1.1。
Base.Sys.isdragonfly
— FunctionSys.isdragonfly([os])
用于测试操作系统是否是 DragonFly BSD 的派生版本的谓词。请参阅 Handling Operating System Variation 中的文档。
不要与 Sys.isbsd()
混淆,后者在 DragonFly 以及其他基于 BSD 的系统上均为 true
。Sys.isdragonfly()
仅指 DragonFly。
此函数至少需要 Julia 1.1。
Base.Sys.iswindows
— FunctionSys.iswindows([os])
用于测试操作系统是否是 Microsoft Windows NT 的衍生版本的谓词。请参阅 处理操作系统变异 中的文档。
Base.Sys.windows_version
— FunctionSys.windows_version()
返回 Windows NT 内核的版本号,格式为 VersionNumber
,即 v"major.minor.build"
,如果不是在 Windows 上运行,则返回 v"0.0.0"
。
Base.Sys.free_memory
— FunctionSys.free_memory()
获取以字节为单位的 RAM 中的总空闲内存。
Base.Sys.total_memory
— FunctionSys.total_memory()
获取RAM中总内存(包括当前使用的内存),以字节为单位。此数量可能受到限制,例如,由Linux控制组限制。有关不受限制的数量,请参见Sys.total_physical_memory()
。
Base.Sys.free_physical_memory
— FunctionSys.free_physical_memory()
获取系统中以字节为单位的可用内存。整个数量可能并不对当前进程可用;使用 Sys.free_memory()
获取实际可用的数量。
Base.Sys.total_physical_memory
— FunctionSys.total_physical_memory()
获取RAM中总内存(包括当前使用的内存),单位为字节。整个内存量可能并不对当前进程可用;请参见Sys.total_memory()
。
Base.Sys.uptime
— FunctionSys.uptime()
获取当前系统的运行时间(以秒为单位)。
Base.Sys.isjsvm
— FunctionSys.isjsvm([os])
用于测试 Julia 是否在 JavaScript 虚拟机 (JSVM) 中运行的谓词,包括例如在网页浏览器中的 WebAssembly JavaScript 嵌入。
此函数至少需要 Julia 1.2。
Base.Sys.loadavg
— FunctionSys.loadavg()
获取负载平均值。请参见:https://en.wikipedia.org/wiki/Load_(computing)。
Base.Sys.isexecutable
— Functionisexecutable(path::String)
如果给定的 path
具有可执行权限,则返回 true
。
在用户执行 path
之前,这个权限可能会改变,因此建议执行文件并处理错误(如果失败),而不是先调用 isexecutable
。
在 Julia 1.6 之前,这个函数无法正确查询 Windows 上的文件系统 ACL,因此它会对任何文件返回 true
。从 Julia 1.6 开始,它能够正确判断文件是否被标记为可执行。
另请参见 ispath
,isreadable
,iswritable
。
Base.Sys.isreadable
— Functionisreadable(path::String)
如果给定 path
的访问权限允许当前用户读取,则返回 true
。
在用户调用 open
之前,这个权限可能会改变,因此建议仅调用 open
并在失败时处理错误,而不是先调用 isreadable
。
目前此函数无法正确查询 Windows 上的文件系统 ACL,因此可能返回错误结果。
此函数至少需要 Julia 1.11。
另请参见 ispath
, isexecutable
, iswritable
。
isreadable(io) -> Bool
如果指定的 IO 对象不可读,则返回 false
。
示例
julia> open("myfile.txt", "w") do io
print(io, "Hello world!");
isreadable(io)
end
false
julia> open("myfile.txt", "r") do io
isreadable(io)
end
true
julia> rm("myfile.txt")
Base.Sys.iswritable
— Functioniswritable(path::String)
如果给定 path
的访问权限允许当前用户写入,则返回 true
。
在用户调用 open
之前,这个权限可能会改变,因此建议仅调用 open
并在失败时处理错误,而不是先调用 iswritable
。
目前此函数在 Windows 上无法正确查询文件系统 ACL,因此可能返回错误结果。
此函数至少需要 Julia 1.11。
另请参见 ispath
, isexecutable
, isreadable
。
iswritable(io) -> Bool
如果指定的 IO 对象不可写,则返回 false
。
示例
julia> open("myfile.txt", "w") do io
print(io, "Hello world!");
iswritable(io)
end
true
julia> open("myfile.txt", "r") do io
iswritable(io)
end
false
julia> rm("myfile.txt")
Base.Sys.username
— FunctionSys.username() -> String
返回当前用户的用户名。如果无法确定用户名或用户名为空,则此函数会抛出错误。
要检索可以通过环境变量覆盖的用户名,例如 USER
,可以考虑使用
user = get(Sys.username, ENV, "USER")
此函数至少需要 Julia 1.11。
另请参见 homedir
.
Base.@static
— Macro@static
在解析时部分求值一个表达式。
例如,@static Sys.iswindows() ? foo : bar
将会求值 Sys.iswindows()
并将 foo
或 bar
插入到表达式中。这在某些情况下非常有用,例如在其他平台上无效的构造,比如对不存在的函数的 ccall
。@static if Sys.isapple() foo end
和 @static foo <&&,||> bar
也是有效的语法。
Versioning
Base.VersionNumber
— Type版本号
版本号类型遵循语义版本控制 (semver)的规范,由主版本号、次版本号和修订号的数字值组成,后面跟有预发布和构建的字母数字注释。
VersionNumber
对象可以与所有标准比较运算符(==
、<
、<=
等)进行比较,结果遵循 semver 规则。
VersionNumber
具有以下公共字段:
v.major::Integer
v.minor::Integer
v.patch::Integer
v.prerelease::Tuple{Vararg{Union{Integer, AbstractString}}}
v.build::Tuple{Vararg{Union{Integer, AbstractString}}}
另请参见 @v_str
,以高效地从 semver 格式的字面字符串构造 VersionNumber
对象,VERSION
获取 Julia 本身的 VersionNumber
,以及手册中的 版本号字面量。
示例
julia> a = VersionNumber(1, 2, 3)
v"1.2.3"
julia> a >= v"1.2"
true
julia> b = VersionNumber("2.0.1-rc1")
v"2.0.1-rc1"
julia> b >= v"2.0.1"
false
Base.@v_str
— MacroErrors
Base.error
— Functionerror(message::AbstractString)
引发一个带有给定消息的 ErrorException
。
error(msg...)
引发一个 ErrorException
,其消息由 string(msg...)
构造。
Core.throw
— FunctionBase.rethrow
— Functionrethrow()
在 catch
块中重新抛出当前异常。重新抛出的异常将继续传播,就好像它没有被捕获一样。
替代形式 rethrow(e)
允许你将一个替代异常对象 e
与当前的回溯关联。然而,这会错误地表示错误发生时程序的状态,因此建议你使用 throw(e)
抛出一个新的异常。在 Julia 1.1 及以上版本中,使用 throw(e)
将保留堆栈上的根本原因异常,如 current_exceptions
中所述。
Base.backtrace
— Functionbacktrace()
获取当前程序点的回溯对象。
Base.catch_backtrace
— Functioncatch_backtrace()
获取当前异常的回溯,用于 catch
块中。
Base.current_exceptions
— Functioncurrent_exceptions(task::Task=current_task(); [backtrace::Bool=true])
获取当前正在处理的异常堆栈。对于嵌套的捕获块,可能会有多个当前异常,在这种情况下,最近抛出的异常在堆栈的最后。堆栈作为 ExceptionStack
返回,它是命名元组 (exception,backtrace)
的 AbstractVector。如果 backtrace
为 false,则每对中的回溯将被设置为 nothing
。
显式传递 task
将返回任意任务上的当前异常堆栈。这对于检查由于未捕获异常而失败的任务非常有用。
这个函数在 Julia 1.1–1.6 中以实验性名称 catch_stack()
存在,并且返回类型是一个普通的元组向量。
Base.@assert
— Macro@assert cond [text]
如果 cond
为 false
,则抛出一个 AssertionError
。这是编写断言的首选语法,断言是被假定为真的条件,但用户可能会决定检查它们,以帮助调试如果它们失败。可选消息 text
在断言失败时显示。
在某些优化级别下,断言可能会被禁用。因此,断言应仅作为调试工具使用,而不应用于身份验证验证(例如,验证密码或检查数组边界)。代码不得依赖于运行 cond
的副作用来确保函数的正确行为。
示例
julia> @assert iseven(3) "3 is an odd number!"
ERROR: AssertionError: 3 is an odd number!
julia> @assert isodd(3) "What even are numbers?"
Base.Experimental.register_error_hint
— FunctionExperimental.register_error_hint(handler, exceptiontype)
注册一个“提示”函数 handler(io, exception)
,该函数可以建议用户绕过错误的潜在方法。handler
应该检查 exception
以确定是否满足提示的条件,如果满足,则生成输出到 io
。包应该在其 __init__
函数中调用 register_error_hint
。
对于特定的异常类型,handler
需要接受额外的参数:
MethodError
:提供handler(io, exc::MethodError, argtypes, kwargs)
,它将组合的参数拆分为位置参数和关键字参数。
发出提示时,输出通常应以 \n
开头。
如果您定义了自定义异常类型,您的 showerror
方法可以通过调用 Experimental.show_error_hints
来支持提示。
示例
julia> module Hinter
only_int(x::Int) = 1
any_number(x::Number) = 2
function __init__()
Base.Experimental.register_error_hint(MethodError) do io, exc, argtypes, kwargs
if exc.f == only_int
# 颜色不是必需的,这只是为了显示这是可能的。
print(io, "\n您是想调用 ")
printstyled(io, "`any_number`?", color=:cyan)
end
end
end
end
然后,如果您在不是 Int
的东西上调用 Hinter.only_int
(从而触发 MethodError
),它会发出提示:
julia> Hinter.only_int(1.0)
ERROR: MethodError: no method matching only_int(::Float64)
函数 `only_int` 存在,但没有为此参数类型组合定义方法。
您是想调用 `any_number`?
最近的候选者是:
...
自定义错误提示自 Julia 1.5 起可用。
此接口是实验性的,可能会在没有通知的情况下更改或删除。为了保护自己免受更改的影响,请考虑将任何注册放在 if isdefined(Base.Experimental, :register_error_hint) ... end
块中。
Base.Experimental.show_error_hints
— FunctionExperimental.show_error_hints(io, ex, args...)
调用来自 Experimental.register_error_hint
的所有处理程序,针对特定异常类型 typeof(ex)
。args
必须包含该类型的处理程序所期望的任何其他参数。
从 Julia 1.5 开始提供自定义错误提示。
此接口是实验性的,可能会在没有通知的情况下更改或删除。
Core.ArgumentError
— TypeArgumentError(msg)
传递给函数的参数无效。msg
是一个描述性的错误消息。
Core.AssertionError
— TypeAssertionError([msg])
断言条件未评估为 true
。可选参数 msg
是一个描述性错误字符串。
示例
julia> @assert false "this is not true"
ERROR: AssertionError: this is not true
AssertionError
通常是从 @assert
抛出的。 ```
Core.BoundsError
— TypeBoundsError([a],[i])
对数组 a
的索引操作尝试访问索引 i
的越界元素。
示例
julia> A = fill(1.0, 7);
julia> A[8]
错误: BoundsError: 尝试访问 7-element Vector{Float64} 的索引 [8]
julia> B = fill(1.0, (2,3));
julia> B[2, 4]
错误: BoundsError: 尝试访问 2×3 Matrix{Float64} 的索引 [2, 4]
julia> B[9]
错误: BoundsError: 尝试访问 2×3 Matrix{Float64} 的索引 [9]
Base.CompositeException
— Type复合异常
将由Task
抛出的异常的Vector
包装起来(例如,从远程工作者通过通道生成,或异步执行的本地I/O写入,或在pmap
下的远程工作者),并提供关于一系列异常的信息。例如,如果一组工作者正在执行多个任务,并且多个工作者失败,结果复合异常
将包含来自每个工作者的“捆绑”信息,指示异常发生的位置和原因。
Base.DimensionMismatch
— TypeDimensionMismatch([msg])
被调用的对象的维度不匹配。可选参数 msg
是一个描述性的错误字符串。
Core.DivideError
— TypeDivideError()
尝试进行整数除法,但分母值为 0。
示例
julia> 2/0
Inf
julia> div(2, 0)
ERROR: DivideError: integer division error
Stacktrace:
[...]
Core.DomainError
— TypeDomainError(val)
DomainError(val, msg)
参数 val
对于一个函数或构造函数来说超出了有效域。
示例
julia> sqrt(-1)
ERROR: DomainError with -1.0:
sqrt 被调用时使用了一个负的实数参数,但只有在使用复数参数时才会返回复数结果。尝试使用 sqrt(Complex(x))。
Stacktrace:
[...]
Base.EOFError
— TypeEOFError()
没有更多数据可供从文件或流中读取。
Core.ErrorException
— TypeErrorException(msg)
通用错误类型。错误消息在 .msg
字段中,可能提供更具体的细节。
示例
julia> ex = ErrorException("我做了一件坏事");
julia> ex.msg
"我做了一件坏事"
Core.InexactError
— TypeInexactError(name::Symbol, T, val)
无法将 val
精确转换为类型 T
,在函数 name
的一个方法中。
示例
julia> convert(Float64, 1+2im)
ERROR: InexactError: Float64(1 + 2im)
Stacktrace:
[...]
Core.InterruptException
— TypeInterruptException()
该进程被终端中断(CTRL+C)停止。
请注意,在没有 -i
(交互式)选项启动的 Julia 脚本中,默认情况下不会抛出 InterruptException
。在脚本中调用 Base.exit_on_sigint(false)
可以恢复 REPL 的行为。或者,可以使用以下命令启动 Julia 脚本:
julia -e "include(popfirst!(ARGS))" script.jl
以便在执行期间让 CTRL+C 抛出 InterruptException
。
Base.KeyError
— TypeKeyError(key)
对 AbstractDict
(Dict
) 或 Set
类对象的索引操作尝试访问或删除一个不存在的元素。
Core.LoadError
— TypeLoadError(file::AbstractString, line::Int, error)
在 include
、require
或 using
文件时发生错误。错误的具体信息应在 .error
字段中可用。
从 Julia 1.7 开始,@macroexpand
、@macroexpand1
和 macroexpand
不再发出 LoadErrors。
Core.MethodError
— TypeMethodError(f, args)
在给定的泛型函数中不存在具有所需类型签名的方法。或者,没有唯一的最特定方法。
Base.MissingException
— TypeMissingException(msg)
当遇到不支持的 missing
值时抛出异常。错误消息可能在 msg
字段中提供更具体的细节。
Core.OutOfMemoryError
— TypeOutOfMemoryError()
一个操作为系统或垃圾收集器分配了过多的内存,导致无法正确处理。
Core.ReadOnlyMemoryError
— TypeReadOnlyMemoryError()
一个操作试图写入只读内存。
Core.OverflowError
— TypeOverflowError(msg)
表达式的结果对于指定类型来说太大,将导致溢出。
Base.ProcessFailedException
— TypeProcessFailedException
表示进程的退出状态有问题。当运行命令或管道时,如果返回了非零的退出代码(即调用的进程失败),则会抛出此异常。
Base.TaskFailedException
— TypeTaskFailedException
此异常由 wait(t)
调用抛出,当任务 t
失败时。TaskFailedException
包装了失败的任务 t
。
Core.StackOverflowError
— TypeStackOverflowError()
函数调用超出了调用栈的大小。这通常发生在调用无限递归时。
Base.SystemError
— TypeSystemError(prefix::AbstractString, [errno::Int32])
系统调用失败,错误代码存储在 errno
全局变量中。
Core.TypeError
— TypeTypeError(func::Symbol, context::AbstractString, expected::Type, got)
类型断言失败,或以不正确的参数类型调用内置函数。
Core.UndefKeywordError
— TypeUndefKeywordError(var::Symbol)
所需的关键字参数 var
在函数调用中未被赋值。
示例
julia> function my_func(;my_arg)
return my_arg + 1
end
my_func (generic function with 1 method)
julia> my_func()
ERROR: UndefKeywordError: keyword argument `my_arg` not assigned
Stacktrace:
[1] my_func() at ./REPL[1]:2
[2] top-level scope at REPL[2]:1
Core.UndefRefError
— TypeUndefRefError()
该项或字段未在给定对象中定义。
示例
julia> struct MyType
a::Vector{Int}
MyType() = new()
end
julia> A = MyType()
MyType(#undef)
julia> A.a
错误:UndefRefError:访问未定义的引用
堆栈跟踪:
[...]
Core.UndefVarError
— TypeUndefVarError(var::Symbol, [scope])
当前作用域中的符号未定义。
示例
julia> a
ERROR: UndefVarError: `a` not defined in `Main`
julia> a = 1;
julia> a
1
Base.StringIndexError
— TypeStringIndexError(str, i)
尝试访问无效索引 i
的 str
时发生错误。
Core.InitError
— TypeInitError(mod::Symbol, error)
在运行模块的 __init__
函数时发生了错误。实际抛出的错误可以在 .error
字段中找到。
Base.retry
— Functionretry(f; delays=ExponentialBackOff(), check=nothing) -> Function
返回一个匿名函数,该函数调用函数 f
。如果出现异常,f
将在每次 check
返回 true
后,重复调用,每次等待 delays
指定的秒数。check
应输入 delays
的当前状态和 Exception
。
在 Julia 1.2 之前,此签名仅限于 f::Function
。
示例
retry(f, delays=fill(5.0, 3))
retry(f, delays=rand(5:10, 2))
retry(f, delays=Base.ExponentialBackOff(n=3, first_delay=5, max_delay=1000))
retry(http_get, check=(s,e)->e.status == "503")(url)
retry(read, check=(s,e)->isa(e, IOError))(io, 128; all=false)
Base.ExponentialBackOff
— TypeExponentialBackOff(; n=1, first_delay=0.05, max_delay=10.0, factor=5.0, jitter=0.1)
一个长度为 n
的 Float64
迭代器,其元素以 factor
* (1 ± jitter
) 的速率指数增长。第一个元素为 first_delay
,所有元素都被限制在 max_delay
之内。
Events
Base.Timer
— MethodTimer(callback::Function, delay; interval = 0)
创建一个定时器,在每次定时器到期时运行函数 callback
。
等待的任务会被唤醒,函数 callback
在初始延迟 delay
秒后被调用,然后以给定的间隔(以秒为单位)重复调用。如果 interval
等于 0
,则回调只会运行一次。函数 callback
以一个参数被调用,即定时器本身。通过调用 close
来停止定时器。如果定时器已经到期,callback
可能仍会被最后一次运行。
示例
这里第一个数字在延迟两秒后打印,然后后续的数字快速打印。
julia> begin
i = 0
cb(timer) = (global i += 1; println(i))
t = Timer(cb, 2, interval=0.2)
wait(t)
sleep(0.5)
close(t)
end
1
2
3
Base.Timer
— TypeTimer(delay; interval = 0)
创建一个定时器,唤醒等待它的任务(通过在定时器对象上调用 wait
)。
等待的任务在至少 delay
秒的初始延迟后被唤醒,然后在至少 interval
秒再次经过后重复唤醒。如果 interval
等于 0
,则定时器只会触发一次。当定时器被关闭(通过 close
)时,等待的任务会被唤醒并抛出错误。使用 isopen
检查定时器是否仍然处于活动状态。
interval
受时间偏差的累积影响。如果您需要在特定绝对时间精确事件,请在每次到期时创建一个新定时器,并计算到下一个时间的差值。
Timer
需要让出点来更新其状态。例如,isopen(t::Timer)
不能用于超时非让出的 while 循环。
Base.AsyncCondition
— TypeAsyncCondition()
创建一个异步条件,当从 C 通过调用 uv_async_send
通知时,唤醒等待它的任务(通过在对象上调用 wait
)。当对象被关闭时(通过 close
),等待的任务会被唤醒并带有错误。使用 isopen
检查它是否仍然处于活动状态。
这在发送和等待线程之间提供了隐式的获取和释放内存顺序。
Base.AsyncCondition
— MethodAsyncCondition(callback::Function)
创建一个异步条件,调用给定的 callback
函数。callback
被传递一个参数,即异步条件对象本身。
Reflection
Base.nameof
— MethodBase.parentmodule
— Functionparentmodule(m::Module) -> Module
获取模块的封闭 Module
。Main
是它自己的父模块。
另请参见:names
, nameof
, fullname
, @__MODULE__
。
示例
julia> parentmodule(Main)
Main
julia> parentmodule(Base.Broadcast)
Base
parentmodule(t::DataType) -> Module
确定包含(可能被 UnionAll
包裹的)DataType
定义的模块。
示例
julia> module Foo
struct Int end
end
Foo
julia> parentmodule(Int)
Core
julia> parentmodule(Foo.Int)
Foo
parentmodule(f::Function) -> Module
确定包含(第一个)通用函数定义的模块。
parentmodule(f::Function, types) -> Module
确定包含与指定 types
匹配的通用函数 f
的第一个方法的模块。
parentmodule(m::Method) -> Module
返回定义给定方法 m
的模块。
将 Method
作为参数传递需要 Julia 1.9 或更高版本。
Base.pathof
— Methodpathof(m::Module)
返回用于 import
模块 m
的 m.jl
文件的路径,如果 m
不是从包中导入的,则返回 nothing
。
使用 dirname
获取路径的目录部分,使用 basename
获取文件名部分。
另见 pkgdir
。
Base.pkgdir
— Methodpkgdir(m::Module[, paths::String...])
返回声明模块 m
的包的根目录,如果 m
不是在包中声明的,则返回 nothing
。可以选择提供更多路径组件字符串,以在包根目录内构造路径。
要获取实现当前模块的包的根目录,可以使用形式 pkgdir(@__MODULE__)
。
如果给定的是扩展模块,则返回父包的根目录。
julia> pkgdir(Foo)
"/path/to/Foo.jl"
julia> pkgdir(Foo, "src", "file.jl")
"/path/to/Foo.jl/src/file.jl"
另见 pathof
。
可选参数 paths
至少需要 Julia 1.7。
Base.pkgversion
— Methodpkgversion(m::Module)
返回导入模块 m
的包的版本,如果 m
不是从包中导入的,或者从没有设置版本字段的包中导入,则返回 nothing
。
版本在包加载期间从包的 Project.toml 中读取。
要获取导入当前模块的包的版本,可以使用形式 pkgversion(@__MODULE__)
。
此函数是在 Julia 1.9 中引入的。
Base.moduleroot
— Functionmoduleroot(m::Module) -> Module
查找给定模块的根模块。这是 m
的父模块链中第一个模块,该模块要么是注册的根模块,要么是其自身的父模块。
__module__
— Keyword__module__
参数 __module__
仅在宏内部可见,它提供有关宏调用的扩展上下文的信息(以 Module
对象的形式)。有关更多信息,请参见手册中关于 Macro invocation 的部分。
__source__
— Keyword__source__
参数 __source__
仅在宏内部可见,它提供有关宏调用中 @
符号的解析器位置的信息(以 LineNumberNode
对象的形式)。有关更多信息,请参见手册中关于 Macro invocation 的部分。
Base.@__MODULE__
— Macro@__MODULE__ -> 模块
获取顶层 eval 的 模块
,即当前正在读取代码的 模块
。
Base.@__FILE__
— Macro@__FILE__ -> String
扩展为包含宏调用的文件路径的字符串,如果通过 julia -e <expr>
评估,则返回空字符串。如果宏缺少解析器源信息,则返回 nothing
。另请参见 PROGRAM_FILE
。
Base.@__DIR__
— Macro@__DIR__ -> String
宏用于获取当前目录的绝对路径作为字符串。
如果在脚本中,返回包含 @__DIR__
宏调用的脚本的目录。如果从 REPL 运行或通过 julia -e <expr>
进行评估,则返回当前工作目录。
示例
该示例通过在与当前工作目录不同的目录中创建一个简单脚本,并执行两个命令,说明了 @__DIR__
和 pwd()
的行为差异:
julia> cd("/home/JuliaUser") # 工作目录
julia> # 在 /home/JuliaUser/Projects 创建脚本
open("/home/JuliaUser/Projects/test.jl","w") do io
print(io, """
println("@__DIR__ = ", @__DIR__)
println("pwd() = ", pwd())
""")
end
julia> # 输出脚本目录和当前工作目录
include("/home/JuliaUser/Projects/test.jl")
@__DIR__ = /home/JuliaUser/Projects
pwd() = /home/JuliaUser
Base.@__LINE__
— Macro@__LINE__ -> Int
扩展为宏调用位置的行号。如果无法确定行号,则返回 0
。
Base.fullname
— Functionfullname(m::Module)
获取模块的完全限定名称,返回一个符号元组。例如,
示例
julia> fullname(Base.Iterators)
(:Base, :Iterators)
julia> fullname(Main)
(:Main,)
Base.names
— Functionnames(x::Module; all::Bool = false, imported::Bool = false)
获取一个 Module
的公共名称向量,排除已弃用的名称。如果 all
为真,则列表还包括模块中定义的非公共名称、已弃用的名称和编译器生成的名称。如果 imported
为真,则还包括从其他模块显式导入的名称。名称按排序顺序返回。
作为特例,所有在 Main
中定义的名称被视为“公共”,因为在 Main
中显式标记名称为公共并不是惯用的做法。
sym ∈ names(SomeModule)
并不 意味着 isdefined(SomeModule, sym)
。names
将返回标记为 public
或 export
的符号,即使它们未在模块中定义。
另请参见: Base.isexported
, Base.ispublic
, Base.@locals
, @__MODULE__
.
Base.isexported
— Functionisexported(m::Module, s::Symbol) -> Bool
返回一个符号是否从模块中导出。
julia> module Mod
export foo
public bar
end
Mod
julia> Base.isexported(Mod, :foo)
true
julia> Base.isexported(Mod, :bar)
false
julia> Base.isexported(Mod, :baz)
false
Base.ispublic
— Functionispublic(m::Module, s::Symbol) -> Bool
返回一个符号在模块中是否被标记为公共。
导出的符号被视为公共。
此函数和公共性的概念是在 Julia 1.11 中添加的。
另请参见: isexported
, names
julia> module Mod
export foo
public bar
end
Mod
julia> Base.ispublic(Mod, :foo)
true
julia> Base.ispublic(Mod, :bar)
true
julia> Base.ispublic(Mod, :baz)
false
Base.nameof
— Methodnameof(f::Function) -> Symbol
获取通用 Function
的名称作为符号。对于匿名函数,这是编译器生成的名称。对于显式声明的 Function
子类型,它是函数类型的名称。
Base.functionloc
— Methodfunctionloc(f::Function, types)
返回一个元组 (filename,line)
,给出通用 Function
定义的位置。
Base.functionloc
— Methodfunctionloc(m::Method)
返回一个元组 (filename,line)
,给出 Method
定义的位置。
Base.@locals
— Macro@locals()
构造一个字典,包含调用位置定义的所有局部变量的名称(作为符号)和值。
!!! 兼容 "Julia 1.1" 此宏至少需要 Julia 1.1。
示例
julia> let x = 1, y = 2
Base.@locals
end
Dict{Symbol, Any} with 2 entries:
:y => 2
:x => 1
julia> function f(x)
local y
show(Base.@locals); println()
for i = 1:1
show(Base.@locals); println()
end
y = 2
show(Base.@locals); println()
nothing
end;
julia> f(42)
Dict{Symbol, Any}(:x => 42)
Dict{Symbol, Any}(:i => 1, :x => 42)
Dict{Symbol, Any}(:y => 2, :x => 42)
Core.getglobal
— Functiongetglobal(module::Module, name::Symbol, [order::Symbol=:monotonic])
从模块 module
中检索绑定 name
的值。可以选择为操作定义原子顺序,否则默认为单调。
虽然使用 getfield
访问模块绑定仍然被支持以保持兼容性,但应始终优先使用 getglobal
,因为 getglobal
允许控制原子顺序(getfield
始终是单调的),并更好地向用户和编译器表明代码的意图。
大多数用户不应直接调用此函数 – 除少数非常特定的用例外,应优先使用 getproperty
函数或相应的语法(即 module.name
)。
此函数需要 Julia 1.9 或更高版本。
另请参见 getproperty
和 setglobal!
。
示例
julia> a = 1
1
julia> module M
a = 2
end;
julia> getglobal(@__MODULE__, :a)
1
julia> getglobal(M, :a)
2
Core.setglobal!
— Functionsetglobal!(module::Module, name::Symbol, x, [order::Symbol=:monotonic])
将模块 module
中的绑定 name
的值设置或更改为 x
。不执行类型转换,因此如果绑定已经声明了类型,x
必须是适当的类型,否则会抛出错误。
此外,可以为此操作指定原子顺序,否则默认为单调。
用户通常通过 setproperty!
函数或相应的语法(即 module.name = x
)访问此功能,因此这仅适用于非常特定的用例。
此函数需要 Julia 1.9 或更高版本。
另请参见 setproperty!
和 getglobal
示例
julia> module M; global a; end;
julia> M.a # 同 `getglobal(M, :a)`
ERROR: UndefVarError: `a` not defined in `M`
建议:添加适当的导入或赋值。此全局变量已声明但未赋值。
Stacktrace:
[1] getproperty(x::Module, f::Symbol)
@ Base ./Base.jl:42
[2] top-level scope
@ none:1
julia> setglobal!(M, :a, 1)
1
julia> M.a
1
Core.modifyglobal!
— Functionmodifyglobal!(module::Module, name::Symbol, op, x, [order::Symbol=:monotonic]) -> Pair
原子地执行操作以获取和设置全局变量,应用函数 op
。
此函数需要 Julia 1.11 或更高版本。
另请参见 modifyproperty!
和 setglobal!
。
Core.swapglobal!
— Functionswapglobal!(module::Module, name::Symbol, x, [order::Symbol=:monotonic])
原子性地执行操作,同时获取和设置全局变量。
此函数需要 Julia 1.11 或更高版本。
另请参见 swapproperty!
和 setglobal!
。
Core.setglobalonce!
— Functionsetglobalonce!(module::Module, name::Symbol, value,
[success_order::Symbol, [fail_order::Symbol=success_order]) -> success::Bool
原子地执行操作,将全局变量设置为给定值,仅在之前未设置的情况下。
此函数需要 Julia 1.11 或更高版本。
另请参见 setpropertyonce!
和 setglobal!
.
Core.replaceglobal!
— Functionreplaceglobal!(module::Module, name::Symbol, expected, desired,
[success_order::Symbol, [fail_order::Symbol=success_order]) -> (; old, success::Bool)
原子地执行操作以获取并有条件地将全局变量设置为给定值。
此函数需要 Julia 1.11 或更高版本。
另请参见 replaceproperty!
和 setglobal!
.
Documentation
(另见 documentation 章节。)
Core.@doc
— Macro文档
函数、方法和类型可以通过在定义之前放置一个字符串来进行文档化:
"""
# Foo 函数
`foo(x)`: 对 `x` 进行极致的 Foo 操作。
"""
foo(x) = ...
@doc
宏可以直接用于设置和检索文档/元数据。该宏具有特殊的解析功能,以便被文档化的对象可以出现在下一行:
@doc "blah"
function foo() ...
默认情况下,文档以 Markdown 格式编写,但任何对象都可以用作第一个参数。
将对象的文档与其定义分开
您可以在对象定义之前或之后进行文档化:
@doc "foo" function_to_doc
@doc "bar" TypeToDoc
对于宏,语法为 @doc "macro doc" :(Module.@macro)
或 @doc "macro doc" :(string_macro"")
用于字符串宏。没有引号 :()
的情况下,宏的扩展将被文档化。
检索文档
您可以按如下方式检索函数、宏和其他对象的文档:
@doc foo
@doc @time
@doc md""
函数与方法
在方法定义之前放置文档(例如 function foo() ...
或 foo() = ...
)将导致该特定方法被文档化,而不是整个函数。方法文档按定义的顺序连接在一起,以提供函数的文档。
Base.Docs.HTML
— TypeHTML(s)
: 创建一个对象,将 s
渲染为 html。
HTML("<div>foo</div>")
您还可以使用流来处理大量数据:
HTML() do io
println(io, "<div>foo</div>")
end
HTML
目前被导出以保持向后兼容性,但此导出已被弃用。建议将此类型用作 Docs.HTML
或从 Docs
显式导入。
Base.Docs.Text
— TypeText(s)
: 创建一个对象,将 s
渲染为纯文本。
Text("foo")
您还可以使用流来处理大量数据:
Text() do io
println(io, "foo")
end
Text
目前被导出以保持向后兼容性,但此导出已被弃用。建议将此类型用作 Docs.Text
或从 Docs
显式导入。
Base.Docs.hasdoc
— FunctionDocs.hasdoc(mod::Module, sym::Symbol)::Bool
如果 sym
在 mod
中有文档字符串,则返回 true
,否则返回 false
。
Base.Docs.undocumented_names
— Functionundocumented_names(mod::Module; private=false)
返回一个已排序的向量,包含 module
中未记录的符号(即缺少文档字符串)。private=false
(默认值)仅返回使用 public
和/或 export
声明的标识符,而 private=true
返回模块中的所有符号(不包括以 #
开头的编译器生成的隐藏符号)。
另请参见: names
, Docs.hasdoc
, Base.ispublic
.
Code loading
Base.identify_package
— FunctionBase.identify_package(name::String)::Union{PkgId, Nothing}
Base.identify_package(where::Union{Module,PkgId}, name::String)::Union{PkgId, Nothing}
通过名称从当前环境栈中识别包,返回其 PkgId
,如果找不到则返回 nothing
。
如果只提供 name
参数,它会搜索栈中的每个环境及其命名的直接依赖项。
where
参数提供了搜索包的上下文:在这种情况下,它首先检查名称是否与上下文本身匹配,否则它会搜索所有递归依赖项(来自每个环境的已解析清单),直到找到上下文 where
,然后从那里识别具有相应名称的依赖项。
julia> Base.identify_package("Pkg") # Pkg 是默认环境的一个依赖项
Pkg [44cfe95a-1eb2-52ea-b672-e2afdf69b78f]
julia> using LinearAlgebra
julia> Base.identify_package(LinearAlgebra, "Pkg") # Pkg 不是 LinearAlgebra 的依赖项
Base.locate_package
— FunctionBase.locate_package(pkg::PkgId)::Union{String, Nothing}
对应于标识符 pkg
的包的入口文件路径,如果未找到则返回 nothing
。另见 identify_package
。
julia> pkg = Base.identify_package("Pkg")
Pkg [44cfe95a-1eb2-52ea-b672-e2afdf69b78f]
julia> Base.locate_package(pkg)
"/path/to/julia/stdlib/v1.11/Pkg/src/Pkg.jl"
Base.require
— Functionrequire(into::Module, module::Symbol)
此函数是 using
/ import
实现的一部分,如果模块尚未在 Main
中定义。它也可以直接调用,以强制重新加载模块,无论它之前是否已被加载(例如,在交互式开发库时)。
在每个活动节点的 Main
模块上下文中加载源文件,搜索标准位置的文件。require
被视为顶级操作,因此它设置当前的 include
路径,但不使用它来搜索文件(请参见 include
的帮助)。此函数通常用于加载库代码,并由 using
隐式调用以加载包。
在搜索文件时,require
首先在全局数组 LOAD_PATH
中查找包代码。require
在所有平台上都是区分大小写的,包括那些具有不区分大小写文件系统的 macOS 和 Windows。
有关代码加载的更多详细信息,请参见手册中关于 modules 和 parallel computing 的部分。
Base.compilecache
— FunctionBase.compilecache(module::PkgId)
为一个模块及其所有依赖项创建一个预编译缓存文件。这可以用来减少包加载时间。缓存文件存储在 DEPOT_PATH[1]/compiled
中。有关重要说明,请参见 Module initialization and precompilation。
Base.isprecompiled
— FunctionBase.isprecompiled(pkg::PkgId; ignore_loaded::Bool=false)
返回给定项目中的 PkgId 是否已预编译。
默认情况下,此检查遵循与代码加载相同的方法,涉及当前加载的不同版本的依赖项与预期的依赖项之间的关系。要忽略已加载的模块并像在一个新的 Julia 会话中一样回答,请指定 ignore_loaded=true
。
此函数至少需要 Julia 1.10。
Base.get_extension
— Functionget_extension(parent::Module, extension::Symbol)
返回 parent
的 extension
模块,如果未加载该扩展,则返回 nothing
。
Internals
Base.GC.gc
— FunctionGC.gc([full=true])
执行垃圾回收。参数 full
决定了收集的类型:完全收集(默认)遍历所有活动对象(即完全标记),并应从所有不可达对象中回收内存。增量收集仅从不可达的年轻对象中回收内存。
即使请求了增量收集,GC 也可能决定执行完全收集。
过度使用可能会导致性能下降。
Base.GC.enable
— FunctionGC.enable(on::Bool)
使用布尔参数(true
表示启用,false
表示禁用)控制是否启用垃圾回收。返回先前的GC状态。
禁用垃圾回收应谨慎使用,因为这可能导致内存使用无限增长。
Base.GC.@preserve
— MacroGC.@preserve x1 x2 ... xn expr
在评估表达式 expr
的过程中,将对象 x1, x2, ...
标记为 正在使用中。这仅在不安全代码中需要,其中 expr
隐式使用 由 x
中的一个拥有的内存或其他资源。
x
的 隐式使用 涉及任何逻辑上由 x
拥有的资源的间接使用,编译器无法看到。一些示例:
- 通过
Ptr
直接访问对象的内存 - 将指针传递给
x
到ccall
- 使用
x
的资源,这些资源将在终结器中被清理。
@preserve
通常在典型用例中不会对性能产生任何影响,因为它只是短暂地延长了对象的生命周期。在实现中,@preserve
具有保护动态分配对象免受垃圾回收的效果。
示例
当使用 unsafe_load
从指针加载时,底层对象被隐式使用,例如 unsafe_load(p)
中隐式使用了 x
,如下所示:
julia> let
x = Ref{Int}(101)
p = Base.unsafe_convert(Ptr{Int}, x)
GC.@preserve x unsafe_load(p)
end
101
在将指针传递给 ccall
时,被指向的对象被隐式使用并应被保留。(但请注意,通常应直接将 x
传递给 ccall
,这算作显式使用。)
julia> let
x = "Hello"
p = pointer(x)
Int(GC.@preserve x @ccall strlen(p::Cstring)::Csize_t)
# 优选替代方案
Int(@ccall strlen(x::Cstring)::Csize_t)
end
5
Base.GC.safepoint
— FunctionGC.safepoint()
在程序中插入一个垃圾收集可能运行的点。这在多线程程序中是有用的,某些线程正在分配内存(因此可能需要运行垃圾收集),而其他线程仅执行简单操作(没有分配、任务切换或 I/O)。在不分配内存的线程中定期调用此函数允许垃圾收集运行。
此函数从 Julia 1.4 开始可用。
Base.GC.enable_logging
— FunctionGC.enable_logging(on::Bool)
当开启时,打印每次垃圾回收的统计信息到标准错误输出。
Base.GC.logging_enabled
— FunctionGC.logging_enabled()
返回是否通过 GC.enable_logging
启用了 GC 日志记录。
Base.Meta.lower
— Functionlower(m, x)
接受表达式 x
并返回在模块 m
中执行的等效表达式的降级形式。另见 code_lowered
。
Base.Meta.@lower
— Macro@lower [m] x
返回模块 m
中表达式 x
的降阶形式。默认情况下,m
是调用宏的模块。另见 lower
。
Base.Meta.parse
— Methodparse(str, start; greedy=true, raise=true, depwarn=true, filename="none")
解析表达式字符串并返回一个表达式(该表达式可以稍后传递给 eval 进行执行)。start
是 str
中第一个要开始解析的字符的代码单元索引(与所有字符串索引一样,这些不是字符索引)。如果 greedy
为 true
(默认值),parse
将尽量消耗尽可能多的输入;否则,它将在解析出有效表达式后立即停止。未完成但在语法上有效的表达式将返回 Expr(:incomplete, "(错误信息)")
。如果 raise
为 true
(默认值),除未完成表达式外的语法错误将引发错误。如果 raise
为 false
,parse
将返回一个在评估时会引发错误的表达式。如果 depwarn
为 false
,将抑制弃用警告。filename
参数用于在引发错误时显示诊断信息。
julia> Meta.parse("(α, β) = 3, 5", 1) # start of string
(:((α, β) = (3, 5)), 16)
julia> Meta.parse("(α, β) = 3, 5", 1, greedy=false)
(:((α, β)), 9)
julia> Meta.parse("(α, β) = 3, 5", 16) # end of string
(nothing, 16)
julia> Meta.parse("(α, β) = 3, 5", 11) # index of 3
(:((3, 5)), 16)
julia> Meta.parse("(α, β) = 3, 5", 11, greedy=false)
(3, 13)
Base.Meta.parse
— Methodparse(str; raise=true, depwarn=true, filename="none")
贪婪地解析表达式字符串,返回一个单一的表达式。如果在第一个表达式之后还有额外的字符,将抛出错误。如果raise
为true
(默认),语法错误将引发错误;否则,parse
将返回一个在评估时会引发错误的表达式。如果depwarn
为false
,则会抑制弃用警告。filename
参数用于在引发错误时显示诊断信息。
julia> Meta.parse("x = 3")
:(x = 3)
julia> Meta.parse("1.0.2")
错误: ParseError:
# 错误 @ none:1:1
1.0.2
└──┘ ── 无效的数字常量
[...]
julia> Meta.parse("1.0.2"; raise = false)
:($(Expr(:error, "无效的数字常量 "1.0."")))
julia> Meta.parse("x = ")
:($(Expr(:incomplete, "不完整: 输入的提前结束")))
Base.Meta.ParseError
— TypeParseError(msg)
传递给 parse
函数的表达式无法被解释为有效的 Julia 表达式。
Core.QuoteNode
— TypeQuoteNode
一个被引用的代码片段,不支持插值。有关详细信息,请参见关于QuoteNodes的手册部分。
Base.macroexpand
— Functionmacroexpand(m::Module, x; recursive=true)
取表达式 x
,并返回一个等效的表达式,去除所有宏(展开),以便在模块 m
中执行。recursive
关键字控制是否也展开更深层次的嵌套宏。下面的示例演示了这一点:
julia> module M
macro m1()
42
end
macro m2()
:(@m1())
end
end
M
julia> macroexpand(M, :(@m2()), recursive=true)
42
julia> macroexpand(M, :(@m2()), recursive=false)
:(#= REPL[16]:6 =# M.@m1)
Base.@macroexpand
— Macro@macroexpand [mod,] ex
返回等效的表达式,所有宏已被移除(展开)。如果提供了两个参数,第一个是要在其中评估的模块。
@macroexpand
和 macroexpand
之间存在差异。
- 虽然
macroexpand
接受一个关键字参数recursive
,@macroexpand
始终是递归的。有关非递归宏版本,请参见@macroexpand1
。 - 虽然
macroexpand
有一个显式的module
参数,@macroexpand
始终相对于调用它的模块进行展开。
这在以下示例中最好理解:
julia> module M
macro m()
1
end
function f()
(@macroexpand(@m),
macroexpand(M, :(@m)),
macroexpand(Main, :(@m))
)
end
end
M
julia> macro m()
2
end
@m (macro with 1 method)
julia> M.f()
(1, 1, 2)
使用 @macroexpand
时,表达式在代码中 @macroexpand
出现的地方展开(示例中的模块 M
)。使用 macroexpand
时,表达式在作为第一个参数给定的模块中展开。
两个参数的形式至少需要 Julia 1.11。
Base.@macroexpand1
— Macro@macroexpand1 [mod,] ex
非递归版本的 @macroexpand
。
Base.code_lowered
— Functioncode_lowered(f, types; generated=true, debuginfo=:default)
返回与给定的泛型函数和类型签名匹配的方法的降级形式(IR)的数组。
如果 generated
为 false
,返回的 CodeInfo
实例将对应于后备实现。如果不存在后备实现,将抛出错误。如果 generated
为 true
,这些 CodeInfo
实例将对应于通过扩展生成器所产生的方法体。
关键字 debuginfo
控制输出中存在的代码元数据的数量。
请注意,如果 types
不是叶类型,并且在 generated
为 true
的情况下,任何相应的方法是 @generated
方法,将抛出错误。
Base.code_typed
— Functioncode_typed(f, types; kw...)
返回一个类型推断的降级形式(IR)数组,适用于与给定的泛型函数和类型签名匹配的方法。
关键字参数
optimize::Bool = true
:可选,控制是否应用额外的优化,例如内联。debuginfo::Symbol = :default
:可选,控制输出中存在的代码元数据的数量,可能的选项是:source
或:none
。
内部关键字参数
本节应视为内部,仅供理解Julia编译器内部的人员使用。
world::UInt = Base.get_world_counter()
:可选,控制查找方法时使用的世界年龄,如果未指定,则使用当前世界年龄。interp::Core.Compiler.AbstractInterpreter = Core.Compiler.NativeInterpreter(world)
:可选,控制要使用的抽象解释器,如果未指定,则使用本地解释器。
示例
可以将参数类型放在元组中以获取相应的 code_typed
。
julia> code_typed(+, (Float64, Float64))
1-element Vector{Any}:
CodeInfo(
1 ─ %1 = Base.add_float(x, y)::Float64
└── return %1
) => Float64
Base.precompile
— Functionprecompile(f, argtypes::Tuple{Vararg{Any}})
编译给定的函数 f
以适应参数元组(类型) argtypes
,但不执行它。
precompile(f, argtypes::Tuple{Vararg{Any}}, m::Method)
为给定的参数类型预编译特定的方法。这可以用来预编译与通常通过调度选择的不同的方法,从而模拟 invoke
。
Base.jit_total_bytes
— FunctionBase.jit_total_bytes()
返回即时编译器为例如本机代码和数据分配的总量(以字节为单位)。
Meta
Base.Meta.quot
— FunctionMeta.quot(ex)::Expr
将表达式 ex
引用以生成一个头为 quote
的表达式。这可以用于表示 AST 中的 Expr
类型的对象。另请参阅关于 QuoteNode 的手册部分。
示例
julia> eval(Meta.quot(:x))
:x
julia> dump(Meta.quot(:x))
Expr
head: Symbol quote
args: Array{Any}((1,))
1: Symbol x
julia> eval(Meta.quot(:(1+2)))
:(1 + 2)
Base.isexpr
— FunctionMeta.isexpr(ex, head[, n])::Bool
如果 ex
是具有给定类型 head
的 Expr
,并且可选地参数列表的长度为 n
,则返回 true
。head
可以是一个 Symbol
或 Symbol
的集合。例如,要检查一个宏是否传递了一个函数调用表达式,可以使用 isexpr(ex, :call)
。
示例
julia> ex = :(f(x))
:(f(x))
julia> Meta.isexpr(ex, :block)
false
julia> Meta.isexpr(ex, :call)
true
julia> Meta.isexpr(ex, [:block, :call]) # 多个可能的头
true
julia> Meta.isexpr(ex, :call, 1)
false
julia> Meta.isexpr(ex, :call, 2)
true
Base.isidentifier
— Function isidentifier(s) -> Bool
返回符号或字符串 s
是否包含在 Julia 代码中解析为有效普通标识符(不是二元/一元运算符)的字符;另见 Base.isoperator
。
在内部,Julia 允许 Symbol
中的任何字符序列(除了 \0
),并且宏自动使用包含 #
的变量名,以避免与周围代码的命名冲突。为了让解析器识别变量,它使用有限的字符集(通过 Unicode 大大扩展)。isidentifier()
使得可以直接查询解析器某个符号是否包含有效字符。
示例
julia> Meta.isidentifier(:x), Meta.isidentifier("1x")
(true, false)
Base.isoperator
— Functionisoperator(s::Symbol)
如果符号可以用作运算符,则返回 true
,否则返回 false
。
示例
julia> Meta.isoperator(:+), Meta.isoperator(:f)
(true, false)
Base.isunaryoperator
— Functionisunaryoperator(s::Symbol)
如果符号可以用作一元(前缀)运算符,则返回 true
,否则返回 false
。
示例
julia> Meta.isunaryoperator(:-), Meta.isunaryoperator(:√), Meta.isunaryoperator(:f)
(true, true, false)
Base.isbinaryoperator
— Functionisbinaryoperator(s::Symbol)
如果符号可以用作二元(中缀)运算符,则返回 true
,否则返回 false
。
示例
julia> Meta.isbinaryoperator(:-), Meta.isbinaryoperator(:√), Meta.isbinaryoperator(:f)
(true, false, false)
Base.Meta.show_sexpr
— FunctionMeta.show_sexpr([io::IO,], ex)
以 lisp 风格的 S 表达式显示表达式 ex
。
示例
julia> Meta.show_sexpr(:(f(x, g(y,z))))
(:call, :f, :x, (:call, :g, :y, :z))