基本概念
简介
Julia Base 包含一系列适合进行科学和数值计算的函数和宏,但也与许多通用编程语言一样广泛。更多功能可从不断增长的 可用包 集合中获得。下面按主题对函数进行分组。
一些一般性说明
- 要使用模块函数,请使用
import Module
导入模块,并使用Module.fn(x)
使用函数。 - 或者,
using Module
会将所有导出的Module
函数导入到当前命名空间中。 - 按照惯例,以感叹号 (
!
) 结尾的函数名会修改它们的参数。某些函数同时拥有修改 (例如,sort!
) 和非修改 (sort
) 版本。
Base
和标准库的行为仅在 SemVer 中定义为稳定,如果它们已记录;即,包含在 Julia 文档 中,并且未被标记为不稳定。有关更多信息,请参见 API 常见问题解答。
使用指南
Base.exit
— 函数exit(code=0)
使用退出代码停止程序。默认退出代码为零,表示程序已成功完成。在交互式会话中,可以使用键盘快捷键 ^D
调用 exit()
。
Base.atexit
— 函数atexit(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
— 函数isinteractive() -> Bool
确定 Julia 是否正在运行交互式会话。
Base.summarysize
— 函数Base.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__
— 函数__precompile__(isprecompilable::Bool)
指定调用此函数的文件是否可预编译,默认为 true
。如果一个模块或文件不能安全地预编译,则它应该调用 __precompile__(false)
,以便在 Julia 尝试预编译它时抛出错误。
Base.include
— 函数Base.include([mapexpr::Function,] m::Module, path::AbstractString)
在模块 m
的全局范围内评估输入源文件的内容。每个模块(除使用 baremodule
定义的模块外)都拥有自己的 include
定义,它省略了 m
参数,该参数在该模块中评估文件。返回输入文件的最后一个已评估表达式的结果。在包含期间,一个任务本地包含路径被设置为包含该文件的目录。对 include
的嵌套调用将在该路径的相对位置进行搜索。此函数通常用于交互式加载源代码,或者将拆分为多个源文件的包中的文件组合起来。
可选的第一个参数 mapexpr
可用于在评估包含的代码之前对其进行转换:对于 path
中的每个解析表达式 expr
,include
函数实际上会评估 mapexpr(expr)
。如果省略,mapexpr
默认为 identity
。
传递 mapexpr
参数需要 Julia 1.5。
Base.MainInclude.include
— 函数include([mapexpr::Function,] path::AbstractString)
在包含模块的全局范围内评估输入源文件的内容。每个模块(除使用 baremodule
定义的模块外)都拥有自己的 include
定义,该参数在该模块中评估文件。返回输入文件的最后一个已评估表达式的结果。在包含期间,一个任务本地包含路径被设置为包含该文件的目录。对 include
的嵌套调用将在该路径的相对位置进行搜索。此函数通常用于交互式加载源代码,或者将拆分为多个源文件的包中的文件组合起来。参数 path
使用 normpath
进行规范化,这将解析诸如 ..
之类的相对路径标记并将 /
转换为适当的路径分隔符。
可选的第一个参数 mapexpr
可用于在评估包含的代码之前对其进行转换:对于 path
中的每个解析表达式 expr
,include
函数实际上会评估 mapexpr(expr)
。如果省略,mapexpr
默认为 identity
。
使用 Base.include
将文件评估到另一个模块中。
传递 mapexpr
参数需要 Julia 1.5。
Base.include_string
— 函数include_string([mapexpr::Function,] m::Module, code::AbstractString, filename::AbstractString="string")
与 include
类似,但从给定的字符串而不是从文件读取代码。
可选的第一个参数 mapexpr
可用于在评估包含的代码之前对其进行转换:对于 code
中的每个解析表达式 expr
,include_string
函数实际上会评估 mapexpr(expr)
。如果省略,mapexpr
默认为 identity
。
传递 mapexpr
参数需要 Julia 1.5。
Base.include_dependency
— 函数include_dependency(path::AbstractString)
在一个模块中,声明由path
指定的文件、目录或符号链接(相对或绝对)是预编译的依赖项;也就是说,如果path
的修改时间改变,则需要重新编译模块。
这只有在您的模块依赖于未通过include
使用的路径时才需要。它在编译之外没有影响。
__init__
— 关键字__init__
模块中的__init__()
函数在模块首次在运行时加载后立即执行。它只调用一次,在模块中所有其他语句执行完毕后。因为它是在完全导入模块后调用的,所以子模块的__init__
函数将首先执行。__init__
的两个典型用途是调用外部 C 库的运行时初始化函数,以及初始化涉及外部库返回的指针的全局常量。有关详细信息,请参阅关于模块的手册部分。
示例
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
— 方法which(f, types)
返回f
(一个Method
对象)的方法,该方法将针对给定types
的参数调用。
如果types
是抽象类型,则返回invoke
将调用的方法。
另请参阅:parentmodule
,以及InteractiveUtils
中的@which
和@edit
。
Base.methods
— 函数methods(f, [types], [module])
返回f
的方法表。
如果指定了types
,则返回一个类型匹配的方法数组。如果指定了module
,则返回在该模块中定义的方法数组。也可以将模块列表指定为数组。
至少需要 Julia 1.4才能指定模块。
另请参阅:which
和@which
。
Base.@show
— 宏@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
— 常量ans
一个变量,引用最后一个计算的值,自动导入到交互式提示符中。
Base.MainInclude.err
— 常量err
一个变量,引用最后一个抛出的错误,自动导入到交互式提示符中。抛出的错误收集在一个异常堆栈中。
Base.active_project
— 函数active_project()
返回活动Project.toml
文件的路径。另请参阅Base.set_active_project
。
Base.set_active_project
— 函数set_active_project(projfile::Union{AbstractString,Nothing})
将活动Project.toml
文件设置为projfile
。另请参阅Base.active_project
。
此函数至少需要 Julia 1.8。
关键字
这是 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
被解析为中缀运算符;outer
在用于修改for
循环的迭代规范中变量的作用域时被解析为一个关键字;as
用作一个关键字,用于重命名由import
或using
引入作用域的标识符。但是,允许创建名为where
、in
、isa
、outer
和as
的变量。
module
— 关键字module
module
声明一个Module
,它是一个独立的全局变量工作区。在一个模块内,您可以控制来自其他模块的哪些名称是可见的(通过导入),并指定哪些名称旨在公开(通过导出)。模块允许您创建顶级定义,而无需担心在您的代码与其他人的代码一起使用时发生名称冲突。有关详细信息,请参阅关于模块的手册部分。
示例
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
— 关键字import
— 关键字import
import Foo
将加载模块或包Foo
。来自导入的Foo
模块的名称可以使用点语法访问(例如,Foo.foo
访问名称foo
)。有关详细信息,请参阅关于模块的手册部分。
using
— 关键字using
using Foo
将加载模块或包Foo
,并使其export
ed名称可供直接使用。名称也可以使用点语法访问(例如,Foo.foo
访问名称foo
),无论它们是否被export
ed。有关详细信息,请参阅关于模块的手册部分。
as
— 关键字as
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
— 关键字baremodule
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
— 关键字function
使用function
关键字定义函数
function add(a, b)
return a + b
end
或简短形式表示法
add(a, b) = a + b
return
关键字的使用与其他语言完全相同,但通常是可选的。没有显式return
语句的函数将返回函数体中的最后一个表达式。
macro
— 关键字macro
macro
定义了一种将生成的代码插入程序的方法。宏将一系列参数表达式映射到返回的表达式,生成的表达式直接替换到调用宏的位置的程序中。宏是一种在不调用eval
的情况下运行生成代码的方法,因为生成代码实际上只是成为周围程序的一部分。宏参数可以包括表达式、字面量值和符号。可以为可变数量的参数(varargs)定义宏,但不能接受关键字参数。每个宏还隐式地传递参数__source__
,其中包含宏调用的行号和文件名,以及__module__
,它是宏扩展所在的模块。
有关如何编写宏的更多信息,请参阅有关元编程的手册部分。
示例
julia> macro sayhello(name)
return :( println("Hello, ", $name, "!") )
end
@sayhello (macro with 1 method)
julia> @sayhello "Charlie"
Hello, Charlie!
julia> macro saylots(x...)
return :( println("Say: ", $(x...)) )
end
@saylots (macro with 1 method)
julia> @saylots "hey " "there " "friend"
Say: hey there friend
return
— 关键字return
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
在第一个示例中,return
在遇到偶数时立即退出test1
,因此test1([5,6,7])
返回12
。
您可能期望第二个示例以相同的方式工作,但实际上那里的return
只退出内部函数(在do
块中)并向map
返回一个值。test2([5,6,7])
然后返回[5,12,7]
。
当在顶级表达式中使用时(即在任何函数之外),return
会导致整个当前顶级表达式提前终止。
do
— 关键字do
创建一个匿名函数,并将其作为第一个参数传递给函数调用。例如
map(1:10) do x
2x
end
等价于map(x->2x, 1:10)
。
使用多个参数,如下所示
map(1:10, 11:20) do x, y
x + y
end
begin
— 关键字begin
begin...end
表示一段代码块。
begin
println("Hello, ")
println("World!")
end
通常begin
是不必要的,因为function
和let
之类的关键字会隐式地开始代码块。另请参阅;
。
begin
还可以在索引时使用,表示集合的第一个索引或数组维度的第一个索引。
示例
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
— 关键字end
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
— 关键字let
let
块创建新的硬作用域,并可选地引入新的局部绑定。
与 其他作用域结构 一样,let
块定义了新引入的局部变量可访问的代码块。此外,语法对逗号分隔的赋值和变量名具有特殊含义,这些变量名可以可选地出现在与 let
相同的行上。
let var1 = value1, var2, var3 = value3
code
end
在此行上引入的变量对 let
块是局部的,赋值按顺序执行,每个右侧在不考虑左侧名称的作用域中执行。因此,编写类似 let 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
— 关键字if/elseif/else
if
/elseif
/else
执行条件评估,这允许根据布尔表达式的值评估或不评估代码的部分。以下是 if
/elseif
/else
条件语法的解剖。
if x < y
println("x is less than y")
elseif x > y
println("x is greater than y")
else
println("x is equal to 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
— 关键字for
for
循环在迭代值序列时重复评估语句块。
迭代变量始终是一个新的变量,即使在封闭作用域中存在相同名称的变量。使用 outer
重用现有局部变量进行迭代。
示例
julia> for i in [1, 4, 0]
println(i)
end
1
4
0
while
— 关键字while
while
循环重复评估条件表达式,只要表达式保持为真,就继续评估 while 循环的主体。如果条件表达式在第一次到达 while 循环时为假,则主体永远不会被评估。
示例
julia> i = 1
1
julia> while i < 5
println(i)
global i += 1
end
1
2
3
4
break
— 关键字break
立即退出循环。
示例
julia> i = 0
0
julia> while true
global i += 1
i > 5 && break
println(i)
end
1
2
3
4
5
continue
— 关键字continue
跳过当前循环迭代的剩余部分。
示例
julia> for i = 1:6
iseven(i) && continue
println(i)
end
1
3
5
try
— 关键字try/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
— 关键字finally
在给定代码块退出时运行一些代码,无论它如何退出。例如,以下是我们如何确保打开的文件已关闭的方法。
f = open("file")
try
operate_on_file(f)
finally
close(f)
end
当控制离开 try
代码块(例如,由于 return
或只是正常完成)时,close(f)
将被执行。如果 try
代码块由于异常而退出,则异常将继续传播。catch
代码块也可以与 try
和 finally
组合使用。在这种情况下,finally
代码块将在 catch
处理错误后运行。
quote
— 关键字quote
quote
在块中创建多个表达式对象,而无需使用显式的 Expr
构造函数。例如。
ex = quote
x = 1
y = 2
x + y
end
与其他引用方式 :( ... )
不同,此形式在表达式树中引入了 QuoteNode
元素,在直接操作树时必须考虑这些元素。对于其他目的,:( ... )
和 quote .. end
代码块将被视为相同。
local
— 关键字local
local
引入新的局部变量。有关更多信息,请参阅 变量作用域手册部分。
示例
julia> function foo(n)
x = 0
for i = 1:n
local x # introduce a loop-local x
x = i
end
x
end
foo (generic function with 1 method)
julia> foo(10)
0
global
— 关键字global
global x
使当前作用域及其内部作用域中的 x
引用具有该名称的全局变量。有关更多信息,请参阅 变量作用域手册部分。
示例
julia> z = 3
3
julia> function foo()
global z = 6 # use the z variable defined outside foo
end
foo (generic function with 1 method)
julia> foo()
6
julia> z
6
outer
— 关键字for 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 # global variable
for outer i = 1:3
end
ERROR: syntax: no outer local variable declaration exists for "for outer"
[...]
const
— 关键字const
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
— 关键字struct
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
— 关键字Base.@kwdef
— 宏@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 # specified default
b::String # required keyword
end
Foo
julia> Foo(b="hi")
Foo(1, "hi")
julia> Foo()
ERROR: UndefKeywordError: keyword argument `b` not assigned
Stacktrace:
[...]
abstract type
— 关键字abstract type
abstract type
声明一个不能实例化的类型,并且仅用作类型图中的节点,从而描述相关具体类型的集合:这些具体类型是其后代。抽象类型形成了概念层次结构,使 Julia 的类型系统不仅仅是对象实现的集合。例如。
abstract type Number end
abstract type Real <: Number end
primitive type
— 关键字primitive type
primitive type
声明一个具体类型,其数据仅包含一系列位。整数和浮点数是基本类型的经典示例。一些示例内置基本类型声明
primitive type Char 32 end
primitive type Bool <: Integer 8 end
名称后的数字表示类型所需的存储位数。目前,仅支持 8 位的倍数大小。Bool
声明显示了如何可选地声明基本类型为某个超类型的子类型。
where
— 关键字where
where
关键字创建一个类型,该类型是其他类型的迭代联合,遍历某个变量的所有值。例如,Vector{T} where T<:Real
包含所有 Vector
,其中元素类型是某种 Real
数。
如果省略,绑定的变量默认值为 Any
Vector{T} where T # short for `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, ...}
将类型“应用”于参数值时变量被替换的顺序一致。
...
— 关键字...
“splat” 运算符 ...
代表一系列参数。...
可用于函数定义中,表示该函数接受任意数量的参数。...
也可用于将函数应用于一系列参数。
示例
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
;
— 关键字;
;
在 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) # without the ; or a trailing comma this would assign to 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; # set variables b and x using property destructuring
julia> b, x
(2, 1)
julia> ; # upon typing ;, the prompt changes (in place) to: shell>
shell> echo hello
hello
=
— 关键字=
=
是赋值运算符。
- 对于变量
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
?:
— 关键字a ? 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("y is larger")
y is larger
标准模块
Main
— 模块Main
Main
是顶层模块,Julia 从将 Main
设置为当前模块开始。在提示符处定义的变量将进入 Main
,而 varinfo
将列出 Main
中的变量。
julia> @__MODULE__
Main
Core
— 模块Core
Core
是包含所有被认为是语言“内置”的标识符的模块,即语言的核心部分,而不是库。每个模块都隐式指定 using Core
,因为如果没有这些定义,就无法执行任何操作。
Base
— 模块Base
Julia 的基本库。Base
是一个包含基本功能的模块(base/
的内容)。所有模块都隐式包含 using Base
,因为这在绝大多数情况下都是必需的。
Base 子模块
Base.Broadcast
— 模块Base.Broadcast
包含广播实现的模块。
Base.Docs
— 模块Base.Iterators
— 模块用于处理迭代器的方法。
Base.Libc
— 模块与 libc(C 标准库)的接口。
Base.Meta
— 模块元编程的便捷函数。
Base.StackTraces
— 模块用于收集和操作堆栈跟踪的工具。主要用于构建错误。
Base.Sys
— 模块提供用于检索有关硬件和操作系统的的信息的方法。
Base.Threads
— 模块多线程支持。
Base.GC
— 模块Base.GC
包含垃圾回收实用程序的模块。
所有对象
Core.:===
— 函数===(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
— 函数isa(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
— 函数isequal(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
— 函数isless(x, y)
根据固定的全序(与 isequal
一起定义),测试 x
是否小于 y
。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
)时才需要实现此函数。具有偏序的类型应实现 <
。有关如何定义可用于排序和相关函数的替代排序方法的详细信息,请参阅 替代排序 的文档。
示例
julia> isless(1, 3)
true
julia> isless("Red", "Blue")
false
Base.isunordered
— 函数isunordered(x)
如果 x
是根据 <
不可排序的值(如 NaN
或 missing
),则返回 true
。
使用此谓词评估为 true
的值可以使用其他排序(如 isless
)进行排序。
此函数需要 Julia 1.7 或更高版本。
Base.ifelse
— 函数ifelse(condition::Bool, x, y)
如果 condition
为 true
,则返回 x
,否则返回 y
。这与 ?
或 if
不同,因为它是一个普通的函数,所以所有参数都会先被求值。在某些情况下,使用 ifelse
而不是 if
语句可以消除生成的代码中的分支,并在紧凑循环中提供更高的性能。
示例
julia> ifelse(1 > 2, 1, 2)
2
Core.typeassert
— 函数typeassert(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
— 函数typeof(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
— 函数tuple(xs...)
构造一个包含给定对象的元组。
另请参见 Tuple
、ntuple
、NamedTuple
。
示例
julia> tuple(1, 'b', pi)
(1, 'b', π)
julia> ans === (1, 'b', π)
true
julia> Tuple(Real[1, 2, pi]) # takes a collection
(1, 2, π)
Base.ntuple
— 函数ntuple(f::Function, 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
— 函数objectid(x) -> UInt
根据对象标识获取 x
的哈希值。
如果 x === y
,则 objectid(x) == objectid(y)
,并且通常当 x !== y
时,objectid(x) != objectid(y)
。
Base.hash
— 函数hash(x[, h::UInt]) -> UInt
计算一个整数哈希码,使得 isequal(x,y)
意味着 hash(x)==hash(y)
。可选的第二个参数 h
是另一个要与结果混合的哈希码。
新的类型应该实现 2 参数形式,通常通过递归地调用 2 参数 hash
方法来实现,以便将内容的哈希值彼此混合(以及与 h
混合)。通常,任何实现 hash
的类型也应该实现自己的 ==
(因此 isequal
)来保证上述属性。支持减法(运算符 -
)的类型也应该实现 widen
,这是对异构数组中的值进行哈希处理所必需的。
当一个新的 Julia 进程启动时,哈希值可能会发生变化。
julia> a = hash(10)
0x95ea2955abd45275
julia> hash(10, a) # only use the output of another hash function as the second argument
0xd42bad54a8575b16
Base.finalizer
— 函数finalizer(f, x)
注册一个函数 f(x)
,当没有程序可访问的引用指向 x
时,该函数会被调用,并返回 x
。x
的类型必须是 mutable struct
,否则函数将抛出异常。
f
不能导致任务切换,这排除了大多数 I/O 操作,例如 println
。使用 @async
宏(将上下文切换延迟到最终器之外)或 ccall
直接在 C 中调用 IO 函数可能有助于调试目的。
请注意,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
可以在对象构造时注册最终器。在以下示例中,请注意我们隐式地依赖于最终器返回新创建的 mutable struct
x
。
示例
mutable struct MyMutableStruct
bar
function MyMutableStruct(bar)
x = new(bar)
f(t) = @async println("Finalizing $t.")
finalizer(f, x)
end
end
Base.finalize
— 函数finalize(x)
立即运行为对象 x
注册的最终器。
Base.copy
— 函数Base.deepcopy
— 函数deepcopy(x)
创建 x
的深拷贝:所有内容都会被递归地复制,从而产生一个完全独立的对象。例如,深拷贝数组会生成一个新的数组,其元素是原始元素的深拷贝。对对象调用 deepcopy
通常应该与序列化它然后反序列化它具有相同的效果。
虽然通常没有必要,但用户定义的类型可以通过定义函数 deepcopy_internal(x::T, dict::IdDict)
(不应该被其他方式使用)的专门版本来覆盖默认的 deepcopy
行为,其中 T
是要为其专门化的类型,而 dict
跟踪到目前为止在递归中复制的对象。在定义中,deepcopy_internal
应该被用作 deepcopy
的替代品,并且 dict
变量应该在返回之前根据需要进行更新。
Base.getproperty
— 函数getproperty(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
的行为不寻常,可能会令人困惑。另外请注意,使用方法通常更可取。有关更多信息,另请参见此风格指南文档:优先使用导出方法而不是直接字段访问。
另请参见 getfield
、propertynames
和 setproperty!
。
Base.setproperty!
— 函数setproperty!(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!
— 函数replaceproperty!(x, f::Symbol, expected, desired, success_order::Symbol=:not_atomic, fail_order::Symbol=success_order)
根据 egal,对 x.f
从 expected
到 desired
执行比较和交换操作。语法 @atomic_replace! x.f expected => desired
可以用作函数调用形式的替代品。
另请参见 replacefield!
和 setproperty!
。
Base.swapproperty!
— 函数swapproperty!(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!
— 函数modifyproperty!(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.propertynames
— 函数propertynames(x, private=false)
获取一个元组或一个包含对象 x
的属性(x.property
)的向量。这通常与 fieldnames(typeof(x))
相同,但重载 getproperty
的类型通常也应该重载 propertynames
以获取该类型实例的属性。
propertynames(x)
可能只返回作为 x
的文档化接口一部分的“公共”属性名。如果您希望它还返回用于内部使用的“私有”属性名,则将 true
传递给可选的第二个参数。x.
上的 REPL 选项卡补全只显示 private=false
的属性。
另请参见:hasproperty
、hasfield
。
Base.hasproperty
— 函数hasproperty(x, s::Symbol)
返回一个布尔值,指示对象 x
是否将 s
作为其自身的属性之一。
此函数至少需要 Julia 1.2。
另请参见:propertynames
、hasfield
。
Core.getfield
— 函数getfield(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!
— 函数setfield!(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!
— 函数modifyfield!(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
如果硬件支持(例如,原子增量),则这可能会被优化为适当的硬件指令,否则它将使用循环。
Core.replacefield!
— 函数replacefield!(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)
如果硬件支持,则这可能会被优化为适当的硬件指令,否则它将使用循环。
Core.swapfield!
— 函数swapfield!(value, name::Symbol, x, [order::Symbol])
swapfield!(value, i::Int, x, [order::Symbol])
这些以原子方式执行同时获取和设置字段的操作
y = getfield(value, name)
setfield!(value, name, x)
return y
Core.isdefined
— 函数isdefined(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
Core.getglobal
— 函数getglobal(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!
— 函数setglobal!(module::Module, name::Symbol, x, [order::Symbol=:monotonic])
将模块module
中绑定name
的值设置为x
。不执行类型转换,因此如果已为绑定声明类型,则x
必须是适当的类型,否则会抛出错误。
此外,可以为此操作指定原子顺序,否则默认为单调。
用户通常会通过 setproperty!
函数或相应的语法(即 module.name = x
)访问此功能,因此这仅适用于非常特殊的用例。
此函数需要 Julia 1.9 或更高版本。
另请参见 setproperty!
和 getglobal
示例
julia> module M end;
julia> M.a # same as `getglobal(M, :a)`
ERROR: UndefVarError: `a` not defined
julia> setglobal!(M, :a, 1)
1
julia> M.a
1
Base.@isdefined
— 宏@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
— 函数convert(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
类型,则它将返回T
可以表示的与x
最接近的值。
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
— 函数promote(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
— 函数oftype(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
— 函数widen(x)
如果x
是类型,则返回一个“更大”的类型,定义为对于类型x
可以保存的任何值的组合,算术运算+
和-
都保证不会溢出或丢失精度。
对于小于 128 位的固定大小整数类型,widen
将返回一个位数加倍的类型。
如果x
是值,则将其转换为 widen(typeof(x))
。
示例
julia> widen(Int32)
Int64
julia> widen(1.5f0)
1.5
Base.identity
— 函数identity(x)
恒等函数。返回其参数。
另请参见: one
,oneunit
和 LinearAlgebra
的 I
。
示例
julia> identity("Well, what did you expect?")
"Well, what did you expect?"
Core.WeakRef
— 类型WeakRef(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 # a reference is maintained via `x`
WeakRef("a string")
julia> x = nothing # clear reference
julia> GC.gc()
julia> w
WeakRef(nothing)
类型的属性
类型关系
Base.supertype
— 函数supertype(T::DataType)
返回 DataType T
的超类型。
示例
julia> supertype(Int32)
Signed
Core.Type
— 类型Core.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
— 类型DataType <: Type{T}
DataType
代表具有名称、显式声明的超类型以及可选参数的显式声明类型。系统中的每个具体值都是某个 DataType
的实例。
示例
julia> typeof(Real)
DataType
julia> typeof(Int)
DataType
julia> struct Point
x::Int
y
end
julia> typeof(Point)
DataType
Core.:<:
— 函数<:(T1, T2)
子类型运算符:当且仅当类型 T1
的所有值也是类型 T2
的值时,返回 true
。
示例
julia> Float64 <: AbstractFloat
true
julia> Vector{Int} <: AbstractArray
true
julia> Matrix{Float64} <: Matrix{AbstractFloat}
false
Base.:>:
— 函数>:(T1, T2)
超类型运算符,等效于 T2 <: T1
。
Base.typejoin
— 函数typejoin(T, S, ...)
返回类型 T
和 S
的最近共同祖先,即它们共同继承的最窄类型。对其他可变参数进行递归。
示例
julia> typejoin(Int, Float64)
Real
julia> typejoin(Int, Float64, ComplexF32)
Number
Base.typeintersect
— 函数typeintersect(T::Type, S::Type)
计算包含 T
和 S
交集的类型。通常,这将是最小的此类类型或接近它的类型。
Base.promote_type
— 函数promote_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
— 函数promote_rule(type1, type2)
指定当给定类型为 type1
和 type2
的值时,promote
应该使用什么类型。此函数不应直接调用,但应为新类型添加定义,以适当地使用它。
Base.promote_typejoin
— 函数promote_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
— 函数isdispatchtuple(T)
确定类型 T
是否是元组“叶类型”,这意味着它可以作为类型签名出现在调度中,并且没有可以出现在调用中的子类型(或超类型)。
声明结构
Base.ismutable
— 函数ismutable(v) -> Bool
当且仅当值 v
是可变的时,返回 true
。有关不可变性的讨论,请参阅 可变复合类型。请注意,此函数作用于值,因此如果您给它一个 DataType
,它将告诉您该类型的某个值是可变的。
由于技术原因,ismutable
会针对某些特殊类型(例如 String
和 Symbol
)的值返回 true
,即使它们不能以允许的方式进行变异。
另请参见 isbits
,isstructtype
。
示例
julia> ismutable(1)
false
julia> ismutable([1,2])
true
此函数至少需要 Julia 1.5。
Base.isimmutable
— 函数isimmutable(v) -> Bool
考虑使用 !ismutable(v)
而不是,因为 isimmutable(v)
将在将来的版本中被 !ismutable(v)
替换。(从 Julia 1.5 开始)
当且仅当值 v
不可变时,返回 true
。有关不可变性的讨论,请参阅 可变复合类型。请注意,此函数作用于值,因此如果您给它一个类型,它将告诉您 DataType
的某个值是可变的。
示例
julia> isimmutable(1)
true
julia> isimmutable([1,2])
false
Base.ismutabletype
— 函数ismutabletype(T) -> Bool
确定类型 T
是否被声明为可变类型(即使用 mutable struct
关键字)。
此函数至少需要 Julia 1.7。
Base.isabstracttype
— 函数isabstracttype(T)
确定类型T
是否声明为抽象类型(即使用abstract type
语法)。
示例
julia> isabstracttype(AbstractArray)
true
julia> isabstracttype(Vector)
false
Base.isprimitivetype
— 函数isprimitivetype(T) -> Bool
确定类型T
是否声明为原始类型(即使用primitive type
语法)。
Base.issingletontype
— 函数Base.issingletontype(T)
确定类型T
是否只有一个可能的实例;例如,一个没有字段的结构体类型。
Base.isstructtype
— 函数isstructtype(T) -> Bool
确定类型T
是否声明为结构体类型(即使用struct
或mutable struct
关键字)。
Base.nameof
— 方法nameof(t::DataType) -> Symbol
将(可能被UnionAll
包裹的)DataType
的名称(不包含其父模块)获取为一个符号。
示例
julia> module Foo
struct S{T}
end
end
Foo
julia> nameof(Foo.S{T} where T)
:S
Base.fieldnames
— 函数fieldnames(x::DataType)
获取一个包含DataType
字段名称的元组。
另请参阅 propertynames
, hasfield
.
示例
julia> fieldnames(Rational)
(:num, :den)
julia> fieldnames(typeof(1+im))
(:re, :im)
Base.fieldname
— 函数fieldname(x::DataType, i::Integer)
获取DataType
中第i
个字段的名称。
示例
julia> fieldname(Rational, 1)
:num
julia> fieldname(Rational, 2)
:den
Core.fieldtype
— 函数fieldtype(T, name::Symbol | index::Int)
确定复合DataTypeT
中一个字段(通过名称或索引指定)的声明类型。
示例
julia> struct Foo
x::Int64
y::String
end
julia> fieldtype(Foo, :x)
Int64
julia> fieldtype(Foo, 2)
String
Base.fieldtypes
— 函数fieldtypes(T::Type)
复合DataTypeT
中所有字段的声明类型,以元组形式返回。
该函数需要至少 Julia 1.1 版本。
示例
julia> struct Foo
x::Int64
y::String
end
julia> fieldtypes(Foo)
(Int64, String)
Base.fieldcount
— 函数fieldcount(t::Type)
获取给定类型实例所具有的字段数量。如果类型过于抽象无法确定,则会抛出错误。
Base.hasfield
— 函数hasfield(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
— 函数nfields(x) -> Int
获取给定对象中的字段数量。
示例
julia> a = 1//2;
julia> nfields(a)
2
julia> b = 1
1
julia> nfields(b)
0
julia> ex = ErrorException("I've done a bad thing");
julia> nfields(ex)
1
在这些示例中,a
是一个Rational
,它有两个字段。b
是一个Int
,它是一个没有字段的原始位类型。ex
是一个ErrorException
,它有一个字段。
Base.isconst
— 函数isconst(m::Module, s::Symbol) -> Bool
确定全局变量是否在给定模块m
中声明为const
。
isconst(t::DataType, s::Union{Int,Symbol}) -> Bool
确定字段s
是否在给定类型t
中声明为const
。
Base.isfieldatomic
— 函数isfieldatomic(t::DataType, s::Union{Int,Symbol}) -> Bool
确定字段s
是否在给定类型t
中声明为@atomic
。
内存布局
Base.sizeof
— 方法sizeof(T::DataType)
sizeof(obj)
给定DataType
T
的规范二进制表示形式的大小(以字节为单位),如果有的话。或者,如果obj
不是DataType
,则为对象obj
的大小(以字节为单位)。
另请参阅 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) # not the sum of `sizeof` of fields due to padding
16
julia> sizeof(Int64) + sizeof(Bool) # different from above
9
如果DataType
T
没有特定大小,则会抛出错误。
julia> sizeof(AbstractArray)
ERROR: Abstract type AbstractArray does not have a definite size.
Stacktrace:
[...]
Base.isconcretetype
— 函数isconcretetype(T)
确定类型T
是否为具体类型,这意味着它可以有直接实例(值x
,使得typeof(x) === T
)。
另请参阅: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
— 函数isbits(x)
如果x
是isbitstype
类型的实例,则返回true
。
Base.isbitstype
— 函数isbitstype(T)
如果类型T
是“纯数据”类型,则返回true
,这意味着它是不可变的,并且不包含对其他值的引用,只包含primitive
类型和其他isbitstype
类型。典型的例子是数值类型,例如UInt8
, Float64
, 和 Complex{Float64}
。这类别类型很重要,因为它们可以作为类型参数,可能不会跟踪isdefined
/ isassigned
状态,并且具有与C兼容的已定义布局。
另请参阅 isbits
, isprimitivetype
, ismutable
.
示例
julia> isbitstype(Complex{Float64})
true
julia> isbitstype(Complex)
false
Base.fieldoffset
— 函数fieldoffset(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
— 函数Base.datatype_alignment(dt::DataType) -> Int
此类型实例的内存分配最小对齐方式。可以在任何isconcretetype
上调用。
Base.datatype_haspadding
— 函数Base.datatype_haspadding(dt::DataType) -> Bool
返回此类型实例的字段是否在内存中打包,没有中间填充字节。可以在任何isconcretetype
上调用。
Base.datatype_pointerfree
— 函数Base.datatype_pointerfree(dt::DataType) -> Bool
返回此类型实例是否可以包含对gc管理内存的引用。可以在任何isconcretetype
上调用。
特殊值
Base.typemin
— 函数typemin(T)
给定(实数)数值DataTypeT
可表示的最低值。
示例
julia> typemin(Int8)
-128
julia> typemin(UInt32)
0x00000000
julia> typemin(Float16)
-Inf16
julia> typemin(Float32)
-Inf32
julia> nextfloat(-Inf32) # smallest finite Float32 floating point number
-3.4028235f38
Base.typemax
— 函数typemax(T)
给定(实数)数值DataType
可表示的最高值。
示例
julia> typemax(Int8)
127
julia> typemax(UInt32)
0xffffffff
julia> typemax(Float64)
Inf
julia> typemax(Float32)
Inf32
julia> floatmax(Float32) # largest finite Float32 floating point number
3.4028235f38
Base.floatmin
— 函数floatmin(T = Float64)
返回浮点类型T
可表示的最小正规数。
示例
julia> floatmin(Float16)
Float16(6.104e-5)
julia> floatmin(Float32)
1.1754944f-38
julia> floatmin()
2.2250738585072014e-308
Base.floatmax
— 函数floatmax(T = Float64)
返回浮点类型T
可表示的最大有限数。
示例
julia> floatmax(Float16)
Float16(6.55e4)
julia> floatmax(Float32)
3.4028235f38
julia> floatmax()
1.7976931348623157e308
julia> typemax(Float64)
Inf
Base.maxintfloat
— 函数maxintfloat(T=Float64)
给定浮点类型T
(默认为Float64
)中可精确表示的最大连续整数值浮点数。
也就是说,maxintfloat
返回最小的正整数值浮点数n
,使得n+1
不能在类型T
中精确表示。
当需要Integer
类型的值时,使用Integer(maxintfloat(T))
。
maxintfloat(T, S)
给定浮点类型T
中可表示的最大连续整数,并且也不超过整数类型S
可表示的最大整数。等效地,它是maxintfloat(T)
和typemax(S)
的最小值。
Base.eps
— 方法eps(::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
— 方法eps(x::AbstractFloat)
返回x
的最后一个位置的单位(ulp)。这是x
处连续可表示的浮点值之间的距离。在大多数情况下,如果x
两侧的距离不同,则采用较大者,即
eps(x) == max(x-prevfloat(x), nextfloat(x)-x)
此规则的例外情况是最小和最大有限值(例如,nextfloat(-Inf)
和prevfloat(Inf)
对于Float64
),它们会四舍五入到较小的值。
此行为的原因是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) # largest finite Float64
1.7976931348623157e308
julia> x + eps(x)/2 # rounds up
Inf
julia> x + prevfloat(eps(x)/2) # rounds down
1.7976931348623157e308
Base.instances
— 函数instances(T::Type)
返回给定类型的所有实例的集合,如果适用的话。主要用于枚举类型(参见@enum
)。
示例
julia> @enum Color red blue green
julia> instances(Color)
(red, blue, green)
特殊类型
Core.Any
— 类型Any::DataType
Any
是所有类型的并集。它具有定义属性isa(x, Any) == true
,适用于任何x
。因此,Any
描述了所有可能值的整个宇宙。例如,Integer
是Any
的一个子集,它包含Int
、Int8
和其他整数类型。
Core.Union
— 类型Union{Types...}
类型联合是一个抽象类型,它包含其所有参数类型的任何实例。空联合Union{}
是Julia的底部类型。
示例
julia> IntOrString = Union{Int,AbstractString}
Union{Int64, AbstractString}
julia> 1 isa IntOrString
true
julia> "Hello!" isa IntOrString
true
julia> 1.0 isa IntOrString
false
Union{}
— 关键字Union{}
Union{}
是一个空类型 Union
,它没有任何值。也就是说,对于任何 x
,它具有定义属性 isa(x, Union{}) == false
。Base.Bottom
被定义为它的别名,Union{}
的类型为 Core.TypeofBottom
。
示例
julia> isa(nothing, Union{})
false
Core.UnionAll
— 类型UnionAll
对类型参数所有值的类型联合。UnionAll
用于描述参数类型,其中一些参数的值未知。
示例
julia> typeof(Vector)
UnionAll
julia> typeof(Vector{Int})
DataType
Core.Tuple
— 类型Tuple{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}
被认为是抽象类型,只有当元组类型的参数是具体类型时,元组类型才是具体的。元组没有字段名称;字段只能通过索引访问。元组类型可以具有任意数量的参数。
参见关于 元组类型 的手册部分。
Core.NTuple
— 类型NTuple{N, T}
表示长度为 N
的元组类型的一种简洁方式,其中所有元素都具有类型 T
。
示例
julia> isa((1, 2, 3, 4, 5, 6), NTuple{6, Int})
true
另见 ntuple
。
Core.NamedTuple
— 类型NamedTuple
顾名思义,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) # the final b overwrites the value from nt1
(a = 1, b = 20, c = 3, d = 4)
julia> (; zip(keys, values)...) # zip yields tuples such as (: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 开始可用。
从 Julia 1.7 开始,可以使用带有多个 Symbol
的 getindex
方法。
Base.@NamedTuple
— 宏@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
— 宏@Kwargs{key1::Type1, key2::Type2, ...}
此宏提供了一种方便的方法,可以使用与 @NamedTuple
相同的语法构造关键字参数的类型表示。例如,当我们有一个类似于 func([positional arguments]; kw1=1.0, kw2="2")
的函数调用时,我们可以使用此宏来构造关键字参数的内部类型表示,如 @Kwargs{kw1::Float64, kw2::String}
。宏语法专门设计用于简化在堆栈跟踪视图中打印关键字方法的签名类型。
julia> @Kwargs{init::Int} # the internal representation of keyword arguments
Base.Pairs{Symbol, Int64, Tuple{Symbol}, @NamedTuple{init::Int64}}
julia> sum("julia"; init=1)
ERROR: MethodError: no method matching +(::Char, ::Char)
Closest candidates are:
+(::Any, ::Any, ::Any, ::Any...)
@ Base operators.jl:585
+(::Integer, ::AbstractChar)
@ Base char.jl:247
+(::T, ::Integer) where T<:AbstractChar
@ Base char.jl:237
Stacktrace:
[1] add_sum(x::Char, y::Char)
@ Base ./reduce.jl:24
[2] BottomRF
@ Base ./reduce.jl:86 [inlined]
[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 [inlined]
[5] mapfoldl_impl(f::typeof(identity), op::typeof(Base.add_sum), nt::Int64, itr::String)
@ Base ./reduce.jl:44 [inlined]
[6] mapfoldl(f::typeof(identity), op::typeof(Base.add_sum), itr::String; init::Int64)
@ Base ./reduce.jl:175 [inlined]
[7] mapreduce(f::typeof(identity), op::typeof(Base.add_sum), itr::String; kw::@Kwargs{init::Int64})
@ Base ./reduce.jl:307 [inlined]
[8] sum(f::typeof(identity), a::String; kw::@Kwargs{init::Int64})
@ Base ./reduce.jl:535 [inlined]
[9] sum(a::String; kw::@Kwargs{init::Int64})
@ Base ./reduce.jl:564 [inlined]
[10] top-level scope
@ REPL[12]:1
此宏从 Julia 1.10 开始可用。
Base.Val
— 类型Val(c)
返回 Val{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
— 常量Vararg{T,N}
元组类型 Tuple
的最后一个参数可以是特殊值 Vararg
,它表示任意数量的尾随元素。Vararg{T,N}
对应于恰好 N
个类型为 T
的元素。最后 Vararg{T}
对应于零个或多个类型为 T
的元素。Vararg
元组类型用于表示可变参数方法接受的参数(参见手册中关于 可变参数函数 的部分。)
另见 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
— 类型Base.isnothing
— 函数isnothing(x)
如果 x === nothing
,则返回 true
,否则返回 false
。
该函数需要至少 Julia 1.1 版本。
Base.notnothing
— 函数notnothing(x)
如果 x === nothing
,则抛出错误,否则返回 x
。
Base.Some
— 类型Some{T}
在 Union{Some{T}, Nothing}
中使用的包装类型,用于区分没有值(nothing
)和存在 nothing
值(即 Some(nothing)
)。
使用 something
访问 Some
对象包装的值。
Base.something
— 函数something(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
— 宏@something(x...)
something
的短路版本。
示例
julia> f(x) = (println("f($x)"); nothing);
julia> a = 1;
julia> a = @something a f(2) f(3) error("Unable to find default for `a`")
1
julia> b = nothing;
julia> b = @something b f(2) f(3) error("Unable to find default for `b`")
f(2)
f(3)
ERROR: Unable to find default for `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
— 类型Enum{T<:Integer}
使用 @enum
定义的所有枚举类型的抽象超类型。
Base.Enums.@enum
— 宏@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
— 类型Expr(head::Symbol, args...)
表示解析的 julia 代码(AST)中的复合表达式的类型。每个表达式都包含一个 head
Symbol
,用于标识它是哪种表达式(例如,调用、for 循环、条件语句等),以及子表达式(例如,调用的参数)。子表达式存储在名为 args
的 Vector{Any}
字段中。
参见关于 元编程 的手册章节和开发者文档 Julia AST。
示例
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
— 类型Symbol
用于表示解析的 julia 代码(AST)中的标识符的类型的对象。也常用于标识实体的名称或标签(例如,作为字典键)。Symbol
可以使用 :
引用运算符输入
julia> :name
:name
julia> typeof(:name)
Symbol
julia> x = 42
42
julia> eval(:x)
42
Symbol
也可以通过调用构造函数 Symbol(x...)
从字符串或其他值构建。
Symbol
是不可变的,它们的实现对所有具有相同名称的 Symbol
使用同一个对象。
与字符串不同,Symbol
是“原子”或“标量”实体,不支持对字符进行迭代。
Core.Symbol
— 方法Symbol(x...) -> Symbol
通过将参数的字符串表示形式连接在一起,创建一个 Symbol
。
示例
julia> Symbol("my", "name")
:myname
julia> Symbol("day", 4)
:day4
Core.Module
— 类型Module
Module
是一个独立的全局变量工作区。参见 module
和关于 模块 的手册部分以了解更多信息。
Module(name::Symbol=:anonymous, std_imports=true, default_names=true)
返回具有指定名称的模块。baremodule
对应于 Module(:ModuleName, false)
可以使用 Module(:ModuleName, false, false)
创建一个不包含任何名称的空模块。此模块不会导入 Base
或 Core
,也不包含对自身的引用。
泛型函数
Core.Function
— 类型Function
所有函数的抽象类型。
示例
julia> isa(+, Function)
true
julia> typeof(sin)
typeof(sin) (singleton type of function sin, subtype of Function)
julia> ans <: Function
true
Base.hasmethod
— 函数hasmethod(f, t::Type{<:Tuple}[, kwnames]; world=get_world_counter()) -> Bool
确定给定的泛型函数是否具有与给定Tuple
的函数参数类型匹配的方法,函数参数类型上界由world
给出。
如果提供关键字参数名称的元组kwnames
,则还会检查f
匹配t
的方法是否具有给定的关键字参数名称。如果匹配的方法接受可变数量的关键字参数,例如使用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 accepts arbitrary kwargs
true
Core.applicable
— 函数applicable(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
— 函数Base.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
— 函数invoke(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
— 宏@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
— 函数invokelatest(f, args...; kwargs...)
调用f(args...; kwargs...)
,但保证执行f
的最新方法。这在特殊情况下很有用,例如长时间运行的事件循环或可能调用过时版本的函数f
的回调函数。(缺点是invokelatest
比直接调用f
稍慢,并且结果的类型无法由编译器推断。)
在 Julia 1.9 之前,此函数未导出,而是以Base.invokelatest
的形式调用。
Base.@invokelatest
— 宏@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
— 关键字new, or new{A,B,...}
内部构造函数可用的特殊函数,用于创建新类型的对象。new{A,B,...} 形式显式指定参数化类型的参数值。有关更多信息,请参见手册中有关内部构造函数方法的部分。
Base.:|>
— 函数|>(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.:∘
— 函数f ∘ 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
Base.ComposedFunction
— 类型ComposedFunction{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
— 函数splat(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
— 类型Base.Fix2
— 类型Fix2(f, x)
一个类型,表示两个参数函数f
的部分应用版本,第二个参数固定为值“x”。换句话说,Fix2(f, x)
的行为类似于 y->f(y, x)
。
语法
Core.eval
— 函数Core.eval(m::Module, expr)
在给定模块中评估表达式并返回结果。
Base.MainInclude.eval
— 函数eval(expr)
在包含模块的全局范围内评估表达式。每个Module
(除了使用baremodule
定义的模块之外)都有其自己的 1 个参数的eval
定义,它在该模块中评估表达式。
Base.@eval
— 宏@eval [mod,] ex
使用eval
将值插入其中的表达式进行评估。如果提供两个参数,第一个参数是用于评估的模块。
Base.evalfile
— 函数evalfile(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
— 函数Base.@inbounds
— 宏@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)
并不安全地在范围内,因为对于子类型为AbstractArray
的所有用户定义类型,A
的第一个索引可能不为1
。
Base.@boundscheck
— 宏@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
— 宏@propagate_inbounds
告诉编译器内联函数,同时保留调用者的边界检查上下文。
Base.@inline
— 宏@inline
给编译器一个提示,表明此函数值得内联。
小型函数通常不需要 @inline
注解,因为编译器会自动进行内联。通过在较大函数上使用 @inline
,可以给编译器一个额外的提示来内联它。
@inline
可以应用在函数定义之前或函数体内部。
# annotate long-form definition
@inline function longdef(x)
...
end
# annotate short-form definition
@inline shortdef(x) = ...
# annotate anonymous function that a `do` block creates
f() do
@inline
...
end
在函数体内部使用需要至少 Julia 1.8 版本。
@inline block
给编译器一个提示,表明 block
中的调用值得内联。
# The compiler will try to inline `f`
@inline f(...)
# The compiler will try to inline `f`, `g` and `+`
@inline f(...) + g(...)
调用点注释始终优先于应用于被调用函数定义的注释。
@noinline function explicit_noinline(args...)
# body
end
let
@inline explicit_noinline(args...) # will be inlined
end
当存在嵌套的调用点注释时,最内层的注释具有优先级。
@noinline let a0, b0 = ...
a = @inline f(a0) # the compiler will try to inline this call
b = f(b0) # the compiler will NOT try to inline this call
return a, b
end
虽然调用点注释将尝试强制内联,无论成本模型如何,但它仍然有可能无法成功内联。特别是,递归调用即使被注释为 @inline
,也不能被内联。
调用点注释需要至少 Julia 1.8 版本。
Base.@noinline
— 宏@noinline
给编译器一个提示,表明它不应该内联函数。
小型函数通常会自动内联。通过在小型函数上使用 @noinline
,可以阻止自动内联。
@noinline
可以应用在函数定义之前或函数体内部。
# annotate long-form definition
@noinline function longdef(x)
...
end
# annotate short-form definition
@noinline shortdef(x) = ...
# annotate anonymous function that a `do` block creates
f() do
@noinline
...
end
在函数体内部使用需要至少 Julia 1.8 版本。
@noinline block
给编译器一个提示,表明它不应该内联 block
中的调用。
# The compiler will try to not inline `f`
@noinline f(...)
# The compiler will try to not inline `f`, `g` and `+`
@noinline f(...) + g(...)
调用点注释始终优先于应用于被调用函数定义的注释。
@inline function explicit_inline(args...)
# body
end
let
@noinline explicit_inline(args...) # will not be inlined
end
当存在嵌套的调用点注释时,最内层的注释具有优先级。
@inline let a0, b0 = ...
a = @noinline f(a0) # the compiler will NOT try to inline this call
b = f(b0) # the compiler will try to inline this call
return a, b
end
调用点注释需要至少 Julia 1.8 版本。
如果函数是微不足道的(例如返回常量),它可能仍然会被内联。
Base.@nospecialize
— 宏@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
影响代码生成,但不影响推断:它限制了生成的本机代码的多样性,但它不会对类型推断(除了标准推断之外)施加任何限制。与 @nospecialize
一起使用 Base.@nospecializeinfer
来额外抑制推断。
示例
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
— 宏@specialize
将参数的专门化提示重置回默认值。有关详细信息,请参阅 @nospecialize
。
Base.@nospecializeinfer
— 宏Base.@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.@constprop
— 宏@constprop setting [ex]
控制为带注释函数应用的过程间常量传播模式。
支持两个 setting
值
@constprop :aggressive [ex]
: 积极地应用常量传播。对于返回类型取决于参数值的函数,这可以提高推断结果,但会增加编译时间。@constprop :none [ex]
: 禁用常量传播。这可以减少 Julia 可能会认为值得进行常量传播的函数的编译时间。常见情况是具有Bool
或Symbol
值参数或关键字参数的函数。
@constprop
可以应用在函数定义之前或函数体内部。
# annotate long-form definition
@constprop :aggressive function longdef(x)
...
end
# annotate short-form definition
@constprop :aggressive shortdef(x) = ...
# annotate anonymous function that a `do` block creates
f() do
@constprop :aggressive
...
end
在函数体内部使用需要至少 Julia 1.10 版本。
Base.gensym
— 函数gensym([tag])
生成一个符号,它不会与其他变量名称(在同一个模块中)冲突。
Base.@gensym
— 宏@gensym
为变量生成一个 gensym 符号。例如,@gensym x y
将转换为 x = gensym("x"); y = gensym("y")
。
var"name"
— 关键字var
语法 var"#example#"
指的是名为 Symbol("#example#")
的变量,即使 #example#
不是有效的 Julia 标识符名称。
这对于与具有不同标识符构造规则的编程语言的互操作性很有用。例如,要引用 R
变量 draw.segments
,您可以在您的 Julia 代码中使用 var"draw.segments"
。
它还用于 show
经过宏卫生处理或包含无法正常解析的变量名称的 Julia 源代码。
请注意,此语法需要解析器支持,因此它由解析器直接扩展,而不是作为普通字符串宏 @var_str
实现。
此语法需要至少 Julia 1.3 版本。
Base.@goto
— 宏@goto name
@goto name
无条件跳转到 @label name
位置的语句。
@label
和 @goto
无法创建到不同顶层语句的跳转。尝试会导致错误。要继续使用 @goto
,请将 @label
和 @goto
包含在一个块中。
Base.@label
— 宏@label name
使用符号标签 name
来标记语句。标签标记了使用 @goto name
的无条件跳转的终点。
Base.SimdLoop.@simd
— 宏@simd
注释 for
循环,以允许编译器采取额外措施,允许循环重新排序。
此功能处于实验阶段,可能会在 Julia 的未来版本中发生变化或消失。不正确使用 @simd
宏可能会导致意外结果。
@simd for
循环中迭代的对象应为一维范围。通过使用 @simd
,您断言循环具有以下几个属性
- 以任意或重叠的顺序执行迭代是安全的,特别要考虑归约变量。
- 对归约变量的浮点运算可以重新排序或合并,这可能导致与不使用
@simd
时不同的结果。
在许多情况下,Julia 能够在不使用 @simd
的情况下自动矢量化内部 for 循环。使用 @simd
可以给编译器一些额外的空间,使其在更多情况下成为可能。无论哪种情况,您的内部循环都应具有以下属性,以允许矢量化
- 循环必须是最内层循环。
- 循环体必须是直线代码。因此,目前需要
@inbounds
用于所有数组访问。如果安全地无条件地评估所有操作数,编译器有时可以将短&&
、||
和?:
表达式转换为直线代码。如果安全地这样做,请考虑在循环中使用ifelse
函数代替?:
。 - 访问必须具有步长模式,不能是“收集”(随机索引读取)或“散布”(随机索引写入)。
- 步长应该是单位步长。
@simd
默认情况下不断言循环完全没有循环携带的内存依赖关系,这是一个在通用代码中很容易被违反的假设。如果您正在编写非通用代码,您可以使用 @simd ivdep for ... end
来断言
- 不存在循环携带的内存依赖关系。
- 没有迭代等待先前迭代以取得进展。
Base.@polly
— 宏@polly
告诉编译器对函数应用多面体优化器 Polly。
Base.@generated
— 宏@generated f
@generated
用于注释将被生成的函数。在生成的函数体中,只能读取参数的类型(而不是值)。函数返回一个引用的表达式,该表达式在函数被调用时进行求值。@generated
宏不应在修改全局作用域或依赖于可变元素的函数上使用。
有关更多详细信息,请参阅 元编程。
示例
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
— 宏@assume_effects setting... [ex]
覆盖给定方法或外部调用的编译器效果建模。@assume_effects
可以应用在函数定义之前或函数体内部。它也可以应用在 @ccall
表达式之前。
使用 Base.@assume_effects
需要 Julia 1.8 版本。
示例
julia> Base.@assume_effects :terminates_locally function pow(x)
# this :terminates_locally allows `pow` to be constant-folded
res = 1
1 < x < 20 || error("bad pow")
while x > 1
res *= x
x -= 1
end
return res
end
pow (generic function with 1 method)
julia> code_typed() do
pow(12)
end
1-element Vector{Any}:
CodeInfo(
1 ─ return 479001600
) => Int64
julia> code_typed() do
map((2,3,4)) do x
# this :terminates_locally allows this anonymous function to be constant-folded
Base.@assume_effects :terminates_locally
res = 1
1 < x < 20 || error("bad pow")
while x > 1
res *= x
x -= 1
end
return res
end
end
1-element Vector{Any}:
CodeInfo(
1 ─ return (2, 6, 24)
) => Tuple{Int64, Int64, Int64}
julia> Base.@assume_effects :total !:nothrow @ccall jl_type_intersection(Vector{Int}::Any, Vector{<:Integer}::Any)::Any
Vector{Int64} (alias for Array{Int64, 1})
在函数体内部使用需要至少 Julia 1.10 版本。
不正确使用此宏会导致未定义行为(包括崩溃、错误答案或其他难以追踪的错误)。谨慎使用,并且只有在绝对必要时才作为最后手段使用。即使在这种情况下,您也应该尽一切努力来最小化效果断言的强度(例如,如果 :nothrow
足够,请不要使用 :total
)。
通常,每个 setting
值都会对函数的行为进行断言,而不需要编译器证明这种行为确实是真实的。这些断言是在所有世界年龄中进行的。因此,建议限制使用可能在以后扩展以使假设失效的通用函数(这会导致未定义行为)。
支持以下 setting
值。
:consistent
:effect_free
:nothrow
:terminates_globally
:terminates_locally
:notaskstate
:inaccessiblememonly
:foldable
:可移除的
:总数
扩展帮助
:consistent
:consistent
设置断言对于相等 (===
) 输入
- 终止方式(返回值、异常、非终止)将始终相同。
- 如果方法返回,结果将始终相等。
特别地,这意味着该方法不得返回新分配的可变对象。多个可变对象的分配(即使内容相同)也不相等。
:consistent
一致性断言是在世界年龄的基础上进行的。更正式地说,将 $fᵢ$ 写为 $f$ 在世界年龄 $i$ 中的评估,那么我们需要
\[∀ i, x, y: x ≡ y → fᵢ(x) ≡ fᵢ(y)\]
但是,对于两个世界年龄 $i$、$j$,使得 $i ≠ j$,我们可能会有 $fᵢ(x) ≢ fⱼ(y)$。
另一个含义是,:consistent
函数不得使其返回值依赖于堆的状态或任何其他对于给定世界年龄不是常量的全局状态。
:consistent
一致性包括优化器执行的所有合法重写。例如,浮点数 fastmath 操作不被视为 :consistent
,因为优化器可能会重写它们,导致输出不一致,即使对于相同的世界年龄也是如此(例如,因为一个在解释器中运行,而另一个被优化了)。
:consistent
一致性断言目前包括断言该函数不会执行任何未定义的行为(对于任何输入)。请注意,未定义的行为在技术上可能会导致该函数违反其他效果断言(例如 :nothrow
或 :effect_free
),但我们没有对此进行建模,除了 :consistent
之外的所有效果都假设不存在未定义的行为。
如果 :consistent
函数通过抛出异常而终止,该异常本身不需要满足上述相等性要求。
:effect_free
:effect_free
设置断言该方法没有外部语义上可见的副作用。以下是外部语义上可见的副作用的不完整列表
- 更改全局变量的值。
- 修改堆(例如数组或可变值),除非以下情况
- 更改方法表(例如,通过调用 eval)
- 文件/网络/等 I/O
- 任务切换
但是,以下内容明确地不是语义上可见的,即使它们可能是可观察的
- 内存分配(可变和不可变)
- 经过的时间
- 垃圾收集
- 堆对寿命不超过方法的对象的修改(即在方法中分配且没有转义的对象)。
- 返回值(它是外部可见的,但不是副作用)
这里经验法则是,外部可见的副作用是任何会影响程序其余部分执行的内容,如果该函数没有执行。
:effect_free
断言针对方法本身以及方法执行的任何代码都成立。请记住,该断言必须对所有世界年龄有效,并相应地限制该断言的使用。
:nothrow
:nothrow
设置断言该方法不会异常终止(即始终返回一个值或从不返回)。
允许 :nothrow
注释方法在内部使用异常处理,只要异常没有被重新抛出方法本身之外即可。
MethodErrors
和类似的异常被视为异常终止。
:terminates_globally
:terminates_globally
设置断言该方法最终会终止(正常或异常),即不会无限循环。
此 :terminates_globally
断言涵盖注释方法调用的任何其他方法。
编译器将认为这是一个强烈的迹象,表明该方法将相对快速地终止,并且可能(如果在法律允许的情况下)在编译时调用该方法。也就是说,对一个技术上但不是实际上终止的方法注释此设置是一个不好的做法。
:terminates_locally
:terminates_locally
设置类似于 :terminates_globally
,只是它只适用于注释方法内部的语法控制流。因此,这是一个更弱(因此更安全)的断言,允许在方法调用某些不终止的其他方法的情况下,可能出现非终止。
:terminates_globally
意味着 :terminates_locally
。
:notaskstate
:notaskstate
设置断言该方法不使用或修改本地任务状态(任务本地存储、RNG 状态等),因此可以在任务之间安全地移动,而不会产生可观察的结果。
异常处理的实现使用存储在任务对象中的状态。但是,此状态目前不被认为在 :notaskstate
的范围内,并使用 :nothrow
效果单独跟踪。
:notaskstate
断言关注当前正在运行的任务的状态。如果通过某种不考虑当前正在运行的任务的方法获得对 Task
对象的引用,则 :notaskstate
效果不需要被污染。即使所述任务对象恰好与当前正在运行的任务相同,也是如此。
访问任务状态通常也会导致其他效果的污染,例如 :effect_free
(如果修改了任务状态)或 :consistent
(如果在计算结果时使用了任务状态)。特别是,不是 :notaskstate
但却是 :effect_free
和 :consistent
的代码仍然可以进行死代码消除,因此可以提升为 :total
。
:inaccessiblememonly
:inaccessiblememonly
设置断言该方法不访问或修改外部可访问的可变内存。这意味着该方法可以访问或修改新分配对象的可变内存,该内存不可由其他方法或方法返回之前进行的顶层执行访问,但它不能访问或修改任何可变全局状态或其参数指向的可变内存。
以下是使此假设失效的示例的不完整列表
- 访问可变全局变量的全局引用或
getglobal
调用 - 对非常量全局变量进行赋值的全局赋值或
setglobal!
调用 - 更改全局可变变量字段的
setfield!
调用
此 :inaccessiblememonly
断言涵盖注释方法调用的任何其他方法。
:foldable
此设置是编译器需要保证在编译时进行常量折叠的一组效果的便捷捷径。它目前等效于以下 设置
:consistent
:effect_free
:terminates_globally
此列表尤其不包括 :nothrow
。编译器仍将尝试进行常量传播并在编译时记录任何抛出的错误。但是请注意,根据 :consistent
一致性要求,任何这样的注释调用在给定相同的参数值的情况下必须始终抛出。
函数内部的显式 @inbounds
注释也将禁用常量折叠,并且不会被 :foldable
覆盖。
:可移除的
此设置是编译器需要保证在编译时删除其结果在编译时未使用的调用的效果集的便捷捷径。它目前等效于以下 设置
:effect_free
:nothrow
:terminates_globally
:总数
此 设置
是最大的可能的设置集。它目前意味着以下其他 设置
:consistent
:effect_free
:nothrow
:terminates_globally
:notaskstate
:inaccessiblememonly
:total
是一个非常强的断言,并且可能会在 Julia 的未来版本中获得额外的语义(例如,如果添加了额外的效果并包含在 :total
的定义中)。因此,应该谨慎使用。只要有可能,最好使用特定应用程序所需的最小可能的特定效果断言集。在大量效果覆盖应用于一组函数的情况下,建议使用自定义宏而不是 :total
。
否定效果
效果名称可以以 !
为前缀,表示应从更早的元效果中删除该效果。例如,:total !:nothrow
表示虽然调用通常是完整的,但它可能抛出异常。
Base.@deprecate
— 宏@deprecate old new [export_old=true]
弃用方法 old
并指定替换调用 new
,在此过程中定义一个具有指定签名的新的方法 old
。
要防止 old
被导出,将 export_old
设置为 false
。
从 Julia 1.5 开始,由 @deprecate
定义的函数在没有设置 --depwarn=yes
标志的情况下运行 julia
时不会打印警告,因为 --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.Missing
— 类型Base.missing
— 常量Base.coalesce
— 函数coalesce(x...)
返回参数中第一个不等于 missing
的值(如果有)。否则返回 missing
。
另请参见 skipmissing
、something
、@coalesce
。
示例
julia> coalesce(missing, 1)
1
julia> coalesce(1, missing)
1
julia> coalesce(nothing, 1) # returns `nothing`
julia> coalesce(missing, missing)
missing
Base.@coalesce
— 宏@coalesce(x...)
coalesce
的短路版本。
示例
julia> f(x) = (println("f($x)"); missing);
julia> a = 1;
julia> a = @coalesce a f(2) f(3) error("`a` is still missing")
1
julia> b = missing;
julia> b = @coalesce b f(2) f(3) error("`b` is still missing")
f(2)
f(3)
ERROR: `b` is still missing
[...]
此宏从 Julia 1.7 开始可用。
Base.ismissing
— 函数Base.skipmissing
— 函数skipmissing(itr)
返回一个迭代器,遍历 itr
中的元素,跳过 missing
值。如果 itr
是可索引的,则返回的对象可以使用 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
— 函数nonmissingtype(T::Type)
如果 T
是包含 Missing
的类型的联合,则返回一个删除了 Missing
的新类型。
示例
julia> nonmissingtype(Union{Int64,Missing})
Int64
julia> nonmissingtype(Any)
Any
此函数从 Julia 1.3 版本开始导出。
系统
Base.run
— 函数run(command, args...; wait::Bool = true)
运行一个命令对象,该对象是用反引号构建的(参见手册中的运行外部程序部分)。如果出现任何错误,包括进程以非零状态退出(当 wait
为真时),则抛出错误。
args...
允许您将文件描述符传递给命令,并且它们的顺序与常规的 Unix 文件描述符相同(例如 stdin, stdout, stderr, FD(3), FD(4)...
)。
如果 wait
为假,则进程异步运行。您可以稍后等待它并通过调用返回的进程对象的 success
来检查其退出状态。
当 wait
为假时,进程的 I/O 流将定向到 devnull
。当 wait
为真时,I/O 流将与父进程共享。使用 pipeline
来控制 I/O 重定向。
Base.devnull
— 常量devnull
在流重定向中使用,以丢弃写入它的所有数据。本质上等同于 Unix 上的 /dev/null
或 Windows 上的 NUL
。用法
run(pipeline(`cat test.txt`, devnull))
Base.success
— 函数success(command)
运行一个命令对象,该对象是用反引号构建的(参见手册中的运行外部程序部分),并判断它是否成功(以 0 代码退出)。如果进程无法启动,则会引发异常。
Base.process_running
— 函数process_running(p::Process)
判断一个进程是否正在运行。
Base.process_exited
— 函数process_exited(p::Process)
判断一个进程是否已退出。
Base.kill
— 方法kill(p::Process, signum=Base.SIGTERM)
向一个进程发送信号。默认情况下,将终止进程。如果进程已退出,则返回成功,但如果由于其他原因(例如权限不足)而无法杀死进程,则抛出错误。
Base.Sys.set_process_title
— 函数Sys.set_process_title(title::AbstractString)
设置进程标题。在某些操作系统上是空操作。
Base.Sys.get_process_title
— 函数Sys.get_process_title()
获取进程标题。在某些系统上,将始终返回空字符串。
Base.ignorestatus
— 函数ignorestatus(command)
标记一个命令对象,以便运行它时,如果结果代码不为零,不会抛出错误。
Base.detach
— 函数detach(command)
标记一个命令对象,以便它将在新的进程组中运行,允许它比 Julia 进程存活更久,并且不会将 Ctrl-C 中断传递给它。
Base.Cmd
— 类型Cmd(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
— 函数setenv(command::Cmd, env; dir)
设置在运行给定 command
时使用的环境变量。env
可以是字典(将字符串映射到字符串)、字符串数组(形式为 "var=val"
)、零个或多个 "var"=>val
键值对参数。为了修改(而不是替换)现有环境,请通过 copy(ENV)
创建 env
,然后设置 env["var"]=val
,或者使用 addenv
。
dir
关键字参数可用于指定命令的工作目录。dir
默认为 command
当前设置的 dir
(如果未指定,则为当前工作目录)。
Base.addenv
— 函数addenv(command::Cmd, env...; inherit::Bool = true)
将新的环境映射合并到给定的 Cmd
对象中,返回一个新的 Cmd
对象。重复的键将被替换。如果 command
不包含任何已设置的环境值,则如果 inherit
为 true
,它将继承 addenv()
调用时的当前环境。值为 nothing
的键将从 env 中删除。
此函数需要 Julia 1.6 或更高版本。
Base.withenv
— 函数withenv(f, kv::Pair...)
在环境中执行 f
,该环境被零个或多个 "var"=>val
参数 kv
临时修改(而不是替换,如 setenv
中所做)。withenv
通常通过 withenv(kv...) do ... end
语法使用。nothing
值可用于临时取消设置环境变量(如果已设置)。当 withenv
返回时,原始环境已恢复。
更改环境不是线程安全的。对于使用与父进程不同的环境运行外部命令,建议使用 addenv
而不是 withenv
。
Base.setcpuaffinity
— 函数setcpuaffinity(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
— 方法pipeline(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
— 方法pipeline(command; stdin, stdout, stderr, append=false)
将 I/O 重定向到或从给定的 command
中。关键字参数指定命令的哪些流应该被重定向。append
控制文件输出是否追加到文件。这是一个更通用的 2 参数 pipeline
函数版本。pipeline(from, to)
等同于 pipeline(from, stdout=to)
(当 from
是命令时),以及 pipeline(to, stdin=from)
(当 from
是其他类型的数据源时)。
示例:
run(pipeline(`dothings`, stdout="out.txt", stderr="errs.txt"))
run(pipeline(`update`, stdout="log.txt", append=true))
Base.Libc.gethostname
— 函数gethostname() -> String
获取本地机器的主机名。
Base.Libc.getpid
— 函数getpid() -> Int32
获取 Julia 的进程 ID。
getpid(process) -> Int32
获取子进程 ID(如果它仍然存在)。
该函数需要至少 Julia 1.1 版本。
Base.Libc.time
— 方法time() -> Float64
获取自纪元以来的系统时间(以秒为单位),具有相当高的(通常是微秒级)分辨率。
Base.time_ns
— 函数time_ns() -> UInt64
获取以纳秒为单位的时间。对应于 0 的时间未定义,并且每 5.8 年循环一次。
Base.@time
— 宏@time expr
@time "description" expr
一个宏,用于执行表达式,在返回表达式的值之前,打印执行该表达式所花费的时间、分配的数量以及其执行导致分配的总字节数。任何花费在垃圾回收 (gc)、编译新代码或重新编译失效代码上的时间都将显示为百分比。
可以选择提供一个描述字符串,在时间报告之前打印。
在某些情况下,系统将查看 @time
表达式内部,并在顶层表达式开始执行之前编译一些被调用的代码。发生这种情况时,一些编译时间将不会被计算。要包含此时间,您可以运行 @time @eval ...
。
另见 @showtime
、@timev
、@timed
、@elapsed
、@allocated
以及 @allocations
。
对于更严肃的基准测试,请考虑 BenchmarkTools.jl 包中的 @btime
宏,该宏除其他事项外,会多次评估函数以减少噪声。
在 Julia 1.8 中引入了添加描述的选项。
在 Julia 1.8 中引入了将重新编译时间与编译时间分开显示的功能。
julia> x = rand(10,10);
julia> @time x * x;
0.606588 seconds (2.19 M allocations: 116.555 MiB, 3.75% gc time, 99.94% compilation time)
julia> @time x * x;
0.000009 seconds (1 allocation: 896 bytes)
julia> @time begin
sleep(0.3)
1+1
end
0.301395 seconds (8 allocations: 336 bytes)
2
julia> @time "A one second sleep" sleep(1)
A one second sleep: 1.005750 seconds (5 allocations: 144 bytes)
julia> for loop in 1:3
@time loop sleep(1)
end
1: 1.006760 seconds (5 allocations: 144 bytes)
2: 1.001263 seconds (5 allocations: 144 bytes)
3: 1.003676 seconds (5 allocations: 144 bytes)
Base.@showtime
— 宏@showtime expr
类似于 @time
,但还会打印被计算的表达式以供参考。
此宏是在 Julia 1.8 中添加的。
另请参阅 @time
.
julia> @showtime sleep(1)
sleep(1): 1.002164 seconds (4 allocations: 128 bytes)
Base.@timev
— 宏@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
— 宏@timed
一个宏,用于执行表达式并返回表达式的值、经过时间、分配的总字节数、垃圾收集时间以及一个包含各种内存分配计数器的对象。
在某些情况下,系统会查看 @timed
表达式内部,并在执行顶层表达式之前编译部分调用的代码。发生这种情况时,一些编译时间将不会被计算在内。要包含此时间,您可以运行 @timed @eval ...
。
另请参阅 @time
、@timev
、@elapsed
、@allocated
和 @allocations
.
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 1.5 中从 Tuple
更改为 NamedTuple
。
Base.@elapsed
— 宏@elapsed
一个宏,用于计算表达式,丢弃结果值,而是返回执行所需时间的秒数,以浮点数形式表示。
在某些情况下,系统会查看 @elapsed
表达式内部,并在执行顶层表达式之前编译部分调用的代码。发生这种情况时,一些编译时间将不会被计算在内。要包含此时间,您可以运行 @elapsed @eval ...
。
另请参阅 @time
、@timev
、@timed
、@allocated
和 @allocations
.
julia> @elapsed sleep(0.3)
0.301391426
Base.@allocated
— 宏@allocated
一个宏,用于计算表达式,丢弃结果值,而是返回在计算表达式期间分配的总字节数。
另请参阅 @allocations
、@time
、@timev
、@timed
和 @elapsed
.
julia> @allocated rand(10^6)
8000080
Base.@allocations
— 宏@allocations
一个宏,用于计算表达式,丢弃结果值,而是返回在计算表达式期间的总分配次数。
另请参阅 @allocated
、@time
、@timev
、@timed
和 @elapsed
.
julia> @allocations rand(10^6)
2
此宏是在 Julia 1.9 中添加的。
Base.EnvDict
— 类型EnvDict() -> EnvDict
此类型的单例提供了对环境变量的哈希表接口。
Base.ENV
— 常量ENV
对单例 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
— 常量Sys.STDLIB::String
一个字符串,包含包含 stdlib
包的目录的完整路径。
Base.Sys.isunix
— 函数Sys.isunix([os])
用于测试操作系统是否提供类 Unix 接口的谓词。请参阅 处理操作系统差异 中的文档。
Base.Sys.isapple
— 函数Sys.isapple([os])
用于测试操作系统是否为 Apple Macintosh OS X 或 Darwin 的派生版本。请参阅 处理操作系统差异 中的文档。
Base.Sys.islinux
— 函数Sys.islinux([os])
用于测试操作系统是否为 Linux 的派生版本。请参阅 处理操作系统差异 中的文档。
Base.Sys.isbsd
— 函数Sys.isbsd([os])
用于测试操作系统是否为 BSD 的派生版本。请参阅 处理操作系统差异 中的文档。
Darwin 内核源于 BSD,这意味着 Sys.isbsd()
在 macOS 系统上为 true
。要从谓词中排除 macOS,请使用 Sys.isbsd() && !Sys.isapple()
。
Base.Sys.isfreebsd
— 函数Sys.isfreebsd([os])
用于测试操作系统是否为 FreeBSD 的派生版本。请参阅 处理操作系统差异 中的文档。
不要与 Sys.isbsd()
混淆,后者在 FreeBSD 上为 true
,但在其他基于 BSD 的系统上也为 true
。Sys.isfreebsd()
仅指 FreeBSD。
该函数需要至少 Julia 1.1 版本。
Base.Sys.isopenbsd
— 函数Sys.isopenbsd([os])
用于测试操作系统是否为 OpenBSD 的派生版本。请参阅 处理操作系统差异 中的文档。
不要与 Sys.isbsd()
混淆,后者在 OpenBSD 上为 true
,但在其他基于 BSD 的系统上也为 true
。Sys.isopenbsd()
仅指 OpenBSD。
该函数需要至少 Julia 1.1 版本。
Base.Sys.isnetbsd
— 函数Sys.isnetbsd([os])
用于测试操作系统是否为 NetBSD 的派生版本。请参阅 处理操作系统差异 中的文档。
不要与 Sys.isbsd()
混淆,后者在 NetBSD 上为 true
,但在其他基于 BSD 的系统上也为 true
。Sys.isnetbsd()
仅指 NetBSD。
该函数需要至少 Julia 1.1 版本。
Base.Sys.isdragonfly
— 函数Sys.isdragonfly([os])
用于测试操作系统是否为 DragonFly BSD 的派生版本。请参阅 处理操作系统差异 中的文档。
不要与 Sys.isbsd()
混淆,后者在 DragonFly 上为 true
,但在其他基于 BSD 的系统上也为 true
。Sys.isdragonfly()
仅指 DragonFly。
该函数需要至少 Julia 1.1 版本。
Base.Sys.iswindows
— 函数Sys.iswindows([os])
用于测试操作系统是否为 Microsoft Windows NT 的派生版本。请参阅 处理操作系统差异 中的文档。
Base.Sys.windows_version
— 函数Sys.windows_version()
将 Windows NT 内核的版本号返回为 VersionNumber
,即 v"major.minor.build"
,或者如果不在 Windows 上运行,则返回 v"0.0.0"
。
Base.Sys.free_memory
— 函数Sys.free_memory()
获取 RAM 中的总空闲内存(以字节为单位)。
Base.Sys.total_memory
— 函数Sys.total_memory()
获取 RAM 中的总内存(包括当前使用的内存),以字节为单位。此数量可能受到限制,例如,受到 Linux 控制组的限制。对于不受约束的数量,请参阅 Sys.total_physical_memory()
。
Base.Sys.free_physical_memory
— 函数Sys.free_physical_memory()
获取系统的空闲内存(以字节为单位)。整个数量可能无法提供给当前进程;使用 Sys.free_memory()
获取实际可用的数量。
Base.Sys.total_physical_memory
— 函数Sys.total_physical_memory()
获取 RAM 中的总内存(包括当前使用的内存),以字节为单位。整个数量可能无法提供给当前进程;请参阅 Sys.total_memory()
。
Base.Sys.uptime
— 函数Sys.uptime()
获取当前系统运行时间(以秒为单位)。
Base.Sys.isjsvm
— 函数Sys.isjsvm([os])
用于测试 Julia 是否在 JavaScript VM (JSVM) 中运行的谓词,包括例如 WebAssembly JavaScript 在网页浏览器中的嵌入。
此函数至少需要 Julia 1.2。
Base.Sys.loadavg
— 函数Sys.loadavg()
获取负载平均值。请参阅:https://en.wikipedia.org/wiki/Load_(computing)。
Base.Sys.isexecutable
— 函数Sys.isexecutable(path::String)
如果给定的 path
具有可执行权限,则返回 true
。
在 Julia 1.6 之前,此方法无法在 Windows 上正确查询文件系统 ACL,因此它会对任何文件返回 true
。从 Julia 1.6 开始,它会正确判断文件是否被标记为可执行文件。
Base.@static
— 宏@static
在解析时部分计算表达式。
例如,@static Sys.iswindows() ? foo : bar
将计算 Sys.iswindows()
并将 foo
或 bar
插入表达式中。这在某些情况下很有用,例如在其他平台上无效的结构,例如对不存在的函数的 ccall
。@static if Sys.isapple() foo end
和 @static foo <&&,||> bar
也是有效的语法。
版本控制
Base.VersionNumber
— 类型VersionNumber
版本号类型,遵循 语义版本控制 (semver) 的规范,由主版本、次版本和修订版本数字组成,后面跟着预发布和构建的字母数字注释。
VersionNumber
对象可以使用所有标准比较运算符(==
、<
、<=
等)进行比较,结果遵循 semver 规则。
另请参见 @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
— 宏错误
Base.error
— 函数error(message::AbstractString)
使用给定消息引发 ErrorException
。
error(msg...)
使用给定消息引发 ErrorException
。
Core.throw
— 函数Base.rethrow
— 函数rethrow()
从 catch
块中重新抛出当前异常。重新抛出的异常将继续传播,就像它没有被捕获一样。
备用形式 rethrow(e)
允许您将备用异常对象 e
与当前回溯相关联。但是,这会错误地表示错误发生时的程序状态,因此建议您改为使用 throw(e)
抛出新异常。在 Julia 1.1 及更高版本中,使用 throw(e)
将保留堆栈上的根本原因异常,如 current_exceptions
中所述。
Base.backtrace
— 函数backtrace()
获取当前程序点的回溯对象。
Base.catch_backtrace
— 函数catch_backtrace()
获取当前异常的回溯,用于 catch
块中。
Base.current_exceptions
— 函数current_exceptions(task::Task=current_task(); [backtrace::Bool=true])
获取当前正在处理的异常堆栈。对于嵌套的 catch 块,可能存在多个当前异常,在这种情况下,最近抛出的异常位于堆栈的最后。堆栈作为 ExceptionStack
返回,它是一个包含命名元组 (exception,backtrace)
的 AbstractVector。如果 backtrace
为 false,则每对中的回溯将设置为 nothing
。
显式传递 task
将返回任意任务上的当前异常堆栈。这对于检查由于未捕获异常而导致失败的任务很有用。
此函数在 Julia 1.1–1.6 中使用实验名称 catch_stack()
,并具有作为返回类型的普通 Vector-of-tuples。
Base.@assert
— 宏@assert cond [text]
如果 cond
为 false
,则抛出 AssertionError
。编写断言的首选语法。消息 text
可选地显示在断言失败时。
断言可能会在不同的优化级别被禁用。因此,断言应该只用作调试工具,不应用于身份验证验证(例如,验证密码),也不应在断言内部使用函数正常工作所需的副作用。
示例
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
— 函数Experimental.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
# Color is not necessary, this is just to show it's possible.
print(io, "\nDid you mean to call ")
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)
Did you mean to call `any_number`?
Closest candidates are:
...
自定义错误提示从 Julia 1.5 开始可用。
此接口是实验性的,可能会在未经通知的情况下更改或删除。为了避免更改,请考虑将任何注册放在 if isdefined(Base.Experimental, :register_error_hint) ... end
块中。
Base.Experimental.show_error_hints
— 函数Experimental.show_error_hints(io, ex, args...)
为特定异常类型 typeof(ex)
调用 Experimental.register_error_hint
中的所有处理程序。args
必须包含该类型处理程序期望的任何其他参数。
自定义错误提示从 Julia 1.5 开始可用。
此接口是实验性的,可能会在未经通知的情况下更改或删除。
Core.ArgumentError
— 类型ArgumentError(msg)
传递给函数的参数无效。msg
是一个描述性的错误消息。
Core.AssertionError
— 类型AssertionError([msg])
断言的条件没有计算为 true
。可选参数 msg
是一个描述性的错误字符串。
示例
julia> @assert false "this is not true"
ERROR: AssertionError: this is not true
AssertionError
通常由 @assert
抛出。
Core.BoundsError
— 类型BoundsError([a],[i])
对数组 a
的索引操作尝试访问索引 i
处越界的元素。
示例
julia> A = fill(1.0, 7);
julia> A[8]
ERROR: BoundsError: attempt to access 7-element Vector{Float64} at index [8]
julia> B = fill(1.0, (2,3));
julia> B[2, 4]
ERROR: BoundsError: attempt to access 2×3 Matrix{Float64} at index [2, 4]
julia> B[9]
ERROR: BoundsError: attempt to access 2×3 Matrix{Float64} at index [9]
Base.CompositeException
— 类型CompositeException
使用有关异常系列的信息包装由 Task
抛出的异常 Vector
(例如,从通道上的远程工作器、异步执行的本地 I/O 写入或 pmap
下的远程工作器生成)。例如,如果一群工作器正在执行多个任务,而多个工作器失败,则生成的 CompositeException
将包含来自每个工作器的“捆绑”信息,指示异常发生的位置和原因。
Base.DimensionMismatch
— 类型DimensionMismatch([msg])
调用的对象没有匹配的维度。可选参数 msg
是一个描述性的错误字符串。
Core.DivideError
— 类型DivideError()
整数除法尝试使用值为 0 的除数。
示例
julia> 2/0
Inf
julia> div(2, 0)
ERROR: DivideError: integer division error
Stacktrace:
[...]
Core.DomainError
— 类型DomainError(val)
DomainError(val, msg)
函数或构造函数的参数 val
位于有效域之外。
示例
julia> sqrt(-1)
ERROR: DomainError with -1.0:
sqrt was called with a negative real argument but will only return a complex result if called with a complex argument. Try sqrt(Complex(x)).
Stacktrace:
[...]
Base.EOFError
— 类型EOFError()
从文件或流中不再有可供读取的数据。
Core.ErrorException
— 类型ErrorException(msg)
通用错误类型。.msg
字段中的错误消息可能提供更具体的详细信息。
示例
julia> ex = ErrorException("I've done a bad thing");
julia> ex.msg
"I've done a bad thing"
Core.InexactError
— 类型InexactError(name::Symbol, T, val)
无法将 val
精确转换为函数 name
方法中的类型 T
。
示例
julia> convert(Float64, 1+2im)
ERROR: InexactError: Float64(1 + 2im)
Stacktrace:
[...]
Core.InterruptException
— 类型InterruptException()
该进程被终端中断(CTRL+C)停止。
请注意,在没有 -i
(交互式)选项的情况下启动的 Julia 脚本中,默认情况下不会抛出 InterruptException
。在脚本中调用 Base.exit_on_sigint(false)
可以恢复 REPL 的行为。或者,可以使用以下方法启动 Julia 脚本:
julia -e "include(popfirst!(ARGS))" script.jl
以允许 InterruptException
在执行期间被 CTRL+C 抛出。
Base.KeyError
— 类型KeyError(key)
对 AbstractDict
(Dict
) 或类似 Set
对象的索引操作尝试访问或删除不存在的元素。
Core.LoadError
— 类型LoadError(file::AbstractString, line::Int, error)
在 include
、require
或 using
文件时发生错误。错误细节应该在 .error
字段中可用。
从 Julia 1.7 开始,@macroexpand
、@macroexpand1
和 macroexpand
不再发出 LoadErrors。
Core.MethodError
— 类型MethodError(f, args)
在给定泛型函数中不存在具有所需类型签名的方法。或者,不存在唯一的、最具体的、最通用的方法。
Base.MissingException
— 类型MissingException(msg)
当在不支持 missing
值的情况下遇到它时,抛出异常。msg
字段中的错误消息可能提供更具体的详细信息。
Core.OutOfMemoryError
— 类型OutOfMemoryError()
操作分配的内存过多,以至于系统或垃圾收集器无法正确处理。
Core.ReadOnlyMemoryError
— 类型ReadOnlyMemoryError()
操作尝试写入只读内存。
Core.OverflowError
— 类型OverflowError(msg)
表达式的结果对于指定的类型来说太大,会导致回绕。
Base.ProcessFailedException
— 类型ProcessFailedException
表示进程退出状态有问题。在运行命令或管道时,抛出此异常以指示返回了非零退出代码(即调用的进程失败)。
Base.TaskFailedException
— 类型TaskFailedException
当任务 t
失败时,此异常由 wait(t)
调用抛出。TaskFailedException
包装了失败的任务 t
。
Core.StackOverflowError
— 类型StackOverflowError()
函数调用超出了调用堆栈的大小。这通常发生在调用无限递归时。
Base.SystemError
— 类型SystemError(prefix::AbstractString, [errno::Int32])
系统调用失败并返回错误代码(在 errno
全局变量中)。
Core.TypeError
— 类型TypeError(func::Symbol, context::AbstractString, expected::Type, got)
类型断言失败,或使用不正确的参数类型调用内在函数。
Core.UndefKeywordError
— 类型UndefKeywordError(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
— 类型UndefRefError()
给定对象未定义项目或字段。
示例
julia> struct MyType
a::Vector{Int}
MyType() = new()
end
julia> A = MyType()
MyType(#undef)
julia> A.a
ERROR: UndefRefError: access to undefined reference
Stacktrace:
[...]
Core.UndefVarError
— 类型UndefVarError(var::Symbol)
当前作用域中未定义符号。
示例
julia> a
ERROR: UndefVarError: `a` not defined
julia> a = 1;
julia> a
1
Base.StringIndexError
— 类型StringIndexError(str, i)
尝试在索引 i
处访问 str
时发生错误,该索引无效。
Core.InitError
— 类型InitError(mod::Symbol, error)
在运行模块的__init__
函数时发生了错误。实际抛出的错误可在.error
字段中找到。
Base.retry
— 函数retry(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
— 类型ExponentialBackOff(; 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
。
事件
Base.Timer
— 方法Timer(callback::Function, delay; interval = 0)
创建一个定时器,在每次定时器到期时运行函数callback
。
等待的任务会在初始延迟delay
秒后被唤醒,函数callback
会被调用,然后以给定的interval
秒为间隔重复调用。如果interval
等于0
,则callback
只运行一次。函数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
— 类型Timer(delay; interval = 0)
创建一个定时器,唤醒等待它的任务(通过对定时器对象调用wait
)。
等待的任务会在至少delay
秒的初始延迟后被唤醒,然后在至少interval
秒后再次被唤醒。如果interval
等于0
,则定时器只触发一次。当定时器关闭(通过close
)时,等待的任务会被唤醒并出现错误。使用isopen
检查定时器是否仍然处于活动状态。
interval
会受到累积时间偏差的影响。如果你需要在特定的绝对时间进行精确的事件,请在每次到期时创建一个新的定时器,并计算到下次时间的差值。
Timer
需要让步点来更新其状态。例如,isopen(t::Timer)
不能用于超时一个不产生让步的 while 循环。
Base.AsyncCondition
— 类型AsyncCondition()
创建一个异步条件,当通过调用uv_async_send
从 C 中收到通知时,会唤醒等待它的任务(通过对对象调用wait
)。当对象关闭(通过close
)时,等待的任务会被唤醒并出现错误。使用isopen
检查它是否仍然处于活动状态。
这在发送线程和等待线程之间提供了一个隐式的获取和释放内存排序。
Base.AsyncCondition
— 方法AsyncCondition(callback::Function)
创建一个异步条件,调用给定的callback
函数。callback
传递一个参数,即异步条件对象本身。
反射
Base.nameof
— 方法Base.parentmodule
— 函数parentmodule(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
确定包含泛型函数f
的第一个方法的模块,该方法与指定的types
匹配。
parentmodule(m::Method) -> Module
返回定义给定方法m
的模块。
将Method
作为参数传递需要 Julia 1.9 或更高版本。
Base.pathof
— 方法pathof(m::Module)
返回用于import
模块m
的m.jl
文件的路径,如果m
不是从包中导入的,则返回nothing
。
Base.pkgdir
— 方法pkgdir(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"
可选参数paths
需要 Julia 1.7 或更高版本。
Base.pkgversion
— 方法pkgversion(m::Module)
返回导入模块m
的包的版本,如果m
不是从包中导入的,或者从没有设置版本字段的包中导入的,则返回nothing
。
版本是在包加载期间从包的 Project.toml 中读取的。
要获取导入当前模块的包的版本,可以使用pkgversion(@__MODULE__)
的形式。
此函数在 Julia 1.9 中引入。
Base.moduleroot
— 函数moduleroot(m::Module) -> Module
查找给定模块的根模块。这是m
的父模块链中的第一个模块,它要么是已注册的根模块,要么是它自己的父模块。
__module__
— 关键字__module__
参数__module__
仅在宏内部可见,它提供有关宏调用扩展上下文的信息(以Module
对象的形式)。有关更多信息,请参阅有关宏调用的手册部分。
__source__
— 关键字__source__
参数__source__
仅在宏内部可见,它提供有关宏调用中@
符号的解析器位置的信息(以LineNumberNode
对象的形式)。有关更多信息,请参阅有关宏调用的手册部分。
Base.@__MODULE__
— 宏@__MODULE__ -> Module
获取顶层评估的Module
,即当前正在从中读取代码的Module
。
Base.@__FILE__
— 宏@__FILE__ -> String
扩展为包含宏调用的文件的路径的字符串,如果通过julia -e <expr>
评估,则为一个空字符串。如果宏缺少解析器源信息,则返回nothing
。或者请参阅PROGRAM_FILE
。
Base.@__DIR__
— 宏@__DIR__ -> String
扩展为包含宏调用的文件的目录的绝对路径的字符串。如果从 REPL 运行或通过julia -e <expr>
评估,则返回当前工作目录。
Base.@__LINE__
— 宏@__LINE__ -> Int
扩展为宏调用的位置的行号。如果无法确定行号,则返回0
。
Base.fullname
— 函数fullname(m::Module)
获取模块的完全限定名称,作为符号元组。例如,
示例
julia> fullname(Base.Iterators)
(:Base, :Iterators)
julia> fullname(Main)
(:Main,)
Base.names
— 函数names(x::Module; all::Bool = false, imported::Bool = false)
获取Module
导出的名称数组,不包括弃用名称。如果all
为真,则列表还包括模块中定义的非导出名称、弃用名称和编译器生成的名称。如果imported
为真,则还包括显式从其他模块导入的名称。
作为特殊情况,Main
中定义的所有名称都被认为是“导出的”,因为在Main
中显式导出名称是不符合习惯的。
另请参阅:@locals
,@__MODULE__
.
Base.nameof
— 方法nameof(f::Function) -> Symbol
获取泛型Function
的名称,作为符号。对于匿名函数,这是一个编译器生成的名称。对于显式声明的Function
子类型,它是函数类型的名称。
Base.functionloc
— 方法functionloc(f::Function, types)
返回一个元组(filename,line)
,给出泛型Function
定义的位置。
Base.functionloc
— 方法functionloc(m::Method)
返回一个元组(filename,line)
,给出Method
定义的位置。
Base.@locals
— 宏@locals()
构造一个字典,包含调用点定义的所有局部变量的名称(作为符号)和值。
此宏需要 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)
代码加载
Base.identify_package
— 函数Base.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 is a dependency of the default environment
Pkg [44cfe95a-1eb2-52ea-b672-e2afdf69b78f]
julia> using LinearAlgebra
julia> Base.identify_package(LinearAlgebra, "Pkg") # Pkg is not a dependency of LinearAlgebra
Base.locate_package
— 函数Base.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.10/Pkg/src/Pkg.jl"
Base.require
— 函数require(into::Module, module::Symbol)
此函数是using
/ import
实现的一部分,如果Main
中尚未定义模块。它也可以直接调用,以强制重新加载模块,而不管它之前是否加载过(例如,在交互式开发库时)。
在每个活动节点上加载源文件,在 Main
模块的上下文中,在标准位置搜索文件。require
被认为是顶级操作,因此它设置当前的 include
路径,但不会使用它来搜索文件(有关 include
的帮助,请参阅帮助)。此函数通常用于加载库代码,并且由 using
隐式调用来加载包。
在搜索文件时,require
首先在全局数组 LOAD_PATH
中查找包代码。require
对所有平台上的文件名大小写敏感,包括 macOS 和 Windows 等具有不区分大小写文件系统的平台。
Base.compilecache
— 函数Base.compilecache(module::PkgId)
为模块及其所有依赖项创建预编译的缓存文件。这可以用于减少包加载时间。缓存文件存储在 DEPOT_PATH[1]/compiled
中。有关重要说明,请参阅 模块初始化和预编译。
Base.isprecompiled
— 函数Base.isprecompiled(pkg::PkgId; ignore_loaded::Bool=false)
返回活动项目中给定 PkgId 是否已预编译。
默认情况下,此检查遵循与代码加载相同的方案,即当前加载的依赖项的不同版本与预期版本相对应。要忽略已加载的模块并像在新的 julia 会话中一样回答,请指定 ignore_loaded=true
。
此函数至少需要 Julia 1.10。
Base.get_extension
— 函数get_extension(parent::Module, extension::Symbol)
返回 parent
的 extension
模块,如果扩展未加载,则返回 nothing
。
内部机制
Base.GC.gc
— 函数GC.gc([full=true])
执行垃圾回收。参数 full
决定回收的类型:完全回收(默认)会清除所有对象,这会使下次 GC 扫描速度变慢,而增量回收可能只清除所谓的年轻对象。
过度使用可能会导致性能下降。
Base.GC.enable
— 函数GC.enable(on::Bool)
使用布尔参数控制是否启用垃圾回收(true
表示启用,false
表示禁用)。返回之前的 GC 状态。
禁用垃圾回收应谨慎使用,因为它会导致内存使用无限增长。
Base.GC.@preserve
— 宏GC.@preserve x1 x2 ... xn expr
在表达式 expr
的评估期间,将对象 x1, x2, ...
标记为正在使用。这仅在不安全的代码中需要,在该代码中,expr
隐式地使用了 x
之一拥有的内存或其他资源。
隐式使用 x
包含对 x
逻辑拥有的资源的任何间接使用,编译器无法看到这些资源。以下是一些示例
- 通过
Ptr
直接访问对象的内存 - 将指向
x
的指针传递给ccall
- 使用
x
的资源,这些资源将在析构函数中清理。
在典型的用例中,@preserve
通常不会对性能产生任何影响,因为它会短暂地延长对象的生命周期。在实现中,@preserve
具有保护动态分配的对象免遭垃圾回收等效果。
示例
从指针加载时,使用 unsafe_load
,底层对象会隐式地使用,例如,在以下示例中,x
会被 unsafe_load(p)
隐式地使用
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)
# Preferred alternative
Int(@ccall strlen(x::Cstring)::Csize_t)
end
5
Base.GC.safepoint
— 函数GC.safepoint()
在程序中插入一个点,垃圾回收可以在该点运行。这在多线程程序中很少见的用例中可能很有用,在这些用例中,一些线程正在分配内存(因此可能需要运行 GC),而其他线程只执行简单的操作(不分配、任务切换或 I/O)。在非分配线程中定期调用此函数允许垃圾回收运行。
此函数从 Julia 1.4 开始可用。
Base.GC.enable_logging
— 函数GC.enable_logging(on::Bool)
启用后,将关于每次 GC 的统计信息打印到 stderr。
Base.Meta.lower
— 函数lower(m, x)
获取表达式 x
并返回在模块 m
中执行的等效表达式,该表达式以降低的形式存在。另请参阅 code_lowered
。
Base.Meta.@lower
— 宏@lower [m] x
返回模块 m
中表达式 x
的降低形式。默认情况下,m
是调用宏的模块。另请参阅 lower
。
Base.Meta.parse
— 方法parse(str, start; greedy=true, raise=true, depwarn=true, filename="none")
解析表达式字符串并返回一个表达式(稍后可以传递给 eval 以执行)。start
是 str
中第一个字符的代码单元索引,从该索引开始解析(与所有字符串索引一样,这些不是字符索引)。如果 greedy
为 true
(默认),parse
将尝试尽可能多地消耗输入;否则,它将在解析有效表达式后立即停止。不完整但语法上有效的表达式将返回 Expr(:incomplete, "(error message)")
。如果 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
— 方法parse(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")
ERROR: ParseError:
# Error @ none:1:1
1.0.2
└──┘ ── invalid numeric constant
[...]
julia> Meta.parse("1.0.2"; raise = false)
:($(Expr(:error, "invalid numeric constant "1.0."")))
julia> Meta.parse("x = ")
:($(Expr(:incomplete, "incomplete: premature end of input")))
Base.Meta.ParseError
— 类型ParseError(msg)
传递给 parse
函数的表达式无法解释为有效的 Julia 表达式。
Core.QuoteNode
— 类型QuoteNode
一段引用的代码,不支持插值。有关详细信息,请参阅 关于 QuoteNodes 的手册部分。
Base.macroexpand
— 函数macroexpand(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
— 宏@macroexpand
返回等效的表达式,其中所有宏都被删除(展开)。
@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
,表达式将在作为第一个参数给出的模块中扩展。
Base.@macroexpand1
— 宏@macroexpand1
@macroexpand
的非递归版本。
Base.code_lowered
— 函数code_lowered(f, types; generated=true, debuginfo=:default)
返回与给定的泛型函数和类型签名匹配的方法的降低形式(IR)的数组。
如果 generated
为 false
,则返回的 CodeInfo
实例将对应于回退实现。如果不存在回退实现,则会抛出错误。如果 generated
为 true
,则这些 CodeInfo
实例将对应于通过展开生成器产生的方法体。
关键字 debuginfo
控制输出中存在的代码元数据的数量。
请注意,如果 types
不是叶类型,而 generated
为 true
,并且任何对应的方法都是 @generated
方法,则会抛出错误。
Base.code_typed
— 函数code_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
— 函数precompile(f, argtypes::Tuple{Vararg{Any}})
为给定的参数元组(类型)argtypes
编译给定的函数 f
,但不执行它。
precompile(f, argtypes::Tuple{Vararg{Any}}, m::Method)
为给定的参数类型预编译特定方法。这可用于预编译与通常由调度选择的不同的方法,从而模拟 invoke
。
Base.jit_total_bytes
— 函数Base.jit_total_bytes()
返回即时编译器为例如本机代码和数据分配的总字节数。
Meta
Base.Meta.quot
— 函数Meta.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
— 函数Meta.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]) # multiple possible heads
true
julia> Meta.isexpr(ex, :call, 1)
false
julia> Meta.isexpr(ex, :call, 2)
true
Base.isidentifier
— 函数 isidentifier(s) -> Bool
返回符号或字符串 s
是否包含在 Julia 代码中解析为有效普通标识符(不是二元/一元运算符)的字符;另请参阅 Base.isoperator
.
在内部,Julia 允许 Symbol
中的任何字符序列(除了 \0
),并且宏会自动使用包含 #
的变量名,以避免与周围代码的命名冲突。为了让解析器识别变量,它使用了一组有限的字符(Unicode 大大扩展)。isidentifier()
使得可以直接查询解析器该符号是否包含有效字符。
示例
julia> Meta.isidentifier(:x), Meta.isidentifier("1x")
(true, false)
Base.isoperator
— 函数isoperator(s::Symbol)
如果符号可以用作运算符,则返回 true
,否则返回 false
。
示例
julia> Meta.isoperator(:+), Meta.isoperator(:f)
(true, false)
Base.isunaryoperator
— 函数isunaryoperator(s::Symbol)
如果符号可以用作一元(前缀)运算符,则返回 true
,否则返回 false
。
示例
julia> Meta.isunaryoperator(:-), Meta.isunaryoperator(:√), Meta.isunaryoperator(:f)
(true, true, false)
Base.isbinaryoperator
— 函数isbinaryoperator(s::Symbol)
如果符号可以用作二元(中缀)运算符,则返回 true
,否则返回 false
。
示例
julia> Meta.isbinaryoperator(:-), Meta.isbinaryoperator(:√), Meta.isbinaryoperator(:f)
(true, false, false)
Base.Meta.show_sexpr
— 函数Meta.show_sexpr([io::IO,], ex)
以 Lisp 风格的 S 表达式形式显示表达式 ex
。
示例
julia> Meta.show_sexpr(:(f(x, g(y,z))))
(:call, :f, :x, (:call, :g, :y, :z))