From 2962bd89bc8c70f8a77ef7135c662deb44318f35 Mon Sep 17 00:00:00 2001 From: "Documenter.jl" Date: Sat, 21 Oct 2023 14:16:10 +0000 Subject: [PATCH] build based on d87b9b0 --- dev/base/arrays/index.html | 2 +- dev/base/base/index.html | 4 +- dev/base/c/index.html | 2 +- dev/base/collections/index.html | 50 +++++++++---------- dev/base/constants/index.html | 2 +- dev/base/file/index.html | 2 +- dev/base/io-network/index.html | 2 +- dev/base/iterators/index.html | 2 +- dev/base/libc/index.html | 2 +- dev/base/math/index.html | 20 ++++---- dev/base/multi-threading/index.html | 2 +- dev/base/numbers/index.html | 2 +- dev/base/parallel/index.html | 4 +- dev/base/punctuation/index.html | 2 +- dev/base/simd-types/index.html | 2 +- dev/base/sort/index.html | 2 +- dev/base/stacktraces/index.html | 2 +- dev/base/strings/index.html | 2 +- dev/devdocs/ast/index.html | 2 +- dev/devdocs/backtraces/index.html | 6 +-- dev/devdocs/boundscheck/index.html | 2 +- dev/devdocs/callconv/index.html | 2 +- dev/devdocs/cartesian/index.html | 2 +- dev/devdocs/compiler/index.html | 2 +- dev/devdocs/debuggingtips/index.html | 2 +- dev/devdocs/eval/index.html | 2 +- dev/devdocs/functions/index.html | 2 +- dev/devdocs/gc-sa/index.html | 2 +- dev/devdocs/inference/index.html | 2 +- dev/devdocs/init/index.html | 2 +- dev/devdocs/isbitsunionarrays/index.html | 2 +- dev/devdocs/llvm/index.html | 2 +- dev/devdocs/locks/index.html | 2 +- dev/devdocs/meta/index.html | 2 +- dev/devdocs/object/index.html | 2 +- dev/devdocs/offset-arrays/index.html | 2 +- dev/devdocs/reflection/index.html | 2 +- dev/devdocs/require/index.html | 2 +- dev/devdocs/sanitizers/index.html | 2 +- dev/devdocs/ssair/index.html | 2 +- dev/devdocs/stdio/index.html | 2 +- dev/devdocs/subarrays/index.html | 2 +- dev/devdocs/sysimg/index.html | 2 +- dev/devdocs/types/index.html | 2 +- dev/devdocs/valgrind/index.html | 2 +- dev/index.html | 2 +- dev/manual/arrays/index.html | 2 +- .../asynchronous-programming/index.html | 2 +- .../calling-c-and-fortran-code/index.html | 2 +- dev/manual/code-loading/index.html | 2 +- dev/manual/command-line-options/index.html | 2 +- .../complex-and-rational-numbers/index.html | 2 +- dev/manual/constructors/index.html | 2 +- dev/manual/control-flow/index.html | 2 +- .../conversion-and-promotion/index.html | 2 +- dev/manual/distributed-computing/index.html | 2 +- dev/manual/documentation/index.html | 2 +- dev/manual/embedding/index.html | 2 +- dev/manual/environment-variables/index.html | 2 +- dev/manual/faq/index.html | 2 +- dev/manual/functions/index.html | 2 +- dev/manual/getting-started/index.html | 2 +- .../index.html | 2 +- dev/manual/index.html | 2 +- .../index.html | 2 +- dev/manual/interfaces/index.html | 2 +- dev/manual/mathematical-operations/index.html | 2 +- dev/manual/metaprogramming/index.html | 2 +- dev/manual/methods/index.html | 2 +- dev/manual/missing/index.html | 2 +- dev/manual/modules/index.html | 2 +- dev/manual/multi-threading/index.html | 2 +- dev/manual/networking-and-streams/index.html | 2 +- dev/manual/noteworthy-differences/index.html | 2 +- dev/manual/parallel-computing/index.html | 2 +- dev/manual/performance-tips/index.html | 2 +- dev/manual/profile/index.html | 2 +- .../running-external-programs/index.html | 2 +- dev/manual/stacktraces/index.html | 2 +- dev/manual/strings/index.html | 2 +- dev/manual/style-guide/index.html | 2 +- dev/manual/types/index.html | 2 +- dev/manual/unicode-input/index.html | 2 +- dev/manual/variables-and-scoping/index.html | 2 +- dev/manual/variables/index.html | 2 +- dev/manual/workflow-tips/index.html | 2 +- dev/search/index.html | 2 +- dev/search_index.js | 2 +- dev/stdlib/Artifacts/index.html | 2 +- dev/stdlib/Base64/index.html | 2 +- dev/stdlib/CRC32c/index.html | 2 +- dev/stdlib/Dates/index.html | 2 +- dev/stdlib/DelimitedFiles/index.html | 2 +- dev/stdlib/Distributed/index.html | 2 +- dev/stdlib/FileWatching/index.html | 2 +- dev/stdlib/Future/index.html | 2 +- dev/stdlib/InteractiveUtils/index.html | 2 +- dev/stdlib/LazyArtifacts/index.html | 2 +- dev/stdlib/LibGit2/index.html | 2 +- dev/stdlib/Libdl/index.html | 2 +- dev/stdlib/LinearAlgebra/index.html | 2 +- dev/stdlib/Logging/index.html | 2 +- dev/stdlib/Markdown/index.html | 2 +- dev/stdlib/Mmap/index.html | 2 +- dev/stdlib/Printf/index.html | 2 +- dev/stdlib/Profile/index.html | 2 +- dev/stdlib/REPL/index.html | 2 +- dev/stdlib/Random/index.html | 2 +- dev/stdlib/SHA/index.html | 2 +- dev/stdlib/Serialization/index.html | 2 +- dev/stdlib/SharedArrays/index.html | 2 +- dev/stdlib/Sockets/index.html | 2 +- dev/stdlib/SparseArrays/index.html | 2 +- dev/stdlib/Statistics/index.html | 2 +- dev/stdlib/TOML/index.html | 2 +- dev/stdlib/Test/index.html | 2 +- dev/stdlib/UUIDs/index.html | 2 +- dev/stdlib/Unicode/index.html | 2 +- 118 files changed, 155 insertions(+), 155 deletions(-) diff --git a/dev/base/arrays/index.html b/dev/base/arrays/index.html index ea3bb92c..0adfe428 100644 --- a/dev/base/arrays/index.html +++ b/dev/base/arrays/index.html @@ -1633,4 +1633,4 @@ 4 3 2 - 1source
reverse!(A; dims=:)

Like reverse, but operates in-place in A.

Julia 1.6

Multidimensional reverse! requires Julia 1.6.

source
+ 1source
reverse!(A; dims=:)

Like reverse, but operates in-place in A.

Julia 1.6

Multidimensional reverse! requires Julia 1.6.

source
diff --git a/dev/base/base/index.html b/dev/base/base/index.html index fd03a53c..17760679 100644 --- a/dev/base/base/index.html +++ b/dev/base/base/index.html @@ -1096,7 +1096,7 @@ Any
Julia 1.3

This function is exported as of Julia 1.3.

source

System

Base.runFunction
run(command, args...; wait::Bool = true)

Run a command object, constructed with backticks (see the Running External Programs section in the manual). Throws an error if anything goes wrong, including the process exiting with a non-zero status (when wait is true).

The args... allow you to pass through file descriptors to the command, and are ordered like regular unix file descriptors (eg stdin, stdout, stderr, FD(3), FD(4)...).

If wait is false, the process runs asynchronously. You can later wait for it and check its exit status by calling success on the returned process object.

When wait is false, the process' I/O streams are directed to devnull. When wait is true, I/O streams are shared with the parent process. Use pipeline to control I/O redirection.

source
Base.devnullConstant
devnull

Used in a stream redirect to discard all data written to it. Essentially equivalent to /dev/null on Unix or NUL on Windows. Usage:

run(pipeline(`cat test.txt`, devnull))
source
Base.successFunction
success(command)

Run a command object, constructed with backticks (see the Running External Programs section in the manual), and tell whether it was successful (exited with a code of 0). An exception is raised if the process cannot be started.

source
Base.process_runningFunction
process_running(p::Process)

Determine whether a process is currently running.

source
Base.process_exitedFunction
process_exited(p::Process)

Determine whether a process has exited.

source
Base.killMethod
kill(p::Process, signum=Base.SIGTERM)

Send a signal to a process. The default is to terminate the process. Returns successfully if the process has already exited, but throws an error if killing the process failed for other reasons (e.g. insufficient permissions).

source
Base.Sys.set_process_titleFunction
Sys.set_process_title(title::AbstractString)

Set the process title. No-op on some operating systems.

source
Base.Sys.get_process_titleFunction
Sys.get_process_title()

Get the process title. On some systems, will always return an empty string.

source
Base.ignorestatusFunction
ignorestatus(command)

Mark a command object so that running it will not throw an error if the result code is non-zero.

source
Base.detachFunction
detach(command)

Mark a command object so that it will be run in a new process group, allowing it to outlive the julia process, and not have Ctrl-C interrupts passed to it.

source
Base.CmdType
Cmd(cmd::Cmd; ignorestatus, detach, windows_verbatim, windows_hide, env, dir)

Construct a new Cmd object, representing an external program and arguments, from cmd, while changing the settings of the optional keyword arguments:

  • ignorestatus::Bool: If true (defaults to false), then the Cmd will not throw an error if the return code is nonzero.
  • detach::Bool: If true (defaults to false), then the Cmd will be run in a new process group, allowing it to outlive the julia process and not have Ctrl-C passed to it.
  • windows_verbatim::Bool: If true (defaults to false), then on Windows the Cmd will send a command-line string to the process with no quoting or escaping of arguments, even arguments containing spaces. (On Windows, arguments are sent to a program as a single "command-line" string, and programs are responsible for parsing it into arguments. By default, empty arguments and arguments with spaces or tabs are quoted with double quotes " in the command line, and \ or " are preceded by backslashes. windows_verbatim=true is useful for launching programs that parse their command line in nonstandard ways.) Has no effect on non-Windows systems.
  • windows_hide::Bool: If true (defaults to false), then on Windows no new console window is displayed when the Cmd is executed. This has no effect if a console is already open or on non-Windows systems.
  • env: Set environment variables to use when running the Cmd. env is either a dictionary mapping strings to strings, an array of strings of the form "var=val", an array or tuple of "var"=>val pairs. In order to modify (rather than replace) the existing environment, initialize env with copy(ENV) and then set env["var"]=val as desired. To add to an environment block within a Cmd object without replacing all elements, use addenv() which will return a Cmd object with the updated environment.
  • dir::AbstractString: Specify a working directory for the command (instead of the current directory).

For any keywords that are not specified, the current settings from cmd are used. Normally, to create a Cmd object in the first place, one uses backticks, e.g.

Cmd(`echo "Hello world"`, ignorestatus=true, detach=false)
source
Base.setenvFunction
setenv(command::Cmd, env; dir)

Set environment variables to use when running the given command. env is either a dictionary mapping strings to strings, an array of strings of the form "var=val", or zero or more "var"=>val pair arguments. In order to modify (rather than replace) the existing environment, create env through copy(ENV) and then setting env["var"]=val as desired, or use addenv.

The dir keyword argument can be used to specify a working directory for the command. dir defaults to the currently set dir for command (which is the current working directory if not specified already).

See also Cmd, addenv, ENV, pwd.

source
Base.addenvFunction
addenv(command::Cmd, env...; inherit::Bool = true)

Merge new environment mappings into the given Cmd object, returning a new Cmd object. Duplicate keys are replaced. If command does not contain any environment values set already, it inherits the current environment at time of addenv() call if inherit is true. Keys with value nothing are deleted from the env.

See also Cmd, setenv, ENV.

Julia 1.6

This function requires Julia 1.6 or later.

source
Base.withenvFunction
withenv(f, kv::Pair...)

Execute f in an environment that is temporarily modified (not replaced as in setenv) by zero or more "var"=>val arguments kv. withenv is generally used via the withenv(kv...) do ... end syntax. A value of nothing can be used to temporarily unset an environment variable (if it is set). When withenv returns, the original environment has been restored.

source
Base.pipelineMethod
pipeline(from, to, ...)

Create a pipeline from a data source to a destination. The source and destination can be commands, I/O streams, strings, or results of other pipeline calls. At least one argument must be a command. Strings refer to filenames. When called with more than two arguments, they are chained together from left to right. For example, pipeline(a,b,c) is equivalent to pipeline(pipeline(a,b),c). This provides a more concise way to specify multi-stage pipelines.

Examples:

run(pipeline(`ls`, `grep xyz`))
 run(pipeline(`ls`, "out.txt"))
 run(pipeline("out.txt", `grep xyz`))
source
Base.pipelineMethod
pipeline(command; stdin, stdout, stderr, append=false)

Redirect I/O to or from the given command. Keyword arguments specify which of the command's streams should be redirected. append controls whether file output appends to the file. This is a more general version of the 2-argument pipeline function. pipeline(from, to) is equivalent to pipeline(from, stdout=to) when from is a command, and to pipeline(to, stdin=from) when from is another kind of data source.

Examples:

run(pipeline(`dothings`, stdout="out.txt", stderr="errs.txt"))
-run(pipeline(`update`, stdout="log.txt", append=true))
source
Base.Libc.gethostnameFunction
gethostname() -> AbstractString

Get the local machine's host name.

source
Base.Libc.getpidFunction
getpid(process) -> Int32

Get the child process ID, if it still exists.

Julia 1.1

This function requires at least Julia 1.1.

source
getpid() -> Int32

Get Julia's process ID.

source
Base.Libc.timeMethod
time()

Get the system time in seconds since the epoch, with fairly high (typically, microsecond) resolution.

source
Base.time_nsFunction
time_ns()

Get the time in nanoseconds. The time corresponding to 0 is undefined, and wraps every 5.8 years.

source
Base.@timeMacro
@time expr
+run(pipeline(`update`, stdout="log.txt", append=true))
source
Base.Libc.gethostnameFunction
gethostname() -> AbstractString

Get the local machine's host name.

source
Base.Libc.getpidFunction
getpid() -> Int32

Get Julia's process ID.

source
getpid(process) -> Int32

Get the child process ID, if it still exists.

Julia 1.1

This function requires at least Julia 1.1.

source
Base.Libc.timeMethod
time()

Get the system time in seconds since the epoch, with fairly high (typically, microsecond) resolution.

source
Base.time_nsFunction
time_ns()

Get the time in nanoseconds. The time corresponding to 0 is undefined, and wraps every 5.8 years.

source
Base.@timeMacro
@time expr
 @time "description" expr

A macro to execute an expression, printing the time it took to execute, the number of allocations, and the total number of bytes its execution caused to be allocated, before returning the value of the expression. Any time spent garbage collecting (gc), compiling new code, or recompiling invalidated code is shown as a percentage.

Optionally provide a description string to print before the time report.

In some cases the system will look inside the @time expression and compile some of the called code before execution of the top-level expression begins. When that happens, some compilation time will not be counted. To include this time you can run @time @eval ....

See also @showtime, @timev, @timed, @elapsed, and @allocated.

Note

For more serious benchmarking, consider the @btime macro from the BenchmarkTools.jl package which among other things evaluates the function multiple times in order to reduce noise.

Julia 1.8

The option to add a description was introduced in Julia 1.8.

Recompilation time being shown separately from compilation time was introduced in Julia 1.8

julia> x = rand(10,10);
 
 julia> @time x * x;
@@ -1426,4 +1426,4 @@
 (true, false)
source
Base.isunaryoperatorFunction
isunaryoperator(s::Symbol)

Return true if the symbol can be used as a unary (prefix) operator, false otherwise.

Examples

julia> Meta.isunaryoperator(:-), Meta.isunaryoperator(:√), Meta.isunaryoperator(:f)
 (true, true, false)
source
Base.isbinaryoperatorFunction
isbinaryoperator(s::Symbol)

Return true if the symbol can be used as a binary (infix) operator, false otherwise.

Examples

julia> Meta.isbinaryoperator(:-), Meta.isbinaryoperator(:√), Meta.isbinaryoperator(:f)
 (true, false, false)
source
Base.Meta.show_sexprFunction
Meta.show_sexpr([io::IO,], ex)

Show expression ex as a lisp style S-expression.

Examples

julia> Meta.show_sexpr(:(f(x, g(y,z))))
-(:call, :f, :x, (:call, :g, :y, :z))
source
+(:call, :f, :x, (:call, :g, :y, :z))source diff --git a/dev/base/c/index.html b/dev/base/c/index.html index 6ec621e0..b944edcf 100644 --- a/dev/base/c/index.html +++ b/dev/base/c/index.html @@ -93,4 +93,4 @@ julia> isassigned(Ref{Int}()) truesource
Base.CcharType
Cchar

Equivalent to the native char c-type.

source
Base.CucharType
Cuchar

Equivalent to the native unsigned char c-type (UInt8).

source
Base.CshortType
Cshort

Equivalent to the native signed short c-type (Int16).

source
Base.CstringType
Cstring

A C-style string composed of the native character type Cchars. Cstrings are NUL-terminated. For C-style strings composed of the native wide character type, see Cwstring. For more information about string interopability with C, see the manual.

source
Base.CushortType
Cushort

Equivalent to the native unsigned short c-type (UInt16).

source
Base.CintType
Cint

Equivalent to the native signed int c-type (Int32).

source
Base.CuintType
Cuint

Equivalent to the native unsigned int c-type (UInt32).

source
Base.ClongType
Clong

Equivalent to the native signed long c-type.

source
Base.CulongType
Culong

Equivalent to the native unsigned long c-type.

source
Base.ClonglongType
Clonglong

Equivalent to the native signed long long c-type (Int64).

source
Base.CulonglongType
Culonglong

Equivalent to the native unsigned long long c-type (UInt64).

source
Base.Cintmax_tType
Cintmax_t

Equivalent to the native intmax_t c-type (Int64).

source
Base.Cuintmax_tType
Cuintmax_t

Equivalent to the native uintmax_t c-type (UInt64).

source
Base.Csize_tType
Csize_t

Equivalent to the native size_t c-type (UInt).

source
Base.Cssize_tType
Cssize_t

Equivalent to the native ssize_t c-type.

source
Base.Cptrdiff_tType
Cptrdiff_t

Equivalent to the native ptrdiff_t c-type (Int).

source
Base.Cwchar_tType
Cwchar_t

Equivalent to the native wchar_t c-type (Int32).

source
Base.CwstringType
Cwstring

A C-style string composed of the native wide character type Cwchar_ts. Cwstrings are NUL-terminated. For C-style strings composed of the native character type, see Cstring. For more information about string interopability with C, see the manual.

source
Base.CfloatType
Cfloat

Equivalent to the native float c-type (Float32).

source
Base.CdoubleType
Cdouble

Equivalent to the native double c-type (Float64).

source

LLVM 接口

Core.Intrinsics.llvmcallFunction
llvmcall(fun_ir::String, returntype, Tuple{argtype1, ...}, argvalue1, ...)
 llvmcall((mod_ir::String, entry_fn::String), returntype, Tuple{argtype1, ...}, argvalue1, ...)
-llvmcall((mod_bc::Vector{UInt8}, entry_fn::String), returntype, Tuple{argtype1, ...}, argvalue1, ...)

Call the LLVM code provided in the first argument. There are several ways to specify this first argument:

  • as a literal string, representing function-level IR (similar to an LLVM define block), with arguments are available as consecutive unnamed SSA variables (%0, %1, etc.);
  • as a 2-element tuple, containing a string of module IR and a string representing the name of the entry-point function to call;
  • as a 2-element tuple, but with the module provided as an Vector{UINt8} with bitcode.

Note that contrary to ccall, the argument types must be specified as a tuple type, and not a tuple of types. All types, as well as the LLVM code, should be specified as literals, and not as variables or expressions (it may be necessary to use @eval to generate these literals).

See test/llvmcall.jl for usage examples.

source
+llvmcall((mod_bc::Vector{UInt8}, entry_fn::String), returntype, Tuple{argtype1, ...}, argvalue1, ...)

Call the LLVM code provided in the first argument. There are several ways to specify this first argument:

Note that contrary to ccall, the argument types must be specified as a tuple type, and not a tuple of types. All types, as well as the LLVM code, should be specified as literals, and not as variables or expressions (it may be necessary to use @eval to generate these literals).

See test/llvmcall.jl for usage examples.

source diff --git a/dev/base/collections/index.html b/dev/base/collections/index.html index 372e5635..d5837639 100644 --- a/dev/base/collections/index.html +++ b/dev/base/collections/index.html @@ -1078,7 +1078,29 @@ julia> collect(values(D)) 2-element Vector{Int64}: 2 - 3source
Base.pairsFunction
pairs(collection)

Return an iterator over key => value pairs for any collection that maps a set of keys to a set of values. This includes arrays, where the keys are the array indices.

Examples

julia> a = Dict(zip(["a", "b", "c"], [1, 2, 3]))
+ 3
source
Base.pairsFunction
pairs(IndexLinear(), A)
+pairs(IndexCartesian(), A)
+pairs(IndexStyle(A), A)

An iterator that accesses each element of the array A, returning i => x, where i is the index for the element and x = A[i]. Identical to pairs(A), except that the style of index can be selected. Also similar to enumerate(A), except i will be a valid index for A, while enumerate always counts from 1 regardless of the indices of A.

Specifying IndexLinear() ensures that i will be an integer; specifying IndexCartesian() ensures that i will be a CartesianIndex; specifying IndexStyle(A) chooses whichever has been defined as the native indexing style for array A.

Mutation of the bounds of the underlying array will invalidate this iterator.

Examples

julia> A = ["a" "d"; "b" "e"; "c" "f"];
+
+julia> for (index, value) in pairs(IndexStyle(A), A)
+           println("$index $value")
+       end
+1 a
+2 b
+3 c
+4 d
+5 e
+6 f
+
+julia> S = view(A, 1:2, :);
+
+julia> for (index, value) in pairs(IndexStyle(S), S)
+           println("$index $value")
+       end
+CartesianIndex(1, 1) a
+CartesianIndex(2, 1) b
+CartesianIndex(1, 2) d
+CartesianIndex(2, 2) e

See also IndexStyle, axes.

source
pairs(collection)

Return an iterator over key => value pairs for any collection that maps a set of keys to a set of values. This includes arrays, where the keys are the array indices.

Examples

julia> a = Dict(zip(["a", "b", "c"], [1, 2, 3]))
 Dict{String, Int64} with 3 entries:
   "c" => 3
   "b" => 2
@@ -1105,29 +1127,7 @@
 3-element Vector{Int64}:
  1
  2
- 3
source
pairs(IndexLinear(), A)
-pairs(IndexCartesian(), A)
-pairs(IndexStyle(A), A)

An iterator that accesses each element of the array A, returning i => x, where i is the index for the element and x = A[i]. Identical to pairs(A), except that the style of index can be selected. Also similar to enumerate(A), except i will be a valid index for A, while enumerate always counts from 1 regardless of the indices of A.

Specifying IndexLinear() ensures that i will be an integer; specifying IndexCartesian() ensures that i will be a CartesianIndex; specifying IndexStyle(A) chooses whichever has been defined as the native indexing style for array A.

Mutation of the bounds of the underlying array will invalidate this iterator.

Examples

julia> A = ["a" "d"; "b" "e"; "c" "f"];
-
-julia> for (index, value) in pairs(IndexStyle(A), A)
-           println("$index $value")
-       end
-1 a
-2 b
-3 c
-4 d
-5 e
-6 f
-
-julia> S = view(A, 1:2, :);
-
-julia> for (index, value) in pairs(IndexStyle(S), S)
-           println("$index $value")
-       end
-CartesianIndex(1, 1) a
-CartesianIndex(2, 1) b
-CartesianIndex(1, 2) d
-CartesianIndex(2, 2) e

See also IndexStyle, axes.

source
Base.mergeFunction
merge(d::AbstractDict, others::AbstractDict...)

Construct a merged collection from the given collections. If necessary, the types of the resulting collection will be promoted to accommodate the types of the merged collections. If the same key is present in another collection, the value for that key will be the value it has in the last collection listed. See also mergewith for custom handling of values with the same key.

Examples

julia> a = Dict("foo" => 0.0, "bar" => 42.0)
+ 3
source
Base.mergeFunction
merge(d::AbstractDict, others::AbstractDict...)

Construct a merged collection from the given collections. If necessary, the types of the resulting collection will be promoted to accommodate the types of the merged collections. If the same key is present in another collection, the value for that key will be the value it has in the last collection listed. See also mergewith for custom handling of values with the same key.

Examples

julia> a = Dict("foo" => 0.0, "bar" => 42.0)
 Dict{String, Float64} with 2 entries:
   "bar" => 42.0
   "foo" => 0.0
@@ -1547,4 +1547,4 @@
            println(x)
        end
 foo
-7
source
Base.PairsType
Iterators.Pairs(values, keys) <: AbstractDict{eltype(keys), eltype(values)}

Transforms an indexable container into a Dictionary-view of the same data. Modifying the key-space of the underlying data may invalidate this object.

source
+7source
Base.PairsType
Iterators.Pairs(values, keys) <: AbstractDict{eltype(keys), eltype(values)}

Transforms an indexable container into a Dictionary-view of the same data. Modifying the key-space of the underlying data may invalidate this object.

source
diff --git a/dev/base/constants/index.html b/dev/base/constants/index.html index 655e7b4f..5f6cfc1e 100644 --- a/dev/base/constants/index.html +++ b/dev/base/constants/index.html @@ -6,4 +6,4 @@ ga('create', 'UA-28835595-9', 'auto'); ga('send', 'pageview', {'page': location.pathname + location.search + location.hash}); -

常量

Base.PROGRAM_FILEConstant
PROGRAM_FILE

A string containing the script name passed to Julia from the command line. Note that the script name remains unchanged from within included files. Alternatively see @__FILE__.

source
Base.ARGSConstant
ARGS

An array of the command line arguments passed to Julia, as strings.

source
Base.C_NULLConstant
C_NULL

The C null pointer constant, sometimes used when calling external code.

source
Base.DEPOT_PATHConstant
DEPOT_PATH

A stack of "depot" locations where the package manager, as well as Julia's code loading mechanisms, look for package registries, installed packages, named environments, repo clones, cached compiled package images, and configuration files. By default it includes:

  1. ~/.julia where ~ is the user home as appropriate on the system;
  2. an architecture-specific shared system directory, e.g. /usr/local/share/julia;
  3. an architecture-independent shared system directory, e.g. /usr/share/julia.

So DEPOT_PATH might be:

[joinpath(homedir(), ".julia"), "/usr/local/share/julia", "/usr/share/julia"]

The first entry is the "user depot" and should be writable by and owned by the current user. The user depot is where: registries are cloned, new package versions are installed, named environments are created and updated, package repos are cloned, newly compiled package image files are saved, log files are written, development packages are checked out by default, and global configuration data is saved. Later entries in the depot path are treated as read-only and are appropriate for registries, packages, etc. installed and managed by system administrators.

DEPOT_PATH is populated based on the JULIA_DEPOT_PATH environment variable if set.

DEPOT_PATH contents

Each entry in DEPOT_PATH is a path to a directory which contains subdirectories used by Julia for various purposes. Here is an overview of some of the subdirectories that may exist in a depot:

  • clones: Contains full clones of package repos. Maintained by Pkg.jl and used as a cache.
  • compiled: Contains precompiled *.ji files for packages. Maintained by Julia.
  • dev: Default directory for Pkg.develop. Maintained by Pkg.jl and the user.
  • environments: Default package environments. For instance the global environment for a specific julia version. Maintained by Pkg.jl.
  • logs: Contains logs of Pkg and REPL operations. Maintained by Pkg.jl and Julia.
  • packages: Contains packages, some of which were explicitly installed and some which are implicit dependencies. Maintained by Pkg.jl.
  • registries: Contains package registries. By default only General. Maintained by Pkg.jl.

See also JULIA_DEPOT_PATH, and Code Loading.

source
Base.LOAD_PATHConstant
LOAD_PATH

An array of paths for using and import statements to consider as project environments or package directories when loading code. It is populated based on the JULIA_LOAD_PATH environment variable if set; otherwise it defaults to ["@", "@v#.#", "@stdlib"]. Entries starting with @ have special meanings:

  • @ refers to the "current active environment", the initial value of which is initially determined by the JULIA_PROJECT environment variable or the --project command-line option.

  • @stdlib expands to the absolute path of the current Julia installation's standard library directory.

  • @name refers to a named environment, which are stored in depots (see JULIA_DEPOT_PATH) under the environments subdirectory. The user's named environments are stored in ~/.julia/environments so @name would refer to the environment in ~/.julia/environments/name if it exists and contains a Project.toml file. If name contains # characters, then they are replaced with the major, minor and patch components of the Julia version number. For example, if you are running Julia 1.2 then @v#.# expands to @v1.2 and will look for an environment by that name, typically at ~/.julia/environments/v1.2.

The fully expanded value of LOAD_PATH that is searched for projects and packages can be seen by calling the Base.load_path() function.

See also JULIA_LOAD_PATH, JULIA_PROJECT, JULIA_DEPOT_PATH, and Code Loading.

source
Base.Sys.BINDIRConstant
Sys.BINDIR::String

A string containing the full path to the directory containing the julia executable.

source
Base.Sys.CPU_THREADSConstant
Sys.CPU_THREADS::Int

The number of logical CPU cores available in the system, i.e. the number of threads that the CPU can run concurrently. Note that this is not necessarily the number of CPU cores, for example, in the presence of hyper-threading.

See Hwloc.jl or CpuId.jl for extended information, including number of physical cores.

source
Base.Sys.KERNELConstant
Sys.KERNEL::Symbol

A symbol representing the name of the operating system, as returned by uname of the build configuration.

source
Base.Sys.ARCHConstant
Sys.ARCH::Symbol

A symbol representing the architecture of the build configuration.

source

参见:

+

常量

Base.PROGRAM_FILEConstant
PROGRAM_FILE

A string containing the script name passed to Julia from the command line. Note that the script name remains unchanged from within included files. Alternatively see @__FILE__.

source
Base.ARGSConstant
ARGS

An array of the command line arguments passed to Julia, as strings.

source
Base.C_NULLConstant
C_NULL

The C null pointer constant, sometimes used when calling external code.

source
Base.DEPOT_PATHConstant
DEPOT_PATH

A stack of "depot" locations where the package manager, as well as Julia's code loading mechanisms, look for package registries, installed packages, named environments, repo clones, cached compiled package images, and configuration files. By default it includes:

  1. ~/.julia where ~ is the user home as appropriate on the system;
  2. an architecture-specific shared system directory, e.g. /usr/local/share/julia;
  3. an architecture-independent shared system directory, e.g. /usr/share/julia.

So DEPOT_PATH might be:

[joinpath(homedir(), ".julia"), "/usr/local/share/julia", "/usr/share/julia"]

The first entry is the "user depot" and should be writable by and owned by the current user. The user depot is where: registries are cloned, new package versions are installed, named environments are created and updated, package repos are cloned, newly compiled package image files are saved, log files are written, development packages are checked out by default, and global configuration data is saved. Later entries in the depot path are treated as read-only and are appropriate for registries, packages, etc. installed and managed by system administrators.

DEPOT_PATH is populated based on the JULIA_DEPOT_PATH environment variable if set.

DEPOT_PATH contents

Each entry in DEPOT_PATH is a path to a directory which contains subdirectories used by Julia for various purposes. Here is an overview of some of the subdirectories that may exist in a depot:

  • clones: Contains full clones of package repos. Maintained by Pkg.jl and used as a cache.
  • compiled: Contains precompiled *.ji files for packages. Maintained by Julia.
  • dev: Default directory for Pkg.develop. Maintained by Pkg.jl and the user.
  • environments: Default package environments. For instance the global environment for a specific julia version. Maintained by Pkg.jl.
  • logs: Contains logs of Pkg and REPL operations. Maintained by Pkg.jl and Julia.
  • packages: Contains packages, some of which were explicitly installed and some which are implicit dependencies. Maintained by Pkg.jl.
  • registries: Contains package registries. By default only General. Maintained by Pkg.jl.

See also JULIA_DEPOT_PATH, and Code Loading.

source
Base.LOAD_PATHConstant
LOAD_PATH

An array of paths for using and import statements to consider as project environments or package directories when loading code. It is populated based on the JULIA_LOAD_PATH environment variable if set; otherwise it defaults to ["@", "@v#.#", "@stdlib"]. Entries starting with @ have special meanings:

  • @ refers to the "current active environment", the initial value of which is initially determined by the JULIA_PROJECT environment variable or the --project command-line option.

  • @stdlib expands to the absolute path of the current Julia installation's standard library directory.

  • @name refers to a named environment, which are stored in depots (see JULIA_DEPOT_PATH) under the environments subdirectory. The user's named environments are stored in ~/.julia/environments so @name would refer to the environment in ~/.julia/environments/name if it exists and contains a Project.toml file. If name contains # characters, then they are replaced with the major, minor and patch components of the Julia version number. For example, if you are running Julia 1.2 then @v#.# expands to @v1.2 and will look for an environment by that name, typically at ~/.julia/environments/v1.2.

The fully expanded value of LOAD_PATH that is searched for projects and packages can be seen by calling the Base.load_path() function.

See also JULIA_LOAD_PATH, JULIA_PROJECT, JULIA_DEPOT_PATH, and Code Loading.

source
Base.Sys.BINDIRConstant
Sys.BINDIR::String

A string containing the full path to the directory containing the julia executable.

source
Base.Sys.CPU_THREADSConstant
Sys.CPU_THREADS::Int

The number of logical CPU cores available in the system, i.e. the number of threads that the CPU can run concurrently. Note that this is not necessarily the number of CPU cores, for example, in the presence of hyper-threading.

See Hwloc.jl or CpuId.jl for extended information, including number of physical cores.

source
Base.Sys.KERNELConstant
Sys.KERNEL::Symbol

A symbol representing the name of the operating system, as returned by uname of the build configuration.

source
Base.Sys.ARCHConstant
Sys.ARCH::Symbol

A symbol representing the architecture of the build configuration.

source

参见:

diff --git a/dev/base/file/index.html b/dev/base/file/index.html index ccf2e64a..43fe6522 100644 --- a/dev/base/file/index.html +++ b/dev/base/file/index.html @@ -229,4 +229,4 @@ "/" "home" "myuser" - "example.jl"source + "example.jl"source diff --git a/dev/base/io-network/index.html b/dev/base/io-network/index.html index 97269ad3..4b376ab5 100644 --- a/dev/base/io-network/index.html +++ b/dev/base/io-network/index.html @@ -445,4 +445,4 @@ falsesource

网络 I/O

Base.bytesavailableFunction
bytesavailable(io)

Return the number of bytes available for reading before a read from this stream or buffer will block.

Examples

julia> io = IOBuffer("JuliaLang is a GitHub organization");
 
 julia> bytesavailable(io)
-34
source
Base.ntohFunction
ntoh(x)

Convert the endianness of a value from Network byte order (big-endian) to that used by the Host.

source
Base.htonFunction
hton(x)

Convert the endianness of a value from that used by the Host to Network byte order (big-endian).

source
Base.ltohFunction
ltoh(x)

Convert the endianness of a value from Little-endian to that used by the Host.

source
Base.htolFunction
htol(x)

Convert the endianness of a value from that used by the Host to Little-endian.

source
Base.ENDIAN_BOMConstant
ENDIAN_BOM

The 32-bit byte-order-mark indicates the native byte order of the host machine. Little-endian machines will contain the value 0x04030201. Big-endian machines will contain the value 0x01020304.

source
+34source
Base.ntohFunction
ntoh(x)

Convert the endianness of a value from Network byte order (big-endian) to that used by the Host.

source
Base.htonFunction
hton(x)

Convert the endianness of a value from that used by the Host to Network byte order (big-endian).

source
Base.ltohFunction
ltoh(x)

Convert the endianness of a value from Little-endian to that used by the Host.

source
Base.htolFunction
htol(x)

Convert the endianness of a value from that used by the Host to Little-endian.

source
Base.ENDIAN_BOMConstant
ENDIAN_BOM

The 32-bit byte-order-mark indicates the native byte order of the host machine. Little-endian machines will contain the value 0x04030201. Big-endian machines will contain the value 0x01020304.

source
diff --git a/dev/base/iterators/index.html b/dev/base/iterators/index.html index 5607f40b..6bbf24a1 100644 --- a/dev/base/iterators/index.html +++ b/dev/base/iterators/index.html @@ -219,4 +219,4 @@ julia> collect(rest) 2-element Vector{Char}: 'b': ASCII/Unicode U+0062 (category Ll: Letter, lowercase) - 'c': ASCII/Unicode U+0063 (category Ll: Letter, lowercase)source + 'c': ASCII/Unicode U+0063 (category Ll: Letter, lowercase)source diff --git a/dev/base/libc/index.html b/dev/base/libc/index.html index 7d3a6f99..1797b59a 100644 --- a/dev/base/libc/index.html +++ b/dev/base/libc/index.html @@ -6,4 +6,4 @@ ga('create', 'UA-28835595-9', 'auto'); ga('send', 'pageview', {'page': location.pathname + location.search + location.hash}); -

C 标准库

Base.Libc.mallocFunction
malloc(size::Integer) -> Ptr{Cvoid}

Call malloc from the C standard library.

source
Base.Libc.callocFunction
calloc(num::Integer, size::Integer) -> Ptr{Cvoid}

Call calloc from the C standard library.

source
Base.Libc.reallocFunction
realloc(addr::Ptr, size::Integer) -> Ptr{Cvoid}

Call realloc from the C standard library.

See warning in the documentation for free regarding only using this on memory originally obtained from malloc.

source
Base.Libc.freeFunction
free(addr::Ptr)

Call free from the C standard library. Only use this on memory obtained from malloc, not on pointers retrieved from other C libraries. Ptr objects obtained from C libraries should be freed by the free functions defined in that library, to avoid assertion failures if multiple libc libraries exist on the system.

source
Base.Libc.errnoFunction
errno([code])

Get the value of the C library's errno. If an argument is specified, it is used to set the value of errno.

The value of errno is only valid immediately after a ccall to a C library routine that sets it. Specifically, you cannot call errno at the next prompt in a REPL, because lots of code is executed between prompts.

source
Base.Libc.FormatMessageFunction
FormatMessage(n=GetLastError())

Convert a Win32 system call error code to a descriptive string [only available on Windows].

source
Base.Libc.timeMethod
time(t::TmStruct)

Converts a TmStruct struct to a number of seconds since the epoch.

source
Base.Libc.strftimeFunction
strftime([format], time)

Convert time, given as a number of seconds since the epoch or a TmStruct, to a formatted string using the given format. Supported formats are the same as those in the standard C library.

source
Base.Libc.strptimeFunction
strptime([format], timestr)

Parse a formatted time string into a TmStruct giving the seconds, minute, hour, date, etc. Supported formats are the same as those in the standard C library. On some platforms, timezones will not be parsed correctly. If the result of this function will be passed to time to convert it to seconds since the epoch, the isdst field should be filled in manually. Setting it to -1 will tell the C library to use the current system settings to determine the timezone.

source
Base.Libc.TmStructType
TmStruct([seconds])

Convert a number of seconds since the epoch to broken-down format, with fields sec, min, hour, mday, month, year, wday, yday, and isdst.

source
Base.Libc.flush_cstdioFunction
flush_cstdio()

Flushes the C stdout and stderr streams (which may have been written to by external C code).

source
Base.Libc.systemsleepFunction
systemsleep(s::Real)

Suspends execution for s seconds. This function does not yield to Julia's scheduler and therefore blocks the Julia thread that it is running on for the duration of the sleep time.

See also sleep.

source
+

C 标准库

Base.Libc.mallocFunction
malloc(size::Integer) -> Ptr{Cvoid}

Call malloc from the C standard library.

source
Base.Libc.callocFunction
calloc(num::Integer, size::Integer) -> Ptr{Cvoid}

Call calloc from the C standard library.

source
Base.Libc.reallocFunction
realloc(addr::Ptr, size::Integer) -> Ptr{Cvoid}

Call realloc from the C standard library.

See warning in the documentation for free regarding only using this on memory originally obtained from malloc.

source
Base.Libc.freeFunction
free(addr::Ptr)

Call free from the C standard library. Only use this on memory obtained from malloc, not on pointers retrieved from other C libraries. Ptr objects obtained from C libraries should be freed by the free functions defined in that library, to avoid assertion failures if multiple libc libraries exist on the system.

source
Base.Libc.errnoFunction
errno([code])

Get the value of the C library's errno. If an argument is specified, it is used to set the value of errno.

The value of errno is only valid immediately after a ccall to a C library routine that sets it. Specifically, you cannot call errno at the next prompt in a REPL, because lots of code is executed between prompts.

source
Base.Libc.FormatMessageFunction
FormatMessage(n=GetLastError())

Convert a Win32 system call error code to a descriptive string [only available on Windows].

source
Base.Libc.timeMethod
time(t::TmStruct)

Converts a TmStruct struct to a number of seconds since the epoch.

source
Base.Libc.strftimeFunction
strftime([format], time)

Convert time, given as a number of seconds since the epoch or a TmStruct, to a formatted string using the given format. Supported formats are the same as those in the standard C library.

source
Base.Libc.strptimeFunction
strptime([format], timestr)

Parse a formatted time string into a TmStruct giving the seconds, minute, hour, date, etc. Supported formats are the same as those in the standard C library. On some platforms, timezones will not be parsed correctly. If the result of this function will be passed to time to convert it to seconds since the epoch, the isdst field should be filled in manually. Setting it to -1 will tell the C library to use the current system settings to determine the timezone.

source
Base.Libc.TmStructType
TmStruct([seconds])

Convert a number of seconds since the epoch to broken-down format, with fields sec, min, hour, mday, month, year, wday, yday, and isdst.

source
Base.Libc.flush_cstdioFunction
flush_cstdio()

Flushes the C stdout and stderr streams (which may have been written to by external C code).

source
Base.Libc.systemsleepFunction
systemsleep(s::Real)

Suspends execution for s seconds. This function does not yield to Julia's scheduler and therefore blocks the Julia thread that it is running on for the duration of the sleep time.

See also sleep.

source
diff --git a/dev/base/math/index.html b/dev/base/math/index.html index 653e7a5d..8334c2c2 100644 --- a/dev/base/math/index.html +++ b/dev/base/math/index.html @@ -27,7 +27,14 @@ 112 julia> *(2, 7, 8) -112source
Base.:/Function
A / B

Matrix right-division: A / B is equivalent to (B' \ A')' where \ is the left-division operator. For square matrices, the result X is such that A == X*B.

See also: rdiv!.

Examples

julia> A = Float64[1 4 5; 3 9 2]; B = Float64[1 4 2; 3 4 2; 8 7 1];
+112
source
Base.:/Function
/(x, y)

Right division operator: multiplication of x by the inverse of y on the right. Gives floating-point results for integer arguments.

Examples

julia> 1/2
+0.5
+
+julia> 4/2
+2.0
+
+julia> 4.5/2
+2.25
source
A / B

Matrix right-division: A / B is equivalent to (B' \ A')' where \ is the left-division operator. For square matrices, the result X is such that A == X*B.

See also: rdiv!.

Examples

julia> A = Float64[1 4 5; 3 9 2]; B = Float64[1 4 2; 3 4 2; 8 7 1];
 
 julia> X = A / B
 2×3 Matrix{Float64}:
@@ -38,14 +45,7 @@
 true
 
 julia> isapprox(X, A*pinv(B))
-true
/(x, y)

Right division operator: multiplication of x by the inverse of y on the right. Gives floating-point results for integer arguments.

Examples

julia> 1/2
-0.5
-
-julia> 4/2
-2.0
-
-julia> 4.5/2
-2.25
source
Base.:\Method
\(x, y)

Left division operator: multiplication of y by the inverse of x on the left. Gives floating-point results for integer arguments.

Examples

julia> 3 \ 6
+true
Base.:\Method
\(x, y)

Left division operator: multiplication of y by the inverse of x on the left. Gives floating-point results for integer arguments.

Examples

julia> 3 \ 6
 2.0
 
 julia> inv(3) * 6
@@ -981,4 +981,4 @@
 3
 
 julia> @fastmath(sin(3))
-0.1411200080598672
source

自定义二元运算符

某些 unicode 字符可用于定义新的支持中缀表示法的二元运算符。 例如, ⊗(x,y) = kron(x,y) 定义 (otimes) 为 Kronecker 积, 并且可以通过中缀语法将它作为一个二元运算符调用: C = A ⊗ B 也可以使用常用的前缀语法 C = ⊗(A,B)

其他支持这种扩展的字符包括 \odot 和 \oplus

The complete list is in the parser code: https://github.com/JuliaLang/julia/blob/master/src/julia-parser.scm

* 一样解析的包括(按优先级排列) * / ÷ % & ⋅ ∘ × |\\| ∩ ∧ ⊗ ⊘ ⊙ ⊚ ⊛ ⊠ ⊡ ⊓ ∗ ∙ ∤ ⅋ ≀ ⊼ ⋄ ⋆ ⋇ ⋉ ⋊ ⋋ ⋌ ⋏ ⋒ ⟑ ⦸ ⦼ ⦾ ⦿ ⧶ ⧷ ⨇ ⨰ ⨱ ⨲ ⨳ ⨴ ⨵ ⨶ ⨷ ⨸ ⨻ ⨼ ⨽ ⩀ ⩃ ⩄ ⩋ ⩍ ⩎ ⩑ ⩓ ⩕ ⩘ ⩚ ⩜ ⩞ ⩟ ⩠ ⫛ ⊍ ▷ ⨝ ⟕ ⟖ ⟗+ 一样解析的包括 + - |\|| ⊕ ⊖ ⊞ ⊟ |++| ∪ ∨ ⊔ ± ∓ ∔ ∸ ≏ ⊎ ⊻ ⊽ ⋎ ⋓ ⧺ ⧻ ⨈ ⨢ ⨣ ⨤ ⨥ ⨦ ⨧ ⨨ ⨩ ⨪ ⨫ ⨬ ⨭ ⨮ ⨹ ⨺ ⩁ ⩂ ⩅ ⩊ ⩌ ⩏ ⩐ ⩒ ⩔ ⩖ ⩗ ⩛ ⩝ ⩡ ⩢ ⩣ 还有许多其他的与箭头、比较和幂相关的符号。

+0.1411200080598672source

自定义二元运算符

某些 unicode 字符可用于定义新的支持中缀表示法的二元运算符。 例如, ⊗(x,y) = kron(x,y) 定义 (otimes) 为 Kronecker 积, 并且可以通过中缀语法将它作为一个二元运算符调用: C = A ⊗ B 也可以使用常用的前缀语法 C = ⊗(A,B)

其他支持这种扩展的字符包括 \odot 和 \oplus

The complete list is in the parser code: https://github.com/JuliaLang/julia/blob/master/src/julia-parser.scm

* 一样解析的包括(按优先级排列) * / ÷ % & ⋅ ∘ × |\\| ∩ ∧ ⊗ ⊘ ⊙ ⊚ ⊛ ⊠ ⊡ ⊓ ∗ ∙ ∤ ⅋ ≀ ⊼ ⋄ ⋆ ⋇ ⋉ ⋊ ⋋ ⋌ ⋏ ⋒ ⟑ ⦸ ⦼ ⦾ ⦿ ⧶ ⧷ ⨇ ⨰ ⨱ ⨲ ⨳ ⨴ ⨵ ⨶ ⨷ ⨸ ⨻ ⨼ ⨽ ⩀ ⩃ ⩄ ⩋ ⩍ ⩎ ⩑ ⩓ ⩕ ⩘ ⩚ ⩜ ⩞ ⩟ ⩠ ⫛ ⊍ ▷ ⨝ ⟕ ⟖ ⟗+ 一样解析的包括 + - |\|| ⊕ ⊖ ⊞ ⊟ |++| ∪ ∨ ⊔ ± ∓ ∔ ∸ ≏ ⊎ ⊻ ⊽ ⋎ ⋓ ⧺ ⧻ ⨈ ⨢ ⨣ ⨤ ⨥ ⨦ ⨧ ⨨ ⨩ ⨪ ⨫ ⨬ ⨭ ⨮ ⨹ ⨺ ⩁ ⩂ ⩅ ⩊ ⩌ ⩏ ⩐ ⩒ ⩔ ⩖ ⩗ ⩛ ⩝ ⩡ ⩢ ⩣ 还有许多其他的与箭头、比较和幂相关的符号。

diff --git a/dev/base/multi-threading/index.html b/dev/base/multi-threading/index.html index 0efc8e21..aef613c6 100644 --- a/dev/base/multi-threading/index.html +++ b/dev/base/multi-threading/index.html @@ -185,4 +185,4 @@ 7 julia> x[] -5source
Base.Threads.atomic_fenceFunction
Threads.atomic_fence()

Insert a sequential-consistency memory fence

Inserts a memory fence with sequentially-consistent ordering semantics. There are algorithms where this is needed, i.e. where an acquire/release ordering is insufficient.

This is likely a very expensive operation. Given that all other atomic operations in Julia already have acquire/release semantics, explicit fences should not be necessary in most cases.

For further details, see LLVM's fence instruction.

source

ccall using a threadpool (Experimental)

Base.@threadcallMacro
@threadcall((cfunc, clib), rettype, (argtypes...), argvals...)

The @threadcall macro is called in the same way as ccall but does the work in a different thread. This is useful when you want to call a blocking C function without causing the main julia thread to become blocked. Concurrency is limited by size of the libuv thread pool, which defaults to 4 threads but can be increased by setting the UV_THREADPOOL_SIZE environment variable and restarting the julia process.

Note that the called function should never call back into Julia.

source

Low-level synchronization primitives

These building blocks are used to create the regular synchronization objects.

Base.Threads.SpinLockType
SpinLock()

Create a non-reentrant, test-and-test-and-set spin lock. Recursive use will result in a deadlock. This kind of lock should only be used around code that takes little time to execute and does not block (e.g. perform I/O). In general, ReentrantLock should be used instead.

Each lock must be matched with an unlock.

Test-and-test-and-set spin locks are quickest up to about 30ish contending threads. If you have more contention than that, different synchronization approaches should be considered.

source
+5source
Base.Threads.atomic_fenceFunction
Threads.atomic_fence()

Insert a sequential-consistency memory fence

Inserts a memory fence with sequentially-consistent ordering semantics. There are algorithms where this is needed, i.e. where an acquire/release ordering is insufficient.

This is likely a very expensive operation. Given that all other atomic operations in Julia already have acquire/release semantics, explicit fences should not be necessary in most cases.

For further details, see LLVM's fence instruction.

source

ccall using a threadpool (Experimental)

Base.@threadcallMacro
@threadcall((cfunc, clib), rettype, (argtypes...), argvals...)

The @threadcall macro is called in the same way as ccall but does the work in a different thread. This is useful when you want to call a blocking C function without causing the main julia thread to become blocked. Concurrency is limited by size of the libuv thread pool, which defaults to 4 threads but can be increased by setting the UV_THREADPOOL_SIZE environment variable and restarting the julia process.

Note that the called function should never call back into Julia.

source

Low-level synchronization primitives

These building blocks are used to create the regular synchronization objects.

Base.Threads.SpinLockType
SpinLock()

Create a non-reentrant, test-and-test-and-set spin lock. Recursive use will result in a deadlock. This kind of lock should only be used around code that takes little time to execute and does not block (e.g. perform I/O). In general, ReentrantLock should be used instead.

Each lock must be matched with an unlock.

Test-and-test-and-set spin locks are quickest up to about 30ish contending threads. If you have more contention than that, different synchronization approaches should be considered.

source
diff --git a/dev/base/numbers/index.html b/dev/base/numbers/index.html index 1c226d7e..3fbe512b 100644 --- a/dev/base/numbers/index.html +++ b/dev/base/numbers/index.html @@ -297,4 +297,4 @@ 123456 julia> big"7891.5" -7891.5source +7891.5source diff --git a/dev/base/parallel/index.html b/dev/base/parallel/index.html index 1271f25e..37e20ef9 100644 --- a/dev/base/parallel/index.html +++ b/dev/base/parallel/index.html @@ -93,7 +93,7 @@ true julia> istaskdone(b) -truesource

Synchronization

Base.errormonitorFunction
errormonitor(t::Task)

Print an error log to stderr if task t fails.

source
Base.@syncMacro
@sync

Wait until all lexically-enclosed uses of @async, @spawn, @spawnat and @distributed are complete. All exceptions thrown by enclosed async operations are collected and thrown as a CompositeException.

source
Base.waitFunction

Special note for Threads.Condition:

The caller must be holding the lock that owns a Threads.Condition before calling this method. The calling task will be blocked until some other task wakes it, usually by calling notify on the same Threads.Condition object. The lock will be atomically released when blocking (even if it was locked recursively), and will be reacquired before returning.

source
wait([x])

Block the current task until some event occurs, depending on the type of the argument:

  • Channel: Wait for a value to be appended to the channel.
  • Condition: Wait for notify on a condition and return the val parameter passed to notify.
  • Process: Wait for a process or process chain to exit. The exitcode field of a process can be used to determine success or failure.
  • Task: Wait for a Task to finish. If the task fails with an exception, a TaskFailedException (which wraps the failed task) is thrown.
  • RawFD: Wait for changes on a file descriptor (see the FileWatching package).

If no argument is passed, the task blocks for an undefined period. A task can only be restarted by an explicit call to schedule or yieldto.

Often wait is called within a while loop to ensure a waited-for condition is met before proceeding.

source
wait(r::Future)

Wait for a value to become available for the specified Future.

wait(r::RemoteChannel, args...)

Wait for a value to become available on the specified RemoteChannel.

Base.fetchMethod
fetch(t::Task)

Wait for a Task to finish, then return its result value. If the task fails with an exception, a TaskFailedException (which wraps the failed task) is thrown.

source
Base.timedwaitFunction
timedwait(callback::Function, timeout::Real; pollint::Real=0.1)

Waits until callback returns true or timeout seconds have passed, whichever is earlier. callback is polled every pollint seconds. The minimum value for timeout and pollint is 0.001, that is, 1 millisecond.

Returns :ok or :timed_out

source
Base.ConditionType
Condition()

Create an edge-triggered event source that tasks can wait for. Tasks that call wait on a Condition are suspended and queued. Tasks are woken up when notify is later called on the Condition. Edge triggering means that only tasks waiting at the time notify is called can be woken up. For level-triggered notifications, you must keep extra state to keep track of whether a notification has happened. The Channel and Threads.Event types do this, and can be used for level-triggered events.

This object is NOT thread-safe. See Threads.Condition for a thread-safe version.

source
Base.notifyFunction
notify(condition, val=nothing; all=true, error=false)

Wake up tasks waiting for a condition, passing them val. If all is true (the default), all waiting tasks are woken, otherwise only one is. If error is true, the passed value is raised as an exception in the woken tasks.

Return the count of tasks woken up. Return 0 if no tasks are waiting on condition.

source
Base.SemaphoreType
Semaphore(sem_size)

Create a counting semaphore that allows at most sem_size acquires to be in use at any time. Each acquire must be matched with a release.

This provides a acquire & release memory ordering on acquire/release calls.

source
Base.acquireFunction
acquire(s::Semaphore)

Wait for one of the sem_size permits to be available, blocking until one can be acquired.

source
acquire(f, s::Semaphore)

Execute f after acquiring from Semaphore s, and release on completion or error.

For example, a do-block form that ensures only 2 calls of foo will be active at the same time:

s = Base.Semaphore(2)
+true
source

Synchronization

Base.errormonitorFunction
errormonitor(t::Task)

Print an error log to stderr if task t fails.

source
Base.@syncMacro
@sync

Wait until all lexically-enclosed uses of @async, @spawn, @spawnat and @distributed are complete. All exceptions thrown by enclosed async operations are collected and thrown as a CompositeException.

source
Base.waitFunction
wait(r::Future)

Wait for a value to become available for the specified Future.

wait(r::RemoteChannel, args...)

Wait for a value to become available on the specified RemoteChannel.

Special note for Threads.Condition:

The caller must be holding the lock that owns a Threads.Condition before calling this method. The calling task will be blocked until some other task wakes it, usually by calling notify on the same Threads.Condition object. The lock will be atomically released when blocking (even if it was locked recursively), and will be reacquired before returning.

source
wait([x])

Block the current task until some event occurs, depending on the type of the argument:

  • Channel: Wait for a value to be appended to the channel.
  • Condition: Wait for notify on a condition and return the val parameter passed to notify.
  • Process: Wait for a process or process chain to exit. The exitcode field of a process can be used to determine success or failure.
  • Task: Wait for a Task to finish. If the task fails with an exception, a TaskFailedException (which wraps the failed task) is thrown.
  • RawFD: Wait for changes on a file descriptor (see the FileWatching package).

If no argument is passed, the task blocks for an undefined period. A task can only be restarted by an explicit call to schedule or yieldto.

Often wait is called within a while loop to ensure a waited-for condition is met before proceeding.

source
Base.fetchMethod
fetch(t::Task)

Wait for a Task to finish, then return its result value. If the task fails with an exception, a TaskFailedException (which wraps the failed task) is thrown.

source
Base.timedwaitFunction
timedwait(callback::Function, timeout::Real; pollint::Real=0.1)

Waits until callback returns true or timeout seconds have passed, whichever is earlier. callback is polled every pollint seconds. The minimum value for timeout and pollint is 0.001, that is, 1 millisecond.

Returns :ok or :timed_out

source
Base.ConditionType
Condition()

Create an edge-triggered event source that tasks can wait for. Tasks that call wait on a Condition are suspended and queued. Tasks are woken up when notify is later called on the Condition. Edge triggering means that only tasks waiting at the time notify is called can be woken up. For level-triggered notifications, you must keep extra state to keep track of whether a notification has happened. The Channel and Threads.Event types do this, and can be used for level-triggered events.

This object is NOT thread-safe. See Threads.Condition for a thread-safe version.

source
Base.notifyFunction
notify(condition, val=nothing; all=true, error=false)

Wake up tasks waiting for a condition, passing them val. If all is true (the default), all waiting tasks are woken, otherwise only one is. If error is true, the passed value is raised as an exception in the woken tasks.

Return the count of tasks woken up. Return 0 if no tasks are waiting on condition.

source
Base.SemaphoreType
Semaphore(sem_size)

Create a counting semaphore that allows at most sem_size acquires to be in use at any time. Each acquire must be matched with a release.

This provides a acquire & release memory ordering on acquire/release calls.

source
Base.acquireFunction
acquire(s::Semaphore)

Wait for one of the sem_size permits to be available, blocking until one can be acquired.

source
acquire(f, s::Semaphore)

Execute f after acquiring from Semaphore s, and release on completion or error.

For example, a do-block form that ensures only 2 calls of foo will be active at the same time:

s = Base.Semaphore(2)
 @sync for _ in 1:100
     Threads.@spawn begin
         Base.acquire(s) do
@@ -168,4 +168,4 @@
 Stacktrace:
 [...]
     nested task error: foo
-[...]
source
+[...]source diff --git a/dev/base/punctuation/index.html b/dev/base/punctuation/index.html index 2ae06994..df7a3b72 100644 --- a/dev/base/punctuation/index.html +++ b/dev/base/punctuation/index.html @@ -6,4 +6,4 @@ ga('create', 'UA-28835595-9', 'auto'); ga('send', 'pageview', {'page': location.pathname + location.search + location.hash}); -

运算符与记号

数学符号与函数的扩展文档在 这里.

符号含义
@the at-sign marks a macro invocation; optionally followed by an argument list
!感叹号是一个表示逻辑否定的前缀算符
a!在函数名的末尾,! 用作表示函数会修改参数(或多个参数)
#the number sign (or hash or pound) character begins single line comments
#=when followed by an equals sign, it begins a multi-line comment (these are nestable)
=#end a multi-line comment by immediately preceding the number sign with an equals sign
$the dollar sign is used for string and expression interpolation
%the percent symbol is the remainder operator
^the caret is the exponentiation operator
&single ampersand is bitwise and
&&double ampersands is short-circuiting boolean and
|single pipe character is bitwise or
||double pipe characters is short-circuiting boolean or
the unicode xor character is bitwise exclusive or
~the tilde is an operator for bitwise not
'a trailing apostrophe is the adjoint (that is, the complex transpose) operator Aᴴ
*the asterisk is used for multiplication, including matrix multiplication and string concatenation
/forward slash divides the argument on its left by the one on its right
\backslash operator divides the argument on its right by the one on its left, commonly used to solve matrix equations
()parentheses with no arguments constructs an empty Tuple
(a,...)parentheses with comma-separated arguments constructs a tuple containing its arguments
(a=1,...)parentheses with comma-separated assignments constructs a NamedTuple
(x;y)parentheses can also be used to group one or more semicolon separated expressions
a[]array indexing (calling getindex or setindex!)
[,]vector literal constructor (calling vect)
[;]vertical concatenation (calling vcat or hvcat)
[   ]with space-separated expressions, horizontal concatenation (calling hcat or hvcat)
T{ }curly braces following a type list that type's parameters
{}curly braces can also be used to group multiple where expressions in function declarations
;semicolons separate statements, begin a list of keyword arguments in function declarations or calls, or are used to separate array literals for vertical concatenation
,commas separate function arguments or tuple or array components
?the question mark delimits the ternary conditional operator (used like: conditional ? if_true : if_false)
" "the single double-quote character delimits String literals
""" """three double-quote characters delimits string literals that may contain " and ignore leading indentation
' 'the single-quote character delimits Char (that is, character) literals
` `the backtick character delimits external process (Cmd) literals
A...triple periods are a postfix operator that "splat" their arguments' contents into many arguments of a function call or declare a varargs function that "slurps" up many arguments into a single tuple
a.bsingle periods access named fields in objects/modules (calling getproperty or setproperty!)
f.()periods may also prefix parentheses (like f.(...)) or infix operators (like .+) to perform the function element-wise (calling broadcast)
a:bcolons (:) used as a binary infix operator construct a range from a to b (inclusive) with fixed step size 1
a:s:bcolons (:) used as a ternary infix operator construct a range from a to b (inclusive) with step size s
:when used by themselves, Colons represent all indices within a dimension, frequently combined with indexing
::double-colons represent a type annotation or typeassert, depending on context, frequently used when declaring function arguments
:( )quoted expression
:aSymbol a
<:子类型运算符
>:supertype operator (reverse of subtype operator)
=single equals sign is assignment
==double equals sign is value equality comparison
===triple equals sign is programmatically identical equality comparison
=>right arrow using an equals sign defines a Pair typically used to populate dictionaries
->right arrow using a hyphen defines an anonymous function on a single line
`>`
function composition operator (typed with \circ{tab}) combines two functions as though they are a single larger function
+

运算符与记号

数学符号与函数的扩展文档在 这里.

符号含义
@the at-sign marks a macro invocation; optionally followed by an argument list
!感叹号是一个表示逻辑否定的前缀算符
a!在函数名的末尾,! 用作表示函数会修改参数(或多个参数)
#the number sign (or hash or pound) character begins single line comments
#=when followed by an equals sign, it begins a multi-line comment (these are nestable)
=#end a multi-line comment by immediately preceding the number sign with an equals sign
$the dollar sign is used for string and expression interpolation
%the percent symbol is the remainder operator
^the caret is the exponentiation operator
&single ampersand is bitwise and
&&double ampersands is short-circuiting boolean and
|single pipe character is bitwise or
||double pipe characters is short-circuiting boolean or
the unicode xor character is bitwise exclusive or
~the tilde is an operator for bitwise not
'a trailing apostrophe is the adjoint (that is, the complex transpose) operator Aᴴ
*the asterisk is used for multiplication, including matrix multiplication and string concatenation
/forward slash divides the argument on its left by the one on its right
\backslash operator divides the argument on its right by the one on its left, commonly used to solve matrix equations
()parentheses with no arguments constructs an empty Tuple
(a,...)parentheses with comma-separated arguments constructs a tuple containing its arguments
(a=1,...)parentheses with comma-separated assignments constructs a NamedTuple
(x;y)parentheses can also be used to group one or more semicolon separated expressions
a[]array indexing (calling getindex or setindex!)
[,]vector literal constructor (calling vect)
[;]vertical concatenation (calling vcat or hvcat)
[   ]with space-separated expressions, horizontal concatenation (calling hcat or hvcat)
T{ }curly braces following a type list that type's parameters
{}curly braces can also be used to group multiple where expressions in function declarations
;semicolons separate statements, begin a list of keyword arguments in function declarations or calls, or are used to separate array literals for vertical concatenation
,commas separate function arguments or tuple or array components
?the question mark delimits the ternary conditional operator (used like: conditional ? if_true : if_false)
" "the single double-quote character delimits String literals
""" """three double-quote characters delimits string literals that may contain " and ignore leading indentation
' 'the single-quote character delimits Char (that is, character) literals
` `the backtick character delimits external process (Cmd) literals
A...triple periods are a postfix operator that "splat" their arguments' contents into many arguments of a function call or declare a varargs function that "slurps" up many arguments into a single tuple
a.bsingle periods access named fields in objects/modules (calling getproperty or setproperty!)
f.()periods may also prefix parentheses (like f.(...)) or infix operators (like .+) to perform the function element-wise (calling broadcast)
a:bcolons (:) used as a binary infix operator construct a range from a to b (inclusive) with fixed step size 1
a:s:bcolons (:) used as a ternary infix operator construct a range from a to b (inclusive) with step size s
:when used by themselves, Colons represent all indices within a dimension, frequently combined with indexing
::double-colons represent a type annotation or typeassert, depending on context, frequently used when declaring function arguments
:( )quoted expression
:aSymbol a
<:子类型运算符
>:supertype operator (reverse of subtype operator)
=single equals sign is assignment
==double equals sign is value equality comparison
===triple equals sign is programmatically identical equality comparison
=>right arrow using an equals sign defines a Pair typically used to populate dictionaries
->right arrow using a hyphen defines an anonymous function on a single line
`>`
function composition operator (typed with \circ{tab}) combines two functions as though they are a single larger function
diff --git a/dev/base/simd-types/index.html b/dev/base/simd-types/index.html index 764bb23f..e54e615b 100644 --- a/dev/base/simd-types/index.html +++ b/dev/base/simd-types/index.html @@ -19,4 +19,4 @@ triple(c::m128) = add(add(c,c),c) -code_native(triple,(m128,))

然而,因为无法依靠自动向量化,以后将主要通过使用基于 llvmcall 的库来提供 SIMD 支持。

+code_native(triple,(m128,))

然而,因为无法依靠自动向量化,以后将主要通过使用基于 llvmcall 的库来提供 SIMD 支持。

diff --git a/dev/base/sort/index.html b/dev/base/sort/index.html index db2ee394..92d6996b 100644 --- a/dev/base/sort/index.html +++ b/dev/base/sort/index.html @@ -362,4 +362,4 @@ map(x->issorted(x[k2]), (s, ps, qs)) # => (true, false, true) s[1:k] == ps[1:k] # => true s[k2] == qs[k2] # => true

MergeSort 是一个时间复杂度为 O(n log n) 的稳定但是非 in-place 的算法,它需要一个大小为输入数组一般的临时数组——同时也不像 QuickSort 一样快。MergeSort 是非数值型数据的默认排序算法。

默认排序算法的选择是基于它们的快速稳定,或者 appear 之类的。对于数值类型,实际上选择了 QuickSort,因为在这种情况下,它更快,与稳定排序没有区别(除非数组以某种方式记录了突变)

Julia选择默认排序算法的机制是通过 Base.Sort.defalg 来实现的,其允许将特定算法注册为特定数组的所有排序函数中的默认值。例如,这有两个默认算法 sort.jl:

defalg(v::AbstractArray) = MergeSort
-defalg(v::AbstractArray{<:Number}) = QuickSort

对于数值型数组,选择非稳定的默认排序算法的原则是稳定的排序算法没有必要的(例如:但两个值相比较时相等且不可区分时)。

Alternate orderings

By default, sort and related functions use isless to compare two elements in order to determine which should come first. The Base.Order.Ordering abstract type provides a mechanism for defining alternate orderings on the same set of elements. Instances of Ordering define a total order on a set of elements, so that for any elements a, b, c the following hold:

The Base.Order.lt function works as a generalization of isless to test whether a is less than b according to a given order.

Base.Order.OrderingType
Base.Order.Ordering

Abstract type which represents a total order on some set of elements.

Use Base.Order.lt to compare two elements according to the ordering.

source
Base.Order.ltFunction
lt(o::Ordering, a, b)

Test whether a is less than b according to the ordering o.

source
Base.Order.ordFunction
ord(lt, by, rev::Union{Bool, Nothing}, order::Ordering=Forward)

Construct an Ordering object from the same arguments used by sort!. Elements are first transformed by the function by (which may be identity) and are then compared according to either the function lt or an existing ordering order. lt should be isless or a function which obeys similar rules. Finally, the resulting order is reversed if rev=true.

Passing an lt other than isless along with an order other than Base.Order.Forward or Base.Order.Reverse is not permitted, otherwise all options are independent and can be used together in all possible combinations.

source
Base.Order.ForwardConstant
Base.Order.Forward

Default ordering according to isless.

source
Base.Order.ReverseOrderingType
ReverseOrdering(fwd::Ordering=Forward)

A wrapper which reverses an ordering.

For a given Ordering o, the following holds for all a, b:

lt(ReverseOrdering(o), a, b) == lt(o, b, a)
source
Base.Order.ReverseConstant
Base.Order.Reverse

Reverse ordering according to isless.

source
Base.Order.ByType
By(by, order::Ordering=Forward)

Ordering which applies order to elements after they have been transformed by the function by.

source
Base.Order.LtType
Lt(lt)

Ordering which calls lt(a, b) to compare elements. lt should obey the same rules as implementations of isless.

source
Base.Order.PermType
Perm(order::Ordering, data::AbstractVector)

Ordering on the indices of data where i is less than j if data[i] is less than data[j] according to order. In the case that data[i] and data[j] are equal, i and j are compared by numeric value.

source
+defalg(v::AbstractArray{<:Number}) = QuickSort

对于数值型数组,选择非稳定的默认排序算法的原则是稳定的排序算法没有必要的(例如:但两个值相比较时相等且不可区分时)。

Alternate orderings

By default, sort and related functions use isless to compare two elements in order to determine which should come first. The Base.Order.Ordering abstract type provides a mechanism for defining alternate orderings on the same set of elements. Instances of Ordering define a total order on a set of elements, so that for any elements a, b, c the following hold:

The Base.Order.lt function works as a generalization of isless to test whether a is less than b according to a given order.

Base.Order.OrderingType
Base.Order.Ordering

Abstract type which represents a total order on some set of elements.

Use Base.Order.lt to compare two elements according to the ordering.

source
Base.Order.ltFunction
lt(o::Ordering, a, b)

Test whether a is less than b according to the ordering o.

source
Base.Order.ordFunction
ord(lt, by, rev::Union{Bool, Nothing}, order::Ordering=Forward)

Construct an Ordering object from the same arguments used by sort!. Elements are first transformed by the function by (which may be identity) and are then compared according to either the function lt or an existing ordering order. lt should be isless or a function which obeys similar rules. Finally, the resulting order is reversed if rev=true.

Passing an lt other than isless along with an order other than Base.Order.Forward or Base.Order.Reverse is not permitted, otherwise all options are independent and can be used together in all possible combinations.

source
Base.Order.ForwardConstant
Base.Order.Forward

Default ordering according to isless.

source
Base.Order.ReverseOrderingType
ReverseOrdering(fwd::Ordering=Forward)

A wrapper which reverses an ordering.

For a given Ordering o, the following holds for all a, b:

lt(ReverseOrdering(o), a, b) == lt(o, b, a)
source
Base.Order.ReverseConstant
Base.Order.Reverse

Reverse ordering according to isless.

source
Base.Order.ByType
By(by, order::Ordering=Forward)

Ordering which applies order to elements after they have been transformed by the function by.

source
Base.Order.LtType
Lt(lt)

Ordering which calls lt(a, b) to compare elements. lt should obey the same rules as implementations of isless.

source
Base.Order.PermType
Perm(order::Ordering, data::AbstractVector)

Ordering on the indices of data where i is less than j if data[i] is less than data[j] according to order. In the case that data[i] and data[j] are equal, i and j are compared by numeric value.

source
diff --git a/dev/base/stacktraces/index.html b/dev/base/stacktraces/index.html index fad5df1e..b98752f8 100644 --- a/dev/base/stacktraces/index.html +++ b/dev/base/stacktraces/index.html @@ -6,4 +6,4 @@ ga('create', 'UA-28835595-9', 'auto'); ga('send', 'pageview', {'page': location.pathname + location.search + location.hash}); -

堆栈跟踪

Base.StackTraces.StackFrameType
StackFrame

Stack information representing execution context, with the following fields:

  • func::Symbol

    The name of the function containing the execution context.

  • linfo::Union{Core.MethodInstance, CodeInfo, Nothing}

    The MethodInstance containing the execution context (if it could be found).

  • file::Symbol

    The path to the file containing the execution context.

  • line::Int

    The line number in the file containing the execution context.

  • from_c::Bool

    True if the code is from C.

  • inlined::Bool

    True if the code is from an inlined frame.

  • pointer::UInt64

    Representation of the pointer to the execution context as returned by backtrace.

source
Base.StackTraces.stacktraceFunction
stacktrace([trace::Vector{Ptr{Cvoid}},] [c_funcs::Bool=false]) -> StackTrace

Returns a stack trace in the form of a vector of StackFrames. (By default stacktrace doesn't return C functions, but this can be enabled.) When called without specifying a trace, stacktrace first calls backtrace.

source

Base.StackTraces 中以下方法和类型不会被导出,需要显式调用,例如 StackTraces.lookup(ptr)

Base.StackTraces.lookupFunction
lookup(pointer::Ptr{Cvoid}) -> Vector{StackFrame}

Given a pointer to an execution context (usually generated by a call to backtrace), looks up stack frame context information. Returns an array of frame information for all functions inlined at that point, innermost function first.

source
Base.StackTraces.remove_frames!Function
remove_frames!(stack::StackTrace, name::Symbol)

Takes a StackTrace (a vector of StackFrames) and a function name (a Symbol) and removes the StackFrame specified by the function name from the StackTrace (also removing all frames above the specified function). Primarily used to remove StackTraces functions from the StackTrace prior to returning it.

source
remove_frames!(stack::StackTrace, m::Module)

Returns the StackTrace with all StackFrames from the provided Module removed.

source
+

堆栈跟踪

Base.StackTraces.StackFrameType
StackFrame

Stack information representing execution context, with the following fields:

  • func::Symbol

    The name of the function containing the execution context.

  • linfo::Union{Core.MethodInstance, CodeInfo, Nothing}

    The MethodInstance containing the execution context (if it could be found).

  • file::Symbol

    The path to the file containing the execution context.

  • line::Int

    The line number in the file containing the execution context.

  • from_c::Bool

    True if the code is from C.

  • inlined::Bool

    True if the code is from an inlined frame.

  • pointer::UInt64

    Representation of the pointer to the execution context as returned by backtrace.

source
Base.StackTraces.stacktraceFunction
stacktrace([trace::Vector{Ptr{Cvoid}},] [c_funcs::Bool=false]) -> StackTrace

Returns a stack trace in the form of a vector of StackFrames. (By default stacktrace doesn't return C functions, but this can be enabled.) When called without specifying a trace, stacktrace first calls backtrace.

source

Base.StackTraces 中以下方法和类型不会被导出,需要显式调用,例如 StackTraces.lookup(ptr)

Base.StackTraces.lookupFunction
lookup(pointer::Ptr{Cvoid}) -> Vector{StackFrame}

Given a pointer to an execution context (usually generated by a call to backtrace), looks up stack frame context information. Returns an array of frame information for all functions inlined at that point, innermost function first.

source
Base.StackTraces.remove_frames!Function
remove_frames!(stack::StackTrace, name::Symbol)

Takes a StackTrace (a vector of StackFrames) and a function name (a Symbol) and removes the StackFrame specified by the function name from the StackTrace (also removing all frames above the specified function). Primarily used to remove StackTraces functions from the StackTrace prior to returning it.

source
remove_frames!(stack::StackTrace, m::Module)

Returns the StackTrace with all StackFrames from the provided Module removed.

source
diff --git a/dev/base/strings/index.html b/dev/base/strings/index.html index f0a95e48..ce676311 100644 --- a/dev/base/strings/index.html +++ b/dev/base/strings/index.html @@ -546,4 +546,4 @@ "A" julia> unescape_string("aaa \\g \\n", ['g']) # using `keep` argument -"aaa \\g \n"source +"aaa \\g \n"source diff --git a/dev/devdocs/ast/index.html b/dev/devdocs/ast/index.html index 8c21bfee..48d95eda 100644 --- a/dev/devdocs/ast/index.html +++ b/dev/devdocs/ast/index.html @@ -25,4 +25,4 @@ (block (line 2) (return (call + x 1))))

Type definition:

mutable struct Foo{T<:S}
     x::T
 end

parses as:

(struct true (curly Foo (<: T S))
-        (block (line 2) (:: x T)))

The first argument is a boolean telling whether the type is mutable.

try blocks parse as (try try_block var catch_block finally_block). If no variable is present after catch, var is #f. If there is no finally clause, then the last argument is not present.

Quote expressions

Julia source syntax forms for code quoting (quote and :( )) support interpolation with $. In Lisp terminology, this means they are actually "backquote" or "quasiquote" forms. Internally, there is also a need for code quoting without interpolation. In Julia's scheme code, non-interpolating quote is represented with the expression head inert.

inert expressions are converted to Julia QuoteNode objects. These objects wrap a single value of any type, and when evaluated simply return that value.

A quote expression whose argument is an atom also gets converted to a QuoteNode.

Line numbers

Source location information is represented as (line line_num file_name) where the third component is optional (and omitted when the current line number, but not file name, changes).

These expressions are represented as LineNumberNodes in Julia.

Macros

Macro hygiene is represented through the expression head pair escape and hygienic-scope. The result of a macro expansion is automatically wrapped in (hygienic-scope block module), to represent the result of the new scope. The user can insert (escape block) inside to interpolate code from the caller.

Lowered form

Lowered form (IR) is more important to the compiler, since it is used for type inference, optimizations like inlining, and code generation. It is also less obvious to the human, since it results from a significant rearrangement of the input syntax.

In addition to Symbols and some number types, the following data types exist in lowered form:

Expr types

These symbols appear in the head field of Exprs in lowered form.

Method

A unique'd container describing the shared metadata for a single method.

MethodInstance

A unique'd container describing a single callable signature for a Method. See especially Proper maintenance and care of multi-threading locks for important details on how to modify these fields safely.

CodeInstance

CodeInfo

A (usually temporary) container for holding lowered source code.

Optional Fields:

Boolean properties:

+ (block (line 2) (:: x T)))

The first argument is a boolean telling whether the type is mutable.

try blocks parse as (try try_block var catch_block finally_block). If no variable is present after catch, var is #f. If there is no finally clause, then the last argument is not present.

Quote expressions

Julia source syntax forms for code quoting (quote and :( )) support interpolation with $. In Lisp terminology, this means they are actually "backquote" or "quasiquote" forms. Internally, there is also a need for code quoting without interpolation. In Julia's scheme code, non-interpolating quote is represented with the expression head inert.

inert expressions are converted to Julia QuoteNode objects. These objects wrap a single value of any type, and when evaluated simply return that value.

A quote expression whose argument is an atom also gets converted to a QuoteNode.

Line numbers

Source location information is represented as (line line_num file_name) where the third component is optional (and omitted when the current line number, but not file name, changes).

These expressions are represented as LineNumberNodes in Julia.

Macros

Macro hygiene is represented through the expression head pair escape and hygienic-scope. The result of a macro expansion is automatically wrapped in (hygienic-scope block module), to represent the result of the new scope. The user can insert (escape block) inside to interpolate code from the caller.

Lowered form

Lowered form (IR) is more important to the compiler, since it is used for type inference, optimizations like inlining, and code generation. It is also less obvious to the human, since it results from a significant rearrangement of the input syntax.

In addition to Symbols and some number types, the following data types exist in lowered form:

Expr types

These symbols appear in the head field of Exprs in lowered form.

Method

A unique'd container describing the shared metadata for a single method.

MethodInstance

A unique'd container describing a single callable signature for a Method. See especially Proper maintenance and care of multi-threading locks for important details on how to modify these fields safely.

CodeInstance

CodeInfo

A (usually temporary) container for holding lowered source code.

Optional Fields:

Boolean properties:

diff --git a/dev/devdocs/backtraces/index.html b/dev/devdocs/backtraces/index.html index c49abf66..0a485518 100644 --- a/dev/devdocs/backtraces/index.html +++ b/dev/devdocs/backtraces/index.html @@ -13,10 +13,10 @@ Commit 17cfb8e65ea (2023-01-08 06:45 UTC) Platform Info: OS: Linux (x86_64-linux-gnu) - CPU: 2 × Intel(R) Xeon(R) CPU E5-2673 v3 @ 2.40GHz + CPU: 2 × Intel(R) Xeon(R) Platinum 8272CL CPU @ 2.60GHz WORD_SIZE: 64 LIBM: libopenlibm - LLVM: libLLVM-13.0.1 (ORCJIT, haswell) + LLVM: libLLVM-13.0.1 (ORCJIT, skylake-avx512) Threads: 1 on 2 virtual cores

Segfaults during bootstrap (sysimg.jl)

Segfaults toward the end of the make process of building Julia are a common symptom of something going wrong while Julia is preparsing the corpus of code in the base/ folder. Many factors can contribute toward this process dying unexpectedly, however it is as often as not due to an error in the C-code portion of Julia, and as such must typically be debugged with a debug build inside of gdb. Explicitly:

Create a debug build of Julia:

$ cd <julia_root>
 $ make debug

Note that this process will likely fail with the same error as a normal make incantation, however this will create a debug executable that will offer gdb the debugging symbols needed to get accurate backtraces. Next, manually run the bootstrap process inside of gdb:

$ cd base/
 $ gdb -x ../contrib/debug_bootstrap.gdb

This will start gdb, attempt to run the bootstrap process using the debug build of Julia, and print out a backtrace if (when) it segfaults. You may need to hit <enter> a few times to get the full backtrace. Create a gist with the backtrace, the version info, and any other pertinent information you can think of and open a new issue on Github with a link to the gist.

Segfaults when running a script

The procedure is very similar to Segfaults during bootstrap (sysimg.jl). Create a debug build of Julia, and run your script inside of a debugged Julia process:

$ cd <julia_root>
@@ -25,4 +25,4 @@
 Starting program: /home/sabae/src/julia/usr/bin/julia-debug ./test.jl
 ...
 (gdb) bt

Create a gist with the backtrace, the version info, and any other pertinent information you can think of and open a new issue on Github with a link to the gist.

Errors during Julia startup

Occasionally errors occur during Julia's startup process (especially when using binary distributions, as opposed to compiling from source) such as the following:

$ julia
-exec: error -5

These errors typically indicate something is not getting loaded properly very early on in the bootup phase, and our best bet in determining what's going wrong is to use external tools to audit the disk activity of the julia process:

Create a gist with the strace/ dtruss output, the version info, and any other pertinent information and open a new issue on Github with a link to the gist.

Other generic segfaults or unreachables reached

As mentioned elsewhere, julia has good integration with rr for generating traces; this includes, on Linux, the ability to automatically run julia under rr and share the trace after a crash. This can be immensely helpful when debugging such crashes and is strongly encouraged when reporting crash issues to the JuliaLang/julia repo. To run julia under rr automatically, do:

julia --bug-report=rr

To generate the rr trace locally, but not share, you can do:

julia --bug-report=rr-local

Note that this is only works on Linux. The blog post on Time Travelling Bug Reporting has many more details.

Glossary

A few terms have been used as shorthand in this guide:

+exec: error -5

These errors typically indicate something is not getting loaded properly very early on in the bootup phase, and our best bet in determining what's going wrong is to use external tools to audit the disk activity of the julia process:

Create a gist with the strace/ dtruss output, the version info, and any other pertinent information and open a new issue on Github with a link to the gist.

Other generic segfaults or unreachables reached

As mentioned elsewhere, julia has good integration with rr for generating traces; this includes, on Linux, the ability to automatically run julia under rr and share the trace after a crash. This can be immensely helpful when debugging such crashes and is strongly encouraged when reporting crash issues to the JuliaLang/julia repo. To run julia under rr automatically, do:

julia --bug-report=rr

To generate the rr trace locally, but not share, you can do:

julia --bug-report=rr-local

Note that this is only works on Linux. The blog post on Time Travelling Bug Reporting has many more details.

Glossary

A few terms have been used as shorthand in this guide:

diff --git a/dev/devdocs/boundscheck/index.html b/dev/devdocs/boundscheck/index.html index 8ff273bd..3200219b 100644 --- a/dev/devdocs/boundscheck/index.html +++ b/dev/devdocs/boundscheck/index.html @@ -13,4 +13,4 @@ end return r end

使用自定义的类数组类型 MyArray,我们有:

@inline getindex(A::MyArray, i::Real) = (@boundscheck checkbounds(A,i); A.data[to_index(i)])

getindexsum 包裹时,对 checkbounds(A,i) 的调用会被忽略。如果存在多层包裹,最多只有一个 @boundscheck 被忽略。这个规则用来防止将来代码被改变时潜在的多余忽略。

Propagating inbounds

There may be certain scenarios where for code-organization reasons you want more than one layer between the @inbounds and @boundscheck declarations. For instance, the default getindex methods have the chain getindex(A::AbstractArray, i::Real) calls getindex(IndexStyle(A), A, i) calls _getindex(::IndexLinear, A, i).

To override the "one layer of inlining" rule, a function may be marked with Base.@propagate_inbounds to propagate an inbounds context (or out of bounds context) through one additional layer of inlining.

The bounds checking call hierarchy

The overall hierarchy is:

Here A is the array, and I contains the "requested" indices. axes(A) returns a tuple of "permitted" indices of A.

checkbounds(A, I...) throws an error if the indices are invalid, whereas checkbounds(Bool, A, I...) returns false in that circumstance. checkbounds_indices discards any information about the array other than its axes tuple, and performs a pure indices-vs-indices comparison: this allows relatively few compiled methods to serve a huge variety of array types. Indices are specified as tuples, and are usually compared in a 1-1 fashion with individual dimensions handled by calling another important function, checkindex: typically,

checkbounds_indices(Bool, (IA1, IA...), (I1, I...)) = checkindex(Bool, IA1, I1) &
-                                                      checkbounds_indices(Bool, IA, I)

so checkindex checks a single dimension. All of these functions, including the unexported checkbounds_indices have docstrings accessible with ? .

If you have to customize bounds checking for a specific array type, you should specialize checkbounds(Bool, A, I...). However, in most cases you should be able to rely on checkbounds_indices as long as you supply useful axes for your array type.

If you have novel index types, first consider specializing checkindex, which handles a single index for a particular dimension of an array. If you have a custom multidimensional index type (similar to CartesianIndex), then you may have to consider specializing checkbounds_indices.

Note this hierarchy has been designed to reduce the likelihood of method ambiguities. We try to make checkbounds the place to specialize on array type, and try to avoid specializations on index types; conversely, checkindex is intended to be specialized only on index type (especially, the last argument).

Emit bounds checks

Julia can be launched with --check-bounds={yes|no|auto} to emit bounds checks always, never, or respect @inbounds declarations.

+ checkbounds_indices(Bool, IA, I)

so checkindex checks a single dimension. All of these functions, including the unexported checkbounds_indices have docstrings accessible with ? .

If you have to customize bounds checking for a specific array type, you should specialize checkbounds(Bool, A, I...). However, in most cases you should be able to rely on checkbounds_indices as long as you supply useful axes for your array type.

If you have novel index types, first consider specializing checkindex, which handles a single index for a particular dimension of an array. If you have a custom multidimensional index type (similar to CartesianIndex), then you may have to consider specializing checkbounds_indices.

Note this hierarchy has been designed to reduce the likelihood of method ambiguities. We try to make checkbounds the place to specialize on array type, and try to avoid specializations on index types; conversely, checkindex is intended to be specialized only on index type (especially, the last argument).

Emit bounds checks

Julia can be launched with --check-bounds={yes|no|auto} to emit bounds checks always, never, or respect @inbounds declarations.

diff --git a/dev/devdocs/callconv/index.html b/dev/devdocs/callconv/index.html index 620a1371..7138400e 100644 --- a/dev/devdocs/callconv/index.html +++ b/dev/devdocs/callconv/index.html @@ -6,4 +6,4 @@ ga('create', 'UA-28835595-9', 'auto'); ga('send', 'pageview', {'page': location.pathname + location.search + location.hash}); -

Calling Conventions

Julia uses three calling conventions for four distinct purposes:

NamePrefixPurpose
Nativejulia_Speed via specialized signatures
JL Calljlcall_Wrapper for generic calls
JL Calljl_Builtins
C ABIjlcapi_Wrapper callable from C

Julia Native Calling Convention

The native calling convention is designed for fast non-generic calls. It usually uses a specialized signature.

  • LLVM ghosts (zero-length types) are omitted.
  • LLVM scalars and vectors are passed by value.
  • LLVM aggregates (arrays and structs) are passed by reference.

A small return values is returned as LLVM return values. A large return values is returned via the "structure return" (sret) convention, where the caller provides a pointer to a return slot.

An argument or return values that is a homogeneous tuple is sometimes represented as an LLVM vector instead of an LLVM array.

JL Call Convention

The JL Call convention is for builtins and generic dispatch. Hand-written functions using this convention are declared via the macro JL_CALLABLE. The convention uses exactly 3 parameters:

  • F - Julia representation of function that is being applied
  • args - pointer to array of pointers to boxes
  • nargs - length of the array

The return value is a pointer to a box.

C ABI

C ABI wrappers enable calling Julia from C. The wrapper calls a function using the native calling convention.

Tuples are always represented as C arrays.

+

Calling Conventions

Julia uses three calling conventions for four distinct purposes:

NamePrefixPurpose
Nativejulia_Speed via specialized signatures
JL Calljlcall_Wrapper for generic calls
JL Calljl_Builtins
C ABIjlcapi_Wrapper callable from C

Julia Native Calling Convention

The native calling convention is designed for fast non-generic calls. It usually uses a specialized signature.

  • LLVM ghosts (zero-length types) are omitted.
  • LLVM scalars and vectors are passed by value.
  • LLVM aggregates (arrays and structs) are passed by reference.

A small return values is returned as LLVM return values. A large return values is returned via the "structure return" (sret) convention, where the caller provides a pointer to a return slot.

An argument or return values that is a homogeneous tuple is sometimes represented as an LLVM vector instead of an LLVM array.

JL Call Convention

The JL Call convention is for builtins and generic dispatch. Hand-written functions using this convention are declared via the macro JL_CALLABLE. The convention uses exactly 3 parameters:

  • F - Julia representation of function that is being applied
  • args - pointer to array of pointers to boxes
  • nargs - length of the array

The return value is a pointer to a box.

C ABI

C ABI wrappers enable calling Julia from C. The wrapper calls a function using the native calling convention.

Tuples are always represented as C arrays.

diff --git a/dev/devdocs/cartesian/index.html b/dev/devdocs/cartesian/index.html index 5a935b85..6736116e 100644 --- a/dev/devdocs/cartesian/index.html +++ b/dev/devdocs/cartesian/index.html @@ -55,4 +55,4 @@ error("Dimension ", 2, " too big") else println("All OK") -endsource +endsource diff --git a/dev/devdocs/compiler/index.html b/dev/devdocs/compiler/index.html index bc7ad2c4..8c69a26f 100644 --- a/dev/devdocs/compiler/index.html +++ b/dev/devdocs/compiler/index.html @@ -6,4 +6,4 @@ ga('create', 'UA-28835595-9', 'auto'); ga('send', 'pageview', {'page': location.pathname + location.search + location.hash}); -

本机代码生成过程的高级概述

指针的表示

When emitting code to an object file, pointers will be emitted as relocations. The deserialization code will ensure any object that pointed to one of these constants gets recreated and contains the right runtime pointer.

Otherwise, they will be emitted as literal constants.

To emit one of these objects, call literal_pointer_val. It'll handle tracking the Julia value and the LLVM global, ensuring they are valid both for the current runtime and after deserialization.

When emitted into the object file, these globals are stored as references in a large gvals table. This allows the deserializer to reference them by index, and implement a custom manual mechanism similar to a Global Offset Table (GOT) to restore them.

Function pointers are handled similarly. They are stored as values in a large fvals table. Like globals, this allows the deserializer to reference them by index.

Note that extern functions are handled separately, with names, via the usual symbol resolution mechanism in the linker.

Note too that ccall functions are also handled separately, via a manual GOT and Procedure Linkage Table (PLT).

Representation of Intermediate Values

Values are passed around in a jl_cgval_t struct. This represents an R-value, and includes enough information to determine how to assign or pass it somewhere.

They are created via one of the helper constructors, usually: mark_julia_type (for immediate values) and mark_julia_slot (for pointers to values).

The function convert_julia_type can transform between any two types. It returns an R-value with cgval.typ set to typ. It'll cast the object to the requested representation, making heap boxes, allocating stack copies, and computing tagged unions as needed to change the representation.

By contrast update_julia_type will change cgval.typ to typ, only if it can be done at zero-cost (i.e. without emitting any code).

Union representation

Inferred union types may be stack allocated via a tagged type representation.

The primitive routines that need to be able to handle tagged unions are:

  • mark-type
  • load-local
  • store-local
  • isa
  • is
  • emit_typeof
  • emit_sizeof
  • boxed
  • unbox
  • specialized cc-ret

Everything else should be possible to handle in inference by using these primitives to implement union-splitting.

The representation of the tagged-union is as a pair of < void* union, byte selector >. The selector is fixed-size as byte & 0x7f, and will union-tag the first 126 isbits. It records the one-based depth-first count into the type-union of the isbits objects inside. An index of zero indicates that the union* is actually a tagged heap-allocated jl_value_t*, and needs to be treated as normal for a boxed object rather than as a tagged union.

The high bit of the selector (byte & 0x80) can be tested to determine if the void* is actually a heap-allocated (jl_value_t*) box, thus avoiding the cost of re-allocating a box, while maintaining the ability to efficiently handle union-splitting based on the low bits.

It is guaranteed that byte & 0x7f is an exact test for the type, if the value can be represented by a tag – it will never be marked byte = 0x80. It is not necessary to also test the type-tag when testing isa.

The union* memory region may be allocated at any size. The only constraint is that it is big enough to contain the data currently specified by selector. It might not be big enough to contain the union of all types that could be stored there according to the associated Union type field. Use appropriate care when copying.

Specialized Calling Convention Signature Representation

A jl_returninfo_t object describes the calling convention details of any callable.

If any of the arguments or return type of a method can be represented unboxed, and the method is not varargs, it'll be given an optimized calling convention signature based on its specTypes and rettype fields.

The general principles are that:

  • Primitive types get passed in int/float registers.
  • Tuples of VecElement types get passed in vector registers.
  • Structs get passed on the stack.
  • Return values are handle similarly to arguments, with a size-cutoff at which they will instead be returned via a hidden sret argument.

The total logic for this is implemented by get_specsig_function and deserves_sret.

Additionally, if the return type is a union, it may be returned as a pair of values (a pointer and a tag). If the union values can be stack-allocated, then sufficient space to store them will also be passed as a hidden first argument. It is up to the callee whether the returned pointer will point to this space, a boxed object, or even other constant memory.

+

本机代码生成过程的高级概述

指针的表示

When emitting code to an object file, pointers will be emitted as relocations. The deserialization code will ensure any object that pointed to one of these constants gets recreated and contains the right runtime pointer.

Otherwise, they will be emitted as literal constants.

To emit one of these objects, call literal_pointer_val. It'll handle tracking the Julia value and the LLVM global, ensuring they are valid both for the current runtime and after deserialization.

When emitted into the object file, these globals are stored as references in a large gvals table. This allows the deserializer to reference them by index, and implement a custom manual mechanism similar to a Global Offset Table (GOT) to restore them.

Function pointers are handled similarly. They are stored as values in a large fvals table. Like globals, this allows the deserializer to reference them by index.

Note that extern functions are handled separately, with names, via the usual symbol resolution mechanism in the linker.

Note too that ccall functions are also handled separately, via a manual GOT and Procedure Linkage Table (PLT).

Representation of Intermediate Values

Values are passed around in a jl_cgval_t struct. This represents an R-value, and includes enough information to determine how to assign or pass it somewhere.

They are created via one of the helper constructors, usually: mark_julia_type (for immediate values) and mark_julia_slot (for pointers to values).

The function convert_julia_type can transform between any two types. It returns an R-value with cgval.typ set to typ. It'll cast the object to the requested representation, making heap boxes, allocating stack copies, and computing tagged unions as needed to change the representation.

By contrast update_julia_type will change cgval.typ to typ, only if it can be done at zero-cost (i.e. without emitting any code).

Union representation

Inferred union types may be stack allocated via a tagged type representation.

The primitive routines that need to be able to handle tagged unions are:

  • mark-type
  • load-local
  • store-local
  • isa
  • is
  • emit_typeof
  • emit_sizeof
  • boxed
  • unbox
  • specialized cc-ret

Everything else should be possible to handle in inference by using these primitives to implement union-splitting.

The representation of the tagged-union is as a pair of < void* union, byte selector >. The selector is fixed-size as byte & 0x7f, and will union-tag the first 126 isbits. It records the one-based depth-first count into the type-union of the isbits objects inside. An index of zero indicates that the union* is actually a tagged heap-allocated jl_value_t*, and needs to be treated as normal for a boxed object rather than as a tagged union.

The high bit of the selector (byte & 0x80) can be tested to determine if the void* is actually a heap-allocated (jl_value_t*) box, thus avoiding the cost of re-allocating a box, while maintaining the ability to efficiently handle union-splitting based on the low bits.

It is guaranteed that byte & 0x7f is an exact test for the type, if the value can be represented by a tag – it will never be marked byte = 0x80. It is not necessary to also test the type-tag when testing isa.

The union* memory region may be allocated at any size. The only constraint is that it is big enough to contain the data currently specified by selector. It might not be big enough to contain the union of all types that could be stored there according to the associated Union type field. Use appropriate care when copying.

Specialized Calling Convention Signature Representation

A jl_returninfo_t object describes the calling convention details of any callable.

If any of the arguments or return type of a method can be represented unboxed, and the method is not varargs, it'll be given an optimized calling convention signature based on its specTypes and rettype fields.

The general principles are that:

  • Primitive types get passed in int/float registers.
  • Tuples of VecElement types get passed in vector registers.
  • Structs get passed on the stack.
  • Return values are handle similarly to arguments, with a size-cutoff at which they will instead be returned via a hidden sret argument.

The total logic for this is implemented by get_specsig_function and deserves_sret.

Additionally, if the return type is a union, it may be returned as a pair of values (a pointer and a tag). If the union values can be stack-allocated, then sufficient space to store them will also be passed as a hidden first argument. It is up to the callee whether the returned pointer will point to this space, a boxed object, or even other constant memory.

diff --git a/dev/devdocs/debuggingtips/index.html b/dev/devdocs/debuggingtips/index.html index 165b427e..996b430c 100644 --- a/dev/devdocs/debuggingtips/index.html +++ b/dev/devdocs/debuggingtips/index.html @@ -32,4 +32,4 @@ Expr(:return, Expr(:call, :box, :Float32, Expr(:call, :fptrunc, :Float32, :x)::Any)::Any)::Any)::Any)::Any

Finally, and perhaps most usefully, we can force the function to be recompiled in order to step through the codegen process. To do this, clear the cached functionObject from the jl_lamdbda_info_t*:

(gdb) p f->linfo->functionObject
 $8 = (void *) 0x1289d070
 (gdb) set f->linfo->functionObject = NULL

Then, set a breakpoint somewhere useful (e.g. emit_function, emit_expr, emit_call, etc.), and run codegen:

(gdb) p jl_compile(f)
-... # your breakpoint here

Debugging precompilation errors

Module precompilation spawns a separate Julia process to precompile each module. Setting a breakpoint or catching failures in a precompile worker requires attaching a debugger to the worker. The easiest approach is to set the debugger watch for new process launches matching a given name. For example:

(gdb) attach -w -n julia-debug

or:

(lldb) process attach -w -n julia-debug

Then run a script/command to start precompilation. As described earlier, use conditional breakpoints in the parent process to catch specific file-loading events and narrow the debugging window. (some operating systems may require alternative approaches, such as following each fork from the parent process)

Mozilla's Record and Replay Framework (rr)

Julia now works out of the box with rr, the lightweight recording and deterministic debugging framework from Mozilla. This allows you to replay the trace of an execution deterministically. The replayed execution's address spaces, register contents, syscall data etc are exactly the same in every run.

A recent version of rr (3.1.0 or higher) is required.

Reproducing concurrency bugs with rr

rr simulates a single-threaded machine by default. In order to debug concurrent code you can use rr record --chaos which will cause rr to simulate between one to eight cores, chosen randomly. You might therefore want to set JULIA_NUM_THREADS=8 and rerun your code under rr until you have caught your bug.

+... # your breakpoint here

Debugging precompilation errors

Module precompilation spawns a separate Julia process to precompile each module. Setting a breakpoint or catching failures in a precompile worker requires attaching a debugger to the worker. The easiest approach is to set the debugger watch for new process launches matching a given name. For example:

(gdb) attach -w -n julia-debug

or:

(lldb) process attach -w -n julia-debug

Then run a script/command to start precompilation. As described earlier, use conditional breakpoints in the parent process to catch specific file-loading events and narrow the debugging window. (some operating systems may require alternative approaches, such as following each fork from the parent process)

Mozilla's Record and Replay Framework (rr)

Julia now works out of the box with rr, the lightweight recording and deterministic debugging framework from Mozilla. This allows you to replay the trace of an execution deterministically. The replayed execution's address spaces, register contents, syscall data etc are exactly the same in every run.

A recent version of rr (3.1.0 or higher) is required.

Reproducing concurrency bugs with rr

rr simulates a single-threaded machine by default. In order to debug concurrent code you can use rr record --chaos which will cause rr to simulate between one to eight cores, chosen randomly. You might therefore want to set JULIA_NUM_THREADS=8 and rerun your code under rr until you have caught your bug.

diff --git a/dev/devdocs/eval/index.html b/dev/devdocs/eval/index.html index e6db3d26..c1be3a9d 100644 --- a/dev/devdocs/eval/index.html +++ b/dev/devdocs/eval/index.html @@ -9,4 +9,4 @@

Julia 代码的 eval

学习 Julia 语言如何运行代码的最难的一部分是 学习如何让所有的小部分工作协同工作来执行一段代码。

每个代码块通常会通过许多步骤来执行,在转变为期望的结果之前(但愿如此)。并且你可能不熟悉它们的名称,例如(非特定顺序): flisp,AST,C++,LLVM,evaltypeinfmacroexpand,sysimg(或 system image),启动,变异,解析,执行,即时编译器,解释器解释,装箱,拆箱,内部函数,原始函数

Definitions
  • REPL

    REPL 表示 读取-求值-输出-循环(Read-Eval-Print Loop)。 我们管这个命令行环境的简称就叫REPL。

  • AST

    抽象语法树(Abstract Syntax Tree)是代码结构的数据表现。在这种表现形式下代码被符号化,因此更加方便操作和执行。

Julia Execution

整个进程的千里之行如下:

  1. 用户打开了 julia
  2. The C function main() from cli/loader_exe.c gets called. This function processes the command line arguments, filling in the jl_options struct and setting the variable ARGS. It then initializes 在 ui/repl.c 中的 C 语言的函数 main() 被调用。这个函数处理命令行参数,填充到 jl_options 结构图并且设置变了 ARGS 。接下来初始化 Julia (通过调用 julia_init in task.c which may load a previously compiled sysimg). Finally, it passes off control to Julia by calling Base._start().
  3. When _start() takes over control, the subsequent sequence of commands depends on the command line arguments given. For example, if a filename was supplied, it will proceed to execute that file. Otherwise, it will start an interactive REPL.
  4. Skipping the details about how the REPL interacts with the user, let's just say the program ends up with a block of code that it wants to run.
  5. If the block of code to run is in a file, jl_load(char *filename) gets invoked to load the file and parse it. Each fragment of code is then passed to eval to execute.
  6. Each fragment of code (or AST), is handed off to eval() to turn into results.
  7. eval() takes each code fragment and tries to run it in jl_toplevel_eval_flex().
  8. jl_toplevel_eval_flex() decides whether the code is a "toplevel" action (such as using or module), which would be invalid inside a function. If so, it passes off the code to the toplevel interpreter.
  9. jl_toplevel_eval_flex() then expands the code to eliminate any macros and to "lower" the AST to make it simpler to execute.
  10. jl_toplevel_eval_flex() then uses some simple heuristics to decide whether to JIT compiler the AST or to interpret it directly.
  11. The bulk of the work to interpret code is handled by eval in interpreter.c.
  12. If instead, the code is compiled, the bulk of the work is handled by codegen.cpp. Whenever a Julia function is called for the first time with a given set of argument types, type inference will be run on that function. This information is used by the codegen step to generate faster code.
  13. Eventually, the user quits the REPL, or the end of the program is reached, and the _start() method returns.
  14. Just before exiting, main() calls jl_atexit_hook(exit_code). This calls Base._atexit() (which calls any functions registered to atexit() inside Julia). Then it calls jl_gc_run_all_finalizers(). Finally, it gracefully cleans up all libuv handles and waits for them to flush and close.

Parsing

The Julia parser is a small lisp program written in femtolisp, the source-code for which is distributed inside Julia in src/flisp.

The interface functions for this are primarily defined in jlfrontend.scm. The code in ast.c handles this handoff on the Julia side.

The other relevant files at this stage are julia-parser.scm, which handles tokenizing Julia code and turning it into an AST, and julia-syntax.scm, which handles transforming complex AST representations into simpler, "lowered" AST representations which are more suitable for analysis and execution.

If you want to test the parser without re-building Julia in its entirety, you can run the frontend on its own as follows:

$ cd src
 $ flisp/flisp
 > (load "jlfrontend.scm")
-> (jl-parse-file "<filename>")

Macro Expansion

When eval() encounters a macro, it expands that AST node before attempting to evaluate the expression. Macro expansion involves a handoff from eval() (in Julia), to the parser function jl_macroexpand() (written in flisp) to the Julia macro itself (written in - what else - Julia) via fl_invoke_julia_macro(), and back.

Typically, macro expansion is invoked as a first step during a call to Meta.lower()/jl_expand(), although it can also be invoked directly by a call to macroexpand()/jl_macroexpand().

Type Inference

Type inference is implemented in Julia by typeinf() in compiler/typeinfer.jl. Type inference is the process of examining a Julia function and determining bounds for the types of each of its variables, as well as bounds on the type of the return value from the function. This enables many future optimizations, such as unboxing of known immutable values, and compile-time hoisting of various run-time operations such as computing field offsets and function pointers. Type inference may also include other steps such as constant propagation and inlining.

More Definitions
  • JIT

    Just-In-Time Compilation The process of generating native-machine code into memory right when it is needed.

  • LLVM

    Low-Level Virtual Machine (a compiler) The Julia JIT compiler is a program/library called libLLVM. Codegen in Julia refers both to the process of taking a Julia AST and turning it into LLVM instructions, and the process of LLVM optimizing that and turning it into native assembly instructions.

  • C++

    The programming language that LLVM is implemented in, which means that codegen is also implemented in this language. The rest of Julia's library is implemented in C, in part because its smaller feature set makes it more usable as a cross-language interface layer.

  • box

    This term is used to describe the process of taking a value and allocating a wrapper around the data that is tracked by the garbage collector (gc) and is tagged with the object's type.

  • unbox

    The reverse of boxing a value. This operation enables more efficient manipulation of data when the type of that data is fully known at compile-time (through type inference).

  • generic function

    A Julia function composed of multiple "methods" that are selected for dynamic dispatch based on the argument type-signature

  • anonymous function or "method"

    A Julia function without a name and without type-dispatch capabilities

  • primitive function

    A function implemented in C but exposed in Julia as a named function "method" (albeit without generic function dispatch capabilities, similar to a anonymous function)

  • intrinsic function

    A low-level operation exposed as a function in Julia. These pseudo-functions implement operations on raw bits such as add and sign extend that cannot be expressed directly in any other way. Since they operate on bits directly, they must be compiled into a function and surrounded by a call to Core.Intrinsics.box(T, ...) to reassign type information to the value.

JIT Code Generation

Codegen is the process of turning a Julia AST into native machine code.

The JIT environment is initialized by an early call to jl_init_codegen in codegen.cpp.

On demand, a Julia method is converted into a native function by the function emit_function(jl_method_instance_t*). (note, when using the MCJIT (in LLVM v3.4+), each function must be JIT into a new module.) This function recursively calls emit_expr() until the entire function has been emitted.

Much of the remaining bulk of this file is devoted to various manual optimizations of specific code patterns. For example, emit_known_call() knows how to inline many of the primitive functions (defined in builtins.c) for various combinations of argument types.

Other parts of codegen are handled by various helper files:

  • debuginfo.cpp

    Handles backtraces for JIT functions

  • ccall.cpp

    Handles the ccall and llvmcall FFI, along with various abi_*.cpp files

  • intrinsics.cpp

    Handles the emission of various low-level intrinsic functions

Bootstrapping

The process of creating a new system image is called "bootstrapping".

The etymology of this word comes from the phrase "pulling oneself up by the bootstraps", and refers to the idea of starting from a very limited set of available functions and definitions and ending with the creation of a full-featured environment.

System Image

The system image is a precompiled archive of a set of Julia files. The sys.ji file distributed with Julia is one such system image, generated by executing the file sysimg.jl, and serializing the resulting environment (including Types, Functions, Modules, and all other defined values) into a file. Therefore, it contains a frozen version of the Main, Core, and Base modules (and whatever else was in the environment at the end of bootstrapping). This serializer/deserializer is implemented by jl_save_system_image/jl_restore_system_image in staticdata.c.

If there is no sysimg file (jl_options.image_file == NULL), this also implies that --build was given on the command line, so the final result should be a new sysimg file. During Julia initialization, minimal Core and Main modules are created. Then a file named boot.jl is evaluated from the current directory. Julia then evaluates any file given as a command line argument until it reaches the end. Finally, it saves the resulting environment to a "sysimg" file for use as a starting point for a future Julia run.

+> (jl-parse-file "<filename>")

Macro Expansion

When eval() encounters a macro, it expands that AST node before attempting to evaluate the expression. Macro expansion involves a handoff from eval() (in Julia), to the parser function jl_macroexpand() (written in flisp) to the Julia macro itself (written in - what else - Julia) via fl_invoke_julia_macro(), and back.

Typically, macro expansion is invoked as a first step during a call to Meta.lower()/jl_expand(), although it can also be invoked directly by a call to macroexpand()/jl_macroexpand().

Type Inference

Type inference is implemented in Julia by typeinf() in compiler/typeinfer.jl. Type inference is the process of examining a Julia function and determining bounds for the types of each of its variables, as well as bounds on the type of the return value from the function. This enables many future optimizations, such as unboxing of known immutable values, and compile-time hoisting of various run-time operations such as computing field offsets and function pointers. Type inference may also include other steps such as constant propagation and inlining.

More Definitions
  • JIT

    Just-In-Time Compilation The process of generating native-machine code into memory right when it is needed.

  • LLVM

    Low-Level Virtual Machine (a compiler) The Julia JIT compiler is a program/library called libLLVM. Codegen in Julia refers both to the process of taking a Julia AST and turning it into LLVM instructions, and the process of LLVM optimizing that and turning it into native assembly instructions.

  • C++

    The programming language that LLVM is implemented in, which means that codegen is also implemented in this language. The rest of Julia's library is implemented in C, in part because its smaller feature set makes it more usable as a cross-language interface layer.

  • box

    This term is used to describe the process of taking a value and allocating a wrapper around the data that is tracked by the garbage collector (gc) and is tagged with the object's type.

  • unbox

    The reverse of boxing a value. This operation enables more efficient manipulation of data when the type of that data is fully known at compile-time (through type inference).

  • generic function

    A Julia function composed of multiple "methods" that are selected for dynamic dispatch based on the argument type-signature

  • anonymous function or "method"

    A Julia function without a name and without type-dispatch capabilities

  • primitive function

    A function implemented in C but exposed in Julia as a named function "method" (albeit without generic function dispatch capabilities, similar to a anonymous function)

  • intrinsic function

    A low-level operation exposed as a function in Julia. These pseudo-functions implement operations on raw bits such as add and sign extend that cannot be expressed directly in any other way. Since they operate on bits directly, they must be compiled into a function and surrounded by a call to Core.Intrinsics.box(T, ...) to reassign type information to the value.

JIT Code Generation

Codegen is the process of turning a Julia AST into native machine code.

The JIT environment is initialized by an early call to jl_init_codegen in codegen.cpp.

On demand, a Julia method is converted into a native function by the function emit_function(jl_method_instance_t*). (note, when using the MCJIT (in LLVM v3.4+), each function must be JIT into a new module.) This function recursively calls emit_expr() until the entire function has been emitted.

Much of the remaining bulk of this file is devoted to various manual optimizations of specific code patterns. For example, emit_known_call() knows how to inline many of the primitive functions (defined in builtins.c) for various combinations of argument types.

Other parts of codegen are handled by various helper files:

Bootstrapping

The process of creating a new system image is called "bootstrapping".

The etymology of this word comes from the phrase "pulling oneself up by the bootstraps", and refers to the idea of starting from a very limited set of available functions and definitions and ending with the creation of a full-featured environment.

System Image

The system image is a precompiled archive of a set of Julia files. The sys.ji file distributed with Julia is one such system image, generated by executing the file sysimg.jl, and serializing the resulting environment (including Types, Functions, Modules, and all other defined values) into a file. Therefore, it contains a frozen version of the Main, Core, and Base modules (and whatever else was in the environment at the end of bootstrapping). This serializer/deserializer is implemented by jl_save_system_image/jl_restore_system_image in staticdata.c.

If there is no sysimg file (jl_options.image_file == NULL), this also implies that --build was given on the command line, so the final result should be a new sysimg file. During Julia initialization, minimal Core and Main modules are created. Then a file named boot.jl is evaluated from the current directory. Julia then evaluates any file given as a command line argument until it reaches the end. Finally, it saves the resulting environment to a "sysimg" file for use as a starting point for a future Julia run.

diff --git a/dev/devdocs/functions/index.html b/dev/devdocs/functions/index.html index 1a4e6a23..d238693e 100644 --- a/dev/devdocs/functions/index.html +++ b/dev/devdocs/functions/index.html @@ -39,4 +39,4 @@ # unless `options` is empty #circle#1(color, fill, pairs(options), circle, center, radius) -end

函数 Core.kwftype(t) 创建字段 t.name.mt.kwsorter(如果它未被创建),并返回该函数的类型。

此设计的特点是不使用关键字参数的调用点不需要特殊处理;这一切的工作方式好像它们根本不是语言的一部分。不使用关键字参数的调用点直接派发到被调用函数的 kwsorter。例如,调用:

circle((0,0), 1.0, color = red; other...)

降低为:

kwfunc(circle)(merge((color = red,), other), circle, (0,0), 1.0)

kwfunc(也在 Core 中)可获取被调用函数的 kwsorter。关键字 splatting 函数(编写为 other...)调用具名元组 merge 函数。此函数进一步解包了 other 的每个元素,预期中每个元素包含两个值(一个符号和一个值)。当然,如果所有 splatted 参数都是具名元组,则可使用更高效的实现。请注意,原来的 circle 被传递,以处理闭包。

Compiler efficiency issues

为每个函数生成新类型在与 Julia 的「默认专门化所有参数」这一设计理念结合使用时,可能对编译器资源的使用产生严重后果。实际上,此设计的初始实现经历了更长的测试和构造时间、高内存占用以及比基线大近乎 2 倍的系统镜像。在一个幼稚的实现中,该问题非常严重,以至于系统几乎无法使用。需要进行几项重要的优化才能使设计变得可行。

第一个问题是函数值参数的不同值导致函数的过度专门化。许多函数只是将参数「传递」到其它地方,例如,到另一个函数或存储位置。这种函数不需要为每个可能传入的闭包专门化。幸运的是,这种情况很容易区分,只需考虑函数是否调用它的某个参数(即,参数出现在某处的「头部位置」)。性能关键的高阶函数,如 map,肯定会直接调用它们的参数函数,因此仍然会按预期进行专门化。此优化通过在前端记录 analyze-variables 传递期间所调用的参数来实现。当 cache_method 看到某个在 Function 类型层次结构的参数传递到声明为 AnyFunction 的槽时,它的行为就好像应用了 @nospecialize 注释一样。这种启发式方法在实践中似乎非常有效。

下一个问题涉及方法缓存哈希表的结构。经验研究表明,绝大多数动态分派调用只涉及一个或两个元素。反过来看,只考虑第一个元素便可解决许多这些情况。(旁白:单派发的支持者根本不会对此感到惊讶。但是,这个观点意味着「多重派发在实践中很容易优化」,因此我们应该使用它,而不是「我们应该使用单派发」!)因此,方法缓存使用第一个参数作为其主键。但请注意,这对应于函数调用的元组类型的第二个元素(第一个元素是函数本身的类型)。通常,头部位置的类型非常少变化——实际上,大多数函数属于没有参数的单态类型。但是,构造函数不是这种情况,一个方法表便保存了所有类型的构造函数。因此,Type 方法表是特殊的,使用元组类型的第一个元素而不是第二个。

前端为所有闭包生成类型声明。起初,这通过生成通常的类型声明来实现。但是,这产生了大量的构造函数,这些构造函数全都很简单(只是将所有参数传递给 new)。因为方法是部分排序的,所以插入所有这些方法是 O(n^2),此外要保留的方法实在太多了。这可通过直接生成 struct_type 表达式(绕过默认的构造函数生成)并直接使用 new 来创建闭包的实例来优化。这事并不漂亮,但你需要做你该做的。

下个问题是 @test 宏,它为每个测试用例生成一个 0 参数闭包。这不是必需的,因为每个用例只需运行一次。因此,@test 被改写以展开到一个 try-catch 块中,该块记录测试结果(true、false 或所引发的异常)并对它调用测试套件处理程序。

+end

函数 Core.kwftype(t) 创建字段 t.name.mt.kwsorter(如果它未被创建),并返回该函数的类型。

此设计的特点是不使用关键字参数的调用点不需要特殊处理;这一切的工作方式好像它们根本不是语言的一部分。不使用关键字参数的调用点直接派发到被调用函数的 kwsorter。例如,调用:

circle((0,0), 1.0, color = red; other...)

降低为:

kwfunc(circle)(merge((color = red,), other), circle, (0,0), 1.0)

kwfunc(也在 Core 中)可获取被调用函数的 kwsorter。关键字 splatting 函数(编写为 other...)调用具名元组 merge 函数。此函数进一步解包了 other 的每个元素,预期中每个元素包含两个值(一个符号和一个值)。当然,如果所有 splatted 参数都是具名元组,则可使用更高效的实现。请注意,原来的 circle 被传递,以处理闭包。

Compiler efficiency issues

为每个函数生成新类型在与 Julia 的「默认专门化所有参数」这一设计理念结合使用时,可能对编译器资源的使用产生严重后果。实际上,此设计的初始实现经历了更长的测试和构造时间、高内存占用以及比基线大近乎 2 倍的系统镜像。在一个幼稚的实现中,该问题非常严重,以至于系统几乎无法使用。需要进行几项重要的优化才能使设计变得可行。

第一个问题是函数值参数的不同值导致函数的过度专门化。许多函数只是将参数「传递」到其它地方,例如,到另一个函数或存储位置。这种函数不需要为每个可能传入的闭包专门化。幸运的是,这种情况很容易区分,只需考虑函数是否调用它的某个参数(即,参数出现在某处的「头部位置」)。性能关键的高阶函数,如 map,肯定会直接调用它们的参数函数,因此仍然会按预期进行专门化。此优化通过在前端记录 analyze-variables 传递期间所调用的参数来实现。当 cache_method 看到某个在 Function 类型层次结构的参数传递到声明为 AnyFunction 的槽时,它的行为就好像应用了 @nospecialize 注释一样。这种启发式方法在实践中似乎非常有效。

下一个问题涉及方法缓存哈希表的结构。经验研究表明,绝大多数动态分派调用只涉及一个或两个元素。反过来看,只考虑第一个元素便可解决许多这些情况。(旁白:单派发的支持者根本不会对此感到惊讶。但是,这个观点意味着「多重派发在实践中很容易优化」,因此我们应该使用它,而不是「我们应该使用单派发」!)因此,方法缓存使用第一个参数作为其主键。但请注意,这对应于函数调用的元组类型的第二个元素(第一个元素是函数本身的类型)。通常,头部位置的类型非常少变化——实际上,大多数函数属于没有参数的单态类型。但是,构造函数不是这种情况,一个方法表便保存了所有类型的构造函数。因此,Type 方法表是特殊的,使用元组类型的第一个元素而不是第二个。

前端为所有闭包生成类型声明。起初,这通过生成通常的类型声明来实现。但是,这产生了大量的构造函数,这些构造函数全都很简单(只是将所有参数传递给 new)。因为方法是部分排序的,所以插入所有这些方法是 O(n^2),此外要保留的方法实在太多了。这可通过直接生成 struct_type 表达式(绕过默认的构造函数生成)并直接使用 new 来创建闭包的实例来优化。这事并不漂亮,但你需要做你该做的。

下个问题是 @test 宏,它为每个测试用例生成一个 0 参数闭包。这不是必需的,因为每个用例只需运行一次。因此,@test 被改写以展开到一个 try-catch 块中,该块记录测试结果(true、false 或所引发的异常)并对它调用测试套件处理程序。

diff --git a/dev/devdocs/gc-sa/index.html b/dev/devdocs/gc-sa/index.html index 4ee90036..f16cb10e 100644 --- a/dev/devdocs/gc-sa/index.html +++ b/dev/devdocs/gc-sa/index.html @@ -75,4 +75,4 @@ // that val is rooted under these conditions JL_GC_PROMISE_ROOTED(val); } -}

Completeness of analysis

The analyzer only looks at local information. In particular, e.g. in the PROPAGATES_ROOT case above, it assumes that such memory is only modified in ways it can see, not in any called functions (unless it happens to decide to consider them in its analysis) and not in any concurrently running threads. As such, it may miss a few problematic cases, though in practice such concurrent modification is fairly rare. Improving the analyzer to handle more such cases may be an interesting topic for future work.

+}

Completeness of analysis

The analyzer only looks at local information. In particular, e.g. in the PROPAGATES_ROOT case above, it assumes that such memory is only modified in ways it can see, not in any called functions (unless it happens to decide to consider them in its analysis) and not in any concurrently running threads. As such, it may miss a few problematic cases, though in practice such concurrent modification is fairly rare. Improving the analyzer to handle more such cases may be an interesting topic for future work.

diff --git a/dev/devdocs/inference/index.html b/dev/devdocs/inference/index.html index d3b4a7e0..286488f0 100644 --- a/dev/devdocs/inference/index.html +++ b/dev/devdocs/inference/index.html @@ -29,4 +29,4 @@ 0 └── goto #4 0 4 ─ goto #5 0 5 ─ %10 = Core.tuple(%7)::Tuple{Float64} - 0 └── return %10

The line costs are in the left column. This includes the consequences of inlining and other forms of optimization.

+ 0 └── return %10

The line costs are in the left column. This includes the consequences of inlining and other forms of optimization.

diff --git a/dev/devdocs/init/index.html b/dev/devdocs/init/index.html index e2de8bc5..22429d4e 100644 --- a/dev/devdocs/init/index.html +++ b/dev/devdocs/init/index.html @@ -15,4 +15,4 @@ jl_any_type, jl_emptysvec, 32);

jl_init_tasks() creates the jl_datatype_t* jl_task_type object; initializes the global jl_root_task struct; and sets jl_current_task to the root task.

jl_init_codegen() initializes the LLVM library.

jl_init_serializer() initializes 8-bit serialization tags for builtin jl_value_t values.

If there is no sysimg file (!jl_options.image_file) then the Core and Main modules are created and boot.jl is evaluated:

jl_core_module = jl_new_module(jl_symbol("Core")) creates the Julia Core module.

jl_init_intrinsic_functions() creates a new Julia module Intrinsics containing constant jl_intrinsic_type symbols. These define an integer code for each intrinsic function. emit_intrinsic() translates these symbols into LLVM instructions during code generation.

jl_init_primitives() hooks C functions up to Julia function symbols. e.g. the symbol Core.:(===)() is bound to C function pointer jl_f_is() by calling add_builtin_func("===", jl_f_is).

jl_new_main_module() creates the global "Main" module and sets jl_current_task->current_module = jl_main_module.

Note: _julia_init() then sets jl_root_task->current_module = jl_core_module. jl_root_task is an alias of jl_current_task at this point, so the current_module set by jl_new_main_module() above is overwritten.

jl_load("boot.jl", sizeof("boot.jl")) calls jl_parse_eval_all which repeatedly calls jl_toplevel_eval_flex() to execute boot.jl. <!– TODO – drill down into eval? –>

jl_get_builtin_hooks() initializes global C pointers to Julia globals defined in boot.jl.

jl_init_box_caches() pre-allocates global boxed integer value objects for values up to 1024. This speeds up allocation of boxed ints later on. e.g.:

jl_value_t *jl_box_uint8(uint32_t x)
 {
     return boxed_uint8_cache[(uint8_t)x];
-}

_julia_init() iterates over the jl_core_module->bindings.table looking for jl_datatype_t values and sets the type name's module prefix to jl_core_module.

jl_add_standard_imports(jl_main_module) does "using Base" in the "Main" module.

Note: _julia_init() now reverts to jl_root_task->current_module = jl_main_module as it was before being set to jl_core_module above.

Platform specific signal handlers are initialized for SIGSEGV (OSX, Linux), and SIGFPE (Windows).

Other signals (SIGINFO, SIGBUS, SIGILL, SIGTERM, SIGABRT, SIGQUIT, SIGSYS and SIGPIPE) are hooked up to sigdie_handler() which prints a backtrace.

jl_init_restored_modules() calls jl_module_run_initializer() for each deserialized module to run the __init__() function.

Finally sigint_handler() is hooked up to SIGINT and calls jl_throw(jl_interrupt_exception).

_julia_init() then returns back to main() in cli/loader_exe.c and main() calls repl_entrypoint(argc, (char**)argv).

sysimg

If there is a sysimg file, it contains a pre-cooked image of the Core and Main modules (and whatever else is created by boot.jl). See Building the Julia system image.

jl_restore_system_image() deserializes the saved sysimg into the current Julia runtime environment and initialization continues after jl_init_box_caches() below...

Note: jl_restore_system_image() (and staticdata.c in general) uses the Legacy ios.c library.

repl_entrypoint()

repl_entrypoint() loads the contents of argv[] into Base.ARGS.

If a .jl "program" file was supplied on the command line, then exec_program() calls jl_load(program,len) which calls jl_parse_eval_all which repeatedly calls jl_toplevel_eval_flex() to execute the program.

However, in our example (julia -e 'println("Hello World!")'), jl_get_global(jl_base_module, jl_symbol("_start")) looks up Base._start and jl_apply() executes it.

Base._start

Base._start calls Base.process_options which calls jl_parse_input_line("println("Hello World!")") to create an expression object and Base.eval() to execute it.

Base.eval

Base.eval() was mapped to jl_f_top_eval by jl_init_primitives().

jl_f_top_eval() calls jl_toplevel_eval_in(jl_main_module, ex), where ex is the parsed expression println("Hello World!").

jl_toplevel_eval_in() calls jl_toplevel_eval_flex() which calls eval() in interpreter.c.

The stack dump below shows how the interpreter works its way through various methods of Base.println() and Base.print() before arriving at write(s::IO, a::Array{T}) where T which does ccall(jl_uv_write()).

jl_uv_write() calls uv_write() to write "Hello World!" to JL_STDOUT. See Libuv wrappers for stdio.:

Hello World!
Stack frameSource codeNotes
jl_uv_write()jl_uv.ccalled though ccall
julia_write_282942stream.jlfunction write!(s::IO, a::Array{T}) where T
julia_print_284639ascii.jlprint(io::IO, s::String) = (write(io, s); nothing)
jlcall_print_284639
jl_apply()julia.h
jl_trampoline()builtins.c
jl_apply()julia.h
jl_apply_generic()gf.cBase.print(Base.TTY, String)
jl_apply()julia.h
jl_trampoline()builtins.c
jl_apply()julia.h
jl_apply_generic()gf.cBase.print(Base.TTY, String, Char, Char...)
jl_apply()julia.h
jl_f_apply()builtins.c
jl_apply()julia.h
jl_trampoline()builtins.c
jl_apply()julia.h
jl_apply_generic()gf.cBase.println(Base.TTY, String, String...)
jl_apply()julia.h
jl_trampoline()builtins.c
jl_apply()julia.h
jl_apply_generic()gf.cBase.println(String,)
jl_apply()julia.h
do_call()interpreter.c
eval()interpreter.c
jl_interpret_toplevel_expr()interpreter.c
jl_toplevel_eval_flex()toplevel.c
jl_toplevel_eval()toplevel.c
jl_toplevel_eval_in()builtins.c
jl_f_top_eval()builtins.c

Since our example has just one function call, which has done its job of printing "Hello World!", the stack now rapidly unwinds back to main().

jl_atexit_hook()

main() calls jl_atexit_hook(). This calls Base._atexit, then calls jl_gc_run_all_finalizers() and cleans up libuv handles.

julia_save()

Finally, main() calls julia_save(), which if requested on the command line, saves the runtime state to a new system image. See jl_compile_all() and jl_save_system_image().

+}

_julia_init() iterates over the jl_core_module->bindings.table looking for jl_datatype_t values and sets the type name's module prefix to jl_core_module.

jl_add_standard_imports(jl_main_module) does "using Base" in the "Main" module.

Note: _julia_init() now reverts to jl_root_task->current_module = jl_main_module as it was before being set to jl_core_module above.

Platform specific signal handlers are initialized for SIGSEGV (OSX, Linux), and SIGFPE (Windows).

Other signals (SIGINFO, SIGBUS, SIGILL, SIGTERM, SIGABRT, SIGQUIT, SIGSYS and SIGPIPE) are hooked up to sigdie_handler() which prints a backtrace.

jl_init_restored_modules() calls jl_module_run_initializer() for each deserialized module to run the __init__() function.

Finally sigint_handler() is hooked up to SIGINT and calls jl_throw(jl_interrupt_exception).

_julia_init() then returns back to main() in cli/loader_exe.c and main() calls repl_entrypoint(argc, (char**)argv).

sysimg

If there is a sysimg file, it contains a pre-cooked image of the Core and Main modules (and whatever else is created by boot.jl). See Building the Julia system image.

jl_restore_system_image() deserializes the saved sysimg into the current Julia runtime environment and initialization continues after jl_init_box_caches() below...

Note: jl_restore_system_image() (and staticdata.c in general) uses the Legacy ios.c library.

repl_entrypoint()

repl_entrypoint() loads the contents of argv[] into Base.ARGS.

If a .jl "program" file was supplied on the command line, then exec_program() calls jl_load(program,len) which calls jl_parse_eval_all which repeatedly calls jl_toplevel_eval_flex() to execute the program.

However, in our example (julia -e 'println("Hello World!")'), jl_get_global(jl_base_module, jl_symbol("_start")) looks up Base._start and jl_apply() executes it.

Base._start

Base._start calls Base.process_options which calls jl_parse_input_line("println("Hello World!")") to create an expression object and Base.eval() to execute it.

Base.eval

Base.eval() was mapped to jl_f_top_eval by jl_init_primitives().

jl_f_top_eval() calls jl_toplevel_eval_in(jl_main_module, ex), where ex is the parsed expression println("Hello World!").

jl_toplevel_eval_in() calls jl_toplevel_eval_flex() which calls eval() in interpreter.c.

The stack dump below shows how the interpreter works its way through various methods of Base.println() and Base.print() before arriving at write(s::IO, a::Array{T}) where T which does ccall(jl_uv_write()).

jl_uv_write() calls uv_write() to write "Hello World!" to JL_STDOUT. See Libuv wrappers for stdio.:

Hello World!
Stack frameSource codeNotes
jl_uv_write()jl_uv.ccalled though ccall
julia_write_282942stream.jlfunction write!(s::IO, a::Array{T}) where T
julia_print_284639ascii.jlprint(io::IO, s::String) = (write(io, s); nothing)
jlcall_print_284639
jl_apply()julia.h
jl_trampoline()builtins.c
jl_apply()julia.h
jl_apply_generic()gf.cBase.print(Base.TTY, String)
jl_apply()julia.h
jl_trampoline()builtins.c
jl_apply()julia.h
jl_apply_generic()gf.cBase.print(Base.TTY, String, Char, Char...)
jl_apply()julia.h
jl_f_apply()builtins.c
jl_apply()julia.h
jl_trampoline()builtins.c
jl_apply()julia.h
jl_apply_generic()gf.cBase.println(Base.TTY, String, String...)
jl_apply()julia.h
jl_trampoline()builtins.c
jl_apply()julia.h
jl_apply_generic()gf.cBase.println(String,)
jl_apply()julia.h
do_call()interpreter.c
eval()interpreter.c
jl_interpret_toplevel_expr()interpreter.c
jl_toplevel_eval_flex()toplevel.c
jl_toplevel_eval()toplevel.c
jl_toplevel_eval_in()builtins.c
jl_f_top_eval()builtins.c

Since our example has just one function call, which has done its job of printing "Hello World!", the stack now rapidly unwinds back to main().

jl_atexit_hook()

main() calls jl_atexit_hook(). This calls Base._atexit, then calls jl_gc_run_all_finalizers() and cleans up libuv handles.

julia_save()

Finally, main() calls julia_save(), which if requested on the command line, saves the runtime state to a new system image. See jl_compile_all() and jl_save_system_image().

diff --git a/dev/devdocs/isbitsunionarrays/index.html b/dev/devdocs/isbitsunionarrays/index.html index 2beb227f..5fe95b6c 100644 --- a/dev/devdocs/isbitsunionarrays/index.html +++ b/dev/devdocs/isbitsunionarrays/index.html @@ -6,4 +6,4 @@ ga('create', 'UA-28835595-9', 'auto'); ga('send', 'pageview', {'page': location.pathname + location.search + location.hash}); -

isbits Union Optimizations

In Julia, the Array type holds both "bits" values as well as heap-allocated "boxed" values. The distinction is whether the value itself is stored inline (in the direct allocated memory of the array), or if the memory of the array is simply a collection of pointers to objects allocated elsewhere. In terms of performance, accessing values inline is clearly an advantage over having to follow a pointer to the actual value. The definition of "isbits" generally means any Julia type with a fixed, determinate size, meaning no "pointer" fields, see ?isbitstype.

Julia also supports Union types, quite literally the union of a set of types. Custom Union type definitions can be extremely handy for applications wishing to "cut across" the nominal type system (i.e. explicit subtype relationships) and define methods or functionality on these, otherwise unrelated, set of types. A compiler challenge, however, is in determining how to treat these Union types. The naive approach (and indeed, what Julia itself did pre-0.7), is to simply make a "box" and then a pointer in the box to the actual value, similar to the previously mentioned "boxed" values. This is unfortunate, however, because of the number of small, primitive "bits" types (think UInt8, Int32, Float64, etc.) that would easily fit themselves inline in this "box" without needing any indirection for value access. There are two main ways Julia can take advantage of this optimization as of 0.7: isbits Union fields in types, and isbits Union Arrays.

isbits Union Structs

Julia now includes an optimization wherein "isbits Union" fields in types (mutable struct, struct, etc.) will be stored inline. This is accomplished by determining the "inline size" of the Union type (e.g. Union{UInt8, Int16} will have a size of two bytes, which represents the size needed of the largest Union type Int16), and in addition, allocating an extra "type tag byte" (UInt8), whose value signals the type of the actual value stored inline of the "Union bytes". The type tag byte value is the index of the actual value's type in the Union type's order of types. For example, a type tag value of 0x02 for a field with type Union{Nothing, UInt8, Int16} would indicate that an Int16 value is stored in the 16 bits of the field in the structure's memory; a 0x01 value would indicate that a UInt8 value was stored in the first 8 bits of the 16 bits of the field's memory. Lastly, a value of 0x00 signals that the nothing value will be returned for this field, even though, as a singleton type with a single type instance, it technically has a size of 0. The type tag byte for a type's Union field is stored directly after the field's computed Union memory.

isbits Union Arrays

Julia can now also store "isbits Union" values inline in an Array, as opposed to requiring an indirection box. The optimization is accomplished by storing an extra "type tag array" of bytes, one byte per array element, alongside the bytes of the actual array data. This type tag array serves the same function as the type field case: its value signals the type of the actual stored Union value in the array. In terms of layout, a Julia Array can include extra "buffer" space before and after its actual data values, which are tracked in the a->offset and a->maxsize fields of the jl_array_t* type. The "type tag array" is treated exactly as another jl_array_t*, but which shares the same a->offset, a->maxsize, and a->len fields. So the formula to access an isbits Union Array's type tag bytes is a->data + (a->maxsize - a->offset) * a->elsize + a->offset; i.e. the Array's a->data pointer is already shifted by a->offset, so correcting for that, we follow the data all the way to the max of what it can hold a->maxsize, then adjust by a->offset more bytes to account for any present "front buffering" the array might be doing. This layout in particular allows for very efficient resizing operations as the type tag data only ever has to move when the actual array's data has to move.

+

isbits Union Optimizations

In Julia, the Array type holds both "bits" values as well as heap-allocated "boxed" values. The distinction is whether the value itself is stored inline (in the direct allocated memory of the array), or if the memory of the array is simply a collection of pointers to objects allocated elsewhere. In terms of performance, accessing values inline is clearly an advantage over having to follow a pointer to the actual value. The definition of "isbits" generally means any Julia type with a fixed, determinate size, meaning no "pointer" fields, see ?isbitstype.

Julia also supports Union types, quite literally the union of a set of types. Custom Union type definitions can be extremely handy for applications wishing to "cut across" the nominal type system (i.e. explicit subtype relationships) and define methods or functionality on these, otherwise unrelated, set of types. A compiler challenge, however, is in determining how to treat these Union types. The naive approach (and indeed, what Julia itself did pre-0.7), is to simply make a "box" and then a pointer in the box to the actual value, similar to the previously mentioned "boxed" values. This is unfortunate, however, because of the number of small, primitive "bits" types (think UInt8, Int32, Float64, etc.) that would easily fit themselves inline in this "box" without needing any indirection for value access. There are two main ways Julia can take advantage of this optimization as of 0.7: isbits Union fields in types, and isbits Union Arrays.

isbits Union Structs

Julia now includes an optimization wherein "isbits Union" fields in types (mutable struct, struct, etc.) will be stored inline. This is accomplished by determining the "inline size" of the Union type (e.g. Union{UInt8, Int16} will have a size of two bytes, which represents the size needed of the largest Union type Int16), and in addition, allocating an extra "type tag byte" (UInt8), whose value signals the type of the actual value stored inline of the "Union bytes". The type tag byte value is the index of the actual value's type in the Union type's order of types. For example, a type tag value of 0x02 for a field with type Union{Nothing, UInt8, Int16} would indicate that an Int16 value is stored in the 16 bits of the field in the structure's memory; a 0x01 value would indicate that a UInt8 value was stored in the first 8 bits of the 16 bits of the field's memory. Lastly, a value of 0x00 signals that the nothing value will be returned for this field, even though, as a singleton type with a single type instance, it technically has a size of 0. The type tag byte for a type's Union field is stored directly after the field's computed Union memory.

isbits Union Arrays

Julia can now also store "isbits Union" values inline in an Array, as opposed to requiring an indirection box. The optimization is accomplished by storing an extra "type tag array" of bytes, one byte per array element, alongside the bytes of the actual array data. This type tag array serves the same function as the type field case: its value signals the type of the actual stored Union value in the array. In terms of layout, a Julia Array can include extra "buffer" space before and after its actual data values, which are tracked in the a->offset and a->maxsize fields of the jl_array_t* type. The "type tag array" is treated exactly as another jl_array_t*, but which shares the same a->offset, a->maxsize, and a->len fields. So the formula to access an isbits Union Array's type tag bytes is a->data + (a->maxsize - a->offset) * a->elsize + a->offset; i.e. the Array's a->data pointer is already shifted by a->offset, so correcting for that, we follow the data all the way to the max of what it can hold a->maxsize, then adjust by a->offset more bytes to account for any present "front buffering" the array might be doing. This layout in particular allows for very efficient resizing operations as the type tag data only ever has to move when the actual array's data has to move.

diff --git a/dev/devdocs/llvm/index.html b/dev/devdocs/llvm/index.html index 9c47b150..bf1d59a0 100644 --- a/dev/devdocs/llvm/index.html +++ b/dev/devdocs/llvm/index.html @@ -18,4 +18,4 @@ error("An error occurred") end

During constant folding, LLVM may discover that the condition is always false, and can remove the basic block. However, if GC root lowering is done early, the GC root slots used in the deleted block, as well as any values kept alive in those slots only because they were used in the error path, would be kept alive by LLVM. By doing GC root lowering late, we give LLVM the license to do any of its usual optimizations (constant folding, dead code elimination, etc.), without having to worry (too much) about which values may or may not be GC tracked.

However, in order to be able to do late GC root placement, we need to be able to identify a) which pointers are GC tracked and b) all uses of such pointers. The goal of the GC placement pass is thus simple:

Minimize the number of needed GC roots/stores to them subject to the constraint that at every safepoint, any live GC-tracked pointer (i.e. for which there is a path after this point that contains a use of this pointer) is in some GC slot.

Representation

The primary difficulty is thus choosing an IR representation that allows us to identify GC-tracked pointers and their uses, even after the program has been run through the optimizer. Our design makes use of three LLVM features to achieve this:

Custom address spaces allow us to tag every point with an integer that needs to be preserved through optimizations. The compiler may not insert casts between address spaces that did not exist in the original program and it must never change the address space of a pointer on a load/store/etc operation. This allows us to annotate which pointers are GC-tracked in an optimizer-resistant way. Note that metadata would not be able to achieve the same purpose. Metadata is supposed to always be discardable without altering the semantics of the program. However, failing to identify a GC-tracked pointer alters the resulting program behavior dramatically - it'll probably crash or return wrong results. We currently use three different address spaces (their numbers are defined in src/codegen_shared.cpp):

Invariants

The GC root placement pass makes use of several invariants, which need to be observed by the frontend and are preserved by the optimizer.

First, only the following address space casts are allowed:

Now let us consider what constitutes a use:

We explicitly allow load/stores and simple calls in address spaces Tracked/Derived. Elements of jlcall argument arrays must always be in address space Tracked (it is required by the ABI that they are valid jl_value_t* pointers). The same is true for return instructions (though note that struct return arguments are allowed to have any of the address spaces). The only allowable use of an address space CalleeRooted pointer is to pass it to a call (which must have an appropriately typed operand).

Further, we disallow getelementptr in addrspace Tracked. This is because unless the operation is a noop, the resulting pointer will not be validly storable to a GC slot and may thus not be in this address space. If such a pointer is required, it should be decayed to addrspace Derived first.

Lastly, we disallow inttoptr/ptrtoint instructions in these address spaces. Having these instructions would mean that some i64 values are really GC tracked. This is problematic, because it breaks that stated requirement that we're able to identify GC-relevant pointers. This invariant is accomplished using the LLVM "non-integral pointers" feature, which is new in LLVM 5.0. It prohibits the optimizer from making optimizations that would introduce these operations. Note we can still insert static constants at JIT time by using inttoptr in address space 0 and then decaying to the appropriate address space afterwards.

Supporting ccall

One important aspect missing from the discussion so far is the handling of ccall. ccall has the peculiar feature that the location and scope of a use do not coincide. As an example consider:

A = randn(1024)
 ccall(:foo, Cvoid, (Ptr{Float64},), A)

In lowering, the compiler will insert a conversion from the array to the pointer which drops the reference to the array value. However, we of course need to make sure that the array does stay alive while we're doing the ccall. To understand how this is done, first recall the lowering of the above code:

return $(Expr(:foreigncall, :(:foo), Cvoid, svec(Ptr{Float64}), 0, :(:ccall), Expr(:foreigncall, :(:jl_array_ptr), Ptr{Float64}, svec(Any), 0, :(:ccall), :(A)), :(A)))

The last :(A), is an extra argument list inserted during lowering that informs the code generator which Julia level values need to be kept alive for the duration of this ccall. We then take this information and represent it in an "operand bundle" at the IR level. An operand bundle is essentially a fake use that is attached to the call site. At the IR level, this looks like so:

call void inttoptr (i64 ... to void (double*)*)(double* %5) [ "jl_roots"(%jl_value_t addrspace(10)* %A) ]

The GC root placement pass will treat the jl_roots operand bundle as if it were a regular operand. However, as a final step, after the GC roots are inserted, it will drop the operand bundle to avoid confusing instruction selection.

Supporting pointer_from_objref

pointer_from_objref is special because it requires the user to take explicit control of GC rooting. By our above invariants, this function is illegal, because it performs an address space cast from 10 to 0. However, it can be useful, in certain situations, so we provide a special intrinsic:

declared %jl_value_t *julia.pointer_from_objref(%jl_value_t addrspace(10)*)

which is lowered to the corresponding address space cast after GC root lowering. Do note however that by using this intrinsic, the caller assumes all responsibility for making sure that the value in question is rooted. Further this intrinsic is not considered a use, so the GC root placement pass will not provide a GC root for the function. As a result, the external rooting must be arranged while the value is still tracked by the system. I.e. it is not valid to attempt to use the result of this operation to establish a global root - the optimizer may have already dropped the value.

Keeping values alive in the absence of uses

In certain cases it is necessary to keep an object alive, even though there is no compiler-visible use of said object. This may be case for low level code that operates on the memory-representation of an object directly or code that needs to interface with C code. In order to allow this, we provide the following intrinsics at the LLVM level:

token @llvm.julia.gc_preserve_begin(...)
-void @llvm.julia.gc_preserve_end(token)

(The llvm. in the name is required in order to be able to use the token type). The semantics of these intrinsics are as follows: At any safepoint that is dominated by a gc_preserve_begin call, but that is not not dominated by a corresponding gc_preserve_end call (i.e. a call whose argument is the token returned by a gc_preserve_begin call), the values passed as arguments to that gc_preserve_begin will be kept live. Note that the gc_preserve_begin still counts as a regular use of those values, so the standard lifetime semantics will ensure that the values will be kept alive before entering the preserve region.

+void @llvm.julia.gc_preserve_end(token)

(The llvm. in the name is required in order to be able to use the token type). The semantics of these intrinsics are as follows: At any safepoint that is dominated by a gc_preserve_begin call, but that is not not dominated by a corresponding gc_preserve_end call (i.e. a call whose argument is the token returned by a gc_preserve_begin call), the values passed as arguments to that gc_preserve_begin will be kept live. Note that the gc_preserve_begin still counts as a regular use of those values, so the standard lifetime semantics will ensure that the values will be kept alive before entering the preserve region.

diff --git a/dev/devdocs/locks/index.html b/dev/devdocs/locks/index.html index 45b94149..0c870db3 100644 --- a/dev/devdocs/locks/index.html +++ b/dev/devdocs/locks/index.html @@ -6,4 +6,4 @@ ga('create', 'UA-28835595-9', 'auto'); ga('send', 'pageview', {'page': location.pathname + location.search + location.hash}); -

Proper maintenance and care of multi-threading locks

The following strategies are used to ensure that the code is dead-lock free (generally by addressing the 4th Coffman condition: circular wait).

  1. structure code such that only one lock will need to be acquired at a time
  2. always acquire shared locks in the same order, as given by the table below
  3. avoid constructs that expect to need unrestricted recursion

Locks

Below are all of the locks that exist in the system and the mechanisms for using them that avoid the potential for deadlocks (no Ostrich algorithm allowed here):

The following are definitely leaf locks (level 1), and must not try to acquire any other lock:

  • safepoint

    Note that this lock is acquired implicitly by JL_LOCK and JL_UNLOCK. use the _NOGC variants to avoid that for level 1 locks.

    While holding this lock, the code must not do any allocation or hit any safepoints. Note that there are safepoints when doing allocation, enabling / disabling GC, entering / restoring exception frames, and taking / releasing locks.

  • shared_map

  • finalizers

  • pagealloc

  • gcpermlock

  • flisp

  • jlinstackwalk (Win32)

    flisp itself is already threadsafe, this lock only protects the jl_ast_context_list_t pool

The following is a leaf lock (level 2), and only acquires level 1 locks (safepoint) internally:

  • typecache
  • Module->lock

The following is a level 3 lock, which can only acquire level 1 or level 2 locks internally:

  • Method->writelock

The following is a level 4 lock, which can only recurse to acquire level 1, 2, or 3 locks:

  • MethodTable->writelock

No Julia code may be called while holding a lock above this point.

The following are a level 6 lock, which can only recurse to acquire locks at lower levels:

  • codegen
  • jlmodulesmutex

The following is an almost root lock (level end-1), meaning only the root look may be held when trying to acquire it:

  • typeinf

    this one is perhaps one of the most tricky ones, since type-inference can be invoked from many points

    currently the lock is merged with the codegen lock, since they call each other recursively

The following lock synchronizes IO operation. Be aware that doing any I/O (for example, printing warning messages or debug information) while holding any other lock listed above may result in pernicious and hard-to-find deadlocks. BE VERY CAREFUL!

  • iolock

  • Individual ThreadSynchronizers locks

    this may continue to be held after releasing the iolock, or acquired without it, but be very careful to never attempt to acquire the iolock while holding it

The following is the root lock, meaning no other lock shall be held when trying to acquire it:

  • toplevel

    this should be held while attempting a top-level action (such as making a new type or defining a new method): trying to obtain this lock inside a staged function will cause a deadlock condition!

    additionally, it's unclear if any code can safely run in parallel with an arbitrary toplevel expression, so it may require all threads to get to a safepoint first

Broken Locks

The following locks are broken:

  • toplevel

    doesn't exist right now

    fix: create it

  • Module->lock

    This is vulnerable to deadlocks since it can't be certain it is acquired in sequence. Some operations (such as import_module) are missing a lock.

    fix: replace with jl_modules_mutex?

  • loading.jl: require and register_root_module

    This file potentially has numerous problems.

    fix: needs locks

Shared Global Data Structures

These data structures each need locks due to being shared mutable global state. It is the inverse list for the above lock priority list. This list does not include level 1 leaf resources due to their simplicity.

MethodTable modifications (def, cache, kwsorter type) : MethodTable->writelock

Type declarations : toplevel lock

Type application : typecache lock

Global variable tables : Module->lock

Module serializer : toplevel lock

JIT & type-inference : codegen lock

MethodInstance/CodeInstance updates : Method->writelock, codegen lock

  • These are set at construction and immutable:
    • specTypes
    • sparam_vals
    • def
  • These are set by jl_type_infer (while holding codegen lock):
    • cache
    • rettype
    • inferred
    * valid ages
  • inInference flag:
    • optimization to quickly avoid recurring into jl_type_infer while it is already running
    • actual state (of setting inferred, then fptr) is protected by codegen lock
  • Function pointers:

    • these transition once, from NULL to a value, while the codegen lock is held
  • Code-generator cache (the contents of functionObjectsDecls):

    • these can transition multiple times, but only while the codegen lock is held
    • it is valid to use old version of this, or block for new versions of this, so races are benign, as long as the code is careful not to reference other data in the method instance (such as rettype) and assume it is coordinated, unless also holding the codegen lock

LLVMContext : codegen lock

Method : Method->writelock

  • roots array (serializer and codegen)
  • invoke / specializations / tfunc modifications
+

Proper maintenance and care of multi-threading locks

The following strategies are used to ensure that the code is dead-lock free (generally by addressing the 4th Coffman condition: circular wait).

  1. structure code such that only one lock will need to be acquired at a time
  2. always acquire shared locks in the same order, as given by the table below
  3. avoid constructs that expect to need unrestricted recursion

Locks

Below are all of the locks that exist in the system and the mechanisms for using them that avoid the potential for deadlocks (no Ostrich algorithm allowed here):

The following are definitely leaf locks (level 1), and must not try to acquire any other lock:

  • safepoint

    Note that this lock is acquired implicitly by JL_LOCK and JL_UNLOCK. use the _NOGC variants to avoid that for level 1 locks.

    While holding this lock, the code must not do any allocation or hit any safepoints. Note that there are safepoints when doing allocation, enabling / disabling GC, entering / restoring exception frames, and taking / releasing locks.

  • shared_map

  • finalizers

  • pagealloc

  • gcpermlock

  • flisp

  • jlinstackwalk (Win32)

    flisp itself is already threadsafe, this lock only protects the jl_ast_context_list_t pool

The following is a leaf lock (level 2), and only acquires level 1 locks (safepoint) internally:

  • typecache
  • Module->lock

The following is a level 3 lock, which can only acquire level 1 or level 2 locks internally:

  • Method->writelock

The following is a level 4 lock, which can only recurse to acquire level 1, 2, or 3 locks:

  • MethodTable->writelock

No Julia code may be called while holding a lock above this point.

The following are a level 6 lock, which can only recurse to acquire locks at lower levels:

  • codegen
  • jlmodulesmutex

The following is an almost root lock (level end-1), meaning only the root look may be held when trying to acquire it:

  • typeinf

    this one is perhaps one of the most tricky ones, since type-inference can be invoked from many points

    currently the lock is merged with the codegen lock, since they call each other recursively

The following lock synchronizes IO operation. Be aware that doing any I/O (for example, printing warning messages or debug information) while holding any other lock listed above may result in pernicious and hard-to-find deadlocks. BE VERY CAREFUL!

  • iolock

  • Individual ThreadSynchronizers locks

    this may continue to be held after releasing the iolock, or acquired without it, but be very careful to never attempt to acquire the iolock while holding it

The following is the root lock, meaning no other lock shall be held when trying to acquire it:

  • toplevel

    this should be held while attempting a top-level action (such as making a new type or defining a new method): trying to obtain this lock inside a staged function will cause a deadlock condition!

    additionally, it's unclear if any code can safely run in parallel with an arbitrary toplevel expression, so it may require all threads to get to a safepoint first

Broken Locks

The following locks are broken:

  • toplevel

    doesn't exist right now

    fix: create it

  • Module->lock

    This is vulnerable to deadlocks since it can't be certain it is acquired in sequence. Some operations (such as import_module) are missing a lock.

    fix: replace with jl_modules_mutex?

  • loading.jl: require and register_root_module

    This file potentially has numerous problems.

    fix: needs locks

Shared Global Data Structures

These data structures each need locks due to being shared mutable global state. It is the inverse list for the above lock priority list. This list does not include level 1 leaf resources due to their simplicity.

MethodTable modifications (def, cache, kwsorter type) : MethodTable->writelock

Type declarations : toplevel lock

Type application : typecache lock

Global variable tables : Module->lock

Module serializer : toplevel lock

JIT & type-inference : codegen lock

MethodInstance/CodeInstance updates : Method->writelock, codegen lock

  • These are set at construction and immutable:
    • specTypes
    • sparam_vals
    • def
  • These are set by jl_type_infer (while holding codegen lock):
    • cache
    • rettype
    • inferred
    * valid ages
  • inInference flag:
    • optimization to quickly avoid recurring into jl_type_infer while it is already running
    • actual state (of setting inferred, then fptr) is protected by codegen lock
  • Function pointers:

    • these transition once, from NULL to a value, while the codegen lock is held
  • Code-generator cache (the contents of functionObjectsDecls):

    • these can transition multiple times, but only while the codegen lock is held
    • it is valid to use old version of this, or block for new versions of this, so races are benign, as long as the code is careful not to reference other data in the method instance (such as rettype) and assume it is coordinated, unless also holding the codegen lock

LLVMContext : codegen lock

Method : Method->writelock

  • roots array (serializer and codegen)
  • invoke / specializations / tfunc modifications
diff --git a/dev/devdocs/meta/index.html b/dev/devdocs/meta/index.html index c00e936f..fdb6cbaa 100644 --- a/dev/devdocs/meta/index.html +++ b/dev/devdocs/meta/index.html @@ -15,4 +15,4 @@ Expr(:meta, :inline) x*(x+3) end -end

Base.pushmeta!(ex, :symbol, args...) appends :symbol to the end of the :meta expression, creating a new :meta expression if necessary. If args is specified, a nested expression containing :symbol and these arguments is appended instead, which can be used to specify additional information.

To use the metadata, you have to parse these :meta expressions. If your implementation can be performed within Julia, Base.popmeta! is very handy: Base.popmeta!(body, :symbol) will scan a function body expression (one without the function signature) for the first :meta expression containing :symbol, extract any arguments, and return a tuple (found::Bool, args::Array{Any}). If the metadata did not have any arguments, or :symbol was not found, the args array will be empty.

Not yet provided is a convenient infrastructure for parsing :meta expressions from C++.

+end

Base.pushmeta!(ex, :symbol, args...) appends :symbol to the end of the :meta expression, creating a new :meta expression if necessary. If args is specified, a nested expression containing :symbol and these arguments is appended instead, which can be used to specify additional information.

To use the metadata, you have to parse these :meta expressions. If your implementation can be performed within Julia, Base.popmeta! is very handy: Base.popmeta!(body, :symbol) will scan a function body expression (one without the function signature) for the first :meta expression containing :symbol, extract any arguments, and return a tuple (found::Bool, args::Array{Any}). If the metadata did not have any arguments, or :symbol was not found, the args array will be empty.

Not yet provided is a convenient infrastructure for parsing :meta expressions from C++.

diff --git a/dev/devdocs/object/index.html b/dev/devdocs/object/index.html index e6d113df..9ee79675 100644 --- a/dev/devdocs/object/index.html +++ b/dev/devdocs/object/index.html @@ -30,4 +30,4 @@ jl_array_t *jl_alloc_array_3d(jl_value_t *atype, size_t nr, size_t nc, size_t z); jl_array_t *jl_alloc_vec_any(size_t n);

Note that many of these have alternative allocation functions for various special-purposes. The list here reflects the more common usages, but a more complete list can be found by reading the julia.h header file.

Internal to Julia, storage is typically allocated by newstruct() (or newobj() for the special types):

jl_value_t *newstruct(jl_value_t *type);
 jl_value_t *newobj(jl_value_t *type, size_t nfields);

And at the lowest level, memory is getting allocated by a call to the garbage collector (in gc.c), then tagged with its type:

jl_value_t *jl_gc_allocobj(size_t nbytes);
-void jl_set_typeof(jl_value_t *v, jl_datatype_t *type);

Note that all objects are allocated in multiples of 4 bytes and aligned to the platform pointer size. Memory is allocated from a pool for smaller objects, or directly with malloc() for large objects.

Singleton Types

Singleton types have only one instance and no data fields. Singleton instances have a size of 0 bytes, and consist only of their metadata. e.g. nothing::Nothing.

See Singleton Types and Nothingness and missing values

+void jl_set_typeof(jl_value_t *v, jl_datatype_t *type);

Note that all objects are allocated in multiples of 4 bytes and aligned to the platform pointer size. Memory is allocated from a pool for smaller objects, or directly with malloc() for large objects.

Singleton Types

Singleton types have only one instance and no data fields. Singleton instances have a size of 0 bytes, and consist only of their metadata. e.g. nothing::Nothing.

See Singleton Types and Nothingness and missing values

diff --git a/dev/devdocs/offset-arrays/index.html b/dev/devdocs/offset-arrays/index.html index d544b89c..07b20314 100644 --- a/dev/devdocs/offset-arrays/index.html +++ b/dev/devdocs/offset-arrays/index.html @@ -26,4 +26,4 @@ function Base.similar(f::Union{Function,DataType}, shape::Tuple{ZeroRange,Vararg{ZeroRange}}) # body -end

Both of these should allocate your custom array type.

Specializing reshape

Optionally, define a method

Base.reshape(A::AbstractArray, shape::Tuple{ZeroRange,Vararg{ZeroRange}}) = ...

and you can reshape an array so that the result has custom indices.

For objects that mimic AbstractArray but are not subtypes

has_offset_axes depends on having axes defined for the objects you call it on. If there is some reason you don't have an axes method defined for your object, consider defining a method

Base.has_offset_axes(obj::MyNon1IndexedArraylikeObject) = true

This will allow code that assumes 1-based indexing to detect a problem and throw a helpful error, rather than returning incorrect results or segfaulting julia.

Catching errors

If your new array type triggers errors in other code, one helpful debugging step can be to comment out @boundscheck in your getindex and setindex! implementation. This will ensure that every element access checks bounds. Or, restart julia with --check-bounds=yes.

In some cases it may also be helpful to temporarily disable size and length for your new array type, since code that makes incorrect assumptions frequently uses these functions.

+end

Both of these should allocate your custom array type.

Specializing reshape

Optionally, define a method

Base.reshape(A::AbstractArray, shape::Tuple{ZeroRange,Vararg{ZeroRange}}) = ...

and you can reshape an array so that the result has custom indices.

For objects that mimic AbstractArray but are not subtypes

has_offset_axes depends on having axes defined for the objects you call it on. If there is some reason you don't have an axes method defined for your object, consider defining a method

Base.has_offset_axes(obj::MyNon1IndexedArraylikeObject) = true

This will allow code that assumes 1-based indexing to detect a problem and throw a helpful error, rather than returning incorrect results or segfaulting julia.

Catching errors

If your new array type triggers errors in other code, one helpful debugging step can be to comment out @boundscheck in your getindex and setindex! implementation. This will ensure that every element access checks bounds. Or, restart julia with --check-bounds=yes.

In some cases it may also be helpful to temporarily disable size and length for your new array type, since code that makes incorrect assumptions frequently uses these functions.

diff --git a/dev/devdocs/reflection/index.html b/dev/devdocs/reflection/index.html index 1b1e173b..54544224 100644 --- a/dev/devdocs/reflection/index.html +++ b/dev/devdocs/reflection/index.html @@ -38,4 +38,4 @@ @ int.jl:53 within `+' 1 ─ %1 = Base.add_int(x, y)::Int64 └── return %1 -) => Int64

Possible values for debuginfo are: :none, :source, and:default. Per default debug information is not printed, but that can be changed by setting Base.IRShow.default_debuginfo[] = :source.

+) => Int64

Possible values for debuginfo are: :none, :source, and:default. Per default debug information is not printed, but that can be changed by setting Base.IRShow.default_debuginfo[] = :source.

diff --git a/dev/devdocs/require/index.html b/dev/devdocs/require/index.html index b2fcdea5..c612b56b 100644 --- a/dev/devdocs/require/index.html +++ b/dev/devdocs/require/index.html @@ -12,4 +12,4 @@ function module_fqn(name::Symbol) fqn = fullname(Base.root_module(name)) return join(fqn, '.') -end +end diff --git a/dev/devdocs/sanitizers/index.html b/dev/devdocs/sanitizers/index.html index 0a9f5a62..0e9521b4 100644 --- a/dev/devdocs/sanitizers/index.html +++ b/dev/devdocs/sanitizers/index.html @@ -12,4 +12,4 @@ CC=~+/deps/scratch/llvm-svn/build_Release/bin/clang \ CXX=~+/deps/scratch/llvm-svn/build_Release/bin/clang++ \ CPPFLAGS="-isysroot $(xcode-select -p)/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk" \ - CXXFLAGS="-isystem $(xcode-select -p)/Toolchains/XcodeDefault.xctoolchain/usr/include/c++/v1"

(or put these into your Make.user, so you don't need to remember them every time).

Address Sanitizer (ASAN)

For detecting or debugging memory bugs, you can use Clang's address sanitizer (ASAN). By compiling with SANITIZE_ADDRESS=1 you enable ASAN for the Julia compiler and its generated code. In addition, you can specify LLVM_SANITIZE=1 to sanitize the LLVM library as well. Note that these options incur a high performance and memory cost. For example, using ASAN for Julia and LLVM makes testall1 takes 8-10 times as long while using 20 times as much memory (this can be reduced to respectively a factor of 3 and 4 by using the options described below).

By default, Julia sets the allow_user_segv_handler=1 ASAN flag, which is required for signal delivery to work properly. You can define other options using the ASAN_OPTIONS environment flag, in which case you'll need to repeat the default option mentioned before. For example, memory usage can be reduced by specifying fast_unwind_on_malloc=0 and malloc_context_size=2, at the cost of backtrace accuracy. For now, Julia also sets detect_leaks=0, but this should be removed in the future.

Memory Sanitizer (MSAN)

For detecting use of uninitialized memory, you can use Clang's memory sanitizer (MSAN) by compiling with SANITIZE_MEMORY=1.

Thread Sanitizer (TSAN)

For debugging data-races and other threading related issues you can use Clang's thread sanitizer (TSAN) by compiling with SANITIZE_THREAD=1.

+ CXXFLAGS="-isystem $(xcode-select -p)/Toolchains/XcodeDefault.xctoolchain/usr/include/c++/v1"

(or put these into your Make.user, so you don't need to remember them every time).

Address Sanitizer (ASAN)

For detecting or debugging memory bugs, you can use Clang's address sanitizer (ASAN). By compiling with SANITIZE_ADDRESS=1 you enable ASAN for the Julia compiler and its generated code. In addition, you can specify LLVM_SANITIZE=1 to sanitize the LLVM library as well. Note that these options incur a high performance and memory cost. For example, using ASAN for Julia and LLVM makes testall1 takes 8-10 times as long while using 20 times as much memory (this can be reduced to respectively a factor of 3 and 4 by using the options described below).

By default, Julia sets the allow_user_segv_handler=1 ASAN flag, which is required for signal delivery to work properly. You can define other options using the ASAN_OPTIONS environment flag, in which case you'll need to repeat the default option mentioned before. For example, memory usage can be reduced by specifying fast_unwind_on_malloc=0 and malloc_context_size=2, at the cost of backtrace accuracy. For now, Julia also sets detect_leaks=0, but this should be removed in the future.

Memory Sanitizer (MSAN)

For detecting use of uninitialized memory, you can use Clang's memory sanitizer (MSAN) by compiling with SANITIZE_MEMORY=1.

Thread Sanitizer (TSAN)

For debugging data-races and other threading related issues you can use Clang's thread sanitizer (TSAN) by compiling with SANITIZE_THREAD=1.

diff --git a/dev/devdocs/ssair/index.html b/dev/devdocs/ssair/index.html index a2ac30ad..ca4c0db3 100644 --- a/dev/devdocs/ssair/index.html +++ b/dev/devdocs/ssair/index.html @@ -58,4 +58,4 @@ 5 ─ $(Expr(:pop_exception, :(%2)))::Any │ $(Expr(:throw_undef_if_not, :y, :(%13)))::Any │ %19 = Core.tuple(%15, %14) -└── return %19

Note in particular that every value live into the critical region gets an upsilon node at the top of the critical region. This is because catch blocks are considered to have an invisible control flow edge from outside the function. As a result, no SSA value dominates the catch blocks, and all incoming values have to come through a φᶜ node.

Main SSA data structure

The main SSAIR data structure is worthy of discussion. It draws inspiration from LLVM and Webkit's B3 IR. The core of the data structure is a flat vector of statements. Each statement is implicitly assigned an SSA value based on its position in the vector (i.e. the result of the statement at idx 1 can be accessed using SSAValue(1) etc). For each SSA value, we additionally maintain its type. Since, SSA values are definitionally assigned only once, this type is also the result type of the expression at the corresponding index. However, while this representation is rather efficient (since the assignments don't need to be explicitly encoded), it of course carries the drawback that order is semantically significant, so reorderings and insertions change statement numbers. Additionally, we do not keep use lists (i.e. it is impossible to walk from a def to all its uses without explicitly computing this map–def lists however are trivial since you can look up the corresponding statement from the index), so the LLVM-style RAUW (replace-all-uses-with) operation is unavailable.

Instead, we do the following:

There is a compact! function that compacts the above data structure by performing the insertion of nodes in the appropriate place, trivial copy propagation, and renaming of uses to any changed SSA values. However, the clever part of this scheme is that this compaction can be done lazily as part of the subsequent pass. Most optimization passes need to walk over the entire list of statements, performing analysis or modifications along the way. We provide an IncrementalCompact iterator that can be used to iterate over the statement list. It will perform any necessary compaction and return the new index of the node, as well as the node itself. It is legal at this point to walk def-use chains, as well as make any modifications or deletions to the IR (insertions are disallowed however).

The idea behind this arrangement is that, since the optimization passes need to touch the corresponding memory anyway and incur the corresponding memory access penalty, performing the extra housekeeping should have comparatively little overhead (and save the overhead of maintaining these data structures during IR modification).

+└── return %19

Note in particular that every value live into the critical region gets an upsilon node at the top of the critical region. This is because catch blocks are considered to have an invisible control flow edge from outside the function. As a result, no SSA value dominates the catch blocks, and all incoming values have to come through a φᶜ node.

Main SSA data structure

The main SSAIR data structure is worthy of discussion. It draws inspiration from LLVM and Webkit's B3 IR. The core of the data structure is a flat vector of statements. Each statement is implicitly assigned an SSA value based on its position in the vector (i.e. the result of the statement at idx 1 can be accessed using SSAValue(1) etc). For each SSA value, we additionally maintain its type. Since, SSA values are definitionally assigned only once, this type is also the result type of the expression at the corresponding index. However, while this representation is rather efficient (since the assignments don't need to be explicitly encoded), it of course carries the drawback that order is semantically significant, so reorderings and insertions change statement numbers. Additionally, we do not keep use lists (i.e. it is impossible to walk from a def to all its uses without explicitly computing this map–def lists however are trivial since you can look up the corresponding statement from the index), so the LLVM-style RAUW (replace-all-uses-with) operation is unavailable.

Instead, we do the following:

There is a compact! function that compacts the above data structure by performing the insertion of nodes in the appropriate place, trivial copy propagation, and renaming of uses to any changed SSA values. However, the clever part of this scheme is that this compaction can be done lazily as part of the subsequent pass. Most optimization passes need to walk over the entire list of statements, performing analysis or modifications along the way. We provide an IncrementalCompact iterator that can be used to iterate over the statement list. It will perform any necessary compaction and return the new index of the node, as well as the node itself. It is legal at this point to walk def-use chains, as well as make any modifications or deletions to the IR (insertions are disallowed however).

The idea behind this arrangement is that, since the optimization passes need to touch the corresponding memory anyway and incur the corresponding memory access penalty, performing the extra housekeeping should have comparatively little overhead (and save the overhead of maintaining these data structures during IR modification).

diff --git a/dev/devdocs/stdio/index.html b/dev/devdocs/stdio/index.html index e5825ed2..ce6aafeb 100644 --- a/dev/devdocs/stdio/index.html +++ b/dev/devdocs/stdio/index.html @@ -21,4 +21,4 @@ jl_uv.c: -> int jl_uv_write(uv_stream_t *stream, ...) -> uv_write(uvw, stream, buf, ...)

printf() during initialization

The libuv streams relied upon by jl_printf() etc., are not available until midway through initialization of the runtime (see init.c, init_stdio()). Error messages or warnings that need to be printed before this are routed to the standard C library fwrite() function by the following mechanism:

In sys.c, the JL_STD* stream pointers are statically initialized to integer constants: STD*_FILENO (0, 1 and 2). In jl_uv.c the jl_uv_puts() function checks its uv_stream_t* stream argument and calls fwrite() if stream is set to STDOUT_FILENO or STDERR_FILENO.

This allows for uniform use of jl_printf() throughout the runtime regardless of whether or not any particular piece of code is reachable before initialization is complete.

Legacy ios.c library

The src/support/ios.c library is inherited from femtolisp. It provides cross-platform buffered file IO and in-memory temporary buffers.

ios.c is still used by:

Use of ios.c in these modules is mostly self-contained and separated from the libuv I/O system. However, there is one place where femtolisp calls through to jl_printf() with a legacy ios_t stream.

There is a hack in ios.h that makes the ios_t.bm field line up with the uv_stream_t.type and ensures that the values used for ios_t.bm to not overlap with valid UV_HANDLE_TYPE values. This allows uv_stream_t pointers to point to ios_t streams.

This is needed because jl_printf() caller jl_static_show() is passed an ios_t stream by femtolisp's fl_print() function. Julia's jl_uv_puts() function has special handling for this:

if (stream->type > UV_HANDLE_TYPE_MAX) {
     return ios_write((ios_t*)stream, str, n);
-}
+} diff --git a/dev/devdocs/subarrays/index.html b/dev/devdocs/subarrays/index.html index 77353cc3..16095e17 100644 --- a/dev/devdocs/subarrays/index.html +++ b/dev/devdocs/subarrays/index.html @@ -69,4 +69,4 @@ 3 2

then A[2:2:4,:] does not have uniform stride, so we cannot guarantee efficient linear indexing. Since we have to base this decision based purely on types encoded in the parameters of the SubArray, S = view(A, 2:2:4, :) cannot implement efficient linear indexing.

A few details

+S = view(A, :, :, 1:1) # Appending extra indices is supported

Naively, you'd think you could just set S.parent = A and S.indices = (:,:,1:1), but supporting this dramatically complicates the reindexing process, especially for views of views. Not only do you need to dispatch on the types of the stored indices, but you need to examine whether a given index is the final one and "merge" any remaining stored indices together. This is not an easy task, and even worse: it's slow since it implicitly depends upon linear indexing.

Fortunately, this is precisely the computation that ReshapedArray performs, and it does so linearly if possible. Consequently, view ensures that the parent array is the appropriate dimensionality for the given indices by reshaping it if needed. The inner SubArray constructor ensures that this invariant is satisfied.

  • CartesianIndex and arrays thereof throw a nasty wrench into the reindex scheme. Recall that reindex simply dispatches on the type of the stored indices in order to determine how many passed indices should be used and where they should go. But with CartesianIndex, there's no longer a one-to-one correspondence between the number of passed arguments and the number of dimensions that they index into. If we return to the above example of Base.reindex(S1, S1.indices, (i, j)), you can see that the expansion is incorrect for i, j = CartesianIndex(), CartesianIndex(2,1). It should skip the CartesianIndex() entirely and return:

    (CartesianIndex(2,1)[1], S1.indices[2], S1.indices[3][CartesianIndex(2,1)[2]])

    Instead, though, we get:

    (CartesianIndex(), S1.indices[2], S1.indices[3][CartesianIndex(2,1)])

    Doing this correctly would require combined dispatch on both the stored and passed indices across all combinations of dimensionalities in an intractable manner. As such, reindex must never be called with CartesianIndex indices. Fortunately, the scalar case is easily handled by first flattening the CartesianIndex arguments to plain integers. Arrays of CartesianIndex, however, cannot be split apart into orthogonal pieces so easily. Before attempting to use reindex, view must ensure that there are no arrays of CartesianIndex in the argument list. If there are, it can simply "punt" by avoiding the reindex calculation entirely, constructing a nested SubArray with two levels of indirection instead.

  • diff --git a/dev/devdocs/sysimg/index.html b/dev/devdocs/sysimg/index.html index fd265668..8afefc2e 100644 --- a/dev/devdocs/sysimg/index.html +++ b/dev/devdocs/sysimg/index.html @@ -6,4 +6,4 @@ ga('create', 'UA-28835595-9', 'auto'); ga('send', 'pageview', {'page': location.pathname + location.search + location.hash}); -

    System Image Building

    Building the Julia system image

    Julia ships with a preparsed system image containing the contents of the Base module, named sys.ji. This file is also precompiled into a shared library called sys.{so,dll,dylib} on as many platforms as possible, so as to give vastly improved startup times. On systems that do not ship with a precompiled system image file, one can be generated from the source files shipped in Julia's DATAROOTDIR/julia/base folder.

    This operation is useful for multiple reasons. A user may:

    • Build a precompiled shared library system image on a platform that did not ship with one, thereby improving startup times.
    • Modify Base, rebuild the system image and use the new Base next time Julia is started.
    • Include a userimg.jl file that includes packages into the system image, thereby creating a system image that has packages embedded into the startup environment.

    The PackageCompiler.jl package contains convenient wrapper functions to automate this process.

    System image optimized for multiple microarchitectures

    The system image can be compiled simultaneously for multiple CPU microarchitectures under the same instruction set architecture (ISA). Multiple versions of the same function may be created with minimum dispatch point inserted into shared functions in order to take advantage of different ISA extensions or other microarchitecture features. The version that offers the best performance will be selected automatically at runtime based on available CPU features.

    Specifying multiple system image targets

    A multi-microarchitecture system image can be enabled by passing multiple targets during system image compilation. This can be done either with the JULIA_CPU_TARGET make option or with the -C command line option when running the compilation command manually. Multiple targets are separated by ; in the option string. The syntax for each target is a CPU name followed by multiple features separated by ,. All features supported by LLVM are supported and a feature can be disabled with a - prefix. (+ prefix is also allowed and ignored to be consistent with LLVM syntax). Additionally, a few special features are supported to control the function cloning behavior.

    1. clone_all

      By default, only functions that are the most likely to benefit from the microarchitecture features will be cloned. When clone_all is specified for a target, however, all functions in the system image will be cloned for the target. The negative form -clone_all can be used to prevent the built-in heuristic from cloning all functions.

    2. base(<n>)

      Where <n> is a placeholder for a non-negative number (e.g. base(0), base(1)). By default, a partially cloned (i.e. not clone_all) target will use functions from the default target (first one specified) if a function is not cloned. This behavior can be changed by specifying a different base with the base(<n>) option. The nth target (0-based) will be used as the base target instead of the default (0th) one. The base target has to be either 0 or another clone_all target. Specifying a non-clone_all target as the base target will cause an error.

    3. opt_size

      This causes the function for the target to be optimized for size when there isn't a significant runtime performance impact. This corresponds to -Os GCC and Clang option.

    4. min_size

      This causes the function for the target to be optimized for size that might have a significant runtime performance impact. This corresponds to -Oz Clang option.

    As an example, at the time of this writing, the following string is used in the creation of the official x86_64 Julia binaries downloadable from julialang.org:

    generic;sandybridge,-xsaveopt,clone_all;haswell,-rdrnd,base(1)

    This creates a system image with three separate targets; one for a generic x86_64 processor, one with a sandybridge ISA (explicitly excluding xsaveopt) that explicitly clones all functions, and one targeting the haswell ISA, based off of the sandybridge sysimg version, and also excluding rdrnd. When a Julia implementation loads the generated sysimg, it will check the host processor for matching CPU capability flags, enabling the highest ISA level possible. Note that the base level (generic) requires the cx16 instruction, which is disabled in some virtualization software and must be enabled for the generic target to be loaded. Alternatively, a sysimg could be generated with the target generic,-cx16 for greater compatibility, however note that this may cause performance and stability problems in some code.

    Implementation overview

    This is a brief overview of different part involved in the implementation. See code comments for each components for more implementation details.

    1. System image compilation

      The parsing and cloning decision are done in src/processor*. We currently support cloning of function based on the present of loops, simd instructions, or other math operations (e.g. fastmath, fma, muladd). This information is passed on to src/llvm-multiversioning.cpp which does the actual cloning. In addition to doing the cloning and insert dispatch slots (see comments in MultiVersioning::runOnModule for how this is done), the pass also generates metadata so that the runtime can load and initialize the system image correctly. A detail description of the metadata is available in src/processor.h.

    2. System image loading

      The loading and initialization of the system image is done in src/processor* by parsing the metadata saved during system image generation. Host feature detection and selection decision are done in src/processor_*.cpp depending on the ISA. The target selection will prefer exact CPU name match, larger vector register size, and larger number of features. An overview of this process is in src/processor.cpp.

    +

    System Image Building

    Building the Julia system image

    Julia ships with a preparsed system image containing the contents of the Base module, named sys.ji. This file is also precompiled into a shared library called sys.{so,dll,dylib} on as many platforms as possible, so as to give vastly improved startup times. On systems that do not ship with a precompiled system image file, one can be generated from the source files shipped in Julia's DATAROOTDIR/julia/base folder.

    This operation is useful for multiple reasons. A user may:

    • Build a precompiled shared library system image on a platform that did not ship with one, thereby improving startup times.
    • Modify Base, rebuild the system image and use the new Base next time Julia is started.
    • Include a userimg.jl file that includes packages into the system image, thereby creating a system image that has packages embedded into the startup environment.

    The PackageCompiler.jl package contains convenient wrapper functions to automate this process.

    System image optimized for multiple microarchitectures

    The system image can be compiled simultaneously for multiple CPU microarchitectures under the same instruction set architecture (ISA). Multiple versions of the same function may be created with minimum dispatch point inserted into shared functions in order to take advantage of different ISA extensions or other microarchitecture features. The version that offers the best performance will be selected automatically at runtime based on available CPU features.

    Specifying multiple system image targets

    A multi-microarchitecture system image can be enabled by passing multiple targets during system image compilation. This can be done either with the JULIA_CPU_TARGET make option or with the -C command line option when running the compilation command manually. Multiple targets are separated by ; in the option string. The syntax for each target is a CPU name followed by multiple features separated by ,. All features supported by LLVM are supported and a feature can be disabled with a - prefix. (+ prefix is also allowed and ignored to be consistent with LLVM syntax). Additionally, a few special features are supported to control the function cloning behavior.

    1. clone_all

      By default, only functions that are the most likely to benefit from the microarchitecture features will be cloned. When clone_all is specified for a target, however, all functions in the system image will be cloned for the target. The negative form -clone_all can be used to prevent the built-in heuristic from cloning all functions.

    2. base(<n>)

      Where <n> is a placeholder for a non-negative number (e.g. base(0), base(1)). By default, a partially cloned (i.e. not clone_all) target will use functions from the default target (first one specified) if a function is not cloned. This behavior can be changed by specifying a different base with the base(<n>) option. The nth target (0-based) will be used as the base target instead of the default (0th) one. The base target has to be either 0 or another clone_all target. Specifying a non-clone_all target as the base target will cause an error.

    3. opt_size

      This causes the function for the target to be optimized for size when there isn't a significant runtime performance impact. This corresponds to -Os GCC and Clang option.

    4. min_size

      This causes the function for the target to be optimized for size that might have a significant runtime performance impact. This corresponds to -Oz Clang option.

    As an example, at the time of this writing, the following string is used in the creation of the official x86_64 Julia binaries downloadable from julialang.org:

    generic;sandybridge,-xsaveopt,clone_all;haswell,-rdrnd,base(1)

    This creates a system image with three separate targets; one for a generic x86_64 processor, one with a sandybridge ISA (explicitly excluding xsaveopt) that explicitly clones all functions, and one targeting the haswell ISA, based off of the sandybridge sysimg version, and also excluding rdrnd. When a Julia implementation loads the generated sysimg, it will check the host processor for matching CPU capability flags, enabling the highest ISA level possible. Note that the base level (generic) requires the cx16 instruction, which is disabled in some virtualization software and must be enabled for the generic target to be loaded. Alternatively, a sysimg could be generated with the target generic,-cx16 for greater compatibility, however note that this may cause performance and stability problems in some code.

    Implementation overview

    This is a brief overview of different part involved in the implementation. See code comments for each components for more implementation details.

    1. System image compilation

      The parsing and cloning decision are done in src/processor*. We currently support cloning of function based on the present of loops, simd instructions, or other math operations (e.g. fastmath, fma, muladd). This information is passed on to src/llvm-multiversioning.cpp which does the actual cloning. In addition to doing the cloning and insert dispatch slots (see comments in MultiVersioning::runOnModule for how this is done), the pass also generates metadata so that the runtime can load and initialize the system image correctly. A detail description of the metadata is available in src/processor.h.

    2. System image loading

      The loading and initialization of the system image is done in src/processor* by parsing the metadata saved during system image generation. Host feature detection and selection decision are done in src/processor_*.cpp depending on the ISA. The target selection will prefer exact CPU name match, larger vector register size, and larger number of features. An overview of this process is in src/processor.cpp.

    diff --git a/dev/devdocs/types/index.html b/dev/devdocs/types/index.html index d249a1e8..799ce5c9 100644 --- a/dev/devdocs/types/index.html +++ b/dev/devdocs/types/index.html @@ -139,4 +139,4 @@ f(nothing, 2.0)

    上述例子告诉我们:当 x 的类型是空集 nothing::Nothing 时,y 的类型就没有任何限制了。此时方法标签中字段 y 可以是任何类型,即 y::Any。确实,下面两个类型是等价的:

    (Tuple{Union{Nothing,T},T} where T) == Union{Tuple{Nothing,Any}, Tuple{T,T} where T}

    一般的规则是:如果出现在共变位置的一个具体变量只被子类型算法(subtyping algorithm)使用一次,则该具体变量的行为就会像一个抽象变量。上例中,当 x 类型为空时 Nothing,集合 Union{Nothing,T} 中的类型 T 不起作用,即 T 只在第二个槽中被用到。此时,无论把 Tuple{T} where T 中的 T 限制为具体类型还是不限制,该类型都等价于 Tuple{Any}

    当变量出现在非共变 位置时,无论是否被使用,该变量都不再是具体变量。否则类型的行为就会因为比较对象类型的不同而不同,从而违反传递律(transitive)。例如,

    Tuple{Int,Int8,Vector{Integer}} <: Tuple{T,T,Vector{Union{Integer,T}}} where T

    如果忽略掉合集 Union 内部的 T,则 T 就是具体的,且上述判断结果是 “否”,因为左侧元组前两个成分的类型是不同的。这两个类型不相同。再看下例:

    Tuple{Int,Int8,Vector{Any}} <: Tuple{T,T,Vector{Union{Integer,T}}} where T

    此处合集 Union 内的 T 是不能被忽略的,因为 T 必须等于 Any,即 T == Any。所以 T 不能是具体的,且判断结果为“真”。所以,类型 T 的具体还是抽象是受制于其他类型特征的。这是不被接受的,因为类型的含义必须是清晰和自洽的。所以,向量 Vector 之内的 T 需要同时考虑这两种情况。

    对角变量的子类型

    对角变量的子系统算法(substyping algorithm)有两个成分:(1)确定变量出现次数;(2)确保对角变量只包含具体类型。

    第一个任务由两个计数器完成。环境中的每个自由变量都有两个计数器 occurs_invoccurs_cov (在文件 src/subtype.c 中),分别用于追踪不变和共变的出现次数。如果 occurs_inv == 0 && occurs_cov > 1 则这个变量就是对角的。

    第二个任务通过在变量下界添加一个条件实现。子类型算法在运行过程中会逐渐压缩每个变量的界限(提高下界和降低上界),以保证子类型关系在该变量范围内能继续保持。评估完对角变量合集类型 UnionAll 后,可以查看边界的最终值。因为变量必须是具体的,所以如果其下边界不是具体类型的子类型,就会产生矛盾。例如,抽象类型 AbstractArray 不可能是一个具体类型的子类型,而具体类型 Int 则可以,空类型 Bottom 也可以。如果下边界没通过该测试,算法将终止并返回 false

    例如,如果 TUnion{Int,String} 的上位类型,则 Tuple{Int,String} 将是 Tuple{T,T} where T 的子集,即 Tuple{Int,String} <: Tuple{T,T} where T 的返回值将为真。但 Union{Int,String} 是一个抽象类型,所以上述关系不成立。

    具体性判断是由函数 is_leaf_bound 完成的。注意该函数与函数 jl_is_leaf_type 稍微有点不同,因为其对类型 Bottom 的返回值也为真 true。该函数目前是启发式的,无法捕获所有的具体类型。该函数的困难在于,其他变量类型的界限会影响当下变量下界限的具体与否。例如,只有当 T 的上界限和下界限都是 Int 时,类型 Vector{T} 才和具体类型 Vector{Int} 相同。目前,设计者还没有想出一个完备的算法来解决该问题。

    内部机制

    大部分类型处理操作都存储在 jltypes.csubtype.c 这两个文件中。了解自类型系统的最好方式是查看其工作方式。用 make debug 创建且在调试器中运行程序。手册gdb debugging tips章中有一些有用的建议。

    因为 REPL 中也经常使用子类型代码 – 这些代码中的断点也经常被触发。所以定义下面函数并在 jl_breakpoint 中设定一个断点将非常方便:

    julia> function mysubtype(a,b)
                ccall(:jl_breakpoint, Cvoid, (Any,), nothing)
                a <: b
    -       end

    一旦该断点被触发,你就可以在其他函数中设定断点了。

    作为热身,试一下下面代码

    mysubtype(Tuple{Int, Float64}, Tuple{Integer, Real})

    你也可以用一个更复杂的例子让其变得更有趣:

    mysubtype(Tuple{Array{Int,2}, Int8}, Tuple{Array{T}, T} where T)

    子类型和方法排序

    函数 type_morespecific 可用来对函数的方法列表从最具特异行到最不具特异性进行部分排序(partial order)。特异性是严格的:如果 ab 更特异,则 b 就不比 a 更特异。

    如果 ab 的严格子类型(strict subtype),那么 a 就自动的比 b 更特异。接下来,函数 type_morespecific 还引进了一些不太形式化的规则。例如,子类型 subtype 对参数的数量敏感,而函数 type_morespecific 则不敏感。特别的,Tuple{Int,AbstractFloat}Tuple{Integer} 更特异,虽然前者不是后者的子类型。此外, Tuple{Int,AbstractFloat}Tuple{Integer,Float64} 不存在特异性关系。类似的,Tuple{Int,Vararg{Int}} 不是 Tuple{Integer} 的子类型,但前者比后者更特异。但是,长度确实也影响特异性关系morespecific,如 Tuple{Int,Int}Tuple{Int,Vararg{Int}} 更特异。

    要调试方法的排序,定义下面的函数很方便:

    type_morespecific(a, b) = ccall(:jl_type_morespecific, Cint, (Any,Any), a, b)

    它可以被用来测试元组 a 是否比元组 b 更特异。

    + end

    一旦该断点被触发,你就可以在其他函数中设定断点了。

    作为热身,试一下下面代码

    mysubtype(Tuple{Int, Float64}, Tuple{Integer, Real})

    你也可以用一个更复杂的例子让其变得更有趣:

    mysubtype(Tuple{Array{Int,2}, Int8}, Tuple{Array{T}, T} where T)

    子类型和方法排序

    函数 type_morespecific 可用来对函数的方法列表从最具特异行到最不具特异性进行部分排序(partial order)。特异性是严格的:如果 ab 更特异,则 b 就不比 a 更特异。

    如果 ab 的严格子类型(strict subtype),那么 a 就自动的比 b 更特异。接下来,函数 type_morespecific 还引进了一些不太形式化的规则。例如,子类型 subtype 对参数的数量敏感,而函数 type_morespecific 则不敏感。特别的,Tuple{Int,AbstractFloat}Tuple{Integer} 更特异,虽然前者不是后者的子类型。此外, Tuple{Int,AbstractFloat}Tuple{Integer,Float64} 不存在特异性关系。类似的,Tuple{Int,Vararg{Int}} 不是 Tuple{Integer} 的子类型,但前者比后者更特异。但是,长度确实也影响特异性关系morespecific,如 Tuple{Int,Int}Tuple{Int,Vararg{Int}} 更特异。

    要调试方法的排序,定义下面的函数很方便:

    type_morespecific(a, b) = ccall(:jl_type_morespecific, Cint, (Any,Any), a, b)

    它可以被用来测试元组 a 是否比元组 b 更特异。

    diff --git a/dev/devdocs/valgrind/index.html b/dev/devdocs/valgrind/index.html index a3a3910c..30aa455c 100644 --- a/dev/devdocs/valgrind/index.html +++ b/dev/devdocs/valgrind/index.html @@ -6,4 +6,4 @@ ga('create', 'UA-28835595-9', 'auto'); ga('send', 'pageview', {'page': location.pathname + location.search + location.hash}); -

    在Julia中使用Valgrind

    Valgrind is a tool for memory debugging, memory leak detection, and profiling. This section describes things to keep in mind when using Valgrind to debug memory issues with Julia.

    General considerations

    By default, Valgrind assumes that there is no self modifying code in the programs it runs. This assumption works fine in most instances but fails miserably for a just-in-time compiler like julia. For this reason it is crucial to pass --smc-check=all-non-file to valgrind, else code may crash or behave unexpectedly (often in subtle ways).

    In some cases, to better detect memory errors using Valgrind it can help to compile julia with memory pools disabled. The compile-time flag MEMDEBUG disables memory pools in Julia, and MEMDEBUG2 disables memory pools in FemtoLisp. To build julia with both flags, add the following line to Make.user:

    CFLAGS = -DMEMDEBUG -DMEMDEBUG2

    Another thing to note: if your program uses multiple workers processes, it is likely that you want all such worker processes to run under Valgrind, not just the parent process. To do this, pass --trace-children=yes to valgrind.

    Suppressions

    Valgrind will typically display spurious warnings as it runs. To reduce the number of such warnings, it helps to provide a suppressions file to Valgrind. A sample suppressions file is included in the Julia source distribution at contrib/valgrind-julia.supp.

    The suppressions file can be used from the julia/ source directory as follows:

    $ valgrind --smc-check=all-non-file --suppressions=contrib/valgrind-julia.supp ./julia progname.jl

    Any memory errors that are displayed should either be reported as bugs or contributed as additional suppressions. Note that some versions of Valgrind are shipped with insufficient default suppressions, so that may be one thing to consider before submitting any bugs.

    Running the Julia test suite under Valgrind

    It is possible to run the entire Julia test suite under Valgrind, but it does take quite some time (typically several hours). To do so, run the following command from the julia/test/ directory:

    valgrind --smc-check=all-non-file --trace-children=yes --suppressions=$PWD/../contrib/valgrind-julia.supp ../julia runtests.jl all

    If you would like to see a report of "definite" memory leaks, pass the flags --leak-check=full --show-leak-kinds=definite to valgrind as well.

    Caveats

    Valgrind currently does not support multiple rounding modes, so code that adjusts the rounding mode will behave differently when run under Valgrind.

    In general, if after setting --smc-check=all-non-file you find that your program behaves differently when run under Valgrind, it may help to pass --tool=none to valgrind as you investigate further. This will enable the minimal Valgrind machinery but will also run much faster than when the full memory checker is enabled.

    +

    在Julia中使用Valgrind

    Valgrind is a tool for memory debugging, memory leak detection, and profiling. This section describes things to keep in mind when using Valgrind to debug memory issues with Julia.

    General considerations

    By default, Valgrind assumes that there is no self modifying code in the programs it runs. This assumption works fine in most instances but fails miserably for a just-in-time compiler like julia. For this reason it is crucial to pass --smc-check=all-non-file to valgrind, else code may crash or behave unexpectedly (often in subtle ways).

    In some cases, to better detect memory errors using Valgrind it can help to compile julia with memory pools disabled. The compile-time flag MEMDEBUG disables memory pools in Julia, and MEMDEBUG2 disables memory pools in FemtoLisp. To build julia with both flags, add the following line to Make.user:

    CFLAGS = -DMEMDEBUG -DMEMDEBUG2

    Another thing to note: if your program uses multiple workers processes, it is likely that you want all such worker processes to run under Valgrind, not just the parent process. To do this, pass --trace-children=yes to valgrind.

    Suppressions

    Valgrind will typically display spurious warnings as it runs. To reduce the number of such warnings, it helps to provide a suppressions file to Valgrind. A sample suppressions file is included in the Julia source distribution at contrib/valgrind-julia.supp.

    The suppressions file can be used from the julia/ source directory as follows:

    $ valgrind --smc-check=all-non-file --suppressions=contrib/valgrind-julia.supp ./julia progname.jl

    Any memory errors that are displayed should either be reported as bugs or contributed as additional suppressions. Note that some versions of Valgrind are shipped with insufficient default suppressions, so that may be one thing to consider before submitting any bugs.

    Running the Julia test suite under Valgrind

    It is possible to run the entire Julia test suite under Valgrind, but it does take quite some time (typically several hours). To do so, run the following command from the julia/test/ directory:

    valgrind --smc-check=all-non-file --trace-children=yes --suppressions=$PWD/../contrib/valgrind-julia.supp ../julia runtests.jl all

    If you would like to see a report of "definite" memory leaks, pass the flags --leak-check=full --show-leak-kinds=definite to valgrind as well.

    Caveats

    Valgrind currently does not support multiple rounding modes, so code that adjusts the rounding mode will behave differently when run under Valgrind.

    In general, if after setting --smc-check=all-non-file you find that your program behaves differently when run under Valgrind, it may help to pass --tool=none to valgrind as you investigate further. This will enable the minimal Valgrind machinery but will also run much faster than when the full memory checker is enabled.

    diff --git a/dev/index.html b/dev/index.html index 65930aae..bd8e325a 100644 --- a/dev/index.html +++ b/dev/index.html @@ -10,4 +10,4 @@ 集智俱乐部 -

    特别感谢集智俱乐部Julia中文文档Julia中文论坛相关服务器资源的赞助!

    ❤❤❤如果您或您所属的组织有意资助Julia中文社区的发展,欢迎前往论坛的社区板块发帖咨询。❤❤❤

    其它中文资料

    简介

    科学计算对性能一直有着最高的需求,但目前各领域的专家却大量使用较慢的动态语言来开展他们的日常工作。 偏爱动态语言有很多很好的理由,因此我们不会舍弃动态的特性。 幸运的是,现代编程语言设计与编译器技术可以大大消除性能折衷(trade-off),并提供有足够生产力的单一环境进行原型设计,而且能高效地部署性能密集型应用程序。 Julia 语言在这其中扮演了这样一个角色:它是一门灵活的动态语言,适合用于科学计算和数值计算,并且性能可与传统的静态类型语言媲美。

    由于 Julia 的编译器和其它语言比如 Python 或 R 的解释器有所不同,一开始你可能发现 Julia 的性能并不是很突出。 如果你觉得速度有点慢,我们强烈建议在尝试其他功能前,先读一读文档中的提高性能的窍门。 在理解了 Julia 的运作方式后,写出和 C 一样快的代码对你而言就是小菜一碟。

    Julia 拥有可选类型标注和多重派发这两个特性,同时还拥有很棒的性能。 这些都得归功于使用 LLVM 实现的类型推导和即时编译(JIT)技术。Julia 是一门支持过程式、函数式和面向对象的多范式语言。 它像 R、MATLAB 和 Python 一样简单,在高级数值计算方面有丰富的表现力,并且支持通用编程。 为了实现这个目标,Julia 以数学编程语言(mathematical programming languages)为基础,同时也参考了不少流行的动态语言,例如 LispPerlPythonLua、和 Ruby

    Julia 与传统动态语言最重要的区别是:

    尽管人们有时会说动态语言是“无类型的”,但实际上绝对不是这样的:每一个对象都有一个类型,无论它是基础的类型(primitive)还是用户自定义的类型。 大多数的动态语言都缺乏类型声明,这意味着程序员无法告诉编译器值的类型,也就无法显式地讨论类型。 另一方面,在静态语言中,往往必须标注对象的类型。但类型只在编译期才存在,而无法在运行时进行操作和表达。 而在 Julia 中,类型本身是运行时的对象,并可用于向编译器传达信息。

    类型系统和多重派发是 Julia 语言最主要的特征,但一般不需要显式地手动标注或使用:函数通过函数名称和不同类型参数的组合进行定义,在调用时会派发到最接近(most specific)的定义上去。这样的编程模型非常适合数学化的编程,尤其是在传统的面向对象派发中,一些函数的第一个变量理论上并不“拥有”这样一个操作时。 在 Julia 中运算符只是函数的一个特殊标记——例如,为用户定义的新类型添加加法运算,你只要为 + 函数定义一个新的方法就可以了。 已有的代码就可以无缝接入这个新的类型。

    Julia 在设计之初就非常看重性能,再加上它的动态类型推导(可以被可选的类型标注增强),使得 Julia 的计算性能超过了其它的动态语言,甚至能够与静态编译语言竞争。对于大型数值问题,速度一直都是,也一直会是一个重要的关注点:在过去的几十年里,需要处理的数据量很容易与摩尔定律保持同步。

    Julia 的目标是创建一个前所未有的集易用、强大、高效于一体的语言。除此之外,Julia 还拥有以下优势:

    +

    特别感谢集智俱乐部Julia中文文档Julia中文论坛相关服务器资源的赞助!

    ❤❤❤如果您或您所属的组织有意资助Julia中文社区的发展,欢迎前往论坛的社区板块发帖咨询。❤❤❤

    其它中文资料

    简介

    科学计算对性能一直有着最高的需求,但目前各领域的专家却大量使用较慢的动态语言来开展他们的日常工作。 偏爱动态语言有很多很好的理由,因此我们不会舍弃动态的特性。 幸运的是,现代编程语言设计与编译器技术可以大大消除性能折衷(trade-off),并提供有足够生产力的单一环境进行原型设计,而且能高效地部署性能密集型应用程序。 Julia 语言在这其中扮演了这样一个角色:它是一门灵活的动态语言,适合用于科学计算和数值计算,并且性能可与传统的静态类型语言媲美。

    由于 Julia 的编译器和其它语言比如 Python 或 R 的解释器有所不同,一开始你可能发现 Julia 的性能并不是很突出。 如果你觉得速度有点慢,我们强烈建议在尝试其他功能前,先读一读文档中的提高性能的窍门。 在理解了 Julia 的运作方式后,写出和 C 一样快的代码对你而言就是小菜一碟。

    Julia 拥有可选类型标注和多重派发这两个特性,同时还拥有很棒的性能。 这些都得归功于使用 LLVM 实现的类型推导和即时编译(JIT)技术。Julia 是一门支持过程式、函数式和面向对象的多范式语言。 它像 R、MATLAB 和 Python 一样简单,在高级数值计算方面有丰富的表现力,并且支持通用编程。 为了实现这个目标,Julia 以数学编程语言(mathematical programming languages)为基础,同时也参考了不少流行的动态语言,例如 LispPerlPythonLua、和 Ruby

    Julia 与传统动态语言最重要的区别是:

    尽管人们有时会说动态语言是“无类型的”,但实际上绝对不是这样的:每一个对象都有一个类型,无论它是基础的类型(primitive)还是用户自定义的类型。 大多数的动态语言都缺乏类型声明,这意味着程序员无法告诉编译器值的类型,也就无法显式地讨论类型。 另一方面,在静态语言中,往往必须标注对象的类型。但类型只在编译期才存在,而无法在运行时进行操作和表达。 而在 Julia 中,类型本身是运行时的对象,并可用于向编译器传达信息。

    类型系统和多重派发是 Julia 语言最主要的特征,但一般不需要显式地手动标注或使用:函数通过函数名称和不同类型参数的组合进行定义,在调用时会派发到最接近(most specific)的定义上去。这样的编程模型非常适合数学化的编程,尤其是在传统的面向对象派发中,一些函数的第一个变量理论上并不“拥有”这样一个操作时。 在 Julia 中运算符只是函数的一个特殊标记——例如,为用户定义的新类型添加加法运算,你只要为 + 函数定义一个新的方法就可以了。 已有的代码就可以无缝接入这个新的类型。

    Julia 在设计之初就非常看重性能,再加上它的动态类型推导(可以被可选的类型标注增强),使得 Julia 的计算性能超过了其它的动态语言,甚至能够与静态编译语言竞争。对于大型数值问题,速度一直都是,也一直会是一个重要的关注点:在过去的几十年里,需要处理的数据量很容易与摩尔定律保持同步。

    Julia 的目标是创建一个前所未有的集易用、强大、高效于一体的语言。除此之外,Julia 还拥有以下优势:

    diff --git a/dev/manual/arrays/index.html b/dev/manual/arrays/index.html index fb0b832c..67ad4d21 100644 --- a/dev/manual/arrays/index.html +++ b/dev/manual/arrays/index.html @@ -473,4 +473,4 @@ julia> stride(V, 1) 3

    这个视图类似于从我们原来的A中每隔一列选择一列——因此当在第二维的索引之间移动时,它需要跳过相当于两个五元素列的内容:

    julia> stride(V, 2)
     10

    第三维很有趣因为它的顺序颠倒了! 因此从第一 "页" 到第二页它必须在内存中到 backwards,所以它在这一维的 strides 是负的!

    julia> stride(V, 3)
    --35

    这意味着Vpointer 实际上指向A 的内存块的中间,并且它在内存中指向元素是同时向后和向前的。 有关定义你自己的跨距数组的更多详细信息,请参阅 等步长数组的接口指南StridedVectorStridedMatrix 被认为是等步长数组的内置数组类型的方便别名,允许它们仅使用指针和步幅,来分派选择调用调整和优化后的 BLAS 和 LAPACK 函数。

    需要强调的是 strides 是关于内存而不是索引中的偏移。如果你在找在线性(单索引)索引和笛卡尔(多索引)索引间切换的方法,见 LinearIndicesCartesianIndices.

    +-35

    这意味着Vpointer 实际上指向A 的内存块的中间,并且它在内存中指向元素是同时向后和向前的。 有关定义你自己的跨距数组的更多详细信息,请参阅 等步长数组的接口指南StridedVectorStridedMatrix 被认为是等步长数组的内置数组类型的方便别名,允许它们仅使用指针和步幅,来分派选择调用调整和优化后的 BLAS 和 LAPACK 函数。

    需要强调的是 strides 是关于内存而不是索引中的偏移。如果你在找在线性(单索引)索引和笛卡尔(多索引)索引间切换的方法,见 LinearIndicesCartesianIndices.

    diff --git a/dev/manual/asynchronous-programming/index.html b/dev/manual/asynchronous-programming/index.html index 775c149f..a3e6cedb 100644 --- a/dev/manual/asynchronous-programming/index.html +++ b/dev/manual/asynchronous-programming/index.html @@ -130,4 +130,4 @@ 10 finished in 0.64 seconds 12 finished in 0.5 seconds 11 finished in 0.97 seconds -0.029772311

    不用 errormonitor(t),一个更稳健的解决方案是使用 bind(results, t),这不仅会记录任何意外故障,还会强制相关资源关闭并向上抛出错误。

    更多任务操作

    任务操作建立在称为 yieldto 的底层原始运算上。 yieldto(task, value) 挂起当前 task,然后切换到指定的 task,并使该任务的最后一个 yieldto 调用返回指定的 value。 请注意,yieldto 是使用任务式流程控制所需的唯一操作;我们总是切换到不同的任务,而不是调用和返回。 这就是为什么这个特性也被称为“对称协程”; 每个任务都使用相同的机制来回切换。

    yieldto 功能强大,但大多数 Task 的使用都不会直接调用它。思考为什么会这样。如果你切换当前 Task,你很可能会在某个时候想切换回来。但知道什么时候切换回来和那个 Task 负责切换回来需要大量的协调。例如,put!take! 是阻塞操作,当在渠道环境中使用时,维持状态以记住消费者是谁。不需要人为地记录消费 Task,正是使得 put! 比底层 yieldto 易用的原因。

    除了 yieldto 之外,也需要一些其它的基本函数来更高效地使用 Task

    Task 和事件

    多数 Task 切换是在等待如 I/O 请求的事件,由 Julia Base 里的调度器执行。调度器维持一个可运行 Task 的队列,并执行一个事件循环,来根据例如收到消息等外部事件来重启 Task

    等待一个事件的基本函数是 wait。很多对象都实现了 wait 函数;例如,给定一个 Process 对象,wait 将等待它退出。wait 通常是隐式的,例如,wait 可能发生在调用 read 时等待数据可用。

    在所有这些情况下,wait 最终会操作一个 Condition 对象,由它负责排队和重启 Task。当 Task 在一个 Condition 上调用 wait 时,该 Task 就被标记为不可执行,加到条件的队列中,并切回调度器。调度器将选择另一个 Task 来运行,或者阻止外部事件的等待。如果所有运行良好,最终一个事件处理器将在这个条件下调用 notify,使得等待该条件的 Task 又变成可运行。

    通过调用 Task 显式创建的任务,一开始并不被调度器知道。这允许你根据需要使用 yieldto 手动管理任务。 但是,当此类任务等待事件时,它仍会在事件发生时自动重新启动,正如你所期望。

    +0.029772311

    不用 errormonitor(t),一个更稳健的解决方案是使用 bind(results, t),这不仅会记录任何意外故障,还会强制相关资源关闭并向上抛出错误。

    更多任务操作

    任务操作建立在称为 yieldto 的底层原始运算上。 yieldto(task, value) 挂起当前 task,然后切换到指定的 task,并使该任务的最后一个 yieldto 调用返回指定的 value。 请注意,yieldto 是使用任务式流程控制所需的唯一操作;我们总是切换到不同的任务,而不是调用和返回。 这就是为什么这个特性也被称为“对称协程”; 每个任务都使用相同的机制来回切换。

    yieldto 功能强大,但大多数 Task 的使用都不会直接调用它。思考为什么会这样。如果你切换当前 Task,你很可能会在某个时候想切换回来。但知道什么时候切换回来和那个 Task 负责切换回来需要大量的协调。例如,put!take! 是阻塞操作,当在渠道环境中使用时,维持状态以记住消费者是谁。不需要人为地记录消费 Task,正是使得 put! 比底层 yieldto 易用的原因。

    除了 yieldto 之外,也需要一些其它的基本函数来更高效地使用 Task

    Task 和事件

    多数 Task 切换是在等待如 I/O 请求的事件,由 Julia Base 里的调度器执行。调度器维持一个可运行 Task 的队列,并执行一个事件循环,来根据例如收到消息等外部事件来重启 Task

    等待一个事件的基本函数是 wait。很多对象都实现了 wait 函数;例如,给定一个 Process 对象,wait 将等待它退出。wait 通常是隐式的,例如,wait 可能发生在调用 read 时等待数据可用。

    在所有这些情况下,wait 最终会操作一个 Condition 对象,由它负责排队和重启 Task。当 Task 在一个 Condition 上调用 wait 时,该 Task 就被标记为不可执行,加到条件的队列中,并切回调度器。调度器将选择另一个 Task 来运行,或者阻止外部事件的等待。如果所有运行良好,最终一个事件处理器将在这个条件下调用 notify,使得等待该条件的 Task 又变成可运行。

    通过调用 Task 显式创建的任务,一开始并不被调度器知道。这允许你根据需要使用 yieldto 手动管理任务。 但是,当此类任务等待事件时,它仍会在事件发生时自动重新启动,正如你所期望。

    diff --git a/dev/manual/calling-c-and-fortran-code/index.html b/dev/manual/calling-c-and-fortran-code/index.html index ffd07420..bf66623a 100644 --- a/dev/manual/calling-c-and-fortran-code/index.html +++ b/dev/manual/calling-c-and-fortran-code/index.html @@ -181,4 +181,4 @@ Libdl.dlclose(lib) # 显式关闭库

    请注意,当将 ccall 与输入元组(例如,ccall((:my_fcn, "./my_lib.so"), ...))一起使用时,库会隐式打开,并且可能不会显式关闭。

    调用规约

    ccall 的第二个参数可以选择是调用约定说明符(直接在返回类型之前)。 没有任何说明符,使用平台默认的 C 调用约定。 其他支持的约定是:stdcallcdeclfastcallthiscall(64 位Windows 上无操作)。 例如(来自base/libc.jl)我们看到与上面相同的gethostnameccall,但具有正确的Windows签名:

    hn = Vector{UInt8}(undef, 256)
     err = ccall(:gethostname, stdcall, Int32, (Ptr{UInt8}, UInt32), hn, length(hn))

    请参阅 LLVM Language Reference 来获得更多信息。

    还有一个额外的特殊调用约定 llvmcall,它允许直接插入对 LLVM 内部函数的调用。 这在针对不常见的平台(例如 GPGPU)时特别有用。 例如,对于CUDA,我们需要能够读取线程索引:

    ccall("llvm.nvvm.read.ptx.sreg.tid.x", llvmcall, Int32, ())

    与任何 ccall 一样,参数签名必须完全正确。另外,请注意,与Core.Intrinsics开放的等效Julia函数不同,没有兼容层级可以确保内在函数有意义并在当前目标上工作。

    访问全局变量

    可以使用 cglobal 函数按名称访问本地库导出的全局变量。 cglobal 的参数与 ccall 使用相同的符号规范,以及描述存储在变量中的值的类型:

    julia> cglobal((:errno, :libc), Int32)
     Ptr{Int32} @0x00007f418d0816b8

    结果是一个给出值地址的指针。 可以使用 unsafe_loadunsafe_store! 通过这个指针来操作该值。

    Note

    在名为“libc”的库中可能找不到此 errno 符号,因为这是系统编译器的实现细节。 通常标准库符号应该只通过名称访问,允许编译器填写正确的符号。 然而,这个例子中显示的 errno 符号在大多数编译器中都是特殊的,所以这里看到的值可能不是你所期望或想要的。 在任何支持多线程的系统上用 C 编译等效代码通常实际上会调用不同的函数(通过宏预处理器重载),并且可能给出与此处打印的遗留值不同的结果。

    通过指针来访问数据

    以下方法被描述为“不安全”,因为错误的指针或类型声明会导致 Julia 突然终止。

    给定一个 Ptr{T},通常可以使用 unsafe_load(ptr, [index])T 类型的内容从引用的内存复制到 Julia 对象中。 index 参数是可选的(默认为 1),并遵循基于 1 的索引的 Julia 惯例。 此函数类似于 getindexsetindex! 的行为(例如[] 访问语法)。

    返回值将是一个初始化为包含引用内存内容副本的新对象。 引用的内存可以安全地释放或释放。

    如果 TAny,则假定内存包含对 Julia 对象的引用(jl_value_t*),结果将是对该对象的引用,并且不会复制该对象。 在这种情况下,你必须小心确保对象始终对垃圾收集器可见(指针不计数,但新引用计数)以确保内存不会过早释放。 请注意,如果对象最初不是由 Julia 分配的,则新对象将永远不会被 Julia 的垃圾收集器终结。 如果 Ptr 本身实际上是一个 jl_value_t*,它可以通过 unsafe_pointer_to_objref(ptr) 转换回 Julia 对象引用。 (Julia 值 v 可以通过调用 pointer_from_objref(v) 转换为 jl_value_t* 指针,如 Ptr{Cvoid}。)

    可以使用 unsafe_store!(ptr, value, [index]) 执行反向操作(将数据写入 Ptr{T})。 目前,这仅支持原始类型或其他无指针(isbits)不可变结构类型。

    任何引发错误的操作目前可能尚未实现,应作为错误发布,以便解决。

    如果感兴趣的指针是纯数据数组(原始类型或不可变结构),则函数 unsafe_wrap(Array, ptr,dims, own = false) 可能更有用。 如果 Julia 应该“获得”底层缓冲区的所有权并在返回的 Array 对象最终确定时调用 free(ptr),则最后一个参数应该为 true。 如果省略了 own 参数或为 false,则调用者必须确保缓冲区一直存在,直到所有访问完成。

    Julia 中 Ptr 类型的算术(例如使用 +)与 C 的指针算术的行为不同。 将整数添加到 Julia 中的 Ptr 总是将指针移动一定数量的 bytes,而不是元素。 这样,通过指针运算获得的地址值不依赖于指针的元素类型。

    线程安全

    一些 C 库从不同的线程执行它们的回调,并且由于 Julia 不是线程安全的,因此你需要采取一些额外的预防措施。 特别是,你需要设置一个两层系统:C 回调应该只 安排(通过 Julia 的事件循环)执行“真实”回调。 为此,创建一个 AsyncCondition 对象并在其上创建 wait

    cond = Base.AsyncCondition()
    -wait(cond)

    传递给 C 的回调应该只通过 ccallcond.handle 作为参数传递给 :uv_async_send 并调用,注意避免任何内存分配操作或与 Julia 运行时的其他交互。

    注意,事件可能会合并,因此对 uv_async_send 的多个调用可能会导致对该条件的单个唤醒通知。

    关于 Callbacks 的更多内容

    关于如何传递 callback 到 C 库的更多细节,请参考此博客

    C++

    如需要直接易用的C++接口,即直接用Julia写封装代码,请参考 Cxx。如需封装C++库的工具,即用C++写封装/胶水代码,请参考CxxWrap

    +wait(cond)

    传递给 C 的回调应该只通过 ccallcond.handle 作为参数传递给 :uv_async_send 并调用,注意避免任何内存分配操作或与 Julia 运行时的其他交互。

    注意,事件可能会合并,因此对 uv_async_send 的多个调用可能会导致对该条件的单个唤醒通知。

    关于 Callbacks 的更多内容

    关于如何传递 callback 到 C 库的更多细节,请参考此博客

    C++

    如需要直接易用的C++接口,即直接用Julia写封装代码,请参考 Cxx。如需封装C++库的工具,即用C++写封装/胶水代码,请参考CxxWrap

    diff --git a/dev/manual/code-loading/index.html b/dev/manual/code-loading/index.html index e24c698a..2ce5bbfe 100644 --- a/dev/manual/code-loading/index.html +++ b/dev/manual/code-loading/index.html @@ -126,4 +126,4 @@ "/home/me/AnimalPackages/Dingo/src/Dingo.jl", )

    根据定义,包目录环境中的所有包都是具有预期入口点文件的子目录,因此它们的路径 映射条目始终具有此格式。

    环境堆栈

    第三种也是最后一种环境是通过覆盖其中的几个环境来组合其他环境,使每个环境中的包在单个组合环境中可用。这些复合环境称为环境堆栈。Julia的LOAD_PATH全局定义一个环境堆栈——Julia进程在其中运行的环境。如果希望Julia进程只能访问一个项目或包目录中的包,请将其设置为LOAD_PATH中的唯一条目。然而,访问一些您喜爱的工具(标准库、探查器、调试器、个人实用程序等)通常是非常有用的,即使它们不是您正在处理的项目的依赖项。通过将包含这些工具的环境添加到加载路径,您可以立即在顶层代码中访问它们,而无需将它们添加到项目中。

    组合环境堆栈组件中根、图和路径的数据结构的机制很简单:它们被作为字典进行合并, 在发生键冲突时,优先使用前面的条目而不是后面的条目。换言之,如果我们有stack = [env₁, env₂, …],那么我们有:

    roots = reduce(merge, reverse([roots₁, roots₂, …]))
     graph = reduce(merge, reverse([graph₁, graph₂, …]))
    -paths = reduce(merge, reverse([paths₁, paths₂, …]))

    带下标的 rootsᵢ, graphᵢ and pathsᵢ变量对应于在stack中包含的下标环境变量envᵢ。 使用reverse 是因为当参数字典中的键之间发生冲突时,使merge 倾向于使用最后一个参数,而不是第一个参数。这种设计有几个值得注意的特点:

    1. 主环境——即堆栈中的第一个环境,被准确地嵌入到堆栈环境中。堆栈中第一个环境的完整依赖关系图是必然被完整包括在含有所有相同版本的依赖项的堆栈环境中。
    2. 非主环境中的包能最终使用与其依赖项不兼容的版本,即使它们自己的环境是完全兼容。这种情况可能发生,当它们的一个依赖项被堆栈(通过图或路径,或两者)中某个早期环境中的版本所覆盖。

    由于主环境通常是您正在处理的项目所在的环境,而堆栈中稍后的环境包含其他工具, 因此这是正确的权衡:最好改进您的开发工具,但保持项目能工作。当这种不兼容发生时,你通常要将开发工具升级到与主项目兼容的版本。

    总结

    在软件包系统中,联邦软件包管理和精确的软件可复制性是困难但有价值的目标。结合起来,这些目标导致了一个比大多数动态语言更加复杂的包加载机制,但它也产生了通常与静态语言相关的可伸缩性和可复制性。通常,Julia用户应该能够使用内置的包管理器来管理他们的项目,而无需精确理解这些交互细节。通过调用Pkg.add("X")添加X包到对应的项目,并清晰显示相关文件,选择Pkg.activate("Y")后, 可调用import X 即可加载X包,而无需作过多考虑。

    +paths = reduce(merge, reverse([paths₁, paths₂, …]))

    带下标的 rootsᵢ, graphᵢ and pathsᵢ变量对应于在stack中包含的下标环境变量envᵢ。 使用reverse 是因为当参数字典中的键之间发生冲突时,使merge 倾向于使用最后一个参数,而不是第一个参数。这种设计有几个值得注意的特点:

    1. 主环境——即堆栈中的第一个环境,被准确地嵌入到堆栈环境中。堆栈中第一个环境的完整依赖关系图是必然被完整包括在含有所有相同版本的依赖项的堆栈环境中。
    2. 非主环境中的包能最终使用与其依赖项不兼容的版本,即使它们自己的环境是完全兼容。这种情况可能发生,当它们的一个依赖项被堆栈(通过图或路径,或两者)中某个早期环境中的版本所覆盖。

    由于主环境通常是您正在处理的项目所在的环境,而堆栈中稍后的环境包含其他工具, 因此这是正确的权衡:最好改进您的开发工具,但保持项目能工作。当这种不兼容发生时,你通常要将开发工具升级到与主项目兼容的版本。

    总结

    在软件包系统中,联邦软件包管理和精确的软件可复制性是困难但有价值的目标。结合起来,这些目标导致了一个比大多数动态语言更加复杂的包加载机制,但它也产生了通常与静态语言相关的可伸缩性和可复制性。通常,Julia用户应该能够使用内置的包管理器来管理他们的项目,而无需精确理解这些交互细节。通过调用Pkg.add("X")添加X包到对应的项目,并清晰显示相关文件,选择Pkg.activate("Y")后, 可调用import X 即可加载X包,而无需作过多考虑。

    diff --git a/dev/manual/command-line-options/index.html b/dev/manual/command-line-options/index.html index 2badd804..94a6fc66 100644 --- a/dev/manual/command-line-options/index.html +++ b/dev/manual/command-line-options/index.html @@ -6,4 +6,4 @@ ga('create', 'UA-28835595-9', 'auto'); ga('send', 'pageview', {'page': location.pathname + location.search + location.hash}); -

    命令行选项

    以下是启动 julia 时可用的命令行选项的完整列表:

    选项描述
    -v, --version显示版本信息
    -h, --help显示命令行参数
    --project[={<dir>|@.}]将 <dir> 设置为主项目/环境。默认的 @. 选项将搜索父目录,直至找到 Project.toml 或 JuliaProject.toml 文件。
    -J, --sysimage <file>用指定的系统镜像文件(system image file)启动
    -H, --home <dir>设置 julia 可执行文件的路径
    --startup-file={yes|no}是否载入 ~/.julia/config/startup.jl
    --handle-signals={yes|no}开启或关闭 Julia 默认的 signal handlers
    --sysimage-native-code={yes|no}在可能的情况下,使用系统镜像里的原生代码
    --compiled-modules={yes|no}开启或关闭 module 的增量预编译功能
    -e, --eval <expr>执行 <expr>
    -E, --print <expr>执行 <expr> 并显示结果
    -L, --load <file>立即在所有进程中载入 <file>
    -t, --threads {N|auto}开启 N 个线程:auto 将 N 设置为当前 CPU 线程数,但这个行为可能在以后版本有所变动。
    -p, --procs {N|auto}这里的整数 N 表示启动 N 个额外的工作进程;auto 表示启动与 CPU 线程数目(logical cores)一样多的进程
    --machine-file <file><file> 中列出的主机上运行进程
    -i交互式模式;REPL 运行且 isinteractive() 为 true
    -q, --quiet安静的启动;REPL 启动时无横幅,不显示警告
    --banner={yes|no|auto}开启或关闭 REPL 横幅
    --color={yes|no|auto}开启或关闭文字颜色
    --history-file={yes|no}载入或导出历史记录
    --depwarn={yes|no|error}开启或关闭语法弃用警告,error 表示将弃用警告转换为错误。
    --warn-overwrite={yes|no}开启或关闭“method overwrite”警告
    -C, --cpu-target <target>设置 <target> 来限制使用 CPU 的某些特性;设置为 help 可以查看可用的选项
    -O, --optimize={0,1,2,3}设置编译器优化级别(若未配置此选项,则默认等级为2;若配置了此选项却没指定具体级别,则默认级别为3)。
    --min-optlevel={0,1,2,3}设置每个模块加载的优化下限(默认为 0)
    -g, -g <level>开启或设置 debug 信息的生成等级。若未配置此选项,则默认 debug 信息的级别为 1;若配置了此选项却没指定具体级别,则默认级别为 2。
    --inline={yes|no}控制是否允许函数内联,此选项会覆盖源文件中的 @inline 声明
    --check-bounds={yes|no|auto}进行边界检查,总是、从不、或依照宏@inbounds声明
    --math-mode={ieee,fast}开启或关闭非安全的浮点数代数计算优化,此选项会覆盖源文件中的 @fastmath 声明
    --code-coverage={none|user|all}对源文件中每行代码执行的次数计数
    --code-coverage等价于 --code-coverage=user
    --track-allocation={none|user|all}对源文件中每行代码的内存分配计数,单位 byte
    --track-allocation等价于 --track-allocation=user
    Julia 1.1

    在 Julia 1.0 中,默认的 --project=@. 选项不会在 Git 仓库的根目录中寻找 Project.toml 文件。从 Julia 1.1 开始,此选项会在其中寻找该文件。

    +

    命令行选项

    以下是启动 julia 时可用的命令行选项的完整列表:

    选项描述
    -v, --version显示版本信息
    -h, --help显示命令行参数
    --project[={<dir>|@.}]将 <dir> 设置为主项目/环境。默认的 @. 选项将搜索父目录,直至找到 Project.toml 或 JuliaProject.toml 文件。
    -J, --sysimage <file>用指定的系统镜像文件(system image file)启动
    -H, --home <dir>设置 julia 可执行文件的路径
    --startup-file={yes|no}是否载入 ~/.julia/config/startup.jl
    --handle-signals={yes|no}开启或关闭 Julia 默认的 signal handlers
    --sysimage-native-code={yes|no}在可能的情况下,使用系统镜像里的原生代码
    --compiled-modules={yes|no}开启或关闭 module 的增量预编译功能
    -e, --eval <expr>执行 <expr>
    -E, --print <expr>执行 <expr> 并显示结果
    -L, --load <file>立即在所有进程中载入 <file>
    -t, --threads {N|auto}开启 N 个线程:auto 将 N 设置为当前 CPU 线程数,但这个行为可能在以后版本有所变动。
    -p, --procs {N|auto}这里的整数 N 表示启动 N 个额外的工作进程;auto 表示启动与 CPU 线程数目(logical cores)一样多的进程
    --machine-file <file><file> 中列出的主机上运行进程
    -i交互式模式;REPL 运行且 isinteractive() 为 true
    -q, --quiet安静的启动;REPL 启动时无横幅,不显示警告
    --banner={yes|no|auto}开启或关闭 REPL 横幅
    --color={yes|no|auto}开启或关闭文字颜色
    --history-file={yes|no}载入或导出历史记录
    --depwarn={yes|no|error}开启或关闭语法弃用警告,error 表示将弃用警告转换为错误。
    --warn-overwrite={yes|no}开启或关闭“method overwrite”警告
    -C, --cpu-target <target>设置 <target> 来限制使用 CPU 的某些特性;设置为 help 可以查看可用的选项
    -O, --optimize={0,1,2,3}设置编译器优化级别(若未配置此选项,则默认等级为2;若配置了此选项却没指定具体级别,则默认级别为3)。
    --min-optlevel={0,1,2,3}设置每个模块加载的优化下限(默认为 0)
    -g, -g <level>开启或设置 debug 信息的生成等级。若未配置此选项,则默认 debug 信息的级别为 1;若配置了此选项却没指定具体级别,则默认级别为 2。
    --inline={yes|no}控制是否允许函数内联,此选项会覆盖源文件中的 @inline 声明
    --check-bounds={yes|no|auto}进行边界检查,总是、从不、或依照宏@inbounds声明
    --math-mode={ieee,fast}开启或关闭非安全的浮点数代数计算优化,此选项会覆盖源文件中的 @fastmath 声明
    --code-coverage={none|user|all}对源文件中每行代码执行的次数计数
    --code-coverage等价于 --code-coverage=user
    --track-allocation={none|user|all}对源文件中每行代码的内存分配计数,单位 byte
    --track-allocation等价于 --track-allocation=user
    Julia 1.1

    在 Julia 1.0 中,默认的 --project=@. 选项不会在 Git 仓库的根目录中寻找 Project.toml 文件。从 Julia 1.1 开始,此选项会在其中寻找该文件。

    diff --git a/dev/manual/complex-and-rational-numbers/index.html b/dev/manual/complex-and-rational-numbers/index.html index 0107d1e4..f3be450c 100644 --- a/dev/manual/complex-and-rational-numbers/index.html +++ b/dev/manual/complex-and-rational-numbers/index.html @@ -187,4 +187,4 @@ true julia> 1//3 - 0.33 -0.0033333333333332993 +0.0033333333333332993 diff --git a/dev/manual/constructors/index.html b/dev/manual/constructors/index.html index bf2ae498..f13de2fb 100644 --- a/dev/manual/constructors/index.html +++ b/dev/manual/constructors/index.html @@ -212,4 +212,4 @@ Closest candidates are: SummedArray(::Vector{T}) where T at none:4 Stacktrace: -[...]

    此构造函数将会被 SummedArray(a) 这种写法触发。new{T,S} 的这种写法允许指定待构建类型的参数,也就是说调用它会返回一个 SummedArray{T,S} 的实例。new{T,S} 也可以用于其它构造函数的定义中,但为了方便,Julia 会根据正在构造的类型自动推导出 new{} 花括号里的参数(如果可行的话)。

    +[...]

    此构造函数将会被 SummedArray(a) 这种写法触发。new{T,S} 的这种写法允许指定待构建类型的参数,也就是说调用它会返回一个 SummedArray{T,S} 的实例。new{T,S} 也可以用于其它构造函数的定义中,但为了方便,Julia 会根据正在构造的类型自动推导出 new{} 花括号里的参数(如果可行的话)。

    diff --git a/dev/manual/control-flow/index.html b/dev/manual/control-flow/index.html index bc563bf5..e189c461 100644 --- a/dev/manual/control-flow/index.html +++ b/dev/manual/control-flow/index.html @@ -364,4 +364,4 @@ # operate on file f finally close(f) -end

    当控制流离开 try 代码块(例如,遇到 return,或者正常结束),close(f) 就会被执行。如果 try 代码块由于异常退出,这个异常会继续传递。catch 代码块可以和 try 还有 finally 配合使用。这时 finally 代码块会在 catch 处理错误之后才运行。

    Tasks 任务(或协程)

    Task 是一种允许计算以更灵活的方式被中断或者恢复的流程控制特性。 我们提及它只是为了说明的完整性;详细的介绍参见:异步编程

    +end

    当控制流离开 try 代码块(例如,遇到 return,或者正常结束),close(f) 就会被执行。如果 try 代码块由于异常退出,这个异常会继续传递。catch 代码块可以和 try 还有 finally 配合使用。这时 finally 代码块会在 catch 处理错误之后才运行。

    Tasks 任务(或协程)

    Task 是一种允许计算以更灵活的方式被中断或者恢复的流程控制特性。 我们提及它只是为了说明的完整性;详细的介绍参见:异步编程

    diff --git a/dev/manual/conversion-and-promotion/index.html b/dev/manual/conversion-and-promotion/index.html index 040931a3..6bb6fa0f 100644 --- a/dev/manual/conversion-and-promotion/index.html +++ b/dev/manual/conversion-and-promotion/index.html @@ -61,4 +61,4 @@ promote_rule(::Type{BigInt}, ::Type{Int8}) = BigInt

    在后一种情况下,输出类型是 BigInt,因为 BigInt 是唯一一个足以容纳任意精度整数运算结果的类型。还要注意,不需要同时定义 promote_rule(::Type{A}, ::Type{B})promote_rule(::Type{B}, ::Type{A})——对称性隐含在类型提升过程中使用 promote_rule 的方式。

    promote_rule 函数为基础定义了 promote_type 函数,在给定任意数量的类型对象时,它返回这些值作为 promote 的参数应被提升的通用类型。因此,如果想知道在没有实际值情况下,具有确定类型的一些值会被类型提升为什么类型,可以使用 promote_type

    julia> promote_type(Int8, Int64)
     Int64

    在内部,promote_typepromote 中用于确定参数值应被转换为什么类型以便进行类型提升。但是,它本身可能是有用的。好奇的读者可以阅读 promotion.jl,该文件用大概 35 行定义了完整的类型提升规则。

    案例研究:有理数的类型提升

    最后,我们来完成关于 Julia 的有理数类型的案例研究,该案例通过以下类型提升规则相对复杂地使用了类型提升机制:

    promote_rule(::Type{Rational{T}}, ::Type{S}) where {T<:Integer,S<:Integer} = Rational{promote_type(T,S)}
     promote_rule(::Type{Rational{T}}, ::Type{Rational{S}}) where {T<:Integer,S<:Integer} = Rational{promote_type(T,S)}
    -promote_rule(::Type{Rational{T}}, ::Type{S}) where {T<:Integer,S<:AbstractFloat} = promote_type(T,S)

    第一条规则说,使用其它整数类型类型提升有理数类型会得到个有理数类型,其分子/分母类型是使用其它整数类型提升该有理数分子/分母类型的结果。第二条规则将相同的逻辑应用于两种不同的有理数类型,它们进行类型提升会得到有理数类型,其分子/分母类型是它们各自的分子/分母类型进行提升的结果。第三个也是最后一个规则规定,使用浮点数类型提升有理数类型与使用该浮点数类型提升其分子/分母类型会产生相同的类型。

    这一小部分的类型提升规则,连同该类型的构造函数和数字的默认 convert 方法,便足以使有理数与 Julia 的其它数值类型——整数、浮点数和复数——完全自然地互操作。通过以相同的方式提供类型转换方法和类型提升规则,任何用户定义的数值类型都可像 Julia 的预定义数值类型一样自然地进行互操作。

    +promote_rule(::Type{Rational{T}}, ::Type{S}) where {T<:Integer,S<:AbstractFloat} = promote_type(T,S)

    第一条规则说,使用其它整数类型类型提升有理数类型会得到个有理数类型,其分子/分母类型是使用其它整数类型提升该有理数分子/分母类型的结果。第二条规则将相同的逻辑应用于两种不同的有理数类型,它们进行类型提升会得到有理数类型,其分子/分母类型是它们各自的分子/分母类型进行提升的结果。第三个也是最后一个规则规定,使用浮点数类型提升有理数类型与使用该浮点数类型提升其分子/分母类型会产生相同的类型。

    这一小部分的类型提升规则,连同该类型的构造函数和数字的默认 convert 方法,便足以使有理数与 Julia 的其它数值类型——整数、浮点数和复数——完全自然地互操作。通过以相同的方式提供类型转换方法和类型提升规则,任何用户定义的数值类型都可像 Julia 的预定义数值类型一样自然地进行互操作。

    diff --git a/dev/manual/distributed-computing/index.html b/dev/manual/distributed-computing/index.html index a3ba4353..78ceeb0c 100644 --- a/dev/manual/distributed-computing/index.html +++ b/dev/manual/distributed-computing/index.html @@ -440,4 +440,4 @@ @printf("sum of ranks: %s\n", sr) end -MPI.Finalize()
    mpirun -np 4 ./julia example.jl
    +MPI.Finalize()
    mpirun -np 4 ./julia example.jl
    diff --git a/dev/manual/documentation/index.html b/dev/manual/documentation/index.html index cdc2d7f8..d1ff9d53 100644 --- a/dev/manual/documentation/index.html +++ b/dev/manual/documentation/index.html @@ -190,4 +190,4 @@ @__doc__ $(f)(x) = 1 $(f)(x, y) = 2 end |> esc -end

    @__doc__ has no effect when a macro that uses it is not documented.

    source +end

    @__doc__ has no effect when a macro that uses it is not documented.

    source diff --git a/dev/manual/embedding/index.html b/dev/manual/embedding/index.html index a90f5840..8af00a0f 100644 --- a/dev/manual/embedding/index.html +++ b/dev/manual/embedding/index.html @@ -155,4 +155,4 @@ printf("%s \n", jl_typeof_str(jl_exception_occurred()));

    如果您使用 支持异常的语言的 Julia C API(例如Python,C#,C ++),使用 检查是否有异常的函数 将每个调用 包装到 libjulia 中是有意义的,然后异常在宿主语言中重新抛出。

    抛出 Julia 异常

    在编写 Julia 可调用函数时,可能需要验证参数 并抛出异常表示错误。 典型的类型检查像这样:

    if (!jl_typeis(val, jl_float64_type)) {
         jl_type_error(function_name, (jl_value_t*)jl_float64_type, val);
     }

    可以使用以下函数 引发一般异常:

    void jl_error(const char *str);
    -void jl_errorf(const char *fmt, ...);

    jl_error采用 C 字符串,而 jl_errorfprintf 一样调用:

    jl_errorf("argument x = %d is too large", x);

    在这个例子中假定 x 是一个整数值。

    +void jl_errorf(const char *fmt, ...);

    jl_error采用 C 字符串,而 jl_errorfprintf 一样调用:

    jl_errorf("argument x = %d is too large", x);

    在这个例子中假定 x 是一个整数值。

    diff --git a/dev/manual/environment-variables/index.html b/dev/manual/environment-variables/index.html index 93073150..923982db 100644 --- a/dev/manual/environment-variables/index.html +++ b/dev/manual/environment-variables/index.html @@ -8,4 +8,4 @@ ga('send', 'pageview', {'page': location.pathname + location.search + location.hash});

    环境变量

    Julia 可以配置许多环境变量,一种常见的方式是直接配置操作系统环境变量,另一种更便携的方式是在 Julia 中配置。假设你要将环境变量 JULIA_EDITOR 设置为 vim,可以直接在 REPL 中输入 ENV["JULIA_EDITOR"] = "vim"(请根据具体情况对此进行修改),也可以将其添加到用户主目录中的配置文件 ~/.julia/config/startup.jl,这样做会使其永久生效。环境变量的当前值是通过执行 ENV["JULIA_EDITOR"] 来确定的。

    Julia 使用的环境变量通常以 JULIA 开头。如果调用 InteractiveUtils.versioninfo 时使用关键字参数 verbose = true,那么输出结果将列出与 Julia 相关的已定义环境变量,即包括那些名称中包含 JULIA 的环境变量。

    Note

    某些变量需要在 Julia 启动之前设置,比如 JULIA_NUM_THREADSJULIA_PROJECT,因为在启动过程中将这些变量添加到 ~/.julia/config/startup.jl 中为时已晚。在 Bash 中,环境变量可以手动设置,这可通过在 Julia 启动前运行诸如 export JULIA_NUM_THREADS=4 的命令,亦可通过向 ~/.bashrc~/.bash_profile 添加相同命令来在 Bash 每次启动时设置该变量。

    文件位置

    JULIA_BINDIR

    包含 Julia 可执行文件的目录的绝对路径,它会设置全局变量 Sys.BINDIR$JULIA_BINDIR 如果没有设置,那么 Julia 会在运行时确定 Sys.BINDIR 的值。

    在默认情况下,可执行文件是指:

    $JULIA_BINDIR/julia
     $JULIA_BINDIR/julia-debug

    全局变量 Base.DATAROOTDIR 是一个从 Sys.BINDIR 到 Julia 数据目录的相对路径。

    $JULIA_BINDIR/$DATAROOTDIR/julia/base

    上述路径是 Julia 最初搜索源文件的路径(通过 Base.find_source_file())。

    同样,全局变量 Base.SYSCONFDIR 是一个到配置文件目录的相对路径。在默认情况下,Julia 会在下列文件中搜索 startup.jl 文件(通过 Base.load_julia_startup()

    $JULIA_BINDIR/$SYSCONFDIR/julia/startup.jl
    -$JULIA_BINDIR/../etc/julia/startup.jl

    例如,在 Linux 下安装的 Julia 可执行文件位于 /bin/juliaDATAROOTDIR../shareSYSCONFDIR../etcJULIA_BINDIR 会被设置为 /bin,会有一个源文件搜索路径:

    /share/julia/base

    和一个全局配置文件搜索路径:

    /etc/julia/startup.jl

    JULIA_PROJECT

    指示哪个项目应该是初始活动项目的目录路径。 设置这个环境变量和指定--project启动选项效果一样,但是--project优先级更高。 如果变量设置为 @.,那么 Julia 会尝试从当前目录及其父目录中查找包含 Project.tomlJuliaProject.toml 文件的项目目录。 另请参阅有关 代码加载 的章节。

    Note

    JULIA_PROJECT 必须在启动 julia 前定义;于 startup.jl 中定义它对于启动的过程为时已晚。

    JULIA_LOAD_PATH

    JULIA_LOAD_PATH 环境变量用于补充全局的 Julia 变量 LOAD_PATH ,该变量可用于确定通过 importusing 可以加载哪些包(请参阅 Code Loading)。

    与 shell 使用的 PATH 变量不同, 在 JULIA_LOAD_PATH 中的空条目将会在填充 LOAD_PATH 时被扩展为 LOAD_PATH 的默认值 ["@", "@v#.#", "@stdlib"] 。这样,无论 JULIA_LOAD_PATH 是否已被设置,均可以使用 shell 脚本轻松地在加载路径前面或后面添加值。例如要将 /foo/bar 添加到 LOAD_PATH 之前,只需要使用下列脚本:

    export JULIA_LOAD_PATH="/foo/bar:$JULIA_LOAD_PATH"

    如果已经设置了 JULIA_LOAD_PATH 环境变量,那么 /foo/bar 将被添加在原有值之前。另一方面,如果 JULIA_LOAD_PATH 尚未设置,那么它会被设置为 /foo/bar: ,而这将使用 LOAD_PATH 的值扩展为 ["/foo/bar", "@", "@v#.#", "@stdlib"] 。如果 JULIA_LOAD_PATH 被设置为空字符串,那么它将被扩展为一个空的 LOAD_PATH 数组。换句话说,这个空字符串数组将被认为是零元素的数组,而非是一个空字符串单元素的数组。使用这样的加载行为是为了可以通过环境变量设置空的加载路径。如果你需要使用默认的加载路径,请不要设置这一环境变量,如果它必须有值,那么可将其设置为字符串 :

    Note

    在 Windows 上,路径元素由 ; 字符分隔,就像 Windows 上的大多数路径列表一样。 将上一段中的 : 替换为 ;

    JULIA_DEPOT_PATH

    JULIA_DEPOT_PATH 环境变量用于填充全局的 Julia 变量 DEPOT_PATH ,该变量用于控制包管理器以及 Juila 代码加载机制在何处查找包注册表、已安装的包、命名环境、克隆的存储库、缓存的预编译包映像、配置文件和 REPL 历史记录文件的默认位置。

    与 shell 使用的 PATH 变量不同,但与 JULIA_LOAD_PATH 类似, 在 JULIA_DEPOT_PATH 中的空条目将会被扩展为 DEPOT_PATH 的默认值。这样,无论 JULIA_DEPOT_PATH 是否已被设置,均可以使用 shell 脚本轻松地在仓库路径前面或后面添加值。例如要将 /foo/bar 添加到 DEPOT_PATH 之前,只需要使用下列脚本:

    export JULIA_DEPOT_PATH="/foo/bar:$JULIA_DEPOT_PATH"

    如果已经设置了 JULIA_DEPOT_PATH 环境变量,那么 /foo/bar 将被添加在原有值之前。另一方面,如果 JULIA_DEPOT_PATH 尚未设置,那么它会被设置为 /foo/bar: ,而这将使 /foo/bar 被添加到默认仓库路径之前。如果 JULIA_DEPOT_PATH 被设置为空字符串,那么它将扩展为一个空的 DEPOT_PATH 数组。换句话说,这个空字符串数组将被认为是零元素的数组,而非是一个空字符串单元素的数组。使用这样的加载行为是为了可以通过环境变量设置空的仓库路径。如果你需要使用默认的仓库路径,请不要设置这一环境变量,如果它必须有值,那么可将其设置为字符串 :

    Note

    在 Windows 上,路径元素由 ; 字符分隔,就像 Windows 上的大多数路径列表一样。 将上一段中的 : 替换为 ;

    JULIA_HISTORY

    REPL 历史文件中 REPL.find_hist_file() 的绝对路径。如果没有设置 $JULIA_HISTORY,那么 REPL.find_hist_file() 默认为

    $(DEPOT_PATH[1])/logs/repl_history.jl

    JULIA_PKG_SERVER

    Pkg.jl 使用,用于下载软件包和更新注册表。默认情况下,Pkg 使用 https://pkg.julialang.org 来获取 Julia 包。你可以使用此环境变量来选择不同的服务器。 此外,你可以禁用 PkgServer 协议的使用,并通过设置直接从它们的主机(GitHub、GitLab 等)访问包:

    export JULIA_PKG_SERVER=""

    外部应用

    JULIA_SHELL

    Julia 用来执行外部命令的 shell 的绝对路径(通过 Base.repl_cmd())。默认为环境变量 $SHELL,如果 $SHELL 未设置,则为 /bin/sh

    Note

    在 Windows 上,此环境变量将被忽略,并且外部命令会直接被执行。

    JULIA_EDITOR

    InteractiveUtils.editor() 的返回值–编辑器,例如,InteractiveUtils.edit,会启动偏好编辑器,比如 vim

    $JULIA_EDITOR 优先于 $VISUAL,而后者优先于 $EDITOR。如果这些环境变量都没有设置,那么在 Windows 和 OS X 上会设置为 open,或者 /etc/alternatives/editor(如果存在的话),否则为 emacs

    并行

    JULIA_CPU_THREADS

    改写全局变量 Base.Sys.CPU_THREADS,逻辑 CPU 核心数。

    JULIA_WORKER_TIMEOUT

    一个 Float64 值,用来确定 Distributed.worker_timeout() 的值(默认:60.0)。此函数提供 worker 进程在死亡之前等待 master 进程建立连接的秒数。

    JULIA_NUM_THREADS

    一个无符号 64 位整数 (uint64_t),用于设置 Julia 可用的最大线程数。 如果$JULIA_NUM_THREADS 不为正数或未设置,或者无法通过系统调用确定CPU 线程数,则将线程数设置为1

    如果$JULIA_NUM_THREADS 设置为auto,则线程数将设置为CPU线程数。

    Note

    JULIA_NUM_THREADS 必须在启动 julia 之前定义; 启动过程中在startup.jl 中定义它是不能奏效的。

    Julia 1.5

    在 Julia 1.5 和更高版本中,也可在启动时使用 -t/--threads 命令行参数指定线程数。

    Julia 1.7

    $JULIA_NUM_THREADSauto 值需要 Julia 1.7 或更高版本。

    JULIA_THREAD_SLEEP_THRESHOLD

    如果被设置为字符串,并且以大小写敏感的子字符串 "infinite" 开头,那么自旋线程从不睡眠。否则,$JULIA_THREAD_SLEEP_THRESHOLD 被解释为一个无符号 64 位整数(uint64_t),并且提供以纳秒为单位的自旋线程睡眠的时间量。

    JULIA_EXCLUSIVE

    如果设置为 0 以外的任何值,那么 Julia 的线程策略与在专用计算机上一致:主线程在 proc 0 上且线程间是关联的。否则,Julia 让操作系统处理线程策略。

    REPL 格式化输出

    决定 REPL 应当如何格式化输出的环境变量。通常,这些变量应当被设置为 ANSI 终端转义序列。Julia 提供了具有相同功能的高级接口;请参阅 Julia REPL 章节。

    JULIA_ERROR_COLOR

    Base.error_color()(默认值:亮红,"\033[91m"),errors 在终端中的格式。

    JULIA_WARN_COLOR

    Base.warn_color()(默认值:黄,"\033[93m"),warnings 在终端中的格式。

    JULIA_INFO_COLOR

    Base.info_color()(默认值:青,"\033[36m"),info 在终端中的格式。

    JULIA_INPUT_COLOR

    Base.input_color()(默认值:标准,"\033[0m"),在终端中,输入应有的格式。

    JULIA_ANSWER_COLOR

    Base.answer_color()(默认值:标准,"\033[0m"),在终端中,输出应有的格式。

    调试和性能分析

    JULIA_DEBUG

    为文件或模块启动调试日志记录,请参阅 日志 了解更多信息。

    JULIA_GC_ALLOC_POOL, JULIA_GC_ALLOC_OTHER, JULIA_GC_ALLOC_PRINT

    这些环境变量取值为字符串,可以以字符 ‘r’ 开头,后接一个由三个带符号 64 位整数(int64_t)组成的、以冒号分割的列表的插值字符串。这个整数的三元组 a:b:c 代表算术序列 a, a + b, a + 2*b, ... c

    • 如果是第 n 次调用 jl_gc_pool_alloc(),并且 n 属于 $JULIA_GC_ALLOC_POOL 代表的算术序列, 那么垃圾回收是强制的。
    • 如果是第 n 次调用 maybe_collect(),并且 n 属于 $JULIA_GC_ALLOC_OTHER 代表的算术序列,那么垃圾 回收是强制的。
    • 如果是第 n 次调用 jl_gc_alloc(),并且 n 属于 $JULIA_GC_ALLOC_PRINT 代表的算术序列,那么 调用 jl_gc_pool_alloc()maybe_collect() 的次数会 被打印。

    如果这些环境变量的值以字符 ‘r' 开头,那么垃圾回收事件间的间隔是随机的。

    Note

    这些环境变量生效要求 Julia 在编译时带有垃圾收集调试支持(也就是,在构建配置中将 WITH_GC_DEBUG_ENV 设置为 1)。

    JULIA_GC_NO_GENERATIONAL

    如果设置为 0 以外的任何值,那么 Julia 的垃圾收集器将从不执行「快速扫描」内存。

    Note

    此环境变量生效要求 Julia 在编译时带有垃圾收集调试支持(也就是,在构建配置中将 WITH_GC_DEBUG_ENV 设置为 1)。

    JULIA_GC_WAIT_FOR_DEBUGGER

    如果设置为 0 以外的任何值,Julia 的垃圾收集器每当出现严重错误时将等待调试器连接而不是中止。

    Note

    此环境变量生效要求 Julia 在编译时带有垃圾收集调试支持(也就是,在构建配置中将 WITH_GC_DEBUG_ENV 设置为 1)。

    ENABLE_JITPROFILING

    如果设置为 0 以外的任何值,那么编译器将为即时(JIT)性能分析创建并注册一个事件监听器。

    Note

    此环境变量仅在使用 JIT 性能分析支持编译 Julia 时有效,使用如下之一:

    • Intel's VTune™ Amplifier(USE_INTEL_JITEVENTS 在配置中设置为1), 或
    • OProfile(USE_OPROFILE_JITEVENTS 在配置中设置为1)。
    • Perf (USE_PERF_JITEVENTS 在构建配置中设置为 1)。 默认情况下启用此集成。

    ENABLE_GDBLISTENER

    如果设置为除0之外的任何内容,则在发布版本上启用 Julia 代码的 GDB 注册。 在 Julia 的调试版本中,这始终处于启用状态。 推荐与 -g 2 一起使用。

    JULIA_LLVM_ARGS

    传递给 LLVM 后端的参数。

    +$JULIA_BINDIR/../etc/julia/startup.jl

    例如,在 Linux 下安装的 Julia 可执行文件位于 /bin/juliaDATAROOTDIR../shareSYSCONFDIR../etcJULIA_BINDIR 会被设置为 /bin,会有一个源文件搜索路径:

    /share/julia/base

    和一个全局配置文件搜索路径:

    /etc/julia/startup.jl

    JULIA_PROJECT

    指示哪个项目应该是初始活动项目的目录路径。 设置这个环境变量和指定--project启动选项效果一样,但是--project优先级更高。 如果变量设置为 @.,那么 Julia 会尝试从当前目录及其父目录中查找包含 Project.tomlJuliaProject.toml 文件的项目目录。 另请参阅有关 代码加载 的章节。

    Note

    JULIA_PROJECT 必须在启动 julia 前定义;于 startup.jl 中定义它对于启动的过程为时已晚。

    JULIA_LOAD_PATH

    JULIA_LOAD_PATH 环境变量用于补充全局的 Julia 变量 LOAD_PATH ,该变量可用于确定通过 importusing 可以加载哪些包(请参阅 Code Loading)。

    与 shell 使用的 PATH 变量不同, 在 JULIA_LOAD_PATH 中的空条目将会在填充 LOAD_PATH 时被扩展为 LOAD_PATH 的默认值 ["@", "@v#.#", "@stdlib"] 。这样,无论 JULIA_LOAD_PATH 是否已被设置,均可以使用 shell 脚本轻松地在加载路径前面或后面添加值。例如要将 /foo/bar 添加到 LOAD_PATH 之前,只需要使用下列脚本:

    export JULIA_LOAD_PATH="/foo/bar:$JULIA_LOAD_PATH"

    如果已经设置了 JULIA_LOAD_PATH 环境变量,那么 /foo/bar 将被添加在原有值之前。另一方面,如果 JULIA_LOAD_PATH 尚未设置,那么它会被设置为 /foo/bar: ,而这将使用 LOAD_PATH 的值扩展为 ["/foo/bar", "@", "@v#.#", "@stdlib"] 。如果 JULIA_LOAD_PATH 被设置为空字符串,那么它将被扩展为一个空的 LOAD_PATH 数组。换句话说,这个空字符串数组将被认为是零元素的数组,而非是一个空字符串单元素的数组。使用这样的加载行为是为了可以通过环境变量设置空的加载路径。如果你需要使用默认的加载路径,请不要设置这一环境变量,如果它必须有值,那么可将其设置为字符串 :

    Note

    在 Windows 上,路径元素由 ; 字符分隔,就像 Windows 上的大多数路径列表一样。 将上一段中的 : 替换为 ;

    JULIA_DEPOT_PATH

    JULIA_DEPOT_PATH 环境变量用于填充全局的 Julia 变量 DEPOT_PATH ,该变量用于控制包管理器以及 Juila 代码加载机制在何处查找包注册表、已安装的包、命名环境、克隆的存储库、缓存的预编译包映像、配置文件和 REPL 历史记录文件的默认位置。

    与 shell 使用的 PATH 变量不同,但与 JULIA_LOAD_PATH 类似, 在 JULIA_DEPOT_PATH 中的空条目将会被扩展为 DEPOT_PATH 的默认值。这样,无论 JULIA_DEPOT_PATH 是否已被设置,均可以使用 shell 脚本轻松地在仓库路径前面或后面添加值。例如要将 /foo/bar 添加到 DEPOT_PATH 之前,只需要使用下列脚本:

    export JULIA_DEPOT_PATH="/foo/bar:$JULIA_DEPOT_PATH"

    如果已经设置了 JULIA_DEPOT_PATH 环境变量,那么 /foo/bar 将被添加在原有值之前。另一方面,如果 JULIA_DEPOT_PATH 尚未设置,那么它会被设置为 /foo/bar: ,而这将使 /foo/bar 被添加到默认仓库路径之前。如果 JULIA_DEPOT_PATH 被设置为空字符串,那么它将扩展为一个空的 DEPOT_PATH 数组。换句话说,这个空字符串数组将被认为是零元素的数组,而非是一个空字符串单元素的数组。使用这样的加载行为是为了可以通过环境变量设置空的仓库路径。如果你需要使用默认的仓库路径,请不要设置这一环境变量,如果它必须有值,那么可将其设置为字符串 :

    Note

    在 Windows 上,路径元素由 ; 字符分隔,就像 Windows 上的大多数路径列表一样。 将上一段中的 : 替换为 ;

    JULIA_HISTORY

    REPL 历史文件中 REPL.find_hist_file() 的绝对路径。如果没有设置 $JULIA_HISTORY,那么 REPL.find_hist_file() 默认为

    $(DEPOT_PATH[1])/logs/repl_history.jl

    JULIA_PKG_SERVER

    Pkg.jl 使用,用于下载软件包和更新注册表。默认情况下,Pkg 使用 https://pkg.julialang.org 来获取 Julia 包。你可以使用此环境变量来选择不同的服务器。 此外,你可以禁用 PkgServer 协议的使用,并通过设置直接从它们的主机(GitHub、GitLab 等)访问包:

    export JULIA_PKG_SERVER=""

    外部应用

    JULIA_SHELL

    Julia 用来执行外部命令的 shell 的绝对路径(通过 Base.repl_cmd())。默认为环境变量 $SHELL,如果 $SHELL 未设置,则为 /bin/sh

    Note

    在 Windows 上,此环境变量将被忽略,并且外部命令会直接被执行。

    JULIA_EDITOR

    InteractiveUtils.editor() 的返回值–编辑器,例如,InteractiveUtils.edit,会启动偏好编辑器,比如 vim

    $JULIA_EDITOR 优先于 $VISUAL,而后者优先于 $EDITOR。如果这些环境变量都没有设置,那么在 Windows 和 OS X 上会设置为 open,或者 /etc/alternatives/editor(如果存在的话),否则为 emacs

    并行

    JULIA_CPU_THREADS

    改写全局变量 Base.Sys.CPU_THREADS,逻辑 CPU 核心数。

    JULIA_WORKER_TIMEOUT

    一个 Float64 值,用来确定 Distributed.worker_timeout() 的值(默认:60.0)。此函数提供 worker 进程在死亡之前等待 master 进程建立连接的秒数。

    JULIA_NUM_THREADS

    一个无符号 64 位整数 (uint64_t),用于设置 Julia 可用的最大线程数。 如果$JULIA_NUM_THREADS 不为正数或未设置,或者无法通过系统调用确定CPU 线程数,则将线程数设置为1

    如果$JULIA_NUM_THREADS 设置为auto,则线程数将设置为CPU线程数。

    Note

    JULIA_NUM_THREADS 必须在启动 julia 之前定义; 启动过程中在startup.jl 中定义它是不能奏效的。

    Julia 1.5

    在 Julia 1.5 和更高版本中,也可在启动时使用 -t/--threads 命令行参数指定线程数。

    Julia 1.7

    $JULIA_NUM_THREADSauto 值需要 Julia 1.7 或更高版本。

    JULIA_THREAD_SLEEP_THRESHOLD

    如果被设置为字符串,并且以大小写敏感的子字符串 "infinite" 开头,那么自旋线程从不睡眠。否则,$JULIA_THREAD_SLEEP_THRESHOLD 被解释为一个无符号 64 位整数(uint64_t),并且提供以纳秒为单位的自旋线程睡眠的时间量。

    JULIA_EXCLUSIVE

    如果设置为 0 以外的任何值,那么 Julia 的线程策略与在专用计算机上一致:主线程在 proc 0 上且线程间是关联的。否则,Julia 让操作系统处理线程策略。

    REPL 格式化输出

    决定 REPL 应当如何格式化输出的环境变量。通常,这些变量应当被设置为 ANSI 终端转义序列。Julia 提供了具有相同功能的高级接口;请参阅 Julia REPL 章节。

    JULIA_ERROR_COLOR

    Base.error_color()(默认值:亮红,"\033[91m"),errors 在终端中的格式。

    JULIA_WARN_COLOR

    Base.warn_color()(默认值:黄,"\033[93m"),warnings 在终端中的格式。

    JULIA_INFO_COLOR

    Base.info_color()(默认值:青,"\033[36m"),info 在终端中的格式。

    JULIA_INPUT_COLOR

    Base.input_color()(默认值:标准,"\033[0m"),在终端中,输入应有的格式。

    JULIA_ANSWER_COLOR

    Base.answer_color()(默认值:标准,"\033[0m"),在终端中,输出应有的格式。

    调试和性能分析

    JULIA_DEBUG

    为文件或模块启动调试日志记录,请参阅 日志 了解更多信息。

    JULIA_GC_ALLOC_POOL, JULIA_GC_ALLOC_OTHER, JULIA_GC_ALLOC_PRINT

    这些环境变量取值为字符串,可以以字符 ‘r’ 开头,后接一个由三个带符号 64 位整数(int64_t)组成的、以冒号分割的列表的插值字符串。这个整数的三元组 a:b:c 代表算术序列 a, a + b, a + 2*b, ... c

    如果这些环境变量的值以字符 ‘r' 开头,那么垃圾回收事件间的间隔是随机的。

    Note

    这些环境变量生效要求 Julia 在编译时带有垃圾收集调试支持(也就是,在构建配置中将 WITH_GC_DEBUG_ENV 设置为 1)。

    JULIA_GC_NO_GENERATIONAL

    如果设置为 0 以外的任何值,那么 Julia 的垃圾收集器将从不执行「快速扫描」内存。

    Note

    此环境变量生效要求 Julia 在编译时带有垃圾收集调试支持(也就是,在构建配置中将 WITH_GC_DEBUG_ENV 设置为 1)。

    JULIA_GC_WAIT_FOR_DEBUGGER

    如果设置为 0 以外的任何值,Julia 的垃圾收集器每当出现严重错误时将等待调试器连接而不是中止。

    Note

    此环境变量生效要求 Julia 在编译时带有垃圾收集调试支持(也就是,在构建配置中将 WITH_GC_DEBUG_ENV 设置为 1)。

    ENABLE_JITPROFILING

    如果设置为 0 以外的任何值,那么编译器将为即时(JIT)性能分析创建并注册一个事件监听器。

    Note

    此环境变量仅在使用 JIT 性能分析支持编译 Julia 时有效,使用如下之一:

    • Intel's VTune™ Amplifier(USE_INTEL_JITEVENTS 在配置中设置为1), 或
    • OProfile(USE_OPROFILE_JITEVENTS 在配置中设置为1)。
    • Perf (USE_PERF_JITEVENTS 在构建配置中设置为 1)。 默认情况下启用此集成。

    ENABLE_GDBLISTENER

    如果设置为除0之外的任何内容,则在发布版本上启用 Julia 代码的 GDB 注册。 在 Julia 的调试版本中,这始终处于启用状态。 推荐与 -g 2 一起使用。

    JULIA_LLVM_ARGS

    传递给 LLVM 后端的参数。

    diff --git a/dev/manual/faq/index.html b/dev/manual/faq/index.html index b99a2cc6..49741091 100644 --- a/dev/manual/faq/index.html +++ b/dev/manual/faq/index.html @@ -332,4 +332,4 @@ A = randn(1000, 1000) B = randn(1000, 1000) @btime $A \ $B -@btime $A * $B

    也许和其他语言不同比如Matlab或R。

    由于像这样的操作都非常直接地从相关的BLAS函数调用,这样做的原因是,

    1. 在每种语言中使用的BLAS库

    2. 并发线程的数量

    Julia 编译并使用自己的 OpenBLAS 副本,当前线程数上限为 8(或内核数)。

    修改 OpenBLAS 设置或使用不同的 BLAS 库编译 Julia,例如 Intel MKL,可能会提高性能。 你可以使用 MKL.jl,这是一个使 Julia 的线性代数使用英特尔 MKL BLAS 和 LAPACK 而不是 OpenBLAS 的包,或搜索论坛以获取有关如何使用的建议。 请注意,英特尔 MKL 不能与 Julia 捆绑在一起,因为它不是开源的。

    计算集群

    我该如何管理分布式文件系统的预编译缓存?

    在高性能计算 (HPC) 设施中使用 julia 时,同时调用 njulia 进程最多会创建 n 个预编译缓存文件的临时副本。 如果这是一个问题(缓慢和/或小型分布式文件系统),你可以:

    1. 使用 julia--compiled-modules=no 标志来关掉预编译。
    2. 使用 pushfirst!(DEPOT_PATH, private_path) 配置一个私有的可写仓库 在这里private_path是一个路径单独地到这个julia进程 也可以通过设置环境变量 JULIA_DEPOT_PATH$private_path:$HOME/.julia.
    3. 在scratch里创建到 ~/.julia/compiled的符号链接。

    Julia 版本发布

    你希望使用稳定的、长期支持的或是每日构建版本的Julia?

    Julia 的稳定版是最新发布的 Julia 版本,这是大多数人想要运行的版本。 它具有最新的功能,包括改进的性能。 Julia 的稳定版本根据 SemVer 版本化为 v1.x.y。 在作为候选版本进行几周的测试后,大约每 4-5 个月就会发布一个与新稳定版本相对应的新 Julia 次要版本。 与 LTS 版本不同,在 Julia 的另一个稳定版本发布后,稳定版本通常不会收到错误修正。 但是,始终可以升级到下一个稳定版本,因为 Julia v1.x 的每个版本都将继续运行为早期版本编写的代码。

    如果正在寻找非常稳定的代码库,你可能更喜欢 Julia 的 LTS(长期支持)版本。 Julia 当前的 LTS 版本根据 SemVer 版本为 v1.0.x; 此分支将继续接收错误修复,直到选择新的 LTS 分支,此时 v1.0.x 系列将不再收到常规错误修复,建议除最保守的用户之外的所有用户升级到新的 LTS 版本系列。作为软件包开发人员,你可能更喜欢针对 LTS 版本进行开发,以最大限度地增加可以使用你的软件包的用户数量。 根据 SemVer,为 v1.0 编写的代码将继续适用于所有未来的 LTS 和稳定版本。 一般来说,即使针对 LTS,也可以在最新的 Stable 版本中开发和运行代码,以利用改进的性能; 只要避免使用新功能(例如添加的库函数或新方法)。

    如果您想利用该语言的最新更新,您可能更喜欢 Julia 的每日构建版本,并且不介意今天可用的版本是否偶尔无法正常工作。 顾名思义,每日构建版本的发布大约每晚发布一次(取决于构建基础设施的稳定性)。 一般来说,每日构建的发布是相当安全的——你的代码不会着火。 然而,它们可能出现偶尔的版本倒退和问题,直到更彻底的预发布测试才会发现。 你可能希望针对每日构建版本进行测试,以确保在发布之前捕获影响你的用例的版本倒退。

    最后,您也可以考虑为自己从源代码构建 Julia。 此选项主要适用于那些熟悉命令行或对学习感兴趣的人。 如果你是这样的人,你可能也有兴趣阅读我们的 贡献指南

    可以在https://julialang.org/downloads/的下载页面上找到每种下载类型的链接。 请注意,并非所有版本的Julia都适用于所有平台。

    更新我的 Julia 版本后,如何转移已安装软件包的列表?

    julia 的每个次要版本都有自己的默认 环境。 因此,在安装新的 Julia 次要版本时,默认情况下你使用先前次要版本添加的包将不可用。 给定 julia 版本的环境由文件Project.tomlManifest.toml定义,文件夹中的文件与.julia/environments/中的版本号匹配,例如.julia/environments/v1.3

    如果你安装了一个新的 Julia 次要版本,比如 1.4,并且想要在它的默认环境中使用与以前版本(例如 1.3)相同的包,你可以从1.3 文件夹复制文件 Project.toml 的内容到1.4。然后,在新的 Julia 版本的会话中,输入] 键进入“包管理模式”,并运行命令 instantiate

    此操作将从复制的文件中解析一组与目标 Julia 版本兼容的可行包,并在合适时安装或更新它们。 如果你不仅要重现软件包,还要重现在以前的 Julia 版本中使用的版本,您还应该在运行 Pkg 命令 instantiate 之前复制 Manifest.toml 文件。 但是,请注意,包可能定义了兼容性约束,这些约束可能会受到更改 Julia 版本的影响,因此你在1.3中拥有的确切版本集可能不适用于1.4

    +@btime $A * $B

    也许和其他语言不同比如Matlab或R。

    由于像这样的操作都非常直接地从相关的BLAS函数调用,这样做的原因是,

    1. 在每种语言中使用的BLAS库

    2. 并发线程的数量

    Julia 编译并使用自己的 OpenBLAS 副本,当前线程数上限为 8(或内核数)。

    修改 OpenBLAS 设置或使用不同的 BLAS 库编译 Julia,例如 Intel MKL,可能会提高性能。 你可以使用 MKL.jl,这是一个使 Julia 的线性代数使用英特尔 MKL BLAS 和 LAPACK 而不是 OpenBLAS 的包,或搜索论坛以获取有关如何使用的建议。 请注意,英特尔 MKL 不能与 Julia 捆绑在一起,因为它不是开源的。

    计算集群

    我该如何管理分布式文件系统的预编译缓存?

    在高性能计算 (HPC) 设施中使用 julia 时,同时调用 njulia 进程最多会创建 n 个预编译缓存文件的临时副本。 如果这是一个问题(缓慢和/或小型分布式文件系统),你可以:

    1. 使用 julia--compiled-modules=no 标志来关掉预编译。
    2. 使用 pushfirst!(DEPOT_PATH, private_path) 配置一个私有的可写仓库 在这里private_path是一个路径单独地到这个julia进程 也可以通过设置环境变量 JULIA_DEPOT_PATH$private_path:$HOME/.julia.
    3. 在scratch里创建到 ~/.julia/compiled的符号链接。

    Julia 版本发布

    你希望使用稳定的、长期支持的或是每日构建版本的Julia?

    Julia 的稳定版是最新发布的 Julia 版本,这是大多数人想要运行的版本。 它具有最新的功能,包括改进的性能。 Julia 的稳定版本根据 SemVer 版本化为 v1.x.y。 在作为候选版本进行几周的测试后,大约每 4-5 个月就会发布一个与新稳定版本相对应的新 Julia 次要版本。 与 LTS 版本不同,在 Julia 的另一个稳定版本发布后,稳定版本通常不会收到错误修正。 但是,始终可以升级到下一个稳定版本,因为 Julia v1.x 的每个版本都将继续运行为早期版本编写的代码。

    如果正在寻找非常稳定的代码库,你可能更喜欢 Julia 的 LTS(长期支持)版本。 Julia 当前的 LTS 版本根据 SemVer 版本为 v1.0.x; 此分支将继续接收错误修复,直到选择新的 LTS 分支,此时 v1.0.x 系列将不再收到常规错误修复,建议除最保守的用户之外的所有用户升级到新的 LTS 版本系列。作为软件包开发人员,你可能更喜欢针对 LTS 版本进行开发,以最大限度地增加可以使用你的软件包的用户数量。 根据 SemVer,为 v1.0 编写的代码将继续适用于所有未来的 LTS 和稳定版本。 一般来说,即使针对 LTS,也可以在最新的 Stable 版本中开发和运行代码,以利用改进的性能; 只要避免使用新功能(例如添加的库函数或新方法)。

    如果您想利用该语言的最新更新,您可能更喜欢 Julia 的每日构建版本,并且不介意今天可用的版本是否偶尔无法正常工作。 顾名思义,每日构建版本的发布大约每晚发布一次(取决于构建基础设施的稳定性)。 一般来说,每日构建的发布是相当安全的——你的代码不会着火。 然而,它们可能出现偶尔的版本倒退和问题,直到更彻底的预发布测试才会发现。 你可能希望针对每日构建版本进行测试,以确保在发布之前捕获影响你的用例的版本倒退。

    最后,您也可以考虑为自己从源代码构建 Julia。 此选项主要适用于那些熟悉命令行或对学习感兴趣的人。 如果你是这样的人,你可能也有兴趣阅读我们的 贡献指南

    可以在https://julialang.org/downloads/的下载页面上找到每种下载类型的链接。 请注意,并非所有版本的Julia都适用于所有平台。

    更新我的 Julia 版本后,如何转移已安装软件包的列表?

    julia 的每个次要版本都有自己的默认 环境。 因此,在安装新的 Julia 次要版本时,默认情况下你使用先前次要版本添加的包将不可用。 给定 julia 版本的环境由文件Project.tomlManifest.toml定义,文件夹中的文件与.julia/environments/中的版本号匹配,例如.julia/environments/v1.3

    如果你安装了一个新的 Julia 次要版本,比如 1.4,并且想要在它的默认环境中使用与以前版本(例如 1.3)相同的包,你可以从1.3 文件夹复制文件 Project.toml 的内容到1.4。然后,在新的 Julia 版本的会话中,输入] 键进入“包管理模式”,并运行命令 instantiate

    此操作将从复制的文件中解析一组与目标 Julia 版本兼容的可行包,并在合适时安装或更新它们。 如果你不仅要重现软件包,还要重现在以前的 Julia 版本中使用的版本,您还应该在运行 Pkg 命令 instantiate 之前复制 Manifest.toml 文件。 但是,请注意,包可能定义了兼容性约束,这些约束可能会受到更改 Julia 版本的影响,因此你在1.3中拥有的确切版本集可能不适用于1.4

    diff --git a/dev/manual/functions/index.html b/dev/manual/functions/index.html index 4e2d113e..6422bf4c 100644 --- a/dev/manual/functions/index.html +++ b/dev/manual/functions/index.html @@ -333,4 +333,4 @@ 0.5 6 -4 - true

    更多阅读

    我们应该在这里提到,这远不是定义函数的完整图景。Julia 拥有一个复杂的类型系统并且允许对参数类型进行多重分派。这里给出的示例都没有为它们的参数提供任何类型注释,意味着它们可以作用于任何类型的参数。类型系统在类型中描述,而方法则描述了根据运行时参数类型上的多重分派所选择的方法定义函数。

    + true

    更多阅读

    我们应该在这里提到,这远不是定义函数的完整图景。Julia 拥有一个复杂的类型系统并且允许对参数类型进行多重分派。这里给出的示例都没有为它们的参数提供任何类型注释,意味着它们可以作用于任何类型的参数。类型系统在类型中描述,而方法则描述了根据运行时参数类型上的多重分派所选择的方法定义函数。

    diff --git a/dev/manual/getting-started/index.html b/dev/manual/getting-started/index.html index 8790049e..8e837058 100644 --- a/dev/manual/getting-started/index.html +++ b/dev/manual/getting-started/index.html @@ -33,4 +33,4 @@ $ julia Greetings! 你好! 안녕하세요? -...

    在你第一次运行 Julia 后,你应该多了一个 ~/.julia 文件夹。 你还可以新建 ~/.julia/config 文件夹和 ~/.julia/config/startup.jl 文件来配置 Julia。

    perlruby 程序类似,还有很多种运行 Julia 代码的方式,运行代码时也有很多选项:

    julia [switches] -- [programfile] [args...]

    详细的命令选项可以在这里找到 Command-line Options.

    资源

    除了本手册以外,官方网站还提供了一个有用的学习资源列表来帮助新用户学习 Julia。

    如果已经对 Julia 有所了解,你可以先看 Performance TipsWorkflow Tips

    +...

    在你第一次运行 Julia 后,你应该多了一个 ~/.julia 文件夹。 你还可以新建 ~/.julia/config 文件夹和 ~/.julia/config/startup.jl 文件来配置 Julia。

    perlruby 程序类似,还有很多种运行 Julia 代码的方式,运行代码时也有很多选项:

    julia [switches] -- [programfile] [args...]

    详细的命令选项可以在这里找到 Command-line Options.

    资源

    除了本手册以外,官方网站还提供了一个有用的学习资源列表来帮助新用户学习 Julia。

    如果已经对 Julia 有所了解,你可以先看 Performance TipsWorkflow Tips

    diff --git a/dev/manual/handling-operating-system-variation/index.html b/dev/manual/handling-operating-system-variation/index.html index 7bd20ad5..bdbd87b1 100644 --- a/dev/manual/handling-operating-system-variation/index.html +++ b/dev/manual/handling-operating-system-variation/index.html @@ -12,4 +12,4 @@ linux_specific_thing(a) else generic_thing(a) -end

    在链式嵌套的条件表达式中(包括 if/elseif/end),@static 必须在每一层都调用(括号是可选的,但是为了可读性,建议添加)。

    @static Sys.iswindows() ? :a : (@static Sys.isapple() ? :b : :c)
    +end

    在链式嵌套的条件表达式中(包括 if/elseif/end),@static 必须在每一层都调用(括号是可选的,但是为了可读性,建议添加)。

    @static Sys.iswindows() ? :a : (@static Sys.isapple() ? :b : :c)
    diff --git a/dev/manual/index.html b/dev/manual/index.html index d157aed8..dea5c56a 100644 --- a/dev/manual/index.html +++ b/dev/manual/index.html @@ -6,4 +6,4 @@ ga('create', 'UA-28835595-9', 'auto'); ga('send', 'pageview', {'page': location.pathname + location.search + location.hash}); -

    Julia 1.8 Documentation

    Welcome to the documentation for Julia 1.8.

    请阅读 release notes 以了解自上次发行以来发生了什么变化。

    Note

    The documentation is also available in PDF format: julia-1.8.5.pdf.

    简介

    科学计算对性能一直有着最高的需求,但目前各领域的专家却大量使用较慢的动态语言来开展他们的日常工作。 偏爱动态语言有很多很好的理由,因此我们不会舍弃动态的特性。 幸运的是,现代编程语言设计与编译器技术可以大大消除性能折衷(trade-off),并提供有足够生产力的单一环境进行原型设计,而且能高效地部署性能密集型应用程序。 Julia 语言在这其中扮演了这样一个角色:它是一门灵活的动态语言,适合用于科学计算和数值计算,并且性能可与传统的静态类型语言媲美。

    由于 Julia 的编译器和其它语言比如 Python 或 R 的解释器有所不同,一开始你可能发现 Julia 的性能并不是很突出。 如果你觉得速度有点慢,我们强烈建议在尝试其他功能前,先读一读文档中的提高性能的窍门部分。 一旦你理解了 Julia 的运作方式后,写出和 C 一样快的代码就是小菜一碟。

    Julia features optional typing, multiple dispatch, and good performance, achieved using type inference and just-in-time (JIT) compilation, implemented using LLVM. It is multi-paradigm, combining features of imperative, functional, and object-oriented programming. Julia provides ease and expressiveness for high-level numerical computing, in the same way as languages such as R, MATLAB, and Python, but also supports general programming. To achieve this, Julia builds upon the lineage of mathematical programming languages, but also borrows much from popular dynamic languages, including Lisp, Perl, Python, Lua, and Ruby.

    Julia 与传统动态语言最重要的区别是:

    • The core language imposes very little; Julia Base and the standard library are written in Julia itself, including primitive operations like integer arithmetic
    • A rich language of types for constructing and describing objects, that can also optionally be used to make type declarations
    • The ability to define function behavior across many combinations of argument types via multiple dispatch
    • Automatic generation of efficient, specialized code for different argument types
    • Good performance, approaching that of statically-compiled languages like C

    Although one sometimes speaks of dynamic languages as being "typeless", they are definitely not: every object, whether primitive or user-defined, has a type. The lack of type declarations in most dynamic languages, however, means that one cannot instruct the compiler about the types of values, and often cannot explicitly talk about types at all. In static languages, on the other hand, while one can – and usually must – annotate types for the compiler, types exist only at compile time and cannot be manipulated or expressed at run time. In Julia, types are themselves run-time objects, and can also be used to convey information to the compiler.

    While the casual programmer need not explicitly use types or multiple dispatch, they are the core unifying features of Julia: functions are defined on different combinations of argument types, and applied by dispatching to the most specific matching definition. This model is a good fit for mathematical programming, where it is unnatural for the first argument to "own" an operation as in traditional object-oriented dispatch. Operators are just functions with special notation – to extend addition to new user-defined data types, you define new methods for the + function. Existing code then seamlessly applies to the new data types.

    Partly because of run-time type inference (augmented by optional type annotations), and partly because of a strong focus on performance from the inception of the project, Julia's computational efficiency exceeds that of other dynamic languages, and even rivals that of statically-compiled languages. For large scale numerical problems, speed always has been, continues to be, and probably always will be crucial: the amount of data being processed has easily kept pace with Moore's Law over the past decades.

    Julia aims to create an unprecedented combination of ease-of-use, power, and efficiency in a single language. In addition to the above, some advantages of Julia over comparable systems include:

    • Free and open source (MIT licensed)
    • User-defined types are as fast and compact as built-ins
    • No need to vectorize code for performance; devectorized code is fast
    • Designed for parallelism and distributed computation
    • Lightweight "green" threading (coroutines)
    • Unobtrusive yet powerful type system
    • Elegant and extensible conversions and promotions for numeric and other types
    • Efficient support for Unicode, including but not limited to UTF-8
    • Call C functions directly (no wrappers or special APIs needed)
    • Powerful shell-like capabilities for managing other processes
    • Lisp-like macros and other metaprogramming facilities
    +

    Julia 1.8 Documentation

    Welcome to the documentation for Julia 1.8.

    请阅读 release notes 以了解自上次发行以来发生了什么变化。

    Note

    The documentation is also available in PDF format: julia-1.8.5.pdf.

    简介

    科学计算对性能一直有着最高的需求,但目前各领域的专家却大量使用较慢的动态语言来开展他们的日常工作。 偏爱动态语言有很多很好的理由,因此我们不会舍弃动态的特性。 幸运的是,现代编程语言设计与编译器技术可以大大消除性能折衷(trade-off),并提供有足够生产力的单一环境进行原型设计,而且能高效地部署性能密集型应用程序。 Julia 语言在这其中扮演了这样一个角色:它是一门灵活的动态语言,适合用于科学计算和数值计算,并且性能可与传统的静态类型语言媲美。

    由于 Julia 的编译器和其它语言比如 Python 或 R 的解释器有所不同,一开始你可能发现 Julia 的性能并不是很突出。 如果你觉得速度有点慢,我们强烈建议在尝试其他功能前,先读一读文档中的提高性能的窍门部分。 一旦你理解了 Julia 的运作方式后,写出和 C 一样快的代码就是小菜一碟。

    Julia features optional typing, multiple dispatch, and good performance, achieved using type inference and just-in-time (JIT) compilation, implemented using LLVM. It is multi-paradigm, combining features of imperative, functional, and object-oriented programming. Julia provides ease and expressiveness for high-level numerical computing, in the same way as languages such as R, MATLAB, and Python, but also supports general programming. To achieve this, Julia builds upon the lineage of mathematical programming languages, but also borrows much from popular dynamic languages, including Lisp, Perl, Python, Lua, and Ruby.

    Julia 与传统动态语言最重要的区别是:

    • The core language imposes very little; Julia Base and the standard library are written in Julia itself, including primitive operations like integer arithmetic
    • A rich language of types for constructing and describing objects, that can also optionally be used to make type declarations
    • The ability to define function behavior across many combinations of argument types via multiple dispatch
    • Automatic generation of efficient, specialized code for different argument types
    • Good performance, approaching that of statically-compiled languages like C

    Although one sometimes speaks of dynamic languages as being "typeless", they are definitely not: every object, whether primitive or user-defined, has a type. The lack of type declarations in most dynamic languages, however, means that one cannot instruct the compiler about the types of values, and often cannot explicitly talk about types at all. In static languages, on the other hand, while one can – and usually must – annotate types for the compiler, types exist only at compile time and cannot be manipulated or expressed at run time. In Julia, types are themselves run-time objects, and can also be used to convey information to the compiler.

    While the casual programmer need not explicitly use types or multiple dispatch, they are the core unifying features of Julia: functions are defined on different combinations of argument types, and applied by dispatching to the most specific matching definition. This model is a good fit for mathematical programming, where it is unnatural for the first argument to "own" an operation as in traditional object-oriented dispatch. Operators are just functions with special notation – to extend addition to new user-defined data types, you define new methods for the + function. Existing code then seamlessly applies to the new data types.

    Partly because of run-time type inference (augmented by optional type annotations), and partly because of a strong focus on performance from the inception of the project, Julia's computational efficiency exceeds that of other dynamic languages, and even rivals that of statically-compiled languages. For large scale numerical problems, speed always has been, continues to be, and probably always will be crucial: the amount of data being processed has easily kept pace with Moore's Law over the past decades.

    Julia aims to create an unprecedented combination of ease-of-use, power, and efficiency in a single language. In addition to the above, some advantages of Julia over comparable systems include:

    • Free and open source (MIT licensed)
    • User-defined types are as fast and compact as built-ins
    • No need to vectorize code for performance; devectorized code is fast
    • Designed for parallelism and distributed computation
    • Lightweight "green" threading (coroutines)
    • Unobtrusive yet powerful type system
    • Elegant and extensible conversions and promotions for numeric and other types
    • Efficient support for Unicode, including but not limited to UTF-8
    • Call C functions directly (no wrappers or special APIs needed)
    • Powerful shell-like capabilities for managing other processes
    • Lisp-like macros and other metaprogramming facilities
    diff --git a/dev/manual/integers-and-floating-point-numbers/index.html b/dev/manual/integers-and-floating-point-numbers/index.html index d37393f3..da19dc08 100644 --- a/dev/manual/integers-and-floating-point-numbers/index.html +++ b/dev/manual/integers-and-floating-point-numbers/index.html @@ -330,4 +330,4 @@ 1 julia> one(BigFloat) -1.0 +1.0 diff --git a/dev/manual/interfaces/index.html b/dev/manual/interfaces/index.html index 7a2a0c96..b5bde1d0 100644 --- a/dev/manual/interfaces/index.html +++ b/dev/manual/interfaces/index.html @@ -197,4 +197,4 @@ Base.BroadcastStyle(::Type{<:SparseMatrixCSC}) = SparseMatStyle()

    每当你定义一个 AbstractArrayStyle 的子类型,你还需要定义用于组合维度的规则,这通过为你的广播风格创建带有一个 Val(N) 参数的构造函数。例如:

    SparseVecStyle(::Val{0}) = SparseVecStyle()
     SparseVecStyle(::Val{1}) = SparseVecStyle()
     SparseVecStyle(::Val{2}) = SparseMatStyle()
    -SparseVecStyle(::Val{N}) where N = Broadcast.DefaultArrayStyle{N}()

    这些规则表明 SparseVecStyle 与 0 维或 1 维数组的组合会产生另一个 SparseVecStyle,与 2 维数组的组合会产生 SparseMatStyle,而与维度更高的数组则回退到任意维密集矩阵的框架中。这些规则允许广播为产生一维或二维输出的操作保持其稀疏表示,但为任何其它维度生成 Array

    +SparseVecStyle(::Val{N}) where N = Broadcast.DefaultArrayStyle{N}()

    这些规则表明 SparseVecStyle 与 0 维或 1 维数组的组合会产生另一个 SparseVecStyle,与 2 维数组的组合会产生 SparseMatStyle,而与维度更高的数组则回退到任意维密集矩阵的框架中。这些规则允许广播为产生一维或二维输出的操作保持其稀疏表示,但为任何其它维度生成 Array

    diff --git a/dev/manual/mathematical-operations/index.html b/dev/manual/mathematical-operations/index.html index 81fa8c00..0919ca20 100644 --- a/dev/manual/mathematical-operations/index.html +++ b/dev/manual/mathematical-operations/index.html @@ -182,4 +182,4 @@ asin acos atan acot asec acsc asinh acosh atanh acoth asech acsch sinc cosc

    所有这些函数都是单参数函数,不过 atan 也可以接收两个参数 来表示传统的 atan2 函数。

    另外,sinpi(x)cospi(x) 分别用来对 sin(pi*x)cos(pi*x) 进行更精确的计算。

    要计算角度而非弧度的三角函数,以 d 做后缀。 比如,sind(x) 计算 x 的 sine 值,其中 x 是一个角度值。 下面是角度变量的三角函数完整列表:

    sind   cosd   tand   cotd   secd   cscd
    -asind  acosd  atand  acotd  asecd  acscd

    特殊函数

    SpecialFunctions.jl 提供了许多其他的特殊数学函数。

    +asind acosd atand acotd asecd acscd

    特殊函数

    SpecialFunctions.jl 提供了许多其他的特殊数学函数。

    diff --git a/dev/manual/metaprogramming/index.html b/dev/manual/metaprogramming/index.html index 86d1337f..fefac02b 100644 --- a/dev/manual/metaprogramming/index.html +++ b/dev/manual/metaprogramming/index.html @@ -485,4 +485,4 @@ end return ind + 1 end -end

    在内部,这段代码创建了函数的两个实现:一个生成函数的实现,其使用 if @generated 中的第一个块,一个通常的函数的实现,其使用 else 块。在 if @generated 块的 then 部分中,代码与其它生成函数具有相同的语义:参数名称引用类型,且代码应返回表达式。可能会出现多个 if @generated 块,在这种情况下,生成函数的实现使用所有的 then 块,而替代实现使用所有的 else 块。

    请注意,我们在函数顶部添加了错误检查。此代码对两个版本都是通用的,且是两个版本中的运行时代码(它将被引用并返回为生成函数版本中的表达式)。这意味着局部变量的值和类型在代码生成时不可用——用于代码生成的代码只能看到参数类型。

    在这种定义方式中,代码生成功能本质上只是一种可选的优化。如果方便,编译器将使用它,否则可能选择使用通常的实现。这种方式是首选的,因为它允许编译器做出更多决策和以更多方式编译程序,还因为通常代码比由代码生成的代码更易读。但是,使用哪种实现取决于编译器实现细节,因此,两个实现的行为必须相同。

    +end

    在内部,这段代码创建了函数的两个实现:一个生成函数的实现,其使用 if @generated 中的第一个块,一个通常的函数的实现,其使用 else 块。在 if @generated 块的 then 部分中,代码与其它生成函数具有相同的语义:参数名称引用类型,且代码应返回表达式。可能会出现多个 if @generated 块,在这种情况下,生成函数的实现使用所有的 then 块,而替代实现使用所有的 else 块。

    请注意,我们在函数顶部添加了错误检查。此代码对两个版本都是通用的,且是两个版本中的运行时代码(它将被引用并返回为生成函数版本中的表达式)。这意味着局部变量的值和类型在代码生成时不可用——用于代码生成的代码只能看到参数类型。

    在这种定义方式中,代码生成功能本质上只是一种可选的优化。如果方便,编译器将使用它,否则可能选择使用通常的实现。这种方式是首选的,因为它允许编译器做出更多决策和以更多方式编译程序,还因为通常代码比由代码生成的代码更易读。但是,使用哪种实现取决于编译器实现细节,因此,两个实现的行为必须相同。

    diff --git a/dev/manual/methods/index.html b/dev/manual/methods/index.html index 943eb8fb..35002eec 100644 --- a/dev/manual/methods/index.html +++ b/dev/manual/methods/index.html @@ -353,4 +353,4 @@ function myfilter(A, kernel, ::NoPad) # Here's the "real" implementation of the core computation -end

    NoPad 被置于与其他 padding 类型一致的参数位置上,这保持了分派层级的良好组织,同时降低了歧义的可能性。而且,它扩展了「公开」的 myfilter 接口:想要显式控制 padding 的用户可以直接调用 NoPad 变量。

    +end

    NoPad 被置于与其他 padding 类型一致的参数位置上,这保持了分派层级的良好组织,同时降低了歧义的可能性。而且,它扩展了「公开」的 myfilter 接口:想要显式控制 padding 的用户可以直接调用 NoPad 变量。

    diff --git a/dev/manual/missing/index.html b/dev/manual/missing/index.html index 9a00d7d8..cedac6d0 100644 --- a/dev/manual/missing/index.html +++ b/dev/manual/missing/index.html @@ -165,4 +165,4 @@ true julia> any([false, missing]) -missing +missing diff --git a/dev/manual/modules/index.html b/dev/manual/modules/index.html index 1ad43e7c..7c160b51 100644 --- a/dev/manual/modules/index.html +++ b/dev/manual/modules/index.html @@ -114,4 +114,4 @@ # instead use accessor functions: getstdout() = Base.stdout #= best option =# # or move the assignment into the runtime: -__init__() = global mystdout = Base.stdout #= also works =#

    此处为预编译中的操作附加了若干限制,以帮助用户避免其他误操作:

    1. 调用 eval 来在另一个模块中引发副作用。当增量预编译被标记时,该操作同时会导致抛出一个警告。
    2. __init__() 已经开始执行后,在局部作用域中声明 global const(见 issue #12010,计划为此情况添加一个错误提示)
    3. 在增量预编译时替换模块是一个运行时错误。

    一些其他需要注意的点:

    1. 在源代码文件本身被修改之后,不会执行代码重载或缓存失效化处理(包括由 Pkg.update 执行的修改,此外在 Pkg.rm 执行后也没有清理操作)
    2. 变形数组的内存共享特性会被预编译忽略(每个数组样貌都会获得一个拷贝)
    3. 文件系统在编译期间和运行期间被假设为不变的,比如使用 @__FILE__/source_path() 在运行期间寻找资源、或使用 BinDeps 宏 @checked_lib。有时这是不可避免的。但是可能的话,在编译期将资源复制到模块里面是个好做法,这样在运行期间,就不需要去寻找它们了。
    4. WeakRef 对象和完成器目前在序列化器中无法被恰当地处理(在接下来的发行版中将修复)。
    5. 通常,最好避免去捕捉内部元数据对象的引用,如 MethodMethodInstanceTypeMapLevelTypeMapEntry 及这些对象的字段,因为这会迷惑序列化器,且可能会引发你不想要的结果。此操作不足以成为一个错误,但你需做好准备:系统会尝试拷贝一部分,然后创建其余部分的单个独立实例。

    在开发模块时,关闭增量预编译可能会有所帮助。命令行标记 --compiled-modules={yes|no} 可以让你切换预编译的开启和关闭。当 Julia 附加 --compiled-modules=no 启动,在载入模块和模块依赖时,编译缓存中的序列化模块会被忽略。Base.compilecache 仍可以被手动调用。此命令行标记的状态会被传递给 Pkg.build,禁止其在安装、更新、显式构建包时触发自动预编译。

    +__init__() = global mystdout = Base.stdout #= also works =#

    此处为预编译中的操作附加了若干限制,以帮助用户避免其他误操作:

    1. 调用 eval 来在另一个模块中引发副作用。当增量预编译被标记时,该操作同时会导致抛出一个警告。
    2. __init__() 已经开始执行后,在局部作用域中声明 global const(见 issue #12010,计划为此情况添加一个错误提示)
    3. 在增量预编译时替换模块是一个运行时错误。

    一些其他需要注意的点:

    1. 在源代码文件本身被修改之后,不会执行代码重载或缓存失效化处理(包括由 Pkg.update 执行的修改,此外在 Pkg.rm 执行后也没有清理操作)
    2. 变形数组的内存共享特性会被预编译忽略(每个数组样貌都会获得一个拷贝)
    3. 文件系统在编译期间和运行期间被假设为不变的,比如使用 @__FILE__/source_path() 在运行期间寻找资源、或使用 BinDeps 宏 @checked_lib。有时这是不可避免的。但是可能的话,在编译期将资源复制到模块里面是个好做法,这样在运行期间,就不需要去寻找它们了。
    4. WeakRef 对象和完成器目前在序列化器中无法被恰当地处理(在接下来的发行版中将修复)。
    5. 通常,最好避免去捕捉内部元数据对象的引用,如 MethodMethodInstanceTypeMapLevelTypeMapEntry 及这些对象的字段,因为这会迷惑序列化器,且可能会引发你不想要的结果。此操作不足以成为一个错误,但你需做好准备:系统会尝试拷贝一部分,然后创建其余部分的单个独立实例。

    在开发模块时,关闭增量预编译可能会有所帮助。命令行标记 --compiled-modules={yes|no} 可以让你切换预编译的开启和关闭。当 Julia 附加 --compiled-modules=no 启动,在载入模块和模块依赖时,编译缓存中的序列化模块会被忽略。Base.compilecache 仍可以被手动调用。此命令行标记的状态会被传递给 Pkg.build,禁止其在安装、更新、显式构建包时触发自动预编译。

    diff --git a/dev/manual/multi-threading/index.html b/dev/manual/multi-threading/index.html index 8ebfe051..a51659ba 100644 --- a/dev/manual/multi-threading/index.html +++ b/dev/manual/multi-threading/index.html @@ -121,4 +121,4 @@ end end nothing -end
  • 相关的第三种策略是使用不需要 yield 的队列。 我们目前没有在 Base 中实现无锁队列,但 Base.InvasiveLinkedListSynchronized{T} 是合适的。 这通常是用于带有事件循环的代码的好策略。 例如,这个策略被 Gtk.jl 用来管理生命周期引用计数。 在这种方法中,我们不会在终结器内部做任何显式工作,而是将其添加到队列中以在更安全的时间运行。 事实上,Julia 的任务调度器已经使用了这种方法,因此将终结器定义为 x -> @spawn do_cleanup(x) 就是这种方法的一个示例。 但是请注意,这并不控制 do_cleanup 在哪个线程上运行,因此 do_cleanup 仍需要获取锁。 如果你实现自己的队列,则不必如此,因为你只能明确地从线程中排出该队列。

  • +end
  • 相关的第三种策略是使用不需要 yield 的队列。 我们目前没有在 Base 中实现无锁队列,但 Base.InvasiveLinkedListSynchronized{T} 是合适的。 这通常是用于带有事件循环的代码的好策略。 例如,这个策略被 Gtk.jl 用来管理生命周期引用计数。 在这种方法中,我们不会在终结器内部做任何显式工作,而是将其添加到队列中以在更安全的时间运行。 事实上,Julia 的任务调度器已经使用了这种方法,因此将终结器定义为 x -> @spawn do_cleanup(x) 就是这种方法的一个示例。 但是请注意,这并不控制 do_cleanup 在哪个线程上运行,因此 do_cleanup 仍需要获取锁。 如果你实现自己的队列,则不必如此,因为你只能明确地从线程中排出该队列。

  • diff --git a/dev/manual/networking-and-streams/index.html b/dev/manual/networking-and-streams/index.html index db914aac..dfdefa29 100644 --- a/dev/manual/networking-and-streams/index.html +++ b/dev/manual/networking-and-streams/index.html @@ -126,4 +126,4 @@ end Finished connection to google.com Finished connection to julialang.org -Finished connection to github.com +Finished connection to github.com diff --git a/dev/manual/noteworthy-differences/index.html b/dev/manual/noteworthy-differences/index.html index e0d463e4..c198bba3 100644 --- a/dev/manual/noteworthy-differences/index.html +++ b/dev/manual/noteworthy-differences/index.html @@ -6,4 +6,4 @@ ga('create', 'UA-28835595-9', 'auto'); ga('send', 'pageview', {'page': location.pathname + location.search + location.hash}); -

    与其他语言的显著差异

    与 MATLAB 的显著差异

    虽然 MATLAB 用户可能会发现 Julia 的语法很熟悉,但 Julia 不是 MATLAB 的克隆。 它们之间存在重大的语法和功能差异。 以下是一些可能会使习惯于 MATLAB 的 Julia 用户感到困扰的显著差异:

    • Julia 数组使用方括号 A[i,j] 进行索引。
    • Julia 数组在分配给另一个变量时不会被复制。 在A = B之后,改变B的元素也会改变A的元素。
    • Julia 的值在向函数传递时不发生复制。如果某个函数修改了数组,这一修改对调用者是可见的。
    • Julia 不会在赋值语句中自动增长数组。 而在 MATLAB 中 a(4) = 3.2 可以创建数组 a = [0 0 0 3.2],而 a(5) = 7 可以将它增长为 a = [0 0 0 3.2 7]。如果 a 的长度小于 5 或者这个语句是第一次使用标识符 a,则相应的 Julia 语句 a[5] = 7 会抛出错误。Julia 使用 push!append! 来增长 Vector,它们比 MATLAB 的 a(end+1) = val 更高效。
    • 虚数单位 sqrt(-1) 在 Julia 中表示为 im,而不是在 MATLAB 中的 ij
    • 在 Julia 中,没有小数点的数字字面量(例如 42)会创建整数而不是浮点数。也支持任意大整数字面量。因此,某些操作(如 2^-1)将抛出 domain error,因为结果不是整数(有关的详细信息,请参阅常见问题中有关 domain errors 的条目)。 在 Julia 中,没有小数点的数字字面量(例如 42)会创建整数而不是浮点数。因此,某些操作会因为需要浮点数而抛出 domain error;例如 julia > a = -1; 2^a ,因为结果不是整数了。请参阅常见问题中有关 domain errors 的条目)。
    • 在 Julia 中,能返回多个值并将其赋值为元组,例如 (a, b) = (1, 2)a, b = 1, 2。 在 Julia 中不存在 MATLAB 的 nargout,它通常在 MATLAB 中用于根据返回值的数量执行可选工作。取而代之的是,用户可以使用可选参数和关键字参数来实现类似的功能。
    • Julia 拥有真正的一维数组。列向量的大小为 N,而不是 Nx1。例如,rand(N) 创建一个一维数组。
    • 在 Julia 中,[x,y,z] 将始终构造一个包含xyz 的 3 元数组。
      • 要在第一个维度(「垂直列」)中连接元素,请使用 vcat(x,y,z) 或用分号分隔([x; y; z])。
      • 要在第二个维度(「水平行」)中连接元素,请使用 hcat(x,y,z) 或用空格分隔([x y z])。
      • 要构造分块矩阵(在前两个维度中连接元素),请使用 hvcat 或组合空格和分号([a b; c d])。
    • 在 Julia 中,a:ba:b:c 构造 AbstractRange 对象。使用 collect(a:b) 构造一个类似 MATLAB 中完整的向量。通常,不需要调用 collect。在大多数情况下,AbstractRange 对象将像普通数组一样运行,但效率更高,因为它是懒惰求值。这种创建专用对象而不是完整数组的模式经常被使用,并且也可以在诸如 range 之类的函数中看到,或者在诸如 enumeratezip 之类的迭代器中看到。特殊对象大多可以像正常数组一样使用。
    • Julia 中的函数返回其最后一个表达式或 return 关键字的值而无需在函数定义中列出要返回的变量的名称(有关详细信息,请参阅 return 关键字)。
    • Julia 脚本可以包含任意数量的函数,并且在加载文件时,所有定义都将在外部可见。可以从当前工作目录之外的文件加载函数定义。
    • 在 Julia 中,例如 sumprodmax 的归约操作会作用到数组的每一个元素上,当调用时只有一个函数,例如 sum(A),即使 A 并不只有一个维度。
    • 在 Julia 中,调用无参数的函数时必须使用小括号,例如 rand()
    • Julia 不鼓励使用分号来结束语句。语句的结果不会自动打印(除了在 REPL 中),并且代码的一行不必使用分号结尾。println 或者 @printf 能用来打印特定输出。
    • 在 Julia 中,如果 AB 是数组,像 A == B 这样的逻辑比较运算符不会返回布尔值数组。相反地,请使用 A .== B。对于其他的像是 <> 的布尔运算符同理。
    • 在 Julia 中,运算符&|xor)进行按位操作,分别与MATLAB中的andorxor 等价,并且优先级与 Python 的按位运算符相似(不像 C)。他们可以对标量运算或者数组中逐元素运算,可以用来合并逻辑数组,但是注意运算顺序的区别:括号可能是必要的(例如,选择 A 中等于 1 或 2 的元素可使用 (A .== 1) .| (A .== 2))。
    • 在 Julia 中,集合的元素可以使用 splat 运算符 ... 来作为参数传递给函数,如 xs=[1,2]; f(xs...)
    • Julia 的 svd 将奇异值作为向量而非密集对角矩阵返回。
    • 在 Julia 中,... 不用于延续代码行。不同的是,Julia 中不完整的表达式会自动延续到下一行。
    • 在 Julia 和 MATLAB 中,变量 ans 被设置为交互式会话中提交的最后一个表达式的值。在 Julia 中与 MATLAB 不同的是,当 Julia 代码以非交互式模式运行时并不会设置 ans
    • Julia 的 struct 不支持在运行时动态地添加字段,这与 MATLAB 的 class 不同。 如需支持,请使用 Dict。Julia 中的字典不是有序的。
    • 在 Julia 中,每个模块有自身的全局作用域/命名空间,而在 MATLAB 中只有一个全局作用域。
    • 在 MATLAB 中,删除不需要的值的惯用方法是使用逻辑索引,如表达式 x(x>3) 或语句 x(x>3) = [] 来 in-place 修改 x。相比之下,Julia 提供了更高阶的函数 filterfilter!,允许用户编写 filter(z->z>3, x)filter!(z->z>3, x) 来代替相应直译 x[x.>3]x = x[x.>3]。使用 filter! 可以减少临时数组的使用。
    • 类似于提取(或「解引用」)元胞数组的所有元素的操作,例如 MATLAB 中的 vertcat(A{:}),在 Julia 中是使用 splat 运算符编写的,例如 vcat(A...)
    • 在 Julia 中,adjoint 函数执行共轭转置;在 MATLAB 中,adjoint 提供了经典伴随,它是余子式的转置。
    • 在 Julia 中,a^b^c 被认为是 a^(b^c) 而在 MATLAB 中它是 (a^b)^c。

    与 R 的显著差异

    Julia 的目标之一是为数据分析和统计编程提供高效的语言。对于从 R 转到 Julia 的用户来说,这是一些显著差异:

    • Julia 的单引号封闭字符,而不是字符串。

    • Julia 可以通过索引字符串来创建子字符串。在 R 中,在创建子字符串之前必须将字符串转换为字符向量。

    • 在 Julia 中,与 Python 相同但与 R 不同的是,字符串可由三重引号 """ ... """ 创建。此语法对于构造包含换行符的字符串很方便。

    • 在 Julia 中,可变参数使用 splat 运算符 ... 指定,该运算符总是跟在具体变量的名称后面,与 R 的不同,R 的 ... 可以单独出现。

    • 在 Julia 中,模数是 mod(a, b),而不是 a %% b。Julia 中的 % 是余数运算符。

    • 在 Julia 中,并非所有数据结构都支持逻辑索引。此外,Julia 中的逻辑索引只支持长度等于被索引对象的向量。例如:

      • 在 R 中,c(1, 2, 3, 4)[c(TRUE, FALSE)] 等价于 c(1, 3)
      • 在 R 中,c(1, 2, 3, 4)[c(TRUE, FALSE, TRUE, FALSE)] 等价于 c(1, 3)
      • 在 Julia 中,[1, 2, 3, 4][[true, false]] 抛出 BoundsError
      • 在 Julia 中,[1, 2, 3, 4][[true, false, true, false]] 产生 [1, 3]
    • 与许多语言一样,Julia 并不总是允许对不同长度的向量进行操作,与 R 不同,R 中的向量只需要共享一个公共的索引范围。例如,c(1, 2, 3, 4) + c(1, 2) 是有效的 R,但等价的 [1, 2, 3, 4] + [1, 2] 在 Julia 中会抛出一个错误。

    • 在逗号不改变代码含义时,Julia 允许使用可选的尾随括号。在索引数组时,这可能在 R 用户间造成混淆。例如,R 中的 x[1,] 将返回矩阵的第一行;但是,在 Julia 中,引号被忽略,于是 x[1,] == x[1],并且将返回第一个元素。要提取一行,请务必使用 :,如 x[1,:]

    • Julia 的 map 首先接受函数,然后是该函数的参数,这与 R 中的 lapply(<structure>, function, ...) 不同。类似地,R 中的 apply(X, MARGIN, FUN, ...) 等价于 Julia 的 mapslices,其中函数是第一个参数。

    • R 中的多变量 apply,如 mapply(choose, 11:13, 1:3),在 Julia 中可以编写成 broadcast(binomial, 11:13, 1:3)。等价地,Julia 提供了更短的点语法来向量化函数 binomial.(11:13, 1:3)

    • Julia 使用 end 来表示条件块(如 if)、循环块(如 while/for)和函数的结束。为了代替单行 if ( cond ) statement,Julia 允许形式为 if cond; statement; endcond && statement!cond || statement 的语句。后两种语法中的赋值语句必须显式地包含在括号中,例如 cond && (x = value),这是因为运算符的优先级。

    • 在 Julia 中,<-, <<--> 不是赋值运算符。

    • Julia 的 -> 创建一个匿名函数。

    • Julia 使用括号构造向量。Julia 的 [1, 2, 3] 等价于 R 的 c(1, 2, 3)

    • Julia 的 * 运算符可以执行矩阵乘法,这与 R 不同。如果 AB 都是矩阵,那么 A * B 在 Julia 中表示矩阵乘法,等价于 R 的 A %*% B。在 R 中,相同的符号将执行逐元素(Hadamard)乘积。要在 Julia 中使用逐元素乘法运算,你需要编写 A .* B

    • Julia 使用 transpose 函数来执行矩阵转置,使用 ' 运算符或 adjoint 函数来执行共轭转置。因此,Julia 的 transpose(A) 等价于 R 的 t(A)。另外,Julia 中的非递归转置由 permutedims 函数提供。

    • Julia 在编写 if 语句或 for/while 循环时不需要括号:请使用 for i in [1, 2, 3] 代替 for (int i=1; i <= 3; i++),以及 if i == 1 代替 if (i == 1)

    • Julia 不把数字 01 视为布尔值。在 Julia 中不能编写 if (1),因为 if 语句只接受布尔值。相反,可以编写 if trueif Bool(1)if 1==1

    • Julia 不提供 nrowncol。相反,请使用 size(M, 1) 代替 nrow(M) 以及 size(M, 2) 代替 ncol(M)

    • Julia 仔细区分了标量、向量和矩阵。在 R 中,1c(1) 是相同的。在 Julia 中,它们不能互换地使用。

    • Julia 的 diagdiagm 与 R 的不同。

    • Julia 赋值操作的左侧不能为函数调用的结果:你不能编写 diag(M) = fill(1, n)

    • Julia 不鼓励使用函数填充主命名空间。Julia 的大多数统计功能都可在 JuliaStats 组织中找到。例如:

    • Julia 提供了元组和真正的哈希表,但不提供 R 风格的列表。在返回多个项时,通常应使用元组或具名元组:请使用 (1, 2)(a=1, b=2) 代替 list(a = 1, b = 2)

    • Julia 鼓励用户编写自己的类型,它比 R 中的 S3 或 S4 对象更容易使用。Julia 的多重派发系统意味着 table(x::TypeA)table(x::TypeB) 类似于 R 的 table.TypeA(x)table.TypeB(x)

    • Julia 的值在向函数传递时不发生复制。如果某个函数修改了数组,这一修改对调用者是可见的。这与 R 非常不同,允许新函数更高效地操作大型数据结构。

    • 在 Julia 中,向量和矩阵使用 hcatvcathvcat 拼接,而不是像在 R 中那样使用 crbindcbind

    • 在 Julia 中,像 a:b 这样的 range 不是 R 中的向量简写,而是一个专门的 AbstractRange 对象,该对象用于没有高内存开销地进行迭代。要将 range 转换为 vector,请使用 collect(a:b)

    • Julia 的 maxmin 分别等价于 R 中的 pmaxpmin,但两者的参数都需要具有相同的维度。虽然 maximumminimum 代替了 R 中的 maxmin,但它们之间有重大区别。

    • Julia 的 sumprodmaximumminimum 与它们在 R 中的对应物不同。它们都接受一个可选的关键字参数 dims,它表示执行操作的维度。例如,在 Julia 中令 A = [1 2; 3 4],在 R 中令 B <- rbind(c(1,2),c(3,4)) 是与之相同的矩阵。然后 sum(A) 得到与 sum(B) 相同的结果,但 sum(A, dims=1) 是一个包含每一列总和的行向量,sum(A, dims=2) 是一个包含每一行总和的列向量。这与 R 的行为形成了对比,在 R 中,单独的 colSums(B)rowSums(B) 提供了这些功能。如果 dims 关键字参数是向量,则它指定执行求和的所有维度,并同时保持待求和数组的维数,例如 sum(A, dims=(1,2)) == hcat(10)。应该注意的是,没有针对第二个参数的错误检查。

    • Julia 具有一些可以改变其参数的函数。例如,它具有 sortsort!

    • 在 R 中,高性能需要向量化。在 Julia 中,这几乎恰恰相反:性能最高的代码通常通过去向量化的循环来实现。

    • Julia 是立即求值的,不支持 R 风格的惰性求值。对于大多数用户来说,这意味着很少有未引用的表达式或列名。

    • Julia 不支持 NULL 类型。最接近的等价物是 nothing,但它的行为类似于标量值而不是列表。请使用 x === nothing 代替 is.null(x)

    • 在 Julia 中,缺失值由 missing 表示,而不是由 NA 表示。请使用 ismissing(x)(或者在向量上使用逐元素操作 ismissing.(x))代替 isna(x)。通常使用 skipmissing 代替 na.rm=TRUE(尽管在某些特定情况下函数接受 skipmissing 参数)。

    • Julia 缺少 R 中的 assignget 的等价物。

    • 在 Julia 中,return 不需要括号。

    • 在 R 中,删除不需要的值的惯用方法是使用逻辑索引,如表达式 x[x>3] 或语句 x = x[x>3] 来 in-place 修改 x。相比之下,Julia 提供了更高阶的函数 filterfilter!,允许用户编写 filter(z->z>3, x)filter!(z->z>3, x) 来代替相应直译 x[x.>3]x = x[x.>3]。使用 filter! 可以减少临时数组的使用。

    与 Python 的显著差异

    • Julia 的 for, if, while 等语句块都以 end 关键字结束。代码的缩进不像在 Python 中那样重要。Julia 也没有 pass 关键字。
    • Julia 中的字符串使用双引号构造,如 "text",也可以使用三引号构造多行字符串。而在 Python 中可以使用单引号('text')或者双引号("text")。单引号在 Julia 中用来表示单个字符,例如 'c'
    • 在 Julia 中字符串的拼接使用 *,而不是像 Python 一样使用 +。类似的,字符串重复多次 Julia 使用 ^ 而不是 *。Julia 也不支持隐式的字符串拼接,例如 Python 中的 'ab' 'cd' == 'abcd'
    • Python 列表——灵活但缓慢——对应于 Julia 的 Vector{Any} 类型或更一般的 Vector{T},其中 T 是一些非具体元素类型。 “快”的数组,如 NumPy 数组,它们就地存储元素(即,dtypenp.float64[('f1', np.uint64), ('f2', np.int32)], 等)可以用 Array{T} 表示,其中 T 是一个具体的、不可变的元素类型。 这包括内置类型,如 Float64Int32Int64,也包括更复杂的类型,如 Tuple{UInt64,Float64} 和许多用户定义的类型。
    • 在 Julia 中,数组、字符串等的索引从 1 开始,而不是从 0 开始。
    • Julia 里的切片包含最后一个元素。Julia 里的 a[2:3] 等同于 Python 中的 a[1:3]
    • Julia 不支持负数索引。特别地,列表或数组的最后一个元素在 Julia 中使用 end 索引,而不像在 Python 中使用 -1
    • Julia 的索引必须写全。Python 中的 x[1:] 等价于 Julia 中的 x[2:end]
    • Julia 的范围语法为 x[start:step:stop],而 Python 的格式为 x[start:(stop+1):step]

    因此 Python 中的 x[0:10:2] 等价于 Julia 里的 x[1:2:10]。类似的 Python 中的反转数组 x[::-1] 等价于 Julia 中的 x[end:-1:1]

    • 在 Julia 中队一个矩阵取索引 X[[1,2], [1,3]] 返回一个子矩阵,它包含了第一和第二行与第一和第三列的交集。

    在 Python 中 X[[1,2], [1,3]] 返回一个向量,它包含索引 [1,1][2,3] 的值。Julia 中的 X[[1,2], [1,3]] 等价于 Python 中的 X[np.ix_([0,1],[0,2])]。Python 中的 X[[1,2], [1,3]] 等价于 Julia 中的 X[[CartesianIndex(1,1), CartesianIndex(2,3)]]

    • Julia 没有用来续行的语法:如果在行的末尾,到目前为止的输入是一个完整的表达式,则认为其已经结束;否则,认为输入继续。强制表达式继续的一种方式是将其包含在括号中。
    • 默认情况下,Julia 数组是列优先(Fortran 排序),而 NumPy 数组是行优先(C 排序)。为了在循环数组时获得最佳性能,Julia 中的循环顺序应相对于 NumPy 颠倒(请参阅性能提示的相关部分)。
    • Julia 的更新运算符(例如 +=-=,···)是非原位操作(not in-place),而 Numpy 的是。这意味着 A = [1, 1]; B = A; B += [3, 3] 不会改变 A 中的值,而将名称 B 重新绑定到右侧表达式 B = B + 3 的结果,这是一个新的数组。对于 in-place 操作,使用 B .+= 3(另请参阅 dot operators)、显式的循环或者 InplaceOps.jl
    • Julia 的函数在调用时,每次都对默认参数重新求值,不像 Python 只在函数定义时对默认参数求一次值。

    举例来说:Julia 的函数 f(x=rand()) = x 在无参数调用时(f()),每次都会返回不同的随机数。 另一方面,函数 g(x=[1,2]) = push!(x,3) 无参数调用时 g(),永远返回 [1,2,3]

    • 在 Julia 中,必须使用关键字来传递关键字参数,这与 Python 中通常可以按位置传递它们不同。尝试按位置传递关键字参数会改变方法签名,从而导致 MethodError 或调用错误的方法。
    • 在 Julia 中,% 是余数运算符,而在 Python 中是模运算符。

    (译注:二者在参数有负数时有区别)

    • 在 Julia 中,常用的整数类型 Int 对应机器的整数类型,Int32Int64。不像 Python 中的整数 int 是任意精度的。这意味着 Julia 中默认的整数类型会溢出,因此 2^64 == 0。如果你要表示一个大数,请选择一个合适的类型。如:Int128、任意精度的 BigInt 或者浮点类型 Flost64
    • Julia 中虚数单位 sqrt(-1)im,而不是 Python 中的 j
    • Julia 中指数是 ^,而不是 Python 中的 **
    • Julia 使用 Nothing 类型的实例 nothing 代表空值(null),而不是 Python 中 NoneType 类的 None
    • 在 Julia 中,标准的运算符作用在矩阵上就得到矩阵操作,不像 Python 标准运算符默认是逐元素操作。当 A 和 B 都是矩阵时,A * B 在 Julia 中代表着矩阵乘法,而不是 Python 中的逐元素相乘。即:Julia 中的 A * B 等同于 Python 的 A @ B;Python 中的 A * B 等同于 Julia 中的 A .* B
    • Julia 中的伴随操作符 ' 返回向量的转置(一种行向量的懒惰表示法)。Python 中对向量执行 .T 返回它本身(没有效果)。
    • 在Julia中,一个函数可能包含多个具体实现(称为方法),与Python中的函数相比,这些实现是根据调用的所有参数的类型通过多重派发选择的,它只有一个实现,没有多态性(与Python方法调用相反,Python方法调用使用不同的语法,并允许在方法的接收者上进行派发)。
    • Julia 没有类(class),取而代替的是结构体(structures),可以是可变的或不可变的,它们只包含数据而不包含方法。
    • 在 Python 中调用类实例的方法 (x = MyClass(*args); x.f(y)) 对应于 Julia 中的函数调用,例如 x = MyType(args...); f(x, y)。 总的来说,多重派发比 Python 类系统更灵活和强大。
    • Julia 的结构体有且只能有一个抽象超类型(abstract supertype),而 Python 的类可以纪成一个或多个、抽象或具体的超类(superclasses)。
    • 逻辑 Julia 程序结构(包和模块)独立于文件结构(include 用于附加文件),而 Python 代码结构由目录(包)和文件(模块)定义。
    • Julia 中的三元运算符 x > 0 ? 1 : -1 对应于 Python 中的条件表达式 1 if x > 0 else -1
    • Julia 中以 @ 开头的符号是宏(macro),而 Python 中是装饰器(decorator)。
    • Julia 的异常处理使用 trycatchfinally,而不是 Python 的 tryexceptfinally。与 Python 不同的是,因为性能的原因,Julia 不推荐在正常流程中使用异常处理。
    • Julia 的循环很快,所以没必要手动向量化(vectorized)。
    • 小心 Julia 中的非常量全局变量,尤其它出现在循环中时。因为你在 Julia 中可以写出贴近硬件的代码,这时使用全局变量的影响非常大(参见性能建议
    • Python 中大多数的值都能用在逻辑运算中。例如:if "a" 永真,if "" 恒假。在 Julia 中你只能使用布尔类型的值,或者显示的将其他值转为布尔类型,否则就会抛出异常。例如当你想测试字符串是否为空是,请使用 if !isempty("")
    • 在 Julia 中大多数代码块都会引入新的本地作用域(local scope)。例如:循环和异常处理的 try — catch — finally。注意:列表推断(comprehensions)与生成器在 Julia 和 Python 中都会引入新的作用域;而 if 分支则都不会引入。

    与 C/C++ 的显著差异

    • Julia 的数组由方括号索引,方括号中可以包含不止一个维度 A[i,j]。这样的语法不仅仅是像 C/C++ 中那样对指针或者地址引用的语法糖,参见关于数组构造的语法的 Julia 文档
    • 在 Julia 中,数组、字符串等的索引从 1 开始,而不是从 0 开始。
    • Julia 的数组在赋值给另一个变量时不发生复制。执行 A = B 后,改变 B 中元素也会修改 A。像 += 这样的更新运算符不会以 in-place 的方式执行,而是相当于 A = A + B,将左侧绑定到右侧表达式的计算结果上。
    • Julia 的数组是列优先的(Fortran 顺序),而 C/C++ 的数组默认是行优先的。要使数组上的循环性能最优,在 Julia 中循环的顺序应该与 C/C++ 相反(参见 性能建议)。
    • Julia 的值在赋值或向函数传递时不发生复制。如果某个函数修改了数组,这一修改对调用者是可见的。
    • 在 Julia 中,空格是有意义的,这与 C/C++ 不同,所以向 Julia 程序中添加或删除空格时必须谨慎。
    • 在 Julia 中,没有小数点的数值字面量(如 42)生成有符号整数,类型为 Int,但如果字面量太长,超过了机器字长,则会被自动提升为容量更大的类型,例如 Int64(如果 IntInt32)、Int128,或者任意精度的 BigInt 类型。不存在诸如 L, LL, U, UL, ULL 这样的数值字面量后缀指示无符号和/或有符号与无符号。十进制字面量始终是有符号的,十六进制字面量(像 C/C++ 一样由 0x 开头)是无符号的。另外,十六进制字面量与 C/C++/Java 不同,也与 Julia 中的十进制字面量不同,它们的类型取决于字面量的长度,包括开头的 0。例如,0x00x00 的类型是 UInt80x0000x0000 的类型是 UInt16。同理,字面量的长度在 5-8 之间,类型为 UInt32;在 9-16 之间,类型为 UInt64;在 17-32 之间,类型为 UInt128。当定义十六进制掩码时,就需要将这一问题考虑在内,比如 ~0xf == 0xf0~0x000f == 0xfff0 完全不同。64 位 Float64 和 32 位 Float32 的字面量分别表示为 1.01.0f0。浮点字面量在无法被精确表示时舍入(且不会提升为 BigFloat 类型)。浮点字面量在行为上与 C/C++ 更接近。八进制(前缀为 0o)和二进制(前缀为 0b)也被视为无符号的。
    • 在 Julia 中,当两个操作数都是整数类型时,除法运算符 / 返回一个浮点数。 要执行整数除法,请使用 div÷
    • 使用浮点类型索引数组在 Julia 中通常是错误的。 C 表达式 a[i / 2] 的 Julia 等价写法是 a[i ÷ 2 + 1],其中 i 是整数类型。
    • 字符串字面量可用 """" 分隔,用 """ 分隔的字面量可以包含 " 字符而无需像 "\"" 这样来引用它。字符串字面量可以包含插入其中的其他变量或表达式,由 $variablename$(expression) 表示,它在该函数所处的上下文中计算变量名或表达式。
    • // 表示 Rational 数,而非单行注释(其在 Julia 中是 #
    • #= 表示多行注释的开头,=# 结束之。
    • Julia 中的函数返回其最后一个表达式或 return 关键字的值。可以从函数中返回多个值并将其作为元组赋值,如 (a, b) = myfunction()a, b = myfunction(),而不必像在 C/C++ 中那样必须传递指向值的指针(即 a = myfunction(&b))。
    • Julia 不要求使用分号来结束语句。表达式的结果不会自动打印(除了在交互式提示符中,即 REPL),且代码行不需要以分号结尾。println@printf 可用于打印特定输出。在 REPL 中,; 可用于抑制输出。;[ ] 中也有不同的含义,需要注意。; 可用于在单行中分隔表达式,但在许多情况下不是绝对必要的,更经常是为了可读性。
    • 在 Julia 中,运算符 xor)执行按位 XOR 操作,即 C/C++ 中的 ^。此外,按位运算符不具有与 C/C++ 相同的优先级,所以可能需要括号。
    • Julia 的 ^ 是取幂(pow),而非 C/C++ 中的按位 XOR(在 Julia 中请使用 xor
    • Julia 有两个右移运算符,>>>>>>> 执行算术移位,>>> 始终执行逻辑移位,这与 C/C++ 不同,其中 >> 的含义取决于被移位的值的类型。
    • Julia 的 -> 创建一个匿名函数,它并不通过指针访问成员。
    • Julia 在编写 if 语句或 for/while 循环时不需要括号:请使用 for i in [1, 2, 3] 代替 for (int i=1; i <= 3; i++),以及 if i == 1 代替 if (i == 1)
    • Julia 不把数字 01 视为布尔值。在 Julia 中不能编写 if (1),因为 if 语句只接受布尔值。相反,可以编写 if trueif Bool(1)if 1==1
    • Julia 使用 end 来表示条件块(如 if)、循环块(如 while/for)和函数的结束。为了代替单行 if ( cond ) statement,Julia 允许形式为 if cond; statement; endcond && statement!cond || statement 的语句。后两种语法中的赋值语句必须显式地包含在括号中,例如 cond && (x = value),这是因为运算符的优先级。
    • Julia 没有用来续行的语法:如果在行的末尾,到目前为止的输入是一个完整的表达式,则认为其已经结束;否则,认为输入继续。强制表达式继续的一种方式是将其包含在括号中。
    • Julia 宏对已解析的表达式进行操作,而非程序的文本,这允许它们执行复杂的 Julia 代码转换。宏名称以 @ 字符开头,具有类似函数的语法 @mymacro(arg1, arg2, arg3) 和类似语句的语法 @mymacro arg1 arg2 arg3。两种形式的语法可以相互转换;如果宏出现在另一个表达式中,则类似函数的形式尤其有用,并且它通常是最清晰的。类似语句的形式通常用于标注块,如在分布式 for 结构中:@distributed for i in 1:n; #= body =#; end。如果宏结构的结尾不那么清晰,请使用类似函数的形式。
    • Julia 有一个枚举类型,使用宏 @enum(name, value1, value2, ...) 来表示,例如:@enum(Fruit, banana=1, apple, pear)
    • 按照惯例,修改其参数的函数在名称的末尾有个 !,例如 push!
    • 在 C++ 中,默认情况下,你具有静态分派,即为了支持动态派发,你需要将函数标注为 virtual 函数。另一方面,Julia 中的每个方法都是「virtual」(尽管它更通用,因为方法是在每个参数类型上派发的,而不仅仅是 this,并且使用的是最具体的声明规则)。

    与 Common Lisp 的显著差异

    • Julia 默认使用 1 开始的数组索引,它也能处理任意的索引顺序

    • 函数和变量共用一个命名空间("Lisp-1")。

    • Julia 中有 Pair 类型,但这并不意味着它能用作 COMMON-LISP:CONS。在 Julia 中绝大多数可迭代的集合都能互换使用,例如:集合解包(splatting)、元组等。Tuple 最接近 Common Lisp 中用于异构元素的列表。使用 NamedTuple 来代替关联表(alists)。对于更大的、同类型元素的集合,应该使用 Array 和 Dict

    • 典型的使用 Julia 进行原型开发时,也会对镜像进行连续的修改,Revise.jl 包提供了这个功能。

    • 对于性能,Julia 更喜欢操作具有 类型稳定性。 Common Lisp 从底层机器操作中抽象出来,而 Julia 则更接近它们。 例如:

      • 使用 / 的整数除法总是返回浮点结果,即使计算是精确的。
        • // 总是返回一个有理数结果
        • ÷ 总是返回一个(被截断的)整数结果
      • Julia 支持大整数,但不会自动转换。默认的整数类型会溢出
      • 支持复数,但要获得复数结果,你需要复数输入
      • 有多种 Complex 和 Rational 类型,具有不同的组成类型。
    • 模块(名称空间)可以是分层的。import 和 using 有着双重角色:他们加载代码并让代码在命名空间中可用。import 用于仅有模块名是可用的情况,大致等价于 ASDF:LOAD-OP。槽名(Slot name)不需要单独导出。全局变量不能从模块的外部赋值,除了 eval(mod, :(var = val)) 这个例外情况。

    • 宏以 @ 开头,并没有像 Common Lisp 那样无缝地集成到语言中;因此在 Julia 中,宏的使用不像在 Common Lisp 中那样广泛。Julia 支持的一种卫生(hygiene)形式。因为不同的表层语法,Julia 中没有 COMMON-LISP:&BODY 的等价形式。

    • 所有的函数都是通用的并且使用多重分派。函数的参数列表也无需遵循一样的模板,这让我们有了一个强大的范式:do。可选参数与关键字参数的处理方式不同。方法的歧义没有像在 Common Lisp 对象系统中那样得到解决,因此需要为交集定义更具体的方法。

    • 符号不属于任何包,它本身也不包含任何值。M.var 会对 M 模块里的  var 符号求值。

    • Julia 完全支持函数式编程风格,包括闭包等特性。但这并不是 Julia 的惯用风格。修改捕获变量时需要一些额外的变通以便提高性能。

    +

    与其他语言的显著差异

    与 MATLAB 的显著差异

    虽然 MATLAB 用户可能会发现 Julia 的语法很熟悉,但 Julia 不是 MATLAB 的克隆。 它们之间存在重大的语法和功能差异。 以下是一些可能会使习惯于 MATLAB 的 Julia 用户感到困扰的显著差异:

    • Julia 数组使用方括号 A[i,j] 进行索引。
    • Julia 数组在分配给另一个变量时不会被复制。 在A = B之后,改变B的元素也会改变A的元素。
    • Julia 的值在向函数传递时不发生复制。如果某个函数修改了数组,这一修改对调用者是可见的。
    • Julia 不会在赋值语句中自动增长数组。 而在 MATLAB 中 a(4) = 3.2 可以创建数组 a = [0 0 0 3.2],而 a(5) = 7 可以将它增长为 a = [0 0 0 3.2 7]。如果 a 的长度小于 5 或者这个语句是第一次使用标识符 a,则相应的 Julia 语句 a[5] = 7 会抛出错误。Julia 使用 push!append! 来增长 Vector,它们比 MATLAB 的 a(end+1) = val 更高效。
    • 虚数单位 sqrt(-1) 在 Julia 中表示为 im,而不是在 MATLAB 中的 ij
    • 在 Julia 中,没有小数点的数字字面量(例如 42)会创建整数而不是浮点数。也支持任意大整数字面量。因此,某些操作(如 2^-1)将抛出 domain error,因为结果不是整数(有关的详细信息,请参阅常见问题中有关 domain errors 的条目)。 在 Julia 中,没有小数点的数字字面量(例如 42)会创建整数而不是浮点数。因此,某些操作会因为需要浮点数而抛出 domain error;例如 julia > a = -1; 2^a ,因为结果不是整数了。请参阅常见问题中有关 domain errors 的条目)。
    • 在 Julia 中,能返回多个值并将其赋值为元组,例如 (a, b) = (1, 2)a, b = 1, 2。 在 Julia 中不存在 MATLAB 的 nargout,它通常在 MATLAB 中用于根据返回值的数量执行可选工作。取而代之的是,用户可以使用可选参数和关键字参数来实现类似的功能。
    • Julia 拥有真正的一维数组。列向量的大小为 N,而不是 Nx1。例如,rand(N) 创建一个一维数组。
    • 在 Julia 中,[x,y,z] 将始终构造一个包含xyz 的 3 元数组。
      • 要在第一个维度(「垂直列」)中连接元素,请使用 vcat(x,y,z) 或用分号分隔([x; y; z])。
      • 要在第二个维度(「水平行」)中连接元素,请使用 hcat(x,y,z) 或用空格分隔([x y z])。
      • 要构造分块矩阵(在前两个维度中连接元素),请使用 hvcat 或组合空格和分号([a b; c d])。
    • 在 Julia 中,a:ba:b:c 构造 AbstractRange 对象。使用 collect(a:b) 构造一个类似 MATLAB 中完整的向量。通常,不需要调用 collect。在大多数情况下,AbstractRange 对象将像普通数组一样运行,但效率更高,因为它是懒惰求值。这种创建专用对象而不是完整数组的模式经常被使用,并且也可以在诸如 range 之类的函数中看到,或者在诸如 enumeratezip 之类的迭代器中看到。特殊对象大多可以像正常数组一样使用。
    • Julia 中的函数返回其最后一个表达式或 return 关键字的值而无需在函数定义中列出要返回的变量的名称(有关详细信息,请参阅 return 关键字)。
    • Julia 脚本可以包含任意数量的函数,并且在加载文件时,所有定义都将在外部可见。可以从当前工作目录之外的文件加载函数定义。
    • 在 Julia 中,例如 sumprodmax 的归约操作会作用到数组的每一个元素上,当调用时只有一个函数,例如 sum(A),即使 A 并不只有一个维度。
    • 在 Julia 中,调用无参数的函数时必须使用小括号,例如 rand()
    • Julia 不鼓励使用分号来结束语句。语句的结果不会自动打印(除了在 REPL 中),并且代码的一行不必使用分号结尾。println 或者 @printf 能用来打印特定输出。
    • 在 Julia 中,如果 AB 是数组,像 A == B 这样的逻辑比较运算符不会返回布尔值数组。相反地,请使用 A .== B。对于其他的像是 <> 的布尔运算符同理。
    • 在 Julia 中,运算符&|xor)进行按位操作,分别与MATLAB中的andorxor 等价,并且优先级与 Python 的按位运算符相似(不像 C)。他们可以对标量运算或者数组中逐元素运算,可以用来合并逻辑数组,但是注意运算顺序的区别:括号可能是必要的(例如,选择 A 中等于 1 或 2 的元素可使用 (A .== 1) .| (A .== 2))。
    • 在 Julia 中,集合的元素可以使用 splat 运算符 ... 来作为参数传递给函数,如 xs=[1,2]; f(xs...)
    • Julia 的 svd 将奇异值作为向量而非密集对角矩阵返回。
    • 在 Julia 中,... 不用于延续代码行。不同的是,Julia 中不完整的表达式会自动延续到下一行。
    • 在 Julia 和 MATLAB 中,变量 ans 被设置为交互式会话中提交的最后一个表达式的值。在 Julia 中与 MATLAB 不同的是,当 Julia 代码以非交互式模式运行时并不会设置 ans
    • Julia 的 struct 不支持在运行时动态地添加字段,这与 MATLAB 的 class 不同。 如需支持,请使用 Dict。Julia 中的字典不是有序的。
    • 在 Julia 中,每个模块有自身的全局作用域/命名空间,而在 MATLAB 中只有一个全局作用域。
    • 在 MATLAB 中,删除不需要的值的惯用方法是使用逻辑索引,如表达式 x(x>3) 或语句 x(x>3) = [] 来 in-place 修改 x。相比之下,Julia 提供了更高阶的函数 filterfilter!,允许用户编写 filter(z->z>3, x)filter!(z->z>3, x) 来代替相应直译 x[x.>3]x = x[x.>3]。使用 filter! 可以减少临时数组的使用。
    • 类似于提取(或「解引用」)元胞数组的所有元素的操作,例如 MATLAB 中的 vertcat(A{:}),在 Julia 中是使用 splat 运算符编写的,例如 vcat(A...)
    • 在 Julia 中,adjoint 函数执行共轭转置;在 MATLAB 中,adjoint 提供了经典伴随,它是余子式的转置。
    • 在 Julia 中,a^b^c 被认为是 a^(b^c) 而在 MATLAB 中它是 (a^b)^c。

    与 R 的显著差异

    Julia 的目标之一是为数据分析和统计编程提供高效的语言。对于从 R 转到 Julia 的用户来说,这是一些显著差异:

    • Julia 的单引号封闭字符,而不是字符串。

    • Julia 可以通过索引字符串来创建子字符串。在 R 中,在创建子字符串之前必须将字符串转换为字符向量。

    • 在 Julia 中,与 Python 相同但与 R 不同的是,字符串可由三重引号 """ ... """ 创建。此语法对于构造包含换行符的字符串很方便。

    • 在 Julia 中,可变参数使用 splat 运算符 ... 指定,该运算符总是跟在具体变量的名称后面,与 R 的不同,R 的 ... 可以单独出现。

    • 在 Julia 中,模数是 mod(a, b),而不是 a %% b。Julia 中的 % 是余数运算符。

    • 在 Julia 中,并非所有数据结构都支持逻辑索引。此外,Julia 中的逻辑索引只支持长度等于被索引对象的向量。例如:

      • 在 R 中,c(1, 2, 3, 4)[c(TRUE, FALSE)] 等价于 c(1, 3)
      • 在 R 中,c(1, 2, 3, 4)[c(TRUE, FALSE, TRUE, FALSE)] 等价于 c(1, 3)
      • 在 Julia 中,[1, 2, 3, 4][[true, false]] 抛出 BoundsError
      • 在 Julia 中,[1, 2, 3, 4][[true, false, true, false]] 产生 [1, 3]
    • 与许多语言一样,Julia 并不总是允许对不同长度的向量进行操作,与 R 不同,R 中的向量只需要共享一个公共的索引范围。例如,c(1, 2, 3, 4) + c(1, 2) 是有效的 R,但等价的 [1, 2, 3, 4] + [1, 2] 在 Julia 中会抛出一个错误。

    • 在逗号不改变代码含义时,Julia 允许使用可选的尾随括号。在索引数组时,这可能在 R 用户间造成混淆。例如,R 中的 x[1,] 将返回矩阵的第一行;但是,在 Julia 中,引号被忽略,于是 x[1,] == x[1],并且将返回第一个元素。要提取一行,请务必使用 :,如 x[1,:]

    • Julia 的 map 首先接受函数,然后是该函数的参数,这与 R 中的 lapply(<structure>, function, ...) 不同。类似地,R 中的 apply(X, MARGIN, FUN, ...) 等价于 Julia 的 mapslices,其中函数是第一个参数。

    • R 中的多变量 apply,如 mapply(choose, 11:13, 1:3),在 Julia 中可以编写成 broadcast(binomial, 11:13, 1:3)。等价地,Julia 提供了更短的点语法来向量化函数 binomial.(11:13, 1:3)

    • Julia 使用 end 来表示条件块(如 if)、循环块(如 while/for)和函数的结束。为了代替单行 if ( cond ) statement,Julia 允许形式为 if cond; statement; endcond && statement!cond || statement 的语句。后两种语法中的赋值语句必须显式地包含在括号中,例如 cond && (x = value),这是因为运算符的优先级。

    • 在 Julia 中,<-, <<--> 不是赋值运算符。

    • Julia 的 -> 创建一个匿名函数。

    • Julia 使用括号构造向量。Julia 的 [1, 2, 3] 等价于 R 的 c(1, 2, 3)

    • Julia 的 * 运算符可以执行矩阵乘法,这与 R 不同。如果 AB 都是矩阵,那么 A * B 在 Julia 中表示矩阵乘法,等价于 R 的 A %*% B。在 R 中,相同的符号将执行逐元素(Hadamard)乘积。要在 Julia 中使用逐元素乘法运算,你需要编写 A .* B

    • Julia 使用 transpose 函数来执行矩阵转置,使用 ' 运算符或 adjoint 函数来执行共轭转置。因此,Julia 的 transpose(A) 等价于 R 的 t(A)。另外,Julia 中的非递归转置由 permutedims 函数提供。

    • Julia 在编写 if 语句或 for/while 循环时不需要括号:请使用 for i in [1, 2, 3] 代替 for (int i=1; i <= 3; i++),以及 if i == 1 代替 if (i == 1)

    • Julia 不把数字 01 视为布尔值。在 Julia 中不能编写 if (1),因为 if 语句只接受布尔值。相反,可以编写 if trueif Bool(1)if 1==1

    • Julia 不提供 nrowncol。相反,请使用 size(M, 1) 代替 nrow(M) 以及 size(M, 2) 代替 ncol(M)

    • Julia 仔细区分了标量、向量和矩阵。在 R 中,1c(1) 是相同的。在 Julia 中,它们不能互换地使用。

    • Julia 的 diagdiagm 与 R 的不同。

    • Julia 赋值操作的左侧不能为函数调用的结果:你不能编写 diag(M) = fill(1, n)

    • Julia 不鼓励使用函数填充主命名空间。Julia 的大多数统计功能都可在 JuliaStats 组织中找到。例如:

    • Julia 提供了元组和真正的哈希表,但不提供 R 风格的列表。在返回多个项时,通常应使用元组或具名元组:请使用 (1, 2)(a=1, b=2) 代替 list(a = 1, b = 2)

    • Julia 鼓励用户编写自己的类型,它比 R 中的 S3 或 S4 对象更容易使用。Julia 的多重派发系统意味着 table(x::TypeA)table(x::TypeB) 类似于 R 的 table.TypeA(x)table.TypeB(x)

    • Julia 的值在向函数传递时不发生复制。如果某个函数修改了数组,这一修改对调用者是可见的。这与 R 非常不同,允许新函数更高效地操作大型数据结构。

    • 在 Julia 中,向量和矩阵使用 hcatvcathvcat 拼接,而不是像在 R 中那样使用 crbindcbind

    • 在 Julia 中,像 a:b 这样的 range 不是 R 中的向量简写,而是一个专门的 AbstractRange 对象,该对象用于没有高内存开销地进行迭代。要将 range 转换为 vector,请使用 collect(a:b)

    • Julia 的 maxmin 分别等价于 R 中的 pmaxpmin,但两者的参数都需要具有相同的维度。虽然 maximumminimum 代替了 R 中的 maxmin,但它们之间有重大区别。

    • Julia 的 sumprodmaximumminimum 与它们在 R 中的对应物不同。它们都接受一个可选的关键字参数 dims,它表示执行操作的维度。例如,在 Julia 中令 A = [1 2; 3 4],在 R 中令 B <- rbind(c(1,2),c(3,4)) 是与之相同的矩阵。然后 sum(A) 得到与 sum(B) 相同的结果,但 sum(A, dims=1) 是一个包含每一列总和的行向量,sum(A, dims=2) 是一个包含每一行总和的列向量。这与 R 的行为形成了对比,在 R 中,单独的 colSums(B)rowSums(B) 提供了这些功能。如果 dims 关键字参数是向量,则它指定执行求和的所有维度,并同时保持待求和数组的维数,例如 sum(A, dims=(1,2)) == hcat(10)。应该注意的是,没有针对第二个参数的错误检查。

    • Julia 具有一些可以改变其参数的函数。例如,它具有 sortsort!

    • 在 R 中,高性能需要向量化。在 Julia 中,这几乎恰恰相反:性能最高的代码通常通过去向量化的循环来实现。

    • Julia 是立即求值的,不支持 R 风格的惰性求值。对于大多数用户来说,这意味着很少有未引用的表达式或列名。

    • Julia 不支持 NULL 类型。最接近的等价物是 nothing,但它的行为类似于标量值而不是列表。请使用 x === nothing 代替 is.null(x)

    • 在 Julia 中,缺失值由 missing 表示,而不是由 NA 表示。请使用 ismissing(x)(或者在向量上使用逐元素操作 ismissing.(x))代替 isna(x)。通常使用 skipmissing 代替 na.rm=TRUE(尽管在某些特定情况下函数接受 skipmissing 参数)。

    • Julia 缺少 R 中的 assignget 的等价物。

    • 在 Julia 中,return 不需要括号。

    • 在 R 中,删除不需要的值的惯用方法是使用逻辑索引,如表达式 x[x>3] 或语句 x = x[x>3] 来 in-place 修改 x。相比之下,Julia 提供了更高阶的函数 filterfilter!,允许用户编写 filter(z->z>3, x)filter!(z->z>3, x) 来代替相应直译 x[x.>3]x = x[x.>3]。使用 filter! 可以减少临时数组的使用。

    与 Python 的显著差异

    • Julia 的 for, if, while 等语句块都以 end 关键字结束。代码的缩进不像在 Python 中那样重要。Julia 也没有 pass 关键字。
    • Julia 中的字符串使用双引号构造,如 "text",也可以使用三引号构造多行字符串。而在 Python 中可以使用单引号('text')或者双引号("text")。单引号在 Julia 中用来表示单个字符,例如 'c'
    • 在 Julia 中字符串的拼接使用 *,而不是像 Python 一样使用 +。类似的,字符串重复多次 Julia 使用 ^ 而不是 *。Julia 也不支持隐式的字符串拼接,例如 Python 中的 'ab' 'cd' == 'abcd'
    • Python 列表——灵活但缓慢——对应于 Julia 的 Vector{Any} 类型或更一般的 Vector{T},其中 T 是一些非具体元素类型。 “快”的数组,如 NumPy 数组,它们就地存储元素(即,dtypenp.float64[('f1', np.uint64), ('f2', np.int32)], 等)可以用 Array{T} 表示,其中 T 是一个具体的、不可变的元素类型。 这包括内置类型,如 Float64Int32Int64,也包括更复杂的类型,如 Tuple{UInt64,Float64} 和许多用户定义的类型。
    • 在 Julia 中,数组、字符串等的索引从 1 开始,而不是从 0 开始。
    • Julia 里的切片包含最后一个元素。Julia 里的 a[2:3] 等同于 Python 中的 a[1:3]
    • Julia 不支持负数索引。特别地,列表或数组的最后一个元素在 Julia 中使用 end 索引,而不像在 Python 中使用 -1
    • Julia 的索引必须写全。Python 中的 x[1:] 等价于 Julia 中的 x[2:end]
    • Julia 的范围语法为 x[start:step:stop],而 Python 的格式为 x[start:(stop+1):step]

    因此 Python 中的 x[0:10:2] 等价于 Julia 里的 x[1:2:10]。类似的 Python 中的反转数组 x[::-1] 等价于 Julia 中的 x[end:-1:1]

    • 在 Julia 中队一个矩阵取索引 X[[1,2], [1,3]] 返回一个子矩阵,它包含了第一和第二行与第一和第三列的交集。

    在 Python 中 X[[1,2], [1,3]] 返回一个向量,它包含索引 [1,1][2,3] 的值。Julia 中的 X[[1,2], [1,3]] 等价于 Python 中的 X[np.ix_([0,1],[0,2])]。Python 中的 X[[1,2], [1,3]] 等价于 Julia 中的 X[[CartesianIndex(1,1), CartesianIndex(2,3)]]

    • Julia 没有用来续行的语法:如果在行的末尾,到目前为止的输入是一个完整的表达式,则认为其已经结束;否则,认为输入继续。强制表达式继续的一种方式是将其包含在括号中。
    • 默认情况下,Julia 数组是列优先(Fortran 排序),而 NumPy 数组是行优先(C 排序)。为了在循环数组时获得最佳性能,Julia 中的循环顺序应相对于 NumPy 颠倒(请参阅性能提示的相关部分)。
    • Julia 的更新运算符(例如 +=-=,···)是非原位操作(not in-place),而 Numpy 的是。这意味着 A = [1, 1]; B = A; B += [3, 3] 不会改变 A 中的值,而将名称 B 重新绑定到右侧表达式 B = B + 3 的结果,这是一个新的数组。对于 in-place 操作,使用 B .+= 3(另请参阅 dot operators)、显式的循环或者 InplaceOps.jl
    • Julia 的函数在调用时,每次都对默认参数重新求值,不像 Python 只在函数定义时对默认参数求一次值。

    举例来说:Julia 的函数 f(x=rand()) = x 在无参数调用时(f()),每次都会返回不同的随机数。 另一方面,函数 g(x=[1,2]) = push!(x,3) 无参数调用时 g(),永远返回 [1,2,3]

    • 在 Julia 中,必须使用关键字来传递关键字参数,这与 Python 中通常可以按位置传递它们不同。尝试按位置传递关键字参数会改变方法签名,从而导致 MethodError 或调用错误的方法。
    • 在 Julia 中,% 是余数运算符,而在 Python 中是模运算符。

    (译注:二者在参数有负数时有区别)

    • 在 Julia 中,常用的整数类型 Int 对应机器的整数类型,Int32Int64。不像 Python 中的整数 int 是任意精度的。这意味着 Julia 中默认的整数类型会溢出,因此 2^64 == 0。如果你要表示一个大数,请选择一个合适的类型。如:Int128、任意精度的 BigInt 或者浮点类型 Flost64
    • Julia 中虚数单位 sqrt(-1)im,而不是 Python 中的 j
    • Julia 中指数是 ^,而不是 Python 中的 **
    • Julia 使用 Nothing 类型的实例 nothing 代表空值(null),而不是 Python 中 NoneType 类的 None
    • 在 Julia 中,标准的运算符作用在矩阵上就得到矩阵操作,不像 Python 标准运算符默认是逐元素操作。当 A 和 B 都是矩阵时,A * B 在 Julia 中代表着矩阵乘法,而不是 Python 中的逐元素相乘。即:Julia 中的 A * B 等同于 Python 的 A @ B;Python 中的 A * B 等同于 Julia 中的 A .* B
    • Julia 中的伴随操作符 ' 返回向量的转置(一种行向量的懒惰表示法)。Python 中对向量执行 .T 返回它本身(没有效果)。
    • 在Julia中,一个函数可能包含多个具体实现(称为方法),与Python中的函数相比,这些实现是根据调用的所有参数的类型通过多重派发选择的,它只有一个实现,没有多态性(与Python方法调用相反,Python方法调用使用不同的语法,并允许在方法的接收者上进行派发)。
    • Julia 没有类(class),取而代替的是结构体(structures),可以是可变的或不可变的,它们只包含数据而不包含方法。
    • 在 Python 中调用类实例的方法 (x = MyClass(*args); x.f(y)) 对应于 Julia 中的函数调用,例如 x = MyType(args...); f(x, y)。 总的来说,多重派发比 Python 类系统更灵活和强大。
    • Julia 的结构体有且只能有一个抽象超类型(abstract supertype),而 Python 的类可以纪成一个或多个、抽象或具体的超类(superclasses)。
    • 逻辑 Julia 程序结构(包和模块)独立于文件结构(include 用于附加文件),而 Python 代码结构由目录(包)和文件(模块)定义。
    • Julia 中的三元运算符 x > 0 ? 1 : -1 对应于 Python 中的条件表达式 1 if x > 0 else -1
    • Julia 中以 @ 开头的符号是宏(macro),而 Python 中是装饰器(decorator)。
    • Julia 的异常处理使用 trycatchfinally,而不是 Python 的 tryexceptfinally。与 Python 不同的是,因为性能的原因,Julia 不推荐在正常流程中使用异常处理。
    • Julia 的循环很快,所以没必要手动向量化(vectorized)。
    • 小心 Julia 中的非常量全局变量,尤其它出现在循环中时。因为你在 Julia 中可以写出贴近硬件的代码,这时使用全局变量的影响非常大(参见性能建议
    • Python 中大多数的值都能用在逻辑运算中。例如:if "a" 永真,if "" 恒假。在 Julia 中你只能使用布尔类型的值,或者显示的将其他值转为布尔类型,否则就会抛出异常。例如当你想测试字符串是否为空是,请使用 if !isempty("")
    • 在 Julia 中大多数代码块都会引入新的本地作用域(local scope)。例如:循环和异常处理的 try — catch — finally。注意:列表推断(comprehensions)与生成器在 Julia 和 Python 中都会引入新的作用域;而 if 分支则都不会引入。

    与 C/C++ 的显著差异

    • Julia 的数组由方括号索引,方括号中可以包含不止一个维度 A[i,j]。这样的语法不仅仅是像 C/C++ 中那样对指针或者地址引用的语法糖,参见关于数组构造的语法的 Julia 文档
    • 在 Julia 中,数组、字符串等的索引从 1 开始,而不是从 0 开始。
    • Julia 的数组在赋值给另一个变量时不发生复制。执行 A = B 后,改变 B 中元素也会修改 A。像 += 这样的更新运算符不会以 in-place 的方式执行,而是相当于 A = A + B,将左侧绑定到右侧表达式的计算结果上。
    • Julia 的数组是列优先的(Fortran 顺序),而 C/C++ 的数组默认是行优先的。要使数组上的循环性能最优,在 Julia 中循环的顺序应该与 C/C++ 相反(参见 性能建议)。
    • Julia 的值在赋值或向函数传递时不发生复制。如果某个函数修改了数组,这一修改对调用者是可见的。
    • 在 Julia 中,空格是有意义的,这与 C/C++ 不同,所以向 Julia 程序中添加或删除空格时必须谨慎。
    • 在 Julia 中,没有小数点的数值字面量(如 42)生成有符号整数,类型为 Int,但如果字面量太长,超过了机器字长,则会被自动提升为容量更大的类型,例如 Int64(如果 IntInt32)、Int128,或者任意精度的 BigInt 类型。不存在诸如 L, LL, U, UL, ULL 这样的数值字面量后缀指示无符号和/或有符号与无符号。十进制字面量始终是有符号的,十六进制字面量(像 C/C++ 一样由 0x 开头)是无符号的。另外,十六进制字面量与 C/C++/Java 不同,也与 Julia 中的十进制字面量不同,它们的类型取决于字面量的长度,包括开头的 0。例如,0x00x00 的类型是 UInt80x0000x0000 的类型是 UInt16。同理,字面量的长度在 5-8 之间,类型为 UInt32;在 9-16 之间,类型为 UInt64;在 17-32 之间,类型为 UInt128。当定义十六进制掩码时,就需要将这一问题考虑在内,比如 ~0xf == 0xf0~0x000f == 0xfff0 完全不同。64 位 Float64 和 32 位 Float32 的字面量分别表示为 1.01.0f0。浮点字面量在无法被精确表示时舍入(且不会提升为 BigFloat 类型)。浮点字面量在行为上与 C/C++ 更接近。八进制(前缀为 0o)和二进制(前缀为 0b)也被视为无符号的。
    • 在 Julia 中,当两个操作数都是整数类型时,除法运算符 / 返回一个浮点数。 要执行整数除法,请使用 div÷
    • 使用浮点类型索引数组在 Julia 中通常是错误的。 C 表达式 a[i / 2] 的 Julia 等价写法是 a[i ÷ 2 + 1],其中 i 是整数类型。
    • 字符串字面量可用 """" 分隔,用 """ 分隔的字面量可以包含 " 字符而无需像 "\"" 这样来引用它。字符串字面量可以包含插入其中的其他变量或表达式,由 $variablename$(expression) 表示,它在该函数所处的上下文中计算变量名或表达式。
    • // 表示 Rational 数,而非单行注释(其在 Julia 中是 #
    • #= 表示多行注释的开头,=# 结束之。
    • Julia 中的函数返回其最后一个表达式或 return 关键字的值。可以从函数中返回多个值并将其作为元组赋值,如 (a, b) = myfunction()a, b = myfunction(),而不必像在 C/C++ 中那样必须传递指向值的指针(即 a = myfunction(&b))。
    • Julia 不要求使用分号来结束语句。表达式的结果不会自动打印(除了在交互式提示符中,即 REPL),且代码行不需要以分号结尾。println@printf 可用于打印特定输出。在 REPL 中,; 可用于抑制输出。;[ ] 中也有不同的含义,需要注意。; 可用于在单行中分隔表达式,但在许多情况下不是绝对必要的,更经常是为了可读性。
    • 在 Julia 中,运算符 xor)执行按位 XOR 操作,即 C/C++ 中的 ^。此外,按位运算符不具有与 C/C++ 相同的优先级,所以可能需要括号。
    • Julia 的 ^ 是取幂(pow),而非 C/C++ 中的按位 XOR(在 Julia 中请使用 xor
    • Julia 有两个右移运算符,>>>>>>> 执行算术移位,>>> 始终执行逻辑移位,这与 C/C++ 不同,其中 >> 的含义取决于被移位的值的类型。
    • Julia 的 -> 创建一个匿名函数,它并不通过指针访问成员。
    • Julia 在编写 if 语句或 for/while 循环时不需要括号:请使用 for i in [1, 2, 3] 代替 for (int i=1; i <= 3; i++),以及 if i == 1 代替 if (i == 1)
    • Julia 不把数字 01 视为布尔值。在 Julia 中不能编写 if (1),因为 if 语句只接受布尔值。相反,可以编写 if trueif Bool(1)if 1==1
    • Julia 使用 end 来表示条件块(如 if)、循环块(如 while/for)和函数的结束。为了代替单行 if ( cond ) statement,Julia 允许形式为 if cond; statement; endcond && statement!cond || statement 的语句。后两种语法中的赋值语句必须显式地包含在括号中,例如 cond && (x = value),这是因为运算符的优先级。
    • Julia 没有用来续行的语法:如果在行的末尾,到目前为止的输入是一个完整的表达式,则认为其已经结束;否则,认为输入继续。强制表达式继续的一种方式是将其包含在括号中。
    • Julia 宏对已解析的表达式进行操作,而非程序的文本,这允许它们执行复杂的 Julia 代码转换。宏名称以 @ 字符开头,具有类似函数的语法 @mymacro(arg1, arg2, arg3) 和类似语句的语法 @mymacro arg1 arg2 arg3。两种形式的语法可以相互转换;如果宏出现在另一个表达式中,则类似函数的形式尤其有用,并且它通常是最清晰的。类似语句的形式通常用于标注块,如在分布式 for 结构中:@distributed for i in 1:n; #= body =#; end。如果宏结构的结尾不那么清晰,请使用类似函数的形式。
    • Julia 有一个枚举类型,使用宏 @enum(name, value1, value2, ...) 来表示,例如:@enum(Fruit, banana=1, apple, pear)
    • 按照惯例,修改其参数的函数在名称的末尾有个 !,例如 push!
    • 在 C++ 中,默认情况下,你具有静态分派,即为了支持动态派发,你需要将函数标注为 virtual 函数。另一方面,Julia 中的每个方法都是「virtual」(尽管它更通用,因为方法是在每个参数类型上派发的,而不仅仅是 this,并且使用的是最具体的声明规则)。

    与 Common Lisp 的显著差异

    • Julia 默认使用 1 开始的数组索引,它也能处理任意的索引顺序

    • 函数和变量共用一个命名空间("Lisp-1")。

    • Julia 中有 Pair 类型,但这并不意味着它能用作 COMMON-LISP:CONS。在 Julia 中绝大多数可迭代的集合都能互换使用,例如:集合解包(splatting)、元组等。Tuple 最接近 Common Lisp 中用于异构元素的列表。使用 NamedTuple 来代替关联表(alists)。对于更大的、同类型元素的集合,应该使用 Array 和 Dict

    • 典型的使用 Julia 进行原型开发时,也会对镜像进行连续的修改,Revise.jl 包提供了这个功能。

    • 对于性能,Julia 更喜欢操作具有 类型稳定性。 Common Lisp 从底层机器操作中抽象出来,而 Julia 则更接近它们。 例如:

      • 使用 / 的整数除法总是返回浮点结果,即使计算是精确的。
        • // 总是返回一个有理数结果
        • ÷ 总是返回一个(被截断的)整数结果
      • Julia 支持大整数,但不会自动转换。默认的整数类型会溢出
      • 支持复数,但要获得复数结果,你需要复数输入
      • 有多种 Complex 和 Rational 类型,具有不同的组成类型。
    • 模块(名称空间)可以是分层的。import 和 using 有着双重角色:他们加载代码并让代码在命名空间中可用。import 用于仅有模块名是可用的情况,大致等价于 ASDF:LOAD-OP。槽名(Slot name)不需要单独导出。全局变量不能从模块的外部赋值,除了 eval(mod, :(var = val)) 这个例外情况。

    • 宏以 @ 开头,并没有像 Common Lisp 那样无缝地集成到语言中;因此在 Julia 中,宏的使用不像在 Common Lisp 中那样广泛。Julia 支持的一种卫生(hygiene)形式。因为不同的表层语法,Julia 中没有 COMMON-LISP:&BODY 的等价形式。

    • 所有的函数都是通用的并且使用多重分派。函数的参数列表也无需遵循一样的模板,这让我们有了一个强大的范式:do。可选参数与关键字参数的处理方式不同。方法的歧义没有像在 Common Lisp 对象系统中那样得到解决,因此需要为交集定义更具体的方法。

    • 符号不属于任何包,它本身也不包含任何值。M.var 会对 M 模块里的  var 符号求值。

    • Julia 完全支持函数式编程风格,包括闭包等特性。但这并不是 Julia 的惯用风格。修改捕获变量时需要一些额外的变通以便提高性能。

    diff --git a/dev/manual/parallel-computing/index.html b/dev/manual/parallel-computing/index.html index 6d97c000..f9ac927b 100644 --- a/dev/manual/parallel-computing/index.html +++ b/dev/manual/parallel-computing/index.html @@ -6,4 +6,4 @@ ga('create', 'UA-28835595-9', 'auto'); ga('send', 'pageview', {'page': location.pathname + location.search + location.hash}); -

    并行计算

    Julia 支持这四类并发和并行编程:

    1. 异步“任务”或协程

      Julia Tasks 允许暂停和恢复 I/O、事件处理、生产者-消费者进程和类似模式的计算。 Tasks 可以通过wailfetch 等操作进行同步,并通过 Channel 进行通信。 虽然严格来说不是并行计算,但 Julia 允许在多个线程上调度任务。

    2. 多线程

      Julia 的多线程提供了在多个线程、CPU 内核或共享内存上同时调度任务的能力。这通常是在个人 PC 或单个大型多核服务器上获得并行性的最简单方法。 Julia 的多线程是可组合的。当一个多线程函数调用另一个多线程函数时,Julia 将在可用资源上全局调度所有线程,而不会超额使用。

    3. 分布式计算:

      分布式计算运行多个具有独立内存空间的 Julia 进程。 这些可以在同一台计算机或多台计算机上。 Distributed 标准库提供了远程执行 Julia 函数的能力。 使用这个基本构建块,可以构建许多不同类型的分布式计算抽象。 像 DistributedArrays.jl 这样的包就是这种抽象的一个示例。 另一方面,像 MPI.jlElemental.jl 这样的包提供对现有 MPI 生态库的访问。

    4. GPU 计算:

      Julia GPU 编译器提供了在 GPU 上本地运行 Julia 代码的能力。 有一个针对 GPU 的丰富的 Julia 软件包生态系统。 JuliaGPU.org 网站提供了功能列表、支持的 GPU、相关包和文档。

    +

    并行计算

    Julia 支持这四类并发和并行编程:

    1. 异步“任务”或协程

      Julia Tasks 允许暂停和恢复 I/O、事件处理、生产者-消费者进程和类似模式的计算。 Tasks 可以通过wailfetch 等操作进行同步,并通过 Channel 进行通信。 虽然严格来说不是并行计算,但 Julia 允许在多个线程上调度任务。

    2. 多线程

      Julia 的多线程提供了在多个线程、CPU 内核或共享内存上同时调度任务的能力。这通常是在个人 PC 或单个大型多核服务器上获得并行性的最简单方法。 Julia 的多线程是可组合的。当一个多线程函数调用另一个多线程函数时,Julia 将在可用资源上全局调度所有线程,而不会超额使用。

    3. 分布式计算:

      分布式计算运行多个具有独立内存空间的 Julia 进程。 这些可以在同一台计算机或多台计算机上。 Distributed 标准库提供了远程执行 Julia 函数的能力。 使用这个基本构建块,可以构建许多不同类型的分布式计算抽象。 像 DistributedArrays.jl 这样的包就是这种抽象的一个示例。 另一方面,像 MPI.jlElemental.jl 这样的包提供对现有 MPI 生态库的访问。

    4. GPU 计算:

      Julia GPU 编译器提供了在 GPU 上本地运行 Julia 代码的能力。 有一个针对 GPU 的丰富的 Julia 软件包生态系统。 JuliaGPU.org 网站提供了功能列表、支持的 GPU、相关包和文档。

    diff --git a/dev/manual/performance-tips/index.html b/dev/manual/performance-tips/index.html index ff3cb8f2..7df89088 100644 --- a/dev/manual/performance-tips/index.html +++ b/dev/manual/performance-tips/index.html @@ -563,4 +563,4 @@ x -> x * r end return f -end

    let 代码块创建了一个新的变量 r,它的作用域只是内部函数。第二种技术在捕获变量存在时完全恢复了语言性能。请注意,这是编译器的一个快速发展的方面,未来的版本可能不需要依靠这种程度的程序员注释来获得性能。与此同时,一些用户提供的包(如 FastClosures)会自动插入像在 abmult3 中那样的 let 语句。

    +end

    let 代码块创建了一个新的变量 r,它的作用域只是内部函数。第二种技术在捕获变量存在时完全恢复了语言性能。请注意,这是编译器的一个快速发展的方面,未来的版本可能不需要依靠这种程度的程序员注释来获得性能。与此同时,一些用户提供的包(如 FastClosures)会自动插入像在 abmult3 中那样的 let 语句。

    diff --git a/dev/manual/profile/index.html b/dev/manual/profile/index.html index ec038395..8ed989c8 100644 --- a/dev/manual/profile/index.html +++ b/dev/manual/profile/index.html @@ -73,4 +73,4 @@ Profile.init(n = 10^7, delay = 0.01)

    n 是能够存储的指令指针总数,默认值为 10^6。如果通常的回溯是 20 个指令指针,那么可以收集 50000 次回溯,这意味着统计不确定性少于 1%。这对于大多数应用来说可能已经足够了。

    因此,你更可能需要修改 delay,它以秒为单位,设置在快照之间 Julia 用于执行所请求计算的时长。长时间运行的工作可能不需要经常回溯。默认设置为 delay = 0.001。当然,你可以减少和增加 delay;但是,一旦 delay 接近执行一次回溯所需的时间(在作者的笔记本上约为 30 微妙),性能分析的开销就会增加。

    内存分配分析

    减少内存分配是提高性能的最常用技术之一。内存分配总量可以用 @time@allocated,触发内存分配的特定行通常可以通过这些行产生的垃圾分配成本从性能分析中推断出来。但是,直接测量每行代码的内存分配总量有时会更高效。

    为了逐行测量内存分配,启动 Julia 时请使用命令行选项 --track-allocation=<setting>,该选项的可选值有 none(默认值,不测量内存分配)、user(测量除 Julia core 代码之外的所有代码的内存分配)或 all(测量 Julia 代码中每一行的内存分配)。这会为每行已编译的代码测量内存。在退出 Julia 时,累积的结果将写入到文本文件中,此文本文件名称为该文件名称后加 .mem,并与源文件位于同一目录下。该文件的每行列出内存分配的总字节数。Coverage包括了一些基本分析工具,例如,按照内存分配的字节数对行进行排序的工具。

    在解释结果时,有一些需要注意的细节。在 user 设定下,直接从 REPL 调用的任何函数的第一行都将会显示内存分配,这是由发生在 REPL 代码本身的事件造成的。更重要的是,JIT 编译也会添加内存分配计数,因为 Julia 的编译器大部分是用 Julia 编写的(并且编译通常需要内存分配)。建议的分析过程是先通过执行待分析的所有命令来强制编译,然后调用 Profile.clear_malloc_data() 来重置所有内存计数器。最后,执行所需的命令并退出 Julia 以触发 .mem 文件的生成。

    外部性能分析

    Julia 目前支持的外部性能分析工具有 Intel VTuneOProfileperf

    根据你所选择的工具,编译时请在 Make.user 中将 USE_INTEL_JITEVENTSUSE_OPROFILE_JITEVENTSUSE_PERF_JITEVENTS 设置为 1。多个上述编译标志是支持的。

    在运行 Julia 前,请将环境变量 ENABLE_JITPROFILING 设置为 1。

    现在,你可以通过多种方式使用这些工具!例如,可以使用 OProfile 来尝试做个简单的记录:

    >ENABLE_JITPROFILING=1 sudo operf -Vdebug ./julia test/fastmath.jl
     >opreport -l `which ./julia`

    或与 perf 类似:

    $ ENABLE_JITPROFILING=1 perf record -o /tmp/perf.data --call-graph dwarf -k 1 ./julia /test/fastmath.jl
     $ perf inject --jit --input /tmp/perf.data --output /tmp/perf-jit.data
    -$ perf report --call-graph -G -i /tmp/perf-jit.data

    你可以测量关于程序的更多有趣数据,若要获得详尽的列表,请阅读 Linux perf 示例页面

    请记住,perf 会为每次执行保存一个 perf.data 文件,即使对于小程序,它也可能变得非常大。此外,perf LLVM 模块会将调试对象保存在 ~/.debug/jit 中,记得经常清理该文件夹。

    +$ perf report --call-graph -G -i /tmp/perf-jit.data

    你可以测量关于程序的更多有趣数据,若要获得详尽的列表,请阅读 Linux perf 示例页面

    请记住,perf 会为每次执行保存一个 perf.data 文件,即使对于小程序,它也可能变得非常大。此外,perf LLVM 模块会将调试对象保存在 ~/.debug/jit 中,记得经常清理该文件夹。

    diff --git a/dev/manual/running-external-programs/index.html b/dev/manual/running-external-programs/index.html index b75d837f..fa6ee043 100644 --- a/dev/manual/running-external-programs/index.html +++ b/dev/manual/running-external-programs/index.html @@ -139,4 +139,4 @@ foo ever! julia> run(addenv(`sh -c "echo foo \$HOWLONG"`, "HOWLONG" => "ever!")); -foo ever! +foo ever! diff --git a/dev/manual/stacktraces/index.html b/dev/manual/stacktraces/index.html index a3aa1916..6c9d140c 100644 --- a/dev/manual/stacktraces/index.html +++ b/dev/manual/stacktraces/index.html @@ -199,4 +199,4 @@ jl_apply_generic at gf.c:2167 julia> println("The top frame is from $(frame[1].func)!") -The top frame is from jl_apply_generic! +The top frame is from jl_apply_generic! diff --git a/dev/manual/strings/index.html b/dev/manual/strings/index.html index 67b49fdb..f3fdaf96 100644 --- a/dev/manual/strings/index.html +++ b/dev/manual/strings/index.html @@ -431,4 +431,4 @@ 0xbf

    字符字面量也用到了相同的行为。

    对于小于 \u80 的代码,每个代码的 UTF-8 编码恰好只是由相应 \x 转义产生的单个字节,因此忽略两者的差别无伤大雅。然而,从 x80\xff 的转义比起从 u80\uff 的转义来,就有一个主要的差别:前者都只编码为一个字节,它没有形成任何有效 UTF-8 数据,除非它后面有非常特殊的连接字节;而后者则都代表 2 字节编码的 Unicode 代码。

    如果这些还是太难理解,试着读一下 "每个软件开发人员绝对必须知道的最基础 Unicode 和字符集知识"。它是一个优质的 Unicode 和 UTF-8 指南,或许能帮助解除一些这方面的疑惑。

    版本号字面量

    版本号很容易用 v"..." 形式的非标准字符串字面量表示。版本号字面量生成遵循语义版本规范的 VersionNumber 对象,因此由主、次、补丁号构成,后跟预发行 (pre-release) 和生成阿尔法数注释(build alpha-numeric)。例如,v"0.2.1-rc1+win64" 可分为主版本号 0,次版本号 2,补丁版本号 1,预发行版号 rc1,以及生成版本 win64。输入版本字面量时,除了主版本号以外所有内容都是可选的,因此 v"0.2" 等效于 v"0.2.0"(预发行号和生成注释为空),v"2" 等效于 v"2.0.0",等等。

    VersionNumber 对象在轻松正确地比较两个(或更多)版本时非常有用。例如,常数 VERSION 把 Julia 的版本号保留为一个 VersionNumber 对象,因此可以像下面这样用简单的声明定义一些特定版本的行为:

    if v"0.2" <= VERSION < v"0.3-"
         # 针对 0.2 发行版系列做些事情
     end

    注意在上例中用到了非标准版本号 v"0.3-",其中有尾随符 -:这个符号是 Julia 标准的扩展,它可以用来表明低于任何 0.3 发行版的版本,包括所有的预发行版。所以上例中代码只能在稳定版本 0.2 上运行,而不能在 v"0.3.0-rc1" 这样的版本上运行。为了支持非稳定(即预发行)的 0.2 版本,下限检查应像这样应该改为:v"0.2-" <= VERSION

    另一个非标准版本规范扩展使得能够使用 + 来表示生成版本的上限,例如 VERSION > v"0.2-rc1+" 可以用来表示任意高于 0.2-rc1 和其任意生成版本的版本:它对 v"0.2-rc1+win64" 返回 false 而对 v"0.2-rc2" 返回 true

    在比较中使用这样的特殊版本是个好办法(特别是,总是应该对高版本使用尾随 -,除非有好理由不这样),但它们不应该被用作任何内容的实际版本,因为它们在语义版本控制方案中无效。

    除了用于定义常数 VERSIONVersionNumber 对象在 Pkg 模块应用广泛,常用于指定软件包的版本及其依赖。

    原始字符串字面量

    无插值和非转义的原始字符串可用 raw"..." 形式的非标准字符串字面量表示。原始字符串字面量生成普通的 String 对象,它无需插值和非转义地包含和输入完全一样的封闭式内容。这对于包含其他语言中使用 " 或 \" 作为特殊字符的代码或标记的字符串很有用。

    例外的是,引号仍必须转义,例如 raw"\"" 等效于 "\""。为了能够表达所有字符串,反斜杠也必须转义,不过只是当它刚好出现在引号前面时。

    julia> println(raw"\\ \\\"")
    -\\ \"

    请注意,前两个反斜杠在输出中逐字显示,这是因为它们不是在引号前面。然而,接下来的一个反斜杠字符转义了后面的一个反斜杠;又由于这些反斜杠出现在引号前面,最后一个反斜杠转义了一个引号。

    +\\ \"

    请注意,前两个反斜杠在输出中逐字显示,这是因为它们不是在引号前面。然而,接下来的一个反斜杠字符转义了后面的一个反斜杠;又由于这些反斜杠出现在引号前面,最后一个反斜杠转义了一个引号。

    diff --git a/dev/manual/style-guide/index.html b/dev/manual/style-guide/index.html index 55af1d72..0752bed4 100644 --- a/dev/manual/style-guide/index.html +++ b/dev/manual/style-guide/index.html @@ -63,4 +63,4 @@ 1.0 julia> h(1) -2//1

    所以,可能时尽量使用 Int 字面量,对非整数字面量使用 Rational{Int},这样可以让代码变得更容易使用。

    +2//1

    所以,可能时尽量使用 Int 字面量,对非整数字面量使用 Rational{Int},这样可以让代码变得更容易使用。

    diff --git a/dev/manual/types/index.html b/dev/manual/types/index.html index 1657a1d1..4b6563b6 100644 --- a/dev/manual/types/index.html +++ b/dev/manual/types/index.html @@ -408,4 +408,4 @@ "First" julia> firstlast(Val(false)) -"Last"

    为了保证 Julia 的一致性,调用处应当始终传递 Val 实例 而不是 类型,也就是使用 foo(Val(:bar)) 而不是 foo(Val{:bar})

    值得注意的是,参数「值」类型非常容易被误用,包括 Val;在不适用的情形下,你很容易使代码性能变得更糟糕。特别是,你可能永远都不会想要写出如上所示的代码。有关 Val 的正确(和不正确)使用的更多信息,请阅读性能建议中更广泛的讨论。

    +"Last"

    为了保证 Julia 的一致性,调用处应当始终传递 Val 实例 而不是 类型,也就是使用 foo(Val(:bar)) 而不是 foo(Val{:bar})

    值得注意的是,参数「值」类型非常容易被误用,包括 Val;在不适用的情形下,你很容易使代码性能变得更糟糕。特别是,你可能永远都不会想要写出如上所示的代码。有关 Val 的正确(和不正确)使用的更多信息,请阅读性能建议中更广泛的讨论。

    diff --git a/dev/manual/unicode-input/index.html b/dev/manual/unicode-input/index.html index 626faa1d..2b81f76e 100644 --- a/dev/manual/unicode-input/index.html +++ b/dev/manual/unicode-input/index.html @@ -6,4 +6,4 @@ ga('create', 'UA-28835595-9', 'auto'); ga('send', 'pageview', {'page': location.pathname + location.search + location.hash}); -

    Unicode 输入表

    在 Julia REPL 或其它编辑器中,可以像输入 LaTeX 符号一样,用 tab 补全下表列出的 Unicode 字符。在 REPL 中,可以先按 ? 进入帮助模式,然后将 Unicode 字符复制粘贴进去,一般在文档开头就会写输入方式。

    Warning

    此表第二列可能会缺失一些字符,对某些字符的显示效果也可能会与在 Julia REPL 中不一致。如果发生了这种状况,强烈建议用户检查一下浏览器或 REPL 的字体设置,目前已知很多字体都有显示问题。

    Code point(s)Character(s)Tab completion sequence(s)Unicode name(s)
    U+000A1¡\exclamdownInverted Exclamation Mark
    U+000A3£\sterlingPound Sign
    U+000A5¥\yenYen Sign
    U+000A6¦\brokenbarBroken Bar / Broken Vertical Bar
    U+000A7§\SSection Sign
    U+000A9©\copyright, \:copyright:Copyright Sign
    U+000AAª\ordfeminineFeminine Ordinal Indicator
    U+000AC¬\negNot Sign
    U+000AE®\circledR, \:registered:Registered Sign / Registered Trade Mark Sign
    U+000AF¯\highminusMacron / Spacing Macron
    U+000B0°\degreeDegree Sign
    U+000B1±\pmPlus-Minus Sign / Plus-Or-Minus Sign
    U+000B2²\^2Superscript Two / Superscript Digit Two
    U+000B3³\^3Superscript Three / Superscript Digit Three
    U+000B6\PPilcrow Sign / Paragraph Sign
    U+000B7·\cdotpMiddle Dot
    U+000B9¹\^1Superscript One / Superscript Digit One
    U+000BAº\ordmasculineMasculine Ordinal Indicator
    U+000BC¼\1/4Vulgar Fraction One Quarter / Fraction One Quarter
    U+000BD½\1/2Vulgar Fraction One Half / Fraction One Half
    U+000BE¾\3/4Vulgar Fraction Three Quarters / Fraction Three Quarters
    U+000BF¿\questiondownInverted Question Mark
    U+000C5Å\AALatin Capital Letter A With Ring Above / Latin Capital Letter A Ring
    U+000C6Æ\AELatin Capital Letter Ae / Latin Capital Letter A E
    U+000D0Ð\DHLatin Capital Letter Eth
    U+000D7×\timesMultiplication Sign
    U+000D8Ø\OLatin Capital Letter O With Stroke / Latin Capital Letter O Slash
    U+000DEÞ\THLatin Capital Letter Thorn
    U+000DFß\ssLatin Small Letter Sharp S
    U+000E5å\aaLatin Small Letter A With Ring Above / Latin Small Letter A Ring
    U+000E6æ\aeLatin Small Letter Ae / Latin Small Letter A E
    U+000F0ð\eth, \dhLatin Small Letter Eth
    U+000F7÷\divDivision Sign
    U+000F8ø\oLatin Small Letter O With Stroke / Latin Small Letter O Slash
    U+000FEþ\thLatin Small Letter Thorn
    U+00110Đ\DJLatin Capital Letter D With Stroke / Latin Capital Letter D Bar
    U+00111đ\djLatin Small Letter D With Stroke / Latin Small Letter D Bar
    U+00127ħ\hbarLatin Small Letter H With Stroke / Latin Small Letter H Bar
    U+00131ı\imathLatin Small Letter Dotless I
    U+00141Ł\LLatin Capital Letter L With Stroke / Latin Capital Letter L Slash
    U+00142ł\lLatin Small Letter L With Stroke / Latin Small Letter L Slash
    U+0014AŊ\NGLatin Capital Letter Eng
    U+0014Bŋ\ngLatin Small Letter Eng
    U+00152Œ\OELatin Capital Ligature Oe / Latin Capital Letter O E
    U+00153œ\oeLatin Small Ligature Oe / Latin Small Letter O E
    U+00195ƕ\hvligLatin Small Letter Hv / Latin Small Letter H V
    U+0019Eƞ\nrlegLatin Small Letter N With Long Right Leg
    U+001B5Ƶ\ZbarLatin Capital Letter Z With Stroke / Latin Capital Letter Z Bar
    U+001C2ǂ\doublepipeLatin Letter Alveolar Click / Latin Letter Pipe Double Bar
    U+00237ȷ\jmathLatin Small Letter Dotless J
    U+00250ɐ\trnaLatin Small Letter Turned A
    U+00252ɒ\trnsaLatin Small Letter Turned Alpha / Latin Small Letter Turned Script A
    U+00254ɔ\openoLatin Small Letter Open O
    U+00256ɖ\rtldLatin Small Letter D With Tail / Latin Small Letter D Retroflex Hook
    U+00259ə\schwaLatin Small Letter Schwa
    U+00263ɣ\pgammaLatin Small Letter Gamma
    U+00264ɤ\pbgamLatin Small Letter Rams Horn / Latin Small Letter Baby Gamma
    U+00265ɥ\trnhLatin Small Letter Turned H
    U+0026Cɬ\btdlLatin Small Letter L With Belt / Latin Small Letter L Belt
    U+0026Dɭ\rtllLatin Small Letter L With Retroflex Hook / Latin Small Letter L Retroflex Hook
    U+0026Fɯ\trnmLatin Small Letter Turned M
    U+00270ɰ\trnmlrLatin Small Letter Turned M With Long Leg
    U+00271ɱ\ltlmrLatin Small Letter M With Hook / Latin Small Letter M Hook
    U+00272ɲ\ltlnLatin Small Letter N With Left Hook / Latin Small Letter N Hook
    U+00273ɳ\rtlnLatin Small Letter N With Retroflex Hook / Latin Small Letter N Retroflex Hook
    U+00277ɷ\clomegLatin Small Letter Closed Omega
    U+00278ɸ\ltphiLatin Small Letter Phi
    U+00279ɹ\trnrLatin Small Letter Turned R
    U+0027Aɺ\trnrlLatin Small Letter Turned R With Long Leg
    U+0027Bɻ\rttrnrLatin Small Letter Turned R With Hook / Latin Small Letter Turned R Hook
    U+0027Cɼ\rlLatin Small Letter R With Long Leg
    U+0027Dɽ\rtlrLatin Small Letter R With Tail / Latin Small Letter R Hook
    U+0027Eɾ\fhrLatin Small Letter R With Fishhook / Latin Small Letter Fishhook R
    U+00282ʂ\rtlsLatin Small Letter S With Hook / Latin Small Letter S Hook
    U+00283ʃ\eshLatin Small Letter Esh
    U+00287ʇ\trntLatin Small Letter Turned T
    U+00288ʈ\rtltLatin Small Letter T With Retroflex Hook / Latin Small Letter T Retroflex Hook
    U+0028Aʊ\pupsilLatin Small Letter Upsilon
    U+0028Bʋ\pscrvLatin Small Letter V With Hook / Latin Small Letter Script V
    U+0028Cʌ\invvLatin Small Letter Turned V
    U+0028Dʍ\invwLatin Small Letter Turned W
    U+0028Eʎ\trnyLatin Small Letter Turned Y
    U+00290ʐ\rtlzLatin Small Letter Z With Retroflex Hook / Latin Small Letter Z Retroflex Hook
    U+00292ʒ\yoghLatin Small Letter Ezh / Latin Small Letter Yogh
    U+00294ʔ\glstLatin Letter Glottal Stop
    U+00295ʕ\reglstLatin Letter Pharyngeal Voiced Fricative / Latin Letter Reversed Glottal Stop
    U+00296ʖ\inglstLatin Letter Inverted Glottal Stop
    U+0029Eʞ\turnkLatin Small Letter Turned K
    U+002A4ʤ\dyoghLatin Small Letter Dezh Digraph / Latin Small Letter D Yogh
    U+002A7ʧ\teshLatin Small Letter Tesh Digraph / Latin Small Letter T Esh
    U+002B0ʰ\^hModifier Letter Small H
    U+002B2ʲ\^jModifier Letter Small J
    U+002B3ʳ\^rModifier Letter Small R
    U+002B7ʷ\^wModifier Letter Small W
    U+002B8ʸ\^yModifier Letter Small Y
    U+002BCʼ\raspModifier Letter Apostrophe
    U+002C8ˈ\vertsModifier Letter Vertical Line
    U+002CCˌ\vertiModifier Letter Low Vertical Line
    U+002D0ː\lmrkModifier Letter Triangular Colon
    U+002D1ˑ\hlmrkModifier Letter Half Triangular Colon
    U+002D2˒\sbrhrModifier Letter Centred Right Half Ring / Modifier Letter Centered Right Half Ring
    U+002D3˓\sblhrModifier Letter Centred Left Half Ring / Modifier Letter Centered Left Half Ring
    U+002D4˔\raisModifier Letter Up Tack
    U+002D5˕\lowModifier Letter Down Tack
    U+002D8˘\uBreve / Spacing Breve
    U+002DC˜\tildelowSmall Tilde / Spacing Tilde
    U+002E1ˡ\^lModifier Letter Small L
    U+002E2ˢ\^sModifier Letter Small S
    U+002E3ˣ\^xModifier Letter Small X
    U+00300 ̀ \graveCombining Grave Accent / Non-Spacing Grave
    U+00301 ́ \acuteCombining Acute Accent / Non-Spacing Acute
    U+00302 ̂ \hatCombining Circumflex Accent / Non-Spacing Circumflex
    U+00303 ̃ \tildeCombining Tilde / Non-Spacing Tilde
    U+00304 ̄ \barCombining Macron / Non-Spacing Macron
    U+00305 ̅ \overbarCombining Overline / Non-Spacing Overscore
    U+00306 ̆ \breveCombining Breve / Non-Spacing Breve
    U+00307 ̇ \dotCombining Dot Above / Non-Spacing Dot Above
    U+00308 ̈ \ddotCombining Diaeresis / Non-Spacing Diaeresis
    U+00309 ̉ \ovhookCombining Hook Above / Non-Spacing Hook Above
    U+0030A ̊ \ocircCombining Ring Above / Non-Spacing Ring Above
    U+0030B ̋ \HCombining Double Acute Accent / Non-Spacing Double Acute
    U+0030C ̌ \checkCombining Caron / Non-Spacing Hacek
    U+00310 ̐ \candraCombining Candrabindu / Non-Spacing Candrabindu
    U+00312 ̒ \oturnedcommaCombining Turned Comma Above / Non-Spacing Turned Comma Above
    U+00315 ̕ \ocommatoprightCombining Comma Above Right / Non-Spacing Comma Above Right
    U+0031A ̚ \droangCombining Left Angle Above / Non-Spacing Left Angle Above
    U+00321 ̡ \palhCombining Palatalized Hook Below / Non-Spacing Palatalized Hook Below
    U+00322 ̢ \rhCombining Retroflex Hook Below / Non-Spacing Retroflex Hook Below
    U+00327 ̧ \cCombining Cedilla / Non-Spacing Cedilla
    U+00328 ̨ \kCombining Ogonek / Non-Spacing Ogonek
    U+0032A ̪ \sbbrgCombining Bridge Below / Non-Spacing Bridge Below
    U+00330 ̰ \wideutildeCombining Tilde Below / Non-Spacing Tilde Below
    U+00332 ̲ \underbarCombining Low Line / Non-Spacing Underscore
    U+00336 ̶ \strike, \soutCombining Long Stroke Overlay / Non-Spacing Long Bar Overlay
    U+00338 ̸ \notCombining Long Solidus Overlay / Non-Spacing Long Slash Overlay
    U+0034D ͍ \underleftrightarrowCombining Left Right Arrow Below
    U+00391Α\AlphaGreek Capital Letter Alpha
    U+00392Β\BetaGreek Capital Letter Beta
    U+00393Γ\GammaGreek Capital Letter Gamma
    U+00394Δ\DeltaGreek Capital Letter Delta
    U+00395Ε\EpsilonGreek Capital Letter Epsilon
    U+00396Ζ\ZetaGreek Capital Letter Zeta
    U+00397Η\EtaGreek Capital Letter Eta
    U+00398Θ\ThetaGreek Capital Letter Theta
    U+00399Ι\IotaGreek Capital Letter Iota
    U+0039AΚ\KappaGreek Capital Letter Kappa
    U+0039BΛ\LambdaGreek Capital Letter Lamda / Greek Capital Letter Lambda
    U+0039CΜ\upMuGreek Capital Letter Mu
    U+0039DΝ\upNuGreek Capital Letter Nu
    U+0039EΞ\XiGreek Capital Letter Xi
    U+0039FΟ\upOmicronGreek Capital Letter Omicron
    U+003A0Π\PiGreek Capital Letter Pi
    U+003A1Ρ\RhoGreek Capital Letter Rho
    U+003A3Σ\SigmaGreek Capital Letter Sigma
    U+003A4Τ\TauGreek Capital Letter Tau
    U+003A5Υ\UpsilonGreek Capital Letter Upsilon
    U+003A6Φ\PhiGreek Capital Letter Phi
    U+003A7Χ\ChiGreek Capital Letter Chi
    U+003A8Ψ\PsiGreek Capital Letter Psi
    U+003A9Ω\OmegaGreek Capital Letter Omega
    U+003B1α\alphaGreek Small Letter Alpha
    U+003B2β\betaGreek Small Letter Beta
    U+003B3γ\gammaGreek Small Letter Gamma
    U+003B4δ\deltaGreek Small Letter Delta
    U+003B5ε\upepsilon, \varepsilonGreek Small Letter Epsilon
    U+003B6ζ\zetaGreek Small Letter Zeta
    U+003B7η\etaGreek Small Letter Eta
    U+003B8θ\thetaGreek Small Letter Theta
    U+003B9ι\iotaGreek Small Letter Iota
    U+003BAκ\kappaGreek Small Letter Kappa
    U+003BBλ\lambdaGreek Small Letter Lamda / Greek Small Letter Lambda
    U+003BCμ\muGreek Small Letter Mu
    U+003BDν\nuGreek Small Letter Nu
    U+003BEξ\xiGreek Small Letter Xi
    U+003BFο\upomicronGreek Small Letter Omicron
    U+003C0π\piGreek Small Letter Pi
    U+003C1ρ\rhoGreek Small Letter Rho
    U+003C2ς\varsigmaGreek Small Letter Final Sigma
    U+003C3σ\sigmaGreek Small Letter Sigma
    U+003C4τ\tauGreek Small Letter Tau
    U+003C5υ\upsilonGreek Small Letter Upsilon
    U+003C6φ\varphiGreek Small Letter Phi
    U+003C7χ\chiGreek Small Letter Chi
    U+003C8ψ\psiGreek Small Letter Psi
    U+003C9ω\omegaGreek Small Letter Omega
    U+003D0ϐ\upvarbetaGreek Beta Symbol / Greek Small Letter Curled Beta
    U+003D1ϑ\varthetaGreek Theta Symbol / Greek Small Letter Script Theta
    U+003D5ϕ\phiGreek Phi Symbol / Greek Small Letter Script Phi
    U+003D6ϖ\varpiGreek Pi Symbol / Greek Small Letter Omega Pi
    U+003D8Ϙ\upoldKoppaGreek Letter Archaic Koppa
    U+003D9ϙ\upoldkoppaGreek Small Letter Archaic Koppa
    U+003DAϚ\StigmaGreek Letter Stigma / Greek Capital Letter Stigma
    U+003DBϛ\upstigmaGreek Small Letter Stigma
    U+003DCϜ\DigammaGreek Letter Digamma / Greek Capital Letter Digamma
    U+003DDϝ\digammaGreek Small Letter Digamma
    U+003DEϞ\KoppaGreek Letter Koppa / Greek Capital Letter Koppa
    U+003DFϟ\upkoppaGreek Small Letter Koppa
    U+003E0Ϡ\SampiGreek Letter Sampi / Greek Capital Letter Sampi
    U+003E1ϡ\upsampiGreek Small Letter Sampi
    U+003F0ϰ\varkappaGreek Kappa Symbol / Greek Small Letter Script Kappa
    U+003F1ϱ\varrhoGreek Rho Symbol / Greek Small Letter Tailed Rho
    U+003F4ϴ\varThetaGreek Capital Theta Symbol
    U+003F5ϵ\epsilonGreek Lunate Epsilon Symbol
    U+003F6϶\backepsilonGreek Reversed Lunate Epsilon Symbol
    U+01D2C\^AModifier Letter Capital A
    U+01D2E\^BModifier Letter Capital B
    U+01D30\^DModifier Letter Capital D
    U+01D31\^EModifier Letter Capital E
    U+01D33\^GModifier Letter Capital G
    U+01D34\^HModifier Letter Capital H
    U+01D35\^IModifier Letter Capital I
    U+01D36\^JModifier Letter Capital J
    U+01D37\^KModifier Letter Capital K
    U+01D38\^LModifier Letter Capital L
    U+01D39\^MModifier Letter Capital M
    U+01D3A\^NModifier Letter Capital N
    U+01D3C\^OModifier Letter Capital O
    U+01D3E\^PModifier Letter Capital P
    U+01D3Fᴿ\^RModifier Letter Capital R
    U+01D40\^TModifier Letter Capital T
    U+01D41\^UModifier Letter Capital U
    U+01D42\^WModifier Letter Capital W
    U+01D43\^aModifier Letter Small A
    U+01D45\^alphaModifier Letter Small Alpha
    U+01D47\^bModifier Letter Small B
    U+01D48\^dModifier Letter Small D
    U+01D49\^eModifier Letter Small E
    U+01D4B\^epsilonModifier Letter Small Open E
    U+01D4D\^gModifier Letter Small G
    U+01D4F\^kModifier Letter Small K
    U+01D50\^mModifier Letter Small M
    U+01D52\^oModifier Letter Small O
    U+01D56\^pModifier Letter Small P
    U+01D57\^tModifier Letter Small T
    U+01D58\^uModifier Letter Small U
    U+01D5B\^vModifier Letter Small V
    U+01D5D\^betaModifier Letter Small Beta
    U+01D5E\^gammaModifier Letter Small Greek Gamma
    U+01D5F\^deltaModifier Letter Small Delta
    U+01D60\^phiModifier Letter Small Greek Phi
    U+01D61\^chiModifier Letter Small Chi
    U+01D62\_iLatin Subscript Small Letter I
    U+01D63\_rLatin Subscript Small Letter R
    U+01D64\_uLatin Subscript Small Letter U
    U+01D65\_vLatin Subscript Small Letter V
    U+01D66\_betaGreek Subscript Small Letter Beta
    U+01D67\_gammaGreek Subscript Small Letter Gamma
    U+01D68\_rhoGreek Subscript Small Letter Rho
    U+01D69\_phiGreek Subscript Small Letter Phi
    U+01D6A\_chiGreek Subscript Small Letter Chi
    U+01D9C\^cModifier Letter Small C
    U+01DA0\^fModifier Letter Small F
    U+01DA5\^iotaModifier Letter Small Iota
    U+01DB2\^ltphiModifier Letter Small Phi
    U+01DBB\^zModifier Letter Small Z
    U+01DBFᶿ\^thetaModifier Letter Small Theta
    U+02002\enspaceEn Space
    U+02003\quadEm Space
    U+02005\thickspaceFour-Per-Em Space
    U+02009\thinspaceThin Space
    U+0200A\hspaceHair Space
    U+02013\endashEn Dash
    U+02014\emdashEm Dash
    U+02016\VertDouble Vertical Line / Double Vertical Bar
    U+02018\lqLeft Single Quotation Mark / Single Turned Comma Quotation Mark
    U+02019\rqRight Single Quotation Mark / Single Comma Quotation Mark
    U+0201B\reaposSingle High-Reversed-9 Quotation Mark / Single Reversed Comma Quotation Mark
    U+0201C\ldqLeft Double Quotation Mark / Double Turned Comma Quotation Mark
    U+0201D\rdqRight Double Quotation Mark / Double Comma Quotation Mark
    U+02020\daggerDagger
    U+02021\ddaggerDouble Dagger
    U+02022\bulletBullet
    U+02026\dots, \ldotsHorizontal Ellipsis
    U+02030\perthousandPer Mille Sign
    U+02031\pertenthousandPer Ten Thousand Sign
    U+02032\primePrime
    U+02033\pprimeDouble Prime
    U+02034\ppprimeTriple Prime
    U+02035\backprimeReversed Prime
    U+02036\backpprimeReversed Double Prime
    U+02037\backppprimeReversed Triple Prime
    U+02039\guilsinglleftSingle Left-Pointing Angle Quotation Mark / Left Pointing Single Guillemet
    U+0203A\guilsinglrightSingle Right-Pointing Angle Quotation Mark / Right Pointing Single Guillemet
    U+0203C\:bangbang:Double Exclamation Mark
    U+02040\tieconcatCharacter Tie
    U+02049\:interrobang:Exclamation Question Mark
    U+02057\pppprimeQuadruple Prime
    U+0205D\tricolonTricolon
    U+02060\nolinebreakWord Joiner
    U+02070\^0Superscript Zero / Superscript Digit Zero
    U+02071\^iSuperscript Latin Small Letter I
    U+02074\^4Superscript Four / Superscript Digit Four
    U+02075\^5Superscript Five / Superscript Digit Five
    U+02076\^6Superscript Six / Superscript Digit Six
    U+02077\^7Superscript Seven / Superscript Digit Seven
    U+02078\^8Superscript Eight / Superscript Digit Eight
    U+02079\^9Superscript Nine / Superscript Digit Nine
    U+0207A\^+Superscript Plus Sign
    U+0207B\^-Superscript Minus / Superscript Hyphen-Minus
    U+0207C\^=Superscript Equals Sign
    U+0207D\^(Superscript Left Parenthesis / Superscript Opening Parenthesis
    U+0207E\^)Superscript Right Parenthesis / Superscript Closing Parenthesis
    U+0207F\^nSuperscript Latin Small Letter N
    U+02080\_0Subscript Zero / Subscript Digit Zero
    U+02081\_1Subscript One / Subscript Digit One
    U+02082\_2Subscript Two / Subscript Digit Two
    U+02083\_3Subscript Three / Subscript Digit Three
    U+02084\_4Subscript Four / Subscript Digit Four
    U+02085\_5Subscript Five / Subscript Digit Five
    U+02086\_6Subscript Six / Subscript Digit Six
    U+02087\_7Subscript Seven / Subscript Digit Seven
    U+02088\_8Subscript Eight / Subscript Digit Eight
    U+02089\_9Subscript Nine / Subscript Digit Nine
    U+0208A\_+Subscript Plus Sign
    U+0208B\_-Subscript Minus / Subscript Hyphen-Minus
    U+0208C\_=Subscript Equals Sign
    U+0208D\_(Subscript Left Parenthesis / Subscript Opening Parenthesis
    U+0208E\_)Subscript Right Parenthesis / Subscript Closing Parenthesis
    U+02090\_aLatin Subscript Small Letter A
    U+02091\_eLatin Subscript Small Letter E
    U+02092\_oLatin Subscript Small Letter O
    U+02093\_xLatin Subscript Small Letter X
    U+02094\_schwaLatin Subscript Small Letter Schwa
    U+02095\_hLatin Subscript Small Letter H
    U+02096\_kLatin Subscript Small Letter K
    U+02097\_lLatin Subscript Small Letter L
    U+02098\_mLatin Subscript Small Letter M
    U+02099\_nLatin Subscript Small Letter N
    U+0209A\_pLatin Subscript Small Letter P
    U+0209B\_sLatin Subscript Small Letter S
    U+0209C\_tLatin Subscript Small Letter T
    U+020A7\pesPeseta Sign
    U+020AC\euroEuro Sign
    U+020D0 ⃐ \leftharpoonaccentCombining Left Harpoon Above / Non-Spacing Left Harpoon Above
    U+020D1 ⃑ \rightharpoonaccentCombining Right Harpoon Above / Non-Spacing Right Harpoon Above
    U+020D2 ⃒ \vertoverlayCombining Long Vertical Line Overlay / Non-Spacing Long Vertical Bar Overlay
    U+020D6 ⃖ \overleftarrowCombining Left Arrow Above / Non-Spacing Left Arrow Above
    U+020D7 ⃗ \vecCombining Right Arrow Above / Non-Spacing Right Arrow Above
    U+020DB ⃛ \dddotCombining Three Dots Above / Non-Spacing Three Dots Above
    U+020DC ⃜ \ddddotCombining Four Dots Above / Non-Spacing Four Dots Above
    U+020DD ⃝ \enclosecircleCombining Enclosing Circle / Enclosing Circle
    U+020DE ⃞ \enclosesquareCombining Enclosing Square / Enclosing Square
    U+020DF ⃟ \enclosediamondCombining Enclosing Diamond / Enclosing Diamond
    U+020E1 ⃡ \overleftrightarrowCombining Left Right Arrow Above / Non-Spacing Left Right Arrow Above
    U+020E4 ⃤ \enclosetriangleCombining Enclosing Upward Pointing Triangle
    U+020E7 ⃧ \annuityCombining Annuity Symbol
    U+020E8 ⃨ \threeunderdotCombining Triple Underdot
    U+020E9 ⃩ \widebridgeaboveCombining Wide Bridge Above
    U+020EC ⃬ \underrightharpoondownCombining Rightwards Harpoon With Barb Downwards
    U+020ED ⃭ \underleftharpoondownCombining Leftwards Harpoon With Barb Downwards
    U+020EE ⃮ \underleftarrowCombining Left Arrow Below
    U+020EF ⃯ \underrightarrowCombining Right Arrow Below
    U+020F0 ⃰ \asteraccentCombining Asterisk Above
    U+02102\bbCDouble-Struck Capital C / Double-Struck C
    U+02107\eulermascheroniEuler Constant / Eulers
    U+0210A\scrgScript Small G
    U+0210B\scrHScript Capital H / Script H
    U+0210C\frakHBlack-Letter Capital H / Black-Letter H
    U+0210D\bbHDouble-Struck Capital H / Double-Struck H
    U+0210E\ith, \planckPlanck Constant
    U+0210F\hslashPlanck Constant Over Two Pi / Planck Constant Over 2 Pi
    U+02110\scrIScript Capital I / Script I
    U+02111\Im, \frakIBlack-Letter Capital I / Black-Letter I
    U+02112\scrLScript Capital L / Script L
    U+02113\ellScript Small L
    U+02115\bbNDouble-Struck Capital N / Double-Struck N
    U+02116\numeroNumero Sign / Numero
    U+02118\wpScript Capital P / Script P
    U+02119\bbPDouble-Struck Capital P / Double-Struck P
    U+0211A\bbQDouble-Struck Capital Q / Double-Struck Q
    U+0211B\scrRScript Capital R / Script R
    U+0211C\Re, \frakRBlack-Letter Capital R / Black-Letter R
    U+0211D\bbRDouble-Struck Capital R / Double-Struck R
    U+0211E\xratPrescription Take
    U+02122\trademark, \:tm:Trade Mark Sign / Trademark
    U+02124\bbZDouble-Struck Capital Z / Double-Struck Z
    U+02126\ohmOhm Sign / Ohm
    U+02127\mhoInverted Ohm Sign / Mho
    U+02128\frakZBlack-Letter Capital Z / Black-Letter Z
    U+02129\turnediotaTurned Greek Small Letter Iota
    U+0212B\AngstromAngstrom Sign / Angstrom Unit
    U+0212C\scrBScript Capital B / Script B
    U+0212D\frakCBlack-Letter Capital C / Black-Letter C
    U+0212F\scre, \eulerScript Small E
    U+02130\scrEScript Capital E / Script E
    U+02131\scrFScript Capital F / Script F
    U+02132\FinvTurned Capital F / Turned F
    U+02133\scrMScript Capital M / Script M
    U+02134\scroScript Small O
    U+02135\alephAlef Symbol / First Transfinite Cardinal
    U+02136\bethBet Symbol / Second Transfinite Cardinal
    U+02137\gimelGimel Symbol / Third Transfinite Cardinal
    U+02138\dalethDalet Symbol / Fourth Transfinite Cardinal
    U+02139\:information_source:Information Source
    U+0213C\bbpiDouble-Struck Small Pi
    U+0213D\bbgammaDouble-Struck Small Gamma
    U+0213E\bbGammaDouble-Struck Capital Gamma
    U+0213F\bbPiDouble-Struck Capital Pi
    U+02140\bbsumDouble-Struck N-Ary Summation
    U+02141\GameTurned Sans-Serif Capital G
    U+02142\sansLturnedTurned Sans-Serif Capital L
    U+02143\sansLmirroredReversed Sans-Serif Capital L
    U+02144\YupTurned Sans-Serif Capital Y
    U+02145\bbiDDouble-Struck Italic Capital D
    U+02146\bbidDouble-Struck Italic Small D
    U+02147\bbieDouble-Struck Italic Small E
    U+02148\bbiiDouble-Struck Italic Small I
    U+02149\bbijDouble-Struck Italic Small J
    U+0214A\PropertyLineProperty Line
    U+0214B\upandTurned Ampersand
    U+02150\1/7Vulgar Fraction One Seventh
    U+02151\1/9Vulgar Fraction One Ninth
    U+02152\1/10Vulgar Fraction One Tenth
    U+02153\1/3Vulgar Fraction One Third / Fraction One Third
    U+02154\2/3Vulgar Fraction Two Thirds / Fraction Two Thirds
    U+02155\1/5Vulgar Fraction One Fifth / Fraction One Fifth
    U+02156\2/5Vulgar Fraction Two Fifths / Fraction Two Fifths
    U+02157\3/5Vulgar Fraction Three Fifths / Fraction Three Fifths
    U+02158\4/5Vulgar Fraction Four Fifths / Fraction Four Fifths
    U+02159\1/6Vulgar Fraction One Sixth / Fraction One Sixth
    U+0215A\5/6Vulgar Fraction Five Sixths / Fraction Five Sixths
    U+0215B\1/8Vulgar Fraction One Eighth / Fraction One Eighth
    U+0215C\3/8Vulgar Fraction Three Eighths / Fraction Three Eighths
    U+0215D\5/8Vulgar Fraction Five Eighths / Fraction Five Eighths
    U+0215E\7/8Vulgar Fraction Seven Eighths / Fraction Seven Eighths
    U+0215F\1/Fraction Numerator One
    U+02189\0/3Vulgar Fraction Zero Thirds
    U+02190\leftarrowLeftwards Arrow / Left Arrow
    U+02191\uparrowUpwards Arrow / Up Arrow
    U+02192\to, \rightarrowRightwards Arrow / Right Arrow
    U+02193\downarrowDownwards Arrow / Down Arrow
    U+02194\leftrightarrow, \:left_right_arrow:Left Right Arrow
    U+02195\updownarrow, \:arrow_up_down:Up Down Arrow
    U+02196\nwarrow, \:arrow_upper_left:North West Arrow / Upper Left Arrow
    U+02197\nearrow, \:arrow_upper_right:North East Arrow / Upper Right Arrow
    U+02198\searrow, \:arrow_lower_right:South East Arrow / Lower Right Arrow
    U+02199\swarrow, \:arrow_lower_left:South West Arrow / Lower Left Arrow
    U+0219A\nleftarrowLeftwards Arrow With Stroke / Left Arrow With Stroke
    U+0219B\nrightarrowRightwards Arrow With Stroke / Right Arrow With Stroke
    U+0219C\leftwavearrowLeftwards Wave Arrow / Left Wave Arrow
    U+0219D\rightwavearrowRightwards Wave Arrow / Right Wave Arrow
    U+0219E\twoheadleftarrowLeftwards Two Headed Arrow / Left Two Headed Arrow
    U+0219F\twoheaduparrowUpwards Two Headed Arrow / Up Two Headed Arrow
    U+021A0\twoheadrightarrowRightwards Two Headed Arrow / Right Two Headed Arrow
    U+021A1\twoheaddownarrowDownwards Two Headed Arrow / Down Two Headed Arrow
    U+021A2\leftarrowtailLeftwards Arrow With Tail / Left Arrow With Tail
    U+021A3\rightarrowtailRightwards Arrow With Tail / Right Arrow With Tail
    U+021A4\mapsfromLeftwards Arrow From Bar / Left Arrow From Bar
    U+021A5\mapsupUpwards Arrow From Bar / Up Arrow From Bar
    U+021A6\mapstoRightwards Arrow From Bar / Right Arrow From Bar
    U+021A7\mapsdownDownwards Arrow From Bar / Down Arrow From Bar
    U+021A8\updownarrowbarUp Down Arrow With Base
    U+021A9\hookleftarrow, \:leftwards_arrow_with_hook:Leftwards Arrow With Hook / Left Arrow With Hook
    U+021AA\hookrightarrow, \:arrow_right_hook:Rightwards Arrow With Hook / Right Arrow With Hook
    U+021AB\looparrowleftLeftwards Arrow With Loop / Left Arrow With Loop
    U+021AC\looparrowrightRightwards Arrow With Loop / Right Arrow With Loop
    U+021AD\leftrightsquigarrowLeft Right Wave Arrow
    U+021AE\nleftrightarrowLeft Right Arrow With Stroke
    U+021AF\downzigzagarrowDownwards Zigzag Arrow / Down Zigzag Arrow
    U+021B0\LshUpwards Arrow With Tip Leftwards / Up Arrow With Tip Left
    U+021B1\RshUpwards Arrow With Tip Rightwards / Up Arrow With Tip Right
    U+021B2\LdshDownwards Arrow With Tip Leftwards / Down Arrow With Tip Left
    U+021B3\RdshDownwards Arrow With Tip Rightwards / Down Arrow With Tip Right
    U+021B4\linefeedRightwards Arrow With Corner Downwards / Right Arrow With Corner Down
    U+021B5\carriagereturnDownwards Arrow With Corner Leftwards / Down Arrow With Corner Left
    U+021B6\curvearrowleftAnticlockwise Top Semicircle Arrow
    U+021B7\curvearrowrightClockwise Top Semicircle Arrow
    U+021B8\barovernorthwestarrowNorth West Arrow To Long Bar / Upper Left Arrow To Long Bar
    U+021B9\barleftarrowrightarrowbarLeftwards Arrow To Bar Over Rightwards Arrow To Bar / Left Arrow To Bar Over Right Arrow To Bar
    U+021BA\circlearrowleftAnticlockwise Open Circle Arrow
    U+021BB\circlearrowrightClockwise Open Circle Arrow
    U+021BC\leftharpoonupLeftwards Harpoon With Barb Upwards / Left Harpoon With Barb Up
    U+021BD\leftharpoondownLeftwards Harpoon With Barb Downwards / Left Harpoon With Barb Down
    U+021BE\upharpoonrightUpwards Harpoon With Barb Rightwards / Up Harpoon With Barb Right
    U+021BF\upharpoonleftUpwards Harpoon With Barb Leftwards / Up Harpoon With Barb Left
    U+021C0\rightharpoonupRightwards Harpoon With Barb Upwards / Right Harpoon With Barb Up
    U+021C1\rightharpoondownRightwards Harpoon With Barb Downwards / Right Harpoon With Barb Down
    U+021C2\downharpoonrightDownwards Harpoon With Barb Rightwards / Down Harpoon With Barb Right
    U+021C3\downharpoonleftDownwards Harpoon With Barb Leftwards / Down Harpoon With Barb Left
    U+021C4\rightleftarrowsRightwards Arrow Over Leftwards Arrow / Right Arrow Over Left Arrow
    U+021C5\dblarrowupdownUpwards Arrow Leftwards Of Downwards Arrow / Up Arrow Left Of Down Arrow
    U+021C6\leftrightarrowsLeftwards Arrow Over Rightwards Arrow / Left Arrow Over Right Arrow
    U+021C7\leftleftarrowsLeftwards Paired Arrows / Left Paired Arrows
    U+021C8\upuparrowsUpwards Paired Arrows / Up Paired Arrows
    U+021C9\rightrightarrowsRightwards Paired Arrows / Right Paired Arrows
    U+021CA\downdownarrowsDownwards Paired Arrows / Down Paired Arrows
    U+021CB\leftrightharpoonsLeftwards Harpoon Over Rightwards Harpoon / Left Harpoon Over Right Harpoon
    U+021CC\rightleftharpoonsRightwards Harpoon Over Leftwards Harpoon / Right Harpoon Over Left Harpoon
    U+021CD\nLeftarrowLeftwards Double Arrow With Stroke / Left Double Arrow With Stroke
    U+021CE\nLeftrightarrowLeft Right Double Arrow With Stroke
    U+021CF\nRightarrowRightwards Double Arrow With Stroke / Right Double Arrow With Stroke
    U+021D0\LeftarrowLeftwards Double Arrow / Left Double Arrow
    U+021D1\UparrowUpwards Double Arrow / Up Double Arrow
    U+021D2\RightarrowRightwards Double Arrow / Right Double Arrow
    U+021D3\DownarrowDownwards Double Arrow / Down Double Arrow
    U+021D4\LeftrightarrowLeft Right Double Arrow
    U+021D5\UpdownarrowUp Down Double Arrow
    U+021D6\NwarrowNorth West Double Arrow / Upper Left Double Arrow
    U+021D7\NearrowNorth East Double Arrow / Upper Right Double Arrow
    U+021D8\SearrowSouth East Double Arrow / Lower Right Double Arrow
    U+021D9\SwarrowSouth West Double Arrow / Lower Left Double Arrow
    U+021DA\LleftarrowLeftwards Triple Arrow / Left Triple Arrow
    U+021DB\RrightarrowRightwards Triple Arrow / Right Triple Arrow
    U+021DC\leftsquigarrowLeftwards Squiggle Arrow / Left Squiggle Arrow
    U+021DD\rightsquigarrowRightwards Squiggle Arrow / Right Squiggle Arrow
    U+021DE\nHuparrowUpwards Arrow With Double Stroke / Up Arrow With Double Stroke
    U+021DF\nHdownarrowDownwards Arrow With Double Stroke / Down Arrow With Double Stroke
    U+021E0\leftdasharrowLeftwards Dashed Arrow / Left Dashed Arrow
    U+021E1\updasharrowUpwards Dashed Arrow / Up Dashed Arrow
    U+021E2\rightdasharrowRightwards Dashed Arrow / Right Dashed Arrow
    U+021E3\downdasharrowDownwards Dashed Arrow / Down Dashed Arrow
    U+021E4\barleftarrowLeftwards Arrow To Bar / Left Arrow To Bar
    U+021E5\rightarrowbarRightwards Arrow To Bar / Right Arrow To Bar
    U+021E6\leftwhitearrowLeftwards White Arrow / White Left Arrow
    U+021E7\upwhitearrowUpwards White Arrow / White Up Arrow
    U+021E8\rightwhitearrowRightwards White Arrow / White Right Arrow
    U+021E9\downwhitearrowDownwards White Arrow / White Down Arrow
    U+021EA\whitearrowupfrombarUpwards White Arrow From Bar / White Up Arrow From Bar
    U+021F4\circleonrightarrowRight Arrow With Small Circle
    U+021F5\DownArrowUpArrowDownwards Arrow Leftwards Of Upwards Arrow
    U+021F6\rightthreearrowsThree Rightwards Arrows
    U+021F7\nvleftarrowLeftwards Arrow With Vertical Stroke
    U+021F8\nvrightarrowRightwards Arrow With Vertical Stroke
    U+021F9\nvleftrightarrowLeft Right Arrow With Vertical Stroke
    U+021FA\nVleftarrowLeftwards Arrow With Double Vertical Stroke
    U+021FB\nVrightarrowRightwards Arrow With Double Vertical Stroke
    U+021FC\nVleftrightarrowLeft Right Arrow With Double Vertical Stroke
    U+021FD\leftarrowtriangleLeftwards Open-Headed Arrow
    U+021FE\rightarrowtriangleRightwards Open-Headed Arrow
    U+021FF\leftrightarrowtriangleLeft Right Open-Headed Arrow
    U+02200\forallFor All
    U+02201\complementComplement
    U+02202\partialPartial Differential
    U+02203\existsThere Exists
    U+02204\nexistsThere Does Not Exist
    U+02205\varnothing, \emptysetEmpty Set
    U+02206\incrementIncrement
    U+02207\del, \nablaNabla
    U+02208\inElement Of
    U+02209\notinNot An Element Of
    U+0220A\smallinSmall Element Of
    U+0220B\niContains As Member
    U+0220C\nniDoes Not Contain As Member
    U+0220D\smallniSmall Contains As Member
    U+0220E\QEDEnd Of Proof
    U+0220F\prodN-Ary Product
    U+02210\coprodN-Ary Coproduct
    U+02211\sumN-Ary Summation
    U+02212\minusMinus Sign
    U+02213\mpMinus-Or-Plus Sign
    U+02214\dotplusDot Plus
    U+02216\setminusSet Minus
    U+02217\astAsterisk Operator
    U+02218\circRing Operator
    U+02219\vysmblkcircleBullet Operator
    U+0221A\surd, \sqrtSquare Root
    U+0221B\cbrtCube Root
    U+0221C\fourthrootFourth Root
    U+0221D\proptoProportional To
    U+0221E\inftyInfinity
    U+0221F\rightangleRight Angle
    U+02220\angleAngle
    U+02221\measuredangleMeasured Angle
    U+02222\sphericalangleSpherical Angle
    U+02223\midDivides
    U+02224\nmidDoes Not Divide
    U+02225\parallelParallel To
    U+02226\nparallelNot Parallel To
    U+02227\wedgeLogical And
    U+02228\veeLogical Or
    U+02229\capIntersection
    U+0222A\cupUnion
    U+0222B\intIntegral
    U+0222C\iintDouble Integral
    U+0222D\iiintTriple Integral
    U+0222E\ointContour Integral
    U+0222F\oiintSurface Integral
    U+02230\oiiintVolume Integral
    U+02231\clwintegralClockwise Integral
    U+02232\varointclockwiseClockwise Contour Integral
    U+02233\ointctrclockwiseAnticlockwise Contour Integral
    U+02234\thereforeTherefore
    U+02235\becauseBecause
    U+02237\ColonProportion
    U+02238\dotminusDot Minus
    U+0223A\dotsminusdotsGeometric Proportion
    U+0223B\kernelcontractionHomothetic
    U+0223C\simTilde Operator
    U+0223D\backsimReversed Tilde
    U+0223E\lazysinvInverted Lazy S
    U+0223F\sinewaveSine Wave
    U+02240\wrWreath Product
    U+02241\nsimNot Tilde
    U+02242\eqsimMinus Tilde
    U+02242 + U+00338≂̸\neqsimMinus Tilde + Combining Long Solidus Overlay / Non-Spacing Long Slash Overlay
    U+02243\simeqAsymptotically Equal To
    U+02244\nsimeNot Asymptotically Equal To
    U+02245\congApproximately Equal To
    U+02246\approxnotequalApproximately But Not Actually Equal To
    U+02247\ncongNeither Approximately Nor Actually Equal To
    U+02248\approxAlmost Equal To
    U+02249\napproxNot Almost Equal To
    U+0224A\approxeqAlmost Equal Or Equal To
    U+0224B\tildetrplTriple Tilde
    U+0224C\allequalAll Equal To
    U+0224D\asympEquivalent To
    U+0224E\BumpeqGeometrically Equivalent To
    U+0224E + U+00338≎̸\nBumpeqGeometrically Equivalent To + Combining Long Solidus Overlay / Non-Spacing Long Slash Overlay
    U+0224F\bumpeqDifference Between
    U+0224F + U+00338≏̸\nbumpeqDifference Between + Combining Long Solidus Overlay / Non-Spacing Long Slash Overlay
    U+02250\doteqApproaches The Limit
    U+02251\DoteqGeometrically Equal To
    U+02252\fallingdotseqApproximately Equal To Or The Image Of
    U+02253\risingdotseqImage Of Or Approximately Equal To
    U+02254\coloneqColon Equals / Colon Equal
    U+02255\eqcolonEquals Colon / Equal Colon
    U+02256\eqcircRing In Equal To
    U+02257\circeqRing Equal To
    U+02258\arceqCorresponds To
    U+02259\wedgeqEstimates
    U+0225A\veeeqEquiangular To
    U+0225B\starequalStar Equals
    U+0225C\triangleqDelta Equal To
    U+0225D\eqdefEqual To By Definition
    U+0225E\measeqMeasured By
    U+0225F\questeqQuestioned Equal To
    U+02260\neNot Equal To
    U+02261\equivIdentical To
    U+02262\nequivNot Identical To
    U+02263\EquivStrictly Equivalent To
    U+02264\le, \leqLess-Than Or Equal To / Less Than Or Equal To
    U+02265\ge, \geqGreater-Than Or Equal To / Greater Than Or Equal To
    U+02266\leqqLess-Than Over Equal To / Less Than Over Equal To
    U+02267\geqqGreater-Than Over Equal To / Greater Than Over Equal To
    U+02268\lneqqLess-Than But Not Equal To / Less Than But Not Equal To
    U+02268 + U+0FE00≨︀\lvertneqqLess-Than But Not Equal To / Less Than But Not Equal To + Variation Selector-1
    U+02269\gneqqGreater-Than But Not Equal To / Greater Than But Not Equal To
    U+02269 + U+0FE00≩︀\gvertneqqGreater-Than But Not Equal To / Greater Than But Not Equal To + Variation Selector-1
    U+0226A\llMuch Less-Than / Much Less Than
    U+0226A + U+00338≪̸\NotLessLessMuch Less-Than / Much Less Than + Combining Long Solidus Overlay / Non-Spacing Long Slash Overlay
    U+0226B\ggMuch Greater-Than / Much Greater Than
    U+0226B + U+00338≫̸\NotGreaterGreaterMuch Greater-Than / Much Greater Than + Combining Long Solidus Overlay / Non-Spacing Long Slash Overlay
    U+0226C\betweenBetween
    U+0226D\nasympNot Equivalent To
    U+0226E\nlessNot Less-Than / Not Less Than
    U+0226F\ngtrNot Greater-Than / Not Greater Than
    U+02270\nleqNeither Less-Than Nor Equal To / Neither Less Than Nor Equal To
    U+02271\ngeqNeither Greater-Than Nor Equal To / Neither Greater Than Nor Equal To
    U+02272\lesssimLess-Than Or Equivalent To / Less Than Or Equivalent To
    U+02273\gtrsimGreater-Than Or Equivalent To / Greater Than Or Equivalent To
    U+02274\nlesssimNeither Less-Than Nor Equivalent To / Neither Less Than Nor Equivalent To
    U+02275\ngtrsimNeither Greater-Than Nor Equivalent To / Neither Greater Than Nor Equivalent To
    U+02276\lessgtrLess-Than Or Greater-Than / Less Than Or Greater Than
    U+02277\gtrlessGreater-Than Or Less-Than / Greater Than Or Less Than
    U+02278\notlessgreaterNeither Less-Than Nor Greater-Than / Neither Less Than Nor Greater Than
    U+02279\notgreaterlessNeither Greater-Than Nor Less-Than / Neither Greater Than Nor Less Than
    U+0227A\precPrecedes
    U+0227B\succSucceeds
    U+0227C\preccurlyeqPrecedes Or Equal To
    U+0227D\succcurlyeqSucceeds Or Equal To
    U+0227E\precsimPrecedes Or Equivalent To
    U+0227E + U+00338≾̸\nprecsimPrecedes Or Equivalent To + Combining Long Solidus Overlay / Non-Spacing Long Slash Overlay
    U+0227F\succsimSucceeds Or Equivalent To
    U+0227F + U+00338≿̸\nsuccsimSucceeds Or Equivalent To + Combining Long Solidus Overlay / Non-Spacing Long Slash Overlay
    U+02280\nprecDoes Not Precede
    U+02281\nsuccDoes Not Succeed
    U+02282\subsetSubset Of
    U+02283\supsetSuperset Of
    U+02284\nsubsetNot A Subset Of
    U+02285\nsupsetNot A Superset Of
    U+02286\subseteqSubset Of Or Equal To
    U+02287\supseteqSuperset Of Or Equal To
    U+02288\nsubseteqNeither A Subset Of Nor Equal To
    U+02289\nsupseteqNeither A Superset Of Nor Equal To
    U+0228A\subsetneqSubset Of With Not Equal To / Subset Of Or Not Equal To
    U+0228A + U+0FE00⊊︀\varsubsetneqqSubset Of With Not Equal To / Subset Of Or Not Equal To + Variation Selector-1
    U+0228B\supsetneqSuperset Of With Not Equal To / Superset Of Or Not Equal To
    U+0228B + U+0FE00⊋︀\varsupsetneqSuperset Of With Not Equal To / Superset Of Or Not Equal To + Variation Selector-1
    U+0228D\cupdotMultiset Multiplication
    U+0228E\uplusMultiset Union
    U+0228F\sqsubsetSquare Image Of
    U+0228F + U+00338⊏̸\NotSquareSubsetSquare Image Of + Combining Long Solidus Overlay / Non-Spacing Long Slash Overlay
    U+02290\sqsupsetSquare Original Of
    U+02290 + U+00338⊐̸\NotSquareSupersetSquare Original Of + Combining Long Solidus Overlay / Non-Spacing Long Slash Overlay
    U+02291\sqsubseteqSquare Image Of Or Equal To
    U+02292\sqsupseteqSquare Original Of Or Equal To
    U+02293\sqcapSquare Cap
    U+02294\sqcupSquare Cup
    U+02295\oplusCircled Plus
    U+02296\ominusCircled Minus
    U+02297\otimesCircled Times
    U+02298\oslashCircled Division Slash
    U+02299\odotCircled Dot Operator
    U+0229A\circledcircCircled Ring Operator
    U+0229B\circledastCircled Asterisk Operator
    U+0229C\circledequalCircled Equals
    U+0229D\circleddashCircled Dash
    U+0229E\boxplusSquared Plus
    U+0229F\boxminusSquared Minus
    U+022A0\boxtimesSquared Times
    U+022A1\boxdotSquared Dot Operator
    U+022A2\vdashRight Tack
    U+022A3\dashvLeft Tack
    U+022A4\topDown Tack
    U+022A5\botUp Tack
    U+022A7\modelsModels
    U+022A8\vDashTrue
    U+022A9\VdashForces
    U+022AA\VvdashTriple Vertical Bar Right Turnstile
    U+022AB\VDashDouble Vertical Bar Double Right Turnstile
    U+022AC\nvdashDoes Not Prove
    U+022AD\nvDashNot True
    U+022AE\nVdashDoes Not Force
    U+022AF\nVDashNegated Double Vertical Bar Double Right Turnstile
    U+022B0\prurelPrecedes Under Relation
    U+022B1\scurelSucceeds Under Relation
    U+022B2\vartriangleleftNormal Subgroup Of
    U+022B3\vartrianglerightContains As Normal Subgroup
    U+022B4\trianglelefteqNormal Subgroup Of Or Equal To
    U+022B5\trianglerighteqContains As Normal Subgroup Or Equal To
    U+022B6\originalOriginal Of
    U+022B7\imageImage Of
    U+022B8\multimapMultimap
    U+022B9\hermitconjmatrixHermitian Conjugate Matrix
    U+022BA\intercalIntercalate
    U+022BB\veebar, \xorXor
    U+022BC\barwedge, \nandNand
    U+022BD\barvee, \norNor
    U+022BE\rightanglearcRight Angle With Arc
    U+022BF\varlrtriangleRight Triangle
    U+022C0\bigwedgeN-Ary Logical And
    U+022C1\bigveeN-Ary Logical Or
    U+022C2\bigcapN-Ary Intersection
    U+022C3\bigcupN-Ary Union
    U+022C4\diamondDiamond Operator
    U+022C5\cdotDot Operator
    U+022C6\starStar Operator
    U+022C7\divideontimesDivision Times
    U+022C8\bowtieBowtie
    U+022C9\ltimesLeft Normal Factor Semidirect Product
    U+022CA\rtimesRight Normal Factor Semidirect Product
    U+022CB\leftthreetimesLeft Semidirect Product
    U+022CC\rightthreetimesRight Semidirect Product
    U+022CD\backsimeqReversed Tilde Equals
    U+022CE\curlyveeCurly Logical Or
    U+022CF\curlywedgeCurly Logical And
    U+022D0\SubsetDouble Subset
    U+022D1\SupsetDouble Superset
    U+022D2\CapDouble Intersection
    U+022D3\CupDouble Union
    U+022D4\pitchforkPitchfork
    U+022D5\equalparallelEqual And Parallel To
    U+022D6\lessdotLess-Than With Dot / Less Than With Dot
    U+022D7\gtrdotGreater-Than With Dot / Greater Than With Dot
    U+022D8\verymuchlessVery Much Less-Than / Very Much Less Than
    U+022D9\gggVery Much Greater-Than / Very Much Greater Than
    U+022DA\lesseqgtrLess-Than Equal To Or Greater-Than / Less Than Equal To Or Greater Than
    U+022DB\gtreqlessGreater-Than Equal To Or Less-Than / Greater Than Equal To Or Less Than
    U+022DC\eqlessEqual To Or Less-Than / Equal To Or Less Than
    U+022DD\eqgtrEqual To Or Greater-Than / Equal To Or Greater Than
    U+022DE\curlyeqprecEqual To Or Precedes
    U+022DF\curlyeqsuccEqual To Or Succeeds
    U+022E0\npreccurlyeqDoes Not Precede Or Equal
    U+022E1\nsucccurlyeqDoes Not Succeed Or Equal
    U+022E2\nsqsubseteqNot Square Image Of Or Equal To
    U+022E3\nsqsupseteqNot Square Original Of Or Equal To
    U+022E4\sqsubsetneqSquare Image Of Or Not Equal To
    U+022E5\sqspneSquare Original Of Or Not Equal To
    U+022E6\lnsimLess-Than But Not Equivalent To / Less Than But Not Equivalent To
    U+022E7\gnsimGreater-Than But Not Equivalent To / Greater Than But Not Equivalent To
    U+022E8\precnsimPrecedes But Not Equivalent To
    U+022E9\succnsimSucceeds But Not Equivalent To
    U+022EA\ntriangleleftNot Normal Subgroup Of
    U+022EB\ntrianglerightDoes Not Contain As Normal Subgroup
    U+022EC\ntrianglelefteqNot Normal Subgroup Of Or Equal To
    U+022ED\ntrianglerighteqDoes Not Contain As Normal Subgroup Or Equal
    U+022EE\vdotsVertical Ellipsis
    U+022EF\cdotsMidline Horizontal Ellipsis
    U+022F0\adotsUp Right Diagonal Ellipsis
    U+022F1\ddotsDown Right Diagonal Ellipsis
    U+022F2\disinElement Of With Long Horizontal Stroke
    U+022F3\varisinsElement Of With Vertical Bar At End Of Horizontal Stroke
    U+022F4\isinsSmall Element Of With Vertical Bar At End Of Horizontal Stroke
    U+022F5\isindotElement Of With Dot Above
    U+022F6\varisinobarElement Of With Overbar
    U+022F7\isinobarSmall Element Of With Overbar
    U+022F8\isinvbElement Of With Underbar
    U+022F9\isinEElement Of With Two Horizontal Strokes
    U+022FA\nisdContains With Long Horizontal Stroke
    U+022FB\varnisContains With Vertical Bar At End Of Horizontal Stroke
    U+022FC\nisSmall Contains With Vertical Bar At End Of Horizontal Stroke
    U+022FD\varniobarContains With Overbar
    U+022FE\niobarSmall Contains With Overbar
    U+022FF\bagmemberZ Notation Bag Membership
    U+02300\diameterDiameter Sign
    U+02302\houseHouse
    U+02305\varbarwedgeProjective
    U+02306\vardoublebarwedgePerspective
    U+02308\lceilLeft Ceiling
    U+02309\rceilRight Ceiling
    U+0230A\lfloorLeft Floor
    U+0230B\rfloorRight Floor
    U+02310\invnotReversed Not Sign
    U+02311\sqlozengeSquare Lozenge
    U+02312\proflineArc
    U+02313\profsurfSegment
    U+02315\recorderTelephone Recorder
    U+02317\viewdataViewdata Square
    U+02319\turnednotTurned Not Sign
    U+0231A\:watch:Watch
    U+0231B\:hourglass:Hourglass
    U+0231C\ulcornerTop Left Corner
    U+0231D\urcornerTop Right Corner
    U+0231E\llcornerBottom Left Corner
    U+0231F\lrcornerBottom Right Corner
    U+02322\frownFrown
    U+02323\smileSmile
    U+0232C\varhexagonlrbondsBenzene Ring
    U+02332\conictaperConical Taper
    U+02336\topbotApl Functional Symbol I-Beam
    U+0233D\obarApl Functional Symbol Circle Stile
    U+0233F\notslashApl Functional Symbol Slash Bar
    U+02340\notbackslashApl Functional Symbol Backslash Bar
    U+02353\boxupcaretApl Functional Symbol Quad Up Caret
    U+02370\boxquestionApl Functional Symbol Quad Question
    U+02394\hexagonSoftware-Function Symbol
    U+023A3\dlcornLeft Square Bracket Lower Corner
    U+023B0\lmoustacheUpper Left Or Lower Right Curly Bracket Section
    U+023B1\rmoustacheUpper Right Or Lower Left Curly Bracket Section
    U+023B4\overbracketTop Square Bracket
    U+023B5\underbracketBottom Square Bracket
    U+023B6\bbrktbrkBottom Square Bracket Over Top Square Bracket
    U+023B7\sqrtbottomRadical Symbol Bottom
    U+023B8\lvboxlineLeft Vertical Box Line
    U+023B9\rvboxlineRight Vertical Box Line
    U+023CE\varcarriagereturnReturn Symbol
    U+023DE\overbraceTop Curly Bracket
    U+023DF\underbraceBottom Curly Bracket
    U+023E2\trapeziumWhite Trapezium
    U+023E3\benzenrBenzene Ring With Circle
    U+023E4\strnsStraightness
    U+023E5\fltnsFlatness
    U+023E6\accurrentAc Current
    U+023E7\elintersElectrical Intersection
    U+023E9\:fast_forward:Black Right-Pointing Double Triangle
    U+023EA\:rewind:Black Left-Pointing Double Triangle
    U+023EB\:arrow_double_up:Black Up-Pointing Double Triangle
    U+023EC\:arrow_double_down:Black Down-Pointing Double Triangle
    U+023F0\:alarm_clock:Alarm Clock
    U+023F3\:hourglass_flowing_sand:Hourglass With Flowing Sand
    U+02422\blanksymbolBlank Symbol / Blank
    U+02423\visiblespaceOpen Box
    U+024C2\:m:Circled Latin Capital Letter M
    U+024C8\circledSCircled Latin Capital Letter S
    U+02506\dshfncBox Drawings Light Triple Dash Vertical / Forms Light Triple Dash Vertical
    U+02519\sqfnwBox Drawings Up Light And Left Heavy / Forms Up Light And Left Heavy
    U+02571\diagupBox Drawings Light Diagonal Upper Right To Lower Left / Forms Light Diagonal Upper Right To Lower Left
    U+02572\diagdownBox Drawings Light Diagonal Upper Left To Lower Right / Forms Light Diagonal Upper Left To Lower Right
    U+02580\blockuphalfUpper Half Block
    U+02584\blocklowhalfLower Half Block
    U+02588\blockfullFull Block
    U+0258C\blocklefthalfLeft Half Block
    U+02590\blockrighthalfRight Half Block
    U+02591\blockqtrshadedLight Shade
    U+02592\blockhalfshadedMedium Shade
    U+02593\blockthreeqtrshadedDark Shade
    U+025A0\blacksquareBlack Square
    U+025A1\squareWhite Square
    U+025A2\squovalWhite Square With Rounded Corners
    U+025A3\blackinwhitesquareWhite Square Containing Black Small Square
    U+025A4\squarehfillSquare With Horizontal Fill
    U+025A5\squarevfillSquare With Vertical Fill
    U+025A6\squarehvfillSquare With Orthogonal Crosshatch Fill
    U+025A7\squarenwsefillSquare With Upper Left To Lower Right Fill
    U+025A8\squareneswfillSquare With Upper Right To Lower Left Fill
    U+025A9\squarecrossfillSquare With Diagonal Crosshatch Fill
    U+025AA\smblksquare, \:black_small_square:Black Small Square
    U+025AB\smwhtsquare, \:white_small_square:White Small Square
    U+025AC\hrectangleblackBlack Rectangle
    U+025AD\hrectangleWhite Rectangle
    U+025AE\vrectangleblackBlack Vertical Rectangle
    U+025AF\vrectoWhite Vertical Rectangle
    U+025B0\parallelogramblackBlack Parallelogram
    U+025B1\parallelogramWhite Parallelogram
    U+025B2\bigblacktriangleupBlack Up-Pointing Triangle / Black Up Pointing Triangle
    U+025B3\bigtriangleupWhite Up-Pointing Triangle / White Up Pointing Triangle
    U+025B4\blacktriangleBlack Up-Pointing Small Triangle / Black Up Pointing Small Triangle
    U+025B5\vartriangleWhite Up-Pointing Small Triangle / White Up Pointing Small Triangle
    U+025B6\blacktriangleright, \:arrow_forward:Black Right-Pointing Triangle / Black Right Pointing Triangle
    U+025B7\trianglerightWhite Right-Pointing Triangle / White Right Pointing Triangle
    U+025B8\smallblacktrianglerightBlack Right-Pointing Small Triangle / Black Right Pointing Small Triangle
    U+025B9\smalltrianglerightWhite Right-Pointing Small Triangle / White Right Pointing Small Triangle
    U+025BA\blackpointerrightBlack Right-Pointing Pointer / Black Right Pointing Pointer
    U+025BB\whitepointerrightWhite Right-Pointing Pointer / White Right Pointing Pointer
    U+025BC\bigblacktriangledownBlack Down-Pointing Triangle / Black Down Pointing Triangle
    U+025BD\bigtriangledownWhite Down-Pointing Triangle / White Down Pointing Triangle
    U+025BE\blacktriangledownBlack Down-Pointing Small Triangle / Black Down Pointing Small Triangle
    U+025BF\triangledownWhite Down-Pointing Small Triangle / White Down Pointing Small Triangle
    U+025C0\blacktriangleleft, \:arrow_backward:Black Left-Pointing Triangle / Black Left Pointing Triangle
    U+025C1\triangleleftWhite Left-Pointing Triangle / White Left Pointing Triangle
    U+025C2\smallblacktriangleleftBlack Left-Pointing Small Triangle / Black Left Pointing Small Triangle
    U+025C3\smalltriangleleftWhite Left-Pointing Small Triangle / White Left Pointing Small Triangle
    U+025C4\blackpointerleftBlack Left-Pointing Pointer / Black Left Pointing Pointer
    U+025C5\whitepointerleftWhite Left-Pointing Pointer / White Left Pointing Pointer
    U+025C6\mdlgblkdiamondBlack Diamond
    U+025C7\mdlgwhtdiamondWhite Diamond
    U+025C8\blackinwhitediamondWhite Diamond Containing Black Small Diamond
    U+025C9\fisheyeFisheye
    U+025CA\lozengeLozenge
    U+025CB\bigcircWhite Circle
    U+025CC\dottedcircleDotted Circle
    U+025CD\circlevertfillCircle With Vertical Fill
    U+025CE\bullseyeBullseye
    U+025CF\mdlgblkcircleBlack Circle
    U+025D0\cirflCircle With Left Half Black
    U+025D1\cirfrCircle With Right Half Black
    U+025D2\cirfbCircle With Lower Half Black
    U+025D3\circletophalfblackCircle With Upper Half Black
    U+025D4\circleurquadblackCircle With Upper Right Quadrant Black
    U+025D5\blackcircleulquadwhiteCircle With All But Upper Left Quadrant Black
    U+025D6\blacklefthalfcircleLeft Half Black Circle
    U+025D7\blackrighthalfcircleRight Half Black Circle
    U+025D8\rvbullInverse Bullet
    U+025D9\inversewhitecircleInverse White Circle
    U+025DA\invwhiteupperhalfcircleUpper Half Inverse White Circle
    U+025DB\invwhitelowerhalfcircleLower Half Inverse White Circle
    U+025DC\ularcUpper Left Quadrant Circular Arc
    U+025DD\urarcUpper Right Quadrant Circular Arc
    U+025DE\lrarcLower Right Quadrant Circular Arc
    U+025DF\llarcLower Left Quadrant Circular Arc
    U+025E0\topsemicircleUpper Half Circle
    U+025E1\botsemicircleLower Half Circle
    U+025E2\lrblacktriangleBlack Lower Right Triangle
    U+025E3\llblacktriangleBlack Lower Left Triangle
    U+025E4\ulblacktriangleBlack Upper Left Triangle
    U+025E5\urblacktriangleBlack Upper Right Triangle
    U+025E6\smwhtcircleWhite Bullet
    U+025E7\sqflSquare With Left Half Black
    U+025E8\sqfrSquare With Right Half Black
    U+025E9\squareulblackSquare With Upper Left Diagonal Half Black
    U+025EA\sqfseSquare With Lower Right Diagonal Half Black
    U+025EB\boxbarWhite Square With Vertical Bisecting Line
    U+025EC\trianglecdotWhite Up-Pointing Triangle With Dot / White Up Pointing Triangle With Dot
    U+025ED\triangleleftblackUp-Pointing Triangle With Left Half Black / Up Pointing Triangle With Left Half Black
    U+025EE\trianglerightblackUp-Pointing Triangle With Right Half Black / Up Pointing Triangle With Right Half Black
    U+025EF\lgwhtcircleLarge Circle
    U+025F0\squareulquadWhite Square With Upper Left Quadrant
    U+025F1\squarellquadWhite Square With Lower Left Quadrant
    U+025F2\squarelrquadWhite Square With Lower Right Quadrant
    U+025F3\squareurquadWhite Square With Upper Right Quadrant
    U+025F4\circleulquadWhite Circle With Upper Left Quadrant
    U+025F5\circlellquadWhite Circle With Lower Left Quadrant
    U+025F6\circlelrquadWhite Circle With Lower Right Quadrant
    U+025F7\circleurquadWhite Circle With Upper Right Quadrant
    U+025F8\ultriangleUpper Left Triangle
    U+025F9\urtriangleUpper Right Triangle
    U+025FA\lltriangleLower Left Triangle
    U+025FB\mdwhtsquare, \:white_medium_square:White Medium Square
    U+025FC\mdblksquare, \:black_medium_square:Black Medium Square
    U+025FD\mdsmwhtsquare, \:white_medium_small_square:White Medium Small Square
    U+025FE\mdsmblksquare, \:black_medium_small_square:Black Medium Small Square
    U+025FF\lrtriangleLower Right Triangle
    U+02600\:sunny:Black Sun With Rays
    U+02601\:cloud:Cloud
    U+02605\bigstarBlack Star
    U+02606\bigwhitestarWhite Star
    U+02609\astrosunSun
    U+0260E\:phone:Black Telephone
    U+02611\:ballot_box_with_check:Ballot Box With Check
    U+02614\:umbrella_with_rain_drops:, \:umbrella:Umbrella With Rain Drops
    U+02615\:coffee:Hot Beverage
    U+0261D\:point_up:White Up Pointing Index
    U+02621\dangerCaution Sign
    U+0263A\:relaxed:White Smiling Face
    U+0263B\blacksmileyBlack Smiling Face
    U+0263C\sunWhite Sun With Rays
    U+0263D\rightmoonFirst Quarter Moon
    U+0263E\leftmoonLast Quarter Moon
    U+0263F\mercuryMercury
    U+02640\venus, \femaleFemale Sign
    U+02642\male, \marsMale Sign
    U+02643\jupiterJupiter
    U+02644\saturnSaturn
    U+02645\uranusUranus
    U+02646\neptuneNeptune
    U+02647\plutoPluto
    U+02648\aries, \:aries:Aries
    U+02649\taurus, \:taurus:Taurus
    U+0264A\gemini, \:gemini:Gemini
    U+0264B\cancer, \:cancer:Cancer
    U+0264C\leo, \:leo:Leo
    U+0264D\virgo, \:virgo:Virgo
    U+0264E\libra, \:libra:Libra
    U+0264F\scorpio, \:scorpius:Scorpius
    U+02650\sagittarius, \:sagittarius:Sagittarius
    U+02651\capricornus, \:capricorn:Capricorn
    U+02652\aquarius, \:aquarius:Aquarius
    U+02653\pisces, \:pisces:Pisces
    U+02660\spadesuit, \:spades:Black Spade Suit
    U+02661\heartsuitWhite Heart Suit
    U+02662\diamondsuitWhite Diamond Suit
    U+02663\clubsuit, \:clubs:Black Club Suit
    U+02664\varspadesuitWhite Spade Suit
    U+02665\varheartsuit, \:hearts:Black Heart Suit
    U+02666\vardiamondsuit, \:diamonds:Black Diamond Suit
    U+02667\varclubsuitWhite Club Suit
    U+02668\:hotsprings:Hot Springs
    U+02669\quarternoteQuarter Note
    U+0266A\eighthnoteEighth Note
    U+0266B\twonotesBeamed Eighth Notes / Barred Eighth Notes
    U+0266D\flatMusic Flat Sign / Flat
    U+0266E\naturalMusic Natural Sign / Natural
    U+0266F\sharpMusic Sharp Sign / Sharp
    U+0267B\:recycle:Black Universal Recycling Symbol
    U+0267E\acidfreePermanent Paper Sign
    U+0267F\:wheelchair:Wheelchair Symbol
    U+02680\diceiDie Face-1
    U+02681\diceiiDie Face-2
    U+02682\diceiiiDie Face-3
    U+02683\diceivDie Face-4
    U+02684\dicevDie Face-5
    U+02685\diceviDie Face-6
    U+02686\circledrightdotWhite Circle With Dot Right
    U+02687\circledtwodotsWhite Circle With Two Dots
    U+02688\blackcircledrightdotBlack Circle With White Dot Right
    U+02689\blackcircledtwodotsBlack Circle With Two White Dots
    U+02693\:anchor:Anchor
    U+026A0\:warning:Warning Sign
    U+026A1\:zap:High Voltage Sign
    U+026A5\hermaphroditeMale And Female Sign
    U+026AA\mdwhtcircle, \:white_circle:Medium White Circle
    U+026AB\mdblkcircle, \:black_circle:Medium Black Circle
    U+026AC\mdsmwhtcircleMedium Small White Circle
    U+026B2\neuterNeuter
    U+026BD\:soccer:Soccer Ball
    U+026BE\:baseball:Baseball
    U+026C4\:snowman:, \:snowman_without_snow:Snowman Without Snow
    U+026C5\:partly_sunny:Sun Behind Cloud
    U+026CE\:ophiuchus:Ophiuchus
    U+026D4\:no_entry:No Entry
    U+026EA\:church:Church
    U+026F2\:fountain:Fountain
    U+026F3\:golf:Flag In Hole
    U+026F5\:boat:Sailboat
    U+026FA\:tent:Tent
    U+026FD\:fuelpump:Fuel Pump
    U+02702\:scissors:Black Scissors
    U+02705\:white_check_mark:White Heavy Check Mark
    U+02708\:airplane:Airplane
    U+02709\:email:Envelope
    U+0270A\:fist:Raised Fist
    U+0270B\:hand:Raised Hand
    U+0270C\:v:Victory Hand
    U+0270F\:pencil2:Pencil
    U+02712\:black_nib:Black Nib
    U+02713\checkmarkCheck Mark
    U+02714\:heavy_check_mark:Heavy Check Mark
    U+02716\:heavy_multiplication_x:Heavy Multiplication X
    U+02720\malteseMaltese Cross
    U+02728\:sparkles:Sparkles
    U+0272A\circledstarCircled White Star
    U+02733\:eight_spoked_asterisk:Eight Spoked Asterisk
    U+02734\:eight_pointed_black_star:Eight Pointed Black Star
    U+02736\varstarSix Pointed Black Star
    U+0273D\dingasteriskHeavy Teardrop-Spoked Asterisk
    U+02744\:snowflake:Snowflake
    U+02747\:sparkle:Sparkle
    U+0274C\:x:Cross Mark
    U+0274E\:negative_squared_cross_mark:Negative Squared Cross Mark
    U+02753\:question:Black Question Mark Ornament
    U+02754\:grey_question:White Question Mark Ornament
    U+02755\:grey_exclamation:White Exclamation Mark Ornament
    U+02757\:exclamation:Heavy Exclamation Mark Symbol
    U+02764\:heart:Heavy Black Heart
    U+02795\:heavy_plus_sign:Heavy Plus Sign
    U+02796\:heavy_minus_sign:Heavy Minus Sign
    U+02797\:heavy_division_sign:Heavy Division Sign
    U+0279B\draftingarrowDrafting Point Rightwards Arrow / Drafting Point Right Arrow
    U+027A1\:arrow_right:Black Rightwards Arrow / Black Right Arrow
    U+027B0\:curly_loop:Curly Loop
    U+027BF\:loop:Double Curly Loop
    U+027C0\threedangleThree Dimensional Angle
    U+027C1\whiteinwhitetriangleWhite Triangle Containing Small White Triangle
    U+027C2\perpPerpendicular
    U+027C8\bsolhsubReverse Solidus Preceding Subset
    U+027C9\suphsolSuperset Preceding Solidus
    U+027D1\wedgedotAnd With Dot
    U+027D2\upinElement Of Opening Upwards
    U+027D5\leftouterjoinLeft Outer Join
    U+027D6\rightouterjoinRight Outer Join
    U+027D7\fullouterjoinFull Outer Join
    U+027D8\bigbotLarge Up Tack
    U+027D9\bigtopLarge Down Tack
    U+027E6\llbracket, \openbracketleftMathematical Left White Square Bracket
    U+027E7\openbracketright, \rrbracketMathematical Right White Square Bracket
    U+027E8\langleMathematical Left Angle Bracket
    U+027E9\rangleMathematical Right Angle Bracket
    U+027F0\UUparrowUpwards Quadruple Arrow
    U+027F1\DDownarrowDownwards Quadruple Arrow
    U+027F5\longleftarrowLong Leftwards Arrow
    U+027F6\longrightarrowLong Rightwards Arrow
    U+027F7\longleftrightarrowLong Left Right Arrow
    U+027F8\impliedby, \LongleftarrowLong Leftwards Double Arrow
    U+027F9\implies, \LongrightarrowLong Rightwards Double Arrow
    U+027FA\Longleftrightarrow, \iffLong Left Right Double Arrow
    U+027FB\longmapsfromLong Leftwards Arrow From Bar
    U+027FC\longmapstoLong Rightwards Arrow From Bar
    U+027FD\LongmapsfromLong Leftwards Double Arrow From Bar
    U+027FE\LongmapstoLong Rightwards Double Arrow From Bar
    U+027FF\longrightsquigarrowLong Rightwards Squiggle Arrow
    U+02900\nvtwoheadrightarrowRightwards Two-Headed Arrow With Vertical Stroke
    U+02901\nVtwoheadrightarrowRightwards Two-Headed Arrow With Double Vertical Stroke
    U+02902\nvLeftarrowLeftwards Double Arrow With Vertical Stroke
    U+02903\nvRightarrowRightwards Double Arrow With Vertical Stroke
    U+02904\nvLeftrightarrowLeft Right Double Arrow With Vertical Stroke
    U+02905\twoheadmapstoRightwards Two-Headed Arrow From Bar
    U+02906\MapsfromLeftwards Double Arrow From Bar
    U+02907\MapstoRightwards Double Arrow From Bar
    U+02908\downarrowbarredDownwards Arrow With Horizontal Stroke
    U+02909\uparrowbarredUpwards Arrow With Horizontal Stroke
    U+0290A\UuparrowUpwards Triple Arrow
    U+0290B\DdownarrowDownwards Triple Arrow
    U+0290C\leftbkarrowLeftwards Double Dash Arrow
    U+0290D\bkarowRightwards Double Dash Arrow
    U+0290E\leftdbkarrowLeftwards Triple Dash Arrow
    U+0290F\dbkarowRightwards Triple Dash Arrow
    U+02910\drbkarrowRightwards Two-Headed Triple Dash Arrow
    U+02911\rightdotarrowRightwards Arrow With Dotted Stem
    U+02912\UpArrowBarUpwards Arrow To Bar
    U+02913\DownArrowBarDownwards Arrow To Bar
    U+02914\nvrightarrowtailRightwards Arrow With Tail With Vertical Stroke
    U+02915\nVrightarrowtailRightwards Arrow With Tail With Double Vertical Stroke
    U+02916\twoheadrightarrowtailRightwards Two-Headed Arrow With Tail
    U+02917\nvtwoheadrightarrowtailRightwards Two-Headed Arrow With Tail With Vertical Stroke
    U+02918\nVtwoheadrightarrowtailRightwards Two-Headed Arrow With Tail With Double Vertical Stroke
    U+0291D\diamondleftarrowLeftwards Arrow To Black Diamond
    U+0291E\rightarrowdiamondRightwards Arrow To Black Diamond
    U+0291F\diamondleftarrowbarLeftwards Arrow From Bar To Black Diamond
    U+02920\barrightarrowdiamondRightwards Arrow From Bar To Black Diamond
    U+02925\hksearowSouth East Arrow With Hook
    U+02926\hkswarowSouth West Arrow With Hook
    U+02927\tonaNorth West Arrow And North East Arrow
    U+02928\toeaNorth East Arrow And South East Arrow
    U+02929\tosaSouth East Arrow And South West Arrow
    U+0292A\towaSouth West Arrow And North West Arrow
    U+0292B\rdiagovfdiagRising Diagonal Crossing Falling Diagonal
    U+0292C\fdiagovrdiagFalling Diagonal Crossing Rising Diagonal
    U+0292D\seovnearrowSouth East Arrow Crossing North East Arrow
    U+0292E\neovsearrowNorth East Arrow Crossing South East Arrow
    U+0292F\fdiagovnearrowFalling Diagonal Crossing North East Arrow
    U+02930\rdiagovsearrowRising Diagonal Crossing South East Arrow
    U+02931\neovnwarrowNorth East Arrow Crossing North West Arrow
    U+02932\nwovnearrowNorth West Arrow Crossing North East Arrow
    U+02934\:arrow_heading_up:Arrow Pointing Rightwards Then Curving Upwards
    U+02935\:arrow_heading_down:Arrow Pointing Rightwards Then Curving Downwards
    U+02942\RlarrRightwards Arrow Above Short Leftwards Arrow
    U+02944\rLarrShort Rightwards Arrow Above Leftwards Arrow
    U+02945\rightarrowplusRightwards Arrow With Plus Below
    U+02946\leftarrowplusLeftwards Arrow With Plus Below
    U+02947\rarrxRightwards Arrow Through X
    U+02948\leftrightarrowcircleLeft Right Arrow Through Small Circle
    U+02949\twoheaduparrowcircleUpwards Two-Headed Arrow From Small Circle
    U+0294A\leftrightharpoonupdownLeft Barb Up Right Barb Down Harpoon
    U+0294B\leftrightharpoondownupLeft Barb Down Right Barb Up Harpoon
    U+0294C\updownharpoonrightleftUp Barb Right Down Barb Left Harpoon
    U+0294D\updownharpoonleftrightUp Barb Left Down Barb Right Harpoon
    U+0294E\LeftRightVectorLeft Barb Up Right Barb Up Harpoon
    U+0294F\RightUpDownVectorUp Barb Right Down Barb Right Harpoon
    U+02950\DownLeftRightVectorLeft Barb Down Right Barb Down Harpoon
    U+02951\LeftUpDownVectorUp Barb Left Down Barb Left Harpoon
    U+02952\LeftVectorBarLeftwards Harpoon With Barb Up To Bar
    U+02953\RightVectorBarRightwards Harpoon With Barb Up To Bar
    U+02954\RightUpVectorBarUpwards Harpoon With Barb Right To Bar
    U+02955\RightDownVectorBarDownwards Harpoon With Barb Right To Bar
    U+02956\DownLeftVectorBarLeftwards Harpoon With Barb Down To Bar
    U+02957\DownRightVectorBarRightwards Harpoon With Barb Down To Bar
    U+02958\LeftUpVectorBarUpwards Harpoon With Barb Left To Bar
    U+02959\LeftDownVectorBarDownwards Harpoon With Barb Left To Bar
    U+0295A\LeftTeeVectorLeftwards Harpoon With Barb Up From Bar
    U+0295B\RightTeeVectorRightwards Harpoon With Barb Up From Bar
    U+0295C\RightUpTeeVectorUpwards Harpoon With Barb Right From Bar
    U+0295D\RightDownTeeVectorDownwards Harpoon With Barb Right From Bar
    U+0295E\DownLeftTeeVectorLeftwards Harpoon With Barb Down From Bar
    U+0295F\DownRightTeeVectorRightwards Harpoon With Barb Down From Bar
    U+02960\LeftUpTeeVectorUpwards Harpoon With Barb Left From Bar
    U+02961\LeftDownTeeVectorDownwards Harpoon With Barb Left From Bar
    U+02962\leftharpoonsupdownLeftwards Harpoon With Barb Up Above Leftwards Harpoon With Barb Down
    U+02963\upharpoonsleftrightUpwards Harpoon With Barb Left Beside Upwards Harpoon With Barb Right
    U+02964\rightharpoonsupdownRightwards Harpoon With Barb Up Above Rightwards Harpoon With Barb Down
    U+02965\downharpoonsleftrightDownwards Harpoon With Barb Left Beside Downwards Harpoon With Barb Right
    U+02966\leftrightharpoonsupLeftwards Harpoon With Barb Up Above Rightwards Harpoon With Barb Up
    U+02967\leftrightharpoonsdownLeftwards Harpoon With Barb Down Above Rightwards Harpoon With Barb Down
    U+02968\rightleftharpoonsupRightwards Harpoon With Barb Up Above Leftwards Harpoon With Barb Up
    U+02969\rightleftharpoonsdownRightwards Harpoon With Barb Down Above Leftwards Harpoon With Barb Down
    U+0296A\leftharpoonupdashLeftwards Harpoon With Barb Up Above Long Dash
    U+0296B\dashleftharpoondownLeftwards Harpoon With Barb Down Below Long Dash
    U+0296C\rightharpoonupdashRightwards Harpoon With Barb Up Above Long Dash
    U+0296D\dashrightharpoondownRightwards Harpoon With Barb Down Below Long Dash
    U+0296E\UpEquilibriumUpwards Harpoon With Barb Left Beside Downwards Harpoon With Barb Right
    U+0296F\ReverseUpEquilibriumDownwards Harpoon With Barb Left Beside Upwards Harpoon With Barb Right
    U+02970\RoundImpliesRight Double Arrow With Rounded Head
    U+02980\VvertTriple Vertical Bar Delimiter
    U+02986\ElroangRight White Parenthesis
    U+02999\ddfncDotted Fence
    U+0299B\measuredangleleftMeasured Angle Opening Left
    U+0299C\AngleRight Angle Variant With Square
    U+0299D\rightanglemdotMeasured Right Angle With Dot
    U+0299E\anglesAngle With S Inside
    U+0299F\angdnrAcute Angle
    U+029A0\lpargtSpherical Angle Opening Left
    U+029A1\sphericalangleupSpherical Angle Opening Up
    U+029A2\turnangleTurned Angle
    U+029A3\revangleReversed Angle
    U+029A4\angleubarAngle With Underbar
    U+029A5\revangleubarReversed Angle With Underbar
    U+029A6\wideangledownOblique Angle Opening Up
    U+029A7\wideangleupOblique Angle Opening Down
    U+029A8\measanglerutoneMeasured Angle With Open Arm Ending In Arrow Pointing Up And Right
    U+029A9\measanglelutonwMeasured Angle With Open Arm Ending In Arrow Pointing Up And Left
    U+029AA\measanglerdtoseMeasured Angle With Open Arm Ending In Arrow Pointing Down And Right
    U+029AB\measangleldtoswMeasured Angle With Open Arm Ending In Arrow Pointing Down And Left
    U+029AC\measangleurtoneMeasured Angle With Open Arm Ending In Arrow Pointing Right And Up
    U+029AD\measangleultonwMeasured Angle With Open Arm Ending In Arrow Pointing Left And Up
    U+029AE\measangledrtoseMeasured Angle With Open Arm Ending In Arrow Pointing Right And Down
    U+029AF\measangledltoswMeasured Angle With Open Arm Ending In Arrow Pointing Left And Down
    U+029B0\revemptysetReversed Empty Set
    U+029B1\emptysetobarEmpty Set With Overbar
    U+029B2\emptysetocircEmpty Set With Small Circle Above
    U+029B3\emptysetoarrEmpty Set With Right Arrow Above
    U+029B4\emptysetoarrlEmpty Set With Left Arrow Above
    U+029B7\circledparallelCircled Parallel
    U+029B8\obslashCircled Reverse Solidus
    U+029BC\odotslashdotCircled Anticlockwise-Rotated Division Sign
    U+029BE\circledwhitebulletCircled White Bullet
    U+029BF⦿\circledbulletCircled Bullet
    U+029C0\olessthanCircled Less-Than
    U+029C1\ogreaterthanCircled Greater-Than
    U+029C4\boxdiagSquared Rising Diagonal Slash
    U+029C5\boxbslashSquared Falling Diagonal Slash
    U+029C6\boxastSquared Asterisk
    U+029C7\boxcircleSquared Small Circle
    U+029CA\LapTriangle With Dot Above
    U+029CB\defasTriangle With Underbar
    U+029CF\LeftTriangleBarLeft Triangle Beside Vertical Bar
    U+029CF + U+00338⧏̸\NotLeftTriangleBarLeft Triangle Beside Vertical Bar + Combining Long Solidus Overlay / Non-Spacing Long Slash Overlay
    U+029D0\RightTriangleBarVertical Bar Beside Right Triangle
    U+029D0 + U+00338⧐̸\NotRightTriangleBarVertical Bar Beside Right Triangle + Combining Long Solidus Overlay / Non-Spacing Long Slash Overlay
    U+029DF\dualmapDouble-Ended Multimap
    U+029E1\lrtriangleeqIncreases As
    U+029E2\shuffleShuffle Product
    U+029E3\eparslEquals Sign And Slanted Parallel
    U+029E4\smeparslEquals Sign And Slanted Parallel With Tilde Above
    U+029E5\eqvparslIdentical To And Slanted Parallel
    U+029EB\blacklozengeBlack Lozenge
    U+029F4\RuleDelayedRule-Delayed
    U+029F6\dsolSolidus With Overbar
    U+029F7\rsolbarReverse Solidus With Horizontal Stroke
    U+029FA\doubleplusDouble Plus
    U+029FB\tripleplusTriple Plus
    U+02A00\bigodotN-Ary Circled Dot Operator
    U+02A01\bigoplusN-Ary Circled Plus Operator
    U+02A02\bigotimesN-Ary Circled Times Operator
    U+02A03\bigcupdotN-Ary Union Operator With Dot
    U+02A04\biguplusN-Ary Union Operator With Plus
    U+02A05\bigsqcapN-Ary Square Intersection Operator
    U+02A06\bigsqcupN-Ary Square Union Operator
    U+02A07\conjquantTwo Logical And Operator
    U+02A08\disjquantTwo Logical Or Operator
    U+02A09\bigtimesN-Ary Times Operator
    U+02A0A\modtwosumModulo Two Sum
    U+02A0B\sumintSummation With Integral
    U+02A0C\iiiintQuadruple Integral Operator
    U+02A0D\intbarFinite Part Integral
    U+02A0E\intBarIntegral With Double Stroke
    U+02A0F\clockointIntegral Average With Slash
    U+02A10\cirfnintCirculation Function
    U+02A11\awintAnticlockwise Integration
    U+02A12\rppolintLine Integration With Rectangular Path Around Pole
    U+02A13\scpolintLine Integration With Semicircular Path Around Pole
    U+02A14\npolintLine Integration Not Including The Pole
    U+02A15\pointintIntegral Around A Point Operator
    U+02A16\sqrintQuaternion Integral Operator
    U+02A18\intxIntegral With Times Sign
    U+02A19\intcapIntegral With Intersection
    U+02A1A\intcupIntegral With Union
    U+02A1B\upintIntegral With Overbar
    U+02A1C\lowintIntegral With Underbar
    U+02A1D\joinJoin
    U+02A1F\bbsemiZ Notation Schema Composition
    U+02A22\ringplusPlus Sign With Small Circle Above
    U+02A23\plushatPlus Sign With Circumflex Accent Above
    U+02A24\simplusPlus Sign With Tilde Above
    U+02A25\plusdotPlus Sign With Dot Below
    U+02A26\plussimPlus Sign With Tilde Below
    U+02A27\plussubtwoPlus Sign With Subscript Two
    U+02A28\plustrifPlus Sign With Black Triangle
    U+02A29\commaminusMinus Sign With Comma Above
    U+02A2A\minusdotMinus Sign With Dot Below
    U+02A2B\minusfdotsMinus Sign With Falling Dots
    U+02A2C\minusrdotsMinus Sign With Rising Dots
    U+02A2D\opluslhrimPlus Sign In Left Half Circle
    U+02A2E\oplusrhrimPlus Sign In Right Half Circle
    U+02A2F\TimesVector Or Cross Product
    U+02A30\dottimesMultiplication Sign With Dot Above
    U+02A31\timesbarMultiplication Sign With Underbar
    U+02A32\btimesSemidirect Product With Bottom Closed
    U+02A33\smashtimesSmash Product
    U+02A34\otimeslhrimMultiplication Sign In Left Half Circle
    U+02A35\otimesrhrimMultiplication Sign In Right Half Circle
    U+02A36\otimeshatCircled Multiplication Sign With Circumflex Accent
    U+02A37\OtimesMultiplication Sign In Double Circle
    U+02A38\odivCircled Division Sign
    U+02A39\triangleplusPlus Sign In Triangle
    U+02A3A\triangleminusMinus Sign In Triangle
    U+02A3B\triangletimesMultiplication Sign In Triangle
    U+02A3C\intprodInterior Product
    U+02A3D\intprodrRighthand Interior Product
    U+02A3F⨿\amalgAmalgamation Or Coproduct
    U+02A40\capdotIntersection With Dot
    U+02A41\uminusUnion With Minus Sign
    U+02A42\barcupUnion With Overbar
    U+02A43\barcapIntersection With Overbar
    U+02A44\capwedgeIntersection With Logical And
    U+02A45\cupveeUnion With Logical Or
    U+02A4A\twocupsUnion Beside And Joined With Union
    U+02A4B\twocapsIntersection Beside And Joined With Intersection
    U+02A4C\closedvarcupClosed Union With Serifs
    U+02A4D\closedvarcapClosed Intersection With Serifs
    U+02A4E\SqcapDouble Square Intersection
    U+02A4F\SqcupDouble Square Union
    U+02A50\closedvarcupsmashprodClosed Union With Serifs And Smash Product
    U+02A51\wedgeodotLogical And With Dot Above
    U+02A52\veeodotLogical Or With Dot Above
    U+02A53\AndDouble Logical And
    U+02A54\OrDouble Logical Or
    U+02A55\wedgeonwedgeTwo Intersecting Logical And
    U+02A56\ElOrTwo Intersecting Logical Or
    U+02A57\bigslopedveeSloping Large Or
    U+02A58\bigslopedwedgeSloping Large And
    U+02A5A\wedgemidvertLogical And With Middle Stem
    U+02A5B\veemidvertLogical Or With Middle Stem
    U+02A5C\midbarwedgeLogical And With Horizontal Dash
    U+02A5D\midbarveeLogical Or With Horizontal Dash
    U+02A5E\perspcorrespondLogical And With Double Overbar
    U+02A5F\minhatLogical And With Underbar
    U+02A60\wedgedoublebarLogical And With Double Underbar
    U+02A61\varveebarSmall Vee With Underbar
    U+02A62\doublebarveeLogical Or With Double Overbar
    U+02A63\veedoublebarLogical Or With Double Underbar
    U+02A66\eqdotEquals Sign With Dot Below
    U+02A67\dotequivIdentical With Dot Above
    U+02A6A\dotsimTilde Operator With Dot Above
    U+02A6B\simrdotsTilde Operator With Rising Dots
    U+02A6C\simminussimSimilar Minus Similar
    U+02A6D\congdotCongruent With Dot Above
    U+02A6E\asteqEquals With Asterisk
    U+02A6F\hatapproxAlmost Equal To With Circumflex Accent
    U+02A70\approxeqqApproximately Equal Or Equal To
    U+02A71\eqqplusEquals Sign Above Plus Sign
    U+02A72\pluseqqPlus Sign Above Equals Sign
    U+02A73\eqqsimEquals Sign Above Tilde Operator
    U+02A74\ColoneqDouble Colon Equal
    U+02A75\EqualTwo Consecutive Equals Signs
    U+02A76\eqeqeqThree Consecutive Equals Signs
    U+02A77\ddotseqEquals Sign With Two Dots Above And Two Dots Below
    U+02A78\equivDDEquivalent With Four Dots Above
    U+02A79\ltcirLess-Than With Circle Inside
    U+02A7A\gtcirGreater-Than With Circle Inside
    U+02A7B\ltquestLess-Than With Question Mark Above
    U+02A7C\gtquestGreater-Than With Question Mark Above
    U+02A7D\leqslantLess-Than Or Slanted Equal To
    U+02A7D + U+00338⩽̸\nleqslantLess-Than Or Slanted Equal To + Combining Long Solidus Overlay / Non-Spacing Long Slash Overlay
    U+02A7E\geqslantGreater-Than Or Slanted Equal To
    U+02A7E + U+00338⩾̸\ngeqslantGreater-Than Or Slanted Equal To + Combining Long Solidus Overlay / Non-Spacing Long Slash Overlay
    U+02A7F⩿\lesdotLess-Than Or Slanted Equal To With Dot Inside
    U+02A80\gesdotGreater-Than Or Slanted Equal To With Dot Inside
    U+02A81\lesdotoLess-Than Or Slanted Equal To With Dot Above
    U+02A82\gesdotoGreater-Than Or Slanted Equal To With Dot Above
    U+02A83\lesdotorLess-Than Or Slanted Equal To With Dot Above Right
    U+02A84\gesdotolGreater-Than Or Slanted Equal To With Dot Above Left
    U+02A85\lessapproxLess-Than Or Approximate
    U+02A86\gtrapproxGreater-Than Or Approximate
    U+02A87\lneqLess-Than And Single-Line Not Equal To
    U+02A88\gneqGreater-Than And Single-Line Not Equal To
    U+02A89\lnapproxLess-Than And Not Approximate
    U+02A8A\gnapproxGreater-Than And Not Approximate
    U+02A8B\lesseqqgtrLess-Than Above Double-Line Equal Above Greater-Than
    U+02A8C\gtreqqlessGreater-Than Above Double-Line Equal Above Less-Than
    U+02A8D\lsimeLess-Than Above Similar Or Equal
    U+02A8E\gsimeGreater-Than Above Similar Or Equal
    U+02A8F\lsimgLess-Than Above Similar Above Greater-Than
    U+02A90\gsimlGreater-Than Above Similar Above Less-Than
    U+02A91\lgELess-Than Above Greater-Than Above Double-Line Equal
    U+02A92\glEGreater-Than Above Less-Than Above Double-Line Equal
    U+02A93\lesgesLess-Than Above Slanted Equal Above Greater-Than Above Slanted Equal
    U+02A94\geslesGreater-Than Above Slanted Equal Above Less-Than Above Slanted Equal
    U+02A95\eqslantlessSlanted Equal To Or Less-Than
    U+02A96\eqslantgtrSlanted Equal To Or Greater-Than
    U+02A97\elsdotSlanted Equal To Or Less-Than With Dot Inside
    U+02A98\egsdotSlanted Equal To Or Greater-Than With Dot Inside
    U+02A99\eqqlessDouble-Line Equal To Or Less-Than
    U+02A9A\eqqgtrDouble-Line Equal To Or Greater-Than
    U+02A9B\eqqslantlessDouble-Line Slanted Equal To Or Less-Than
    U+02A9C\eqqslantgtrDouble-Line Slanted Equal To Or Greater-Than
    U+02A9D\simlessSimilar Or Less-Than
    U+02A9E\simgtrSimilar Or Greater-Than
    U+02A9F\simlESimilar Above Less-Than Above Equals Sign
    U+02AA0\simgESimilar Above Greater-Than Above Equals Sign
    U+02AA1\NestedLessLessDouble Nested Less-Than
    U+02AA1 + U+00338⪡̸\NotNestedLessLessDouble Nested Less-Than + Combining Long Solidus Overlay / Non-Spacing Long Slash Overlay
    U+02AA2\NestedGreaterGreaterDouble Nested Greater-Than
    U+02AA2 + U+00338⪢̸\NotNestedGreaterGreaterDouble Nested Greater-Than + Combining Long Solidus Overlay / Non-Spacing Long Slash Overlay
    U+02AA3\partialmeetcontractionDouble Nested Less-Than With Underbar
    U+02AA4\gljGreater-Than Overlapping Less-Than
    U+02AA5\glaGreater-Than Beside Less-Than
    U+02AA6\ltccLess-Than Closed By Curve
    U+02AA7\gtccGreater-Than Closed By Curve
    U+02AA8\lesccLess-Than Closed By Curve Above Slanted Equal
    U+02AA9\gesccGreater-Than Closed By Curve Above Slanted Equal
    U+02AAA\smtSmaller Than
    U+02AAB\latLarger Than
    U+02AAC\smteSmaller Than Or Equal To
    U+02AAD\lateLarger Than Or Equal To
    U+02AAE\bumpeqqEquals Sign With Bumpy Above
    U+02AAF\preceqPrecedes Above Single-Line Equals Sign
    U+02AAF + U+00338⪯̸\npreceqPrecedes Above Single-Line Equals Sign + Combining Long Solidus Overlay / Non-Spacing Long Slash Overlay
    U+02AB0\succeqSucceeds Above Single-Line Equals Sign
    U+02AB0 + U+00338⪰̸\nsucceqSucceeds Above Single-Line Equals Sign + Combining Long Solidus Overlay / Non-Spacing Long Slash Overlay
    U+02AB1\precneqPrecedes Above Single-Line Not Equal To
    U+02AB2\succneqSucceeds Above Single-Line Not Equal To
    U+02AB3\preceqqPrecedes Above Equals Sign
    U+02AB4\succeqqSucceeds Above Equals Sign
    U+02AB5\precneqqPrecedes Above Not Equal To
    U+02AB6\succneqqSucceeds Above Not Equal To
    U+02AB7\precapproxPrecedes Above Almost Equal To
    U+02AB8\succapproxSucceeds Above Almost Equal To
    U+02AB9\precnapproxPrecedes Above Not Almost Equal To
    U+02ABA\succnapproxSucceeds Above Not Almost Equal To
    U+02ABB\PrecDouble Precedes
    U+02ABC\SuccDouble Succeeds
    U+02ABD\subsetdotSubset With Dot
    U+02ABE\supsetdotSuperset With Dot
    U+02ABF⪿\subsetplusSubset With Plus Sign Below
    U+02AC0\supsetplusSuperset With Plus Sign Below
    U+02AC1\submultSubset With Multiplication Sign Below
    U+02AC2\supmultSuperset With Multiplication Sign Below
    U+02AC3\subedotSubset Of Or Equal To With Dot Above
    U+02AC4\supedotSuperset Of Or Equal To With Dot Above
    U+02AC5\subseteqqSubset Of Above Equals Sign
    U+02AC5 + U+00338⫅̸\nsubseteqqSubset Of Above Equals Sign + Combining Long Solidus Overlay / Non-Spacing Long Slash Overlay
    U+02AC6\supseteqqSuperset Of Above Equals Sign
    U+02AC6 + U+00338⫆̸\nsupseteqqSuperset Of Above Equals Sign + Combining Long Solidus Overlay / Non-Spacing Long Slash Overlay
    U+02AC7\subsimSubset Of Above Tilde Operator
    U+02AC8\supsimSuperset Of Above Tilde Operator
    U+02AC9\subsetapproxSubset Of Above Almost Equal To
    U+02ACA\supsetapproxSuperset Of Above Almost Equal To
    U+02ACB\subsetneqqSubset Of Above Not Equal To
    U+02ACC\supsetneqqSuperset Of Above Not Equal To
    U+02ACD\lsqhookSquare Left Open Box Operator
    U+02ACE\rsqhookSquare Right Open Box Operator
    U+02ACF\csubClosed Subset
    U+02AD0\csupClosed Superset
    U+02AD1\csubeClosed Subset Or Equal To
    U+02AD2\csupeClosed Superset Or Equal To
    U+02AD3\subsupSubset Above Superset
    U+02AD4\supsubSuperset Above Subset
    U+02AD5\subsubSubset Above Subset
    U+02AD6\supsupSuperset Above Superset
    U+02AD7\suphsubSuperset Beside Subset
    U+02AD8\supdsubSuperset Beside And Joined By Dash With Subset
    U+02AD9\forkvElement Of Opening Downwards
    U+02ADB\mlcpTransversal Intersection
    U+02ADC\forksForking
    U+02ADD\forksnotNonforking
    U+02AE3\dashVDouble Vertical Bar Left Turnstile
    U+02AE4\DashvVertical Bar Double Left Turnstile
    U+02AEA\Top, \downvDashDouble Down Tack
    U+02AEB\upvDash, \Bot, \indepDouble Up Tack
    U+02AF4\interleaveTriple Vertical Bar Binary Relation
    U+02AF6\tdcolTriple Colon Operator
    U+02AF7\lllnestTriple Nested Less-Than
    U+02AF8\gggnestTriple Nested Greater-Than
    U+02AF9\leqqslantDouble-Line Slanted Less-Than Or Equal To
    U+02AFA\geqqslantDouble-Line Slanted Greater-Than Or Equal To
    U+02B05\:arrow_left:Leftwards Black Arrow
    U+02B06\:arrow_up:Upwards Black Arrow
    U+02B07\:arrow_down:Downwards Black Arrow
    U+02B12\squaretopblackSquare With Top Half Black
    U+02B13\squarebotblackSquare With Bottom Half Black
    U+02B14\squareurblackSquare With Upper Right Diagonal Half Black
    U+02B15\squarellblackSquare With Lower Left Diagonal Half Black
    U+02B16\diamondleftblackDiamond With Left Half Black
    U+02B17\diamondrightblackDiamond With Right Half Black
    U+02B18\diamondtopblackDiamond With Top Half Black
    U+02B19\diamondbotblackDiamond With Bottom Half Black
    U+02B1A\dottedsquareDotted Square
    U+02B1B\lgblksquare, \:black_large_square:Black Large Square
    U+02B1C\lgwhtsquare, \:white_large_square:White Large Square
    U+02B1D\vysmblksquareBlack Very Small Square
    U+02B1E\vysmwhtsquareWhite Very Small Square
    U+02B1F\pentagonblackBlack Pentagon
    U+02B20\pentagonWhite Pentagon
    U+02B21\varhexagonWhite Hexagon
    U+02B22\varhexagonblackBlack Hexagon
    U+02B23\hexagonblackHorizontal Black Hexagon
    U+02B24\lgblkcircleBlack Large Circle
    U+02B25\mdblkdiamondBlack Medium Diamond
    U+02B26\mdwhtdiamondWhite Medium Diamond
    U+02B27\mdblklozengeBlack Medium Lozenge
    U+02B28\mdwhtlozengeWhite Medium Lozenge
    U+02B29\smblkdiamondBlack Small Diamond
    U+02B2A\smblklozengeBlack Small Lozenge
    U+02B2B\smwhtlozengeWhite Small Lozenge
    U+02B2C\blkhorzovalBlack Horizontal Ellipse
    U+02B2D\whthorzovalWhite Horizontal Ellipse
    U+02B2E\blkvertovalBlack Vertical Ellipse
    U+02B2F\whtvertovalWhite Vertical Ellipse
    U+02B30\circleonleftarrowLeft Arrow With Small Circle
    U+02B31\leftthreearrowsThree Leftwards Arrows
    U+02B32\leftarrowonoplusLeft Arrow With Circled Plus
    U+02B33\longleftsquigarrowLong Leftwards Squiggle Arrow
    U+02B34\nvtwoheadleftarrowLeftwards Two-Headed Arrow With Vertical Stroke
    U+02B35\nVtwoheadleftarrowLeftwards Two-Headed Arrow With Double Vertical Stroke
    U+02B36\twoheadmapsfromLeftwards Two-Headed Arrow From Bar
    U+02B37\twoheadleftdbkarrowLeftwards Two-Headed Triple Dash Arrow
    U+02B38\leftdotarrowLeftwards Arrow With Dotted Stem
    U+02B39\nvleftarrowtailLeftwards Arrow With Tail With Vertical Stroke
    U+02B3A\nVleftarrowtailLeftwards Arrow With Tail With Double Vertical Stroke
    U+02B3B\twoheadleftarrowtailLeftwards Two-Headed Arrow With Tail
    U+02B3C\nvtwoheadleftarrowtailLeftwards Two-Headed Arrow With Tail With Vertical Stroke
    U+02B3D\nVtwoheadleftarrowtailLeftwards Two-Headed Arrow With Tail With Double Vertical Stroke
    U+02B3E\leftarrowxLeftwards Arrow Through X
    U+02B3F⬿\leftcurvedarrowWave Arrow Pointing Directly Left
    U+02B40\equalleftarrowEquals Sign Above Leftwards Arrow
    U+02B41\bsimilarleftarrowReverse Tilde Operator Above Leftwards Arrow
    U+02B42\leftarrowbackapproxLeftwards Arrow Above Reverse Almost Equal To
    U+02B43\rightarrowgtrRightwards Arrow Through Greater-Than
    U+02B44\rightarrowsupsetRightwards Arrow Through Superset
    U+02B45\LLeftarrowLeftwards Quadruple Arrow
    U+02B46\RRightarrowRightwards Quadruple Arrow
    U+02B47\bsimilarrightarrowReverse Tilde Operator Above Rightwards Arrow
    U+02B48\rightarrowbackapproxRightwards Arrow Above Reverse Almost Equal To
    U+02B49\similarleftarrowTilde Operator Above Leftwards Arrow
    U+02B4A\leftarrowapproxLeftwards Arrow Above Almost Equal To
    U+02B4B\leftarrowbsimilarLeftwards Arrow Above Reverse Tilde Operator
    U+02B4C\rightarrowbsimilarRightwards Arrow Above Reverse Tilde Operator
    U+02B50\medwhitestar, \:star:White Medium Star
    U+02B51\medblackstarBlack Small Star
    U+02B52\smwhitestarWhite Small Star
    U+02B53\rightpentagonblackBlack Right-Pointing Pentagon
    U+02B54\rightpentagonWhite Right-Pointing Pentagon
    U+02B55\:o:Heavy Large Circle
    U+02C7C\_jLatin Subscript Small Letter J
    U+02C7D\^VModifier Letter Capital V
    U+03012\postalmarkPostal Mark
    U+03030\:wavy_dash:Wavy Dash
    U+0303D\:part_alternation_mark:Part Alternation Mark
    U+03297\:congratulations:Circled Ideograph Congratulation
    U+03299\:secret:Circled Ideograph Secret
    U+0A71B\^uparrowModifier Letter Raised Up Arrow
    U+0A71C\^downarrowModifier Letter Raised Down Arrow
    U+0A71D\^!Modifier Letter Raised Exclamation Mark
    U+1D400𝐀\bfAMathematical Bold Capital A
    U+1D401𝐁\bfBMathematical Bold Capital B
    U+1D402𝐂\bfCMathematical Bold Capital C
    U+1D403𝐃\bfDMathematical Bold Capital D
    U+1D404𝐄\bfEMathematical Bold Capital E
    U+1D405𝐅\bfFMathematical Bold Capital F
    U+1D406𝐆\bfGMathematical Bold Capital G
    U+1D407𝐇\bfHMathematical Bold Capital H
    U+1D408𝐈\bfIMathematical Bold Capital I
    U+1D409𝐉\bfJMathematical Bold Capital J
    U+1D40A𝐊\bfKMathematical Bold Capital K
    U+1D40B𝐋\bfLMathematical Bold Capital L
    U+1D40C𝐌\bfMMathematical Bold Capital M
    U+1D40D𝐍\bfNMathematical Bold Capital N
    U+1D40E𝐎\bfOMathematical Bold Capital O
    U+1D40F𝐏\bfPMathematical Bold Capital P
    U+1D410𝐐\bfQMathematical Bold Capital Q
    U+1D411𝐑\bfRMathematical Bold Capital R
    U+1D412𝐒\bfSMathematical Bold Capital S
    U+1D413𝐓\bfTMathematical Bold Capital T
    U+1D414𝐔\bfUMathematical Bold Capital U
    U+1D415𝐕\bfVMathematical Bold Capital V
    U+1D416𝐖\bfWMathematical Bold Capital W
    U+1D417𝐗\bfXMathematical Bold Capital X
    U+1D418𝐘\bfYMathematical Bold Capital Y
    U+1D419𝐙\bfZMathematical Bold Capital Z
    U+1D41A𝐚\bfaMathematical Bold Small A
    U+1D41B𝐛\bfbMathematical Bold Small B
    U+1D41C𝐜\bfcMathematical Bold Small C
    U+1D41D𝐝\bfdMathematical Bold Small D
    U+1D41E𝐞\bfeMathematical Bold Small E
    U+1D41F𝐟\bffMathematical Bold Small F
    U+1D420𝐠\bfgMathematical Bold Small G
    U+1D421𝐡\bfhMathematical Bold Small H
    U+1D422𝐢\bfiMathematical Bold Small I
    U+1D423𝐣\bfjMathematical Bold Small J
    U+1D424𝐤\bfkMathematical Bold Small K
    U+1D425𝐥\bflMathematical Bold Small L
    U+1D426𝐦\bfmMathematical Bold Small M
    U+1D427𝐧\bfnMathematical Bold Small N
    U+1D428𝐨\bfoMathematical Bold Small O
    U+1D429𝐩\bfpMathematical Bold Small P
    U+1D42A𝐪\bfqMathematical Bold Small Q
    U+1D42B𝐫\bfrMathematical Bold Small R
    U+1D42C𝐬\bfsMathematical Bold Small S
    U+1D42D𝐭\bftMathematical Bold Small T
    U+1D42E𝐮\bfuMathematical Bold Small U
    U+1D42F𝐯\bfvMathematical Bold Small V
    U+1D430𝐰\bfwMathematical Bold Small W
    U+1D431𝐱\bfxMathematical Bold Small X
    U+1D432𝐲\bfyMathematical Bold Small Y
    U+1D433𝐳\bfzMathematical Bold Small Z
    U+1D434𝐴\itAMathematical Italic Capital A
    U+1D435𝐵\itBMathematical Italic Capital B
    U+1D436𝐶\itCMathematical Italic Capital C
    U+1D437𝐷\itDMathematical Italic Capital D
    U+1D438𝐸\itEMathematical Italic Capital E
    U+1D439𝐹\itFMathematical Italic Capital F
    U+1D43A𝐺\itGMathematical Italic Capital G
    U+1D43B𝐻\itHMathematical Italic Capital H
    U+1D43C𝐼\itIMathematical Italic Capital I
    U+1D43D𝐽\itJMathematical Italic Capital J
    U+1D43E𝐾\itKMathematical Italic Capital K
    U+1D43F𝐿\itLMathematical Italic Capital L
    U+1D440𝑀\itMMathematical Italic Capital M
    U+1D441𝑁\itNMathematical Italic Capital N
    U+1D442𝑂\itOMathematical Italic Capital O
    U+1D443𝑃\itPMathematical Italic Capital P
    U+1D444𝑄\itQMathematical Italic Capital Q
    U+1D445𝑅\itRMathematical Italic Capital R
    U+1D446𝑆\itSMathematical Italic Capital S
    U+1D447𝑇\itTMathematical Italic Capital T
    U+1D448𝑈\itUMathematical Italic Capital U
    U+1D449𝑉\itVMathematical Italic Capital V
    U+1D44A𝑊\itWMathematical Italic Capital W
    U+1D44B𝑋\itXMathematical Italic Capital X
    U+1D44C𝑌\itYMathematical Italic Capital Y
    U+1D44D𝑍\itZMathematical Italic Capital Z
    U+1D44E𝑎\itaMathematical Italic Small A
    U+1D44F𝑏\itbMathematical Italic Small B
    U+1D450𝑐\itcMathematical Italic Small C
    U+1D451𝑑\itdMathematical Italic Small D
    U+1D452𝑒\iteMathematical Italic Small E
    U+1D453𝑓\itfMathematical Italic Small F
    U+1D454𝑔\itgMathematical Italic Small G
    U+1D456𝑖\itiMathematical Italic Small I
    U+1D457𝑗\itjMathematical Italic Small J
    U+1D458𝑘\itkMathematical Italic Small K
    U+1D459𝑙\itlMathematical Italic Small L
    U+1D45A𝑚\itmMathematical Italic Small M
    U+1D45B𝑛\itnMathematical Italic Small N
    U+1D45C𝑜\itoMathematical Italic Small O
    U+1D45D𝑝\itpMathematical Italic Small P
    U+1D45E𝑞\itqMathematical Italic Small Q
    U+1D45F𝑟\itrMathematical Italic Small R
    U+1D460𝑠\itsMathematical Italic Small S
    U+1D461𝑡\ittMathematical Italic Small T
    U+1D462𝑢\ituMathematical Italic Small U
    U+1D463𝑣\itvMathematical Italic Small V
    U+1D464𝑤\itwMathematical Italic Small W
    U+1D465𝑥\itxMathematical Italic Small X
    U+1D466𝑦\ityMathematical Italic Small Y
    U+1D467𝑧\itzMathematical Italic Small Z
    U+1D468𝑨\biAMathematical Bold Italic Capital A
    U+1D469𝑩\biBMathematical Bold Italic Capital B
    U+1D46A𝑪\biCMathematical Bold Italic Capital C
    U+1D46B𝑫\biDMathematical Bold Italic Capital D
    U+1D46C𝑬\biEMathematical Bold Italic Capital E
    U+1D46D𝑭\biFMathematical Bold Italic Capital F
    U+1D46E𝑮\biGMathematical Bold Italic Capital G
    U+1D46F𝑯\biHMathematical Bold Italic Capital H
    U+1D470𝑰\biIMathematical Bold Italic Capital I
    U+1D471𝑱\biJMathematical Bold Italic Capital J
    U+1D472𝑲\biKMathematical Bold Italic Capital K
    U+1D473𝑳\biLMathematical Bold Italic Capital L
    U+1D474𝑴\biMMathematical Bold Italic Capital M
    U+1D475𝑵\biNMathematical Bold Italic Capital N
    U+1D476𝑶\biOMathematical Bold Italic Capital O
    U+1D477𝑷\biPMathematical Bold Italic Capital P
    U+1D478𝑸\biQMathematical Bold Italic Capital Q
    U+1D479𝑹\biRMathematical Bold Italic Capital R
    U+1D47A𝑺\biSMathematical Bold Italic Capital S
    U+1D47B𝑻\biTMathematical Bold Italic Capital T
    U+1D47C𝑼\biUMathematical Bold Italic Capital U
    U+1D47D𝑽\biVMathematical Bold Italic Capital V
    U+1D47E𝑾\biWMathematical Bold Italic Capital W
    U+1D47F𝑿\biXMathematical Bold Italic Capital X
    U+1D480𝒀\biYMathematical Bold Italic Capital Y
    U+1D481𝒁\biZMathematical Bold Italic Capital Z
    U+1D482𝒂\biaMathematical Bold Italic Small A
    U+1D483𝒃\bibMathematical Bold Italic Small B
    U+1D484𝒄\bicMathematical Bold Italic Small C
    U+1D485𝒅\bidMathematical Bold Italic Small D
    U+1D486𝒆\bieMathematical Bold Italic Small E
    U+1D487𝒇\bifMathematical Bold Italic Small F
    U+1D488𝒈\bigMathematical Bold Italic Small G
    U+1D489𝒉\bihMathematical Bold Italic Small H
    U+1D48A𝒊\biiMathematical Bold Italic Small I
    U+1D48B𝒋\bijMathematical Bold Italic Small J
    U+1D48C𝒌\bikMathematical Bold Italic Small K
    U+1D48D𝒍\bilMathematical Bold Italic Small L
    U+1D48E𝒎\bimMathematical Bold Italic Small M
    U+1D48F𝒏\binMathematical Bold Italic Small N
    U+1D490𝒐\bioMathematical Bold Italic Small O
    U+1D491𝒑\bipMathematical Bold Italic Small P
    U+1D492𝒒\biqMathematical Bold Italic Small Q
    U+1D493𝒓\birMathematical Bold Italic Small R
    U+1D494𝒔\bisMathematical Bold Italic Small S
    U+1D495𝒕\bitMathematical Bold Italic Small T
    U+1D496𝒖\biuMathematical Bold Italic Small U
    U+1D497𝒗\bivMathematical Bold Italic Small V
    U+1D498𝒘\biwMathematical Bold Italic Small W
    U+1D499𝒙\bixMathematical Bold Italic Small X
    U+1D49A𝒚\biyMathematical Bold Italic Small Y
    U+1D49B𝒛\bizMathematical Bold Italic Small Z
    U+1D49C𝒜\scrAMathematical Script Capital A
    U+1D49E𝒞\scrCMathematical Script Capital C
    U+1D49F𝒟\scrDMathematical Script Capital D
    U+1D4A2𝒢\scrGMathematical Script Capital G
    U+1D4A5𝒥\scrJMathematical Script Capital J
    U+1D4A6𝒦\scrKMathematical Script Capital K
    U+1D4A9𝒩\scrNMathematical Script Capital N
    U+1D4AA𝒪\scrOMathematical Script Capital O
    U+1D4AB𝒫\scrPMathematical Script Capital P
    U+1D4AC𝒬\scrQMathematical Script Capital Q
    U+1D4AE𝒮\scrSMathematical Script Capital S
    U+1D4AF𝒯\scrTMathematical Script Capital T
    U+1D4B0𝒰\scrUMathematical Script Capital U
    U+1D4B1𝒱\scrVMathematical Script Capital V
    U+1D4B2𝒲\scrWMathematical Script Capital W
    U+1D4B3𝒳\scrXMathematical Script Capital X
    U+1D4B4𝒴\scrYMathematical Script Capital Y
    U+1D4B5𝒵\scrZMathematical Script Capital Z
    U+1D4B6𝒶\scraMathematical Script Small A
    U+1D4B7𝒷\scrbMathematical Script Small B
    U+1D4B8𝒸\scrcMathematical Script Small C
    U+1D4B9𝒹\scrdMathematical Script Small D
    U+1D4BB𝒻\scrfMathematical Script Small F
    U+1D4BD𝒽\scrhMathematical Script Small H
    U+1D4BE𝒾\scriMathematical Script Small I
    U+1D4BF𝒿\scrjMathematical Script Small J
    U+1D4C0𝓀\scrkMathematical Script Small K
    U+1D4C1𝓁\scrlMathematical Script Small L
    U+1D4C2𝓂\scrmMathematical Script Small M
    U+1D4C3𝓃\scrnMathematical Script Small N
    U+1D4C5𝓅\scrpMathematical Script Small P
    U+1D4C6𝓆\scrqMathematical Script Small Q
    U+1D4C7𝓇\scrrMathematical Script Small R
    U+1D4C8𝓈\scrsMathematical Script Small S
    U+1D4C9𝓉\scrtMathematical Script Small T
    U+1D4CA𝓊\scruMathematical Script Small U
    U+1D4CB𝓋\scrvMathematical Script Small V
    U+1D4CC𝓌\scrwMathematical Script Small W
    U+1D4CD𝓍\scrxMathematical Script Small X
    U+1D4CE𝓎\scryMathematical Script Small Y
    U+1D4CF𝓏\scrzMathematical Script Small Z
    U+1D4D0𝓐\bscrAMathematical Bold Script Capital A
    U+1D4D1𝓑\bscrBMathematical Bold Script Capital B
    U+1D4D2𝓒\bscrCMathematical Bold Script Capital C
    U+1D4D3𝓓\bscrDMathematical Bold Script Capital D
    U+1D4D4𝓔\bscrEMathematical Bold Script Capital E
    U+1D4D5𝓕\bscrFMathematical Bold Script Capital F
    U+1D4D6𝓖\bscrGMathematical Bold Script Capital G
    U+1D4D7𝓗\bscrHMathematical Bold Script Capital H
    U+1D4D8𝓘\bscrIMathematical Bold Script Capital I
    U+1D4D9𝓙\bscrJMathematical Bold Script Capital J
    U+1D4DA𝓚\bscrKMathematical Bold Script Capital K
    U+1D4DB𝓛\bscrLMathematical Bold Script Capital L
    U+1D4DC𝓜\bscrMMathematical Bold Script Capital M
    U+1D4DD𝓝\bscrNMathematical Bold Script Capital N
    U+1D4DE𝓞\bscrOMathematical Bold Script Capital O
    U+1D4DF𝓟\bscrPMathematical Bold Script Capital P
    U+1D4E0𝓠\bscrQMathematical Bold Script Capital Q
    U+1D4E1𝓡\bscrRMathematical Bold Script Capital R
    U+1D4E2𝓢\bscrSMathematical Bold Script Capital S
    U+1D4E3𝓣\bscrTMathematical Bold Script Capital T
    U+1D4E4𝓤\bscrUMathematical Bold Script Capital U
    U+1D4E5𝓥\bscrVMathematical Bold Script Capital V
    U+1D4E6𝓦\bscrWMathematical Bold Script Capital W
    U+1D4E7𝓧\bscrXMathematical Bold Script Capital X
    U+1D4E8𝓨\bscrYMathematical Bold Script Capital Y
    U+1D4E9𝓩\bscrZMathematical Bold Script Capital Z
    U+1D4EA𝓪\bscraMathematical Bold Script Small A
    U+1D4EB𝓫\bscrbMathematical Bold Script Small B
    U+1D4EC𝓬\bscrcMathematical Bold Script Small C
    U+1D4ED𝓭\bscrdMathematical Bold Script Small D
    U+1D4EE𝓮\bscreMathematical Bold Script Small E
    U+1D4EF𝓯\bscrfMathematical Bold Script Small F
    U+1D4F0𝓰\bscrgMathematical Bold Script Small G
    U+1D4F1𝓱\bscrhMathematical Bold Script Small H
    U+1D4F2𝓲\bscriMathematical Bold Script Small I
    U+1D4F3𝓳\bscrjMathematical Bold Script Small J
    U+1D4F4𝓴\bscrkMathematical Bold Script Small K
    U+1D4F5𝓵\bscrlMathematical Bold Script Small L
    U+1D4F6𝓶\bscrmMathematical Bold Script Small M
    U+1D4F7𝓷\bscrnMathematical Bold Script Small N
    U+1D4F8𝓸\bscroMathematical Bold Script Small O
    U+1D4F9𝓹\bscrpMathematical Bold Script Small P
    U+1D4FA𝓺\bscrqMathematical Bold Script Small Q
    U+1D4FB𝓻\bscrrMathematical Bold Script Small R
    U+1D4FC𝓼\bscrsMathematical Bold Script Small S
    U+1D4FD𝓽\bscrtMathematical Bold Script Small T
    U+1D4FE𝓾\bscruMathematical Bold Script Small U
    U+1D4FF𝓿\bscrvMathematical Bold Script Small V
    U+1D500𝔀\bscrwMathematical Bold Script Small W
    U+1D501𝔁\bscrxMathematical Bold Script Small X
    U+1D502𝔂\bscryMathematical Bold Script Small Y
    U+1D503𝔃\bscrzMathematical Bold Script Small Z
    U+1D504𝔄\frakAMathematical Fraktur Capital A
    U+1D505𝔅\frakBMathematical Fraktur Capital B
    U+1D507𝔇\frakDMathematical Fraktur Capital D
    U+1D508𝔈\frakEMathematical Fraktur Capital E
    U+1D509𝔉\frakFMathematical Fraktur Capital F
    U+1D50A𝔊\frakGMathematical Fraktur Capital G
    U+1D50D𝔍\frakJMathematical Fraktur Capital J
    U+1D50E𝔎\frakKMathematical Fraktur Capital K
    U+1D50F𝔏\frakLMathematical Fraktur Capital L
    U+1D510𝔐\frakMMathematical Fraktur Capital M
    U+1D511𝔑\frakNMathematical Fraktur Capital N
    U+1D512𝔒\frakOMathematical Fraktur Capital O
    U+1D513𝔓\frakPMathematical Fraktur Capital P
    U+1D514𝔔\frakQMathematical Fraktur Capital Q
    U+1D516𝔖\frakSMathematical Fraktur Capital S
    U+1D517𝔗\frakTMathematical Fraktur Capital T
    U+1D518𝔘\frakUMathematical Fraktur Capital U
    U+1D519𝔙\frakVMathematical Fraktur Capital V
    U+1D51A𝔚\frakWMathematical Fraktur Capital W
    U+1D51B𝔛\frakXMathematical Fraktur Capital X
    U+1D51C𝔜\frakYMathematical Fraktur Capital Y
    U+1D51E𝔞\frakaMathematical Fraktur Small A
    U+1D51F𝔟\frakbMathematical Fraktur Small B
    U+1D520𝔠\frakcMathematical Fraktur Small C
    U+1D521𝔡\frakdMathematical Fraktur Small D
    U+1D522𝔢\frakeMathematical Fraktur Small E
    U+1D523𝔣\frakfMathematical Fraktur Small F
    U+1D524𝔤\frakgMathematical Fraktur Small G
    U+1D525𝔥\frakhMathematical Fraktur Small H
    U+1D526𝔦\frakiMathematical Fraktur Small I
    U+1D527𝔧\frakjMathematical Fraktur Small J
    U+1D528𝔨\frakkMathematical Fraktur Small K
    U+1D529𝔩\fraklMathematical Fraktur Small L
    U+1D52A𝔪\frakmMathematical Fraktur Small M
    U+1D52B𝔫\fraknMathematical Fraktur Small N
    U+1D52C𝔬\frakoMathematical Fraktur Small O
    U+1D52D𝔭\frakpMathematical Fraktur Small P
    U+1D52E𝔮\frakqMathematical Fraktur Small Q
    U+1D52F𝔯\frakrMathematical Fraktur Small R
    U+1D530𝔰\fraksMathematical Fraktur Small S
    U+1D531𝔱\fraktMathematical Fraktur Small T
    U+1D532𝔲\frakuMathematical Fraktur Small U
    U+1D533𝔳\frakvMathematical Fraktur Small V
    U+1D534𝔴\frakwMathematical Fraktur Small W
    U+1D535𝔵\frakxMathematical Fraktur Small X
    U+1D536𝔶\frakyMathematical Fraktur Small Y
    U+1D537𝔷\frakzMathematical Fraktur Small Z
    U+1D538𝔸\bbAMathematical Double-Struck Capital A
    U+1D539𝔹\bbBMathematical Double-Struck Capital B
    U+1D53B𝔻\bbDMathematical Double-Struck Capital D
    U+1D53C𝔼\bbEMathematical Double-Struck Capital E
    U+1D53D𝔽\bbFMathematical Double-Struck Capital F
    U+1D53E𝔾\bbGMathematical Double-Struck Capital G
    U+1D540𝕀\bbIMathematical Double-Struck Capital I
    U+1D541𝕁\bbJMathematical Double-Struck Capital J
    U+1D542𝕂\bbKMathematical Double-Struck Capital K
    U+1D543𝕃\bbLMathematical Double-Struck Capital L
    U+1D544𝕄\bbMMathematical Double-Struck Capital M
    U+1D546𝕆\bbOMathematical Double-Struck Capital O
    U+1D54A𝕊\bbSMathematical Double-Struck Capital S
    U+1D54B𝕋\bbTMathematical Double-Struck Capital T
    U+1D54C𝕌\bbUMathematical Double-Struck Capital U
    U+1D54D𝕍\bbVMathematical Double-Struck Capital V
    U+1D54E𝕎\bbWMathematical Double-Struck Capital W
    U+1D54F𝕏\bbXMathematical Double-Struck Capital X
    U+1D550𝕐\bbYMathematical Double-Struck Capital Y
    U+1D552𝕒\bbaMathematical Double-Struck Small A
    U+1D553𝕓\bbbMathematical Double-Struck Small B
    U+1D554𝕔\bbcMathematical Double-Struck Small C
    U+1D555𝕕\bbdMathematical Double-Struck Small D
    U+1D556𝕖\bbeMathematical Double-Struck Small E
    U+1D557𝕗\bbfMathematical Double-Struck Small F
    U+1D558𝕘\bbgMathematical Double-Struck Small G
    U+1D559𝕙\bbhMathematical Double-Struck Small H
    U+1D55A𝕚\bbiMathematical Double-Struck Small I
    U+1D55B𝕛\bbjMathematical Double-Struck Small J
    U+1D55C𝕜\bbkMathematical Double-Struck Small K
    U+1D55D𝕝\bblMathematical Double-Struck Small L
    U+1D55E𝕞\bbmMathematical Double-Struck Small M
    U+1D55F𝕟\bbnMathematical Double-Struck Small N
    U+1D560𝕠\bboMathematical Double-Struck Small O
    U+1D561𝕡\bbpMathematical Double-Struck Small P
    U+1D562𝕢\bbqMathematical Double-Struck Small Q
    U+1D563𝕣\bbrMathematical Double-Struck Small R
    U+1D564𝕤\bbsMathematical Double-Struck Small S
    U+1D565𝕥\bbtMathematical Double-Struck Small T
    U+1D566𝕦\bbuMathematical Double-Struck Small U
    U+1D567𝕧\bbvMathematical Double-Struck Small V
    U+1D568𝕨\bbwMathematical Double-Struck Small W
    U+1D569𝕩\bbxMathematical Double-Struck Small X
    U+1D56A𝕪\bbyMathematical Double-Struck Small Y
    U+1D56B𝕫\bbzMathematical Double-Struck Small Z
    U+1D56C𝕬\bfrakAMathematical Bold Fraktur Capital A
    U+1D56D𝕭\bfrakBMathematical Bold Fraktur Capital B
    U+1D56E𝕮\bfrakCMathematical Bold Fraktur Capital C
    U+1D56F𝕯\bfrakDMathematical Bold Fraktur Capital D
    U+1D570𝕰\bfrakEMathematical Bold Fraktur Capital E
    U+1D571𝕱\bfrakFMathematical Bold Fraktur Capital F
    U+1D572𝕲\bfrakGMathematical Bold Fraktur Capital G
    U+1D573𝕳\bfrakHMathematical Bold Fraktur Capital H
    U+1D574𝕴\bfrakIMathematical Bold Fraktur Capital I
    U+1D575𝕵\bfrakJMathematical Bold Fraktur Capital J
    U+1D576𝕶\bfrakKMathematical Bold Fraktur Capital K
    U+1D577𝕷\bfrakLMathematical Bold Fraktur Capital L
    U+1D578𝕸\bfrakMMathematical Bold Fraktur Capital M
    U+1D579𝕹\bfrakNMathematical Bold Fraktur Capital N
    U+1D57A𝕺\bfrakOMathematical Bold Fraktur Capital O
    U+1D57B𝕻\bfrakPMathematical Bold Fraktur Capital P
    U+1D57C𝕼\bfrakQMathematical Bold Fraktur Capital Q
    U+1D57D𝕽\bfrakRMathematical Bold Fraktur Capital R
    U+1D57E𝕾\bfrakSMathematical Bold Fraktur Capital S
    U+1D57F𝕿\bfrakTMathematical Bold Fraktur Capital T
    U+1D580𝖀\bfrakUMathematical Bold Fraktur Capital U
    U+1D581𝖁\bfrakVMathematical Bold Fraktur Capital V
    U+1D582𝖂\bfrakWMathematical Bold Fraktur Capital W
    U+1D583𝖃\bfrakXMathematical Bold Fraktur Capital X
    U+1D584𝖄\bfrakYMathematical Bold Fraktur Capital Y
    U+1D585𝖅\bfrakZMathematical Bold Fraktur Capital Z
    U+1D586𝖆\bfrakaMathematical Bold Fraktur Small A
    U+1D587𝖇\bfrakbMathematical Bold Fraktur Small B
    U+1D588𝖈\bfrakcMathematical Bold Fraktur Small C
    U+1D589𝖉\bfrakdMathematical Bold Fraktur Small D
    U+1D58A𝖊\bfrakeMathematical Bold Fraktur Small E
    U+1D58B𝖋\bfrakfMathematical Bold Fraktur Small F
    U+1D58C𝖌\bfrakgMathematical Bold Fraktur Small G
    U+1D58D𝖍\bfrakhMathematical Bold Fraktur Small H
    U+1D58E𝖎\bfrakiMathematical Bold Fraktur Small I
    U+1D58F𝖏\bfrakjMathematical Bold Fraktur Small J
    U+1D590𝖐\bfrakkMathematical Bold Fraktur Small K
    U+1D591𝖑\bfraklMathematical Bold Fraktur Small L
    U+1D592𝖒\bfrakmMathematical Bold Fraktur Small M
    U+1D593𝖓\bfraknMathematical Bold Fraktur Small N
    U+1D594𝖔\bfrakoMathematical Bold Fraktur Small O
    U+1D595𝖕\bfrakpMathematical Bold Fraktur Small P
    U+1D596𝖖\bfrakqMathematical Bold Fraktur Small Q
    U+1D597𝖗\bfrakrMathematical Bold Fraktur Small R
    U+1D598𝖘\bfraksMathematical Bold Fraktur Small S
    U+1D599𝖙\bfraktMathematical Bold Fraktur Small T
    U+1D59A𝖚\bfrakuMathematical Bold Fraktur Small U
    U+1D59B𝖛\bfrakvMathematical Bold Fraktur Small V
    U+1D59C𝖜\bfrakwMathematical Bold Fraktur Small W
    U+1D59D𝖝\bfrakxMathematical Bold Fraktur Small X
    U+1D59E𝖞\bfrakyMathematical Bold Fraktur Small Y
    U+1D59F𝖟\bfrakzMathematical Bold Fraktur Small Z
    U+1D5A0𝖠\sansAMathematical Sans-Serif Capital A
    U+1D5A1𝖡\sansBMathematical Sans-Serif Capital B
    U+1D5A2𝖢\sansCMathematical Sans-Serif Capital C
    U+1D5A3𝖣\sansDMathematical Sans-Serif Capital D
    U+1D5A4𝖤\sansEMathematical Sans-Serif Capital E
    U+1D5A5𝖥\sansFMathematical Sans-Serif Capital F
    U+1D5A6𝖦\sansGMathematical Sans-Serif Capital G
    U+1D5A7𝖧\sansHMathematical Sans-Serif Capital H
    U+1D5A8𝖨\sansIMathematical Sans-Serif Capital I
    U+1D5A9𝖩\sansJMathematical Sans-Serif Capital J
    U+1D5AA𝖪\sansKMathematical Sans-Serif Capital K
    U+1D5AB𝖫\sansLMathematical Sans-Serif Capital L
    U+1D5AC𝖬\sansMMathematical Sans-Serif Capital M
    U+1D5AD𝖭\sansNMathematical Sans-Serif Capital N
    U+1D5AE𝖮\sansOMathematical Sans-Serif Capital O
    U+1D5AF𝖯\sansPMathematical Sans-Serif Capital P
    U+1D5B0𝖰\sansQMathematical Sans-Serif Capital Q
    U+1D5B1𝖱\sansRMathematical Sans-Serif Capital R
    U+1D5B2𝖲\sansSMathematical Sans-Serif Capital S
    U+1D5B3𝖳\sansTMathematical Sans-Serif Capital T
    U+1D5B4𝖴\sansUMathematical Sans-Serif Capital U
    U+1D5B5𝖵\sansVMathematical Sans-Serif Capital V
    U+1D5B6𝖶\sansWMathematical Sans-Serif Capital W
    U+1D5B7𝖷\sansXMathematical Sans-Serif Capital X
    U+1D5B8𝖸\sansYMathematical Sans-Serif Capital Y
    U+1D5B9𝖹\sansZMathematical Sans-Serif Capital Z
    U+1D5BA𝖺\sansaMathematical Sans-Serif Small A
    U+1D5BB𝖻\sansbMathematical Sans-Serif Small B
    U+1D5BC𝖼\sanscMathematical Sans-Serif Small C
    U+1D5BD𝖽\sansdMathematical Sans-Serif Small D
    U+1D5BE𝖾\sanseMathematical Sans-Serif Small E
    U+1D5BF𝖿\sansfMathematical Sans-Serif Small F
    U+1D5C0𝗀\sansgMathematical Sans-Serif Small G
    U+1D5C1𝗁\sanshMathematical Sans-Serif Small H
    U+1D5C2𝗂\sansiMathematical Sans-Serif Small I
    U+1D5C3𝗃\sansjMathematical Sans-Serif Small J
    U+1D5C4𝗄\sanskMathematical Sans-Serif Small K
    U+1D5C5𝗅\sanslMathematical Sans-Serif Small L
    U+1D5C6𝗆\sansmMathematical Sans-Serif Small M
    U+1D5C7𝗇\sansnMathematical Sans-Serif Small N
    U+1D5C8𝗈\sansoMathematical Sans-Serif Small O
    U+1D5C9𝗉\sanspMathematical Sans-Serif Small P
    U+1D5CA𝗊\sansqMathematical Sans-Serif Small Q
    U+1D5CB𝗋\sansrMathematical Sans-Serif Small R
    U+1D5CC𝗌\sanssMathematical Sans-Serif Small S
    U+1D5CD𝗍\sanstMathematical Sans-Serif Small T
    U+1D5CE𝗎\sansuMathematical Sans-Serif Small U
    U+1D5CF𝗏\sansvMathematical Sans-Serif Small V
    U+1D5D0𝗐\sanswMathematical Sans-Serif Small W
    U+1D5D1𝗑\sansxMathematical Sans-Serif Small X
    U+1D5D2𝗒\sansyMathematical Sans-Serif Small Y
    U+1D5D3𝗓\sanszMathematical Sans-Serif Small Z
    U+1D5D4𝗔\bsansAMathematical Sans-Serif Bold Capital A
    U+1D5D5𝗕\bsansBMathematical Sans-Serif Bold Capital B
    U+1D5D6𝗖\bsansCMathematical Sans-Serif Bold Capital C
    U+1D5D7𝗗\bsansDMathematical Sans-Serif Bold Capital D
    U+1D5D8𝗘\bsansEMathematical Sans-Serif Bold Capital E
    U+1D5D9𝗙\bsansFMathematical Sans-Serif Bold Capital F
    U+1D5DA𝗚\bsansGMathematical Sans-Serif Bold Capital G
    U+1D5DB𝗛\bsansHMathematical Sans-Serif Bold Capital H
    U+1D5DC𝗜\bsansIMathematical Sans-Serif Bold Capital I
    U+1D5DD𝗝\bsansJMathematical Sans-Serif Bold Capital J
    U+1D5DE𝗞\bsansKMathematical Sans-Serif Bold Capital K
    U+1D5DF𝗟\bsansLMathematical Sans-Serif Bold Capital L
    U+1D5E0𝗠\bsansMMathematical Sans-Serif Bold Capital M
    U+1D5E1𝗡\bsansNMathematical Sans-Serif Bold Capital N
    U+1D5E2𝗢\bsansOMathematical Sans-Serif Bold Capital O
    U+1D5E3𝗣\bsansPMathematical Sans-Serif Bold Capital P
    U+1D5E4𝗤\bsansQMathematical Sans-Serif Bold Capital Q
    U+1D5E5𝗥\bsansRMathematical Sans-Serif Bold Capital R
    U+1D5E6𝗦\bsansSMathematical Sans-Serif Bold Capital S
    U+1D5E7𝗧\bsansTMathematical Sans-Serif Bold Capital T
    U+1D5E8𝗨\bsansUMathematical Sans-Serif Bold Capital U
    U+1D5E9𝗩\bsansVMathematical Sans-Serif Bold Capital V
    U+1D5EA𝗪\bsansWMathematical Sans-Serif Bold Capital W
    U+1D5EB𝗫\bsansXMathematical Sans-Serif Bold Capital X
    U+1D5EC𝗬\bsansYMathematical Sans-Serif Bold Capital Y
    U+1D5ED𝗭\bsansZMathematical Sans-Serif Bold Capital Z
    U+1D5EE𝗮\bsansaMathematical Sans-Serif Bold Small A
    U+1D5EF𝗯\bsansbMathematical Sans-Serif Bold Small B
    U+1D5F0𝗰\bsanscMathematical Sans-Serif Bold Small C
    U+1D5F1𝗱\bsansdMathematical Sans-Serif Bold Small D
    U+1D5F2𝗲\bsanseMathematical Sans-Serif Bold Small E
    U+1D5F3𝗳\bsansfMathematical Sans-Serif Bold Small F
    U+1D5F4𝗴\bsansgMathematical Sans-Serif Bold Small G
    U+1D5F5𝗵\bsanshMathematical Sans-Serif Bold Small H
    U+1D5F6𝗶\bsansiMathematical Sans-Serif Bold Small I
    U+1D5F7𝗷\bsansjMathematical Sans-Serif Bold Small J
    U+1D5F8𝗸\bsanskMathematical Sans-Serif Bold Small K
    U+1D5F9𝗹\bsanslMathematical Sans-Serif Bold Small L
    U+1D5FA𝗺\bsansmMathematical Sans-Serif Bold Small M
    U+1D5FB𝗻\bsansnMathematical Sans-Serif Bold Small N
    U+1D5FC𝗼\bsansoMathematical Sans-Serif Bold Small O
    U+1D5FD𝗽\bsanspMathematical Sans-Serif Bold Small P
    U+1D5FE𝗾\bsansqMathematical Sans-Serif Bold Small Q
    U+1D5FF𝗿\bsansrMathematical Sans-Serif Bold Small R
    U+1D600𝘀\bsanssMathematical Sans-Serif Bold Small S
    U+1D601𝘁\bsanstMathematical Sans-Serif Bold Small T
    U+1D602𝘂\bsansuMathematical Sans-Serif Bold Small U
    U+1D603𝘃\bsansvMathematical Sans-Serif Bold Small V
    U+1D604𝘄\bsanswMathematical Sans-Serif Bold Small W
    U+1D605𝘅\bsansxMathematical Sans-Serif Bold Small X
    U+1D606𝘆\bsansyMathematical Sans-Serif Bold Small Y
    U+1D607𝘇\bsanszMathematical Sans-Serif Bold Small Z
    U+1D608𝘈\isansAMathematical Sans-Serif Italic Capital A
    U+1D609𝘉\isansBMathematical Sans-Serif Italic Capital B
    U+1D60A𝘊\isansCMathematical Sans-Serif Italic Capital C
    U+1D60B𝘋\isansDMathematical Sans-Serif Italic Capital D
    U+1D60C𝘌\isansEMathematical Sans-Serif Italic Capital E
    U+1D60D𝘍\isansFMathematical Sans-Serif Italic Capital F
    U+1D60E𝘎\isansGMathematical Sans-Serif Italic Capital G
    U+1D60F𝘏\isansHMathematical Sans-Serif Italic Capital H
    U+1D610𝘐\isansIMathematical Sans-Serif Italic Capital I
    U+1D611𝘑\isansJMathematical Sans-Serif Italic Capital J
    U+1D612𝘒\isansKMathematical Sans-Serif Italic Capital K
    U+1D613𝘓\isansLMathematical Sans-Serif Italic Capital L
    U+1D614𝘔\isansMMathematical Sans-Serif Italic Capital M
    U+1D615𝘕\isansNMathematical Sans-Serif Italic Capital N
    U+1D616𝘖\isansOMathematical Sans-Serif Italic Capital O
    U+1D617𝘗\isansPMathematical Sans-Serif Italic Capital P
    U+1D618𝘘\isansQMathematical Sans-Serif Italic Capital Q
    U+1D619𝘙\isansRMathematical Sans-Serif Italic Capital R
    U+1D61A𝘚\isansSMathematical Sans-Serif Italic Capital S
    U+1D61B𝘛\isansTMathematical Sans-Serif Italic Capital T
    U+1D61C𝘜\isansUMathematical Sans-Serif Italic Capital U
    U+1D61D𝘝\isansVMathematical Sans-Serif Italic Capital V
    U+1D61E𝘞\isansWMathematical Sans-Serif Italic Capital W
    U+1D61F𝘟\isansXMathematical Sans-Serif Italic Capital X
    U+1D620𝘠\isansYMathematical Sans-Serif Italic Capital Y
    U+1D621𝘡\isansZMathematical Sans-Serif Italic Capital Z
    U+1D622𝘢\isansaMathematical Sans-Serif Italic Small A
    U+1D623𝘣\isansbMathematical Sans-Serif Italic Small B
    U+1D624𝘤\isanscMathematical Sans-Serif Italic Small C
    U+1D625𝘥\isansdMathematical Sans-Serif Italic Small D
    U+1D626𝘦\isanseMathematical Sans-Serif Italic Small E
    U+1D627𝘧\isansfMathematical Sans-Serif Italic Small F
    U+1D628𝘨\isansgMathematical Sans-Serif Italic Small G
    U+1D629𝘩\isanshMathematical Sans-Serif Italic Small H
    U+1D62A𝘪\isansiMathematical Sans-Serif Italic Small I
    U+1D62B𝘫\isansjMathematical Sans-Serif Italic Small J
    U+1D62C𝘬\isanskMathematical Sans-Serif Italic Small K
    U+1D62D𝘭\isanslMathematical Sans-Serif Italic Small L
    U+1D62E𝘮\isansmMathematical Sans-Serif Italic Small M
    U+1D62F𝘯\isansnMathematical Sans-Serif Italic Small N
    U+1D630𝘰\isansoMathematical Sans-Serif Italic Small O
    U+1D631𝘱\isanspMathematical Sans-Serif Italic Small P
    U+1D632𝘲\isansqMathematical Sans-Serif Italic Small Q
    U+1D633𝘳\isansrMathematical Sans-Serif Italic Small R
    U+1D634𝘴\isanssMathematical Sans-Serif Italic Small S
    U+1D635𝘵\isanstMathematical Sans-Serif Italic Small T
    U+1D636𝘶\isansuMathematical Sans-Serif Italic Small U
    U+1D637𝘷\isansvMathematical Sans-Serif Italic Small V
    U+1D638𝘸\isanswMathematical Sans-Serif Italic Small W
    U+1D639𝘹\isansxMathematical Sans-Serif Italic Small X
    U+1D63A𝘺\isansyMathematical Sans-Serif Italic Small Y
    U+1D63B𝘻\isanszMathematical Sans-Serif Italic Small Z
    U+1D63C𝘼\bisansAMathematical Sans-Serif Bold Italic Capital A
    U+1D63D𝘽\bisansBMathematical Sans-Serif Bold Italic Capital B
    U+1D63E𝘾\bisansCMathematical Sans-Serif Bold Italic Capital C
    U+1D63F𝘿\bisansDMathematical Sans-Serif Bold Italic Capital D
    U+1D640𝙀\bisansEMathematical Sans-Serif Bold Italic Capital E
    U+1D641𝙁\bisansFMathematical Sans-Serif Bold Italic Capital F
    U+1D642𝙂\bisansGMathematical Sans-Serif Bold Italic Capital G
    U+1D643𝙃\bisansHMathematical Sans-Serif Bold Italic Capital H
    U+1D644𝙄\bisansIMathematical Sans-Serif Bold Italic Capital I
    U+1D645𝙅\bisansJMathematical Sans-Serif Bold Italic Capital J
    U+1D646𝙆\bisansKMathematical Sans-Serif Bold Italic Capital K
    U+1D647𝙇\bisansLMathematical Sans-Serif Bold Italic Capital L
    U+1D648𝙈\bisansMMathematical Sans-Serif Bold Italic Capital M
    U+1D649𝙉\bisansNMathematical Sans-Serif Bold Italic Capital N
    U+1D64A𝙊\bisansOMathematical Sans-Serif Bold Italic Capital O
    U+1D64B𝙋\bisansPMathematical Sans-Serif Bold Italic Capital P
    U+1D64C𝙌\bisansQMathematical Sans-Serif Bold Italic Capital Q
    U+1D64D𝙍\bisansRMathematical Sans-Serif Bold Italic Capital R
    U+1D64E𝙎\bisansSMathematical Sans-Serif Bold Italic Capital S
    U+1D64F𝙏\bisansTMathematical Sans-Serif Bold Italic Capital T
    U+1D650𝙐\bisansUMathematical Sans-Serif Bold Italic Capital U
    U+1D651𝙑\bisansVMathematical Sans-Serif Bold Italic Capital V
    U+1D652𝙒\bisansWMathematical Sans-Serif Bold Italic Capital W
    U+1D653𝙓\bisansXMathematical Sans-Serif Bold Italic Capital X
    U+1D654𝙔\bisansYMathematical Sans-Serif Bold Italic Capital Y
    U+1D655𝙕\bisansZMathematical Sans-Serif Bold Italic Capital Z
    U+1D656𝙖\bisansaMathematical Sans-Serif Bold Italic Small A
    U+1D657𝙗\bisansbMathematical Sans-Serif Bold Italic Small B
    U+1D658𝙘\bisanscMathematical Sans-Serif Bold Italic Small C
    U+1D659𝙙\bisansdMathematical Sans-Serif Bold Italic Small D
    U+1D65A𝙚\bisanseMathematical Sans-Serif Bold Italic Small E
    U+1D65B𝙛\bisansfMathematical Sans-Serif Bold Italic Small F
    U+1D65C𝙜\bisansgMathematical Sans-Serif Bold Italic Small G
    U+1D65D𝙝\bisanshMathematical Sans-Serif Bold Italic Small H
    U+1D65E𝙞\bisansiMathematical Sans-Serif Bold Italic Small I
    U+1D65F𝙟\bisansjMathematical Sans-Serif Bold Italic Small J
    U+1D660𝙠\bisanskMathematical Sans-Serif Bold Italic Small K
    U+1D661𝙡\bisanslMathematical Sans-Serif Bold Italic Small L
    U+1D662𝙢\bisansmMathematical Sans-Serif Bold Italic Small M
    U+1D663𝙣\bisansnMathematical Sans-Serif Bold Italic Small N
    U+1D664𝙤\bisansoMathematical Sans-Serif Bold Italic Small O
    U+1D665𝙥\bisanspMathematical Sans-Serif Bold Italic Small P
    U+1D666𝙦\bisansqMathematical Sans-Serif Bold Italic Small Q
    U+1D667𝙧\bisansrMathematical Sans-Serif Bold Italic Small R
    U+1D668𝙨\bisanssMathematical Sans-Serif Bold Italic Small S
    U+1D669𝙩\bisanstMathematical Sans-Serif Bold Italic Small T
    U+1D66A𝙪\bisansuMathematical Sans-Serif Bold Italic Small U
    U+1D66B𝙫\bisansvMathematical Sans-Serif Bold Italic Small V
    U+1D66C𝙬\bisanswMathematical Sans-Serif Bold Italic Small W
    U+1D66D𝙭\bisansxMathematical Sans-Serif Bold Italic Small X
    U+1D66E𝙮\bisansyMathematical Sans-Serif Bold Italic Small Y
    U+1D66F𝙯\bisanszMathematical Sans-Serif Bold Italic Small Z
    U+1D670𝙰\ttAMathematical Monospace Capital A
    U+1D671𝙱\ttBMathematical Monospace Capital B
    U+1D672𝙲\ttCMathematical Monospace Capital C
    U+1D673𝙳\ttDMathematical Monospace Capital D
    U+1D674𝙴\ttEMathematical Monospace Capital E
    U+1D675𝙵\ttFMathematical Monospace Capital F
    U+1D676𝙶\ttGMathematical Monospace Capital G
    U+1D677𝙷\ttHMathematical Monospace Capital H
    U+1D678𝙸\ttIMathematical Monospace Capital I
    U+1D679𝙹\ttJMathematical Monospace Capital J
    U+1D67A𝙺\ttKMathematical Monospace Capital K
    U+1D67B𝙻\ttLMathematical Monospace Capital L
    U+1D67C𝙼\ttMMathematical Monospace Capital M
    U+1D67D𝙽\ttNMathematical Monospace Capital N
    U+1D67E𝙾\ttOMathematical Monospace Capital O
    U+1D67F𝙿\ttPMathematical Monospace Capital P
    U+1D680𝚀\ttQMathematical Monospace Capital Q
    U+1D681𝚁\ttRMathematical Monospace Capital R
    U+1D682𝚂\ttSMathematical Monospace Capital S
    U+1D683𝚃\ttTMathematical Monospace Capital T
    U+1D684𝚄\ttUMathematical Monospace Capital U
    U+1D685𝚅\ttVMathematical Monospace Capital V
    U+1D686𝚆\ttWMathematical Monospace Capital W
    U+1D687𝚇\ttXMathematical Monospace Capital X
    U+1D688𝚈\ttYMathematical Monospace Capital Y
    U+1D689𝚉\ttZMathematical Monospace Capital Z
    U+1D68A𝚊\ttaMathematical Monospace Small A
    U+1D68B𝚋\ttbMathematical Monospace Small B
    U+1D68C𝚌\ttcMathematical Monospace Small C
    U+1D68D𝚍\ttdMathematical Monospace Small D
    U+1D68E𝚎\tteMathematical Monospace Small E
    U+1D68F𝚏\ttfMathematical Monospace Small F
    U+1D690𝚐\ttgMathematical Monospace Small G
    U+1D691𝚑\tthMathematical Monospace Small H
    U+1D692𝚒\ttiMathematical Monospace Small I
    U+1D693𝚓\ttjMathematical Monospace Small J
    U+1D694𝚔\ttkMathematical Monospace Small K
    U+1D695𝚕\ttlMathematical Monospace Small L
    U+1D696𝚖\ttmMathematical Monospace Small M
    U+1D697𝚗\ttnMathematical Monospace Small N
    U+1D698𝚘\ttoMathematical Monospace Small O
    U+1D699𝚙\ttpMathematical Monospace Small P
    U+1D69A𝚚\ttqMathematical Monospace Small Q
    U+1D69B𝚛\ttrMathematical Monospace Small R
    U+1D69C𝚜\ttsMathematical Monospace Small S
    U+1D69D𝚝\tttMathematical Monospace Small T
    U+1D69E𝚞\ttuMathematical Monospace Small U
    U+1D69F𝚟\ttvMathematical Monospace Small V
    U+1D6A0𝚠\ttwMathematical Monospace Small W
    U+1D6A1𝚡\ttxMathematical Monospace Small X
    U+1D6A2𝚢\ttyMathematical Monospace Small Y
    U+1D6A3𝚣\ttzMathematical Monospace Small Z
    U+1D6A4𝚤\itimathMathematical Italic Small Dotless I
    U+1D6A5𝚥\itjmathMathematical Italic Small Dotless J
    U+1D6A8𝚨\bfAlphaMathematical Bold Capital Alpha
    U+1D6A9𝚩\bfBetaMathematical Bold Capital Beta
    U+1D6AA𝚪\bfGammaMathematical Bold Capital Gamma
    U+1D6AB𝚫\bfDeltaMathematical Bold Capital Delta
    U+1D6AC𝚬\bfEpsilonMathematical Bold Capital Epsilon
    U+1D6AD𝚭\bfZetaMathematical Bold Capital Zeta
    U+1D6AE𝚮\bfEtaMathematical Bold Capital Eta
    U+1D6AF𝚯\bfThetaMathematical Bold Capital Theta
    U+1D6B0𝚰\bfIotaMathematical Bold Capital Iota
    U+1D6B1𝚱\bfKappaMathematical Bold Capital Kappa
    U+1D6B2𝚲\bfLambdaMathematical Bold Capital Lamda
    U+1D6B3𝚳\bfMuMathematical Bold Capital Mu
    U+1D6B4𝚴\bfNuMathematical Bold Capital Nu
    U+1D6B5𝚵\bfXiMathematical Bold Capital Xi
    U+1D6B6𝚶\bfOmicronMathematical Bold Capital Omicron
    U+1D6B7𝚷\bfPiMathematical Bold Capital Pi
    U+1D6B8𝚸\bfRhoMathematical Bold Capital Rho
    U+1D6B9𝚹\bfvarThetaMathematical Bold Capital Theta Symbol
    U+1D6BA𝚺\bfSigmaMathematical Bold Capital Sigma
    U+1D6BB𝚻\bfTauMathematical Bold Capital Tau
    U+1D6BC𝚼\bfUpsilonMathematical Bold Capital Upsilon
    U+1D6BD𝚽\bfPhiMathematical Bold Capital Phi
    U+1D6BE𝚾\bfChiMathematical Bold Capital Chi
    U+1D6BF𝚿\bfPsiMathematical Bold Capital Psi
    U+1D6C0𝛀\bfOmegaMathematical Bold Capital Omega
    U+1D6C1𝛁\bfnablaMathematical Bold Nabla
    U+1D6C2𝛂\bfalphaMathematical Bold Small Alpha
    U+1D6C3𝛃\bfbetaMathematical Bold Small Beta
    U+1D6C4𝛄\bfgammaMathematical Bold Small Gamma
    U+1D6C5𝛅\bfdeltaMathematical Bold Small Delta
    U+1D6C6𝛆\bfvarepsilonMathematical Bold Small Epsilon
    U+1D6C7𝛇\bfzetaMathematical Bold Small Zeta
    U+1D6C8𝛈\bfetaMathematical Bold Small Eta
    U+1D6C9𝛉\bfthetaMathematical Bold Small Theta
    U+1D6CA𝛊\bfiotaMathematical Bold Small Iota
    U+1D6CB𝛋\bfkappaMathematical Bold Small Kappa
    U+1D6CC𝛌\bflambdaMathematical Bold Small Lamda
    U+1D6CD𝛍\bfmuMathematical Bold Small Mu
    U+1D6CE𝛎\bfnuMathematical Bold Small Nu
    U+1D6CF𝛏\bfxiMathematical Bold Small Xi
    U+1D6D0𝛐\bfomicronMathematical Bold Small Omicron
    U+1D6D1𝛑\bfpiMathematical Bold Small Pi
    U+1D6D2𝛒\bfrhoMathematical Bold Small Rho
    U+1D6D3𝛓\bfvarsigmaMathematical Bold Small Final Sigma
    U+1D6D4𝛔\bfsigmaMathematical Bold Small Sigma
    U+1D6D5𝛕\bftauMathematical Bold Small Tau
    U+1D6D6𝛖\bfupsilonMathematical Bold Small Upsilon
    U+1D6D7𝛗\bfvarphiMathematical Bold Small Phi
    U+1D6D8𝛘\bfchiMathematical Bold Small Chi
    U+1D6D9𝛙\bfpsiMathematical Bold Small Psi
    U+1D6DA𝛚\bfomegaMathematical Bold Small Omega
    U+1D6DB𝛛\bfpartialMathematical Bold Partial Differential
    U+1D6DC𝛜\bfepsilonMathematical Bold Epsilon Symbol
    U+1D6DD𝛝\bfvarthetaMathematical Bold Theta Symbol
    U+1D6DE𝛞\bfvarkappaMathematical Bold Kappa Symbol
    U+1D6DF𝛟\bfphiMathematical Bold Phi Symbol
    U+1D6E0𝛠\bfvarrhoMathematical Bold Rho Symbol
    U+1D6E1𝛡\bfvarpiMathematical Bold Pi Symbol
    U+1D6E2𝛢\itAlphaMathematical Italic Capital Alpha
    U+1D6E3𝛣\itBetaMathematical Italic Capital Beta
    U+1D6E4𝛤\itGammaMathematical Italic Capital Gamma
    U+1D6E5𝛥\itDeltaMathematical Italic Capital Delta
    U+1D6E6𝛦\itEpsilonMathematical Italic Capital Epsilon
    U+1D6E7𝛧\itZetaMathematical Italic Capital Zeta
    U+1D6E8𝛨\itEtaMathematical Italic Capital Eta
    U+1D6E9𝛩\itThetaMathematical Italic Capital Theta
    U+1D6EA𝛪\itIotaMathematical Italic Capital Iota
    U+1D6EB𝛫\itKappaMathematical Italic Capital Kappa
    U+1D6EC𝛬\itLambdaMathematical Italic Capital Lamda
    U+1D6ED𝛭\itMuMathematical Italic Capital Mu
    U+1D6EE𝛮\itNuMathematical Italic Capital Nu
    U+1D6EF𝛯\itXiMathematical Italic Capital Xi
    U+1D6F0𝛰\itOmicronMathematical Italic Capital Omicron
    U+1D6F1𝛱\itPiMathematical Italic Capital Pi
    U+1D6F2𝛲\itRhoMathematical Italic Capital Rho
    U+1D6F3𝛳\itvarThetaMathematical Italic Capital Theta Symbol
    U+1D6F4𝛴\itSigmaMathematical Italic Capital Sigma
    U+1D6F5𝛵\itTauMathematical Italic Capital Tau
    U+1D6F6𝛶\itUpsilonMathematical Italic Capital Upsilon
    U+1D6F7𝛷\itPhiMathematical Italic Capital Phi
    U+1D6F8𝛸\itChiMathematical Italic Capital Chi
    U+1D6F9𝛹\itPsiMathematical Italic Capital Psi
    U+1D6FA𝛺\itOmegaMathematical Italic Capital Omega
    U+1D6FB𝛻\itnablaMathematical Italic Nabla
    U+1D6FC𝛼\italphaMathematical Italic Small Alpha
    U+1D6FD𝛽\itbetaMathematical Italic Small Beta
    U+1D6FE𝛾\itgammaMathematical Italic Small Gamma
    U+1D6FF𝛿\itdeltaMathematical Italic Small Delta
    U+1D700𝜀\itvarepsilonMathematical Italic Small Epsilon
    U+1D701𝜁\itzetaMathematical Italic Small Zeta
    U+1D702𝜂\itetaMathematical Italic Small Eta
    U+1D703𝜃\itthetaMathematical Italic Small Theta
    U+1D704𝜄\itiotaMathematical Italic Small Iota
    U+1D705𝜅\itkappaMathematical Italic Small Kappa
    U+1D706𝜆\itlambdaMathematical Italic Small Lamda
    U+1D707𝜇\itmuMathematical Italic Small Mu
    U+1D708𝜈\itnuMathematical Italic Small Nu
    U+1D709𝜉\itxiMathematical Italic Small Xi
    U+1D70A𝜊\itomicronMathematical Italic Small Omicron
    U+1D70B𝜋\itpiMathematical Italic Small Pi
    U+1D70C𝜌\itrhoMathematical Italic Small Rho
    U+1D70D𝜍\itvarsigmaMathematical Italic Small Final Sigma
    U+1D70E𝜎\itsigmaMathematical Italic Small Sigma
    U+1D70F𝜏\ittauMathematical Italic Small Tau
    U+1D710𝜐\itupsilonMathematical Italic Small Upsilon
    U+1D711𝜑\itvarphiMathematical Italic Small Phi
    U+1D712𝜒\itchiMathematical Italic Small Chi
    U+1D713𝜓\itpsiMathematical Italic Small Psi
    U+1D714𝜔\itomegaMathematical Italic Small Omega
    U+1D715𝜕\itpartialMathematical Italic Partial Differential
    U+1D716𝜖\itepsilonMathematical Italic Epsilon Symbol
    U+1D717𝜗\itvarthetaMathematical Italic Theta Symbol
    U+1D718𝜘\itvarkappaMathematical Italic Kappa Symbol
    U+1D719𝜙\itphiMathematical Italic Phi Symbol
    U+1D71A𝜚\itvarrhoMathematical Italic Rho Symbol
    U+1D71B𝜛\itvarpiMathematical Italic Pi Symbol
    U+1D71C𝜜\biAlphaMathematical Bold Italic Capital Alpha
    U+1D71D𝜝\biBetaMathematical Bold Italic Capital Beta
    U+1D71E𝜞\biGammaMathematical Bold Italic Capital Gamma
    U+1D71F𝜟\biDeltaMathematical Bold Italic Capital Delta
    U+1D720𝜠\biEpsilonMathematical Bold Italic Capital Epsilon
    U+1D721𝜡\biZetaMathematical Bold Italic Capital Zeta
    U+1D722𝜢\biEtaMathematical Bold Italic Capital Eta
    U+1D723𝜣\biThetaMathematical Bold Italic Capital Theta
    U+1D724𝜤\biIotaMathematical Bold Italic Capital Iota
    U+1D725𝜥\biKappaMathematical Bold Italic Capital Kappa
    U+1D726𝜦\biLambdaMathematical Bold Italic Capital Lamda
    U+1D727𝜧\biMuMathematical Bold Italic Capital Mu
    U+1D728𝜨\biNuMathematical Bold Italic Capital Nu
    U+1D729𝜩\biXiMathematical Bold Italic Capital Xi
    U+1D72A𝜪\biOmicronMathematical Bold Italic Capital Omicron
    U+1D72B𝜫\biPiMathematical Bold Italic Capital Pi
    U+1D72C𝜬\biRhoMathematical Bold Italic Capital Rho
    U+1D72D𝜭\bivarThetaMathematical Bold Italic Capital Theta Symbol
    U+1D72E𝜮\biSigmaMathematical Bold Italic Capital Sigma
    U+1D72F𝜯\biTauMathematical Bold Italic Capital Tau
    U+1D730𝜰\biUpsilonMathematical Bold Italic Capital Upsilon
    U+1D731𝜱\biPhiMathematical Bold Italic Capital Phi
    U+1D732𝜲\biChiMathematical Bold Italic Capital Chi
    U+1D733𝜳\biPsiMathematical Bold Italic Capital Psi
    U+1D734𝜴\biOmegaMathematical Bold Italic Capital Omega
    U+1D735𝜵\binablaMathematical Bold Italic Nabla
    U+1D736𝜶\bialphaMathematical Bold Italic Small Alpha
    U+1D737𝜷\bibetaMathematical Bold Italic Small Beta
    U+1D738𝜸\bigammaMathematical Bold Italic Small Gamma
    U+1D739𝜹\bideltaMathematical Bold Italic Small Delta
    U+1D73A𝜺\bivarepsilonMathematical Bold Italic Small Epsilon
    U+1D73B𝜻\bizetaMathematical Bold Italic Small Zeta
    U+1D73C𝜼\bietaMathematical Bold Italic Small Eta
    U+1D73D𝜽\bithetaMathematical Bold Italic Small Theta
    U+1D73E𝜾\biiotaMathematical Bold Italic Small Iota
    U+1D73F𝜿\bikappaMathematical Bold Italic Small Kappa
    U+1D740𝝀\bilambdaMathematical Bold Italic Small Lamda
    U+1D741𝝁\bimuMathematical Bold Italic Small Mu
    U+1D742𝝂\binuMathematical Bold Italic Small Nu
    U+1D743𝝃\bixiMathematical Bold Italic Small Xi
    U+1D744𝝄\biomicronMathematical Bold Italic Small Omicron
    U+1D745𝝅\bipiMathematical Bold Italic Small Pi
    U+1D746𝝆\birhoMathematical Bold Italic Small Rho
    U+1D747𝝇\bivarsigmaMathematical Bold Italic Small Final Sigma
    U+1D748𝝈\bisigmaMathematical Bold Italic Small Sigma
    U+1D749𝝉\bitauMathematical Bold Italic Small Tau
    U+1D74A𝝊\biupsilonMathematical Bold Italic Small Upsilon
    U+1D74B𝝋\bivarphiMathematical Bold Italic Small Phi
    U+1D74C𝝌\bichiMathematical Bold Italic Small Chi
    U+1D74D𝝍\bipsiMathematical Bold Italic Small Psi
    U+1D74E𝝎\biomegaMathematical Bold Italic Small Omega
    U+1D74F𝝏\bipartialMathematical Bold Italic Partial Differential
    U+1D750𝝐\biepsilonMathematical Bold Italic Epsilon Symbol
    U+1D751𝝑\bivarthetaMathematical Bold Italic Theta Symbol
    U+1D752𝝒\bivarkappaMathematical Bold Italic Kappa Symbol
    U+1D753𝝓\biphiMathematical Bold Italic Phi Symbol
    U+1D754𝝔\bivarrhoMathematical Bold Italic Rho Symbol
    U+1D755𝝕\bivarpiMathematical Bold Italic Pi Symbol
    U+1D756𝝖\bsansAlphaMathematical Sans-Serif Bold Capital Alpha
    U+1D757𝝗\bsansBetaMathematical Sans-Serif Bold Capital Beta
    U+1D758𝝘\bsansGammaMathematical Sans-Serif Bold Capital Gamma
    U+1D759𝝙\bsansDeltaMathematical Sans-Serif Bold Capital Delta
    U+1D75A𝝚\bsansEpsilonMathematical Sans-Serif Bold Capital Epsilon
    U+1D75B𝝛\bsansZetaMathematical Sans-Serif Bold Capital Zeta
    U+1D75C𝝜\bsansEtaMathematical Sans-Serif Bold Capital Eta
    U+1D75D𝝝\bsansThetaMathematical Sans-Serif Bold Capital Theta
    U+1D75E𝝞\bsansIotaMathematical Sans-Serif Bold Capital Iota
    U+1D75F𝝟\bsansKappaMathematical Sans-Serif Bold Capital Kappa
    U+1D760𝝠\bsansLambdaMathematical Sans-Serif Bold Capital Lamda
    U+1D761𝝡\bsansMuMathematical Sans-Serif Bold Capital Mu
    U+1D762𝝢\bsansNuMathematical Sans-Serif Bold Capital Nu
    U+1D763𝝣\bsansXiMathematical Sans-Serif Bold Capital Xi
    U+1D764𝝤\bsansOmicronMathematical Sans-Serif Bold Capital Omicron
    U+1D765𝝥\bsansPiMathematical Sans-Serif Bold Capital Pi
    U+1D766𝝦\bsansRhoMathematical Sans-Serif Bold Capital Rho
    U+1D767𝝧\bsansvarThetaMathematical Sans-Serif Bold Capital Theta Symbol
    U+1D768𝝨\bsansSigmaMathematical Sans-Serif Bold Capital Sigma
    U+1D769𝝩\bsansTauMathematical Sans-Serif Bold Capital Tau
    U+1D76A𝝪\bsansUpsilonMathematical Sans-Serif Bold Capital Upsilon
    U+1D76B𝝫\bsansPhiMathematical Sans-Serif Bold Capital Phi
    U+1D76C𝝬\bsansChiMathematical Sans-Serif Bold Capital Chi
    U+1D76D𝝭\bsansPsiMathematical Sans-Serif Bold Capital Psi
    U+1D76E𝝮\bsansOmegaMathematical Sans-Serif Bold Capital Omega
    U+1D76F𝝯\bsansnablaMathematical Sans-Serif Bold Nabla
    U+1D770𝝰\bsansalphaMathematical Sans-Serif Bold Small Alpha
    U+1D771𝝱\bsansbetaMathematical Sans-Serif Bold Small Beta
    U+1D772𝝲\bsansgammaMathematical Sans-Serif Bold Small Gamma
    U+1D773𝝳\bsansdeltaMathematical Sans-Serif Bold Small Delta
    U+1D774𝝴\bsansvarepsilonMathematical Sans-Serif Bold Small Epsilon
    U+1D775𝝵\bsanszetaMathematical Sans-Serif Bold Small Zeta
    U+1D776𝝶\bsansetaMathematical Sans-Serif Bold Small Eta
    U+1D777𝝷\bsansthetaMathematical Sans-Serif Bold Small Theta
    U+1D778𝝸\bsansiotaMathematical Sans-Serif Bold Small Iota
    U+1D779𝝹\bsanskappaMathematical Sans-Serif Bold Small Kappa
    U+1D77A𝝺\bsanslambdaMathematical Sans-Serif Bold Small Lamda
    U+1D77B𝝻\bsansmuMathematical Sans-Serif Bold Small Mu
    U+1D77C𝝼\bsansnuMathematical Sans-Serif Bold Small Nu
    U+1D77D𝝽\bsansxiMathematical Sans-Serif Bold Small Xi
    U+1D77E𝝾\bsansomicronMathematical Sans-Serif Bold Small Omicron
    U+1D77F𝝿\bsanspiMathematical Sans-Serif Bold Small Pi
    U+1D780𝞀\bsansrhoMathematical Sans-Serif Bold Small Rho
    U+1D781𝞁\bsansvarsigmaMathematical Sans-Serif Bold Small Final Sigma
    U+1D782𝞂\bsanssigmaMathematical Sans-Serif Bold Small Sigma
    U+1D783𝞃\bsanstauMathematical Sans-Serif Bold Small Tau
    U+1D784𝞄\bsansupsilonMathematical Sans-Serif Bold Small Upsilon
    U+1D785𝞅\bsansvarphiMathematical Sans-Serif Bold Small Phi
    U+1D786𝞆\bsanschiMathematical Sans-Serif Bold Small Chi
    U+1D787𝞇\bsanspsiMathematical Sans-Serif Bold Small Psi
    U+1D788𝞈\bsansomegaMathematical Sans-Serif Bold Small Omega
    U+1D789𝞉\bsanspartialMathematical Sans-Serif Bold Partial Differential
    U+1D78A𝞊\bsansepsilonMathematical Sans-Serif Bold Epsilon Symbol
    U+1D78B𝞋\bsansvarthetaMathematical Sans-Serif Bold Theta Symbol
    U+1D78C𝞌\bsansvarkappaMathematical Sans-Serif Bold Kappa Symbol
    U+1D78D𝞍\bsansphiMathematical Sans-Serif Bold Phi Symbol
    U+1D78E𝞎\bsansvarrhoMathematical Sans-Serif Bold Rho Symbol
    U+1D78F𝞏\bsansvarpiMathematical Sans-Serif Bold Pi Symbol
    U+1D790𝞐\bisansAlphaMathematical Sans-Serif Bold Italic Capital Alpha
    U+1D791𝞑\bisansBetaMathematical Sans-Serif Bold Italic Capital Beta
    U+1D792𝞒\bisansGammaMathematical Sans-Serif Bold Italic Capital Gamma
    U+1D793𝞓\bisansDeltaMathematical Sans-Serif Bold Italic Capital Delta
    U+1D794𝞔\bisansEpsilonMathematical Sans-Serif Bold Italic Capital Epsilon
    U+1D795𝞕\bisansZetaMathematical Sans-Serif Bold Italic Capital Zeta
    U+1D796𝞖\bisansEtaMathematical Sans-Serif Bold Italic Capital Eta
    U+1D797𝞗\bisansThetaMathematical Sans-Serif Bold Italic Capital Theta
    U+1D798𝞘\bisansIotaMathematical Sans-Serif Bold Italic Capital Iota
    U+1D799𝞙\bisansKappaMathematical Sans-Serif Bold Italic Capital Kappa
    U+1D79A𝞚\bisansLambdaMathematical Sans-Serif Bold Italic Capital Lamda
    U+1D79B𝞛\bisansMuMathematical Sans-Serif Bold Italic Capital Mu
    U+1D79C𝞜\bisansNuMathematical Sans-Serif Bold Italic Capital Nu
    U+1D79D𝞝\bisansXiMathematical Sans-Serif Bold Italic Capital Xi
    U+1D79E𝞞\bisansOmicronMathematical Sans-Serif Bold Italic Capital Omicron
    U+1D79F𝞟\bisansPiMathematical Sans-Serif Bold Italic Capital Pi
    U+1D7A0𝞠\bisansRhoMathematical Sans-Serif Bold Italic Capital Rho
    U+1D7A1𝞡\bisansvarThetaMathematical Sans-Serif Bold Italic Capital Theta Symbol
    U+1D7A2𝞢\bisansSigmaMathematical Sans-Serif Bold Italic Capital Sigma
    U+1D7A3𝞣\bisansTauMathematical Sans-Serif Bold Italic Capital Tau
    U+1D7A4𝞤\bisansUpsilonMathematical Sans-Serif Bold Italic Capital Upsilon
    U+1D7A5𝞥\bisansPhiMathematical Sans-Serif Bold Italic Capital Phi
    U+1D7A6𝞦\bisansChiMathematical Sans-Serif Bold Italic Capital Chi
    U+1D7A7𝞧\bisansPsiMathematical Sans-Serif Bold Italic Capital Psi
    U+1D7A8𝞨\bisansOmegaMathematical Sans-Serif Bold Italic Capital Omega
    U+1D7A9𝞩\bisansnablaMathematical Sans-Serif Bold Italic Nabla
    U+1D7AA𝞪\bisansalphaMathematical Sans-Serif Bold Italic Small Alpha
    U+1D7AB𝞫\bisansbetaMathematical Sans-Serif Bold Italic Small Beta
    U+1D7AC𝞬\bisansgammaMathematical Sans-Serif Bold Italic Small Gamma
    U+1D7AD𝞭\bisansdeltaMathematical Sans-Serif Bold Italic Small Delta
    U+1D7AE𝞮\bisansvarepsilonMathematical Sans-Serif Bold Italic Small Epsilon
    U+1D7AF𝞯\bisanszetaMathematical Sans-Serif Bold Italic Small Zeta
    U+1D7B0𝞰\bisansetaMathematical Sans-Serif Bold Italic Small Eta
    U+1D7B1𝞱\bisansthetaMathematical Sans-Serif Bold Italic Small Theta
    U+1D7B2𝞲\bisansiotaMathematical Sans-Serif Bold Italic Small Iota
    U+1D7B3𝞳\bisanskappaMathematical Sans-Serif Bold Italic Small Kappa
    U+1D7B4𝞴\bisanslambdaMathematical Sans-Serif Bold Italic Small Lamda
    U+1D7B5𝞵\bisansmuMathematical Sans-Serif Bold Italic Small Mu
    U+1D7B6𝞶\bisansnuMathematical Sans-Serif Bold Italic Small Nu
    U+1D7B7𝞷\bisansxiMathematical Sans-Serif Bold Italic Small Xi
    U+1D7B8𝞸\bisansomicronMathematical Sans-Serif Bold Italic Small Omicron
    U+1D7B9𝞹\bisanspiMathematical Sans-Serif Bold Italic Small Pi
    U+1D7BA𝞺\bisansrhoMathematical Sans-Serif Bold Italic Small Rho
    U+1D7BB𝞻\bisansvarsigmaMathematical Sans-Serif Bold Italic Small Final Sigma
    U+1D7BC𝞼\bisanssigmaMathematical Sans-Serif Bold Italic Small Sigma
    U+1D7BD𝞽\bisanstauMathematical Sans-Serif Bold Italic Small Tau
    U+1D7BE𝞾\bisansupsilonMathematical Sans-Serif Bold Italic Small Upsilon
    U+1D7BF𝞿\bisansvarphiMathematical Sans-Serif Bold Italic Small Phi
    U+1D7C0𝟀\bisanschiMathematical Sans-Serif Bold Italic Small Chi
    U+1D7C1𝟁\bisanspsiMathematical Sans-Serif Bold Italic Small Psi
    U+1D7C2𝟂\bisansomegaMathematical Sans-Serif Bold Italic Small Omega
    U+1D7C3𝟃\bisanspartialMathematical Sans-Serif Bold Italic Partial Differential
    U+1D7C4𝟄\bisansepsilonMathematical Sans-Serif Bold Italic Epsilon Symbol
    U+1D7C5𝟅\bisansvarthetaMathematical Sans-Serif Bold Italic Theta Symbol
    U+1D7C6𝟆\bisansvarkappaMathematical Sans-Serif Bold Italic Kappa Symbol
    U+1D7C7𝟇\bisansphiMathematical Sans-Serif Bold Italic Phi Symbol
    U+1D7C8𝟈\bisansvarrhoMathematical Sans-Serif Bold Italic Rho Symbol
    U+1D7C9𝟉\bisansvarpiMathematical Sans-Serif Bold Italic Pi Symbol
    U+1D7CA𝟊\bfDigammaMathematical Bold Capital Digamma
    U+1D7CB𝟋\bfdigammaMathematical Bold Small Digamma
    U+1D7CE𝟎\bfzeroMathematical Bold Digit Zero
    U+1D7CF𝟏\bfoneMathematical Bold Digit One
    U+1D7D0𝟐\bftwoMathematical Bold Digit Two
    U+1D7D1𝟑\bfthreeMathematical Bold Digit Three
    U+1D7D2𝟒\bffourMathematical Bold Digit Four
    U+1D7D3𝟓\bffiveMathematical Bold Digit Five
    U+1D7D4𝟔\bfsixMathematical Bold Digit Six
    U+1D7D5𝟕\bfsevenMathematical Bold Digit Seven
    U+1D7D6𝟖\bfeightMathematical Bold Digit Eight
    U+1D7D7𝟗\bfnineMathematical Bold Digit Nine
    U+1D7D8𝟘\bbzeroMathematical Double-Struck Digit Zero
    U+1D7D9𝟙\bboneMathematical Double-Struck Digit One
    U+1D7DA𝟚\bbtwoMathematical Double-Struck Digit Two
    U+1D7DB𝟛\bbthreeMathematical Double-Struck Digit Three
    U+1D7DC𝟜\bbfourMathematical Double-Struck Digit Four
    U+1D7DD𝟝\bbfiveMathematical Double-Struck Digit Five
    U+1D7DE𝟞\bbsixMathematical Double-Struck Digit Six
    U+1D7DF𝟟\bbsevenMathematical Double-Struck Digit Seven
    U+1D7E0𝟠\bbeightMathematical Double-Struck Digit Eight
    U+1D7E1𝟡\bbnineMathematical Double-Struck Digit Nine
    U+1D7E2𝟢\sanszeroMathematical Sans-Serif Digit Zero
    U+1D7E3𝟣\sansoneMathematical Sans-Serif Digit One
    U+1D7E4𝟤\sanstwoMathematical Sans-Serif Digit Two
    U+1D7E5𝟥\sansthreeMathematical Sans-Serif Digit Three
    U+1D7E6𝟦\sansfourMathematical Sans-Serif Digit Four
    U+1D7E7𝟧\sansfiveMathematical Sans-Serif Digit Five
    U+1D7E8𝟨\sanssixMathematical Sans-Serif Digit Six
    U+1D7E9𝟩\sanssevenMathematical Sans-Serif Digit Seven
    U+1D7EA𝟪\sanseightMathematical Sans-Serif Digit Eight
    U+1D7EB𝟫\sansnineMathematical Sans-Serif Digit Nine
    U+1D7EC𝟬\bsanszeroMathematical Sans-Serif Bold Digit Zero
    U+1D7ED𝟭\bsansoneMathematical Sans-Serif Bold Digit One
    U+1D7EE𝟮\bsanstwoMathematical Sans-Serif Bold Digit Two
    U+1D7EF𝟯\bsansthreeMathematical Sans-Serif Bold Digit Three
    U+1D7F0𝟰\bsansfourMathematical Sans-Serif Bold Digit Four
    U+1D7F1𝟱\bsansfiveMathematical Sans-Serif Bold Digit Five
    U+1D7F2𝟲\bsanssixMathematical Sans-Serif Bold Digit Six
    U+1D7F3𝟳\bsanssevenMathematical Sans-Serif Bold Digit Seven
    U+1D7F4𝟴\bsanseightMathematical Sans-Serif Bold Digit Eight
    U+1D7F5𝟵\bsansnineMathematical Sans-Serif Bold Digit Nine
    U+1D7F6𝟶\ttzeroMathematical Monospace Digit Zero
    U+1D7F7𝟷\ttoneMathematical Monospace Digit One
    U+1D7F8𝟸\tttwoMathematical Monospace Digit Two
    U+1D7F9𝟹\ttthreeMathematical Monospace Digit Three
    U+1D7FA𝟺\ttfourMathematical Monospace Digit Four
    U+1D7FB𝟻\ttfiveMathematical Monospace Digit Five
    U+1D7FC𝟼\ttsixMathematical Monospace Digit Six
    U+1D7FD𝟽\ttsevenMathematical Monospace Digit Seven
    U+1D7FE𝟾\tteightMathematical Monospace Digit Eight
    U+1D7FF𝟿\ttnineMathematical Monospace Digit Nine
    U+1F004🀄\:mahjong:Mahjong Tile Red Dragon
    U+1F0CF🃏\:black_joker:Playing Card Black Joker
    U+1F170🅰\:a:Negative Squared Latin Capital Letter A
    U+1F171🅱\:b:Negative Squared Latin Capital Letter B
    U+1F17E🅾\:o2:Negative Squared Latin Capital Letter O
    U+1F17F🅿\:parking:Negative Squared Latin Capital Letter P
    U+1F18E🆎\:ab:Negative Squared Ab
    U+1F191🆑\:cl:Squared Cl
    U+1F192🆒\:cool:Squared Cool
    U+1F193🆓\:free:Squared Free
    U+1F194🆔\:id:Squared Id
    U+1F195🆕\:new:Squared New
    U+1F196🆖\:ng:Squared Ng
    U+1F197🆗\:ok:Squared Ok
    U+1F198🆘\:sos:Squared Sos
    U+1F199🆙\:up:Squared Up With Exclamation Mark
    U+1F19A🆚\:vs:Squared Vs
    U+1F201🈁\:koko:Squared Katakana Koko
    U+1F202🈂\:sa:Squared Katakana Sa
    U+1F21A🈚\:u7121:Squared Cjk Unified Ideograph-7121
    U+1F22F🈯\:u6307:Squared Cjk Unified Ideograph-6307
    U+1F232🈲\:u7981:Squared Cjk Unified Ideograph-7981
    U+1F233🈳\:u7a7a:Squared Cjk Unified Ideograph-7A7A
    U+1F234🈴\:u5408:Squared Cjk Unified Ideograph-5408
    U+1F235🈵\:u6e80:Squared Cjk Unified Ideograph-6E80
    U+1F236🈶\:u6709:Squared Cjk Unified Ideograph-6709
    U+1F237🈷\:u6708:Squared Cjk Unified Ideograph-6708
    U+1F238🈸\:u7533:Squared Cjk Unified Ideograph-7533
    U+1F239🈹\:u5272:Squared Cjk Unified Ideograph-5272
    U+1F23A🈺\:u55b6:Squared Cjk Unified Ideograph-55B6
    U+1F250🉐\:ideograph_advantage:Circled Ideograph Advantage
    U+1F251🉑\:accept:Circled Ideograph Accept
    U+1F300🌀\:cyclone:Cyclone
    U+1F301🌁\:foggy:Foggy
    U+1F302🌂\:closed_umbrella:Closed Umbrella
    U+1F303🌃\:night_with_stars:Night With Stars
    U+1F304🌄\:sunrise_over_mountains:Sunrise Over Mountains
    U+1F305🌅\:sunrise:Sunrise
    U+1F306🌆\:city_sunset:Cityscape At Dusk
    U+1F307🌇\:city_sunrise:Sunset Over Buildings
    U+1F308🌈\:rainbow:Rainbow
    U+1F309🌉\:bridge_at_night:Bridge At Night
    U+1F30A🌊\:ocean:Water Wave
    U+1F30B🌋\:volcano:Volcano
    U+1F30C🌌\:milky_way:Milky Way
    U+1F30D🌍\:earth_africa:Earth Globe Europe-Africa
    U+1F30E🌎\:earth_americas:Earth Globe Americas
    U+1F30F🌏\:earth_asia:Earth Globe Asia-Australia
    U+1F310🌐\:globe_with_meridians:Globe With Meridians
    U+1F311🌑\:new_moon:New Moon Symbol
    U+1F312🌒\:waxing_crescent_moon:Waxing Crescent Moon Symbol
    U+1F313🌓\:first_quarter_moon:First Quarter Moon Symbol
    U+1F314🌔\:moon:Waxing Gibbous Moon Symbol
    U+1F315🌕\:full_moon:Full Moon Symbol
    U+1F316🌖\:waning_gibbous_moon:Waning Gibbous Moon Symbol
    U+1F317🌗\:last_quarter_moon:Last Quarter Moon Symbol
    U+1F318🌘\:waning_crescent_moon:Waning Crescent Moon Symbol
    U+1F319🌙\:crescent_moon:Crescent Moon
    U+1F31A🌚\:new_moon_with_face:New Moon With Face
    U+1F31B🌛\:first_quarter_moon_with_face:First Quarter Moon With Face
    U+1F31C🌜\:last_quarter_moon_with_face:Last Quarter Moon With Face
    U+1F31D🌝\:full_moon_with_face:Full Moon With Face
    U+1F31E🌞\:sun_with_face:Sun With Face
    U+1F31F🌟\:star2:Glowing Star
    U+1F320🌠\:stars:Shooting Star
    U+1F32D🌭\:hotdog:Hot Dog
    U+1F32E🌮\:taco:Taco
    U+1F32F🌯\:burrito:Burrito
    U+1F330🌰\:chestnut:Chestnut
    U+1F331🌱\:seedling:Seedling
    U+1F332🌲\:evergreen_tree:Evergreen Tree
    U+1F333🌳\:deciduous_tree:Deciduous Tree
    U+1F334🌴\:palm_tree:Palm Tree
    U+1F335🌵\:cactus:Cactus
    U+1F337🌷\:tulip:Tulip
    U+1F338🌸\:cherry_blossom:Cherry Blossom
    U+1F339🌹\:rose:Rose
    U+1F33A🌺\:hibiscus:Hibiscus
    U+1F33B🌻\:sunflower:Sunflower
    U+1F33C🌼\:blossom:Blossom
    U+1F33D🌽\:corn:Ear Of Maize
    U+1F33E🌾\:ear_of_rice:Ear Of Rice
    U+1F33F🌿\:herb:Herb
    U+1F340🍀\:four_leaf_clover:Four Leaf Clover
    U+1F341🍁\:maple_leaf:Maple Leaf
    U+1F342🍂\:fallen_leaf:Fallen Leaf
    U+1F343🍃\:leaves:Leaf Fluttering In Wind
    U+1F344🍄\:mushroom:Mushroom
    U+1F345🍅\:tomato:Tomato
    U+1F346🍆\:eggplant:Aubergine
    U+1F347🍇\:grapes:Grapes
    U+1F348🍈\:melon:Melon
    U+1F349🍉\:watermelon:Watermelon
    U+1F34A🍊\:tangerine:Tangerine
    U+1F34B🍋\:lemon:Lemon
    U+1F34C🍌\:banana:Banana
    U+1F34D🍍\:pineapple:Pineapple
    U+1F34E🍎\:apple:Red Apple
    U+1F34F🍏\:green_apple:Green Apple
    U+1F350🍐\:pear:Pear
    U+1F351🍑\:peach:Peach
    U+1F352🍒\:cherries:Cherries
    U+1F353🍓\:strawberry:Strawberry
    U+1F354🍔\:hamburger:Hamburger
    U+1F355🍕\:pizza:Slice Of Pizza
    U+1F356🍖\:meat_on_bone:Meat On Bone
    U+1F357🍗\:poultry_leg:Poultry Leg
    U+1F358🍘\:rice_cracker:Rice Cracker
    U+1F359🍙\:rice_ball:Rice Ball
    U+1F35A🍚\:rice:Cooked Rice
    U+1F35B🍛\:curry:Curry And Rice
    U+1F35C🍜\:ramen:Steaming Bowl
    U+1F35D🍝\:spaghetti:Spaghetti
    U+1F35E🍞\:bread:Bread
    U+1F35F🍟\:fries:French Fries
    U+1F360🍠\:sweet_potato:Roasted Sweet Potato
    U+1F361🍡\:dango:Dango
    U+1F362🍢\:oden:Oden
    U+1F363🍣\:sushi:Sushi
    U+1F364🍤\:fried_shrimp:Fried Shrimp
    U+1F365🍥\:fish_cake:Fish Cake With Swirl Design
    U+1F366🍦\:icecream:Soft Ice Cream
    U+1F367🍧\:shaved_ice:Shaved Ice
    U+1F368🍨\:ice_cream:Ice Cream
    U+1F369🍩\:doughnut:Doughnut
    U+1F36A🍪\:cookie:Cookie
    U+1F36B🍫\:chocolate_bar:Chocolate Bar
    U+1F36C🍬\:candy:Candy
    U+1F36D🍭\:lollipop:Lollipop
    U+1F36E🍮\:custard:Custard
    U+1F36F🍯\:honey_pot:Honey Pot
    U+1F370🍰\:cake:Shortcake
    U+1F371🍱\:bento:Bento Box
    U+1F372🍲\:stew:Pot Of Food
    U+1F373🍳\:fried_egg:Cooking
    U+1F374🍴\:fork_and_knife:Fork And Knife
    U+1F375🍵\:tea:Teacup Without Handle
    U+1F376🍶\:sake:Sake Bottle And Cup
    U+1F377🍷\:wine_glass:Wine Glass
    U+1F378🍸\:cocktail:Cocktail Glass
    U+1F379🍹\:tropical_drink:Tropical Drink
    U+1F37A🍺\:beer:Beer Mug
    U+1F37B🍻\:beers:Clinking Beer Mugs
    U+1F37C🍼\:baby_bottle:Baby Bottle
    U+1F37E🍾\:champagne:Bottle With Popping Cork
    U+1F37F🍿\:popcorn:Popcorn
    U+1F380🎀\:ribbon:Ribbon
    U+1F381🎁\:gift:Wrapped Present
    U+1F382🎂\:birthday:Birthday Cake
    U+1F383🎃\:jack_o_lantern:Jack-O-Lantern
    U+1F384🎄\:christmas_tree:Christmas Tree
    U+1F385🎅\:santa:Father Christmas
    U+1F386🎆\:fireworks:Fireworks
    U+1F387🎇\:sparkler:Firework Sparkler
    U+1F388🎈\:balloon:Balloon
    U+1F389🎉\:tada:Party Popper
    U+1F38A🎊\:confetti_ball:Confetti Ball
    U+1F38B🎋\:tanabata_tree:Tanabata Tree
    U+1F38C🎌\:crossed_flags:Crossed Flags
    U+1F38D🎍\:bamboo:Pine Decoration
    U+1F38E🎎\:dolls:Japanese Dolls
    U+1F38F🎏\:flags:Carp Streamer
    U+1F390🎐\:wind_chime:Wind Chime
    U+1F391🎑\:rice_scene:Moon Viewing Ceremony
    U+1F392🎒\:school_satchel:School Satchel
    U+1F393🎓\:mortar_board:Graduation Cap
    U+1F3A0🎠\:carousel_horse:Carousel Horse
    U+1F3A1🎡\:ferris_wheel:Ferris Wheel
    U+1F3A2🎢\:roller_coaster:Roller Coaster
    U+1F3A3🎣\:fishing_pole_and_fish:Fishing Pole And Fish
    U+1F3A4🎤\:microphone:Microphone
    U+1F3A5🎥\:movie_camera:Movie Camera
    U+1F3A6🎦\:cinema:Cinema
    U+1F3A7🎧\:headphones:Headphone
    U+1F3A8🎨\:art:Artist Palette
    U+1F3A9🎩\:tophat:Top Hat
    U+1F3AA🎪\:circus_tent:Circus Tent
    U+1F3AB🎫\:ticket:Ticket
    U+1F3AC🎬\:clapper:Clapper Board
    U+1F3AD🎭\:performing_arts:Performing Arts
    U+1F3AE🎮\:video_game:Video Game
    U+1F3AF🎯\:dart:Direct Hit
    U+1F3B0🎰\:slot_machine:Slot Machine
    U+1F3B1🎱\:8ball:Billiards
    U+1F3B2🎲\:game_die:Game Die
    U+1F3B3🎳\:bowling:Bowling
    U+1F3B4🎴\:flower_playing_cards:Flower Playing Cards
    U+1F3B5🎵\:musical_note:Musical Note
    U+1F3B6🎶\:notes:Multiple Musical Notes
    U+1F3B7🎷\:saxophone:Saxophone
    U+1F3B8🎸\:guitar:Guitar
    U+1F3B9🎹\:musical_keyboard:Musical Keyboard
    U+1F3BA🎺\:trumpet:Trumpet
    U+1F3BB🎻\:violin:Violin
    U+1F3BC🎼\:musical_score:Musical Score
    U+1F3BD🎽\:running_shirt_with_sash:Running Shirt With Sash
    U+1F3BE🎾\:tennis:Tennis Racquet And Ball
    U+1F3BF🎿\:ski:Ski And Ski Boot
    U+1F3C0🏀\:basketball:Basketball And Hoop
    U+1F3C1🏁\:checkered_flag:Chequered Flag
    U+1F3C2🏂\:snowboarder:Snowboarder
    U+1F3C3🏃\:runner:Runner
    U+1F3C4🏄\:surfer:Surfer
    U+1F3C5🏅\:sports_medal:Sports Medal
    U+1F3C6🏆\:trophy:Trophy
    U+1F3C7🏇\:horse_racing:Horse Racing
    U+1F3C8🏈\:football:American Football
    U+1F3C9🏉\:rugby_football:Rugby Football
    U+1F3CA🏊\:swimmer:Swimmer
    U+1F3CF🏏\:cricket_bat_and_ball:Cricket Bat And Ball
    U+1F3D0🏐\:volleyball:Volleyball
    U+1F3D1🏑\:field_hockey_stick_and_ball:Field Hockey Stick And Ball
    U+1F3D2🏒\:ice_hockey_stick_and_puck:Ice Hockey Stick And Puck
    U+1F3D3🏓\:table_tennis_paddle_and_ball:Table Tennis Paddle And Ball
    U+1F3E0🏠\:house:House Building
    U+1F3E1🏡\:house_with_garden:House With Garden
    U+1F3E2🏢\:office:Office Building
    U+1F3E3🏣\:post_office:Japanese Post Office
    U+1F3E4🏤\:european_post_office:European Post Office
    U+1F3E5🏥\:hospital:Hospital
    U+1F3E6🏦\:bank:Bank
    U+1F3E7🏧\:atm:Automated Teller Machine
    U+1F3E8🏨\:hotel:Hotel
    U+1F3E9🏩\:love_hotel:Love Hotel
    U+1F3EA🏪\:convenience_store:Convenience Store
    U+1F3EB🏫\:school:School
    U+1F3EC🏬\:department_store:Department Store
    U+1F3ED🏭\:factory:Factory
    U+1F3EE🏮\:izakaya_lantern:Izakaya Lantern
    U+1F3EF🏯\:japanese_castle:Japanese Castle
    U+1F3F0🏰\:european_castle:European Castle
    U+1F3F4🏴\:waving_black_flag:Waving Black Flag
    U+1F3F8🏸\:badminton_racquet_and_shuttlecock:Badminton Racquet And Shuttlecock
    U+1F3F9🏹\:bow_and_arrow:Bow And Arrow
    U+1F3FA🏺\:amphora:Amphora
    U+1F3FB🏻\:skin-tone-2:Emoji Modifier Fitzpatrick Type-1-2
    U+1F3FC🏼\:skin-tone-3:Emoji Modifier Fitzpatrick Type-3
    U+1F3FD🏽\:skin-tone-4:Emoji Modifier Fitzpatrick Type-4
    U+1F3FE🏾\:skin-tone-5:Emoji Modifier Fitzpatrick Type-5
    U+1F3FF🏿\:skin-tone-6:Emoji Modifier Fitzpatrick Type-6
    U+1F400🐀\:rat:Rat
    U+1F401🐁\:mouse2:Mouse
    U+1F402🐂\:ox:Ox
    U+1F403🐃\:water_buffalo:Water Buffalo
    U+1F404🐄\:cow2:Cow
    U+1F405🐅\:tiger2:Tiger
    U+1F406🐆\:leopard:Leopard
    U+1F407🐇\:rabbit2:Rabbit
    U+1F408🐈\:cat2:Cat
    U+1F409🐉\:dragon:Dragon
    U+1F40A🐊\:crocodile:Crocodile
    U+1F40B🐋\:whale2:Whale
    U+1F40C🐌\:snail:Snail
    U+1F40D🐍\:snake:Snake
    U+1F40E🐎\:racehorse:Horse
    U+1F40F🐏\:ram:Ram
    U+1F410🐐\:goat:Goat
    U+1F411🐑\:sheep:Sheep
    U+1F412🐒\:monkey:Monkey
    U+1F413🐓\:rooster:Rooster
    U+1F414🐔\:chicken:Chicken
    U+1F415🐕\:dog2:Dog
    U+1F416🐖\:pig2:Pig
    U+1F417🐗\:boar:Boar
    U+1F418🐘\:elephant:Elephant
    U+1F419🐙\:octopus:Octopus
    U+1F41A🐚\:shell:Spiral Shell
    U+1F41B🐛\:bug:Bug
    U+1F41C🐜\:ant:Ant
    U+1F41D🐝\:bee:Honeybee
    U+1F41E🐞\:ladybug:Lady Beetle
    U+1F41F🐟\:fish:Fish
    U+1F420🐠\:tropical_fish:Tropical Fish
    U+1F421🐡\:blowfish:Blowfish
    U+1F422🐢\:turtle:Turtle
    U+1F423🐣\:hatching_chick:Hatching Chick
    U+1F424🐤\:baby_chick:Baby Chick
    U+1F425🐥\:hatched_chick:Front-Facing Baby Chick
    U+1F426🐦\:bird:Bird
    U+1F427🐧\:penguin:Penguin
    U+1F428🐨\:koala:Koala
    U+1F429🐩\:poodle:Poodle
    U+1F42A🐪\:dromedary_camel:Dromedary Camel
    U+1F42B🐫\:camel:Bactrian Camel
    U+1F42C🐬\:dolphin:Dolphin
    U+1F42D🐭\:mouse:Mouse Face
    U+1F42E🐮\:cow:Cow Face
    U+1F42F🐯\:tiger:Tiger Face
    U+1F430🐰\:rabbit:Rabbit Face
    U+1F431🐱\:cat:Cat Face
    U+1F432🐲\:dragon_face:Dragon Face
    U+1F433🐳\:whale:Spouting Whale
    U+1F434🐴\:horse:Horse Face
    U+1F435🐵\:monkey_face:Monkey Face
    U+1F436🐶\:dog:Dog Face
    U+1F437🐷\:pig:Pig Face
    U+1F438🐸\:frog:Frog Face
    U+1F439🐹\:hamster:Hamster Face
    U+1F43A🐺\:wolf:Wolf Face
    U+1F43B🐻\:bear:Bear Face
    U+1F43C🐼\:panda_face:Panda Face
    U+1F43D🐽\:pig_nose:Pig Nose
    U+1F43E🐾\:feet:Paw Prints
    U+1F440👀\:eyes:Eyes
    U+1F442👂\:ear:Ear
    U+1F443👃\:nose:Nose
    U+1F444👄\:lips:Mouth
    U+1F445👅\:tongue:Tongue
    U+1F446👆\:point_up_2:White Up Pointing Backhand Index
    U+1F447👇\:point_down:White Down Pointing Backhand Index
    U+1F448👈\:point_left:White Left Pointing Backhand Index
    U+1F449👉\:point_right:White Right Pointing Backhand Index
    U+1F44A👊\:facepunch:Fisted Hand Sign
    U+1F44B👋\:wave:Waving Hand Sign
    U+1F44C👌\:ok_hand:Ok Hand Sign
    U+1F44D👍\:+1:Thumbs Up Sign
    U+1F44E👎\:-1:Thumbs Down Sign
    U+1F44F👏\:clap:Clapping Hands Sign
    U+1F450👐\:open_hands:Open Hands Sign
    U+1F451👑\:crown:Crown
    U+1F452👒\:womans_hat:Womans Hat
    U+1F453👓\:eyeglasses:Eyeglasses
    U+1F454👔\:necktie:Necktie
    U+1F455👕\:shirt:T-Shirt
    U+1F456👖\:jeans:Jeans
    U+1F457👗\:dress:Dress
    U+1F458👘\:kimono:Kimono
    U+1F459👙\:bikini:Bikini
    U+1F45A👚\:womans_clothes:Womans Clothes
    U+1F45B👛\:purse:Purse
    U+1F45C👜\:handbag:Handbag
    U+1F45D👝\:pouch:Pouch
    U+1F45E👞\:mans_shoe:Mans Shoe
    U+1F45F👟\:athletic_shoe:Athletic Shoe
    U+1F460👠\:high_heel:High-Heeled Shoe
    U+1F461👡\:sandal:Womans Sandal
    U+1F462👢\:boot:Womans Boots
    U+1F463👣\:footprints:Footprints
    U+1F464👤\:bust_in_silhouette:Bust In Silhouette
    U+1F465👥\:busts_in_silhouette:Busts In Silhouette
    U+1F466👦\:boy:Boy
    U+1F467👧\:girl:Girl
    U+1F468👨\:man:Man
    U+1F469👩\:woman:Woman
    U+1F46A👪\:family:Family
    U+1F46B👫\:couple:, \:man_and_woman_holding_hands:Man And Woman Holding Hands
    U+1F46C👬\:two_men_holding_hands:Two Men Holding Hands
    U+1F46D👭\:two_women_holding_hands:Two Women Holding Hands
    U+1F46E👮\:cop:Police Officer
    U+1F46F👯\:dancers:Woman With Bunny Ears
    U+1F470👰\:bride_with_veil:Bride With Veil
    U+1F471👱\:person_with_blond_hair:Person With Blond Hair
    U+1F472👲\:man_with_gua_pi_mao:Man With Gua Pi Mao
    U+1F473👳\:man_with_turban:Man With Turban
    U+1F474👴\:older_man:Older Man
    U+1F475👵\:older_woman:Older Woman
    U+1F476👶\:baby:Baby
    U+1F477👷\:construction_worker:Construction Worker
    U+1F478👸\:princess:Princess
    U+1F479👹\:japanese_ogre:Japanese Ogre
    U+1F47A👺\:japanese_goblin:Japanese Goblin
    U+1F47B👻\:ghost:Ghost
    U+1F47C👼\:angel:Baby Angel
    U+1F47D👽\:alien:Extraterrestrial Alien
    U+1F47E👾\:space_invader:Alien Monster
    U+1F47F👿\:imp:Imp
    U+1F480💀\:skull:Skull
    U+1F481💁\:information_desk_person:Information Desk Person
    U+1F482💂\:guardsman:Guardsman
    U+1F483💃\:dancer:Dancer
    U+1F484💄\:lipstick:Lipstick
    U+1F485💅\:nail_care:Nail Polish
    U+1F486💆\:massage:Face Massage
    U+1F487💇\:haircut:Haircut
    U+1F488💈\:barber:Barber Pole
    U+1F489💉\:syringe:Syringe
    U+1F48A💊\:pill:Pill
    U+1F48B💋\:kiss:Kiss Mark
    U+1F48C💌\:love_letter:Love Letter
    U+1F48D💍\:ring:Ring
    U+1F48E💎\:gem:Gem Stone
    U+1F48F💏\:couplekiss:Kiss
    U+1F490💐\:bouquet:Bouquet
    U+1F491💑\:couple_with_heart:Couple With Heart
    U+1F492💒\:wedding:Wedding
    U+1F493💓\:heartbeat:Beating Heart
    U+1F494💔\:broken_heart:Broken Heart
    U+1F495💕\:two_hearts:Two Hearts
    U+1F496💖\:sparkling_heart:Sparkling Heart
    U+1F497💗\:heartpulse:Growing Heart
    U+1F498💘\:cupid:Heart With Arrow
    U+1F499💙\:blue_heart:Blue Heart
    U+1F49A💚\:green_heart:Green Heart
    U+1F49B💛\:yellow_heart:Yellow Heart
    U+1F49C💜\:purple_heart:Purple Heart
    U+1F49D💝\:gift_heart:Heart With Ribbon
    U+1F49E💞\:revolving_hearts:Revolving Hearts
    U+1F49F💟\:heart_decoration:Heart Decoration
    U+1F4A0💠\:diamond_shape_with_a_dot_inside:Diamond Shape With A Dot Inside
    U+1F4A1💡\:bulb:Electric Light Bulb
    U+1F4A2💢\:anger:Anger Symbol
    U+1F4A3💣\:bomb:Bomb
    U+1F4A4💤\:zzz:Sleeping Symbol
    U+1F4A5💥\:boom:Collision Symbol
    U+1F4A6💦\:sweat_drops:Splashing Sweat Symbol
    U+1F4A7💧\:droplet:Droplet
    U+1F4A8💨\:dash:Dash Symbol
    U+1F4A9💩\:hankey:Pile Of Poo
    U+1F4AA💪\:muscle:Flexed Biceps
    U+1F4AB💫\:dizzy:Dizzy Symbol
    U+1F4AC💬\:speech_balloon:Speech Balloon
    U+1F4AD💭\:thought_balloon:Thought Balloon
    U+1F4AE💮\:white_flower:White Flower
    U+1F4AF💯\:100:Hundred Points Symbol
    U+1F4B0💰\:moneybag:Money Bag
    U+1F4B1💱\:currency_exchange:Currency Exchange
    U+1F4B2💲\:heavy_dollar_sign:Heavy Dollar Sign
    U+1F4B3💳\:credit_card:Credit Card
    U+1F4B4💴\:yen:Banknote With Yen Sign
    U+1F4B5💵\:dollar:Banknote With Dollar Sign
    U+1F4B6💶\:euro:Banknote With Euro Sign
    U+1F4B7💷\:pound:Banknote With Pound Sign
    U+1F4B8💸\:money_with_wings:Money With Wings
    U+1F4B9💹\:chart:Chart With Upwards Trend And Yen Sign
    U+1F4BA💺\:seat:Seat
    U+1F4BB💻\:computer:Personal Computer
    U+1F4BC💼\:briefcase:Briefcase
    U+1F4BD💽\:minidisc:Minidisc
    U+1F4BE💾\:floppy_disk:Floppy Disk
    U+1F4BF💿\:cd:Optical Disc
    U+1F4C0📀\:dvd:Dvd
    U+1F4C1📁\:file_folder:File Folder
    U+1F4C2📂\:open_file_folder:Open File Folder
    U+1F4C3📃\:page_with_curl:Page With Curl
    U+1F4C4📄\:page_facing_up:Page Facing Up
    U+1F4C5📅\:date:Calendar
    U+1F4C6📆\:calendar:Tear-Off Calendar
    U+1F4C7📇\:card_index:Card Index
    U+1F4C8📈\:chart_with_upwards_trend:Chart With Upwards Trend
    U+1F4C9📉\:chart_with_downwards_trend:Chart With Downwards Trend
    U+1F4CA📊\:bar_chart:Bar Chart
    U+1F4CB📋\:clipboard:Clipboard
    U+1F4CC📌\:pushpin:Pushpin
    U+1F4CD📍\:round_pushpin:Round Pushpin
    U+1F4CE📎\:paperclip:Paperclip
    U+1F4CF📏\:straight_ruler:Straight Ruler
    U+1F4D0📐\:triangular_ruler:Triangular Ruler
    U+1F4D1📑\:bookmark_tabs:Bookmark Tabs
    U+1F4D2📒\:ledger:Ledger
    U+1F4D3📓\:notebook:Notebook
    U+1F4D4📔\:notebook_with_decorative_cover:Notebook With Decorative Cover
    U+1F4D5📕\:closed_book:Closed Book
    U+1F4D6📖\:book:Open Book
    U+1F4D7📗\:green_book:Green Book
    U+1F4D8📘\:blue_book:Blue Book
    U+1F4D9📙\:orange_book:Orange Book
    U+1F4DA📚\:books:Books
    U+1F4DB📛\:name_badge:Name Badge
    U+1F4DC📜\:scroll:Scroll
    U+1F4DD📝\:memo:Memo
    U+1F4DE📞\:telephone_receiver:Telephone Receiver
    U+1F4DF📟\:pager:Pager
    U+1F4E0📠\:fax:Fax Machine
    U+1F4E1📡\:satellite:, \:satellite_antenna:Satellite Antenna
    U+1F4E2📢\:loudspeaker:Public Address Loudspeaker
    U+1F4E3📣\:mega:Cheering Megaphone
    U+1F4E4📤\:outbox_tray:Outbox Tray
    U+1F4E5📥\:inbox_tray:Inbox Tray
    U+1F4E6📦\:package:Package
    U+1F4E7📧\:e-mail:E-Mail Symbol
    U+1F4E8📨\:incoming_envelope:Incoming Envelope
    U+1F4E9📩\:envelope_with_arrow:Envelope With Downwards Arrow Above
    U+1F4EA📪\:mailbox_closed:Closed Mailbox With Lowered Flag
    U+1F4EB📫\:mailbox:Closed Mailbox With Raised Flag
    U+1F4EC📬\:mailbox_with_mail:Open Mailbox With Raised Flag
    U+1F4ED📭\:mailbox_with_no_mail:Open Mailbox With Lowered Flag
    U+1F4EE📮\:postbox:Postbox
    U+1F4EF📯\:postal_horn:Postal Horn
    U+1F4F0📰\:newspaper:Newspaper
    U+1F4F1📱\:iphone:Mobile Phone
    U+1F4F2📲\:calling:Mobile Phone With Rightwards Arrow At Left
    U+1F4F3📳\:vibration_mode:Vibration Mode
    U+1F4F4📴\:mobile_phone_off:Mobile Phone Off
    U+1F4F5📵\:no_mobile_phones:No Mobile Phones
    U+1F4F6📶\:signal_strength:Antenna With Bars
    U+1F4F7📷\:camera:Camera
    U+1F4F8📸\:camera_with_flash:Camera With Flash
    U+1F4F9📹\:video_camera:Video Camera
    U+1F4FA📺\:tv:Television
    U+1F4FB📻\:radio:Radio
    U+1F4FC📼\:vhs:Videocassette
    U+1F4FF📿\:prayer_beads:Prayer Beads
    U+1F500🔀\:twisted_rightwards_arrows:Twisted Rightwards Arrows
    U+1F501🔁\:repeat:Clockwise Rightwards And Leftwards Open Circle Arrows
    U+1F502🔂\:repeat_one:Clockwise Rightwards And Leftwards Open Circle Arrows With Circled One Overlay
    U+1F503🔃\:arrows_clockwise:Clockwise Downwards And Upwards Open Circle Arrows
    U+1F504🔄\:arrows_counterclockwise:Anticlockwise Downwards And Upwards Open Circle Arrows
    U+1F505🔅\:low_brightness:Low Brightness Symbol
    U+1F506🔆\:high_brightness:High Brightness Symbol
    U+1F507🔇\:mute:Speaker With Cancellation Stroke
    U+1F508🔈\:speaker:Speaker
    U+1F509🔉\:sound:Speaker With One Sound Wave
    U+1F50A🔊\:loud_sound:Speaker With Three Sound Waves
    U+1F50B🔋\:battery:Battery
    U+1F50C🔌\:electric_plug:Electric Plug
    U+1F50D🔍\:mag:Left-Pointing Magnifying Glass
    U+1F50E🔎\:mag_right:Right-Pointing Magnifying Glass
    U+1F50F🔏\:lock_with_ink_pen:Lock With Ink Pen
    U+1F510🔐\:closed_lock_with_key:Closed Lock With Key
    U+1F511🔑\:key:Key
    U+1F512🔒\:lock:Lock
    U+1F513🔓\:unlock:Open Lock
    U+1F514🔔\:bell:Bell
    U+1F515🔕\:no_bell:Bell With Cancellation Stroke
    U+1F516🔖\:bookmark:Bookmark
    U+1F517🔗\:link:Link Symbol
    U+1F518🔘\:radio_button:Radio Button
    U+1F519🔙\:back:Back With Leftwards Arrow Above
    U+1F51A🔚\:end:End With Leftwards Arrow Above
    U+1F51B🔛\:on:On With Exclamation Mark With Left Right Arrow Above
    U+1F51C🔜\:soon:Soon With Rightwards Arrow Above
    U+1F51D🔝\:top:Top With Upwards Arrow Above
    U+1F51E🔞\:underage:No One Under Eighteen Symbol
    U+1F51F🔟\:keycap_ten:Keycap Ten
    U+1F520🔠\:capital_abcd:Input Symbol For Latin Capital Letters
    U+1F521🔡\:abcd:Input Symbol For Latin Small Letters
    U+1F522🔢\:1234:Input Symbol For Numbers
    U+1F523🔣\:symbols:Input Symbol For Symbols
    U+1F524🔤\:abc:Input Symbol For Latin Letters
    U+1F525🔥\:fire:Fire
    U+1F526🔦\:flashlight:Electric Torch
    U+1F527🔧\:wrench:Wrench
    U+1F528🔨\:hammer:Hammer
    U+1F529🔩\:nut_and_bolt:Nut And Bolt
    U+1F52A🔪\:hocho:Hocho
    U+1F52B🔫\:gun:Pistol
    U+1F52C🔬\:microscope:Microscope
    U+1F52D🔭\:telescope:Telescope
    U+1F52E🔮\:crystal_ball:Crystal Ball
    U+1F52F🔯\:six_pointed_star:Six Pointed Star With Middle Dot
    U+1F530🔰\:beginner:Japanese Symbol For Beginner
    U+1F531🔱\:trident:Trident Emblem
    U+1F532🔲\:black_square_button:Black Square Button
    U+1F533🔳\:white_square_button:White Square Button
    U+1F534🔴\:red_circle:Large Red Circle
    U+1F535🔵\:large_blue_circle:Large Blue Circle
    U+1F536🔶\:large_orange_diamond:Large Orange Diamond
    U+1F537🔷\:large_blue_diamond:Large Blue Diamond
    U+1F538🔸\:small_orange_diamond:Small Orange Diamond
    U+1F539🔹\:small_blue_diamond:Small Blue Diamond
    U+1F53A🔺\:small_red_triangle:Up-Pointing Red Triangle
    U+1F53B🔻\:small_red_triangle_down:Down-Pointing Red Triangle
    U+1F53C🔼\:arrow_up_small:Up-Pointing Small Red Triangle
    U+1F53D🔽\:arrow_down_small:Down-Pointing Small Red Triangle
    U+1F54B🕋\:kaaba:Kaaba
    U+1F54C🕌\:mosque:Mosque
    U+1F54D🕍\:synagogue:Synagogue
    U+1F54E🕎\:menorah_with_nine_branches:Menorah With Nine Branches
    U+1F550🕐\:clock1:Clock Face One Oclock
    U+1F551🕑\:clock2:Clock Face Two Oclock
    U+1F552🕒\:clock3:Clock Face Three Oclock
    U+1F553🕓\:clock4:Clock Face Four Oclock
    U+1F554🕔\:clock5:Clock Face Five Oclock
    U+1F555🕕\:clock6:Clock Face Six Oclock
    U+1F556🕖\:clock7:Clock Face Seven Oclock
    U+1F557🕗\:clock8:Clock Face Eight Oclock
    U+1F558🕘\:clock9:Clock Face Nine Oclock
    U+1F559🕙\:clock10:Clock Face Ten Oclock
    U+1F55A🕚\:clock11:Clock Face Eleven Oclock
    U+1F55B🕛\:clock12:Clock Face Twelve Oclock
    U+1F55C🕜\:clock130:Clock Face One-Thirty
    U+1F55D🕝\:clock230:Clock Face Two-Thirty
    U+1F55E🕞\:clock330:Clock Face Three-Thirty
    U+1F55F🕟\:clock430:Clock Face Four-Thirty
    U+1F560🕠\:clock530:Clock Face Five-Thirty
    U+1F561🕡\:clock630:Clock Face Six-Thirty
    U+1F562🕢\:clock730:Clock Face Seven-Thirty
    U+1F563🕣\:clock830:Clock Face Eight-Thirty
    U+1F564🕤\:clock930:Clock Face Nine-Thirty
    U+1F565🕥\:clock1030:Clock Face Ten-Thirty
    U+1F566🕦\:clock1130:Clock Face Eleven-Thirty
    U+1F567🕧\:clock1230:Clock Face Twelve-Thirty
    U+1F57A🕺\:man_dancing:Man Dancing
    U+1F595🖕\:middle_finger:Reversed Hand With Middle Finger Extended
    U+1F596🖖\:spock-hand:Raised Hand With Part Between Middle And Ring Fingers
    U+1F5A4🖤\:black_heart:Black Heart
    U+1F5FB🗻\:mount_fuji:Mount Fuji
    U+1F5FC🗼\:tokyo_tower:Tokyo Tower
    U+1F5FD🗽\:statue_of_liberty:Statue Of Liberty
    U+1F5FE🗾\:japan:Silhouette Of Japan
    U+1F5FF🗿\:moyai:Moyai
    U+1F600😀\:grinning:Grinning Face
    U+1F601😁\:grin:Grinning Face With Smiling Eyes
    U+1F602😂\:joy:Face With Tears Of Joy
    U+1F603😃\:smiley:Smiling Face With Open Mouth
    U+1F604😄\:smile:Smiling Face With Open Mouth And Smiling Eyes
    U+1F605😅\:sweat_smile:Smiling Face With Open Mouth And Cold Sweat
    U+1F606😆\:laughing:Smiling Face With Open Mouth And Tightly-Closed Eyes
    U+1F607😇\:innocent:Smiling Face With Halo
    U+1F608😈\:smiling_imp:Smiling Face With Horns
    U+1F609😉\:wink:Winking Face
    U+1F60A😊\:blush:Smiling Face With Smiling Eyes
    U+1F60B😋\:yum:Face Savouring Delicious Food
    U+1F60C😌\:relieved:Relieved Face
    U+1F60D😍\:heart_eyes:Smiling Face With Heart-Shaped Eyes
    U+1F60E😎\:sunglasses:Smiling Face With Sunglasses
    U+1F60F😏\:smirk:Smirking Face
    U+1F610😐\:neutral_face:Neutral Face
    U+1F611😑\:expressionless:Expressionless Face
    U+1F612😒\:unamused:Unamused Face
    U+1F613😓\:sweat:Face With Cold Sweat
    U+1F614😔\:pensive:Pensive Face
    U+1F615😕\:confused:Confused Face
    U+1F616😖\:confounded:Confounded Face
    U+1F617😗\:kissing:Kissing Face
    U+1F618😘\:kissing_heart:Face Throwing A Kiss
    U+1F619😙\:kissing_smiling_eyes:Kissing Face With Smiling Eyes
    U+1F61A😚\:kissing_closed_eyes:Kissing Face With Closed Eyes
    U+1F61B😛\:stuck_out_tongue:Face With Stuck-Out Tongue
    U+1F61C😜\:stuck_out_tongue_winking_eye:Face With Stuck-Out Tongue And Winking Eye
    U+1F61D😝\:stuck_out_tongue_closed_eyes:Face With Stuck-Out Tongue And Tightly-Closed Eyes
    U+1F61E😞\:disappointed:Disappointed Face
    U+1F61F😟\:worried:Worried Face
    U+1F620😠\:angry:Angry Face
    U+1F621😡\:rage:Pouting Face
    U+1F622😢\:cry:Crying Face
    U+1F623😣\:persevere:Persevering Face
    U+1F624😤\:triumph:Face With Look Of Triumph
    U+1F625😥\:disappointed_relieved:Disappointed But Relieved Face
    U+1F626😦\:frowning:Frowning Face With Open Mouth
    U+1F627😧\:anguished:Anguished Face
    U+1F628😨\:fearful:Fearful Face
    U+1F629😩\:weary:Weary Face
    U+1F62A😪\:sleepy:Sleepy Face
    U+1F62B😫\:tired_face:Tired Face
    U+1F62C😬\:grimacing:Grimacing Face
    U+1F62D😭\:sob:Loudly Crying Face
    U+1F62E😮\:open_mouth:Face With Open Mouth
    U+1F62F😯\:hushed:Hushed Face
    U+1F630😰\:cold_sweat:Face With Open Mouth And Cold Sweat
    U+1F631😱\:scream:Face Screaming In Fear
    U+1F632😲\:astonished:Astonished Face
    U+1F633😳\:flushed:Flushed Face
    U+1F634😴\:sleeping:Sleeping Face
    U+1F635😵\:dizzy_face:Dizzy Face
    U+1F636😶\:no_mouth:Face Without Mouth
    U+1F637😷\:mask:Face With Medical Mask
    U+1F638😸\:smile_cat:Grinning Cat Face With Smiling Eyes
    U+1F639😹\:joy_cat:Cat Face With Tears Of Joy
    U+1F63A😺\:smiley_cat:Smiling Cat Face With Open Mouth
    U+1F63B😻\:heart_eyes_cat:Smiling Cat Face With Heart-Shaped Eyes
    U+1F63C😼\:smirk_cat:Cat Face With Wry Smile
    U+1F63D😽\:kissing_cat:Kissing Cat Face With Closed Eyes
    U+1F63E😾\:pouting_cat:Pouting Cat Face
    U+1F63F😿\:crying_cat_face:Crying Cat Face
    U+1F640🙀\:scream_cat:Weary Cat Face
    U+1F641🙁\:slightly_frowning_face:Slightly Frowning Face
    U+1F642🙂\:slightly_smiling_face:Slightly Smiling Face
    U+1F643🙃\:upside_down_face:Upside-Down Face
    U+1F644🙄\:face_with_rolling_eyes:Face With Rolling Eyes
    U+1F645🙅\:no_good:Face With No Good Gesture
    U+1F646🙆\:ok_woman:Face With Ok Gesture
    U+1F647🙇\:bow:Person Bowing Deeply
    U+1F648🙈\:see_no_evil:See-No-Evil Monkey
    U+1F649🙉\:hear_no_evil:Hear-No-Evil Monkey
    U+1F64A🙊\:speak_no_evil:Speak-No-Evil Monkey
    U+1F64B🙋\:raising_hand:Happy Person Raising One Hand
    U+1F64C🙌\:raised_hands:Person Raising Both Hands In Celebration
    U+1F64D🙍\:person_frowning:Person Frowning
    U+1F64E🙎\:person_with_pouting_face:Person With Pouting Face
    U+1F64F🙏\:pray:Person With Folded Hands
    U+1F680🚀\:rocket:Rocket
    U+1F681🚁\:helicopter:Helicopter
    U+1F682🚂\:steam_locomotive:Steam Locomotive
    U+1F683🚃\:railway_car:Railway Car
    U+1F684🚄\:bullettrain_side:High-Speed Train
    U+1F685🚅\:bullettrain_front:High-Speed Train With Bullet Nose
    U+1F686🚆\:train2:Train
    U+1F687🚇\:metro:Metro
    U+1F688🚈\:light_rail:Light Rail
    U+1F689🚉\:station:Station
    U+1F68A🚊\:tram:Tram
    U+1F68B🚋\:train:Tram Car
    U+1F68C🚌\:bus:Bus
    U+1F68D🚍\:oncoming_bus:Oncoming Bus
    U+1F68E🚎\:trolleybus:Trolleybus
    U+1F68F🚏\:busstop:Bus Stop
    U+1F690🚐\:minibus:Minibus
    U+1F691🚑\:ambulance:Ambulance
    U+1F692🚒\:fire_engine:Fire Engine
    U+1F693🚓\:police_car:Police Car
    U+1F694🚔\:oncoming_police_car:Oncoming Police Car
    U+1F695🚕\:taxi:Taxi
    U+1F696🚖\:oncoming_taxi:Oncoming Taxi
    U+1F697🚗\:car:Automobile
    U+1F698🚘\:oncoming_automobile:Oncoming Automobile
    U+1F699🚙\:blue_car:Recreational Vehicle
    U+1F69A🚚\:truck:Delivery Truck
    U+1F69B🚛\:articulated_lorry:Articulated Lorry
    U+1F69C🚜\:tractor:Tractor
    U+1F69D🚝\:monorail:Monorail
    U+1F69E🚞\:mountain_railway:Mountain Railway
    U+1F69F🚟\:suspension_railway:Suspension Railway
    U+1F6A0🚠\:mountain_cableway:Mountain Cableway
    U+1F6A1🚡\:aerial_tramway:Aerial Tramway
    U+1F6A2🚢\:ship:Ship
    U+1F6A3🚣\:rowboat:Rowboat
    U+1F6A4🚤\:speedboat:Speedboat
    U+1F6A5🚥\:traffic_light:Horizontal Traffic Light
    U+1F6A6🚦\:vertical_traffic_light:Vertical Traffic Light
    U+1F6A7🚧\:construction:Construction Sign
    U+1F6A8🚨\:rotating_light:Police Cars Revolving Light
    U+1F6A9🚩\:triangular_flag_on_post:Triangular Flag On Post
    U+1F6AA🚪\:door:Door
    U+1F6AB🚫\:no_entry_sign:No Entry Sign
    U+1F6AC🚬\:smoking:Smoking Symbol
    U+1F6AD🚭\:no_smoking:No Smoking Symbol
    U+1F6AE🚮\:put_litter_in_its_place:Put Litter In Its Place Symbol
    U+1F6AF🚯\:do_not_litter:Do Not Litter Symbol
    U+1F6B0🚰\:potable_water:Potable Water Symbol
    U+1F6B1🚱\:non-potable_water:Non-Potable Water Symbol
    U+1F6B2🚲\:bike:Bicycle
    U+1F6B3🚳\:no_bicycles:No Bicycles
    U+1F6B4🚴\:bicyclist:Bicyclist
    U+1F6B5🚵\:mountain_bicyclist:Mountain Bicyclist
    U+1F6B6🚶\:walking:Pedestrian
    U+1F6B7🚷\:no_pedestrians:No Pedestrians
    U+1F6B8🚸\:children_crossing:Children Crossing
    U+1F6B9🚹\:mens:Mens Symbol
    U+1F6BA🚺\:womens:Womens Symbol
    U+1F6BB🚻\:restroom:Restroom
    U+1F6BC🚼\:baby_symbol:Baby Symbol
    U+1F6BD🚽\:toilet:Toilet
    U+1F6BE🚾\:wc:Water Closet
    U+1F6BF🚿\:shower:Shower
    U+1F6C0🛀\:bath:Bath
    U+1F6C1🛁\:bathtub:Bathtub
    U+1F6C2🛂\:passport_control:Passport Control
    U+1F6C3🛃\:customs:Customs
    U+1F6C4🛄\:baggage_claim:Baggage Claim
    U+1F6C5🛅\:left_luggage:Left Luggage
    U+1F6CC🛌\:sleeping_accommodation:Sleeping Accommodation
    U+1F6D0🛐\:place_of_worship:Place Of Worship
    U+1F6D1🛑\:octagonal_sign:Octagonal Sign
    U+1F6D2🛒\:shopping_trolley:Shopping Trolley
    U+1F6D5🛕\:hindu_temple:(No Unicode name)
    U+1F6D6🛖\:hut:(No Unicode name)
    U+1F6D7🛗\:elevator:(No Unicode name)
    U+1F6EB🛫\:airplane_departure:Airplane Departure
    U+1F6EC🛬\:airplane_arriving:Airplane Arriving
    U+1F6F4🛴\:scooter:Scooter
    U+1F6F5🛵\:motor_scooter:Motor Scooter
    U+1F6F6🛶\:canoe:Canoe
    U+1F6F7🛷\:sled:(No Unicode name)
    U+1F6F8🛸\:flying_saucer:(No Unicode name)
    U+1F6F9🛹\:skateboard:(No Unicode name)
    U+1F6FA🛺\:auto_rickshaw:(No Unicode name)
    U+1F6FB🛻\:pickup_truck:(No Unicode name)
    U+1F6FC🛼\:roller_skate:(No Unicode name)
    U+1F7E0🟠\:large_orange_circle:(No Unicode name)
    U+1F7E1🟡\:large_yellow_circle:(No Unicode name)
    U+1F7E2🟢\:large_green_circle:(No Unicode name)
    U+1F7E3🟣\:large_purple_circle:(No Unicode name)
    U+1F7E4🟤\:large_brown_circle:(No Unicode name)
    U+1F7E5🟥\:large_red_square:(No Unicode name)
    U+1F7E6🟦\:large_blue_square:(No Unicode name)
    U+1F7E7🟧\:large_orange_square:(No Unicode name)
    U+1F7E8🟨\:large_yellow_square:(No Unicode name)
    U+1F7E9🟩\:large_green_square:(No Unicode name)
    U+1F7EA🟪\:large_purple_square:(No Unicode name)
    U+1F7EB🟫\:large_brown_square:(No Unicode name)
    U+1F90C🤌\:pinched_fingers:(No Unicode name)
    U+1F90D🤍\:white_heart:(No Unicode name)
    U+1F90E🤎\:brown_heart:(No Unicode name)
    U+1F90F🤏\:pinching_hand:(No Unicode name)
    U+1F910🤐\:zipper_mouth_face:Zipper-Mouth Face
    U+1F911🤑\:money_mouth_face:Money-Mouth Face
    U+1F912🤒\:face_with_thermometer:Face With Thermometer
    U+1F913🤓\:nerd_face:Nerd Face
    U+1F914🤔\:thinking_face:Thinking Face
    U+1F915🤕\:face_with_head_bandage:Face With Head-Bandage
    U+1F916🤖\:robot_face:Robot Face
    U+1F917🤗\:hugging_face:Hugging Face
    U+1F918🤘\:the_horns:Sign Of The Horns
    U+1F919🤙\:call_me_hand:Call Me Hand
    U+1F91A🤚\:raised_back_of_hand:Raised Back Of Hand
    U+1F91B🤛\:left-facing_fist:Left-Facing Fist
    U+1F91C🤜\:right-facing_fist:Right-Facing Fist
    U+1F91D🤝\:handshake:Handshake
    U+1F91E🤞\:crossed_fingers:Hand With Index And Middle Fingers Crossed
    U+1F91F🤟\:i_love_you_hand_sign:(No Unicode name)
    U+1F920🤠\:face_with_cowboy_hat:Face With Cowboy Hat
    U+1F921🤡\:clown_face:Clown Face
    U+1F922🤢\:nauseated_face:Nauseated Face
    U+1F923🤣\:rolling_on_the_floor_laughing:Rolling On The Floor Laughing
    U+1F924🤤\:drooling_face:Drooling Face
    U+1F925🤥\:lying_face:Lying Face
    U+1F926🤦\:face_palm:Face Palm
    U+1F927🤧\:sneezing_face:Sneezing Face
    U+1F928🤨\:face_with_raised_eyebrow:(No Unicode name)
    U+1F929🤩\:star-struck:(No Unicode name)
    U+1F92A🤪\:zany_face:(No Unicode name)
    U+1F92B🤫\:shushing_face:(No Unicode name)
    U+1F92C🤬\:face_with_symbols_on_mouth:(No Unicode name)
    U+1F92D🤭\:face_with_hand_over_mouth:(No Unicode name)
    U+1F92E🤮\:face_vomiting:(No Unicode name)
    U+1F92F🤯\:exploding_head:(No Unicode name)
    U+1F930🤰\:pregnant_woman:Pregnant Woman
    U+1F931🤱\:breast-feeding:(No Unicode name)
    U+1F932🤲\:palms_up_together:(No Unicode name)
    U+1F933🤳\:selfie:Selfie
    U+1F934🤴\:prince:Prince
    U+1F935🤵\:person_in_tuxedo:Man In Tuxedo
    U+1F936🤶\:mrs_claus:Mother Christmas
    U+1F937🤷\:shrug:Shrug
    U+1F938🤸\:person_doing_cartwheel:Person Doing Cartwheel
    U+1F939🤹\:juggling:Juggling
    U+1F93A🤺\:fencer:Fencer
    U+1F93C🤼\:wrestlers:Wrestlers
    U+1F93D🤽\:water_polo:Water Polo
    U+1F93E🤾\:handball:Handball
    U+1F93F🤿\:diving_mask:(No Unicode name)
    U+1F940🥀\:wilted_flower:Wilted Flower
    U+1F941🥁\:drum_with_drumsticks:Drum With Drumsticks
    U+1F942🥂\:clinking_glasses:Clinking Glasses
    U+1F943🥃\:tumbler_glass:Tumbler Glass
    U+1F944🥄\:spoon:Spoon
    U+1F945🥅\:goal_net:Goal Net
    U+1F947🥇\:first_place_medal:First Place Medal
    U+1F948🥈\:second_place_medal:Second Place Medal
    U+1F949🥉\:third_place_medal:Third Place Medal
    U+1F94A🥊\:boxing_glove:Boxing Glove
    U+1F94B🥋\:martial_arts_uniform:Martial Arts Uniform
    U+1F94C🥌\:curling_stone:(No Unicode name)
    U+1F94D🥍\:lacrosse:(No Unicode name)
    U+1F94E🥎\:softball:(No Unicode name)
    U+1F94F🥏\:flying_disc:(No Unicode name)
    U+1F950🥐\:croissant:Croissant
    U+1F951🥑\:avocado:Avocado
    U+1F952🥒\:cucumber:Cucumber
    U+1F953🥓\:bacon:Bacon
    U+1F954🥔\:potato:Potato
    U+1F955🥕\:carrot:Carrot
    U+1F956🥖\:baguette_bread:Baguette Bread
    U+1F957🥗\:green_salad:Green Salad
    U+1F958🥘\:shallow_pan_of_food:Shallow Pan Of Food
    U+1F959🥙\:stuffed_flatbread:Stuffed Flatbread
    U+1F95A🥚\:egg:Egg
    U+1F95B🥛\:glass_of_milk:Glass Of Milk
    U+1F95C🥜\:peanuts:Peanuts
    U+1F95D🥝\:kiwifruit:Kiwifruit
    U+1F95E🥞\:pancakes:Pancakes
    U+1F95F🥟\:dumpling:(No Unicode name)
    U+1F960🥠\:fortune_cookie:(No Unicode name)
    U+1F961🥡\:takeout_box:(No Unicode name)
    U+1F962🥢\:chopsticks:(No Unicode name)
    U+1F963🥣\:bowl_with_spoon:(No Unicode name)
    U+1F964🥤\:cup_with_straw:(No Unicode name)
    U+1F965🥥\:coconut:(No Unicode name)
    U+1F966🥦\:broccoli:(No Unicode name)
    U+1F967🥧\:pie:(No Unicode name)
    U+1F968🥨\:pretzel:(No Unicode name)
    U+1F969🥩\:cut_of_meat:(No Unicode name)
    U+1F96A🥪\:sandwich:(No Unicode name)
    U+1F96B🥫\:canned_food:(No Unicode name)
    U+1F96C🥬\:leafy_green:(No Unicode name)
    U+1F96D🥭\:mango:(No Unicode name)
    U+1F96E🥮\:moon_cake:(No Unicode name)
    U+1F96F🥯\:bagel:(No Unicode name)
    U+1F970🥰\:smiling_face_with_3_hearts:(No Unicode name)
    U+1F971🥱\:yawning_face:(No Unicode name)
    U+1F972🥲\:smiling_face_with_tear:(No Unicode name)
    U+1F973🥳\:partying_face:(No Unicode name)
    U+1F974🥴\:woozy_face:(No Unicode name)
    U+1F975🥵\:hot_face:(No Unicode name)
    U+1F976🥶\:cold_face:(No Unicode name)
    U+1F977🥷\:ninja:(No Unicode name)
    U+1F978🥸\:disguised_face:(No Unicode name)
    U+1F97A🥺\:pleading_face:(No Unicode name)
    U+1F97B🥻\:sari:(No Unicode name)
    U+1F97C🥼\:lab_coat:(No Unicode name)
    U+1F97D🥽\:goggles:(No Unicode name)
    U+1F97E🥾\:hiking_boot:(No Unicode name)
    U+1F97F🥿\:womans_flat_shoe:(No Unicode name)
    U+1F980🦀\:crab:Crab
    U+1F981🦁\:lion_face:Lion Face
    U+1F982🦂\:scorpion:Scorpion
    U+1F983🦃\:turkey:Turkey
    U+1F984🦄\:unicorn_face:Unicorn Face
    U+1F985🦅\:eagle:Eagle
    U+1F986🦆\:duck:Duck
    U+1F987🦇\:bat:Bat
    U+1F988🦈\:shark:Shark
    U+1F989🦉\:owl:Owl
    U+1F98A🦊\:fox_face:Fox Face
    U+1F98B🦋\:butterfly:Butterfly
    U+1F98C🦌\:deer:Deer
    U+1F98D🦍\:gorilla:Gorilla
    U+1F98E🦎\:lizard:Lizard
    U+1F98F🦏\:rhinoceros:Rhinoceros
    U+1F990🦐\:shrimp:Shrimp
    U+1F991🦑\:squid:Squid
    U+1F992🦒\:giraffe_face:(No Unicode name)
    U+1F993🦓\:zebra_face:(No Unicode name)
    U+1F994🦔\:hedgehog:(No Unicode name)
    U+1F995🦕\:sauropod:(No Unicode name)
    U+1F996🦖\:t-rex:(No Unicode name)
    U+1F997🦗\:cricket:(No Unicode name)
    U+1F998🦘\:kangaroo:(No Unicode name)
    U+1F999🦙\:llama:(No Unicode name)
    U+1F99A🦚\:peacock:(No Unicode name)
    U+1F99B🦛\:hippopotamus:(No Unicode name)
    U+1F99C🦜\:parrot:(No Unicode name)
    U+1F99D🦝\:raccoon:(No Unicode name)
    U+1F99E🦞\:lobster:(No Unicode name)
    U+1F99F🦟\:mosquito:(No Unicode name)
    U+1F9A0🦠\:microbe:(No Unicode name)
    U+1F9A1🦡\:badger:(No Unicode name)
    U+1F9A2🦢\:swan:(No Unicode name)
    U+1F9A3🦣\:mammoth:(No Unicode name)
    U+1F9A4🦤\:dodo:(No Unicode name)
    U+1F9A5🦥\:sloth:(No Unicode name)
    U+1F9A6🦦\:otter:(No Unicode name)
    U+1F9A7🦧\:orangutan:(No Unicode name)
    U+1F9A8🦨\:skunk:(No Unicode name)
    U+1F9A9🦩\:flamingo:(No Unicode name)
    U+1F9AA🦪\:oyster:(No Unicode name)
    U+1F9AB🦫\:beaver:(No Unicode name)
    U+1F9AC🦬\:bison:(No Unicode name)
    U+1F9AD🦭\:seal:(No Unicode name)
    U+1F9AE🦮\:guide_dog:(No Unicode name)
    U+1F9AF🦯\:probing_cane:(No Unicode name)
    U+1F9B4🦴\:bone:(No Unicode name)
    U+1F9B5🦵\:leg:(No Unicode name)
    U+1F9B6🦶\:foot:(No Unicode name)
    U+1F9B7🦷\:tooth:(No Unicode name)
    U+1F9B8🦸\:superhero:(No Unicode name)
    U+1F9B9🦹\:supervillain:(No Unicode name)
    U+1F9BA🦺\:safety_vest:(No Unicode name)
    U+1F9BB🦻\:ear_with_hearing_aid:(No Unicode name)
    U+1F9BC🦼\:motorized_wheelchair:(No Unicode name)
    U+1F9BD🦽\:manual_wheelchair:(No Unicode name)
    U+1F9BE🦾\:mechanical_arm:(No Unicode name)
    U+1F9BF🦿\:mechanical_leg:(No Unicode name)
    U+1F9C0🧀\:cheese_wedge:Cheese Wedge
    U+1F9C1🧁\:cupcake:(No Unicode name)
    U+1F9C2🧂\:salt:(No Unicode name)
    U+1F9C3🧃\:beverage_box:(No Unicode name)
    U+1F9C4🧄\:garlic:(No Unicode name)
    U+1F9C5🧅\:onion:(No Unicode name)
    U+1F9C6🧆\:falafel:(No Unicode name)
    U+1F9C7🧇\:waffle:(No Unicode name)
    U+1F9C8🧈\:butter:(No Unicode name)
    U+1F9C9🧉\:mate_drink:(No Unicode name)
    U+1F9CA🧊\:ice_cube:(No Unicode name)
    U+1F9CB🧋\:bubble_tea:(No Unicode name)
    U+1F9CD🧍\:standing_person:(No Unicode name)
    U+1F9CE🧎\:kneeling_person:(No Unicode name)
    U+1F9CF🧏\:deaf_person:(No Unicode name)
    U+1F9D0🧐\:face_with_monocle:(No Unicode name)
    U+1F9D1🧑\:adult:(No Unicode name)
    U+1F9D2🧒\:child:(No Unicode name)
    U+1F9D3🧓\:older_adult:(No Unicode name)
    U+1F9D4🧔\:bearded_person:(No Unicode name)
    U+1F9D5🧕\:person_with_headscarf:(No Unicode name)
    U+1F9D6🧖\:person_in_steamy_room:(No Unicode name)
    U+1F9D7🧗\:person_climbing:(No Unicode name)
    U+1F9D8🧘\:person_in_lotus_position:(No Unicode name)
    U+1F9D9🧙\:mage:(No Unicode name)
    U+1F9DA🧚\:fairy:(No Unicode name)
    U+1F9DB🧛\:vampire:(No Unicode name)
    U+1F9DC🧜\:merperson:(No Unicode name)
    U+1F9DD🧝\:elf:(No Unicode name)
    U+1F9DE🧞\:genie:(No Unicode name)
    U+1F9DF🧟\:zombie:(No Unicode name)
    U+1F9E0🧠\:brain:(No Unicode name)
    U+1F9E1🧡\:orange_heart:(No Unicode name)
    U+1F9E2🧢\:billed_cap:(No Unicode name)
    U+1F9E3🧣\:scarf:(No Unicode name)
    U+1F9E4🧤\:gloves:(No Unicode name)
    U+1F9E5🧥\:coat:(No Unicode name)
    U+1F9E6🧦\:socks:(No Unicode name)
    U+1F9E7🧧\:red_envelope:(No Unicode name)
    U+1F9E8🧨\:firecracker:(No Unicode name)
    U+1F9E9🧩\:jigsaw:(No Unicode name)
    U+1F9EA🧪\:test_tube:(No Unicode name)
    U+1F9EB🧫\:petri_dish:(No Unicode name)
    U+1F9EC🧬\:dna:(No Unicode name)
    U+1F9ED🧭\:compass:(No Unicode name)
    U+1F9EE🧮\:abacus:(No Unicode name)
    U+1F9EF🧯\:fire_extinguisher:(No Unicode name)
    U+1F9F0🧰\:toolbox:(No Unicode name)
    U+1F9F1🧱\:bricks:(No Unicode name)
    U+1F9F2🧲\:magnet:(No Unicode name)
    U+1F9F3🧳\:luggage:(No Unicode name)
    U+1F9F4🧴\:lotion_bottle:(No Unicode name)
    U+1F9F5🧵\:thread:(No Unicode name)
    U+1F9F6🧶\:yarn:(No Unicode name)
    U+1F9F7🧷\:safety_pin:(No Unicode name)
    U+1F9F8🧸\:teddy_bear:(No Unicode name)
    U+1F9F9🧹\:broom:(No Unicode name)
    U+1F9FA🧺\:basket:(No Unicode name)
    U+1F9FB🧻\:roll_of_paper:(No Unicode name)
    U+1F9FC🧼\:soap:(No Unicode name)
    U+1F9FD🧽\:sponge:(No Unicode name)
    U+1F9FE🧾\:receipt:(No Unicode name)
    U+1F9FF🧿\:nazar_amulet:(No Unicode name)
    U+1FA70🩰\:ballet_shoes:(No Unicode name)
    U+1FA71🩱\:one-piece_swimsuit:(No Unicode name)
    U+1FA72🩲\:briefs:(No Unicode name)
    U+1FA73🩳\:shorts:(No Unicode name)
    U+1FA74🩴\:thong_sandal:(No Unicode name)
    U+1FA78🩸\:drop_of_blood:(No Unicode name)
    U+1FA79🩹\:adhesive_bandage:(No Unicode name)
    U+1FA7A🩺\:stethoscope:(No Unicode name)
    U+1FA80🪀\:yo-yo:(No Unicode name)
    U+1FA81🪁\:kite:(No Unicode name)
    U+1FA82🪂\:parachute:(No Unicode name)
    U+1FA83🪃\:boomerang:(No Unicode name)
    U+1FA84🪄\:magic_wand:(No Unicode name)
    U+1FA85🪅\:pinata:(No Unicode name)
    U+1FA86🪆\:nesting_dolls:(No Unicode name)
    U+1FA90🪐\:ringed_planet:(No Unicode name)
    U+1FA91🪑\:chair:(No Unicode name)
    U+1FA92🪒\:razor:(No Unicode name)
    U+1FA93🪓\:axe:(No Unicode name)
    U+1FA94🪔\:diya_lamp:(No Unicode name)
    U+1FA95🪕\:banjo:(No Unicode name)
    U+1FA96🪖\:military_helmet:(No Unicode name)
    U+1FA97🪗\:accordion:(No Unicode name)
    U+1FA98🪘\:long_drum:(No Unicode name)
    U+1FA99🪙\:coin:(No Unicode name)
    U+1FA9A🪚\:carpentry_saw:(No Unicode name)
    U+1FA9B🪛\:screwdriver:(No Unicode name)
    U+1FA9C🪜\:ladder:(No Unicode name)
    U+1FA9D🪝\:hook:(No Unicode name)
    U+1FA9E🪞\:mirror:(No Unicode name)
    U+1FA9F🪟\:window:(No Unicode name)
    U+1FAA0🪠\:plunger:(No Unicode name)
    U+1FAA1🪡\:sewing_needle:(No Unicode name)
    U+1FAA2🪢\:knot:(No Unicode name)
    U+1FAA3🪣\:bucket:(No Unicode name)
    U+1FAA4🪤\:mouse_trap:(No Unicode name)
    U+1FAA5🪥\:toothbrush:(No Unicode name)
    U+1FAA6🪦\:headstone:(No Unicode name)
    U+1FAA7🪧\:placard:(No Unicode name)
    U+1FAA8🪨\:rock:(No Unicode name)
    U+1FAB0🪰\:fly:(No Unicode name)
    U+1FAB1🪱\:worm:(No Unicode name)
    U+1FAB2🪲\:beetle:(No Unicode name)
    U+1FAB3🪳\:cockroach:(No Unicode name)
    U+1FAB4🪴\:potted_plant:(No Unicode name)
    U+1FAB5🪵\:wood:(No Unicode name)
    U+1FAB6🪶\:feather:(No Unicode name)
    U+1FAC0🫀\:anatomical_heart:(No Unicode name)
    U+1FAC1🫁\:lungs:(No Unicode name)
    U+1FAC2🫂\:people_hugging:(No Unicode name)
    U+1FAD0🫐\:blueberries:(No Unicode name)
    U+1FAD1🫑\:bell_pepper:(No Unicode name)
    U+1FAD2🫒\:olive:(No Unicode name)
    U+1FAD3🫓\:flatbread:(No Unicode name)
    U+1FAD4🫔\:tamale:(No Unicode name)
    U+1FAD5🫕\:fondue:(No Unicode name)
    U+1FAD6🫖\:teapot:(No Unicode name)
    +

    Unicode 输入表

    在 Julia REPL 或其它编辑器中,可以像输入 LaTeX 符号一样,用 tab 补全下表列出的 Unicode 字符。在 REPL 中,可以先按 ? 进入帮助模式,然后将 Unicode 字符复制粘贴进去,一般在文档开头就会写输入方式。

    Warning

    此表第二列可能会缺失一些字符,对某些字符的显示效果也可能会与在 Julia REPL 中不一致。如果发生了这种状况,强烈建议用户检查一下浏览器或 REPL 的字体设置,目前已知很多字体都有显示问题。

    Code point(s)Character(s)Tab completion sequence(s)Unicode name(s)
    U+000A1¡\exclamdownInverted Exclamation Mark
    U+000A3£\sterlingPound Sign
    U+000A5¥\yenYen Sign
    U+000A6¦\brokenbarBroken Bar / Broken Vertical Bar
    U+000A7§\SSection Sign
    U+000A9©\copyright, \:copyright:Copyright Sign
    U+000AAª\ordfeminineFeminine Ordinal Indicator
    U+000AC¬\negNot Sign
    U+000AE®\circledR, \:registered:Registered Sign / Registered Trade Mark Sign
    U+000AF¯\highminusMacron / Spacing Macron
    U+000B0°\degreeDegree Sign
    U+000B1±\pmPlus-Minus Sign / Plus-Or-Minus Sign
    U+000B2²\^2Superscript Two / Superscript Digit Two
    U+000B3³\^3Superscript Three / Superscript Digit Three
    U+000B6\PPilcrow Sign / Paragraph Sign
    U+000B7·\cdotpMiddle Dot
    U+000B9¹\^1Superscript One / Superscript Digit One
    U+000BAº\ordmasculineMasculine Ordinal Indicator
    U+000BC¼\1/4Vulgar Fraction One Quarter / Fraction One Quarter
    U+000BD½\1/2Vulgar Fraction One Half / Fraction One Half
    U+000BE¾\3/4Vulgar Fraction Three Quarters / Fraction Three Quarters
    U+000BF¿\questiondownInverted Question Mark
    U+000C5Å\AALatin Capital Letter A With Ring Above / Latin Capital Letter A Ring
    U+000C6Æ\AELatin Capital Letter Ae / Latin Capital Letter A E
    U+000D0Ð\DHLatin Capital Letter Eth
    U+000D7×\timesMultiplication Sign
    U+000D8Ø\OLatin Capital Letter O With Stroke / Latin Capital Letter O Slash
    U+000DEÞ\THLatin Capital Letter Thorn
    U+000DFß\ssLatin Small Letter Sharp S
    U+000E5å\aaLatin Small Letter A With Ring Above / Latin Small Letter A Ring
    U+000E6æ\aeLatin Small Letter Ae / Latin Small Letter A E
    U+000F0ð\eth, \dhLatin Small Letter Eth
    U+000F7÷\divDivision Sign
    U+000F8ø\oLatin Small Letter O With Stroke / Latin Small Letter O Slash
    U+000FEþ\thLatin Small Letter Thorn
    U+00110Đ\DJLatin Capital Letter D With Stroke / Latin Capital Letter D Bar
    U+00111đ\djLatin Small Letter D With Stroke / Latin Small Letter D Bar
    U+00127ħ\hbarLatin Small Letter H With Stroke / Latin Small Letter H Bar
    U+00131ı\imathLatin Small Letter Dotless I
    U+00141Ł\LLatin Capital Letter L With Stroke / Latin Capital Letter L Slash
    U+00142ł\lLatin Small Letter L With Stroke / Latin Small Letter L Slash
    U+0014AŊ\NGLatin Capital Letter Eng
    U+0014Bŋ\ngLatin Small Letter Eng
    U+00152Œ\OELatin Capital Ligature Oe / Latin Capital Letter O E
    U+00153œ\oeLatin Small Ligature Oe / Latin Small Letter O E
    U+00195ƕ\hvligLatin Small Letter Hv / Latin Small Letter H V
    U+0019Eƞ\nrlegLatin Small Letter N With Long Right Leg
    U+001B5Ƶ\ZbarLatin Capital Letter Z With Stroke / Latin Capital Letter Z Bar
    U+001C2ǂ\doublepipeLatin Letter Alveolar Click / Latin Letter Pipe Double Bar
    U+00237ȷ\jmathLatin Small Letter Dotless J
    U+00250ɐ\trnaLatin Small Letter Turned A
    U+00252ɒ\trnsaLatin Small Letter Turned Alpha / Latin Small Letter Turned Script A
    U+00254ɔ\openoLatin Small Letter Open O
    U+00256ɖ\rtldLatin Small Letter D With Tail / Latin Small Letter D Retroflex Hook
    U+00259ə\schwaLatin Small Letter Schwa
    U+00263ɣ\pgammaLatin Small Letter Gamma
    U+00264ɤ\pbgamLatin Small Letter Rams Horn / Latin Small Letter Baby Gamma
    U+00265ɥ\trnhLatin Small Letter Turned H
    U+0026Cɬ\btdlLatin Small Letter L With Belt / Latin Small Letter L Belt
    U+0026Dɭ\rtllLatin Small Letter L With Retroflex Hook / Latin Small Letter L Retroflex Hook
    U+0026Fɯ\trnmLatin Small Letter Turned M
    U+00270ɰ\trnmlrLatin Small Letter Turned M With Long Leg
    U+00271ɱ\ltlmrLatin Small Letter M With Hook / Latin Small Letter M Hook
    U+00272ɲ\ltlnLatin Small Letter N With Left Hook / Latin Small Letter N Hook
    U+00273ɳ\rtlnLatin Small Letter N With Retroflex Hook / Latin Small Letter N Retroflex Hook
    U+00277ɷ\clomegLatin Small Letter Closed Omega
    U+00278ɸ\ltphiLatin Small Letter Phi
    U+00279ɹ\trnrLatin Small Letter Turned R
    U+0027Aɺ\trnrlLatin Small Letter Turned R With Long Leg
    U+0027Bɻ\rttrnrLatin Small Letter Turned R With Hook / Latin Small Letter Turned R Hook
    U+0027Cɼ\rlLatin Small Letter R With Long Leg
    U+0027Dɽ\rtlrLatin Small Letter R With Tail / Latin Small Letter R Hook
    U+0027Eɾ\fhrLatin Small Letter R With Fishhook / Latin Small Letter Fishhook R
    U+00282ʂ\rtlsLatin Small Letter S With Hook / Latin Small Letter S Hook
    U+00283ʃ\eshLatin Small Letter Esh
    U+00287ʇ\trntLatin Small Letter Turned T
    U+00288ʈ\rtltLatin Small Letter T With Retroflex Hook / Latin Small Letter T Retroflex Hook
    U+0028Aʊ\pupsilLatin Small Letter Upsilon
    U+0028Bʋ\pscrvLatin Small Letter V With Hook / Latin Small Letter Script V
    U+0028Cʌ\invvLatin Small Letter Turned V
    U+0028Dʍ\invwLatin Small Letter Turned W
    U+0028Eʎ\trnyLatin Small Letter Turned Y
    U+00290ʐ\rtlzLatin Small Letter Z With Retroflex Hook / Latin Small Letter Z Retroflex Hook
    U+00292ʒ\yoghLatin Small Letter Ezh / Latin Small Letter Yogh
    U+00294ʔ\glstLatin Letter Glottal Stop
    U+00295ʕ\reglstLatin Letter Pharyngeal Voiced Fricative / Latin Letter Reversed Glottal Stop
    U+00296ʖ\inglstLatin Letter Inverted Glottal Stop
    U+0029Eʞ\turnkLatin Small Letter Turned K
    U+002A4ʤ\dyoghLatin Small Letter Dezh Digraph / Latin Small Letter D Yogh
    U+002A7ʧ\teshLatin Small Letter Tesh Digraph / Latin Small Letter T Esh
    U+002B0ʰ\^hModifier Letter Small H
    U+002B2ʲ\^jModifier Letter Small J
    U+002B3ʳ\^rModifier Letter Small R
    U+002B7ʷ\^wModifier Letter Small W
    U+002B8ʸ\^yModifier Letter Small Y
    U+002BCʼ\raspModifier Letter Apostrophe
    U+002C8ˈ\vertsModifier Letter Vertical Line
    U+002CCˌ\vertiModifier Letter Low Vertical Line
    U+002D0ː\lmrkModifier Letter Triangular Colon
    U+002D1ˑ\hlmrkModifier Letter Half Triangular Colon
    U+002D2˒\sbrhrModifier Letter Centred Right Half Ring / Modifier Letter Centered Right Half Ring
    U+002D3˓\sblhrModifier Letter Centred Left Half Ring / Modifier Letter Centered Left Half Ring
    U+002D4˔\raisModifier Letter Up Tack
    U+002D5˕\lowModifier Letter Down Tack
    U+002D8˘\uBreve / Spacing Breve
    U+002DC˜\tildelowSmall Tilde / Spacing Tilde
    U+002E1ˡ\^lModifier Letter Small L
    U+002E2ˢ\^sModifier Letter Small S
    U+002E3ˣ\^xModifier Letter Small X
    U+00300 ̀ \graveCombining Grave Accent / Non-Spacing Grave
    U+00301 ́ \acuteCombining Acute Accent / Non-Spacing Acute
    U+00302 ̂ \hatCombining Circumflex Accent / Non-Spacing Circumflex
    U+00303 ̃ \tildeCombining Tilde / Non-Spacing Tilde
    U+00304 ̄ \barCombining Macron / Non-Spacing Macron
    U+00305 ̅ \overbarCombining Overline / Non-Spacing Overscore
    U+00306 ̆ \breveCombining Breve / Non-Spacing Breve
    U+00307 ̇ \dotCombining Dot Above / Non-Spacing Dot Above
    U+00308 ̈ \ddotCombining Diaeresis / Non-Spacing Diaeresis
    U+00309 ̉ \ovhookCombining Hook Above / Non-Spacing Hook Above
    U+0030A ̊ \ocircCombining Ring Above / Non-Spacing Ring Above
    U+0030B ̋ \HCombining Double Acute Accent / Non-Spacing Double Acute
    U+0030C ̌ \checkCombining Caron / Non-Spacing Hacek
    U+00310 ̐ \candraCombining Candrabindu / Non-Spacing Candrabindu
    U+00312 ̒ \oturnedcommaCombining Turned Comma Above / Non-Spacing Turned Comma Above
    U+00315 ̕ \ocommatoprightCombining Comma Above Right / Non-Spacing Comma Above Right
    U+0031A ̚ \droangCombining Left Angle Above / Non-Spacing Left Angle Above
    U+00321 ̡ \palhCombining Palatalized Hook Below / Non-Spacing Palatalized Hook Below
    U+00322 ̢ \rhCombining Retroflex Hook Below / Non-Spacing Retroflex Hook Below
    U+00327 ̧ \cCombining Cedilla / Non-Spacing Cedilla
    U+00328 ̨ \kCombining Ogonek / Non-Spacing Ogonek
    U+0032A ̪ \sbbrgCombining Bridge Below / Non-Spacing Bridge Below
    U+00330 ̰ \wideutildeCombining Tilde Below / Non-Spacing Tilde Below
    U+00332 ̲ \underbarCombining Low Line / Non-Spacing Underscore
    U+00336 ̶ \strike, \soutCombining Long Stroke Overlay / Non-Spacing Long Bar Overlay
    U+00338 ̸ \notCombining Long Solidus Overlay / Non-Spacing Long Slash Overlay
    U+0034D ͍ \underleftrightarrowCombining Left Right Arrow Below
    U+00391Α\AlphaGreek Capital Letter Alpha
    U+00392Β\BetaGreek Capital Letter Beta
    U+00393Γ\GammaGreek Capital Letter Gamma
    U+00394Δ\DeltaGreek Capital Letter Delta
    U+00395Ε\EpsilonGreek Capital Letter Epsilon
    U+00396Ζ\ZetaGreek Capital Letter Zeta
    U+00397Η\EtaGreek Capital Letter Eta
    U+00398Θ\ThetaGreek Capital Letter Theta
    U+00399Ι\IotaGreek Capital Letter Iota
    U+0039AΚ\KappaGreek Capital Letter Kappa
    U+0039BΛ\LambdaGreek Capital Letter Lamda / Greek Capital Letter Lambda
    U+0039CΜ\upMuGreek Capital Letter Mu
    U+0039DΝ\upNuGreek Capital Letter Nu
    U+0039EΞ\XiGreek Capital Letter Xi
    U+0039FΟ\upOmicronGreek Capital Letter Omicron
    U+003A0Π\PiGreek Capital Letter Pi
    U+003A1Ρ\RhoGreek Capital Letter Rho
    U+003A3Σ\SigmaGreek Capital Letter Sigma
    U+003A4Τ\TauGreek Capital Letter Tau
    U+003A5Υ\UpsilonGreek Capital Letter Upsilon
    U+003A6Φ\PhiGreek Capital Letter Phi
    U+003A7Χ\ChiGreek Capital Letter Chi
    U+003A8Ψ\PsiGreek Capital Letter Psi
    U+003A9Ω\OmegaGreek Capital Letter Omega
    U+003B1α\alphaGreek Small Letter Alpha
    U+003B2β\betaGreek Small Letter Beta
    U+003B3γ\gammaGreek Small Letter Gamma
    U+003B4δ\deltaGreek Small Letter Delta
    U+003B5ε\upepsilon, \varepsilonGreek Small Letter Epsilon
    U+003B6ζ\zetaGreek Small Letter Zeta
    U+003B7η\etaGreek Small Letter Eta
    U+003B8θ\thetaGreek Small Letter Theta
    U+003B9ι\iotaGreek Small Letter Iota
    U+003BAκ\kappaGreek Small Letter Kappa
    U+003BBλ\lambdaGreek Small Letter Lamda / Greek Small Letter Lambda
    U+003BCμ\muGreek Small Letter Mu
    U+003BDν\nuGreek Small Letter Nu
    U+003BEξ\xiGreek Small Letter Xi
    U+003BFο\upomicronGreek Small Letter Omicron
    U+003C0π\piGreek Small Letter Pi
    U+003C1ρ\rhoGreek Small Letter Rho
    U+003C2ς\varsigmaGreek Small Letter Final Sigma
    U+003C3σ\sigmaGreek Small Letter Sigma
    U+003C4τ\tauGreek Small Letter Tau
    U+003C5υ\upsilonGreek Small Letter Upsilon
    U+003C6φ\varphiGreek Small Letter Phi
    U+003C7χ\chiGreek Small Letter Chi
    U+003C8ψ\psiGreek Small Letter Psi
    U+003C9ω\omegaGreek Small Letter Omega
    U+003D0ϐ\upvarbetaGreek Beta Symbol / Greek Small Letter Curled Beta
    U+003D1ϑ\varthetaGreek Theta Symbol / Greek Small Letter Script Theta
    U+003D5ϕ\phiGreek Phi Symbol / Greek Small Letter Script Phi
    U+003D6ϖ\varpiGreek Pi Symbol / Greek Small Letter Omega Pi
    U+003D8Ϙ\upoldKoppaGreek Letter Archaic Koppa
    U+003D9ϙ\upoldkoppaGreek Small Letter Archaic Koppa
    U+003DAϚ\StigmaGreek Letter Stigma / Greek Capital Letter Stigma
    U+003DBϛ\upstigmaGreek Small Letter Stigma
    U+003DCϜ\DigammaGreek Letter Digamma / Greek Capital Letter Digamma
    U+003DDϝ\digammaGreek Small Letter Digamma
    U+003DEϞ\KoppaGreek Letter Koppa / Greek Capital Letter Koppa
    U+003DFϟ\upkoppaGreek Small Letter Koppa
    U+003E0Ϡ\SampiGreek Letter Sampi / Greek Capital Letter Sampi
    U+003E1ϡ\upsampiGreek Small Letter Sampi
    U+003F0ϰ\varkappaGreek Kappa Symbol / Greek Small Letter Script Kappa
    U+003F1ϱ\varrhoGreek Rho Symbol / Greek Small Letter Tailed Rho
    U+003F4ϴ\varThetaGreek Capital Theta Symbol
    U+003F5ϵ\epsilonGreek Lunate Epsilon Symbol
    U+003F6϶\backepsilonGreek Reversed Lunate Epsilon Symbol
    U+01D2C\^AModifier Letter Capital A
    U+01D2E\^BModifier Letter Capital B
    U+01D30\^DModifier Letter Capital D
    U+01D31\^EModifier Letter Capital E
    U+01D33\^GModifier Letter Capital G
    U+01D34\^HModifier Letter Capital H
    U+01D35\^IModifier Letter Capital I
    U+01D36\^JModifier Letter Capital J
    U+01D37\^KModifier Letter Capital K
    U+01D38\^LModifier Letter Capital L
    U+01D39\^MModifier Letter Capital M
    U+01D3A\^NModifier Letter Capital N
    U+01D3C\^OModifier Letter Capital O
    U+01D3E\^PModifier Letter Capital P
    U+01D3Fᴿ\^RModifier Letter Capital R
    U+01D40\^TModifier Letter Capital T
    U+01D41\^UModifier Letter Capital U
    U+01D42\^WModifier Letter Capital W
    U+01D43\^aModifier Letter Small A
    U+01D45\^alphaModifier Letter Small Alpha
    U+01D47\^bModifier Letter Small B
    U+01D48\^dModifier Letter Small D
    U+01D49\^eModifier Letter Small E
    U+01D4B\^epsilonModifier Letter Small Open E
    U+01D4D\^gModifier Letter Small G
    U+01D4F\^kModifier Letter Small K
    U+01D50\^mModifier Letter Small M
    U+01D52\^oModifier Letter Small O
    U+01D56\^pModifier Letter Small P
    U+01D57\^tModifier Letter Small T
    U+01D58\^uModifier Letter Small U
    U+01D5B\^vModifier Letter Small V
    U+01D5D\^betaModifier Letter Small Beta
    U+01D5E\^gammaModifier Letter Small Greek Gamma
    U+01D5F\^deltaModifier Letter Small Delta
    U+01D60\^phiModifier Letter Small Greek Phi
    U+01D61\^chiModifier Letter Small Chi
    U+01D62\_iLatin Subscript Small Letter I
    U+01D63\_rLatin Subscript Small Letter R
    U+01D64\_uLatin Subscript Small Letter U
    U+01D65\_vLatin Subscript Small Letter V
    U+01D66\_betaGreek Subscript Small Letter Beta
    U+01D67\_gammaGreek Subscript Small Letter Gamma
    U+01D68\_rhoGreek Subscript Small Letter Rho
    U+01D69\_phiGreek Subscript Small Letter Phi
    U+01D6A\_chiGreek Subscript Small Letter Chi
    U+01D9C\^cModifier Letter Small C
    U+01DA0\^fModifier Letter Small F
    U+01DA5\^iotaModifier Letter Small Iota
    U+01DB2\^ltphiModifier Letter Small Phi
    U+01DBB\^zModifier Letter Small Z
    U+01DBFᶿ\^thetaModifier Letter Small Theta
    U+02002\enspaceEn Space
    U+02003\quadEm Space
    U+02005\thickspaceFour-Per-Em Space
    U+02009\thinspaceThin Space
    U+0200A\hspaceHair Space
    U+02013\endashEn Dash
    U+02014\emdashEm Dash
    U+02016\VertDouble Vertical Line / Double Vertical Bar
    U+02018\lqLeft Single Quotation Mark / Single Turned Comma Quotation Mark
    U+02019\rqRight Single Quotation Mark / Single Comma Quotation Mark
    U+0201B\reaposSingle High-Reversed-9 Quotation Mark / Single Reversed Comma Quotation Mark
    U+0201C\ldqLeft Double Quotation Mark / Double Turned Comma Quotation Mark
    U+0201D\rdqRight Double Quotation Mark / Double Comma Quotation Mark
    U+02020\daggerDagger
    U+02021\ddaggerDouble Dagger
    U+02022\bulletBullet
    U+02026\dots, \ldotsHorizontal Ellipsis
    U+02030\perthousandPer Mille Sign
    U+02031\pertenthousandPer Ten Thousand Sign
    U+02032\primePrime
    U+02033\pprimeDouble Prime
    U+02034\ppprimeTriple Prime
    U+02035\backprimeReversed Prime
    U+02036\backpprimeReversed Double Prime
    U+02037\backppprimeReversed Triple Prime
    U+02039\guilsinglleftSingle Left-Pointing Angle Quotation Mark / Left Pointing Single Guillemet
    U+0203A\guilsinglrightSingle Right-Pointing Angle Quotation Mark / Right Pointing Single Guillemet
    U+0203C\:bangbang:Double Exclamation Mark
    U+02040\tieconcatCharacter Tie
    U+02049\:interrobang:Exclamation Question Mark
    U+02057\pppprimeQuadruple Prime
    U+0205D\tricolonTricolon
    U+02060\nolinebreakWord Joiner
    U+02070\^0Superscript Zero / Superscript Digit Zero
    U+02071\^iSuperscript Latin Small Letter I
    U+02074\^4Superscript Four / Superscript Digit Four
    U+02075\^5Superscript Five / Superscript Digit Five
    U+02076\^6Superscript Six / Superscript Digit Six
    U+02077\^7Superscript Seven / Superscript Digit Seven
    U+02078\^8Superscript Eight / Superscript Digit Eight
    U+02079\^9Superscript Nine / Superscript Digit Nine
    U+0207A\^+Superscript Plus Sign
    U+0207B\^-Superscript Minus / Superscript Hyphen-Minus
    U+0207C\^=Superscript Equals Sign
    U+0207D\^(Superscript Left Parenthesis / Superscript Opening Parenthesis
    U+0207E\^)Superscript Right Parenthesis / Superscript Closing Parenthesis
    U+0207F\^nSuperscript Latin Small Letter N
    U+02080\_0Subscript Zero / Subscript Digit Zero
    U+02081\_1Subscript One / Subscript Digit One
    U+02082\_2Subscript Two / Subscript Digit Two
    U+02083\_3Subscript Three / Subscript Digit Three
    U+02084\_4Subscript Four / Subscript Digit Four
    U+02085\_5Subscript Five / Subscript Digit Five
    U+02086\_6Subscript Six / Subscript Digit Six
    U+02087\_7Subscript Seven / Subscript Digit Seven
    U+02088\_8Subscript Eight / Subscript Digit Eight
    U+02089\_9Subscript Nine / Subscript Digit Nine
    U+0208A\_+Subscript Plus Sign
    U+0208B\_-Subscript Minus / Subscript Hyphen-Minus
    U+0208C\_=Subscript Equals Sign
    U+0208D\_(Subscript Left Parenthesis / Subscript Opening Parenthesis
    U+0208E\_)Subscript Right Parenthesis / Subscript Closing Parenthesis
    U+02090\_aLatin Subscript Small Letter A
    U+02091\_eLatin Subscript Small Letter E
    U+02092\_oLatin Subscript Small Letter O
    U+02093\_xLatin Subscript Small Letter X
    U+02094\_schwaLatin Subscript Small Letter Schwa
    U+02095\_hLatin Subscript Small Letter H
    U+02096\_kLatin Subscript Small Letter K
    U+02097\_lLatin Subscript Small Letter L
    U+02098\_mLatin Subscript Small Letter M
    U+02099\_nLatin Subscript Small Letter N
    U+0209A\_pLatin Subscript Small Letter P
    U+0209B\_sLatin Subscript Small Letter S
    U+0209C\_tLatin Subscript Small Letter T
    U+020A7\pesPeseta Sign
    U+020AC\euroEuro Sign
    U+020D0 ⃐ \leftharpoonaccentCombining Left Harpoon Above / Non-Spacing Left Harpoon Above
    U+020D1 ⃑ \rightharpoonaccentCombining Right Harpoon Above / Non-Spacing Right Harpoon Above
    U+020D2 ⃒ \vertoverlayCombining Long Vertical Line Overlay / Non-Spacing Long Vertical Bar Overlay
    U+020D6 ⃖ \overleftarrowCombining Left Arrow Above / Non-Spacing Left Arrow Above
    U+020D7 ⃗ \vecCombining Right Arrow Above / Non-Spacing Right Arrow Above
    U+020DB ⃛ \dddotCombining Three Dots Above / Non-Spacing Three Dots Above
    U+020DC ⃜ \ddddotCombining Four Dots Above / Non-Spacing Four Dots Above
    U+020DD ⃝ \enclosecircleCombining Enclosing Circle / Enclosing Circle
    U+020DE ⃞ \enclosesquareCombining Enclosing Square / Enclosing Square
    U+020DF ⃟ \enclosediamondCombining Enclosing Diamond / Enclosing Diamond
    U+020E1 ⃡ \overleftrightarrowCombining Left Right Arrow Above / Non-Spacing Left Right Arrow Above
    U+020E4 ⃤ \enclosetriangleCombining Enclosing Upward Pointing Triangle
    U+020E7 ⃧ \annuityCombining Annuity Symbol
    U+020E8 ⃨ \threeunderdotCombining Triple Underdot
    U+020E9 ⃩ \widebridgeaboveCombining Wide Bridge Above
    U+020EC ⃬ \underrightharpoondownCombining Rightwards Harpoon With Barb Downwards
    U+020ED ⃭ \underleftharpoondownCombining Leftwards Harpoon With Barb Downwards
    U+020EE ⃮ \underleftarrowCombining Left Arrow Below
    U+020EF ⃯ \underrightarrowCombining Right Arrow Below
    U+020F0 ⃰ \asteraccentCombining Asterisk Above
    U+02102\bbCDouble-Struck Capital C / Double-Struck C
    U+02107\eulermascheroniEuler Constant / Eulers
    U+0210A\scrgScript Small G
    U+0210B\scrHScript Capital H / Script H
    U+0210C\frakHBlack-Letter Capital H / Black-Letter H
    U+0210D\bbHDouble-Struck Capital H / Double-Struck H
    U+0210E\ith, \planckPlanck Constant
    U+0210F\hslashPlanck Constant Over Two Pi / Planck Constant Over 2 Pi
    U+02110\scrIScript Capital I / Script I
    U+02111\Im, \frakIBlack-Letter Capital I / Black-Letter I
    U+02112\scrLScript Capital L / Script L
    U+02113\ellScript Small L
    U+02115\bbNDouble-Struck Capital N / Double-Struck N
    U+02116\numeroNumero Sign / Numero
    U+02118\wpScript Capital P / Script P
    U+02119\bbPDouble-Struck Capital P / Double-Struck P
    U+0211A\bbQDouble-Struck Capital Q / Double-Struck Q
    U+0211B\scrRScript Capital R / Script R
    U+0211C\Re, \frakRBlack-Letter Capital R / Black-Letter R
    U+0211D\bbRDouble-Struck Capital R / Double-Struck R
    U+0211E\xratPrescription Take
    U+02122\trademark, \:tm:Trade Mark Sign / Trademark
    U+02124\bbZDouble-Struck Capital Z / Double-Struck Z
    U+02126\ohmOhm Sign / Ohm
    U+02127\mhoInverted Ohm Sign / Mho
    U+02128\frakZBlack-Letter Capital Z / Black-Letter Z
    U+02129\turnediotaTurned Greek Small Letter Iota
    U+0212B\AngstromAngstrom Sign / Angstrom Unit
    U+0212C\scrBScript Capital B / Script B
    U+0212D\frakCBlack-Letter Capital C / Black-Letter C
    U+0212F\scre, \eulerScript Small E
    U+02130\scrEScript Capital E / Script E
    U+02131\scrFScript Capital F / Script F
    U+02132\FinvTurned Capital F / Turned F
    U+02133\scrMScript Capital M / Script M
    U+02134\scroScript Small O
    U+02135\alephAlef Symbol / First Transfinite Cardinal
    U+02136\bethBet Symbol / Second Transfinite Cardinal
    U+02137\gimelGimel Symbol / Third Transfinite Cardinal
    U+02138\dalethDalet Symbol / Fourth Transfinite Cardinal
    U+02139\:information_source:Information Source
    U+0213C\bbpiDouble-Struck Small Pi
    U+0213D\bbgammaDouble-Struck Small Gamma
    U+0213E\bbGammaDouble-Struck Capital Gamma
    U+0213F\bbPiDouble-Struck Capital Pi
    U+02140\bbsumDouble-Struck N-Ary Summation
    U+02141\GameTurned Sans-Serif Capital G
    U+02142\sansLturnedTurned Sans-Serif Capital L
    U+02143\sansLmirroredReversed Sans-Serif Capital L
    U+02144\YupTurned Sans-Serif Capital Y
    U+02145\bbiDDouble-Struck Italic Capital D
    U+02146\bbidDouble-Struck Italic Small D
    U+02147\bbieDouble-Struck Italic Small E
    U+02148\bbiiDouble-Struck Italic Small I
    U+02149\bbijDouble-Struck Italic Small J
    U+0214A\PropertyLineProperty Line
    U+0214B\upandTurned Ampersand
    U+02150\1/7Vulgar Fraction One Seventh
    U+02151\1/9Vulgar Fraction One Ninth
    U+02152\1/10Vulgar Fraction One Tenth
    U+02153\1/3Vulgar Fraction One Third / Fraction One Third
    U+02154\2/3Vulgar Fraction Two Thirds / Fraction Two Thirds
    U+02155\1/5Vulgar Fraction One Fifth / Fraction One Fifth
    U+02156\2/5Vulgar Fraction Two Fifths / Fraction Two Fifths
    U+02157\3/5Vulgar Fraction Three Fifths / Fraction Three Fifths
    U+02158\4/5Vulgar Fraction Four Fifths / Fraction Four Fifths
    U+02159\1/6Vulgar Fraction One Sixth / Fraction One Sixth
    U+0215A\5/6Vulgar Fraction Five Sixths / Fraction Five Sixths
    U+0215B\1/8Vulgar Fraction One Eighth / Fraction One Eighth
    U+0215C\3/8Vulgar Fraction Three Eighths / Fraction Three Eighths
    U+0215D\5/8Vulgar Fraction Five Eighths / Fraction Five Eighths
    U+0215E\7/8Vulgar Fraction Seven Eighths / Fraction Seven Eighths
    U+0215F\1/Fraction Numerator One
    U+02189\0/3Vulgar Fraction Zero Thirds
    U+02190\leftarrowLeftwards Arrow / Left Arrow
    U+02191\uparrowUpwards Arrow / Up Arrow
    U+02192\to, \rightarrowRightwards Arrow / Right Arrow
    U+02193\downarrowDownwards Arrow / Down Arrow
    U+02194\leftrightarrow, \:left_right_arrow:Left Right Arrow
    U+02195\updownarrow, \:arrow_up_down:Up Down Arrow
    U+02196\nwarrow, \:arrow_upper_left:North West Arrow / Upper Left Arrow
    U+02197\nearrow, \:arrow_upper_right:North East Arrow / Upper Right Arrow
    U+02198\searrow, \:arrow_lower_right:South East Arrow / Lower Right Arrow
    U+02199\swarrow, \:arrow_lower_left:South West Arrow / Lower Left Arrow
    U+0219A\nleftarrowLeftwards Arrow With Stroke / Left Arrow With Stroke
    U+0219B\nrightarrowRightwards Arrow With Stroke / Right Arrow With Stroke
    U+0219C\leftwavearrowLeftwards Wave Arrow / Left Wave Arrow
    U+0219D\rightwavearrowRightwards Wave Arrow / Right Wave Arrow
    U+0219E\twoheadleftarrowLeftwards Two Headed Arrow / Left Two Headed Arrow
    U+0219F\twoheaduparrowUpwards Two Headed Arrow / Up Two Headed Arrow
    U+021A0\twoheadrightarrowRightwards Two Headed Arrow / Right Two Headed Arrow
    U+021A1\twoheaddownarrowDownwards Two Headed Arrow / Down Two Headed Arrow
    U+021A2\leftarrowtailLeftwards Arrow With Tail / Left Arrow With Tail
    U+021A3\rightarrowtailRightwards Arrow With Tail / Right Arrow With Tail
    U+021A4\mapsfromLeftwards Arrow From Bar / Left Arrow From Bar
    U+021A5\mapsupUpwards Arrow From Bar / Up Arrow From Bar
    U+021A6\mapstoRightwards Arrow From Bar / Right Arrow From Bar
    U+021A7\mapsdownDownwards Arrow From Bar / Down Arrow From Bar
    U+021A8\updownarrowbarUp Down Arrow With Base
    U+021A9\hookleftarrow, \:leftwards_arrow_with_hook:Leftwards Arrow With Hook / Left Arrow With Hook
    U+021AA\hookrightarrow, \:arrow_right_hook:Rightwards Arrow With Hook / Right Arrow With Hook
    U+021AB\looparrowleftLeftwards Arrow With Loop / Left Arrow With Loop
    U+021AC\looparrowrightRightwards Arrow With Loop / Right Arrow With Loop
    U+021AD\leftrightsquigarrowLeft Right Wave Arrow
    U+021AE\nleftrightarrowLeft Right Arrow With Stroke
    U+021AF\downzigzagarrowDownwards Zigzag Arrow / Down Zigzag Arrow
    U+021B0\LshUpwards Arrow With Tip Leftwards / Up Arrow With Tip Left
    U+021B1\RshUpwards Arrow With Tip Rightwards / Up Arrow With Tip Right
    U+021B2\LdshDownwards Arrow With Tip Leftwards / Down Arrow With Tip Left
    U+021B3\RdshDownwards Arrow With Tip Rightwards / Down Arrow With Tip Right
    U+021B4\linefeedRightwards Arrow With Corner Downwards / Right Arrow With Corner Down
    U+021B5\carriagereturnDownwards Arrow With Corner Leftwards / Down Arrow With Corner Left
    U+021B6\curvearrowleftAnticlockwise Top Semicircle Arrow
    U+021B7\curvearrowrightClockwise Top Semicircle Arrow
    U+021B8\barovernorthwestarrowNorth West Arrow To Long Bar / Upper Left Arrow To Long Bar
    U+021B9\barleftarrowrightarrowbarLeftwards Arrow To Bar Over Rightwards Arrow To Bar / Left Arrow To Bar Over Right Arrow To Bar
    U+021BA\circlearrowleftAnticlockwise Open Circle Arrow
    U+021BB\circlearrowrightClockwise Open Circle Arrow
    U+021BC\leftharpoonupLeftwards Harpoon With Barb Upwards / Left Harpoon With Barb Up
    U+021BD\leftharpoondownLeftwards Harpoon With Barb Downwards / Left Harpoon With Barb Down
    U+021BE\upharpoonrightUpwards Harpoon With Barb Rightwards / Up Harpoon With Barb Right
    U+021BF\upharpoonleftUpwards Harpoon With Barb Leftwards / Up Harpoon With Barb Left
    U+021C0\rightharpoonupRightwards Harpoon With Barb Upwards / Right Harpoon With Barb Up
    U+021C1\rightharpoondownRightwards Harpoon With Barb Downwards / Right Harpoon With Barb Down
    U+021C2\downharpoonrightDownwards Harpoon With Barb Rightwards / Down Harpoon With Barb Right
    U+021C3\downharpoonleftDownwards Harpoon With Barb Leftwards / Down Harpoon With Barb Left
    U+021C4\rightleftarrowsRightwards Arrow Over Leftwards Arrow / Right Arrow Over Left Arrow
    U+021C5\dblarrowupdownUpwards Arrow Leftwards Of Downwards Arrow / Up Arrow Left Of Down Arrow
    U+021C6\leftrightarrowsLeftwards Arrow Over Rightwards Arrow / Left Arrow Over Right Arrow
    U+021C7\leftleftarrowsLeftwards Paired Arrows / Left Paired Arrows
    U+021C8\upuparrowsUpwards Paired Arrows / Up Paired Arrows
    U+021C9\rightrightarrowsRightwards Paired Arrows / Right Paired Arrows
    U+021CA\downdownarrowsDownwards Paired Arrows / Down Paired Arrows
    U+021CB\leftrightharpoonsLeftwards Harpoon Over Rightwards Harpoon / Left Harpoon Over Right Harpoon
    U+021CC\rightleftharpoonsRightwards Harpoon Over Leftwards Harpoon / Right Harpoon Over Left Harpoon
    U+021CD\nLeftarrowLeftwards Double Arrow With Stroke / Left Double Arrow With Stroke
    U+021CE\nLeftrightarrowLeft Right Double Arrow With Stroke
    U+021CF\nRightarrowRightwards Double Arrow With Stroke / Right Double Arrow With Stroke
    U+021D0\LeftarrowLeftwards Double Arrow / Left Double Arrow
    U+021D1\UparrowUpwards Double Arrow / Up Double Arrow
    U+021D2\RightarrowRightwards Double Arrow / Right Double Arrow
    U+021D3\DownarrowDownwards Double Arrow / Down Double Arrow
    U+021D4\LeftrightarrowLeft Right Double Arrow
    U+021D5\UpdownarrowUp Down Double Arrow
    U+021D6\NwarrowNorth West Double Arrow / Upper Left Double Arrow
    U+021D7\NearrowNorth East Double Arrow / Upper Right Double Arrow
    U+021D8\SearrowSouth East Double Arrow / Lower Right Double Arrow
    U+021D9\SwarrowSouth West Double Arrow / Lower Left Double Arrow
    U+021DA\LleftarrowLeftwards Triple Arrow / Left Triple Arrow
    U+021DB\RrightarrowRightwards Triple Arrow / Right Triple Arrow
    U+021DC\leftsquigarrowLeftwards Squiggle Arrow / Left Squiggle Arrow
    U+021DD\rightsquigarrowRightwards Squiggle Arrow / Right Squiggle Arrow
    U+021DE\nHuparrowUpwards Arrow With Double Stroke / Up Arrow With Double Stroke
    U+021DF\nHdownarrowDownwards Arrow With Double Stroke / Down Arrow With Double Stroke
    U+021E0\leftdasharrowLeftwards Dashed Arrow / Left Dashed Arrow
    U+021E1\updasharrowUpwards Dashed Arrow / Up Dashed Arrow
    U+021E2\rightdasharrowRightwards Dashed Arrow / Right Dashed Arrow
    U+021E3\downdasharrowDownwards Dashed Arrow / Down Dashed Arrow
    U+021E4\barleftarrowLeftwards Arrow To Bar / Left Arrow To Bar
    U+021E5\rightarrowbarRightwards Arrow To Bar / Right Arrow To Bar
    U+021E6\leftwhitearrowLeftwards White Arrow / White Left Arrow
    U+021E7\upwhitearrowUpwards White Arrow / White Up Arrow
    U+021E8\rightwhitearrowRightwards White Arrow / White Right Arrow
    U+021E9\downwhitearrowDownwards White Arrow / White Down Arrow
    U+021EA\whitearrowupfrombarUpwards White Arrow From Bar / White Up Arrow From Bar
    U+021F4\circleonrightarrowRight Arrow With Small Circle
    U+021F5\DownArrowUpArrowDownwards Arrow Leftwards Of Upwards Arrow
    U+021F6\rightthreearrowsThree Rightwards Arrows
    U+021F7\nvleftarrowLeftwards Arrow With Vertical Stroke
    U+021F8\nvrightarrowRightwards Arrow With Vertical Stroke
    U+021F9\nvleftrightarrowLeft Right Arrow With Vertical Stroke
    U+021FA\nVleftarrowLeftwards Arrow With Double Vertical Stroke
    U+021FB\nVrightarrowRightwards Arrow With Double Vertical Stroke
    U+021FC\nVleftrightarrowLeft Right Arrow With Double Vertical Stroke
    U+021FD\leftarrowtriangleLeftwards Open-Headed Arrow
    U+021FE\rightarrowtriangleRightwards Open-Headed Arrow
    U+021FF\leftrightarrowtriangleLeft Right Open-Headed Arrow
    U+02200\forallFor All
    U+02201\complementComplement
    U+02202\partialPartial Differential
    U+02203\existsThere Exists
    U+02204\nexistsThere Does Not Exist
    U+02205\varnothing, \emptysetEmpty Set
    U+02206\incrementIncrement
    U+02207\del, \nablaNabla
    U+02208\inElement Of
    U+02209\notinNot An Element Of
    U+0220A\smallinSmall Element Of
    U+0220B\niContains As Member
    U+0220C\nniDoes Not Contain As Member
    U+0220D\smallniSmall Contains As Member
    U+0220E\QEDEnd Of Proof
    U+0220F\prodN-Ary Product
    U+02210\coprodN-Ary Coproduct
    U+02211\sumN-Ary Summation
    U+02212\minusMinus Sign
    U+02213\mpMinus-Or-Plus Sign
    U+02214\dotplusDot Plus
    U+02216\setminusSet Minus
    U+02217\astAsterisk Operator
    U+02218\circRing Operator
    U+02219\vysmblkcircleBullet Operator
    U+0221A\surd, \sqrtSquare Root
    U+0221B\cbrtCube Root
    U+0221C\fourthrootFourth Root
    U+0221D\proptoProportional To
    U+0221E\inftyInfinity
    U+0221F\rightangleRight Angle
    U+02220\angleAngle
    U+02221\measuredangleMeasured Angle
    U+02222\sphericalangleSpherical Angle
    U+02223\midDivides
    U+02224\nmidDoes Not Divide
    U+02225\parallelParallel To
    U+02226\nparallelNot Parallel To
    U+02227\wedgeLogical And
    U+02228\veeLogical Or
    U+02229\capIntersection
    U+0222A\cupUnion
    U+0222B\intIntegral
    U+0222C\iintDouble Integral
    U+0222D\iiintTriple Integral
    U+0222E\ointContour Integral
    U+0222F\oiintSurface Integral
    U+02230\oiiintVolume Integral
    U+02231\clwintegralClockwise Integral
    U+02232\varointclockwiseClockwise Contour Integral
    U+02233\ointctrclockwiseAnticlockwise Contour Integral
    U+02234\thereforeTherefore
    U+02235\becauseBecause
    U+02237\ColonProportion
    U+02238\dotminusDot Minus
    U+0223A\dotsminusdotsGeometric Proportion
    U+0223B\kernelcontractionHomothetic
    U+0223C\simTilde Operator
    U+0223D\backsimReversed Tilde
    U+0223E\lazysinvInverted Lazy S
    U+0223F\sinewaveSine Wave
    U+02240\wrWreath Product
    U+02241\nsimNot Tilde
    U+02242\eqsimMinus Tilde
    U+02242 + U+00338≂̸\neqsimMinus Tilde + Combining Long Solidus Overlay / Non-Spacing Long Slash Overlay
    U+02243\simeqAsymptotically Equal To
    U+02244\nsimeNot Asymptotically Equal To
    U+02245\congApproximately Equal To
    U+02246\approxnotequalApproximately But Not Actually Equal To
    U+02247\ncongNeither Approximately Nor Actually Equal To
    U+02248\approxAlmost Equal To
    U+02249\napproxNot Almost Equal To
    U+0224A\approxeqAlmost Equal Or Equal To
    U+0224B\tildetrplTriple Tilde
    U+0224C\allequalAll Equal To
    U+0224D\asympEquivalent To
    U+0224E\BumpeqGeometrically Equivalent To
    U+0224E + U+00338≎̸\nBumpeqGeometrically Equivalent To + Combining Long Solidus Overlay / Non-Spacing Long Slash Overlay
    U+0224F\bumpeqDifference Between
    U+0224F + U+00338≏̸\nbumpeqDifference Between + Combining Long Solidus Overlay / Non-Spacing Long Slash Overlay
    U+02250\doteqApproaches The Limit
    U+02251\DoteqGeometrically Equal To
    U+02252\fallingdotseqApproximately Equal To Or The Image Of
    U+02253\risingdotseqImage Of Or Approximately Equal To
    U+02254\coloneqColon Equals / Colon Equal
    U+02255\eqcolonEquals Colon / Equal Colon
    U+02256\eqcircRing In Equal To
    U+02257\circeqRing Equal To
    U+02258\arceqCorresponds To
    U+02259\wedgeqEstimates
    U+0225A\veeeqEquiangular To
    U+0225B\starequalStar Equals
    U+0225C\triangleqDelta Equal To
    U+0225D\eqdefEqual To By Definition
    U+0225E\measeqMeasured By
    U+0225F\questeqQuestioned Equal To
    U+02260\neNot Equal To
    U+02261\equivIdentical To
    U+02262\nequivNot Identical To
    U+02263\EquivStrictly Equivalent To
    U+02264\le, \leqLess-Than Or Equal To / Less Than Or Equal To
    U+02265\ge, \geqGreater-Than Or Equal To / Greater Than Or Equal To
    U+02266\leqqLess-Than Over Equal To / Less Than Over Equal To
    U+02267\geqqGreater-Than Over Equal To / Greater Than Over Equal To
    U+02268\lneqqLess-Than But Not Equal To / Less Than But Not Equal To
    U+02268 + U+0FE00≨︀\lvertneqqLess-Than But Not Equal To / Less Than But Not Equal To + Variation Selector-1
    U+02269\gneqqGreater-Than But Not Equal To / Greater Than But Not Equal To
    U+02269 + U+0FE00≩︀\gvertneqqGreater-Than But Not Equal To / Greater Than But Not Equal To + Variation Selector-1
    U+0226A\llMuch Less-Than / Much Less Than
    U+0226A + U+00338≪̸\NotLessLessMuch Less-Than / Much Less Than + Combining Long Solidus Overlay / Non-Spacing Long Slash Overlay
    U+0226B\ggMuch Greater-Than / Much Greater Than
    U+0226B + U+00338≫̸\NotGreaterGreaterMuch Greater-Than / Much Greater Than + Combining Long Solidus Overlay / Non-Spacing Long Slash Overlay
    U+0226C\betweenBetween
    U+0226D\nasympNot Equivalent To
    U+0226E\nlessNot Less-Than / Not Less Than
    U+0226F\ngtrNot Greater-Than / Not Greater Than
    U+02270\nleqNeither Less-Than Nor Equal To / Neither Less Than Nor Equal To
    U+02271\ngeqNeither Greater-Than Nor Equal To / Neither Greater Than Nor Equal To
    U+02272\lesssimLess-Than Or Equivalent To / Less Than Or Equivalent To
    U+02273\gtrsimGreater-Than Or Equivalent To / Greater Than Or Equivalent To
    U+02274\nlesssimNeither Less-Than Nor Equivalent To / Neither Less Than Nor Equivalent To
    U+02275\ngtrsimNeither Greater-Than Nor Equivalent To / Neither Greater Than Nor Equivalent To
    U+02276\lessgtrLess-Than Or Greater-Than / Less Than Or Greater Than
    U+02277\gtrlessGreater-Than Or Less-Than / Greater Than Or Less Than
    U+02278\notlessgreaterNeither Less-Than Nor Greater-Than / Neither Less Than Nor Greater Than
    U+02279\notgreaterlessNeither Greater-Than Nor Less-Than / Neither Greater Than Nor Less Than
    U+0227A\precPrecedes
    U+0227B\succSucceeds
    U+0227C\preccurlyeqPrecedes Or Equal To
    U+0227D\succcurlyeqSucceeds Or Equal To
    U+0227E\precsimPrecedes Or Equivalent To
    U+0227E + U+00338≾̸\nprecsimPrecedes Or Equivalent To + Combining Long Solidus Overlay / Non-Spacing Long Slash Overlay
    U+0227F\succsimSucceeds Or Equivalent To
    U+0227F + U+00338≿̸\nsuccsimSucceeds Or Equivalent To + Combining Long Solidus Overlay / Non-Spacing Long Slash Overlay
    U+02280\nprecDoes Not Precede
    U+02281\nsuccDoes Not Succeed
    U+02282\subsetSubset Of
    U+02283\supsetSuperset Of
    U+02284\nsubsetNot A Subset Of
    U+02285\nsupsetNot A Superset Of
    U+02286\subseteqSubset Of Or Equal To
    U+02287\supseteqSuperset Of Or Equal To
    U+02288\nsubseteqNeither A Subset Of Nor Equal To
    U+02289\nsupseteqNeither A Superset Of Nor Equal To
    U+0228A\subsetneqSubset Of With Not Equal To / Subset Of Or Not Equal To
    U+0228A + U+0FE00⊊︀\varsubsetneqqSubset Of With Not Equal To / Subset Of Or Not Equal To + Variation Selector-1
    U+0228B\supsetneqSuperset Of With Not Equal To / Superset Of Or Not Equal To
    U+0228B + U+0FE00⊋︀\varsupsetneqSuperset Of With Not Equal To / Superset Of Or Not Equal To + Variation Selector-1
    U+0228D\cupdotMultiset Multiplication
    U+0228E\uplusMultiset Union
    U+0228F\sqsubsetSquare Image Of
    U+0228F + U+00338⊏̸\NotSquareSubsetSquare Image Of + Combining Long Solidus Overlay / Non-Spacing Long Slash Overlay
    U+02290\sqsupsetSquare Original Of
    U+02290 + U+00338⊐̸\NotSquareSupersetSquare Original Of + Combining Long Solidus Overlay / Non-Spacing Long Slash Overlay
    U+02291\sqsubseteqSquare Image Of Or Equal To
    U+02292\sqsupseteqSquare Original Of Or Equal To
    U+02293\sqcapSquare Cap
    U+02294\sqcupSquare Cup
    U+02295\oplusCircled Plus
    U+02296\ominusCircled Minus
    U+02297\otimesCircled Times
    U+02298\oslashCircled Division Slash
    U+02299\odotCircled Dot Operator
    U+0229A\circledcircCircled Ring Operator
    U+0229B\circledastCircled Asterisk Operator
    U+0229C\circledequalCircled Equals
    U+0229D\circleddashCircled Dash
    U+0229E\boxplusSquared Plus
    U+0229F\boxminusSquared Minus
    U+022A0\boxtimesSquared Times
    U+022A1\boxdotSquared Dot Operator
    U+022A2\vdashRight Tack
    U+022A3\dashvLeft Tack
    U+022A4\topDown Tack
    U+022A5\botUp Tack
    U+022A7\modelsModels
    U+022A8\vDashTrue
    U+022A9\VdashForces
    U+022AA\VvdashTriple Vertical Bar Right Turnstile
    U+022AB\VDashDouble Vertical Bar Double Right Turnstile
    U+022AC\nvdashDoes Not Prove
    U+022AD\nvDashNot True
    U+022AE\nVdashDoes Not Force
    U+022AF\nVDashNegated Double Vertical Bar Double Right Turnstile
    U+022B0\prurelPrecedes Under Relation
    U+022B1\scurelSucceeds Under Relation
    U+022B2\vartriangleleftNormal Subgroup Of
    U+022B3\vartrianglerightContains As Normal Subgroup
    U+022B4\trianglelefteqNormal Subgroup Of Or Equal To
    U+022B5\trianglerighteqContains As Normal Subgroup Or Equal To
    U+022B6\originalOriginal Of
    U+022B7\imageImage Of
    U+022B8\multimapMultimap
    U+022B9\hermitconjmatrixHermitian Conjugate Matrix
    U+022BA\intercalIntercalate
    U+022BB\veebar, \xorXor
    U+022BC\barwedge, \nandNand
    U+022BD\barvee, \norNor
    U+022BE\rightanglearcRight Angle With Arc
    U+022BF\varlrtriangleRight Triangle
    U+022C0\bigwedgeN-Ary Logical And
    U+022C1\bigveeN-Ary Logical Or
    U+022C2\bigcapN-Ary Intersection
    U+022C3\bigcupN-Ary Union
    U+022C4\diamondDiamond Operator
    U+022C5\cdotDot Operator
    U+022C6\starStar Operator
    U+022C7\divideontimesDivision Times
    U+022C8\bowtieBowtie
    U+022C9\ltimesLeft Normal Factor Semidirect Product
    U+022CA\rtimesRight Normal Factor Semidirect Product
    U+022CB\leftthreetimesLeft Semidirect Product
    U+022CC\rightthreetimesRight Semidirect Product
    U+022CD\backsimeqReversed Tilde Equals
    U+022CE\curlyveeCurly Logical Or
    U+022CF\curlywedgeCurly Logical And
    U+022D0\SubsetDouble Subset
    U+022D1\SupsetDouble Superset
    U+022D2\CapDouble Intersection
    U+022D3\CupDouble Union
    U+022D4\pitchforkPitchfork
    U+022D5\equalparallelEqual And Parallel To
    U+022D6\lessdotLess-Than With Dot / Less Than With Dot
    U+022D7\gtrdotGreater-Than With Dot / Greater Than With Dot
    U+022D8\verymuchlessVery Much Less-Than / Very Much Less Than
    U+022D9\gggVery Much Greater-Than / Very Much Greater Than
    U+022DA\lesseqgtrLess-Than Equal To Or Greater-Than / Less Than Equal To Or Greater Than
    U+022DB\gtreqlessGreater-Than Equal To Or Less-Than / Greater Than Equal To Or Less Than
    U+022DC\eqlessEqual To Or Less-Than / Equal To Or Less Than
    U+022DD\eqgtrEqual To Or Greater-Than / Equal To Or Greater Than
    U+022DE\curlyeqprecEqual To Or Precedes
    U+022DF\curlyeqsuccEqual To Or Succeeds
    U+022E0\npreccurlyeqDoes Not Precede Or Equal
    U+022E1\nsucccurlyeqDoes Not Succeed Or Equal
    U+022E2\nsqsubseteqNot Square Image Of Or Equal To
    U+022E3\nsqsupseteqNot Square Original Of Or Equal To
    U+022E4\sqsubsetneqSquare Image Of Or Not Equal To
    U+022E5\sqspneSquare Original Of Or Not Equal To
    U+022E6\lnsimLess-Than But Not Equivalent To / Less Than But Not Equivalent To
    U+022E7\gnsimGreater-Than But Not Equivalent To / Greater Than But Not Equivalent To
    U+022E8\precnsimPrecedes But Not Equivalent To
    U+022E9\succnsimSucceeds But Not Equivalent To
    U+022EA\ntriangleleftNot Normal Subgroup Of
    U+022EB\ntrianglerightDoes Not Contain As Normal Subgroup
    U+022EC\ntrianglelefteqNot Normal Subgroup Of Or Equal To
    U+022ED\ntrianglerighteqDoes Not Contain As Normal Subgroup Or Equal
    U+022EE\vdotsVertical Ellipsis
    U+022EF\cdotsMidline Horizontal Ellipsis
    U+022F0\adotsUp Right Diagonal Ellipsis
    U+022F1\ddotsDown Right Diagonal Ellipsis
    U+022F2\disinElement Of With Long Horizontal Stroke
    U+022F3\varisinsElement Of With Vertical Bar At End Of Horizontal Stroke
    U+022F4\isinsSmall Element Of With Vertical Bar At End Of Horizontal Stroke
    U+022F5\isindotElement Of With Dot Above
    U+022F6\varisinobarElement Of With Overbar
    U+022F7\isinobarSmall Element Of With Overbar
    U+022F8\isinvbElement Of With Underbar
    U+022F9\isinEElement Of With Two Horizontal Strokes
    U+022FA\nisdContains With Long Horizontal Stroke
    U+022FB\varnisContains With Vertical Bar At End Of Horizontal Stroke
    U+022FC\nisSmall Contains With Vertical Bar At End Of Horizontal Stroke
    U+022FD\varniobarContains With Overbar
    U+022FE\niobarSmall Contains With Overbar
    U+022FF\bagmemberZ Notation Bag Membership
    U+02300\diameterDiameter Sign
    U+02302\houseHouse
    U+02305\varbarwedgeProjective
    U+02306\vardoublebarwedgePerspective
    U+02308\lceilLeft Ceiling
    U+02309\rceilRight Ceiling
    U+0230A\lfloorLeft Floor
    U+0230B\rfloorRight Floor
    U+02310\invnotReversed Not Sign
    U+02311\sqlozengeSquare Lozenge
    U+02312\proflineArc
    U+02313\profsurfSegment
    U+02315\recorderTelephone Recorder
    U+02317\viewdataViewdata Square
    U+02319\turnednotTurned Not Sign
    U+0231A\:watch:Watch
    U+0231B\:hourglass:Hourglass
    U+0231C\ulcornerTop Left Corner
    U+0231D\urcornerTop Right Corner
    U+0231E\llcornerBottom Left Corner
    U+0231F\lrcornerBottom Right Corner
    U+02322\frownFrown
    U+02323\smileSmile
    U+0232C\varhexagonlrbondsBenzene Ring
    U+02332\conictaperConical Taper
    U+02336\topbotApl Functional Symbol I-Beam
    U+0233D\obarApl Functional Symbol Circle Stile
    U+0233F\notslashApl Functional Symbol Slash Bar
    U+02340\notbackslashApl Functional Symbol Backslash Bar
    U+02353\boxupcaretApl Functional Symbol Quad Up Caret
    U+02370\boxquestionApl Functional Symbol Quad Question
    U+02394\hexagonSoftware-Function Symbol
    U+023A3\dlcornLeft Square Bracket Lower Corner
    U+023B0\lmoustacheUpper Left Or Lower Right Curly Bracket Section
    U+023B1\rmoustacheUpper Right Or Lower Left Curly Bracket Section
    U+023B4\overbracketTop Square Bracket
    U+023B5\underbracketBottom Square Bracket
    U+023B6\bbrktbrkBottom Square Bracket Over Top Square Bracket
    U+023B7\sqrtbottomRadical Symbol Bottom
    U+023B8\lvboxlineLeft Vertical Box Line
    U+023B9\rvboxlineRight Vertical Box Line
    U+023CE\varcarriagereturnReturn Symbol
    U+023DE\overbraceTop Curly Bracket
    U+023DF\underbraceBottom Curly Bracket
    U+023E2\trapeziumWhite Trapezium
    U+023E3\benzenrBenzene Ring With Circle
    U+023E4\strnsStraightness
    U+023E5\fltnsFlatness
    U+023E6\accurrentAc Current
    U+023E7\elintersElectrical Intersection
    U+023E9\:fast_forward:Black Right-Pointing Double Triangle
    U+023EA\:rewind:Black Left-Pointing Double Triangle
    U+023EB\:arrow_double_up:Black Up-Pointing Double Triangle
    U+023EC\:arrow_double_down:Black Down-Pointing Double Triangle
    U+023F0\:alarm_clock:Alarm Clock
    U+023F3\:hourglass_flowing_sand:Hourglass With Flowing Sand
    U+02422\blanksymbolBlank Symbol / Blank
    U+02423\visiblespaceOpen Box
    U+024C2\:m:Circled Latin Capital Letter M
    U+024C8\circledSCircled Latin Capital Letter S
    U+02506\dshfncBox Drawings Light Triple Dash Vertical / Forms Light Triple Dash Vertical
    U+02519\sqfnwBox Drawings Up Light And Left Heavy / Forms Up Light And Left Heavy
    U+02571\diagupBox Drawings Light Diagonal Upper Right To Lower Left / Forms Light Diagonal Upper Right To Lower Left
    U+02572\diagdownBox Drawings Light Diagonal Upper Left To Lower Right / Forms Light Diagonal Upper Left To Lower Right
    U+02580\blockuphalfUpper Half Block
    U+02584\blocklowhalfLower Half Block
    U+02588\blockfullFull Block
    U+0258C\blocklefthalfLeft Half Block
    U+02590\blockrighthalfRight Half Block
    U+02591\blockqtrshadedLight Shade
    U+02592\blockhalfshadedMedium Shade
    U+02593\blockthreeqtrshadedDark Shade
    U+025A0\blacksquareBlack Square
    U+025A1\squareWhite Square
    U+025A2\squovalWhite Square With Rounded Corners
    U+025A3\blackinwhitesquareWhite Square Containing Black Small Square
    U+025A4\squarehfillSquare With Horizontal Fill
    U+025A5\squarevfillSquare With Vertical Fill
    U+025A6\squarehvfillSquare With Orthogonal Crosshatch Fill
    U+025A7\squarenwsefillSquare With Upper Left To Lower Right Fill
    U+025A8\squareneswfillSquare With Upper Right To Lower Left Fill
    U+025A9\squarecrossfillSquare With Diagonal Crosshatch Fill
    U+025AA\smblksquare, \:black_small_square:Black Small Square
    U+025AB\smwhtsquare, \:white_small_square:White Small Square
    U+025AC\hrectangleblackBlack Rectangle
    U+025AD\hrectangleWhite Rectangle
    U+025AE\vrectangleblackBlack Vertical Rectangle
    U+025AF\vrectoWhite Vertical Rectangle
    U+025B0\parallelogramblackBlack Parallelogram
    U+025B1\parallelogramWhite Parallelogram
    U+025B2\bigblacktriangleupBlack Up-Pointing Triangle / Black Up Pointing Triangle
    U+025B3\bigtriangleupWhite Up-Pointing Triangle / White Up Pointing Triangle
    U+025B4\blacktriangleBlack Up-Pointing Small Triangle / Black Up Pointing Small Triangle
    U+025B5\vartriangleWhite Up-Pointing Small Triangle / White Up Pointing Small Triangle
    U+025B6\blacktriangleright, \:arrow_forward:Black Right-Pointing Triangle / Black Right Pointing Triangle
    U+025B7\trianglerightWhite Right-Pointing Triangle / White Right Pointing Triangle
    U+025B8\smallblacktrianglerightBlack Right-Pointing Small Triangle / Black Right Pointing Small Triangle
    U+025B9\smalltrianglerightWhite Right-Pointing Small Triangle / White Right Pointing Small Triangle
    U+025BA\blackpointerrightBlack Right-Pointing Pointer / Black Right Pointing Pointer
    U+025BB\whitepointerrightWhite Right-Pointing Pointer / White Right Pointing Pointer
    U+025BC\bigblacktriangledownBlack Down-Pointing Triangle / Black Down Pointing Triangle
    U+025BD\bigtriangledownWhite Down-Pointing Triangle / White Down Pointing Triangle
    U+025BE\blacktriangledownBlack Down-Pointing Small Triangle / Black Down Pointing Small Triangle
    U+025BF\triangledownWhite Down-Pointing Small Triangle / White Down Pointing Small Triangle
    U+025C0\blacktriangleleft, \:arrow_backward:Black Left-Pointing Triangle / Black Left Pointing Triangle
    U+025C1\triangleleftWhite Left-Pointing Triangle / White Left Pointing Triangle
    U+025C2\smallblacktriangleleftBlack Left-Pointing Small Triangle / Black Left Pointing Small Triangle
    U+025C3\smalltriangleleftWhite Left-Pointing Small Triangle / White Left Pointing Small Triangle
    U+025C4\blackpointerleftBlack Left-Pointing Pointer / Black Left Pointing Pointer
    U+025C5\whitepointerleftWhite Left-Pointing Pointer / White Left Pointing Pointer
    U+025C6\mdlgblkdiamondBlack Diamond
    U+025C7\mdlgwhtdiamondWhite Diamond
    U+025C8\blackinwhitediamondWhite Diamond Containing Black Small Diamond
    U+025C9\fisheyeFisheye
    U+025CA\lozengeLozenge
    U+025CB\bigcircWhite Circle
    U+025CC\dottedcircleDotted Circle
    U+025CD\circlevertfillCircle With Vertical Fill
    U+025CE\bullseyeBullseye
    U+025CF\mdlgblkcircleBlack Circle
    U+025D0\cirflCircle With Left Half Black
    U+025D1\cirfrCircle With Right Half Black
    U+025D2\cirfbCircle With Lower Half Black
    U+025D3\circletophalfblackCircle With Upper Half Black
    U+025D4\circleurquadblackCircle With Upper Right Quadrant Black
    U+025D5\blackcircleulquadwhiteCircle With All But Upper Left Quadrant Black
    U+025D6\blacklefthalfcircleLeft Half Black Circle
    U+025D7\blackrighthalfcircleRight Half Black Circle
    U+025D8\rvbullInverse Bullet
    U+025D9\inversewhitecircleInverse White Circle
    U+025DA\invwhiteupperhalfcircleUpper Half Inverse White Circle
    U+025DB\invwhitelowerhalfcircleLower Half Inverse White Circle
    U+025DC\ularcUpper Left Quadrant Circular Arc
    U+025DD\urarcUpper Right Quadrant Circular Arc
    U+025DE\lrarcLower Right Quadrant Circular Arc
    U+025DF\llarcLower Left Quadrant Circular Arc
    U+025E0\topsemicircleUpper Half Circle
    U+025E1\botsemicircleLower Half Circle
    U+025E2\lrblacktriangleBlack Lower Right Triangle
    U+025E3\llblacktriangleBlack Lower Left Triangle
    U+025E4\ulblacktriangleBlack Upper Left Triangle
    U+025E5\urblacktriangleBlack Upper Right Triangle
    U+025E6\smwhtcircleWhite Bullet
    U+025E7\sqflSquare With Left Half Black
    U+025E8\sqfrSquare With Right Half Black
    U+025E9\squareulblackSquare With Upper Left Diagonal Half Black
    U+025EA\sqfseSquare With Lower Right Diagonal Half Black
    U+025EB\boxbarWhite Square With Vertical Bisecting Line
    U+025EC\trianglecdotWhite Up-Pointing Triangle With Dot / White Up Pointing Triangle With Dot
    U+025ED\triangleleftblackUp-Pointing Triangle With Left Half Black / Up Pointing Triangle With Left Half Black
    U+025EE\trianglerightblackUp-Pointing Triangle With Right Half Black / Up Pointing Triangle With Right Half Black
    U+025EF\lgwhtcircleLarge Circle
    U+025F0\squareulquadWhite Square With Upper Left Quadrant
    U+025F1\squarellquadWhite Square With Lower Left Quadrant
    U+025F2\squarelrquadWhite Square With Lower Right Quadrant
    U+025F3\squareurquadWhite Square With Upper Right Quadrant
    U+025F4\circleulquadWhite Circle With Upper Left Quadrant
    U+025F5\circlellquadWhite Circle With Lower Left Quadrant
    U+025F6\circlelrquadWhite Circle With Lower Right Quadrant
    U+025F7\circleurquadWhite Circle With Upper Right Quadrant
    U+025F8\ultriangleUpper Left Triangle
    U+025F9\urtriangleUpper Right Triangle
    U+025FA\lltriangleLower Left Triangle
    U+025FB\mdwhtsquare, \:white_medium_square:White Medium Square
    U+025FC\mdblksquare, \:black_medium_square:Black Medium Square
    U+025FD\mdsmwhtsquare, \:white_medium_small_square:White Medium Small Square
    U+025FE\mdsmblksquare, \:black_medium_small_square:Black Medium Small Square
    U+025FF\lrtriangleLower Right Triangle
    U+02600\:sunny:Black Sun With Rays
    U+02601\:cloud:Cloud
    U+02605\bigstarBlack Star
    U+02606\bigwhitestarWhite Star
    U+02609\astrosunSun
    U+0260E\:phone:Black Telephone
    U+02611\:ballot_box_with_check:Ballot Box With Check
    U+02614\:umbrella_with_rain_drops:, \:umbrella:Umbrella With Rain Drops
    U+02615\:coffee:Hot Beverage
    U+0261D\:point_up:White Up Pointing Index
    U+02621\dangerCaution Sign
    U+0263A\:relaxed:White Smiling Face
    U+0263B\blacksmileyBlack Smiling Face
    U+0263C\sunWhite Sun With Rays
    U+0263D\rightmoonFirst Quarter Moon
    U+0263E\leftmoonLast Quarter Moon
    U+0263F\mercuryMercury
    U+02640\venus, \femaleFemale Sign
    U+02642\male, \marsMale Sign
    U+02643\jupiterJupiter
    U+02644\saturnSaturn
    U+02645\uranusUranus
    U+02646\neptuneNeptune
    U+02647\plutoPluto
    U+02648\aries, \:aries:Aries
    U+02649\taurus, \:taurus:Taurus
    U+0264A\gemini, \:gemini:Gemini
    U+0264B\cancer, \:cancer:Cancer
    U+0264C\leo, \:leo:Leo
    U+0264D\virgo, \:virgo:Virgo
    U+0264E\libra, \:libra:Libra
    U+0264F\scorpio, \:scorpius:Scorpius
    U+02650\sagittarius, \:sagittarius:Sagittarius
    U+02651\capricornus, \:capricorn:Capricorn
    U+02652\aquarius, \:aquarius:Aquarius
    U+02653\pisces, \:pisces:Pisces
    U+02660\spadesuit, \:spades:Black Spade Suit
    U+02661\heartsuitWhite Heart Suit
    U+02662\diamondsuitWhite Diamond Suit
    U+02663\clubsuit, \:clubs:Black Club Suit
    U+02664\varspadesuitWhite Spade Suit
    U+02665\varheartsuit, \:hearts:Black Heart Suit
    U+02666\vardiamondsuit, \:diamonds:Black Diamond Suit
    U+02667\varclubsuitWhite Club Suit
    U+02668\:hotsprings:Hot Springs
    U+02669\quarternoteQuarter Note
    U+0266A\eighthnoteEighth Note
    U+0266B\twonotesBeamed Eighth Notes / Barred Eighth Notes
    U+0266D\flatMusic Flat Sign / Flat
    U+0266E\naturalMusic Natural Sign / Natural
    U+0266F\sharpMusic Sharp Sign / Sharp
    U+0267B\:recycle:Black Universal Recycling Symbol
    U+0267E\acidfreePermanent Paper Sign
    U+0267F\:wheelchair:Wheelchair Symbol
    U+02680\diceiDie Face-1
    U+02681\diceiiDie Face-2
    U+02682\diceiiiDie Face-3
    U+02683\diceivDie Face-4
    U+02684\dicevDie Face-5
    U+02685\diceviDie Face-6
    U+02686\circledrightdotWhite Circle With Dot Right
    U+02687\circledtwodotsWhite Circle With Two Dots
    U+02688\blackcircledrightdotBlack Circle With White Dot Right
    U+02689\blackcircledtwodotsBlack Circle With Two White Dots
    U+02693\:anchor:Anchor
    U+026A0\:warning:Warning Sign
    U+026A1\:zap:High Voltage Sign
    U+026A5\hermaphroditeMale And Female Sign
    U+026AA\mdwhtcircle, \:white_circle:Medium White Circle
    U+026AB\mdblkcircle, \:black_circle:Medium Black Circle
    U+026AC\mdsmwhtcircleMedium Small White Circle
    U+026B2\neuterNeuter
    U+026BD\:soccer:Soccer Ball
    U+026BE\:baseball:Baseball
    U+026C4\:snowman:, \:snowman_without_snow:Snowman Without Snow
    U+026C5\:partly_sunny:Sun Behind Cloud
    U+026CE\:ophiuchus:Ophiuchus
    U+026D4\:no_entry:No Entry
    U+026EA\:church:Church
    U+026F2\:fountain:Fountain
    U+026F3\:golf:Flag In Hole
    U+026F5\:boat:Sailboat
    U+026FA\:tent:Tent
    U+026FD\:fuelpump:Fuel Pump
    U+02702\:scissors:Black Scissors
    U+02705\:white_check_mark:White Heavy Check Mark
    U+02708\:airplane:Airplane
    U+02709\:email:Envelope
    U+0270A\:fist:Raised Fist
    U+0270B\:hand:Raised Hand
    U+0270C\:v:Victory Hand
    U+0270F\:pencil2:Pencil
    U+02712\:black_nib:Black Nib
    U+02713\checkmarkCheck Mark
    U+02714\:heavy_check_mark:Heavy Check Mark
    U+02716\:heavy_multiplication_x:Heavy Multiplication X
    U+02720\malteseMaltese Cross
    U+02728\:sparkles:Sparkles
    U+0272A\circledstarCircled White Star
    U+02733\:eight_spoked_asterisk:Eight Spoked Asterisk
    U+02734\:eight_pointed_black_star:Eight Pointed Black Star
    U+02736\varstarSix Pointed Black Star
    U+0273D\dingasteriskHeavy Teardrop-Spoked Asterisk
    U+02744\:snowflake:Snowflake
    U+02747\:sparkle:Sparkle
    U+0274C\:x:Cross Mark
    U+0274E\:negative_squared_cross_mark:Negative Squared Cross Mark
    U+02753\:question:Black Question Mark Ornament
    U+02754\:grey_question:White Question Mark Ornament
    U+02755\:grey_exclamation:White Exclamation Mark Ornament
    U+02757\:exclamation:Heavy Exclamation Mark Symbol
    U+02764\:heart:Heavy Black Heart
    U+02795\:heavy_plus_sign:Heavy Plus Sign
    U+02796\:heavy_minus_sign:Heavy Minus Sign
    U+02797\:heavy_division_sign:Heavy Division Sign
    U+0279B\draftingarrowDrafting Point Rightwards Arrow / Drafting Point Right Arrow
    U+027A1\:arrow_right:Black Rightwards Arrow / Black Right Arrow
    U+027B0\:curly_loop:Curly Loop
    U+027BF\:loop:Double Curly Loop
    U+027C0\threedangleThree Dimensional Angle
    U+027C1\whiteinwhitetriangleWhite Triangle Containing Small White Triangle
    U+027C2\perpPerpendicular
    U+027C8\bsolhsubReverse Solidus Preceding Subset
    U+027C9\suphsolSuperset Preceding Solidus
    U+027D1\wedgedotAnd With Dot
    U+027D2\upinElement Of Opening Upwards
    U+027D5\leftouterjoinLeft Outer Join
    U+027D6\rightouterjoinRight Outer Join
    U+027D7\fullouterjoinFull Outer Join
    U+027D8\bigbotLarge Up Tack
    U+027D9\bigtopLarge Down Tack
    U+027E6\llbracket, \openbracketleftMathematical Left White Square Bracket
    U+027E7\openbracketright, \rrbracketMathematical Right White Square Bracket
    U+027E8\langleMathematical Left Angle Bracket
    U+027E9\rangleMathematical Right Angle Bracket
    U+027F0\UUparrowUpwards Quadruple Arrow
    U+027F1\DDownarrowDownwards Quadruple Arrow
    U+027F5\longleftarrowLong Leftwards Arrow
    U+027F6\longrightarrowLong Rightwards Arrow
    U+027F7\longleftrightarrowLong Left Right Arrow
    U+027F8\impliedby, \LongleftarrowLong Leftwards Double Arrow
    U+027F9\implies, \LongrightarrowLong Rightwards Double Arrow
    U+027FA\Longleftrightarrow, \iffLong Left Right Double Arrow
    U+027FB\longmapsfromLong Leftwards Arrow From Bar
    U+027FC\longmapstoLong Rightwards Arrow From Bar
    U+027FD\LongmapsfromLong Leftwards Double Arrow From Bar
    U+027FE\LongmapstoLong Rightwards Double Arrow From Bar
    U+027FF\longrightsquigarrowLong Rightwards Squiggle Arrow
    U+02900\nvtwoheadrightarrowRightwards Two-Headed Arrow With Vertical Stroke
    U+02901\nVtwoheadrightarrowRightwards Two-Headed Arrow With Double Vertical Stroke
    U+02902\nvLeftarrowLeftwards Double Arrow With Vertical Stroke
    U+02903\nvRightarrowRightwards Double Arrow With Vertical Stroke
    U+02904\nvLeftrightarrowLeft Right Double Arrow With Vertical Stroke
    U+02905\twoheadmapstoRightwards Two-Headed Arrow From Bar
    U+02906\MapsfromLeftwards Double Arrow From Bar
    U+02907\MapstoRightwards Double Arrow From Bar
    U+02908\downarrowbarredDownwards Arrow With Horizontal Stroke
    U+02909\uparrowbarredUpwards Arrow With Horizontal Stroke
    U+0290A\UuparrowUpwards Triple Arrow
    U+0290B\DdownarrowDownwards Triple Arrow
    U+0290C\leftbkarrowLeftwards Double Dash Arrow
    U+0290D\bkarowRightwards Double Dash Arrow
    U+0290E\leftdbkarrowLeftwards Triple Dash Arrow
    U+0290F\dbkarowRightwards Triple Dash Arrow
    U+02910\drbkarrowRightwards Two-Headed Triple Dash Arrow
    U+02911\rightdotarrowRightwards Arrow With Dotted Stem
    U+02912\UpArrowBarUpwards Arrow To Bar
    U+02913\DownArrowBarDownwards Arrow To Bar
    U+02914\nvrightarrowtailRightwards Arrow With Tail With Vertical Stroke
    U+02915\nVrightarrowtailRightwards Arrow With Tail With Double Vertical Stroke
    U+02916\twoheadrightarrowtailRightwards Two-Headed Arrow With Tail
    U+02917\nvtwoheadrightarrowtailRightwards Two-Headed Arrow With Tail With Vertical Stroke
    U+02918\nVtwoheadrightarrowtailRightwards Two-Headed Arrow With Tail With Double Vertical Stroke
    U+0291D\diamondleftarrowLeftwards Arrow To Black Diamond
    U+0291E\rightarrowdiamondRightwards Arrow To Black Diamond
    U+0291F\diamondleftarrowbarLeftwards Arrow From Bar To Black Diamond
    U+02920\barrightarrowdiamondRightwards Arrow From Bar To Black Diamond
    U+02925\hksearowSouth East Arrow With Hook
    U+02926\hkswarowSouth West Arrow With Hook
    U+02927\tonaNorth West Arrow And North East Arrow
    U+02928\toeaNorth East Arrow And South East Arrow
    U+02929\tosaSouth East Arrow And South West Arrow
    U+0292A\towaSouth West Arrow And North West Arrow
    U+0292B\rdiagovfdiagRising Diagonal Crossing Falling Diagonal
    U+0292C\fdiagovrdiagFalling Diagonal Crossing Rising Diagonal
    U+0292D\seovnearrowSouth East Arrow Crossing North East Arrow
    U+0292E\neovsearrowNorth East Arrow Crossing South East Arrow
    U+0292F\fdiagovnearrowFalling Diagonal Crossing North East Arrow
    U+02930\rdiagovsearrowRising Diagonal Crossing South East Arrow
    U+02931\neovnwarrowNorth East Arrow Crossing North West Arrow
    U+02932\nwovnearrowNorth West Arrow Crossing North East Arrow
    U+02934\:arrow_heading_up:Arrow Pointing Rightwards Then Curving Upwards
    U+02935\:arrow_heading_down:Arrow Pointing Rightwards Then Curving Downwards
    U+02942\RlarrRightwards Arrow Above Short Leftwards Arrow
    U+02944\rLarrShort Rightwards Arrow Above Leftwards Arrow
    U+02945\rightarrowplusRightwards Arrow With Plus Below
    U+02946\leftarrowplusLeftwards Arrow With Plus Below
    U+02947\rarrxRightwards Arrow Through X
    U+02948\leftrightarrowcircleLeft Right Arrow Through Small Circle
    U+02949\twoheaduparrowcircleUpwards Two-Headed Arrow From Small Circle
    U+0294A\leftrightharpoonupdownLeft Barb Up Right Barb Down Harpoon
    U+0294B\leftrightharpoondownupLeft Barb Down Right Barb Up Harpoon
    U+0294C\updownharpoonrightleftUp Barb Right Down Barb Left Harpoon
    U+0294D\updownharpoonleftrightUp Barb Left Down Barb Right Harpoon
    U+0294E\LeftRightVectorLeft Barb Up Right Barb Up Harpoon
    U+0294F\RightUpDownVectorUp Barb Right Down Barb Right Harpoon
    U+02950\DownLeftRightVectorLeft Barb Down Right Barb Down Harpoon
    U+02951\LeftUpDownVectorUp Barb Left Down Barb Left Harpoon
    U+02952\LeftVectorBarLeftwards Harpoon With Barb Up To Bar
    U+02953\RightVectorBarRightwards Harpoon With Barb Up To Bar
    U+02954\RightUpVectorBarUpwards Harpoon With Barb Right To Bar
    U+02955\RightDownVectorBarDownwards Harpoon With Barb Right To Bar
    U+02956\DownLeftVectorBarLeftwards Harpoon With Barb Down To Bar
    U+02957\DownRightVectorBarRightwards Harpoon With Barb Down To Bar
    U+02958\LeftUpVectorBarUpwards Harpoon With Barb Left To Bar
    U+02959\LeftDownVectorBarDownwards Harpoon With Barb Left To Bar
    U+0295A\LeftTeeVectorLeftwards Harpoon With Barb Up From Bar
    U+0295B\RightTeeVectorRightwards Harpoon With Barb Up From Bar
    U+0295C\RightUpTeeVectorUpwards Harpoon With Barb Right From Bar
    U+0295D\RightDownTeeVectorDownwards Harpoon With Barb Right From Bar
    U+0295E\DownLeftTeeVectorLeftwards Harpoon With Barb Down From Bar
    U+0295F\DownRightTeeVectorRightwards Harpoon With Barb Down From Bar
    U+02960\LeftUpTeeVectorUpwards Harpoon With Barb Left From Bar
    U+02961\LeftDownTeeVectorDownwards Harpoon With Barb Left From Bar
    U+02962\leftharpoonsupdownLeftwards Harpoon With Barb Up Above Leftwards Harpoon With Barb Down
    U+02963\upharpoonsleftrightUpwards Harpoon With Barb Left Beside Upwards Harpoon With Barb Right
    U+02964\rightharpoonsupdownRightwards Harpoon With Barb Up Above Rightwards Harpoon With Barb Down
    U+02965\downharpoonsleftrightDownwards Harpoon With Barb Left Beside Downwards Harpoon With Barb Right
    U+02966\leftrightharpoonsupLeftwards Harpoon With Barb Up Above Rightwards Harpoon With Barb Up
    U+02967\leftrightharpoonsdownLeftwards Harpoon With Barb Down Above Rightwards Harpoon With Barb Down
    U+02968\rightleftharpoonsupRightwards Harpoon With Barb Up Above Leftwards Harpoon With Barb Up
    U+02969\rightleftharpoonsdownRightwards Harpoon With Barb Down Above Leftwards Harpoon With Barb Down
    U+0296A\leftharpoonupdashLeftwards Harpoon With Barb Up Above Long Dash
    U+0296B\dashleftharpoondownLeftwards Harpoon With Barb Down Below Long Dash
    U+0296C\rightharpoonupdashRightwards Harpoon With Barb Up Above Long Dash
    U+0296D\dashrightharpoondownRightwards Harpoon With Barb Down Below Long Dash
    U+0296E\UpEquilibriumUpwards Harpoon With Barb Left Beside Downwards Harpoon With Barb Right
    U+0296F\ReverseUpEquilibriumDownwards Harpoon With Barb Left Beside Upwards Harpoon With Barb Right
    U+02970\RoundImpliesRight Double Arrow With Rounded Head
    U+02980\VvertTriple Vertical Bar Delimiter
    U+02986\ElroangRight White Parenthesis
    U+02999\ddfncDotted Fence
    U+0299B\measuredangleleftMeasured Angle Opening Left
    U+0299C\AngleRight Angle Variant With Square
    U+0299D\rightanglemdotMeasured Right Angle With Dot
    U+0299E\anglesAngle With S Inside
    U+0299F\angdnrAcute Angle
    U+029A0\lpargtSpherical Angle Opening Left
    U+029A1\sphericalangleupSpherical Angle Opening Up
    U+029A2\turnangleTurned Angle
    U+029A3\revangleReversed Angle
    U+029A4\angleubarAngle With Underbar
    U+029A5\revangleubarReversed Angle With Underbar
    U+029A6\wideangledownOblique Angle Opening Up
    U+029A7\wideangleupOblique Angle Opening Down
    U+029A8\measanglerutoneMeasured Angle With Open Arm Ending In Arrow Pointing Up And Right
    U+029A9\measanglelutonwMeasured Angle With Open Arm Ending In Arrow Pointing Up And Left
    U+029AA\measanglerdtoseMeasured Angle With Open Arm Ending In Arrow Pointing Down And Right
    U+029AB\measangleldtoswMeasured Angle With Open Arm Ending In Arrow Pointing Down And Left
    U+029AC\measangleurtoneMeasured Angle With Open Arm Ending In Arrow Pointing Right And Up
    U+029AD\measangleultonwMeasured Angle With Open Arm Ending In Arrow Pointing Left And Up
    U+029AE\measangledrtoseMeasured Angle With Open Arm Ending In Arrow Pointing Right And Down
    U+029AF\measangledltoswMeasured Angle With Open Arm Ending In Arrow Pointing Left And Down
    U+029B0\revemptysetReversed Empty Set
    U+029B1\emptysetobarEmpty Set With Overbar
    U+029B2\emptysetocircEmpty Set With Small Circle Above
    U+029B3\emptysetoarrEmpty Set With Right Arrow Above
    U+029B4\emptysetoarrlEmpty Set With Left Arrow Above
    U+029B7\circledparallelCircled Parallel
    U+029B8\obslashCircled Reverse Solidus
    U+029BC\odotslashdotCircled Anticlockwise-Rotated Division Sign
    U+029BE\circledwhitebulletCircled White Bullet
    U+029BF⦿\circledbulletCircled Bullet
    U+029C0\olessthanCircled Less-Than
    U+029C1\ogreaterthanCircled Greater-Than
    U+029C4\boxdiagSquared Rising Diagonal Slash
    U+029C5\boxbslashSquared Falling Diagonal Slash
    U+029C6\boxastSquared Asterisk
    U+029C7\boxcircleSquared Small Circle
    U+029CA\LapTriangle With Dot Above
    U+029CB\defasTriangle With Underbar
    U+029CF\LeftTriangleBarLeft Triangle Beside Vertical Bar
    U+029CF + U+00338⧏̸\NotLeftTriangleBarLeft Triangle Beside Vertical Bar + Combining Long Solidus Overlay / Non-Spacing Long Slash Overlay
    U+029D0\RightTriangleBarVertical Bar Beside Right Triangle
    U+029D0 + U+00338⧐̸\NotRightTriangleBarVertical Bar Beside Right Triangle + Combining Long Solidus Overlay / Non-Spacing Long Slash Overlay
    U+029DF\dualmapDouble-Ended Multimap
    U+029E1\lrtriangleeqIncreases As
    U+029E2\shuffleShuffle Product
    U+029E3\eparslEquals Sign And Slanted Parallel
    U+029E4\smeparslEquals Sign And Slanted Parallel With Tilde Above
    U+029E5\eqvparslIdentical To And Slanted Parallel
    U+029EB\blacklozengeBlack Lozenge
    U+029F4\RuleDelayedRule-Delayed
    U+029F6\dsolSolidus With Overbar
    U+029F7\rsolbarReverse Solidus With Horizontal Stroke
    U+029FA\doubleplusDouble Plus
    U+029FB\tripleplusTriple Plus
    U+02A00\bigodotN-Ary Circled Dot Operator
    U+02A01\bigoplusN-Ary Circled Plus Operator
    U+02A02\bigotimesN-Ary Circled Times Operator
    U+02A03\bigcupdotN-Ary Union Operator With Dot
    U+02A04\biguplusN-Ary Union Operator With Plus
    U+02A05\bigsqcapN-Ary Square Intersection Operator
    U+02A06\bigsqcupN-Ary Square Union Operator
    U+02A07\conjquantTwo Logical And Operator
    U+02A08\disjquantTwo Logical Or Operator
    U+02A09\bigtimesN-Ary Times Operator
    U+02A0A\modtwosumModulo Two Sum
    U+02A0B\sumintSummation With Integral
    U+02A0C\iiiintQuadruple Integral Operator
    U+02A0D\intbarFinite Part Integral
    U+02A0E\intBarIntegral With Double Stroke
    U+02A0F\clockointIntegral Average With Slash
    U+02A10\cirfnintCirculation Function
    U+02A11\awintAnticlockwise Integration
    U+02A12\rppolintLine Integration With Rectangular Path Around Pole
    U+02A13\scpolintLine Integration With Semicircular Path Around Pole
    U+02A14\npolintLine Integration Not Including The Pole
    U+02A15\pointintIntegral Around A Point Operator
    U+02A16\sqrintQuaternion Integral Operator
    U+02A18\intxIntegral With Times Sign
    U+02A19\intcapIntegral With Intersection
    U+02A1A\intcupIntegral With Union
    U+02A1B\upintIntegral With Overbar
    U+02A1C\lowintIntegral With Underbar
    U+02A1D\joinJoin
    U+02A1F\bbsemiZ Notation Schema Composition
    U+02A22\ringplusPlus Sign With Small Circle Above
    U+02A23\plushatPlus Sign With Circumflex Accent Above
    U+02A24\simplusPlus Sign With Tilde Above
    U+02A25\plusdotPlus Sign With Dot Below
    U+02A26\plussimPlus Sign With Tilde Below
    U+02A27\plussubtwoPlus Sign With Subscript Two
    U+02A28\plustrifPlus Sign With Black Triangle
    U+02A29\commaminusMinus Sign With Comma Above
    U+02A2A\minusdotMinus Sign With Dot Below
    U+02A2B\minusfdotsMinus Sign With Falling Dots
    U+02A2C\minusrdotsMinus Sign With Rising Dots
    U+02A2D\opluslhrimPlus Sign In Left Half Circle
    U+02A2E\oplusrhrimPlus Sign In Right Half Circle
    U+02A2F\TimesVector Or Cross Product
    U+02A30\dottimesMultiplication Sign With Dot Above
    U+02A31\timesbarMultiplication Sign With Underbar
    U+02A32\btimesSemidirect Product With Bottom Closed
    U+02A33\smashtimesSmash Product
    U+02A34\otimeslhrimMultiplication Sign In Left Half Circle
    U+02A35\otimesrhrimMultiplication Sign In Right Half Circle
    U+02A36\otimeshatCircled Multiplication Sign With Circumflex Accent
    U+02A37\OtimesMultiplication Sign In Double Circle
    U+02A38\odivCircled Division Sign
    U+02A39\triangleplusPlus Sign In Triangle
    U+02A3A\triangleminusMinus Sign In Triangle
    U+02A3B\triangletimesMultiplication Sign In Triangle
    U+02A3C\intprodInterior Product
    U+02A3D\intprodrRighthand Interior Product
    U+02A3F⨿\amalgAmalgamation Or Coproduct
    U+02A40\capdotIntersection With Dot
    U+02A41\uminusUnion With Minus Sign
    U+02A42\barcupUnion With Overbar
    U+02A43\barcapIntersection With Overbar
    U+02A44\capwedgeIntersection With Logical And
    U+02A45\cupveeUnion With Logical Or
    U+02A4A\twocupsUnion Beside And Joined With Union
    U+02A4B\twocapsIntersection Beside And Joined With Intersection
    U+02A4C\closedvarcupClosed Union With Serifs
    U+02A4D\closedvarcapClosed Intersection With Serifs
    U+02A4E\SqcapDouble Square Intersection
    U+02A4F\SqcupDouble Square Union
    U+02A50\closedvarcupsmashprodClosed Union With Serifs And Smash Product
    U+02A51\wedgeodotLogical And With Dot Above
    U+02A52\veeodotLogical Or With Dot Above
    U+02A53\AndDouble Logical And
    U+02A54\OrDouble Logical Or
    U+02A55\wedgeonwedgeTwo Intersecting Logical And
    U+02A56\ElOrTwo Intersecting Logical Or
    U+02A57\bigslopedveeSloping Large Or
    U+02A58\bigslopedwedgeSloping Large And
    U+02A5A\wedgemidvertLogical And With Middle Stem
    U+02A5B\veemidvertLogical Or With Middle Stem
    U+02A5C\midbarwedgeLogical And With Horizontal Dash
    U+02A5D\midbarveeLogical Or With Horizontal Dash
    U+02A5E\perspcorrespondLogical And With Double Overbar
    U+02A5F\minhatLogical And With Underbar
    U+02A60\wedgedoublebarLogical And With Double Underbar
    U+02A61\varveebarSmall Vee With Underbar
    U+02A62\doublebarveeLogical Or With Double Overbar
    U+02A63\veedoublebarLogical Or With Double Underbar
    U+02A66\eqdotEquals Sign With Dot Below
    U+02A67\dotequivIdentical With Dot Above
    U+02A6A\dotsimTilde Operator With Dot Above
    U+02A6B\simrdotsTilde Operator With Rising Dots
    U+02A6C\simminussimSimilar Minus Similar
    U+02A6D\congdotCongruent With Dot Above
    U+02A6E\asteqEquals With Asterisk
    U+02A6F\hatapproxAlmost Equal To With Circumflex Accent
    U+02A70\approxeqqApproximately Equal Or Equal To
    U+02A71\eqqplusEquals Sign Above Plus Sign
    U+02A72\pluseqqPlus Sign Above Equals Sign
    U+02A73\eqqsimEquals Sign Above Tilde Operator
    U+02A74\ColoneqDouble Colon Equal
    U+02A75\EqualTwo Consecutive Equals Signs
    U+02A76\eqeqeqThree Consecutive Equals Signs
    U+02A77\ddotseqEquals Sign With Two Dots Above And Two Dots Below
    U+02A78\equivDDEquivalent With Four Dots Above
    U+02A79\ltcirLess-Than With Circle Inside
    U+02A7A\gtcirGreater-Than With Circle Inside
    U+02A7B\ltquestLess-Than With Question Mark Above
    U+02A7C\gtquestGreater-Than With Question Mark Above
    U+02A7D\leqslantLess-Than Or Slanted Equal To
    U+02A7D + U+00338⩽̸\nleqslantLess-Than Or Slanted Equal To + Combining Long Solidus Overlay / Non-Spacing Long Slash Overlay
    U+02A7E\geqslantGreater-Than Or Slanted Equal To
    U+02A7E + U+00338⩾̸\ngeqslantGreater-Than Or Slanted Equal To + Combining Long Solidus Overlay / Non-Spacing Long Slash Overlay
    U+02A7F⩿\lesdotLess-Than Or Slanted Equal To With Dot Inside
    U+02A80\gesdotGreater-Than Or Slanted Equal To With Dot Inside
    U+02A81\lesdotoLess-Than Or Slanted Equal To With Dot Above
    U+02A82\gesdotoGreater-Than Or Slanted Equal To With Dot Above
    U+02A83\lesdotorLess-Than Or Slanted Equal To With Dot Above Right
    U+02A84\gesdotolGreater-Than Or Slanted Equal To With Dot Above Left
    U+02A85\lessapproxLess-Than Or Approximate
    U+02A86\gtrapproxGreater-Than Or Approximate
    U+02A87\lneqLess-Than And Single-Line Not Equal To
    U+02A88\gneqGreater-Than And Single-Line Not Equal To
    U+02A89\lnapproxLess-Than And Not Approximate
    U+02A8A\gnapproxGreater-Than And Not Approximate
    U+02A8B\lesseqqgtrLess-Than Above Double-Line Equal Above Greater-Than
    U+02A8C\gtreqqlessGreater-Than Above Double-Line Equal Above Less-Than
    U+02A8D\lsimeLess-Than Above Similar Or Equal
    U+02A8E\gsimeGreater-Than Above Similar Or Equal
    U+02A8F\lsimgLess-Than Above Similar Above Greater-Than
    U+02A90\gsimlGreater-Than Above Similar Above Less-Than
    U+02A91\lgELess-Than Above Greater-Than Above Double-Line Equal
    U+02A92\glEGreater-Than Above Less-Than Above Double-Line Equal
    U+02A93\lesgesLess-Than Above Slanted Equal Above Greater-Than Above Slanted Equal
    U+02A94\geslesGreater-Than Above Slanted Equal Above Less-Than Above Slanted Equal
    U+02A95\eqslantlessSlanted Equal To Or Less-Than
    U+02A96\eqslantgtrSlanted Equal To Or Greater-Than
    U+02A97\elsdotSlanted Equal To Or Less-Than With Dot Inside
    U+02A98\egsdotSlanted Equal To Or Greater-Than With Dot Inside
    U+02A99\eqqlessDouble-Line Equal To Or Less-Than
    U+02A9A\eqqgtrDouble-Line Equal To Or Greater-Than
    U+02A9B\eqqslantlessDouble-Line Slanted Equal To Or Less-Than
    U+02A9C\eqqslantgtrDouble-Line Slanted Equal To Or Greater-Than
    U+02A9D\simlessSimilar Or Less-Than
    U+02A9E\simgtrSimilar Or Greater-Than
    U+02A9F\simlESimilar Above Less-Than Above Equals Sign
    U+02AA0\simgESimilar Above Greater-Than Above Equals Sign
    U+02AA1\NestedLessLessDouble Nested Less-Than
    U+02AA1 + U+00338⪡̸\NotNestedLessLessDouble Nested Less-Than + Combining Long Solidus Overlay / Non-Spacing Long Slash Overlay
    U+02AA2\NestedGreaterGreaterDouble Nested Greater-Than
    U+02AA2 + U+00338⪢̸\NotNestedGreaterGreaterDouble Nested Greater-Than + Combining Long Solidus Overlay / Non-Spacing Long Slash Overlay
    U+02AA3\partialmeetcontractionDouble Nested Less-Than With Underbar
    U+02AA4\gljGreater-Than Overlapping Less-Than
    U+02AA5\glaGreater-Than Beside Less-Than
    U+02AA6\ltccLess-Than Closed By Curve
    U+02AA7\gtccGreater-Than Closed By Curve
    U+02AA8\lesccLess-Than Closed By Curve Above Slanted Equal
    U+02AA9\gesccGreater-Than Closed By Curve Above Slanted Equal
    U+02AAA\smtSmaller Than
    U+02AAB\latLarger Than
    U+02AAC\smteSmaller Than Or Equal To
    U+02AAD\lateLarger Than Or Equal To
    U+02AAE\bumpeqqEquals Sign With Bumpy Above
    U+02AAF\preceqPrecedes Above Single-Line Equals Sign
    U+02AAF + U+00338⪯̸\npreceqPrecedes Above Single-Line Equals Sign + Combining Long Solidus Overlay / Non-Spacing Long Slash Overlay
    U+02AB0\succeqSucceeds Above Single-Line Equals Sign
    U+02AB0 + U+00338⪰̸\nsucceqSucceeds Above Single-Line Equals Sign + Combining Long Solidus Overlay / Non-Spacing Long Slash Overlay
    U+02AB1\precneqPrecedes Above Single-Line Not Equal To
    U+02AB2\succneqSucceeds Above Single-Line Not Equal To
    U+02AB3\preceqqPrecedes Above Equals Sign
    U+02AB4\succeqqSucceeds Above Equals Sign
    U+02AB5\precneqqPrecedes Above Not Equal To
    U+02AB6\succneqqSucceeds Above Not Equal To
    U+02AB7\precapproxPrecedes Above Almost Equal To
    U+02AB8\succapproxSucceeds Above Almost Equal To
    U+02AB9\precnapproxPrecedes Above Not Almost Equal To
    U+02ABA\succnapproxSucceeds Above Not Almost Equal To
    U+02ABB\PrecDouble Precedes
    U+02ABC\SuccDouble Succeeds
    U+02ABD\subsetdotSubset With Dot
    U+02ABE\supsetdotSuperset With Dot
    U+02ABF⪿\subsetplusSubset With Plus Sign Below
    U+02AC0\supsetplusSuperset With Plus Sign Below
    U+02AC1\submultSubset With Multiplication Sign Below
    U+02AC2\supmultSuperset With Multiplication Sign Below
    U+02AC3\subedotSubset Of Or Equal To With Dot Above
    U+02AC4\supedotSuperset Of Or Equal To With Dot Above
    U+02AC5\subseteqqSubset Of Above Equals Sign
    U+02AC5 + U+00338⫅̸\nsubseteqqSubset Of Above Equals Sign + Combining Long Solidus Overlay / Non-Spacing Long Slash Overlay
    U+02AC6\supseteqqSuperset Of Above Equals Sign
    U+02AC6 + U+00338⫆̸\nsupseteqqSuperset Of Above Equals Sign + Combining Long Solidus Overlay / Non-Spacing Long Slash Overlay
    U+02AC7\subsimSubset Of Above Tilde Operator
    U+02AC8\supsimSuperset Of Above Tilde Operator
    U+02AC9\subsetapproxSubset Of Above Almost Equal To
    U+02ACA\supsetapproxSuperset Of Above Almost Equal To
    U+02ACB\subsetneqqSubset Of Above Not Equal To
    U+02ACC\supsetneqqSuperset Of Above Not Equal To
    U+02ACD\lsqhookSquare Left Open Box Operator
    U+02ACE\rsqhookSquare Right Open Box Operator
    U+02ACF\csubClosed Subset
    U+02AD0\csupClosed Superset
    U+02AD1\csubeClosed Subset Or Equal To
    U+02AD2\csupeClosed Superset Or Equal To
    U+02AD3\subsupSubset Above Superset
    U+02AD4\supsubSuperset Above Subset
    U+02AD5\subsubSubset Above Subset
    U+02AD6\supsupSuperset Above Superset
    U+02AD7\suphsubSuperset Beside Subset
    U+02AD8\supdsubSuperset Beside And Joined By Dash With Subset
    U+02AD9\forkvElement Of Opening Downwards
    U+02ADB\mlcpTransversal Intersection
    U+02ADC\forksForking
    U+02ADD\forksnotNonforking
    U+02AE3\dashVDouble Vertical Bar Left Turnstile
    U+02AE4\DashvVertical Bar Double Left Turnstile
    U+02AEA\Top, \downvDashDouble Down Tack
    U+02AEB\upvDash, \Bot, \indepDouble Up Tack
    U+02AF4\interleaveTriple Vertical Bar Binary Relation
    U+02AF6\tdcolTriple Colon Operator
    U+02AF7\lllnestTriple Nested Less-Than
    U+02AF8\gggnestTriple Nested Greater-Than
    U+02AF9\leqqslantDouble-Line Slanted Less-Than Or Equal To
    U+02AFA\geqqslantDouble-Line Slanted Greater-Than Or Equal To
    U+02B05\:arrow_left:Leftwards Black Arrow
    U+02B06\:arrow_up:Upwards Black Arrow
    U+02B07\:arrow_down:Downwards Black Arrow
    U+02B12\squaretopblackSquare With Top Half Black
    U+02B13\squarebotblackSquare With Bottom Half Black
    U+02B14\squareurblackSquare With Upper Right Diagonal Half Black
    U+02B15\squarellblackSquare With Lower Left Diagonal Half Black
    U+02B16\diamondleftblackDiamond With Left Half Black
    U+02B17\diamondrightblackDiamond With Right Half Black
    U+02B18\diamondtopblackDiamond With Top Half Black
    U+02B19\diamondbotblackDiamond With Bottom Half Black
    U+02B1A\dottedsquareDotted Square
    U+02B1B\lgblksquare, \:black_large_square:Black Large Square
    U+02B1C\lgwhtsquare, \:white_large_square:White Large Square
    U+02B1D\vysmblksquareBlack Very Small Square
    U+02B1E\vysmwhtsquareWhite Very Small Square
    U+02B1F\pentagonblackBlack Pentagon
    U+02B20\pentagonWhite Pentagon
    U+02B21\varhexagonWhite Hexagon
    U+02B22\varhexagonblackBlack Hexagon
    U+02B23\hexagonblackHorizontal Black Hexagon
    U+02B24\lgblkcircleBlack Large Circle
    U+02B25\mdblkdiamondBlack Medium Diamond
    U+02B26\mdwhtdiamondWhite Medium Diamond
    U+02B27\mdblklozengeBlack Medium Lozenge
    U+02B28\mdwhtlozengeWhite Medium Lozenge
    U+02B29\smblkdiamondBlack Small Diamond
    U+02B2A\smblklozengeBlack Small Lozenge
    U+02B2B\smwhtlozengeWhite Small Lozenge
    U+02B2C\blkhorzovalBlack Horizontal Ellipse
    U+02B2D\whthorzovalWhite Horizontal Ellipse
    U+02B2E\blkvertovalBlack Vertical Ellipse
    U+02B2F\whtvertovalWhite Vertical Ellipse
    U+02B30\circleonleftarrowLeft Arrow With Small Circle
    U+02B31\leftthreearrowsThree Leftwards Arrows
    U+02B32\leftarrowonoplusLeft Arrow With Circled Plus
    U+02B33\longleftsquigarrowLong Leftwards Squiggle Arrow
    U+02B34\nvtwoheadleftarrowLeftwards Two-Headed Arrow With Vertical Stroke
    U+02B35\nVtwoheadleftarrowLeftwards Two-Headed Arrow With Double Vertical Stroke
    U+02B36\twoheadmapsfromLeftwards Two-Headed Arrow From Bar
    U+02B37\twoheadleftdbkarrowLeftwards Two-Headed Triple Dash Arrow
    U+02B38\leftdotarrowLeftwards Arrow With Dotted Stem
    U+02B39\nvleftarrowtailLeftwards Arrow With Tail With Vertical Stroke
    U+02B3A\nVleftarrowtailLeftwards Arrow With Tail With Double Vertical Stroke
    U+02B3B\twoheadleftarrowtailLeftwards Two-Headed Arrow With Tail
    U+02B3C\nvtwoheadleftarrowtailLeftwards Two-Headed Arrow With Tail With Vertical Stroke
    U+02B3D\nVtwoheadleftarrowtailLeftwards Two-Headed Arrow With Tail With Double Vertical Stroke
    U+02B3E\leftarrowxLeftwards Arrow Through X
    U+02B3F⬿\leftcurvedarrowWave Arrow Pointing Directly Left
    U+02B40\equalleftarrowEquals Sign Above Leftwards Arrow
    U+02B41\bsimilarleftarrowReverse Tilde Operator Above Leftwards Arrow
    U+02B42\leftarrowbackapproxLeftwards Arrow Above Reverse Almost Equal To
    U+02B43\rightarrowgtrRightwards Arrow Through Greater-Than
    U+02B44\rightarrowsupsetRightwards Arrow Through Superset
    U+02B45\LLeftarrowLeftwards Quadruple Arrow
    U+02B46\RRightarrowRightwards Quadruple Arrow
    U+02B47\bsimilarrightarrowReverse Tilde Operator Above Rightwards Arrow
    U+02B48\rightarrowbackapproxRightwards Arrow Above Reverse Almost Equal To
    U+02B49\similarleftarrowTilde Operator Above Leftwards Arrow
    U+02B4A\leftarrowapproxLeftwards Arrow Above Almost Equal To
    U+02B4B\leftarrowbsimilarLeftwards Arrow Above Reverse Tilde Operator
    U+02B4C\rightarrowbsimilarRightwards Arrow Above Reverse Tilde Operator
    U+02B50\medwhitestar, \:star:White Medium Star
    U+02B51\medblackstarBlack Small Star
    U+02B52\smwhitestarWhite Small Star
    U+02B53\rightpentagonblackBlack Right-Pointing Pentagon
    U+02B54\rightpentagonWhite Right-Pointing Pentagon
    U+02B55\:o:Heavy Large Circle
    U+02C7C\_jLatin Subscript Small Letter J
    U+02C7D\^VModifier Letter Capital V
    U+03012\postalmarkPostal Mark
    U+03030\:wavy_dash:Wavy Dash
    U+0303D\:part_alternation_mark:Part Alternation Mark
    U+03297\:congratulations:Circled Ideograph Congratulation
    U+03299\:secret:Circled Ideograph Secret
    U+0A71B\^uparrowModifier Letter Raised Up Arrow
    U+0A71C\^downarrowModifier Letter Raised Down Arrow
    U+0A71D\^!Modifier Letter Raised Exclamation Mark
    U+1D400𝐀\bfAMathematical Bold Capital A
    U+1D401𝐁\bfBMathematical Bold Capital B
    U+1D402𝐂\bfCMathematical Bold Capital C
    U+1D403𝐃\bfDMathematical Bold Capital D
    U+1D404𝐄\bfEMathematical Bold Capital E
    U+1D405𝐅\bfFMathematical Bold Capital F
    U+1D406𝐆\bfGMathematical Bold Capital G
    U+1D407𝐇\bfHMathematical Bold Capital H
    U+1D408𝐈\bfIMathematical Bold Capital I
    U+1D409𝐉\bfJMathematical Bold Capital J
    U+1D40A𝐊\bfKMathematical Bold Capital K
    U+1D40B𝐋\bfLMathematical Bold Capital L
    U+1D40C𝐌\bfMMathematical Bold Capital M
    U+1D40D𝐍\bfNMathematical Bold Capital N
    U+1D40E𝐎\bfOMathematical Bold Capital O
    U+1D40F𝐏\bfPMathematical Bold Capital P
    U+1D410𝐐\bfQMathematical Bold Capital Q
    U+1D411𝐑\bfRMathematical Bold Capital R
    U+1D412𝐒\bfSMathematical Bold Capital S
    U+1D413𝐓\bfTMathematical Bold Capital T
    U+1D414𝐔\bfUMathematical Bold Capital U
    U+1D415𝐕\bfVMathematical Bold Capital V
    U+1D416𝐖\bfWMathematical Bold Capital W
    U+1D417𝐗\bfXMathematical Bold Capital X
    U+1D418𝐘\bfYMathematical Bold Capital Y
    U+1D419𝐙\bfZMathematical Bold Capital Z
    U+1D41A𝐚\bfaMathematical Bold Small A
    U+1D41B𝐛\bfbMathematical Bold Small B
    U+1D41C𝐜\bfcMathematical Bold Small C
    U+1D41D𝐝\bfdMathematical Bold Small D
    U+1D41E𝐞\bfeMathematical Bold Small E
    U+1D41F𝐟\bffMathematical Bold Small F
    U+1D420𝐠\bfgMathematical Bold Small G
    U+1D421𝐡\bfhMathematical Bold Small H
    U+1D422𝐢\bfiMathematical Bold Small I
    U+1D423𝐣\bfjMathematical Bold Small J
    U+1D424𝐤\bfkMathematical Bold Small K
    U+1D425𝐥\bflMathematical Bold Small L
    U+1D426𝐦\bfmMathematical Bold Small M
    U+1D427𝐧\bfnMathematical Bold Small N
    U+1D428𝐨\bfoMathematical Bold Small O
    U+1D429𝐩\bfpMathematical Bold Small P
    U+1D42A𝐪\bfqMathematical Bold Small Q
    U+1D42B𝐫\bfrMathematical Bold Small R
    U+1D42C𝐬\bfsMathematical Bold Small S
    U+1D42D𝐭\bftMathematical Bold Small T
    U+1D42E𝐮\bfuMathematical Bold Small U
    U+1D42F𝐯\bfvMathematical Bold Small V
    U+1D430𝐰\bfwMathematical Bold Small W
    U+1D431𝐱\bfxMathematical Bold Small X
    U+1D432𝐲\bfyMathematical Bold Small Y
    U+1D433𝐳\bfzMathematical Bold Small Z
    U+1D434𝐴\itAMathematical Italic Capital A
    U+1D435𝐵\itBMathematical Italic Capital B
    U+1D436𝐶\itCMathematical Italic Capital C
    U+1D437𝐷\itDMathematical Italic Capital D
    U+1D438𝐸\itEMathematical Italic Capital E
    U+1D439𝐹\itFMathematical Italic Capital F
    U+1D43A𝐺\itGMathematical Italic Capital G
    U+1D43B𝐻\itHMathematical Italic Capital H
    U+1D43C𝐼\itIMathematical Italic Capital I
    U+1D43D𝐽\itJMathematical Italic Capital J
    U+1D43E𝐾\itKMathematical Italic Capital K
    U+1D43F𝐿\itLMathematical Italic Capital L
    U+1D440𝑀\itMMathematical Italic Capital M
    U+1D441𝑁\itNMathematical Italic Capital N
    U+1D442𝑂\itOMathematical Italic Capital O
    U+1D443𝑃\itPMathematical Italic Capital P
    U+1D444𝑄\itQMathematical Italic Capital Q
    U+1D445𝑅\itRMathematical Italic Capital R
    U+1D446𝑆\itSMathematical Italic Capital S
    U+1D447𝑇\itTMathematical Italic Capital T
    U+1D448𝑈\itUMathematical Italic Capital U
    U+1D449𝑉\itVMathematical Italic Capital V
    U+1D44A𝑊\itWMathematical Italic Capital W
    U+1D44B𝑋\itXMathematical Italic Capital X
    U+1D44C𝑌\itYMathematical Italic Capital Y
    U+1D44D𝑍\itZMathematical Italic Capital Z
    U+1D44E𝑎\itaMathematical Italic Small A
    U+1D44F𝑏\itbMathematical Italic Small B
    U+1D450𝑐\itcMathematical Italic Small C
    U+1D451𝑑\itdMathematical Italic Small D
    U+1D452𝑒\iteMathematical Italic Small E
    U+1D453𝑓\itfMathematical Italic Small F
    U+1D454𝑔\itgMathematical Italic Small G
    U+1D456𝑖\itiMathematical Italic Small I
    U+1D457𝑗\itjMathematical Italic Small J
    U+1D458𝑘\itkMathematical Italic Small K
    U+1D459𝑙\itlMathematical Italic Small L
    U+1D45A𝑚\itmMathematical Italic Small M
    U+1D45B𝑛\itnMathematical Italic Small N
    U+1D45C𝑜\itoMathematical Italic Small O
    U+1D45D𝑝\itpMathematical Italic Small P
    U+1D45E𝑞\itqMathematical Italic Small Q
    U+1D45F𝑟\itrMathematical Italic Small R
    U+1D460𝑠\itsMathematical Italic Small S
    U+1D461𝑡\ittMathematical Italic Small T
    U+1D462𝑢\ituMathematical Italic Small U
    U+1D463𝑣\itvMathematical Italic Small V
    U+1D464𝑤\itwMathematical Italic Small W
    U+1D465𝑥\itxMathematical Italic Small X
    U+1D466𝑦\ityMathematical Italic Small Y
    U+1D467𝑧\itzMathematical Italic Small Z
    U+1D468𝑨\biAMathematical Bold Italic Capital A
    U+1D469𝑩\biBMathematical Bold Italic Capital B
    U+1D46A𝑪\biCMathematical Bold Italic Capital C
    U+1D46B𝑫\biDMathematical Bold Italic Capital D
    U+1D46C𝑬\biEMathematical Bold Italic Capital E
    U+1D46D𝑭\biFMathematical Bold Italic Capital F
    U+1D46E𝑮\biGMathematical Bold Italic Capital G
    U+1D46F𝑯\biHMathematical Bold Italic Capital H
    U+1D470𝑰\biIMathematical Bold Italic Capital I
    U+1D471𝑱\biJMathematical Bold Italic Capital J
    U+1D472𝑲\biKMathematical Bold Italic Capital K
    U+1D473𝑳\biLMathematical Bold Italic Capital L
    U+1D474𝑴\biMMathematical Bold Italic Capital M
    U+1D475𝑵\biNMathematical Bold Italic Capital N
    U+1D476𝑶\biOMathematical Bold Italic Capital O
    U+1D477𝑷\biPMathematical Bold Italic Capital P
    U+1D478𝑸\biQMathematical Bold Italic Capital Q
    U+1D479𝑹\biRMathematical Bold Italic Capital R
    U+1D47A𝑺\biSMathematical Bold Italic Capital S
    U+1D47B𝑻\biTMathematical Bold Italic Capital T
    U+1D47C𝑼\biUMathematical Bold Italic Capital U
    U+1D47D𝑽\biVMathematical Bold Italic Capital V
    U+1D47E𝑾\biWMathematical Bold Italic Capital W
    U+1D47F𝑿\biXMathematical Bold Italic Capital X
    U+1D480𝒀\biYMathematical Bold Italic Capital Y
    U+1D481𝒁\biZMathematical Bold Italic Capital Z
    U+1D482𝒂\biaMathematical Bold Italic Small A
    U+1D483𝒃\bibMathematical Bold Italic Small B
    U+1D484𝒄\bicMathematical Bold Italic Small C
    U+1D485𝒅\bidMathematical Bold Italic Small D
    U+1D486𝒆\bieMathematical Bold Italic Small E
    U+1D487𝒇\bifMathematical Bold Italic Small F
    U+1D488𝒈\bigMathematical Bold Italic Small G
    U+1D489𝒉\bihMathematical Bold Italic Small H
    U+1D48A𝒊\biiMathematical Bold Italic Small I
    U+1D48B𝒋\bijMathematical Bold Italic Small J
    U+1D48C𝒌\bikMathematical Bold Italic Small K
    U+1D48D𝒍\bilMathematical Bold Italic Small L
    U+1D48E𝒎\bimMathematical Bold Italic Small M
    U+1D48F𝒏\binMathematical Bold Italic Small N
    U+1D490𝒐\bioMathematical Bold Italic Small O
    U+1D491𝒑\bipMathematical Bold Italic Small P
    U+1D492𝒒\biqMathematical Bold Italic Small Q
    U+1D493𝒓\birMathematical Bold Italic Small R
    U+1D494𝒔\bisMathematical Bold Italic Small S
    U+1D495𝒕\bitMathematical Bold Italic Small T
    U+1D496𝒖\biuMathematical Bold Italic Small U
    U+1D497𝒗\bivMathematical Bold Italic Small V
    U+1D498𝒘\biwMathematical Bold Italic Small W
    U+1D499𝒙\bixMathematical Bold Italic Small X
    U+1D49A𝒚\biyMathematical Bold Italic Small Y
    U+1D49B𝒛\bizMathematical Bold Italic Small Z
    U+1D49C𝒜\scrAMathematical Script Capital A
    U+1D49E𝒞\scrCMathematical Script Capital C
    U+1D49F𝒟\scrDMathematical Script Capital D
    U+1D4A2𝒢\scrGMathematical Script Capital G
    U+1D4A5𝒥\scrJMathematical Script Capital J
    U+1D4A6𝒦\scrKMathematical Script Capital K
    U+1D4A9𝒩\scrNMathematical Script Capital N
    U+1D4AA𝒪\scrOMathematical Script Capital O
    U+1D4AB𝒫\scrPMathematical Script Capital P
    U+1D4AC𝒬\scrQMathematical Script Capital Q
    U+1D4AE𝒮\scrSMathematical Script Capital S
    U+1D4AF𝒯\scrTMathematical Script Capital T
    U+1D4B0𝒰\scrUMathematical Script Capital U
    U+1D4B1𝒱\scrVMathematical Script Capital V
    U+1D4B2𝒲\scrWMathematical Script Capital W
    U+1D4B3𝒳\scrXMathematical Script Capital X
    U+1D4B4𝒴\scrYMathematical Script Capital Y
    U+1D4B5𝒵\scrZMathematical Script Capital Z
    U+1D4B6𝒶\scraMathematical Script Small A
    U+1D4B7𝒷\scrbMathematical Script Small B
    U+1D4B8𝒸\scrcMathematical Script Small C
    U+1D4B9𝒹\scrdMathematical Script Small D
    U+1D4BB𝒻\scrfMathematical Script Small F
    U+1D4BD𝒽\scrhMathematical Script Small H
    U+1D4BE𝒾\scriMathematical Script Small I
    U+1D4BF𝒿\scrjMathematical Script Small J
    U+1D4C0𝓀\scrkMathematical Script Small K
    U+1D4C1𝓁\scrlMathematical Script Small L
    U+1D4C2𝓂\scrmMathematical Script Small M
    U+1D4C3𝓃\scrnMathematical Script Small N
    U+1D4C5𝓅\scrpMathematical Script Small P
    U+1D4C6𝓆\scrqMathematical Script Small Q
    U+1D4C7𝓇\scrrMathematical Script Small R
    U+1D4C8𝓈\scrsMathematical Script Small S
    U+1D4C9𝓉\scrtMathematical Script Small T
    U+1D4CA𝓊\scruMathematical Script Small U
    U+1D4CB𝓋\scrvMathematical Script Small V
    U+1D4CC𝓌\scrwMathematical Script Small W
    U+1D4CD𝓍\scrxMathematical Script Small X
    U+1D4CE𝓎\scryMathematical Script Small Y
    U+1D4CF𝓏\scrzMathematical Script Small Z
    U+1D4D0𝓐\bscrAMathematical Bold Script Capital A
    U+1D4D1𝓑\bscrBMathematical Bold Script Capital B
    U+1D4D2𝓒\bscrCMathematical Bold Script Capital C
    U+1D4D3𝓓\bscrDMathematical Bold Script Capital D
    U+1D4D4𝓔\bscrEMathematical Bold Script Capital E
    U+1D4D5𝓕\bscrFMathematical Bold Script Capital F
    U+1D4D6𝓖\bscrGMathematical Bold Script Capital G
    U+1D4D7𝓗\bscrHMathematical Bold Script Capital H
    U+1D4D8𝓘\bscrIMathematical Bold Script Capital I
    U+1D4D9𝓙\bscrJMathematical Bold Script Capital J
    U+1D4DA𝓚\bscrKMathematical Bold Script Capital K
    U+1D4DB𝓛\bscrLMathematical Bold Script Capital L
    U+1D4DC𝓜\bscrMMathematical Bold Script Capital M
    U+1D4DD𝓝\bscrNMathematical Bold Script Capital N
    U+1D4DE𝓞\bscrOMathematical Bold Script Capital O
    U+1D4DF𝓟\bscrPMathematical Bold Script Capital P
    U+1D4E0𝓠\bscrQMathematical Bold Script Capital Q
    U+1D4E1𝓡\bscrRMathematical Bold Script Capital R
    U+1D4E2𝓢\bscrSMathematical Bold Script Capital S
    U+1D4E3𝓣\bscrTMathematical Bold Script Capital T
    U+1D4E4𝓤\bscrUMathematical Bold Script Capital U
    U+1D4E5𝓥\bscrVMathematical Bold Script Capital V
    U+1D4E6𝓦\bscrWMathematical Bold Script Capital W
    U+1D4E7𝓧\bscrXMathematical Bold Script Capital X
    U+1D4E8𝓨\bscrYMathematical Bold Script Capital Y
    U+1D4E9𝓩\bscrZMathematical Bold Script Capital Z
    U+1D4EA𝓪\bscraMathematical Bold Script Small A
    U+1D4EB𝓫\bscrbMathematical Bold Script Small B
    U+1D4EC𝓬\bscrcMathematical Bold Script Small C
    U+1D4ED𝓭\bscrdMathematical Bold Script Small D
    U+1D4EE𝓮\bscreMathematical Bold Script Small E
    U+1D4EF𝓯\bscrfMathematical Bold Script Small F
    U+1D4F0𝓰\bscrgMathematical Bold Script Small G
    U+1D4F1𝓱\bscrhMathematical Bold Script Small H
    U+1D4F2𝓲\bscriMathematical Bold Script Small I
    U+1D4F3𝓳\bscrjMathematical Bold Script Small J
    U+1D4F4𝓴\bscrkMathematical Bold Script Small K
    U+1D4F5𝓵\bscrlMathematical Bold Script Small L
    U+1D4F6𝓶\bscrmMathematical Bold Script Small M
    U+1D4F7𝓷\bscrnMathematical Bold Script Small N
    U+1D4F8𝓸\bscroMathematical Bold Script Small O
    U+1D4F9𝓹\bscrpMathematical Bold Script Small P
    U+1D4FA𝓺\bscrqMathematical Bold Script Small Q
    U+1D4FB𝓻\bscrrMathematical Bold Script Small R
    U+1D4FC𝓼\bscrsMathematical Bold Script Small S
    U+1D4FD𝓽\bscrtMathematical Bold Script Small T
    U+1D4FE𝓾\bscruMathematical Bold Script Small U
    U+1D4FF𝓿\bscrvMathematical Bold Script Small V
    U+1D500𝔀\bscrwMathematical Bold Script Small W
    U+1D501𝔁\bscrxMathematical Bold Script Small X
    U+1D502𝔂\bscryMathematical Bold Script Small Y
    U+1D503𝔃\bscrzMathematical Bold Script Small Z
    U+1D504𝔄\frakAMathematical Fraktur Capital A
    U+1D505𝔅\frakBMathematical Fraktur Capital B
    U+1D507𝔇\frakDMathematical Fraktur Capital D
    U+1D508𝔈\frakEMathematical Fraktur Capital E
    U+1D509𝔉\frakFMathematical Fraktur Capital F
    U+1D50A𝔊\frakGMathematical Fraktur Capital G
    U+1D50D𝔍\frakJMathematical Fraktur Capital J
    U+1D50E𝔎\frakKMathematical Fraktur Capital K
    U+1D50F𝔏\frakLMathematical Fraktur Capital L
    U+1D510𝔐\frakMMathematical Fraktur Capital M
    U+1D511𝔑\frakNMathematical Fraktur Capital N
    U+1D512𝔒\frakOMathematical Fraktur Capital O
    U+1D513𝔓\frakPMathematical Fraktur Capital P
    U+1D514𝔔\frakQMathematical Fraktur Capital Q
    U+1D516𝔖\frakSMathematical Fraktur Capital S
    U+1D517𝔗\frakTMathematical Fraktur Capital T
    U+1D518𝔘\frakUMathematical Fraktur Capital U
    U+1D519𝔙\frakVMathematical Fraktur Capital V
    U+1D51A𝔚\frakWMathematical Fraktur Capital W
    U+1D51B𝔛\frakXMathematical Fraktur Capital X
    U+1D51C𝔜\frakYMathematical Fraktur Capital Y
    U+1D51E𝔞\frakaMathematical Fraktur Small A
    U+1D51F𝔟\frakbMathematical Fraktur Small B
    U+1D520𝔠\frakcMathematical Fraktur Small C
    U+1D521𝔡\frakdMathematical Fraktur Small D
    U+1D522𝔢\frakeMathematical Fraktur Small E
    U+1D523𝔣\frakfMathematical Fraktur Small F
    U+1D524𝔤\frakgMathematical Fraktur Small G
    U+1D525𝔥\frakhMathematical Fraktur Small H
    U+1D526𝔦\frakiMathematical Fraktur Small I
    U+1D527𝔧\frakjMathematical Fraktur Small J
    U+1D528𝔨\frakkMathematical Fraktur Small K
    U+1D529𝔩\fraklMathematical Fraktur Small L
    U+1D52A𝔪\frakmMathematical Fraktur Small M
    U+1D52B𝔫\fraknMathematical Fraktur Small N
    U+1D52C𝔬\frakoMathematical Fraktur Small O
    U+1D52D𝔭\frakpMathematical Fraktur Small P
    U+1D52E𝔮\frakqMathematical Fraktur Small Q
    U+1D52F𝔯\frakrMathematical Fraktur Small R
    U+1D530𝔰\fraksMathematical Fraktur Small S
    U+1D531𝔱\fraktMathematical Fraktur Small T
    U+1D532𝔲\frakuMathematical Fraktur Small U
    U+1D533𝔳\frakvMathematical Fraktur Small V
    U+1D534𝔴\frakwMathematical Fraktur Small W
    U+1D535𝔵\frakxMathematical Fraktur Small X
    U+1D536𝔶\frakyMathematical Fraktur Small Y
    U+1D537𝔷\frakzMathematical Fraktur Small Z
    U+1D538𝔸\bbAMathematical Double-Struck Capital A
    U+1D539𝔹\bbBMathematical Double-Struck Capital B
    U+1D53B𝔻\bbDMathematical Double-Struck Capital D
    U+1D53C𝔼\bbEMathematical Double-Struck Capital E
    U+1D53D𝔽\bbFMathematical Double-Struck Capital F
    U+1D53E𝔾\bbGMathematical Double-Struck Capital G
    U+1D540𝕀\bbIMathematical Double-Struck Capital I
    U+1D541𝕁\bbJMathematical Double-Struck Capital J
    U+1D542𝕂\bbKMathematical Double-Struck Capital K
    U+1D543𝕃\bbLMathematical Double-Struck Capital L
    U+1D544𝕄\bbMMathematical Double-Struck Capital M
    U+1D546𝕆\bbOMathematical Double-Struck Capital O
    U+1D54A𝕊\bbSMathematical Double-Struck Capital S
    U+1D54B𝕋\bbTMathematical Double-Struck Capital T
    U+1D54C𝕌\bbUMathematical Double-Struck Capital U
    U+1D54D𝕍\bbVMathematical Double-Struck Capital V
    U+1D54E𝕎\bbWMathematical Double-Struck Capital W
    U+1D54F𝕏\bbXMathematical Double-Struck Capital X
    U+1D550𝕐\bbYMathematical Double-Struck Capital Y
    U+1D552𝕒\bbaMathematical Double-Struck Small A
    U+1D553𝕓\bbbMathematical Double-Struck Small B
    U+1D554𝕔\bbcMathematical Double-Struck Small C
    U+1D555𝕕\bbdMathematical Double-Struck Small D
    U+1D556𝕖\bbeMathematical Double-Struck Small E
    U+1D557𝕗\bbfMathematical Double-Struck Small F
    U+1D558𝕘\bbgMathematical Double-Struck Small G
    U+1D559𝕙\bbhMathematical Double-Struck Small H
    U+1D55A𝕚\bbiMathematical Double-Struck Small I
    U+1D55B𝕛\bbjMathematical Double-Struck Small J
    U+1D55C𝕜\bbkMathematical Double-Struck Small K
    U+1D55D𝕝\bblMathematical Double-Struck Small L
    U+1D55E𝕞\bbmMathematical Double-Struck Small M
    U+1D55F𝕟\bbnMathematical Double-Struck Small N
    U+1D560𝕠\bboMathematical Double-Struck Small O
    U+1D561𝕡\bbpMathematical Double-Struck Small P
    U+1D562𝕢\bbqMathematical Double-Struck Small Q
    U+1D563𝕣\bbrMathematical Double-Struck Small R
    U+1D564𝕤\bbsMathematical Double-Struck Small S
    U+1D565𝕥\bbtMathematical Double-Struck Small T
    U+1D566𝕦\bbuMathematical Double-Struck Small U
    U+1D567𝕧\bbvMathematical Double-Struck Small V
    U+1D568𝕨\bbwMathematical Double-Struck Small W
    U+1D569𝕩\bbxMathematical Double-Struck Small X
    U+1D56A𝕪\bbyMathematical Double-Struck Small Y
    U+1D56B𝕫\bbzMathematical Double-Struck Small Z
    U+1D56C𝕬\bfrakAMathematical Bold Fraktur Capital A
    U+1D56D𝕭\bfrakBMathematical Bold Fraktur Capital B
    U+1D56E𝕮\bfrakCMathematical Bold Fraktur Capital C
    U+1D56F𝕯\bfrakDMathematical Bold Fraktur Capital D
    U+1D570𝕰\bfrakEMathematical Bold Fraktur Capital E
    U+1D571𝕱\bfrakFMathematical Bold Fraktur Capital F
    U+1D572𝕲\bfrakGMathematical Bold Fraktur Capital G
    U+1D573𝕳\bfrakHMathematical Bold Fraktur Capital H
    U+1D574𝕴\bfrakIMathematical Bold Fraktur Capital I
    U+1D575𝕵\bfrakJMathematical Bold Fraktur Capital J
    U+1D576𝕶\bfrakKMathematical Bold Fraktur Capital K
    U+1D577𝕷\bfrakLMathematical Bold Fraktur Capital L
    U+1D578𝕸\bfrakMMathematical Bold Fraktur Capital M
    U+1D579𝕹\bfrakNMathematical Bold Fraktur Capital N
    U+1D57A𝕺\bfrakOMathematical Bold Fraktur Capital O
    U+1D57B𝕻\bfrakPMathematical Bold Fraktur Capital P
    U+1D57C𝕼\bfrakQMathematical Bold Fraktur Capital Q
    U+1D57D𝕽\bfrakRMathematical Bold Fraktur Capital R
    U+1D57E𝕾\bfrakSMathematical Bold Fraktur Capital S
    U+1D57F𝕿\bfrakTMathematical Bold Fraktur Capital T
    U+1D580𝖀\bfrakUMathematical Bold Fraktur Capital U
    U+1D581𝖁\bfrakVMathematical Bold Fraktur Capital V
    U+1D582𝖂\bfrakWMathematical Bold Fraktur Capital W
    U+1D583𝖃\bfrakXMathematical Bold Fraktur Capital X
    U+1D584𝖄\bfrakYMathematical Bold Fraktur Capital Y
    U+1D585𝖅\bfrakZMathematical Bold Fraktur Capital Z
    U+1D586𝖆\bfrakaMathematical Bold Fraktur Small A
    U+1D587𝖇\bfrakbMathematical Bold Fraktur Small B
    U+1D588𝖈\bfrakcMathematical Bold Fraktur Small C
    U+1D589𝖉\bfrakdMathematical Bold Fraktur Small D
    U+1D58A𝖊\bfrakeMathematical Bold Fraktur Small E
    U+1D58B𝖋\bfrakfMathematical Bold Fraktur Small F
    U+1D58C𝖌\bfrakgMathematical Bold Fraktur Small G
    U+1D58D𝖍\bfrakhMathematical Bold Fraktur Small H
    U+1D58E𝖎\bfrakiMathematical Bold Fraktur Small I
    U+1D58F𝖏\bfrakjMathematical Bold Fraktur Small J
    U+1D590𝖐\bfrakkMathematical Bold Fraktur Small K
    U+1D591𝖑\bfraklMathematical Bold Fraktur Small L
    U+1D592𝖒\bfrakmMathematical Bold Fraktur Small M
    U+1D593𝖓\bfraknMathematical Bold Fraktur Small N
    U+1D594𝖔\bfrakoMathematical Bold Fraktur Small O
    U+1D595𝖕\bfrakpMathematical Bold Fraktur Small P
    U+1D596𝖖\bfrakqMathematical Bold Fraktur Small Q
    U+1D597𝖗\bfrakrMathematical Bold Fraktur Small R
    U+1D598𝖘\bfraksMathematical Bold Fraktur Small S
    U+1D599𝖙\bfraktMathematical Bold Fraktur Small T
    U+1D59A𝖚\bfrakuMathematical Bold Fraktur Small U
    U+1D59B𝖛\bfrakvMathematical Bold Fraktur Small V
    U+1D59C𝖜\bfrakwMathematical Bold Fraktur Small W
    U+1D59D𝖝\bfrakxMathematical Bold Fraktur Small X
    U+1D59E𝖞\bfrakyMathematical Bold Fraktur Small Y
    U+1D59F𝖟\bfrakzMathematical Bold Fraktur Small Z
    U+1D5A0𝖠\sansAMathematical Sans-Serif Capital A
    U+1D5A1𝖡\sansBMathematical Sans-Serif Capital B
    U+1D5A2𝖢\sansCMathematical Sans-Serif Capital C
    U+1D5A3𝖣\sansDMathematical Sans-Serif Capital D
    U+1D5A4𝖤\sansEMathematical Sans-Serif Capital E
    U+1D5A5𝖥\sansFMathematical Sans-Serif Capital F
    U+1D5A6𝖦\sansGMathematical Sans-Serif Capital G
    U+1D5A7𝖧\sansHMathematical Sans-Serif Capital H
    U+1D5A8𝖨\sansIMathematical Sans-Serif Capital I
    U+1D5A9𝖩\sansJMathematical Sans-Serif Capital J
    U+1D5AA𝖪\sansKMathematical Sans-Serif Capital K
    U+1D5AB𝖫\sansLMathematical Sans-Serif Capital L
    U+1D5AC𝖬\sansMMathematical Sans-Serif Capital M
    U+1D5AD𝖭\sansNMathematical Sans-Serif Capital N
    U+1D5AE𝖮\sansOMathematical Sans-Serif Capital O
    U+1D5AF𝖯\sansPMathematical Sans-Serif Capital P
    U+1D5B0𝖰\sansQMathematical Sans-Serif Capital Q
    U+1D5B1𝖱\sansRMathematical Sans-Serif Capital R
    U+1D5B2𝖲\sansSMathematical Sans-Serif Capital S
    U+1D5B3𝖳\sansTMathematical Sans-Serif Capital T
    U+1D5B4𝖴\sansUMathematical Sans-Serif Capital U
    U+1D5B5𝖵\sansVMathematical Sans-Serif Capital V
    U+1D5B6𝖶\sansWMathematical Sans-Serif Capital W
    U+1D5B7𝖷\sansXMathematical Sans-Serif Capital X
    U+1D5B8𝖸\sansYMathematical Sans-Serif Capital Y
    U+1D5B9𝖹\sansZMathematical Sans-Serif Capital Z
    U+1D5BA𝖺\sansaMathematical Sans-Serif Small A
    U+1D5BB𝖻\sansbMathematical Sans-Serif Small B
    U+1D5BC𝖼\sanscMathematical Sans-Serif Small C
    U+1D5BD𝖽\sansdMathematical Sans-Serif Small D
    U+1D5BE𝖾\sanseMathematical Sans-Serif Small E
    U+1D5BF𝖿\sansfMathematical Sans-Serif Small F
    U+1D5C0𝗀\sansgMathematical Sans-Serif Small G
    U+1D5C1𝗁\sanshMathematical Sans-Serif Small H
    U+1D5C2𝗂\sansiMathematical Sans-Serif Small I
    U+1D5C3𝗃\sansjMathematical Sans-Serif Small J
    U+1D5C4𝗄\sanskMathematical Sans-Serif Small K
    U+1D5C5𝗅\sanslMathematical Sans-Serif Small L
    U+1D5C6𝗆\sansmMathematical Sans-Serif Small M
    U+1D5C7𝗇\sansnMathematical Sans-Serif Small N
    U+1D5C8𝗈\sansoMathematical Sans-Serif Small O
    U+1D5C9𝗉\sanspMathematical Sans-Serif Small P
    U+1D5CA𝗊\sansqMathematical Sans-Serif Small Q
    U+1D5CB𝗋\sansrMathematical Sans-Serif Small R
    U+1D5CC𝗌\sanssMathematical Sans-Serif Small S
    U+1D5CD𝗍\sanstMathematical Sans-Serif Small T
    U+1D5CE𝗎\sansuMathematical Sans-Serif Small U
    U+1D5CF𝗏\sansvMathematical Sans-Serif Small V
    U+1D5D0𝗐\sanswMathematical Sans-Serif Small W
    U+1D5D1𝗑\sansxMathematical Sans-Serif Small X
    U+1D5D2𝗒\sansyMathematical Sans-Serif Small Y
    U+1D5D3𝗓\sanszMathematical Sans-Serif Small Z
    U+1D5D4𝗔\bsansAMathematical Sans-Serif Bold Capital A
    U+1D5D5𝗕\bsansBMathematical Sans-Serif Bold Capital B
    U+1D5D6𝗖\bsansCMathematical Sans-Serif Bold Capital C
    U+1D5D7𝗗\bsansDMathematical Sans-Serif Bold Capital D
    U+1D5D8𝗘\bsansEMathematical Sans-Serif Bold Capital E
    U+1D5D9𝗙\bsansFMathematical Sans-Serif Bold Capital F
    U+1D5DA𝗚\bsansGMathematical Sans-Serif Bold Capital G
    U+1D5DB𝗛\bsansHMathematical Sans-Serif Bold Capital H
    U+1D5DC𝗜\bsansIMathematical Sans-Serif Bold Capital I
    U+1D5DD𝗝\bsansJMathematical Sans-Serif Bold Capital J
    U+1D5DE𝗞\bsansKMathematical Sans-Serif Bold Capital K
    U+1D5DF𝗟\bsansLMathematical Sans-Serif Bold Capital L
    U+1D5E0𝗠\bsansMMathematical Sans-Serif Bold Capital M
    U+1D5E1𝗡\bsansNMathematical Sans-Serif Bold Capital N
    U+1D5E2𝗢\bsansOMathematical Sans-Serif Bold Capital O
    U+1D5E3𝗣\bsansPMathematical Sans-Serif Bold Capital P
    U+1D5E4𝗤\bsansQMathematical Sans-Serif Bold Capital Q
    U+1D5E5𝗥\bsansRMathematical Sans-Serif Bold Capital R
    U+1D5E6𝗦\bsansSMathematical Sans-Serif Bold Capital S
    U+1D5E7𝗧\bsansTMathematical Sans-Serif Bold Capital T
    U+1D5E8𝗨\bsansUMathematical Sans-Serif Bold Capital U
    U+1D5E9𝗩\bsansVMathematical Sans-Serif Bold Capital V
    U+1D5EA𝗪\bsansWMathematical Sans-Serif Bold Capital W
    U+1D5EB𝗫\bsansXMathematical Sans-Serif Bold Capital X
    U+1D5EC𝗬\bsansYMathematical Sans-Serif Bold Capital Y
    U+1D5ED𝗭\bsansZMathematical Sans-Serif Bold Capital Z
    U+1D5EE𝗮\bsansaMathematical Sans-Serif Bold Small A
    U+1D5EF𝗯\bsansbMathematical Sans-Serif Bold Small B
    U+1D5F0𝗰\bsanscMathematical Sans-Serif Bold Small C
    U+1D5F1𝗱\bsansdMathematical Sans-Serif Bold Small D
    U+1D5F2𝗲\bsanseMathematical Sans-Serif Bold Small E
    U+1D5F3𝗳\bsansfMathematical Sans-Serif Bold Small F
    U+1D5F4𝗴\bsansgMathematical Sans-Serif Bold Small G
    U+1D5F5𝗵\bsanshMathematical Sans-Serif Bold Small H
    U+1D5F6𝗶\bsansiMathematical Sans-Serif Bold Small I
    U+1D5F7𝗷\bsansjMathematical Sans-Serif Bold Small J
    U+1D5F8𝗸\bsanskMathematical Sans-Serif Bold Small K
    U+1D5F9𝗹\bsanslMathematical Sans-Serif Bold Small L
    U+1D5FA𝗺\bsansmMathematical Sans-Serif Bold Small M
    U+1D5FB𝗻\bsansnMathematical Sans-Serif Bold Small N
    U+1D5FC𝗼\bsansoMathematical Sans-Serif Bold Small O
    U+1D5FD𝗽\bsanspMathematical Sans-Serif Bold Small P
    U+1D5FE𝗾\bsansqMathematical Sans-Serif Bold Small Q
    U+1D5FF𝗿\bsansrMathematical Sans-Serif Bold Small R
    U+1D600𝘀\bsanssMathematical Sans-Serif Bold Small S
    U+1D601𝘁\bsanstMathematical Sans-Serif Bold Small T
    U+1D602𝘂\bsansuMathematical Sans-Serif Bold Small U
    U+1D603𝘃\bsansvMathematical Sans-Serif Bold Small V
    U+1D604𝘄\bsanswMathematical Sans-Serif Bold Small W
    U+1D605𝘅\bsansxMathematical Sans-Serif Bold Small X
    U+1D606𝘆\bsansyMathematical Sans-Serif Bold Small Y
    U+1D607𝘇\bsanszMathematical Sans-Serif Bold Small Z
    U+1D608𝘈\isansAMathematical Sans-Serif Italic Capital A
    U+1D609𝘉\isansBMathematical Sans-Serif Italic Capital B
    U+1D60A𝘊\isansCMathematical Sans-Serif Italic Capital C
    U+1D60B𝘋\isansDMathematical Sans-Serif Italic Capital D
    U+1D60C𝘌\isansEMathematical Sans-Serif Italic Capital E
    U+1D60D𝘍\isansFMathematical Sans-Serif Italic Capital F
    U+1D60E𝘎\isansGMathematical Sans-Serif Italic Capital G
    U+1D60F𝘏\isansHMathematical Sans-Serif Italic Capital H
    U+1D610𝘐\isansIMathematical Sans-Serif Italic Capital I
    U+1D611𝘑\isansJMathematical Sans-Serif Italic Capital J
    U+1D612𝘒\isansKMathematical Sans-Serif Italic Capital K
    U+1D613𝘓\isansLMathematical Sans-Serif Italic Capital L
    U+1D614𝘔\isansMMathematical Sans-Serif Italic Capital M
    U+1D615𝘕\isansNMathematical Sans-Serif Italic Capital N
    U+1D616𝘖\isansOMathematical Sans-Serif Italic Capital O
    U+1D617𝘗\isansPMathematical Sans-Serif Italic Capital P
    U+1D618𝘘\isansQMathematical Sans-Serif Italic Capital Q
    U+1D619𝘙\isansRMathematical Sans-Serif Italic Capital R
    U+1D61A𝘚\isansSMathematical Sans-Serif Italic Capital S
    U+1D61B𝘛\isansTMathematical Sans-Serif Italic Capital T
    U+1D61C𝘜\isansUMathematical Sans-Serif Italic Capital U
    U+1D61D𝘝\isansVMathematical Sans-Serif Italic Capital V
    U+1D61E𝘞\isansWMathematical Sans-Serif Italic Capital W
    U+1D61F𝘟\isansXMathematical Sans-Serif Italic Capital X
    U+1D620𝘠\isansYMathematical Sans-Serif Italic Capital Y
    U+1D621𝘡\isansZMathematical Sans-Serif Italic Capital Z
    U+1D622𝘢\isansaMathematical Sans-Serif Italic Small A
    U+1D623𝘣\isansbMathematical Sans-Serif Italic Small B
    U+1D624𝘤\isanscMathematical Sans-Serif Italic Small C
    U+1D625𝘥\isansdMathematical Sans-Serif Italic Small D
    U+1D626𝘦\isanseMathematical Sans-Serif Italic Small E
    U+1D627𝘧\isansfMathematical Sans-Serif Italic Small F
    U+1D628𝘨\isansgMathematical Sans-Serif Italic Small G
    U+1D629𝘩\isanshMathematical Sans-Serif Italic Small H
    U+1D62A𝘪\isansiMathematical Sans-Serif Italic Small I
    U+1D62B𝘫\isansjMathematical Sans-Serif Italic Small J
    U+1D62C𝘬\isanskMathematical Sans-Serif Italic Small K
    U+1D62D𝘭\isanslMathematical Sans-Serif Italic Small L
    U+1D62E𝘮\isansmMathematical Sans-Serif Italic Small M
    U+1D62F𝘯\isansnMathematical Sans-Serif Italic Small N
    U+1D630𝘰\isansoMathematical Sans-Serif Italic Small O
    U+1D631𝘱\isanspMathematical Sans-Serif Italic Small P
    U+1D632𝘲\isansqMathematical Sans-Serif Italic Small Q
    U+1D633𝘳\isansrMathematical Sans-Serif Italic Small R
    U+1D634𝘴\isanssMathematical Sans-Serif Italic Small S
    U+1D635𝘵\isanstMathematical Sans-Serif Italic Small T
    U+1D636𝘶\isansuMathematical Sans-Serif Italic Small U
    U+1D637𝘷\isansvMathematical Sans-Serif Italic Small V
    U+1D638𝘸\isanswMathematical Sans-Serif Italic Small W
    U+1D639𝘹\isansxMathematical Sans-Serif Italic Small X
    U+1D63A𝘺\isansyMathematical Sans-Serif Italic Small Y
    U+1D63B𝘻\isanszMathematical Sans-Serif Italic Small Z
    U+1D63C𝘼\bisansAMathematical Sans-Serif Bold Italic Capital A
    U+1D63D𝘽\bisansBMathematical Sans-Serif Bold Italic Capital B
    U+1D63E𝘾\bisansCMathematical Sans-Serif Bold Italic Capital C
    U+1D63F𝘿\bisansDMathematical Sans-Serif Bold Italic Capital D
    U+1D640𝙀\bisansEMathematical Sans-Serif Bold Italic Capital E
    U+1D641𝙁\bisansFMathematical Sans-Serif Bold Italic Capital F
    U+1D642𝙂\bisansGMathematical Sans-Serif Bold Italic Capital G
    U+1D643𝙃\bisansHMathematical Sans-Serif Bold Italic Capital H
    U+1D644𝙄\bisansIMathematical Sans-Serif Bold Italic Capital I
    U+1D645𝙅\bisansJMathematical Sans-Serif Bold Italic Capital J
    U+1D646𝙆\bisansKMathematical Sans-Serif Bold Italic Capital K
    U+1D647𝙇\bisansLMathematical Sans-Serif Bold Italic Capital L
    U+1D648𝙈\bisansMMathematical Sans-Serif Bold Italic Capital M
    U+1D649𝙉\bisansNMathematical Sans-Serif Bold Italic Capital N
    U+1D64A𝙊\bisansOMathematical Sans-Serif Bold Italic Capital O
    U+1D64B𝙋\bisansPMathematical Sans-Serif Bold Italic Capital P
    U+1D64C𝙌\bisansQMathematical Sans-Serif Bold Italic Capital Q
    U+1D64D𝙍\bisansRMathematical Sans-Serif Bold Italic Capital R
    U+1D64E𝙎\bisansSMathematical Sans-Serif Bold Italic Capital S
    U+1D64F𝙏\bisansTMathematical Sans-Serif Bold Italic Capital T
    U+1D650𝙐\bisansUMathematical Sans-Serif Bold Italic Capital U
    U+1D651𝙑\bisansVMathematical Sans-Serif Bold Italic Capital V
    U+1D652𝙒\bisansWMathematical Sans-Serif Bold Italic Capital W
    U+1D653𝙓\bisansXMathematical Sans-Serif Bold Italic Capital X
    U+1D654𝙔\bisansYMathematical Sans-Serif Bold Italic Capital Y
    U+1D655𝙕\bisansZMathematical Sans-Serif Bold Italic Capital Z
    U+1D656𝙖\bisansaMathematical Sans-Serif Bold Italic Small A
    U+1D657𝙗\bisansbMathematical Sans-Serif Bold Italic Small B
    U+1D658𝙘\bisanscMathematical Sans-Serif Bold Italic Small C
    U+1D659𝙙\bisansdMathematical Sans-Serif Bold Italic Small D
    U+1D65A𝙚\bisanseMathematical Sans-Serif Bold Italic Small E
    U+1D65B𝙛\bisansfMathematical Sans-Serif Bold Italic Small F
    U+1D65C𝙜\bisansgMathematical Sans-Serif Bold Italic Small G
    U+1D65D𝙝\bisanshMathematical Sans-Serif Bold Italic Small H
    U+1D65E𝙞\bisansiMathematical Sans-Serif Bold Italic Small I
    U+1D65F𝙟\bisansjMathematical Sans-Serif Bold Italic Small J
    U+1D660𝙠\bisanskMathematical Sans-Serif Bold Italic Small K
    U+1D661𝙡\bisanslMathematical Sans-Serif Bold Italic Small L
    U+1D662𝙢\bisansmMathematical Sans-Serif Bold Italic Small M
    U+1D663𝙣\bisansnMathematical Sans-Serif Bold Italic Small N
    U+1D664𝙤\bisansoMathematical Sans-Serif Bold Italic Small O
    U+1D665𝙥\bisanspMathematical Sans-Serif Bold Italic Small P
    U+1D666𝙦\bisansqMathematical Sans-Serif Bold Italic Small Q
    U+1D667𝙧\bisansrMathematical Sans-Serif Bold Italic Small R
    U+1D668𝙨\bisanssMathematical Sans-Serif Bold Italic Small S
    U+1D669𝙩\bisanstMathematical Sans-Serif Bold Italic Small T
    U+1D66A𝙪\bisansuMathematical Sans-Serif Bold Italic Small U
    U+1D66B𝙫\bisansvMathematical Sans-Serif Bold Italic Small V
    U+1D66C𝙬\bisanswMathematical Sans-Serif Bold Italic Small W
    U+1D66D𝙭\bisansxMathematical Sans-Serif Bold Italic Small X
    U+1D66E𝙮\bisansyMathematical Sans-Serif Bold Italic Small Y
    U+1D66F𝙯\bisanszMathematical Sans-Serif Bold Italic Small Z
    U+1D670𝙰\ttAMathematical Monospace Capital A
    U+1D671𝙱\ttBMathematical Monospace Capital B
    U+1D672𝙲\ttCMathematical Monospace Capital C
    U+1D673𝙳\ttDMathematical Monospace Capital D
    U+1D674𝙴\ttEMathematical Monospace Capital E
    U+1D675𝙵\ttFMathematical Monospace Capital F
    U+1D676𝙶\ttGMathematical Monospace Capital G
    U+1D677𝙷\ttHMathematical Monospace Capital H
    U+1D678𝙸\ttIMathematical Monospace Capital I
    U+1D679𝙹\ttJMathematical Monospace Capital J
    U+1D67A𝙺\ttKMathematical Monospace Capital K
    U+1D67B𝙻\ttLMathematical Monospace Capital L
    U+1D67C𝙼\ttMMathematical Monospace Capital M
    U+1D67D𝙽\ttNMathematical Monospace Capital N
    U+1D67E𝙾\ttOMathematical Monospace Capital O
    U+1D67F𝙿\ttPMathematical Monospace Capital P
    U+1D680𝚀\ttQMathematical Monospace Capital Q
    U+1D681𝚁\ttRMathematical Monospace Capital R
    U+1D682𝚂\ttSMathematical Monospace Capital S
    U+1D683𝚃\ttTMathematical Monospace Capital T
    U+1D684𝚄\ttUMathematical Monospace Capital U
    U+1D685𝚅\ttVMathematical Monospace Capital V
    U+1D686𝚆\ttWMathematical Monospace Capital W
    U+1D687𝚇\ttXMathematical Monospace Capital X
    U+1D688𝚈\ttYMathematical Monospace Capital Y
    U+1D689𝚉\ttZMathematical Monospace Capital Z
    U+1D68A𝚊\ttaMathematical Monospace Small A
    U+1D68B𝚋\ttbMathematical Monospace Small B
    U+1D68C𝚌\ttcMathematical Monospace Small C
    U+1D68D𝚍\ttdMathematical Monospace Small D
    U+1D68E𝚎\tteMathematical Monospace Small E
    U+1D68F𝚏\ttfMathematical Monospace Small F
    U+1D690𝚐\ttgMathematical Monospace Small G
    U+1D691𝚑\tthMathematical Monospace Small H
    U+1D692𝚒\ttiMathematical Monospace Small I
    U+1D693𝚓\ttjMathematical Monospace Small J
    U+1D694𝚔\ttkMathematical Monospace Small K
    U+1D695𝚕\ttlMathematical Monospace Small L
    U+1D696𝚖\ttmMathematical Monospace Small M
    U+1D697𝚗\ttnMathematical Monospace Small N
    U+1D698𝚘\ttoMathematical Monospace Small O
    U+1D699𝚙\ttpMathematical Monospace Small P
    U+1D69A𝚚\ttqMathematical Monospace Small Q
    U+1D69B𝚛\ttrMathematical Monospace Small R
    U+1D69C𝚜\ttsMathematical Monospace Small S
    U+1D69D𝚝\tttMathematical Monospace Small T
    U+1D69E𝚞\ttuMathematical Monospace Small U
    U+1D69F𝚟\ttvMathematical Monospace Small V
    U+1D6A0𝚠\ttwMathematical Monospace Small W
    U+1D6A1𝚡\ttxMathematical Monospace Small X
    U+1D6A2𝚢\ttyMathematical Monospace Small Y
    U+1D6A3𝚣\ttzMathematical Monospace Small Z
    U+1D6A4𝚤\itimathMathematical Italic Small Dotless I
    U+1D6A5𝚥\itjmathMathematical Italic Small Dotless J
    U+1D6A8𝚨\bfAlphaMathematical Bold Capital Alpha
    U+1D6A9𝚩\bfBetaMathematical Bold Capital Beta
    U+1D6AA𝚪\bfGammaMathematical Bold Capital Gamma
    U+1D6AB𝚫\bfDeltaMathematical Bold Capital Delta
    U+1D6AC𝚬\bfEpsilonMathematical Bold Capital Epsilon
    U+1D6AD𝚭\bfZetaMathematical Bold Capital Zeta
    U+1D6AE𝚮\bfEtaMathematical Bold Capital Eta
    U+1D6AF𝚯\bfThetaMathematical Bold Capital Theta
    U+1D6B0𝚰\bfIotaMathematical Bold Capital Iota
    U+1D6B1𝚱\bfKappaMathematical Bold Capital Kappa
    U+1D6B2𝚲\bfLambdaMathematical Bold Capital Lamda
    U+1D6B3𝚳\bfMuMathematical Bold Capital Mu
    U+1D6B4𝚴\bfNuMathematical Bold Capital Nu
    U+1D6B5𝚵\bfXiMathematical Bold Capital Xi
    U+1D6B6𝚶\bfOmicronMathematical Bold Capital Omicron
    U+1D6B7𝚷\bfPiMathematical Bold Capital Pi
    U+1D6B8𝚸\bfRhoMathematical Bold Capital Rho
    U+1D6B9𝚹\bfvarThetaMathematical Bold Capital Theta Symbol
    U+1D6BA𝚺\bfSigmaMathematical Bold Capital Sigma
    U+1D6BB𝚻\bfTauMathematical Bold Capital Tau
    U+1D6BC𝚼\bfUpsilonMathematical Bold Capital Upsilon
    U+1D6BD𝚽\bfPhiMathematical Bold Capital Phi
    U+1D6BE𝚾\bfChiMathematical Bold Capital Chi
    U+1D6BF𝚿\bfPsiMathematical Bold Capital Psi
    U+1D6C0𝛀\bfOmegaMathematical Bold Capital Omega
    U+1D6C1𝛁\bfnablaMathematical Bold Nabla
    U+1D6C2𝛂\bfalphaMathematical Bold Small Alpha
    U+1D6C3𝛃\bfbetaMathematical Bold Small Beta
    U+1D6C4𝛄\bfgammaMathematical Bold Small Gamma
    U+1D6C5𝛅\bfdeltaMathematical Bold Small Delta
    U+1D6C6𝛆\bfvarepsilonMathematical Bold Small Epsilon
    U+1D6C7𝛇\bfzetaMathematical Bold Small Zeta
    U+1D6C8𝛈\bfetaMathematical Bold Small Eta
    U+1D6C9𝛉\bfthetaMathematical Bold Small Theta
    U+1D6CA𝛊\bfiotaMathematical Bold Small Iota
    U+1D6CB𝛋\bfkappaMathematical Bold Small Kappa
    U+1D6CC𝛌\bflambdaMathematical Bold Small Lamda
    U+1D6CD𝛍\bfmuMathematical Bold Small Mu
    U+1D6CE𝛎\bfnuMathematical Bold Small Nu
    U+1D6CF𝛏\bfxiMathematical Bold Small Xi
    U+1D6D0𝛐\bfomicronMathematical Bold Small Omicron
    U+1D6D1𝛑\bfpiMathematical Bold Small Pi
    U+1D6D2𝛒\bfrhoMathematical Bold Small Rho
    U+1D6D3𝛓\bfvarsigmaMathematical Bold Small Final Sigma
    U+1D6D4𝛔\bfsigmaMathematical Bold Small Sigma
    U+1D6D5𝛕\bftauMathematical Bold Small Tau
    U+1D6D6𝛖\bfupsilonMathematical Bold Small Upsilon
    U+1D6D7𝛗\bfvarphiMathematical Bold Small Phi
    U+1D6D8𝛘\bfchiMathematical Bold Small Chi
    U+1D6D9𝛙\bfpsiMathematical Bold Small Psi
    U+1D6DA𝛚\bfomegaMathematical Bold Small Omega
    U+1D6DB𝛛\bfpartialMathematical Bold Partial Differential
    U+1D6DC𝛜\bfepsilonMathematical Bold Epsilon Symbol
    U+1D6DD𝛝\bfvarthetaMathematical Bold Theta Symbol
    U+1D6DE𝛞\bfvarkappaMathematical Bold Kappa Symbol
    U+1D6DF𝛟\bfphiMathematical Bold Phi Symbol
    U+1D6E0𝛠\bfvarrhoMathematical Bold Rho Symbol
    U+1D6E1𝛡\bfvarpiMathematical Bold Pi Symbol
    U+1D6E2𝛢\itAlphaMathematical Italic Capital Alpha
    U+1D6E3𝛣\itBetaMathematical Italic Capital Beta
    U+1D6E4𝛤\itGammaMathematical Italic Capital Gamma
    U+1D6E5𝛥\itDeltaMathematical Italic Capital Delta
    U+1D6E6𝛦\itEpsilonMathematical Italic Capital Epsilon
    U+1D6E7𝛧\itZetaMathematical Italic Capital Zeta
    U+1D6E8𝛨\itEtaMathematical Italic Capital Eta
    U+1D6E9𝛩\itThetaMathematical Italic Capital Theta
    U+1D6EA𝛪\itIotaMathematical Italic Capital Iota
    U+1D6EB𝛫\itKappaMathematical Italic Capital Kappa
    U+1D6EC𝛬\itLambdaMathematical Italic Capital Lamda
    U+1D6ED𝛭\itMuMathematical Italic Capital Mu
    U+1D6EE𝛮\itNuMathematical Italic Capital Nu
    U+1D6EF𝛯\itXiMathematical Italic Capital Xi
    U+1D6F0𝛰\itOmicronMathematical Italic Capital Omicron
    U+1D6F1𝛱\itPiMathematical Italic Capital Pi
    U+1D6F2𝛲\itRhoMathematical Italic Capital Rho
    U+1D6F3𝛳\itvarThetaMathematical Italic Capital Theta Symbol
    U+1D6F4𝛴\itSigmaMathematical Italic Capital Sigma
    U+1D6F5𝛵\itTauMathematical Italic Capital Tau
    U+1D6F6𝛶\itUpsilonMathematical Italic Capital Upsilon
    U+1D6F7𝛷\itPhiMathematical Italic Capital Phi
    U+1D6F8𝛸\itChiMathematical Italic Capital Chi
    U+1D6F9𝛹\itPsiMathematical Italic Capital Psi
    U+1D6FA𝛺\itOmegaMathematical Italic Capital Omega
    U+1D6FB𝛻\itnablaMathematical Italic Nabla
    U+1D6FC𝛼\italphaMathematical Italic Small Alpha
    U+1D6FD𝛽\itbetaMathematical Italic Small Beta
    U+1D6FE𝛾\itgammaMathematical Italic Small Gamma
    U+1D6FF𝛿\itdeltaMathematical Italic Small Delta
    U+1D700𝜀\itvarepsilonMathematical Italic Small Epsilon
    U+1D701𝜁\itzetaMathematical Italic Small Zeta
    U+1D702𝜂\itetaMathematical Italic Small Eta
    U+1D703𝜃\itthetaMathematical Italic Small Theta
    U+1D704𝜄\itiotaMathematical Italic Small Iota
    U+1D705𝜅\itkappaMathematical Italic Small Kappa
    U+1D706𝜆\itlambdaMathematical Italic Small Lamda
    U+1D707𝜇\itmuMathematical Italic Small Mu
    U+1D708𝜈\itnuMathematical Italic Small Nu
    U+1D709𝜉\itxiMathematical Italic Small Xi
    U+1D70A𝜊\itomicronMathematical Italic Small Omicron
    U+1D70B𝜋\itpiMathematical Italic Small Pi
    U+1D70C𝜌\itrhoMathematical Italic Small Rho
    U+1D70D𝜍\itvarsigmaMathematical Italic Small Final Sigma
    U+1D70E𝜎\itsigmaMathematical Italic Small Sigma
    U+1D70F𝜏\ittauMathematical Italic Small Tau
    U+1D710𝜐\itupsilonMathematical Italic Small Upsilon
    U+1D711𝜑\itvarphiMathematical Italic Small Phi
    U+1D712𝜒\itchiMathematical Italic Small Chi
    U+1D713𝜓\itpsiMathematical Italic Small Psi
    U+1D714𝜔\itomegaMathematical Italic Small Omega
    U+1D715𝜕\itpartialMathematical Italic Partial Differential
    U+1D716𝜖\itepsilonMathematical Italic Epsilon Symbol
    U+1D717𝜗\itvarthetaMathematical Italic Theta Symbol
    U+1D718𝜘\itvarkappaMathematical Italic Kappa Symbol
    U+1D719𝜙\itphiMathematical Italic Phi Symbol
    U+1D71A𝜚\itvarrhoMathematical Italic Rho Symbol
    U+1D71B𝜛\itvarpiMathematical Italic Pi Symbol
    U+1D71C𝜜\biAlphaMathematical Bold Italic Capital Alpha
    U+1D71D𝜝\biBetaMathematical Bold Italic Capital Beta
    U+1D71E𝜞\biGammaMathematical Bold Italic Capital Gamma
    U+1D71F𝜟\biDeltaMathematical Bold Italic Capital Delta
    U+1D720𝜠\biEpsilonMathematical Bold Italic Capital Epsilon
    U+1D721𝜡\biZetaMathematical Bold Italic Capital Zeta
    U+1D722𝜢\biEtaMathematical Bold Italic Capital Eta
    U+1D723𝜣\biThetaMathematical Bold Italic Capital Theta
    U+1D724𝜤\biIotaMathematical Bold Italic Capital Iota
    U+1D725𝜥\biKappaMathematical Bold Italic Capital Kappa
    U+1D726𝜦\biLambdaMathematical Bold Italic Capital Lamda
    U+1D727𝜧\biMuMathematical Bold Italic Capital Mu
    U+1D728𝜨\biNuMathematical Bold Italic Capital Nu
    U+1D729𝜩\biXiMathematical Bold Italic Capital Xi
    U+1D72A𝜪\biOmicronMathematical Bold Italic Capital Omicron
    U+1D72B𝜫\biPiMathematical Bold Italic Capital Pi
    U+1D72C𝜬\biRhoMathematical Bold Italic Capital Rho
    U+1D72D𝜭\bivarThetaMathematical Bold Italic Capital Theta Symbol
    U+1D72E𝜮\biSigmaMathematical Bold Italic Capital Sigma
    U+1D72F𝜯\biTauMathematical Bold Italic Capital Tau
    U+1D730𝜰\biUpsilonMathematical Bold Italic Capital Upsilon
    U+1D731𝜱\biPhiMathematical Bold Italic Capital Phi
    U+1D732𝜲\biChiMathematical Bold Italic Capital Chi
    U+1D733𝜳\biPsiMathematical Bold Italic Capital Psi
    U+1D734𝜴\biOmegaMathematical Bold Italic Capital Omega
    U+1D735𝜵\binablaMathematical Bold Italic Nabla
    U+1D736𝜶\bialphaMathematical Bold Italic Small Alpha
    U+1D737𝜷\bibetaMathematical Bold Italic Small Beta
    U+1D738𝜸\bigammaMathematical Bold Italic Small Gamma
    U+1D739𝜹\bideltaMathematical Bold Italic Small Delta
    U+1D73A𝜺\bivarepsilonMathematical Bold Italic Small Epsilon
    U+1D73B𝜻\bizetaMathematical Bold Italic Small Zeta
    U+1D73C𝜼\bietaMathematical Bold Italic Small Eta
    U+1D73D𝜽\bithetaMathematical Bold Italic Small Theta
    U+1D73E𝜾\biiotaMathematical Bold Italic Small Iota
    U+1D73F𝜿\bikappaMathematical Bold Italic Small Kappa
    U+1D740𝝀\bilambdaMathematical Bold Italic Small Lamda
    U+1D741𝝁\bimuMathematical Bold Italic Small Mu
    U+1D742𝝂\binuMathematical Bold Italic Small Nu
    U+1D743𝝃\bixiMathematical Bold Italic Small Xi
    U+1D744𝝄\biomicronMathematical Bold Italic Small Omicron
    U+1D745𝝅\bipiMathematical Bold Italic Small Pi
    U+1D746𝝆\birhoMathematical Bold Italic Small Rho
    U+1D747𝝇\bivarsigmaMathematical Bold Italic Small Final Sigma
    U+1D748𝝈\bisigmaMathematical Bold Italic Small Sigma
    U+1D749𝝉\bitauMathematical Bold Italic Small Tau
    U+1D74A𝝊\biupsilonMathematical Bold Italic Small Upsilon
    U+1D74B𝝋\bivarphiMathematical Bold Italic Small Phi
    U+1D74C𝝌\bichiMathematical Bold Italic Small Chi
    U+1D74D𝝍\bipsiMathematical Bold Italic Small Psi
    U+1D74E𝝎\biomegaMathematical Bold Italic Small Omega
    U+1D74F𝝏\bipartialMathematical Bold Italic Partial Differential
    U+1D750𝝐\biepsilonMathematical Bold Italic Epsilon Symbol
    U+1D751𝝑\bivarthetaMathematical Bold Italic Theta Symbol
    U+1D752𝝒\bivarkappaMathematical Bold Italic Kappa Symbol
    U+1D753𝝓\biphiMathematical Bold Italic Phi Symbol
    U+1D754𝝔\bivarrhoMathematical Bold Italic Rho Symbol
    U+1D755𝝕\bivarpiMathematical Bold Italic Pi Symbol
    U+1D756𝝖\bsansAlphaMathematical Sans-Serif Bold Capital Alpha
    U+1D757𝝗\bsansBetaMathematical Sans-Serif Bold Capital Beta
    U+1D758𝝘\bsansGammaMathematical Sans-Serif Bold Capital Gamma
    U+1D759𝝙\bsansDeltaMathematical Sans-Serif Bold Capital Delta
    U+1D75A𝝚\bsansEpsilonMathematical Sans-Serif Bold Capital Epsilon
    U+1D75B𝝛\bsansZetaMathematical Sans-Serif Bold Capital Zeta
    U+1D75C𝝜\bsansEtaMathematical Sans-Serif Bold Capital Eta
    U+1D75D𝝝\bsansThetaMathematical Sans-Serif Bold Capital Theta
    U+1D75E𝝞\bsansIotaMathematical Sans-Serif Bold Capital Iota
    U+1D75F𝝟\bsansKappaMathematical Sans-Serif Bold Capital Kappa
    U+1D760𝝠\bsansLambdaMathematical Sans-Serif Bold Capital Lamda
    U+1D761𝝡\bsansMuMathematical Sans-Serif Bold Capital Mu
    U+1D762𝝢\bsansNuMathematical Sans-Serif Bold Capital Nu
    U+1D763𝝣\bsansXiMathematical Sans-Serif Bold Capital Xi
    U+1D764𝝤\bsansOmicronMathematical Sans-Serif Bold Capital Omicron
    U+1D765𝝥\bsansPiMathematical Sans-Serif Bold Capital Pi
    U+1D766𝝦\bsansRhoMathematical Sans-Serif Bold Capital Rho
    U+1D767𝝧\bsansvarThetaMathematical Sans-Serif Bold Capital Theta Symbol
    U+1D768𝝨\bsansSigmaMathematical Sans-Serif Bold Capital Sigma
    U+1D769𝝩\bsansTauMathematical Sans-Serif Bold Capital Tau
    U+1D76A𝝪\bsansUpsilonMathematical Sans-Serif Bold Capital Upsilon
    U+1D76B𝝫\bsansPhiMathematical Sans-Serif Bold Capital Phi
    U+1D76C𝝬\bsansChiMathematical Sans-Serif Bold Capital Chi
    U+1D76D𝝭\bsansPsiMathematical Sans-Serif Bold Capital Psi
    U+1D76E𝝮\bsansOmegaMathematical Sans-Serif Bold Capital Omega
    U+1D76F𝝯\bsansnablaMathematical Sans-Serif Bold Nabla
    U+1D770𝝰\bsansalphaMathematical Sans-Serif Bold Small Alpha
    U+1D771𝝱\bsansbetaMathematical Sans-Serif Bold Small Beta
    U+1D772𝝲\bsansgammaMathematical Sans-Serif Bold Small Gamma
    U+1D773𝝳\bsansdeltaMathematical Sans-Serif Bold Small Delta
    U+1D774𝝴\bsansvarepsilonMathematical Sans-Serif Bold Small Epsilon
    U+1D775𝝵\bsanszetaMathematical Sans-Serif Bold Small Zeta
    U+1D776𝝶\bsansetaMathematical Sans-Serif Bold Small Eta
    U+1D777𝝷\bsansthetaMathematical Sans-Serif Bold Small Theta
    U+1D778𝝸\bsansiotaMathematical Sans-Serif Bold Small Iota
    U+1D779𝝹\bsanskappaMathematical Sans-Serif Bold Small Kappa
    U+1D77A𝝺\bsanslambdaMathematical Sans-Serif Bold Small Lamda
    U+1D77B𝝻\bsansmuMathematical Sans-Serif Bold Small Mu
    U+1D77C𝝼\bsansnuMathematical Sans-Serif Bold Small Nu
    U+1D77D𝝽\bsansxiMathematical Sans-Serif Bold Small Xi
    U+1D77E𝝾\bsansomicronMathematical Sans-Serif Bold Small Omicron
    U+1D77F𝝿\bsanspiMathematical Sans-Serif Bold Small Pi
    U+1D780𝞀\bsansrhoMathematical Sans-Serif Bold Small Rho
    U+1D781𝞁\bsansvarsigmaMathematical Sans-Serif Bold Small Final Sigma
    U+1D782𝞂\bsanssigmaMathematical Sans-Serif Bold Small Sigma
    U+1D783𝞃\bsanstauMathematical Sans-Serif Bold Small Tau
    U+1D784𝞄\bsansupsilonMathematical Sans-Serif Bold Small Upsilon
    U+1D785𝞅\bsansvarphiMathematical Sans-Serif Bold Small Phi
    U+1D786𝞆\bsanschiMathematical Sans-Serif Bold Small Chi
    U+1D787𝞇\bsanspsiMathematical Sans-Serif Bold Small Psi
    U+1D788𝞈\bsansomegaMathematical Sans-Serif Bold Small Omega
    U+1D789𝞉\bsanspartialMathematical Sans-Serif Bold Partial Differential
    U+1D78A𝞊\bsansepsilonMathematical Sans-Serif Bold Epsilon Symbol
    U+1D78B𝞋\bsansvarthetaMathematical Sans-Serif Bold Theta Symbol
    U+1D78C𝞌\bsansvarkappaMathematical Sans-Serif Bold Kappa Symbol
    U+1D78D𝞍\bsansphiMathematical Sans-Serif Bold Phi Symbol
    U+1D78E𝞎\bsansvarrhoMathematical Sans-Serif Bold Rho Symbol
    U+1D78F𝞏\bsansvarpiMathematical Sans-Serif Bold Pi Symbol
    U+1D790𝞐\bisansAlphaMathematical Sans-Serif Bold Italic Capital Alpha
    U+1D791𝞑\bisansBetaMathematical Sans-Serif Bold Italic Capital Beta
    U+1D792𝞒\bisansGammaMathematical Sans-Serif Bold Italic Capital Gamma
    U+1D793𝞓\bisansDeltaMathematical Sans-Serif Bold Italic Capital Delta
    U+1D794𝞔\bisansEpsilonMathematical Sans-Serif Bold Italic Capital Epsilon
    U+1D795𝞕\bisansZetaMathematical Sans-Serif Bold Italic Capital Zeta
    U+1D796𝞖\bisansEtaMathematical Sans-Serif Bold Italic Capital Eta
    U+1D797𝞗\bisansThetaMathematical Sans-Serif Bold Italic Capital Theta
    U+1D798𝞘\bisansIotaMathematical Sans-Serif Bold Italic Capital Iota
    U+1D799𝞙\bisansKappaMathematical Sans-Serif Bold Italic Capital Kappa
    U+1D79A𝞚\bisansLambdaMathematical Sans-Serif Bold Italic Capital Lamda
    U+1D79B𝞛\bisansMuMathematical Sans-Serif Bold Italic Capital Mu
    U+1D79C𝞜\bisansNuMathematical Sans-Serif Bold Italic Capital Nu
    U+1D79D𝞝\bisansXiMathematical Sans-Serif Bold Italic Capital Xi
    U+1D79E𝞞\bisansOmicronMathematical Sans-Serif Bold Italic Capital Omicron
    U+1D79F𝞟\bisansPiMathematical Sans-Serif Bold Italic Capital Pi
    U+1D7A0𝞠\bisansRhoMathematical Sans-Serif Bold Italic Capital Rho
    U+1D7A1𝞡\bisansvarThetaMathematical Sans-Serif Bold Italic Capital Theta Symbol
    U+1D7A2𝞢\bisansSigmaMathematical Sans-Serif Bold Italic Capital Sigma
    U+1D7A3𝞣\bisansTauMathematical Sans-Serif Bold Italic Capital Tau
    U+1D7A4𝞤\bisansUpsilonMathematical Sans-Serif Bold Italic Capital Upsilon
    U+1D7A5𝞥\bisansPhiMathematical Sans-Serif Bold Italic Capital Phi
    U+1D7A6𝞦\bisansChiMathematical Sans-Serif Bold Italic Capital Chi
    U+1D7A7𝞧\bisansPsiMathematical Sans-Serif Bold Italic Capital Psi
    U+1D7A8𝞨\bisansOmegaMathematical Sans-Serif Bold Italic Capital Omega
    U+1D7A9𝞩\bisansnablaMathematical Sans-Serif Bold Italic Nabla
    U+1D7AA𝞪\bisansalphaMathematical Sans-Serif Bold Italic Small Alpha
    U+1D7AB𝞫\bisansbetaMathematical Sans-Serif Bold Italic Small Beta
    U+1D7AC𝞬\bisansgammaMathematical Sans-Serif Bold Italic Small Gamma
    U+1D7AD𝞭\bisansdeltaMathematical Sans-Serif Bold Italic Small Delta
    U+1D7AE𝞮\bisansvarepsilonMathematical Sans-Serif Bold Italic Small Epsilon
    U+1D7AF𝞯\bisanszetaMathematical Sans-Serif Bold Italic Small Zeta
    U+1D7B0𝞰\bisansetaMathematical Sans-Serif Bold Italic Small Eta
    U+1D7B1𝞱\bisansthetaMathematical Sans-Serif Bold Italic Small Theta
    U+1D7B2𝞲\bisansiotaMathematical Sans-Serif Bold Italic Small Iota
    U+1D7B3𝞳\bisanskappaMathematical Sans-Serif Bold Italic Small Kappa
    U+1D7B4𝞴\bisanslambdaMathematical Sans-Serif Bold Italic Small Lamda
    U+1D7B5𝞵\bisansmuMathematical Sans-Serif Bold Italic Small Mu
    U+1D7B6𝞶\bisansnuMathematical Sans-Serif Bold Italic Small Nu
    U+1D7B7𝞷\bisansxiMathematical Sans-Serif Bold Italic Small Xi
    U+1D7B8𝞸\bisansomicronMathematical Sans-Serif Bold Italic Small Omicron
    U+1D7B9𝞹\bisanspiMathematical Sans-Serif Bold Italic Small Pi
    U+1D7BA𝞺\bisansrhoMathematical Sans-Serif Bold Italic Small Rho
    U+1D7BB𝞻\bisansvarsigmaMathematical Sans-Serif Bold Italic Small Final Sigma
    U+1D7BC𝞼\bisanssigmaMathematical Sans-Serif Bold Italic Small Sigma
    U+1D7BD𝞽\bisanstauMathematical Sans-Serif Bold Italic Small Tau
    U+1D7BE𝞾\bisansupsilonMathematical Sans-Serif Bold Italic Small Upsilon
    U+1D7BF𝞿\bisansvarphiMathematical Sans-Serif Bold Italic Small Phi
    U+1D7C0𝟀\bisanschiMathematical Sans-Serif Bold Italic Small Chi
    U+1D7C1𝟁\bisanspsiMathematical Sans-Serif Bold Italic Small Psi
    U+1D7C2𝟂\bisansomegaMathematical Sans-Serif Bold Italic Small Omega
    U+1D7C3𝟃\bisanspartialMathematical Sans-Serif Bold Italic Partial Differential
    U+1D7C4𝟄\bisansepsilonMathematical Sans-Serif Bold Italic Epsilon Symbol
    U+1D7C5𝟅\bisansvarthetaMathematical Sans-Serif Bold Italic Theta Symbol
    U+1D7C6𝟆\bisansvarkappaMathematical Sans-Serif Bold Italic Kappa Symbol
    U+1D7C7𝟇\bisansphiMathematical Sans-Serif Bold Italic Phi Symbol
    U+1D7C8𝟈\bisansvarrhoMathematical Sans-Serif Bold Italic Rho Symbol
    U+1D7C9𝟉\bisansvarpiMathematical Sans-Serif Bold Italic Pi Symbol
    U+1D7CA𝟊\bfDigammaMathematical Bold Capital Digamma
    U+1D7CB𝟋\bfdigammaMathematical Bold Small Digamma
    U+1D7CE𝟎\bfzeroMathematical Bold Digit Zero
    U+1D7CF𝟏\bfoneMathematical Bold Digit One
    U+1D7D0𝟐\bftwoMathematical Bold Digit Two
    U+1D7D1𝟑\bfthreeMathematical Bold Digit Three
    U+1D7D2𝟒\bffourMathematical Bold Digit Four
    U+1D7D3𝟓\bffiveMathematical Bold Digit Five
    U+1D7D4𝟔\bfsixMathematical Bold Digit Six
    U+1D7D5𝟕\bfsevenMathematical Bold Digit Seven
    U+1D7D6𝟖\bfeightMathematical Bold Digit Eight
    U+1D7D7𝟗\bfnineMathematical Bold Digit Nine
    U+1D7D8𝟘\bbzeroMathematical Double-Struck Digit Zero
    U+1D7D9𝟙\bboneMathematical Double-Struck Digit One
    U+1D7DA𝟚\bbtwoMathematical Double-Struck Digit Two
    U+1D7DB𝟛\bbthreeMathematical Double-Struck Digit Three
    U+1D7DC𝟜\bbfourMathematical Double-Struck Digit Four
    U+1D7DD𝟝\bbfiveMathematical Double-Struck Digit Five
    U+1D7DE𝟞\bbsixMathematical Double-Struck Digit Six
    U+1D7DF𝟟\bbsevenMathematical Double-Struck Digit Seven
    U+1D7E0𝟠\bbeightMathematical Double-Struck Digit Eight
    U+1D7E1𝟡\bbnineMathematical Double-Struck Digit Nine
    U+1D7E2𝟢\sanszeroMathematical Sans-Serif Digit Zero
    U+1D7E3𝟣\sansoneMathematical Sans-Serif Digit One
    U+1D7E4𝟤\sanstwoMathematical Sans-Serif Digit Two
    U+1D7E5𝟥\sansthreeMathematical Sans-Serif Digit Three
    U+1D7E6𝟦\sansfourMathematical Sans-Serif Digit Four
    U+1D7E7𝟧\sansfiveMathematical Sans-Serif Digit Five
    U+1D7E8𝟨\sanssixMathematical Sans-Serif Digit Six
    U+1D7E9𝟩\sanssevenMathematical Sans-Serif Digit Seven
    U+1D7EA𝟪\sanseightMathematical Sans-Serif Digit Eight
    U+1D7EB𝟫\sansnineMathematical Sans-Serif Digit Nine
    U+1D7EC𝟬\bsanszeroMathematical Sans-Serif Bold Digit Zero
    U+1D7ED𝟭\bsansoneMathematical Sans-Serif Bold Digit One
    U+1D7EE𝟮\bsanstwoMathematical Sans-Serif Bold Digit Two
    U+1D7EF𝟯\bsansthreeMathematical Sans-Serif Bold Digit Three
    U+1D7F0𝟰\bsansfourMathematical Sans-Serif Bold Digit Four
    U+1D7F1𝟱\bsansfiveMathematical Sans-Serif Bold Digit Five
    U+1D7F2𝟲\bsanssixMathematical Sans-Serif Bold Digit Six
    U+1D7F3𝟳\bsanssevenMathematical Sans-Serif Bold Digit Seven
    U+1D7F4𝟴\bsanseightMathematical Sans-Serif Bold Digit Eight
    U+1D7F5𝟵\bsansnineMathematical Sans-Serif Bold Digit Nine
    U+1D7F6𝟶\ttzeroMathematical Monospace Digit Zero
    U+1D7F7𝟷\ttoneMathematical Monospace Digit One
    U+1D7F8𝟸\tttwoMathematical Monospace Digit Two
    U+1D7F9𝟹\ttthreeMathematical Monospace Digit Three
    U+1D7FA𝟺\ttfourMathematical Monospace Digit Four
    U+1D7FB𝟻\ttfiveMathematical Monospace Digit Five
    U+1D7FC𝟼\ttsixMathematical Monospace Digit Six
    U+1D7FD𝟽\ttsevenMathematical Monospace Digit Seven
    U+1D7FE𝟾\tteightMathematical Monospace Digit Eight
    U+1D7FF𝟿\ttnineMathematical Monospace Digit Nine
    U+1F004🀄\:mahjong:Mahjong Tile Red Dragon
    U+1F0CF🃏\:black_joker:Playing Card Black Joker
    U+1F170🅰\:a:Negative Squared Latin Capital Letter A
    U+1F171🅱\:b:Negative Squared Latin Capital Letter B
    U+1F17E🅾\:o2:Negative Squared Latin Capital Letter O
    U+1F17F🅿\:parking:Negative Squared Latin Capital Letter P
    U+1F18E🆎\:ab:Negative Squared Ab
    U+1F191🆑\:cl:Squared Cl
    U+1F192🆒\:cool:Squared Cool
    U+1F193🆓\:free:Squared Free
    U+1F194🆔\:id:Squared Id
    U+1F195🆕\:new:Squared New
    U+1F196🆖\:ng:Squared Ng
    U+1F197🆗\:ok:Squared Ok
    U+1F198🆘\:sos:Squared Sos
    U+1F199🆙\:up:Squared Up With Exclamation Mark
    U+1F19A🆚\:vs:Squared Vs
    U+1F201🈁\:koko:Squared Katakana Koko
    U+1F202🈂\:sa:Squared Katakana Sa
    U+1F21A🈚\:u7121:Squared Cjk Unified Ideograph-7121
    U+1F22F🈯\:u6307:Squared Cjk Unified Ideograph-6307
    U+1F232🈲\:u7981:Squared Cjk Unified Ideograph-7981
    U+1F233🈳\:u7a7a:Squared Cjk Unified Ideograph-7A7A
    U+1F234🈴\:u5408:Squared Cjk Unified Ideograph-5408
    U+1F235🈵\:u6e80:Squared Cjk Unified Ideograph-6E80
    U+1F236🈶\:u6709:Squared Cjk Unified Ideograph-6709
    U+1F237🈷\:u6708:Squared Cjk Unified Ideograph-6708
    U+1F238🈸\:u7533:Squared Cjk Unified Ideograph-7533
    U+1F239🈹\:u5272:Squared Cjk Unified Ideograph-5272
    U+1F23A🈺\:u55b6:Squared Cjk Unified Ideograph-55B6
    U+1F250🉐\:ideograph_advantage:Circled Ideograph Advantage
    U+1F251🉑\:accept:Circled Ideograph Accept
    U+1F300🌀\:cyclone:Cyclone
    U+1F301🌁\:foggy:Foggy
    U+1F302🌂\:closed_umbrella:Closed Umbrella
    U+1F303🌃\:night_with_stars:Night With Stars
    U+1F304🌄\:sunrise_over_mountains:Sunrise Over Mountains
    U+1F305🌅\:sunrise:Sunrise
    U+1F306🌆\:city_sunset:Cityscape At Dusk
    U+1F307🌇\:city_sunrise:Sunset Over Buildings
    U+1F308🌈\:rainbow:Rainbow
    U+1F309🌉\:bridge_at_night:Bridge At Night
    U+1F30A🌊\:ocean:Water Wave
    U+1F30B🌋\:volcano:Volcano
    U+1F30C🌌\:milky_way:Milky Way
    U+1F30D🌍\:earth_africa:Earth Globe Europe-Africa
    U+1F30E🌎\:earth_americas:Earth Globe Americas
    U+1F30F🌏\:earth_asia:Earth Globe Asia-Australia
    U+1F310🌐\:globe_with_meridians:Globe With Meridians
    U+1F311🌑\:new_moon:New Moon Symbol
    U+1F312🌒\:waxing_crescent_moon:Waxing Crescent Moon Symbol
    U+1F313🌓\:first_quarter_moon:First Quarter Moon Symbol
    U+1F314🌔\:moon:Waxing Gibbous Moon Symbol
    U+1F315🌕\:full_moon:Full Moon Symbol
    U+1F316🌖\:waning_gibbous_moon:Waning Gibbous Moon Symbol
    U+1F317🌗\:last_quarter_moon:Last Quarter Moon Symbol
    U+1F318🌘\:waning_crescent_moon:Waning Crescent Moon Symbol
    U+1F319🌙\:crescent_moon:Crescent Moon
    U+1F31A🌚\:new_moon_with_face:New Moon With Face
    U+1F31B🌛\:first_quarter_moon_with_face:First Quarter Moon With Face
    U+1F31C🌜\:last_quarter_moon_with_face:Last Quarter Moon With Face
    U+1F31D🌝\:full_moon_with_face:Full Moon With Face
    U+1F31E🌞\:sun_with_face:Sun With Face
    U+1F31F🌟\:star2:Glowing Star
    U+1F320🌠\:stars:Shooting Star
    U+1F32D🌭\:hotdog:Hot Dog
    U+1F32E🌮\:taco:Taco
    U+1F32F🌯\:burrito:Burrito
    U+1F330🌰\:chestnut:Chestnut
    U+1F331🌱\:seedling:Seedling
    U+1F332🌲\:evergreen_tree:Evergreen Tree
    U+1F333🌳\:deciduous_tree:Deciduous Tree
    U+1F334🌴\:palm_tree:Palm Tree
    U+1F335🌵\:cactus:Cactus
    U+1F337🌷\:tulip:Tulip
    U+1F338🌸\:cherry_blossom:Cherry Blossom
    U+1F339🌹\:rose:Rose
    U+1F33A🌺\:hibiscus:Hibiscus
    U+1F33B🌻\:sunflower:Sunflower
    U+1F33C🌼\:blossom:Blossom
    U+1F33D🌽\:corn:Ear Of Maize
    U+1F33E🌾\:ear_of_rice:Ear Of Rice
    U+1F33F🌿\:herb:Herb
    U+1F340🍀\:four_leaf_clover:Four Leaf Clover
    U+1F341🍁\:maple_leaf:Maple Leaf
    U+1F342🍂\:fallen_leaf:Fallen Leaf
    U+1F343🍃\:leaves:Leaf Fluttering In Wind
    U+1F344🍄\:mushroom:Mushroom
    U+1F345🍅\:tomato:Tomato
    U+1F346🍆\:eggplant:Aubergine
    U+1F347🍇\:grapes:Grapes
    U+1F348🍈\:melon:Melon
    U+1F349🍉\:watermelon:Watermelon
    U+1F34A🍊\:tangerine:Tangerine
    U+1F34B🍋\:lemon:Lemon
    U+1F34C🍌\:banana:Banana
    U+1F34D🍍\:pineapple:Pineapple
    U+1F34E🍎\:apple:Red Apple
    U+1F34F🍏\:green_apple:Green Apple
    U+1F350🍐\:pear:Pear
    U+1F351🍑\:peach:Peach
    U+1F352🍒\:cherries:Cherries
    U+1F353🍓\:strawberry:Strawberry
    U+1F354🍔\:hamburger:Hamburger
    U+1F355🍕\:pizza:Slice Of Pizza
    U+1F356🍖\:meat_on_bone:Meat On Bone
    U+1F357🍗\:poultry_leg:Poultry Leg
    U+1F358🍘\:rice_cracker:Rice Cracker
    U+1F359🍙\:rice_ball:Rice Ball
    U+1F35A🍚\:rice:Cooked Rice
    U+1F35B🍛\:curry:Curry And Rice
    U+1F35C🍜\:ramen:Steaming Bowl
    U+1F35D🍝\:spaghetti:Spaghetti
    U+1F35E🍞\:bread:Bread
    U+1F35F🍟\:fries:French Fries
    U+1F360🍠\:sweet_potato:Roasted Sweet Potato
    U+1F361🍡\:dango:Dango
    U+1F362🍢\:oden:Oden
    U+1F363🍣\:sushi:Sushi
    U+1F364🍤\:fried_shrimp:Fried Shrimp
    U+1F365🍥\:fish_cake:Fish Cake With Swirl Design
    U+1F366🍦\:icecream:Soft Ice Cream
    U+1F367🍧\:shaved_ice:Shaved Ice
    U+1F368🍨\:ice_cream:Ice Cream
    U+1F369🍩\:doughnut:Doughnut
    U+1F36A🍪\:cookie:Cookie
    U+1F36B🍫\:chocolate_bar:Chocolate Bar
    U+1F36C🍬\:candy:Candy
    U+1F36D🍭\:lollipop:Lollipop
    U+1F36E🍮\:custard:Custard
    U+1F36F🍯\:honey_pot:Honey Pot
    U+1F370🍰\:cake:Shortcake
    U+1F371🍱\:bento:Bento Box
    U+1F372🍲\:stew:Pot Of Food
    U+1F373🍳\:fried_egg:Cooking
    U+1F374🍴\:fork_and_knife:Fork And Knife
    U+1F375🍵\:tea:Teacup Without Handle
    U+1F376🍶\:sake:Sake Bottle And Cup
    U+1F377🍷\:wine_glass:Wine Glass
    U+1F378🍸\:cocktail:Cocktail Glass
    U+1F379🍹\:tropical_drink:Tropical Drink
    U+1F37A🍺\:beer:Beer Mug
    U+1F37B🍻\:beers:Clinking Beer Mugs
    U+1F37C🍼\:baby_bottle:Baby Bottle
    U+1F37E🍾\:champagne:Bottle With Popping Cork
    U+1F37F🍿\:popcorn:Popcorn
    U+1F380🎀\:ribbon:Ribbon
    U+1F381🎁\:gift:Wrapped Present
    U+1F382🎂\:birthday:Birthday Cake
    U+1F383🎃\:jack_o_lantern:Jack-O-Lantern
    U+1F384🎄\:christmas_tree:Christmas Tree
    U+1F385🎅\:santa:Father Christmas
    U+1F386🎆\:fireworks:Fireworks
    U+1F387🎇\:sparkler:Firework Sparkler
    U+1F388🎈\:balloon:Balloon
    U+1F389🎉\:tada:Party Popper
    U+1F38A🎊\:confetti_ball:Confetti Ball
    U+1F38B🎋\:tanabata_tree:Tanabata Tree
    U+1F38C🎌\:crossed_flags:Crossed Flags
    U+1F38D🎍\:bamboo:Pine Decoration
    U+1F38E🎎\:dolls:Japanese Dolls
    U+1F38F🎏\:flags:Carp Streamer
    U+1F390🎐\:wind_chime:Wind Chime
    U+1F391🎑\:rice_scene:Moon Viewing Ceremony
    U+1F392🎒\:school_satchel:School Satchel
    U+1F393🎓\:mortar_board:Graduation Cap
    U+1F3A0🎠\:carousel_horse:Carousel Horse
    U+1F3A1🎡\:ferris_wheel:Ferris Wheel
    U+1F3A2🎢\:roller_coaster:Roller Coaster
    U+1F3A3🎣\:fishing_pole_and_fish:Fishing Pole And Fish
    U+1F3A4🎤\:microphone:Microphone
    U+1F3A5🎥\:movie_camera:Movie Camera
    U+1F3A6🎦\:cinema:Cinema
    U+1F3A7🎧\:headphones:Headphone
    U+1F3A8🎨\:art:Artist Palette
    U+1F3A9🎩\:tophat:Top Hat
    U+1F3AA🎪\:circus_tent:Circus Tent
    U+1F3AB🎫\:ticket:Ticket
    U+1F3AC🎬\:clapper:Clapper Board
    U+1F3AD🎭\:performing_arts:Performing Arts
    U+1F3AE🎮\:video_game:Video Game
    U+1F3AF🎯\:dart:Direct Hit
    U+1F3B0🎰\:slot_machine:Slot Machine
    U+1F3B1🎱\:8ball:Billiards
    U+1F3B2🎲\:game_die:Game Die
    U+1F3B3🎳\:bowling:Bowling
    U+1F3B4🎴\:flower_playing_cards:Flower Playing Cards
    U+1F3B5🎵\:musical_note:Musical Note
    U+1F3B6🎶\:notes:Multiple Musical Notes
    U+1F3B7🎷\:saxophone:Saxophone
    U+1F3B8🎸\:guitar:Guitar
    U+1F3B9🎹\:musical_keyboard:Musical Keyboard
    U+1F3BA🎺\:trumpet:Trumpet
    U+1F3BB🎻\:violin:Violin
    U+1F3BC🎼\:musical_score:Musical Score
    U+1F3BD🎽\:running_shirt_with_sash:Running Shirt With Sash
    U+1F3BE🎾\:tennis:Tennis Racquet And Ball
    U+1F3BF🎿\:ski:Ski And Ski Boot
    U+1F3C0🏀\:basketball:Basketball And Hoop
    U+1F3C1🏁\:checkered_flag:Chequered Flag
    U+1F3C2🏂\:snowboarder:Snowboarder
    U+1F3C3🏃\:runner:Runner
    U+1F3C4🏄\:surfer:Surfer
    U+1F3C5🏅\:sports_medal:Sports Medal
    U+1F3C6🏆\:trophy:Trophy
    U+1F3C7🏇\:horse_racing:Horse Racing
    U+1F3C8🏈\:football:American Football
    U+1F3C9🏉\:rugby_football:Rugby Football
    U+1F3CA🏊\:swimmer:Swimmer
    U+1F3CF🏏\:cricket_bat_and_ball:Cricket Bat And Ball
    U+1F3D0🏐\:volleyball:Volleyball
    U+1F3D1🏑\:field_hockey_stick_and_ball:Field Hockey Stick And Ball
    U+1F3D2🏒\:ice_hockey_stick_and_puck:Ice Hockey Stick And Puck
    U+1F3D3🏓\:table_tennis_paddle_and_ball:Table Tennis Paddle And Ball
    U+1F3E0🏠\:house:House Building
    U+1F3E1🏡\:house_with_garden:House With Garden
    U+1F3E2🏢\:office:Office Building
    U+1F3E3🏣\:post_office:Japanese Post Office
    U+1F3E4🏤\:european_post_office:European Post Office
    U+1F3E5🏥\:hospital:Hospital
    U+1F3E6🏦\:bank:Bank
    U+1F3E7🏧\:atm:Automated Teller Machine
    U+1F3E8🏨\:hotel:Hotel
    U+1F3E9🏩\:love_hotel:Love Hotel
    U+1F3EA🏪\:convenience_store:Convenience Store
    U+1F3EB🏫\:school:School
    U+1F3EC🏬\:department_store:Department Store
    U+1F3ED🏭\:factory:Factory
    U+1F3EE🏮\:izakaya_lantern:Izakaya Lantern
    U+1F3EF🏯\:japanese_castle:Japanese Castle
    U+1F3F0🏰\:european_castle:European Castle
    U+1F3F4🏴\:waving_black_flag:Waving Black Flag
    U+1F3F8🏸\:badminton_racquet_and_shuttlecock:Badminton Racquet And Shuttlecock
    U+1F3F9🏹\:bow_and_arrow:Bow And Arrow
    U+1F3FA🏺\:amphora:Amphora
    U+1F3FB🏻\:skin-tone-2:Emoji Modifier Fitzpatrick Type-1-2
    U+1F3FC🏼\:skin-tone-3:Emoji Modifier Fitzpatrick Type-3
    U+1F3FD🏽\:skin-tone-4:Emoji Modifier Fitzpatrick Type-4
    U+1F3FE🏾\:skin-tone-5:Emoji Modifier Fitzpatrick Type-5
    U+1F3FF🏿\:skin-tone-6:Emoji Modifier Fitzpatrick Type-6
    U+1F400🐀\:rat:Rat
    U+1F401🐁\:mouse2:Mouse
    U+1F402🐂\:ox:Ox
    U+1F403🐃\:water_buffalo:Water Buffalo
    U+1F404🐄\:cow2:Cow
    U+1F405🐅\:tiger2:Tiger
    U+1F406🐆\:leopard:Leopard
    U+1F407🐇\:rabbit2:Rabbit
    U+1F408🐈\:cat2:Cat
    U+1F409🐉\:dragon:Dragon
    U+1F40A🐊\:crocodile:Crocodile
    U+1F40B🐋\:whale2:Whale
    U+1F40C🐌\:snail:Snail
    U+1F40D🐍\:snake:Snake
    U+1F40E🐎\:racehorse:Horse
    U+1F40F🐏\:ram:Ram
    U+1F410🐐\:goat:Goat
    U+1F411🐑\:sheep:Sheep
    U+1F412🐒\:monkey:Monkey
    U+1F413🐓\:rooster:Rooster
    U+1F414🐔\:chicken:Chicken
    U+1F415🐕\:dog2:Dog
    U+1F416🐖\:pig2:Pig
    U+1F417🐗\:boar:Boar
    U+1F418🐘\:elephant:Elephant
    U+1F419🐙\:octopus:Octopus
    U+1F41A🐚\:shell:Spiral Shell
    U+1F41B🐛\:bug:Bug
    U+1F41C🐜\:ant:Ant
    U+1F41D🐝\:bee:Honeybee
    U+1F41E🐞\:ladybug:Lady Beetle
    U+1F41F🐟\:fish:Fish
    U+1F420🐠\:tropical_fish:Tropical Fish
    U+1F421🐡\:blowfish:Blowfish
    U+1F422🐢\:turtle:Turtle
    U+1F423🐣\:hatching_chick:Hatching Chick
    U+1F424🐤\:baby_chick:Baby Chick
    U+1F425🐥\:hatched_chick:Front-Facing Baby Chick
    U+1F426🐦\:bird:Bird
    U+1F427🐧\:penguin:Penguin
    U+1F428🐨\:koala:Koala
    U+1F429🐩\:poodle:Poodle
    U+1F42A🐪\:dromedary_camel:Dromedary Camel
    U+1F42B🐫\:camel:Bactrian Camel
    U+1F42C🐬\:dolphin:Dolphin
    U+1F42D🐭\:mouse:Mouse Face
    U+1F42E🐮\:cow:Cow Face
    U+1F42F🐯\:tiger:Tiger Face
    U+1F430🐰\:rabbit:Rabbit Face
    U+1F431🐱\:cat:Cat Face
    U+1F432🐲\:dragon_face:Dragon Face
    U+1F433🐳\:whale:Spouting Whale
    U+1F434🐴\:horse:Horse Face
    U+1F435🐵\:monkey_face:Monkey Face
    U+1F436🐶\:dog:Dog Face
    U+1F437🐷\:pig:Pig Face
    U+1F438🐸\:frog:Frog Face
    U+1F439🐹\:hamster:Hamster Face
    U+1F43A🐺\:wolf:Wolf Face
    U+1F43B🐻\:bear:Bear Face
    U+1F43C🐼\:panda_face:Panda Face
    U+1F43D🐽\:pig_nose:Pig Nose
    U+1F43E🐾\:feet:Paw Prints
    U+1F440👀\:eyes:Eyes
    U+1F442👂\:ear:Ear
    U+1F443👃\:nose:Nose
    U+1F444👄\:lips:Mouth
    U+1F445👅\:tongue:Tongue
    U+1F446👆\:point_up_2:White Up Pointing Backhand Index
    U+1F447👇\:point_down:White Down Pointing Backhand Index
    U+1F448👈\:point_left:White Left Pointing Backhand Index
    U+1F449👉\:point_right:White Right Pointing Backhand Index
    U+1F44A👊\:facepunch:Fisted Hand Sign
    U+1F44B👋\:wave:Waving Hand Sign
    U+1F44C👌\:ok_hand:Ok Hand Sign
    U+1F44D👍\:+1:Thumbs Up Sign
    U+1F44E👎\:-1:Thumbs Down Sign
    U+1F44F👏\:clap:Clapping Hands Sign
    U+1F450👐\:open_hands:Open Hands Sign
    U+1F451👑\:crown:Crown
    U+1F452👒\:womans_hat:Womans Hat
    U+1F453👓\:eyeglasses:Eyeglasses
    U+1F454👔\:necktie:Necktie
    U+1F455👕\:shirt:T-Shirt
    U+1F456👖\:jeans:Jeans
    U+1F457👗\:dress:Dress
    U+1F458👘\:kimono:Kimono
    U+1F459👙\:bikini:Bikini
    U+1F45A👚\:womans_clothes:Womans Clothes
    U+1F45B👛\:purse:Purse
    U+1F45C👜\:handbag:Handbag
    U+1F45D👝\:pouch:Pouch
    U+1F45E👞\:mans_shoe:Mans Shoe
    U+1F45F👟\:athletic_shoe:Athletic Shoe
    U+1F460👠\:high_heel:High-Heeled Shoe
    U+1F461👡\:sandal:Womans Sandal
    U+1F462👢\:boot:Womans Boots
    U+1F463👣\:footprints:Footprints
    U+1F464👤\:bust_in_silhouette:Bust In Silhouette
    U+1F465👥\:busts_in_silhouette:Busts In Silhouette
    U+1F466👦\:boy:Boy
    U+1F467👧\:girl:Girl
    U+1F468👨\:man:Man
    U+1F469👩\:woman:Woman
    U+1F46A👪\:family:Family
    U+1F46B👫\:couple:, \:man_and_woman_holding_hands:Man And Woman Holding Hands
    U+1F46C👬\:two_men_holding_hands:Two Men Holding Hands
    U+1F46D👭\:two_women_holding_hands:Two Women Holding Hands
    U+1F46E👮\:cop:Police Officer
    U+1F46F👯\:dancers:Woman With Bunny Ears
    U+1F470👰\:bride_with_veil:Bride With Veil
    U+1F471👱\:person_with_blond_hair:Person With Blond Hair
    U+1F472👲\:man_with_gua_pi_mao:Man With Gua Pi Mao
    U+1F473👳\:man_with_turban:Man With Turban
    U+1F474👴\:older_man:Older Man
    U+1F475👵\:older_woman:Older Woman
    U+1F476👶\:baby:Baby
    U+1F477👷\:construction_worker:Construction Worker
    U+1F478👸\:princess:Princess
    U+1F479👹\:japanese_ogre:Japanese Ogre
    U+1F47A👺\:japanese_goblin:Japanese Goblin
    U+1F47B👻\:ghost:Ghost
    U+1F47C👼\:angel:Baby Angel
    U+1F47D👽\:alien:Extraterrestrial Alien
    U+1F47E👾\:space_invader:Alien Monster
    U+1F47F👿\:imp:Imp
    U+1F480💀\:skull:Skull
    U+1F481💁\:information_desk_person:Information Desk Person
    U+1F482💂\:guardsman:Guardsman
    U+1F483💃\:dancer:Dancer
    U+1F484💄\:lipstick:Lipstick
    U+1F485💅\:nail_care:Nail Polish
    U+1F486💆\:massage:Face Massage
    U+1F487💇\:haircut:Haircut
    U+1F488💈\:barber:Barber Pole
    U+1F489💉\:syringe:Syringe
    U+1F48A💊\:pill:Pill
    U+1F48B💋\:kiss:Kiss Mark
    U+1F48C💌\:love_letter:Love Letter
    U+1F48D💍\:ring:Ring
    U+1F48E💎\:gem:Gem Stone
    U+1F48F💏\:couplekiss:Kiss
    U+1F490💐\:bouquet:Bouquet
    U+1F491💑\:couple_with_heart:Couple With Heart
    U+1F492💒\:wedding:Wedding
    U+1F493💓\:heartbeat:Beating Heart
    U+1F494💔\:broken_heart:Broken Heart
    U+1F495💕\:two_hearts:Two Hearts
    U+1F496💖\:sparkling_heart:Sparkling Heart
    U+1F497💗\:heartpulse:Growing Heart
    U+1F498💘\:cupid:Heart With Arrow
    U+1F499💙\:blue_heart:Blue Heart
    U+1F49A💚\:green_heart:Green Heart
    U+1F49B💛\:yellow_heart:Yellow Heart
    U+1F49C💜\:purple_heart:Purple Heart
    U+1F49D💝\:gift_heart:Heart With Ribbon
    U+1F49E💞\:revolving_hearts:Revolving Hearts
    U+1F49F💟\:heart_decoration:Heart Decoration
    U+1F4A0💠\:diamond_shape_with_a_dot_inside:Diamond Shape With A Dot Inside
    U+1F4A1💡\:bulb:Electric Light Bulb
    U+1F4A2💢\:anger:Anger Symbol
    U+1F4A3💣\:bomb:Bomb
    U+1F4A4💤\:zzz:Sleeping Symbol
    U+1F4A5💥\:boom:Collision Symbol
    U+1F4A6💦\:sweat_drops:Splashing Sweat Symbol
    U+1F4A7💧\:droplet:Droplet
    U+1F4A8💨\:dash:Dash Symbol
    U+1F4A9💩\:hankey:Pile Of Poo
    U+1F4AA💪\:muscle:Flexed Biceps
    U+1F4AB💫\:dizzy:Dizzy Symbol
    U+1F4AC💬\:speech_balloon:Speech Balloon
    U+1F4AD💭\:thought_balloon:Thought Balloon
    U+1F4AE💮\:white_flower:White Flower
    U+1F4AF💯\:100:Hundred Points Symbol
    U+1F4B0💰\:moneybag:Money Bag
    U+1F4B1💱\:currency_exchange:Currency Exchange
    U+1F4B2💲\:heavy_dollar_sign:Heavy Dollar Sign
    U+1F4B3💳\:credit_card:Credit Card
    U+1F4B4💴\:yen:Banknote With Yen Sign
    U+1F4B5💵\:dollar:Banknote With Dollar Sign
    U+1F4B6💶\:euro:Banknote With Euro Sign
    U+1F4B7💷\:pound:Banknote With Pound Sign
    U+1F4B8💸\:money_with_wings:Money With Wings
    U+1F4B9💹\:chart:Chart With Upwards Trend And Yen Sign
    U+1F4BA💺\:seat:Seat
    U+1F4BB💻\:computer:Personal Computer
    U+1F4BC💼\:briefcase:Briefcase
    U+1F4BD💽\:minidisc:Minidisc
    U+1F4BE💾\:floppy_disk:Floppy Disk
    U+1F4BF💿\:cd:Optical Disc
    U+1F4C0📀\:dvd:Dvd
    U+1F4C1📁\:file_folder:File Folder
    U+1F4C2📂\:open_file_folder:Open File Folder
    U+1F4C3📃\:page_with_curl:Page With Curl
    U+1F4C4📄\:page_facing_up:Page Facing Up
    U+1F4C5📅\:date:Calendar
    U+1F4C6📆\:calendar:Tear-Off Calendar
    U+1F4C7📇\:card_index:Card Index
    U+1F4C8📈\:chart_with_upwards_trend:Chart With Upwards Trend
    U+1F4C9📉\:chart_with_downwards_trend:Chart With Downwards Trend
    U+1F4CA📊\:bar_chart:Bar Chart
    U+1F4CB📋\:clipboard:Clipboard
    U+1F4CC📌\:pushpin:Pushpin
    U+1F4CD📍\:round_pushpin:Round Pushpin
    U+1F4CE📎\:paperclip:Paperclip
    U+1F4CF📏\:straight_ruler:Straight Ruler
    U+1F4D0📐\:triangular_ruler:Triangular Ruler
    U+1F4D1📑\:bookmark_tabs:Bookmark Tabs
    U+1F4D2📒\:ledger:Ledger
    U+1F4D3📓\:notebook:Notebook
    U+1F4D4📔\:notebook_with_decorative_cover:Notebook With Decorative Cover
    U+1F4D5📕\:closed_book:Closed Book
    U+1F4D6📖\:book:Open Book
    U+1F4D7📗\:green_book:Green Book
    U+1F4D8📘\:blue_book:Blue Book
    U+1F4D9📙\:orange_book:Orange Book
    U+1F4DA📚\:books:Books
    U+1F4DB📛\:name_badge:Name Badge
    U+1F4DC📜\:scroll:Scroll
    U+1F4DD📝\:memo:Memo
    U+1F4DE📞\:telephone_receiver:Telephone Receiver
    U+1F4DF📟\:pager:Pager
    U+1F4E0📠\:fax:Fax Machine
    U+1F4E1📡\:satellite:, \:satellite_antenna:Satellite Antenna
    U+1F4E2📢\:loudspeaker:Public Address Loudspeaker
    U+1F4E3📣\:mega:Cheering Megaphone
    U+1F4E4📤\:outbox_tray:Outbox Tray
    U+1F4E5📥\:inbox_tray:Inbox Tray
    U+1F4E6📦\:package:Package
    U+1F4E7📧\:e-mail:E-Mail Symbol
    U+1F4E8📨\:incoming_envelope:Incoming Envelope
    U+1F4E9📩\:envelope_with_arrow:Envelope With Downwards Arrow Above
    U+1F4EA📪\:mailbox_closed:Closed Mailbox With Lowered Flag
    U+1F4EB📫\:mailbox:Closed Mailbox With Raised Flag
    U+1F4EC📬\:mailbox_with_mail:Open Mailbox With Raised Flag
    U+1F4ED📭\:mailbox_with_no_mail:Open Mailbox With Lowered Flag
    U+1F4EE📮\:postbox:Postbox
    U+1F4EF📯\:postal_horn:Postal Horn
    U+1F4F0📰\:newspaper:Newspaper
    U+1F4F1📱\:iphone:Mobile Phone
    U+1F4F2📲\:calling:Mobile Phone With Rightwards Arrow At Left
    U+1F4F3📳\:vibration_mode:Vibration Mode
    U+1F4F4📴\:mobile_phone_off:Mobile Phone Off
    U+1F4F5📵\:no_mobile_phones:No Mobile Phones
    U+1F4F6📶\:signal_strength:Antenna With Bars
    U+1F4F7📷\:camera:Camera
    U+1F4F8📸\:camera_with_flash:Camera With Flash
    U+1F4F9📹\:video_camera:Video Camera
    U+1F4FA📺\:tv:Television
    U+1F4FB📻\:radio:Radio
    U+1F4FC📼\:vhs:Videocassette
    U+1F4FF📿\:prayer_beads:Prayer Beads
    U+1F500🔀\:twisted_rightwards_arrows:Twisted Rightwards Arrows
    U+1F501🔁\:repeat:Clockwise Rightwards And Leftwards Open Circle Arrows
    U+1F502🔂\:repeat_one:Clockwise Rightwards And Leftwards Open Circle Arrows With Circled One Overlay
    U+1F503🔃\:arrows_clockwise:Clockwise Downwards And Upwards Open Circle Arrows
    U+1F504🔄\:arrows_counterclockwise:Anticlockwise Downwards And Upwards Open Circle Arrows
    U+1F505🔅\:low_brightness:Low Brightness Symbol
    U+1F506🔆\:high_brightness:High Brightness Symbol
    U+1F507🔇\:mute:Speaker With Cancellation Stroke
    U+1F508🔈\:speaker:Speaker
    U+1F509🔉\:sound:Speaker With One Sound Wave
    U+1F50A🔊\:loud_sound:Speaker With Three Sound Waves
    U+1F50B🔋\:battery:Battery
    U+1F50C🔌\:electric_plug:Electric Plug
    U+1F50D🔍\:mag:Left-Pointing Magnifying Glass
    U+1F50E🔎\:mag_right:Right-Pointing Magnifying Glass
    U+1F50F🔏\:lock_with_ink_pen:Lock With Ink Pen
    U+1F510🔐\:closed_lock_with_key:Closed Lock With Key
    U+1F511🔑\:key:Key
    U+1F512🔒\:lock:Lock
    U+1F513🔓\:unlock:Open Lock
    U+1F514🔔\:bell:Bell
    U+1F515🔕\:no_bell:Bell With Cancellation Stroke
    U+1F516🔖\:bookmark:Bookmark
    U+1F517🔗\:link:Link Symbol
    U+1F518🔘\:radio_button:Radio Button
    U+1F519🔙\:back:Back With Leftwards Arrow Above
    U+1F51A🔚\:end:End With Leftwards Arrow Above
    U+1F51B🔛\:on:On With Exclamation Mark With Left Right Arrow Above
    U+1F51C🔜\:soon:Soon With Rightwards Arrow Above
    U+1F51D🔝\:top:Top With Upwards Arrow Above
    U+1F51E🔞\:underage:No One Under Eighteen Symbol
    U+1F51F🔟\:keycap_ten:Keycap Ten
    U+1F520🔠\:capital_abcd:Input Symbol For Latin Capital Letters
    U+1F521🔡\:abcd:Input Symbol For Latin Small Letters
    U+1F522🔢\:1234:Input Symbol For Numbers
    U+1F523🔣\:symbols:Input Symbol For Symbols
    U+1F524🔤\:abc:Input Symbol For Latin Letters
    U+1F525🔥\:fire:Fire
    U+1F526🔦\:flashlight:Electric Torch
    U+1F527🔧\:wrench:Wrench
    U+1F528🔨\:hammer:Hammer
    U+1F529🔩\:nut_and_bolt:Nut And Bolt
    U+1F52A🔪\:hocho:Hocho
    U+1F52B🔫\:gun:Pistol
    U+1F52C🔬\:microscope:Microscope
    U+1F52D🔭\:telescope:Telescope
    U+1F52E🔮\:crystal_ball:Crystal Ball
    U+1F52F🔯\:six_pointed_star:Six Pointed Star With Middle Dot
    U+1F530🔰\:beginner:Japanese Symbol For Beginner
    U+1F531🔱\:trident:Trident Emblem
    U+1F532🔲\:black_square_button:Black Square Button
    U+1F533🔳\:white_square_button:White Square Button
    U+1F534🔴\:red_circle:Large Red Circle
    U+1F535🔵\:large_blue_circle:Large Blue Circle
    U+1F536🔶\:large_orange_diamond:Large Orange Diamond
    U+1F537🔷\:large_blue_diamond:Large Blue Diamond
    U+1F538🔸\:small_orange_diamond:Small Orange Diamond
    U+1F539🔹\:small_blue_diamond:Small Blue Diamond
    U+1F53A🔺\:small_red_triangle:Up-Pointing Red Triangle
    U+1F53B🔻\:small_red_triangle_down:Down-Pointing Red Triangle
    U+1F53C🔼\:arrow_up_small:Up-Pointing Small Red Triangle
    U+1F53D🔽\:arrow_down_small:Down-Pointing Small Red Triangle
    U+1F54B🕋\:kaaba:Kaaba
    U+1F54C🕌\:mosque:Mosque
    U+1F54D🕍\:synagogue:Synagogue
    U+1F54E🕎\:menorah_with_nine_branches:Menorah With Nine Branches
    U+1F550🕐\:clock1:Clock Face One Oclock
    U+1F551🕑\:clock2:Clock Face Two Oclock
    U+1F552🕒\:clock3:Clock Face Three Oclock
    U+1F553🕓\:clock4:Clock Face Four Oclock
    U+1F554🕔\:clock5:Clock Face Five Oclock
    U+1F555🕕\:clock6:Clock Face Six Oclock
    U+1F556🕖\:clock7:Clock Face Seven Oclock
    U+1F557🕗\:clock8:Clock Face Eight Oclock
    U+1F558🕘\:clock9:Clock Face Nine Oclock
    U+1F559🕙\:clock10:Clock Face Ten Oclock
    U+1F55A🕚\:clock11:Clock Face Eleven Oclock
    U+1F55B🕛\:clock12:Clock Face Twelve Oclock
    U+1F55C🕜\:clock130:Clock Face One-Thirty
    U+1F55D🕝\:clock230:Clock Face Two-Thirty
    U+1F55E🕞\:clock330:Clock Face Three-Thirty
    U+1F55F🕟\:clock430:Clock Face Four-Thirty
    U+1F560🕠\:clock530:Clock Face Five-Thirty
    U+1F561🕡\:clock630:Clock Face Six-Thirty
    U+1F562🕢\:clock730:Clock Face Seven-Thirty
    U+1F563🕣\:clock830:Clock Face Eight-Thirty
    U+1F564🕤\:clock930:Clock Face Nine-Thirty
    U+1F565🕥\:clock1030:Clock Face Ten-Thirty
    U+1F566🕦\:clock1130:Clock Face Eleven-Thirty
    U+1F567🕧\:clock1230:Clock Face Twelve-Thirty
    U+1F57A🕺\:man_dancing:Man Dancing
    U+1F595🖕\:middle_finger:Reversed Hand With Middle Finger Extended
    U+1F596🖖\:spock-hand:Raised Hand With Part Between Middle And Ring Fingers
    U+1F5A4🖤\:black_heart:Black Heart
    U+1F5FB🗻\:mount_fuji:Mount Fuji
    U+1F5FC🗼\:tokyo_tower:Tokyo Tower
    U+1F5FD🗽\:statue_of_liberty:Statue Of Liberty
    U+1F5FE🗾\:japan:Silhouette Of Japan
    U+1F5FF🗿\:moyai:Moyai
    U+1F600😀\:grinning:Grinning Face
    U+1F601😁\:grin:Grinning Face With Smiling Eyes
    U+1F602😂\:joy:Face With Tears Of Joy
    U+1F603😃\:smiley:Smiling Face With Open Mouth
    U+1F604😄\:smile:Smiling Face With Open Mouth And Smiling Eyes
    U+1F605😅\:sweat_smile:Smiling Face With Open Mouth And Cold Sweat
    U+1F606😆\:laughing:Smiling Face With Open Mouth And Tightly-Closed Eyes
    U+1F607😇\:innocent:Smiling Face With Halo
    U+1F608😈\:smiling_imp:Smiling Face With Horns
    U+1F609😉\:wink:Winking Face
    U+1F60A😊\:blush:Smiling Face With Smiling Eyes
    U+1F60B😋\:yum:Face Savouring Delicious Food
    U+1F60C😌\:relieved:Relieved Face
    U+1F60D😍\:heart_eyes:Smiling Face With Heart-Shaped Eyes
    U+1F60E😎\:sunglasses:Smiling Face With Sunglasses
    U+1F60F😏\:smirk:Smirking Face
    U+1F610😐\:neutral_face:Neutral Face
    U+1F611😑\:expressionless:Expressionless Face
    U+1F612😒\:unamused:Unamused Face
    U+1F613😓\:sweat:Face With Cold Sweat
    U+1F614😔\:pensive:Pensive Face
    U+1F615😕\:confused:Confused Face
    U+1F616😖\:confounded:Confounded Face
    U+1F617😗\:kissing:Kissing Face
    U+1F618😘\:kissing_heart:Face Throwing A Kiss
    U+1F619😙\:kissing_smiling_eyes:Kissing Face With Smiling Eyes
    U+1F61A😚\:kissing_closed_eyes:Kissing Face With Closed Eyes
    U+1F61B😛\:stuck_out_tongue:Face With Stuck-Out Tongue
    U+1F61C😜\:stuck_out_tongue_winking_eye:Face With Stuck-Out Tongue And Winking Eye
    U+1F61D😝\:stuck_out_tongue_closed_eyes:Face With Stuck-Out Tongue And Tightly-Closed Eyes
    U+1F61E😞\:disappointed:Disappointed Face
    U+1F61F😟\:worried:Worried Face
    U+1F620😠\:angry:Angry Face
    U+1F621😡\:rage:Pouting Face
    U+1F622😢\:cry:Crying Face
    U+1F623😣\:persevere:Persevering Face
    U+1F624😤\:triumph:Face With Look Of Triumph
    U+1F625😥\:disappointed_relieved:Disappointed But Relieved Face
    U+1F626😦\:frowning:Frowning Face With Open Mouth
    U+1F627😧\:anguished:Anguished Face
    U+1F628😨\:fearful:Fearful Face
    U+1F629😩\:weary:Weary Face
    U+1F62A😪\:sleepy:Sleepy Face
    U+1F62B😫\:tired_face:Tired Face
    U+1F62C😬\:grimacing:Grimacing Face
    U+1F62D😭\:sob:Loudly Crying Face
    U+1F62E😮\:open_mouth:Face With Open Mouth
    U+1F62F😯\:hushed:Hushed Face
    U+1F630😰\:cold_sweat:Face With Open Mouth And Cold Sweat
    U+1F631😱\:scream:Face Screaming In Fear
    U+1F632😲\:astonished:Astonished Face
    U+1F633😳\:flushed:Flushed Face
    U+1F634😴\:sleeping:Sleeping Face
    U+1F635😵\:dizzy_face:Dizzy Face
    U+1F636😶\:no_mouth:Face Without Mouth
    U+1F637😷\:mask:Face With Medical Mask
    U+1F638😸\:smile_cat:Grinning Cat Face With Smiling Eyes
    U+1F639😹\:joy_cat:Cat Face With Tears Of Joy
    U+1F63A😺\:smiley_cat:Smiling Cat Face With Open Mouth
    U+1F63B😻\:heart_eyes_cat:Smiling Cat Face With Heart-Shaped Eyes
    U+1F63C😼\:smirk_cat:Cat Face With Wry Smile
    U+1F63D😽\:kissing_cat:Kissing Cat Face With Closed Eyes
    U+1F63E😾\:pouting_cat:Pouting Cat Face
    U+1F63F😿\:crying_cat_face:Crying Cat Face
    U+1F640🙀\:scream_cat:Weary Cat Face
    U+1F641🙁\:slightly_frowning_face:Slightly Frowning Face
    U+1F642🙂\:slightly_smiling_face:Slightly Smiling Face
    U+1F643🙃\:upside_down_face:Upside-Down Face
    U+1F644🙄\:face_with_rolling_eyes:Face With Rolling Eyes
    U+1F645🙅\:no_good:Face With No Good Gesture
    U+1F646🙆\:ok_woman:Face With Ok Gesture
    U+1F647🙇\:bow:Person Bowing Deeply
    U+1F648🙈\:see_no_evil:See-No-Evil Monkey
    U+1F649🙉\:hear_no_evil:Hear-No-Evil Monkey
    U+1F64A🙊\:speak_no_evil:Speak-No-Evil Monkey
    U+1F64B🙋\:raising_hand:Happy Person Raising One Hand
    U+1F64C🙌\:raised_hands:Person Raising Both Hands In Celebration
    U+1F64D🙍\:person_frowning:Person Frowning
    U+1F64E🙎\:person_with_pouting_face:Person With Pouting Face
    U+1F64F🙏\:pray:Person With Folded Hands
    U+1F680🚀\:rocket:Rocket
    U+1F681🚁\:helicopter:Helicopter
    U+1F682🚂\:steam_locomotive:Steam Locomotive
    U+1F683🚃\:railway_car:Railway Car
    U+1F684🚄\:bullettrain_side:High-Speed Train
    U+1F685🚅\:bullettrain_front:High-Speed Train With Bullet Nose
    U+1F686🚆\:train2:Train
    U+1F687🚇\:metro:Metro
    U+1F688🚈\:light_rail:Light Rail
    U+1F689🚉\:station:Station
    U+1F68A🚊\:tram:Tram
    U+1F68B🚋\:train:Tram Car
    U+1F68C🚌\:bus:Bus
    U+1F68D🚍\:oncoming_bus:Oncoming Bus
    U+1F68E🚎\:trolleybus:Trolleybus
    U+1F68F🚏\:busstop:Bus Stop
    U+1F690🚐\:minibus:Minibus
    U+1F691🚑\:ambulance:Ambulance
    U+1F692🚒\:fire_engine:Fire Engine
    U+1F693🚓\:police_car:Police Car
    U+1F694🚔\:oncoming_police_car:Oncoming Police Car
    U+1F695🚕\:taxi:Taxi
    U+1F696🚖\:oncoming_taxi:Oncoming Taxi
    U+1F697🚗\:car:Automobile
    U+1F698🚘\:oncoming_automobile:Oncoming Automobile
    U+1F699🚙\:blue_car:Recreational Vehicle
    U+1F69A🚚\:truck:Delivery Truck
    U+1F69B🚛\:articulated_lorry:Articulated Lorry
    U+1F69C🚜\:tractor:Tractor
    U+1F69D🚝\:monorail:Monorail
    U+1F69E🚞\:mountain_railway:Mountain Railway
    U+1F69F🚟\:suspension_railway:Suspension Railway
    U+1F6A0🚠\:mountain_cableway:Mountain Cableway
    U+1F6A1🚡\:aerial_tramway:Aerial Tramway
    U+1F6A2🚢\:ship:Ship
    U+1F6A3🚣\:rowboat:Rowboat
    U+1F6A4🚤\:speedboat:Speedboat
    U+1F6A5🚥\:traffic_light:Horizontal Traffic Light
    U+1F6A6🚦\:vertical_traffic_light:Vertical Traffic Light
    U+1F6A7🚧\:construction:Construction Sign
    U+1F6A8🚨\:rotating_light:Police Cars Revolving Light
    U+1F6A9🚩\:triangular_flag_on_post:Triangular Flag On Post
    U+1F6AA🚪\:door:Door
    U+1F6AB🚫\:no_entry_sign:No Entry Sign
    U+1F6AC🚬\:smoking:Smoking Symbol
    U+1F6AD🚭\:no_smoking:No Smoking Symbol
    U+1F6AE🚮\:put_litter_in_its_place:Put Litter In Its Place Symbol
    U+1F6AF🚯\:do_not_litter:Do Not Litter Symbol
    U+1F6B0🚰\:potable_water:Potable Water Symbol
    U+1F6B1🚱\:non-potable_water:Non-Potable Water Symbol
    U+1F6B2🚲\:bike:Bicycle
    U+1F6B3🚳\:no_bicycles:No Bicycles
    U+1F6B4🚴\:bicyclist:Bicyclist
    U+1F6B5🚵\:mountain_bicyclist:Mountain Bicyclist
    U+1F6B6🚶\:walking:Pedestrian
    U+1F6B7🚷\:no_pedestrians:No Pedestrians
    U+1F6B8🚸\:children_crossing:Children Crossing
    U+1F6B9🚹\:mens:Mens Symbol
    U+1F6BA🚺\:womens:Womens Symbol
    U+1F6BB🚻\:restroom:Restroom
    U+1F6BC🚼\:baby_symbol:Baby Symbol
    U+1F6BD🚽\:toilet:Toilet
    U+1F6BE🚾\:wc:Water Closet
    U+1F6BF🚿\:shower:Shower
    U+1F6C0🛀\:bath:Bath
    U+1F6C1🛁\:bathtub:Bathtub
    U+1F6C2🛂\:passport_control:Passport Control
    U+1F6C3🛃\:customs:Customs
    U+1F6C4🛄\:baggage_claim:Baggage Claim
    U+1F6C5🛅\:left_luggage:Left Luggage
    U+1F6CC🛌\:sleeping_accommodation:Sleeping Accommodation
    U+1F6D0🛐\:place_of_worship:Place Of Worship
    U+1F6D1🛑\:octagonal_sign:Octagonal Sign
    U+1F6D2🛒\:shopping_trolley:Shopping Trolley
    U+1F6D5🛕\:hindu_temple:(No Unicode name)
    U+1F6D6🛖\:hut:(No Unicode name)
    U+1F6D7🛗\:elevator:(No Unicode name)
    U+1F6EB🛫\:airplane_departure:Airplane Departure
    U+1F6EC🛬\:airplane_arriving:Airplane Arriving
    U+1F6F4🛴\:scooter:Scooter
    U+1F6F5🛵\:motor_scooter:Motor Scooter
    U+1F6F6🛶\:canoe:Canoe
    U+1F6F7🛷\:sled:(No Unicode name)
    U+1F6F8🛸\:flying_saucer:(No Unicode name)
    U+1F6F9🛹\:skateboard:(No Unicode name)
    U+1F6FA🛺\:auto_rickshaw:(No Unicode name)
    U+1F6FB🛻\:pickup_truck:(No Unicode name)
    U+1F6FC🛼\:roller_skate:(No Unicode name)
    U+1F7E0🟠\:large_orange_circle:(No Unicode name)
    U+1F7E1🟡\:large_yellow_circle:(No Unicode name)
    U+1F7E2🟢\:large_green_circle:(No Unicode name)
    U+1F7E3🟣\:large_purple_circle:(No Unicode name)
    U+1F7E4🟤\:large_brown_circle:(No Unicode name)
    U+1F7E5🟥\:large_red_square:(No Unicode name)
    U+1F7E6🟦\:large_blue_square:(No Unicode name)
    U+1F7E7🟧\:large_orange_square:(No Unicode name)
    U+1F7E8🟨\:large_yellow_square:(No Unicode name)
    U+1F7E9🟩\:large_green_square:(No Unicode name)
    U+1F7EA🟪\:large_purple_square:(No Unicode name)
    U+1F7EB🟫\:large_brown_square:(No Unicode name)
    U+1F90C🤌\:pinched_fingers:(No Unicode name)
    U+1F90D🤍\:white_heart:(No Unicode name)
    U+1F90E🤎\:brown_heart:(No Unicode name)
    U+1F90F🤏\:pinching_hand:(No Unicode name)
    U+1F910🤐\:zipper_mouth_face:Zipper-Mouth Face
    U+1F911🤑\:money_mouth_face:Money-Mouth Face
    U+1F912🤒\:face_with_thermometer:Face With Thermometer
    U+1F913🤓\:nerd_face:Nerd Face
    U+1F914🤔\:thinking_face:Thinking Face
    U+1F915🤕\:face_with_head_bandage:Face With Head-Bandage
    U+1F916🤖\:robot_face:Robot Face
    U+1F917🤗\:hugging_face:Hugging Face
    U+1F918🤘\:the_horns:Sign Of The Horns
    U+1F919🤙\:call_me_hand:Call Me Hand
    U+1F91A🤚\:raised_back_of_hand:Raised Back Of Hand
    U+1F91B🤛\:left-facing_fist:Left-Facing Fist
    U+1F91C🤜\:right-facing_fist:Right-Facing Fist
    U+1F91D🤝\:handshake:Handshake
    U+1F91E🤞\:crossed_fingers:Hand With Index And Middle Fingers Crossed
    U+1F91F🤟\:i_love_you_hand_sign:(No Unicode name)
    U+1F920🤠\:face_with_cowboy_hat:Face With Cowboy Hat
    U+1F921🤡\:clown_face:Clown Face
    U+1F922🤢\:nauseated_face:Nauseated Face
    U+1F923🤣\:rolling_on_the_floor_laughing:Rolling On The Floor Laughing
    U+1F924🤤\:drooling_face:Drooling Face
    U+1F925🤥\:lying_face:Lying Face
    U+1F926🤦\:face_palm:Face Palm
    U+1F927🤧\:sneezing_face:Sneezing Face
    U+1F928🤨\:face_with_raised_eyebrow:(No Unicode name)
    U+1F929🤩\:star-struck:(No Unicode name)
    U+1F92A🤪\:zany_face:(No Unicode name)
    U+1F92B🤫\:shushing_face:(No Unicode name)
    U+1F92C🤬\:face_with_symbols_on_mouth:(No Unicode name)
    U+1F92D🤭\:face_with_hand_over_mouth:(No Unicode name)
    U+1F92E🤮\:face_vomiting:(No Unicode name)
    U+1F92F🤯\:exploding_head:(No Unicode name)
    U+1F930🤰\:pregnant_woman:Pregnant Woman
    U+1F931🤱\:breast-feeding:(No Unicode name)
    U+1F932🤲\:palms_up_together:(No Unicode name)
    U+1F933🤳\:selfie:Selfie
    U+1F934🤴\:prince:Prince
    U+1F935🤵\:person_in_tuxedo:Man In Tuxedo
    U+1F936🤶\:mrs_claus:Mother Christmas
    U+1F937🤷\:shrug:Shrug
    U+1F938🤸\:person_doing_cartwheel:Person Doing Cartwheel
    U+1F939🤹\:juggling:Juggling
    U+1F93A🤺\:fencer:Fencer
    U+1F93C🤼\:wrestlers:Wrestlers
    U+1F93D🤽\:water_polo:Water Polo
    U+1F93E🤾\:handball:Handball
    U+1F93F🤿\:diving_mask:(No Unicode name)
    U+1F940🥀\:wilted_flower:Wilted Flower
    U+1F941🥁\:drum_with_drumsticks:Drum With Drumsticks
    U+1F942🥂\:clinking_glasses:Clinking Glasses
    U+1F943🥃\:tumbler_glass:Tumbler Glass
    U+1F944🥄\:spoon:Spoon
    U+1F945🥅\:goal_net:Goal Net
    U+1F947🥇\:first_place_medal:First Place Medal
    U+1F948🥈\:second_place_medal:Second Place Medal
    U+1F949🥉\:third_place_medal:Third Place Medal
    U+1F94A🥊\:boxing_glove:Boxing Glove
    U+1F94B🥋\:martial_arts_uniform:Martial Arts Uniform
    U+1F94C🥌\:curling_stone:(No Unicode name)
    U+1F94D🥍\:lacrosse:(No Unicode name)
    U+1F94E🥎\:softball:(No Unicode name)
    U+1F94F🥏\:flying_disc:(No Unicode name)
    U+1F950🥐\:croissant:Croissant
    U+1F951🥑\:avocado:Avocado
    U+1F952🥒\:cucumber:Cucumber
    U+1F953🥓\:bacon:Bacon
    U+1F954🥔\:potato:Potato
    U+1F955🥕\:carrot:Carrot
    U+1F956🥖\:baguette_bread:Baguette Bread
    U+1F957🥗\:green_salad:Green Salad
    U+1F958🥘\:shallow_pan_of_food:Shallow Pan Of Food
    U+1F959🥙\:stuffed_flatbread:Stuffed Flatbread
    U+1F95A🥚\:egg:Egg
    U+1F95B🥛\:glass_of_milk:Glass Of Milk
    U+1F95C🥜\:peanuts:Peanuts
    U+1F95D🥝\:kiwifruit:Kiwifruit
    U+1F95E🥞\:pancakes:Pancakes
    U+1F95F🥟\:dumpling:(No Unicode name)
    U+1F960🥠\:fortune_cookie:(No Unicode name)
    U+1F961🥡\:takeout_box:(No Unicode name)
    U+1F962🥢\:chopsticks:(No Unicode name)
    U+1F963🥣\:bowl_with_spoon:(No Unicode name)
    U+1F964🥤\:cup_with_straw:(No Unicode name)
    U+1F965🥥\:coconut:(No Unicode name)
    U+1F966🥦\:broccoli:(No Unicode name)
    U+1F967🥧\:pie:(No Unicode name)
    U+1F968🥨\:pretzel:(No Unicode name)
    U+1F969🥩\:cut_of_meat:(No Unicode name)
    U+1F96A🥪\:sandwich:(No Unicode name)
    U+1F96B🥫\:canned_food:(No Unicode name)
    U+1F96C🥬\:leafy_green:(No Unicode name)
    U+1F96D🥭\:mango:(No Unicode name)
    U+1F96E🥮\:moon_cake:(No Unicode name)
    U+1F96F🥯\:bagel:(No Unicode name)
    U+1F970🥰\:smiling_face_with_3_hearts:(No Unicode name)
    U+1F971🥱\:yawning_face:(No Unicode name)
    U+1F972🥲\:smiling_face_with_tear:(No Unicode name)
    U+1F973🥳\:partying_face:(No Unicode name)
    U+1F974🥴\:woozy_face:(No Unicode name)
    U+1F975🥵\:hot_face:(No Unicode name)
    U+1F976🥶\:cold_face:(No Unicode name)
    U+1F977🥷\:ninja:(No Unicode name)
    U+1F978🥸\:disguised_face:(No Unicode name)
    U+1F97A🥺\:pleading_face:(No Unicode name)
    U+1F97B🥻\:sari:(No Unicode name)
    U+1F97C🥼\:lab_coat:(No Unicode name)
    U+1F97D🥽\:goggles:(No Unicode name)
    U+1F97E🥾\:hiking_boot:(No Unicode name)
    U+1F97F🥿\:womans_flat_shoe:(No Unicode name)
    U+1F980🦀\:crab:Crab
    U+1F981🦁\:lion_face:Lion Face
    U+1F982🦂\:scorpion:Scorpion
    U+1F983🦃\:turkey:Turkey
    U+1F984🦄\:unicorn_face:Unicorn Face
    U+1F985🦅\:eagle:Eagle
    U+1F986🦆\:duck:Duck
    U+1F987🦇\:bat:Bat
    U+1F988🦈\:shark:Shark
    U+1F989🦉\:owl:Owl
    U+1F98A🦊\:fox_face:Fox Face
    U+1F98B🦋\:butterfly:Butterfly
    U+1F98C🦌\:deer:Deer
    U+1F98D🦍\:gorilla:Gorilla
    U+1F98E🦎\:lizard:Lizard
    U+1F98F🦏\:rhinoceros:Rhinoceros
    U+1F990🦐\:shrimp:Shrimp
    U+1F991🦑\:squid:Squid
    U+1F992🦒\:giraffe_face:(No Unicode name)
    U+1F993🦓\:zebra_face:(No Unicode name)
    U+1F994🦔\:hedgehog:(No Unicode name)
    U+1F995🦕\:sauropod:(No Unicode name)
    U+1F996🦖\:t-rex:(No Unicode name)
    U+1F997🦗\:cricket:(No Unicode name)
    U+1F998🦘\:kangaroo:(No Unicode name)
    U+1F999🦙\:llama:(No Unicode name)
    U+1F99A🦚\:peacock:(No Unicode name)
    U+1F99B🦛\:hippopotamus:(No Unicode name)
    U+1F99C🦜\:parrot:(No Unicode name)
    U+1F99D🦝\:raccoon:(No Unicode name)
    U+1F99E🦞\:lobster:(No Unicode name)
    U+1F99F🦟\:mosquito:(No Unicode name)
    U+1F9A0🦠\:microbe:(No Unicode name)
    U+1F9A1🦡\:badger:(No Unicode name)
    U+1F9A2🦢\:swan:(No Unicode name)
    U+1F9A3🦣\:mammoth:(No Unicode name)
    U+1F9A4🦤\:dodo:(No Unicode name)
    U+1F9A5🦥\:sloth:(No Unicode name)
    U+1F9A6🦦\:otter:(No Unicode name)
    U+1F9A7🦧\:orangutan:(No Unicode name)
    U+1F9A8🦨\:skunk:(No Unicode name)
    U+1F9A9🦩\:flamingo:(No Unicode name)
    U+1F9AA🦪\:oyster:(No Unicode name)
    U+1F9AB🦫\:beaver:(No Unicode name)
    U+1F9AC🦬\:bison:(No Unicode name)
    U+1F9AD🦭\:seal:(No Unicode name)
    U+1F9AE🦮\:guide_dog:(No Unicode name)
    U+1F9AF🦯\:probing_cane:(No Unicode name)
    U+1F9B4🦴\:bone:(No Unicode name)
    U+1F9B5🦵\:leg:(No Unicode name)
    U+1F9B6🦶\:foot:(No Unicode name)
    U+1F9B7🦷\:tooth:(No Unicode name)
    U+1F9B8🦸\:superhero:(No Unicode name)
    U+1F9B9🦹\:supervillain:(No Unicode name)
    U+1F9BA🦺\:safety_vest:(No Unicode name)
    U+1F9BB🦻\:ear_with_hearing_aid:(No Unicode name)
    U+1F9BC🦼\:motorized_wheelchair:(No Unicode name)
    U+1F9BD🦽\:manual_wheelchair:(No Unicode name)
    U+1F9BE🦾\:mechanical_arm:(No Unicode name)
    U+1F9BF🦿\:mechanical_leg:(No Unicode name)
    U+1F9C0🧀\:cheese_wedge:Cheese Wedge
    U+1F9C1🧁\:cupcake:(No Unicode name)
    U+1F9C2🧂\:salt:(No Unicode name)
    U+1F9C3🧃\:beverage_box:(No Unicode name)
    U+1F9C4🧄\:garlic:(No Unicode name)
    U+1F9C5🧅\:onion:(No Unicode name)
    U+1F9C6🧆\:falafel:(No Unicode name)
    U+1F9C7🧇\:waffle:(No Unicode name)
    U+1F9C8🧈\:butter:(No Unicode name)
    U+1F9C9🧉\:mate_drink:(No Unicode name)
    U+1F9CA🧊\:ice_cube:(No Unicode name)
    U+1F9CB🧋\:bubble_tea:(No Unicode name)
    U+1F9CD🧍\:standing_person:(No Unicode name)
    U+1F9CE🧎\:kneeling_person:(No Unicode name)
    U+1F9CF🧏\:deaf_person:(No Unicode name)
    U+1F9D0🧐\:face_with_monocle:(No Unicode name)
    U+1F9D1🧑\:adult:(No Unicode name)
    U+1F9D2🧒\:child:(No Unicode name)
    U+1F9D3🧓\:older_adult:(No Unicode name)
    U+1F9D4🧔\:bearded_person:(No Unicode name)
    U+1F9D5🧕\:person_with_headscarf:(No Unicode name)
    U+1F9D6🧖\:person_in_steamy_room:(No Unicode name)
    U+1F9D7🧗\:person_climbing:(No Unicode name)
    U+1F9D8🧘\:person_in_lotus_position:(No Unicode name)
    U+1F9D9🧙\:mage:(No Unicode name)
    U+1F9DA🧚\:fairy:(No Unicode name)
    U+1F9DB🧛\:vampire:(No Unicode name)
    U+1F9DC🧜\:merperson:(No Unicode name)
    U+1F9DD🧝\:elf:(No Unicode name)
    U+1F9DE🧞\:genie:(No Unicode name)
    U+1F9DF🧟\:zombie:(No Unicode name)
    U+1F9E0🧠\:brain:(No Unicode name)
    U+1F9E1🧡\:orange_heart:(No Unicode name)
    U+1F9E2🧢\:billed_cap:(No Unicode name)
    U+1F9E3🧣\:scarf:(No Unicode name)
    U+1F9E4🧤\:gloves:(No Unicode name)
    U+1F9E5🧥\:coat:(No Unicode name)
    U+1F9E6🧦\:socks:(No Unicode name)
    U+1F9E7🧧\:red_envelope:(No Unicode name)
    U+1F9E8🧨\:firecracker:(No Unicode name)
    U+1F9E9🧩\:jigsaw:(No Unicode name)
    U+1F9EA🧪\:test_tube:(No Unicode name)
    U+1F9EB🧫\:petri_dish:(No Unicode name)
    U+1F9EC🧬\:dna:(No Unicode name)
    U+1F9ED🧭\:compass:(No Unicode name)
    U+1F9EE🧮\:abacus:(No Unicode name)
    U+1F9EF🧯\:fire_extinguisher:(No Unicode name)
    U+1F9F0🧰\:toolbox:(No Unicode name)
    U+1F9F1🧱\:bricks:(No Unicode name)
    U+1F9F2🧲\:magnet:(No Unicode name)
    U+1F9F3🧳\:luggage:(No Unicode name)
    U+1F9F4🧴\:lotion_bottle:(No Unicode name)
    U+1F9F5🧵\:thread:(No Unicode name)
    U+1F9F6🧶\:yarn:(No Unicode name)
    U+1F9F7🧷\:safety_pin:(No Unicode name)
    U+1F9F8🧸\:teddy_bear:(No Unicode name)
    U+1F9F9🧹\:broom:(No Unicode name)
    U+1F9FA🧺\:basket:(No Unicode name)
    U+1F9FB🧻\:roll_of_paper:(No Unicode name)
    U+1F9FC🧼\:soap:(No Unicode name)
    U+1F9FD🧽\:sponge:(No Unicode name)
    U+1F9FE🧾\:receipt:(No Unicode name)
    U+1F9FF🧿\:nazar_amulet:(No Unicode name)
    U+1FA70🩰\:ballet_shoes:(No Unicode name)
    U+1FA71🩱\:one-piece_swimsuit:(No Unicode name)
    U+1FA72🩲\:briefs:(No Unicode name)
    U+1FA73🩳\:shorts:(No Unicode name)
    U+1FA74🩴\:thong_sandal:(No Unicode name)
    U+1FA78🩸\:drop_of_blood:(No Unicode name)
    U+1FA79🩹\:adhesive_bandage:(No Unicode name)
    U+1FA7A🩺\:stethoscope:(No Unicode name)
    U+1FA80🪀\:yo-yo:(No Unicode name)
    U+1FA81🪁\:kite:(No Unicode name)
    U+1FA82🪂\:parachute:(No Unicode name)
    U+1FA83🪃\:boomerang:(No Unicode name)
    U+1FA84🪄\:magic_wand:(No Unicode name)
    U+1FA85🪅\:pinata:(No Unicode name)
    U+1FA86🪆\:nesting_dolls:(No Unicode name)
    U+1FA90🪐\:ringed_planet:(No Unicode name)
    U+1FA91🪑\:chair:(No Unicode name)
    U+1FA92🪒\:razor:(No Unicode name)
    U+1FA93🪓\:axe:(No Unicode name)
    U+1FA94🪔\:diya_lamp:(No Unicode name)
    U+1FA95🪕\:banjo:(No Unicode name)
    U+1FA96🪖\:military_helmet:(No Unicode name)
    U+1FA97🪗\:accordion:(No Unicode name)
    U+1FA98🪘\:long_drum:(No Unicode name)
    U+1FA99🪙\:coin:(No Unicode name)
    U+1FA9A🪚\:carpentry_saw:(No Unicode name)
    U+1FA9B🪛\:screwdriver:(No Unicode name)
    U+1FA9C🪜\:ladder:(No Unicode name)
    U+1FA9D🪝\:hook:(No Unicode name)
    U+1FA9E🪞\:mirror:(No Unicode name)
    U+1FA9F🪟\:window:(No Unicode name)
    U+1FAA0🪠\:plunger:(No Unicode name)
    U+1FAA1🪡\:sewing_needle:(No Unicode name)
    U+1FAA2🪢\:knot:(No Unicode name)
    U+1FAA3🪣\:bucket:(No Unicode name)
    U+1FAA4🪤\:mouse_trap:(No Unicode name)
    U+1FAA5🪥\:toothbrush:(No Unicode name)
    U+1FAA6🪦\:headstone:(No Unicode name)
    U+1FAA7🪧\:placard:(No Unicode name)
    U+1FAA8🪨\:rock:(No Unicode name)
    U+1FAB0🪰\:fly:(No Unicode name)
    U+1FAB1🪱\:worm:(No Unicode name)
    U+1FAB2🪲\:beetle:(No Unicode name)
    U+1FAB3🪳\:cockroach:(No Unicode name)
    U+1FAB4🪴\:potted_plant:(No Unicode name)
    U+1FAB5🪵\:wood:(No Unicode name)
    U+1FAB6🪶\:feather:(No Unicode name)
    U+1FAC0🫀\:anatomical_heart:(No Unicode name)
    U+1FAC1🫁\:lungs:(No Unicode name)
    U+1FAC2🫂\:people_hugging:(No Unicode name)
    U+1FAD0🫐\:blueberries:(No Unicode name)
    U+1FAD1🫑\:bell_pepper:(No Unicode name)
    U+1FAD2🫒\:olive:(No Unicode name)
    U+1FAD3🫓\:flatbread:(No Unicode name)
    U+1FAD4🫔\:tamale:(No Unicode name)
    U+1FAD5🫕\:fondue:(No Unicode name)
    U+1FAD6🫖\:teapot:(No Unicode name)
    diff --git a/dev/manual/variables-and-scoping/index.html b/dev/manual/variables-and-scoping/index.html index 72059402..d656095c 100644 --- a/dev/manual/variables-and-scoping/index.html +++ b/dev/manual/variables-and-scoping/index.html @@ -289,4 +289,4 @@ 2 julia> f() -1 +1 diff --git a/dev/manual/variables/index.html b/dev/manual/variables/index.html index 78ddfe63..713d0a2b 100644 --- a/dev/manual/variables/index.html +++ b/dev/manual/variables/index.html @@ -62,4 +62,4 @@ ERROR: syntax: unexpected "else" julia> try = "No" -ERROR: syntax: unexpected "="

    某些 Unicode 字符被认为是等效的标识符。不同的输入 Unicode 组合字符的方法(例如:重音)被视为等价的(Julia 标识符采用 NFC 标准)。Julia 还加入了一些非标准的等价字符,用于在视觉上相似且易于通过某些输入法输入的字符。Unicode 字符 ɛ (U+025B: Latin small letter open e) 和 µ (U+00B5: micro sign) 被视为等同于相应的希腊字母。点 · (U+00B7) 和希腊字符间断 · (U+0387) 都被当作数学上的点积运算符 (U+22C5)。减号 (U+2212) 与连接号 - (U+002D) 也被视作相同的符号。

    命名规范

    虽然 Julia 语言对合法名字的限制非常少,但是遵循以下这些命名规范是非常有用的:

    关于命名规范的更多信息,可查看代码风格指南

    +ERROR: syntax: unexpected "="

    某些 Unicode 字符被认为是等效的标识符。不同的输入 Unicode 组合字符的方法(例如:重音)被视为等价的(Julia 标识符采用 NFC 标准)。Julia 还加入了一些非标准的等价字符,用于在视觉上相似且易于通过某些输入法输入的字符。Unicode 字符 ɛ (U+025B: Latin small letter open e) 和 µ (U+00B5: micro sign) 被视为等同于相应的希腊字母。点 · (U+00B7) 和希腊字符间断 · (U+0387) 都被当作数学上的点积运算符 (U+22C5)。减号 (U+2212) 与连接号 - (U+002D) 也被视作相同的符号。

    命名规范

    虽然 Julia 语言对合法名字的限制非常少,但是遵循以下这些命名规范是非常有用的:

    关于命名规范的更多信息,可查看代码风格指南

    diff --git a/dev/manual/workflow-tips/index.html b/dev/manual/workflow-tips/index.html index 74b7f45f..37a780bd 100644 --- a/dev/manual/workflow-tips/index.html +++ b/dev/manual/workflow-tips/index.html @@ -34,4 +34,4 @@ t("MyPkg")

    这将在 .julia/dev 目录中创建一个空白包"MyPkg"。 请注意,通过它的 Template 构造器,PkgTemplates 允许控制许多不同的选项。

    在下面的第 2 步中,编辑 MyPkg/src/MyPkg.jl 以更改源代码,并编辑 MyPkg/test/runtests.jl 以进行测试。

  • 对于“一次性”项目,您可以通过在临时目录(例如 /tmp)中进行工作来避免任何清理需求。

    切换到临时目录并启动 Julia,然后执行以下操作:

    pkg> generate MyPkg            # type ] to enter pkg mode
     julia> push!(LOAD_PATH, pwd())   # hit backspace to exit pkg mode

    如果你重新启动 Julia 会话,则必须重新发出修改 LOAD_PATH 的命令。

    在下面的第 2 步中,编辑 MyPkg/src/MyPkg.jl 以更改源代码,并创建你选择的任何测试文件。

  • 构建你自己的包

    在加载任何代码之前, 确保 Revise 已经被启用: using Revise 或者按照教程设置自动加载。

    然后切换到包含测试文件(假设文件为"runtests.jl")的目录下,并:

    julia> using MyPkg
     
    -julia> include("runtests.jl")

    你可以修改在 MyPkg 文件夹中的代码然后用include("runtests.jl")重新跑一遍测试。 通常,你可能需要重新启动Julia 会话来使得这些变化生效(受一些 限制)。

  • +julia> include("runtests.jl")

    你可以修改在 MyPkg 文件夹中的代码然后用include("runtests.jl")重新跑一遍测试。 通常,你可能需要重新启动Julia 会话来使得这些变化生效(受一些 限制)。

    diff --git a/dev/search/index.html b/dev/search/index.html index 1ca898a0..dd3cb22c 100644 --- a/dev/search/index.html +++ b/dev/search/index.html @@ -6,4 +6,4 @@ ga('create', 'UA-28835595-9', 'auto'); ga('send', 'pageview', {'page': location.pathname + location.search + location.hash}); -

    Loading search...

      +

      Loading search...

        diff --git a/dev/search_index.js b/dev/search_index.js index 64309dd8..29d4f8e6 100644 --- a/dev/search_index.js +++ b/dev/search_index.js @@ -1,3 +1,3 @@ var documenterSearchIndex = {"docs": -[{"location":"stdlib/CRC32c/#CRC32c","page":"CRC32c","title":"CRC32c","text":"","category":"section"},{"location":"stdlib/CRC32c/","page":"CRC32c","title":"CRC32c","text":"CRC32c.crc32c\nCRC32c.crc32c(::IO, ::Integer, ::UInt32)","category":"page"},{"location":"stdlib/CRC32c/#CRC32c.crc32c","page":"CRC32c","title":"CRC32c.crc32c","text":"crc32c(data, crc::UInt32=0x00000000)\n\nCompute the CRC-32c checksum of the given data, which can be an Array{UInt8}, a contiguous subarray thereof, or a String. Optionally, you can pass a starting crc integer to be mixed in with the checksum. The crc parameter can be used to compute a checksum on data divided into chunks: performing crc32c(data2, crc32c(data1)) is equivalent to the checksum of [data1; data2]. (Technically, a little-endian checksum is computed.)\n\nThere is also a method crc32c(io, nb, crc) to checksum nb bytes from a stream io, or crc32c(io, crc) to checksum all the remaining bytes. Hence you can do open(crc32c, filename) to checksum an entire file, or crc32c(seekstart(buf)) to checksum an IOBuffer without calling take!.\n\nFor a String, note that the result is specific to the UTF-8 encoding (a different checksum would be obtained from a different Unicode encoding). To checksum an a::Array of some other bitstype, you can do crc32c(reinterpret(UInt8,a)), but note that the result may be endian-dependent.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/CRC32c/#CRC32c.crc32c-Tuple{IO, Integer, UInt32}","page":"CRC32c","title":"CRC32c.crc32c","text":"crc32c(io::IO, [nb::Integer,] crc::UInt32=0x00000000)\n\nRead up to nb bytes from io and return the CRC-32c checksum, optionally mixed with a starting crc integer. If nb is not supplied, then io will be read until the end of the stream.\n\n\n\n\n\n","category":"method"},{"location":"base/sort/#排序及相关函数","page":"排序及相关函数","title":"排序及相关函数","text":"","category":"section"},{"location":"base/sort/","page":"排序及相关函数","title":"排序及相关函数","text":"Julia 拥有为数众多的灵活的 API,用于对已经排序的值数组进行排序和交互。默认情况下,Julia 会选择合理的算法并按标准升序进行排序:","category":"page"},{"location":"base/sort/","page":"排序及相关函数","title":"排序及相关函数","text":"julia> sort([2,3,1])\n3-element Vector{Int64}:\n 1\n 2\n 3","category":"page"},{"location":"base/sort/","page":"排序及相关函数","title":"排序及相关函数","text":"你同样可以轻松实现逆序排序:","category":"page"},{"location":"base/sort/","page":"排序及相关函数","title":"排序及相关函数","text":"julia> sort([2,3,1], rev=true)\n3-element Vector{Int64}:\n 3\n 2\n 1","category":"page"},{"location":"base/sort/","page":"排序及相关函数","title":"排序及相关函数","text":"对数组进行 in-place 排序时,要使用 ! 版的排序函数:","category":"page"},{"location":"base/sort/","page":"排序及相关函数","title":"排序及相关函数","text":"julia> a = [2,3,1];\n\njulia> sort!(a);\n\njulia> a\n3-element Vector{Int64}:\n 1\n 2\n 3","category":"page"},{"location":"base/sort/","page":"排序及相关函数","title":"排序及相关函数","text":"你可以计算用于排列的索引,而不是直接对数组进行排序:","category":"page"},{"location":"base/sort/","page":"排序及相关函数","title":"排序及相关函数","text":"julia> v = randn(5)\n5-element Array{Float64,1}:\n 0.297288\n 0.382396\n -0.597634\n -0.0104452\n -0.839027\n\njulia> p = sortperm(v)\n5-element Array{Int64,1}:\n 5\n 3\n 4\n 1\n 2\n\njulia> v[p]\n5-element Array{Float64,1}:\n -0.839027\n -0.597634\n -0.0104452\n 0.297288\n 0.382396","category":"page"},{"location":"base/sort/","page":"排序及相关函数","title":"排序及相关函数","text":"数组可以根据对其值任意的转换结果来进行排序;","category":"page"},{"location":"base/sort/","page":"排序及相关函数","title":"排序及相关函数","text":"julia> sort(v, by=abs)\n5-element Array{Float64,1}:\n -0.0104452\n 0.297288\n 0.382396\n -0.597634\n -0.839027","category":"page"},{"location":"base/sort/","page":"排序及相关函数","title":"排序及相关函数","text":"或者通过转换来进行逆序排序","category":"page"},{"location":"base/sort/","page":"排序及相关函数","title":"排序及相关函数","text":"julia> sort(v, by=abs, rev=true)\n5-element Array{Float64,1}:\n -0.839027\n -0.597634\n 0.382396\n 0.297288\n -0.0104452","category":"page"},{"location":"base/sort/","page":"排序及相关函数","title":"排序及相关函数","text":"如有必要,可以选择排序算法:","category":"page"},{"location":"base/sort/","page":"排序及相关函数","title":"排序及相关函数","text":"julia> sort(v, alg=InsertionSort)\n5-element Array{Float64,1}:\n -0.839027\n -0.597634\n -0.0104452\n 0.297288\n 0.382396","category":"page"},{"location":"base/sort/","page":"排序及相关函数","title":"排序及相关函数","text":"所有与排序和顺序相关的函数依赖于“小于”关系,该关系定义了要操纵的值的总顺序。默认情况下会调用 isless 函数,但可以通过 lt 关键字指定关系。","category":"page"},{"location":"base/sort/#排序函数","page":"排序及相关函数","title":"排序函数","text":"","category":"section"},{"location":"base/sort/","page":"排序及相关函数","title":"排序及相关函数","text":"Base.sort!\nBase.sort\nBase.sortperm\nBase.InsertionSort\nBase.MergeSort\nBase.QuickSort\nBase.PartialQuickSort\nBase.Sort.sortperm!\nBase.Sort.sortslices","category":"page"},{"location":"base/sort/#Base.sort!","page":"排序及相关函数","title":"Base.sort!","text":"sort!(v; alg::Algorithm=defalg(v), lt=isless, by=identity, rev::Bool=false, order::Ordering=Forward)\n\nSort the vector v in place. QuickSort is used by default for numeric arrays while MergeSort is used for other arrays. You can specify an algorithm to use via the alg keyword (see Sorting Algorithms for available algorithms). The by keyword lets you provide a function that will be applied to each element before comparison; the lt keyword allows providing a custom \"less than\" function (note that for every x and y, only one of lt(x,y) and lt(y,x) can return true); use rev=true to reverse the sorting order. These options are independent and can be used together in all possible combinations: if both by and lt are specified, the lt function is applied to the result of the by function; rev=true reverses whatever ordering specified via the by and lt keywords.\n\nExamples\n\njulia> v = [3, 1, 2]; sort!(v); v\n3-element Vector{Int64}:\n 1\n 2\n 3\n\njulia> v = [3, 1, 2]; sort!(v, rev = true); v\n3-element Vector{Int64}:\n 3\n 2\n 1\n\njulia> v = [(1, \"c\"), (3, \"a\"), (2, \"b\")]; sort!(v, by = x -> x[1]); v\n3-element Vector{Tuple{Int64, String}}:\n (1, \"c\")\n (2, \"b\")\n (3, \"a\")\n\njulia> v = [(1, \"c\"), (3, \"a\"), (2, \"b\")]; sort!(v, by = x -> x[2]); v\n3-element Vector{Tuple{Int64, String}}:\n (3, \"a\")\n (2, \"b\")\n (1, \"c\")\n\n\n\n\n\nsort!(A; dims::Integer, alg::Algorithm=defalg(A), lt=isless, by=identity, rev::Bool=false, order::Ordering=Forward)\n\nSort the multidimensional array A along dimension dims. See sort! for a description of possible keyword arguments.\n\nTo sort slices of an array, refer to sortslices.\n\ncompat: Julia 1.1\nThis function requires at least Julia 1.1.\n\nExamples\n\njulia> A = [4 3; 1 2]\n2×2 Matrix{Int64}:\n 4 3\n 1 2\n\njulia> sort!(A, dims = 1); A\n2×2 Matrix{Int64}:\n 1 2\n 4 3\n\njulia> sort!(A, dims = 2); A\n2×2 Matrix{Int64}:\n 1 2\n 3 4\n\n\n\n\n\n","category":"function"},{"location":"base/sort/#Base.sort","page":"排序及相关函数","title":"Base.sort","text":"sort(v; alg::Algorithm=defalg(v), lt=isless, by=identity, rev::Bool=false, order::Ordering=Forward)\n\nVariant of sort! that returns a sorted copy of v leaving v itself unmodified.\n\nExamples\n\njulia> v = [3, 1, 2];\n\njulia> sort(v)\n3-element Vector{Int64}:\n 1\n 2\n 3\n\njulia> v\n3-element Vector{Int64}:\n 3\n 1\n 2\n\n\n\n\n\nsort(A; dims::Integer, alg::Algorithm=DEFAULT_UNSTABLE, lt=isless, by=identity, rev::Bool=false, order::Ordering=Forward)\n\nSort a multidimensional array A along the given dimension. See sort! for a description of possible keyword arguments.\n\nTo sort slices of an array, refer to sortslices.\n\nExamples\n\njulia> A = [4 3; 1 2]\n2×2 Matrix{Int64}:\n 4 3\n 1 2\n\njulia> sort(A, dims = 1)\n2×2 Matrix{Int64}:\n 1 2\n 4 3\n\njulia> sort(A, dims = 2)\n2×2 Matrix{Int64}:\n 3 4\n 1 2\n\n\n\n\n\n","category":"function"},{"location":"base/sort/#Base.sortperm","page":"排序及相关函数","title":"Base.sortperm","text":"sortperm(v; alg::Algorithm=DEFAULT_UNSTABLE, lt=isless, by=identity, rev::Bool=false, order::Ordering=Forward)\n\nReturn a permutation vector I that puts v[I] in sorted order. The order is specified using the same keywords as sort!. The permutation is guaranteed to be stable even if the sorting algorithm is unstable, meaning that indices of equal elements appear in ascending order.\n\nSee also sortperm!, partialsortperm, invperm, indexin.\n\nExamples\n\njulia> v = [3, 1, 2];\n\njulia> p = sortperm(v)\n3-element Vector{Int64}:\n 2\n 3\n 1\n\njulia> v[p]\n3-element Vector{Int64}:\n 1\n 2\n 3\n\n\n\n\n\n","category":"function"},{"location":"base/sort/#Base.Sort.InsertionSort","page":"排序及相关函数","title":"Base.Sort.InsertionSort","text":"InsertionSort\n\nIndicate that a sorting function should use the insertion sort algorithm. Insertion sort traverses the collection one element at a time, inserting each element into its correct, sorted position in the output list.\n\nCharacteristics:\n\nstable: preserves the ordering of elements which compare equal (e.g. \"a\" and \"A\" in a sort of letters which ignores case).\nin-place in memory.\nquadratic performance in the number of elements to be sorted: it is well-suited to small collections but should not be used for large ones.\n\n\n\n\n\n","category":"constant"},{"location":"base/sort/#Base.Sort.MergeSort","page":"排序及相关函数","title":"Base.Sort.MergeSort","text":"MergeSort\n\nIndicate that a sorting function should use the merge sort algorithm. Merge sort divides the collection into subcollections and repeatedly merges them, sorting each subcollection at each step, until the entire collection has been recombined in sorted form.\n\nCharacteristics:\n\nstable: preserves the ordering of elements which compare equal (e.g. \"a\" and \"A\" in a sort of letters which ignores case).\nnot in-place in memory.\ndivide-and-conquer sort strategy.\n\n\n\n\n\n","category":"constant"},{"location":"base/sort/#Base.Sort.QuickSort","page":"排序及相关函数","title":"Base.Sort.QuickSort","text":"QuickSort\n\nIndicate that a sorting function should use the quick sort algorithm, which is not stable.\n\nCharacteristics:\n\nnot stable: does not preserve the ordering of elements which compare equal (e.g. \"a\" and \"A\" in a sort of letters which ignores case).\nin-place in memory.\ndivide-and-conquer: sort strategy similar to MergeSort.\ngood performance for large collections.\n\n\n\n\n\n","category":"constant"},{"location":"base/sort/#Base.Sort.PartialQuickSort","page":"排序及相关函数","title":"Base.Sort.PartialQuickSort","text":"PartialQuickSort{T <: Union{Integer,OrdinalRange}}\n\nIndicate that a sorting function should use the partial quick sort algorithm. Partial quick sort returns the smallest k elements sorted from smallest to largest, finding them and sorting them using QuickSort.\n\nCharacteristics:\n\nnot stable: does not preserve the ordering of elements which compare equal (e.g. \"a\" and \"A\" in a sort of letters which ignores case).\nin-place in memory.\ndivide-and-conquer: sort strategy similar to MergeSort.\n\n\n\n\n\n","category":"type"},{"location":"base/sort/#Base.Sort.sortperm!","page":"排序及相关函数","title":"Base.Sort.sortperm!","text":"sortperm!(ix, v; alg::Algorithm=DEFAULT_UNSTABLE, lt=isless, by=identity, rev::Bool=false, order::Ordering=Forward, initialized::Bool=false)\n\nLike sortperm, but accepts a preallocated index vector ix. If initialized is false (the default), ix is initialized to contain the values 1:length(v).\n\nExamples\n\njulia> v = [3, 1, 2]; p = zeros(Int, 3);\n\njulia> sortperm!(p, v); p\n3-element Vector{Int64}:\n 2\n 3\n 1\n\njulia> v[p]\n3-element Vector{Int64}:\n 1\n 2\n 3\n\n\n\n\n\n","category":"function"},{"location":"base/sort/#Base.sortslices","page":"排序及相关函数","title":"Base.sortslices","text":"sortslices(A; dims, alg::Algorithm=DEFAULT_UNSTABLE, lt=isless, by=identity, rev::Bool=false, order::Ordering=Forward)\n\nSort slices of an array A. The required keyword argument dims must be either an integer or a tuple of integers. It specifies the dimension(s) over which the slices are sorted.\n\nE.g., if A is a matrix, dims=1 will sort rows, dims=2 will sort columns. Note that the default comparison function on one dimensional slices sorts lexicographically.\n\nFor the remaining keyword arguments, see the documentation of sort!.\n\nExamples\n\njulia> sortslices([7 3 5; -1 6 4; 9 -2 8], dims=1) # Sort rows\n3×3 Matrix{Int64}:\n -1 6 4\n 7 3 5\n 9 -2 8\n\njulia> sortslices([7 3 5; -1 6 4; 9 -2 8], dims=1, lt=(x,y)->isless(x[2],y[2]))\n3×3 Matrix{Int64}:\n 9 -2 8\n 7 3 5\n -1 6 4\n\njulia> sortslices([7 3 5; -1 6 4; 9 -2 8], dims=1, rev=true)\n3×3 Matrix{Int64}:\n 9 -2 8\n 7 3 5\n -1 6 4\n\njulia> sortslices([7 3 5; 6 -1 -4; 9 -2 8], dims=2) # Sort columns\n3×3 Matrix{Int64}:\n 3 5 7\n -1 -4 6\n -2 8 9\n\njulia> sortslices([7 3 5; 6 -1 -4; 9 -2 8], dims=2, alg=InsertionSort, lt=(x,y)->isless(x[2],y[2]))\n3×3 Matrix{Int64}:\n 5 3 7\n -4 -1 6\n 8 -2 9\n\njulia> sortslices([7 3 5; 6 -1 -4; 9 -2 8], dims=2, rev=true)\n3×3 Matrix{Int64}:\n 7 5 3\n 6 -4 -1\n 9 8 -2\n\nHigher dimensions\n\nsortslices extends naturally to higher dimensions. E.g., if A is a a 2x2x2 array, sortslices(A, dims=3) will sort slices within the 3rd dimension, passing the 2x2 slices A[:, :, 1] and A[:, :, 2] to the comparison function. Note that while there is no default order on higher-dimensional slices, you may use the by or lt keyword argument to specify such an order.\n\nIf dims is a tuple, the order of the dimensions in dims is relevant and specifies the linear order of the slices. E.g., if A is three dimensional and dims is (1, 2), the orderings of the first two dimensions are re-arranged such that the slices (of the remaining third dimension) are sorted. If dims is (2, 1) instead, the same slices will be taken, but the result order will be row-major instead.\n\nHigher dimensional examples\n\njulia> A = permutedims(reshape([4 3; 2 1; 'A' 'B'; 'C' 'D'], (2, 2, 2)), (1, 3, 2))\n2×2×2 Array{Any, 3}:\n[:, :, 1] =\n 4 3\n 2 1\n\n[:, :, 2] =\n 'A' 'B'\n 'C' 'D'\n\njulia> sortslices(A, dims=(1,2))\n2×2×2 Array{Any, 3}:\n[:, :, 1] =\n 1 3\n 2 4\n\n[:, :, 2] =\n 'D' 'B'\n 'C' 'A'\n\njulia> sortslices(A, dims=(2,1))\n2×2×2 Array{Any, 3}:\n[:, :, 1] =\n 1 2\n 3 4\n\n[:, :, 2] =\n 'D' 'C'\n 'B' 'A'\n\njulia> sortslices(reshape([5; 4; 3; 2; 1], (1,1,5)), dims=3, by=x->x[1,1])\n1×1×5 Array{Int64, 3}:\n[:, :, 1] =\n 1\n\n[:, :, 2] =\n 2\n\n[:, :, 3] =\n 3\n\n[:, :, 4] =\n 4\n\n[:, :, 5] =\n 5\n\n\n\n\n\n","category":"function"},{"location":"base/sort/#排列顺序相关的函数","page":"排序及相关函数","title":"排列顺序相关的函数","text":"","category":"section"},{"location":"base/sort/","page":"排序及相关函数","title":"排序及相关函数","text":"Base.issorted\nBase.Sort.searchsorted\nBase.Sort.searchsortedfirst\nBase.Sort.searchsortedlast\nBase.Sort.insorted\nBase.Sort.partialsort!\nBase.Sort.partialsort\nBase.Sort.partialsortperm\nBase.Sort.partialsortperm!","category":"page"},{"location":"base/sort/#Base.issorted","page":"排序及相关函数","title":"Base.issorted","text":"issorted(v, lt=isless, by=identity, rev::Bool=false, order::Ordering=Forward)\n\nTest whether a vector is in sorted order. The lt, by and rev keywords modify what order is considered to be sorted just as they do for sort.\n\nExamples\n\njulia> issorted([1, 2, 3])\ntrue\n\njulia> issorted([(1, \"b\"), (2, \"a\")], by = x -> x[1])\ntrue\n\njulia> issorted([(1, \"b\"), (2, \"a\")], by = x -> x[2])\nfalse\n\njulia> issorted([(1, \"b\"), (2, \"a\")], by = x -> x[2], rev=true)\ntrue\n\n\n\n\n\n","category":"function"},{"location":"base/sort/#Base.Sort.searchsorted","page":"排序及相关函数","title":"Base.Sort.searchsorted","text":"searchsorted(a, x; by=, lt=, rev=false)\n\nReturn the range of indices of a which compare as equal to x (using binary search) according to the order specified by the by, lt and rev keywords, assuming that a is already sorted in that order. Return an empty range located at the insertion point if a does not contain values equal to x.\n\nSee also: insorted, searchsortedfirst, sort, findall.\n\nExamples\n\njulia> searchsorted([1, 2, 4, 5, 5, 7], 4) # single match\n3:3\n\njulia> searchsorted([1, 2, 4, 5, 5, 7], 5) # multiple matches\n4:5\n\njulia> searchsorted([1, 2, 4, 5, 5, 7], 3) # no match, insert in the middle\n3:2\n\njulia> searchsorted([1, 2, 4, 5, 5, 7], 9) # no match, insert at end\n7:6\n\njulia> searchsorted([1, 2, 4, 5, 5, 7], 0) # no match, insert at start\n1:0\n\n\n\n\n\n","category":"function"},{"location":"base/sort/#Base.Sort.searchsortedfirst","page":"排序及相关函数","title":"Base.Sort.searchsortedfirst","text":"searchsortedfirst(a, x; by=, lt=, rev=false)\n\nReturn the index of the first value in a greater than or equal to x, according to the specified order. Return lastindex(a) + 1 if x is greater than all values in a. a is assumed to be sorted.\n\nSee also: searchsortedlast, searchsorted, findfirst.\n\nExamples\n\njulia> searchsortedfirst([1, 2, 4, 5, 5, 7], 4) # single match\n3\n\njulia> searchsortedfirst([1, 2, 4, 5, 5, 7], 5) # multiple matches\n4\n\njulia> searchsortedfirst([1, 2, 4, 5, 5, 7], 3) # no match, insert in the middle\n3\n\njulia> searchsortedfirst([1, 2, 4, 5, 5, 7], 9) # no match, insert at end\n7\n\njulia> searchsortedfirst([1, 2, 4, 5, 5, 7], 0) # no match, insert at start\n1\n\n\n\n\n\n","category":"function"},{"location":"base/sort/#Base.Sort.searchsortedlast","page":"排序及相关函数","title":"Base.Sort.searchsortedlast","text":"searchsortedlast(a, x; by=, lt=, rev=false)\n\nReturn the index of the last value in a less than or equal to x, according to the specified order. Return firstindex(a) - 1 if x is less than all values in a. a is assumed to be sorted.\n\nExamples\n\njulia> searchsortedlast([1, 2, 4, 5, 5, 7], 4) # single match\n3\n\njulia> searchsortedlast([1, 2, 4, 5, 5, 7], 5) # multiple matches\n5\n\njulia> searchsortedlast([1, 2, 4, 5, 5, 7], 3) # no match, insert in the middle\n2\n\njulia> searchsortedlast([1, 2, 4, 5, 5, 7], 9) # no match, insert at end\n6\n\njulia> searchsortedlast([1, 2, 4, 5, 5, 7], 0) # no match, insert at start\n0\n\n\n\n\n\n","category":"function"},{"location":"base/sort/#Base.Sort.insorted","page":"排序及相关函数","title":"Base.Sort.insorted","text":"insorted(a, x; by=, lt=, rev=false) -> Bool\n\nDetermine whether an item is in the given sorted collection, in the sense that it is == to one of the values of the collection according to the order specified by the by, lt and rev keywords, assuming that a is already sorted in that order, see sort for the keywords.\n\nSee also in.\n\nExamples\n\njulia> insorted(4, [1, 2, 4, 5, 5, 7]) # single match\ntrue\n\njulia> insorted(5, [1, 2, 4, 5, 5, 7]) # multiple matches\ntrue\n\njulia> insorted(3, [1, 2, 4, 5, 5, 7]) # no match\nfalse\n\njulia> insorted(9, [1, 2, 4, 5, 5, 7]) # no match\nfalse\n\njulia> insorted(0, [1, 2, 4, 5, 5, 7]) # no match\nfalse\n\ncompat: Julia 1.6\ninsorted was added in Julia 1.6.\n\n\n\n\n\n","category":"function"},{"location":"base/sort/#Base.Sort.partialsort!","page":"排序及相关函数","title":"Base.Sort.partialsort!","text":"partialsort!(v, k; by=, lt=, rev=false)\n\nPartially sort the vector v in place, according to the order specified by by, lt and rev so that the value at index k (or range of adjacent values if k is a range) occurs at the position where it would appear if the array were fully sorted via a non-stable algorithm. If k is a single index, that value is returned; if k is a range, an array of values at those indices is returned. Note that partialsort! does not fully sort the input array.\n\nExamples\n\njulia> a = [1, 2, 4, 3, 4]\n5-element Vector{Int64}:\n 1\n 2\n 4\n 3\n 4\n\njulia> partialsort!(a, 4)\n4\n\njulia> a\n5-element Vector{Int64}:\n 1\n 2\n 3\n 4\n 4\n\njulia> a = [1, 2, 4, 3, 4]\n5-element Vector{Int64}:\n 1\n 2\n 4\n 3\n 4\n\njulia> partialsort!(a, 4, rev=true)\n2\n\njulia> a\n5-element Vector{Int64}:\n 4\n 4\n 3\n 2\n 1\n\n\n\n\n\n","category":"function"},{"location":"base/sort/#Base.Sort.partialsort","page":"排序及相关函数","title":"Base.Sort.partialsort","text":"partialsort(v, k, by=, lt=, rev=false)\n\nVariant of partialsort! which copies v before partially sorting it, thereby returning the same thing as partialsort! but leaving v unmodified.\n\n\n\n\n\n","category":"function"},{"location":"base/sort/#Base.Sort.partialsortperm","page":"排序及相关函数","title":"Base.Sort.partialsortperm","text":"partialsortperm(v, k; by=, lt=, rev=false)\n\nReturn a partial permutation I of the vector v, so that v[I] returns values of a fully sorted version of v at index k. If k is a range, a vector of indices is returned; if k is an integer, a single index is returned. The order is specified using the same keywords as sort!. The permutation is stable, meaning that indices of equal elements appear in ascending order.\n\nNote that this function is equivalent to, but more efficient than, calling sortperm(...)[k].\n\nExamples\n\njulia> v = [3, 1, 2, 1];\n\njulia> v[partialsortperm(v, 1)]\n1\n\njulia> p = partialsortperm(v, 1:3)\n3-element view(::Vector{Int64}, 1:3) with eltype Int64:\n 2\n 4\n 3\n\njulia> v[p]\n3-element Vector{Int64}:\n 1\n 1\n 2\n\n\n\n\n\n","category":"function"},{"location":"base/sort/#Base.Sort.partialsortperm!","page":"排序及相关函数","title":"Base.Sort.partialsortperm!","text":"partialsortperm!(ix, v, k; by=, lt=, rev=false, initialized=false)\n\nLike partialsortperm, but accepts a preallocated index vector ix the same size as v, which is used to store (a permutation of) the indices of v.\n\nIf the index vector ix is initialized with the indices of v (or a permutation thereof), initialized should be set to true.\n\nIf initialized is false (the default), then ix is initialized to contain the indices of v.\n\nIf initialized is true, but ix does not contain (a permutation of) the indices of v, the behavior of partialsortperm! is undefined.\n\n(Typically, the indices of v will be 1:length(v), although if v has an alternative array type with non-one-based indices, such as an OffsetArray, ix must also be an OffsetArray with the same indices, and must contain as values (a permutation of) these same indices.)\n\nUpon return, ix is guaranteed to have the indices k in their sorted positions, such that\n\npartialsortperm!(ix, v, k);\nv[ix[k]] == partialsort(v, k)\n\nThe return value is the kth element of ix if k is an integer, or view into ix if k is a range.\n\nExamples\n\njulia> v = [3, 1, 2, 1];\n\njulia> ix = Vector{Int}(undef, 4);\n\njulia> partialsortperm!(ix, v, 1)\n2\n\njulia> ix = [1:4;];\n\njulia> partialsortperm!(ix, v, 2:3, initialized=true)\n2-element view(::Vector{Int64}, 2:3) with eltype Int64:\n 4\n 3\n\n\n\n\n\n\n\n","category":"function"},{"location":"base/sort/#排序算法","page":"排序及相关函数","title":"排序算法","text":"","category":"section"},{"location":"base/sort/","page":"排序及相关函数","title":"排序及相关函数","text":"目前,Julia Base 中有四种可用的排序算法:","category":"page"},{"location":"base/sort/","page":"排序及相关函数","title":"排序及相关函数","text":"InsertionSort\nQuickSort\nPartialQuickSort(k)\nMergeSort","category":"page"},{"location":"base/sort/","page":"排序及相关函数","title":"排序及相关函数","text":"InsertionSort 是一个在 QuickSort 中使用的时间复杂度为 O(n^2) 的稳定的排序算法,它通常在 n 比较小的时候才具有较高的效率。","category":"page"},{"location":"base/sort/","page":"排序及相关函数","title":"排序及相关函数","text":"QuickSort 是一个内置并且非常快,但是不稳定的时间复杂度为 O(n log n)的排序算法,例如即使数组两个元素相等的,它们排序之后的顺序也可能和在原数组中顺序不一致。QuickSort 是内置的包括整数和浮点数在内的数字值的默认排序算法。","category":"page"},{"location":"base/sort/","page":"排序及相关函数","title":"排序及相关函数","text":"PartialQuickSort(k) 类似于 QuickSort,但是如果 k 是一个整数,输出数组只排序到索引 k,如果 k 是 OrdinalRange,则输出数组排在 k 范围内。 例如:","category":"page"},{"location":"base/sort/","page":"排序及相关函数","title":"排序及相关函数","text":"x = rand(1:500, 100)\nk = 50\nk2 = 50:100\ns = sort(x; alg=QuickSort)\nps = sort(x; alg=PartialQuickSort(k))\nqs = sort(x; alg=PartialQuickSort(k2))\nmap(issorted, (s, ps, qs)) # => (true, false, false)\nmap(x->issorted(x[1:k]), (s, ps, qs)) # => (true, true, false)\nmap(x->issorted(x[k2]), (s, ps, qs)) # => (true, false, true)\ns[1:k] == ps[1:k] # => true\ns[k2] == qs[k2] # => true","category":"page"},{"location":"base/sort/","page":"排序及相关函数","title":"排序及相关函数","text":"MergeSort 是一个时间复杂度为 O(n log n) 的稳定但是非 in-place 的算法,它需要一个大小为输入数组一般的临时数组——同时也不像 QuickSort 一样快。MergeSort 是非数值型数据的默认排序算法。","category":"page"},{"location":"base/sort/","page":"排序及相关函数","title":"排序及相关函数","text":"默认排序算法的选择是基于它们的快速稳定,或者 appear 之类的。对于数值类型,实际上选择了 QuickSort,因为在这种情况下,它更快,与稳定排序没有区别(除非数组以某种方式记录了突变)","category":"page"},{"location":"base/sort/","page":"排序及相关函数","title":"排序及相关函数","text":"Julia选择默认排序算法的机制是通过 Base.Sort.defalg 来实现的,其允许将特定算法注册为特定数组的所有排序函数中的默认值。例如,这有两个默认算法 sort.jl:","category":"page"},{"location":"base/sort/","page":"排序及相关函数","title":"排序及相关函数","text":"defalg(v::AbstractArray) = MergeSort\ndefalg(v::AbstractArray{<:Number}) = QuickSort","category":"page"},{"location":"base/sort/","page":"排序及相关函数","title":"排序及相关函数","text":"对于数值型数组,选择非稳定的默认排序算法的原则是稳定的排序算法没有必要的(例如:但两个值相比较时相等且不可区分时)。","category":"page"},{"location":"base/sort/#Alternate-orderings","page":"排序及相关函数","title":"Alternate orderings","text":"","category":"section"},{"location":"base/sort/","page":"排序及相关函数","title":"排序及相关函数","text":"By default, sort and related functions use isless to compare two elements in order to determine which should come first. The Base.Order.Ordering abstract type provides a mechanism for defining alternate orderings on the same set of elements. Instances of Ordering define a total order on a set of elements, so that for any elements a, b, c the following hold:","category":"page"},{"location":"base/sort/","page":"排序及相关函数","title":"排序及相关函数","text":"Exactly one of the following is true: a is less than b, b is less than a, or a and b are equal (according to isequal).\nThe relation is transitive - if a is less than b and b is less than c then a is less than c.","category":"page"},{"location":"base/sort/","page":"排序及相关函数","title":"排序及相关函数","text":"The Base.Order.lt function works as a generalization of isless to test whether a is less than b according to a given order.","category":"page"},{"location":"base/sort/","page":"排序及相关函数","title":"排序及相关函数","text":"Base.Order.Ordering\nBase.Order.lt\nBase.Order.ord\nBase.Order.Forward\nBase.Order.ReverseOrdering\nBase.Order.Reverse\nBase.Order.By\nBase.Order.Lt\nBase.Order.Perm","category":"page"},{"location":"base/sort/#Base.Order.Ordering","page":"排序及相关函数","title":"Base.Order.Ordering","text":"Base.Order.Ordering\n\nAbstract type which represents a total order on some set of elements.\n\nUse Base.Order.lt to compare two elements according to the ordering.\n\n\n\n\n\n","category":"type"},{"location":"base/sort/#Base.Order.lt","page":"排序及相关函数","title":"Base.Order.lt","text":"lt(o::Ordering, a, b)\n\nTest whether a is less than b according to the ordering o.\n\n\n\n\n\n","category":"function"},{"location":"base/sort/#Base.Order.ord","page":"排序及相关函数","title":"Base.Order.ord","text":"ord(lt, by, rev::Union{Bool, Nothing}, order::Ordering=Forward)\n\nConstruct an Ordering object from the same arguments used by sort!. Elements are first transformed by the function by (which may be identity) and are then compared according to either the function lt or an existing ordering order. lt should be isless or a function which obeys similar rules. Finally, the resulting order is reversed if rev=true.\n\nPassing an lt other than isless along with an order other than Base.Order.Forward or Base.Order.Reverse is not permitted, otherwise all options are independent and can be used together in all possible combinations.\n\n\n\n\n\n","category":"function"},{"location":"base/sort/#Base.Order.Forward","page":"排序及相关函数","title":"Base.Order.Forward","text":"Base.Order.Forward\n\nDefault ordering according to isless.\n\n\n\n\n\n","category":"constant"},{"location":"base/sort/#Base.Order.ReverseOrdering","page":"排序及相关函数","title":"Base.Order.ReverseOrdering","text":"ReverseOrdering(fwd::Ordering=Forward)\n\nA wrapper which reverses an ordering.\n\nFor a given Ordering o, the following holds for all a, b:\n\nlt(ReverseOrdering(o), a, b) == lt(o, b, a)\n\n\n\n\n\n","category":"type"},{"location":"base/sort/#Base.Order.Reverse","page":"排序及相关函数","title":"Base.Order.Reverse","text":"Base.Order.Reverse\n\nReverse ordering according to isless.\n\n\n\n\n\n","category":"constant"},{"location":"base/sort/#Base.Order.By","page":"排序及相关函数","title":"Base.Order.By","text":"By(by, order::Ordering=Forward)\n\nOrdering which applies order to elements after they have been transformed by the function by.\n\n\n\n\n\n","category":"type"},{"location":"base/sort/#Base.Order.Lt","page":"排序及相关函数","title":"Base.Order.Lt","text":"Lt(lt)\n\nOrdering which calls lt(a, b) to compare elements. lt should obey the same rules as implementations of isless.\n\n\n\n\n\n","category":"type"},{"location":"base/sort/#Base.Order.Perm","page":"排序及相关函数","title":"Base.Order.Perm","text":"Perm(order::Ordering, data::AbstractVector)\n\nOrdering on the indices of data where i is less than j if data[i] is less than data[j] according to order. In the case that data[i] and data[j] are equal, i and j are compared by numeric value.\n\n\n\n\n\n","category":"type"},{"location":"stdlib/Base64/#Base64","page":"Base64","title":"Base64","text":"","category":"section"},{"location":"stdlib/Base64/","page":"Base64","title":"Base64","text":"Base64.Base64\nBase64.Base64EncodePipe\nBase64.base64encode\nBase64.Base64DecodePipe\nBase64.base64decode\nBase64.stringmime","category":"page"},{"location":"stdlib/Base64/#Base64.Base64","page":"Base64","title":"Base64.Base64","text":"Base64\n\nFunctionality for base-64 encoded strings and IO.\n\n\n\n\n\n","category":"module"},{"location":"stdlib/Base64/#Base64.Base64EncodePipe","page":"Base64","title":"Base64.Base64EncodePipe","text":"Base64EncodePipe(ostream)\n\nReturn a new write-only I/O stream, which converts any bytes written to it into base64-encoded ASCII bytes written to ostream. Calling close on the Base64EncodePipe stream is necessary to complete the encoding (but does not close ostream).\n\nExamples\n\njulia> io = IOBuffer();\n\njulia> iob64_encode = Base64EncodePipe(io);\n\njulia> write(iob64_encode, \"Hello!\")\n6\n\njulia> close(iob64_encode);\n\njulia> str = String(take!(io))\n\"SGVsbG8h\"\n\njulia> String(base64decode(str))\n\"Hello!\"\n\n\n\n\n\n","category":"type"},{"location":"stdlib/Base64/#Base64.base64encode","page":"Base64","title":"Base64.base64encode","text":"base64encode(writefunc, args...; context=nothing)\nbase64encode(args...; context=nothing)\n\nGiven a write-like function writefunc, which takes an I/O stream as its first argument, base64encode(writefunc, args...) calls writefunc to write args... to a base64-encoded string, and returns the string. base64encode(args...) is equivalent to base64encode(write, args...): it converts its arguments into bytes using the standard write functions and returns the base64-encoded string.\n\nThe optional keyword argument context can be set to :key=>value pair or an IO or IOContext object whose attributes are used for the I/O stream passed to writefunc or write.\n\nSee also base64decode.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/Base64/#Base64.Base64DecodePipe","page":"Base64","title":"Base64.Base64DecodePipe","text":"Base64DecodePipe(istream)\n\nReturn a new read-only I/O stream, which decodes base64-encoded data read from istream.\n\nExamples\n\njulia> io = IOBuffer();\n\njulia> iob64_decode = Base64DecodePipe(io);\n\njulia> write(io, \"SGVsbG8h\")\n8\n\njulia> seekstart(io);\n\njulia> String(read(iob64_decode))\n\"Hello!\"\n\n\n\n\n\n","category":"type"},{"location":"stdlib/Base64/#Base64.base64decode","page":"Base64","title":"Base64.base64decode","text":"base64decode(string)\n\nDecode the base64-encoded string and returns a Vector{UInt8} of the decoded bytes.\n\nSee also base64encode.\n\nExamples\n\njulia> b = base64decode(\"SGVsbG8h\")\n6-element Vector{UInt8}:\n 0x48\n 0x65\n 0x6c\n 0x6c\n 0x6f\n 0x21\n\njulia> String(b)\n\"Hello!\"\n\n\n\n\n\n","category":"function"},{"location":"stdlib/Base64/#Base64.stringmime","page":"Base64","title":"Base64.stringmime","text":"stringmime(mime, x; context=nothing)\n\nReturns an AbstractString containing the representation of x in the requested mime type. This is similar to repr(mime, x) except that binary data is base64-encoded as an ASCII string.\n\nThe optional keyword argument context can be set to :key=>value pair or an IO or IOContext object whose attributes are used for the I/O stream passed to show.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/FileWatching/#文件相关事件","page":"文件相关事件","title":"文件相关事件","text":"","category":"section"},{"location":"stdlib/FileWatching/","page":"文件相关事件","title":"文件相关事件","text":"FileWatching.poll_fd\nFileWatching.poll_file\nFileWatching.watch_file\nFileWatching.watch_folder\nFileWatching.unwatch_folder","category":"page"},{"location":"stdlib/FileWatching/#FileWatching.poll_fd","page":"文件相关事件","title":"FileWatching.poll_fd","text":"poll_fd(fd, timeout_s::Real=-1; readable=false, writable=false)\n\nMonitor a file descriptor fd for changes in the read or write availability, and with a timeout given by timeout_s seconds.\n\nThe keyword arguments determine which of read and/or write status should be monitored; at least one of them must be set to true.\n\nThe returned value is an object with boolean fields readable, writable, and timedout, giving the result of the polling.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/FileWatching/#FileWatching.poll_file","page":"文件相关事件","title":"FileWatching.poll_file","text":"poll_file(path::AbstractString, interval_s::Real=5.007, timeout_s::Real=-1) -> (previous::StatStruct, current)\n\nMonitor a file for changes by polling every interval_s seconds until a change occurs or timeout_s seconds have elapsed. The interval_s should be a long period; the default is 5.007 seconds.\n\nReturns a pair of status objects (previous, current) when a change is detected. The previous status is always a StatStruct, but it may have all of the fields zeroed (indicating the file didn't previously exist, or wasn't previously accessible).\n\nThe current status object may be a StatStruct, an EOFError (indicating the timeout elapsed), or some other Exception subtype (if the stat operation failed - for example, if the path does not exist).\n\nTo determine when a file was modified, compare current isa StatStruct && mtime(prev) != mtime(current) to detect notification of changes. However, using watch_file for this operation is preferred, since it is more reliable and efficient, although in some situations it may not be available.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/FileWatching/#FileWatching.watch_file","page":"文件相关事件","title":"FileWatching.watch_file","text":"watch_file(path::AbstractString, timeout_s::Real=-1)\n\nWatch file or directory path for changes until a change occurs or timeout_s seconds have elapsed.\n\nThe returned value is an object with boolean fields changed, renamed, and timedout, giving the result of watching the file.\n\nThis behavior of this function varies slightly across platforms. See https://nodejs.org/api/fs.html#fs_caveats for more detailed information.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/FileWatching/#FileWatching.watch_folder","page":"文件相关事件","title":"FileWatching.watch_folder","text":"watch_folder(path::AbstractString, timeout_s::Real=-1)\n\nWatches a file or directory path for changes until a change has occurred or timeout_s seconds have elapsed.\n\nThis will continuing tracking changes for path in the background until unwatch_folder is called on the same path.\n\nThe returned value is an pair where the first field is the name of the changed file (if available) and the second field is an object with boolean fields changed, renamed, and timedout, giving the event.\n\nThis behavior of this function varies slightly across platforms. See https://nodejs.org/api/fs.html#fs_caveats for more detailed information.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/FileWatching/#FileWatching.unwatch_folder","page":"文件相关事件","title":"FileWatching.unwatch_folder","text":"unwatch_folder(path::AbstractString)\n\nStop background tracking of changes for path. It is not recommended to do this while another task is waiting for watch_folder to return on the same path, as the result may be unpredictable.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/Logging/#日志记录","page":"日志记录","title":"日志记录","text":"","category":"section"},{"location":"stdlib/Logging/","page":"日志记录","title":"日志记录","text":"Logging 模块提供了一个将历史和计算进度记录为事件的日志。事件通过在源代码里插入日志语句产生,例如:","category":"page"},{"location":"stdlib/Logging/","page":"日志记录","title":"日志记录","text":"@warn \"Abandon printf debugging, all ye who enter here!\"\n┌ Warning: Abandon printf debugging, all ye who enter here!\n└ @ Main REPL[1]:1","category":"page"},{"location":"stdlib/Logging/","page":"日志记录","title":"日志记录","text":"The system provides several advantages over peppering your source code with calls to println(). First, it allows you to control the visibility and presentation of messages without editing the source code. For example, in contrast to the @warn above","category":"page"},{"location":"stdlib/Logging/","page":"日志记录","title":"日志记录","text":"@debug \"The sum of some values $(sum(rand(100)))\"","category":"page"},{"location":"stdlib/Logging/","page":"日志记录","title":"日志记录","text":"will produce no output by default. Furthermore, it's very cheap to leave debug statements like this in the source code because the system avoids evaluating the message if it would later be ignored. In this case sum(rand(100)) and the associated string processing will never be executed unless debug logging is enabled.","category":"page"},{"location":"stdlib/Logging/","page":"日志记录","title":"日志记录","text":"Second, the logging tools allow you to attach arbitrary data to each event as a set of key–value pairs. This allows you to capture local variables and other program state for later analysis. For example, to attach the local array variable A and the sum of a vector v as the key s you can use","category":"page"},{"location":"stdlib/Logging/","page":"日志记录","title":"日志记录","text":"A = ones(Int, 4, 4)\nv = ones(100)\n@info \"Some variables\" A s=sum(v)\n\n# output\n┌ Info: Some variables\n│ A =\n│ 4×4 Matrix{Int64}:\n│ 1 1 1 1\n│ 1 1 1 1\n│ 1 1 1 1\n│ 1 1 1 1\n└ s = 100.0","category":"page"},{"location":"stdlib/Logging/","page":"日志记录","title":"日志记录","text":"所有的日志宏如 @debug, @info, @warn 和 @error 有着共同的特征, 这些共同特征在更通用的宏 @logmsg 的文档里有细致说明。","category":"page"},{"location":"stdlib/Logging/#日志事件结构","page":"日志记录","title":"日志事件结构","text":"","category":"section"},{"location":"stdlib/Logging/","page":"日志记录","title":"日志记录","text":"Each event generates several pieces of data, some provided by the user and some automatically extracted. Let's examine the user-defined data first:","category":"page"},{"location":"stdlib/Logging/","page":"日志记录","title":"日志记录","text":"The log level is a broad category for the message that is used for early filtering. There are several standard levels of type LogLevel; user-defined levels are also possible. Each is distinct in purpose:\nLogging.Debug (log level -1000) is information intended for the developer of the program. These events are disabled by default.\nLogging.Info (log level 0) is for general information to the user. Think of it as an alternative to using println directly.\nLogging.Warn (log level 1000) means something is wrong and action is likely required but that for now the program is still working.\nLogging.Error (log level 2000) means something is wrong and it is unlikely to be recovered, at least by this part of the code. Often this log-level is unneeded as throwing an exception can convey all the required information.\nThe message is an object describing the event. By convention AbstractStrings passed as messages are assumed to be in markdown format. Other types will be displayed using print(io, obj) or string(obj) for text-based output and possibly show(io,mime,obj) for other multimedia displays used in the installed logger.\nOptional key–value pairs allow arbitrary data to be attached to each event. Some keys have conventional meaning that can affect the way an event is interpreted (see @logmsg).","category":"page"},{"location":"stdlib/Logging/","page":"日志记录","title":"日志记录","text":"The system also generates some standard information for each event:","category":"page"},{"location":"stdlib/Logging/","page":"日志记录","title":"日志记录","text":"The module in which the logging macro was expanded.\nThe file and line where the logging macro occurs in the source code.\nA message id that is a unique, fixed identifier for the source code statement where the logging macro appears. This identifier is designed to be fairly stable even if the source code of the file changes, as long as the logging statement itself remains the same.\nA group for the event, which is set to the base name of the file by default, without extension. This can be used to group messages into categories more finely than the log level (for example, all deprecation warnings have group :depwarn), or into logical groupings across or within modules.","category":"page"},{"location":"stdlib/Logging/","page":"日志记录","title":"日志记录","text":"Notice that some useful information such as the event time is not included by default. This is because such information can be expensive to extract and is also dynamically available to the current logger. It's simple to define a custom logger to augment event data with the time, backtrace, values of global variables and other useful information as required.","category":"page"},{"location":"stdlib/Logging/#Processing-log-events","page":"日志记录","title":"Processing log events","text":"","category":"section"},{"location":"stdlib/Logging/","page":"日志记录","title":"日志记录","text":"As you can see in the examples, logging statements make no mention of where log events go or how they are processed. This is a key design feature that makes the system composable and natural for concurrent use. It does this by separating two different concerns:","category":"page"},{"location":"stdlib/Logging/","page":"日志记录","title":"日志记录","text":"Creating log events is the concern of the module author who needs to decide where events are triggered and which information to include.\nProcessing of log events — that is, display, filtering, aggregation and recording — is the concern of the application author who needs to bring multiple modules together into a cooperating application.","category":"page"},{"location":"stdlib/Logging/#Loggers","page":"日志记录","title":"Loggers","text":"","category":"section"},{"location":"stdlib/Logging/","page":"日志记录","title":"日志记录","text":"Processing of events is performed by a logger, which is the first piece of user configurable code to see the event. All loggers must be subtypes of AbstractLogger.","category":"page"},{"location":"stdlib/Logging/","page":"日志记录","title":"日志记录","text":"When an event is triggered, the appropriate logger is found by looking for a task-local logger with the global logger as fallback. The idea here is that the application code knows how log events should be processed and exists somewhere at the top of the call stack. So we should look up through the call stack to discover the logger — that is, the logger should be dynamically scoped. (This is a point of contrast with logging frameworks where the logger is lexically scoped; provided explicitly by the module author or as a simple global variable. In such a system it's awkward to control logging while composing functionality from multiple modules.)","category":"page"},{"location":"stdlib/Logging/","page":"日志记录","title":"日志记录","text":"The global logger may be set with global_logger, and task-local loggers controlled using with_logger. Newly spawned tasks inherit the logger of the parent task.","category":"page"},{"location":"stdlib/Logging/","page":"日志记录","title":"日志记录","text":"There are three logger types provided by the library. ConsoleLogger is the default logger you see when starting the REPL. It displays events in a readable text format and tries to give simple but user friendly control over formatting and filtering. NullLogger is a convenient way to drop all messages where necessary; it is the logging equivalent of the devnull stream. SimpleLogger is a very simplistic text formatting logger, mainly useful for debugging the logging system itself.","category":"page"},{"location":"stdlib/Logging/","page":"日志记录","title":"日志记录","text":"Custom loggers should come with overloads for the functions described in the reference section.","category":"page"},{"location":"stdlib/Logging/#Early-filtering-and-message-handling","page":"日志记录","title":"Early filtering and message handling","text":"","category":"section"},{"location":"stdlib/Logging/","page":"日志记录","title":"日志记录","text":"When an event occurs, a few steps of early filtering occur to avoid generating messages that will be discarded:","category":"page"},{"location":"stdlib/Logging/","page":"日志记录","title":"日志记录","text":"The message log level is checked against a global minimum level (set via disable_logging). This is a crude but extremely cheap global setting.\nThe current logger state is looked up and the message level checked against the logger's cached minimum level, as found by calling Logging.min_enabled_level. This behavior can be overridden via environment variables (more on this later).\nThe Logging.shouldlog function is called with the current logger, taking some minimal information (level, module, group, id) which can be computed statically. Most usefully, shouldlog is passed an event id which can be used to discard events early based on a cached predicate.","category":"page"},{"location":"stdlib/Logging/","page":"日志记录","title":"日志记录","text":"If all these checks pass, the message and key–value pairs are evaluated in full and passed to the current logger via the Logging.handle_message function. handle_message() may perform additional filtering as required and display the event to the screen, save it to a file, etc.","category":"page"},{"location":"stdlib/Logging/","page":"日志记录","title":"日志记录","text":"Exceptions that occur while generating the log event are captured and logged by default. This prevents individual broken events from crashing the application, which is helpful when enabling little-used debug events in a production system. This behavior can be customized per logger type by extending Logging.catch_exceptions.","category":"page"},{"location":"stdlib/Logging/#Testing-log-events","page":"日志记录","title":"Testing log events","text":"","category":"section"},{"location":"stdlib/Logging/","page":"日志记录","title":"日志记录","text":"Log events are a side effect of running normal code, but you might find yourself wanting to test particular informational messages and warnings. The Test module provides a @test_logs macro that can be used to pattern match against the log event stream.","category":"page"},{"location":"stdlib/Logging/#Environment-variables","page":"日志记录","title":"Environment variables","text":"","category":"section"},{"location":"stdlib/Logging/","page":"日志记录","title":"日志记录","text":"Message filtering can be influenced through the JULIA_DEBUG environment variable, and serves as an easy way to enable debug logging for a file or module. For example, loading julia with JULIA_DEBUG=loading will activate @debug log messages in loading.jl:","category":"page"},{"location":"stdlib/Logging/","page":"日志记录","title":"日志记录","text":"$ JULIA_DEBUG=loading julia -e 'using OhMyREPL'\n┌ Debug: Rejecting cache file /home/user/.julia/compiled/v0.7/OhMyREPL.ji due to it containing an invalid cache header\n└ @ Base loading.jl:1328\n[ Info: Recompiling stale cache file /home/user/.julia/compiled/v0.7/OhMyREPL.ji for module OhMyREPL\n┌ Debug: Rejecting cache file /home/user/.julia/compiled/v0.7/Tokenize.ji due to it containing an invalid cache header\n└ @ Base loading.jl:1328\n...","category":"page"},{"location":"stdlib/Logging/","page":"日志记录","title":"日志记录","text":"Similarly, the environment variable can be used to enable debug logging of modules, such as Pkg, or module roots (see Base.moduleroot). To enable all debug logging, use the special value all.","category":"page"},{"location":"stdlib/Logging/","page":"日志记录","title":"日志记录","text":"To turn debug logging on from the REPL, set ENV[\"JULIA_DEBUG\"] to the name of the module of interest. Functions defined in the REPL belong to module Main; logging for them can be enabled like this:","category":"page"},{"location":"stdlib/Logging/","page":"日志记录","title":"日志记录","text":"julia> foo() = @debug \"foo\"\nfoo (generic function with 1 method)\n\njulia> foo()\n\njulia> ENV[\"JULIA_DEBUG\"] = Main\nMain\n\njulia> foo()\n┌ Debug: foo\n└ @ Main REPL[1]:1\n","category":"page"},{"location":"stdlib/Logging/#Examples","page":"日志记录","title":"Examples","text":"","category":"section"},{"location":"stdlib/Logging/#Example:-Writing-log-events-to-a-file","page":"日志记录","title":"Example: Writing log events to a file","text":"","category":"section"},{"location":"stdlib/Logging/","page":"日志记录","title":"日志记录","text":"Sometimes it can be useful to write log events to a file. Here is an example of how to use a task-local and global logger to write information to a text file:","category":"page"},{"location":"stdlib/Logging/","page":"日志记录","title":"日志记录","text":"# Load the logging module\njulia> using Logging\n\n# Open a textfile for writing\njulia> io = open(\"log.txt\", \"w+\")\nIOStream()\n\n# Create a simple logger\njulia> logger = SimpleLogger(io)\nSimpleLogger(IOStream(), Info, Dict{Any,Int64}())\n\n# Log a task-specific message\njulia> with_logger(logger) do\n @info(\"a context specific log message\")\n end\n\n# Write all buffered messages to the file\njulia> flush(io)\n\n# Set the global logger to logger\njulia> global_logger(logger)\nSimpleLogger(IOStream(), Info, Dict{Any,Int64}())\n\n# This message will now also be written to the file\njulia> @info(\"a global log message\")\n\n# Close the file\njulia> close(io)","category":"page"},{"location":"stdlib/Logging/#Example:-Enable-debug-level-messages","page":"日志记录","title":"Example: Enable debug-level messages","text":"","category":"section"},{"location":"stdlib/Logging/","page":"日志记录","title":"日志记录","text":"Here is an example of creating a ConsoleLogger that lets through any messages with log level higher than, or equal, to Logging.Debug.","category":"page"},{"location":"stdlib/Logging/","page":"日志记录","title":"日志记录","text":"julia> using Logging\n\n# Create a ConsoleLogger that prints any log messages with level >= Debug to stderr\njulia> debuglogger = ConsoleLogger(stderr, Logging.Debug)\n\n# Enable debuglogger for a task\njulia> with_logger(debuglogger) do\n @debug \"a context specific log message\"\n end\n\n# Set the global logger\njulia> global_logger(debuglogger)","category":"page"},{"location":"stdlib/Logging/#Reference","page":"日志记录","title":"Reference","text":"","category":"section"},{"location":"stdlib/Logging/#Logging-module","page":"日志记录","title":"Logging module","text":"","category":"section"},{"location":"stdlib/Logging/","page":"日志记录","title":"日志记录","text":"Logging.Logging","category":"page"},{"location":"stdlib/Logging/#Logging.Logging","page":"日志记录","title":"Logging.Logging","text":"Utilities for capturing, filtering and presenting streams of log events. Normally you don't need to import Logging to create log events; for this the standard logging macros such as @info are already exported by Base and available by default.\n\n\n\n\n\n","category":"module"},{"location":"stdlib/Logging/#Creating-events","page":"日志记录","title":"Creating events","text":"","category":"section"},{"location":"stdlib/Logging/","page":"日志记录","title":"日志记录","text":"Logging.@logmsg\nLogging.LogLevel\nLogging.Debug\nLogging.Info\nLogging.Warn\nLogging.Error","category":"page"},{"location":"stdlib/Logging/#Logging.@logmsg","page":"日志记录","title":"Logging.@logmsg","text":"@debug message [key=value | value ...]\n@info message [key=value | value ...]\n@warn message [key=value | value ...]\n@error message [key=value | value ...]\n\n@logmsg level message [key=value | value ...]\n\nCreate a log record with an informational message. For convenience, four logging macros @debug, @info, @warn and @error are defined which log at the standard severity levels Debug, Info, Warn and Error. @logmsg allows level to be set programmatically to any LogLevel or custom log level types.\n\nmessage should be an expression which evaluates to a string which is a human readable description of the log event. By convention, this string will be formatted as markdown when presented.\n\nThe optional list of key=value pairs supports arbitrary user defined metadata which will be passed through to the logging backend as part of the log record. If only a value expression is supplied, a key representing the expression will be generated using Symbol. For example, x becomes x=x, and foo(10) becomes Symbol(\"foo(10)\")=foo(10). For splatting a list of key value pairs, use the normal splatting syntax, @info \"blah\" kws....\n\nThere are some keys which allow automatically generated log data to be overridden:\n\n_module=mod can be used to specify a different originating module from the source location of the message.\n_group=symbol can be used to override the message group (this is normally derived from the base name of the source file).\n_id=symbol can be used to override the automatically generated unique message identifier. This is useful if you need to very closely associate messages generated on different source lines.\n_file=string and _line=integer can be used to override the apparent source location of a log message.\n\nThere's also some key value pairs which have conventional meaning:\n\nmaxlog=integer should be used as a hint to the backend that the message should be displayed no more than maxlog times.\nexception=ex should be used to transport an exception with a log message, often used with @error. An associated backtrace bt may be attached using the tuple exception=(ex,bt).\n\nExamples\n\n@debug \"Verbose debugging information. Invisible by default\"\n@info \"An informational message\"\n@warn \"Something was odd. You should pay attention\"\n@error \"A non fatal error occurred\"\n\nx = 10\n@info \"Some variables attached to the message\" x a=42.0\n\n@debug begin\n sA = sum(A)\n \"sum(A) = $sA is an expensive operation, evaluated only when `shouldlog` returns true\"\nend\n\nfor i=1:10000\n @info \"With the default backend, you will only see (i = $i) ten times\" maxlog=10\n @debug \"Algorithm1\" i progress=i/10000\nend\n\n\n\n\n\n","category":"macro"},{"location":"stdlib/Logging/#Logging.LogLevel","page":"日志记录","title":"Logging.LogLevel","text":"LogLevel(level)\n\nSeverity/verbosity of a log record.\n\nThe log level provides a key against which potential log records may be filtered, before any other work is done to construct the log record data structure itself.\n\nExamples\n\njulia> Logging.LogLevel(0) == Logging.Info\ntrue\n\n\n\n\n\n","category":"type"},{"location":"stdlib/Logging/#Logging.Debug","page":"日志记录","title":"Logging.Debug","text":"Debug\n\nAlias for LogLevel(-1000).\n\n\n\n\n\n","category":"constant"},{"location":"stdlib/Logging/#Logging.Info","page":"日志记录","title":"Logging.Info","text":"Info\n\nAlias for LogLevel(0).\n\n\n\n\n\n","category":"constant"},{"location":"stdlib/Logging/#Logging.Warn","page":"日志记录","title":"Logging.Warn","text":"Warn\n\nAlias for LogLevel(1000).\n\n\n\n\n\n","category":"constant"},{"location":"stdlib/Logging/#Logging.Error","page":"日志记录","title":"Logging.Error","text":"Error\n\nAlias for LogLevel(2000).\n\n\n\n\n\n","category":"constant"},{"location":"stdlib/Logging/#AbstractLogger-interface","page":"日志记录","title":"Processing events with AbstractLogger","text":"","category":"section"},{"location":"stdlib/Logging/","page":"日志记录","title":"日志记录","text":"Event processing is controlled by overriding functions associated with AbstractLogger:","category":"page"},{"location":"stdlib/Logging/","page":"日志记录","title":"日志记录","text":"Methods to implement Brief description\nLogging.handle_message Handle a log event\nLogging.shouldlog Early filtering of events\nLogging.min_enabled_level Lower bound for log level of accepted events\nOptional methods Default definition Brief description\nLogging.catch_exceptions true Catch exceptions during event evaluation","category":"page"},{"location":"stdlib/Logging/","page":"日志记录","title":"日志记录","text":"Logging.AbstractLogger\nLogging.handle_message\nLogging.shouldlog\nLogging.min_enabled_level\nLogging.catch_exceptions\nLogging.disable_logging","category":"page"},{"location":"stdlib/Logging/#Logging.AbstractLogger","page":"日志记录","title":"Logging.AbstractLogger","text":"A logger controls how log records are filtered and dispatched. When a log record is generated, the logger is the first piece of user configurable code which gets to inspect the record and decide what to do with it.\n\n\n\n\n\n","category":"type"},{"location":"stdlib/Logging/#Logging.handle_message","page":"日志记录","title":"Logging.handle_message","text":"handle_message(logger, level, message, _module, group, id, file, line; key1=val1, ...)\n\nLog a message to logger at level. The logical location at which the message was generated is given by module _module and group; the source location by file and line. id is an arbitrary unique value (typically a Symbol) to be used as a key to identify the log statement when filtering.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/Logging/#Logging.shouldlog","page":"日志记录","title":"Logging.shouldlog","text":"shouldlog(logger, level, _module, group, id)\n\nReturn true when logger accepts a message at level, generated for _module, group and with unique log identifier id.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/Logging/#Logging.min_enabled_level","page":"日志记录","title":"Logging.min_enabled_level","text":"min_enabled_level(logger)\n\nReturn the minimum enabled level for logger for early filtering. That is, the log level below or equal to which all messages are filtered.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/Logging/#Logging.catch_exceptions","page":"日志记录","title":"Logging.catch_exceptions","text":"catch_exceptions(logger)\n\nReturn true if the logger should catch exceptions which happen during log record construction. By default, messages are caught\n\nBy default all exceptions are caught to prevent log message generation from crashing the program. This lets users confidently toggle little-used functionality - such as debug logging - in a production system.\n\nIf you want to use logging as an audit trail you should disable this for your logger type.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/Logging/#Logging.disable_logging","page":"日志记录","title":"Logging.disable_logging","text":"disable_logging(level)\n\nDisable all log messages at log levels equal to or less than level. This is a global setting, intended to make debug logging extremely cheap when disabled.\n\nExamples\n\nLogging.disable_logging(Logging.Info) # Disable debug and info\n\n\n\n\n\n","category":"function"},{"location":"stdlib/Logging/#Using-Loggers","page":"日志记录","title":"Using Loggers","text":"","category":"section"},{"location":"stdlib/Logging/","page":"日志记录","title":"日志记录","text":"Logger installation and inspection:","category":"page"},{"location":"stdlib/Logging/","page":"日志记录","title":"日志记录","text":"Logging.global_logger\nLogging.with_logger\nLogging.current_logger","category":"page"},{"location":"stdlib/Logging/#Logging.global_logger","page":"日志记录","title":"Logging.global_logger","text":"global_logger()\n\nReturn the global logger, used to receive messages when no specific logger exists for the current task.\n\nglobal_logger(logger)\n\nSet the global logger to logger, and return the previous global logger.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/Logging/#Logging.with_logger","page":"日志记录","title":"Logging.with_logger","text":"with_logger(function, logger)\n\nExecute function, directing all log messages to logger.\n\nExample\n\nfunction test(x)\n @info \"x = $x\"\nend\n\nwith_logger(logger) do\n test(1)\n test([1,2])\nend\n\n\n\n\n\n","category":"function"},{"location":"stdlib/Logging/#Logging.current_logger","page":"日志记录","title":"Logging.current_logger","text":"current_logger()\n\nReturn the logger for the current task, or the global logger if none is attached to the task.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/Logging/","page":"日志记录","title":"日志记录","text":"Loggers that are supplied with the system:","category":"page"},{"location":"stdlib/Logging/","page":"日志记录","title":"日志记录","text":"Logging.NullLogger\nLogging.ConsoleLogger\nLogging.SimpleLogger","category":"page"},{"location":"stdlib/Logging/#Logging.NullLogger","page":"日志记录","title":"Logging.NullLogger","text":"NullLogger()\n\nLogger which disables all messages and produces no output - the logger equivalent of /dev/null.\n\n\n\n\n\n","category":"type"},{"location":"stdlib/Logging/#Logging.ConsoleLogger","page":"日志记录","title":"Logging.ConsoleLogger","text":"ConsoleLogger([stream,] min_level=Info; meta_formatter=default_metafmt,\n show_limited=true, right_justify=0)\n\nLogger with formatting optimized for readability in a text console, for example interactive work with the Julia REPL.\n\nLog levels less than min_level are filtered out.\n\nMessage formatting can be controlled by setting keyword arguments:\n\nmeta_formatter is a function which takes the log event metadata (level, _module, group, id, file, line) and returns a color (as would be passed to printstyled), prefix and suffix for the log message. The default is to prefix with the log level and a suffix containing the module, file and line location.\nshow_limited limits the printing of large data structures to something which can fit on the screen by setting the :limit IOContext key during formatting.\nright_justify is the integer column which log metadata is right justified at. The default is zero (metadata goes on its own line).\n\n\n\n\n\n","category":"type"},{"location":"stdlib/Logging/#Logging.SimpleLogger","page":"日志记录","title":"Logging.SimpleLogger","text":"SimpleLogger([stream,] min_level=Info)\n\nSimplistic logger for logging all messages with level greater than or equal to min_level to stream. If stream is closed then messages with log level greater or equal to Warn will be logged to stderr and below to stdout.\n\n\n\n\n\n","category":"type"},{"location":"devdocs/valgrind/#在Julia中使用Valgrind","page":"在Julia中使用Valgrind","title":"在Julia中使用Valgrind","text":"","category":"section"},{"location":"devdocs/valgrind/","page":"在Julia中使用Valgrind","title":"在Julia中使用Valgrind","text":"Valgrind is a tool for memory debugging, memory leak detection, and profiling. This section describes things to keep in mind when using Valgrind to debug memory issues with Julia.","category":"page"},{"location":"devdocs/valgrind/#General-considerations","page":"在Julia中使用Valgrind","title":"General considerations","text":"","category":"section"},{"location":"devdocs/valgrind/","page":"在Julia中使用Valgrind","title":"在Julia中使用Valgrind","text":"By default, Valgrind assumes that there is no self modifying code in the programs it runs. This assumption works fine in most instances but fails miserably for a just-in-time compiler like julia. For this reason it is crucial to pass --smc-check=all-non-file to valgrind, else code may crash or behave unexpectedly (often in subtle ways).","category":"page"},{"location":"devdocs/valgrind/","page":"在Julia中使用Valgrind","title":"在Julia中使用Valgrind","text":"In some cases, to better detect memory errors using Valgrind it can help to compile julia with memory pools disabled. The compile-time flag MEMDEBUG disables memory pools in Julia, and MEMDEBUG2 disables memory pools in FemtoLisp. To build julia with both flags, add the following line to Make.user:","category":"page"},{"location":"devdocs/valgrind/","page":"在Julia中使用Valgrind","title":"在Julia中使用Valgrind","text":"CFLAGS = -DMEMDEBUG -DMEMDEBUG2","category":"page"},{"location":"devdocs/valgrind/","page":"在Julia中使用Valgrind","title":"在Julia中使用Valgrind","text":"Another thing to note: if your program uses multiple workers processes, it is likely that you want all such worker processes to run under Valgrind, not just the parent process. To do this, pass --trace-children=yes to valgrind.","category":"page"},{"location":"devdocs/valgrind/#Suppressions","page":"在Julia中使用Valgrind","title":"Suppressions","text":"","category":"section"},{"location":"devdocs/valgrind/","page":"在Julia中使用Valgrind","title":"在Julia中使用Valgrind","text":"Valgrind will typically display spurious warnings as it runs. To reduce the number of such warnings, it helps to provide a suppressions file to Valgrind. A sample suppressions file is included in the Julia source distribution at contrib/valgrind-julia.supp.","category":"page"},{"location":"devdocs/valgrind/","page":"在Julia中使用Valgrind","title":"在Julia中使用Valgrind","text":"The suppressions file can be used from the julia/ source directory as follows:","category":"page"},{"location":"devdocs/valgrind/","page":"在Julia中使用Valgrind","title":"在Julia中使用Valgrind","text":"$ valgrind --smc-check=all-non-file --suppressions=contrib/valgrind-julia.supp ./julia progname.jl","category":"page"},{"location":"devdocs/valgrind/","page":"在Julia中使用Valgrind","title":"在Julia中使用Valgrind","text":"Any memory errors that are displayed should either be reported as bugs or contributed as additional suppressions. Note that some versions of Valgrind are shipped with insufficient default suppressions, so that may be one thing to consider before submitting any bugs.","category":"page"},{"location":"devdocs/valgrind/#Running-the-Julia-test-suite-under-Valgrind","page":"在Julia中使用Valgrind","title":"Running the Julia test suite under Valgrind","text":"","category":"section"},{"location":"devdocs/valgrind/","page":"在Julia中使用Valgrind","title":"在Julia中使用Valgrind","text":"It is possible to run the entire Julia test suite under Valgrind, but it does take quite some time (typically several hours). To do so, run the following command from the julia/test/ directory:","category":"page"},{"location":"devdocs/valgrind/","page":"在Julia中使用Valgrind","title":"在Julia中使用Valgrind","text":"valgrind --smc-check=all-non-file --trace-children=yes --suppressions=$PWD/../contrib/valgrind-julia.supp ../julia runtests.jl all","category":"page"},{"location":"devdocs/valgrind/","page":"在Julia中使用Valgrind","title":"在Julia中使用Valgrind","text":"If you would like to see a report of \"definite\" memory leaks, pass the flags --leak-check=full --show-leak-kinds=definite to valgrind as well.","category":"page"},{"location":"devdocs/valgrind/#Caveats","page":"在Julia中使用Valgrind","title":"Caveats","text":"","category":"section"},{"location":"devdocs/valgrind/","page":"在Julia中使用Valgrind","title":"在Julia中使用Valgrind","text":"Valgrind currently does not support multiple rounding modes, so code that adjusts the rounding mode will behave differently when run under Valgrind.","category":"page"},{"location":"devdocs/valgrind/","page":"在Julia中使用Valgrind","title":"在Julia中使用Valgrind","text":"In general, if after setting --smc-check=all-non-file you find that your program behaves differently when run under Valgrind, it may help to pass --tool=none to valgrind as you investigate further. This will enable the minimal Valgrind machinery but will also run much faster than when the full memory checker is enabled.","category":"page"},{"location":"manual/metaprogramming/#Metaprogramming","page":"元编程","title":"元编程","text":"","category":"section"},{"location":"manual/metaprogramming/","page":"元编程","title":"元编程","text":"Lisp 留给 Julia 最大的遗产就是它的元编程支持。和 Lisp 一样,Julia 把自己的代码表示为语言中的数据结构。既然代码被表示为了可以在语言中创建和操作的对象,程序就可以变换和生成自己的代码。这允许在没有额外构建步骤的情况下生成复杂的代码,并且还允许在 abstract syntax trees 级别上运行的真正的 Lisp 风格的宏。与之相对的是预处理器“宏”系统,比如 C 和 C++ 中的,它们在解析和解释代码之前进行文本操作和变换。由于 Julia 中的所有数据类型和代码都被表示为 Julia 的 数据结构,强大的 reflection 功能可用于探索程序的内部及其类型,就像任何其他数据一样。","category":"page"},{"location":"manual/metaprogramming/#程序表示","page":"元编程","title":"程序表示","text":"","category":"section"},{"location":"manual/metaprogramming/","page":"元编程","title":"元编程","text":"每个 Julia 程序均以字符串开始:","category":"page"},{"location":"manual/metaprogramming/","page":"元编程","title":"元编程","text":"julia> prog = \"1 + 1\"\n\"1 + 1\"","category":"page"},{"location":"manual/metaprogramming/","page":"元编程","title":"元编程","text":"接下来会发生什么?","category":"page"},{"location":"manual/metaprogramming/","page":"元编程","title":"元编程","text":"下一步是 parse 每个字符串到一个称为表达式的对象,由 Julia 的类型 Expr 表示:","category":"page"},{"location":"manual/metaprogramming/","page":"元编程","title":"元编程","text":"julia> ex1 = Meta.parse(prog)\n:(1 + 1)\n\njulia> typeof(ex1)\nExpr","category":"page"},{"location":"manual/metaprogramming/","page":"元编程","title":"元编程","text":"Expr 对象包含两个部分:","category":"page"},{"location":"manual/metaprogramming/","page":"元编程","title":"元编程","text":"一个标识表达式类型的 Symbol。","category":"page"},{"location":"manual/metaprogramming/","page":"元编程","title":"元编程","text":"Symbol 就是一个 interned string 标识符(下面会有更多讨论)","category":"page"},{"location":"manual/metaprogramming/","page":"元编程","title":"元编程","text":"julia> ex1.head\n:call","category":"page"},{"location":"manual/metaprogramming/","page":"元编程","title":"元编程","text":"表达式的参数,可能是符号、其他表达式或字面量:","category":"page"},{"location":"manual/metaprogramming/","page":"元编程","title":"元编程","text":"julia> ex1.args\n3-element Vector{Any}:\n :+\n 1\n 1","category":"page"},{"location":"manual/metaprogramming/","page":"元编程","title":"元编程","text":"表达式也可能直接用 prefix notation 构造:","category":"page"},{"location":"manual/metaprogramming/","page":"元编程","title":"元编程","text":"julia> ex2 = Expr(:call, :+, 1, 1)\n:(1 + 1)","category":"page"},{"location":"manual/metaprogramming/","page":"元编程","title":"元编程","text":"上面构造的两个表达式 – 一个通过解析构造一个通过直接构造 – 是等价的:","category":"page"},{"location":"manual/metaprogramming/","page":"元编程","title":"元编程","text":"julia> ex1 == ex2\ntrue","category":"page"},{"location":"manual/metaprogramming/","page":"元编程","title":"元编程","text":"这里的关键点是 Julia 的代码在内部表示为可以从语言本身访问的数据结构","category":"page"},{"location":"manual/metaprogramming/","page":"元编程","title":"元编程","text":"函数 dump 可以带有缩进和注释地显示 Expr 对象:","category":"page"},{"location":"manual/metaprogramming/","page":"元编程","title":"元编程","text":"julia> dump(ex2)\nExpr\n head: Symbol call\n args: Array{Any}((3,))\n 1: Symbol +\n 2: Int64 1\n 3: Int64 1","category":"page"},{"location":"manual/metaprogramming/","page":"元编程","title":"元编程","text":"Expr 对象也可以嵌套:","category":"page"},{"location":"manual/metaprogramming/","page":"元编程","title":"元编程","text":"julia> ex3 = Meta.parse(\"(4 + 4) / 2\")\n:((4 + 4) / 2)","category":"page"},{"location":"manual/metaprogramming/","page":"元编程","title":"元编程","text":"另外一个查看表达式的方法是使用 Meta.show_sexpr,它能显示给定 Expr 的 S-expression,对 Lisp 用户来说,这看着很熟悉。下面是一个示例,阐释了如何显示嵌套的 Expr:","category":"page"},{"location":"manual/metaprogramming/","page":"元编程","title":"元编程","text":"julia> Meta.show_sexpr(ex3)\n(:call, :/, (:call, :+, 4, 4), 2)","category":"page"},{"location":"manual/metaprogramming/#符号","page":"元编程","title":"符号","text":"","category":"section"},{"location":"manual/metaprogramming/","page":"元编程","title":"元编程","text":"字符 : 在 Julia 中有两个作用。第一种形式构造一个 Symbol,这是作为表达式组成部分的一个 interned string:","category":"page"},{"location":"manual/metaprogramming/","page":"元编程","title":"元编程","text":"julia> s = :foo\n:foo\n\njulia> typeof(s)\nSymbol","category":"page"},{"location":"manual/metaprogramming/","page":"元编程","title":"元编程","text":"构造函数 Symbol 接受任意数量的参数并通过把它们的字符串表示连在一起创建一个新的符号:","category":"page"},{"location":"manual/metaprogramming/","page":"元编程","title":"元编程","text":"julia> :foo == Symbol(\"foo\")\ntrue\n\njulia> Symbol(\"func\",10)\n:func10\n\njulia> Symbol(:var,'_',\"sym\")\n:var_sym","category":"page"},{"location":"manual/metaprogramming/","page":"元编程","title":"元编程","text":"注意,要使用 : 语法,符号的名称必须是有效的标识符。否则,必须使用 Symbol(str) 构造函数。","category":"page"},{"location":"manual/metaprogramming/","page":"元编程","title":"元编程","text":"在表达式的上下文中,符号用来表示对变量的访问;当一个表达式被求值时,符号会被替换为这个符号在合适的 scope 中所绑定的值。","category":"page"},{"location":"manual/metaprogramming/","page":"元编程","title":"元编程","text":"有时需要在 : 的参数两边加上额外的括号,以避免在解析时出现歧义:","category":"page"},{"location":"manual/metaprogramming/","page":"元编程","title":"元编程","text":"julia> :(:)\n:(:)\n\njulia> :(::)\n:(::)","category":"page"},{"location":"manual/metaprogramming/#表达式与求值","page":"元编程","title":"表达式与求值","text":"","category":"section"},{"location":"manual/metaprogramming/#引用","page":"元编程","title":"引用","text":"","category":"section"},{"location":"manual/metaprogramming/","page":"元编程","title":"元编程","text":": 的第二个语义是不显式调用 Expr 构造器来创建表达式对象。这被称为引用。: 后面跟着包围着单个 Julia 语句括号,可以基于被包围的代码生成一个 Expr 对象。下面是一个引用算数表达式的例子:","category":"page"},{"location":"manual/metaprogramming/","page":"元编程","title":"元编程","text":"julia> ex = :(a+b*c+1)\n:(a + b * c + 1)\n\njulia> typeof(ex)\nExpr","category":"page"},{"location":"manual/metaprogramming/","page":"元编程","title":"元编程","text":"(为了查看这个表达式的结构,可以试一试 ex.head 和 ex.args,或者使用 dump 同时查看 ex.head 和 ex.args 或者 Meta.@dump)","category":"page"},{"location":"manual/metaprogramming/","page":"元编程","title":"元编程","text":"注意等价的表达式也可以使用 Meta.parse 或者直接用 Expr 构造:","category":"page"},{"location":"manual/metaprogramming/","page":"元编程","title":"元编程","text":"julia> :(a + b*c + 1) ==\n Meta.parse(\"a + b*c + 1\") ==\n Expr(:call, :+, :a, Expr(:call, :*, :b, :c), 1)\ntrue","category":"page"},{"location":"manual/metaprogramming/","page":"元编程","title":"元编程","text":"解析器提供的表达式通常只有符号、其它表达式和字面量值作为其参数,而由 Julia 代码构造的表达式能以非字面量形式的任意运行期值作为其参数。在此特例中,+ 和 a 都是符号,*(b,c) 是子表达式,而 1 是 64 位带符号整数字面量。","category":"page"},{"location":"manual/metaprogramming/","page":"元编程","title":"元编程","text":"引用多个表达式有第二种语法形式:在 quote ... end 中包含代码块。","category":"page"},{"location":"manual/metaprogramming/","page":"元编程","title":"元编程","text":"julia> ex = quote\n x = 1\n y = 2\n x + y\n end\nquote\n #= none:2 =#\n x = 1\n #= none:3 =#\n y = 2\n #= none:4 =#\n x + y\nend\n\njulia> typeof(ex)\nExpr","category":"page"},{"location":"manual/metaprogramming/#man-expression-interpolation","page":"元编程","title":"插值","text":"","category":"section"},{"location":"manual/metaprogramming/","page":"元编程","title":"元编程","text":"使用值参数直接构造 Expr 对象虽然很强大,但与「通常的」 Julia 语法相比,Expr 构造函数可能让人觉得乏味。作为替代方法,Julia 允许将字面量或表达式插入到被引用的表达式中。表达式插值由前缀 $ 表示。","category":"page"},{"location":"manual/metaprogramming/","page":"元编程","title":"元编程","text":"在此示例中,插入了变量 a 的值:","category":"page"},{"location":"manual/metaprogramming/","page":"元编程","title":"元编程","text":"julia> a = 1;\n\njulia> ex = :($a + b)\n:(1 + b)","category":"page"},{"location":"manual/metaprogramming/","page":"元编程","title":"元编程","text":"对未被引用的表达式进行插值是不支持的,这会导致编译期错误:","category":"page"},{"location":"manual/metaprogramming/","page":"元编程","title":"元编程","text":"julia> $a + b\nERROR: syntax: \"$\" expression outside quote","category":"page"},{"location":"manual/metaprogramming/","page":"元编程","title":"元编程","text":"在此示例中,元组 (1,2,3) 作为表达式插入到条件测试中:","category":"page"},{"location":"manual/metaprogramming/","page":"元编程","title":"元编程","text":"julia> ex = :(a in $:((1,2,3)) )\n:(a in (1, 2, 3))","category":"page"},{"location":"manual/metaprogramming/","page":"元编程","title":"元编程","text":"在表达式插值中使用 $ 是有意让人联想到字符串插值和命令插值。表达式插值使得复杂 Julia 表达式的程序化构造变得方便和易读。","category":"page"},{"location":"manual/metaprogramming/#Splatting-插值","page":"元编程","title":"Splatting 插值","text":"","category":"section"},{"location":"manual/metaprogramming/","page":"元编程","title":"元编程","text":"请注意,$ 插值语法只允许插入单个表达式到包含它的表达式中。有时,你手头有个由表达式组成的数组,需要它们都变成其所处表达式的参数,而这可通过 $(xs...) 语法做到。例如,下面的代码生成了一个函数调用,其参数数量通过编程确定:","category":"page"},{"location":"manual/metaprogramming/","page":"元编程","title":"元编程","text":"julia> args = [:x, :y, :z];\n\njulia> :(f(1, $(args...)))\n:(f(1, x, y, z))","category":"page"},{"location":"manual/metaprogramming/#嵌套引用","page":"元编程","title":"嵌套引用","text":"","category":"section"},{"location":"manual/metaprogramming/","page":"元编程","title":"元编程","text":"自然地,引用表达式可以包含在其它引用表达式中。插值在这些情形中的工作方式可能会有点难以理解。考虑这个例子:","category":"page"},{"location":"manual/metaprogramming/","page":"元编程","title":"元编程","text":"julia> x = :(1 + 2);\n\njulia> e = quote quote $x end end\nquote\n #= none:1 =#\n $(Expr(:quote, quote\n #= none:1 =#\n $(Expr(:$, :x))\nend))\nend","category":"page"},{"location":"manual/metaprogramming/","page":"元编程","title":"元编程","text":"Notice that the result contains $x, which means that x has not been evaluated yet. In other words, the $ expression \"belongs to\" the inner quote expression, and so its argument is only evaluated when the inner quote expression is:","category":"page"},{"location":"manual/metaprogramming/","page":"元编程","title":"元编程","text":"julia> eval(e)\nquote\n #= none:1 =#\n 1 + 2\nend","category":"page"},{"location":"manual/metaprogramming/","page":"元编程","title":"元编程","text":"但是,外部 quote 表达式可以把值插入到内部引用表达式的 $ 中去。这通过多个 $ 实现:","category":"page"},{"location":"manual/metaprogramming/","page":"元编程","title":"元编程","text":"julia> e = quote quote $$x end end\nquote\n #= none:1 =#\n $(Expr(:quote, quote\n #= none:1 =#\n $(Expr(:$, :(1 + 2)))\nend))\nend","category":"page"},{"location":"manual/metaprogramming/","page":"元编程","title":"元编程","text":"Notice that (1 + 2) now appears in the result instead of the symbol x. Evaluating this expression yields an interpolated 3:","category":"page"},{"location":"manual/metaprogramming/","page":"元编程","title":"元编程","text":"julia> eval(e)\nquote\n #= none:1 =#\n 3\nend","category":"page"},{"location":"manual/metaprogramming/","page":"元编程","title":"元编程","text":"这种行为背后的直觉是每个 $ 都将 x 求值一遍:一个 $ 工作方式类似于 eval(:x),其返回 x 的值,而两个 $ 行为相当于 eval(eval(:x))。","category":"page"},{"location":"manual/metaprogramming/#man-quote-node","page":"元编程","title":"QuoteNode","text":"","category":"section"},{"location":"manual/metaprogramming/","page":"元编程","title":"元编程","text":"quote 形式在 AST 中通常表示为一个 head 为 :quote 的 Expr :","category":"page"},{"location":"manual/metaprogramming/","page":"元编程","title":"元编程","text":"julia> dump(Meta.parse(\":(1+2)\"))\nExpr\n head: Symbol quote\n args: Array{Any}((1,))\n 1: Expr\n head: Symbol call\n args: Array{Any}((3,))\n 1: Symbol +\n 2: Int64 1\n 3: Int64 2","category":"page"},{"location":"manual/metaprogramming/","page":"元编程","title":"元编程","text":"正如我们所看到的,这些表达式支持插值符号 $。但是,在某些情况下,需要在不执行插值的情况下引用代码。 这种引用还没有语法,但在内部表示为 QuoteNode 类型的对象:","category":"page"},{"location":"manual/metaprogramming/","page":"元编程","title":"元编程","text":"julia> eval(Meta.quot(Expr(:$, :(1+2))))\n3\n\njulia> eval(QuoteNode(Expr(:$, :(1+2))))\n:($(Expr(:$, :(1 + 2))))","category":"page"},{"location":"manual/metaprogramming/","page":"元编程","title":"元编程","text":"解析器为简单的引用项(如符号)生成 QuoteNode:","category":"page"},{"location":"manual/metaprogramming/","page":"元编程","title":"元编程","text":"julia> dump(Meta.parse(\":x\"))\nQuoteNode\n value: Symbol x","category":"page"},{"location":"manual/metaprogramming/","page":"元编程","title":"元编程","text":"QuoteNode 也可用于某些高级的元编程任务。","category":"page"},{"location":"manual/metaprogramming/#表达式求值","page":"元编程","title":"表达式求值","text":"","category":"section"},{"location":"manual/metaprogramming/","page":"元编程","title":"元编程","text":"给定一个表达式对象,可以使用 eval 使 Julia 在全局作用域内评估(执行)它:","category":"page"},{"location":"manual/metaprogramming/","page":"元编程","title":"元编程","text":"julia> ex1 = :(1 + 2)\n:(1 + 2)\n\njulia> eval(ex1)\n3\n\njulia> ex = :(a + b)\n:(a + b)\n\njulia> eval(ex)\nERROR: UndefVarError: b not defined\n[...]\n\njulia> a = 1; b = 2;\n\njulia> eval(ex)\n3","category":"page"},{"location":"manual/metaprogramming/","page":"元编程","title":"元编程","text":"每个模块有自己的 eval 函数,该函数在其全局作用域内对表达式求值。传给 eval 的表达式不止可以返回值——它们还能具有改变封闭模块的环境状态的副作用:","category":"page"},{"location":"manual/metaprogramming/","page":"元编程","title":"元编程","text":"julia> ex = :(x = 1)\n:(x = 1)\n\njulia> x\nERROR: UndefVarError: x not defined\n\njulia> eval(ex)\n1\n\njulia> x\n1","category":"page"},{"location":"manual/metaprogramming/","page":"元编程","title":"元编程","text":"这里,表达式对象的求值导致一个值被赋值给全局变量 x。","category":"page"},{"location":"manual/metaprogramming/","page":"元编程","title":"元编程","text":"由于表达式只是 Expr 对象,而其可以通过编程方式构造然后对它求值,因此可以动态地生成任意代码,然后使用 eval 运行所生成的代码。这是个简单的例子:","category":"page"},{"location":"manual/metaprogramming/","page":"元编程","title":"元编程","text":"julia> a = 1;\n\njulia> ex = Expr(:call, :+, a, :b)\n:(1 + b)\n\njulia> a = 0; b = 2;\n\njulia> eval(ex)\n3","category":"page"},{"location":"manual/metaprogramming/","page":"元编程","title":"元编程","text":"a 的值被用于构造表达式 ex,该表达式将函数 + 作用于值 1 和变量 b。请注意 a 和 b 使用方式间的重要区别:","category":"page"},{"location":"manual/metaprogramming/","page":"元编程","title":"元编程","text":"变量 a 在表达式构造时的值在表达式中用作立即值。因此,在对表达式求值时,a 的值就无关紧要了:表达式中的值已经是 1,与 a 的值无关。\n另一方面,因为在表达式构造时用的是符号 :b,所以变量 b 的值无关紧要——:b 只是一个符号,变量 b 甚至无需被定义。然而,在表达式求值时,符号 :b 的值通过寻找变量 b 的值来解析。","category":"page"},{"location":"manual/metaprogramming/#关于表达式的函数","page":"元编程","title":"关于表达式的函数","text":"","category":"section"},{"location":"manual/metaprogramming/","page":"元编程","title":"元编程","text":"如上所述,Julia 能在其内部生成和操作 Julia 代码,这是个非常有用的功能。我们已经见过返回 Expr 对象的函数例子:parse 函数,它接受字符串形式的 Julia 代码并返回相应的 Expr。函数也可以接受一个或多个 Expr 对象作为参数,并返回另一个 Expr。这是个简单、提神的例子:","category":"page"},{"location":"manual/metaprogramming/","page":"元编程","title":"元编程","text":"julia> function math_expr(op, op1, op2)\n expr = Expr(:call, op, op1, op2)\n return expr\n end\nmath_expr (generic function with 1 method)\n\njulia> ex = math_expr(:+, 1, Expr(:call, :*, 4, 5))\n:(1 + 4 * 5)\n\njulia> eval(ex)\n21","category":"page"},{"location":"manual/metaprogramming/","page":"元编程","title":"元编程","text":"作为另一个例子,这个函数将数值参数加倍,但不处理表达式:","category":"page"},{"location":"manual/metaprogramming/","page":"元编程","title":"元编程","text":"julia> function make_expr2(op, opr1, opr2)\n opr1f, opr2f = map(x -> isa(x, Number) ? 2*x : x, (opr1, opr2))\n retexpr = Expr(:call, op, opr1f, opr2f)\n return retexpr\n end\nmake_expr2 (generic function with 1 method)\n\njulia> make_expr2(:+, 1, 2)\n:(2 + 4)\n\njulia> ex = make_expr2(:+, 1, Expr(:call, :*, 5, 8))\n:(2 + 5 * 8)\n\njulia> eval(ex)\n42","category":"page"},{"location":"manual/metaprogramming/#man-macros","page":"元编程","title":"宏","text":"","category":"section"},{"location":"manual/metaprogramming/","page":"元编程","title":"元编程","text":"宏提供了一种机制,可以将生成的代码包含在程序的最终主体中。 宏将一组参数映射到返回的 表达式,并且生成的表达式被直接编译,而不需要运行时 eval 调用。 宏参数可能包括表达式、字面量和符号。","category":"page"},{"location":"manual/metaprogramming/#基础","page":"元编程","title":"基础","text":"","category":"section"},{"location":"manual/metaprogramming/","page":"元编程","title":"元编程","text":"这是一个非常简单的宏:","category":"page"},{"location":"manual/metaprogramming/","page":"元编程","title":"元编程","text":"julia> macro sayhello()\n return :( println(\"Hello, world!\") )\n end\n@sayhello (macro with 1 method)","category":"page"},{"location":"manual/metaprogramming/","page":"元编程","title":"元编程","text":"宏在Julia的语法中有一个专门的字符 @ (at-sign),紧接着是其使用macro NAME ... end 形式来声明的唯一的宏名。在这个例子中,编译器会把所有的@sayhello 替换成:","category":"page"},{"location":"manual/metaprogramming/","page":"元编程","title":"元编程","text":":( println(\"Hello, world!\") )","category":"page"},{"location":"manual/metaprogramming/","page":"元编程","title":"元编程","text":"当 @sayhello 在REPL中被输入时,解释器立即执行,因此我们只会看到计算后的结果:","category":"page"},{"location":"manual/metaprogramming/","page":"元编程","title":"元编程","text":"julia> @sayhello()\nHello, world!","category":"page"},{"location":"manual/metaprogramming/","page":"元编程","title":"元编程","text":"现在,考虑一个稍微复杂一点的宏:","category":"page"},{"location":"manual/metaprogramming/","page":"元编程","title":"元编程","text":"julia> macro sayhello(name)\n return :( println(\"Hello, \", $name) )\n end\n@sayhello (macro with 1 method)","category":"page"},{"location":"manual/metaprogramming/","page":"元编程","title":"元编程","text":"这个宏接受一个参数name。当遇到@sayhello时,quoted 表达式会被展开并将参数中的值插入到最终的表达式中:","category":"page"},{"location":"manual/metaprogramming/","page":"元编程","title":"元编程","text":"julia> @sayhello(\"human\")\nHello, human","category":"page"},{"location":"manual/metaprogramming/","page":"元编程","title":"元编程","text":"我们可以使用函数 macroexpand 查看引用的返回表达式(重要提示: 这是一个非常有用的调试宏的工具):","category":"page"},{"location":"manual/metaprogramming/","page":"元编程","title":"元编程","text":"julia> ex = macroexpand(Main, :(@sayhello(\"human\")) )\n:(Main.println(\"Hello, \", \"human\"))\n\njulia> typeof(ex)\nExpr","category":"page"},{"location":"manual/metaprogramming/","page":"元编程","title":"元编程","text":"我们可以看到 \"human\" 字面量已被插入到表达式中了。","category":"page"},{"location":"manual/metaprogramming/","page":"元编程","title":"元编程","text":"还有一个宏 @ macroexpand,它可能比 macroexpand 函数更方便:","category":"page"},{"location":"manual/metaprogramming/","page":"元编程","title":"元编程","text":"julia> @macroexpand @sayhello \"human\"\n:(println(\"Hello, \", \"human\"))","category":"page"},{"location":"manual/metaprogramming/#停:为什么需要宏?","page":"元编程","title":"停:为什么需要宏?","text":"","category":"section"},{"location":"manual/metaprogramming/","page":"元编程","title":"元编程","text":"我们已经在上一节中看到了一个函数 f(::Expr...) -> Expr。 其实macroexpand也是这样一个函数。 那么,为什么会要设计宏呢?","category":"page"},{"location":"manual/metaprogramming/","page":"元编程","title":"元编程","text":"宏是必需的,因为它们在解析代码时执行,因此,宏允许程序员在运行完整程序之前生成定制代码的片段。 为了说明差异,请考虑以下示例:","category":"page"},{"location":"manual/metaprogramming/","page":"元编程","title":"元编程","text":"julia> macro twostep(arg)\n println(\"I execute at parse time. The argument is: \", arg)\n return :(println(\"I execute at runtime. The argument is: \", $arg))\n end\n@twostep (macro with 1 method)\n\njulia> ex = macroexpand(Main, :(@twostep :(1, 2, 3)) );\nI execute at parse time. The argument is: :((1, 2, 3))","category":"page"},{"location":"manual/metaprogramming/","page":"元编程","title":"元编程","text":"第一个 println 调用在调用 macroexpand 时执行。生成的表达式只包含第二个 println:","category":"page"},{"location":"manual/metaprogramming/","page":"元编程","title":"元编程","text":"julia> typeof(ex)\nExpr\n\njulia> ex\n:(println(\"I execute at runtime. The argument is: \", $(Expr(:copyast, :($(QuoteNode(:((1, 2, 3)))))))))\n\njulia> eval(ex)\nI execute at runtime. The argument is: (1, 2, 3)","category":"page"},{"location":"manual/metaprogramming/#宏的调用","page":"元编程","title":"宏的调用","text":"","category":"section"},{"location":"manual/metaprogramming/","page":"元编程","title":"元编程","text":"宏的通常调用语法如下:","category":"page"},{"location":"manual/metaprogramming/","page":"元编程","title":"元编程","text":"@name expr1 expr2 ...\n@name(expr1, expr2, ...)","category":"page"},{"location":"manual/metaprogramming/","page":"元编程","title":"元编程","text":"请注意,在宏名称前的标志 @,且在第一种形式中参数表达式间没有逗号,而在第二种形式中 @name 后没有空格。这两种风格不应混淆。例如,下列语法不同于上述例子;它把元组 (expr1, expr2, ...) 作为参数传给宏:","category":"page"},{"location":"manual/metaprogramming/","page":"元编程","title":"元编程","text":"@name (expr1, expr2, ...)","category":"page"},{"location":"manual/metaprogramming/","page":"元编程","title":"元编程","text":"在数组字面量(或推导式)上调用宏的另一种方法是不使用括号直接并列两者。在这种情况下,数组将是唯一的传给宏的表达式。以下语法等价(且与 @name [a b] * v 不同):","category":"page"},{"location":"manual/metaprogramming/","page":"元编程","title":"元编程","text":"@name[a b] * v\n@name([a b]) * v","category":"page"},{"location":"manual/metaprogramming/","page":"元编程","title":"元编程","text":"在这着重强调,宏把它们的参数作为表达式、字面量或符号接收。浏览宏参数的一种方法是在宏的内部调用 show 函数:","category":"page"},{"location":"manual/metaprogramming/","page":"元编程","title":"元编程","text":"julia> macro showarg(x)\n show(x)\n # ... remainder of macro, returning an expression\n end\n@showarg (macro with 1 method)\n\njulia> @showarg(a)\n:a\n\njulia> @showarg(1+1)\n:(1 + 1)\n\njulia> @showarg(println(\"Yo!\"))\n:(println(\"Yo!\"))","category":"page"},{"location":"manual/metaprogramming/","page":"元编程","title":"元编程","text":"除了给定的参数列表,每个宏都会传递名为 __source__ 和 __module__ 的额外参数。","category":"page"},{"location":"manual/metaprogramming/","page":"元编程","title":"元编程","text":"参数 __source__ 提供 @ 符号在宏调用处的解析器位置的相关信息(以 LineNumberNode 对象的形式)。这使得宏能包含更好的错误诊断信息,其通常用于日志记录、字符串解析器宏和文档,比如,用于实现 @__LINE__、@__FILE__ 和 @__DIR__ 宏。","category":"page"},{"location":"manual/metaprogramming/","page":"元编程","title":"元编程","text":"引用 __source__.line 和 __source__.file 即可访问位置信息:","category":"page"},{"location":"manual/metaprogramming/","page":"元编程","title":"元编程","text":"julia> macro __LOCATION__(); return QuoteNode(__source__); end\n@__LOCATION__ (macro with 1 method)\n\njulia> dump(\n @__LOCATION__(\n ))\nLineNumberNode\n line: Int64 2\n file: Symbol none","category":"page"},{"location":"manual/metaprogramming/","page":"元编程","title":"元编程","text":"参数 __module__ 提供宏调用展开处的上下文相关信息(以 Module 对象的形式)。这允许宏查找上下文相关的信息,比如现有的绑定,或者将值作为附加参数插入到一个在当前模块中进行自我反射的运行时函数调用中。","category":"page"},{"location":"manual/metaprogramming/#构建高级的宏","page":"元编程","title":"构建高级的宏","text":"","category":"section"},{"location":"manual/metaprogramming/","page":"元编程","title":"元编程","text":"这是 Julia 的 @assert 宏的简化定义:","category":"page"},{"location":"manual/metaprogramming/","page":"元编程","title":"元编程","text":"julia> macro assert(ex)\n return :( $ex ? nothing : throw(AssertionError($(string(ex)))) )\n end\n@assert (macro with 1 method)","category":"page"},{"location":"manual/metaprogramming/","page":"元编程","title":"元编程","text":"这个宏可以像这样使用:","category":"page"},{"location":"manual/metaprogramming/","page":"元编程","title":"元编程","text":"julia> @assert 1 == 1.0\n\njulia> @assert 1 == 0\nERROR: AssertionError: 1 == 0","category":"page"},{"location":"manual/metaprogramming/","page":"元编程","title":"元编程","text":"宏调用在解析时扩展为其返回结果,并替代已编写的语法。这相当于编写:","category":"page"},{"location":"manual/metaprogramming/","page":"元编程","title":"元编程","text":"1 == 1.0 ? nothing : throw(AssertionError(\"1 == 1.0\"))\n1 == 0 ? nothing : throw(AssertionError(\"1 == 0\"))","category":"page"},{"location":"manual/metaprogramming/","page":"元编程","title":"元编程","text":"也就是说,在第一个调用中,表达式 :(1 == 1.0) 拼接到测试条件槽中,而 string(:(1 == 1.0)) 拼接到断言信息槽中。如此构造的表达式会被放置在发生 @assert 宏调用处的语法树。然后在执行时,如果测试表达式的计算结果为真,则返回 nothing,但如果测试结果为假,则会引发错误,表明声明的表达式为假。请注意,将其编写为函数是不可能的,因为能获取的只有条件的值而无法在错误信息中显示计算出它的表达式。","category":"page"},{"location":"manual/metaprogramming/","page":"元编程","title":"元编程","text":"在 Julia Base 中,@assert 的实际定义更复杂。它允许用户可选地制定自己的错误信息,而不仅仅是打印断言失败的表达式。与函数一样,具有可变数量的参数( 变参函数)可在最后一个参数后面用省略号指定:","category":"page"},{"location":"manual/metaprogramming/","page":"元编程","title":"元编程","text":"julia> macro assert(ex, msgs...)\n msg_body = isempty(msgs) ? ex : msgs[1]\n msg = string(msg_body)\n return :($ex ? nothing : throw(AssertionError($msg)))\n end\n@assert (macro with 1 method)","category":"page"},{"location":"manual/metaprogramming/","page":"元编程","title":"元编程","text":"现在@assert 有两种操作模式,这取决于它接收到的参数数量!如果只有一个参数,msgs 捕获的表达式元组将为空,并且其行为与上面更简单的定义相同。 但是现在如果用户指定了第二个参数,它会打印在消息正文中而不是不相等的表达式中。你可以使用恰当命名的 @macroexpand 宏检查宏展开的结果:","category":"page"},{"location":"manual/metaprogramming/","page":"元编程","title":"元编程","text":"julia> @macroexpand @assert a == b\n:(if Main.a == Main.b\n Main.nothing\n else\n Main.throw(Main.AssertionError(\"a == b\"))\n end)\n\njulia> @macroexpand @assert a==b \"a should equal b!\"\n:(if Main.a == Main.b\n Main.nothing\n else\n Main.throw(Main.AssertionError(\"a should equal b!\"))\n end)","category":"page"},{"location":"manual/metaprogramming/","page":"元编程","title":"元编程","text":"实际的 @assert 宏还处理了另一种情形:我们如果除了打印「a should equal b」外还想打印它们的值?有人也许会天真地尝试在自定义消息中使用字符串插值,例如,@assert a==b \"a ($a) should equal b ($b)!\",但这不会像上面的宏一样按预期工作。你能想到为什么吗?回想一下字符串插值,内插字符串会被重写为 string 的调用。比较:","category":"page"},{"location":"manual/metaprogramming/","page":"元编程","title":"元编程","text":"julia> typeof(:(\"a should equal b\"))\nString\n\njulia> typeof(:(\"a ($a) should equal b ($b)!\"))\nExpr\n\njulia> dump(:(\"a ($a) should equal b ($b)!\"))\nExpr\n head: Symbol string\n args: Array{Any}((5,))\n 1: String \"a (\"\n 2: Symbol a\n 3: String \") should equal b (\"\n 4: Symbol b\n 5: String \")!\"","category":"page"},{"location":"manual/metaprogramming/","page":"元编程","title":"元编程","text":"所以,现在宏在 msg_body 中获得的不是单纯的字符串,其接收了一个完整的表达式,该表达式需进行求值才能按预期显示。这可作为 string 调用的参数直接拼接到返回的表达式中;有关完整实现,请参阅 error.jl。","category":"page"},{"location":"manual/metaprogramming/","page":"元编程","title":"元编程","text":"@assert 宏充分利用拼接被引用的表达式,以便简化对宏内部表达式的操作。","category":"page"},{"location":"manual/metaprogramming/#卫生宏","page":"元编程","title":"卫生宏","text":"","category":"section"},{"location":"manual/metaprogramming/","page":"元编程","title":"元编程","text":"在更复杂的宏中会出现关于卫生宏 的问题。简而言之,宏必须确保在其返回表达式中引入的变量不会意外地与其展开处周围代码中的现有变量相冲突。相反,作为参数传递给宏的表达式通常被认为在其周围代码的上下文中进行求值,与现有变量交互并修改之。另一个问题源于这样的事实:宏可以在不同于其定义所处模块的模块中调用。在这种情况下,我们需要确保所有全局变量都被解析到正确的模块中。Julia 比使用文本宏展开的语言(比如 C)具有更大的优势,因为它只需要考虑返回的表达式。所有其它变量(例如上面@assert 中的 msg)遵循通常的作用域块规则。","category":"page"},{"location":"manual/metaprogramming/","page":"元编程","title":"元编程","text":"为了演示这些问题,让我们来编写宏 @time,其以表达式为参数,记录当前时间,对表达式求值,再次记录当前时间,打印前后的时间差,然后以表达式的值作为其最终值。该宏可能看起来就像这样:","category":"page"},{"location":"manual/metaprogramming/","page":"元编程","title":"元编程","text":"macro time(ex)\n return quote\n local t0 = time_ns()\n local val = $ex\n local t1 = time_ns()\n println(\"elapsed time: \", (t1-t0)/1e9, \" seconds\")\n val\n end\nend","category":"page"},{"location":"manual/metaprogramming/","page":"元编程","title":"元编程","text":"在这里,我们希望 t0、t1 和 val 成为私有临时变量,并且我们希望 time_ns 引用 Julia Base 中的 time_ns 函数,而不是任何用户可能拥有的 time_ns 变量(同样适用于 println)。 想象一下,如果用户表达式 ex 还包含对名为 t0 的变量的赋值,或者定义了自己的 time_ns 变量,可能会出现什么问题。 程序可能会报错,或者进行未知的行为。","category":"page"},{"location":"manual/metaprogramming/","page":"元编程","title":"元编程","text":"Julia 的宏展开器通过以下方式解决了这些问题。 首先,宏结果中的变量分为局部变量或全局变量。 如果变量被赋值(并且不是声明为全局的)、声明为局部、或用作函数参数名称,则该变量被视为局部变量。 否则,它被认为是全局的。 然后将局部变量重命名为唯一的(使用 gensym 函数,该函数生成新符号),并在宏定义环境中解析全局变量。 因此,上述两个问题都得到了处理; 宏的局部变量不会与任何用户变量冲突,并且 time_ns 和 println 将引用 Julia Base 定义。","category":"page"},{"location":"manual/metaprogramming/","page":"元编程","title":"元编程","text":"然而,仍有另外的问题。考虑此宏的以下用法:","category":"page"},{"location":"manual/metaprogramming/","page":"元编程","title":"元编程","text":"module MyModule\nimport Base.@time\n\ntime_ns() = ... # compute something\n\n@time time_ns()\nend","category":"page"},{"location":"manual/metaprogramming/","page":"元编程","title":"元编程","text":"这里的用户表达式ex 是对time_ns 的调用,但与宏使用的time_ns 函数不同。 它清楚地指向MyModule.time_ns。 因此我们必须安排在宏调用环境中解析ex中的代码。 这是通过使用 esc“转义”表达式来完成的:","category":"page"},{"location":"manual/metaprogramming/","page":"元编程","title":"元编程","text":"macro time(ex)\n ...\n local val = $(esc(ex))\n ...\nend","category":"page"},{"location":"manual/metaprogramming/","page":"元编程","title":"元编程","text":"以这种方式封装的表达式会被宏展开器单独保留,并将其简单地逐字粘贴到输出中。因此,它将在宏调用所处环境中解析。","category":"page"},{"location":"manual/metaprogramming/","page":"元编程","title":"元编程","text":"这种转义机制可以在必要时用于「违反」卫生,以便于引入或操作用户变量。例如,以下宏在其调用所处环境中将 x 设置为零:","category":"page"},{"location":"manual/metaprogramming/","page":"元编程","title":"元编程","text":"julia> macro zerox()\n return esc(:(x = 0))\n end\n@zerox (macro with 1 method)\n\njulia> function foo()\n x = 1\n @zerox\n return x # is zero\n end\nfoo (generic function with 1 method)\n\njulia> foo()\n0","category":"page"},{"location":"manual/metaprogramming/","page":"元编程","title":"元编程","text":"应当明智地使用这种变量操作,但它偶尔会很方便。","category":"page"},{"location":"manual/metaprogramming/","page":"元编程","title":"元编程","text":"获得正确的规则也许是个艰巨的挑战。在使用宏之前,你可以去考虑是否函数闭包便已足够。另一个有用的策略是将尽可能多的工作推迟到运行时。例如,许多宏只是将其参数封装为 QuoteNode 或类似的 Expr。这方面的例子有 @task body,它只返回 schedule(Task(() -> $body)), 和 @eval expr,它只返回 eval(QuoteNode(expr))。","category":"page"},{"location":"manual/metaprogramming/","page":"元编程","title":"元编程","text":"为了演示,我们可以将上面的 @time 示例重新编写成:","category":"page"},{"location":"manual/metaprogramming/","page":"元编程","title":"元编程","text":"macro time(expr)\n return :(timeit(() -> $(esc(expr))))\nend\nfunction timeit(f)\n t0 = time_ns()\n val = f()\n t1 = time_ns()\n println(\"elapsed time: \", (t1-t0)/1e9, \" seconds\")\n return val\nend","category":"page"},{"location":"manual/metaprogramming/","page":"元编程","title":"元编程","text":"但是,我们不这样做也是有充分理由的:将 expr 封装在新的作用域块(该匿名函数)中也会稍微改变该表达式的含义(其中任何变量的作用域),而我们想要 @time 使用时对其封装的代码影响最小。","category":"page"},{"location":"manual/metaprogramming/#宏与派发","page":"元编程","title":"宏与派发","text":"","category":"section"},{"location":"manual/metaprogramming/","page":"元编程","title":"元编程","text":"与 Julia 函数一样,宏也是泛型的。由于多重派发,这意味着宏也能有多个方法定义:","category":"page"},{"location":"manual/metaprogramming/","page":"元编程","title":"元编程","text":"julia> macro m end\n@m (macro with 0 methods)\n\njulia> macro m(args...)\n println(\"$(length(args)) arguments\")\n end\n@m (macro with 1 method)\n\njulia> macro m(x,y)\n println(\"Two arguments\")\n end\n@m (macro with 2 methods)\n\njulia> @m \"asd\"\n1 arguments\n\njulia> @m 1 2\nTwo arguments","category":"page"},{"location":"manual/metaprogramming/","page":"元编程","title":"元编程","text":"但是应该记住,宏派发基于传递给宏的 AST 的类型,而不是 AST 在运行时进行求值的类型:","category":"page"},{"location":"manual/metaprogramming/","page":"元编程","title":"元编程","text":"julia> macro m(::Int)\n println(\"An Integer\")\n end\n@m (macro with 3 methods)\n\njulia> @m 2\nAn Integer\n\njulia> x = 2\n2\n\njulia> @m x\n1 arguments","category":"page"},{"location":"manual/metaprogramming/#代码生成","page":"元编程","title":"代码生成","text":"","category":"section"},{"location":"manual/metaprogramming/","page":"元编程","title":"元编程","text":"当需要大量重复的样板代码时,为了避免冗余,通常以编程方式生成它。在大多数语言中,这需要一个额外的构建步骤以及生成重复代码的独立程序。在 Julia 中,表达式插值和 eval 允许在通常的程序执行过程中生成这些代码。例如,考虑下列自定义类型","category":"page"},{"location":"manual/metaprogramming/","page":"元编程","title":"元编程","text":"struct MyNumber\n x::Float64\nend\n# output\n","category":"page"},{"location":"manual/metaprogramming/","page":"元编程","title":"元编程","text":"我们想为该类型添加一些方法。在下面的循环中,我们以编程的方式完成此工作:","category":"page"},{"location":"manual/metaprogramming/","page":"元编程","title":"元编程","text":"for op = (:sin, :cos, :tan, :log, :exp)\n eval(quote\n Base.$op(a::MyNumber) = MyNumber($op(a.x))\n end)\nend\n# output\n","category":"page"},{"location":"manual/metaprogramming/","page":"元编程","title":"元编程","text":"现在,我们对自定义类型调用这些函数:","category":"page"},{"location":"manual/metaprogramming/","page":"元编程","title":"元编程","text":"julia> x = MyNumber(π)\nMyNumber(3.141592653589793)\n\njulia> sin(x)\nMyNumber(1.2246467991473532e-16)\n\njulia> cos(x)\nMyNumber(-1.0)","category":"page"},{"location":"manual/metaprogramming/","page":"元编程","title":"元编程","text":"在这种方法中,Julia 充当了自己的预处理器,并且允许从语言内部生成代码。使用 : 前缀的引用形式编写上述代码会使其更简洁:","category":"page"},{"location":"manual/metaprogramming/","page":"元编程","title":"元编程","text":"for op = (:sin, :cos, :tan, :log, :exp)\n eval(:(Base.$op(a::MyNumber) = MyNumber($op(a.x))))\nend","category":"page"},{"location":"manual/metaprogramming/","page":"元编程","title":"元编程","text":"不管怎样,这种使用 eval(quote(...)) 模式生成语言内部的代码很常见,为此,Julia 自带了一个宏来缩写该模式:","category":"page"},{"location":"manual/metaprogramming/","page":"元编程","title":"元编程","text":"for op = (:sin, :cos, :tan, :log, :exp)\n @eval Base.$op(a::MyNumber) = MyNumber($op(a.x))\nend","category":"page"},{"location":"manual/metaprogramming/","page":"元编程","title":"元编程","text":"@eval 重写此调用,使其与上面的较长版本完全等价。为了生成较长的代码块,可以把一个代码块作为表达式参数传给 @eval:","category":"page"},{"location":"manual/metaprogramming/","page":"元编程","title":"元编程","text":"@eval begin\n # multiple lines\nend","category":"page"},{"location":"manual/metaprogramming/#meta-non-standard-string-literals","page":"元编程","title":"非标准字符串字面量","text":"","category":"section"},{"location":"manual/metaprogramming/","page":"元编程","title":"元编程","text":"回想一下在字符串的文档中,以标识符为前缀的字符串字面量被称为非标准字符串字面量,它们可以具有与未加前缀的字符串字面量不同的语义。例如:","category":"page"},{"location":"manual/metaprogramming/","page":"元编程","title":"元编程","text":"r\"^\\s*(?:#|$)\" 产生一个正则表达式对象而不是一个字符串\nb\"DATA\\xff\\u2200\" 是一个字节数组字面量 ,表示[68,65,84,65,255,226,136,128]。","category":"page"},{"location":"manual/metaprogramming/","page":"元编程","title":"元编程","text":"可能令人惊讶的是,这些行为并没有被硬编码到 Julia 的解释器或编译器中。相反,它们是由一个通用机制实现的自定义行为,且任何人都可以使用该机制:带前缀的字符串字面量被解析为特定名称的宏的调用。例如,正则表达式宏如下:","category":"page"},{"location":"manual/metaprogramming/","page":"元编程","title":"元编程","text":"macro r_str(p)\n Regex(p)\nend","category":"page"},{"location":"manual/metaprogramming/","page":"元编程","title":"元编程","text":"这便是全部代码。这个宏说的是字符串字面量 r\"^\\s*(?:#|$)\" 的字面内容应该传给宏 @r_str,并且展开后的结果应当放在该字符串字面量出现处的语法树中。换句话说,表达式 r\"^\\s*(?:#|$)\" 等价于直接把下列对象放进语法树中:","category":"page"},{"location":"manual/metaprogramming/","page":"元编程","title":"元编程","text":"Regex(\"^\\\\s*(?:#|\\$)\")","category":"page"},{"location":"manual/metaprogramming/","page":"元编程","title":"元编程","text":"字符串字面量形式不仅更短、更方便,也更高效:因为正则表达式需要编译,Regex 对象实际上是在编译代码时创建的,所以编译只发生一次,而不是每次执行代码时都再编译一次。请考虑如果正则表达式出现在循环中:","category":"page"},{"location":"manual/metaprogramming/","page":"元编程","title":"元编程","text":"for line = lines\n m = match(r\"^\\s*(?:#|$)\", line)\n if m === nothing\n # non-comment\n else\n # comment\n end\nend","category":"page"},{"location":"manual/metaprogramming/","page":"元编程","title":"元编程","text":"因为正则表达式 r\"^\\s*(?:#|$)\" 在这段代码解析时便已编译并被插入到语法树中,所以它只编译一次,而不是每次执行循环时都再编译一次。要在不使用宏的情况下实现此效果,必须像这样编写此循环:","category":"page"},{"location":"manual/metaprogramming/","page":"元编程","title":"元编程","text":"re = Regex(\"^\\\\s*(?:#|\\$)\")\nfor line = lines\n m = match(re, line)\n if m === nothing\n # non-comment\n else\n # comment\n end\nend","category":"page"},{"location":"manual/metaprogramming/","page":"元编程","title":"元编程","text":"此外,如果编译器无法确定在所有循环中正则表达式对象都是常量,可能无法进行某些优化,使得此版本的效率依旧低于上面的更方便的字面量形式。当然,在某些情况下,非字面量形式更方便:如果需要向正则表达式中插入变量,就必须采用这种更冗长的方法;如果正则表达式模式本身是动态的,可能在每次循环迭代时发生变化,就必须在每次迭代中构造新的正则表达式对象。然而,在绝大多数用例中,正则表达式不是基于运行时的数据构造的。在大多数情况下,将正则表达式编写为编译期值的能力是无法估量的。","category":"page"},{"location":"manual/metaprogramming/","page":"元编程","title":"元编程","text":"用户定义字符串文字的机制非常强大。不仅使用它实现了 Julia 的非标准字面量,而且还使用以下看起来无害的宏实现了命令行字面量语法(`echo \"Hello, $person\"`):","category":"page"},{"location":"manual/metaprogramming/","page":"元编程","title":"元编程","text":"macro cmd(str)\n :(cmd_gen($(shell_parse(str)[1])))\nend","category":"page"},{"location":"manual/metaprogramming/","page":"元编程","title":"元编程","text":"当然,这个宏的定义中使用的函数隐藏了许多复杂性,但它们只是函数且完全用 Julia 编写。你可以阅读它们的源代码并精确地看到它们的行为——它们所做的一切就是构造要插入到你的程序的语法树的表达式对象。","category":"page"},{"location":"manual/metaprogramming/","page":"元编程","title":"元编程","text":"与字符串字面量一样,命令行字面量也可以以标识符为前缀,以形成所谓的非标准命令行字面量。 这些命令行字面量被解析为对特殊命名的宏的调用。 例如,语法 custom`literal` 被解析为 @custom_cmd \"literal\"。 Julia 本身不包含任何非标准的命令行字面量,但包可以使用这种语法。 除了不同的语法和 _cmd 后缀而不是 _str 后缀,非标准命令行字面量的行为与非标准字符串字面量完全一样。","category":"page"},{"location":"manual/metaprogramming/","page":"元编程","title":"元编程","text":"如果两个模块提供了同名的非标准字符串或命令字面量,能使用模块名限定该字符串或命令字面量。例如,如果 Foo 和 Bar 提供了相同的字符串字面量 @x_str,那么可以编写 Foo.x\"literal\" 或 Bar.x\"literal\" 来消除两者的歧义。","category":"page"},{"location":"manual/metaprogramming/","page":"元编程","title":"元编程","text":"以下是另一种定义宏的方式:","category":"page"},{"location":"manual/metaprogramming/","page":"元编程","title":"元编程","text":"macro foo_str(str, flag)\n # do stuff\nend","category":"page"},{"location":"manual/metaprogramming/","page":"元编程","title":"元编程","text":"可以使用如下语法来调用这个宏","category":"page"},{"location":"manual/metaprogramming/","page":"元编程","title":"元编程","text":"foo\"str\"flag","category":"page"},{"location":"manual/metaprogramming/","page":"元编程","title":"元编程","text":"上述语法中 flag 的类型可以是一个String,在字符串字面量之后包含的内容。","category":"page"},{"location":"manual/metaprogramming/#生成函数","page":"元编程","title":"生成函数","text":"","category":"section"},{"location":"manual/metaprogramming/","page":"元编程","title":"元编程","text":"有个非常特殊的宏叫 @generated,它允许你定义所谓的生成函数。它们能根据其参数类型生成专用代码,与用多重派发所能实现的代码相比,其代码更灵活和/或少。虽然宏在解析时使用表达式且无法访问其输入值的类型,但是生成函数在参数类型已知时会被展开,但该函数尚未编译。","category":"page"},{"location":"manual/metaprogramming/","page":"元编程","title":"元编程","text":"生成函数的声明不会执行某些计算或操作,而会返回一个被引用的表达式,接着该表达式构成参数类型所对应方法的主体。在调用生成函数时,其返回的表达式会被编译然后执行。为了提高效率,通常会缓存结果。为了能推断是否缓存结果,只能使用语言的受限子集。因此,生成函数提供了一个灵活的方式来将工作重运行时移到编译时,代价则是其构造能力受到更大的限制。","category":"page"},{"location":"manual/metaprogramming/","page":"元编程","title":"元编程","text":"定义生成函数与普通函数有五个主要区别:","category":"page"},{"location":"manual/metaprogramming/","page":"元编程","title":"元编程","text":"使用 @generated 标注函数声明。这会向 AST 附加一些信息,让编译器知道这个函数是生成函数。\n在生成函数的主体中,你只能访问参数的类型,而不能访问其值,以及在生成函数的定义之前便已定义的任何函数。\n不应计算某些东西或执行某些操作,应返回一个被引用的表达式,它会在被求值时执行你想要的操作。\n生成函数只允许调用在生成函数定义之前定义的函数。(如果不遵循这一点,引用来自未来世界的函数可能会导致 MethodErrors )\n生成函数不能更改或观察任何非常量的全局状态。(例如,其包括 IO、锁、非局部的字典或者使用 hasmethod)即它们只能读取全局常量,且没有任何副作用。换句话说,它们必须是纯函数。由于实现限制,这也意味着它们目前无法定义闭包或生成器。","category":"page"},{"location":"manual/metaprogramming/","page":"元编程","title":"元编程","text":"举例子来说明这个是最简单的。我们可以将生成函数 foo 声明为","category":"page"},{"location":"manual/metaprogramming/","page":"元编程","title":"元编程","text":"julia> @generated function foo(x)\n Core.println(x)\n return :(x * x)\n end\nfoo (generic function with 1 method)","category":"page"},{"location":"manual/metaprogramming/","page":"元编程","title":"元编程","text":"请注意,代码主体返回一个被引用的表达式,即 :(x * x),而不仅仅是 x * x 的值。","category":"page"},{"location":"manual/metaprogramming/","page":"元编程","title":"元编程","text":"从调用者的角度看,这与通常的函数等价;实际上,你无需知道你所调用的是通常的函数还是生成函数。让我们看看 foo 的行为:","category":"page"},{"location":"manual/metaprogramming/","page":"元编程","title":"元编程","text":"julia> x = foo(2); # note: output is from println() statement in the body\nInt64\n\njulia> x # now we print x\n4\n\njulia> y = foo(\"bar\");\nString\n\njulia> y\n\"barbar\"","category":"page"},{"location":"manual/metaprogramming/","page":"元编程","title":"元编程","text":"因此,我们知道在生成函数的主体中,x 是所传递参数的类型,并且,生成函数的返回值是其定义所返回的被引用的表达式的求值结果,在该表达式求值时 x 表示其值。","category":"page"},{"location":"manual/metaprogramming/","page":"元编程","title":"元编程","text":"如果我们使用我们已经使用过的类型再次对 foo 求值会发生什么?","category":"page"},{"location":"manual/metaprogramming/","page":"元编程","title":"元编程","text":"julia> foo(4)\n16","category":"page"},{"location":"manual/metaprogramming/","page":"元编程","title":"元编程","text":"请注意,这里并没有打印 Int64。我们可以看到对于特定的参数类型集来说,生成函数的主体只执行一次,且结果会被缓存。此后,对于此示例,生成函数首次调用返回的表达式被重新用作方法主体。但是,实际的缓存行为是由实现定义的性能优化,过于依赖此行为并不实际。","category":"page"},{"location":"manual/metaprogramming/","page":"元编程","title":"元编程","text":"生成函数可能只生成一次函数,但也可能多次生成,或者看起来根本就没有生成过函数。因此,你应该从不编写有副作用的生成函数——因为副作用发生的时间和频率是不确定的。(对于宏来说也是如此——跟宏一样,在生成函数中使用 eval 也许意味着你正以错误的方式做某事。)但是,与宏不同,运行时系统无法正确处理对 eval 的调用,所以不允许这样做。","category":"page"},{"location":"manual/metaprogramming/","page":"元编程","title":"元编程","text":"理解 @generated 函数与方法的重定义间如何相互作用也很重要。遵循正确的 @generated 函数不能观察任何可变状态或导致全局状态的任何更改的原则,我们看到以下行为。观察到,生成函数不能调用在生成函数本身的定义之前未定义的任何方法。","category":"page"},{"location":"manual/metaprogramming/","page":"元编程","title":"元编程","text":"一开始 f(x) 有一个定义","category":"page"},{"location":"manual/metaprogramming/","page":"元编程","title":"元编程","text":"julia> f(x) = \"original definition\";","category":"page"},{"location":"manual/metaprogramming/","page":"元编程","title":"元编程","text":"定义使用 f(x) 的其它操作:","category":"page"},{"location":"manual/metaprogramming/","page":"元编程","title":"元编程","text":"julia> g(x) = f(x);\n\njulia> @generated gen1(x) = f(x);\n\njulia> @generated gen2(x) = :(f(x));","category":"page"},{"location":"manual/metaprogramming/","page":"元编程","title":"元编程","text":"我们现在为 f(x) 添加几个新定义:","category":"page"},{"location":"manual/metaprogramming/","page":"元编程","title":"元编程","text":"julia> f(x::Int) = \"definition for Int\";\n\njulia> f(x::Type{Int}) = \"definition for Type{Int}\";","category":"page"},{"location":"manual/metaprogramming/","page":"元编程","title":"元编程","text":"并比较这些结果的差异:","category":"page"},{"location":"manual/metaprogramming/","page":"元编程","title":"元编程","text":"julia> f(1)\n\"definition for Int\"\n\njulia> g(1)\n\"definition for Int\"\n\njulia> gen1(1)\n\"original definition\"\n\njulia> gen2(1)\n\"definition for Int\"","category":"page"},{"location":"manual/metaprogramming/","page":"元编程","title":"元编程","text":"生成函数的每个方法都有自己的已定义函数视图:","category":"page"},{"location":"manual/metaprogramming/","page":"元编程","title":"元编程","text":"julia> @generated gen1(x::Real) = f(x);\n\njulia> gen1(1)\n\"definition for Type{Int}\"","category":"page"},{"location":"manual/metaprogramming/","page":"元编程","title":"元编程","text":"上例中的生成函数 foo 能做的,通常的函数 foo(x) = x * x 也能做(除了在第一次调用时打印类型,并产生了更高的开销)。但是,生成函数的强大之处在于其能够根据传递给它的类型计算不同的被引用的表达式:","category":"page"},{"location":"manual/metaprogramming/","page":"元编程","title":"元编程","text":"julia> @generated function bar(x)\n if x <: Integer\n return :(x ^ 2)\n else\n return :(x)\n end\n end\nbar (generic function with 1 method)\n\njulia> bar(4)\n16\n\njulia> bar(\"baz\")\n\"baz\"","category":"page"},{"location":"manual/metaprogramming/","page":"元编程","title":"元编程","text":"(当然,这个刻意的例子可以更简单地通过多重派发实现······)","category":"page"},{"location":"manual/metaprogramming/","page":"元编程","title":"元编程","text":"滥用它会破坏运行时系统并导致未定义行为:","category":"page"},{"location":"manual/metaprogramming/","page":"元编程","title":"元编程","text":"julia> @generated function baz(x)\n if rand() < .9\n return :(x^2)\n else\n return :(\"boo!\")\n end\n end\nbaz (generic function with 1 method)","category":"page"},{"location":"manual/metaprogramming/","page":"元编程","title":"元编程","text":"由于生成函数的主体具有不确定性,其行为和所有后续代码的行为并未定义。","category":"page"},{"location":"manual/metaprogramming/","page":"元编程","title":"元编程","text":"不要复制这些例子!","category":"page"},{"location":"manual/metaprogramming/","page":"元编程","title":"元编程","text":"这些例子有助于说明生成函数定义和调用的工作方式;但是,不要复制它们,原因如下:","category":"page"},{"location":"manual/metaprogramming/","page":"元编程","title":"元编程","text":"foo 函数有副作用(对 Core.println 的调用),并且未确切定义这些副作用发生的时间、频率和次数。\nbar 函数解决的问题可通过多重派发被更好地解决——定义 bar(x) = x 和 bar(x::Integer) = x ^ 2 会做同样的事,但它更简单和快捷。\nbaz 函数是病态的","category":"page"},{"location":"manual/metaprogramming/","page":"元编程","title":"元编程","text":"请注意,不应在生成函数中尝试的操作并无严格限制,且运行时系统现在只能检测一部分无效操作。还有许多操作只会破坏运行时系统而没有通知,通常以微妙的方式而非显然地与错误的定义相关联。因为函数生成器是在类型推导期间运行的,所以它必须遵守该代码的所有限制。","category":"page"},{"location":"manual/metaprogramming/","page":"元编程","title":"元编程","text":"一些不应该尝试的操作包括:","category":"page"},{"location":"manual/metaprogramming/","page":"元编程","title":"元编程","text":"缓存本地指针。\n以任何方式与 Core.Compiler 的内容或方法交互。\n观察任何可变状态。\n生成函数的类型推导可以在任何时候运行,包括你的代码正在尝试观察或更改此状态时。\n采用任何锁:你调用的 C 代码可以在内部使用锁(例如,调用 malloc 不会有问题,即使大多数实现在内部需要锁),但是不要试图在执行 Julia 代码时保持或请求任何锁。\n调用在生成函数的主体后定义的任何函数。对于增量加载的预编译模块,则放宽此条件,以允许调用模块中的任何函数。","category":"page"},{"location":"manual/metaprogramming/","page":"元编程","title":"元编程","text":"那好,我们现在已经更好地理解了生成函数的工作方式,让我们使用它来构建一些更高级(和有效)的功能……","category":"page"},{"location":"manual/metaprogramming/#一个高级的例子","page":"元编程","title":"一个高级的例子","text":"","category":"section"},{"location":"manual/metaprogramming/","page":"元编程","title":"元编程","text":"Julia 的 base 库有个内部函数 sub2ind,用于根据一组 n 重线性索引计算 n 维数组的线性索引——换句话说,用于计算索引 i,其可用于使用 A[i] 来索引数组 A,而不是用 A[x,y,z,...]。一种可能的实现如下:","category":"page"},{"location":"manual/metaprogramming/","page":"元编程","title":"元编程","text":"julia> function sub2ind_loop(dims::NTuple{N}, I::Integer...) where N\n ind = I[N] - 1\n for i = N-1:-1:1\n ind = I[i]-1 + dims[i]*ind\n end\n return ind + 1\n end\nsub2ind_loop (generic function with 1 method)\n\njulia> sub2ind_loop((3, 5), 1, 2)\n4","category":"page"},{"location":"manual/metaprogramming/","page":"元编程","title":"元编程","text":"用递归可以完成同样的事情:","category":"page"},{"location":"manual/metaprogramming/","page":"元编程","title":"元编程","text":"julia> sub2ind_rec(dims::Tuple{}) = 1;\n\njulia> sub2ind_rec(dims::Tuple{}, i1::Integer, I::Integer...) =\n i1 == 1 ? sub2ind_rec(dims, I...) : throw(BoundsError());\n\njulia> sub2ind_rec(dims::Tuple{Integer, Vararg{Integer}}, i1::Integer) = i1;\n\njulia> sub2ind_rec(dims::Tuple{Integer, Vararg{Integer}}, i1::Integer, I::Integer...) =\n i1 + dims[1] * (sub2ind_rec(Base.tail(dims), I...) - 1);\n\njulia> sub2ind_rec((3, 5), 1, 2)\n4","category":"page"},{"location":"manual/metaprogramming/","page":"元编程","title":"元编程","text":"这两种实现虽然不同,但本质上做同样的事情:在数组维度上的运行时循环,将每个维度上的偏移量收集到最后的索引中。","category":"page"},{"location":"manual/metaprogramming/","page":"元编程","title":"元编程","text":"然而,循环所需的信息都已嵌入到参数的类型信息中。因此,我们可以利用生成函数将迭代移动到编译期;用编译器的说法,我们用生成函数手动展开循环。代码主体变得几乎相同,但我们不是计算线性索引,而是建立计算索引的表达式:","category":"page"},{"location":"manual/metaprogramming/","page":"元编程","title":"元编程","text":"julia> @generated function sub2ind_gen(dims::NTuple{N}, I::Integer...) where N\n ex = :(I[$N] - 1)\n for i = (N - 1):-1:1\n ex = :(I[$i] - 1 + dims[$i] * $ex)\n end\n return :($ex + 1)\n end\nsub2ind_gen (generic function with 1 method)\n\njulia> sub2ind_gen((3, 5), 1, 2)\n4","category":"page"},{"location":"manual/metaprogramming/","page":"元编程","title":"元编程","text":"这会生成什么代码?","category":"page"},{"location":"manual/metaprogramming/","page":"元编程","title":"元编程","text":"找出所生成代码的一个简单方法是将生成函数的主体提取到另一个(通常的)函数中:","category":"page"},{"location":"manual/metaprogramming/","page":"元编程","title":"元编程","text":"julia> @generated function sub2ind_gen(dims::NTuple{N}, I::Integer...) where N\n return sub2ind_gen_impl(dims, I...)\n end\nsub2ind_gen (generic function with 1 method)\n\njulia> function sub2ind_gen_impl(dims::Type{T}, I...) where T <: NTuple{N,Any} where N\n length(I) == N || return :(error(\"partial indexing is unsupported\"))\n ex = :(I[$N] - 1)\n for i = (N - 1):-1:1\n ex = :(I[$i] - 1 + dims[$i] * $ex)\n end\n return :($ex + 1)\n end\nsub2ind_gen_impl (generic function with 1 method)","category":"page"},{"location":"manual/metaprogramming/","page":"元编程","title":"元编程","text":"我们现在可以执行 sub2ind_gen_impl 并检查它所返回的表达式:","category":"page"},{"location":"manual/metaprogramming/","page":"元编程","title":"元编程","text":"julia> sub2ind_gen_impl(Tuple{Int,Int}, Int, Int)\n:(((I[1] - 1) + dims[1] * (I[2] - 1)) + 1)","category":"page"},{"location":"manual/metaprogramming/","page":"元编程","title":"元编程","text":"因此,这里使用的方法主体根本不包含循环——只有两个元组的索引、乘法和加法/减法。所有循环都是在编译期执行的,我们完全避免了在执行期间的循环。因此,我们只需对每个类型循环一次,在本例中每个 N 循环一次(除了在该函数被多次生成的边缘情况——请参阅上面的免责声明)。","category":"page"},{"location":"manual/metaprogramming/#可选地生成函数","page":"元编程","title":"可选地生成函数","text":"","category":"section"},{"location":"manual/metaprogramming/","page":"元编程","title":"元编程","text":"生成函数可以在运行时实现高效率,但需要编译时间成本:必须为具体的参数类型的每个组合生成新的函数体。通常,Julia 能够编译函数的「泛型」版本,其适用于任何参数,但对于生成函数,这是不可能的。这意味着大量使用生成函数的程序可能无法静态编译。","category":"page"},{"location":"manual/metaprogramming/","page":"元编程","title":"元编程","text":"为了解决这个问题,语言提供用于编写生成函数的通常、非生成的替代实现的语法。应用于上面的 sub2ind 示例,它看起来像这样:","category":"page"},{"location":"manual/metaprogramming/","page":"元编程","title":"元编程","text":"function sub2ind_gen(dims::NTuple{N}, I::Integer...) where N\n if N != length(I)\n throw(ArgumentError(\"Number of dimensions must match number of indices.\"))\n end\n if @generated\n ex = :(I[$N] - 1)\n for i = (N - 1):-1:1\n ex = :(I[$i] - 1 + dims[$i] * $ex)\n end\n return :($ex + 1)\n else\n ind = I[N] - 1\n for i = (N - 1):-1:1\n ind = I[i] - 1 + dims[i]*ind\n end\n return ind + 1\n end\nend","category":"page"},{"location":"manual/metaprogramming/","page":"元编程","title":"元编程","text":"在内部,这段代码创建了函数的两个实现:一个生成函数的实现,其使用 if @generated 中的第一个块,一个通常的函数的实现,其使用 else 块。在 if @generated 块的 then 部分中,代码与其它生成函数具有相同的语义:参数名称引用类型,且代码应返回表达式。可能会出现多个 if @generated 块,在这种情况下,生成函数的实现使用所有的 then 块,而替代实现使用所有的 else 块。","category":"page"},{"location":"manual/metaprogramming/","page":"元编程","title":"元编程","text":"请注意,我们在函数顶部添加了错误检查。此代码对两个版本都是通用的,且是两个版本中的运行时代码(它将被引用并返回为生成函数版本中的表达式)。这意味着局部变量的值和类型在代码生成时不可用——用于代码生成的代码只能看到参数类型。","category":"page"},{"location":"manual/metaprogramming/","page":"元编程","title":"元编程","text":"在这种定义方式中,代码生成功能本质上只是一种可选的优化。如果方便,编译器将使用它,否则可能选择使用通常的实现。这种方式是首选的,因为它允许编译器做出更多决策和以更多方式编译程序,还因为通常代码比由代码生成的代码更易读。但是,使用哪种实现取决于编译器实现细节,因此,两个实现的行为必须相同。","category":"page"},{"location":"devdocs/offset-arrays/#man-custom-indices","page":"Arrays with custom indices","title":"Arrays with custom indices","text":"","category":"section"},{"location":"devdocs/offset-arrays/","page":"Arrays with custom indices","title":"Arrays with custom indices","text":"Conventionally, Julia's arrays are indexed starting at 1, whereas some other languages start numbering at 0, and yet others (e.g., Fortran) allow you to specify arbitrary starting indices. While there is much merit in picking a standard (i.e., 1 for Julia), there are some algorithms which simplify considerably if you can index outside the range 1:size(A,d) (and not just 0:size(A,d)-1, either). To facilitate such computations, Julia supports arrays with arbitrary indices.","category":"page"},{"location":"devdocs/offset-arrays/","page":"Arrays with custom indices","title":"Arrays with custom indices","text":"The purpose of this page is to address the question, \"what do I have to do to support such arrays in my own code?\" First, let's address the simplest case: if you know that your code will never need to handle arrays with unconventional indexing, hopefully the answer is \"nothing.\" Old code, on conventional arrays, should function essentially without alteration as long as it was using the exported interfaces of Julia. If you find it more convenient to just force your users to supply traditional arrays where indexing starts at one, you can add","category":"page"},{"location":"devdocs/offset-arrays/","page":"Arrays with custom indices","title":"Arrays with custom indices","text":"Base.require_one_based_indexing(arrays...)","category":"page"},{"location":"devdocs/offset-arrays/","page":"Arrays with custom indices","title":"Arrays with custom indices","text":"where arrays... is a list of the array objects that you wish to check for anything that violates 1-based indexing.","category":"page"},{"location":"devdocs/offset-arrays/#Generalizing-existing-code","page":"Arrays with custom indices","title":"Generalizing existing code","text":"","category":"section"},{"location":"devdocs/offset-arrays/","page":"Arrays with custom indices","title":"Arrays with custom indices","text":"As an overview, the steps are:","category":"page"},{"location":"devdocs/offset-arrays/","page":"Arrays with custom indices","title":"Arrays with custom indices","text":"replace many uses of size with axes\nreplace 1:length(A) with eachindex(A), or in some cases LinearIndices(A)\nreplace explicit allocations like Array{Int}(undef, size(B)) with similar(Array{Int}, axes(B))","category":"page"},{"location":"devdocs/offset-arrays/","page":"Arrays with custom indices","title":"Arrays with custom indices","text":"These are described in more detail below.","category":"page"},{"location":"devdocs/offset-arrays/#Things-to-watch-out-for","page":"Arrays with custom indices","title":"Things to watch out for","text":"","category":"section"},{"location":"devdocs/offset-arrays/","page":"Arrays with custom indices","title":"Arrays with custom indices","text":"Because unconventional indexing breaks many people's assumptions that all arrays start indexing with 1, there is always the chance that using such arrays will trigger errors. The most frustrating bugs would be incorrect results or segfaults (total crashes of Julia). For example, consider the following function:","category":"page"},{"location":"devdocs/offset-arrays/","page":"Arrays with custom indices","title":"Arrays with custom indices","text":"function mycopy!(dest::AbstractVector, src::AbstractVector)\n length(dest) == length(src) || throw(DimensionMismatch(\"vectors must match\"))\n # OK, now we're safe to use @inbounds, right? (not anymore!)\n for i = 1:length(src)\n @inbounds dest[i] = src[i]\n end\n dest\nend","category":"page"},{"location":"devdocs/offset-arrays/","page":"Arrays with custom indices","title":"Arrays with custom indices","text":"This code implicitly assumes that vectors are indexed from 1; if dest starts at a different index than src, there is a chance that this code would trigger a segfault. (If you do get segfaults, to help locate the cause try running julia with the option --check-bounds=yes.)","category":"page"},{"location":"devdocs/offset-arrays/#Using-axes-for-bounds-checks-and-loop-iteration","page":"Arrays with custom indices","title":"Using axes for bounds checks and loop iteration","text":"","category":"section"},{"location":"devdocs/offset-arrays/","page":"Arrays with custom indices","title":"Arrays with custom indices","text":"axes(A) (reminiscent of size(A)) returns a tuple of AbstractUnitRange{<:Integer} objects, specifying the range of valid indices along each dimension of A. When A has unconventional indexing, the ranges may not start at 1. If you just want the range for a particular dimension d, there is axes(A, d).","category":"page"},{"location":"devdocs/offset-arrays/","page":"Arrays with custom indices","title":"Arrays with custom indices","text":"Base implements a custom range type, OneTo, where OneTo(n) means the same thing as 1:n but in a form that guarantees (via the type system) that the lower index is 1. For any new AbstractArray type, this is the default returned by axes, and it indicates that this array type uses \"conventional\" 1-based indexing.","category":"page"},{"location":"devdocs/offset-arrays/","page":"Arrays with custom indices","title":"Arrays with custom indices","text":"For bounds checking, note that there are dedicated functions checkbounds and checkindex which can sometimes simplify such tests.","category":"page"},{"location":"devdocs/offset-arrays/#Linear-indexing-(LinearIndices)","page":"Arrays with custom indices","title":"Linear indexing (LinearIndices)","text":"","category":"section"},{"location":"devdocs/offset-arrays/","page":"Arrays with custom indices","title":"Arrays with custom indices","text":"Some algorithms are most conveniently (or efficiently) written in terms of a single linear index, A[i] even if A is multi-dimensional. Regardless of the array's native indices, linear indices always range from 1:length(A). However, this raises an ambiguity for one-dimensional arrays (a.k.a., AbstractVector): does v[i] mean linear indexing , or Cartesian indexing with the array's native indices?","category":"page"},{"location":"devdocs/offset-arrays/","page":"Arrays with custom indices","title":"Arrays with custom indices","text":"For this reason, your best option may be to iterate over the array with eachindex(A), or, if you require the indices to be sequential integers, to get the index range by calling LinearIndices(A). This will return axes(A, 1) if A is an AbstractVector, and the equivalent of 1:length(A) otherwise.","category":"page"},{"location":"devdocs/offset-arrays/","page":"Arrays with custom indices","title":"Arrays with custom indices","text":"By this definition, 1-dimensional arrays always use Cartesian indexing with the array's native indices. To help enforce this, it's worth noting that the index conversion functions will throw an error if shape indicates a 1-dimensional array with unconventional indexing (i.e., is a Tuple{UnitRange} rather than a tuple of OneTo). For arrays with conventional indexing, these functions continue to work the same as always.","category":"page"},{"location":"devdocs/offset-arrays/","page":"Arrays with custom indices","title":"Arrays with custom indices","text":"Using axes and LinearIndices, here is one way you could rewrite mycopy!:","category":"page"},{"location":"devdocs/offset-arrays/","page":"Arrays with custom indices","title":"Arrays with custom indices","text":"function mycopy!(dest::AbstractVector, src::AbstractVector)\n axes(dest) == axes(src) || throw(DimensionMismatch(\"vectors must match\"))\n for i in LinearIndices(src)\n @inbounds dest[i] = src[i]\n end\n dest\nend","category":"page"},{"location":"devdocs/offset-arrays/#Allocating-storage-using-generalizations-of-similar","page":"Arrays with custom indices","title":"Allocating storage using generalizations of similar","text":"","category":"section"},{"location":"devdocs/offset-arrays/","page":"Arrays with custom indices","title":"Arrays with custom indices","text":"Storage is often allocated with Array{Int}(undef, dims) or similar(A, args...). When the result needs to match the indices of some other array, this may not always suffice. The generic replacement for such patterns is to use similar(storagetype, shape). storagetype indicates the kind of underlying \"conventional\" behavior you'd like, e.g., Array{Int} or BitArray or even dims->zeros(Float32, dims) (which would allocate an all-zeros array). shape is a tuple of Integer or AbstractUnitRange values, specifying the indices that you want the result to use. Note that a convenient way of producing an all-zeros array that matches the indices of A is simply zeros(A).","category":"page"},{"location":"devdocs/offset-arrays/","page":"Arrays with custom indices","title":"Arrays with custom indices","text":"Let's walk through a couple of explicit examples. First, if A has conventional indices, then similar(Array{Int}, axes(A)) would end up calling Array{Int}(undef, size(A)), and thus return an array. If A is an AbstractArray type with unconventional indexing, then similar(Array{Int}, axes(A)) should return something that \"behaves like\" an Array{Int} but with a shape (including indices) that matches A. (The most obvious implementation is to allocate an Array{Int}(undef, size(A)) and then \"wrap\" it in a type that shifts the indices.)","category":"page"},{"location":"devdocs/offset-arrays/","page":"Arrays with custom indices","title":"Arrays with custom indices","text":"Note also that similar(Array{Int}, (axes(A, 2),)) would allocate an AbstractVector{Int} (i.e., 1-dimensional array) that matches the indices of the columns of A.","category":"page"},{"location":"devdocs/offset-arrays/#Writing-custom-array-types-with-non-1-indexing","page":"Arrays with custom indices","title":"Writing custom array types with non-1 indexing","text":"","category":"section"},{"location":"devdocs/offset-arrays/","page":"Arrays with custom indices","title":"Arrays with custom indices","text":"Most of the methods you'll need to define are standard for any AbstractArray type, see Abstract Arrays. This page focuses on the steps needed to define unconventional indexing.","category":"page"},{"location":"devdocs/offset-arrays/#Custom-AbstractUnitRange-types","page":"Arrays with custom indices","title":"Custom AbstractUnitRange types","text":"","category":"section"},{"location":"devdocs/offset-arrays/","page":"Arrays with custom indices","title":"Arrays with custom indices","text":"If you're writing a non-1 indexed array type, you will want to specialize axes so it returns a UnitRange, or (perhaps better) a custom AbstractUnitRange. The advantage of a custom type is that it \"signals\" the allocation type for functions like similar. If we're writing an array type for which indexing will start at 0, we likely want to begin by creating a new AbstractUnitRange, ZeroRange, where ZeroRange(n) is equivalent to 0:n-1.","category":"page"},{"location":"devdocs/offset-arrays/","page":"Arrays with custom indices","title":"Arrays with custom indices","text":"In general, you should probably not export ZeroRange from your package: there may be other packages that implement their own ZeroRange, and having multiple distinct ZeroRange types is (perhaps counterintuitively) an advantage: ModuleA.ZeroRange indicates that similar should create a ModuleA.ZeroArray, whereas ModuleB.ZeroRange indicates a ModuleB.ZeroArray type. This design allows peaceful coexistence among many different custom array types.","category":"page"},{"location":"devdocs/offset-arrays/","page":"Arrays with custom indices","title":"Arrays with custom indices","text":"Note that the Julia package CustomUnitRanges.jl can sometimes be used to avoid the need to write your own ZeroRange type.","category":"page"},{"location":"devdocs/offset-arrays/#Specializing-axes","page":"Arrays with custom indices","title":"Specializing axes","text":"","category":"section"},{"location":"devdocs/offset-arrays/","page":"Arrays with custom indices","title":"Arrays with custom indices","text":"Once you have your AbstractUnitRange type, then specialize axes:","category":"page"},{"location":"devdocs/offset-arrays/","page":"Arrays with custom indices","title":"Arrays with custom indices","text":"Base.axes(A::ZeroArray) = map(n->ZeroRange(n), A.size)","category":"page"},{"location":"devdocs/offset-arrays/","page":"Arrays with custom indices","title":"Arrays with custom indices","text":"where here we imagine that ZeroArray has a field called size (there would be other ways to implement this).","category":"page"},{"location":"devdocs/offset-arrays/","page":"Arrays with custom indices","title":"Arrays with custom indices","text":"In some cases, the fallback definition for axes(A, d):","category":"page"},{"location":"devdocs/offset-arrays/","page":"Arrays with custom indices","title":"Arrays with custom indices","text":"axes(A::AbstractArray{T,N}, d) where {T,N} = d <= N ? axes(A)[d] : OneTo(1)","category":"page"},{"location":"devdocs/offset-arrays/","page":"Arrays with custom indices","title":"Arrays with custom indices","text":"may not be what you want: you may need to specialize it to return something other than OneTo(1) when d > ndims(A). Likewise, in Base there is a dedicated function axes1 which is equivalent to axes(A, 1) but which avoids checking (at runtime) whether ndims(A) > 0. (This is purely a performance optimization.) It is defined as:","category":"page"},{"location":"devdocs/offset-arrays/","page":"Arrays with custom indices","title":"Arrays with custom indices","text":"axes1(A::AbstractArray{T,0}) where {T} = OneTo(1)\naxes1(A::AbstractArray) = axes(A)[1]","category":"page"},{"location":"devdocs/offset-arrays/","page":"Arrays with custom indices","title":"Arrays with custom indices","text":"If the first of these (the zero-dimensional case) is problematic for your custom array type, be sure to specialize it appropriately.","category":"page"},{"location":"devdocs/offset-arrays/#Specializing-similar","page":"Arrays with custom indices","title":"Specializing similar","text":"","category":"section"},{"location":"devdocs/offset-arrays/","page":"Arrays with custom indices","title":"Arrays with custom indices","text":"Given your custom ZeroRange type, then you should also add the following two specializations for similar:","category":"page"},{"location":"devdocs/offset-arrays/","page":"Arrays with custom indices","title":"Arrays with custom indices","text":"function Base.similar(A::AbstractArray, T::Type, shape::Tuple{ZeroRange,Vararg{ZeroRange}})\n # body\nend\n\nfunction Base.similar(f::Union{Function,DataType}, shape::Tuple{ZeroRange,Vararg{ZeroRange}})\n # body\nend","category":"page"},{"location":"devdocs/offset-arrays/","page":"Arrays with custom indices","title":"Arrays with custom indices","text":"Both of these should allocate your custom array type.","category":"page"},{"location":"devdocs/offset-arrays/#Specializing-reshape","page":"Arrays with custom indices","title":"Specializing reshape","text":"","category":"section"},{"location":"devdocs/offset-arrays/","page":"Arrays with custom indices","title":"Arrays with custom indices","text":"Optionally, define a method","category":"page"},{"location":"devdocs/offset-arrays/","page":"Arrays with custom indices","title":"Arrays with custom indices","text":"Base.reshape(A::AbstractArray, shape::Tuple{ZeroRange,Vararg{ZeroRange}}) = ...","category":"page"},{"location":"devdocs/offset-arrays/","page":"Arrays with custom indices","title":"Arrays with custom indices","text":"and you can reshape an array so that the result has custom indices.","category":"page"},{"location":"devdocs/offset-arrays/#For-objects-that-mimic-AbstractArray-but-are-not-subtypes","page":"Arrays with custom indices","title":"For objects that mimic AbstractArray but are not subtypes","text":"","category":"section"},{"location":"devdocs/offset-arrays/","page":"Arrays with custom indices","title":"Arrays with custom indices","text":"has_offset_axes depends on having axes defined for the objects you call it on. If there is some reason you don't have an axes method defined for your object, consider defining a method","category":"page"},{"location":"devdocs/offset-arrays/","page":"Arrays with custom indices","title":"Arrays with custom indices","text":"Base.has_offset_axes(obj::MyNon1IndexedArraylikeObject) = true","category":"page"},{"location":"devdocs/offset-arrays/","page":"Arrays with custom indices","title":"Arrays with custom indices","text":"This will allow code that assumes 1-based indexing to detect a problem and throw a helpful error, rather than returning incorrect results or segfaulting julia.","category":"page"},{"location":"devdocs/offset-arrays/#Catching-errors","page":"Arrays with custom indices","title":"Catching errors","text":"","category":"section"},{"location":"devdocs/offset-arrays/","page":"Arrays with custom indices","title":"Arrays with custom indices","text":"If your new array type triggers errors in other code, one helpful debugging step can be to comment out @boundscheck in your getindex and setindex! implementation. This will ensure that every element access checks bounds. Or, restart julia with --check-bounds=yes.","category":"page"},{"location":"devdocs/offset-arrays/","page":"Arrays with custom indices","title":"Arrays with custom indices","text":"In some cases it may also be helpful to temporarily disable size and length for your new array type, since code that makes incorrect assumptions frequently uses these functions.","category":"page"},{"location":"devdocs/boundscheck/#边界检查","page":"边界检查","title":"边界检查","text":"","category":"section"},{"location":"devdocs/boundscheck/","page":"边界检查","title":"边界检查","text":"和许多其他现代编程语言一样,Julia 在访问数组元素的时候也要通过边界检查来确保程序安全。当循环次数很多,或者在其他性能敏感的场景下,你可能希望不进行边界检查以提高运行时性能。比如要使用矢量 (SIMD) 指令,循环体就不能有分支语句,因此无法进行边界检查。Julia 提供了一个宏 @inbounds(...) 来告诉编译器在指定语句块不进行边界检查。用户自定义的数组类型可以通过宏 @boundscheck(...) 来达到上下文敏感的代码选择目的。","category":"page"},{"location":"devdocs/boundscheck/#移除边界检查","page":"边界检查","title":"移除边界检查","text":"","category":"section"},{"location":"devdocs/boundscheck/","page":"边界检查","title":"边界检查","text":"宏 @boundscheck(...) 把代码块标记为要执行边界检查。但当这些代码块被被宏 @inbounds(...) 标记的代码包裹时,它们可能会被编译器移除。仅当@boundscheck(...) 代码块被调用函数包裹时,编译器会移除它们。比如你可能这样写的 sum 方法: ","category":"page"},{"location":"devdocs/boundscheck/","page":"边界检查","title":"边界检查","text":"function sum(A::AbstractArray)\n r = zero(eltype(A))\n for i in eachindex(A)\n @inbounds r += A[i]\n end\n return r\nend","category":"page"},{"location":"devdocs/boundscheck/","page":"边界检查","title":"边界检查","text":"使用自定义的类数组类型 MyArray,我们有:","category":"page"},{"location":"devdocs/boundscheck/","page":"边界检查","title":"边界检查","text":"@inline getindex(A::MyArray, i::Real) = (@boundscheck checkbounds(A,i); A.data[to_index(i)])","category":"page"},{"location":"devdocs/boundscheck/","page":"边界检查","title":"边界检查","text":"当 getindex 被 sum 包裹时,对 checkbounds(A,i) 的调用会被忽略。如果存在多层包裹,最多只有一个 @boundscheck 被忽略。这个规则用来防止将来代码被改变时潜在的多余忽略。","category":"page"},{"location":"devdocs/boundscheck/#Propagating-inbounds","page":"边界检查","title":"Propagating inbounds","text":"","category":"section"},{"location":"devdocs/boundscheck/","page":"边界检查","title":"边界检查","text":"There may be certain scenarios where for code-organization reasons you want more than one layer between the @inbounds and @boundscheck declarations. For instance, the default getindex methods have the chain getindex(A::AbstractArray, i::Real) calls getindex(IndexStyle(A), A, i) calls _getindex(::IndexLinear, A, i).","category":"page"},{"location":"devdocs/boundscheck/","page":"边界检查","title":"边界检查","text":"To override the \"one layer of inlining\" rule, a function may be marked with Base.@propagate_inbounds to propagate an inbounds context (or out of bounds context) through one additional layer of inlining.","category":"page"},{"location":"devdocs/boundscheck/#The-bounds-checking-call-hierarchy","page":"边界检查","title":"The bounds checking call hierarchy","text":"","category":"section"},{"location":"devdocs/boundscheck/","page":"边界检查","title":"边界检查","text":"The overall hierarchy is:","category":"page"},{"location":"devdocs/boundscheck/","page":"边界检查","title":"边界检查","text":"checkbounds(A, I...) which calls\ncheckbounds(Bool, A, I...) which calls\ncheckbounds_indices(Bool, axes(A), I) which recursively calls\ncheckindex for each dimension","category":"page"},{"location":"devdocs/boundscheck/","page":"边界检查","title":"边界检查","text":"Here A is the array, and I contains the \"requested\" indices. axes(A) returns a tuple of \"permitted\" indices of A.","category":"page"},{"location":"devdocs/boundscheck/","page":"边界检查","title":"边界检查","text":"checkbounds(A, I...) throws an error if the indices are invalid, whereas checkbounds(Bool, A, I...) returns false in that circumstance. checkbounds_indices discards any information about the array other than its axes tuple, and performs a pure indices-vs-indices comparison: this allows relatively few compiled methods to serve a huge variety of array types. Indices are specified as tuples, and are usually compared in a 1-1 fashion with individual dimensions handled by calling another important function, checkindex: typically,","category":"page"},{"location":"devdocs/boundscheck/","page":"边界检查","title":"边界检查","text":"checkbounds_indices(Bool, (IA1, IA...), (I1, I...)) = checkindex(Bool, IA1, I1) &\n checkbounds_indices(Bool, IA, I)","category":"page"},{"location":"devdocs/boundscheck/","page":"边界检查","title":"边界检查","text":"so checkindex checks a single dimension. All of these functions, including the unexported checkbounds_indices have docstrings accessible with ? .","category":"page"},{"location":"devdocs/boundscheck/","page":"边界检查","title":"边界检查","text":"If you have to customize bounds checking for a specific array type, you should specialize checkbounds(Bool, A, I...). However, in most cases you should be able to rely on checkbounds_indices as long as you supply useful axes for your array type.","category":"page"},{"location":"devdocs/boundscheck/","page":"边界检查","title":"边界检查","text":"If you have novel index types, first consider specializing checkindex, which handles a single index for a particular dimension of an array. If you have a custom multidimensional index type (similar to CartesianIndex), then you may have to consider specializing checkbounds_indices.","category":"page"},{"location":"devdocs/boundscheck/","page":"边界检查","title":"边界检查","text":"Note this hierarchy has been designed to reduce the likelihood of method ambiguities. We try to make checkbounds the place to specialize on array type, and try to avoid specializations on index types; conversely, checkindex is intended to be specialized only on index type (especially, the last argument).","category":"page"},{"location":"devdocs/boundscheck/#Emit-bounds-checks","page":"边界检查","title":"Emit bounds checks","text":"","category":"section"},{"location":"devdocs/boundscheck/","page":"边界检查","title":"边界检查","text":"Julia can be launched with --check-bounds={yes|no|auto} to emit bounds checks always, never, or respect @inbounds declarations.","category":"page"},{"location":"stdlib/Random/#随机数","page":"随机数","title":"随机数","text":"","category":"section"},{"location":"stdlib/Random/","page":"随机数","title":"随机数","text":"DocTestSetup = :(using Random)","category":"page"},{"location":"stdlib/Random/","page":"随机数","title":"随机数","text":"Random number generation in Julia uses the Xoshiro256++ algorithm by default, with per-Task state. Other RNG types can be plugged in by inheriting the AbstractRNG type; they can then be used to obtain multiple streams of random numbers. Besides the default TaskLocalRNG type, the Random package also provides MersenneTwister, RandomDevice (which exposes OS-provided entropy), and Xoshiro (for explicitly-managed Xoshiro256++ streams).","category":"page"},{"location":"stdlib/Random/","page":"随机数","title":"随机数","text":"Most functions related to random generation accept an optional AbstractRNG object as first argument. Some also accept dimension specifications dims... (which can also be given as a tuple) to generate arrays of random values. In a multi-threaded program, you should generally use different RNG objects from different threads or tasks in order to be thread-safe. However, the default RNG is thread-safe as of Julia 1.3 (using a per-thread RNG up to version 1.6, and per-task thereafter).","category":"page"},{"location":"stdlib/Random/","page":"随机数","title":"随机数","text":"The provided RNGs can generate uniform random numbers of the following types: Float16, Float32, Float64, BigFloat, Bool, Int8, UInt8, Int16, UInt16, Int32, UInt32, Int64, UInt64, Int128, UInt128, BigInt (or complex numbers of those types). Random floating point numbers are generated uniformly in 0 1). As BigInt represents unbounded integers, the interval must be specified (e.g. rand(big.(1:6))).","category":"page"},{"location":"stdlib/Random/","page":"随机数","title":"随机数","text":"另外,正态和指数分布是针对某些 AbstractFloat 和 Complex 类型,详细内容见 randn 和 randexp。","category":"page"},{"location":"stdlib/Random/","page":"随机数","title":"随机数","text":"warning: Warning\nBecause the precise way in which random numbers are generated is considered an implementation detail, bug fixes and speed improvements may change the stream of numbers that are generated after a version change. Relying on a specific seed or generated stream of numbers during unit testing is thus discouraged - consider testing properties of the methods in question instead.","category":"page"},{"location":"stdlib/Random/#Random-numbers-module","page":"随机数","title":"Random numbers module","text":"","category":"section"},{"location":"stdlib/Random/","page":"随机数","title":"随机数","text":"Random.Random","category":"page"},{"location":"stdlib/Random/#Random.Random","page":"随机数","title":"Random.Random","text":"Random\n\nSupport for generating random numbers. Provides rand, randn, AbstractRNG, MersenneTwister, and RandomDevice.\n\n\n\n\n\n","category":"module"},{"location":"stdlib/Random/#Random-generation-functions","page":"随机数","title":"Random generation functions","text":"","category":"section"},{"location":"stdlib/Random/","page":"随机数","title":"随机数","text":"Random.rand\nRandom.rand!\nRandom.bitrand\nRandom.randn\nRandom.randn!\nRandom.randexp\nRandom.randexp!\nRandom.randstring","category":"page"},{"location":"stdlib/Random/#Base.rand","page":"随机数","title":"Base.rand","text":"rand([rng=GLOBAL_RNG], [S], [dims...])\n\nPick a random element or array of random elements from the set of values specified by S; S can be\n\nan indexable collection (for example 1:9 or ('x', \"y\", :z)),\nan AbstractDict or AbstractSet object,\na string (considered as a collection of characters), or\na type: the set of values to pick from is then equivalent to typemin(S):typemax(S) for integers (this is not applicable to BigInt), to 0 1) for floating point numbers and to 0 1)+i0 1) for complex floating point numbers;\n\nS defaults to Float64. When only one argument is passed besides the optional rng and is a Tuple, it is interpreted as a collection of values (S) and not as dims.\n\ncompat: Julia 1.1\nSupport for S as a tuple requires at least Julia 1.1.\n\nExamples\n\njulia> rand(Int, 2)\n2-element Array{Int64,1}:\n 1339893410598768192\n 1575814717733606317\n\njulia> using Random\n\njulia> rand(MersenneTwister(0), Dict(1=>2, 3=>4))\n1=>2\n\njulia> rand((2, 3))\n3\n\njulia> rand(Float64, (2, 3))\n2×3 Array{Float64,2}:\n 0.999717 0.0143835 0.540787\n 0.696556 0.783855 0.938235\n\nnote: Note\nThe complexity of rand(rng, s::Union{AbstractDict,AbstractSet}) is linear in the length of s, unless an optimized method with constant complexity is available, which is the case for Dict, Set and dense BitSets. For more than a few calls, use rand(rng, collect(s)) instead, or either rand(rng, Dict(s)) or rand(rng, Set(s)) as appropriate.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/Random/#Random.rand!","page":"随机数","title":"Random.rand!","text":"rand!([rng=GLOBAL_RNG], A, [S=eltype(A)])\n\nPopulate the array A with random values. If S is specified (S can be a type or a collection, cf. rand for details), the values are picked randomly from S. This is equivalent to copyto!(A, rand(rng, S, size(A))) but without allocating a new array.\n\nExamples\n\njulia> rng = MersenneTwister(1234);\n\njulia> rand!(rng, zeros(5))\n5-element Vector{Float64}:\n 0.5908446386657102\n 0.7667970365022592\n 0.5662374165061859\n 0.4600853424625171\n 0.7940257103317943\n\n\n\n\n\n","category":"function"},{"location":"stdlib/Random/#Random.bitrand","page":"随机数","title":"Random.bitrand","text":"bitrand([rng=GLOBAL_RNG], [dims...])\n\nGenerate a BitArray of random boolean values.\n\nExamples\n\njulia> rng = MersenneTwister(1234);\n\njulia> bitrand(rng, 10)\n10-element BitVector:\n 0\n 0\n 0\n 0\n 1\n 0\n 0\n 0\n 1\n 1\n\n\n\n\n\n","category":"function"},{"location":"stdlib/Random/#Base.randn","page":"随机数","title":"Base.randn","text":"randn([rng=GLOBAL_RNG], [T=Float64], [dims...])\n\nGenerate a normally-distributed random number of type T with mean 0 and standard deviation 1. Optionally generate an array of normally-distributed random numbers. The Base module currently provides an implementation for the types Float16, Float32, and Float64 (the default), and their Complex counterparts. When the type argument is complex, the values are drawn from the circularly symmetric complex normal distribution of variance 1 (corresponding to real and imaginary part having independent normal distribution with mean zero and variance 1/2).\n\nExamples\n\njulia> using Random\n\njulia> rng = MersenneTwister(1234);\n\njulia> randn(rng, ComplexF64)\n0.6133070881429037 - 0.6376291670853887im\n\njulia> randn(rng, ComplexF32, (2, 3))\n2×3 Matrix{ComplexF32}:\n -0.349649-0.638457im 0.376756-0.192146im -0.396334-0.0136413im\n 0.611224+1.56403im 0.355204-0.365563im 0.0905552+1.31012im\n\n\n\n\n\n","category":"function"},{"location":"stdlib/Random/#Random.randn!","page":"随机数","title":"Random.randn!","text":"randn!([rng=GLOBAL_RNG], A::AbstractArray) -> A\n\nFill the array A with normally-distributed (mean 0, standard deviation 1) random numbers. Also see the rand function.\n\nExamples\n\njulia> rng = MersenneTwister(1234);\n\njulia> randn!(rng, zeros(5))\n5-element Vector{Float64}:\n 0.8673472019512456\n -0.9017438158568171\n -0.4944787535042339\n -0.9029142938652416\n 0.8644013132535154\n\n\n\n\n\n","category":"function"},{"location":"stdlib/Random/#Random.randexp","page":"随机数","title":"Random.randexp","text":"randexp([rng=GLOBAL_RNG], [T=Float64], [dims...])\n\nGenerate a random number of type T according to the exponential distribution with scale 1. Optionally generate an array of such random numbers. The Base module currently provides an implementation for the types Float16, Float32, and Float64 (the default).\n\nExamples\n\njulia> rng = MersenneTwister(1234);\n\njulia> randexp(rng, Float32)\n2.4835055f0\n\njulia> randexp(rng, 3, 3)\n3×3 Matrix{Float64}:\n 1.5167 1.30652 0.344435\n 0.604436 2.78029 0.418516\n 0.695867 0.693292 0.643644\n\n\n\n\n\n","category":"function"},{"location":"stdlib/Random/#Random.randexp!","page":"随机数","title":"Random.randexp!","text":"randexp!([rng=GLOBAL_RNG], A::AbstractArray) -> A\n\nFill the array A with random numbers following the exponential distribution (with scale 1).\n\nExamples\n\njulia> rng = MersenneTwister(1234);\n\njulia> randexp!(rng, zeros(5))\n5-element Vector{Float64}:\n 2.4835053723904896\n 1.516703605376473\n 0.6044364871025417\n 0.6958665886385867\n 1.3065196315496677\n\n\n\n\n\n","category":"function"},{"location":"stdlib/Random/#Random.randstring","page":"随机数","title":"Random.randstring","text":"randstring([rng=GLOBAL_RNG], [chars], [len=8])\n\nCreate a random string of length len, consisting of characters from chars, which defaults to the set of upper- and lower-case letters and the digits 0-9. The optional rng argument specifies a random number generator, see Random Numbers.\n\nExamples\n\njulia> Random.seed!(3); randstring()\n\"Lxz5hUwn\"\n\njulia> randstring(MersenneTwister(3), 'a':'z', 6)\n\"ocucay\"\n\njulia> randstring(\"ACGT\")\n\"TGCTCCTC\"\n\nnote: Note\nchars can be any collection of characters, of type Char or UInt8 (more efficient), provided rand can randomly pick characters from it.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/Random/#Subsequences,-permutations-and-shuffling","page":"随机数","title":"Subsequences, permutations and shuffling","text":"","category":"section"},{"location":"stdlib/Random/","page":"随机数","title":"随机数","text":"Random.randsubseq\nRandom.randsubseq!\nRandom.randperm\nRandom.randperm!\nRandom.randcycle\nRandom.randcycle!\nRandom.shuffle\nRandom.shuffle!","category":"page"},{"location":"stdlib/Random/#Random.randsubseq","page":"随机数","title":"Random.randsubseq","text":"randsubseq([rng=GLOBAL_RNG,] A, p) -> Vector\n\nReturn a vector consisting of a random subsequence of the given array A, where each element of A is included (in order) with independent probability p. (Complexity is linear in p*length(A), so this function is efficient even if p is small and A is large.) Technically, this process is known as \"Bernoulli sampling\" of A.\n\nExamples\n\njulia> rng = MersenneTwister(1234);\n\njulia> randsubseq(rng, 1:8, 0.3)\n2-element Vector{Int64}:\n 7\n 8\n\n\n\n\n\n","category":"function"},{"location":"stdlib/Random/#Random.randsubseq!","page":"随机数","title":"Random.randsubseq!","text":"randsubseq!([rng=GLOBAL_RNG,] S, A, p)\n\nLike randsubseq, but the results are stored in S (which is resized as needed).\n\nExamples\n\njulia> rng = MersenneTwister(1234);\n\njulia> S = Int64[];\n\njulia> randsubseq!(rng, S, 1:8, 0.3)\n2-element Vector{Int64}:\n 7\n 8\n\njulia> S\n2-element Vector{Int64}:\n 7\n 8\n\n\n\n\n\n","category":"function"},{"location":"stdlib/Random/#Random.randperm","page":"随机数","title":"Random.randperm","text":"randperm([rng=GLOBAL_RNG,] n::Integer)\n\nConstruct a random permutation of length n. The optional rng argument specifies a random number generator (see Random Numbers). The element type of the result is the same as the type of n.\n\nTo randomly permute an arbitrary vector, see shuffle or shuffle!.\n\ncompat: Julia 1.1\nIn Julia 1.1 randperm returns a vector v with eltype(v) == typeof(n) while in Julia 1.0 eltype(v) == Int.\n\nExamples\n\njulia> randperm(MersenneTwister(1234), 4)\n4-element Vector{Int64}:\n 2\n 1\n 4\n 3\n\n\n\n\n\n","category":"function"},{"location":"stdlib/Random/#Random.randperm!","page":"随机数","title":"Random.randperm!","text":"randperm!([rng=GLOBAL_RNG,] A::Array{<:Integer})\n\nConstruct in A a random permutation of length length(A). The optional rng argument specifies a random number generator (see Random Numbers). To randomly permute an arbitrary vector, see shuffle or shuffle!.\n\nExamples\n\njulia> randperm!(MersenneTwister(1234), Vector{Int}(undef, 4))\n4-element Vector{Int64}:\n 2\n 1\n 4\n 3\n\n\n\n\n\n","category":"function"},{"location":"stdlib/Random/#Random.randcycle","page":"随机数","title":"Random.randcycle","text":"randcycle([rng=GLOBAL_RNG,] n::Integer)\n\nConstruct a random cyclic permutation of length n. The optional rng argument specifies a random number generator, see Random Numbers. The element type of the result is the same as the type of n.\n\ncompat: Julia 1.1\nIn Julia 1.1 randcycle returns a vector v with eltype(v) == typeof(n) while in Julia 1.0 eltype(v) == Int.\n\nExamples\n\njulia> randcycle(MersenneTwister(1234), 6)\n6-element Vector{Int64}:\n 3\n 5\n 4\n 6\n 1\n 2\n\n\n\n\n\n","category":"function"},{"location":"stdlib/Random/#Random.randcycle!","page":"随机数","title":"Random.randcycle!","text":"randcycle!([rng=GLOBAL_RNG,] A::Array{<:Integer})\n\nConstruct in A a random cyclic permutation of length length(A). The optional rng argument specifies a random number generator, see Random Numbers.\n\nExamples\n\njulia> randcycle!(MersenneTwister(1234), Vector{Int}(undef, 6))\n6-element Vector{Int64}:\n 3\n 5\n 4\n 6\n 1\n 2\n\n\n\n\n\n","category":"function"},{"location":"stdlib/Random/#Random.shuffle","page":"随机数","title":"Random.shuffle","text":"shuffle([rng=GLOBAL_RNG,] v::AbstractArray)\n\nReturn a randomly permuted copy of v. The optional rng argument specifies a random number generator (see Random Numbers). To permute v in-place, see shuffle!. To obtain randomly permuted indices, see randperm.\n\nExamples\n\njulia> rng = MersenneTwister(1234);\n\njulia> shuffle(rng, Vector(1:10))\n10-element Vector{Int64}:\n 6\n 1\n 10\n 2\n 3\n 9\n 5\n 7\n 4\n 8\n\n\n\n\n\n","category":"function"},{"location":"stdlib/Random/#Random.shuffle!","page":"随机数","title":"Random.shuffle!","text":"shuffle!([rng=GLOBAL_RNG,] v::AbstractArray)\n\nIn-place version of shuffle: randomly permute v in-place, optionally supplying the random-number generator rng.\n\nExamples\n\njulia> rng = MersenneTwister(1234);\n\njulia> shuffle!(rng, Vector(1:16))\n16-element Vector{Int64}:\n 2\n 15\n 5\n 14\n 1\n 9\n 10\n 6\n 11\n 3\n 16\n 7\n 4\n 12\n 8\n 13\n\n\n\n\n\n","category":"function"},{"location":"stdlib/Random/#Generators-(creation-and-seeding)","page":"随机数","title":"Generators (creation and seeding)","text":"","category":"section"},{"location":"stdlib/Random/","page":"随机数","title":"随机数","text":"Random.seed!\nRandom.AbstractRNG\nRandom.TaskLocalRNG\nRandom.Xoshiro\nRandom.MersenneTwister\nRandom.RandomDevice","category":"page"},{"location":"stdlib/Random/#Random.seed!","page":"随机数","title":"Random.seed!","text":"seed!([rng=GLOBAL_RNG], seed) -> rng\nseed!([rng=GLOBAL_RNG]) -> rng\n\nReseed the random number generator: rng will give a reproducible sequence of numbers if and only if a seed is provided. Some RNGs don't accept a seed, like RandomDevice. After the call to seed!, rng is equivalent to a newly created object initialized with the same seed.\n\nIf rng is not specified, it defaults to seeding the state of the shared task-local generator.\n\nExamples\n\njulia> Random.seed!(1234);\n\njulia> x1 = rand(2)\n2-element Array{Float64,1}:\n 0.590845\n 0.766797\n\njulia> Random.seed!(1234);\n\njulia> x2 = rand(2)\n2-element Array{Float64,1}:\n 0.590845\n 0.766797\n\njulia> x1 == x2\ntrue\n\njulia> rng = MersenneTwister(1234); rand(rng, 2) == x1\ntrue\n\njulia> MersenneTwister(1) == Random.seed!(rng, 1)\ntrue\n\njulia> rand(Random.seed!(rng), Bool) # not reproducible\ntrue\n\njulia> rand(Random.seed!(rng), Bool)\nfalse\n\njulia> rand(MersenneTwister(), Bool) # not reproducible either\ntrue\n\n\n\n\n\n","category":"function"},{"location":"stdlib/Random/#Random.AbstractRNG","page":"随机数","title":"Random.AbstractRNG","text":"AbstractRNG\n\nSupertype for random number generators such as MersenneTwister and RandomDevice.\n\n\n\n\n\n","category":"type"},{"location":"stdlib/Random/#Random.TaskLocalRNG","page":"随机数","title":"Random.TaskLocalRNG","text":"TaskLocalRNG\n\nThe TaskLocalRNG has state that is local to its task, not its thread. It is seeded upon task creation, from the state of its parent task. Therefore, task creation is an event that changes the parent's RNG state.\n\nAs an upside, the TaskLocalRNG is pretty fast, and permits reproducible multithreaded simulations (barring race conditions), independent of scheduler decisions. As long as the number of threads is not used to make decisions on task creation, simulation results are also independent of the number of available threads / CPUs. The random stream should not depend on hardware specifics, up to endianness and possibly word size.\n\nUsing or seeding the RNG of any other task than the one returned by current_task() is undefined behavior: it will work most of the time, and may sometimes fail silently.\n\n\n\n\n\n","category":"type"},{"location":"stdlib/Random/#Random.Xoshiro","page":"随机数","title":"Random.Xoshiro","text":"Xoshiro(seed)\nXoshiro()\n\nXoshiro256++ is a fast pseudorandom number generator described by David Blackman and Sebastiano Vigna in \"Scrambled Linear Pseudorandom Number Generators\", ACM Trans. Math. Softw., 2021. Reference implementation is available at http://prng.di.unimi.it\n\nApart from the high speed, Xoshiro has a small memory footprint, making it suitable for applications where many different random states need to be held for long time.\n\nJulia's Xoshiro implementation has a bulk-generation mode; this seeds new virtual PRNGs from the parent, and uses SIMD to generate in parallel (i.e. the bulk stream consists of multiple interleaved xoshiro instances). The virtual PRNGs are discarded once the bulk request has been serviced (and should cause no heap allocations).\n\nExamples\n\njulia> using Random\n\njulia> rng = Xoshiro(1234);\n\njulia> x1 = rand(rng, 2)\n2-element Vector{Float64}:\n 0.32597672886359486\n 0.5490511363155669\n\njulia> rng = Xoshiro(1234);\n\njulia> x2 = rand(rng, 2)\n2-element Vector{Float64}:\n 0.32597672886359486\n 0.5490511363155669\n\njulia> x1 == x2\ntrue\n\n\n\n\n\n","category":"type"},{"location":"stdlib/Random/#Random.MersenneTwister","page":"随机数","title":"Random.MersenneTwister","text":"MersenneTwister(seed)\nMersenneTwister()\n\nCreate a MersenneTwister RNG object. Different RNG objects can have their own seeds, which may be useful for generating different streams of random numbers. The seed may be a non-negative integer or a vector of UInt32 integers. If no seed is provided, a randomly generated one is created (using entropy from the system). See the seed! function for reseeding an already existing MersenneTwister object.\n\nExamples\n\njulia> rng = MersenneTwister(1234);\n\njulia> x1 = rand(rng, 2)\n2-element Vector{Float64}:\n 0.5908446386657102\n 0.7667970365022592\n\njulia> rng = MersenneTwister(1234);\n\njulia> x2 = rand(rng, 2)\n2-element Vector{Float64}:\n 0.5908446386657102\n 0.7667970365022592\n\njulia> x1 == x2\ntrue\n\n\n\n\n\n","category":"type"},{"location":"stdlib/Random/#Random.RandomDevice","page":"随机数","title":"Random.RandomDevice","text":"RandomDevice()\n\nCreate a RandomDevice RNG object. Two such objects will always generate different streams of random numbers. The entropy is obtained from the operating system.\n\n\n\n\n\n","category":"type"},{"location":"stdlib/Random/#Hooking-into-the-Random-API","page":"随机数","title":"Hooking into the Random API","text":"","category":"section"},{"location":"stdlib/Random/","page":"随机数","title":"随机数","text":"There are two mostly orthogonal ways to extend Random functionalities:","category":"page"},{"location":"stdlib/Random/","page":"随机数","title":"随机数","text":"generating random values of custom types\ncreating new generators","category":"page"},{"location":"stdlib/Random/","page":"随机数","title":"随机数","text":"The API for 1) is quite functional, but is relatively recent so it may still have to evolve in subsequent releases of the Random module. For example, it's typically sufficient to implement one rand method in order to have all other usual methods work automatically.","category":"page"},{"location":"stdlib/Random/","page":"随机数","title":"随机数","text":"The API for 2) is still rudimentary, and may require more work than strictly necessary from the implementor, in order to support usual types of generated values.","category":"page"},{"location":"stdlib/Random/#Generating-random-values-of-custom-types","page":"随机数","title":"Generating random values of custom types","text":"","category":"section"},{"location":"stdlib/Random/","page":"随机数","title":"随机数","text":"Generating random values for some distributions may involve various trade-offs. Pre-computed values, such as an alias table for discrete distributions, or “squeezing” functions for univariate distributions, can speed up sampling considerably. How much information should be pre-computed can depend on the number of values we plan to draw from a distribution. Also, some random number generators can have certain properties that various algorithms may want to exploit.","category":"page"},{"location":"stdlib/Random/","page":"随机数","title":"随机数","text":"The Random module defines a customizable framework for obtaining random values that can address these issues. Each invocation of rand generates a sampler which can be customized with the above trade-offs in mind, by adding methods to Sampler, which in turn can dispatch on the random number generator, the object that characterizes the distribution, and a suggestion for the number of repetitions. Currently, for the latter, Val{1} (for a single sample) and Val{Inf} (for an arbitrary number) are used, with Random.Repetition an alias for both.","category":"page"},{"location":"stdlib/Random/","page":"随机数","title":"随机数","text":"The object returned by Sampler is then used to generate the random values. When implementing the random generation interface for a value X that can be sampled from, the implementor should define the method","category":"page"},{"location":"stdlib/Random/","page":"随机数","title":"随机数","text":"rand(rng, sampler)","category":"page"},{"location":"stdlib/Random/","page":"随机数","title":"随机数","text":"for the particular sampler returned by Sampler(rng, X, repetition).","category":"page"},{"location":"stdlib/Random/","page":"随机数","title":"随机数","text":"Samplers can be arbitrary values that implement rand(rng, sampler), but for most applications the following predefined samplers may be sufficient:","category":"page"},{"location":"stdlib/Random/","page":"随机数","title":"随机数","text":"SamplerType{T}() can be used for implementing samplers that draw from type T (e.g. rand(Int)). This is the default returned by Sampler for types.\nSamplerTrivial(self) is a simple wrapper for self, which can be accessed with []. This is the recommended sampler when no pre-computed information is needed (e.g. rand(1:3)), and is the default returned by Sampler for values.\nSamplerSimple(self, data) also contains the additional data field, which can be used to store arbitrary pre-computed values, which should be computed in a custom method of Sampler.","category":"page"},{"location":"stdlib/Random/","page":"随机数","title":"随机数","text":"We provide examples for each of these. We assume here that the choice of algorithm is independent of the RNG, so we use AbstractRNG in our signatures.","category":"page"},{"location":"stdlib/Random/","page":"随机数","title":"随机数","text":"Random.Sampler\nRandom.SamplerType\nRandom.SamplerTrivial\nRandom.SamplerSimple","category":"page"},{"location":"stdlib/Random/#Random.Sampler","page":"随机数","title":"Random.Sampler","text":"Sampler(rng, x, repetition = Val(Inf))\n\nReturn a sampler object that can be used to generate random values from rng for x.\n\nWhen sp = Sampler(rng, x, repetition), rand(rng, sp) will be used to draw random values, and should be defined accordingly.\n\nrepetition can be Val(1) or Val(Inf), and should be used as a suggestion for deciding the amount of precomputation, if applicable.\n\nRandom.SamplerType and Random.SamplerTrivial are default fallbacks for types and values, respectively. Random.SamplerSimple can be used to store pre-computed values without defining extra types for only this purpose.\n\n\n\n\n\n","category":"type"},{"location":"stdlib/Random/#Random.SamplerType","page":"随机数","title":"Random.SamplerType","text":"SamplerType{T}()\n\nA sampler for types, containing no other information. The default fallback for Sampler when called with types.\n\n\n\n\n\n","category":"type"},{"location":"stdlib/Random/#Random.SamplerTrivial","page":"随机数","title":"Random.SamplerTrivial","text":"SamplerTrivial(x)\n\nCreate a sampler that just wraps the given value x. This is the default fall-back for values. The eltype of this sampler is equal to eltype(x).\n\nThe recommended use case is sampling from values without precomputed data.\n\n\n\n\n\n","category":"type"},{"location":"stdlib/Random/#Random.SamplerSimple","page":"随机数","title":"Random.SamplerSimple","text":"SamplerSimple(x, data)\n\nCreate a sampler that wraps the given value x and the data. The eltype of this sampler is equal to eltype(x).\n\nThe recommended use case is sampling from values with precomputed data.\n\n\n\n\n\n","category":"type"},{"location":"stdlib/Random/","page":"随机数","title":"随机数","text":"Decoupling pre-computation from actually generating the values is part of the API, and is also available to the user. As an example, assume that rand(rng, 1:20) has to be called repeatedly in a loop: the way to take advantage of this decoupling is as follows:","category":"page"},{"location":"stdlib/Random/","page":"随机数","title":"随机数","text":"rng = MersenneTwister()\nsp = Random.Sampler(rng, 1:20) # or Random.Sampler(MersenneTwister, 1:20)\nfor x in X\n n = rand(rng, sp) # similar to n = rand(rng, 1:20)\n # use n\nend","category":"page"},{"location":"stdlib/Random/","page":"随机数","title":"随机数","text":"This is the mechanism that is also used in the standard library, e.g. by the default implementation of random array generation (like in rand(1:20, 10)).","category":"page"},{"location":"stdlib/Random/#Generating-values-from-a-type","page":"随机数","title":"Generating values from a type","text":"","category":"section"},{"location":"stdlib/Random/","page":"随机数","title":"随机数","text":"Given a type T, it's currently assumed that if rand(T) is defined, an object of type T will be produced. SamplerType is the default sampler for types. In order to define random generation of values of type T, the rand(rng::AbstractRNG, ::Random.SamplerType{T}) method should be defined, and should return values what rand(rng, T) is expected to return.","category":"page"},{"location":"stdlib/Random/","page":"随机数","title":"随机数","text":"Let's take the following example: we implement a Die type, with a variable number n of sides, numbered from 1 to n. We want rand(Die) to produce a Die with a random number of up to 20 sides (and at least 4):","category":"page"},{"location":"stdlib/Random/","page":"随机数","title":"随机数","text":"struct Die\n nsides::Int # number of sides\nend\n\nRandom.rand(rng::AbstractRNG, ::Random.SamplerType{Die}) = Die(rand(rng, 4:20))\n\n# output\n","category":"page"},{"location":"stdlib/Random/","page":"随机数","title":"随机数","text":"Scalar and array methods for Die now work as expected:","category":"page"},{"location":"stdlib/Random/","page":"随机数","title":"随机数","text":"julia> rand(Die)\nDie(7)\n\njulia> rand(MersenneTwister(0), Die)\nDie(11)\n\njulia> rand(Die, 3)\n3-element Vector{Die}:\n Die(13)\n Die(8)\n Die(20)\n\njulia> a = Vector{Die}(undef, 3); rand!(a)\n3-element Vector{Die}:\n Die(4)\n Die(14)\n Die(10)","category":"page"},{"location":"stdlib/Random/#A-simple-sampler-without-pre-computed-data","page":"随机数","title":"A simple sampler without pre-computed data","text":"","category":"section"},{"location":"stdlib/Random/","page":"随机数","title":"随机数","text":"Here we define a sampler for a collection. If no pre-computed data is required, it can be implemented with a SamplerTrivial sampler, which is in fact the default fallback for values.","category":"page"},{"location":"stdlib/Random/","page":"随机数","title":"随机数","text":"In order to define random generation out of objects of type S, the following method should be defined: rand(rng::AbstractRNG, sp::Random.SamplerTrivial{S}). Here, sp simply wraps an object of type S, which can be accessed via sp[]. Continuing the Die example, we want now to define rand(d::Die) to produce an Int corresponding to one of d's sides:","category":"page"},{"location":"stdlib/Random/","page":"随机数","title":"随机数","text":"julia> Random.rand(rng::AbstractRNG, d::Random.SamplerTrivial{Die}) = rand(rng, 1:d[].nsides);\n\njulia> rand(Die(4))\n1\n\njulia> rand(Die(4), 3)\n3-element Vector{Any}:\n 3\n 2\n 4","category":"page"},{"location":"stdlib/Random/","page":"随机数","title":"随机数","text":"Given a collection type S, it's currently assumed that if rand(::S) is defined, an object of type eltype(S) will be produced. In the last example, a Vector{Any} is produced; the reason is that eltype(Die) == Any. The remedy is to define Base.eltype(::Type{Die}) = Int.","category":"page"},{"location":"stdlib/Random/#Generating-values-for-an-AbstractFloat-type","page":"随机数","title":"Generating values for an AbstractFloat type","text":"","category":"section"},{"location":"stdlib/Random/","page":"随机数","title":"随机数","text":"AbstractFloat types are special-cased, because by default random values are not produced in the whole type domain, but rather in [0,1). The following method should be implemented for T <: AbstractFloat: Random.rand(::AbstractRNG, ::Random.SamplerTrivial{Random.CloseOpen01{T}})","category":"page"},{"location":"stdlib/Random/#An-optimized-sampler-with-pre-computed-data","page":"随机数","title":"An optimized sampler with pre-computed data","text":"","category":"section"},{"location":"stdlib/Random/","page":"随机数","title":"随机数","text":"Consider a discrete distribution, where numbers 1:n are drawn with given probabilities that sum to one. When many values are needed from this distribution, the fastest method is using an alias table. We don't provide the algorithm for building such a table here, but suppose it is available in make_alias_table(probabilities) instead, and draw_number(rng, alias_table) can be used to draw a random number from it.","category":"page"},{"location":"stdlib/Random/","page":"随机数","title":"随机数","text":"Suppose that the distribution is described by","category":"page"},{"location":"stdlib/Random/","page":"随机数","title":"随机数","text":"struct DiscreteDistribution{V <: AbstractVector}\n probabilities::V\nend","category":"page"},{"location":"stdlib/Random/","page":"随机数","title":"随机数","text":"and that we always want to build an alias table, regardless of the number of values needed (we learn how to customize this below). The methods","category":"page"},{"location":"stdlib/Random/","page":"随机数","title":"随机数","text":"Random.eltype(::Type{<:DiscreteDistribution}) = Int\n\nfunction Random.Sampler(::Type{<:AbstractRNG}, distribution::DiscreteDistribution, ::Repetition)\n SamplerSimple(disribution, make_alias_table(distribution.probabilities))\nend","category":"page"},{"location":"stdlib/Random/","page":"随机数","title":"随机数","text":"should be defined to return a sampler with pre-computed data, then","category":"page"},{"location":"stdlib/Random/","page":"随机数","title":"随机数","text":"function rand(rng::AbstractRNG, sp::SamplerSimple{<:DiscreteDistribution})\n draw_number(rng, sp.data)\nend","category":"page"},{"location":"stdlib/Random/","page":"随机数","title":"随机数","text":"will be used to draw the values.","category":"page"},{"location":"stdlib/Random/#Custom-sampler-types","page":"随机数","title":"Custom sampler types","text":"","category":"section"},{"location":"stdlib/Random/","page":"随机数","title":"随机数","text":"The SamplerSimple type is sufficient for most use cases with precomputed data. However, in order to demonstrate how to use custom sampler types, here we implement something similar to SamplerSimple.","category":"page"},{"location":"stdlib/Random/","page":"随机数","title":"随机数","text":"Going back to our Die example: rand(::Die) uses random generation from a range, so there is an opportunity for this optimization. We call our custom sampler SamplerDie.","category":"page"},{"location":"stdlib/Random/","page":"随机数","title":"随机数","text":"import Random: Sampler, rand\n\nstruct SamplerDie <: Sampler{Int} # generates values of type Int\n die::Die\n sp::Sampler{Int} # this is an abstract type, so this could be improved\nend\n\nSampler(RNG::Type{<:AbstractRNG}, die::Die, r::Random.Repetition) =\n SamplerDie(die, Sampler(RNG, 1:die.nsides, r))\n# the `r` parameter will be explained later on\n\nrand(rng::AbstractRNG, sp::SamplerDie) = rand(rng, sp.sp)","category":"page"},{"location":"stdlib/Random/","page":"随机数","title":"随机数","text":"It's now possible to get a sampler with sp = Sampler(rng, die), and use sp instead of die in any rand call involving rng. In the simplistic example above, die doesn't need to be stored in SamplerDie but this is often the case in practice.","category":"page"},{"location":"stdlib/Random/","page":"随机数","title":"随机数","text":"Of course, this pattern is so frequent that the helper type used above, namely Random.SamplerSimple, is available, saving us the definition of SamplerDie: we could have implemented our decoupling with:","category":"page"},{"location":"stdlib/Random/","page":"随机数","title":"随机数","text":"Sampler(RNG::Type{<:AbstractRNG}, die::Die, r::Random.Repetition) =\n SamplerSimple(die, Sampler(RNG, 1:die.nsides, r))\n\nrand(rng::AbstractRNG, sp::SamplerSimple{Die}) = rand(rng, sp.data)","category":"page"},{"location":"stdlib/Random/","page":"随机数","title":"随机数","text":"Here, sp.data refers to the second parameter in the call to the SamplerSimple constructor (in this case equal to Sampler(rng, 1:die.nsides, r)), while the Die object can be accessed via sp[].","category":"page"},{"location":"stdlib/Random/","page":"随机数","title":"随机数","text":"Like SamplerDie, any custom sampler must be a subtype of Sampler{T} where T is the type of the generated values. Note that SamplerSimple(x, data) isa Sampler{eltype(x)}, so this constrains what the first argument to SamplerSimple can be (it's recommended to use SamplerSimple like in the Die example, where x is simply forwarded while defining a Sampler method). Similarly, SamplerTrivial(x) isa Sampler{eltype(x)}.","category":"page"},{"location":"stdlib/Random/","page":"随机数","title":"随机数","text":"Another helper type is currently available for other cases, Random.SamplerTag, but is considered as internal API, and can break at any time without proper deprecations.","category":"page"},{"location":"stdlib/Random/#Using-distinct-algorithms-for-scalar-or-array-generation","page":"随机数","title":"Using distinct algorithms for scalar or array generation","text":"","category":"section"},{"location":"stdlib/Random/","page":"随机数","title":"随机数","text":"In some cases, whether one wants to generate only a handful of values or a large number of values will have an impact on the choice of algorithm. This is handled with the third parameter of the Sampler constructor. Let's assume we defined two helper types for Die, say SamplerDie1 which should be used to generate only few random values, and SamplerDieMany for many values. We can use those types as follows:","category":"page"},{"location":"stdlib/Random/","page":"随机数","title":"随机数","text":"Sampler(RNG::Type{<:AbstractRNG}, die::Die, ::Val{1}) = SamplerDie1(...)\nSampler(RNG::Type{<:AbstractRNG}, die::Die, ::Val{Inf}) = SamplerDieMany(...)","category":"page"},{"location":"stdlib/Random/","page":"随机数","title":"随机数","text":"Of course, rand must also be defined on those types (i.e. rand(::AbstractRNG, ::SamplerDie1) and rand(::AbstractRNG, ::SamplerDieMany)). Note that, as usual, SamplerTrivial and SamplerSimple can be used if custom types are not necessary.","category":"page"},{"location":"stdlib/Random/","page":"随机数","title":"随机数","text":"Note: Sampler(rng, x) is simply a shorthand for Sampler(rng, x, Val(Inf)), and Random.Repetition is an alias for Union{Val{1}, Val{Inf}}.","category":"page"},{"location":"stdlib/Random/#Creating-new-generators","page":"随机数","title":"Creating new generators","text":"","category":"section"},{"location":"stdlib/Random/","page":"随机数","title":"随机数","text":"The API is not clearly defined yet, but as a rule of thumb:","category":"page"},{"location":"stdlib/Random/","page":"随机数","title":"随机数","text":"any rand method producing \"basic\" types (isbitstype integer and floating types in Base) should be defined for this specific RNG, if they are needed;\nother documented rand methods accepting an AbstractRNG should work out of the box, (provided the methods from 1) what are relied on are implemented), but can of course be specialized for this RNG if there is room for optimization;\ncopy for pseudo-RNGs should return an independent copy that generates the exact same random sequence as the original from that point when called in the same way. When this is not feasible (e.g. hardware-based RNGs), copy must not be implemented.","category":"page"},{"location":"stdlib/Random/","page":"随机数","title":"随机数","text":"Concerning 1), a rand method may happen to work automatically, but it's not officially supported and may break without warnings in a subsequent release.","category":"page"},{"location":"stdlib/Random/","page":"随机数","title":"随机数","text":"To define a new rand method for an hypothetical MyRNG generator, and a value specification s (e.g. s == Int, or s == 1:10) of type S==typeof(s) or S==Type{s} if s is a type, the same two methods as we saw before must be defined:","category":"page"},{"location":"stdlib/Random/","page":"随机数","title":"随机数","text":"Sampler(::Type{MyRNG}, ::S, ::Repetition), which returns an object of type say SamplerS\nrand(rng::MyRNG, sp::SamplerS)","category":"page"},{"location":"stdlib/Random/","page":"随机数","title":"随机数","text":"It can happen that Sampler(rng::AbstractRNG, ::S, ::Repetition) is already defined in the Random module. It would then be possible to skip step 1) in practice (if one wants to specialize generation for this particular RNG type), but the corresponding SamplerS type is considered as internal detail, and may be changed without warning.","category":"page"},{"location":"stdlib/Random/#Specializing-array-generation","page":"随机数","title":"Specializing array generation","text":"","category":"section"},{"location":"stdlib/Random/","page":"随机数","title":"随机数","text":"In some cases, for a given RNG type, generating an array of random values can be more efficient with a specialized method than by merely using the decoupling technique explained before. This is for example the case for MersenneTwister, which natively writes random values in an array.","category":"page"},{"location":"stdlib/Random/","page":"随机数","title":"随机数","text":"To implement this specialization for MyRNG and for a specification s, producing elements of type S, the following method can be defined: rand!(rng::MyRNG, a::AbstractArray{S}, ::SamplerS), where SamplerS is the type of the sampler returned by Sampler(MyRNG, s, Val(Inf)). Instead of AbstractArray, it's possible to implement the functionality only for a subtype, e.g. Array{S}. The non-mutating array method of rand will automatically call this specialization internally.","category":"page"},{"location":"stdlib/Random/","page":"随机数","title":"随机数","text":"DocTestSetup = nothing","category":"page"},{"location":"stdlib/Random/#Reproducibility","page":"随机数","title":"Reproducibility","text":"","category":"section"},{"location":"stdlib/Random/","page":"随机数","title":"随机数","text":"By using an RNG parameter initialized with a given seed, you can reproduce the same pseudorandom number sequence when running your program multiple times. However, a minor release of Julia (e.g. 1.3 to 1.4) may change the sequence of pseudorandom numbers generated from a specific seed, in particular if MersenneTwister is used. (Even if the sequence produced by a low-level function like rand does not change, the output of higher-level functions like randsubseq may change due to algorithm updates.) Rationale: guaranteeing that pseudorandom streams never change prohibits many algorithmic improvements.","category":"page"},{"location":"stdlib/Random/","page":"随机数","title":"随机数","text":"If you need to guarantee exact reproducibility of random data, it is advisable to simply save the data (e.g. as a supplementary attachment in a scientific publication). (You can also, of course, specify a particular Julia version and package manifest, especially if you require bit reproducibility.)","category":"page"},{"location":"stdlib/Random/","page":"随机数","title":"随机数","text":"Software tests that rely on specific \"random\" data should also generally either save the data, embed it into the test code, or use third-party packages like StableRNGs.jl. On the other hand, tests that should pass for most random data (e.g. testing A \\ (A*x) ≈ x for a random matrix A = randn(n,n)) can use an RNG with a fixed seed to ensure that simply running the test many times does not encounter a failure due to very improbable data (e.g. an extremely ill-conditioned matrix).","category":"page"},{"location":"stdlib/Random/","page":"随机数","title":"随机数","text":"The statistical distribution from which random samples are drawn is guaranteed to be the same across any minor Julia releases.","category":"page"},{"location":"manual/profile/#profiling","page":"性能分析","title":"性能分析","text":"","category":"section"},{"location":"manual/profile/","page":"性能分析","title":"性能分析","text":"Profile 模块提供了一些工具来帮助开发者提高其代码的性能。在使用时,它运行代码并进行测量,并生成输出,该输出帮助你了解在每行(或几行)上花费了多少时间。最常见的用法是识别性能「瓶颈」并将其作为优化目标。","category":"page"},{"location":"manual/profile/","page":"性能分析","title":"性能分析","text":"Profile 实现了所谓的「抽样」或统计分析器。它通过在执行任何任务期间定期进行回溯来工作。每次回溯捕获当前运行的函数和行号,以及导致该行执行的完整函数调用链,因此是当前执行状态的「快照」。","category":"page"},{"location":"manual/profile/","page":"性能分析","title":"性能分析","text":"如果大部分运行时间都花在执行特定代码行上,则此行会在所有回溯的集合中频繁出现。换句话说,执行给定行的「成本」——或实际上,调用及包含此行的函数序列的成本——与它在所有回溯的集合中的出现频率成正比。","category":"page"},{"location":"manual/profile/","page":"性能分析","title":"性能分析","text":"抽样分析器不提供完整的逐行覆盖功能,因为回溯是间隔发生的(默认情况下,该时间间隔在 Unix 上是 1 ms,而在 Windows 上是 10 ms,但实际调度受操作系统负载的影响)。此外,正如下文中进一步讨论的,因为样本是在所有执行点的稀疏子集处收集的,所以抽样分析器收集的数据会受到统计噪声的影响。","category":"page"},{"location":"manual/profile/","page":"性能分析","title":"性能分析","text":"尽管有这些限制,但抽样分析器仍然有很大的优势:","category":"page"},{"location":"manual/profile/","page":"性能分析","title":"性能分析","text":"你无需对代码进行任何修改即可进行时间测量。\n它可以分析 Julia 的核心代码,甚至(可选)可以分析 C 和 Fortran 库。\n通过「偶尔」运行,它只有很少的性能开销;代码在性能分析时能以接近本机的速度运行。","category":"page"},{"location":"manual/profile/","page":"性能分析","title":"性能分析","text":"出于这些原因,建议你在考虑任何替代方案前尝试使用内置的抽样分析器。","category":"page"},{"location":"manual/profile/#基本用法","page":"性能分析","title":"基本用法","text":"","category":"section"},{"location":"manual/profile/","page":"性能分析","title":"性能分析","text":"让我们使用一个简单的测试用例:","category":"page"},{"location":"manual/profile/","page":"性能分析","title":"性能分析","text":"julia> function myfunc()\n A = rand(200, 200, 400)\n maximum(A)\n end","category":"page"},{"location":"manual/profile/","page":"性能分析","title":"性能分析","text":"最好先至少运行一次你想要分析的代码(除非你想要分析 Julia 的 JIT 编译器):","category":"page"},{"location":"manual/profile/","page":"性能分析","title":"性能分析","text":"julia> myfunc() # run once to force compilation","category":"page"},{"location":"manual/profile/","page":"性能分析","title":"性能分析","text":"现在我们准备分析这个函数:","category":"page"},{"location":"manual/profile/","page":"性能分析","title":"性能分析","text":"julia> using Profile\n\njulia> @profile myfunc()","category":"page"},{"location":"manual/profile/","page":"性能分析","title":"性能分析","text":"有一些图形界面可以查看性能分析的结果。这其中有一类是基于 FlameGraphs.jl打造的,只不过提供了不同的用户接口:","category":"page"},{"location":"manual/profile/","page":"性能分析","title":"性能分析","text":"Juno 是一个完整的 IDE,内置对性能分析可视化的支持\nProfileView.jl 是一个基于 GTK 的独立可视化工具\nProfileVega.jl 使用 VegaLight 并与 Jupyter notebooks 很好地集成\nStatProfilerHTML 生成 HTML 并提供一些额外的摘要,并且还与 Jupyter 笔记本很好地集成\nProfileSVG 渲染 SVG","category":"page"},{"location":"manual/profile/","page":"性能分析","title":"性能分析","text":"一种完全独立的性能分析可视化方法是 PProf.jl,它使用外部 pprof 工具。","category":"page"},{"location":"manual/profile/","page":"性能分析","title":"性能分析","text":"不过,在这里,我们将使用标准库附带的基于文本的显示:","category":"page"},{"location":"manual/profile/","page":"性能分析","title":"性能分析","text":"julia> Profile.print()\n80 ./event.jl:73; (::Base.REPL.##1#2{Base.REPL.REPLBackend})()\n 80 ./REPL.jl:97; macro expansion\n 80 ./REPL.jl:66; eval_user_input(::Any, ::Base.REPL.REPLBackend)\n 80 ./boot.jl:235; eval(::Module, ::Any)\n 80 ./:?; anonymous\n 80 ./profile.jl:23; macro expansion\n 52 ./REPL[1]:2; myfunc()\n 38 ./random.jl:431; rand!(::MersenneTwister, ::Array{Float64,3}, ::Int64, ::Type{B...\n 38 ./dSFMT.jl:84; dsfmt_fill_array_close_open!(::Base.dSFMT.DSFMT_state, ::Ptr{F...\n 14 ./random.jl:278; rand\n 14 ./random.jl:277; rand\n 14 ./random.jl:366; rand\n 14 ./random.jl:369; rand\n 28 ./REPL[1]:3; myfunc()\n 28 ./reduce.jl:270; _mapreduce(::Base.#identity, ::Base.#scalarmax, ::IndexLinear,...\n 3 ./reduce.jl:426; mapreduce_impl(::Base.#identity, ::Base.#scalarmax, ::Array{F...\n 25 ./reduce.jl:428; mapreduce_impl(::Base.#identity, ::Base.#scalarmax, ::Array{F...","category":"page"},{"location":"manual/profile/","page":"性能分析","title":"性能分析","text":"显示结果中的每行表示代码中的特定点(行数)。缩进用来标明嵌套的函数调用序列,其中缩进更多的行在调用序列中更深。在每一行中,第一个「字段」是在这一行或由这一行执行的任何函数中获取的回溯(样本)数量。第二个字段是文件名和行数,第三个字段是函数名。请注意,具体的行号可能会随着 Julia 代码的改变而改变;如果你想跟上,最好自己运行这个示例。","category":"page"},{"location":"manual/profile/","page":"性能分析","title":"性能分析","text":"在此例中,我们可以看到顶层的调用函数位于文件 event.jl 中。这是启动 Julia 时运行 REPL 的函数。如果你查看 REPL.jl 的第 97 行,你会看到这是调用函数 eval_user_input() 的地方。这是对你在 REPL 上的输入进行求值的函数,因为我们正以交互方式运行,所以当我们输入 @profile myfunc() 时会调用这些函数。下一行反映了 @profile 所采取的操作。","category":"page"},{"location":"manual/profile/","page":"性能分析","title":"性能分析","text":"第一行显示在 event.jl 的第 73 行获取了 80 次回溯,但这并不是说此行本身「昂贵」:第三行表明所有这些 80 次回溯实际上它调用的 eval_user_input 中触发的,以此类推。为了找出实际占用时间的操作,我们需要深入了解调用链。","category":"page"},{"location":"manual/profile/","page":"性能分析","title":"性能分析","text":"此输出中第一个「重要」的行是这行:","category":"page"},{"location":"manual/profile/","page":"性能分析","title":"性能分析","text":"52 ./REPL[1]:2; myfunc()","category":"page"},{"location":"manual/profile/","page":"性能分析","title":"性能分析","text":"REPL 指的是我们在 REPL 中定义了 myfunc,而不是把它放在文件中;如果我们使用文件,这将显示文件名。[1] 表示函数 myfunc 是在当前 REPL 会话中第一个进行求值的表达式。myfunc() 的第 2 行包含对 rand 的调用,(80 次中)有 52 次回溯发生在该行。在此之下,你可以看到在 dSFMT.jl 中对 dsfmt_fill_array_close_open! 的调用。","category":"page"},{"location":"manual/profile/","page":"性能分析","title":"性能分析","text":"更进一步,你会看到:","category":"page"},{"location":"manual/profile/","page":"性能分析","title":"性能分析","text":"28 ./REPL[1]:3; myfunc()","category":"page"},{"location":"manual/profile/","page":"性能分析","title":"性能分析","text":"myfunc 的第 3 行包含对 maximum 的调用,(80 次中)有 28 次回溯发生在这里。在此之下,你可以看到对于这种类型的输入数据,maximum 函数中执行的耗时操作在 base/reduce.jl 中的具体位置。","category":"page"},{"location":"manual/profile/","page":"性能分析","title":"性能分析","text":"总的来说,我们可以暂时得出结论,生成随机数的成本大概是找到最大元素的两倍。通过收集更多样本,我们可以增加对此结果的信心:","category":"page"},{"location":"manual/profile/","page":"性能分析","title":"性能分析","text":"julia> @profile (for i = 1:100; myfunc(); end)\n\njulia> Profile.print()\n[....]\n 3821 ./REPL[1]:2; myfunc()\n 3511 ./random.jl:431; rand!(::MersenneTwister, ::Array{Float64,3}, ::Int64, ::Type...\n 3511 ./dSFMT.jl:84; dsfmt_fill_array_close_open!(::Base.dSFMT.DSFMT_state, ::Ptr...\n 310 ./random.jl:278; rand\n [....]\n 2893 ./REPL[1]:3; myfunc()\n 2893 ./reduce.jl:270; _mapreduce(::Base.#identity, ::Base.#scalarmax, ::IndexLinea...\n [....]","category":"page"},{"location":"manual/profile/","page":"性能分析","title":"性能分析","text":"一般来说,如果你在某行上收集到 N 个样本,那你可以预期其有 sqrt(N) 的不确定性(忽略其它噪音源,比如计算机在其它任务上的繁忙程度)。这个规则的主要例外是垃圾收集,它很少运行但往往成本高昂。(因为 Julia 的垃圾收集器是用 C 语言编写的,此类事件可使用下文描述的 C=true 输出模式来检测,或者使用 ProfileView.jl 来检测。)","category":"page"},{"location":"manual/profile/","page":"性能分析","title":"性能分析","text":"这展示了默认的「树」形转储;另一种选择是「扁平」形转储,它会累积与其嵌套无关的计数:","category":"page"},{"location":"manual/profile/","page":"性能分析","title":"性能分析","text":"julia> Profile.print(format=:flat)\n Count File Line Function\n 6714 ./ -1 anonymous\n 6714 ./REPL.jl 66 eval_user_input(::Any, ::Base.REPL.REPLBackend)\n 6714 ./REPL.jl 97 macro expansion\n 3821 ./REPL[1] 2 myfunc()\n 2893 ./REPL[1] 3 myfunc()\n 6714 ./REPL[7] 1 macro expansion\n 6714 ./boot.jl 235 eval(::Module, ::Any)\n 3511 ./dSFMT.jl 84 dsfmt_fill_array_close_open!(::Base.dSFMT.DSFMT_s...\n 6714 ./event.jl 73 (::Base.REPL.##1#2{Base.REPL.REPLBackend})()\n 6714 ./profile.jl 23 macro expansion\n 3511 ./random.jl 431 rand!(::MersenneTwister, ::Array{Float64,3}, ::In...\n 310 ./random.jl 277 rand\n 310 ./random.jl 278 rand\n 310 ./random.jl 366 rand\n 310 ./random.jl 369 rand\n 2893 ./reduce.jl 270 _mapreduce(::Base.#identity, ::Base.#scalarmax, :...\n 5 ./reduce.jl 420 mapreduce_impl(::Base.#identity, ::Base.#scalarma...\n 253 ./reduce.jl 426 mapreduce_impl(::Base.#identity, ::Base.#scalarma...\n 2592 ./reduce.jl 428 mapreduce_impl(::Base.#identity, ::Base.#scalarma...\n 43 ./reduce.jl 429 mapreduce_impl(::Base.#identity, ::Base.#scalarma...","category":"page"},{"location":"manual/profile/","page":"性能分析","title":"性能分析","text":"如果你的代码有递归,那么可能令人困惑的就是「子」函数中的行的累积计数可以多于总回溯次数。考虑以下函数定义:","category":"page"},{"location":"manual/profile/","page":"性能分析","title":"性能分析","text":"dumbsum(n::Integer) = n == 1 ? 1 : 1 + dumbsum(n-1)\ndumbsum3() = dumbsum(3)","category":"page"},{"location":"manual/profile/","page":"性能分析","title":"性能分析","text":"如果你要分析 dumbsum3,并在执行 dumbsum(1) 时执行了回溯,那么该回溯将如下所示:","category":"page"},{"location":"manual/profile/","page":"性能分析","title":"性能分析","text":"dumbsum3\n dumbsum(3)\n dumbsum(2)\n dumbsum(1)","category":"page"},{"location":"manual/profile/","page":"性能分析","title":"性能分析","text":"因此,即使父函数只获得 1 个计数,这个子函数也会获得 3 个计数。「树」形表示使这更清晰,因此(以及其它原因)可能是查看结果的最实用方法。","category":"page"},{"location":"manual/profile/#结果累积和清空","page":"性能分析","title":"结果累积和清空","text":"","category":"section"},{"location":"manual/profile/","page":"性能分析","title":"性能分析","text":"@profile 的结果会累积在一个缓冲区中;如果你在 @profile 下运行多端代码,那么 Profile.print() 会显示合并的结果。这可能非常有用,但有时你会想重新开始,这可通过 Profile.clear()。","category":"page"},{"location":"manual/profile/#用于控制性能分析结果显示的选项","page":"性能分析","title":"用于控制性能分析结果显示的选项","text":"","category":"section"},{"location":"manual/profile/","page":"性能分析","title":"性能分析","text":"Profile.print 还有一些未曾描述的选项。让我们看看完整的声明:","category":"page"},{"location":"manual/profile/","page":"性能分析","title":"性能分析","text":"function print(io::IO = stdout, data = fetch(); kwargs...)","category":"page"},{"location":"manual/profile/","page":"性能分析","title":"性能分析","text":"我们先讨论两个位置参数,然后讨论关键字参数:","category":"page"},{"location":"manual/profile/","page":"性能分析","title":"性能分析","text":"io——允许你将结果保存到缓冲区,例如一个文件,但默认是打印到 stdout(控制台)。\ndata——包含你要分析的数据;默认情况下,它是从 Profile.fetch() 中获取的,该函数从预先分配的缓冲区中拉出回溯。例如,如果你要分析性能分析器,可以说:\ndata = copy(Profile.fetch())\nProfile.clear()\n@profile Profile.print(stdout, data) # Prints the previous results\nProfile.print() # Prints results from Profile.print()","category":"page"},{"location":"manual/profile/","page":"性能分析","title":"性能分析","text":"关键字参数可以是以下参数的任意组合:","category":"page"},{"location":"manual/profile/","page":"性能分析","title":"性能分析","text":"format——上文已经介绍,确定是使用(默认值,:tree)还是不使用(:flat)缩进来表示其树形结构。\nC——如果为 true,则显示 C 和 Fortran 代码中的回溯(通常它们被排除在外)。请尝试用 Profile.print(C = true) 运行介绍性示例。这对于判断是 Julia 代码还是 C 代码导致了性能瓶颈非常有帮助;设置 C = true 也可提高嵌套的可解释性,代价是更长的性能分析转储。\ncombine——某些代码行包含多个操作;例如,s += A[i] 包含一个数组引用(A[i])和一个求和操作。这些操作在所生成的机器代码中对应不同的行,因此回溯期间可能会在此行中捕获两个或以上地址。combine = true 把它们混合在一起,可能你通常想要这样,但使用 combine = false,你可为每个唯一的指令指针单独生成输出。\nmaxdepth——限制 :tree 格式中深度大于 maxdepth 的帧。\n  * sortedby——控制 :flat 格式中的次序。为 :filefuncline(默认值)时按源代码行排序,而为 :count 时按收集的样本数排序。\nnoisefloor——限制低于样本的启发式噪音下限的帧(只适用于格式 :tree)。尝试此选项的建议值是 2.0(默认值是 0)。此参数会隐藏 n <= noisefloor * √N 的样本,其中 n 是该行上的样本数,N 是被调用者的样本数。\nmincount——限制出现次数少于 mincount 的帧。","category":"page"},{"location":"manual/profile/","page":"性能分析","title":"性能分析","text":"文件/函数名有时会被(用 ...)截断,缩进也有可能在开头用 +n 截断,其中 n 是在空间充足的情况下应该插入的额外空格数。如果你想要深层嵌套代码的完整性能分析,保存到文件并在 IOContext 中使用宽的 displaysize 通常是个好主意:","category":"page"},{"location":"manual/profile/","page":"性能分析","title":"性能分析","text":"open(\"/tmp/prof.txt\", \"w\") do s\n Profile.print(IOContext(s, :displaysize => (24, 500)))\nend","category":"page"},{"location":"manual/profile/#配置","page":"性能分析","title":"配置","text":"","category":"section"},{"location":"manual/profile/","page":"性能分析","title":"性能分析","text":"@profile 只是累积回溯,在你调用 Profile.print() 时才会进行性能分析。对于长时间运行的计算,完全有可能把用于存储回溯的预分配缓冲区填满。如果发生这种情况,回溯会停止,但你的计算会继续。因此,你也许会丢失一些重要的性能分析数据(当发生这种情况时,你会受到警告)。","category":"page"},{"location":"manual/profile/","page":"性能分析","title":"性能分析","text":"你可通过以下方式获取和配置相关参数:","category":"page"},{"location":"manual/profile/","page":"性能分析","title":"性能分析","text":"Profile.init() # returns the current settings\nProfile.init(n = 10^7, delay = 0.01)","category":"page"},{"location":"manual/profile/","page":"性能分析","title":"性能分析","text":"n 是能够存储的指令指针总数,默认值为 10^6。如果通常的回溯是 20 个指令指针,那么可以收集 50000 次回溯,这意味着统计不确定性少于 1%。这对于大多数应用来说可能已经足够了。","category":"page"},{"location":"manual/profile/","page":"性能分析","title":"性能分析","text":"因此,你更可能需要修改 delay,它以秒为单位,设置在快照之间 Julia 用于执行所请求计算的时长。长时间运行的工作可能不需要经常回溯。默认设置为 delay = 0.001。当然,你可以减少和增加 delay;但是,一旦 delay 接近执行一次回溯所需的时间(在作者的笔记本上约为 30 微妙),性能分析的开销就会增加。","category":"page"},{"location":"manual/profile/#memory-allocation-analysis","page":"性能分析","title":"内存分配分析","text":"","category":"section"},{"location":"manual/profile/","page":"性能分析","title":"性能分析","text":"减少内存分配是提高性能的最常用技术之一。内存分配总量可以用 @time 和 @allocated,触发内存分配的特定行通常可以通过这些行产生的垃圾分配成本从性能分析中推断出来。但是,直接测量每行代码的内存分配总量有时会更高效。","category":"page"},{"location":"manual/profile/","page":"性能分析","title":"性能分析","text":"为了逐行测量内存分配,启动 Julia 时请使用命令行选项 --track-allocation=,该选项的可选值有 none(默认值,不测量内存分配)、user(测量除 Julia core 代码之外的所有代码的内存分配)或 all(测量 Julia 代码中每一行的内存分配)。这会为每行已编译的代码测量内存。在退出 Julia 时,累积的结果将写入到文本文件中,此文本文件名称为该文件名称后加 .mem,并与源文件位于同一目录下。该文件的每行列出内存分配的总字节数。Coverage 包包括了一些基本分析工具,例如,按照内存分配的字节数对行进行排序的工具。","category":"page"},{"location":"manual/profile/","page":"性能分析","title":"性能分析","text":"在解释结果时,有一些需要注意的细节。在 user 设定下,直接从 REPL 调用的任何函数的第一行都将会显示内存分配,这是由发生在 REPL 代码本身的事件造成的。更重要的是,JIT 编译也会添加内存分配计数,因为 Julia 的编译器大部分是用 Julia 编写的(并且编译通常需要内存分配)。建议的分析过程是先通过执行待分析的所有命令来强制编译,然后调用 Profile.clear_malloc_data() 来重置所有内存计数器。最后,执行所需的命令并退出 Julia 以触发 .mem 文件的生成。","category":"page"},{"location":"manual/profile/#外部性能分析","page":"性能分析","title":"外部性能分析","text":"","category":"section"},{"location":"manual/profile/","page":"性能分析","title":"性能分析","text":"Julia 目前支持的外部性能分析工具有 Intel VTune、OProfile 和 perf。","category":"page"},{"location":"manual/profile/","page":"性能分析","title":"性能分析","text":"根据你所选择的工具,编译时请在 Make.user 中将 USE_INTEL_JITEVENTS、USE_OPROFILE_JITEVENTS 和 USE_PERF_JITEVENTS 设置为 1。多个上述编译标志是支持的。","category":"page"},{"location":"manual/profile/","page":"性能分析","title":"性能分析","text":"在运行 Julia 前,请将环境变量 ENABLE_JITPROFILING 设置为 1。","category":"page"},{"location":"manual/profile/","page":"性能分析","title":"性能分析","text":"现在,你可以通过多种方式使用这些工具!例如,可以使用 OProfile 来尝试做个简单的记录:","category":"page"},{"location":"manual/profile/","page":"性能分析","title":"性能分析","text":">ENABLE_JITPROFILING=1 sudo operf -Vdebug ./julia test/fastmath.jl\n>opreport -l `which ./julia`","category":"page"},{"location":"manual/profile/","page":"性能分析","title":"性能分析","text":"或与 perf 类似:","category":"page"},{"location":"manual/profile/","page":"性能分析","title":"性能分析","text":"$ ENABLE_JITPROFILING=1 perf record -o /tmp/perf.data --call-graph dwarf -k 1 ./julia /test/fastmath.jl\n$ perf inject --jit --input /tmp/perf.data --output /tmp/perf-jit.data\n$ perf report --call-graph -G -i /tmp/perf-jit.data","category":"page"},{"location":"manual/profile/","page":"性能分析","title":"性能分析","text":"你可以测量关于程序的更多有趣数据,若要获得详尽的列表,请阅读 Linux perf 示例页面。","category":"page"},{"location":"manual/profile/","page":"性能分析","title":"性能分析","text":"请记住,perf 会为每次执行保存一个 perf.data 文件,即使对于小程序,它也可能变得非常大。此外,perf LLVM 模块会将调试对象保存在 ~/.debug/jit 中,记得经常清理该文件夹。","category":"page"},{"location":"manual/variables/#man-variables","page":"变量","title":"变量","text":"","category":"section"},{"location":"manual/variables/","page":"变量","title":"变量","text":"Julia 语言中,变量是与某个值相关联(或绑定)的名字。你可以用它来保存一个值(例如某些计算得到的结果),供之后的代码使用。例如:","category":"page"},{"location":"manual/variables/","page":"变量","title":"变量","text":"# 将 10 赋值给变量 x\njulia> x = 10\n10\n\n# 使用 x 的值做计算\njulia> x + 1\n11\n\n# 重新给 x 赋值\njulia> x = 1 + 1\n2\n\n# 也可以给 x 赋其它类型的值, 比如字符串文本\njulia> x = \"Hello World!\"\n\"Hello World!\"","category":"page"},{"location":"manual/variables/","page":"变量","title":"变量","text":"Julia 提供了非常灵活的变量命名策略。变量名是大小写敏感的,且不包含语义,意思是说,Julia 不会根据变量的名字来区别对待它们。 (译者注:Julia 不会自动将全大写的变量识别为常量,也不会将有特定前后缀的变量自动识别为某种特定类型的变量,即不会根据变量名字,自动判断变量的任何属性。)","category":"page"},{"location":"manual/variables/","page":"变量","title":"变量","text":"julia> x = 1.0\n1.0\n\njulia> y = -3\n-3\n\njulia> Z = \"My string\"\n\"My string\"\n\njulia> customary_phrase = \"Hello world!\"\n\"Hello world!\"\n\njulia> UniversalDeclarationOfHumanRightsStart = \"人人生而自由,在尊严和权利上一律平等。\"\n\"人人生而自由,在尊严和权利上一律平等。\"","category":"page"},{"location":"manual/variables/","page":"变量","title":"变量","text":"你还可以使用 UTF-8 编码的 Unicode 字符作为变量名:","category":"page"},{"location":"manual/variables/","page":"变量","title":"变量","text":"julia> δ = 0.00001\n1.0e-5\n\njulia> 안녕하세요 = \"Hello\"\n\"Hello\"","category":"page"},{"location":"manual/variables/","page":"变量","title":"变量","text":"在 Julia REPL 和一些其它 Julia 的编辑器中,很多 Unicode 数学符号可以使用反斜杠加 LaTeX 符号接 tab 健打出。例如: 变量名 δ 可以通过 \\delta-tab 来输入,甚至可以用 \\alpha-tab-\\hat-tab-\\^(2)-tab来输入 α̂⁽²⁾ 这种复杂的变量名。(如果你在某个地方发现了一个不知道怎么输入的符号,比如在别人的代码里,输入? 接着复制那个符号,REPL的帮助功能会告诉你输入方法。)","category":"page"},{"location":"manual/variables/","page":"变量","title":"变量","text":"如果有需要的话,Julia 甚至允许你重定义内置常量和函数。(这样做可能引发潜在的混淆,所以并不推荐)","category":"page"},{"location":"manual/variables/","page":"变量","title":"变量","text":"julia> pi = 3\n3\n\njulia> pi\n3\n\njulia> sqrt = 4\n4","category":"page"},{"location":"manual/variables/","page":"变量","title":"变量","text":"然而,如果你试图重定义一个已经在使用中的内置常量或函数,Julia 会报错:","category":"page"},{"location":"manual/variables/","page":"变量","title":"变量","text":"julia> pi\nπ = 3.1415926535897...\n\njulia> pi = 3\nERROR: cannot assign a value to variable MathConstants.pi from module Main\n\njulia> sqrt(100)\n10.0\n\njulia> sqrt = 4\nERROR: cannot assign a value to variable Base.sqrt from module Main","category":"page"},{"location":"manual/variables/#man-allowed-variable-names","page":"变量","title":"合法的变量名","text":"","category":"section"},{"location":"manual/variables/","page":"变量","title":"变量","text":"变量名字必须以英文字母(A-Z 或 a-z)、下划线或编码大于 00A0 的 Unicode 字符的一个子集开头。 具体来说指的是,Unicode字符分类中的 Lu/Ll/Lt/Lm/Lo/Nl(字母)、Sc/So(货币和其他符号)以及一些其它像字母的符号(例如 Sm 类别数学符号中的一部分)。 变量名的非首字符还允许使用惊叹号 !、数字(包括 0-9 和其他 Nd/No 类别中的 Unicode 字符)以及其它 Unicode 字符:变音符号和其他修改标记(Mn/Mc/Me/Sk 类别)、标点和连接符(Pc 类别)、引号和少许其他字符。","category":"page"},{"location":"manual/variables/","page":"变量","title":"变量","text":"像 + 这样的运算符也是合法的标识符,但是它们会被特别地解析。 在一些上下文中,运算符可以像变量一样使用,比如 (+) 表示加函数,语句 (+) = f会把它重新赋值。大部分 Unicode 中缀运算符(Sm 类别),像 ⊕,会被解析成真正的中缀运算符,并且支持用户自定义方法(举个例子,你可以使用语句 const ⊗ = kron将 ⊗ 定义为中缀的 Kronecker 积)。 运算符也可以使用修改标记、引号和上标/下标进行加缀,例如 +̂ₐ″ 被解析成一个与 + 具有相同优先级的中缀运算符。以下标/上标字母结尾的运算符与后续变量名之间需要一个空格。举个例子,如果 +ᵃ 是一个运算符,那么 +ᵃx 应该被写为+ᵃ x,以区分表达式 + ᵃx ,其中 ᵃx 是变量名。","category":"page"},{"location":"manual/variables/","page":"变量","title":"变量","text":"一类特定的变量名是只包含下划线的变量名。这些标识符只能赋值,不能用于给其他变量赋值。严格来说,它们只能用作左值 而不能作右值:","category":"page"},{"location":"manual/variables/","page":"变量","title":"变量","text":"julia> x, ___ = size([2 2; 1 1])\n(2, 2)\n\njulia> y = ___\nERROR: syntax: all-underscore identifier used as rvalue","category":"page"},{"location":"manual/variables/","page":"变量","title":"变量","text":"唯一明确禁止的变量名称是内置关键字的名称:","category":"page"},{"location":"manual/variables/","page":"变量","title":"变量","text":"julia> else = false\nERROR: syntax: unexpected \"else\"\n\njulia> try = \"No\"\nERROR: syntax: unexpected \"=\"","category":"page"},{"location":"manual/variables/","page":"变量","title":"变量","text":"某些 Unicode 字符被认为是等效的标识符。不同的输入 Unicode 组合字符的方法(例如:重音)被视为等价的(Julia 标识符采用 NFC 标准)。Julia 还加入了一些非标准的等价字符,用于在视觉上相似且易于通过某些输入法输入的字符。Unicode 字符 ɛ (U+025B: Latin small letter open e) 和 µ (U+00B5: micro sign) 被视为等同于相应的希腊字母。点 · (U+00B7) 和希腊字符间断 · (U+0387) 都被当作数学上的点积运算符 ⋅ (U+22C5)。减号 − (U+2212) 与连接号 - (U+002D) 也被视作相同的符号。","category":"page"},{"location":"manual/variables/#命名规范","page":"变量","title":"命名规范","text":"","category":"section"},{"location":"manual/variables/","page":"变量","title":"变量","text":"虽然 Julia 语言对合法名字的限制非常少,但是遵循以下这些命名规范是非常有用的:","category":"page"},{"location":"manual/variables/","page":"变量","title":"变量","text":"变量的名字采用小写。\n使用下划线('_')来分隔名字中的单词,但是不鼓励使用下划线 除非在不使用下划线时名字会非常难读。\n类型 (Type) 和模块(Module)的名字使用大写字母开头,并且用大写字母 而不是用下划线分隔单词。\n函数(function)和宏(macro)的名字使用小写,不使用下划线。\n会对输入参数进行更改的函数要使用 ! 结尾。这些函数有时叫做 “mutating” 或 “in-place” 函数,因为它们在被调用后会修改他们的输入参数的内容 而不仅仅只是返回一个值。","category":"page"},{"location":"manual/variables/","page":"变量","title":"变量","text":"关于命名规范的更多信息,可查看代码风格指南。","category":"page"},{"location":"stdlib/InteractiveUtils/#man-interactive-utils","page":"Interactive Utilities","title":"Interactive Utilities","text":"","category":"section"},{"location":"stdlib/InteractiveUtils/","page":"Interactive Utilities","title":"Interactive Utilities","text":"This module is intended for interactive work. It is loaded automaticaly in interactive mode.","category":"page"},{"location":"stdlib/InteractiveUtils/","page":"Interactive Utilities","title":"Interactive Utilities","text":"InteractiveUtils.apropos\nInteractiveUtils.varinfo\nInteractiveUtils.versioninfo\nInteractiveUtils.methodswith\nInteractiveUtils.subtypes\nInteractiveUtils.supertypes\nInteractiveUtils.edit(::AbstractString, ::Integer)\nInteractiveUtils.edit(::Any)\nInteractiveUtils.@edit\nInteractiveUtils.define_editor\nInteractiveUtils.less(::AbstractString)\nInteractiveUtils.less(::Any)\nInteractiveUtils.@less\nInteractiveUtils.@which\nInteractiveUtils.@functionloc\nInteractiveUtils.@code_lowered\nInteractiveUtils.@code_typed\nInteractiveUtils.code_warntype\nInteractiveUtils.@code_warntype\nInteractiveUtils.code_llvm\nInteractiveUtils.@code_llvm\nInteractiveUtils.code_native\nInteractiveUtils.@code_native\nInteractiveUtils.clipboard","category":"page"},{"location":"stdlib/InteractiveUtils/#Base.Docs.apropos","page":"Interactive Utilities","title":"Base.Docs.apropos","text":"apropos([io::IO=stdout], pattern::Union{AbstractString,Regex})\n\nSearch available docstrings for entries containing pattern.\n\nWhen pattern is a string, case is ignored. Results are printed to io.\n\napropos can be called from the help mode in the REPL by wrapping the query in double quotes:\n\nhelp?> \"pattern\"\n\n\n\n\n\n","category":"function"},{"location":"stdlib/InteractiveUtils/#InteractiveUtils.varinfo","page":"Interactive Utilities","title":"InteractiveUtils.varinfo","text":"varinfo(m::Module=Main, pattern::Regex=r\"\"; all::Bool = false, imported::Bool = false, sortby::Symbol = :name, minsize::Int = 0)\n\nReturn a markdown table giving information about exported global variables in a module, optionally restricted to those matching pattern.\n\nThe memory consumption estimate is an approximate lower bound on the size of the internal structure of the object.\n\nall : also list non-exported objects defined in the module, deprecated objects, and compiler-generated objects.\nimported : also list objects explicitly imported from other modules.\nrecursive : recursively include objects in sub-modules, observing the same settings in each.\nsortby : the column to sort results by. Options are :name (default), :size, and :summary.\nminsize : only includes objects with size at least minsize bytes. Defaults to 0.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/InteractiveUtils/#InteractiveUtils.versioninfo","page":"Interactive Utilities","title":"InteractiveUtils.versioninfo","text":"versioninfo(io::IO=stdout; verbose::Bool=false)\n\nPrint information about the version of Julia in use. The output is controlled with boolean keyword arguments:\n\nverbose: print all additional information\n\nwarning: Warning\nThe output of this function may contain sensitive information. Before sharing the output, please review the output and remove any data that should not be shared publicly.\n\nSee also: VERSION.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/InteractiveUtils/#InteractiveUtils.methodswith","page":"Interactive Utilities","title":"InteractiveUtils.methodswith","text":"methodswith(typ[, module or function]; supertypes::Bool=false])\n\nReturn an array of methods with an argument of type typ.\n\nThe optional second argument restricts the search to a particular module or function (the default is all top-level modules).\n\nIf keyword supertypes is true, also return arguments with a parent type of typ, excluding type Any.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/InteractiveUtils/#InteractiveUtils.subtypes","page":"Interactive Utilities","title":"InteractiveUtils.subtypes","text":"subtypes(T::DataType)\n\nReturn a list of immediate subtypes of DataType T. Note that all currently loaded subtypes are included, including those not visible in the current module.\n\nSee also supertype, supertypes, methodswith.\n\nExamples\n\njulia> subtypes(Integer)\n3-element Vector{Any}:\n Bool\n Signed\n Unsigned\n\n\n\n\n\n","category":"function"},{"location":"stdlib/InteractiveUtils/#InteractiveUtils.supertypes","page":"Interactive Utilities","title":"InteractiveUtils.supertypes","text":"supertypes(T::Type)\n\nReturn a tuple (T, ..., Any) of T and all its supertypes, as determined by successive calls to the supertype function, listed in order of <: and terminated by Any.\n\nSee also subtypes.\n\nExamples\n\njulia> supertypes(Int)\n(Int64, Signed, Integer, Real, Number, Any)\n\n\n\n\n\n","category":"function"},{"location":"stdlib/InteractiveUtils/#InteractiveUtils.edit-Tuple{AbstractString, Integer}","page":"Interactive Utilities","title":"InteractiveUtils.edit","text":"edit(path::AbstractString, line::Integer=0)\n\nEdit a file or directory optionally providing a line number to edit the file at. Return to the julia prompt when you quit the editor. The editor can be changed by setting JULIA_EDITOR, VISUAL or EDITOR as an environment variable.\n\nSee also define_editor.\n\n\n\n\n\n","category":"method"},{"location":"stdlib/InteractiveUtils/#InteractiveUtils.edit-Tuple{Any}","page":"Interactive Utilities","title":"InteractiveUtils.edit","text":"edit(function, [types])\nedit(module)\n\nEdit the definition of a function, optionally specifying a tuple of types to indicate which method to edit. For modules, open the main source file. The module needs to be loaded with using or import first.\n\ncompat: Julia 1.1\nedit on modules requires at least Julia 1.1.\n\nTo ensure that the file can be opened at the given line, you may need to call define_editor first.\n\n\n\n\n\n","category":"method"},{"location":"stdlib/InteractiveUtils/#InteractiveUtils.@edit","page":"Interactive Utilities","title":"InteractiveUtils.@edit","text":"@edit\n\nEvaluates the arguments to the function or macro call, determines their types, and calls the edit function on the resulting expression.\n\nSee also: @less, @which.\n\n\n\n\n\n","category":"macro"},{"location":"stdlib/InteractiveUtils/#InteractiveUtils.define_editor","page":"Interactive Utilities","title":"InteractiveUtils.define_editor","text":"define_editor(fn, pattern; wait=false)\n\nDefine a new editor matching pattern that can be used to open a file (possibly at a given line number) using fn.\n\nThe fn argument is a function that determines how to open a file with the given editor. It should take three arguments, as follows:\n\ncmd - a base command object for the editor\npath - the path to the source file to open\nline - the line number to open the editor at\n\nEditors which cannot open to a specific line with a command may ignore the line argument. The fn callback must return either an appropriate Cmd object to open a file or nothing to indicate that they cannot edit this file. Use nothing to indicate that this editor is not appropriate for the current environment and another editor should be attempted. It is possible to add more general editing hooks that need not spawn external commands by pushing a callback directly to the vector EDITOR_CALLBACKS.\n\nThe pattern argument is a string, regular expression, or an array of strings and regular expressions. For the fn to be called, one of the patterns must match the value of EDITOR, VISUAL or JULIA_EDITOR. For strings, the string must equal the basename of the first word of the editor command, with its extension, if any, removed. E.g. \"vi\" doesn't match \"vim -g\" but matches \"/usr/bin/vi -m\"; it also matches vi.exe. If pattern is a regex it is matched against all of the editor command as a shell-escaped string. An array pattern matches if any of its items match. If multiple editors match, the one added most recently is used.\n\nBy default julia does not wait for the editor to close, running it in the background. However, if the editor is terminal based, you will probably want to set wait=true and julia will wait for the editor to close before resuming.\n\nIf one of the editor environment variables is set, but no editor entry matches it, the default editor entry is invoked:\n\n(cmd, path, line) -> `$cmd $path`\n\nNote that many editors are already defined. All of the following commands should already work:\n\nemacs\nemacsclient\nvim\nnvim\nnano\nmicro\nkak\ntextmate\nmate\nkate\nsubl\natom\nnotepad++\nVisual Studio Code\nopen\npycharm\nbbedit\n\nExample:\n\nThe following defines the usage of terminal-based emacs:\n\ndefine_editor(\n r\"\\bemacs\\b.*\\s(-nw|--no-window-system)\\b\", wait=true) do cmd, path, line\n `$cmd +$line $path`\nend\n\ncompat: Julia 1.4\ndefine_editor was introduced in Julia 1.4.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/InteractiveUtils/#InteractiveUtils.less-Tuple{AbstractString}","page":"Interactive Utilities","title":"InteractiveUtils.less","text":"less(file::AbstractString, [line::Integer])\n\nShow a file using the default pager, optionally providing a starting line number. Returns to the julia prompt when you quit the pager.\n\n\n\n\n\n","category":"method"},{"location":"stdlib/InteractiveUtils/#InteractiveUtils.less-Tuple{Any}","page":"Interactive Utilities","title":"InteractiveUtils.less","text":"less(function, [types])\n\nShow the definition of a function using the default pager, optionally specifying a tuple of types to indicate which method to see.\n\n\n\n\n\n","category":"method"},{"location":"stdlib/InteractiveUtils/#InteractiveUtils.@less","page":"Interactive Utilities","title":"InteractiveUtils.@less","text":"@less\n\nEvaluates the arguments to the function or macro call, determines their types, and calls the less function on the resulting expression.\n\nSee also: @edit, @which, @code_lowered.\n\n\n\n\n\n","category":"macro"},{"location":"stdlib/InteractiveUtils/#InteractiveUtils.@which","page":"Interactive Utilities","title":"InteractiveUtils.@which","text":"@which\n\nApplied to a function or macro call, it evaluates the arguments to the specified call, and returns the Method object for the method that would be called for those arguments. Applied to a variable, it returns the module in which the variable was bound. It calls out to the which function.\n\nSee also: @less, @edit.\n\n\n\n\n\n","category":"macro"},{"location":"stdlib/InteractiveUtils/#InteractiveUtils.@functionloc","page":"Interactive Utilities","title":"InteractiveUtils.@functionloc","text":"@functionloc\n\nApplied to a function or macro call, it evaluates the arguments to the specified call, and returns a tuple (filename,line) giving the location for the method that would be called for those arguments. It calls out to the functionloc function.\n\n\n\n\n\n","category":"macro"},{"location":"stdlib/InteractiveUtils/#InteractiveUtils.@code_lowered","page":"Interactive Utilities","title":"InteractiveUtils.@code_lowered","text":"@code_lowered\n\nEvaluates the arguments to the function or macro call, determines their types, and calls code_lowered on the resulting expression.\n\n\n\n\n\n","category":"macro"},{"location":"stdlib/InteractiveUtils/#InteractiveUtils.@code_typed","page":"Interactive Utilities","title":"InteractiveUtils.@code_typed","text":"@code_typed\n\nEvaluates the arguments to the function or macro call, determines their types, and calls code_typed on the resulting expression. Use the optional argument optimize with\n\n@code_typed optimize=true foo(x)\n\nto control whether additional optimizations, such as inlining, are also applied.\n\n\n\n\n\n","category":"macro"},{"location":"stdlib/InteractiveUtils/#InteractiveUtils.code_warntype","page":"Interactive Utilities","title":"InteractiveUtils.code_warntype","text":"code_warntype([io::IO], f, types; debuginfo=:default)\n\nPrints lowered and type-inferred ASTs for the methods matching the given generic function and type signature to io which defaults to stdout. The ASTs are annotated in such a way as to cause \"non-leaf\" types to be emphasized (if color is available, displayed in red). This serves as a warning of potential type instability. Not all non-leaf types are particularly problematic for performance, so the results need to be used judiciously. In particular, unions containing either missing or nothing are displayed in yellow, since these are often intentional.\n\nKeyword argument debuginfo may be one of :source or :none (default), to specify the verbosity of code comments.\n\nSee @code_warntype for more information.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/InteractiveUtils/#InteractiveUtils.@code_warntype","page":"Interactive Utilities","title":"InteractiveUtils.@code_warntype","text":"@code_warntype\n\nEvaluates the arguments to the function or macro call, determines their types, and calls code_warntype on the resulting expression.\n\n\n\n\n\n","category":"macro"},{"location":"stdlib/InteractiveUtils/#InteractiveUtils.code_llvm","page":"Interactive Utilities","title":"InteractiveUtils.code_llvm","text":"code_llvm([io=stdout,], f, types; raw=false, dump_module=false, optimize=true, debuginfo=:default)\n\nPrints the LLVM bitcodes generated for running the method matching the given generic function and type signature to io.\n\nIf the optimize keyword is unset, the code will be shown before LLVM optimizations. All metadata and dbg.* calls are removed from the printed bitcode. For the full IR, set the raw keyword to true. To dump the entire module that encapsulates the function (with declarations), set the dump_module keyword to true. Keyword argument debuginfo may be one of source (default) or none, to specify the verbosity of code comments.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/InteractiveUtils/#InteractiveUtils.@code_llvm","page":"Interactive Utilities","title":"InteractiveUtils.@code_llvm","text":"@code_llvm\n\nEvaluates the arguments to the function or macro call, determines their types, and calls code_llvm on the resulting expression. Set the optional keyword arguments raw, dump_module, debuginfo, optimize by putting them and their value before the function call, like this:\n\n@code_llvm raw=true dump_module=true debuginfo=:default f(x)\n@code_llvm optimize=false f(x)\n\noptimize controls whether additional optimizations, such as inlining, are also applied. raw makes all metadata and dbg.* calls visible. debuginfo may be one of :source (default) or :none, to specify the verbosity of code comments. dump_module prints the entire module that encapsulates the function.\n\n\n\n\n\n","category":"macro"},{"location":"stdlib/InteractiveUtils/#InteractiveUtils.code_native","page":"Interactive Utilities","title":"InteractiveUtils.code_native","text":"code_native([io=stdout,], f, types; syntax=:att, debuginfo=:default, binary=false, dump_module=true)\n\nPrints the native assembly instructions generated for running the method matching the given generic function and type signature to io.\n\nSet assembly syntax by setting syntax to :att (default) for AT&T syntax or :intel for Intel syntax.\nSpecify verbosity of code comments by setting debuginfo to :source (default) or :none.\nIf binary is true, also print the binary machine code for each instruction precedented by an abbreviated address.\nIf dump_module is false, do not print metadata such as rodata or directives.\n\nSee also: @code_native, code_llvm, code_typed and code_lowered\n\n\n\n\n\n","category":"function"},{"location":"stdlib/InteractiveUtils/#InteractiveUtils.@code_native","page":"Interactive Utilities","title":"InteractiveUtils.@code_native","text":"@code_native\n\nEvaluates the arguments to the function or macro call, determines their types, and calls code_native on the resulting expression.\n\nSet any of the optional keyword arguments syntax, debuginfo, binary or dump_module by putting it before the function call, like this:\n\n@code_native syntax=:intel debuginfo=:default binary=true dump_module=false f(x)\n\nSet assembly syntax by setting syntax to :att (default) for AT&T syntax or :intel for Intel syntax.\nSpecify verbosity of code comments by setting debuginfo to :source (default) or :none.\nIf binary is true, also print the binary machine code for each instruction precedented by an abbreviated address.\nIf dump_module is false, do not print metadata such as rodata or directives.\n\nSee also: code_native, @code_llvm, @code_typed and @code_lowered\n\n\n\n\n\n","category":"macro"},{"location":"stdlib/InteractiveUtils/#InteractiveUtils.clipboard","page":"Interactive Utilities","title":"InteractiveUtils.clipboard","text":"clipboard(x)\n\nSend a printed form of x to the operating system clipboard (\"copy\").\n\n\n\n\n\nclipboard() -> AbstractString\n\nReturn a string with the contents of the operating system clipboard (\"paste\").\n\n\n\n\n\n","category":"function"},{"location":"stdlib/Serialization/#序列化","page":"序列化","title":"序列化","text":"","category":"section"},{"location":"stdlib/Serialization/","page":"序列化","title":"序列化","text":"Serialization.serialize\nSerialization.deserialize\nSerialization.writeheader","category":"page"},{"location":"stdlib/Serialization/#Serialization.serialize","page":"序列化","title":"Serialization.serialize","text":"serialize(stream::IO, value)\n\nWrite an arbitrary value to a stream in an opaque format, such that it can be read back by deserialize. The read-back value will be as identical as possible to the original, but note that Ptr values are serialized as all-zero bit patterns (NULL).\n\nAn 8-byte identifying header is written to the stream first. To avoid writing the header, construct a Serializer and use it as the first argument to serialize instead. See also Serialization.writeheader.\n\nThe data format can change in minor (1.x) Julia releases, but files written by prior 1.x versions will remain readable. The main exception to this is when the definition of a type in an external package changes. If that occurs, it may be necessary to specify an explicit compatible version of the affected package in your environment. Renaming functions, even private functions, inside packages can also put existing files out of sync. Anonymous functions require special care: because their names are automatically generated, minor code changes can cause them to be renamed. Serializing anonymous functions should be avoided in files intended for long-term storage.\n\nIn some cases, the word size (32- or 64-bit) of the reading and writing machines must match. In rarer cases the OS or architecture must also match, for example when using packages that contain platform-dependent code.\n\n\n\n\n\nserialize(filename::AbstractString, value)\n\nOpen a file and serialize the given value to it.\n\ncompat: Julia 1.1\nThis method is available as of Julia 1.1.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/Serialization/#Serialization.deserialize","page":"序列化","title":"Serialization.deserialize","text":"deserialize(stream)\n\nRead a value written by serialize. deserialize assumes the binary data read from stream is correct and has been serialized by a compatible implementation of serialize. deserialize is designed for simplicity and performance, and so does not validate the data read. Malformed data can result in process termination. The caller must ensure the integrity and correctness of data read from stream.\n\n\n\n\n\ndeserialize(filename::AbstractString)\n\nOpen a file and deserialize its contents.\n\ncompat: Julia 1.1\nThis method is available as of Julia 1.1.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/Serialization/#Serialization.writeheader","page":"序列化","title":"Serialization.writeheader","text":"Serialization.writeheader(s::AbstractSerializer)\n\nWrite an identifying header to the specified serializer. The header consists of 8 bytes as follows:\n\nOffset Description\n0 tag byte (0x37)\n1-2 signature bytes \"JL\"\n3 protocol version\n4 bits 0-1: endianness: 0 = little, 1 = big\n4 bits 2-3: platform: 0 = 32-bit, 1 = 64-bit\n5-7 reserved\n\n\n\n\n\n","category":"function"},{"location":"stdlib/Future/#Future","page":"Future","title":"Future","text":"","category":"section"},{"location":"stdlib/Future/","page":"Future","title":"Future","text":"The Future module implements future behavior of already existing functions, which will replace the current version in a future release of Julia.","category":"page"},{"location":"stdlib/Future/","page":"Future","title":"Future","text":"Future.copy!\nFuture.randjump","category":"page"},{"location":"stdlib/Future/#Future.copy!","page":"Future","title":"Future.copy!","text":"Future.copy!(dst, src) -> dst\n\nCopy src into dst.\n\ncompat: Julia 1.1\nThis function has moved to Base with Julia 1.1, consider using copy!(dst, src) instead. Future.copy! will be deprecated in the future.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/Future/#Future.randjump","page":"Future","title":"Future.randjump","text":"randjump(r::MersenneTwister, steps::Integer) -> MersenneTwister\n\nCreate an initialized MersenneTwister object, whose state is moved forward (without generating numbers) from r by steps steps. One such step corresponds to the generation of two Float64 numbers. For each different value of steps, a large polynomial has to be generated internally. One is already pre-computed for steps=big(10)^20.\n\n\n\n\n\n","category":"function"},{"location":"manual/documentation/#man-documentation","page":"文档","title":"文档","text":"","category":"section"},{"location":"manual/documentation/","page":"文档","title":"文档","text":"Julia允许开发者和用户,使用其内置的文档系统更加便捷地为函数、类型以及其他对象编写文档。  ","category":"page"},{"location":"manual/documentation/","page":"文档","title":"文档","text":"基础语法很简单:紧接在对象(函数,宏,类型和实例)之前的字符串都会被认为是对应对象的文档(称作 docstrings)。 注意不要在 docstring 和文档对象之间有空行或者注释。 这里有个基础的例子:","category":"page"},{"location":"manual/documentation/","page":"文档","title":"文档","text":"\"Tell whether there are too foo items in the array.\"\nfoo(xs::Array) = ...","category":"page"},{"location":"manual/documentation/","page":"文档","title":"文档","text":"文档会被翻译成 Markdown,所以你可以 使用缩进和代码块来分隔代码示例和文本。从技术上来说,任何对象 都可以作为 metadata 与任何其他对象关联;Markdown 是默认的,但是可以创建 其它字符串宏并传递给 @doc 宏来使用其他格式。","category":"page"},{"location":"manual/documentation/","page":"文档","title":"文档","text":"note: Note\nMarkdown 支持由 Markdown 标准库实现,有关支持语法的完整列表,请参阅其文档。","category":"page"},{"location":"manual/documentation/","page":"文档","title":"文档","text":"这里是一个更加复杂的例子,但仍然使用 Markdown:","category":"page"},{"location":"manual/documentation/","page":"文档","title":"文档","text":"\"\"\"\n bar(x[, y])\n\nCompute the Bar index between `x` and `y`.\n\nIf `y` is unspecified, compute the Bar index between all pairs of columns of `x`.\n\n# Examples\n```julia-repl\njulia> bar([1, 2], [1, 2])\n1\n```\n\"\"\"\nfunction bar(x, y) ...","category":"page"},{"location":"manual/documentation/","page":"文档","title":"文档","text":"如上例所示,我们推荐在写文档时遵守一些简单约定:","category":"page"},{"location":"manual/documentation/","page":"文档","title":"文档","text":"始终在文档顶部显示函数的签名并带有四空格缩进,以便能够显示成 Julia 代码。\n这和在 Julia 代码中的签名是一样的(比如 mean(x::AbstractArray)),或是简化版。可选参数应该尽可能与默认值一同显示(例如 f(x, y=1)),这与实际的 Julia 语法一致。没有默认值的可选参数应该放在括号中(例如 f(x[, y]) 和 f(x[, y[, z]]))。可选的解决方法是使用多行:一个没有可选参数,其他的拥有可选参数(或者多个可选参数)。这个解决方案也可以用作给某个函数的多个方法来写文档。当一个函数接收到多个关键字参数,只在签名中包含占位符 (例如 f(x; )),并在 # Arguments 章节给出完整列表(参照下列第 4 点)。\n在简化的签名块后请包含一个描述函数能做什么或者对象代表什么的单行句。如果需要的话,在一个空行之后,在第二段提供更详细的信息。\n撰写函数的文档时,单行语句应使用祈使结构(比如「Do this」、「Return that」)而非第三人称(不要写「Returns the length...」)。并且应以句号结尾。如果函数的意义不能简单地总结,更好的方法是分成分开的组合句(虽然这不应被看做是对于每种情况下的绝对要求)。\n不要自我重复。\n因为签名给出了函数名,所以没有必要用「The function bar...」开始文档:直接说要点。类似地,如果签名指定了参数的类型,在描述中提到这些是多余的。\n只在确实必要时提供参数列表。\n对于简单函数,直接在函数目的的描述中提到参数的作用常常更加清楚。参数列表只会重复再其他地方提供过的信息。但是,对于拥有多个参数的(特别是含有关键字参数的)复杂函数来说,提供一个参数列表是个好主意。在这种情况下,请在函数的一般描述之后、标题 # Arguments 之下插入参数列表,并在每个参数前加个着重号 -。参数列表应该提到参数的类型和默认值(如果有):\n\"\"\"\n...\n# Arguments\n- `n::Integer`: the number of elements to compute.\n- `dim::Integer=1`: the dimensions along which to perform the computation.\n...\n\"\"\"\n给相关函数提供提示。\n有时会存在具有功能相联系的函数。为了更易于发现相关函数,请在段落 See also: 中为其提供一个小列表。\nSee also [`bar!`](@ref), [`baz`](@ref), [`baaz`](@ref).\n请在 # Examples 中包含一些代码例子。\n例子应尽可能按照 doctest 来写。doctest 是一个栅栏分隔开的代码块(请参阅代码块),其以 ```jldoctest 开头并包含任意数量的提示符 julia> 以及用来模拟 Julia REPL 的输入和预期输出。\nnote: Note\nDoctest 由 Documenter.jl 支持。有关更详细的文档,请参阅 Documenter 的手册。\n例如在下面的 docstring 中定义了变量 a,预期的输出,跟在 Julia REPL 中打印的一样,出现在后面。\n\"\"\"\nSome nice documentation here.\n\n# Examples\n```jldoctest\njulia> a = [1 2; 3 4]\n2×2 Array{Int64,2}:\n 1 2\n 3 4\n```\n\"\"\"\nwarning: Warning\nCalling rand and other RNG-related functions should be avoided in doctests since they will not produce consistent outputs during different Julia sessions. If you would like to show some random number generation related functionality, one option is to explicitly construct and seed your own RNG object (see Random) and pass it to the functions you are doctesting.Operating system word size (Int32 or Int64) as well as path separator differences (/ or \\) will also affect the reproducibility of some doctests.Note that whitespace in your doctest is significant! The doctest will fail if you misalign the output of pretty-printing an array, for example.\n你可以运行 make -C doc doctest=true 来运行在 Julia 手册和 API 文档中的 doctests,这样可以确保你的例子都能正常运行。\n为了表示输出结果被截断了,你应该在校验应该停止的一行写上 [...]。这个在当 doctest 显示有个异常被抛出时隐藏堆栈跟踪时很有用(堆栈跟踪包含对 julia 代码的行的非永久引用),例如:\n```jldoctest\njulia> div(1, 0)\nERROR: DivideError: integer division error\n[...]\n```\n那些不能进行测试的例子应该写在以 ```julia 开头的栅栏分隔的代码块中,以便在生成的文档中正确地高亮显示。\ntip: Tip\n例子应尽可能独立和可运行以便读者可以在不需要引入任何依赖的情况下对它们进行实验。\n使用倒引号来标识代码和方程。\nJulia 标识符和代码摘录应该出现在倒引号 ` 之间来使其能高亮显示。LaTeX 语法下的方程应该插入到双倒引号 `` 之间。请使用 Unicode 字符而非 LaTeX 转义序列,比如 ``α = 1`` 而非 ``\\\\alpha = 1``。\n请将起始和结束的\"\"\"符号单独成行。\n也就是说,请写:\n\"\"\"\n...\n\n...\n\"\"\"\nf(x, y) = ...\n而非:\n\"\"\"...\n\n...\"\"\"\nf(x, y) = ...\n这将让 docstring 的起始和结束位置更加清楚。\n请在代码中遵守单行长度限制。\nDocstring 是使用与代码相同的工具编辑的。所以应运用同样的约定。 建议一行 92 个字符后换行。\n请在 # Implementation 章节中提供自定义类型如何实现该函数的信息。这些实现细节是针对开发者而非用户的,解释了例如哪些函数应该被重写、哪些函数自动使用恰当的回退函数等信息,最好与描述函数的主体描述分开。\n对于长文档字符串,可以考虑使用 # Extended help 头拆分文档。典型的帮助模式将只显示标题上方的内容;你可以通过添加一个 ? 在表达的开头来查看完整的文档(即 ??foo 而不是 ?foo)。","category":"page"},{"location":"manual/documentation/#访问文档","page":"文档","title":"访问文档","text":"","category":"section"},{"location":"manual/documentation/","page":"文档","title":"文档","text":"文档可以在REPL中访问,也可以在 IJulia 中通过键入?紧接函数或者宏的名字并按下Enter访问。例如,","category":"page"},{"location":"manual/documentation/","page":"文档","title":"文档","text":"?cos\n?@time\n?r\"\"","category":"page"},{"location":"manual/documentation/","page":"文档","title":"文档","text":"会分别为相应的函数,宏或者字符显示文档。在 Juno 中,使用 Ctrl-J, Ctrl-D 会为光标处的对象显示文档。","category":"page"},{"location":"manual/documentation/#函数与方法","page":"文档","title":"函数与方法","text":"","category":"section"},{"location":"manual/documentation/","page":"文档","title":"文档","text":"在Julia中函数可能有多种实现,被称为方法。虽然通用函数 一般只有一个目的,Julia允许在必要时可以对方法独立写文档。 通常,应该只有最通用的方法才有文档,或者甚至只是函数本身 (也就是在function bar end之前没有任何方法的对象)。特定方法应该 只因为其行为与其他通用方法有所区别才写文档。在任何情况下都不应 重复其他地方有的信息。例如","category":"page"},{"location":"manual/documentation/","page":"文档","title":"文档","text":"\"\"\"\n *(x, y, z...)\n\nMultiplication operator. `x * y * z *...` calls this function with multiple\narguments, i.e. `*(x, y, z...)`.\n\"\"\"\nfunction *(x, y, z...)\n # ... [implementation sold separately] ...\nend\n\n\"\"\"\n *(x::AbstractString, y::AbstractString, z::AbstractString...)\n\nWhen applied to strings, concatenates them.\n\"\"\"\nfunction *(x::AbstractString, y::AbstractString, z::AbstractString...)\n # ... [insert secret sauce here] ...\nend\n\nhelp?> *\nsearch: * .*\n\n *(x, y, z...)\n\n Multiplication operator. x * y * z *... calls this function with multiple\n arguments, i.e. *(x,y,z...).\n\n *(x::AbstractString, y::AbstractString, z::AbstractString...)\n\n When applied to strings, concatenates them.","category":"page"},{"location":"manual/documentation/","page":"文档","title":"文档","text":"当从通用函数里抽取文档时,每个方法的元数据会用函数catdoc拼接,其当然可以被自定义类型重写。","category":"page"},{"location":"manual/documentation/#进阶用法","page":"文档","title":"进阶用法","text":"","category":"section"},{"location":"manual/documentation/","page":"文档","title":"文档","text":"@doc 宏将它的第一个参数与它的第二个参数关联在各个模块的名为 META 的字典中。","category":"page"},{"location":"manual/documentation/","page":"文档","title":"文档","text":"为了让写文档更加简单,语法分析器对宏名@doc特殊对待:如果@doc的调用只有一个参数,但是在下一行出现了另外一个表达式,那么这个表达式就会追加为宏的参数。所以接下来的语法会被分析成@doc的2个参数的调用:","category":"page"},{"location":"manual/documentation/","page":"文档","title":"文档","text":"@doc raw\"\"\"\n...\n\"\"\"\nf(x) = x","category":"page"},{"location":"manual/documentation/","page":"文档","title":"文档","text":"这就让使用任意对象(这里指的是原始字符串 raw\"\")作为 docstring 变得简单。","category":"page"},{"location":"manual/documentation/","page":"文档","title":"文档","text":"当@doc宏(或者doc函数)用作抽取文档时,他会在所有的META字典寻找与对象相关的元数据并且返回。返回的对象(例如一些Markdown内容)会默认智能地显示。这个设计也让以编程方法使用文档系统变得容易;例如,在一个函数的不同版本中重用文档:","category":"page"},{"location":"manual/documentation/","page":"文档","title":"文档","text":"@doc \"...\" foo!\n@doc (@doc foo!) foo","category":"page"},{"location":"manual/documentation/","page":"文档","title":"文档","text":"或者与Julia的元编程功能一起使用:","category":"page"},{"location":"manual/documentation/","page":"文档","title":"文档","text":"for (f, op) in ((:add, :+), (:subtract, :-), (:multiply, :*), (:divide, :/))\n @eval begin\n $f(a,b) = $op(a,b)\n end\nend\n@doc \"`add(a,b)` adds `a` and `b` together\" add\n@doc \"`subtract(a,b)` subtracts `b` from `a`\" subtract","category":"page"},{"location":"manual/documentation/","page":"文档","title":"文档","text":"写在非顶级块,比如begin, if, for, 和 let,中的文档会根据块的评估情况加入文档系统中,例如:","category":"page"},{"location":"manual/documentation/","page":"文档","title":"文档","text":"if condition()\n \"...\"\n f(x) = x\nend","category":"page"},{"location":"manual/documentation/","page":"文档","title":"文档","text":"会被加到f(x)的文档中,当condition()是true的时候。注意即使f(x)在块的末尾离开了作用域,他的文档还会保留。","category":"page"},{"location":"manual/documentation/","page":"文档","title":"文档","text":"可以利用元编程来帮助创建文档。当在文档字符串中使用字符串插值时,需要使用额外的 $ 例如:$($name)","category":"page"},{"location":"manual/documentation/","page":"文档","title":"文档","text":"for func in (:day, :dayofmonth)\n name = string(func)\n @eval begin\n @doc \"\"\"\n $($name)(dt::TimeType) -> Int64\n\n The day of month of a `Date` or `DateTime` as an `Int64`.\n \"\"\" $func(dt::Dates.TimeType)\n end\nend","category":"page"},{"location":"manual/documentation/#动态写文档","page":"文档","title":"动态写文档","text":"","category":"section"},{"location":"manual/documentation/","page":"文档","title":"文档","text":"有些时候类型的实例的合适的文档并非只取决于类型本身,也取决于实例的值。在这些情况下,你可以添加一个方法给自定义类型的Docs.getdoc函数,返回基于每个实例的文档。例如,","category":"page"},{"location":"manual/documentation/","page":"文档","title":"文档","text":"struct MyType\n value::Int\nend\n\nDocs.getdoc(t::MyType) = \"Documentation for MyType with value $(t.value)\"\n\nx = MyType(1)\ny = MyType(2)","category":"page"},{"location":"manual/documentation/","page":"文档","title":"文档","text":"?x 将显示“Documentation for MyType with value 1”,而?y 将显示“Documentation for MyType with value 2”。","category":"page"},{"location":"manual/documentation/#语法指南","page":"文档","title":"语法指南","text":"","category":"section"},{"location":"manual/documentation/","page":"文档","title":"文档","text":"本指南提供了如何将文档附加到所有可能的 Julia 语法构造的全面概述。","category":"page"},{"location":"manual/documentation/","page":"文档","title":"文档","text":"在下述例子中\"...\"用来表示任意的docstring。","category":"page"},{"location":"manual/documentation/#与-\\-字符","page":"文档","title":"$ 与 \\ 字符","text":"","category":"section"},{"location":"manual/documentation/","page":"文档","title":"文档","text":"$ 和 \\ 字符仍然被解析为字符串插值或转义序列的开始字符。 raw\"\" 字符串宏和 @doc 宏可以用来避免对它们进行转义。 当文档字符串包含 LaTeX 或 Julia 源代码,且示例中包含插值时,这是很方便的:","category":"page"},{"location":"manual/documentation/","page":"文档","title":"文档","text":"@doc raw\"\"\"\n```math\n\\LaTeX\n```\n\"\"\"\nfunction f end","category":"page"},{"location":"manual/documentation/#函数与方法-2","page":"文档","title":"函数与方法","text":"","category":"section"},{"location":"manual/documentation/","page":"文档","title":"文档","text":"\"...\"\nfunction f end\n\n\"...\"\nf","category":"page"},{"location":"manual/documentation/","page":"文档","title":"文档","text":"把 docstring \"...\" 添加给了函数 f。首选的语法是第一种,虽然两者是等价的。","category":"page"},{"location":"manual/documentation/","page":"文档","title":"文档","text":"\"...\"\nf(x) = x\n\n\"...\"\nfunction f(x)\n x\nend\n\n\"...\"\nf(x)","category":"page"},{"location":"manual/documentation/","page":"文档","title":"文档","text":"把 docstring \"...\" 添加给了方法 f(::Any)。","category":"page"},{"location":"manual/documentation/","page":"文档","title":"文档","text":"\"...\"\nf(x, y = 1) = x + y","category":"page"},{"location":"manual/documentation/","page":"文档","title":"文档","text":"把 docstring \"...\" 添加给了两个方法,分别为 f(::Any) 和 f(::Any, ::Any)。","category":"page"},{"location":"manual/documentation/#宏","page":"文档","title":"宏","text":"","category":"section"},{"location":"manual/documentation/","page":"文档","title":"文档","text":"\"...\"\nmacro m(x) end","category":"page"},{"location":"manual/documentation/","page":"文档","title":"文档","text":"把 docstring \"...\" 添加给了宏 @m(::Any) 的定义。","category":"page"},{"location":"manual/documentation/","page":"文档","title":"文档","text":"\"...\"\n:(@m)","category":"page"},{"location":"manual/documentation/","page":"文档","title":"文档","text":"把 docstring \"...\" 添加给了名为 @m 的宏。","category":"page"},{"location":"manual/documentation/#类型","page":"文档","title":"类型","text":"","category":"section"},{"location":"manual/documentation/","page":"文档","title":"文档","text":"\"...\"\nabstract type T1 end\n\n\"...\"\nmutable struct T2\n ...\nend\n\n\"...\"\nstruct T3\n ...\nend","category":"page"},{"location":"manual/documentation/","page":"文档","title":"文档","text":"把 docstring \"...\" 添加给了类型 T1、T2 和 T3。","category":"page"},{"location":"manual/documentation/","page":"文档","title":"文档","text":"\"...\"\nstruct T\n \"x\"\n x\n \"y\"\n y\nend","category":"page"},{"location":"manual/documentation/","page":"文档","title":"文档","text":"把 docstring \"...\" 添加给了类型 T,\"x\" 添加给字段 T.x,\"y\" 添加给字段 T.y。也可以运用于mutable struct 类型。","category":"page"},{"location":"manual/documentation/#模块","page":"文档","title":"模块","text":"","category":"section"},{"location":"manual/documentation/","page":"文档","title":"文档","text":"\"...\"\nmodule M end\n\nmodule M\n\n\"...\"\nM\n\nend","category":"page"},{"location":"manual/documentation/","page":"文档","title":"文档","text":"把 docstring \"...\" 添加给了模块 M。首选的语法是在模块之前添加 docstring,虽然两者是等价的。","category":"page"},{"location":"manual/documentation/","page":"文档","title":"文档","text":"\"...\"\nbaremodule M\n# ...\nend\n\nbaremodule M\n\nimport Base: @doc\n\n\"...\"\nf(x) = x\n\nend","category":"page"},{"location":"manual/documentation/","page":"文档","title":"文档","text":"通过在表达式上方放置一个 docstring 来记录 baremodule 会自动将 @doc 导入到模块中。 当没有记录模块表达式时,必须手动完成这些导入。","category":"page"},{"location":"manual/documentation/#全局变量","page":"文档","title":"全局变量","text":"","category":"section"},{"location":"manual/documentation/","page":"文档","title":"文档","text":"\"...\"\nconst a = 1\n\n\"...\"\nb = 2\n\n\"...\"\nglobal c = 3","category":"page"},{"location":"manual/documentation/","page":"文档","title":"文档","text":"把docstring\"...\"添加给了绑定 a,b和c。","category":"page"},{"location":"manual/documentation/","page":"文档","title":"文档","text":"绑定是用来在模块中存储对于特定符号的引用而非存储被引用的值本身。","category":"page"},{"location":"manual/documentation/","page":"文档","title":"文档","text":"note: Note\n当一个 const 定义只是用作定义另外一个定义的别名时,比如函数 div 和其在 Base 中的别名 ÷,并不要为别名写文档,转而去为实际的函数写文档。如果别名写了文档而实际定义没有,那么文档系统(? 模式)在寻找实际定义的文档时将不会返回别名的对应文档。比如你应该写\"...\"\nf(x) = x + 1\nconst alias = f而非f(x) = x + 1\n\"...\"\nconst alias = f","category":"page"},{"location":"manual/documentation/","page":"文档","title":"文档","text":"\"...\"\nsym","category":"page"},{"location":"manual/documentation/","page":"文档","title":"文档","text":"把 docstring \"...\" 添加给值 sym。但是应首选在 sym 的定义处写文档。","category":"page"},{"location":"manual/documentation/#多重对象","page":"文档","title":"多重对象","text":"","category":"section"},{"location":"manual/documentation/","page":"文档","title":"文档","text":"\"...\"\na, b","category":"page"},{"location":"manual/documentation/","page":"文档","title":"文档","text":"把docstring \"...\" 添加给a和b,两个都应该是可以写文档的表达式。这个语法等价于","category":"page"},{"location":"manual/documentation/","page":"文档","title":"文档","text":"\"...\"\na\n\n\"...\"\nb","category":"page"},{"location":"manual/documentation/","page":"文档","title":"文档","text":"这种方法可以给任意数量的表达式写文档。当两个函数相关,比如非变版本f和可变版本f!,这个语法是有用的。","category":"page"},{"location":"manual/documentation/#宏生成代码","page":"文档","title":"宏生成代码","text":"","category":"section"},{"location":"manual/documentation/","page":"文档","title":"文档","text":"\"...\"\n@m expression","category":"page"},{"location":"manual/documentation/","page":"文档","title":"文档","text":"把docstring \"...\" 添加给通过展开 @m expression 生成的表达式。 这就允许由 @inline、@noinline、@generated 或者任意其他宏装饰的表达式,能和没有装饰的表达式以同样的方式写文档。","category":"page"},{"location":"manual/documentation/","page":"文档","title":"文档","text":"宏作者应该注意到只有只生成单个表达式的宏才会自动支持docstring。如果宏返回的是含有多个子表达式的块,需要写文档的子表达式应该使用宏 @__doc__ 标记。","category":"page"},{"location":"manual/documentation/","page":"文档","title":"文档","text":"@enum 宏使用了 @__doc__ 来允许给 Enum 写文档。它的做法可以作为如何正确使用 @__doc__ 的范例。","category":"page"},{"location":"manual/documentation/","page":"文档","title":"文档","text":"Core.@__doc__","category":"page"},{"location":"manual/documentation/#Core.@__doc__","page":"文档","title":"Core.@__doc__","text":"@__doc__(ex)\n\nLow-level macro used to mark expressions returned by a macro that should be documented. If more than one expression is marked then the same docstring is applied to each expression.\n\nmacro example(f)\n quote\n $(f)() = 0\n @__doc__ $(f)(x) = 1\n $(f)(x, y) = 2\n end |> esc\nend\n\n@__doc__ has no effect when a macro that uses it is not documented.\n\n\n\n\n\n","category":"macro"},{"location":"manual/noteworthy-differences/#与其他语言的显著差异","page":"与其他语言的显著差异","title":"与其他语言的显著差异","text":"","category":"section"},{"location":"manual/noteworthy-differences/#Noteworthy-differences-from-MATLAB","page":"与其他语言的显著差异","title":"与 MATLAB 的显著差异","text":"","category":"section"},{"location":"manual/noteworthy-differences/","page":"与其他语言的显著差异","title":"与其他语言的显著差异","text":"虽然 MATLAB 用户可能会发现 Julia 的语法很熟悉,但 Julia 不是 MATLAB 的克隆。 它们之间存在重大的语法和功能差异。 以下是一些可能会使习惯于 MATLAB 的 Julia 用户感到困扰的显著差异:","category":"page"},{"location":"manual/noteworthy-differences/","page":"与其他语言的显著差异","title":"与其他语言的显著差异","text":"Julia 数组使用方括号 A[i,j] 进行索引。\nJulia 数组在分配给另一个变量时不会被复制。 在A = B之后,改变B的元素也会改变A的元素。\nJulia 的值在向函数传递时不发生复制。如果某个函数修改了数组,这一修改对调用者是可见的。\nJulia 不会在赋值语句中自动增长数组。 而在 MATLAB 中 a(4) = 3.2 可以创建数组 a = [0 0 0 3.2],而 a(5) = 7 可以将它增长为 a = [0 0 0 3.2 7]。如果 a 的长度小于 5 或者这个语句是第一次使用标识符 a,则相应的 Julia 语句 a[5] = 7 会抛出错误。Julia 使用 push! 和 append! 来增长 Vector,它们比 MATLAB 的 a(end+1) = val 更高效。\n虚数单位 sqrt(-1) 在 Julia 中表示为 im,而不是在 MATLAB 中的 i 或 j。\n在 Julia 中,没有小数点的数字字面量(例如 42)会创建整数而不是浮点数。也支持任意大整数字面量。因此,某些操作(如 2^-1)将抛出 domain error,因为结果不是整数(有关的详细信息,请参阅常见问题中有关 domain errors 的条目)。 在 Julia 中,没有小数点的数字字面量(例如 42)会创建整数而不是浮点数。因此,某些操作会因为需要浮点数而抛出 domain error;例如 julia > a = -1; 2^a ,因为结果不是整数了。请参阅常见问题中有关 domain errors 的条目)。\n在 Julia 中,能返回多个值并将其赋值为元组,例如 (a, b) = (1, 2) 或 a, b = 1, 2。 在 Julia 中不存在 MATLAB 的 nargout,它通常在 MATLAB 中用于根据返回值的数量执行可选工作。取而代之的是,用户可以使用可选参数和关键字参数来实现类似的功能。\nJulia 拥有真正的一维数组。列向量的大小为 N,而不是 Nx1。例如,rand(N) 创建一个一维数组。\n在 Julia 中,[x,y,z] 将始终构造一个包含x、y 和 z 的 3 元数组。\n要在第一个维度(「垂直列」)中连接元素,请使用 vcat(x,y,z) 或用分号分隔([x; y; z])。\n要在第二个维度(「水平行」)中连接元素,请使用 hcat(x,y,z) 或用空格分隔([x y z])。\n要构造分块矩阵(在前两个维度中连接元素),请使用 hvcat 或组合空格和分号([a b; c d])。\n在 Julia 中,a:b 和 a:b:c 构造 AbstractRange 对象。使用 collect(a:b) 构造一个类似 MATLAB 中完整的向量。通常,不需要调用 collect。在大多数情况下,AbstractRange 对象将像普通数组一样运行,但效率更高,因为它是懒惰求值。这种创建专用对象而不是完整数组的模式经常被使用,并且也可以在诸如 range 之类的函数中看到,或者在诸如 enumerate 和 zip 之类的迭代器中看到。特殊对象大多可以像正常数组一样使用。\nJulia 中的函数返回其最后一个表达式或 return 关键字的值而无需在函数定义中列出要返回的变量的名称(有关详细信息,请参阅 return 关键字)。\nJulia 脚本可以包含任意数量的函数,并且在加载文件时,所有定义都将在外部可见。可以从当前工作目录之外的文件加载函数定义。\n在 Julia 中,例如 sum、prod 和 max 的归约操作会作用到数组的每一个元素上,当调用时只有一个函数,例如 sum(A),即使 A 并不只有一个维度。\n在 Julia 中,调用无参数的函数时必须使用小括号,例如 rand()。\nJulia 不鼓励使用分号来结束语句。语句的结果不会自动打印(除了在 REPL 中),并且代码的一行不必使用分号结尾。println 或者 @printf 能用来打印特定输出。\n在 Julia 中,如果 A 和 B 是数组,像 A == B 这样的逻辑比较运算符不会返回布尔值数组。相反地,请使用 A .== B。对于其他的像是 <、> 的布尔运算符同理。\n在 Julia 中,运算符&、| 和 ⊻(xor)进行按位操作,分别与MATLAB中的and、or 和 xor 等价,并且优先级与 Python 的按位运算符相似(不像 C)。他们可以对标量运算或者数组中逐元素运算,可以用来合并逻辑数组,但是注意运算顺序的区别:括号可能是必要的(例如,选择 A 中等于 1 或 2 的元素可使用 (A .== 1) .| (A .== 2))。\n在 Julia 中,集合的元素可以使用 splat 运算符 ... 来作为参数传递给函数,如 xs=[1,2]; f(xs...)。\nJulia 的 svd 将奇异值作为向量而非密集对角矩阵返回。\n在 Julia 中,... 不用于延续代码行。不同的是,Julia 中不完整的表达式会自动延续到下一行。\n在 Julia 和 MATLAB 中,变量 ans 被设置为交互式会话中提交的最后一个表达式的值。在 Julia 中与 MATLAB 不同的是,当 Julia 代码以非交互式模式运行时并不会设置 ans。\nJulia 的 struct 不支持在运行时动态地添加字段,这与 MATLAB 的 class 不同。 如需支持,请使用 Dict。Julia 中的字典不是有序的。\n在 Julia 中,每个模块有自身的全局作用域/命名空间,而在 MATLAB 中只有一个全局作用域。\n在 MATLAB 中,删除不需要的值的惯用方法是使用逻辑索引,如表达式 x(x>3) 或语句 x(x>3) = [] 来 in-place 修改 x。相比之下,Julia 提供了更高阶的函数 filter 和 filter!,允许用户编写 filter(z->z>3, x) 和 filter!(z->z>3, x) 来代替相应直译 x[x.>3] 和 x = x[x.>3]。使用 filter! 可以减少临时数组的使用。\n类似于提取(或「解引用」)元胞数组的所有元素的操作,例如 MATLAB 中的 vertcat(A{:}),在 Julia 中是使用 splat 运算符编写的,例如 vcat(A...)。\n在 Julia 中,adjoint 函数执行共轭转置;在 MATLAB 中,adjoint 提供了经典伴随,它是余子式的转置。\n在 Julia 中,a^b^c 被认为是 a^(b^c) 而在 MATLAB 中它是 (a^b)^c。","category":"page"},{"location":"manual/noteworthy-differences/#Noteworthy-differences-from-R","page":"与其他语言的显著差异","title":"与 R 的显著差异","text":"","category":"section"},{"location":"manual/noteworthy-differences/","page":"与其他语言的显著差异","title":"与其他语言的显著差异","text":"Julia 的目标之一是为数据分析和统计编程提供高效的语言。对于从 R 转到 Julia 的用户来说,这是一些显著差异:","category":"page"},{"location":"manual/noteworthy-differences/","page":"与其他语言的显著差异","title":"与其他语言的显著差异","text":"Julia 的单引号封闭字符,而不是字符串。\nJulia 可以通过索引字符串来创建子字符串。在 R 中,在创建子字符串之前必须将字符串转换为字符向量。\n在 Julia 中,与 Python 相同但与 R 不同的是,字符串可由三重引号 \"\"\" ... \"\"\" 创建。此语法对于构造包含换行符的字符串很方便。\n在 Julia 中,可变参数使用 splat 运算符 ... 指定,该运算符总是跟在具体变量的名称后面,与 R 的不同,R 的 ... 可以单独出现。\n在 Julia 中,模数是 mod(a, b),而不是 a %% b。Julia 中的 % 是余数运算符。\n在 Julia 中,并非所有数据结构都支持逻辑索引。此外,Julia 中的逻辑索引只支持长度等于被索引对象的向量。例如:\n在 R 中,c(1, 2, 3, 4)[c(TRUE, FALSE)] 等价于 c(1, 3)。\n在 R 中,c(1, 2, 3, 4)[c(TRUE, FALSE, TRUE, FALSE)] 等价于 c(1, 3)。\n在 Julia 中,[1, 2, 3, 4][[true, false]] 抛出 BoundsError。\n在 Julia 中,[1, 2, 3, 4][[true, false, true, false]] 产生 [1, 3]。\n与许多语言一样,Julia 并不总是允许对不同长度的向量进行操作,与 R 不同,R 中的向量只需要共享一个公共的索引范围。例如,c(1, 2, 3, 4) + c(1, 2) 是有效的 R,但等价的 [1, 2, 3, 4] + [1, 2] 在 Julia 中会抛出一个错误。\n在逗号不改变代码含义时,Julia 允许使用可选的尾随括号。在索引数组时,这可能在 R 用户间造成混淆。例如,R 中的 x[1,] 将返回矩阵的第一行;但是,在 Julia 中,引号被忽略,于是 x[1,] == x[1],并且将返回第一个元素。要提取一行,请务必使用 :,如 x[1,:]。\nJulia 的 map 首先接受函数,然后是该函数的参数,这与 R 中的 lapply(, function, ...) 不同。类似地,R 中的 apply(X, MARGIN, FUN, ...) 等价于 Julia 的 mapslices,其中函数是第一个参数。\nR 中的多变量 apply,如 mapply(choose, 11:13, 1:3),在 Julia 中可以编写成 broadcast(binomial, 11:13, 1:3)。等价地,Julia 提供了更短的点语法来向量化函数 binomial.(11:13, 1:3)。\nJulia 使用 end 来表示条件块(如 if)、循环块(如 while/for)和函数的结束。为了代替单行 if ( cond ) statement,Julia 允许形式为 if cond; statement; end、cond && statement 和 !cond || statement 的语句。后两种语法中的赋值语句必须显式地包含在括号中,例如 cond && (x = value),这是因为运算符的优先级。\n在 Julia 中,<-, <<- 和 -> 不是赋值运算符。\nJulia 的 -> 创建一个匿名函数。\nJulia 使用括号构造向量。Julia 的 [1, 2, 3] 等价于 R 的 c(1, 2, 3)。\nJulia 的 * 运算符可以执行矩阵乘法,这与 R 不同。如果 A 和 B 都是矩阵,那么 A * B 在 Julia 中表示矩阵乘法,等价于 R 的 A %*% B。在 R 中,相同的符号将执行逐元素(Hadamard)乘积。要在 Julia 中使用逐元素乘法运算,你需要编写 A .* B。\nJulia 使用 transpose 函数来执行矩阵转置,使用 ' 运算符或 adjoint 函数来执行共轭转置。因此,Julia 的 transpose(A) 等价于 R 的 t(A)。另外,Julia 中的非递归转置由 permutedims 函数提供。\nJulia 在编写 if 语句或 for/while 循环时不需要括号:请使用 for i in [1, 2, 3] 代替 for (int i=1; i <= 3; i++),以及 if i == 1 代替 if (i == 1)\nJulia 不把数字 0 和 1 视为布尔值。在 Julia 中不能编写 if (1),因为 if 语句只接受布尔值。相反,可以编写 if true、if Bool(1) 或 if 1==1。\nJulia 不提供 nrow 和 ncol。相反,请使用 size(M, 1) 代替 nrow(M) 以及 size(M, 2) 代替 ncol(M)\nJulia 仔细区分了标量、向量和矩阵。在 R 中,1 和 c(1) 是相同的。在 Julia 中,它们不能互换地使用。\nJulia 的 diag 和 diagm 与 R 的不同。\nJulia 赋值操作的左侧不能为函数调用的结果:你不能编写 diag(M) = fill(1, n)。\nJulia 不鼓励使用函数填充主命名空间。Julia 的大多数统计功能都可在 JuliaStats 组织的包中找到。例如:\n与概率分布相关的函数由 Distributions 包提供。\nDataFrames 包提供数据帧。\n广义线性模型由 GLM 包提供。\nJulia 提供了元组和真正的哈希表,但不提供 R 风格的列表。在返回多个项时,通常应使用元组或具名元组:请使用 (1, 2) 或 (a=1, b=2) 代替 list(a = 1, b = 2)。\nJulia 鼓励用户编写自己的类型,它比 R 中的 S3 或 S4 对象更容易使用。Julia 的多重派发系统意味着 table(x::TypeA) 和 table(x::TypeB) 类似于 R 的 table.TypeA(x) 和 table.TypeB(x)。\nJulia 的值在向函数传递时不发生复制。如果某个函数修改了数组,这一修改对调用者是可见的。这与 R 非常不同,允许新函数更高效地操作大型数据结构。\n在 Julia 中,向量和矩阵使用 hcat、vcat 和 hvcat 拼接,而不是像在 R 中那样使用 c、rbind 和 cbind。\n在 Julia 中,像 a:b 这样的 range 不是 R 中的向量简写,而是一个专门的 AbstractRange 对象,该对象用于没有高内存开销地进行迭代。要将 range 转换为 vector,请使用 collect(a:b)。\nJulia 的 max 和 min 分别等价于 R 中的 pmax 和 pmin,但两者的参数都需要具有相同的维度。虽然 maximum 和 minimum 代替了 R 中的 max 和 min,但它们之间有重大区别。\nJulia 的 sum、prod、maximum 和 minimum 与它们在 R 中的对应物不同。它们都接受一个可选的关键字参数 dims,它表示执行操作的维度。例如,在 Julia 中令 A = [1 2; 3 4],在 R 中令 B <- rbind(c(1,2),c(3,4)) 是与之相同的矩阵。然后 sum(A) 得到与 sum(B) 相同的结果,但 sum(A, dims=1) 是一个包含每一列总和的行向量,sum(A, dims=2) 是一个包含每一行总和的列向量。这与 R 的行为形成了对比,在 R 中,单独的 colSums(B) 和 rowSums(B) 提供了这些功能。如果 dims 关键字参数是向量,则它指定执行求和的所有维度,并同时保持待求和数组的维数,例如 sum(A, dims=(1,2)) == hcat(10)。应该注意的是,没有针对第二个参数的错误检查。\nJulia 具有一些可以改变其参数的函数。例如,它具有 sort 和 sort!。\n在 R 中,高性能需要向量化。在 Julia 中,这几乎恰恰相反:性能最高的代码通常通过去向量化的循环来实现。\nJulia 是立即求值的,不支持 R 风格的惰性求值。对于大多数用户来说,这意味着很少有未引用的表达式或列名。\nJulia 不支持 NULL 类型。最接近的等价物是 nothing,但它的行为类似于标量值而不是列表。请使用 x === nothing 代替 is.null(x)。\n在 Julia 中,缺失值由 missing 表示,而不是由 NA 表示。请使用 ismissing(x)(或者在向量上使用逐元素操作 ismissing.(x))代替 isna(x)。通常使用 skipmissing 代替 na.rm=TRUE(尽管在某些特定情况下函数接受 skipmissing 参数)。\nJulia 缺少 R 中的 assign 或 get 的等价物。\n在 Julia 中,return 不需要括号。\n在 R 中,删除不需要的值的惯用方法是使用逻辑索引,如表达式 x[x>3] 或语句 x = x[x>3] 来 in-place 修改 x。相比之下,Julia 提供了更高阶的函数 filter 和 filter!,允许用户编写 filter(z->z>3, x) 和 filter!(z->z>3, x) 来代替相应直译 x[x.>3] 和 x = x[x.>3]。使用 filter! 可以减少临时数组的使用。","category":"page"},{"location":"manual/noteworthy-differences/#Noteworthy-differences-from-Python","page":"与其他语言的显著差异","title":"与 Python 的显著差异","text":"","category":"section"},{"location":"manual/noteworthy-differences/","page":"与其他语言的显著差异","title":"与其他语言的显著差异","text":"Julia 的 for, if, while 等语句块都以 end 关键字结束。代码的缩进不像在 Python 中那样重要。Julia 也没有 pass 关键字。 \nJulia 中的字符串使用双引号构造,如 \"text\",也可以使用三引号构造多行字符串。而在 Python 中可以使用单引号('text')或者双引号(\"text\")。单引号在 Julia 中用来表示单个字符,例如 'c'。\n在 Julia 中字符串的拼接使用 *,而不是像 Python 一样使用 +。类似的,字符串重复多次 Julia 使用 ^ 而不是 *。Julia 也不支持隐式的字符串拼接,例如 Python 中的 'ab' 'cd' == 'abcd'。\nPython 列表——灵活但缓慢——对应于 Julia 的 Vector{Any} 类型或更一般的 Vector{T},其中 T 是一些非具体元素类型。 “快”的数组,如 NumPy 数组,它们就地存储元素(即,dtype 是 np.float64、[('f1', np.uint64), ('f2', np.int32)], 等)可以用 Array{T} 表示,其中 T 是一个具体的、不可变的元素类型。 这包括内置类型,如 Float64、Int32、Int64,也包括更复杂的类型,如 Tuple{UInt64,Float64} 和许多用户定义的类型。\n在 Julia 中,数组、字符串等的索引从 1 开始,而不是从 0 开始。\nJulia 里的切片包含最后一个元素。Julia 里的 a[2:3] 等同于 Python 中的 a[1:3]。\nJulia 不支持负数索引。特别地,列表或数组的最后一个元素在 Julia 中使用 end 索引,而不像在 Python 中使用 -1。\nJulia 的索引必须写全。Python 中的 x[1:] 等价于 Julia 中的 x[2:end]。\nJulia 的范围语法为 x[start:step:stop],而 Python 的格式为 x[start:(stop+1):step]。","category":"page"},{"location":"manual/noteworthy-differences/","page":"与其他语言的显著差异","title":"与其他语言的显著差异","text":"因此 Python 中的 x[0:10:2] 等价于 Julia 里的 x[1:2:10]。类似的 Python 中的反转数组 x[::-1] 等价于 Julia 中的 x[end:-1:1]。","category":"page"},{"location":"manual/noteworthy-differences/","page":"与其他语言的显著差异","title":"与其他语言的显著差异","text":"在 Julia 中队一个矩阵取索引 X[[1,2], [1,3]] 返回一个子矩阵,它包含了第一和第二行与第一和第三列的交集。","category":"page"},{"location":"manual/noteworthy-differences/","page":"与其他语言的显著差异","title":"与其他语言的显著差异","text":"在 Python 中 X[[1,2], [1,3]] 返回一个向量,它包含索引 [1,1] 和 [2,3] 的值。Julia 中的 X[[1,2], [1,3]] 等价于 Python 中的 X[np.ix_([0,1],[0,2])]。Python 中的 X[[1,2], [1,3]] 等价于 Julia 中的 X[[CartesianIndex(1,1), CartesianIndex(2,3)]]。","category":"page"},{"location":"manual/noteworthy-differences/","page":"与其他语言的显著差异","title":"与其他语言的显著差异","text":"Julia 没有用来续行的语法:如果在行的末尾,到目前为止的输入是一个完整的表达式,则认为其已经结束;否则,认为输入继续。强制表达式继续的一种方式是将其包含在括号中。\n默认情况下,Julia 数组是列优先(Fortran 排序),而 NumPy 数组是行优先(C 排序)。为了在循环数组时获得最佳性能,Julia 中的循环顺序应相对于 NumPy 颠倒(请参阅性能提示的相关部分)。\nJulia 的更新运算符(例如 +=,-=,···)是非原位操作(not in-place),而 Numpy 的是。这意味着 A = [1, 1]; B = A; B += [3, 3] 不会改变 A 中的值,而将名称 B 重新绑定到右侧表达式 B = B + 3 的结果,这是一个新的数组。对于 in-place 操作,使用 B .+= 3(另请参阅 dot operators)、显式的循环或者 InplaceOps.jl。\nJulia 的函数在调用时,每次都对默认参数重新求值,不像 Python 只在函数定义时对默认参数求一次值。","category":"page"},{"location":"manual/noteworthy-differences/","page":"与其他语言的显著差异","title":"与其他语言的显著差异","text":"举例来说:Julia 的函数 f(x=rand()) = x 在无参数调用时(f()),每次都会返回不同的随机数。 另一方面,函数 g(x=[1,2]) = push!(x,3) 无参数调用时 g(),永远返回 [1,2,3]。","category":"page"},{"location":"manual/noteworthy-differences/","page":"与其他语言的显著差异","title":"与其他语言的显著差异","text":"在 Julia 中,必须使用关键字来传递关键字参数,这与 Python 中通常可以按位置传递它们不同。尝试按位置传递关键字参数会改变方法签名,从而导致 MethodError 或调用错误的方法。\n在 Julia 中,% 是余数运算符,而在 Python 中是模运算符。","category":"page"},{"location":"manual/noteworthy-differences/","page":"与其他语言的显著差异","title":"与其他语言的显著差异","text":"(译注:二者在参数有负数时有区别)","category":"page"},{"location":"manual/noteworthy-differences/","page":"与其他语言的显著差异","title":"与其他语言的显著差异","text":"在 Julia 中,常用的整数类型 Int 对应机器的整数类型,Int32 或 Int64。不像 Python 中的整数 int 是任意精度的。这意味着 Julia 中默认的整数类型会溢出,因此 2^64 == 0。如果你要表示一个大数,请选择一个合适的类型。如:Int128、任意精度的 BigInt 或者浮点类型 Flost64。\nJulia 中虚数单位 sqrt(-1) 是 im,而不是 Python 中的 j。\nJulia 中指数是 ^,而不是 Python 中的 **。\nJulia 使用 Nothing 类型的实例 nothing 代表空值(null),而不是 Python 中 NoneType 类的 None。\n在 Julia 中,标准的运算符作用在矩阵上就得到矩阵操作,不像 Python 标准运算符默认是逐元素操作。当 A 和 B 都是矩阵时,A * B 在 Julia 中代表着矩阵乘法,而不是 Python 中的逐元素相乘。即:Julia 中的 A * B 等同于 Python 的 A @ B;Python 中的 A * B 等同于 Julia 中的 A .* B。\nJulia 中的伴随操作符 ' 返回向量的转置(一种行向量的懒惰表示法)。Python 中对向量执行 .T 返回它本身(没有效果)。\n在Julia中,一个函数可能包含多个具体实现(称为方法),与Python中的函数相比,这些实现是根据调用的所有参数的类型通过多重派发选择的,它只有一个实现,没有多态性(与Python方法调用相反,Python方法调用使用不同的语法,并允许在方法的接收者上进行派发)。\nJulia 没有类(class),取而代替的是结构体(structures),可以是可变的或不可变的,它们只包含数据而不包含方法。","category":"page"},{"location":"manual/noteworthy-differences/","page":"与其他语言的显著差异","title":"与其他语言的显著差异","text":"在 Python 中调用类实例的方法 (x = MyClass(*args); x.f(y)) 对应于 Julia 中的函数调用,例如 x = MyType(args...); f(x, y)。 总的来说,多重派发比 Python 类系统更灵活和强大。\nJulia 的结构体有且只能有一个抽象超类型(abstract supertype),而 Python 的类可以纪成一个或多个、抽象或具体的超类(superclasses)。\n逻辑 Julia 程序结构(包和模块)独立于文件结构(include 用于附加文件),而 Python 代码结构由目录(包)和文件(模块)定义。\nJulia 中的三元运算符 x > 0 ? 1 : -1 对应于 Python 中的条件表达式 1 if x > 0 else -1。\nJulia 中以 @ 开头的符号是宏(macro),而 Python 中是装饰器(decorator)。\nJulia 的异常处理使用 try — catch — finally,而不是 Python 的 try — except — finally。与 Python 不同的是,因为性能的原因,Julia 不推荐在正常流程中使用异常处理。\nJulia 的循环很快,所以没必要手动向量化(vectorized)。\n小心 Julia 中的非常量全局变量,尤其它出现在循环中时。因为你在 Julia 中可以写出贴近硬件的代码,这时使用全局变量的影响非常大(参见性能建议)\nPython 中大多数的值都能用在逻辑运算中。例如:if \"a\" 永真,if \"\" 恒假。在 Julia 中你只能使用布尔类型的值,或者显示的将其他值转为布尔类型,否则就会抛出异常。例如当你想测试字符串是否为空是,请使用 if !isempty(\"\")。\n在 Julia 中大多数代码块都会引入新的本地作用域(local scope)。例如:循环和异常处理的 try — catch — finally。注意:列表推断(comprehensions)与生成器在 Julia 和 Python 中都会引入新的作用域;而 if 分支则都不会引入。","category":"page"},{"location":"manual/noteworthy-differences/#Noteworthy-differences-from-C/C","page":"与其他语言的显著差异","title":"与 C/C++ 的显著差异","text":"","category":"section"},{"location":"manual/noteworthy-differences/","page":"与其他语言的显著差异","title":"与其他语言的显著差异","text":"Julia 的数组由方括号索引,方括号中可以包含不止一个维度 A[i,j]。这样的语法不仅仅是像 C/C++ 中那样对指针或者地址引用的语法糖,参见关于数组构造的语法的 Julia 文档。\n在 Julia 中,数组、字符串等的索引从 1 开始,而不是从 0 开始。\nJulia 的数组在赋值给另一个变量时不发生复制。执行 A = B 后,改变 B 中元素也会修改 A。像 += 这样的更新运算符不会以 in-place 的方式执行,而是相当于 A = A + B,将左侧绑定到右侧表达式的计算结果上。\nJulia 的数组是列优先的(Fortran 顺序),而 C/C++ 的数组默认是行优先的。要使数组上的循环性能最优,在 Julia 中循环的顺序应该与 C/C++ 相反(参见 性能建议)。\nJulia 的值在赋值或向函数传递时不发生复制。如果某个函数修改了数组,这一修改对调用者是可见的。\n在 Julia 中,空格是有意义的,这与 C/C++ 不同,所以向 Julia 程序中添加或删除空格时必须谨慎。\n在 Julia 中,没有小数点的数值字面量(如 42)生成有符号整数,类型为 Int,但如果字面量太长,超过了机器字长,则会被自动提升为容量更大的类型,例如 Int64(如果 Int 是 Int32)、Int128,或者任意精度的 BigInt 类型。不存在诸如 L, LL, U, UL, ULL 这样的数值字面量后缀指示无符号和/或有符号与无符号。十进制字面量始终是有符号的,十六进制字面量(像 C/C++ 一样由 0x 开头)是无符号的。另外,十六进制字面量与 C/C++/Java 不同,也与 Julia 中的十进制字面量不同,它们的类型取决于字面量的长度,包括开头的 0。例如,0x0 和 0x00 的类型是 UInt8,0x000 和 0x0000 的类型是 UInt16。同理,字面量的长度在 5-8 之间,类型为 UInt32;在 9-16 之间,类型为 UInt64;在 17-32 之间,类型为 UInt128。当定义十六进制掩码时,就需要将这一问题考虑在内,比如 ~0xf == 0xf0 与 ~0x000f == 0xfff0 完全不同。64 位 Float64 和 32 位 Float32 的字面量分别表示为 1.0 和 1.0f0。浮点字面量在无法被精确表示时舍入(且不会提升为 BigFloat 类型)。浮点字面量在行为上与 C/C++ 更接近。八进制(前缀为 0o)和二进制(前缀为 0b)也被视为无符号的。\n在 Julia 中,当两个操作数都是整数类型时,除法运算符 / 返回一个浮点数。 要执行整数除法,请使用 div 或 ÷。\n使用浮点类型索引数组在 Julia 中通常是错误的。 C 表达式 a[i / 2] 的 Julia 等价写法是 a[i ÷ 2 + 1],其中 i 是整数类型。\n字符串字面量可用 \" 或 \"\"\" 分隔,用 \"\"\" 分隔的字面量可以包含 \" 字符而无需像 \"\\\"\" 这样来引用它。字符串字面量可以包含插入其中的其他变量或表达式,由 $variablename 或 $(expression) 表示,它在该函数所处的上下文中计算变量名或表达式。\n// 表示 Rational 数,而非单行注释(其在 Julia 中是 #)\n#= 表示多行注释的开头,=# 结束之。\nJulia 中的函数返回其最后一个表达式或 return 关键字的值。可以从函数中返回多个值并将其作为元组赋值,如 (a, b) = myfunction() 或 a, b = myfunction(),而不必像在 C/C++ 中那样必须传递指向值的指针(即 a = myfunction(&b))。\nJulia 不要求使用分号来结束语句。表达式的结果不会自动打印(除了在交互式提示符中,即 REPL),且代码行不需要以分号结尾。println 或 @printf 可用于打印特定输出。在 REPL 中,; 可用于抑制输出。; 在 [ ] 中也有不同的含义,需要注意。; 可用于在单行中分隔表达式,但在许多情况下不是绝对必要的,更经常是为了可读性。\n在 Julia 中,运算符 ⊻(xor)执行按位 XOR 操作,即 C/C++ 中的 ^。此外,按位运算符不具有与 C/C++ 相同的优先级,所以可能需要括号。\nJulia 的 ^ 是取幂(pow),而非 C/C++ 中的按位 XOR(在 Julia 中请使用 ⊻ 或 xor)\nJulia 有两个右移运算符,>> 和 >>>。 >> 执行算术移位,>>> 始终执行逻辑移位,这与 C/C++ 不同,其中 >> 的含义取决于被移位的值的类型。\nJulia 的 -> 创建一个匿名函数,它并不通过指针访问成员。\nJulia 在编写 if 语句或 for/while 循环时不需要括号:请使用 for i in [1, 2, 3] 代替 for (int i=1; i <= 3; i++),以及 if i == 1 代替 if (i == 1)\nJulia 不把数字 0 和 1 视为布尔值。在 Julia 中不能编写 if (1),因为 if 语句只接受布尔值。相反,可以编写 if true、if Bool(1) 或 if 1==1。\nJulia 使用 end 来表示条件块(如 if)、循环块(如 while/for)和函数的结束。为了代替单行 if ( cond ) statement,Julia 允许形式为 if cond; statement; end、cond && statement 和 !cond || statement 的语句。后两种语法中的赋值语句必须显式地包含在括号中,例如 cond && (x = value),这是因为运算符的优先级。\nJulia 没有用来续行的语法:如果在行的末尾,到目前为止的输入是一个完整的表达式,则认为其已经结束;否则,认为输入继续。强制表达式继续的一种方式是将其包含在括号中。\nJulia 宏对已解析的表达式进行操作,而非程序的文本,这允许它们执行复杂的 Julia 代码转换。宏名称以 @ 字符开头,具有类似函数的语法 @mymacro(arg1, arg2, arg3) 和类似语句的语法 @mymacro arg1 arg2 arg3。两种形式的语法可以相互转换;如果宏出现在另一个表达式中,则类似函数的形式尤其有用,并且它通常是最清晰的。类似语句的形式通常用于标注块,如在分布式 for 结构中:@distributed for i in 1:n; #= body =#; end。如果宏结构的结尾不那么清晰,请使用类似函数的形式。\nJulia 有一个枚举类型,使用宏 @enum(name, value1, value2, ...) 来表示,例如:@enum(Fruit, banana=1, apple, pear)。\n按照惯例,修改其参数的函数在名称的末尾有个 !,例如 push!。\n在 C++ 中,默认情况下,你具有静态分派,即为了支持动态派发,你需要将函数标注为 virtual 函数。另一方面,Julia 中的每个方法都是「virtual」(尽管它更通用,因为方法是在每个参数类型上派发的,而不仅仅是 this,并且使用的是最具体的声明规则)。","category":"page"},{"location":"manual/noteworthy-differences/#Noteworthy-differences-from-Common-Lisp","page":"与其他语言的显著差异","title":"与 Common Lisp 的显著差异","text":"","category":"section"},{"location":"manual/noteworthy-differences/","page":"与其他语言的显著差异","title":"与其他语言的显著差异","text":"Julia 默认使用 1 开始的数组索引,它也能处理任意的索引顺序。\n函数和变量共用一个命名空间(\"Lisp-1\")。\nJulia 中有 Pair 类型,但这并不意味着它能用作 COMMON-LISP:CONS。在 Julia 中绝大多数可迭代的集合都能互换使用,例如:集合解包(splatting)、元组等。Tuple 最接近 Common Lisp 中用于异构元素的短列表。使用 NamedTuple 来代替关联表(alists)。对于更大的、同类型元素的集合,应该使用 Array 和 Dict。\n典型的使用 Julia 进行原型开发时,也会对镜像进行连续的修改,Revise.jl 包提供了这个功能。\n对于性能,Julia 更喜欢操作具有 类型稳定性。 Common Lisp 从底层机器操作中抽象出来,而 Julia 则更接近它们。 例如:\n使用 / 的整数除法总是返回浮点结果,即使计算是精确的。\n// 总是返回一个有理数结果\n÷ 总是返回一个(被截断的)整数结果\nJulia 支持大整数,但不会自动转换。默认的整数类型会溢出。\n支持复数,但要获得复数结果,你需要复数输入。\n有多种 Complex 和 Rational 类型,具有不同的组成类型。\n模块(名称空间)可以是分层的。import 和 using 有着双重角色:他们加载代码并让代码在命名空间中可用。import 用于仅有模块名是可用的情况,大致等价于 ASDF:LOAD-OP。槽名(Slot name)不需要单独导出。全局变量不能从模块的外部赋值,除了 eval(mod, :(var = val)) 这个例外情况。\n宏以 @ 开头,并没有像 Common Lisp 那样无缝地集成到语言中;因此在 Julia 中,宏的使用不像在 Common Lisp 中那样广泛。Julia 支持宏的一种卫生(hygiene)形式。因为不同的表层语法,Julia 中没有 COMMON-LISP:&BODY 的等价形式。\n所有的函数都是通用的并且使用多重分派。函数的参数列表也无需遵循一样的模板,这让我们有了一个强大的范式:do。可选参数与关键字参数的处理方式不同。方法的歧义没有像在 Common Lisp 对象系统中那样得到解决,因此需要为交集定义更具体的方法。\n符号不属于任何包,它本身也不包含任何值。M.var 会对 M 模块里的  var 符号求值。\nJulia 完全支持函数式编程风格,包括闭包等特性。但这并不是 Julia 的惯用风格。修改捕获变量时需要一些额外的变通以便提高性能。","category":"page"},{"location":"stdlib/LibGit2/#LibGit2","page":"LibGit2","title":"LibGit2","text":"","category":"section"},{"location":"stdlib/LibGit2/","page":"LibGit2","title":"LibGit2","text":"The LibGit2 module provides bindings to libgit2, a portable C library that implements core functionality for the Git version control system. These bindings are currently used to power Julia's package manager. It is expected that this module will eventually be moved into a separate package.","category":"page"},{"location":"stdlib/LibGit2/#Functionality","page":"LibGit2","title":"Functionality","text":"","category":"section"},{"location":"stdlib/LibGit2/","page":"LibGit2","title":"LibGit2","text":"Some of this documentation assumes some prior knowledge of the libgit2 API. For more information on some of the objects and methods referenced here, consult the upstream libgit2 API reference.","category":"page"},{"location":"stdlib/LibGit2/","page":"LibGit2","title":"LibGit2","text":"LibGit2.Buffer\nLibGit2.CheckoutOptions\nLibGit2.CloneOptions\nLibGit2.DescribeOptions\nLibGit2.DescribeFormatOptions\nLibGit2.DiffDelta\nLibGit2.DiffFile\nLibGit2.DiffOptionsStruct\nLibGit2.FetchHead\nLibGit2.FetchOptions\nLibGit2.GitAnnotated\nLibGit2.GitBlame\nLibGit2.GitBlob\nLibGit2.GitCommit\nLibGit2.GitHash\nLibGit2.GitObject\nLibGit2.GitRemote\nLibGit2.GitRemoteAnon\nLibGit2.GitRepo\nLibGit2.GitRepoExt\nLibGit2.GitRevWalker\nLibGit2.GitShortHash\nLibGit2.GitSignature\nLibGit2.GitStatus\nLibGit2.GitTag\nLibGit2.GitTree\nLibGit2.IndexEntry\nLibGit2.IndexTime\nLibGit2.BlameOptions\nLibGit2.MergeOptions\nLibGit2.ProxyOptions\nLibGit2.PushOptions\nLibGit2.RebaseOperation\nLibGit2.RebaseOptions\nLibGit2.RemoteCallbacks\nLibGit2.SignatureStruct\nLibGit2.StatusEntry\nLibGit2.StatusOptions\nLibGit2.StrArrayStruct\nLibGit2.TimeStruct\nLibGit2.add!\nLibGit2.add_fetch!\nLibGit2.add_push!\nLibGit2.addblob!\nLibGit2.author\nLibGit2.authors\nLibGit2.branch\nLibGit2.branch!\nLibGit2.checkout!\nLibGit2.clone\nLibGit2.commit\nLibGit2.committer\nLibGit2.count\nLibGit2.counthunks\nLibGit2.create_branch\nLibGit2.credentials_callback\nLibGit2.credentials_cb\nLibGit2.default_signature\nLibGit2.delete_branch\nLibGit2.diff_files\nLibGit2.entryid\nLibGit2.entrytype\nLibGit2.fetch\nLibGit2.fetchheads\nLibGit2.fetch_refspecs\nLibGit2.fetchhead_foreach_cb\nLibGit2.merge_base\nLibGit2.merge!(::LibGit2.GitRepo; ::Any...)\nLibGit2.merge!(::LibGit2.GitRepo, ::Vector{LibGit2.GitAnnotated}; ::LibGit2.MergeOptions, ::LibGit2.CheckoutOptions)\nLibGit2.merge!(::LibGit2.GitRepo, ::Vector{LibGit2.GitAnnotated}, ::Bool; ::LibGit2.MergeOptions, ::LibGit2.CheckoutOptions)\nLibGit2.ffmerge!\nLibGit2.fullname\nLibGit2.features\nLibGit2.filename\nLibGit2.filemode\nLibGit2.gitdir\nLibGit2.git_url\nLibGit2.@githash_str\nLibGit2.head\nLibGit2.head!\nLibGit2.head_oid\nLibGit2.headname\nLibGit2.init\nLibGit2.is_ancestor_of\nLibGit2.isbinary\nLibGit2.iscommit\nLibGit2.isdiff\nLibGit2.isdirty\nLibGit2.isorphan\nLibGit2.isset\nLibGit2.iszero\nLibGit2.lookup_branch\nLibGit2.map\nLibGit2.mirror_callback\nLibGit2.mirror_cb\nLibGit2.message\nLibGit2.merge_analysis\nLibGit2.name\nLibGit2.need_update\nLibGit2.objtype\nLibGit2.path\nLibGit2.peel\nLibGit2.posixpath\nLibGit2.push\nLibGit2.push!(::LibGit2.GitRevWalker, ::LibGit2.GitHash)\nLibGit2.push_head!\nLibGit2.push_refspecs\nLibGit2.raw\nLibGit2.read_tree!\nLibGit2.rebase!\nLibGit2.ref_list\nLibGit2.reftype\nLibGit2.remotes\nLibGit2.remove!\nLibGit2.reset\nLibGit2.reset!\nLibGit2.restore\nLibGit2.revcount\nLibGit2.set_remote_url\nLibGit2.shortname\nLibGit2.snapshot\nLibGit2.split_cfg_entry\nLibGit2.status\nLibGit2.stage\nLibGit2.tag_create\nLibGit2.tag_delete\nLibGit2.tag_list\nLibGit2.target\nLibGit2.toggle\nLibGit2.transact\nLibGit2.treewalk\nLibGit2.upstream\nLibGit2.update!\nLibGit2.url\nLibGit2.version\nLibGit2.with\nLibGit2.with_warn\nLibGit2.workdir\nLibGit2.GitObject(::LibGit2.GitTreeEntry)\nLibGit2.UserPasswordCredential\nLibGit2.SSHCredential\nLibGit2.isfilled\nLibGit2.CachedCredentials\nLibGit2.CredentialPayload\nLibGit2.approve\nLibGit2.reject","category":"page"},{"location":"stdlib/LibGit2/#LibGit2.Buffer","page":"LibGit2","title":"LibGit2.Buffer","text":"LibGit2.Buffer\n\nA data buffer for exporting data from libgit2. Matches the git_buf struct.\n\nWhen fetching data from LibGit2, a typical usage would look like:\n\nbuf_ref = Ref(Buffer())\n@check ccall(..., (Ptr{Buffer},), buf_ref)\n# operation on buf_ref\nfree(buf_ref)\n\nIn particular, note that LibGit2.free should be called afterward on the Ref object.\n\n\n\n\n\n","category":"type"},{"location":"stdlib/LibGit2/#LibGit2.CheckoutOptions","page":"LibGit2","title":"LibGit2.CheckoutOptions","text":"LibGit2.CheckoutOptions\n\nMatches the git_checkout_options struct.\n\nThe fields represent:\n\nversion: version of the struct in use, in case this changes later. For now, always 1.\ncheckout_strategy: determine how to handle conflicts and whether to force the checkout/recreate missing files.\ndisable_filters: if nonzero, do not apply filters like CLRF (to convert file newlines between UNIX and DOS).\ndir_mode: read/write/access mode for any directories involved in the checkout. Default is 0755.\nfile_mode: read/write/access mode for any files involved in the checkout. Default is 0755 or 0644, depending on the blob.\nfile_open_flags: bitflags used to open any files during the checkout.\nnotify_flags: Flags for what sort of conflicts the user should be notified about.\nnotify_cb: An optional callback function to notify the user if a checkout conflict occurs. If this function returns a non-zero value, the checkout will be cancelled.\nnotify_payload: Payload for the notify callback function.\nprogress_cb: An optional callback function to display checkout progress.\nprogress_payload: Payload for the progress callback.\npaths: If not empty, describes which paths to search during the checkout. If empty, the checkout will occur over all files in the repository.\nbaseline: Expected content of the workdir, captured in a (pointer to a) GitTree. Defaults to the state of the tree at HEAD.\nbaseline_index: Expected content of the workdir, captured in a (pointer to a) GitIndex. Defaults to the state of the index at HEAD.\ntarget_directory: If not empty, checkout to this directory instead of the workdir.\nancestor_label: In case of conflicts, the name of the common ancestor side.\nour_label: In case of conflicts, the name of \"our\" side.\ntheir_label: In case of conflicts, the name of \"their\" side.\nperfdata_cb: An optional callback function to display performance data.\nperfdata_payload: Payload for the performance callback.\n\n\n\n\n\n","category":"type"},{"location":"stdlib/LibGit2/#LibGit2.CloneOptions","page":"LibGit2","title":"LibGit2.CloneOptions","text":"LibGit2.CloneOptions\n\nMatches the git_clone_options struct.\n\nThe fields represent:\n\nversion: version of the struct in use, in case this changes later. For now, always 1.\ncheckout_opts: The options for performing the checkout of the remote as part of the clone.\nfetch_opts: The options for performing the pre-checkout fetch of the remote as part of the clone.\nbare: If 0, clone the full remote repository. If non-zero, perform a bare clone, in which there is no local copy of the source files in the repository and the gitdir and workdir are the same.\nlocalclone: Flag whether to clone a local object database or do a fetch. The default is to let git decide. It will not use the git-aware transport for a local clone, but will use it for URLs which begin with file://.\ncheckout_branch: The name of the branch to checkout. If an empty string, the default branch of the remote will be checked out.\nrepository_cb: An optional callback which will be used to create the new repository into which the clone is made.\nrepository_cb_payload: The payload for the repository callback.\nremote_cb: An optional callback used to create the GitRemote before making the clone from it.\nremote_cb_payload: The payload for the remote callback.\n\n\n\n\n\n","category":"type"},{"location":"stdlib/LibGit2/#LibGit2.DescribeOptions","page":"LibGit2","title":"LibGit2.DescribeOptions","text":"LibGit2.DescribeOptions\n\nMatches the git_describe_options struct.\n\nThe fields represent:\n\nversion: version of the struct in use, in case this changes later. For now, always 1.\nmax_candidates_tags: consider this many most recent tags in refs/tags to describe a commit. Defaults to 10 (so that the 10 most recent tags would be examined to see if they describe a commit).\ndescribe_strategy: whether to consider all entries in refs/tags (equivalent to git-describe --tags) or all entries in refs/ (equivalent to git-describe --all). The default is to only show annotated tags. If Consts.DESCRIBE_TAGS is passed, all tags, annotated or not, will be considered. If Consts.DESCRIBE_ALL is passed, any ref in refs/ will be considered.\npattern: only consider tags which match pattern. Supports glob expansion.\nonly_follow_first_parent: when finding the distance from a matching reference to the described object, only consider the distance from the first parent.\nshow_commit_oid_as_fallback: if no matching reference can be found which describes a commit, show the commit's GitHash instead of throwing an error (the default behavior).\n\n\n\n\n\n","category":"type"},{"location":"stdlib/LibGit2/#LibGit2.DescribeFormatOptions","page":"LibGit2","title":"LibGit2.DescribeFormatOptions","text":"LibGit2.DescribeFormatOptions\n\nMatches the git_describe_format_options struct.\n\nThe fields represent:\n\nversion: version of the struct in use, in case this changes later. For now, always 1.\nabbreviated_size: lower bound on the size of the abbreviated GitHash to use, defaulting to 7.\nalways_use_long_format: set to 1 to use the long format for strings even if a short format can be used.\ndirty_suffix: if set, this will be appended to the end of the description string if the workdir is dirty.\n\n\n\n\n\n","category":"type"},{"location":"stdlib/LibGit2/#LibGit2.DiffDelta","page":"LibGit2","title":"LibGit2.DiffDelta","text":"LibGit2.DiffDelta\n\nDescription of changes to one entry. Matches the git_diff_delta struct.\n\nThe fields represent:\n\nstatus: One of Consts.DELTA_STATUS, indicating whether the file has been added/modified/deleted.\nflags: Flags for the delta and the objects on each side. Determines whether to treat the file(s) as binary/text, whether they exist on each side of the diff, and whether the object ids are known to be correct.\nsimilarity: Used to indicate if a file has been renamed or copied.\nnfiles: The number of files in the delta (for instance, if the delta was run on a submodule commit id, it may contain more than one file).\nold_file: A DiffFile containing information about the file(s) before the changes.\nnew_file: A DiffFile containing information about the file(s) after the changes.\n\n\n\n\n\n","category":"type"},{"location":"stdlib/LibGit2/#LibGit2.DiffFile","page":"LibGit2","title":"LibGit2.DiffFile","text":"LibGit2.DiffFile\n\nDescription of one side of a delta. Matches the git_diff_file struct.\n\nThe fields represent:\n\nid: the GitHash of the item in the diff. If the item is empty on this side of the diff (for instance, if the diff is of the removal of a file), this will be GitHash(0).\npath: a NULL terminated path to the item relative to the working directory of the repository.\nsize: the size of the item in bytes.\nflags: a combination of the git_diff_flag_t flags. The ith bit of this integer sets the ith flag.\nmode: the stat mode for the item.\nid_abbrev: only present in LibGit2 versions newer than or equal to 0.25.0. The length of the id field when converted using string. Usually equal to OID_HEXSZ (40).\n\n\n\n\n\n","category":"type"},{"location":"stdlib/LibGit2/#LibGit2.DiffOptionsStruct","page":"LibGit2","title":"LibGit2.DiffOptionsStruct","text":"LibGit2.DiffOptionsStruct\n\nMatches the git_diff_options struct.\n\nThe fields represent:\n\nversion: version of the struct in use, in case this changes later. For now, always 1.\nflags: flags controlling which files will appear in the diff. Defaults to DIFF_NORMAL.\nignore_submodules: whether to look at files in submodules or not. Defaults to SUBMODULE_IGNORE_UNSPECIFIED, which means the submodule's configuration will control whether it appears in the diff or not.\npathspec: path to files to include in the diff. Default is to use all files in the repository.\nnotify_cb: optional callback which will notify the user of changes to the diff as file deltas are added to it.\nprogress_cb: optional callback which will display diff progress. Only relevant on libgit2 versions at least as new as 0.24.0.\npayload: the payload to pass to notify_cb and progress_cb.\ncontext_lines: the number of unchanged lines used to define the edges of a hunk. This is also the number of lines which will be shown before/after a hunk to provide context. Default is 3.\ninterhunk_lines: the maximum number of unchanged lines between two separate hunks allowed before the hunks will be combined. Default is 0.\nid_abbrev: sets the length of the abbreviated GitHash to print. Default is 7.\nmax_size: the maximum file size of a blob. Above this size, it will be treated as a binary blob. The default is 512 MB.\nold_prefix: the virtual file directory in which to place old files on one side of the diff. Default is \"a\".\nnew_prefix: the virtual file directory in which to place new files on one side of the diff. Default is \"b\".\n\n\n\n\n\n","category":"type"},{"location":"stdlib/LibGit2/#LibGit2.FetchHead","page":"LibGit2","title":"LibGit2.FetchHead","text":"LibGit2.FetchHead\n\nContains the information about HEAD during a fetch, including the name and URL of the branch fetched from, the oid of the HEAD, and whether the fetched HEAD has been merged locally.\n\nThe fields represent:\n\nname: The name in the local reference database of the fetch head, for example, \"refs/heads/master\".\nurl: The URL of the fetch head.\noid: The GitHash of the tip of the fetch head.\nismerge: Boolean flag indicating whether the changes at the remote have been merged into the local copy yet or not. If true, the local copy is up to date with the remote fetch head.\n\n\n\n\n\n","category":"type"},{"location":"stdlib/LibGit2/#LibGit2.FetchOptions","page":"LibGit2","title":"LibGit2.FetchOptions","text":"LibGit2.FetchOptions\n\nMatches the git_fetch_options struct.\n\nThe fields represent:\n\nversion: version of the struct in use, in case this changes later. For now, always 1.\ncallbacks: remote callbacks to use during the fetch.\nprune: whether to perform a prune after the fetch or not. The default is to use the setting from the GitConfig.\nupdate_fetchhead: whether to update the FetchHead after the fetch. The default is to perform the update, which is the normal git behavior.\ndownload_tags: whether to download tags present at the remote or not. The default is to request the tags for objects which are being downloaded anyway from the server.\nproxy_opts: options for connecting to the remote through a proxy. See ProxyOptions. Only present on libgit2 versions newer than or equal to 0.25.0.\ncustom_headers: any extra headers needed for the fetch. Only present on libgit2 versions newer than or equal to 0.24.0.\n\n\n\n\n\n","category":"type"},{"location":"stdlib/LibGit2/#LibGit2.GitAnnotated","page":"LibGit2","title":"LibGit2.GitAnnotated","text":"GitAnnotated(repo::GitRepo, commit_id::GitHash)\nGitAnnotated(repo::GitRepo, ref::GitReference)\nGitAnnotated(repo::GitRepo, fh::FetchHead)\nGitAnnotated(repo::GitRepo, committish::AbstractString)\n\nAn annotated git commit carries with it information about how it was looked up and why, so that rebase or merge operations have more information about the context of the commit. Conflict files contain information about the source/target branches in the merge which are conflicting, for instance. An annotated commit can refer to the tip of a remote branch, for instance when a FetchHead is passed, or to a branch head described using GitReference.\n\n\n\n\n\n","category":"type"},{"location":"stdlib/LibGit2/#LibGit2.GitBlame","page":"LibGit2","title":"LibGit2.GitBlame","text":"GitBlame(repo::GitRepo, path::AbstractString; options::BlameOptions=BlameOptions())\n\nConstruct a GitBlame object for the file at path, using change information gleaned from the history of repo. The GitBlame object records who changed which chunks of the file when, and how. options controls how to separate the contents of the file and which commits to probe - see BlameOptions for more information.\n\n\n\n\n\n","category":"type"},{"location":"stdlib/LibGit2/#LibGit2.GitBlob","page":"LibGit2","title":"LibGit2.GitBlob","text":"GitBlob(repo::GitRepo, hash::AbstractGitHash)\nGitBlob(repo::GitRepo, spec::AbstractString)\n\nReturn a GitBlob object from repo specified by hash/spec.\n\nhash is a full (GitHash) or partial (GitShortHash) hash.\nspec is a textual specification: see the git docs for a full list.\n\n\n\n\n\n","category":"type"},{"location":"stdlib/LibGit2/#LibGit2.GitCommit","page":"LibGit2","title":"LibGit2.GitCommit","text":"GitCommit(repo::GitRepo, hash::AbstractGitHash)\nGitCommit(repo::GitRepo, spec::AbstractString)\n\nReturn a GitCommit object from repo specified by hash/spec.\n\nhash is a full (GitHash) or partial (GitShortHash) hash.\nspec is a textual specification: see the git docs for a full list.\n\n\n\n\n\n","category":"type"},{"location":"stdlib/LibGit2/#LibGit2.GitHash","page":"LibGit2","title":"LibGit2.GitHash","text":"GitHash\n\nA git object identifier, based on the sha-1 hash. It is a 20 byte string (40 hex digits) used to identify a GitObject in a repository.\n\n\n\n\n\n","category":"type"},{"location":"stdlib/LibGit2/#LibGit2.GitObject","page":"LibGit2","title":"LibGit2.GitObject","text":"GitObject(repo::GitRepo, hash::AbstractGitHash)\nGitObject(repo::GitRepo, spec::AbstractString)\n\nReturn the specified object (GitCommit, GitBlob, GitTree or GitTag) from repo specified by hash/spec.\n\nhash is a full (GitHash) or partial (GitShortHash) hash.\nspec is a textual specification: see the git docs for a full list.\n\n\n\n\n\n","category":"type"},{"location":"stdlib/LibGit2/#LibGit2.GitRemote","page":"LibGit2","title":"LibGit2.GitRemote","text":"GitRemote(repo::GitRepo, rmt_name::AbstractString, rmt_url::AbstractString) -> GitRemote\n\nLook up a remote git repository using its name and URL. Uses the default fetch refspec.\n\nExamples\n\nrepo = LibGit2.init(repo_path)\nremote = LibGit2.GitRemote(repo, \"upstream\", repo_url)\n\n\n\n\n\nGitRemote(repo::GitRepo, rmt_name::AbstractString, rmt_url::AbstractString, fetch_spec::AbstractString) -> GitRemote\n\nLook up a remote git repository using the repository's name and URL, as well as specifications for how to fetch from the remote (e.g. which remote branch to fetch from).\n\nExamples\n\nrepo = LibGit2.init(repo_path)\nrefspec = \"+refs/heads/mybranch:refs/remotes/origin/mybranch\"\nremote = LibGit2.GitRemote(repo, \"upstream\", repo_url, refspec)\n\n\n\n\n\n","category":"type"},{"location":"stdlib/LibGit2/#LibGit2.GitRemoteAnon","page":"LibGit2","title":"LibGit2.GitRemoteAnon","text":"GitRemoteAnon(repo::GitRepo, url::AbstractString) -> GitRemote\n\nLook up a remote git repository using only its URL, not its name.\n\nExamples\n\nrepo = LibGit2.init(repo_path)\nremote = LibGit2.GitRemoteAnon(repo, repo_url)\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LibGit2/#LibGit2.GitRepo","page":"LibGit2","title":"LibGit2.GitRepo","text":"LibGit2.GitRepo(path::AbstractString)\n\nOpen a git repository at path.\n\n\n\n\n\n","category":"type"},{"location":"stdlib/LibGit2/#LibGit2.GitRepoExt","page":"LibGit2","title":"LibGit2.GitRepoExt","text":"LibGit2.GitRepoExt(path::AbstractString, flags::Cuint = Cuint(Consts.REPOSITORY_OPEN_DEFAULT))\n\nOpen a git repository at path with extended controls (for instance, if the current user must be a member of a special access group to read path).\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LibGit2/#LibGit2.GitRevWalker","page":"LibGit2","title":"LibGit2.GitRevWalker","text":"GitRevWalker(repo::GitRepo)\n\nA GitRevWalker walks through the revisions (i.e. commits) of a git repository repo. It is a collection of the commits in the repository, and supports iteration and calls to LibGit2.map and LibGit2.count (for instance, LibGit2.count could be used to determine what percentage of commits in a repository were made by a certain author).\n\ncnt = LibGit2.with(LibGit2.GitRevWalker(repo)) do walker\n LibGit2.count((oid,repo)->(oid == commit_oid1), walker, oid=commit_oid1, by=LibGit2.Consts.SORT_TIME)\nend\n\nHere, LibGit2.count finds the number of commits along the walk with a certain GitHash. Since the GitHash is unique to a commit, cnt will be 1.\n\n\n\n\n\n","category":"type"},{"location":"stdlib/LibGit2/#LibGit2.GitShortHash","page":"LibGit2","title":"LibGit2.GitShortHash","text":"GitShortHash(hash::GitHash, len::Integer)\n\nA shortened git object identifier, which can be used to identify a git object when it is unique, consisting of the initial len hexadecimal digits of hash (the remaining digits are ignored).\n\n\n\n\n\n","category":"type"},{"location":"stdlib/LibGit2/#LibGit2.GitSignature","page":"LibGit2","title":"LibGit2.GitSignature","text":"LibGit2.GitSignature\n\nThis is a Julia wrapper around a pointer to a git_signature object.\n\n\n\n\n\n","category":"type"},{"location":"stdlib/LibGit2/#LibGit2.GitStatus","page":"LibGit2","title":"LibGit2.GitStatus","text":"LibGit2.GitStatus(repo::GitRepo; status_opts=StatusOptions())\n\nCollect information about the status of each file in the git repository repo (e.g. is the file modified, staged, etc.). status_opts can be used to set various options, for instance whether or not to look at untracked files or whether to include submodules or not. See StatusOptions for more information.\n\n\n\n\n\n","category":"type"},{"location":"stdlib/LibGit2/#LibGit2.GitTag","page":"LibGit2","title":"LibGit2.GitTag","text":"GitTag(repo::GitRepo, hash::AbstractGitHash)\nGitTag(repo::GitRepo, spec::AbstractString)\n\nReturn a GitTag object from repo specified by hash/spec.\n\nhash is a full (GitHash) or partial (GitShortHash) hash.\nspec is a textual specification: see the git docs for a full list.\n\n\n\n\n\n","category":"type"},{"location":"stdlib/LibGit2/#LibGit2.GitTree","page":"LibGit2","title":"LibGit2.GitTree","text":"GitTree(repo::GitRepo, hash::AbstractGitHash)\nGitTree(repo::GitRepo, spec::AbstractString)\n\nReturn a GitTree object from repo specified by hash/spec.\n\nhash is a full (GitHash) or partial (GitShortHash) hash.\nspec is a textual specification: see the git docs for a full list.\n\n\n\n\n\n","category":"type"},{"location":"stdlib/LibGit2/#LibGit2.IndexEntry","page":"LibGit2","title":"LibGit2.IndexEntry","text":"LibGit2.IndexEntry\n\nIn-memory representation of a file entry in the index. Matches the git_index_entry struct.\n\n\n\n\n\n","category":"type"},{"location":"stdlib/LibGit2/#LibGit2.IndexTime","page":"LibGit2","title":"LibGit2.IndexTime","text":"LibGit2.IndexTime\n\nMatches the git_index_time struct.\n\n\n\n\n\n","category":"type"},{"location":"stdlib/LibGit2/#LibGit2.BlameOptions","page":"LibGit2","title":"LibGit2.BlameOptions","text":"LibGit2.BlameOptions\n\nMatches the git_blame_options struct.\n\nThe fields represent:\n\nversion: version of the struct in use, in case this changes later. For now, always 1.\nflags: one of Consts.BLAME_NORMAL or Consts.BLAME_FIRST_PARENT (the other blame flags are not yet implemented by libgit2).\nmin_match_characters: the minimum number of alphanumeric characters which much change in a commit in order for the change to be associated with that commit. The default is 20. Only takes effect if one of the Consts.BLAME_*_COPIES flags are used, which libgit2 does not implement yet.\nnewest_commit: the GitHash of the newest commit from which to look at changes.\noldest_commit: the GitHash of the oldest commit from which to look at changes.\nmin_line: the first line of the file from which to starting blaming. The default is 1.\nmax_line: the last line of the file to which to blame. The default is 0, meaning the last line of the file.\n\n\n\n\n\n","category":"type"},{"location":"stdlib/LibGit2/#LibGit2.MergeOptions","page":"LibGit2","title":"LibGit2.MergeOptions","text":"LibGit2.MergeOptions\n\nMatches the git_merge_options struct.\n\nThe fields represent:\n\nversion: version of the struct in use, in case this changes later. For now, always 1.\nflags: an enum for flags describing merge behavior. Defined in git_merge_flag_t. The corresponding Julia enum is GIT_MERGE and has values:\nMERGE_FIND_RENAMES: detect if a file has been renamed between the common ancestor and the \"ours\" or \"theirs\" side of the merge. Allows merges where a file has been renamed.\nMERGE_FAIL_ON_CONFLICT: exit immediately if a conflict is found rather than trying to resolve it.\nMERGE_SKIP_REUC: do not write the REUC extension on the index resulting from the merge.\nMERGE_NO_RECURSIVE: if the commits being merged have multiple merge bases, use the first one, rather than trying to recursively merge the bases.\nrename_threshold: how similar two files must to consider one a rename of the other. This is an integer that sets the percentage similarity. The default is 50.\ntarget_limit: the maximum number of files to compare with to look for renames. The default is 200.\nmetric: optional custom function to use to determine the similarity between two files for rename detection.\nrecursion_limit: the upper limit on the number of merges of common ancestors to perform to try to build a new virtual merge base for the merge. The default is no limit. This field is only present on libgit2 versions newer than 0.24.0.\ndefault_driver: the merge driver to use if both sides have changed. This field is only present on libgit2 versions newer than 0.25.0.\nfile_favor: how to handle conflicting file contents for the text driver.\nMERGE_FILE_FAVOR_NORMAL: if both sides of the merge have changes to a section, make a note of the conflict in the index which git checkout will use to create a merge file, which the user can then reference to resolve the conflicts. This is the default.\nMERGE_FILE_FAVOR_OURS: if both sides of the merge have changes to a section, use the version in the \"ours\" side of the merge in the index.\nMERGE_FILE_FAVOR_THEIRS: if both sides of the merge have changes to a section, use the version in the \"theirs\" side of the merge in the index.\nMERGE_FILE_FAVOR_UNION: if both sides of the merge have changes to a section, include each unique line from both sides in the file which is put into the index.\nfile_flags: guidelines for merging files.\n\n\n\n\n\n","category":"type"},{"location":"stdlib/LibGit2/#LibGit2.ProxyOptions","page":"LibGit2","title":"LibGit2.ProxyOptions","text":"LibGit2.ProxyOptions\n\nOptions for connecting through a proxy.\n\nMatches the git_proxy_options struct.\n\nThe fields represent:\n\nversion: version of the struct in use, in case this changes later. For now, always 1.\nproxytype: an enum for the type of proxy to use. Defined in git_proxy_t. The corresponding Julia enum is GIT_PROXY and has values:\nPROXY_NONE: do not attempt the connection through a proxy.\nPROXY_AUTO: attempt to figure out the proxy configuration from the git configuration.\nPROXY_SPECIFIED: connect using the URL given in the url field of this struct.\nDefault is to auto-detect the proxy type.\nurl: the URL of the proxy.\ncredential_cb: a pointer to a callback function which will be called if the remote requires authentication to connect.\ncertificate_cb: a pointer to a callback function which will be called if certificate verification fails. This lets the user decide whether or not to keep connecting. If the function returns 1, connecting will be allowed. If it returns 0, the connection will not be allowed. A negative value can be used to return errors.\npayload: the payload to be provided to the two callback functions.\n\nExamples\n\njulia> fo = LibGit2.FetchOptions(\n proxy_opts = LibGit2.ProxyOptions(url = Cstring(\"https://my_proxy_url.com\")))\n\njulia> fetch(remote, \"master\", options=fo)\n\n\n\n\n\n","category":"type"},{"location":"stdlib/LibGit2/#LibGit2.PushOptions","page":"LibGit2","title":"LibGit2.PushOptions","text":"LibGit2.PushOptions\n\nMatches the git_push_options struct.\n\nThe fields represent:\n\nversion: version of the struct in use, in case this changes later. For now, always 1.\nparallelism: if a pack file must be created, this variable sets the number of worker threads which will be spawned by the packbuilder. If 0, the packbuilder will auto-set the number of threads to use. The default is 1.\ncallbacks: the callbacks (e.g. for authentication with the remote) to use for the push.\nproxy_opts: only relevant if the LibGit2 version is greater than or equal to 0.25.0. Sets options for using a proxy to communicate with a remote. See ProxyOptions for more information.\ncustom_headers: only relevant if the LibGit2 version is greater than or equal to 0.24.0. Extra headers needed for the push operation.\n\n\n\n\n\n","category":"type"},{"location":"stdlib/LibGit2/#LibGit2.RebaseOperation","page":"LibGit2","title":"LibGit2.RebaseOperation","text":"LibGit2.RebaseOperation\n\nDescribes a single instruction/operation to be performed during the rebase. Matches the git_rebase_operation struct.\n\nThe fields represent:\n\noptype: the type of rebase operation currently being performed. The options are:\nREBASE_OPERATION_PICK: cherry-pick the commit in question.\nREBASE_OPERATION_REWORD: cherry-pick the commit in question, but rewrite its message using the prompt.\nREBASE_OPERATION_EDIT: cherry-pick the commit in question, but allow the user to edit the commit's contents and its message.\nREBASE_OPERATION_SQUASH: squash the commit in question into the previous commit. The commit messages of the two commits will be merged.\nREBASE_OPERATION_FIXUP: squash the commit in question into the previous commit. Only the commit message of the previous commit will be used.\nREBASE_OPERATION_EXEC: do not cherry-pick a commit. Run a command and continue if the command exits successfully.\nid: the GitHash of the commit being worked on during this rebase step.\nexec: in case REBASE_OPERATION_EXEC is used, the command to run during this step (for instance, running the test suite after each commit).\n\n\n\n\n\n","category":"type"},{"location":"stdlib/LibGit2/#LibGit2.RebaseOptions","page":"LibGit2","title":"LibGit2.RebaseOptions","text":"LibGit2.RebaseOptions\n\nMatches the git_rebase_options struct.\n\nThe fields represent:\n\nversion: version of the struct in use, in case this changes later. For now, always 1.\nquiet: inform other git clients helping with/working on the rebase that the rebase should be done \"quietly\". Used for interoperability. The default is 1.\ninmemory: start an in-memory rebase. Callers working on the rebase can go through its steps and commit any changes, but cannot rewind HEAD or update the repository. The workdir will not be modified. Only present on libgit2 versions newer than or equal to 0.24.0.\nrewrite_notes_ref: name of the reference to notes to use to rewrite the commit notes as the rebase is finished.\nmerge_opts: merge options controlling how the trees will be merged at each rebase step. Only present on libgit2 versions newer than or equal to 0.24.0.\ncheckout_opts: checkout options for writing files when initializing the rebase, stepping through it, and aborting it. See CheckoutOptions for more information.\n\n\n\n\n\n","category":"type"},{"location":"stdlib/LibGit2/#LibGit2.RemoteCallbacks","page":"LibGit2","title":"LibGit2.RemoteCallbacks","text":"LibGit2.RemoteCallbacks\n\nCallback settings. Matches the git_remote_callbacks struct.\n\n\n\n\n\n","category":"type"},{"location":"stdlib/LibGit2/#LibGit2.SignatureStruct","page":"LibGit2","title":"LibGit2.SignatureStruct","text":"LibGit2.SignatureStruct\n\nAn action signature (e.g. for committers, taggers, etc). Matches the git_signature struct.\n\nThe fields represent:\n\nname: The full name of the committer or author of the commit.\nemail: The email at which the committer/author can be contacted.\nwhen: a TimeStruct indicating when the commit was authored/committed into the repository.\n\n\n\n\n\n","category":"type"},{"location":"stdlib/LibGit2/#LibGit2.StatusEntry","page":"LibGit2","title":"LibGit2.StatusEntry","text":"LibGit2.StatusEntry\n\nProviding the differences between the file as it exists in HEAD and the index, and providing the differences between the index and the working directory. Matches the git_status_entry struct.\n\nThe fields represent:\n\nstatus: contains the status flags for the file, indicating if it is current, or has been changed in some way in the index or work tree.\nhead_to_index: a pointer to a DiffDelta which encapsulates the difference(s) between the file as it exists in HEAD and in the index.\nindex_to_workdir: a pointer to a DiffDelta which encapsulates the difference(s) between the file as it exists in the index and in the workdir.\n\n\n\n\n\n","category":"type"},{"location":"stdlib/LibGit2/#LibGit2.StatusOptions","page":"LibGit2","title":"LibGit2.StatusOptions","text":"LibGit2.StatusOptions\n\nOptions to control how git_status_foreach_ext() will issue callbacks. Matches the git_status_opt_t struct.\n\nThe fields represent:\n\nversion: version of the struct in use, in case this changes later. For now, always 1.\nshow: a flag for which files to examine and in which order. The default is Consts.STATUS_SHOW_INDEX_AND_WORKDIR.\nflags: flags for controlling any callbacks used in a status call.\npathspec: an array of paths to use for path-matching. The behavior of the path-matching will vary depending on the values of show and flags.\nThe baseline is the tree to be used for comparison to the working directory and index; defaults to HEAD.\n\n\n\n\n\n","category":"type"},{"location":"stdlib/LibGit2/#LibGit2.StrArrayStruct","page":"LibGit2","title":"LibGit2.StrArrayStruct","text":"LibGit2.StrArrayStruct\n\nA LibGit2 representation of an array of strings. Matches the git_strarray struct.\n\nWhen fetching data from LibGit2, a typical usage would look like:\n\nsa_ref = Ref(StrArrayStruct())\n@check ccall(..., (Ptr{StrArrayStruct},), sa_ref)\nres = convert(Vector{String}, sa_ref[])\nfree(sa_ref)\n\nIn particular, note that LibGit2.free should be called afterward on the Ref object.\n\nConversely, when passing a vector of strings to LibGit2, it is generally simplest to rely on implicit conversion:\n\nstrs = String[...]\n@check ccall(..., (Ptr{StrArrayStruct},), strs)\n\nNote that no call to free is required as the data is allocated by Julia.\n\n\n\n\n\n","category":"type"},{"location":"stdlib/LibGit2/#LibGit2.TimeStruct","page":"LibGit2","title":"LibGit2.TimeStruct","text":"LibGit2.TimeStruct\n\nTime in a signature. Matches the git_time struct.\n\n\n\n\n\n","category":"type"},{"location":"stdlib/LibGit2/#LibGit2.add!","page":"LibGit2","title":"LibGit2.add!","text":"add!(repo::GitRepo, files::AbstractString...; flags::Cuint = Consts.INDEX_ADD_DEFAULT)\nadd!(idx::GitIndex, files::AbstractString...; flags::Cuint = Consts.INDEX_ADD_DEFAULT)\n\nAdd all the files with paths specified by files to the index idx (or the index of the repo). If the file already exists, the index entry will be updated. If the file does not exist already, it will be newly added into the index. files may contain glob patterns which will be expanded and any matching files will be added (unless INDEX_ADD_DISABLE_PATHSPEC_MATCH is set, see below). If a file has been ignored (in .gitignore or in the config), it will not be added, unless it is already being tracked in the index, in which case it will be updated. The keyword argument flags is a set of bit-flags which control the behavior with respect to ignored files:\n\nConsts.INDEX_ADD_DEFAULT - default, described above.\nConsts.INDEX_ADD_FORCE - disregard the existing ignore rules and force addition of the file to the index even if it is already ignored.\nConsts.INDEX_ADD_CHECK_PATHSPEC - cannot be used at the same time as INDEX_ADD_FORCE. Check that each file in files which exists on disk is not in the ignore list. If one of the files is ignored, the function will return EINVALIDSPEC.\nConsts.INDEX_ADD_DISABLE_PATHSPEC_MATCH - turn off glob matching, and only add files to the index which exactly match the paths specified in files.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LibGit2/#LibGit2.add_fetch!","page":"LibGit2","title":"LibGit2.add_fetch!","text":"add_fetch!(repo::GitRepo, rmt::GitRemote, fetch_spec::String)\n\nAdd a fetch refspec for the specified rmt. This refspec will contain information about which branch(es) to fetch from.\n\nExamples\n\njulia> LibGit2.add_fetch!(repo, remote, \"upstream\");\n\njulia> LibGit2.fetch_refspecs(remote)\nString[\"+refs/heads/*:refs/remotes/upstream/*\"]\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LibGit2/#LibGit2.add_push!","page":"LibGit2","title":"LibGit2.add_push!","text":"add_push!(repo::GitRepo, rmt::GitRemote, push_spec::String)\n\nAdd a push refspec for the specified rmt. This refspec will contain information about which branch(es) to push to.\n\nExamples\n\njulia> LibGit2.add_push!(repo, remote, \"refs/heads/master\");\n\njulia> remote = LibGit2.get(LibGit2.GitRemote, repo, branch);\n\njulia> LibGit2.push_refspecs(remote)\nString[\"refs/heads/master\"]\n\nnote: Note\nYou may need to close and reopen the GitRemote in question after updating its push refspecs in order for the change to take effect and for calls to push to work.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LibGit2/#LibGit2.addblob!","page":"LibGit2","title":"LibGit2.addblob!","text":"LibGit2.addblob!(repo::GitRepo, path::AbstractString)\n\nRead the file at path and adds it to the object database of repo as a loose blob. Return the GitHash of the resulting blob.\n\nExamples\n\nhash_str = string(commit_oid)\nblob_file = joinpath(repo_path, \".git\", \"objects\", hash_str[1:2], hash_str[3:end])\nid = LibGit2.addblob!(repo, blob_file)\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LibGit2/#LibGit2.author","page":"LibGit2","title":"LibGit2.author","text":"author(c::GitCommit)\n\nReturn the Signature of the author of the commit c. The author is the person who made changes to the relevant file(s). See also committer.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LibGit2/#LibGit2.authors","page":"LibGit2","title":"LibGit2.authors","text":"authors(repo::GitRepo) -> Vector{Signature}\n\nReturn all authors of commits to the repo repository.\n\nExamples\n\nrepo = LibGit2.GitRepo(repo_path)\nrepo_file = open(joinpath(repo_path, test_file), \"a\")\n\nprintln(repo_file, commit_msg)\nflush(repo_file)\nLibGit2.add!(repo, test_file)\nsig = LibGit2.Signature(\"TEST\", \"TEST@TEST.COM\", round(time(), 0), 0)\ncommit_oid1 = LibGit2.commit(repo, \"commit1\"; author=sig, committer=sig)\nprintln(repo_file, randstring(10))\nflush(repo_file)\nLibGit2.add!(repo, test_file)\ncommit_oid2 = LibGit2.commit(repo, \"commit2\"; author=sig, committer=sig)\n\n# will be a Vector of [sig, sig]\nauths = LibGit2.authors(repo)\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LibGit2/#LibGit2.branch","page":"LibGit2","title":"LibGit2.branch","text":"branch(repo::GitRepo)\n\nEquivalent to git branch. Create a new branch from the current HEAD.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LibGit2/#LibGit2.branch!","page":"LibGit2","title":"LibGit2.branch!","text":"branch!(repo::GitRepo, branch_name::AbstractString, commit::AbstractString=\"\"; kwargs...)\n\nCheckout a new git branch in the repo repository. commit is the GitHash, in string form, which will be the start of the new branch. If commit is an empty string, the current HEAD will be used.\n\nThe keyword arguments are:\n\ntrack::AbstractString=\"\": the name of the remote branch this new branch should track, if any. If empty (the default), no remote branch will be tracked.\nforce::Bool=false: if true, branch creation will be forced.\nset_head::Bool=true: if true, after the branch creation finishes the branch head will be set as the HEAD of repo.\n\nEquivalent to git checkout [-b|-B] [] [--track ].\n\nExamples\n\nrepo = LibGit2.GitRepo(repo_path)\nLibGit2.branch!(repo, \"new_branch\", set_head=false)\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LibGit2/#LibGit2.checkout!","page":"LibGit2","title":"LibGit2.checkout!","text":"checkout!(repo::GitRepo, commit::AbstractString=\"\"; force::Bool=true)\n\nEquivalent to git checkout [-f] --detach . Checkout the git commit commit (a GitHash in string form) in repo. If force is true, force the checkout and discard any current changes. Note that this detaches the current HEAD.\n\nExamples\n\nrepo = LibGit2.init(repo_path)\nopen(joinpath(LibGit2.path(repo), \"file1\"), \"w\") do f\n write(f, \"111\n\")\nend\nLibGit2.add!(repo, \"file1\")\ncommit_oid = LibGit2.commit(repo, \"add file1\")\nopen(joinpath(LibGit2.path(repo), \"file1\"), \"w\") do f\n write(f, \"112\n\")\nend\n# would fail without the force=true\n# since there are modifications to the file\nLibGit2.checkout!(repo, string(commit_oid), force=true)\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LibGit2/#LibGit2.clone","page":"LibGit2","title":"LibGit2.clone","text":"clone(repo_url::AbstractString, repo_path::AbstractString, clone_opts::CloneOptions)\n\nClone the remote repository at repo_url (which can be a remote URL or a path on the local filesystem) to repo_path (which must be a path on the local filesystem). Options for the clone, such as whether to perform a bare clone or not, are set by CloneOptions.\n\nExamples\n\nrepo_url = \"https://github.com/JuliaLang/Example.jl\"\nrepo = LibGit2.clone(repo_url, \"/home/me/projects/Example\")\n\n\n\n\n\nclone(repo_url::AbstractString, repo_path::AbstractString; kwargs...)\n\nClone a remote repository located at repo_url to the local filesystem location repo_path.\n\nThe keyword arguments are:\n\nbranch::AbstractString=\"\": which branch of the remote to clone, if not the default repository branch (usually master).\nisbare::Bool=false: if true, clone the remote as a bare repository, which will make repo_path itself the git directory instead of repo_path/.git. This means that a working tree cannot be checked out. Plays the role of the git CLI argument --bare.\nremote_cb::Ptr{Cvoid}=C_NULL: a callback which will be used to create the remote before it is cloned. If C_NULL (the default), no attempt will be made to create the remote - it will be assumed to already exist.\ncredentials::Creds=nothing: provides credentials and/or settings when authenticating against a private repository.\ncallbacks::Callbacks=Callbacks(): user provided callbacks and payloads.\n\nEquivalent to git clone [-b ] [--bare] .\n\nExamples\n\nrepo_url = \"https://github.com/JuliaLang/Example.jl\"\nrepo1 = LibGit2.clone(repo_url, \"test_path\")\nrepo2 = LibGit2.clone(repo_url, \"test_path\", isbare=true)\njulia_url = \"https://github.com/JuliaLang/julia\"\njulia_repo = LibGit2.clone(julia_url, \"julia_path\", branch=\"release-0.6\")\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LibGit2/#LibGit2.commit","page":"LibGit2","title":"LibGit2.commit","text":"commit(repo::GitRepo, msg::AbstractString; kwargs...) -> GitHash\n\nWrapper around git_commit_create. Create a commit in the repository repo. msg is the commit message. Return the OID of the new commit.\n\nThe keyword arguments are:\n\nrefname::AbstractString=Consts.HEAD_FILE: if not NULL, the name of the reference to update to point to the new commit. For example, \"HEAD\" will update the HEAD of the current branch. If the reference does not yet exist, it will be created.\nauthor::Signature = Signature(repo) is a Signature containing information about the person who authored the commit.\ncommitter::Signature = Signature(repo) is a Signature containing information about the person who committed the commit to the repository. Not necessarily the same as author, for instance if author emailed a patch to committer who committed it.\ntree_id::GitHash = GitHash() is a git tree to use to create the commit, showing its ancestry and relationship with any other history. tree must belong to repo.\nparent_ids::Vector{GitHash}=GitHash[] is a list of commits by GitHash to use as parent commits for the new one, and may be empty. A commit might have multiple parents if it is a merge commit, for example.\n\n\n\n\n\nLibGit2.commit(rb::GitRebase, sig::GitSignature)\n\nCommit the current patch to the rebase rb, using sig as the committer. Is silent if the commit has already been applied.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LibGit2/#LibGit2.committer","page":"LibGit2","title":"LibGit2.committer","text":"committer(c::GitCommit)\n\nReturn the Signature of the committer of the commit c. The committer is the person who committed the changes originally authored by the author, but need not be the same as the author, for example, if the author emailed a patch to a committer who committed it.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LibGit2/#LibGit2.count","page":"LibGit2","title":"LibGit2.count","text":"LibGit2.count(f::Function, walker::GitRevWalker; oid::GitHash=GitHash(), by::Cint=Consts.SORT_NONE, rev::Bool=false)\n\nUsing the GitRevWalker walker to \"walk\" over every commit in the repository's history, find the number of commits which return true when f is applied to them. The keyword arguments are: * oid: The GitHash of the commit to begin the walk from. The default is to use push_head! and therefore the HEAD commit and all its ancestors. * by: The sorting method. The default is not to sort. Other options are to sort by topology (LibGit2.Consts.SORT_TOPOLOGICAL), to sort forwards in time (LibGit2.Consts.SORT_TIME, most ancient first) or to sort backwards in time (LibGit2.Consts.SORT_REVERSE, most recent first). * rev: Whether to reverse the sorted order (for instance, if topological sorting is used).\n\nExamples\n\ncnt = LibGit2.with(LibGit2.GitRevWalker(repo)) do walker\n LibGit2.count((oid, repo)->(oid == commit_oid1), walker, oid=commit_oid1, by=LibGit2.Consts.SORT_TIME)\nend\n\nLibGit2.count finds the number of commits along the walk with a certain GitHash commit_oid1, starting the walk from that commit and moving forwards in time from it. Since the GitHash is unique to a commit, cnt will be 1.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LibGit2/#LibGit2.counthunks","page":"LibGit2","title":"LibGit2.counthunks","text":"counthunks(blame::GitBlame)\n\nReturn the number of distinct \"hunks\" with a file. A hunk may contain multiple lines. A hunk is usually a piece of a file that was added/changed/removed together, for example, a function added to a source file or an inner loop that was optimized out of that function later.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LibGit2/#LibGit2.create_branch","page":"LibGit2","title":"LibGit2.create_branch","text":"LibGit2.create_branch(repo::GitRepo, bname::AbstractString, commit_obj::GitCommit; force::Bool=false)\n\nCreate a new branch in the repository repo with name bname, which points to commit commit_obj (which has to be part of repo). If force is true, overwrite an existing branch named bname if it exists. If force is false and a branch already exists named bname, this function will throw an error.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LibGit2/#LibGit2.credentials_callback","page":"LibGit2","title":"LibGit2.credentials_callback","text":"credential_callback(...) -> Cint\n\nA LibGit2 credential callback function which provides different credential acquisition functionality w.r.t. a connection protocol. The payload_ptr is required to contain a LibGit2.CredentialPayload object which will keep track of state and settings.\n\nThe allowed_types contains a bitmask of LibGit2.Consts.GIT_CREDTYPE values specifying which authentication methods should be attempted.\n\nCredential authentication is done in the following order (if supported):\n\nSSH agent\nSSH private/public key pair\nUsername/password plain text\n\nIf a user is presented with a credential prompt they can abort the prompt by typing ^D (pressing the control key together with the d key).\n\nNote: Due to the specifics of the libgit2 authentication procedure, when authentication fails, this function is called again without any indication whether authentication was successful or not. To avoid an infinite loop from repeatedly using the same faulty credentials, we will keep track of state using the payload.\n\nFor addition details see the LibGit2 guide on authenticating against a server.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LibGit2/#LibGit2.credentials_cb","page":"LibGit2","title":"LibGit2.credentials_cb","text":"C function pointer for credentials_callback\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LibGit2/#LibGit2.default_signature","page":"LibGit2","title":"LibGit2.default_signature","text":"Return signature object. Free it after use.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LibGit2/#LibGit2.delete_branch","page":"LibGit2","title":"LibGit2.delete_branch","text":"LibGit2.delete_branch(branch::GitReference)\n\nDelete the branch pointed to by branch.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LibGit2/#LibGit2.diff_files","page":"LibGit2","title":"LibGit2.diff_files","text":"diff_files(repo::GitRepo, branch1::AbstractString, branch2::AbstractString; kwarg...) -> Vector{AbstractString}\n\nShow which files have changed in the git repository repo between branches branch1 and branch2.\n\nThe keyword argument is:\n\nfilter::Set{Consts.DELTA_STATUS}=Set([Consts.DELTA_ADDED, Consts.DELTA_MODIFIED, Consts.DELTA_DELETED])), and it sets options for the diff. The default is to show files added, modified, or deleted.\n\nReturn only the names of the files which have changed, not their contents.\n\nExamples\n\nLibGit2.branch!(repo, \"branch/a\")\nLibGit2.branch!(repo, \"branch/b\")\n# add a file to repo\nopen(joinpath(LibGit2.path(repo),\"file\"),\"w\") do f\n write(f, \"hello repo\n\")\nend\nLibGit2.add!(repo, \"file\")\nLibGit2.commit(repo, \"add file\")\n# returns [\"file\"]\nfilt = Set([LibGit2.Consts.DELTA_ADDED])\nfiles = LibGit2.diff_files(repo, \"branch/a\", \"branch/b\", filter=filt)\n# returns [] because existing files weren't modified\nfilt = Set([LibGit2.Consts.DELTA_MODIFIED])\nfiles = LibGit2.diff_files(repo, \"branch/a\", \"branch/b\", filter=filt)\n\nEquivalent to git diff --name-only --diff-filter= .\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LibGit2/#LibGit2.entryid","page":"LibGit2","title":"LibGit2.entryid","text":"entryid(te::GitTreeEntry)\n\nReturn the GitHash of the object to which te refers.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LibGit2/#LibGit2.entrytype","page":"LibGit2","title":"LibGit2.entrytype","text":"entrytype(te::GitTreeEntry)\n\nReturn the type of the object to which te refers. The result will be one of the types which objtype returns, e.g. a GitTree or GitBlob.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LibGit2/#LibGit2.fetch","page":"LibGit2","title":"LibGit2.fetch","text":"fetch(rmt::GitRemote, refspecs; options::FetchOptions=FetchOptions(), msg=\"\")\n\nFetch from the specified rmt remote git repository, using refspecs to determine which remote branch(es) to fetch. The keyword arguments are:\n\noptions: determines the options for the fetch, e.g. whether to prune afterwards. See FetchOptions for more information.\nmsg: a message to insert into the reflogs.\n\n\n\n\n\nfetch(repo::GitRepo; kwargs...)\n\nFetches updates from an upstream of the repository repo.\n\nThe keyword arguments are:\n\nremote::AbstractString=\"origin\": which remote, specified by name, of repo to fetch from. If this is empty, the URL will be used to construct an anonymous remote.\nremoteurl::AbstractString=\"\": the URL of remote. If not specified, will be assumed based on the given name of remote.\nrefspecs=AbstractString[]: determines properties of the fetch.\ncredentials=nothing: provides credentials and/or settings when authenticating against a private remote.\ncallbacks=Callbacks(): user provided callbacks and payloads.\n\nEquivalent to git fetch [|] [].\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LibGit2/#LibGit2.fetchheads","page":"LibGit2","title":"LibGit2.fetchheads","text":"fetchheads(repo::GitRepo) -> Vector{FetchHead}\n\nReturn the list of all the fetch heads for repo, each represented as a FetchHead, including their names, URLs, and merge statuses.\n\nExamples\n\njulia> fetch_heads = LibGit2.fetchheads(repo);\n\njulia> fetch_heads[1].name\n\"refs/heads/master\"\n\njulia> fetch_heads[1].ismerge\ntrue\n\njulia> fetch_heads[2].name\n\"refs/heads/test_branch\"\n\njulia> fetch_heads[2].ismerge\nfalse\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LibGit2/#LibGit2.fetch_refspecs","page":"LibGit2","title":"LibGit2.fetch_refspecs","text":"fetch_refspecs(rmt::GitRemote) -> Vector{String}\n\nGet the fetch refspecs for the specified rmt. These refspecs contain information about which branch(es) to fetch from.\n\nExamples\n\njulia> remote = LibGit2.get(LibGit2.GitRemote, repo, \"upstream\");\n\njulia> LibGit2.add_fetch!(repo, remote, \"upstream\");\n\njulia> LibGit2.fetch_refspecs(remote)\nString[\"+refs/heads/*:refs/remotes/upstream/*\"]\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LibGit2/#LibGit2.fetchhead_foreach_cb","page":"LibGit2","title":"LibGit2.fetchhead_foreach_cb","text":"C function pointer for fetchhead_foreach_callback\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LibGit2/#LibGit2.merge_base","page":"LibGit2","title":"LibGit2.merge_base","text":"merge_base(repo::GitRepo, one::AbstractString, two::AbstractString) -> GitHash\n\nFind a merge base (a common ancestor) between the commits one and two. one and two may both be in string form. Return the GitHash of the merge base.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LibGit2/#LibGit2.merge!-Tuple{GitRepo}","page":"LibGit2","title":"LibGit2.merge!","text":"merge!(repo::GitRepo; kwargs...) -> Bool\n\nPerform a git merge on the repository repo, merging commits with diverging history into the current branch. Return true if the merge succeeded, false if not.\n\nThe keyword arguments are:\n\ncommittish::AbstractString=\"\": Merge the named commit(s) in committish.\nbranch::AbstractString=\"\": Merge the branch branch and all its commits since it diverged from the current branch.\nfastforward::Bool=false: If fastforward is true, only merge if the merge is a fast-forward (the current branch head is an ancestor of the commits to be merged), otherwise refuse to merge and return false. This is equivalent to the git CLI option --ff-only.\nmerge_opts::MergeOptions=MergeOptions(): merge_opts specifies options for the merge, such as merge strategy in case of conflicts.\ncheckout_opts::CheckoutOptions=CheckoutOptions(): checkout_opts specifies options for the checkout step.\n\nEquivalent to git merge [--ff-only] [ | ].\n\nnote: Note\nIf you specify a branch, this must be done in reference format, since the string will be turned into a GitReference. For example, if you wanted to merge branch branch_a, you would call merge!(repo, branch=\"refs/heads/branch_a\").\n\n\n\n\n\n","category":"method"},{"location":"stdlib/LibGit2/#LibGit2.merge!-Tuple{GitRepo, Vector{LibGit2.GitAnnotated}}","page":"LibGit2","title":"LibGit2.merge!","text":"merge!(repo::GitRepo, anns::Vector{GitAnnotated}; kwargs...) -> Bool\n\nMerge changes from the annotated commits (captured as GitAnnotated objects) anns into the HEAD of the repository repo. The keyword arguments are:\n\nmerge_opts::MergeOptions = MergeOptions(): options for how to perform the merge, including whether fastforwarding is allowed. See MergeOptions for more information.\ncheckout_opts::CheckoutOptions = CheckoutOptions(): options for how to perform the checkout. See CheckoutOptions for more information.\n\nanns may refer to remote or local branch heads. Return true if the merge is successful, otherwise return false (for instance, if no merge is possible because the branches have no common ancestor).\n\nExamples\n\nupst_ann = LibGit2.GitAnnotated(repo, \"branch/a\")\n\n# merge the branch in\nLibGit2.merge!(repo, [upst_ann])\n\n\n\n\n\n","category":"method"},{"location":"stdlib/LibGit2/#LibGit2.merge!-Tuple{GitRepo, Vector{LibGit2.GitAnnotated}, Bool}","page":"LibGit2","title":"LibGit2.merge!","text":"merge!(repo::GitRepo, anns::Vector{GitAnnotated}, fastforward::Bool; kwargs...) -> Bool\n\nMerge changes from the annotated commits (captured as GitAnnotated objects) anns into the HEAD of the repository repo. If fastforward is true, only a fastforward merge is allowed. In this case, if conflicts occur, the merge will fail. Otherwise, if fastforward is false, the merge may produce a conflict file which the user will need to resolve.\n\nThe keyword arguments are:\n\nmerge_opts::MergeOptions = MergeOptions(): options for how to perform the merge, including whether fastforwarding is allowed. See MergeOptions for more information.\ncheckout_opts::CheckoutOptions = CheckoutOptions(): options for how to perform the checkout. See CheckoutOptions for more information.\n\nanns may refer to remote or local branch heads. Return true if the merge is successful, otherwise return false (for instance, if no merge is possible because the branches have no common ancestor).\n\nExamples\n\nupst_ann_1 = LibGit2.GitAnnotated(repo, \"branch/a\")\n\n# merge the branch in, fastforward\nLibGit2.merge!(repo, [upst_ann_1], true)\n\n# merge conflicts!\nupst_ann_2 = LibGit2.GitAnnotated(repo, \"branch/b\")\n# merge the branch in, try to fastforward\nLibGit2.merge!(repo, [upst_ann_2], true) # will return false\nLibGit2.merge!(repo, [upst_ann_2], false) # will return true\n\n\n\n\n\n","category":"method"},{"location":"stdlib/LibGit2/#LibGit2.ffmerge!","page":"LibGit2","title":"LibGit2.ffmerge!","text":"ffmerge!(repo::GitRepo, ann::GitAnnotated)\n\nFastforward merge changes into current HEAD. This is only possible if the commit referred to by ann is descended from the current HEAD (e.g. if pulling changes from a remote branch which is simply ahead of the local branch tip).\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LibGit2/#LibGit2.fullname","page":"LibGit2","title":"LibGit2.fullname","text":"LibGit2.fullname(ref::GitReference)\n\nReturn the name of the reference pointed to by the symbolic reference ref. If ref is not a symbolic reference, return an empty string.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LibGit2/#LibGit2.features","page":"LibGit2","title":"LibGit2.features","text":"features()\n\nReturn a list of git features the current version of libgit2 supports, such as threading or using HTTPS or SSH.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LibGit2/#LibGit2.filename","page":"LibGit2","title":"LibGit2.filename","text":"filename(te::GitTreeEntry)\n\nReturn the filename of the object on disk to which te refers.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LibGit2/#LibGit2.filemode","page":"LibGit2","title":"LibGit2.filemode","text":"filemode(te::GitTreeEntry) -> Cint\n\nReturn the UNIX filemode of the object on disk to which te refers as an integer.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LibGit2/#LibGit2.gitdir","page":"LibGit2","title":"LibGit2.gitdir","text":"LibGit2.gitdir(repo::GitRepo)\n\nReturn the location of the \"git\" files of repo:\n\nfor normal repositories, this is the location of the .git folder.\nfor bare repositories, this is the location of the repository itself.\n\nSee also workdir, path.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LibGit2/#LibGit2.git_url","page":"LibGit2","title":"LibGit2.git_url","text":"LibGit2.git_url(; kwargs...) -> String\n\nCreate a string based upon the URL components provided. When the scheme keyword is not provided the URL produced will use the alternative scp-like syntax.\n\nKeywords\n\nscheme::AbstractString=\"\": the URL scheme which identifies the protocol to be used. For HTTP use \"http\", SSH use \"ssh\", etc. When scheme is not provided the output format will be \"ssh\" but using the scp-like syntax.\nusername::AbstractString=\"\": the username to use in the output if provided.\npassword::AbstractString=\"\": the password to use in the output if provided.\nhost::AbstractString=\"\": the hostname to use in the output. A hostname is required to be specified.\nport::Union{AbstractString,Integer}=\"\": the port number to use in the output if provided. Cannot be specified when using the scp-like syntax.\npath::AbstractString=\"\": the path to use in the output if provided.\n\nwarning: Warning\nAvoid using passwords in URLs. Unlike the credential objects, Julia is not able to securely zero or destroy the sensitive data after use and the password may remain in memory; possibly to be exposed by an uninitialized memory.\n\nExamples\n\njulia> LibGit2.git_url(username=\"git\", host=\"github.com\", path=\"JuliaLang/julia.git\")\n\"git@github.com:JuliaLang/julia.git\"\n\njulia> LibGit2.git_url(scheme=\"https\", host=\"github.com\", path=\"/JuliaLang/julia.git\")\n\"https://github.com/JuliaLang/julia.git\"\n\njulia> LibGit2.git_url(scheme=\"ssh\", username=\"git\", host=\"github.com\", port=2222, path=\"JuliaLang/julia.git\")\n\"ssh://git@github.com:2222/JuliaLang/julia.git\"\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LibGit2/#LibGit2.@githash_str","page":"LibGit2","title":"LibGit2.@githash_str","text":"@githash_str -> AbstractGitHash\n\nConstruct a git hash object from the given string, returning a GitShortHash if the string is shorter than 40 hexadecimal digits, otherwise a GitHash.\n\nExamples\n\njulia> LibGit2.githash\"d114feb74ce633\"\nGitShortHash(\"d114feb74ce633\")\n\njulia> LibGit2.githash\"d114feb74ce63307afe878a5228ad014e0289a85\"\nGitHash(\"d114feb74ce63307afe878a5228ad014e0289a85\")\n\n\n\n\n\n","category":"macro"},{"location":"stdlib/LibGit2/#LibGit2.head","page":"LibGit2","title":"LibGit2.head","text":"LibGit2.head(repo::GitRepo) -> GitReference\n\nReturn a GitReference to the current HEAD of repo.\n\n\n\n\n\nhead(pkg::AbstractString) -> String\n\nReturn current HEAD GitHash of the pkg repo as a string.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LibGit2/#LibGit2.head!","page":"LibGit2","title":"LibGit2.head!","text":"LibGit2.head!(repo::GitRepo, ref::GitReference) -> GitReference\n\nSet the HEAD of repo to the object pointed to by ref.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LibGit2/#LibGit2.head_oid","page":"LibGit2","title":"LibGit2.head_oid","text":"LibGit2.head_oid(repo::GitRepo) -> GitHash\n\nLookup the object id of the current HEAD of git repository repo.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LibGit2/#LibGit2.headname","page":"LibGit2","title":"LibGit2.headname","text":"LibGit2.headname(repo::GitRepo)\n\nLookup the name of the current HEAD of git repository repo. If repo is currently detached, return the name of the HEAD it's detached from.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LibGit2/#LibGit2.init","page":"LibGit2","title":"LibGit2.init","text":"LibGit2.init(path::AbstractString, bare::Bool=false) -> GitRepo\n\nOpen a new git repository at path. If bare is false, the working tree will be created in path/.git. If bare is true, no working directory will be created.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LibGit2/#LibGit2.is_ancestor_of","page":"LibGit2","title":"LibGit2.is_ancestor_of","text":"is_ancestor_of(a::AbstractString, b::AbstractString, repo::GitRepo) -> Bool\n\nReturn true if a, a GitHash in string form, is an ancestor of b, a GitHash in string form.\n\nExamples\n\njulia> repo = LibGit2.GitRepo(repo_path);\n\njulia> LibGit2.add!(repo, test_file1);\n\njulia> commit_oid1 = LibGit2.commit(repo, \"commit1\");\n\njulia> LibGit2.add!(repo, test_file2);\n\njulia> commit_oid2 = LibGit2.commit(repo, \"commit2\");\n\njulia> LibGit2.is_ancestor_of(string(commit_oid1), string(commit_oid2), repo)\ntrue\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LibGit2/#LibGit2.isbinary","page":"LibGit2","title":"LibGit2.isbinary","text":"isbinary(blob::GitBlob) -> Bool\n\nUse a heuristic to guess if a file is binary: searching for NULL bytes and looking for a reasonable ratio of printable to non-printable characters among the first 8000 bytes.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LibGit2/#LibGit2.iscommit","page":"LibGit2","title":"LibGit2.iscommit","text":"iscommit(id::AbstractString, repo::GitRepo) -> Bool\n\nCheck if commit id (which is a GitHash in string form) is in the repository.\n\nExamples\n\njulia> repo = LibGit2.GitRepo(repo_path);\n\njulia> LibGit2.add!(repo, test_file);\n\njulia> commit_oid = LibGit2.commit(repo, \"add test_file\");\n\njulia> LibGit2.iscommit(string(commit_oid), repo)\ntrue\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LibGit2/#LibGit2.isdiff","page":"LibGit2","title":"LibGit2.isdiff","text":"LibGit2.isdiff(repo::GitRepo, treeish::AbstractString, pathspecs::AbstractString=\"\"; cached::Bool=false)\n\nChecks if there are any differences between the tree specified by treeish and the tracked files in the working tree (if cached=false) or the index (if cached=true). pathspecs are the specifications for options for the diff.\n\nExamples\n\nrepo = LibGit2.GitRepo(repo_path)\nLibGit2.isdiff(repo, \"HEAD\") # should be false\nopen(joinpath(repo_path, new_file), \"a\") do f\n println(f, \"here's my cool new file\")\nend\nLibGit2.isdiff(repo, \"HEAD\") # now true\n\nEquivalent to git diff-index [-- ].\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LibGit2/#LibGit2.isdirty","page":"LibGit2","title":"LibGit2.isdirty","text":"LibGit2.isdirty(repo::GitRepo, pathspecs::AbstractString=\"\"; cached::Bool=false) -> Bool\n\nCheck if there have been any changes to tracked files in the working tree (if cached=false) or the index (if cached=true). pathspecs are the specifications for options for the diff.\n\nExamples\n\nrepo = LibGit2.GitRepo(repo_path)\nLibGit2.isdirty(repo) # should be false\nopen(joinpath(repo_path, new_file), \"a\") do f\n println(f, \"here's my cool new file\")\nend\nLibGit2.isdirty(repo) # now true\nLibGit2.isdirty(repo, new_file) # now true\n\nEquivalent to git diff-index HEAD [-- ].\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LibGit2/#LibGit2.isorphan","page":"LibGit2","title":"LibGit2.isorphan","text":"LibGit2.isorphan(repo::GitRepo)\n\nCheck if the current branch is an \"orphan\" branch, i.e. has no commits. The first commit to this branch will have no parents.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LibGit2/#LibGit2.isset","page":"LibGit2","title":"LibGit2.isset","text":"isset(val::Integer, flag::Integer)\n\nTest whether the bits of val indexed by flag are set (1) or unset (0).\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LibGit2/#LibGit2.iszero","page":"LibGit2","title":"LibGit2.iszero","text":"iszero(id::GitHash) -> Bool\n\nDetermine whether all hexadecimal digits of the given GitHash are zero.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LibGit2/#LibGit2.lookup_branch","page":"LibGit2","title":"LibGit2.lookup_branch","text":"lookup_branch(repo::GitRepo, branch_name::AbstractString, remote::Bool=false) -> Union{GitReference, Nothing}\n\nDetermine if the branch specified by branch_name exists in the repository repo. If remote is true, repo is assumed to be a remote git repository. Otherwise, it is part of the local filesystem.\n\nReturn either a GitReference to the requested branch if it exists, or nothing if not.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LibGit2/#LibGit2.map","page":"LibGit2","title":"LibGit2.map","text":"LibGit2.map(f::Function, walker::GitRevWalker; oid::GitHash=GitHash(), range::AbstractString=\"\", by::Cint=Consts.SORT_NONE, rev::Bool=false)\n\nUsing the GitRevWalker walker to \"walk\" over every commit in the repository's history, apply f to each commit in the walk. The keyword arguments are: * oid: The GitHash of the commit to begin the walk from. The default is to use push_head! and therefore the HEAD commit and all its ancestors. * range: A range of GitHashs in the format oid1..oid2. f will be applied to all commits between the two. * by: The sorting method. The default is not to sort. Other options are to sort by topology (LibGit2.Consts.SORT_TOPOLOGICAL), to sort forwards in time (LibGit2.Consts.SORT_TIME, most ancient first) or to sort backwards in time (LibGit2.Consts.SORT_REVERSE, most recent first). * rev: Whether to reverse the sorted order (for instance, if topological sorting is used).\n\nExamples\n\noids = LibGit2.with(LibGit2.GitRevWalker(repo)) do walker\n LibGit2.map((oid, repo)->string(oid), walker, by=LibGit2.Consts.SORT_TIME)\nend\n\nHere, LibGit2.map visits each commit using the GitRevWalker and finds its GitHash.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LibGit2/#LibGit2.mirror_callback","page":"LibGit2","title":"LibGit2.mirror_callback","text":"Mirror callback function\n\nFunction sets +refs/*:refs/* refspecs and mirror flag for remote reference.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LibGit2/#LibGit2.mirror_cb","page":"LibGit2","title":"LibGit2.mirror_cb","text":"C function pointer for mirror_callback\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LibGit2/#LibGit2.message","page":"LibGit2","title":"LibGit2.message","text":"message(c::GitCommit, raw::Bool=false)\n\nReturn the commit message describing the changes made in commit c. If raw is false, return a slightly \"cleaned up\" message (which has any leading newlines removed). If raw is true, the message is not stripped of any such newlines.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LibGit2/#LibGit2.merge_analysis","page":"LibGit2","title":"LibGit2.merge_analysis","text":"merge_analysis(repo::GitRepo, anns::Vector{GitAnnotated}) -> analysis, preference\n\nRun analysis on the branches pointed to by the annotated branch tips anns and determine under what circumstances they can be merged. For instance, if anns[1] is simply an ancestor of ann[2], then merge_analysis will report that a fast-forward merge is possible.\n\nReturn two outputs, analysis and preference. analysis has several possible values: * MERGE_ANALYSIS_NONE: it is not possible to merge the elements of anns. * MERGE_ANALYSIS_NORMAL: a regular merge, when HEAD and the commits that the user wishes to merge have all diverged from a common ancestor. In this case the changes have to be resolved and conflicts may occur. * MERGE_ANALYSIS_UP_TO_DATE: all the input commits the user wishes to merge can be reached from HEAD, so no merge needs to be performed. * MERGE_ANALYSIS_FASTFORWARD: the input commit is a descendant of HEAD and so no merge needs to be performed - instead, the user can simply checkout the input commit(s). * MERGE_ANALYSIS_UNBORN: the HEAD of the repository refers to a commit which does not exist. It is not possible to merge, but it may be possible to checkout the input commits. preference also has several possible values: * MERGE_PREFERENCE_NONE: the user has no preference. * MERGE_PREFERENCE_NO_FASTFORWARD: do not allow any fast-forward merges. * MERGE_PREFERENCE_FASTFORWARD_ONLY: allow only fast-forward merges and no other type (which may introduce conflicts). preference can be controlled through the repository or global git configuration.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LibGit2/#LibGit2.name","page":"LibGit2","title":"LibGit2.name","text":"LibGit2.name(ref::GitReference)\n\nReturn the full name of ref.\n\n\n\n\n\nname(rmt::GitRemote)\n\nGet the name of a remote repository, for instance \"origin\". If the remote is anonymous (see GitRemoteAnon) the name will be an empty string \"\".\n\nExamples\n\njulia> repo_url = \"https://github.com/JuliaLang/Example.jl\";\n\njulia> repo = LibGit2.clone(cache_repo, \"test_directory\");\n\njulia> remote = LibGit2.GitRemote(repo, \"origin\", repo_url);\n\njulia> name(remote)\n\"origin\"\n\n\n\n\n\nLibGit2.name(tag::GitTag)\n\nThe name of tag (e.g. \"v0.5\").\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LibGit2/#LibGit2.need_update","page":"LibGit2","title":"LibGit2.need_update","text":"need_update(repo::GitRepo)\n\nEquivalent to git update-index. Return true if repo needs updating.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LibGit2/#LibGit2.objtype","page":"LibGit2","title":"LibGit2.objtype","text":"objtype(obj_type::Consts.OBJECT)\n\nReturn the type corresponding to the enum value.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LibGit2/#LibGit2.path","page":"LibGit2","title":"LibGit2.path","text":"LibGit2.path(repo::GitRepo)\n\nReturn the base file path of the repository repo.\n\nfor normal repositories, this will typically be the parent directory of the \".git\" directory (note: this may be different than the working directory, see workdir for more details).\nfor bare repositories, this is the location of the \"git\" files.\n\nSee also gitdir, workdir.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LibGit2/#LibGit2.peel","page":"LibGit2","title":"LibGit2.peel","text":"peel([T,] ref::GitReference)\n\nRecursively peel ref until an object of type T is obtained. If no T is provided, then ref will be peeled until an object other than a GitTag is obtained.\n\nA GitTag will be peeled to the object it references.\nA GitCommit will be peeled to a GitTree.\n\nnote: Note\nOnly annotated tags can be peeled to GitTag objects. Lightweight tags (the default) are references under refs/tags/ which point directly to GitCommit objects.\n\n\n\n\n\npeel([T,] obj::GitObject)\n\nRecursively peel obj until an object of type T is obtained. If no T is provided, then obj will be peeled until the type changes.\n\nA GitTag will be peeled to the object it references.\nA GitCommit will be peeled to a GitTree.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LibGit2/#LibGit2.posixpath","page":"LibGit2","title":"LibGit2.posixpath","text":"LibGit2.posixpath(path)\n\nStandardise the path string path to use POSIX separators.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LibGit2/#LibGit2.push","page":"LibGit2","title":"LibGit2.push","text":"push(rmt::GitRemote, refspecs; force::Bool=false, options::PushOptions=PushOptions())\n\nPush to the specified rmt remote git repository, using refspecs to determine which remote branch(es) to push to. The keyword arguments are:\n\nforce: if true, a force-push will occur, disregarding conflicts.\noptions: determines the options for the push, e.g. which proxy headers to use. See PushOptions for more information.\n\nnote: Note\nYou can add information about the push refspecs in two other ways: by setting an option in the repository's GitConfig (with push.default as the key) or by calling add_push!. Otherwise you will need to explicitly specify a push refspec in the call to push for it to have any effect, like so: LibGit2.push(repo, refspecs=[\"refs/heads/master\"]).\n\n\n\n\n\npush(repo::GitRepo; kwargs...)\n\nPushes updates to an upstream of repo.\n\nThe keyword arguments are:\n\nremote::AbstractString=\"origin\": the name of the upstream remote to push to.\nremoteurl::AbstractString=\"\": the URL of remote.\nrefspecs=AbstractString[]: determines properties of the push.\nforce::Bool=false: determines if the push will be a force push, overwriting the remote branch.\ncredentials=nothing: provides credentials and/or settings when authenticating against a private remote.\ncallbacks=Callbacks(): user provided callbacks and payloads.\n\nEquivalent to git push [|] [].\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LibGit2/#LibGit2.push!-Tuple{LibGit2.GitRevWalker, LibGit2.GitHash}","page":"LibGit2","title":"LibGit2.push!","text":"LibGit2.push!(w::GitRevWalker, cid::GitHash)\n\nStart the GitRevWalker walker at commit cid. This function can be used to apply a function to all commits since a certain year, by passing the first commit of that year as cid and then passing the resulting w to LibGit2.map.\n\n\n\n\n\n","category":"method"},{"location":"stdlib/LibGit2/#LibGit2.push_head!","page":"LibGit2","title":"LibGit2.push_head!","text":"LibGit2.push_head!(w::GitRevWalker)\n\nPush the HEAD commit and its ancestors onto the GitRevWalker w. This ensures that HEAD and all its ancestor commits will be encountered during the walk.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LibGit2/#LibGit2.push_refspecs","page":"LibGit2","title":"LibGit2.push_refspecs","text":"push_refspecs(rmt::GitRemote) -> Vector{String}\n\nGet the push refspecs for the specified rmt. These refspecs contain information about which branch(es) to push to.\n\nExamples\n\njulia> remote = LibGit2.get(LibGit2.GitRemote, repo, \"upstream\");\n\njulia> LibGit2.add_push!(repo, remote, \"refs/heads/master\");\n\njulia> close(remote);\n\njulia> remote = LibGit2.get(LibGit2.GitRemote, repo, \"upstream\");\n\njulia> LibGit2.push_refspecs(remote)\nString[\"refs/heads/master\"]\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LibGit2/#LibGit2.raw","page":"LibGit2","title":"LibGit2.raw","text":"raw(id::GitHash) -> Vector{UInt8}\n\nObtain the raw bytes of the GitHash as a vector of length 20.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LibGit2/#LibGit2.read_tree!","page":"LibGit2","title":"LibGit2.read_tree!","text":"LibGit2.read_tree!(idx::GitIndex, tree::GitTree)\nLibGit2.read_tree!(idx::GitIndex, treehash::AbstractGitHash)\n\nRead the tree tree (or the tree pointed to by treehash in the repository owned by idx) into the index idx. The current index contents will be replaced.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LibGit2/#LibGit2.rebase!","page":"LibGit2","title":"LibGit2.rebase!","text":"LibGit2.rebase!(repo::GitRepo, upstream::AbstractString=\"\", newbase::AbstractString=\"\")\n\nAttempt an automatic merge rebase of the current branch, from upstream if provided, or otherwise from the upstream tracking branch. newbase is the branch to rebase onto. By default this is upstream.\n\nIf any conflicts arise which cannot be automatically resolved, the rebase will abort, leaving the repository and working tree in its original state, and the function will throw a GitError. This is roughly equivalent to the following command line statement:\n\ngit rebase --merge []\nif [ -d \".git/rebase-merge\" ]; then\n git rebase --abort\nfi\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LibGit2/#LibGit2.ref_list","page":"LibGit2","title":"LibGit2.ref_list","text":"LibGit2.ref_list(repo::GitRepo) -> Vector{String}\n\nGet a list of all reference names in the repo repository.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LibGit2/#LibGit2.reftype","page":"LibGit2","title":"LibGit2.reftype","text":"LibGit2.reftype(ref::GitReference) -> Cint\n\nReturn a Cint corresponding to the type of ref:\n\n0 if the reference is invalid\n1 if the reference is an object id\n2 if the reference is symbolic\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LibGit2/#LibGit2.remotes","page":"LibGit2","title":"LibGit2.remotes","text":"LibGit2.remotes(repo::GitRepo)\n\nReturn a vector of the names of the remotes of repo.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LibGit2/#LibGit2.remove!","page":"LibGit2","title":"LibGit2.remove!","text":"remove!(repo::GitRepo, files::AbstractString...)\nremove!(idx::GitIndex, files::AbstractString...)\n\nRemove all the files with paths specified by files in the index idx (or the index of the repo).\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LibGit2/#LibGit2.reset","page":"LibGit2","title":"LibGit2.reset","text":"reset(val::Integer, flag::Integer)\n\nUnset the bits of val indexed by flag, returning them to 0.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LibGit2/#LibGit2.reset!","page":"LibGit2","title":"LibGit2.reset!","text":"reset!(payload, [config]) -> CredentialPayload\n\nReset the payload state back to the initial values so that it can be used again within the credential callback. If a config is provided the configuration will also be updated.\n\n\n\n\n\nUpdates some entries, determined by the pathspecs, in the index from the target commit tree.\n\n\n\n\n\nSets the current head to the specified commit oid and optionally resets the index and working tree to match.\n\n\n\n\n\ngit reset [] [–] ... \n\n\n\n\n\nreset!(repo::GitRepo, id::GitHash, mode::Cint=Consts.RESET_MIXED)\n\nReset the repository repo to its state at id, using one of three modes set by mode:\n\nConsts.RESET_SOFT - move HEAD to id.\nConsts.RESET_MIXED - default, move HEAD to id and reset the index to id.\nConsts.RESET_HARD - move HEAD to id, reset the index to id, and discard all working changes.\n\nExamples\n\n# fetch changes\nLibGit2.fetch(repo)\nisfile(joinpath(repo_path, our_file)) # will be false\n\n# fastforward merge the changes\nLibGit2.merge!(repo, fastforward=true)\n\n# because there was not any file locally, but there is\n# a file remotely, we need to reset the branch\nhead_oid = LibGit2.head_oid(repo)\nnew_head = LibGit2.reset!(repo, head_oid, LibGit2.Consts.RESET_HARD)\n\nIn this example, the remote which is being fetched from does have a file called our_file in its index, which is why we must reset.\n\nEquivalent to git reset [--soft | --mixed | --hard] .\n\nExamples\n\nrepo = LibGit2.GitRepo(repo_path)\nhead_oid = LibGit2.head_oid(repo)\nopen(joinpath(repo_path, \"file1\"), \"w\") do f\n write(f, \"111\n\")\nend\nLibGit2.add!(repo, \"file1\")\nmode = LibGit2.Consts.RESET_HARD\n# will discard the changes to file1\n# and unstage it\nnew_head = LibGit2.reset!(repo, head_oid, mode)\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LibGit2/#LibGit2.restore","page":"LibGit2","title":"LibGit2.restore","text":"restore(s::State, repo::GitRepo)\n\nReturn a repository repo to a previous State s, for example the HEAD of a branch before a merge attempt. s can be generated using the snapshot function.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LibGit2/#LibGit2.revcount","page":"LibGit2","title":"LibGit2.revcount","text":"LibGit2.revcount(repo::GitRepo, commit1::AbstractString, commit2::AbstractString)\n\nList the number of revisions between commit1 and commit2 (committish OIDs in string form). Since commit1 and commit2 may be on different branches, revcount performs a \"left-right\" revision list (and count), returning a tuple of Ints - the number of left and right commits, respectively. A left (or right) commit refers to which side of a symmetric difference in a tree the commit is reachable from.\n\nEquivalent to git rev-list --left-right --count .\n\nExamples\n\nrepo = LibGit2.GitRepo(repo_path)\nrepo_file = open(joinpath(repo_path, test_file), \"a\")\nprintln(repo_file, \"hello world\")\nflush(repo_file)\nLibGit2.add!(repo, test_file)\ncommit_oid1 = LibGit2.commit(repo, \"commit 1\")\nprintln(repo_file, \"hello world again\")\nflush(repo_file)\nLibGit2.add!(repo, test_file)\ncommit_oid2 = LibGit2.commit(repo, \"commit 2\")\nLibGit2.revcount(repo, string(commit_oid1), string(commit_oid2))\n\nThis will return (-1, 0).\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LibGit2/#LibGit2.set_remote_url","page":"LibGit2","title":"LibGit2.set_remote_url","text":"set_remote_url(repo::GitRepo, remote_name, url)\nset_remote_url(repo::String, remote_name, url)\n\nSet both the fetch and push url for remote_name for the GitRepo or the git repository located at path. Typically git repos use \"origin\" as the remote name.\n\nExamples\n\nrepo_path = joinpath(tempdir(), \"Example\")\nrepo = LibGit2.init(repo_path)\nLibGit2.set_remote_url(repo, \"upstream\", \"https://github.com/JuliaLang/Example.jl\")\nLibGit2.set_remote_url(repo_path, \"upstream2\", \"https://github.com/JuliaLang/Example2.jl\")\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LibGit2/#LibGit2.shortname","page":"LibGit2","title":"LibGit2.shortname","text":"LibGit2.shortname(ref::GitReference)\n\nReturn a shortened version of the name of ref that's \"human-readable\".\n\njulia> repo = LibGit2.GitRepo(path_to_repo);\n\njulia> branch_ref = LibGit2.head(repo);\n\njulia> LibGit2.name(branch_ref)\n\"refs/heads/master\"\n\njulia> LibGit2.shortname(branch_ref)\n\"master\"\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LibGit2/#LibGit2.snapshot","page":"LibGit2","title":"LibGit2.snapshot","text":"snapshot(repo::GitRepo) -> State\n\nTake a snapshot of the current state of the repository repo, storing the current HEAD, index, and any uncommitted work. The output State can be used later during a call to restore to return the repository to the snapshotted state.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LibGit2/#LibGit2.split_cfg_entry","page":"LibGit2","title":"LibGit2.split_cfg_entry","text":"LibGit2.split_cfg_entry(ce::LibGit2.ConfigEntry) -> Tuple{String,String,String,String}\n\nBreak the ConfigEntry up to the following pieces: section, subsection, name, and value.\n\nExamples\n\nGiven the git configuration file containing:\n\n[credential \"https://example.com\"]\n username = me\n\nThe ConfigEntry would look like the following:\n\njulia> entry\nConfigEntry(\"credential.https://example.com.username\", \"me\")\n\njulia> LibGit2.split_cfg_entry(entry)\n(\"credential\", \"https://example.com\", \"username\", \"me\")\n\nRefer to the git config syntax documentation for more details.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LibGit2/#LibGit2.status","page":"LibGit2","title":"LibGit2.status","text":"LibGit2.status(repo::GitRepo, path::String) -> Union{Cuint, Cvoid}\n\nLookup the status of the file at path in the git repository repo. For instance, this can be used to check if the file at path has been modified and needs to be staged and committed.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LibGit2/#LibGit2.stage","page":"LibGit2","title":"LibGit2.stage","text":"stage(ie::IndexEntry) -> Cint\n\nGet the stage number of ie. The stage number 0 represents the current state of the working tree, but other numbers can be used in the case of a merge conflict. In such a case, the various stage numbers on an IndexEntry describe which side(s) of the conflict the current state of the file belongs to. Stage 0 is the state before the attempted merge, stage 1 is the changes which have been made locally, stages 2 and larger are for changes from other branches (for instance, in the case of a multi-branch \"octopus\" merge, stages 2, 3, and 4 might be used).\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LibGit2/#LibGit2.tag_create","page":"LibGit2","title":"LibGit2.tag_create","text":"LibGit2.tag_create(repo::GitRepo, tag::AbstractString, commit; kwargs...)\n\nCreate a new git tag tag (e.g. \"v0.5\") in the repository repo, at the commit commit.\n\nThe keyword arguments are:\n\nmsg::AbstractString=\"\": the message for the tag.\nforce::Bool=false: if true, existing references will be overwritten.\nsig::Signature=Signature(repo): the tagger's signature.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LibGit2/#LibGit2.tag_delete","page":"LibGit2","title":"LibGit2.tag_delete","text":"LibGit2.tag_delete(repo::GitRepo, tag::AbstractString)\n\nRemove the git tag tag from the repository repo.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LibGit2/#LibGit2.tag_list","page":"LibGit2","title":"LibGit2.tag_list","text":"LibGit2.tag_list(repo::GitRepo) -> Vector{String}\n\nGet a list of all tags in the git repository repo.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LibGit2/#LibGit2.target","page":"LibGit2","title":"LibGit2.target","text":"LibGit2.target(tag::GitTag)\n\nThe GitHash of the target object of tag.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LibGit2/#LibGit2.toggle","page":"LibGit2","title":"LibGit2.toggle","text":"toggle(val::Integer, flag::Integer)\n\nFlip the bits of val indexed by flag, so that if a bit is 0 it will be 1 after the toggle, and vice-versa.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LibGit2/#LibGit2.transact","page":"LibGit2","title":"LibGit2.transact","text":"transact(f::Function, repo::GitRepo)\n\nApply function f to the git repository repo, taking a snapshot before applying f. If an error occurs within f, repo will be returned to its snapshot state using restore. The error which occurred will be rethrown, but the state of repo will not be corrupted.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LibGit2/#LibGit2.treewalk","page":"LibGit2","title":"LibGit2.treewalk","text":"treewalk(f, tree::GitTree, post::Bool=false)\n\nTraverse the entries in tree and its subtrees in post or pre order. Preorder means beginning at the root and then traversing the leftmost subtree (and recursively on down through that subtree's leftmost subtrees) and moving right through the subtrees. Postorder means beginning at the bottom of the leftmost subtree, traversing upwards through it, then traversing the next right subtree (again beginning at the bottom) and finally visiting the tree root last of all.\n\nThe function parameter f should have following signature:\n\n(String, GitTreeEntry) -> Cint\n\nA negative value returned from f stops the tree walk. A positive value means that the entry will be skipped if post is false.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LibGit2/#LibGit2.upstream","page":"LibGit2","title":"LibGit2.upstream","text":"upstream(ref::GitReference) -> Union{GitReference, Nothing}\n\nDetermine if the branch containing ref has a specified upstream branch.\n\nReturn either a GitReference to the upstream branch if it exists, or nothing if the requested branch does not have an upstream counterpart.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LibGit2/#LibGit2.update!","page":"LibGit2","title":"LibGit2.update!","text":"update!(repo::GitRepo, files::AbstractString...)\nupdate!(idx::GitIndex, files::AbstractString...)\n\nUpdate all the files with paths specified by files in the index idx (or the index of the repo). Match the state of each file in the index with the current state on disk, removing it if it has been removed on disk, or updating its entry in the object database.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LibGit2/#LibGit2.url","page":"LibGit2","title":"LibGit2.url","text":"url(rmt::GitRemote)\n\nGet the fetch URL of a remote git repository.\n\nExamples\n\njulia> repo_url = \"https://github.com/JuliaLang/Example.jl\";\n\njulia> repo = LibGit2.init(mktempdir());\n\njulia> remote = LibGit2.GitRemote(repo, \"origin\", repo_url);\n\njulia> LibGit2.url(remote)\n\"https://github.com/JuliaLang/Example.jl\"\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LibGit2/#LibGit2.version","page":"LibGit2","title":"LibGit2.version","text":"version() -> VersionNumber\n\nReturn the version of libgit2 in use, as a VersionNumber.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LibGit2/#LibGit2.with","page":"LibGit2","title":"LibGit2.with","text":"with(f::Function, obj)\n\nResource management helper function. Applies f to obj, making sure to call close on obj after f successfully returns or throws an error. Ensures that allocated git resources are finalized as soon as they are no longer needed.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LibGit2/#LibGit2.with_warn","page":"LibGit2","title":"LibGit2.with_warn","text":"with_warn(f::Function, ::Type{T}, args...)\n\nResource management helper function. Apply f to args, first constructing an instance of type T from args. Makes sure to call close on the resulting object after f successfully returns or throws an error. Ensures that allocated git resources are finalized as soon as they are no longer needed. If an error is thrown by f, a warning is shown containing the error.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LibGit2/#LibGit2.workdir","page":"LibGit2","title":"LibGit2.workdir","text":"LibGit2.workdir(repo::GitRepo)\n\nReturn the location of the working directory of repo. This will throw an error for bare repositories.\n\nnote: Note\nThis will typically be the parent directory of gitdir(repo), but can be different in some cases: e.g. if either the core.worktree configuration variable or the GIT_WORK_TREE environment variable is set.\n\nSee also gitdir, path.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LibGit2/#LibGit2.GitObject-Tuple{LibGit2.GitTreeEntry}","page":"LibGit2","title":"LibGit2.GitObject","text":"(::Type{T})(te::GitTreeEntry) where T<:GitObject\n\nGet the git object to which te refers and return it as its actual type (the type entrytype would show), for instance a GitBlob or GitTag.\n\nExamples\n\ntree = LibGit2.GitTree(repo, \"HEAD^{tree}\")\ntree_entry = tree[1]\nblob = LibGit2.GitBlob(tree_entry)\n\n\n\n\n\n","category":"method"},{"location":"stdlib/LibGit2/#LibGit2.UserPasswordCredential","page":"LibGit2","title":"LibGit2.UserPasswordCredential","text":"Credential that support only user and password parameters\n\n\n\n\n\n","category":"type"},{"location":"stdlib/LibGit2/#LibGit2.SSHCredential","page":"LibGit2","title":"LibGit2.SSHCredential","text":"SSH credential type\n\n\n\n\n\n","category":"type"},{"location":"stdlib/LibGit2/#LibGit2.isfilled","page":"LibGit2","title":"LibGit2.isfilled","text":"isfilled(cred::AbstractCredential) -> Bool\n\nVerifies that a credential is ready for use in authentication.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LibGit2/#LibGit2.CachedCredentials","page":"LibGit2","title":"LibGit2.CachedCredentials","text":"Caches credential information for re-use\n\n\n\n\n\n","category":"type"},{"location":"stdlib/LibGit2/#LibGit2.CredentialPayload","page":"LibGit2","title":"LibGit2.CredentialPayload","text":"LibGit2.CredentialPayload\n\nRetains the state between multiple calls to the credential callback for the same URL. A CredentialPayload instance is expected to be reset! whenever it will be used with a different URL.\n\n\n\n\n\n","category":"type"},{"location":"stdlib/LibGit2/#LibGit2.approve","page":"LibGit2","title":"LibGit2.approve","text":"approve(payload::CredentialPayload; shred::Bool=true) -> Nothing\n\nStore the payload credential for re-use in a future authentication. Should only be called when authentication was successful.\n\nThe shred keyword controls whether sensitive information in the payload credential field should be destroyed. Should only be set to false during testing.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LibGit2/#LibGit2.reject","page":"LibGit2","title":"LibGit2.reject","text":"reject(payload::CredentialPayload; shred::Bool=true) -> Nothing\n\nDiscard the payload credential from begin re-used in future authentication. Should only be called when authentication was unsuccessful.\n\nThe shred keyword controls whether sensitive information in the payload credential field should be destroyed. Should only be set to false during testing.\n\n\n\n\n\n","category":"function"},{"location":"base/punctuation/#运算符与记号","page":"运算符与记号","title":"运算符与记号","text":"","category":"section"},{"location":"base/punctuation/","page":"运算符与记号","title":"运算符与记号","text":"数学符号与函数的扩展文档在 这里.","category":"page"},{"location":"base/punctuation/","page":"运算符与记号","title":"运算符与记号","text":"符号 含义\n@ the at-sign marks a macro invocation; optionally followed by an argument list\n! 感叹号是一个表示逻辑否定的前缀算符\na! 在函数名的末尾,! 用作表示函数会修改参数(或多个参数)\n# the number sign (or hash or pound) character begins single line comments\n#= when followed by an equals sign, it begins a multi-line comment (these are nestable)\n=# end a multi-line comment by immediately preceding the number sign with an equals sign\n$ the dollar sign is used for string and expression interpolation\n% the percent symbol is the remainder operator\n^ the caret is the exponentiation operator\n& single ampersand is bitwise and\n&& double ampersands is short-circuiting boolean and\n| single pipe character is bitwise or\n|| double pipe characters is short-circuiting boolean or\n⊻ the unicode xor character is bitwise exclusive or\n~ the tilde is an operator for bitwise not\n' a trailing apostrophe is the adjoint (that is, the complex transpose) operator Aᴴ\n* the asterisk is used for multiplication, including matrix multiplication and string concatenation\n/ forward slash divides the argument on its left by the one on its right\n\\ backslash operator divides the argument on its right by the one on its left, commonly used to solve matrix equations\n() parentheses with no arguments constructs an empty Tuple\n(a,...) parentheses with comma-separated arguments constructs a tuple containing its arguments\n(a=1,...) parentheses with comma-separated assignments constructs a NamedTuple\n(x;y) parentheses can also be used to group one or more semicolon separated expressions\na[] array indexing (calling getindex or setindex!)\n[,] vector literal constructor (calling vect)\n[;] vertical concatenation (calling vcat or hvcat)\n[   ] with space-separated expressions, horizontal concatenation (calling hcat or hvcat)\nT{ } curly braces following a type list that type's parameters\n{} curly braces can also be used to group multiple where expressions in function declarations\n; semicolons separate statements, begin a list of keyword arguments in function declarations or calls, or are used to separate array literals for vertical concatenation\n, commas separate function arguments or tuple or array components\n? the question mark delimits the ternary conditional operator (used like: conditional ? if_true : if_false)\n\" \" the single double-quote character delimits String literals\n\"\"\" \"\"\" three double-quote characters delimits string literals that may contain \" and ignore leading indentation\n' ' the single-quote character delimits Char (that is, character) literals\n` ` the backtick character delimits external process (Cmd) literals\nA... triple periods are a postfix operator that \"splat\" their arguments' contents into many arguments of a function call or declare a varargs function that \"slurps\" up many arguments into a single tuple\na.b single periods access named fields in objects/modules (calling getproperty or setproperty!)\nf.() periods may also prefix parentheses (like f.(...)) or infix operators (like .+) to perform the function element-wise (calling broadcast)\na:b colons (:) used as a binary infix operator construct a range from a to b (inclusive) with fixed step size 1\na:s:b colons (:) used as a ternary infix operator construct a range from a to b (inclusive) with step size s\n: when used by themselves, Colons represent all indices within a dimension, frequently combined with indexing\n:: double-colons represent a type annotation or typeassert, depending on context, frequently used when declaring function arguments\n:( ) quoted expression\n:a Symbol a\n<: 子类型运算符\n>: supertype operator (reverse of subtype operator)\n= single equals sign is assignment\n== double equals sign is value equality comparison\n=== triple equals sign is programmatically identical equality comparison\n=> right arrow using an equals sign defines a Pair typically used to populate dictionaries\n-> right arrow using a hyphen defines an anonymous function on a single line\n` >`\n∘ function composition operator (typed with \\circ{tab}) combines two functions as though they are a single larger function","category":"page"},{"location":"manual/multi-threading/#man-multithreading","page":"多线程","title":"多线程","text":"","category":"section"},{"location":"manual/multi-threading/","page":"多线程","title":"多线程","text":"访问此 博客文章 以了解 Julia 多线程特性。","category":"page"},{"location":"manual/multi-threading/#启用Julia多线程","page":"多线程","title":"启用Julia多线程","text":"","category":"section"},{"location":"manual/multi-threading/","page":"多线程","title":"多线程","text":"Julia 默认启动一个线程执行代码,这点可以通过 Threads.nthreads() 来确认:","category":"page"},{"location":"manual/multi-threading/","page":"多线程","title":"多线程","text":"julia> Threads.nthreads()\n1","category":"page"},{"location":"manual/multi-threading/","page":"多线程","title":"多线程","text":"执行线程的数量通过使用-t/--threads 命令行参数或使用JULIA_NUM_THREADS 环境变量。 当两者都被指定时,-t/--threads 优先级更高。","category":"page"},{"location":"manual/multi-threading/","page":"多线程","title":"多线程","text":"compat: Julia 1.5\n-t/--threads 命令行参数至少需要 Julia 1.5。在旧版本中,你必须改用环境变量。","category":"page"},{"location":"manual/multi-threading/","page":"多线程","title":"多线程","text":"让我们以4个线程启动Julia","category":"page"},{"location":"manual/multi-threading/","page":"多线程","title":"多线程","text":"$ julia --threads 4","category":"page"},{"location":"manual/multi-threading/","page":"多线程","title":"多线程","text":"现在确认下确实有4个线程:","category":"page"},{"location":"manual/multi-threading/","page":"多线程","title":"多线程","text":"julia> Threads.nthreads()\n4","category":"page"},{"location":"manual/multi-threading/","page":"多线程","title":"多线程","text":"不过我们现在是在 master 线程,用 Threads.threadid 确认下:","category":"page"},{"location":"manual/multi-threading/","page":"多线程","title":"多线程","text":"julia> Threads.threadid()\n1","category":"page"},{"location":"manual/multi-threading/","page":"多线程","title":"多线程","text":"note: Note\n如果你更喜欢使用环境变量,可以按如下方式设置它 Bash (Linux/macOS):export JULIA_NUM_THREADS=4C shell on Linux/macOS, CMD on Windows:set JULIA_NUM_THREADS=4Powershell on Windows:$env:JULIA_NUM_THREADS=4Note that this must be done before starting Julia.","category":"page"},{"location":"manual/multi-threading/","page":"多线程","title":"多线程","text":"note: Note\n使用 -t/--threads 指定的线程数传播到使用 -p/--procs 或 --machine-file 命令行选项产生的工作进程。 例如,julia -p2 -t2 产生 1 个主进程和 2 个工作进程,并且所有三个进程都启用了 2 个线程。 要对工作线程进行更细粒度的控制,请使用 addprocs 并将 -t/--threads 作为 exeflags 传递。","category":"page"},{"location":"manual/multi-threading/#数据竞争自由","page":"多线程","title":"数据竞争自由","text":"","category":"section"},{"location":"manual/multi-threading/","page":"多线程","title":"多线程","text":"你有责任确保程序没有数据竞争,如果你不遵守该要求,则不能假设这里承诺的任何内容。 观察到的结果可能是反直觉的。","category":"page"},{"location":"manual/multi-threading/","page":"多线程","title":"多线程","text":"为了确保这一点,最好的办法是获取多线程同时访问的数据的锁。 例如,在大多数情况下,你应该使用以下代码模板:","category":"page"},{"location":"manual/multi-threading/","page":"多线程","title":"多线程","text":"julia> lock(lk) do\n use(a)\n end\n\njulia> begin\n lock(lk)\n try\n use(a)\n finally\n unlock(lk)\n end\n end","category":"page"},{"location":"manual/multi-threading/","page":"多线程","title":"多线程","text":"其中 lk 是一个锁(例如 ReentrantLock()), a 是数据。","category":"page"},{"location":"manual/multi-threading/","page":"多线程","title":"多线程","text":"此外,Julia 在出现数据竞争时不是内存安全的。如果另一个线程可能会写入数据,则在读取任何数据时都要非常小心! 相反,在更改其他线程访问的数据(例如分配给全局或闭包变量)时,请始终使用上述锁模式。","category":"page"},{"location":"manual/multi-threading/","page":"多线程","title":"多线程","text":"Thread 1:\nglobal b = false\nglobal a = rand()\nglobal b = true\n\nThread 2:\nwhile !b; end\nbad_read1(a) # it is NOT safe to access `a` here!\n\nThread 3:\nwhile !@isdefined(a); end\nbad_read2(a) # it is NOT safe to access `a` here","category":"page"},{"location":"manual/multi-threading/#@threads宏","page":"多线程","title":"@threads宏","text":"","category":"section"},{"location":"manual/multi-threading/","page":"多线程","title":"多线程","text":"下面用一个简单的例子测试我们原生的线程,首先创建一个全零的数组:","category":"page"},{"location":"manual/multi-threading/","page":"多线程","title":"多线程","text":"julia> a = zeros(10)\n10-element Vector{Float64}:\n 0.0\n 0.0\n 0.0\n 0.0\n 0.0\n 0.0\n 0.0\n 0.0\n 0.0\n 0.0","category":"page"},{"location":"manual/multi-threading/","page":"多线程","title":"多线程","text":"现在用4个线程模拟操作这个数组,每个线程往对应的位置写入线程ID。","category":"page"},{"location":"manual/multi-threading/","page":"多线程","title":"多线程","text":"Julia 用 Threads.@threads 宏实现并行循环,该宏加在 for 循环前面,提示 Julia 循环部分是一个多线程的区域:","category":"page"},{"location":"manual/multi-threading/","page":"多线程","title":"多线程","text":"julia> Threads.@threads for i = 1:10\n a[i] = Threads.threadid()\n end","category":"page"},{"location":"manual/multi-threading/","page":"多线程","title":"多线程","text":"根据线程调度,迭代在各线程中进行拆分,之后各线程将自己的线程ID写入对应区域。","category":"page"},{"location":"manual/multi-threading/","page":"多线程","title":"多线程","text":"julia> a\n10-element Vector{Float64}:\n 1.0\n 1.0\n 1.0\n 2.0\n 2.0\n 2.0\n 3.0\n 3.0\n 4.0\n 4.0","category":"page"},{"location":"manual/multi-threading/","page":"多线程","title":"多线程","text":"注意 Threads.@threads 并没有一个像 @distributed 一样的可选的 reduction 参数。","category":"page"},{"location":"manual/multi-threading/#原子操作","page":"多线程","title":"原子操作","text":"","category":"section"},{"location":"manual/multi-threading/","page":"多线程","title":"多线程","text":"Julia 支持访问和修改值的原子操作,即以一种线程安全的方式来避免竞态条件。一个值(必须是基本类型的,primitive type)可以通过 Threads.Atomic 来包装起来从而支持原子操作。下面看个例子:","category":"page"},{"location":"manual/multi-threading/","page":"多线程","title":"多线程","text":"julia> i = Threads.Atomic{Int}(0);\n\njulia> ids = zeros(4);\n\njulia> old_is = zeros(4);\n\njulia> Threads.@threads for id in 1:4\n old_is[id] = Threads.atomic_add!(i, id)\n ids[id] = id\n end\n\njulia> old_is\n4-element Vector{Float64}:\n 0.0\n 1.0\n 7.0\n 3.0\n\njulia> i[]\n 10\n\njulia> ids\n4-element Vector{Float64}:\n 1.0\n 2.0\n 3.0\n 4.0","category":"page"},{"location":"manual/multi-threading/","page":"多线程","title":"多线程","text":"如果不加 Atomic 的话,那么会因为竞态条件而得到错误的结果,下面是一个没有避免竞态条件的例子:","category":"page"},{"location":"manual/multi-threading/","page":"多线程","title":"多线程","text":"julia> using Base.Threads\n\njulia> nthreads()\n4\n\njulia> acc = Ref(0)\nBase.RefValue{Int64}(0)\n\njulia> @threads for i in 1:1000\n acc[] += 1\n end\n\njulia> acc[]\n926\n\njulia> acc = Atomic{Int64}(0)\nAtomic{Int64}(0)\n\njulia> @threads for i in 1:1000\n atomic_add!(acc, 1)\n end\n\njulia> acc[]\n1000","category":"page"},{"location":"manual/multi-threading/#man-atomics","page":"多线程","title":"field粒度的原子操作","text":"","category":"section"},{"location":"manual/multi-threading/","page":"多线程","title":"多线程","text":"我们还可以使用@atomic、@atomicswap和@atomicreplace 宏在更细粒度的级别上使用原子。","category":"page"},{"location":"manual/multi-threading/","page":"多线程","title":"多线程","text":"内存模型的具体细节和设计的其他细节写在Julia Atomics Manifesto中,稍后将正式发布。","category":"page"},{"location":"manual/multi-threading/","page":"多线程","title":"多线程","text":"struct 声明中的任何字段都可以用 @atomic 修饰,然后任何写入也必须用 @atomic 标记,并且必须使用定义的原子顺序之一(:monotonic、:acquire、:release、:acquire _release 或 :sequentially_consistent)。 对原子字段的任何读取也可以使用原子排序约束进行注释,或者如果未指定,将使用单调(宽松)排序完成。","category":"page"},{"location":"manual/multi-threading/","page":"多线程","title":"多线程","text":"compat: Julia 1.7\nfield粒度的原子操作至少需要 Julia 1.7.","category":"page"},{"location":"manual/multi-threading/#副作用和可变的函数参数","page":"多线程","title":"副作用和可变的函数参数","text":"","category":"section"},{"location":"manual/multi-threading/","page":"多线程","title":"多线程","text":"使用多线程时,我们必须小心使用非 纯 的函数,因为我们可能会得到错误的答案。 例如,按照惯例具有 名称以! 结尾 的函数会修改它们的参数,因此不是纯函数。","category":"page"},{"location":"manual/multi-threading/#@threadcall","page":"多线程","title":"@threadcall","text":"","category":"section"},{"location":"manual/multi-threading/","page":"多线程","title":"多线程","text":"外部库,例如通过 ccall 调用的库,给 Julia 基于任务的 I/O 机制带来了问题。 如果 C 库执行阻塞操作,这会阻止 Julia 调度程序执行任何其他任务,直到调用返回。(例外情况是调用回调到 Julia 的自定义 C 代码,然后它可能会 yield,或者调用 jl_yield() 的 C 代码,jl_yield 是 yield 的 C 等价物。)","category":"page"},{"location":"manual/multi-threading/","page":"多线程","title":"多线程","text":"@threadcall 宏提供了一种避免在这种情况下停止执行的方法。它调度一个 C 函数以在单独的线程中执行。为此使用默认大小为 4 的线程池。线程池的大小由环境变量UV_THREADPOOL_SIZE控制。 在等待空闲线程时,以及一旦线程可用后的函数执行期间,请求任务(在主 Julia 事件循环上)让步给其他任务。 注意,@threadcall 在执行完成之前不会返回。 因此,从用户的角度来看,它与其他 Julia API 一样是一个阻塞调用。","category":"page"},{"location":"manual/multi-threading/","page":"多线程","title":"多线程","text":"非常关键的一点是,被调用的函数不会再调用回 Julia。","category":"page"},{"location":"manual/multi-threading/","page":"多线程","title":"多线程","text":"@threadcall 在 Julia 未来的版本中可能会被移除或改变。","category":"page"},{"location":"manual/multi-threading/#注意!","page":"多线程","title":"注意!","text":"","category":"section"},{"location":"manual/multi-threading/","page":"多线程","title":"多线程","text":"此时,如果用户代码没有数据竞争,Julia 运行时和标准库中的大多数操作都可以以线程安全的方式使用。 然而,在某些领域,稳定线程支持的工作正在进行中。多线程编程有许多内在的困难,如果使用线程的程序表现出异常或与预期不符的行为(例如崩溃或神秘的结果),通常应该首先怀疑线程交互。","category":"page"},{"location":"manual/multi-threading/","page":"多线程","title":"多线程","text":"在 Julia 中使用线程时需要注意以下这些特定的限制和警告:","category":"page"},{"location":"manual/multi-threading/","page":"多线程","title":"多线程","text":"如果多个线程同时使用基本容器类型,且至少有一个线程修改容器时,需要手动加锁(常见示例包括 push! 数组,或将项插入 Dict)。\n任务开始在某个线程上运行后(例如通过@spawn),它会在阻塞后始终在同一线程上重新启动。 将来这个限制将被移除,任务会在线程之间迁移。\n@threads 当前使用静态调度,使用所有线程并为每个线程分配相等的迭代计数。将来,默认时间表可能会更改为动态的。\n@spawn 使用的时间表是不确定的,不应依赖。\n计算绑定、非内存分配任务可以防止垃圾回收在其他正在分配内存的线程中运行。 在这些情况下,可能需要手动调用 GC.safepoint() 以允许 GC 运行。\n该限制在未来会被移除。\n避免并行运行顶层操作,例如,include 或 eval 评估类型、方法和模块定义。\n请注意,如果启用线程,则库注册的终结器可能会中断。 这可能需要在整个生态系统中进行一些过渡工作,然后才能放心地广泛采用线程。 有关更多详细信息,请参阅下一节。","category":"page"},{"location":"manual/multi-threading/#终结器的安全使用","page":"多线程","title":"终结器的安全使用","text":"","category":"section"},{"location":"manual/multi-threading/","page":"多线程","title":"多线程","text":"因为终结器可以中断任何代码,所以它们在如何与任何全局状态交互时必须非常小心。 不幸的是,使用终结器的主要原因是更新全局状态(纯函数作为终结器通常毫无意义)。 这让我们陷入了一个难题。 有几种方法可以处理这个问题:","category":"page"},{"location":"manual/multi-threading/","page":"多线程","title":"多线程","text":"当单线程时,代码可以调用内部 jl_gc_enable_finalizers C 函数以防止在关键区域内调度终结器。 在内部,这在某些函数(例如我们的 C locks)中使用,以防止在执行某些操作(增量包加载、代码生成等)时发生递归。 锁和此标志的组合可用于使终结器安全。\nBase 在几个地方采用的第二种策略是显式延迟终结器,直到它可以非递归地获取其锁。 以下示例演示了如何将此策略应用于 Distributed.finalize_ref:\nfunction finalize_ref(r::AbstractRemoteRef)\n if r.where > 0 # Check if the finalizer is already run\n if islocked(client_refs) || !trylock(client_refs)\n # delay finalizer for later if we aren't free to acquire the lock\n finalizer(finalize_ref, r)\n return nothing\n end\n try # `lock` should always be followed by `try`\n if r.where > 0 # Must check again here\n # Do actual cleanup here\n r.where = 0\n end\n finally\n unlock(client_refs)\n end\n end\n nothing\nend\n相关的第三种策略是使用不需要 yield 的队列。 我们目前没有在 Base 中实现无锁队列,但 Base.InvasiveLinkedListSynchronized{T} 是合适的。 这通常是用于带有事件循环的代码的好策略。 例如,这个策略被 Gtk.jl 用来管理生命周期引用计数。 在这种方法中,我们不会在终结器内部做任何显式工作,而是将其添加到队列中以在更安全的时间运行。 事实上,Julia 的任务调度器已经使用了这种方法,因此将终结器定义为 x -> @spawn do_cleanup(x) 就是这种方法的一个示例。 但是请注意,这并不控制 do_cleanup 在哪个线程上运行,因此 do_cleanup 仍需要获取锁。 如果你实现自己的队列,则不必如此,因为你只能明确地从线程中排出该队列。","category":"page"},{"location":"manual/methods/#方法","page":"方法","title":"方法","text":"","category":"section"},{"location":"manual/methods/","page":"方法","title":"方法","text":"我们回想一下,在函数中我们知道函数是这么一个对象,它把一组参数映射成一个返回值,或者当没有办法返回恰当的值时扔出一个异常。具有相同概念的函数或者运算,经常会根据参数类型的不同而进行有很大差异的实现:两个整数的加法与两个浮点数的加法是相当不一样的,整数与浮点数之间的加法也不一样。除了它们实现上的不同,这些运算都归在\"加法\"这么一个广义的概念之下,因此在 Julia 中这些行为都属于同一个对象:+ 函数。","category":"page"},{"location":"manual/methods/","page":"方法","title":"方法","text":"为了让对同样的概念使用许多不同的实现这件事更顺畅,函数没有必要马上全部都被定义,反而应该是一块一块地定义,为特定的参数类型和数量的组合提供指定的行为。对于一个函数的一个可能行为的定义叫做方法。直到这里,我们只展示了那些只定了一个方法的,对参数的所有类型都适用的函数。但是方法定义的特征是不仅能表明参数的数量,也能表明参数的类型,并且能提供多个方法定义。当一个函数被应用于特殊的一组参数时,能用于这一组参数的最特定的方法会被使用。所以,函数的全体行为是他的不同的方法定义的行为的组合。如果这个组合被设计得好,即使方法们的实现之间会很不一样,函数的外部行为也会显得无缝而自洽。","category":"page"},{"location":"manual/methods/","page":"方法","title":"方法","text":"当一个函数被应用时执行方法的选择被称为 分派。Julia 允许分派过程基于给定的参数个数和所有参数的类型来选择调用函数的哪个方法。这与传统的面对对象的语言不一样,面对对象语言的分派只基于第一参数,经常有特殊的参数语法,并且有时是暗含而非显式写成一个参数。 [1] 使用函数的所有参数,而非只用第一个,来决定调用哪个方法被称为多重分派。多重分派对于数学代码来说特别有用,人工地将运算视为对于其中一个参数的属于程度比其他所有的参数都强的这个概念对于数学代码是几乎没有意义的:x + y 中的加法运算对 x 的属于程度比对 y 更强?一个数学运算符的实现普遍基于它所有的参数的类型。即使跳出数学运算,多重分派是对于结构和组织程序来说也是一个强大而方便的范式。","category":"page"},{"location":"manual/methods/","page":"方法","title":"方法","text":"[1]: In C++ or Java, for example, in a method call like obj.meth(arg1,arg2), the object obj \"receives\" the method call and is implicitly passed to the method via the this keyword, rather than as an explicit method argument. When the current this object is the receiver of a method call, it can be omitted altogether, writing just meth(arg1,arg2), with this implied as the receiving object.","category":"page"},{"location":"manual/methods/","page":"方法","title":"方法","text":"note: Note\n本章中的所有示例都假定是为相同模块中的函数定义模块。 如果你想给另一个模块中的函数添加方法,你必须import它或使用模块名称限定的名称。 请参阅有关 命名空间管理 的部分。","category":"page"},{"location":"manual/methods/#定义方法","page":"方法","title":"定义方法","text":"","category":"section"},{"location":"manual/methods/","page":"方法","title":"方法","text":"直到这里,在我们的例子中,我们定义的函数只有一个不限制参数类型的方法。这种函数的行为就与传统动态类型语言中的函数一样。不过,我们已经在没有意识到的情况下已经使用了多重分派和方法:所有 Julia 标准函数和运算符,就像之前提到的 + 函数,都根据参数的类型和数量的不同组合而定义了大量方法。","category":"page"},{"location":"manual/methods/","page":"方法","title":"方法","text":"当定义一个函数时,可以根据需要使用在复合类型中介绍的 :: 类型断言运算符来限制参数类型,","category":"page"},{"location":"manual/methods/","page":"方法","title":"方法","text":"julia> f(x::Float64, y::Float64) = 2x + y\nf (generic function with 1 method)","category":"page"},{"location":"manual/methods/","page":"方法","title":"方法","text":"这个函数只在 x 和 y 的类型都是 Float64 的情况下才会被调用:","category":"page"},{"location":"manual/methods/","page":"方法","title":"方法","text":"julia> f(2.0, 3.0)\n7.0","category":"page"},{"location":"manual/methods/","page":"方法","title":"方法","text":"用其它任意的参数类型则会导致 MethodError:","category":"page"},{"location":"manual/methods/","page":"方法","title":"方法","text":"julia> f(2.0, 3)\nERROR: MethodError: no method matching f(::Float64, ::Int64)\nClosest candidates are:\n f(::Float64, !Matched::Float64) at none:1\n\njulia> f(Float32(2.0), 3.0)\nERROR: MethodError: no method matching f(::Float32, ::Float64)\nClosest candidates are:\n f(!Matched::Float64, ::Float64) at none:1\n\njulia> f(2.0, \"3.0\")\nERROR: MethodError: no method matching f(::Float64, ::String)\nClosest candidates are:\n f(::Float64, !Matched::Float64) at none:1\n\njulia> f(\"2.0\", \"3.0\")\nERROR: MethodError: no method matching f(::String, ::String)","category":"page"},{"location":"manual/methods/","page":"方法","title":"方法","text":"如同你所看到的,参数必须精确地是 Float64 类型。其它数字类型,比如整数或者 32 位浮点数值,都不会自动转化成 64 位浮点数,字符串也不会解析成数字。由于 Float64 是一个具体类型,且在 Julia 中具体类型无法拥有子类,所以这种定义方式只能适用于函数的输入类型精确地是 Float64 的情况,但一个常见的做法是用抽象类型来定义通用的方法:","category":"page"},{"location":"manual/methods/","page":"方法","title":"方法","text":"julia> f(x::Number, y::Number) = 2x - y\nf (generic function with 2 methods)\n\njulia> f(2.0, 3)\n1.0","category":"page"},{"location":"manual/methods/","page":"方法","title":"方法","text":"用上面这种方式定义的方法可以接收任意一对 Number 的实例参数,且它们不需要是同一类型的,只要求都是数值。如何根据不同的类型来做相应的处理就可以委托给表达式 2x - y 中的代数运算。","category":"page"},{"location":"manual/methods/","page":"方法","title":"方法","text":"为了定义一个有多个方法的函数,只需简单定义这个函数多次,使用不同的参数数量和类型。函数的第一个方法定义会建立这个函数对象,后续的方法定义会添加新的方法到存在的函数对象中去。当函数被应用时,最符合参数的数量和类型的特定方法会被执行。所以,上面的两个方法定义在一起定义了函数f对于所有的一对虚拟类型Number实例的行为 – 但是针对一对Float64值有不同的行为。如果一个参数是64位浮点数而另一个不是,f(Float64,Float64)方法不会被调用,而一定使用更加通用的f(Number,Number)方法:","category":"page"},{"location":"manual/methods/","page":"方法","title":"方法","text":"julia> f(2.0, 3.0)\n7.0\n\njulia> f(2, 3.0)\n1.0\n\njulia> f(2.0, 3)\n1.0\n\njulia> f(2, 3)\n1","category":"page"},{"location":"manual/methods/","page":"方法","title":"方法","text":"2x + y 定义只用于第一个情况,2x - y 定义用于其他的情况。没有使用任何自动的函数参数的指派或者类型转换:Julia中的所有转换都不是 magic 的,都是完全显式的。然而类型转换和类型提升显示了足够先进的技术的智能应用能够与 magic 不可分辨到什么程度。[Clarke61] 对于非数字值,和比两个参数更多或者更少的情况,函数 f 并没有定义,应用会导致 MethodError:","category":"page"},{"location":"manual/methods/","page":"方法","title":"方法","text":"julia> f(\"foo\", 3)\nERROR: MethodError: no method matching f(::String, ::Int64)\nClosest candidates are:\n f(!Matched::Number, ::Number) at none:1\n\njulia> f()\nERROR: MethodError: no method matching f()\nClosest candidates are:\n f(!Matched::Float64, !Matched::Float64) at none:1\n f(!Matched::Number, !Matched::Number) at none:1","category":"page"},{"location":"manual/methods/","page":"方法","title":"方法","text":"可以简单地看到对于函数存在哪些方法,通过在交互式会话中键入函数对象本身:","category":"page"},{"location":"manual/methods/","page":"方法","title":"方法","text":"julia> f\nf (generic function with 2 methods)","category":"page"},{"location":"manual/methods/","page":"方法","title":"方法","text":"这个输出展示了f有两个方法。为了找到这些方法的前面,使用methods函数:","category":"page"},{"location":"manual/methods/","page":"方法","title":"方法","text":"julia> methods(f)\n# 2 methods for generic function \"f\":\n[1] f(x::Float64, y::Float64) in Main at none:1\n[2] f(x::Number, y::Number) in Main at none:1","category":"page"},{"location":"manual/methods/","page":"方法","title":"方法","text":"这表示f有两个方法,一个接受两个Float64参数一个接受两个Number类型的参数。它也显示了这些方法定义所在的文件和行数:因为这些方法是在REPL中定义的,我们得到了表面上的行数none:1.","category":"page"},{"location":"manual/methods/","page":"方法","title":"方法","text":"没有::的类型声明,方法参数的类型默认为Any,这就意味着没有约束,因为Julia中的所有的值都是抽象类型Any的实例。所以,我们可以为f定义一个接受所有的方法,像这样:","category":"page"},{"location":"manual/methods/","page":"方法","title":"方法","text":"julia> f(x,y) = println(\"Whoa there, Nelly.\")\nf (generic function with 3 methods)\n\njulia> methods(f)\n# 3 methods for generic function \"f\":\n[1] f(x::Float64, y::Float64) in Main at none:1\n[2] f(x::Number, y::Number) in Main at none:1\n[3] f(x, y) in Main at none:1\n\njulia> f(\"foo\", 1)\nWhoa there, Nelly.","category":"page"},{"location":"manual/methods/","page":"方法","title":"方法","text":"这个接受所有参数类型的方法比其他的对一对参数值的其他任意可能的方法定义更不专用。所以他只会被没有其他方法定义应用的一对参数调用。","category":"page"},{"location":"manual/methods/","page":"方法","title":"方法","text":"注意到第三个方法的签名中并没有指定参数x和y的类型。它是f(x::Any, y::Any)的简写。","category":"page"},{"location":"manual/methods/","page":"方法","title":"方法","text":"尽管这看起来很简单,但对值类型的多重派发可能是 Julia 语言最强大和最核心的特性。 核心运算通常有几十种方法:","category":"page"},{"location":"manual/methods/","page":"方法","title":"方法","text":"julia> methods(+)\n# 180 methods for generic function \"+\":\n[1] +(x::Bool, z::Complex{Bool}) in Base at complex.jl:227\n[2] +(x::Bool, y::Bool) in Base at bool.jl:89\n[3] +(x::Bool) in Base at bool.jl:86\n[4] +(x::Bool, y::T) where T<:AbstractFloat in Base at bool.jl:96\n[5] +(x::Bool, z::Complex) in Base at complex.jl:234\n[6] +(a::Float16, b::Float16) in Base at float.jl:373\n[7] +(x::Float32, y::Float32) in Base at float.jl:375\n[8] +(x::Float64, y::Float64) in Base at float.jl:376\n[9] +(z::Complex{Bool}, x::Bool) in Base at complex.jl:228\n[10] +(z::Complex{Bool}, x::Real) in Base at complex.jl:242\n[11] +(x::Char, y::Integer) in Base at char.jl:40\n[12] +(c::BigInt, x::BigFloat) in Base.MPFR at mpfr.jl:307\n[13] +(a::BigInt, b::BigInt, c::BigInt, d::BigInt, e::BigInt) in Base.GMP at gmp.jl:392\n[14] +(a::BigInt, b::BigInt, c::BigInt, d::BigInt) in Base.GMP at gmp.jl:391\n[15] +(a::BigInt, b::BigInt, c::BigInt) in Base.GMP at gmp.jl:390\n[16] +(x::BigInt, y::BigInt) in Base.GMP at gmp.jl:361\n[17] +(x::BigInt, c::Union{UInt16, UInt32, UInt64, UInt8}) in Base.GMP at gmp.jl:398\n...\n[180] +(a, b, c, xs...) in Base at operators.jl:424","category":"page"},{"location":"manual/methods/","page":"方法","title":"方法","text":"多重分派和灵活的参数类型系统让Julia有能力抽象地表达高层级算法,而与实现细节解耦,也能生成高效而专用的代码来在运行中处理每个情况。","category":"page"},{"location":"manual/methods/#man-ambiguities","page":"方法","title":"方法歧义","text":"","category":"section"},{"location":"manual/methods/","page":"方法","title":"方法","text":"在一系列的函数方法定义时有可能没有单独的最专用的方法能适用于参数的某些组合:","category":"page"},{"location":"manual/methods/","page":"方法","title":"方法","text":"julia> g(x::Float64, y) = 2x + y\ng (generic function with 1 method)\n\njulia> g(x, y::Float64) = x + 2y\ng (generic function with 2 methods)\n\njulia> g(2.0, 3)\n7.0\n\njulia> g(2, 3.0)\n8.0\n\njulia> g(2.0, 3.0)\nERROR: MethodError: g(::Float64, ::Float64) is ambiguous. Candidates:\n g(x::Float64, y) in Main at none:1\n g(x, y::Float64) in Main at none:1\nPossible fix, define\n g(::Float64, ::Float64)","category":"page"},{"location":"manual/methods/","page":"方法","title":"方法","text":"这里g(2.0,3.0)的调用使用g(Float64, Any)和g(Any, Float64)都能处理,并且两个都不更加专用。在这样的情况下,Julia会扔出MethodError而非任意选择一个方法。你可以通过对交叉情况指定一个合适的方法来避免方法歧义:","category":"page"},{"location":"manual/methods/","page":"方法","title":"方法","text":"julia> g(x::Float64, y::Float64) = 2x + 2y\ng (generic function with 3 methods)\n\njulia> g(2.0, 3)\n7.0\n\njulia> g(2, 3.0)\n8.0\n\njulia> g(2.0, 3.0)\n10.0","category":"page"},{"location":"manual/methods/","page":"方法","title":"方法","text":"建议先定义没有歧义的方法,因为不这样的话,歧义就会存在,即使是暂时性的,直到更加专用的方法被定义。","category":"page"},{"location":"manual/methods/","page":"方法","title":"方法","text":"在更加复杂的情况下,解决方法歧义会会涉及到设计的某一个元素;这个主题将会在下面进行进一步的探索。","category":"page"},{"location":"manual/methods/#参数方法","page":"方法","title":"参数方法","text":"","category":"section"},{"location":"manual/methods/","page":"方法","title":"方法","text":"方法定义可以视需要存在限定特征的类型参数:","category":"page"},{"location":"manual/methods/","page":"方法","title":"方法","text":"julia> same_type(x::T, y::T) where {T} = true\nsame_type (generic function with 1 method)\n\njulia> same_type(x,y) = false\nsame_type (generic function with 2 methods)","category":"page"},{"location":"manual/methods/","page":"方法","title":"方法","text":"第一个方法应用于两个参数都是同一个具体类型时,不管类型是什么,而第二个方法接受一切,涉及其他所有情况。所以,总得来说,这个定义了一个布尔函数来检查两个参数是否是同样的类型:","category":"page"},{"location":"manual/methods/","page":"方法","title":"方法","text":"julia> same_type(1, 2)\ntrue\n\njulia> same_type(1, 2.0)\nfalse\n\njulia> same_type(1.0, 2.0)\ntrue\n\njulia> same_type(\"foo\", 2.0)\nfalse\n\njulia> same_type(\"foo\", \"bar\")\ntrue\n\njulia> same_type(Int32(1), Int64(2))\nfalse","category":"page"},{"location":"manual/methods/","page":"方法","title":"方法","text":"这样的定义对应着那些类型签名是 UnionAll 类型的方法(参见 UnionAll 类型)。","category":"page"},{"location":"manual/methods/","page":"方法","title":"方法","text":"在Julia中这种通过分派进行函数行为的定义是十分常见的,甚至是惯用的。方法类型参数并不局限于用作参数的类型:他们可以用在任意地方,只要值会在函数或者函数体的特征中。这里有个例子,例子中方法类型参数T用作方法特征中的参数类型Vector{T}的类型参数:","category":"page"},{"location":"manual/methods/","page":"方法","title":"方法","text":"julia> myappend(v::Vector{T}, x::T) where {T} = [v..., x]\nmyappend (generic function with 1 method)\n\njulia> myappend([1,2,3],4)\n4-element Vector{Int64}:\n 1\n 2\n 3\n 4\n\njulia> myappend([1,2,3],2.5)\nERROR: MethodError: no method matching myappend(::Vector{Int64}, ::Float64)\nClosest candidates are:\n myappend(::Vector{T}, !Matched::T) where T at none:1\nStacktrace:\n[...]\n\njulia> myappend([1.0,2.0,3.0],4.0)\n4-element Vector{Float64}:\n 1.0\n 2.0\n 3.0\n 4.0\n\njulia> myappend([1.0,2.0,3.0],4)\nERROR: MethodError: no method matching myappend(::Vector{Float64}, ::Int64)\nClosest candidates are:\n myappend(::Vector{T}, !Matched::T) where T at none:1\nStacktrace:\n[...]","category":"page"},{"location":"manual/methods/","page":"方法","title":"方法","text":"如你所看到的,追加的元素的类型必须匹配它追加到的向量的元素类型,否则会引起MethodError。在下面的例子中,方法类型参量T用作返回值:","category":"page"},{"location":"manual/methods/","page":"方法","title":"方法","text":"julia> mytypeof(x::T) where {T} = T\nmytypeof (generic function with 1 method)\n\njulia> mytypeof(1)\nInt64\n\njulia> mytypeof(1.0)\nFloat64","category":"page"},{"location":"manual/methods/","page":"方法","title":"方法","text":"就像你能在类型声明时通过类型参数对子类型进行约束一样(参见参数类型),你也可以约束方法的类型参数:","category":"page"},{"location":"manual/methods/","page":"方法","title":"方法","text":"julia> same_type_numeric(x::T, y::T) where {T<:Number} = true\nsame_type_numeric (generic function with 1 method)\n\njulia> same_type_numeric(x::Number, y::Number) = false\nsame_type_numeric (generic function with 2 methods)\n\njulia> same_type_numeric(1, 2)\ntrue\n\njulia> same_type_numeric(1, 2.0)\nfalse\n\njulia> same_type_numeric(1.0, 2.0)\ntrue\n\njulia> same_type_numeric(\"foo\", 2.0)\nERROR: MethodError: no method matching same_type_numeric(::String, ::Float64)\nClosest candidates are:\n same_type_numeric(!Matched::T, ::T) where T<:Number at none:1\n same_type_numeric(!Matched::Number, ::Number) at none:1\n\njulia> same_type_numeric(\"foo\", \"bar\")\nERROR: MethodError: no method matching same_type_numeric(::String, ::String)\n\njulia> same_type_numeric(Int32(1), Int64(2))\nfalse","category":"page"},{"location":"manual/methods/","page":"方法","title":"方法","text":"same_type_numeric函数的行为与上面定义的same_type函数基本相似,但是它只对一对数定义。","category":"page"},{"location":"manual/methods/","page":"方法","title":"方法","text":"参数方法允许与 where 表达式同样的语法用来写类型(参见 UnionAll 类型)。如果只有一个参数,封闭的大括号(在 where {T} 中)可以省略,但是为了清楚起见推荐写上。多个参数可以使用逗号隔开,例如 where {T, S <: Real},或者使用嵌套的 where 来写,例如 where S<:Real where T。","category":"page"},{"location":"manual/methods/#重定义方法","page":"方法","title":"重定义方法","text":"","category":"section"},{"location":"manual/methods/","page":"方法","title":"方法","text":"当重定义一个方法或者增加一个方法时,知道这个变化不会立即生效很重要。这是Julia能够静态推断和编译代码使其运行很快而没有惯常的JIT技巧和额外开销的关键。实际上,任意新的方法定义不会对当前运行环境可见,包括Tasks和线程(和所有的之前定义的@generated函数)。让我们通过一个例子说明这意味着什么:","category":"page"},{"location":"manual/methods/","page":"方法","title":"方法","text":"julia> function tryeval()\n @eval newfun() = 1\n newfun()\n end\ntryeval (generic function with 1 method)\n\njulia> tryeval()\nERROR: MethodError: no method matching newfun()\nThe applicable method may be too new: running in world age xxxx1, while current world is xxxx2.\nClosest candidates are:\n newfun() at none:1 (method too new to be called from this world context.)\n in tryeval() at none:1\n ...\n\njulia> newfun()\n1","category":"page"},{"location":"manual/methods/","page":"方法","title":"方法","text":"在这个例子中看到newfun的新定义已经被创建,但是并不能立即调用。新的全局变量立即对tryeval函数可见,所以你可以写return newfun(没有小括号)。但是你,你的调用器,和他们调用的函数等等都不能调用这个新的方法定义!","category":"page"},{"location":"manual/methods/","page":"方法","title":"方法","text":"但是这里有个例外:之后的在 REPL 中的 newfun 的调用会按照预期工作,能够见到并调用newfun 的新定义。","category":"page"},{"location":"manual/methods/","page":"方法","title":"方法","text":"但是,之后的 tryeval 的调用将会继续看到 newfun 的定义,因为该定义位于 REPL 的前一个语句中并因此在之后的 tryeval 的调用之前。","category":"page"},{"location":"manual/methods/","page":"方法","title":"方法","text":"你可以试试这个来让自己了解这是如何工作的。","category":"page"},{"location":"manual/methods/","page":"方法","title":"方法","text":"这个行为的实现通过一个「world age 计数器」。这个单调递增的值会跟踪每个方法定义操作。此计数器允许用单个数字描述「对于给定运行时环境可见的方法定义集」,或者说「world age」。它还允许仅仅通过其序数值来比较在两个 world 中可用的方法。在上例中,我们看到(方法 newfun 所存在的)「current world」比局部于任务的「runtime world」大一,后者在 tryeval 开始执行时是固定的。","category":"page"},{"location":"manual/methods/","page":"方法","title":"方法","text":"有时规避这个是必要的(例如,如果你在实现上面的REPL)。幸运的是这里有个简单地解决方法:使用Base.invokelatest调用函数:","category":"page"},{"location":"manual/methods/","page":"方法","title":"方法","text":"julia> function tryeval2()\n @eval newfun2() = 2\n Base.invokelatest(newfun2)\n end\ntryeval2 (generic function with 1 method)\n\njulia> tryeval2()\n2","category":"page"},{"location":"manual/methods/","page":"方法","title":"方法","text":"最后,让我们看一些这个规则生效的更复杂的例子。 定义一个函数f(x),最开始有一个方法:","category":"page"},{"location":"manual/methods/","page":"方法","title":"方法","text":"julia> f(x) = \"original definition\"\nf (generic function with 1 method)","category":"page"},{"location":"manual/methods/","page":"方法","title":"方法","text":"开始一些使用f(x)的运算:","category":"page"},{"location":"manual/methods/","page":"方法","title":"方法","text":"julia> g(x) = f(x)\ng (generic function with 1 method)\n\njulia> t = @async f(wait()); yield();","category":"page"},{"location":"manual/methods/","page":"方法","title":"方法","text":"现在我们给f(x)加上一些新的方法:","category":"page"},{"location":"manual/methods/","page":"方法","title":"方法","text":"julia> f(x::Int) = \"definition for Int\"\nf (generic function with 2 methods)\n\njulia> f(x::Type{Int}) = \"definition for Type{Int}\"\nf (generic function with 3 methods)","category":"page"},{"location":"manual/methods/","page":"方法","title":"方法","text":"比较一下这些结果如何不同:","category":"page"},{"location":"manual/methods/","page":"方法","title":"方法","text":"julia> f(1)\n\"definition for Int\"\n\njulia> g(1)\n\"definition for Int\"\n\njulia> fetch(schedule(t, 1))\n\"original definition\"\n\njulia> t = @async f(wait()); yield();\n\njulia> fetch(schedule(t, 1))\n\"definition for Int\"","category":"page"},{"location":"manual/methods/#使用参数方法设计样式","page":"方法","title":"使用参数方法设计样式","text":"","category":"section"},{"location":"manual/methods/","page":"方法","title":"方法","text":"虽然复杂的分派逻辑对于性能或者可用性并不是必须的,但是有时这是表达某些算法的最好的方法。 这里有一些常见的设计样式,在以这个方法使用分派时有时会出现。","category":"page"},{"location":"manual/methods/#从超类型中提取出类型参数","page":"方法","title":"从超类型中提取出类型参数","text":"","category":"section"},{"location":"manual/methods/","page":"方法","title":"方法","text":"以下是一个正确的代码模板,用于返回具有明确定义的元素类型的 AbstractArray 的任意子类型的元素类型 T:","category":"page"},{"location":"manual/methods/","page":"方法","title":"方法","text":"abstract type AbstractArray{T, N} end\neltype(::Type{<:AbstractArray{T}}) where {T} = T","category":"page"},{"location":"manual/methods/","page":"方法","title":"方法","text":"使用所谓的三角派发。 请注意,UnionAll 类型,对于示例eltype(AbstractArray{T} where T <: Integer),与上述方法不符。 在这种情况下,Base 中 eltype 的实现为 Any 增加了一个回退方法。","category":"page"},{"location":"manual/methods/","page":"方法","title":"方法","text":"一个常见的错误是试着使用内省来得到元素类型:","category":"page"},{"location":"manual/methods/","page":"方法","title":"方法","text":"eltype_wrong(::Type{A}) where {A<:AbstractArray} = A.parameters[1]","category":"page"},{"location":"manual/methods/","page":"方法","title":"方法","text":"但是创建一个这个方法会失败的情况不难:","category":"page"},{"location":"manual/methods/","page":"方法","title":"方法","text":"struct BitVector <: AbstractArray{Bool, 1}; end","category":"page"},{"location":"manual/methods/","page":"方法","title":"方法","text":"这里我们已经创建了一个没有参数的类型BitVector,但是元素类型已经完全指定了,T等于Bool!","category":"page"},{"location":"manual/methods/","page":"方法","title":"方法","text":"另一个错误是尝试使用 supertype 沿着类型层次结构向上走:","category":"page"},{"location":"manual/methods/","page":"方法","title":"方法","text":"eltype_wrong(::Type{AbstractArray{T}}) where {T} = T\neltype_wrong(::Type{AbstractArray{T, N}}) where {T, N} = T\neltype_wrong(::Type{A}) where {A<:AbstractArray} = eltype_wrong(supertype(A))","category":"page"},{"location":"manual/methods/","page":"方法","title":"方法","text":"虽然这适用于声明的类型,但对于不适用于没有超类型的类型:","category":"page"},{"location":"manual/methods/","page":"方法","title":"方法","text":"julia> eltype_wrong(Union{AbstractArray{Int}, AbstractArray{Float64}})\nERROR: MethodError: no method matching supertype(::Type{Union{AbstractArray{Float64,N} where N, AbstractArray{Int64,N} where N}})\nClosest candidates are:\n supertype(::DataType) at operators.jl:43\n supertype(::UnionAll) at operators.jl:48","category":"page"},{"location":"manual/methods/#用不同的类型参数构建相似的类型","page":"方法","title":"用不同的类型参数构建相似的类型","text":"","category":"section"},{"location":"manual/methods/","page":"方法","title":"方法","text":"当构建通用代码时,通常需要创建一些类似对象,在类型的布局上有一些变化,这就也让类型参数的变化变得必要。 例如,你会有一些任意元素类型的抽象数组,想使用特定的元素类型来编写你基于它的计算。你必须实现为每个AbstractArray{T}的子类型实现方法,这些方法描述了如何计算类型转换。从一个子类型转化成拥有一个不同参数的另一个子类型的通用方法在这里不存在。(快速复习:你明白为什么吗?)","category":"page"},{"location":"manual/methods/","page":"方法","title":"方法","text":"AbstractArray的子类型典型情况下会实现两个方法来完成这个: 一个方法把输入输入转换成特定的AbstractArray{T,N}抽象类型的子类型;一个方法用特定的元素类型构建一个新的未初始化的数组。这些的样例实现可以在Julia Base里面找到。这里是一个基础的样例使用,保证输入与输出是同一种类型:","category":"page"},{"location":"manual/methods/","page":"方法","title":"方法","text":"input = convert(AbstractArray{Eltype}, input)\noutput = similar(input, Eltype)","category":"page"},{"location":"manual/methods/","page":"方法","title":"方法","text":"作为这个的扩展,在算法需要输入数组的拷贝的情况下,convert使无法胜任的,因为返回值可能只是原始输入的别名。把similar(构建输出数组)和copyto!(用输入数据填满)结合起来是需要给出输入参数的可变拷贝的一个范用方法:","category":"page"},{"location":"manual/methods/","page":"方法","title":"方法","text":"copy_with_eltype(input, Eltype) = copyto!(similar(input, Eltype), input)","category":"page"},{"location":"manual/methods/#迭代分派","page":"方法","title":"迭代分派","text":"","category":"section"},{"location":"manual/methods/","page":"方法","title":"方法","text":"为了分派一个多层的参数参量列表,将每一层分派分开到不同的函数中常常是最好的。这可能听起来跟单分派的方法相似,但是你会在下面见到,这个更加灵活。","category":"page"},{"location":"manual/methods/","page":"方法","title":"方法","text":"例如,尝试按照数组的元素类型进行分派常常会引起歧义。相反地,常见的代码会首先按照容易类型分派,然后基于eltype递归到更加更加专用的方法。在大部分情况下,算法会很方便地就屈从与这个分层方法,在其他情况下,这种严苛的工作必须手动解决。这个分派分支能被观察到,例如在两个矩阵的加法的逻辑中:","category":"page"},{"location":"manual/methods/","page":"方法","title":"方法","text":"# 首先分派选择了逐元素相加的map算法。\n+(a::Matrix, b::Matrix) = map(+, a, b)\n# 然后分派处理了每个元素然后选择了计算的\n# 恰当的常见元素类型。\n+(a, b) = +(promote(a, b)...)\n# 一旦元素有了相同类型,它们就可以相加。\n# 例如,通过处理器暴露出的原始运算。\n+(a::Float64, b::Float64) = Core.add(a, b)","category":"page"},{"location":"manual/methods/#基于-Trait-的分派","page":"方法","title":"基于 Trait 的分派","text":"","category":"section"},{"location":"manual/methods/","page":"方法","title":"方法","text":"对于上面的可迭代分派的一个自然扩展是给方法选择加一个内涵层,这个层允许按照那些与类型层级定义的集合相独立的类型的集合来分派。我们可以通过写出问题中的类型的一个Union来创建这个一个集合,但是这不能够扩展,因为Union类型在创建之后无法改变。但是这么一个可扩展的集合可以通过一个叫做\"Holy-trait\"的一个设计样式来实现。","category":"page"},{"location":"manual/methods/","page":"方法","title":"方法","text":"这个样式是通过定义一个范用函数来实现,这个函数为函数参数可能属于的每个trait集合都计算出不同的单例值(或者类型)。如果这个函数是单纯的,这与通常的分派对于性能没有任何影响。","category":"page"},{"location":"manual/methods/","page":"方法","title":"方法","text":"上一部分中的示例掩盖了 map 和 promote 的实现细节,这两个都是依据trait来进行运算的。 在迭代矩阵时,例如在 map 的实现中,一个重要的问题是使用什么顺序遍历数据。 当 AbstractArray 子类型实现 Base.IndexStyle trait 时,map 等其他函数可以根据此信息进行派发以选择最佳算法(请参阅 [抽象数组接口](@ref man-interface-array))。这意味着每个子类型不需要实现map的自定义版本,因为通用定义+trait类将使系统能够选择最快的版本。 下面是 map 的一个简单实现,说明了基于 trait 的调度:","category":"page"},{"location":"manual/methods/","page":"方法","title":"方法","text":"map(f, a::AbstractArray, b::AbstractArray) = map(Base.IndexStyle(a, b), f, a, b)\n# generic implementation:\nmap(::Base.IndexCartesian, f, a::AbstractArray, b::AbstractArray) = ...\n# linear-indexing implementation (faster)\nmap(::Base.IndexLinear, f, a::AbstractArray, b::AbstractArray) = ...","category":"page"},{"location":"manual/methods/","page":"方法","title":"方法","text":"这个基于trait的方法也出现在promote机制中,被标量+使用。 它使用了promote_type,这在知道两个计算对象的类型的情况下返回计算这个运算的最佳的常用类型。这就使得我们不用为每一对可能的类型参数实现每一个函数,而把问题简化为对于每个类型实现一个类型转换运算这样一个小很多的问题,还有一个优选的逐对的类型提升规则的表格。","category":"page"},{"location":"manual/methods/#输出类型计算","page":"方法","title":"输出类型计算","text":"","category":"section"},{"location":"manual/methods/","page":"方法","title":"方法","text":"基于trait的类型提升的讨论可以过渡到我们的下一个设计样式:为矩阵运算计算输出元素类型。","category":"page"},{"location":"manual/methods/","page":"方法","title":"方法","text":"为了实现像加法这样的原始运算,我们使用promote_type函数来计算想要的输出类型。(像之前一样,我们在+调用中的promote调用中见到了这个工作)。","category":"page"},{"location":"manual/methods/","page":"方法","title":"方法","text":"对于矩阵的更加复杂的函数,对于更加复杂的运算符序列来计算预期的返回类型是必要的。这经常按下列步骤进行:","category":"page"},{"location":"manual/methods/","page":"方法","title":"方法","text":"编写一个小函数op来表示算法核心中使用的运算的集合。\n使用promote_op(op, argument_types...)计算结果矩阵的元素类型R, 这里argument_types是通过应用到每个输入数组的eltype计算的。\n创建类似于similar(R, dims)的输出矩阵,这里dims是输出矩阵的预期维度数。","category":"page"},{"location":"manual/methods/","page":"方法","title":"方法","text":"作为一个更加具体的例子,一个范用的方阵乘法的伪代码是:","category":"page"},{"location":"manual/methods/","page":"方法","title":"方法","text":"function matmul(a::AbstractMatrix, b::AbstractMatrix)\n op = (ai, bi) -> ai * bi + ai * bi\n\n ## this is insufficient because it assumes `one(eltype(a))` is constructable:\n # R = typeof(op(one(eltype(a)), one(eltype(b))))\n\n ## this fails because it assumes `a[1]` exists and is representative of all elements of the array\n # R = typeof(op(a[1], b[1]))\n\n ## this is incorrect because it assumes that `+` calls `promote_type`\n ## but this is not true for some types, such as Bool:\n # R = promote_type(ai, bi)\n\n # this is wrong, since depending on the return value\n # of type-inference is very brittle (as well as not being optimizable):\n # R = Base.return_types(op, (eltype(a), eltype(b)))\n\n ## but, finally, this works:\n R = promote_op(op, eltype(a), eltype(b))\n ## although sometimes it may give a larger type than desired\n ## it will always give a correct type\n\n output = similar(b, R, (size(a, 1), size(b, 2)))\n if size(a, 2) > 0\n for j in 1:size(b, 2)\n for i in 1:size(a, 1)\n ## here we don't use `ab = zero(R)`,\n ## since `R` might be `Any` and `zero(Any)` is not defined\n ## we also must declare `ab::R` to make the type of `ab` constant in the loop,\n ## since it is possible that typeof(a * b) != typeof(a * b + a * b) == R\n ab::R = a[i, 1] * b[1, j]\n for k in 2:size(a, 2)\n ab += a[i, k] * b[k, j]\n end\n output[i, j] = ab\n end\n end\n end\n return output\nend","category":"page"},{"location":"manual/methods/#分离转换和内核逻辑","page":"方法","title":"分离转换和内核逻辑","text":"","category":"section"},{"location":"manual/methods/","page":"方法","title":"方法","text":"能有效减少编译时间和测试复杂度的一个方法是将预期的类型和计算转换的逻辑隔离。这会让编译器将与大型内核的其他部分相独立的类型转换逻辑特别化并内联。","category":"page"},{"location":"manual/methods/","page":"方法","title":"方法","text":"将更大的类型类转换成被算法实际支持的特定参数类是一个常见的设计样式:","category":"page"},{"location":"manual/methods/","page":"方法","title":"方法","text":"complexfunction(arg::Int) = ...\ncomplexfunction(arg::Any) = complexfunction(convert(Int, arg))\n\nmatmul(a::T, b::T) = ...\nmatmul(a, b) = matmul(promote(a, b)...)","category":"page"},{"location":"manual/methods/#参数化约束的可变参数方法","page":"方法","title":"参数化约束的可变参数方法","text":"","category":"section"},{"location":"manual/methods/","page":"方法","title":"方法","text":"函数参数也可以用于约束应用于\"可变参数\"函数(变参函数)的参数的数量。Vararg{T,N} 可用于表明这么一个约束。举个例子:","category":"page"},{"location":"manual/methods/","page":"方法","title":"方法","text":"julia> bar(a,b,x::Vararg{Any,2}) = (a,b,x)\nbar (generic function with 1 method)\n\njulia> bar(1,2,3)\nERROR: MethodError: no method matching bar(::Int64, ::Int64, ::Int64)\nClosest candidates are:\n bar(::Any, ::Any, ::Any, !Matched::Any) at none:1\n\njulia> bar(1,2,3,4)\n(1, 2, (3, 4))\n\njulia> bar(1,2,3,4,5)\nERROR: MethodError: no method matching bar(::Int64, ::Int64, ::Int64, ::Int64, ::Int64)\nClosest candidates are:\n bar(::Any, ::Any, ::Any, ::Any) at none:1","category":"page"},{"location":"manual/methods/","page":"方法","title":"方法","text":"更加有用的是,用一个参数就约束可变参数的方法是可能的。例如:","category":"page"},{"location":"manual/methods/","page":"方法","title":"方法","text":"function getindex(A::AbstractArray{T,N}, indices::Vararg{Number,N}) where {T,N}","category":"page"},{"location":"manual/methods/","page":"方法","title":"方法","text":"只会在indices的个数与数组的维数相同时才会调用。","category":"page"},{"location":"manual/methods/","page":"方法","title":"方法","text":"当只有提供的参数的类型需要被约束时,Vararg{T}可以写成T...。例如f(x::Int...) = x是f(x::Vararg{Int}) = x的简便写法。","category":"page"},{"location":"manual/methods/#可选参数和关键字的参数的注意事项","page":"方法","title":"可选参数和关键字的参数的注意事项","text":"","category":"section"},{"location":"manual/methods/","page":"方法","title":"方法","text":"与在函数中简要提到的一样,可选参数是使用多方法定义语法来实现的。例如,这个定义:","category":"page"},{"location":"manual/methods/","page":"方法","title":"方法","text":"f(a=1,b=2) = a+2b","category":"page"},{"location":"manual/methods/","page":"方法","title":"方法","text":"翻译成下列三个方法:","category":"page"},{"location":"manual/methods/","page":"方法","title":"方法","text":"f(a,b) = a+2b\nf(a) = f(a,2)\nf() = f(1,2)","category":"page"},{"location":"manual/methods/","page":"方法","title":"方法","text":"这就意味着调用f()等于调用f(1,2)。在这个情况下结果是5,因为f(1,2)使用的是上面f的第一个方法。但是,不总是需要是这种情况。如果你定义了第四个对于整数更加专用的方法:","category":"page"},{"location":"manual/methods/","page":"方法","title":"方法","text":"f(a::Int,b::Int) = a-2b","category":"page"},{"location":"manual/methods/","page":"方法","title":"方法","text":"此时f()和f(1,2)的结果都是-3。换句话说,可选参数只与函数捆绑,而不是函数的任意一个特定的方法。这个决定于使用的方法的可选参数的类型。当可选参数是用全局变量的形式定义时,可选参数的类型甚至会在运行时改变。","category":"page"},{"location":"manual/methods/","page":"方法","title":"方法","text":"关键字参数与普通的位置参数的行为很不一样。特别地,他们不参与到方法分派中。方法只基于位置参数分派,在匹配得方法确定之后关键字参数才会被处理。","category":"page"},{"location":"manual/methods/#类函数对象","page":"方法","title":"类函数对象","text":"","category":"section"},{"location":"manual/methods/","page":"方法","title":"方法","text":"方法与类型相关,所以可以通过给类型加方法使得任意一个Julia类型变得\"可被调用\"。(这个\"可调用\"的对象有时称为\"函子\"。)","category":"page"},{"location":"manual/methods/","page":"方法","title":"方法","text":"例如,你可以定义一个类型,存储着多项式的系数,但是行为像是一个函数,可以为多项式求值:","category":"page"},{"location":"manual/methods/","page":"方法","title":"方法","text":"julia> struct Polynomial{R}\n coeffs::Vector{R}\n end\n\njulia> function (p::Polynomial)(x)\n v = p.coeffs[end]\n for i = (length(p.coeffs)-1):-1:1\n v = v*x + p.coeffs[i]\n end\n return v\n end\n\njulia> (p::Polynomial)() = p(5)","category":"page"},{"location":"manual/methods/","page":"方法","title":"方法","text":"注意函数是通过类型而非名字来指定的。如同普通函数一样这里有一个简洁的语法形式。在函数体内,p会指向被调用的对象。Polynomial会按如下方式使用:","category":"page"},{"location":"manual/methods/","page":"方法","title":"方法","text":"julia> p = Polynomial([1,10,100])\nPolynomial{Int64}([1, 10, 100])\n\njulia> p(3)\n931\n\njulia> p()\n2551","category":"page"},{"location":"manual/methods/","page":"方法","title":"方法","text":"这个机制也是Julia中类型构造函数和闭包(指向其环境的内部函数)的工作原理。","category":"page"},{"location":"manual/methods/#空泛型函数","page":"方法","title":"空泛型函数","text":"","category":"section"},{"location":"manual/methods/","page":"方法","title":"方法","text":"有时引入一个没有添加方法的范用函数是有用的。这会用于分离实现与接口定义。这也可为了文档或者代码可读性。为了这个的语法是没有参数组的一个空函数块:","category":"page"},{"location":"manual/methods/","page":"方法","title":"方法","text":"function emptyfunc end","category":"page"},{"location":"manual/methods/#man-method-design-ambiguities","page":"方法","title":"方法设计与避免歧义","text":"","category":"section"},{"location":"manual/methods/","page":"方法","title":"方法","text":"Julia的方法多态性是其最有力的特性之一,利用这个功能会带来设计上的挑战。特别地,在更加复杂的方法层级中出现歧义不能说不常见。","category":"page"},{"location":"manual/methods/","page":"方法","title":"方法","text":"在上面我们曾经指出我们可以像这样解决歧义","category":"page"},{"location":"manual/methods/","page":"方法","title":"方法","text":"f(x, y::Int) = 1\nf(x::Int, y) = 2","category":"page"},{"location":"manual/methods/","page":"方法","title":"方法","text":"靠定义一个方法","category":"page"},{"location":"manual/methods/","page":"方法","title":"方法","text":"f(x::Int, y::Int) = 3","category":"page"},{"location":"manual/methods/","page":"方法","title":"方法","text":"这通常是正确的方案; 然而,在某些情况下,盲目地遵循这一建议可能会适得其反。 特别是,泛型函数的方法越多,产生歧义的可能性就越大。 当方法层次结构变得比这个简单的示例更复杂时,仔细考虑替代策略可能是值得的。","category":"page"},{"location":"manual/methods/","page":"方法","title":"方法","text":"下面我们会讨论特别的一些挑战和解决这些挑战的一些可选方法。","category":"page"},{"location":"manual/methods/#元组和N元组参数","page":"方法","title":"元组和N元组参数","text":"","category":"section"},{"location":"manual/methods/","page":"方法","title":"方法","text":"Tuple(和NTuple)参数会带来特别的挑战。例如,","category":"page"},{"location":"manual/methods/","page":"方法","title":"方法","text":"f(x::NTuple{N,Int}) where {N} = 1\nf(x::NTuple{N,Float64}) where {N} = 2","category":"page"},{"location":"manual/methods/","page":"方法","title":"方法","text":"是有歧义的,因为存在N == 0的可能性:没有元素去确定Int还是Float64变体应该被调用。为了解决歧义,一个方法是为空元组定义方法:","category":"page"},{"location":"manual/methods/","page":"方法","title":"方法","text":"f(x::Tuple{}) = 3","category":"page"},{"location":"manual/methods/","page":"方法","title":"方法","text":"作为一种选择,对于其中一个方法之外的所有的方法可以坚持元组中至少有一个元素:","category":"page"},{"location":"manual/methods/","page":"方法","title":"方法","text":"f(x::NTuple{N,Int}) where {N} = 1 # this is the fallback\nf(x::Tuple{Float64, Vararg{Float64}}) = 2 # this requires at least one Float64","category":"page"},{"location":"manual/methods/#man-methods-orthogonalize","page":"方法","title":"正交化你的设计","text":"","category":"section"},{"location":"manual/methods/","page":"方法","title":"方法","text":"当你打算根据两个或更多的参数进行分派时,考虑一下,一个「包裹」函数是否会让设计简单一些。举个例子,与其编写多变量:","category":"page"},{"location":"manual/methods/","page":"方法","title":"方法","text":"f(x::A, y::A) = ...\nf(x::A, y::B) = ...\nf(x::B, y::A) = ...\nf(x::B, y::B) = ...","category":"page"},{"location":"manual/methods/","page":"方法","title":"方法","text":"不如考虑定义","category":"page"},{"location":"manual/methods/","page":"方法","title":"方法","text":"f(x::A, y::A) = ...\nf(x, y) = f(g(x), g(y))","category":"page"},{"location":"manual/methods/","page":"方法","title":"方法","text":"这里g把参数转变为类型A。这是更加普遍的正交设计原理的一个特别特殊的例子,在正交设计中不同的概念被分配到不同的方法中去。这里g最可能需要一个fallback定义","category":"page"},{"location":"manual/methods/","page":"方法","title":"方法","text":"g(x::A) = x","category":"page"},{"location":"manual/methods/","page":"方法","title":"方法","text":"一个相关的方案使用promote来把x和y变成常见的类型:","category":"page"},{"location":"manual/methods/","page":"方法","title":"方法","text":"f(x::T, y::T) where {T} = ...\nf(x, y) = f(promote(x, y)...)","category":"page"},{"location":"manual/methods/","page":"方法","title":"方法","text":"这个设计的一个隐患是:如果没有合适的把 x 和 y 转换到同样类型的类型提升方法,第二个方法就可能无限自递归然后引发堆溢出。","category":"page"},{"location":"manual/methods/#一次只根据一个参数分派","page":"方法","title":"一次只根据一个参数分派","text":"","category":"section"},{"location":"manual/methods/","page":"方法","title":"方法","text":"如果你你需要根据多个参数进行分派,并且有太多的为了能定义所有可能的变量而存在的组合,而存在很多回退函数,你可以考虑引入\"名字级联\",这里(例如)你根据第一个参数分配然后调用一个内部的方法:","category":"page"},{"location":"manual/methods/","page":"方法","title":"方法","text":"f(x::A, y) = _fA(x, y)\nf(x::B, y) = _fB(x, y)","category":"page"},{"location":"manual/methods/","page":"方法","title":"方法","text":"接着内部方法_fA和_fB可以根据y进行分派,而不考虑有关x的歧义存在。","category":"page"},{"location":"manual/methods/","page":"方法","title":"方法","text":"需要意识到这个方案至少有一个主要的缺点:在很多情况下,用户没有办法通过进一步定义你的输出函数f的具体行为来进一步定制f的行为。相反,他们需要去定义你的内部方法_fA和_fB的具体行为,这会模糊输出方法和内部方法之间的界线。","category":"page"},{"location":"manual/methods/#抽象容器与元素类型","page":"方法","title":"抽象容器与元素类型","text":"","category":"section"},{"location":"manual/methods/","page":"方法","title":"方法","text":"在可能的情况下要试图避免定义根据抽象容器的具体元素类型来分派的方法。举个例子,","category":"page"},{"location":"manual/methods/","page":"方法","title":"方法","text":"-(A::AbstractArray{T}, b::Date) where {T<:Date}","category":"page"},{"location":"manual/methods/","page":"方法","title":"方法","text":"会引起歧义,当定义了这个方法:","category":"page"},{"location":"manual/methods/","page":"方法","title":"方法","text":"-(A::MyArrayType{T}, b::T) where {T}","category":"page"},{"location":"manual/methods/","page":"方法","title":"方法","text":"最好的方法是不要定义这些方法中的任何一个。相反,使用范用方法-(A::AbstractArray, b)并确认这个方法是使用分别对于每个容器类型和元素类型都是适用的通用调用(像similar和-)实现的。这只是建议正交化你的方法的一个更加复杂的变种而已。","category":"page"},{"location":"manual/methods/","page":"方法","title":"方法","text":"当这个方法不可行时,这就值得与其他开发者开始讨论如果解决歧义;只是因为一个函数先定义并不总是意味着他不能改变或者被移除。作为最后一个手段,开发者可以定义\"创可贴\"方法","category":"page"},{"location":"manual/methods/","page":"方法","title":"方法","text":"-(A::MyArrayType{T}, b::Date) where {T<:Date} = ...","category":"page"},{"location":"manual/methods/","page":"方法","title":"方法","text":"可以暴力解决歧义。","category":"page"},{"location":"manual/methods/#与默认参数的复杂方法\"级联\"","page":"方法","title":"与默认参数的复杂方法\"级联\"","text":"","category":"section"},{"location":"manual/methods/","page":"方法","title":"方法","text":"如果你定义了提供默认的方法\"级联\",要小心去掉对应着潜在默认的任何参数。例如,假设你在写一个数字过滤算法,你有一个通过应用padding来出来信号的边的方法:","category":"page"},{"location":"manual/methods/","page":"方法","title":"方法","text":"function myfilter(A, kernel, ::Replicate)\n Apadded = replicate_edges(A, size(kernel))\n myfilter(Apadded, kernel) # now perform the \"real\" computation\nend","category":"page"},{"location":"manual/methods/","page":"方法","title":"方法","text":"这会与提供默认padding的方法产生冲突:","category":"page"},{"location":"manual/methods/","page":"方法","title":"方法","text":"myfilter(A, kernel) = myfilter(A, kernel, Replicate()) # replicate the edge by default","category":"page"},{"location":"manual/methods/","page":"方法","title":"方法","text":"这两个方法一起会生成无限的递归,A会不断变大。","category":"page"},{"location":"manual/methods/","page":"方法","title":"方法","text":"更好的设计是像这样定义你的调用层级:","category":"page"},{"location":"manual/methods/","page":"方法","title":"方法","text":"struct NoPad end # indicate that no padding is desired, or that it's already applied\n\nmyfilter(A, kernel) = myfilter(A, kernel, Replicate()) # default boundary conditions\n\nfunction myfilter(A, kernel, ::Replicate)\n Apadded = replicate_edges(A, size(kernel))\n myfilter(Apadded, kernel, NoPad()) # indicate the new boundary conditions\nend\n\n# other padding methods go here\n\nfunction myfilter(A, kernel, ::NoPad)\n # Here's the \"real\" implementation of the core computation\nend","category":"page"},{"location":"manual/methods/","page":"方法","title":"方法","text":"NoPad 被置于与其他 padding 类型一致的参数位置上,这保持了分派层级的良好组织,同时降低了歧义的可能性。而且,它扩展了「公开」的 myfilter 接口:想要显式控制 padding 的用户可以直接调用 NoPad 变量。","category":"page"},{"location":"manual/methods/","page":"方法","title":"方法","text":"[Clarke61]: Arthur C. Clarke, Profiles of the Future (1961): Clarke's Third Law.","category":"page"},{"location":"devdocs/sanitizers/#Sanitizer-support","page":"Sanitizer support","title":"Sanitizer support","text":"","category":"section"},{"location":"devdocs/sanitizers/#General-considerations","page":"Sanitizer support","title":"General considerations","text":"","category":"section"},{"location":"devdocs/sanitizers/","page":"Sanitizer support","title":"Sanitizer support","text":"Using Clang's sanitizers obviously require you to use Clang (USECLANG=1), but there's another catch: most sanitizers require a run-time library, provided by the host compiler, while the instrumented code generated by Julia's JIT relies on functionality from that library. This implies that the LLVM version of your host compiler matches that of the LLVM library used within Julia.","category":"page"},{"location":"devdocs/sanitizers/","page":"Sanitizer support","title":"Sanitizer support","text":"An easy solution is to have an dedicated build folder for providing a matching toolchain, by building with BUILD_LLVM_CLANG=1. You can then refer to this toolchain from another build folder by specifying USECLANG=1 while overriding the CC and CXX variables.","category":"page"},{"location":"devdocs/sanitizers/","page":"Sanitizer support","title":"Sanitizer support","text":"To use one of of the sanitizers set SANITIZE=1 and then the appropriate flag for the sanitizer you want to use.","category":"page"},{"location":"devdocs/sanitizers/","page":"Sanitizer support","title":"Sanitizer support","text":"On macOS, this might need some extra flags also to work. Altogether, it might look like this, plus one or more of the SANITIZE_* flags listed below:","category":"page"},{"location":"devdocs/sanitizers/","page":"Sanitizer support","title":"Sanitizer support","text":"make -C deps USE_BINARYBUILDER_LLVM=0 LLVM_VER=svn stage-llvm\n\nmake -C src SANITIZE=1 USECLANG=1 \\\n CC=~+/deps/scratch/llvm-svn/build_Release/bin/clang \\\n CXX=~+/deps/scratch/llvm-svn/build_Release/bin/clang++ \\\n CPPFLAGS=\"-isysroot $(xcode-select -p)/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk\" \\\n CXXFLAGS=\"-isystem $(xcode-select -p)/Toolchains/XcodeDefault.xctoolchain/usr/include/c++/v1\"","category":"page"},{"location":"devdocs/sanitizers/","page":"Sanitizer support","title":"Sanitizer support","text":"(or put these into your Make.user, so you don't need to remember them every time).","category":"page"},{"location":"devdocs/sanitizers/#Address-Sanitizer-(ASAN)","page":"Sanitizer support","title":"Address Sanitizer (ASAN)","text":"","category":"section"},{"location":"devdocs/sanitizers/","page":"Sanitizer support","title":"Sanitizer support","text":"For detecting or debugging memory bugs, you can use Clang's address sanitizer (ASAN). By compiling with SANITIZE_ADDRESS=1 you enable ASAN for the Julia compiler and its generated code. In addition, you can specify LLVM_SANITIZE=1 to sanitize the LLVM library as well. Note that these options incur a high performance and memory cost. For example, using ASAN for Julia and LLVM makes testall1 takes 8-10 times as long while using 20 times as much memory (this can be reduced to respectively a factor of 3 and 4 by using the options described below).","category":"page"},{"location":"devdocs/sanitizers/","page":"Sanitizer support","title":"Sanitizer support","text":"By default, Julia sets the allow_user_segv_handler=1 ASAN flag, which is required for signal delivery to work properly. You can define other options using the ASAN_OPTIONS environment flag, in which case you'll need to repeat the default option mentioned before. For example, memory usage can be reduced by specifying fast_unwind_on_malloc=0 and malloc_context_size=2, at the cost of backtrace accuracy. For now, Julia also sets detect_leaks=0, but this should be removed in the future.","category":"page"},{"location":"devdocs/sanitizers/#Memory-Sanitizer-(MSAN)","page":"Sanitizer support","title":"Memory Sanitizer (MSAN)","text":"","category":"section"},{"location":"devdocs/sanitizers/","page":"Sanitizer support","title":"Sanitizer support","text":"For detecting use of uninitialized memory, you can use Clang's memory sanitizer (MSAN) by compiling with SANITIZE_MEMORY=1.","category":"page"},{"location":"devdocs/sanitizers/#Thread-Sanitizer-(TSAN)","page":"Sanitizer support","title":"Thread Sanitizer (TSAN)","text":"","category":"section"},{"location":"devdocs/sanitizers/","page":"Sanitizer support","title":"Sanitizer support","text":"For debugging data-races and other threading related issues you can use Clang's thread sanitizer (TSAN) by compiling with SANITIZE_THREAD=1.","category":"page"},{"location":"stdlib/Dates/#日期","page":"日期","title":"日期","text":"","category":"section"},{"location":"stdlib/Dates/","page":"日期","title":"日期","text":"DocTestSetup = :(using Dates)","category":"page"},{"location":"stdlib/Dates/","page":"日期","title":"日期","text":"Dates 模块提供了两种类型来处理日期:Date 和 DateTime,分别精确到日和毫秒;两者都是抽象类型 TimeType 的子类型。区分类型的动机很简单:不必处理更高精度所带来的复杂性时,一些操作在代码和思维推理上都更加简单。例如,由于 Date 类型仅精确到日(即没有时、分或秒),因此避免了时区、夏令时和闰秒等不必要的通常考虑。","category":"page"},{"location":"stdlib/Dates/","page":"日期","title":"日期","text":"Date 和 DateTime 类型都是基本不可变类型 Int64 的包装类。这两种类型的单个 instant 字段实际上属于 UTInstant{P} 类型。这种类型表示的是一种基于世界时间(UT)持续增长的机器时间 [1]。DateTime 类型并不考虑时区(用 Python 的话讲,它是 naive 的),与 Java 8 中的 LocalDateTime 类似。如果需要附加时区功能,可以通过 TimeZones.jl 包 实现,其汇编了来自 IANA 时区数据库 的数据。Date 和 DateTime 都基于 ISO 8601 标准,遵循公历(格里高利历)。 值得注意的是,ISO 8601 标准对公元前的日期需要特别处理。通常来说,公元前的最后一天是公元前 1 年的 12 月 31 日,接下来的一天是公元 1 年的 1 月 1 日,公元 0 年是不存在的。但是,在 ISO 8601 标准中,公元前 1 年被表示为 0 年,即 0001-01-01 的前一天是 0000-12-31,而 -0001(没错,年数为-1)的那一年则实际上是公元前 2 年,-0002 则表示公元前 3 年,以此类推。","category":"page"},{"location":"stdlib/Dates/","page":"日期","title":"日期","text":"[1]: The notion of the UT second is actually quite fundamental. There are basically two different notions of time generally accepted, one based on the physical rotation of the earth (one full rotation = 1 day), the other based on the SI second (a fixed, constant value). These are radically different! Think about it, a \"UT second\", as defined relative to the rotation of the earth, may have a different absolute length depending on the day! Anyway, the fact that Date and DateTime are based on UT seconds is a simplifying, yet honest assumption so that things like leap seconds and all their complexity can be avoided. This basis of time is formally called UT or UT1. Basing types on the UT second basically means that every minute has 60 seconds and every day has 24 hours and leads to more natural calculations when working with calendar dates.","category":"page"},{"location":"stdlib/Dates/#构造函数","page":"日期","title":"构造函数","text":"","category":"section"},{"location":"stdlib/Dates/","page":"日期","title":"日期","text":"Date 和 DateTime 类型可以通过整数或 Period 类型,解析,或调整器来构造(稍后会详细介绍):","category":"page"},{"location":"stdlib/Dates/","page":"日期","title":"日期","text":"julia> DateTime(2013)\n2013-01-01T00:00:00\n\njulia> DateTime(2013,7)\n2013-07-01T00:00:00\n\njulia> DateTime(2013,7,1)\n2013-07-01T00:00:00\n\njulia> DateTime(2013,7,1,12)\n2013-07-01T12:00:00\n\njulia> DateTime(2013,7,1,12,30)\n2013-07-01T12:30:00\n\njulia> DateTime(2013,7,1,12,30,59)\n2013-07-01T12:30:59\n\njulia> DateTime(2013,7,1,12,30,59,1)\n2013-07-01T12:30:59.001\n\njulia> Date(2013)\n2013-01-01\n\njulia> Date(2013,7)\n2013-07-01\n\njulia> Date(2013,7,1)\n2013-07-01\n\njulia> Date(Dates.Year(2013),Dates.Month(7),Dates.Day(1))\n2013-07-01\n\njulia> Date(Dates.Month(7),Dates.Year(2013))\n2013-07-01","category":"page"},{"location":"stdlib/Dates/","page":"日期","title":"日期","text":"Date or DateTime parsing is accomplished by the use of format strings. Format strings work by the notion of defining delimited or fixed-width \"slots\" that contain a period to parse and passing the text to parse and format string to a Date or DateTime constructor, of the form Date(\"2015-01-01\",dateformat\"y-m-d\") or DateTime(\"20150101\",dateformat\"yyyymmdd\").","category":"page"},{"location":"stdlib/Dates/","page":"日期","title":"日期","text":"有分隔的插入点是通过指定解析器在两个时段之间的分隔符来进行标记的。例如,\"y-m-d\" 会告诉解析器,一个诸如 \"2014-07-16\" 的时间字符串,应该在第一个和第二个插入点之间查找 - 字符。y,m 和 d 字符则告诉解析器每一个插入点对应的时段名称。","category":"page"},{"location":"stdlib/Dates/","page":"日期","title":"日期","text":"As in the case of constructors above such as Date(2013), delimited DateFormats allow for missing parts of dates and times so long as the preceding parts are given. The other parts are given the usual default values. For example, Date(\"1981-03\", dateformat\"y-m-d\") returns 1981-03-01, whilst Date(\"31/12\", dateformat\"d/m/y\") gives 0001-12-31. (Note that the default year is 1 AD/CE.) Consequently, an empty string will always return 0001-01-01 for Dates, and 0001-01-01T00:00:00.000 for DateTimes.","category":"page"},{"location":"stdlib/Dates/","page":"日期","title":"日期","text":"Fixed-width slots are specified by repeating the period character the number of times corresponding to the width with no delimiter between characters. So dateformat\"yyyymmdd\" would correspond to a date string like \"20140716\". The parser distinguishes a fixed-width slot by the absence of a delimiter, noting the transition \"yyyymm\" from one period character to the next.","category":"page"},{"location":"stdlib/Dates/","page":"日期","title":"日期","text":"Support for text-form month parsing is also supported through the u and U characters, for abbreviated and full-length month names, respectively. By default, only English month names are supported, so u corresponds to \"Jan\", \"Feb\", \"Mar\", etc. And U corresponds to \"January\", \"February\", \"March\", etc. Similar to other name=>value mapping functions dayname and monthname, custom locales can be loaded by passing in the locale=>Dict{String,Int} mapping to the MONTHTOVALUEABBR and MONTHTOVALUE dicts for abbreviated and full-name month names, respectively.","category":"page"},{"location":"stdlib/Dates/","page":"日期","title":"日期","text":"The above examples used the dateformat\"\" string macro. This macro creates a DateFormat object once when the macro is expanded and uses the same DateFormat object even if a code snippet is run multiple times.","category":"page"},{"location":"stdlib/Dates/","page":"日期","title":"日期","text":"julia> for i = 1:10^5\n Date(\"2015-01-01\", dateformat\"y-m-d\")\n end","category":"page"},{"location":"stdlib/Dates/","page":"日期","title":"日期","text":"Or you can create the DateFormat object explicitly:","category":"page"},{"location":"stdlib/Dates/","page":"日期","title":"日期","text":"julia> df = DateFormat(\"y-m-d\");\n\njulia> dt = Date(\"2015-01-01\",df)\n2015-01-01\n\njulia> dt2 = Date(\"2015-01-02\",df)\n2015-01-02","category":"page"},{"location":"stdlib/Dates/","page":"日期","title":"日期","text":"Alternatively, use broadcasting:","category":"page"},{"location":"stdlib/Dates/","page":"日期","title":"日期","text":"julia> years = [\"2015\", \"2016\"];\n\njulia> Date.(years, DateFormat(\"yyyy\"))\n2-element Vector{Date}:\n 2015-01-01\n 2016-01-01","category":"page"},{"location":"stdlib/Dates/","page":"日期","title":"日期","text":"For convenience, you may pass the format string directly (e.g., Date(\"2015-01-01\",\"y-m-d\")), although this form incurs performance costs if you are parsing the same format repeatedly, as it internally creates a new DateFormat object each time.","category":"page"},{"location":"stdlib/Dates/","page":"日期","title":"日期","text":"As well as via the constructors, a Date or DateTime can be constructed from strings using the parse and tryparse functions, but with an optional third argument of type DateFormat specifying the format; for example, parse(Date, \"06.23.2013\", dateformat\"m.d.y\"), or tryparse(DateTime, \"1999-12-31T23:59:59\") which uses the default format. The notable difference between the functions is that with tryparse, an error is not thrown if the string is in an invalid format; instead nothing is returned. Note however that as with the constructors above, empty date and time parts assume default values and consequently an empty string (\"\") is valid for any DateFormat, giving for example a Date of 0001-01-01. Code relying on parse or tryparse for Date and DateTime parsing should therefore also check whether parsed strings are empty before using the result.","category":"page"},{"location":"stdlib/Dates/","page":"日期","title":"日期","text":"A full suite of parsing and formatting tests and examples is available in stdlib/Dates/test/io.jl.","category":"page"},{"location":"stdlib/Dates/#Durations/Comparisons","page":"日期","title":"Durations/Comparisons","text":"","category":"section"},{"location":"stdlib/Dates/","page":"日期","title":"日期","text":"Finding the length of time between two Date or DateTime is straightforward given their underlying representation as UTInstant{Day} and UTInstant{Millisecond}, respectively. The difference between Date is returned in the number of Day, and DateTime in the number of Millisecond. Similarly, comparing TimeType is a simple matter of comparing the underlying machine instants (which in turn compares the internal Int64 values).","category":"page"},{"location":"stdlib/Dates/","page":"日期","title":"日期","text":"julia> dt = Date(2012,2,29)\n2012-02-29\n\njulia> dt2 = Date(2000,2,1)\n2000-02-01\n\njulia> dump(dt)\nDate\n instant: Dates.UTInstant{Day}\n periods: Day\n value: Int64 734562\n\njulia> dump(dt2)\nDate\n instant: Dates.UTInstant{Day}\n periods: Day\n value: Int64 730151\n\njulia> dt > dt2\ntrue\n\njulia> dt != dt2\ntrue\n\njulia> dt + dt2\nERROR: MethodError: no method matching +(::Date, ::Date)\n[...]\n\njulia> dt * dt2\nERROR: MethodError: no method matching *(::Date, ::Date)\n[...]\n\njulia> dt / dt2\nERROR: MethodError: no method matching /(::Date, ::Date)\n\njulia> dt - dt2\n4411 days\n\njulia> dt2 - dt\n-4411 days\n\njulia> dt = DateTime(2012,2,29)\n2012-02-29T00:00:00\n\njulia> dt2 = DateTime(2000,2,1)\n2000-02-01T00:00:00\n\njulia> dt - dt2\n381110400000 milliseconds","category":"page"},{"location":"stdlib/Dates/#Accessor-Functions","page":"日期","title":"Accessor Functions","text":"","category":"section"},{"location":"stdlib/Dates/","page":"日期","title":"日期","text":"Because the Date and DateTime types are stored as single Int64 values, date parts or fields can be retrieved through accessor functions. The lowercase accessors return the field as an integer:","category":"page"},{"location":"stdlib/Dates/","page":"日期","title":"日期","text":"julia> t = Date(2014, 1, 31)\n2014-01-31\n\njulia> Dates.year(t)\n2014\n\njulia> Dates.month(t)\n1\n\njulia> Dates.week(t)\n5\n\njulia> Dates.day(t)\n31","category":"page"},{"location":"stdlib/Dates/","page":"日期","title":"日期","text":"While propercase return the same value in the corresponding Period type:","category":"page"},{"location":"stdlib/Dates/","page":"日期","title":"日期","text":"julia> Dates.Year(t)\n2014 years\n\njulia> Dates.Day(t)\n31 days","category":"page"},{"location":"stdlib/Dates/","page":"日期","title":"日期","text":"Compound methods are provided because it is more efficient to access multiple fields at the same time than individually:","category":"page"},{"location":"stdlib/Dates/","page":"日期","title":"日期","text":"julia> Dates.yearmonth(t)\n(2014, 1)\n\njulia> Dates.monthday(t)\n(1, 31)\n\njulia> Dates.yearmonthday(t)\n(2014, 1, 31)","category":"page"},{"location":"stdlib/Dates/","page":"日期","title":"日期","text":"One may also access the underlying UTInstant or integer value:","category":"page"},{"location":"stdlib/Dates/","page":"日期","title":"日期","text":"julia> dump(t)\nDate\n instant: Dates.UTInstant{Day}\n periods: Day\n value: Int64 735264\n\njulia> t.instant\nDates.UTInstant{Day}(Day(735264))\n\njulia> Dates.value(t)\n735264","category":"page"},{"location":"stdlib/Dates/#Query-Functions","page":"日期","title":"Query Functions","text":"","category":"section"},{"location":"stdlib/Dates/","page":"日期","title":"日期","text":"Query functions provide calendrical information about a TimeType. They include information about the day of the week:","category":"page"},{"location":"stdlib/Dates/","page":"日期","title":"日期","text":"julia> t = Date(2014, 1, 31)\n2014-01-31\n\njulia> Dates.dayofweek(t)\n5\n\njulia> Dates.dayname(t)\n\"Friday\"\n\njulia> Dates.dayofweekofmonth(t) # 5th Friday of January\n5","category":"page"},{"location":"stdlib/Dates/","page":"日期","title":"日期","text":"Month of the year:","category":"page"},{"location":"stdlib/Dates/","page":"日期","title":"日期","text":"julia> Dates.monthname(t)\n\"January\"\n\njulia> Dates.daysinmonth(t)\n31","category":"page"},{"location":"stdlib/Dates/","page":"日期","title":"日期","text":"As well as information about the TimeType's year and quarter:","category":"page"},{"location":"stdlib/Dates/","page":"日期","title":"日期","text":"julia> Dates.isleapyear(t)\nfalse\n\njulia> Dates.dayofyear(t)\n31\n\njulia> Dates.quarterofyear(t)\n1\n\njulia> Dates.dayofquarter(t)\n31","category":"page"},{"location":"stdlib/Dates/","page":"日期","title":"日期","text":"The dayname and monthname methods can also take an optional locale keyword that can be used to return the name of the day or month of the year for other languages/locales. There are also versions of these functions returning the abbreviated names, namely dayabbr and monthabbr. First the mapping is loaded into the LOCALES variable:","category":"page"},{"location":"stdlib/Dates/","page":"日期","title":"日期","text":"julia> french_months = [\"janvier\", \"février\", \"mars\", \"avril\", \"mai\", \"juin\",\n \"juillet\", \"août\", \"septembre\", \"octobre\", \"novembre\", \"décembre\"];\n\njulia> french_monts_abbrev = [\"janv\",\"févr\",\"mars\",\"avril\",\"mai\",\"juin\",\n \"juil\",\"août\",\"sept\",\"oct\",\"nov\",\"déc\"];\n\njulia> french_days = [\"lundi\",\"mardi\",\"mercredi\",\"jeudi\",\"vendredi\",\"samedi\",\"dimanche\"];\n\njulia> Dates.LOCALES[\"french\"] = Dates.DateLocale(french_months, french_monts_abbrev, french_days, [\"\"]);","category":"page"},{"location":"stdlib/Dates/","page":"日期","title":"日期","text":"The above mentioned functions can then be used to perform the queries:","category":"page"},{"location":"stdlib/Dates/","page":"日期","title":"日期","text":"julia> Dates.dayname(t;locale=\"french\")\n\"vendredi\"\n\njulia> Dates.monthname(t;locale=\"french\")\n\"janvier\"\n\njulia> Dates.monthabbr(t;locale=\"french\")\n\"janv\"","category":"page"},{"location":"stdlib/Dates/","page":"日期","title":"日期","text":"Since the abbreviated versions of the days are not loaded, trying to use the function dayabbr will error.","category":"page"},{"location":"stdlib/Dates/","page":"日期","title":"日期","text":"julia> Dates.dayabbr(t;locale=\"french\")\nERROR: BoundsError: attempt to access 1-element Vector{String} at index [5]\nStacktrace:\n[...]","category":"page"},{"location":"stdlib/Dates/#TimeType-Period-Arithmetic","page":"日期","title":"TimeType-Period Arithmetic","text":"","category":"section"},{"location":"stdlib/Dates/","page":"日期","title":"日期","text":"It's good practice when using any language/date framework to be familiar with how date-period arithmetic is handled as there are some tricky issues to deal with (though much less so for day-precision types).","category":"page"},{"location":"stdlib/Dates/","page":"日期","title":"日期","text":"The Dates module approach tries to follow the simple principle of trying to change as little as possible when doing Period arithmetic. This approach is also often known as calendrical arithmetic or what you would probably guess if someone were to ask you the same calculation in a conversation. Why all the fuss about this? Let's take a classic example: add 1 month to January 31st, 2014. What's the answer? Javascript will say March 3 (assumes 31 days). PHP says March 2 (assumes 30 days). The fact is, there is no right answer. In the Dates module, it gives the result of February 28th. How does it figure that out? Consider the classic 7-7-7 gambling game in casinos.","category":"page"},{"location":"stdlib/Dates/","page":"日期","title":"日期","text":"Now just imagine that instead of 7-7-7, the slots are Year-Month-Day, or in our example, 2014-01-31. When you ask to add 1 month to this date, the month slot is incremented, so now we have 2014-02-31. Then the day number is checked if it is greater than the last valid day of the new month; if it is (as in the case above), the day number is adjusted down to the last valid day (28). What are the ramifications with this approach? Go ahead and add another month to our date, 2014-02-28 + Month(1) == 2014-03-28. What? Were you expecting the last day of March? Nope, sorry, remember the 7-7-7 slots. As few slots as possible are going to change, so we first increment the month slot by 1, 2014-03-28, and boom, we're done because that's a valid date. On the other hand, if we were to add 2 months to our original date, 2014-01-31, then we end up with 2014-03-31, as expected. The other ramification of this approach is a loss in associativity when a specific ordering is forced (i.e. adding things in different orders results in different outcomes). For example:","category":"page"},{"location":"stdlib/Dates/","page":"日期","title":"日期","text":"julia> (Date(2014,1,29)+Dates.Day(1)) + Dates.Month(1)\n2014-02-28\n\njulia> (Date(2014,1,29)+Dates.Month(1)) + Dates.Day(1)\n2014-03-01","category":"page"},{"location":"stdlib/Dates/","page":"日期","title":"日期","text":"What's going on there? In the first line, we're adding 1 day to January 29th, which results in 2014-01-30; then we add 1 month, so we get 2014-02-30, which then adjusts down to 2014-02-28. In the second example, we add 1 month first, where we get 2014-02-29, which adjusts down to 2014-02-28, and then add 1 day, which results in 2014-03-01. One design principle that helps in this case is that, in the presence of multiple Periods, the operations will be ordered by the Periods' types, not their value or positional order; this means Year will always be added first, then Month, then Week, etc. Hence the following does result in associativity and Just Works:","category":"page"},{"location":"stdlib/Dates/","page":"日期","title":"日期","text":"julia> Date(2014,1,29) + Dates.Day(1) + Dates.Month(1)\n2014-03-01\n\njulia> Date(2014,1,29) + Dates.Month(1) + Dates.Day(1)\n2014-03-01","category":"page"},{"location":"stdlib/Dates/","page":"日期","title":"日期","text":"Tricky? Perhaps. What is an innocent Dates user to do? The bottom line is to be aware that explicitly forcing a certain associativity, when dealing with months, may lead to some unexpected results, but otherwise, everything should work as expected. Thankfully, that's pretty much the extent of the odd cases in date-period arithmetic when dealing with time in UT (avoiding the \"joys\" of dealing with daylight savings, leap seconds, etc.).","category":"page"},{"location":"stdlib/Dates/","page":"日期","title":"日期","text":"As a bonus, all period arithmetic objects work directly with ranges:","category":"page"},{"location":"stdlib/Dates/","page":"日期","title":"日期","text":"julia> dr = Date(2014,1,29):Day(1):Date(2014,2,3)\nDate(\"2014-01-29\"):Day(1):Date(\"2014-02-03\")\n\njulia> collect(dr)\n6-element Vector{Date}:\n 2014-01-29\n 2014-01-30\n 2014-01-31\n 2014-02-01\n 2014-02-02\n 2014-02-03\n\njulia> dr = Date(2014,1,29):Dates.Month(1):Date(2014,07,29)\nDate(\"2014-01-29\"):Month(1):Date(\"2014-07-29\")\n\njulia> collect(dr)\n7-element Vector{Date}:\n 2014-01-29\n 2014-02-28\n 2014-03-29\n 2014-04-29\n 2014-05-29\n 2014-06-29\n 2014-07-29","category":"page"},{"location":"stdlib/Dates/#Adjuster-Functions","page":"日期","title":"Adjuster Functions","text":"","category":"section"},{"location":"stdlib/Dates/","page":"日期","title":"日期","text":"As convenient as date-period arithmetic is, often the kinds of calculations needed on dates take on a calendrical or temporal nature rather than a fixed number of periods. Holidays are a perfect example; most follow rules such as \"Memorial Day = Last Monday of May\", or \"Thanksgiving = 4th Thursday of November\". These kinds of temporal expressions deal with rules relative to the calendar, like first or last of the month, next Tuesday, or the first and third Wednesdays, etc.","category":"page"},{"location":"stdlib/Dates/","page":"日期","title":"日期","text":"The Dates module provides the adjuster API through several convenient methods that aid in simply and succinctly expressing temporal rules. The first group of adjuster methods deal with the first and last of weeks, months, quarters, and years. They each take a single TimeType as input and return or adjust to the first or last of the desired period relative to the input.","category":"page"},{"location":"stdlib/Dates/","page":"日期","title":"日期","text":"julia> Dates.firstdayofweek(Date(2014,7,16)) # Adjusts the input to the Monday of the input's week\n2014-07-14\n\njulia> Dates.lastdayofmonth(Date(2014,7,16)) # Adjusts to the last day of the input's month\n2014-07-31\n\njulia> Dates.lastdayofquarter(Date(2014,7,16)) # Adjusts to the last day of the input's quarter\n2014-09-30","category":"page"},{"location":"stdlib/Dates/","page":"日期","title":"日期","text":"The next two higher-order methods, tonext, and toprev, generalize working with temporal expressions by taking a DateFunction as first argument, along with a starting TimeType. A DateFunction is just a function, usually anonymous, that takes a single TimeType as input and returns a Bool, true indicating a satisfied adjustment criterion. For example:","category":"page"},{"location":"stdlib/Dates/","page":"日期","title":"日期","text":"julia> istuesday = x->Dates.dayofweek(x) == Dates.Tuesday; # Returns true if the day of the week of x is Tuesday\n\njulia> Dates.tonext(istuesday, Date(2014,7,13)) # 2014-07-13 is a Sunday\n2014-07-15\n\njulia> Dates.tonext(Date(2014,7,13), Dates.Tuesday) # Convenience method provided for day of the week adjustments\n2014-07-15","category":"page"},{"location":"stdlib/Dates/","page":"日期","title":"日期","text":"This is useful with the do-block syntax for more complex temporal expressions:","category":"page"},{"location":"stdlib/Dates/","page":"日期","title":"日期","text":"julia> Dates.tonext(Date(2014,7,13)) do x\n # Return true on the 4th Thursday of November (Thanksgiving)\n Dates.dayofweek(x) == Dates.Thursday &&\n Dates.dayofweekofmonth(x) == 4 &&\n Dates.month(x) == Dates.November\n end\n2014-11-27","category":"page"},{"location":"stdlib/Dates/","page":"日期","title":"日期","text":"The Base.filter method can be used to obtain all valid dates/moments in a specified range:","category":"page"},{"location":"stdlib/Dates/","page":"日期","title":"日期","text":"# Pittsburgh street cleaning; Every 2nd Tuesday from April to November\n# Date range from January 1st, 2014 to January 1st, 2015\njulia> dr = Dates.Date(2014):Day(1):Dates.Date(2015);\n\njulia> filter(dr) do x\n Dates.dayofweek(x) == Dates.Tue &&\n Dates.April <= Dates.month(x) <= Dates.Nov &&\n Dates.dayofweekofmonth(x) == 2\n end\n8-element Vector{Date}:\n 2014-04-08\n 2014-05-13\n 2014-06-10\n 2014-07-08\n 2014-08-12\n 2014-09-09\n 2014-10-14\n 2014-11-11","category":"page"},{"location":"stdlib/Dates/","page":"日期","title":"日期","text":"Additional examples and tests are available in stdlib/Dates/test/adjusters.jl.","category":"page"},{"location":"stdlib/Dates/#Period-Types","page":"日期","title":"Period Types","text":"","category":"section"},{"location":"stdlib/Dates/","page":"日期","title":"日期","text":"Periods are a human view of discrete, sometimes irregular durations of time. Consider 1 month; it could represent, in days, a value of 28, 29, 30, or 31 depending on the year and month context. Or a year could represent 365 or 366 days in the case of a leap year. Period types are simple Int64 wrappers and are constructed by wrapping any Int64 convertible type, i.e. Year(1) or Month(3.0). Arithmetic between Period of the same type behave like integers, and limited Period-Real arithmetic is available. You can extract the underlying integer with Dates.value.","category":"page"},{"location":"stdlib/Dates/","page":"日期","title":"日期","text":"julia> y1 = Dates.Year(1)\n1 year\n\njulia> y2 = Dates.Year(2)\n2 years\n\njulia> y3 = Dates.Year(10)\n10 years\n\njulia> y1 + y2\n3 years\n\njulia> div(y3,y2)\n5\n\njulia> y3 - y2\n8 years\n\njulia> y3 % y2\n0 years\n\njulia> div(y3,3) # mirrors integer division\n3 years\n\njulia> Dates.value(Dates.Millisecond(10))\n10","category":"page"},{"location":"stdlib/Dates/#Rounding","page":"日期","title":"Rounding","text":"","category":"section"},{"location":"stdlib/Dates/","page":"日期","title":"日期","text":"Date and DateTime values can be rounded to a specified resolution (e.g., 1 month or 15 minutes) with floor, ceil, or round:","category":"page"},{"location":"stdlib/Dates/","page":"日期","title":"日期","text":"julia> floor(Date(1985, 8, 16), Dates.Month)\n1985-08-01\n\njulia> ceil(DateTime(2013, 2, 13, 0, 31, 20), Dates.Minute(15))\n2013-02-13T00:45:00\n\njulia> round(DateTime(2016, 8, 6, 20, 15), Dates.Day)\n2016-08-07T00:00:00","category":"page"},{"location":"stdlib/Dates/","page":"日期","title":"日期","text":"Unlike the numeric round method, which breaks ties toward the even number by default, the TimeTyperound method uses the RoundNearestTiesUp rounding mode. (It's difficult to guess what breaking ties to nearest \"even\" TimeType would entail.) Further details on the available RoundingMode s can be found in the API reference.","category":"page"},{"location":"stdlib/Dates/","page":"日期","title":"日期","text":"Rounding should generally behave as expected, but there are a few cases in which the expected behaviour is not obvious.","category":"page"},{"location":"stdlib/Dates/#Rounding-Epoch","page":"日期","title":"Rounding Epoch","text":"","category":"section"},{"location":"stdlib/Dates/","page":"日期","title":"日期","text":"In many cases, the resolution specified for rounding (e.g., Dates.Second(30)) divides evenly into the next largest period (in this case, Dates.Minute(1)). But rounding behaviour in cases in which this is not true may lead to confusion. What is the expected result of rounding a DateTime to the nearest 10 hours?","category":"page"},{"location":"stdlib/Dates/","page":"日期","title":"日期","text":"julia> round(DateTime(2016, 7, 17, 11, 55), Dates.Hour(10))\n2016-07-17T12:00:00","category":"page"},{"location":"stdlib/Dates/","page":"日期","title":"日期","text":"That may seem confusing, given that the hour (12) is not divisible by 10. The reason that 2016-07-17T12:00:00 was chosen is that it is 17,676,660 hours after 0000-01-01T00:00:00, and 17,676,660 is divisible by 10.","category":"page"},{"location":"stdlib/Dates/","page":"日期","title":"日期","text":"As Julia Date and DateTime values are represented according to the ISO 8601 standard, 0000-01-01T00:00:00 was chosen as base (or \"rounding epoch\") from which to begin the count of days (and milliseconds) used in rounding calculations. (Note that this differs slightly from Julia's internal representation of Date s using Rata Die notation; but since the ISO 8601 standard is most visible to the end user, 0000-01-01T00:00:00 was chosen as the rounding epoch instead of the 0000-12-31T00:00:00 used internally to minimize confusion.)","category":"page"},{"location":"stdlib/Dates/","page":"日期","title":"日期","text":"The only exception to the use of 0000-01-01T00:00:00 as the rounding epoch is when rounding to weeks. Rounding to the nearest week will always return a Monday (the first day of the week as specified by ISO 8601). For this reason, we use 0000-01-03T00:00:00 (the first day of the first week of year 0000, as defined by ISO 8601) as the base when rounding to a number of weeks.","category":"page"},{"location":"stdlib/Dates/","page":"日期","title":"日期","text":"Here is a related case in which the expected behaviour is not necessarily obvious: What happens when we round to the nearest P(2), where P is a Period type? In some cases (specifically, when P <: Dates.TimePeriod) the answer is clear:","category":"page"},{"location":"stdlib/Dates/","page":"日期","title":"日期","text":"julia> round(DateTime(2016, 7, 17, 8, 55, 30), Dates.Hour(2))\n2016-07-17T08:00:00\n\njulia> round(DateTime(2016, 7, 17, 8, 55, 30), Dates.Minute(2))\n2016-07-17T08:56:00","category":"page"},{"location":"stdlib/Dates/","page":"日期","title":"日期","text":"This seems obvious, because two of each of these periods still divides evenly into the next larger order period. But in the case of two months (which still divides evenly into one year), the answer may be surprising:","category":"page"},{"location":"stdlib/Dates/","page":"日期","title":"日期","text":"julia> round(DateTime(2016, 7, 17, 8, 55, 30), Dates.Month(2))\n2016-07-01T00:00:00","category":"page"},{"location":"stdlib/Dates/","page":"日期","title":"日期","text":"Why round to the first day in July, even though it is month 7 (an odd number)? The key is that months are 1-indexed (the first month is assigned 1), unlike hours, minutes, seconds, and milliseconds (the first of which are assigned 0).","category":"page"},{"location":"stdlib/Dates/","page":"日期","title":"日期","text":"This means that rounding a DateTime to an even multiple of seconds, minutes, hours, or years (because the ISO 8601 specification includes a year zero) will result in a DateTime with an even value in that field, while rounding a DateTime to an even multiple of months will result in the months field having an odd value. Because both months and years may contain an irregular number of days, whether rounding to an even number of days will result in an even value in the days field is uncertain.","category":"page"},{"location":"stdlib/Dates/","page":"日期","title":"日期","text":"See the API reference for additional information on methods exported from the Dates module.","category":"page"},{"location":"stdlib/Dates/#stdlib-dates-api","page":"日期","title":"API reference","text":"","category":"section"},{"location":"stdlib/Dates/#Dates-and-Time-Types","page":"日期","title":"Dates and Time Types","text":"","category":"section"},{"location":"stdlib/Dates/","page":"日期","title":"日期","text":"Dates.Period\nDates.CompoundPeriod\nDates.Instant\nDates.UTInstant\nDates.TimeType\nDates.DateTime\nDates.Date\nDates.Time\nDates.TimeZone\nDates.UTC","category":"page"},{"location":"stdlib/Dates/#Dates.Period","page":"日期","title":"Dates.Period","text":"Period\nYear\nQuarter\nMonth\nWeek\nDay\nHour\nMinute\nSecond\nMillisecond\nMicrosecond\nNanosecond\n\nPeriod types represent discrete, human representations of time.\n\n\n\n\n\n","category":"type"},{"location":"stdlib/Dates/#Dates.CompoundPeriod","page":"日期","title":"Dates.CompoundPeriod","text":"CompoundPeriod\n\nA CompoundPeriod is useful for expressing time periods that are not a fixed multiple of smaller periods. For example, \"a year and a day\" is not a fixed number of days, but can be expressed using a CompoundPeriod. In fact, a CompoundPeriod is automatically generated by addition of different period types, e.g. Year(1) + Day(1) produces a CompoundPeriod result.\n\n\n\n\n\n","category":"type"},{"location":"stdlib/Dates/#Dates.Instant","page":"日期","title":"Dates.Instant","text":"Instant\n\nInstant types represent integer-based, machine representations of time as continuous timelines starting from an epoch.\n\n\n\n\n\n","category":"type"},{"location":"stdlib/Dates/#Dates.UTInstant","page":"日期","title":"Dates.UTInstant","text":"UTInstant{T}\n\nThe UTInstant represents a machine timeline based on UT time (1 day = one revolution of the earth). The T is a Period parameter that indicates the resolution or precision of the instant.\n\n\n\n\n\n","category":"type"},{"location":"stdlib/Dates/#Dates.TimeType","page":"日期","title":"Dates.TimeType","text":"TimeType\n\nTimeType types wrap Instant machine instances to provide human representations of the machine instant. Time, DateTime and Date are subtypes of TimeType.\n\n\n\n\n\n","category":"type"},{"location":"stdlib/Dates/#Dates.DateTime","page":"日期","title":"Dates.DateTime","text":"DateTime\n\nDateTime wraps a UTInstant{Millisecond} and interprets it according to the proleptic Gregorian calendar.\n\n\n\n\n\n","category":"type"},{"location":"stdlib/Dates/#Dates.Date","page":"日期","title":"Dates.Date","text":"Date\n\nDate wraps a UTInstant{Day} and interprets it according to the proleptic Gregorian calendar.\n\n\n\n\n\n","category":"type"},{"location":"stdlib/Dates/#Dates.Time","page":"日期","title":"Dates.Time","text":"Time\n\nTime wraps a Nanosecond and represents a specific moment in a 24-hour day.\n\n\n\n\n\n","category":"type"},{"location":"stdlib/Dates/#Dates.TimeZone","page":"日期","title":"Dates.TimeZone","text":"TimeZone\n\nGeographic zone generally based on longitude determining what the time is at a certain location. Some time zones observe daylight savings (eg EST -> EDT). For implementations and more support, see the TimeZones.jl package\n\n\n\n\n\n","category":"type"},{"location":"stdlib/Dates/#Dates.UTC","page":"日期","title":"Dates.UTC","text":"UTC\n\nUTC, or Coordinated Universal Time, is the TimeZone from which all others are measured. It is associated with the time at 0° longitude. It is not adjusted for daylight savings.\n\n\n\n\n\n","category":"type"},{"location":"stdlib/Dates/#Dates-Functions","page":"日期","title":"Dates Functions","text":"","category":"section"},{"location":"stdlib/Dates/","page":"日期","title":"日期","text":"Dates.DateTime(::Int64, ::Int64, ::Int64, ::Int64, ::Int64, ::Int64, ::Int64)\nDates.DateTime(::Dates.Period)\nDates.DateTime(::Function, ::Any...)\nDates.DateTime(::Dates.TimeType)\nDates.DateTime(::AbstractString, ::AbstractString)\nDates.format(::Dates.TimeType, ::AbstractString)\nDates.DateFormat\nDates.@dateformat_str\nDates.DateTime(::AbstractString, ::Dates.DateFormat)\nDates.Date(::Int64, ::Int64, ::Int64)\nDates.Date(::Dates.Period)\nDates.Date(::Function, ::Any, ::Any, ::Any)\nDates.Date(::Dates.TimeType)\nDates.Date(::AbstractString, ::AbstractString)\nDates.Date(::AbstractString, ::Dates.DateFormat)\nDates.Time(::Int64::Int64, ::Int64, ::Int64, ::Int64, ::Int64)\nDates.Time(::Dates.TimePeriod)\nDates.Time(::Function, ::Any...)\nDates.Time(::Dates.DateTime)\nDates.Time(::AbstractString, ::AbstractString)\nDates.Time(::AbstractString, ::Dates.DateFormat)\nDates.now()\nDates.now(::Type{Dates.UTC})\nBase.eps(::Union{Type{DateTime}, Type{Date}, Type{Time}, TimeType})","category":"page"},{"location":"stdlib/Dates/#Dates.DateTime-NTuple{7, Int64}","page":"日期","title":"Dates.DateTime","text":"DateTime(y, [m, d, h, mi, s, ms]) -> DateTime\n\nConstruct a DateTime type by parts. Arguments must be convertible to Int64.\n\n\n\n\n\n","category":"method"},{"location":"stdlib/Dates/#Dates.DateTime-Tuple{Period}","page":"日期","title":"Dates.DateTime","text":"DateTime(periods::Period...) -> DateTime\n\nConstruct a DateTime type by Period type parts. Arguments may be in any order. DateTime parts not provided will default to the value of Dates.default(period).\n\n\n\n\n\n","category":"method"},{"location":"stdlib/Dates/#Dates.DateTime-Tuple{Function, Vararg{Any}}","page":"日期","title":"Dates.DateTime","text":"DateTime(f::Function, y[, m, d, h, mi, s]; step=Day(1), limit=10000) -> DateTime\n\nCreate a DateTime through the adjuster API. The starting point will be constructed from the provided y, m, d... arguments, and will be adjusted until f::Function returns true. The step size in adjusting can be provided manually through the step keyword. limit provides a limit to the max number of iterations the adjustment API will pursue before throwing an error (in the case that f::Function is never satisfied).\n\nExamples\n\njulia> DateTime(dt -> Dates.second(dt) == 40, 2010, 10, 20, 10; step = Dates.Second(1))\n2010-10-20T10:00:40\n\njulia> DateTime(dt -> Dates.hour(dt) == 20, 2010, 10, 20, 10; step = Dates.Hour(1), limit = 5)\nERROR: ArgumentError: Adjustment limit reached: 5 iterations\nStacktrace:\n[...]\n\n\n\n\n\n","category":"method"},{"location":"stdlib/Dates/#Dates.DateTime-Tuple{TimeType}","page":"日期","title":"Dates.DateTime","text":"DateTime(dt::Date) -> DateTime\n\nConvert a Date to a DateTime. The hour, minute, second, and millisecond parts of the new DateTime are assumed to be zero.\n\n\n\n\n\n","category":"method"},{"location":"stdlib/Dates/#Dates.DateTime-Tuple{AbstractString, AbstractString}","page":"日期","title":"Dates.DateTime","text":"DateTime(dt::AbstractString, format::AbstractString; locale=\"english\") -> DateTime\n\nConstruct a DateTime by parsing the dt date time string following the pattern given in the format string (see DateFormat for syntax).\n\nnote: Note\nThis method creates a DateFormat object each time it is called. It is recommended that you create a DateFormat object instead and use that as the second argument to avoid performance loss when using the same format repeatedly.\n\nExample\n\njulia> DateTime(\"2020-01-01\", \"yyyy-mm-dd\")\n2020-01-01T00:00:00\n\njulia> a = (\"2020-01-01\", \"2020-01-02\");\n\njulia> [DateTime(d, dateformat\"yyyy-mm-dd\") for d ∈ a] # preferred\n2-element Vector{DateTime}:\n 2020-01-01T00:00:00\n 2020-01-02T00:00:00\n\n\n\n\n\n","category":"method"},{"location":"stdlib/Dates/#Dates.format-Tuple{TimeType, AbstractString}","page":"日期","title":"Dates.format","text":"format(dt::TimeType, format::AbstractString; locale=\"english\") -> AbstractString\n\nConstruct a string by using a TimeType object and applying the provided format. The following character codes can be used to construct the format string:\n\nCode Examples Comment\ny 6 Numeric year with a fixed width\nY 1996 Numeric year with a minimum width\nm 1, 12 Numeric month with a minimum width\nu Jan Month name shortened to 3-chars according to the locale\nU January Full month name according to the locale keyword\nd 1, 31 Day of the month with a minimum width\nH 0, 23 Hour (24-hour clock) with a minimum width\nM 0, 59 Minute with a minimum width\nS 0, 59 Second with a minimum width\ns 000, 500 Millisecond with a minimum width of 3\ne Mon, Tue Abbreviated days of the week\nE Monday Full day of week name\n\nThe number of sequential code characters indicate the width of the code. A format of yyyy-mm specifies that the code y should have a width of four while m a width of two. Codes that yield numeric digits have an associated mode: fixed-width or minimum-width. The fixed-width mode left-pads the value with zeros when it is shorter than the specified width and truncates the value when longer. Minimum-width mode works the same as fixed-width except that it does not truncate values longer than the width.\n\nWhen creating a format you can use any non-code characters as a separator. For example to generate the string \"1996-01-15T00:00:00\" you could use format: \"yyyy-mm-ddTHH:MM:SS\". Note that if you need to use a code character as a literal you can use the escape character backslash. The string \"1996y01m\" can be produced with the format \"yyyy\\ymm\\m\".\n\n\n\n\n\n","category":"method"},{"location":"stdlib/Dates/#Dates.DateFormat","page":"日期","title":"Dates.DateFormat","text":"DateFormat(format::AbstractString, locale=\"english\") -> DateFormat\n\nConstruct a date formatting object that can be used for parsing date strings or formatting a date object as a string. The following character codes can be used to construct the format string:\n\nCode Matches Comment\ny 1996, 96 Returns year of 1996, 0096\nY 1996, 96 Returns year of 1996, 0096. Equivalent to y\nm 1, 01 Matches 1 or 2-digit months\nu Jan Matches abbreviated months according to the locale keyword\nU January Matches full month names according to the locale keyword\nd 1, 01 Matches 1 or 2-digit days\nH 00 Matches hours (24-hour clock)\nI 00 For outputting hours with 12-hour clock\nM 00 Matches minutes\nS 00 Matches seconds\ns .500 Matches milliseconds\ne Mon, Tues Matches abbreviated days of the week\nE Monday Matches full name days of the week\np AM Matches AM/PM (case-insensitive)\nyyyymmdd 19960101 Matches fixed-width year, month, and day\n\nCharacters not listed above are normally treated as delimiters between date and time slots. For example a dt string of \"1996-01-15T00:00:00.0\" would have a format string like \"y-m-dTH:M:S.s\". If you need to use a code character as a delimiter you can escape it using backslash. The date \"1995y01m\" would have the format \"y\\ym\\m\".\n\nNote that 12:00AM corresponds 00:00 (midnight), and 12:00PM corresponds to 12:00 (noon). When parsing a time with a p specifier, any hour (either H or I) is interpreted as as a 12-hour clock, so the I code is mainly useful for output.\n\nCreating a DateFormat object is expensive. Whenever possible, create it once and use it many times or try the dateformat\"\" string macro. Using this macro creates the DateFormat object once at macro expansion time and reuses it later. There are also several pre-defined formatters, listed later.\n\nSee DateTime and format for how to use a DateFormat object to parse and write Date strings respectively.\n\n\n\n\n\n","category":"type"},{"location":"stdlib/Dates/#Dates.@dateformat_str","page":"日期","title":"Dates.@dateformat_str","text":"dateformat\"Y-m-d H:M:S\"\n\nCreate a DateFormat object. Similar to DateFormat(\"Y-m-d H:M:S\") but creates the DateFormat object once during macro expansion.\n\nSee DateFormat for details about format specifiers.\n\n\n\n\n\n","category":"macro"},{"location":"stdlib/Dates/#Dates.DateTime-Tuple{AbstractString, DateFormat}","page":"日期","title":"Dates.DateTime","text":"DateTime(dt::AbstractString, df::DateFormat=ISODateTimeFormat) -> DateTime\n\nConstruct a DateTime by parsing the dt date time string following the pattern given in the DateFormat object, or dateformat\"yyyy-mm-ddTHH:MM:SS.s\" if omitted.\n\nSimilar to DateTime(::AbstractString, ::AbstractString) but more efficient when repeatedly parsing similarly formatted date time strings with a pre-created DateFormat object.\n\n\n\n\n\n","category":"method"},{"location":"stdlib/Dates/#Dates.Date-Tuple{Int64, Int64, Int64}","page":"日期","title":"Dates.Date","text":"Date(y, [m, d]) -> Date\n\nConstruct a Date type by parts. Arguments must be convertible to Int64.\n\n\n\n\n\n","category":"method"},{"location":"stdlib/Dates/#Dates.Date-Tuple{Period}","page":"日期","title":"Dates.Date","text":"Date(period::Period...) -> Date\n\nConstruct a Date type by Period type parts. Arguments may be in any order. Date parts not provided will default to the value of Dates.default(period).\n\n\n\n\n\n","category":"method"},{"location":"stdlib/Dates/#Dates.Date-Tuple{Function, Any, Any, Any}","page":"日期","title":"Dates.Date","text":"Date(f::Function, y[, m, d]; step=Day(1), limit=10000) -> Date\n\nCreate a Date through the adjuster API. The starting point will be constructed from the provided y, m, d arguments, and will be adjusted until f::Function returns true. The step size in adjusting can be provided manually through the step keyword. limit provides a limit to the max number of iterations the adjustment API will pursue before throwing an error (given that f::Function is never satisfied).\n\nExamples\n\njulia> Date(date -> Dates.week(date) == 20, 2010, 01, 01)\n2010-05-17\n\njulia> Date(date -> Dates.year(date) == 2010, 2000, 01, 01)\n2010-01-01\n\njulia> Date(date -> Dates.month(date) == 10, 2000, 01, 01; limit = 5)\nERROR: ArgumentError: Adjustment limit reached: 5 iterations\nStacktrace:\n[...]\n\n\n\n\n\n","category":"method"},{"location":"stdlib/Dates/#Dates.Date-Tuple{TimeType}","page":"日期","title":"Dates.Date","text":"Date(dt::DateTime) -> Date\n\nConvert a DateTime to a Date. The hour, minute, second, and millisecond parts of the DateTime are truncated, so only the year, month and day parts are used in construction.\n\n\n\n\n\n","category":"method"},{"location":"stdlib/Dates/#Dates.Date-Tuple{AbstractString, AbstractString}","page":"日期","title":"Dates.Date","text":"Date(d::AbstractString, format::AbstractString; locale=\"english\") -> Date\n\nConstruct a Date by parsing the d date string following the pattern given in the format string (see DateFormat for syntax).\n\nnote: Note\nThis method creates a DateFormat object each time it is called. It is recommended that you create a DateFormat object instead and use that as the second argument to avoid performance loss when using the same format repeatedly.\n\nExample\n\njulia> Date(\"2020-01-01\", \"yyyy-mm-dd\")\n2020-01-01\n\njulia> a = (\"2020-01-01\", \"2020-01-02\");\n\njulia> [Date(d, dateformat\"yyyy-mm-dd\") for d ∈ a] # preferred\n2-element Vector{Date}:\n 2020-01-01\n 2020-01-02\n\n\n\n\n\n","category":"method"},{"location":"stdlib/Dates/#Dates.Date-Tuple{AbstractString, DateFormat}","page":"日期","title":"Dates.Date","text":"Date(d::AbstractString, df::DateFormat=ISODateFormat) -> Date\n\nConstruct a Date by parsing the d date string following the pattern given in the DateFormat object, or dateformat\"yyyy-mm-dd\" if omitted.\n\nSimilar to Date(::AbstractString, ::AbstractString) but more efficient when repeatedly parsing similarly formatted date strings with a pre-created DateFormat object.\n\n\n\n\n\n","category":"method"},{"location":"stdlib/Dates/#Dates.Time-NTuple{5, Int64}","page":"日期","title":"Dates.Time","text":"Time(h, [mi, s, ms, us, ns]) -> Time\n\nConstruct a Time type by parts. Arguments must be convertible to Int64.\n\n\n\n\n\n","category":"method"},{"location":"stdlib/Dates/#Dates.Time-Tuple{TimePeriod}","page":"日期","title":"Dates.Time","text":"Time(period::TimePeriod...) -> Time\n\nConstruct a Time type by Period type parts. Arguments may be in any order. Time parts not provided will default to the value of Dates.default(period).\n\n\n\n\n\n","category":"method"},{"location":"stdlib/Dates/#Dates.Time-Tuple{Function, Vararg{Any}}","page":"日期","title":"Dates.Time","text":"Time(f::Function, h, mi=0; step::Period=Second(1), limit::Int=10000)\nTime(f::Function, h, mi, s; step::Period=Millisecond(1), limit::Int=10000)\nTime(f::Function, h, mi, s, ms; step::Period=Microsecond(1), limit::Int=10000)\nTime(f::Function, h, mi, s, ms, us; step::Period=Nanosecond(1), limit::Int=10000)\n\nCreate a Time through the adjuster API. The starting point will be constructed from the provided h, mi, s, ms, us arguments, and will be adjusted until f::Function returns true. The step size in adjusting can be provided manually through the step keyword. limit provides a limit to the max number of iterations the adjustment API will pursue before throwing an error (in the case that f::Function is never satisfied). Note that the default step will adjust to allow for greater precision for the given arguments; i.e. if hour, minute, and second arguments are provided, the default step will be Millisecond(1) instead of Second(1).\n\nExamples\n\njulia> Dates.Time(t -> Dates.minute(t) == 30, 20)\n20:30:00\n\njulia> Dates.Time(t -> Dates.minute(t) == 0, 20)\n20:00:00\n\njulia> Dates.Time(t -> Dates.hour(t) == 10, 3; limit = 5)\nERROR: ArgumentError: Adjustment limit reached: 5 iterations\nStacktrace:\n[...]\n\n\n\n\n\n","category":"method"},{"location":"stdlib/Dates/#Dates.Time-Tuple{DateTime}","page":"日期","title":"Dates.Time","text":"Time(dt::DateTime) -> Time\n\nConvert a DateTime to a Time. The hour, minute, second, and millisecond parts of the DateTime are used to create the new Time. Microsecond and nanoseconds are zero by default.\n\n\n\n\n\n","category":"method"},{"location":"stdlib/Dates/#Dates.Time-Tuple{AbstractString, AbstractString}","page":"日期","title":"Dates.Time","text":"Time(t::AbstractString, format::AbstractString; locale=\"english\") -> Time\n\nConstruct a Time by parsing the t time string following the pattern given in the format string (see DateFormat for syntax).\n\nnote: Note\nThis method creates a DateFormat object each time it is called. It is recommended that you create a DateFormat object instead and use that as the second argument to avoid performance loss when using the same format repeatedly.\n\nExample\n\njulia> Time(\"12:34pm\", \"HH:MMp\")\n12:34:00\n\njulia> a = (\"12:34pm\", \"2:34am\");\n\njulia> [Time(d, dateformat\"HH:MMp\") for d ∈ a] # preferred\n2-element Vector{Time}:\n 12:34:00\n 02:34:00\n\n\n\n\n\n","category":"method"},{"location":"stdlib/Dates/#Dates.Time-Tuple{AbstractString, DateFormat}","page":"日期","title":"Dates.Time","text":"Time(t::AbstractString, df::DateFormat=ISOTimeFormat) -> Time\n\nConstruct a Time by parsing the t date time string following the pattern given in the DateFormat object, or dateformat\"HH:MM:SS.s\" if omitted.\n\nSimilar to Time(::AbstractString, ::AbstractString) but more efficient when repeatedly parsing similarly formatted time strings with a pre-created DateFormat object.\n\n\n\n\n\n","category":"method"},{"location":"stdlib/Dates/#Dates.now-Tuple{}","page":"日期","title":"Dates.now","text":"now() -> DateTime\n\nReturn a DateTime corresponding to the user's system time including the system timezone locale.\n\n\n\n\n\n","category":"method"},{"location":"stdlib/Dates/#Dates.now-Tuple{Type{UTC}}","page":"日期","title":"Dates.now","text":"now(::Type{UTC}) -> DateTime\n\nReturn a DateTime corresponding to the user's system time as UTC/GMT.\n\n\n\n\n\n","category":"method"},{"location":"stdlib/Dates/#Base.eps-Tuple{Union{Type{Date}, Type{DateTime}, Type{Time}, TimeType}}","page":"日期","title":"Base.eps","text":"eps(::Type{DateTime}) -> Millisecond\neps(::Type{Date}) -> Day\neps(::Type{Time}) -> Nanosecond\neps(::TimeType) -> Period\n\nReturn the smallest unit value supported by the TimeType.\n\nExamples\n\njulia> eps(DateTime)\n1 millisecond\n\njulia> eps(Date)\n1 day\n\njulia> eps(Time)\n1 nanosecond\n\n\n\n\n\n","category":"method"},{"location":"stdlib/Dates/#Accessor-Functions-2","page":"日期","title":"Accessor Functions","text":"","category":"section"},{"location":"stdlib/Dates/","page":"日期","title":"日期","text":"Dates.year\nDates.month\nDates.week\nDates.day\nDates.hour\nDates.minute\nDates.second\nDates.millisecond\nDates.microsecond\nDates.nanosecond\nDates.Year(::Dates.TimeType)\nDates.Month(::Dates.TimeType)\nDates.Week(::Dates.TimeType)\nDates.Day(::Dates.TimeType)\nDates.Hour(::DateTime)\nDates.Minute(::DateTime)\nDates.Second(::DateTime)\nDates.Millisecond(::DateTime)\nDates.Microsecond(::Dates.Time)\nDates.Nanosecond(::Dates.Time)\nDates.yearmonth\nDates.monthday\nDates.yearmonthday","category":"page"},{"location":"stdlib/Dates/#Dates.year","page":"日期","title":"Dates.year","text":"year(dt::TimeType) -> Int64\n\nThe year of a Date or DateTime as an Int64.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/Dates/#Dates.month","page":"日期","title":"Dates.month","text":"month(dt::TimeType) -> Int64\n\nThe month of a Date or DateTime as an Int64.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/Dates/#Dates.week","page":"日期","title":"Dates.week","text":"week(dt::TimeType) -> Int64\n\nReturn the ISO week date of a Date or DateTime as an Int64. Note that the first week of a year is the week that contains the first Thursday of the year, which can result in dates prior to January 4th being in the last week of the previous year. For example, week(Date(2005, 1, 1)) is the 53rd week of 2004.\n\nExamples\n\njulia> Dates.week(Date(1989, 6, 22))\n25\n\njulia> Dates.week(Date(2005, 1, 1))\n53\n\njulia> Dates.week(Date(2004, 12, 31))\n53\n\n\n\n\n\n","category":"function"},{"location":"stdlib/Dates/#Dates.day","page":"日期","title":"Dates.day","text":"day(dt::TimeType) -> Int64\n\nThe day of month of a Date or DateTime as an Int64.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/Dates/#Dates.hour","page":"日期","title":"Dates.hour","text":"hour(dt::DateTime) -> Int64\n\nThe hour of day of a DateTime as an Int64.\n\n\n\n\n\nhour(t::Time) -> Int64\n\nThe hour of a Time as an Int64.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/Dates/#Dates.minute","page":"日期","title":"Dates.minute","text":"minute(dt::DateTime) -> Int64\n\nThe minute of a DateTime as an Int64.\n\n\n\n\n\nminute(t::Time) -> Int64\n\nThe minute of a Time as an Int64.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/Dates/#Dates.second","page":"日期","title":"Dates.second","text":"second(dt::DateTime) -> Int64\n\nThe second of a DateTime as an Int64.\n\n\n\n\n\nsecond(t::Time) -> Int64\n\nThe second of a Time as an Int64.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/Dates/#Dates.millisecond","page":"日期","title":"Dates.millisecond","text":"millisecond(dt::DateTime) -> Int64\n\nThe millisecond of a DateTime as an Int64.\n\n\n\n\n\nmillisecond(t::Time) -> Int64\n\nThe millisecond of a Time as an Int64.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/Dates/#Dates.microsecond","page":"日期","title":"Dates.microsecond","text":"microsecond(t::Time) -> Int64\n\nThe microsecond of a Time as an Int64.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/Dates/#Dates.nanosecond","page":"日期","title":"Dates.nanosecond","text":"nanosecond(t::Time) -> Int64\n\nThe nanosecond of a Time as an Int64.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/Dates/#Dates.Year-Tuple{TimeType}","page":"日期","title":"Dates.Year","text":"Year(v)\n\nConstruct a Year object with the given v value. Input must be losslessly convertible to an Int64.\n\n\n\n\n\n","category":"method"},{"location":"stdlib/Dates/#Dates.Month-Tuple{TimeType}","page":"日期","title":"Dates.Month","text":"Month(v)\n\nConstruct a Month object with the given v value. Input must be losslessly convertible to an Int64.\n\n\n\n\n\n","category":"method"},{"location":"stdlib/Dates/#Dates.Week-Tuple{TimeType}","page":"日期","title":"Dates.Week","text":"Week(v)\n\nConstruct a Week object with the given v value. Input must be losslessly convertible to an Int64.\n\n\n\n\n\n","category":"method"},{"location":"stdlib/Dates/#Dates.Day-Tuple{TimeType}","page":"日期","title":"Dates.Day","text":"Day(v)\n\nConstruct a Day object with the given v value. Input must be losslessly convertible to an Int64.\n\n\n\n\n\n","category":"method"},{"location":"stdlib/Dates/#Dates.Hour-Tuple{DateTime}","page":"日期","title":"Dates.Hour","text":"Hour(dt::DateTime) -> Hour\n\nThe hour part of a DateTime as a Hour.\n\n\n\n\n\n","category":"method"},{"location":"stdlib/Dates/#Dates.Minute-Tuple{DateTime}","page":"日期","title":"Dates.Minute","text":"Minute(dt::DateTime) -> Minute\n\nThe minute part of a DateTime as a Minute.\n\n\n\n\n\n","category":"method"},{"location":"stdlib/Dates/#Dates.Second-Tuple{DateTime}","page":"日期","title":"Dates.Second","text":"Second(dt::DateTime) -> Second\n\nThe second part of a DateTime as a Second.\n\n\n\n\n\n","category":"method"},{"location":"stdlib/Dates/#Dates.Millisecond-Tuple{DateTime}","page":"日期","title":"Dates.Millisecond","text":"Millisecond(dt::DateTime) -> Millisecond\n\nThe millisecond part of a DateTime as a Millisecond.\n\n\n\n\n\n","category":"method"},{"location":"stdlib/Dates/#Dates.Microsecond-Tuple{Time}","page":"日期","title":"Dates.Microsecond","text":"Microsecond(dt::Time) -> Microsecond\n\nThe microsecond part of a Time as a Microsecond.\n\n\n\n\n\n","category":"method"},{"location":"stdlib/Dates/#Dates.Nanosecond-Tuple{Time}","page":"日期","title":"Dates.Nanosecond","text":"Nanosecond(dt::Time) -> Nanosecond\n\nThe nanosecond part of a Time as a Nanosecond.\n\n\n\n\n\n","category":"method"},{"location":"stdlib/Dates/#Dates.yearmonth","page":"日期","title":"Dates.yearmonth","text":"yearmonth(dt::TimeType) -> (Int64, Int64)\n\nSimultaneously return the year and month parts of a Date or DateTime.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/Dates/#Dates.monthday","page":"日期","title":"Dates.monthday","text":"monthday(dt::TimeType) -> (Int64, Int64)\n\nSimultaneously return the month and day parts of a Date or DateTime.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/Dates/#Dates.yearmonthday","page":"日期","title":"Dates.yearmonthday","text":"yearmonthday(dt::TimeType) -> (Int64, Int64, Int64)\n\nSimultaneously return the year, month and day parts of a Date or DateTime.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/Dates/#Query-Functions-2","page":"日期","title":"Query Functions","text":"","category":"section"},{"location":"stdlib/Dates/","page":"日期","title":"日期","text":"Dates.dayname\nDates.dayabbr\nDates.dayofweek\nDates.dayofmonth\nDates.dayofweekofmonth\nDates.daysofweekinmonth\nDates.monthname\nDates.monthabbr\nDates.daysinmonth\nDates.isleapyear\nDates.dayofyear\nDates.daysinyear\nDates.quarterofyear\nDates.dayofquarter","category":"page"},{"location":"stdlib/Dates/#Dates.dayname","page":"日期","title":"Dates.dayname","text":"dayname(dt::TimeType; locale=\"english\") -> String\ndayname(day::Integer; locale=\"english\") -> String\n\nReturn the full day name corresponding to the day of the week of the Date or DateTime in the given locale. Also accepts Integer.\n\nExamples\n\njulia> Dates.dayname(Date(\"2000-01-01\"))\n\"Saturday\"\n\njulia> Dates.dayname(4)\n\"Thursday\"\n\n\n\n\n\n","category":"function"},{"location":"stdlib/Dates/#Dates.dayabbr","page":"日期","title":"Dates.dayabbr","text":"dayabbr(dt::TimeType; locale=\"english\") -> String\ndayabbr(day::Integer; locale=\"english\") -> String\n\nReturn the abbreviated name corresponding to the day of the week of the Date or DateTime in the given locale. Also accepts Integer.\n\nExamples\n\njulia> Dates.dayabbr(Date(\"2000-01-01\"))\n\"Sat\"\n\njulia> Dates.dayabbr(3)\n\"Wed\"\n\n\n\n\n\n","category":"function"},{"location":"stdlib/Dates/#Dates.dayofweek","page":"日期","title":"Dates.dayofweek","text":"dayofweek(dt::TimeType) -> Int64\n\nReturn the day of the week as an Int64 with 1 = Monday, 2 = Tuesday, etc..\n\nExamples\n\njulia> Dates.dayofweek(Date(\"2000-01-01\"))\n6\n\n\n\n\n\n","category":"function"},{"location":"stdlib/Dates/#Dates.dayofmonth","page":"日期","title":"Dates.dayofmonth","text":"dayofmonth(dt::TimeType) -> Int64\n\nThe day of month of a Date or DateTime as an Int64.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/Dates/#Dates.dayofweekofmonth","page":"日期","title":"Dates.dayofweekofmonth","text":"dayofweekofmonth(dt::TimeType) -> Int\n\nFor the day of week of dt, return which number it is in dt's month. So if the day of the week of dt is Monday, then 1 = First Monday of the month, 2 = Second Monday of the month, etc. In the range 1:5.\n\nExamples\n\njulia> Dates.dayofweekofmonth(Date(\"2000-02-01\"))\n1\n\njulia> Dates.dayofweekofmonth(Date(\"2000-02-08\"))\n2\n\njulia> Dates.dayofweekofmonth(Date(\"2000-02-15\"))\n3\n\n\n\n\n\n","category":"function"},{"location":"stdlib/Dates/#Dates.daysofweekinmonth","page":"日期","title":"Dates.daysofweekinmonth","text":"daysofweekinmonth(dt::TimeType) -> Int\n\nFor the day of week of dt, return the total number of that day of the week in dt's month. Returns 4 or 5. Useful in temporal expressions for specifying the last day of a week in a month by including dayofweekofmonth(dt) == daysofweekinmonth(dt) in the adjuster function.\n\nExamples\n\njulia> Dates.daysofweekinmonth(Date(\"2005-01-01\"))\n5\n\njulia> Dates.daysofweekinmonth(Date(\"2005-01-04\"))\n4\n\n\n\n\n\n","category":"function"},{"location":"stdlib/Dates/#Dates.monthname","page":"日期","title":"Dates.monthname","text":"monthname(dt::TimeType; locale=\"english\") -> String\nmonthname(month::Integer, locale=\"english\") -> String\n\nReturn the full name of the month of the Date or DateTime or Integer in the given locale.\n\nExamples\n\njulia> Dates.monthname(Date(\"2005-01-04\"))\n\"January\"\n\njulia> Dates.monthname(2)\n\"February\"\n\n\n\n\n\n","category":"function"},{"location":"stdlib/Dates/#Dates.monthabbr","page":"日期","title":"Dates.monthabbr","text":"monthabbr(dt::TimeType; locale=\"english\") -> String\nmonthabbr(month::Integer, locale=\"english\") -> String\n\nReturn the abbreviated month name of the Date or DateTime or Integer in the given locale.\n\nExamples\n\njulia> Dates.monthabbr(Date(\"2005-01-04\"))\n\"Jan\"\n\njulia> monthabbr(2)\n\"Feb\"\n\n\n\n\n\n","category":"function"},{"location":"stdlib/Dates/#Dates.daysinmonth","page":"日期","title":"Dates.daysinmonth","text":"daysinmonth(dt::TimeType) -> Int\n\nReturn the number of days in the month of dt. Value will be 28, 29, 30, or 31.\n\nExamples\n\njulia> Dates.daysinmonth(Date(\"2000-01\"))\n31\n\njulia> Dates.daysinmonth(Date(\"2001-02\"))\n28\n\njulia> Dates.daysinmonth(Date(\"2000-02\"))\n29\n\n\n\n\n\n","category":"function"},{"location":"stdlib/Dates/#Dates.isleapyear","page":"日期","title":"Dates.isleapyear","text":"isleapyear(dt::TimeType) -> Bool\n\nReturn true if the year of dt is a leap year.\n\nExamples\n\njulia> Dates.isleapyear(Date(\"2004\"))\ntrue\n\njulia> Dates.isleapyear(Date(\"2005\"))\nfalse\n\n\n\n\n\n","category":"function"},{"location":"stdlib/Dates/#Dates.dayofyear","page":"日期","title":"Dates.dayofyear","text":"dayofyear(dt::TimeType) -> Int\n\nReturn the day of the year for dt with January 1st being day 1.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/Dates/#Dates.daysinyear","page":"日期","title":"Dates.daysinyear","text":"daysinyear(dt::TimeType) -> Int\n\nReturn 366 if the year of dt is a leap year, otherwise return 365.\n\nExamples\n\njulia> Dates.daysinyear(1999)\n365\n\njulia> Dates.daysinyear(2000)\n366\n\n\n\n\n\n","category":"function"},{"location":"stdlib/Dates/#Dates.quarterofyear","page":"日期","title":"Dates.quarterofyear","text":"quarterofyear(dt::TimeType) -> Int\n\nReturn the quarter that dt resides in. Range of value is 1:4.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/Dates/#Dates.dayofquarter","page":"日期","title":"Dates.dayofquarter","text":"dayofquarter(dt::TimeType) -> Int\n\nReturn the day of the current quarter of dt. Range of value is 1:92.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/Dates/#Adjuster-Functions-2","page":"日期","title":"Adjuster Functions","text":"","category":"section"},{"location":"stdlib/Dates/","page":"日期","title":"日期","text":"Base.trunc(::Dates.TimeType, ::Type{Dates.Period})\nDates.firstdayofweek\nDates.lastdayofweek\nDates.firstdayofmonth\nDates.lastdayofmonth\nDates.firstdayofyear\nDates.lastdayofyear\nDates.firstdayofquarter\nDates.lastdayofquarter\nDates.tonext(::Dates.TimeType, ::Int)\nDates.toprev(::Dates.TimeType, ::Int)\nDates.tofirst\nDates.tolast\nDates.tonext(::Function, ::Dates.TimeType)\nDates.toprev(::Function, ::Dates.TimeType)","category":"page"},{"location":"stdlib/Dates/#Base.trunc-Tuple{TimeType, Type{Period}}","page":"日期","title":"Base.trunc","text":"trunc(dt::TimeType, ::Type{Period}) -> TimeType\n\nTruncates the value of dt according to the provided Period type.\n\nExamples\n\njulia> trunc(Dates.DateTime(\"1996-01-01T12:30:00\"), Dates.Day)\n1996-01-01T00:00:00\n\n\n\n\n\n","category":"method"},{"location":"stdlib/Dates/#Dates.firstdayofweek","page":"日期","title":"Dates.firstdayofweek","text":"firstdayofweek(dt::TimeType) -> TimeType\n\nAdjusts dt to the Monday of its week.\n\nExamples\n\njulia> Dates.firstdayofweek(DateTime(\"1996-01-05T12:30:00\"))\n1996-01-01T00:00:00\n\n\n\n\n\n","category":"function"},{"location":"stdlib/Dates/#Dates.lastdayofweek","page":"日期","title":"Dates.lastdayofweek","text":"lastdayofweek(dt::TimeType) -> TimeType\n\nAdjusts dt to the Sunday of its week.\n\nExamples\n\njulia> Dates.lastdayofweek(DateTime(\"1996-01-05T12:30:00\"))\n1996-01-07T00:00:00\n\n\n\n\n\n","category":"function"},{"location":"stdlib/Dates/#Dates.firstdayofmonth","page":"日期","title":"Dates.firstdayofmonth","text":"firstdayofmonth(dt::TimeType) -> TimeType\n\nAdjusts dt to the first day of its month.\n\nExamples\n\njulia> Dates.firstdayofmonth(DateTime(\"1996-05-20\"))\n1996-05-01T00:00:00\n\n\n\n\n\n","category":"function"},{"location":"stdlib/Dates/#Dates.lastdayofmonth","page":"日期","title":"Dates.lastdayofmonth","text":"lastdayofmonth(dt::TimeType) -> TimeType\n\nAdjusts dt to the last day of its month.\n\nExamples\n\njulia> Dates.lastdayofmonth(DateTime(\"1996-05-20\"))\n1996-05-31T00:00:00\n\n\n\n\n\n","category":"function"},{"location":"stdlib/Dates/#Dates.firstdayofyear","page":"日期","title":"Dates.firstdayofyear","text":"firstdayofyear(dt::TimeType) -> TimeType\n\nAdjusts dt to the first day of its year.\n\nExamples\n\njulia> Dates.firstdayofyear(DateTime(\"1996-05-20\"))\n1996-01-01T00:00:00\n\n\n\n\n\n","category":"function"},{"location":"stdlib/Dates/#Dates.lastdayofyear","page":"日期","title":"Dates.lastdayofyear","text":"lastdayofyear(dt::TimeType) -> TimeType\n\nAdjusts dt to the last day of its year.\n\nExamples\n\njulia> Dates.lastdayofyear(DateTime(\"1996-05-20\"))\n1996-12-31T00:00:00\n\n\n\n\n\n","category":"function"},{"location":"stdlib/Dates/#Dates.firstdayofquarter","page":"日期","title":"Dates.firstdayofquarter","text":"firstdayofquarter(dt::TimeType) -> TimeType\n\nAdjusts dt to the first day of its quarter.\n\nExamples\n\njulia> Dates.firstdayofquarter(DateTime(\"1996-05-20\"))\n1996-04-01T00:00:00\n\njulia> Dates.firstdayofquarter(DateTime(\"1996-08-20\"))\n1996-07-01T00:00:00\n\n\n\n\n\n","category":"function"},{"location":"stdlib/Dates/#Dates.lastdayofquarter","page":"日期","title":"Dates.lastdayofquarter","text":"lastdayofquarter(dt::TimeType) -> TimeType\n\nAdjusts dt to the last day of its quarter.\n\nExamples\n\njulia> Dates.lastdayofquarter(DateTime(\"1996-05-20\"))\n1996-06-30T00:00:00\n\njulia> Dates.lastdayofquarter(DateTime(\"1996-08-20\"))\n1996-09-30T00:00:00\n\n\n\n\n\n","category":"function"},{"location":"stdlib/Dates/#Dates.tonext-Tuple{TimeType, Int64}","page":"日期","title":"Dates.tonext","text":"tonext(dt::TimeType, dow::Int; same::Bool=false) -> TimeType\n\nAdjusts dt to the next day of week corresponding to dow with 1 = Monday, 2 = Tuesday, etc. Setting same=true allows the current dt to be considered as the next dow, allowing for no adjustment to occur.\n\n\n\n\n\n","category":"method"},{"location":"stdlib/Dates/#Dates.toprev-Tuple{TimeType, Int64}","page":"日期","title":"Dates.toprev","text":"toprev(dt::TimeType, dow::Int; same::Bool=false) -> TimeType\n\nAdjusts dt to the previous day of week corresponding to dow with 1 = Monday, 2 = Tuesday, etc. Setting same=true allows the current dt to be considered as the previous dow, allowing for no adjustment to occur.\n\n\n\n\n\n","category":"method"},{"location":"stdlib/Dates/#Dates.tofirst","page":"日期","title":"Dates.tofirst","text":"tofirst(dt::TimeType, dow::Int; of=Month) -> TimeType\n\nAdjusts dt to the first dow of its month. Alternatively, of=Year will adjust to the first dow of the year.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/Dates/#Dates.tolast","page":"日期","title":"Dates.tolast","text":"tolast(dt::TimeType, dow::Int; of=Month) -> TimeType\n\nAdjusts dt to the last dow of its month. Alternatively, of=Year will adjust to the last dow of the year.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/Dates/#Dates.tonext-Tuple{Function, TimeType}","page":"日期","title":"Dates.tonext","text":"tonext(func::Function, dt::TimeType; step=Day(1), limit=10000, same=false) -> TimeType\n\nAdjusts dt by iterating at most limit iterations by step increments until func returns true. func must take a single TimeType argument and return a Bool. same allows dt to be considered in satisfying func.\n\n\n\n\n\n","category":"method"},{"location":"stdlib/Dates/#Dates.toprev-Tuple{Function, TimeType}","page":"日期","title":"Dates.toprev","text":"toprev(func::Function, dt::TimeType; step=Day(-1), limit=10000, same=false) -> TimeType\n\nAdjusts dt by iterating at most limit iterations by step increments until func returns true. func must take a single TimeType argument and return a Bool. same allows dt to be considered in satisfying func.\n\n\n\n\n\n","category":"method"},{"location":"stdlib/Dates/#Periods","page":"日期","title":"Periods","text":"","category":"section"},{"location":"stdlib/Dates/","page":"日期","title":"日期","text":"Dates.Period(::Any)\nDates.CompoundPeriod(::Vector{<:Dates.Period})\nDates.value\nDates.default\nDates.periods","category":"page"},{"location":"stdlib/Dates/#Dates.Period-Tuple{Any}","page":"日期","title":"Dates.Period","text":"Year(v)\nQuarter(v)\nMonth(v)\nWeek(v)\nDay(v)\nHour(v)\nMinute(v)\nSecond(v)\nMillisecond(v)\nMicrosecond(v)\nNanosecond(v)\n\nConstruct a Period type with the given v value. Input must be losslessly convertible to an Int64.\n\n\n\n\n\n","category":"method"},{"location":"stdlib/Dates/#Dates.CompoundPeriod-Tuple{Vector{<:Period}}","page":"日期","title":"Dates.CompoundPeriod","text":"CompoundPeriod(periods) -> CompoundPeriod\n\nConstruct a CompoundPeriod from a Vector of Periods. All Periods of the same type will be added together.\n\nExamples\n\njulia> Dates.CompoundPeriod(Dates.Hour(12), Dates.Hour(13))\n25 hours\n\njulia> Dates.CompoundPeriod(Dates.Hour(-1), Dates.Minute(1))\n-1 hour, 1 minute\n\njulia> Dates.CompoundPeriod(Dates.Month(1), Dates.Week(-2))\n1 month, -2 weeks\n\njulia> Dates.CompoundPeriod(Dates.Minute(50000))\n50000 minutes\n\n\n\n\n\n","category":"method"},{"location":"stdlib/Dates/#Dates.value","page":"日期","title":"Dates.value","text":"Dates.value(x::Period) -> Int64\n\nFor a given period, return the value associated with that period. For example, value(Millisecond(10)) returns 10 as an integer.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/Dates/#Dates.default","page":"日期","title":"Dates.default","text":"default(p::Period) -> Period\n\nReturns a sensible \"default\" value for the input Period by returning T(1) for Year, Month, and Day, and T(0) for Hour, Minute, Second, and Millisecond.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/Dates/#Dates.periods","page":"日期","title":"Dates.periods","text":"Dates.periods(::CompoundPeriod) -> Vector{Period}\n\nReturn the Vector of Periods that comprise the given CompoundPeriod.\n\ncompat: Julia 1.7\nThis function requires Julia 1.7 or later.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/Dates/#Rounding-Functions","page":"日期","title":"Rounding Functions","text":"","category":"section"},{"location":"stdlib/Dates/","page":"日期","title":"日期","text":"Date and DateTime values can be rounded to a specified resolution (e.g., 1 month or 15 minutes) with floor, ceil, or round.","category":"page"},{"location":"stdlib/Dates/","page":"日期","title":"日期","text":"Base.floor(::Dates.TimeType, ::Dates.Period)\nBase.ceil(::Dates.TimeType, ::Dates.Period)\nBase.round(::Dates.TimeType, ::Dates.Period, ::RoundingMode{:NearestTiesUp})","category":"page"},{"location":"stdlib/Dates/#Base.floor-Tuple{TimeType, Period}","page":"日期","title":"Base.floor","text":"floor(dt::TimeType, p::Period) -> TimeType\n\nReturn the nearest Date or DateTime less than or equal to dt at resolution p.\n\nFor convenience, p may be a type instead of a value: floor(dt, Dates.Hour) is a shortcut for floor(dt, Dates.Hour(1)).\n\njulia> floor(Date(1985, 8, 16), Dates.Month)\n1985-08-01\n\njulia> floor(DateTime(2013, 2, 13, 0, 31, 20), Dates.Minute(15))\n2013-02-13T00:30:00\n\njulia> floor(DateTime(2016, 8, 6, 12, 0, 0), Dates.Day)\n2016-08-06T00:00:00\n\n\n\n\n\n","category":"method"},{"location":"stdlib/Dates/#Base.ceil-Tuple{TimeType, Period}","page":"日期","title":"Base.ceil","text":"ceil(dt::TimeType, p::Period) -> TimeType\n\nReturn the nearest Date or DateTime greater than or equal to dt at resolution p.\n\nFor convenience, p may be a type instead of a value: ceil(dt, Dates.Hour) is a shortcut for ceil(dt, Dates.Hour(1)).\n\njulia> ceil(Date(1985, 8, 16), Dates.Month)\n1985-09-01\n\njulia> ceil(DateTime(2013, 2, 13, 0, 31, 20), Dates.Minute(15))\n2013-02-13T00:45:00\n\njulia> ceil(DateTime(2016, 8, 6, 12, 0, 0), Dates.Day)\n2016-08-07T00:00:00\n\n\n\n\n\n","category":"method"},{"location":"stdlib/Dates/#Base.round-Tuple{TimeType, Period, RoundingMode{:NearestTiesUp}}","page":"日期","title":"Base.round","text":"round(dt::TimeType, p::Period, [r::RoundingMode]) -> TimeType\n\nReturn the Date or DateTime nearest to dt at resolution p. By default (RoundNearestTiesUp), ties (e.g., rounding 9:30 to the nearest hour) will be rounded up.\n\nFor convenience, p may be a type instead of a value: round(dt, Dates.Hour) is a shortcut for round(dt, Dates.Hour(1)).\n\njulia> round(Date(1985, 8, 16), Dates.Month)\n1985-08-01\n\njulia> round(DateTime(2013, 2, 13, 0, 31, 20), Dates.Minute(15))\n2013-02-13T00:30:00\n\njulia> round(DateTime(2016, 8, 6, 12, 0, 0), Dates.Day)\n2016-08-07T00:00:00\n\nValid rounding modes for round(::TimeType, ::Period, ::RoundingMode) are RoundNearestTiesUp (default), RoundDown (floor), and RoundUp (ceil).\n\n\n\n\n\n","category":"method"},{"location":"stdlib/Dates/","page":"日期","title":"日期","text":"Most Period values can also be rounded to a specified resolution:","category":"page"},{"location":"stdlib/Dates/","page":"日期","title":"日期","text":"Base.floor(::Dates.ConvertiblePeriod, ::T) where T <: Dates.ConvertiblePeriod\nBase.ceil(::Dates.ConvertiblePeriod, ::Dates.ConvertiblePeriod)\nBase.round(::Dates.ConvertiblePeriod, ::Dates.ConvertiblePeriod, ::RoundingMode{:NearestTiesUp})","category":"page"},{"location":"stdlib/Dates/#Base.floor-Union{Tuple{T}, Tuple{Union{Day, Week, TimePeriod}, T}} where T<:Union{Day, Week, TimePeriod}","page":"日期","title":"Base.floor","text":"floor(x::Period, precision::T) where T <: Union{TimePeriod, Week, Day} -> T\n\nRound x down to the nearest multiple of precision. If x and precision are different subtypes of Period, the return value will have the same type as precision.\n\nFor convenience, precision may be a type instead of a value: floor(x, Dates.Hour) is a shortcut for floor(x, Dates.Hour(1)).\n\njulia> floor(Dates.Day(16), Dates.Week)\n2 weeks\n\njulia> floor(Dates.Minute(44), Dates.Minute(15))\n30 minutes\n\njulia> floor(Dates.Hour(36), Dates.Day)\n1 day\n\nRounding to a precision of Months or Years is not supported, as these Periods are of inconsistent length.\n\n\n\n\n\n","category":"method"},{"location":"stdlib/Dates/#Base.ceil-Tuple{Union{Day, Week, TimePeriod}, Union{Day, Week, TimePeriod}}","page":"日期","title":"Base.ceil","text":"ceil(x::Period, precision::T) where T <: Union{TimePeriod, Week, Day} -> T\n\nRound x up to the nearest multiple of precision. If x and precision are different subtypes of Period, the return value will have the same type as precision.\n\nFor convenience, precision may be a type instead of a value: ceil(x, Dates.Hour) is a shortcut for ceil(x, Dates.Hour(1)).\n\njulia> ceil(Dates.Day(16), Dates.Week)\n3 weeks\n\njulia> ceil(Dates.Minute(44), Dates.Minute(15))\n45 minutes\n\njulia> ceil(Dates.Hour(36), Dates.Day)\n2 days\n\nRounding to a precision of Months or Years is not supported, as these Periods are of inconsistent length.\n\n\n\n\n\n","category":"method"},{"location":"stdlib/Dates/#Base.round-Tuple{Union{Day, Week, TimePeriod}, Union{Day, Week, TimePeriod}, RoundingMode{:NearestTiesUp}}","page":"日期","title":"Base.round","text":"round(x::Period, precision::T, [r::RoundingMode]) where T <: Union{TimePeriod, Week, Day} -> T\n\nRound x to the nearest multiple of precision. If x and precision are different subtypes of Period, the return value will have the same type as precision. By default (RoundNearestTiesUp), ties (e.g., rounding 90 minutes to the nearest hour) will be rounded up.\n\nFor convenience, precision may be a type instead of a value: round(x, Dates.Hour) is a shortcut for round(x, Dates.Hour(1)).\n\njulia> round(Dates.Day(16), Dates.Week)\n2 weeks\n\njulia> round(Dates.Minute(44), Dates.Minute(15))\n45 minutes\n\njulia> round(Dates.Hour(36), Dates.Day)\n2 days\n\nValid rounding modes for round(::Period, ::T, ::RoundingMode) are RoundNearestTiesUp (default), RoundDown (floor), and RoundUp (ceil).\n\nRounding to a precision of Months or Years is not supported, as these Periods are of inconsistent length.\n\n\n\n\n\n","category":"method"},{"location":"stdlib/Dates/","page":"日期","title":"日期","text":"The following functions are not exported:","category":"page"},{"location":"stdlib/Dates/","page":"日期","title":"日期","text":"Dates.floorceil\nDates.epochdays2date\nDates.epochms2datetime\nDates.date2epochdays\nDates.datetime2epochms","category":"page"},{"location":"stdlib/Dates/#Dates.floorceil","page":"日期","title":"Dates.floorceil","text":"floorceil(dt::TimeType, p::Period) -> (TimeType, TimeType)\n\nSimultaneously return the floor and ceil of a Date or DateTime at resolution p. More efficient than calling both floor and ceil individually.\n\n\n\n\n\nfloorceil(x::Period, precision::T) where T <: Union{TimePeriod, Week, Day} -> (T, T)\n\nSimultaneously return the floor and ceil of Period at resolution p. More efficient than calling both floor and ceil individually.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/Dates/#Dates.epochdays2date","page":"日期","title":"Dates.epochdays2date","text":"epochdays2date(days) -> Date\n\nTake the number of days since the rounding epoch (0000-01-01T00:00:00) and return the corresponding Date.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/Dates/#Dates.epochms2datetime","page":"日期","title":"Dates.epochms2datetime","text":"epochms2datetime(milliseconds) -> DateTime\n\nTake the number of milliseconds since the rounding epoch (0000-01-01T00:00:00) and return the corresponding DateTime.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/Dates/#Dates.date2epochdays","page":"日期","title":"Dates.date2epochdays","text":"date2epochdays(dt::Date) -> Int64\n\nTake the given Date and return the number of days since the rounding epoch (0000-01-01T00:00:00) as an Int64.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/Dates/#Dates.datetime2epochms","page":"日期","title":"Dates.datetime2epochms","text":"datetime2epochms(dt::DateTime) -> Int64\n\nTake the given DateTime and return the number of milliseconds since the rounding epoch (0000-01-01T00:00:00) as an Int64.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/Dates/#Conversion-Functions","page":"日期","title":"Conversion Functions","text":"","category":"section"},{"location":"stdlib/Dates/","page":"日期","title":"日期","text":"Dates.today\nDates.unix2datetime\nDates.datetime2unix\nDates.julian2datetime\nDates.datetime2julian\nDates.rata2datetime\nDates.datetime2rata","category":"page"},{"location":"stdlib/Dates/#Dates.today","page":"日期","title":"Dates.today","text":"today() -> Date\n\nReturn the date portion of now().\n\n\n\n\n\n","category":"function"},{"location":"stdlib/Dates/#Dates.unix2datetime","page":"日期","title":"Dates.unix2datetime","text":"unix2datetime(x) -> DateTime\n\nTake the number of seconds since unix epoch 1970-01-01T00:00:00 and convert to the corresponding DateTime.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/Dates/#Dates.datetime2unix","page":"日期","title":"Dates.datetime2unix","text":"datetime2unix(dt::DateTime) -> Float64\n\nTake the given DateTime and return the number of seconds since the unix epoch 1970-01-01T00:00:00 as a Float64.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/Dates/#Dates.julian2datetime","page":"日期","title":"Dates.julian2datetime","text":"julian2datetime(julian_days) -> DateTime\n\nTake the number of Julian calendar days since epoch -4713-11-24T12:00:00 and return the corresponding DateTime.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/Dates/#Dates.datetime2julian","page":"日期","title":"Dates.datetime2julian","text":"datetime2julian(dt::DateTime) -> Float64\n\nTake the given DateTime and return the number of Julian calendar days since the julian epoch -4713-11-24T12:00:00 as a Float64.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/Dates/#Dates.rata2datetime","page":"日期","title":"Dates.rata2datetime","text":"rata2datetime(days) -> DateTime\n\nTake the number of Rata Die days since epoch 0000-12-31T00:00:00 and return the corresponding DateTime.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/Dates/#Dates.datetime2rata","page":"日期","title":"Dates.datetime2rata","text":"datetime2rata(dt::TimeType) -> Int64\n\nReturn the number of Rata Die days since epoch from the given Date or DateTime.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/Dates/#Constants","page":"日期","title":"Constants","text":"","category":"section"},{"location":"stdlib/Dates/","page":"日期","title":"日期","text":"Days of the Week:","category":"page"},{"location":"stdlib/Dates/","page":"日期","title":"日期","text":"Variable Abbr. Value (Int)\nMonday Mon 1\nTuesday Tue 2\nWednesday Wed 3\nThursday Thu 4\nFriday Fri 5\nSaturday Sat 6\nSunday Sun 7","category":"page"},{"location":"stdlib/Dates/","page":"日期","title":"日期","text":"Months of the Year:","category":"page"},{"location":"stdlib/Dates/","page":"日期","title":"日期","text":"Variable Abbr. Value (Int)\nJanuary Jan 1\nFebruary Feb 2\nMarch Mar 3\nApril Apr 4\nMay May 5\nJune Jun 6\nJuly Jul 7\nAugust Aug 8\nSeptember Sep 9\nOctober Oct 10\nNovember Nov 11\nDecember Dec 12","category":"page"},{"location":"stdlib/Dates/#Common-Date-Formatters","page":"日期","title":"Common Date Formatters","text":"","category":"section"},{"location":"stdlib/Dates/","page":"日期","title":"日期","text":"ISODateTimeFormat\nISODateFormat\nISOTimeFormat\nRFC1123Format","category":"page"},{"location":"stdlib/Dates/#Dates.ISODateTimeFormat","page":"日期","title":"Dates.ISODateTimeFormat","text":"Dates.ISODateTimeFormat\n\nDescribes the ISO8601 formatting for a date and time. This is the default value for Dates.format of a DateTime.\n\nExample\n\njulia> Dates.format(DateTime(2018, 8, 8, 12, 0, 43, 1), ISODateTimeFormat)\n\"2018-08-08T12:00:43.001\"\n\n\n\n\n\n","category":"constant"},{"location":"stdlib/Dates/#Dates.ISODateFormat","page":"日期","title":"Dates.ISODateFormat","text":"Dates.ISODateFormat\n\nDescribes the ISO8601 formatting for a date. This is the default value for Dates.format of a Date.\n\nExample\n\njulia> Dates.format(Date(2018, 8, 8), ISODateFormat)\n\"2018-08-08\"\n\n\n\n\n\n","category":"constant"},{"location":"stdlib/Dates/#Dates.ISOTimeFormat","page":"日期","title":"Dates.ISOTimeFormat","text":"Dates.ISOTimeFormat\n\nDescribes the ISO8601 formatting for a time. This is the default value for Dates.format of a Time.\n\nExample\n\njulia> Dates.format(Time(12, 0, 43, 1), ISOTimeFormat)\n\"12:00:43.001\"\n\n\n\n\n\n","category":"constant"},{"location":"stdlib/Dates/#Dates.RFC1123Format","page":"日期","title":"Dates.RFC1123Format","text":"Dates.RFC1123Format\n\nDescribes the RFC1123 formatting for a date and time.\n\nExample\n\njulia> Dates.format(DateTime(2018, 8, 8, 12, 0, 43, 1), RFC1123Format)\n\"Wed, 08 Aug 2018 12:00:43\"\n\n\n\n\n\n","category":"constant"},{"location":"stdlib/Dates/","page":"日期","title":"日期","text":"DocTestSetup = nothing","category":"page"},{"location":"stdlib/TOML/#TOML","page":"TOML","title":"TOML","text":"","category":"section"},{"location":"stdlib/TOML/","page":"TOML","title":"TOML","text":"TOML.jl is a Julia standard library for parsing and writing TOML v1.0 files.","category":"page"},{"location":"stdlib/TOML/#Parsing-TOML-data","page":"TOML","title":"Parsing TOML data","text":"","category":"section"},{"location":"stdlib/TOML/","page":"TOML","title":"TOML","text":"julia> using TOML\n\njulia> data = \"\"\"\n [database]\n server = \"192.168.1.1\"\n ports = [ 8001, 8001, 8002 ]\n \"\"\";\n\njulia> TOML.parse(data)\nDict{String, Any} with 1 entry:\n \"database\" => Dict{String, Any}(\"server\"=>\"192.168.1.1\", \"ports\"=>[8001, 8001…","category":"page"},{"location":"stdlib/TOML/","page":"TOML","title":"TOML","text":"To parse a file, use TOML.parsefile. If the file has a syntax error, an exception is thrown:","category":"page"},{"location":"stdlib/TOML/","page":"TOML","title":"TOML","text":"julia> using TOML\n\njulia> TOML.parse(\"\"\"\n value = 0.0.0\n \"\"\")\nERROR: TOML Parser error:\nnone:1:16 error: failed to parse value\n value = 0.0.0\n ^\n[...]","category":"page"},{"location":"stdlib/TOML/","page":"TOML","title":"TOML","text":"There are other versions of the parse functions (TOML.tryparse and [TOML.tryparsefile]) that instead of throwing exceptions on parser error returns a TOML.ParserError with information:","category":"page"},{"location":"stdlib/TOML/","page":"TOML","title":"TOML","text":"julia> using TOML\n\njulia> err = TOML.tryparse(\"\"\"\n value = 0.0.0\n \"\"\");\n\njulia> err.type\nErrGenericValueError::ErrorType = 14\n\njulia> err.line\n1\n\njulia> err.column\n16","category":"page"},{"location":"stdlib/TOML/#Exporting-data-to-TOML-file","page":"TOML","title":"Exporting data to TOML file","text":"","category":"section"},{"location":"stdlib/TOML/","page":"TOML","title":"TOML","text":"The TOML.print function is used to print (or serialize) data into TOML format.","category":"page"},{"location":"stdlib/TOML/","page":"TOML","title":"TOML","text":"julia> using TOML\n\njulia> data = Dict(\n \"names\" => [\"Julia\", \"Julio\"],\n \"age\" => [10, 20],\n );\n\njulia> TOML.print(data)\nnames = [\"Julia\", \"Julio\"]\nage = [10, 20]\n\njulia> fname = tempname();\n\njulia> open(fname, \"w\") do io\n TOML.print(io, data)\n end\n\njulia> TOML.parsefile(fname)\nDict{String, Any} with 2 entries:\n \"names\" => [\"Julia\", \"Julio\"]\n \"age\" => [10, 20]","category":"page"},{"location":"stdlib/TOML/","page":"TOML","title":"TOML","text":"Keys can be sorted according to some value","category":"page"},{"location":"stdlib/TOML/","page":"TOML","title":"TOML","text":"julia> using TOML\n\njulia> TOML.print(Dict(\n \"abc\" => 1,\n \"ab\" => 2,\n \"abcd\" => 3,\n ); sorted=true, by=length)\nab = 2\nabc = 1\nabcd = 3","category":"page"},{"location":"stdlib/TOML/","page":"TOML","title":"TOML","text":"For custom structs, pass a function that converts the struct to a supported type","category":"page"},{"location":"stdlib/TOML/","page":"TOML","title":"TOML","text":"julia> using TOML\n\njulia> struct MyStruct\n a::Int\n b::String\n end\n\njulia> TOML.print(Dict(\"foo\" => MyStruct(5, \"bar\"))) do x\n x isa MyStruct && return [x.a, x.b]\n error(\"unhandled type $(typeof(x))\")\n end\nfoo = [5, \"bar\"]","category":"page"},{"location":"stdlib/TOML/#References","page":"TOML","title":"References","text":"","category":"section"},{"location":"stdlib/TOML/","page":"TOML","title":"TOML","text":"TOML.parse\nTOML.parsefile\nTOML.tryparse\nTOML.tryparsefile\nTOML.print\nTOML.Parser\nTOML.ParserError","category":"page"},{"location":"stdlib/TOML/#TOML.parse","page":"TOML","title":"TOML.parse","text":"parse(x::Union{AbstractString, IO})\nparse(p::Parser, x::Union{AbstractString, IO})\n\nParse the string or stream x, and return the resulting table (dictionary). Throw a ParserError upon failure.\n\nSee also TOML.tryparse.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/TOML/#TOML.parsefile","page":"TOML","title":"TOML.parsefile","text":"parsefile(f::AbstractString)\nparsefile(p::Parser, f::AbstractString)\n\nParse file f and return the resulting table (dictionary). Throw a ParserError upon failure.\n\nSee also TOML.tryparsefile.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/TOML/#TOML.tryparse","page":"TOML","title":"TOML.tryparse","text":"tryparse(x::Union{AbstractString, IO})\ntryparse(p::Parser, x::Union{AbstractString, IO})\n\nParse the string or stream x, and return the resulting table (dictionary). Return a ParserError upon failure.\n\nSee also TOML.parse.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/TOML/#TOML.tryparsefile","page":"TOML","title":"TOML.tryparsefile","text":"tryparsefile(f::AbstractString)\ntryparsefile(p::Parser, f::AbstractString)\n\nParse file f and return the resulting table (dictionary). Return a ParserError upon failure.\n\nSee also TOML.parsefile.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/TOML/#TOML.print","page":"TOML","title":"TOML.print","text":"print([to_toml::Function], io::IO [=stdout], data::AbstractDict; sorted=false, by=identity)\n\nWrite data as TOML syntax to the stream io. If the keyword argument sorted is set to true, sort tables according to the function given by the keyword argument by.\n\nThe following data types are supported: AbstractDict, Integer, AbstractFloat, Bool, Dates.DateTime, Dates.Time, Dates.Date. Note that the integers and floats need to be convertible to Float64 and Int64 respectively. For other data types, pass the function to_toml that takes the data types and returns a value of a supported type.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/TOML/#TOML.Parser","page":"TOML","title":"TOML.Parser","text":"Parser()\n\nConstructor for a TOML Parser. Note that in most cases one does not need to explicitly create a Parser but instead one directly use use TOML.parsefile or TOML.parse. Using an explicit parser will however reuse some internal data structures which can be beneficial for performance if a larger number of small files are parsed.\n\n\n\n\n\n","category":"type"},{"location":"stdlib/TOML/#TOML.ParserError","page":"TOML","title":"TOML.ParserError","text":"ParserError\n\nType that is returned from tryparse and tryparsefile when parsing fails. It contains (among others) the following fields:\n\npos, the position in the string when the error happened\ntable, the result that so far was successfully parsed\ntype, an error type, different for different types of errors\n\n\n\n\n\n","category":"type"},{"location":"manual/command-line-options/#command-line-options","page":"命令行选项","title":"命令行选项","text":"","category":"section"},{"location":"manual/command-line-options/","page":"命令行选项","title":"命令行选项","text":"以下是启动 julia 时可用的命令行选项的完整列表:","category":"page"},{"location":"manual/command-line-options/","page":"命令行选项","title":"命令行选项","text":"选项 描述\n-v, --version 显示版本信息\n-h, --help 显示命令行参数\n--project[={|@.}] 将 设置为主项目/环境。默认的 @. 选项将搜索父目录,直至找到 Project.toml 或 JuliaProject.toml 文件。\n-J, --sysimage 用指定的系统镜像文件(system image file)启动\n-H, --home 设置 julia 可执行文件的路径\n--startup-file={yes|no} 是否载入 ~/.julia/config/startup.jl\n--handle-signals={yes|no} 开启或关闭 Julia 默认的 signal handlers\n--sysimage-native-code={yes|no} 在可能的情况下,使用系统镜像里的原生代码\n--compiled-modules={yes|no} 开启或关闭 module 的增量预编译功能\n-e, --eval 执行 \n-E, --print 执行 并显示结果\n-L, --load 立即在所有进程中载入 \n-t, --threads {N|auto} 开启 N 个线程:auto 将 N 设置为当前 CPU 线程数,但这个行为可能在以后版本有所变动。\n-p, --procs {N|auto} 这里的整数 N 表示启动 N 个额外的工作进程;auto 表示启动与 CPU 线程数目(logical cores)一样多的进程\n--machine-file 中列出的主机上运行进程\n-i 交互式模式;REPL 运行且 isinteractive() 为 true\n-q, --quiet 安静的启动;REPL 启动时无横幅,不显示警告\n--banner={yes|no|auto} 开启或关闭 REPL 横幅\n--color={yes|no|auto} 开启或关闭文字颜色\n--history-file={yes|no} 载入或导出历史记录\n--depwarn={yes|no|error} 开启或关闭语法弃用警告,error 表示将弃用警告转换为错误。\n--warn-overwrite={yes|no} 开启或关闭“method overwrite”警告\n-C, --cpu-target 设置 来限制使用 CPU 的某些特性;设置为 help 可以查看可用的选项\n-O, --optimize={0,1,2,3} 设置编译器优化级别(若未配置此选项,则默认等级为2;若配置了此选项却没指定具体级别,则默认级别为3)。\n--min-optlevel={0,1,2,3} 设置每个模块加载的优化下限(默认为 0)\n-g, -g 开启或设置 debug 信息的生成等级。若未配置此选项,则默认 debug 信息的级别为 1;若配置了此选项却没指定具体级别,则默认级别为 2。\n--inline={yes|no} 控制是否允许函数内联,此选项会覆盖源文件中的 @inline 声明\n--check-bounds={yes|no|auto} 进行边界检查,总是、从不、或依照宏@inbounds声明\n--math-mode={ieee,fast} 开启或关闭非安全的浮点数代数计算优化,此选项会覆盖源文件中的 @fastmath 声明\n--code-coverage={none|user|all} 对源文件中每行代码执行的次数计数\n--code-coverage 等价于 --code-coverage=user\n--track-allocation={none|user|all} 对源文件中每行代码的内存分配计数,单位 byte\n--track-allocation 等价于 --track-allocation=user","category":"page"},{"location":"manual/command-line-options/","page":"命令行选项","title":"命令行选项","text":"compat: Julia 1.1\n在 Julia 1.0 中,默认的 --project=@. 选项不会在 Git 仓库的根目录中寻找 Project.toml 文件。从 Julia 1.1 开始,此选项会在其中寻找该文件。","category":"page"},{"location":"manual/asynchronous-programming/#man-asynchronous","page":"异步编程","title":"异步编程","text":"","category":"section"},{"location":"manual/asynchronous-programming/","page":"异步编程","title":"异步编程","text":"当程序需要与外部世界交互时,例如通过互联网与另一台机器通信时,程序中的操作可能需要以无法预测的顺序发生。假设你的程序需要下载一个文件。我们想启动下载操作,在等待下载完成的同时执行其他操作,然后在空闲时继续执行下载文件的代码。这种场景属于异步编程,有时也称为并发编程(因为从概念上讲,同时发生多种事情)。","category":"page"},{"location":"manual/asynchronous-programming/","page":"异步编程","title":"异步编程","text":"为了解决这些可能的情况,Julia 提供了任务 Task(也有其他几个名称,例如对称协程、轻量级线程、协作多任务处理或one-shot continuations)。当一项计算工作(实际上,执行特定功能)被指定为 Task 时,可以通过切换到另一个 Task 来中断它。 最初的 Task 稍后可以恢复,此时它将从上次中断的地方开始。 初看这似乎类似于函数调用。 但是,有两个关键区别。 首先,切换任务不占用任何空间,因此可以在不消耗调用堆栈的情况下进行任意数量的任务切换。 其次,任务之间的切换可以以任何顺序发生,这与函数调用不同,在函数调用中,被调用的函数必须在返回到调用函数之前完成执行。","category":"page"},{"location":"manual/asynchronous-programming/#基本-Task-操作","page":"异步编程","title":"基本 Task 操作","text":"","category":"section"},{"location":"manual/asynchronous-programming/","page":"异步编程","title":"异步编程","text":"你可以将Task视为要执行的计算工作单元的句柄。 它有一个创建-开始-运行-结束的生命周期。 Task 是通过在要运行的 0 参数函数上调用 Task 构造函数来创建的,或者使用 @task 宏:","category":"page"},{"location":"manual/asynchronous-programming/","page":"异步编程","title":"异步编程","text":"julia> t = @task begin; sleep(5); println(\"done\"); end\nTask (runnable) @0x00007f13a40c0eb0","category":"page"},{"location":"manual/asynchronous-programming/","page":"异步编程","title":"异步编程","text":"@task x 等价于 Task(()->x)。","category":"page"},{"location":"manual/asynchronous-programming/","page":"异步编程","title":"异步编程","text":"此任务将等待五秒钟,然后打印done。 但是,它还没有开始运行。 我们可以随时通过调用 schedule 来运行它:","category":"page"},{"location":"manual/asynchronous-programming/","page":"异步编程","title":"异步编程","text":"julia> schedule(t);","category":"page"},{"location":"manual/asynchronous-programming/","page":"异步编程","title":"异步编程","text":"如果你在 REPL 中尝试这个,你会看到 schedule 立即有返回值。那是因为它只是将 t 添加到要运行的内部任务队列中。然后,REPL 将打印下一个提示并等待更多输入。等待键盘输入为其他任务提供了运行的机会,因此此时 t 将启动。 t 调用 sleep,它设置一个计时器并停止执行。 如果已经安排了其他任务,那么它们就可以运行了。五秒后,计时器触发并重新启动t,你将看到打印的done。 然后t 执行完毕了。","category":"page"},{"location":"manual/asynchronous-programming/","page":"异步编程","title":"异步编程","text":"wait 函数会阻塞调用任务,直到其他任务完成。 例如,如果输入:","category":"page"},{"location":"manual/asynchronous-programming/","page":"异步编程","title":"异步编程","text":"julia> schedule(t); wait(t)","category":"page"},{"location":"manual/asynchronous-programming/","page":"异步编程","title":"异步编程","text":"在下一个输入提示出现之前,你将看到五秒钟的停顿,而不是只调用 schedule。 那是因为 REPL 等待 t 完成之后才继续。","category":"page"},{"location":"manual/asynchronous-programming/","page":"异步编程","title":"异步编程","text":"一般来说,创建一个任务会想立即执行它,为此提供了宏 @async –- @async x 等价于 schedule(@task x )。","category":"page"},{"location":"manual/asynchronous-programming/#在-Channel-中进行通信","page":"异步编程","title":"在 Channel 中进行通信","text":"","category":"section"},{"location":"manual/asynchronous-programming/","page":"异步编程","title":"异步编程","text":"在某些问题中,所需的各种工作并不是通过函数调用自然关联的; 在需要完成的工作中没有明显的“调用者”或“被调用者”。 一个典型的例子是生产者-消费者问题,其中一个复杂的过程正在生成值,而另一个复杂的过程正在消耗它们。消费者不能简单地调用生产者函数来获取一个值,因为生产者可能有更多的值要生成,因此可能还没有准备好返回。对于任务,生产者和消费者都可以根据需要运行,根据需要来回传递值。","category":"page"},{"location":"manual/asynchronous-programming/","page":"异步编程","title":"异步编程","text":"Julia 提供了 Channel 机制来解决这个问题。一个 Channel 是一个先进先出的队列,允许多个 Task 对它可以进行读和写。","category":"page"},{"location":"manual/asynchronous-programming/","page":"异步编程","title":"异步编程","text":"让我们定义一个生产者任务,调用 put! 来生产数值。为了消费数值,我们需要对生产者开始新任务进行排班。可以使用一个特殊的 Channel 组件来运行一个与其绑定的 Task,它能接受单参数函数作为其参数,然后可以用 take! 从 Channel 对象里不断地提取值:","category":"page"},{"location":"manual/asynchronous-programming/","page":"异步编程","title":"异步编程","text":"julia> function producer(c::Channel)\n put!(c, \"start\")\n for n=1:4\n put!(c, 2n)\n end\n put!(c, \"stop\")\n end;\n\njulia> chnl = Channel(producer);\n\njulia> take!(chnl)\n\"start\"\n\njulia> take!(chnl)\n2\n\njulia> take!(chnl)\n4\n\njulia> take!(chnl)\n6\n\njulia> take!(chnl)\n8\n\njulia> take!(chnl)\n\"stop\"","category":"page"},{"location":"manual/asynchronous-programming/","page":"异步编程","title":"异步编程","text":"一种思考这种行为的方式是,“生产者”能够多次返回。在两次调用 put! 之间,生产者的执行是挂起的,此时由消费者接管控制。","category":"page"},{"location":"manual/asynchronous-programming/","page":"异步编程","title":"异步编程","text":"返回的 Channel 可以被用作一个 for 循环的迭代对象,此时循环变量会依次取到所有产生的值。当 Channel 关闭时,循环就会终止。","category":"page"},{"location":"manual/asynchronous-programming/","page":"异步编程","title":"异步编程","text":"julia> for x in Channel(producer)\n println(x)\n end\nstart\n2\n4\n6\n8\nstop","category":"page"},{"location":"manual/asynchronous-programming/","page":"异步编程","title":"异步编程","text":"注意我们并不需要显式地在生产者中关闭 Channel。这是因为 Channel 对 Task 的绑定同时也意味着 Channel 的生命周期与绑定的 Task 一致。当 Task 结束时,Channel 对象会自动关闭。多个 Channel 可以绑定到一个 Task,反之亦然。","category":"page"},{"location":"manual/asynchronous-programming/","page":"异步编程","title":"异步编程","text":"Task 构造函数需要一个不带参数的函数,而创建任务绑定的 channel 的 Channel 方法需要一个接受 Channel类型的单个参数的函数。 一个常见的模式是对生产者进行参数化,在这种情况下,需要一个偏函数来创建一个 0 或 1 个参数 匿名函数。","category":"page"},{"location":"manual/asynchronous-programming/","page":"异步编程","title":"异步编程","text":"对于 Task 对象,可以直接用,也可以为了方便用宏。","category":"page"},{"location":"manual/asynchronous-programming/","page":"异步编程","title":"异步编程","text":"function mytask(myarg)\n ...\nend\n\ntaskHdl = Task(() -> mytask(7))\n# or, equivalently\ntaskHdl = @task mytask(7)","category":"page"},{"location":"manual/asynchronous-programming/","page":"异步编程","title":"异步编程","text":"为了安排更高级的工作分配模式,bind 和 schedule 可以与 Task 和 Channel 构造函数配合使用,显式地连接一些 Channel 和生产者或消费者 Task。","category":"page"},{"location":"manual/asynchronous-programming/#更多关于-Channel-的知识","page":"异步编程","title":"更多关于 Channel 的知识","text":"","category":"section"},{"location":"manual/asynchronous-programming/","page":"异步编程","title":"异步编程","text":"一个管道可以形象得看做是一个管子,一端可读,另一端可写:","category":"page"},{"location":"manual/asynchronous-programming/","page":"异步编程","title":"异步编程","text":"不同的 task 可以通过 put! 往同一个 channel 并发地写入。\n不同的 task 也可以通过 take! 从同一个 channel 并发地取数据\n举个例子:\n# Given Channels c1 and c2,\nc1 = Channel(32)\nc2 = Channel(32)\n\n# and a function `foo` which reads items from c1, processes the item read\n# and writes a result to c2,\nfunction foo()\n while true\n data = take!(c1)\n [...] # process data\n put!(c2, result) # write out result\n end\nend\n\n# we can schedule `n` instances of `foo` to be active concurrently.\nfor _ in 1:n\n errormonitor(@async foo())\nend\nChannel 可以通过 Channel{T}(sz) 构造,得到的 channel 只能存储类型 T 的数据。如果 T 没有指定,那么 channel 可以存任意类型。sz 表示该 channel 能够存储的最大元素个数。比如 Channel(32) 得到的 channel 最多可以存储32个元素。而 Channel{MyType}(64) 则可以最多存储64个 MyType 类型的数据。\n如果一个 Channel 是空的,读取的 task(即执行 take! 的 task)会被阻塞直到有新的数据准备好了。\n如果一个 Channel 是满的,那么写入的 task(即执行 put! 的 task)则会被阻塞,直到 Channel 有空余。\n\n一个 Channel 一开始处于开启状态,也就是说可以被 take! 读取和 put! 写入。close 会关闭一个 Channel,对于一个已经关闭的 Channel,put! 会失败,例如:\njulia> c = Channel(2);\n\njulia> put!(c, 1) # `put!` on an open channel succeeds\n1\n\njulia> close(c);\n\njulia> put!(c, 2) # `put!` on a closed channel throws an exception.\nERROR: InvalidStateException(\"Channel is closed.\",:closed)\nStacktrace:\n[...]\ntake! 和 fetch (只读取,不会将元素从 channel 中删掉)仍然可以从一个已经关闭的 channel 中读数据,直到 channel 被取空了为止。继续上面的例子:\njulia> fetch(c) # Any number of `fetch` calls succeed.\n1\n\njulia> fetch(c)\n1\n\njulia> take!(c) # The first `take!` removes the value.\n1\n\njulia> take!(c) # No more data available on a closed channel.\nERROR: InvalidStateException(\"Channel is closed.\",:closed)\nStacktrace:\n[...]","category":"page"},{"location":"manual/asynchronous-programming/","page":"异步编程","title":"异步编程","text":"考虑这样一个用 channel 做 task 之间通信的例子。首先,起 4 个 task 来处理一个 jobs channel 中的数据。jobs 中的每个任务通过 job_id 来表示,然后每个 task 模拟读取一个 job_id,然后随机等待一会儿,然后往一个 results channel 中写入一个元组,它分别包含 job_id 和执行的时间,最后将结果打印出来:","category":"page"},{"location":"manual/asynchronous-programming/","page":"异步编程","title":"异步编程","text":"julia> const jobs = Channel{Int}(32);\n\njulia> const results = Channel{Tuple}(32);\n\njulia> function do_work()\n for job_id in jobs\n exec_time = rand()\n sleep(exec_time) # simulates elapsed time doing actual work\n # typically performed externally.\n put!(results, (job_id, exec_time))\n end\n end;\n\njulia> function make_jobs(n)\n for i in 1:n\n put!(jobs, i)\n end\n end;\n\njulia> n = 12;\n\njulia> errormonitor(@async make_jobs(n)); # feed the jobs channel with \"n\" jobs\n\njulia> for i in 1:4 # start 4 tasks to process requests in parallel\n errormonitor(@async do_work())\n end\n\njulia> @elapsed while n > 0 # print out results\n job_id, exec_time = take!(results)\n println(\"$job_id finished in $(round(exec_time; digits=2)) seconds\")\n global n = n - 1\n end\n4 finished in 0.22 seconds\n3 finished in 0.45 seconds\n1 finished in 0.5 seconds\n7 finished in 0.14 seconds\n2 finished in 0.78 seconds\n5 finished in 0.9 seconds\n9 finished in 0.36 seconds\n6 finished in 0.87 seconds\n8 finished in 0.79 seconds\n10 finished in 0.64 seconds\n12 finished in 0.5 seconds\n11 finished in 0.97 seconds\n0.029772311","category":"page"},{"location":"manual/asynchronous-programming/","page":"异步编程","title":"异步编程","text":"不用 errormonitor(t),一个更稳健的解决方案是使用 bind(results, t),这不仅会记录任何意外故障,还会强制相关资源关闭并向上抛出错误。","category":"page"},{"location":"manual/asynchronous-programming/#更多任务操作","page":"异步编程","title":"更多任务操作","text":"","category":"section"},{"location":"manual/asynchronous-programming/","page":"异步编程","title":"异步编程","text":"任务操作建立在称为 yieldto 的底层原始运算上。 yieldto(task, value) 挂起当前 task,然后切换到指定的 task,并使该任务的最后一个 yieldto 调用返回指定的 value。 请注意,yieldto 是使用任务式流程控制所需的唯一操作;我们总是切换到不同的任务,而不是调用和返回。 这就是为什么这个特性也被称为“对称协程”; 每个任务都使用相同的机制来回切换。","category":"page"},{"location":"manual/asynchronous-programming/","page":"异步编程","title":"异步编程","text":"yieldto 功能强大,但大多数 Task 的使用都不会直接调用它。思考为什么会这样。如果你切换当前 Task,你很可能会在某个时候想切换回来。但知道什么时候切换回来和那个 Task 负责切换回来需要大量的协调。例如,put! 和 take! 是阻塞操作,当在渠道环境中使用时,维持状态以记住消费者是谁。不需要人为地记录消费 Task,正是使得 put! 比底层 yieldto 易用的原因。","category":"page"},{"location":"manual/asynchronous-programming/","page":"异步编程","title":"异步编程","text":"除了 yieldto 之外,也需要一些其它的基本函数来更高效地使用 Task。","category":"page"},{"location":"manual/asynchronous-programming/","page":"异步编程","title":"异步编程","text":"current_task 获取当前运行 Task 的索引。\nistaskdone 查询一个 Task 是否退出.\nistaskstarted 查询一个 Task 是否已经开始运行。\ntask_local_storage 操纵针对当前 Task 的键值存储。","category":"page"},{"location":"manual/asynchronous-programming/#Task-和事件","page":"异步编程","title":"Task 和事件","text":"","category":"section"},{"location":"manual/asynchronous-programming/","page":"异步编程","title":"异步编程","text":"多数 Task 切换是在等待如 I/O 请求的事件,由 Julia Base 里的调度器执行。调度器维持一个可运行 Task 的队列,并执行一个事件循环,来根据例如收到消息等外部事件来重启 Task。","category":"page"},{"location":"manual/asynchronous-programming/","page":"异步编程","title":"异步编程","text":"等待一个事件的基本函数是 wait。很多对象都实现了 wait 函数;例如,给定一个 Process 对象,wait 将等待它退出。wait 通常是隐式的,例如,wait 可能发生在调用 read 时等待数据可用。","category":"page"},{"location":"manual/asynchronous-programming/","page":"异步编程","title":"异步编程","text":"在所有这些情况下,wait 最终会操作一个 Condition 对象,由它负责排队和重启 Task。当 Task 在一个 Condition 上调用 wait 时,该 Task 就被标记为不可执行,加到条件的队列中,并切回调度器。调度器将选择另一个 Task 来运行,或者阻止外部事件的等待。如果所有运行良好,最终一个事件处理器将在这个条件下调用 notify,使得等待该条件的 Task 又变成可运行。","category":"page"},{"location":"manual/asynchronous-programming/","page":"异步编程","title":"异步编程","text":"通过调用 Task 显式创建的任务,一开始并不被调度器知道。这允许你根据需要使用 yieldto 手动管理任务。 但是,当此类任务等待事件时,它仍会在事件发生时自动重新启动,正如你所期望。","category":"page"},{"location":"base/strings/#lib-strings","page":"字符串","title":"字符串","text":"","category":"section"},{"location":"base/strings/","page":"字符串","title":"字符串","text":"Core.AbstractChar\nCore.Char\nBase.codepoint\nBase.length(::AbstractString)\nBase.sizeof(::AbstractString)\nBase.:*(::Union{AbstractChar, AbstractString}, ::Union{AbstractChar, AbstractString}...)\nBase.:^(::Union{AbstractString, AbstractChar}, ::Integer)\nBase.string\nBase.repeat(::AbstractString, ::Integer)\nBase.repeat(::AbstractChar, ::Integer)\nBase.repr(::Any)\nCore.String(::AbstractString)\nBase.SubString\nBase.transcode\nBase.unsafe_string\nBase.ncodeunits(::AbstractString)\nBase.codeunit\nBase.codeunits\nBase.ascii\nBase.Regex\nBase.@r_str\nBase.SubstitutionString\nBase.@s_str\nBase.@raw_str\nBase.@b_str\nBase.Docs.@html_str\nBase.Docs.@text_str\nBase.isvalid(::Any)\nBase.isvalid(::Any, ::Any)\nBase.isvalid(::AbstractString, ::Integer)\nBase.match\nBase.eachmatch\nBase.RegexMatch\nBase.keys(::RegexMatch)\nBase.isless(::AbstractString, ::AbstractString)\nBase.:(==)(::AbstractString, ::AbstractString)\nBase.cmp(::AbstractString, ::AbstractString)\nBase.lpad\nBase.rpad\nBase.findfirst(::AbstractString, ::AbstractString)\nBase.findnext(::AbstractString, ::AbstractString, ::Integer)\nBase.findnext(::AbstractChar, ::AbstractString, ::Integer)\nBase.findlast(::AbstractString, ::AbstractString)\nBase.findlast(::AbstractChar, ::AbstractString)\nBase.findprev(::AbstractString, ::AbstractString, ::Integer)\nBase.occursin\nBase.reverse(::Union{String,SubString{String}})\nBase.replace(s::AbstractString, ::Pair)\nBase.split\nBase.rsplit\nBase.strip\nBase.lstrip\nBase.rstrip\nBase.startswith\nBase.endswith\nBase.contains\nBase.first(::AbstractString, ::Integer)\nBase.last(::AbstractString, ::Integer)\nBase.uppercase\nBase.lowercase\nBase.titlecase\nBase.uppercasefirst\nBase.lowercasefirst\nBase.join\nBase.chop\nBase.chomp\nBase.thisind\nBase.nextind\nBase.prevind\nBase.textwidth\nBase.isascii\nBase.iscntrl\nBase.isdigit\nBase.isletter\nBase.islowercase\nBase.isnumeric\nBase.isprint\nBase.ispunct\nBase.isspace\nBase.isuppercase\nBase.isxdigit\nBase.escape_string\nBase.unescape_string","category":"page"},{"location":"base/strings/#Core.AbstractChar","page":"字符串","title":"Core.AbstractChar","text":"The AbstractChar type is the supertype of all character implementations in Julia. A character represents a Unicode code point, and can be converted to an integer via the codepoint function in order to obtain the numerical value of the code point, or constructed from the same integer. These numerical values determine how characters are compared with < and ==, for example. New T <: AbstractChar types should define a codepoint(::T) method and a T(::UInt32) constructor, at minimum.\n\nA given AbstractChar subtype may be capable of representing only a subset of Unicode, in which case conversion from an unsupported UInt32 value may throw an error. Conversely, the built-in Char type represents a superset of Unicode (in order to losslessly encode invalid byte streams), in which case conversion of a non-Unicode value to UInt32 throws an error. The isvalid function can be used to check which codepoints are representable in a given AbstractChar type.\n\nInternally, an AbstractChar type may use a variety of encodings. Conversion via codepoint(char) will not reveal this encoding because it always returns the Unicode value of the character. print(io, c) of any c::AbstractChar produces an encoding determined by io (UTF-8 for all built-in IO types), via conversion to Char if necessary.\n\nwrite(io, c), in contrast, may emit an encoding depending on typeof(c), and read(io, typeof(c)) should read the same encoding as write. New AbstractChar types must provide their own implementations of write and read.\n\n\n\n\n\n","category":"type"},{"location":"base/strings/#Core.Char","page":"字符串","title":"Core.Char","text":"Char(c::Union{Number,AbstractChar})\n\nChar is a 32-bit AbstractChar type that is the default representation of characters in Julia. Char is the type used for character literals like 'x' and it is also the element type of String.\n\nIn order to losslessly represent arbitrary byte streams stored in a String, a Char value may store information that cannot be converted to a Unicode codepoint — converting such a Char to UInt32 will throw an error. The isvalid(c::Char) function can be used to query whether c represents a valid Unicode character.\n\n\n\n\n\n","category":"type"},{"location":"base/strings/#Base.codepoint","page":"字符串","title":"Base.codepoint","text":"codepoint(c::AbstractChar) -> Integer\n\nReturn the Unicode codepoint (an unsigned integer) corresponding to the character c (or throw an exception if c does not represent a valid character). For Char, this is a UInt32 value, but AbstractChar types that represent only a subset of Unicode may return a different-sized integer (e.g. UInt8).\n\n\n\n\n\n","category":"function"},{"location":"base/strings/#Base.length-Tuple{AbstractString}","page":"字符串","title":"Base.length","text":"length(s::AbstractString) -> Int\nlength(s::AbstractString, i::Integer, j::Integer) -> Int\n\nReturn the number of characters in string s from indices i through j.\n\nThis is computed as the number of code unit indices from i to j which are valid character indices. With only a single string argument, this computes the number of characters in the entire string. With i and j arguments it computes the number of indices between i and j inclusive that are valid indices in the string s. In addition to in-bounds values, i may take the out-of-bounds value ncodeunits(s) + 1 and j may take the out-of-bounds value 0.\n\nnote: Note\nThe time complexity of this operation is linear in general. That is, it will take the time proportional to the number of bytes or characters in the string because it counts the value on the fly. This is in contrast to the method for arrays, which is a constant-time operation.\n\nSee also isvalid, ncodeunits, lastindex, thisind, nextind, prevind.\n\nExamples\n\njulia> length(\"jμΛIα\")\n5\n\n\n\n\n\n","category":"method"},{"location":"base/strings/#Base.sizeof-Tuple{AbstractString}","page":"字符串","title":"Base.sizeof","text":"sizeof(str::AbstractString)\n\nSize, in bytes, of the string str. Equal to the number of code units in str multiplied by the size, in bytes, of one code unit in str.\n\nExamples\n\njulia> sizeof(\"\")\n0\n\njulia> sizeof(\"∀\")\n3\n\n\n\n\n\n","category":"method"},{"location":"base/strings/#Base.:*-Tuple{Union{AbstractChar, AbstractString}, Vararg{Union{AbstractChar, AbstractString}}}","page":"字符串","title":"Base.:*","text":"*(s::Union{AbstractString, AbstractChar}, t::Union{AbstractString, AbstractChar}...) -> AbstractString\n\nConcatenate strings and/or characters, producing a String. This is equivalent to calling the string function on the arguments. Concatenation of built-in string types always produces a value of type String but other string types may choose to return a string of a different type as appropriate.\n\nExamples\n\njulia> \"Hello \" * \"world\"\n\"Hello world\"\n\njulia> 'j' * \"ulia\"\n\"julia\"\n\n\n\n\n\n","category":"method"},{"location":"base/strings/#Base.:^-Tuple{Union{AbstractChar, AbstractString}, Integer}","page":"字符串","title":"Base.:^","text":"^(s::Union{AbstractString,AbstractChar}, n::Integer)\n\nRepeat a string or character n times. This can also be written as repeat(s, n).\n\nSee also repeat.\n\nExamples\n\njulia> \"Test \"^3\n\"Test Test Test \"\n\n\n\n\n\n","category":"method"},{"location":"base/strings/#Base.string","page":"字符串","title":"Base.string","text":"string(n::Integer; base::Integer = 10, pad::Integer = 1)\n\nConvert an integer n to a string in the given base, optionally specifying a number of digits to pad to.\n\nSee also digits, bitstring, count_zeros.\n\nExamples\n\njulia> string(5, base = 13, pad = 4)\n\"0005\"\n\njulia> string(-13, base = 5, pad = 4)\n\"-0023\"\n\n\n\n\n\nstring(xs...)\n\nCreate a string from any values using the print function.\n\nstring should usually not be defined directly. Instead, define a method print(io::IO, x::MyType). If string(x) for a certain type needs to be highly efficient, then it may make sense to add a method to string and define print(io::IO, x::MyType) = print(io, string(x)) to ensure the functions are consistent.\n\nSee also: String, repr, sprint, show.\n\nExamples\n\njulia> string(\"a\", 1, true)\n\"a1true\"\n\n\n\n\n\n","category":"function"},{"location":"base/strings/#Base.repeat-Tuple{AbstractString, Integer}","page":"字符串","title":"Base.repeat","text":"repeat(s::AbstractString, r::Integer)\n\nRepeat a string r times. This can be written as s^r.\n\nSee also ^.\n\nExamples\n\njulia> repeat(\"ha\", 3)\n\"hahaha\"\n\n\n\n\n\n","category":"method"},{"location":"base/strings/#Base.repeat-Tuple{AbstractChar, Integer}","page":"字符串","title":"Base.repeat","text":"repeat(c::AbstractChar, r::Integer) -> String\n\nRepeat a character r times. This can equivalently be accomplished by calling c^r.\n\nExamples\n\njulia> repeat('A', 3)\n\"AAA\"\n\n\n\n\n\n","category":"method"},{"location":"base/strings/#Base.repr-Tuple{Any}","page":"字符串","title":"Base.repr","text":"repr(x; context=nothing)\n\nCreate a string from any value using the show function. You should not add methods to repr; define a show method instead.\n\nThe optional keyword argument context can be set to a :key=>value pair, a tuple of :key=>value pairs, or an IO or IOContext object whose attributes are used for the I/O stream passed to show.\n\nNote that repr(x) is usually similar to how the value of x would be entered in Julia. See also repr(MIME(\"text/plain\"), x) to instead return a \"pretty-printed\" version of x designed more for human consumption, equivalent to the REPL display of x.\n\ncompat: Julia 1.7\nPassing a tuple to keyword context requires Julia 1.7 or later.\n\nExamples\n\njulia> repr(1)\n\"1\"\n\njulia> repr(zeros(3))\n\"[0.0, 0.0, 0.0]\"\n\njulia> repr(big(1/3))\n\"0.333333333333333314829616256247390992939472198486328125\"\n\njulia> repr(big(1/3), context=:compact => true)\n\"0.333333\"\n\n\n\n\n\n\n","category":"method"},{"location":"base/strings/#Core.String-Tuple{AbstractString}","page":"字符串","title":"Core.String","text":"String(s::AbstractString)\n\nConvert a string to a contiguous byte array representation encoded as UTF-8 bytes. This representation is often appropriate for passing strings to C.\n\n\n\n\n\n","category":"method"},{"location":"base/strings/#Base.SubString","page":"字符串","title":"Base.SubString","text":"SubString(s::AbstractString, i::Integer, j::Integer=lastindex(s))\nSubString(s::AbstractString, r::UnitRange{<:Integer})\n\nLike getindex, but returns a view into the parent string s within range i:j or r respectively instead of making a copy.\n\nExamples\n\njulia> SubString(\"abc\", 1, 2)\n\"ab\"\n\njulia> SubString(\"abc\", 1:2)\n\"ab\"\n\njulia> SubString(\"abc\", 2)\n\"bc\"\n\n\n\n\n\n","category":"type"},{"location":"base/strings/#Base.transcode","page":"字符串","title":"Base.transcode","text":"transcode(T, src)\n\nConvert string data between Unicode encodings. src is either a String or a Vector{UIntXX} of UTF-XX code units, where XX is 8, 16, or 32. T indicates the encoding of the return value: String to return a (UTF-8 encoded) String or UIntXX to return a Vector{UIntXX} of UTF-XX data. (The alias Cwchar_t can also be used as the integer type, for converting wchar_t* strings used by external C libraries.)\n\nThe transcode function succeeds as long as the input data can be reasonably represented in the target encoding; it always succeeds for conversions between UTF-XX encodings, even for invalid Unicode data.\n\nOnly conversion to/from UTF-8 is currently supported.\n\nExamples\n\njulia> str = \"αβγ\"\n\"αβγ\"\n\njulia> transcode(UInt16, str)\n3-element Vector{UInt16}:\n 0x03b1\n 0x03b2\n 0x03b3\n\njulia> transcode(String, transcode(UInt16, str))\n\"αβγ\"\n\n\n\n\n\n","category":"function"},{"location":"base/strings/#Base.unsafe_string","page":"字符串","title":"Base.unsafe_string","text":"unsafe_string(p::Ptr{UInt8}, [length::Integer])\n\nCopy a string from the address of a C-style (NUL-terminated) string encoded as UTF-8. (The pointer can be safely freed afterwards.) If length is specified (the length of the data in bytes), the string does not have to be NUL-terminated.\n\nThis function is labeled \"unsafe\" because it will crash if p is not a valid memory address to data of the requested length.\n\n\n\n\n\n","category":"function"},{"location":"base/strings/#Base.ncodeunits-Tuple{AbstractString}","page":"字符串","title":"Base.ncodeunits","text":"ncodeunits(s::AbstractString) -> Int\n\nReturn the number of code units in a string. Indices that are in bounds to access this string must satisfy 1 ≤ i ≤ ncodeunits(s). Not all such indices are valid – they may not be the start of a character, but they will return a code unit value when calling codeunit(s,i).\n\nExamples\n\njulia> ncodeunits(\"The Julia Language\")\n18\n\njulia> ncodeunits(\"∫eˣ\")\n6\n\njulia> ncodeunits('∫'), ncodeunits('e'), ncodeunits('ˣ')\n(3, 1, 2)\n\nSee also codeunit, checkbounds, sizeof, length, lastindex.\n\n\n\n\n\n","category":"method"},{"location":"base/strings/#Base.codeunit","page":"字符串","title":"Base.codeunit","text":"codeunit(s::AbstractString) -> Type{<:Union{UInt8, UInt16, UInt32}}\n\nReturn the code unit type of the given string object. For ASCII, Latin-1, or UTF-8 encoded strings, this would be UInt8; for UCS-2 and UTF-16 it would be UInt16; for UTF-32 it would be UInt32. The code unit type need not be limited to these three types, but it's hard to think of widely used string encodings that don't use one of these units. codeunit(s) is the same as typeof(codeunit(s,1)) when s is a non-empty string.\n\nSee also ncodeunits.\n\n\n\n\n\ncodeunit(s::AbstractString, i::Integer) -> Union{UInt8, UInt16, UInt32}\n\nReturn the code unit value in the string s at index i. Note that\n\ncodeunit(s, i) :: codeunit(s)\n\nI.e. the value returned by codeunit(s, i) is of the type returned by codeunit(s).\n\nExamples\n\njulia> a = codeunit(\"Hello\", 2)\n0x65\n\njulia> typeof(a)\nUInt8\n\nSee also ncodeunits, checkbounds.\n\n\n\n\n\n","category":"function"},{"location":"base/strings/#Base.codeunits","page":"字符串","title":"Base.codeunits","text":"codeunits(s::AbstractString)\n\nObtain a vector-like object containing the code units of a string. Returns a CodeUnits wrapper by default, but codeunits may optionally be defined for new string types if necessary.\n\nExamples\n\njulia> codeunits(\"Juλia\")\n6-element Base.CodeUnits{UInt8, String}:\n 0x4a\n 0x75\n 0xce\n 0xbb\n 0x69\n 0x61\n\n\n\n\n\n","category":"function"},{"location":"base/strings/#Base.ascii","page":"字符串","title":"Base.ascii","text":"ascii(s::AbstractString)\n\nConvert a string to String type and check that it contains only ASCII data, otherwise throwing an ArgumentError indicating the position of the first non-ASCII byte.\n\nSee also the isascii predicate to filter or replace non-ASCII characters.\n\nExamples\n\njulia> ascii(\"abcdeγfgh\")\nERROR: ArgumentError: invalid ASCII at index 6 in \"abcdeγfgh\"\nStacktrace:\n[...]\n\njulia> ascii(\"abcdefgh\")\n\"abcdefgh\"\n\n\n\n\n\n","category":"function"},{"location":"base/strings/#Base.Regex","page":"字符串","title":"Base.Regex","text":"Regex(pattern[, flags])\n\nA type representing a regular expression. Regex objects can be used to match strings with match.\n\nRegex objects can be created using the @r_str string macro. The Regex(pattern[, flags]) constructor is usually used if the pattern string needs to be interpolated. See the documentation of the string macro for details on flags.\n\nnote: Note\nTo escape interpolated variables use \\Q and \\E (e.g. Regex(\"\\\\Q$x\\\\E\"))\n\n\n\n\n\n","category":"type"},{"location":"base/strings/#Base.@r_str","page":"字符串","title":"Base.@r_str","text":"@r_str -> Regex\n\nConstruct a regex, such as r\"^[a-z]*$\", without interpolation and unescaping (except for quotation mark \" which still has to be escaped). The regex also accepts one or more flags, listed after the ending quote, to change its behaviour:\n\ni enables case-insensitive matching\nm treats the ^ and $ tokens as matching the start and end of individual lines, as opposed to the whole string.\ns allows the . modifier to match newlines.\nx enables \"comment mode\": whitespace is enabled except when escaped with \\, and # is treated as starting a comment.\na disables UCP mode (enables ASCII mode). By default \\B, \\b, \\D, \\d, \\S, \\s, \\W, \\w, etc. match based on Unicode character properties. With this option, these sequences only match ASCII characters.\n\nSee Regex if interpolation is needed.\n\nExamples\n\njulia> match(r\"a+.*b+.*?d$\"ism, \"Goodbye,\\nOh, angry,\\nBad world\\n\")\nRegexMatch(\"angry,\\nBad world\")\n\nThis regex has the first three flags enabled.\n\n\n\n\n\n","category":"macro"},{"location":"base/strings/#Base.SubstitutionString","page":"字符串","title":"Base.SubstitutionString","text":"SubstitutionString(substr)\n\nStores the given string substr as a SubstitutionString, for use in regular expression substitutions. Most commonly constructed using the @s_str macro.\n\nExamples\n\njulia> SubstitutionString(\"Hello \\\\g, it's \\\\1\")\ns\"Hello \\g, it's \\1\"\n\njulia> subst = s\"Hello \\g, it's \\1\"\ns\"Hello \\g, it's \\1\"\n\njulia> typeof(subst)\nSubstitutionString{String}\n\n\n\n\n\n\n","category":"type"},{"location":"base/strings/#Base.@s_str","page":"字符串","title":"Base.@s_str","text":"@s_str -> SubstitutionString\n\nConstruct a substitution string, used for regular expression substitutions. Within the string, sequences of the form \\N refer to the Nth capture group in the regex, and \\g refers to a named capture group with name groupname.\n\nExamples\n\njulia> msg = \"#Hello# from Julia\";\n\njulia> replace(msg, r\"#(.+)# from (?\\w+)\" => s\"FROM: \\g; MESSAGE: \\1\")\n\"FROM: Julia; MESSAGE: Hello\"\n\n\n\n\n\n","category":"macro"},{"location":"base/strings/#Base.@raw_str","page":"字符串","title":"Base.@raw_str","text":"@raw_str -> String\n\nCreate a raw string without interpolation and unescaping. The exception is that quotation marks still must be escaped. Backslashes escape both quotation marks and other backslashes, but only when a sequence of backslashes precedes a quote character. Thus, 2n backslashes followed by a quote encodes n backslashes and the end of the literal while 2n+1 backslashes followed by a quote encodes n backslashes followed by a quote character.\n\nExamples\n\njulia> println(raw\"\\ $x\")\n\\ $x\n\njulia> println(raw\"\\\"\")\n\"\n\njulia> println(raw\"\\\\\\\"\")\n\\\"\n\njulia> println(raw\"\\\\x \\\\\\\"\")\n\\\\x \\\"\n\n\n\n\n\n","category":"macro"},{"location":"base/strings/#Base.@b_str","page":"字符串","title":"Base.@b_str","text":"@b_str\n\nCreate an immutable byte (UInt8) vector using string syntax.\n\nExamples\n\njulia> v = b\"12\\x01\\x02\"\n4-element Base.CodeUnits{UInt8, String}:\n 0x31\n 0x32\n 0x01\n 0x02\n\njulia> v[2]\n0x32\n\n\n\n\n\n","category":"macro"},{"location":"base/strings/#Base.Docs.@html_str","page":"字符串","title":"Base.Docs.@html_str","text":"@html_str -> Docs.HTML\n\nCreate an HTML object from a literal string.\n\nExamples\n\njulia> html\"Julia\"\nHTML{String}(\"Julia\")\n\n\n\n\n\n","category":"macro"},{"location":"base/strings/#Base.Docs.@text_str","page":"字符串","title":"Base.Docs.@text_str","text":"@text_str -> Docs.Text\n\nCreate a Text object from a literal string.\n\nExamples\n\njulia> text\"Julia\"\nJulia\n\n\n\n\n\n","category":"macro"},{"location":"base/strings/#Base.isvalid-Tuple{Any}","page":"字符串","title":"Base.isvalid","text":"isvalid(value) -> Bool\n\nReturns true if the given value is valid for its type, which currently can be either AbstractChar or String or SubString{String}.\n\nExamples\n\njulia> isvalid(Char(0xd800))\nfalse\n\njulia> isvalid(SubString(String(UInt8[0xfe,0x80,0x80,0x80,0x80,0x80]),1,2))\nfalse\n\njulia> isvalid(Char(0xd799))\ntrue\n\n\n\n\n\n","category":"method"},{"location":"base/strings/#Base.isvalid-Tuple{Any, Any}","page":"字符串","title":"Base.isvalid","text":"isvalid(T, value) -> Bool\n\nReturns true if the given value is valid for that type. Types currently can be either AbstractChar or String. Values for AbstractChar can be of type AbstractChar or UInt32. Values for String can be of that type, SubString{String}, Vector{UInt8}, or a contiguous subarray thereof.\n\nExamples\n\njulia> isvalid(Char, 0xd800)\nfalse\n\njulia> isvalid(String, SubString(\"thisisvalid\",1,5))\ntrue\n\njulia> isvalid(Char, 0xd799)\ntrue\n\ncompat: Julia 1.6\nSupport for subarray values was added in Julia 1.6.\n\n\n\n\n\n","category":"method"},{"location":"base/strings/#Base.isvalid-Tuple{AbstractString, Integer}","page":"字符串","title":"Base.isvalid","text":"isvalid(s::AbstractString, i::Integer) -> Bool\n\nPredicate indicating whether the given index is the start of the encoding of a character in s or not. If isvalid(s, i) is true then s[i] will return the character whose encoding starts at that index, if it's false, then s[i] will raise an invalid index error or a bounds error depending on if i is in bounds. In order for isvalid(s, i) to be an O(1) function, the encoding of s must be self-synchronizing. This is a basic assumption of Julia's generic string support.\n\nSee also getindex, iterate, thisind, nextind, prevind, length.\n\nExamples\n\njulia> str = \"αβγdef\";\n\njulia> isvalid(str, 1)\ntrue\n\njulia> str[1]\n'α': Unicode U+03B1 (category Ll: Letter, lowercase)\n\njulia> isvalid(str, 2)\nfalse\n\njulia> str[2]\nERROR: StringIndexError: invalid index [2], valid nearby indices [1]=>'α', [3]=>'β'\nStacktrace:\n[...]\n\n\n\n\n\n","category":"method"},{"location":"base/strings/#Base.match","page":"字符串","title":"Base.match","text":"match(r::Regex, s::AbstractString[, idx::Integer[, addopts]])\n\nSearch for the first match of the regular expression r in s and return a RegexMatch object containing the match, or nothing if the match failed. The matching substring can be retrieved by accessing m.match and the captured sequences can be retrieved by accessing m.captures The optional idx argument specifies an index at which to start the search.\n\nExamples\n\njulia> rx = r\"a(.)a\"\nr\"a(.)a\"\n\njulia> m = match(rx, \"cabac\")\nRegexMatch(\"aba\", 1=\"b\")\n\njulia> m.captures\n1-element Vector{Union{Nothing, SubString{String}}}:\n \"b\"\n\njulia> m.match\n\"aba\"\n\njulia> match(rx, \"cabac\", 3) === nothing\ntrue\n\n\n\n\n\n","category":"function"},{"location":"base/strings/#Base.eachmatch","page":"字符串","title":"Base.eachmatch","text":"eachmatch(r::Regex, s::AbstractString; overlap::Bool=false)\n\nSearch for all matches of the regular expression r in s and return an iterator over the matches. If overlap is true, the matching sequences are allowed to overlap indices in the original string, otherwise they must be from distinct character ranges.\n\nExamples\n\njulia> rx = r\"a.a\"\nr\"a.a\"\n\njulia> m = eachmatch(rx, \"a1a2a3a\")\nBase.RegexMatchIterator(r\"a.a\", \"a1a2a3a\", false)\n\njulia> collect(m)\n2-element Vector{RegexMatch}:\n RegexMatch(\"a1a\")\n RegexMatch(\"a3a\")\n\njulia> collect(eachmatch(rx, \"a1a2a3a\", overlap = true))\n3-element Vector{RegexMatch}:\n RegexMatch(\"a1a\")\n RegexMatch(\"a2a\")\n RegexMatch(\"a3a\")\n\n\n\n\n\n","category":"function"},{"location":"base/strings/#Base.RegexMatch","page":"字符串","title":"Base.RegexMatch","text":"RegexMatch\n\nA type representing a single match to a Regex found in a string. Typically created from the match function.\n\nThe match field stores the substring of the entire matched string. The captures field stores the substrings for each capture group, indexed by number. To index by capture group name, the entire match object should be indexed instead, as shown in the examples. The location of the start of the match is stored in the offset field. The offsets field stores the locations of the start of each capture group, with 0 denoting a group that was not captured.\n\nThis type can be used as an iterator over the capture groups of the Regex, yielding the substrings captured in each group. Because of this, the captures of a match can be destructured. If a group was not captured, nothing will be yielded instead of a substring.\n\nMethods that accept a RegexMatch object are defined for iterate, length, eltype, keys, haskey, and getindex, where keys are the the names or numbers of a capture group. See keys for more information.\n\nExamples\n\njulia> m = match(r\"(?\\d+):(?\\d+)(am|pm)?\", \"11:30 in the morning\")\nRegexMatch(\"11:30\", hour=\"11\", minute=\"30\", 3=nothing)\n\njulia> hr, min, ampm = m;\n\njulia> hr\n\"11\"\n\njulia> m[\"minute\"]\n\"30\"\n\njulia> m.match\n\"11:30\"\n\n\n\n\n\n","category":"type"},{"location":"base/strings/#Base.keys-Tuple{RegexMatch}","page":"字符串","title":"Base.keys","text":"keys(m::RegexMatch) -> Vector\n\nReturn a vector of keys for all capture groups of the underlying regex. A key is included even if the capture group fails to match. That is, idx will be in the return value even if m[idx] == nothing.\n\nUnnamed capture groups will have integer keys corresponding to their index. Named capture groups will have string keys.\n\ncompat: Julia 1.6\nThis method was added in Julia 1.6\n\nExamples\n\njulia> keys(match(r\"(?\\d+):(?\\d+)(am|pm)?\", \"11:30\"))\n3-element Vector{Any}:\n \"hour\"\n \"minute\"\n 3\n\n\n\n\n\n","category":"method"},{"location":"base/strings/#Base.isless-Tuple{AbstractString, AbstractString}","page":"字符串","title":"Base.isless","text":"isless(a::AbstractString, b::AbstractString) -> Bool\n\nTest whether string a comes before string b in alphabetical order (technically, in lexicographical order by Unicode code points).\n\nExamples\n\njulia> isless(\"a\", \"b\")\ntrue\n\njulia> isless(\"β\", \"α\")\nfalse\n\njulia> isless(\"a\", \"a\")\nfalse\n\n\n\n\n\n","category":"method"},{"location":"base/strings/#Base.:==-Tuple{AbstractString, AbstractString}","page":"字符串","title":"Base.:==","text":"==(a::AbstractString, b::AbstractString) -> Bool\n\nTest whether two strings are equal character by character (technically, Unicode code point by code point).\n\nExamples\n\njulia> \"abc\" == \"abc\"\ntrue\n\njulia> \"abc\" == \"αβγ\"\nfalse\n\n\n\n\n\n","category":"method"},{"location":"base/strings/#Base.cmp-Tuple{AbstractString, AbstractString}","page":"字符串","title":"Base.cmp","text":"cmp(a::AbstractString, b::AbstractString) -> Int\n\nCompare two strings. Return 0 if both strings have the same length and the character at each index is the same in both strings. Return -1 if a is a prefix of b, or if a comes before b in alphabetical order. Return 1 if b is a prefix of a, or if b comes before a in alphabetical order (technically, lexicographical order by Unicode code points).\n\nExamples\n\njulia> cmp(\"abc\", \"abc\")\n0\n\njulia> cmp(\"ab\", \"abc\")\n-1\n\njulia> cmp(\"abc\", \"ab\")\n1\n\njulia> cmp(\"ab\", \"ac\")\n-1\n\njulia> cmp(\"ac\", \"ab\")\n1\n\njulia> cmp(\"α\", \"a\")\n1\n\njulia> cmp(\"b\", \"β\")\n-1\n\n\n\n\n\n","category":"method"},{"location":"base/strings/#Base.lpad","page":"字符串","title":"Base.lpad","text":"lpad(s, n::Integer, p::Union{AbstractChar,AbstractString}=' ') -> String\n\nStringify s and pad the resulting string on the left with p to make it n characters (in textwidth) long. If s is already n characters long, an equal string is returned. Pad with spaces by default.\n\nExamples\n\njulia> lpad(\"March\", 10)\n\" March\"\n\ncompat: Julia 1.7\nIn Julia 1.7, this function was changed to use textwidth rather than a raw character (codepoint) count.\n\n\n\n\n\n","category":"function"},{"location":"base/strings/#Base.rpad","page":"字符串","title":"Base.rpad","text":"rpad(s, n::Integer, p::Union{AbstractChar,AbstractString}=' ') -> String\n\nStringify s and pad the resulting string on the right with p to make it n characters (in textwidth) long. If s is already n characters long, an equal string is returned. Pad with spaces by default.\n\nExamples\n\njulia> rpad(\"March\", 20)\n\"March \"\n\ncompat: Julia 1.7\nIn Julia 1.7, this function was changed to use textwidth rather than a raw character (codepoint) count.\n\n\n\n\n\n","category":"function"},{"location":"base/strings/#Base.findfirst-Tuple{AbstractString, AbstractString}","page":"字符串","title":"Base.findfirst","text":"findfirst(pattern::AbstractString, string::AbstractString)\nfindfirst(pattern::AbstractPattern, string::String)\n\nFind the first occurrence of pattern in string. Equivalent to findnext(pattern, string, firstindex(s)).\n\nExamples\n\njulia> findfirst(\"z\", \"Hello to the world\") # returns nothing, but not printed in the REPL\n\njulia> findfirst(\"Julia\", \"JuliaLang\")\n1:5\n\n\n\n\n\n","category":"method"},{"location":"base/strings/#Base.findnext-Tuple{AbstractString, AbstractString, Integer}","page":"字符串","title":"Base.findnext","text":"findnext(pattern::AbstractString, string::AbstractString, start::Integer)\nfindnext(pattern::AbstractPattern, string::String, start::Integer)\n\nFind the next occurrence of pattern in string starting at position start. pattern can be either a string, or a regular expression, in which case string must be of type String.\n\nThe return value is a range of indices where the matching sequence is found, such that s[findnext(x, s, i)] == x:\n\nfindnext(\"substring\", string, i) == start:stop such that string[start:stop] == \"substring\" and i <= start, or nothing if unmatched.\n\nExamples\n\njulia> findnext(\"z\", \"Hello to the world\", 1) === nothing\ntrue\n\njulia> findnext(\"o\", \"Hello to the world\", 6)\n8:8\n\njulia> findnext(\"Lang\", \"JuliaLang\", 2)\n6:9\n\n\n\n\n\n","category":"method"},{"location":"base/strings/#Base.findnext-Tuple{AbstractChar, AbstractString, Integer}","page":"字符串","title":"Base.findnext","text":"findnext(ch::AbstractChar, string::AbstractString, start::Integer)\n\nFind the next occurrence of character ch in string starting at position start.\n\ncompat: Julia 1.3\nThis method requires at least Julia 1.3.\n\nExamples\n\njulia> findnext('z', \"Hello to the world\", 1) === nothing\ntrue\n\njulia> findnext('o', \"Hello to the world\", 6)\n8\n\n\n\n\n\n","category":"method"},{"location":"base/strings/#Base.findlast-Tuple{AbstractString, AbstractString}","page":"字符串","title":"Base.findlast","text":"findlast(pattern::AbstractString, string::AbstractString)\n\nFind the last occurrence of pattern in string. Equivalent to findprev(pattern, string, lastindex(string)).\n\nExamples\n\njulia> findlast(\"o\", \"Hello to the world\")\n15:15\n\njulia> findfirst(\"Julia\", \"JuliaLang\")\n1:5\n\n\n\n\n\n","category":"method"},{"location":"base/strings/#Base.findlast-Tuple{AbstractChar, AbstractString}","page":"字符串","title":"Base.findlast","text":"findlast(ch::AbstractChar, string::AbstractString)\n\nFind the last occurrence of character ch in string.\n\ncompat: Julia 1.3\nThis method requires at least Julia 1.3.\n\nExamples\n\njulia> findlast('p', \"happy\")\n4\n\njulia> findlast('z', \"happy\") === nothing\ntrue\n\n\n\n\n\n","category":"method"},{"location":"base/strings/#Base.findprev-Tuple{AbstractString, AbstractString, Integer}","page":"字符串","title":"Base.findprev","text":"findprev(pattern::AbstractString, string::AbstractString, start::Integer)\n\nFind the previous occurrence of pattern in string starting at position start.\n\nThe return value is a range of indices where the matching sequence is found, such that s[findprev(x, s, i)] == x:\n\nfindprev(\"substring\", string, i) == start:stop such that string[start:stop] == \"substring\" and stop <= i, or nothing if unmatched.\n\nExamples\n\njulia> findprev(\"z\", \"Hello to the world\", 18) === nothing\ntrue\n\njulia> findprev(\"o\", \"Hello to the world\", 18)\n15:15\n\njulia> findprev(\"Julia\", \"JuliaLang\", 6)\n1:5\n\n\n\n\n\n","category":"method"},{"location":"base/strings/#Base.occursin","page":"字符串","title":"Base.occursin","text":"occursin(needle::Union{AbstractString,AbstractPattern,AbstractChar}, haystack::AbstractString)\n\nDetermine whether the first argument is a substring of the second. If needle is a regular expression, checks whether haystack contains a match.\n\nExamples\n\njulia> occursin(\"Julia\", \"JuliaLang is pretty cool!\")\ntrue\n\njulia> occursin('a', \"JuliaLang is pretty cool!\")\ntrue\n\njulia> occursin(r\"a.a\", \"aba\")\ntrue\n\njulia> occursin(r\"a.a\", \"abba\")\nfalse\n\nSee also contains.\n\n\n\n\n\noccursin(haystack)\n\nCreate a function that checks whether its argument occurs in haystack, i.e. a function equivalent to needle -> occursin(needle, haystack).\n\nThe returned function is of type Base.Fix2{typeof(occursin)}.\n\ncompat: Julia 1.6\nThis method requires Julia 1.6 or later.\n\n\n\n\n\n","category":"function"},{"location":"base/strings/#Base.reverse-Tuple{Union{SubString{String}, String}}","page":"字符串","title":"Base.reverse","text":"reverse(s::AbstractString) -> AbstractString\n\nReverses a string. Technically, this function reverses the codepoints in a string and its main utility is for reversed-order string processing, especially for reversed regular-expression searches. See also reverseind to convert indices in s to indices in reverse(s) and vice-versa, and graphemes from module Unicode to operate on user-visible \"characters\" (graphemes) rather than codepoints. See also Iterators.reverse for reverse-order iteration without making a copy. Custom string types must implement the reverse function themselves and should typically return a string with the same type and encoding. If they return a string with a different encoding, they must also override reverseind for that string type to satisfy s[reverseind(s,i)] == reverse(s)[i].\n\nExamples\n\njulia> reverse(\"JuliaLang\")\n\"gnaLailuJ\"\n\nnote: Note\nThe examples below may be rendered differently on different systems. The comments indicate how they're supposed to be rendered\n\nCombining characters can lead to surprising results:\n\njulia> reverse(\"ax̂e\") # hat is above x in the input, above e in the output\n\"êxa\"\n\njulia> using Unicode\n\njulia> join(reverse(collect(graphemes(\"ax̂e\")))) # reverses graphemes; hat is above x in both in- and output\n\"ex̂a\"\n\n\n\n\n\n","category":"method"},{"location":"base/strings/#Base.replace-Tuple{AbstractString, Pair}","page":"字符串","title":"Base.replace","text":"replace(A, old_new::Pair...; [count::Integer])\n\nReturn a copy of collection A where, for each pair old=>new in old_new, all occurrences of old are replaced by new. Equality is determined using isequal. If count is specified, then replace at most count occurrences in total.\n\nThe element type of the result is chosen using promotion (see promote_type) based on the element type of A and on the types of the new values in pairs. If count is omitted and the element type of A is a Union, the element type of the result will not include singleton types which are replaced with values of a different type: for example, Union{T,Missing} will become T if missing is replaced.\n\nSee also replace!, splice!, delete!, insert!.\n\ncompat: Julia 1.7\nVersion 1.7 is required to replace elements of a Tuple.\n\nExamples\n\njulia> replace([1, 2, 1, 3], 1=>0, 2=>4, count=2)\n4-element Vector{Int64}:\n 0\n 4\n 1\n 3\n\njulia> replace([1, missing], missing=>0)\n2-element Vector{Int64}:\n 1\n 0\n\n\n\n\n\nreplace(s::AbstractString, pat=>r, [pat2=>r2, ...]; [count::Integer])\n\nSearch for the given pattern pat in s, and replace each occurrence with r. If count is provided, replace at most count occurrences. pat may be a single character, a vector or a set of characters, a string, or a regular expression. If r is a function, each occurrence is replaced with r(s) where s is the matched substring (when pat is a AbstractPattern or AbstractString) or character (when pat is an AbstractChar or a collection of AbstractChar). If pat is a regular expression and r is a SubstitutionString, then capture group references in r are replaced with the corresponding matched text. To remove instances of pat from string, set r to the empty String (\"\").\n\nMultiple patterns can be specified, and they will be applied left-to-right simultaneously, so only one pattern will be applied to any character, and the patterns will only be applied to the input text, not the replacements.\n\ncompat: Julia 1.7\nSupport for multiple patterns requires version 1.7.\n\nExamples\n\njulia> replace(\"Python is a programming language.\", \"Python\" => \"Julia\")\n\"Julia is a programming language.\"\n\njulia> replace(\"The quick foxes run quickly.\", \"quick\" => \"slow\", count=1)\n\"The slow foxes run quickly.\"\n\njulia> replace(\"The quick foxes run quickly.\", \"quick\" => \"\", count=1)\n\"The foxes run quickly.\"\n\njulia> replace(\"The quick foxes run quickly.\", r\"fox(es)?\" => s\"bus\\1\")\n\"The quick buses run quickly.\"\n\njulia> replace(\"abcabc\", \"a\" => \"b\", \"b\" => \"c\", r\".+\" => \"a\")\n\"bca\"\n\n\n\n\n\n","category":"method"},{"location":"base/strings/#Base.split","page":"字符串","title":"Base.split","text":"split(str::AbstractString, dlm; limit::Integer=0, keepempty::Bool=true)\nsplit(str::AbstractString; limit::Integer=0, keepempty::Bool=false)\n\nSplit str into an array of substrings on occurrences of the delimiter(s) dlm. dlm can be any of the formats allowed by findnext's first argument (i.e. as a string, regular expression or a function), or as a single character or collection of characters.\n\nIf dlm is omitted, it defaults to isspace.\n\nThe optional keyword arguments are:\n\nlimit: the maximum size of the result. limit=0 implies no maximum (default)\nkeepempty: whether empty fields should be kept in the result. Default is false without a dlm argument, true with a dlm argument.\n\nSee also rsplit, eachsplit.\n\nExamples\n\njulia> a = \"Ma.rch\"\n\"Ma.rch\"\n\njulia> split(a, \".\")\n2-element Vector{SubString{String}}:\n \"Ma\"\n \"rch\"\n\n\n\n\n\n","category":"function"},{"location":"base/strings/#Base.rsplit","page":"字符串","title":"Base.rsplit","text":"rsplit(s::AbstractString; limit::Integer=0, keepempty::Bool=false)\nrsplit(s::AbstractString, chars; limit::Integer=0, keepempty::Bool=true)\n\nSimilar to split, but starting from the end of the string.\n\nExamples\n\njulia> a = \"M.a.r.c.h\"\n\"M.a.r.c.h\"\n\njulia> rsplit(a, \".\")\n5-element Vector{SubString{String}}:\n \"M\"\n \"a\"\n \"r\"\n \"c\"\n \"h\"\n\njulia> rsplit(a, \".\"; limit=1)\n1-element Vector{SubString{String}}:\n \"M.a.r.c.h\"\n\njulia> rsplit(a, \".\"; limit=2)\n2-element Vector{SubString{String}}:\n \"M.a.r.c\"\n \"h\"\n\n\n\n\n\n","category":"function"},{"location":"base/strings/#Base.strip","page":"字符串","title":"Base.strip","text":"strip([pred=isspace,] str::AbstractString) -> SubString\nstrip(str::AbstractString, chars) -> SubString\n\nRemove leading and trailing characters from str, either those specified by chars or those for which the function pred returns true.\n\nThe default behaviour is to remove leading and trailing whitespace and delimiters: see isspace for precise details.\n\nThe optional chars argument specifies which characters to remove: it can be a single character, vector or set of characters.\n\nSee also lstrip and rstrip.\n\ncompat: Julia 1.2\nThe method which accepts a predicate function requires Julia 1.2 or later.\n\nExamples\n\njulia> strip(\"{3, 5}\\n\", ['{', '}', '\\n'])\n\"3, 5\"\n\n\n\n\n\n","category":"function"},{"location":"base/strings/#Base.lstrip","page":"字符串","title":"Base.lstrip","text":"lstrip([pred=isspace,] str::AbstractString) -> SubString\nlstrip(str::AbstractString, chars) -> SubString\n\nRemove leading characters from str, either those specified by chars or those for which the function pred returns true.\n\nThe default behaviour is to remove leading whitespace and delimiters: see isspace for precise details.\n\nThe optional chars argument specifies which characters to remove: it can be a single character, or a vector or set of characters.\n\nSee also strip and rstrip.\n\nExamples\n\njulia> a = lpad(\"March\", 20)\n\" March\"\n\njulia> lstrip(a)\n\"March\"\n\n\n\n\n\n","category":"function"},{"location":"base/strings/#Base.rstrip","page":"字符串","title":"Base.rstrip","text":"rstrip([pred=isspace,] str::AbstractString) -> SubString\nrstrip(str::AbstractString, chars) -> SubString\n\nRemove trailing characters from str, either those specified by chars or those for which the function pred returns true.\n\nThe default behaviour is to remove trailing whitespace and delimiters: see isspace for precise details.\n\nThe optional chars argument specifies which characters to remove: it can be a single character, or a vector or set of characters.\n\nSee also strip and lstrip.\n\nExamples\n\njulia> a = rpad(\"March\", 20)\n\"March \"\n\njulia> rstrip(a)\n\"March\"\n\n\n\n\n\n","category":"function"},{"location":"base/strings/#Base.startswith","page":"字符串","title":"Base.startswith","text":"startswith(s::AbstractString, prefix::AbstractString)\n\nReturn true if s starts with prefix. If prefix is a vector or set of characters, test whether the first character of s belongs to that set.\n\nSee also endswith, contains.\n\nExamples\n\njulia> startswith(\"JuliaLang\", \"Julia\")\ntrue\n\n\n\n\n\nstartswith(prefix)\n\nCreate a function that checks whether its argument starts with prefix, i.e. a function equivalent to y -> startswith(y, prefix).\n\nThe returned function is of type Base.Fix2{typeof(startswith)}, which can be used to implement specialized methods.\n\ncompat: Julia 1.5\nThe single argument startswith(prefix) requires at least Julia 1.5.\n\nExamples\n\njulia> startswith_julia = startswith(\"Julia\");\n\njulia> startswith_julia(\"Julia\")\ntrue\n\njulia> startswith_julia(\"NotJulia\")\nfalse\n\n\n\n\n\nstartswith(s::AbstractString, prefix::Regex)\n\nReturn true if s starts with the regex pattern, prefix.\n\nnote: Note\nstartswith does not compile the anchoring into the regular expression, but instead passes the anchoring as match_option to PCRE. If compile time is amortized, occursin(r\"^...\", s) is faster than startswith(s, r\"...\").\n\nSee also occursin and endswith.\n\ncompat: Julia 1.2\nThis method requires at least Julia 1.2.\n\nExamples\n\njulia> startswith(\"JuliaLang\", r\"Julia|Romeo\")\ntrue\n\n\n\n\n\n","category":"function"},{"location":"base/strings/#Base.endswith","page":"字符串","title":"Base.endswith","text":"endswith(s::AbstractString, suffix::AbstractString)\n\nReturn true if s ends with suffix. If suffix is a vector or set of characters, test whether the last character of s belongs to that set.\n\nSee also startswith, contains.\n\nExamples\n\njulia> endswith(\"Sunday\", \"day\")\ntrue\n\n\n\n\n\nendswith(suffix)\n\nCreate a function that checks whether its argument ends with suffix, i.e. a function equivalent to y -> endswith(y, suffix).\n\nThe returned function is of type Base.Fix2{typeof(endswith)}, which can be used to implement specialized methods.\n\ncompat: Julia 1.5\nThe single argument endswith(suffix) requires at least Julia 1.5.\n\nExamples\n\njulia> endswith_julia = endswith(\"Julia\");\n\njulia> endswith_julia(\"Julia\")\ntrue\n\njulia> endswith_julia(\"JuliaLang\")\nfalse\n\n\n\n\n\nendswith(s::AbstractString, suffix::Regex)\n\nReturn true if s ends with the regex pattern, suffix.\n\nnote: Note\nendswith does not compile the anchoring into the regular expression, but instead passes the anchoring as match_option to PCRE. If compile time is amortized, occursin(r\"...$\", s) is faster than endswith(s, r\"...\").\n\nSee also occursin and startswith.\n\ncompat: Julia 1.2\nThis method requires at least Julia 1.2.\n\nExamples\n\njulia> endswith(\"JuliaLang\", r\"Lang|Roberts\")\ntrue\n\n\n\n\n\n","category":"function"},{"location":"base/strings/#Base.contains","page":"字符串","title":"Base.contains","text":"contains(haystack::AbstractString, needle)\n\nReturn true if haystack contains needle. This is the same as occursin(needle, haystack), but is provided for consistency with startswith(haystack, needle) and endswith(haystack, needle).\n\nSee also occursin, in, issubset.\n\nExamples\n\njulia> contains(\"JuliaLang is pretty cool!\", \"Julia\")\ntrue\n\njulia> contains(\"JuliaLang is pretty cool!\", 'a')\ntrue\n\njulia> contains(\"aba\", r\"a.a\")\ntrue\n\njulia> contains(\"abba\", r\"a.a\")\nfalse\n\ncompat: Julia 1.5\nThe contains function requires at least Julia 1.5.\n\n\n\n\n\ncontains(needle)\n\nCreate a function that checks whether its argument contains needle, i.e. a function equivalent to haystack -> contains(haystack, needle).\n\nThe returned function is of type Base.Fix2{typeof(contains)}, which can be used to implement specialized methods.\n\n\n\n\n\n","category":"function"},{"location":"base/strings/#Base.first-Tuple{AbstractString, Integer}","page":"字符串","title":"Base.first","text":"first(s::AbstractString, n::Integer)\n\nGet a string consisting of the first n characters of s.\n\nExamples\n\njulia> first(\"∀ϵ≠0: ϵ²>0\", 0)\n\"\"\n\njulia> first(\"∀ϵ≠0: ϵ²>0\", 1)\n\"∀\"\n\njulia> first(\"∀ϵ≠0: ϵ²>0\", 3)\n\"∀ϵ≠\"\n\n\n\n\n\n","category":"method"},{"location":"base/strings/#Base.last-Tuple{AbstractString, Integer}","page":"字符串","title":"Base.last","text":"last(s::AbstractString, n::Integer)\n\nGet a string consisting of the last n characters of s.\n\nExamples\n\njulia> last(\"∀ϵ≠0: ϵ²>0\", 0)\n\"\"\n\njulia> last(\"∀ϵ≠0: ϵ²>0\", 1)\n\"0\"\n\njulia> last(\"∀ϵ≠0: ϵ²>0\", 3)\n\"²>0\"\n\n\n\n\n\n","category":"method"},{"location":"base/strings/#Base.Unicode.uppercase","page":"字符串","title":"Base.Unicode.uppercase","text":"uppercase(s::AbstractString)\n\nReturn s with all characters converted to uppercase.\n\nSee also lowercase, titlecase, uppercasefirst.\n\nExamples\n\njulia> uppercase(\"Julia\")\n\"JULIA\"\n\n\n\n\n\n","category":"function"},{"location":"base/strings/#Base.Unicode.lowercase","page":"字符串","title":"Base.Unicode.lowercase","text":"lowercase(s::AbstractString)\n\nReturn s with all characters converted to lowercase.\n\nSee also uppercase, titlecase, lowercasefirst.\n\nExamples\n\njulia> lowercase(\"STRINGS AND THINGS\")\n\"strings and things\"\n\n\n\n\n\n","category":"function"},{"location":"base/strings/#Base.Unicode.titlecase","page":"字符串","title":"Base.Unicode.titlecase","text":"titlecase(s::AbstractString; [wordsep::Function], strict::Bool=true) -> String\n\nCapitalize the first character of each word in s; if strict is true, every other character is converted to lowercase, otherwise they are left unchanged. By default, all non-letters beginning a new grapheme are considered as word separators; a predicate can be passed as the wordsep keyword to determine which characters should be considered as word separators. See also uppercasefirst to capitalize only the first character in s.\n\nSee also uppercase, lowercase, uppercasefirst.\n\nExamples\n\njulia> titlecase(\"the JULIA programming language\")\n\"The Julia Programming Language\"\n\njulia> titlecase(\"ISS - international space station\", strict=false)\n\"ISS - International Space Station\"\n\njulia> titlecase(\"a-a b-b\", wordsep = c->c==' ')\n\"A-a B-b\"\n\n\n\n\n\n","category":"function"},{"location":"base/strings/#Base.Unicode.uppercasefirst","page":"字符串","title":"Base.Unicode.uppercasefirst","text":"uppercasefirst(s::AbstractString) -> String\n\nReturn s with the first character converted to uppercase (technically \"title case\" for Unicode). See also titlecase to capitalize the first character of every word in s.\n\nSee also lowercasefirst, uppercase, lowercase, titlecase.\n\nExamples\n\njulia> uppercasefirst(\"python\")\n\"Python\"\n\n\n\n\n\n","category":"function"},{"location":"base/strings/#Base.Unicode.lowercasefirst","page":"字符串","title":"Base.Unicode.lowercasefirst","text":"lowercasefirst(s::AbstractString)\n\nReturn s with the first character converted to lowercase.\n\nSee also uppercasefirst, uppercase, lowercase, titlecase.\n\nExamples\n\njulia> lowercasefirst(\"Julia\")\n\"julia\"\n\n\n\n\n\n","category":"function"},{"location":"base/strings/#Base.join","page":"字符串","title":"Base.join","text":"join([io::IO,] iterator [, delim [, last]])\n\nJoin any iterator into a single string, inserting the given delimiter (if any) between adjacent items. If last is given, it will be used instead of delim between the last two items. Each item of iterator is converted to a string via print(io::IOBuffer, x). If io is given, the result is written to io rather than returned as a String.\n\nExamples\n\njulia> join([\"apples\", \"bananas\", \"pineapples\"], \", \", \" and \")\n\"apples, bananas and pineapples\"\n\njulia> join([1,2,3,4,5])\n\"12345\"\n\n\n\n\n\n","category":"function"},{"location":"base/strings/#Base.chop","page":"字符串","title":"Base.chop","text":"chop(s::AbstractString; head::Integer = 0, tail::Integer = 1)\n\nRemove the first head and the last tail characters from s. The call chop(s) removes the last character from s. If it is requested to remove more characters than length(s) then an empty string is returned.\n\nSee also chomp, startswith, first.\n\nExamples\n\njulia> a = \"March\"\n\"March\"\n\njulia> chop(a)\n\"Marc\"\n\njulia> chop(a, head = 1, tail = 2)\n\"ar\"\n\njulia> chop(a, head = 5, tail = 5)\n\"\"\n\n\n\n\n\n","category":"function"},{"location":"base/strings/#Base.chomp","page":"字符串","title":"Base.chomp","text":"chomp(s::AbstractString) -> SubString\n\nRemove a single trailing newline from a string.\n\nSee also chop.\n\nExamples\n\njulia> chomp(\"Hello\\n\")\n\"Hello\"\n\n\n\n\n\n","category":"function"},{"location":"base/strings/#Base.thisind","page":"字符串","title":"Base.thisind","text":"thisind(s::AbstractString, i::Integer) -> Int\n\nIf i is in bounds in s return the index of the start of the character whose encoding code unit i is part of. In other words, if i is the start of a character, return i; if i is not the start of a character, rewind until the start of a character and return that index. If i is equal to 0 or ncodeunits(s)+1 return i. In all other cases throw BoundsError.\n\nExamples\n\njulia> thisind(\"α\", 0)\n0\n\njulia> thisind(\"α\", 1)\n1\n\njulia> thisind(\"α\", 2)\n1\n\njulia> thisind(\"α\", 3)\n3\n\njulia> thisind(\"α\", 4)\nERROR: BoundsError: attempt to access 2-codeunit String at index [4]\n[...]\n\njulia> thisind(\"α\", -1)\nERROR: BoundsError: attempt to access 2-codeunit String at index [-1]\n[...]\n\n\n\n\n\n","category":"function"},{"location":"base/strings/#Base.nextind","page":"字符串","title":"Base.nextind","text":"nextind(str::AbstractString, i::Integer, n::Integer=1) -> Int\n\nCase n == 1\nIf i is in bounds in s return the index of the start of the character whose encoding starts after index i. In other words, if i is the start of a character, return the start of the next character; if i is not the start of a character, move forward until the start of a character and return that index. If i is equal to 0 return 1. If i is in bounds but greater or equal to lastindex(str) return ncodeunits(str)+1. Otherwise throw BoundsError.\nCase n > 1\nBehaves like applying n times nextind for n==1. The only difference is that if n is so large that applying nextind would reach ncodeunits(str)+1 then each remaining iteration increases the returned value by 1. This means that in this case nextind can return a value greater than ncodeunits(str)+1.\nCase n == 0\nReturn i only if i is a valid index in s or is equal to 0. Otherwise StringIndexError or BoundsError is thrown.\n\nExamples\n\njulia> nextind(\"α\", 0)\n1\n\njulia> nextind(\"α\", 1)\n3\n\njulia> nextind(\"α\", 3)\nERROR: BoundsError: attempt to access 2-codeunit String at index [3]\n[...]\n\njulia> nextind(\"α\", 0, 2)\n3\n\njulia> nextind(\"α\", 1, 2)\n4\n\n\n\n\n\n","category":"function"},{"location":"base/strings/#Base.prevind","page":"字符串","title":"Base.prevind","text":"prevind(str::AbstractString, i::Integer, n::Integer=1) -> Int\n\nCase n == 1\nIf i is in bounds in s return the index of the start of the character whose encoding starts before index i. In other words, if i is the start of a character, return the start of the previous character; if i is not the start of a character, rewind until the start of a character and return that index. If i is equal to 1 return 0. If i is equal to ncodeunits(str)+1 return lastindex(str). Otherwise throw BoundsError.\nCase n > 1\nBehaves like applying n times prevind for n==1. The only difference is that if n is so large that applying prevind would reach 0 then each remaining iteration decreases the returned value by 1. This means that in this case prevind can return a negative value.\nCase n == 0\nReturn i only if i is a valid index in str or is equal to ncodeunits(str)+1. Otherwise StringIndexError or BoundsError is thrown.\n\nExamples\n\njulia> prevind(\"α\", 3)\n1\n\njulia> prevind(\"α\", 1)\n0\n\njulia> prevind(\"α\", 0)\nERROR: BoundsError: attempt to access 2-codeunit String at index [0]\n[...]\n\njulia> prevind(\"α\", 2, 2)\n0\n\njulia> prevind(\"α\", 2, 3)\n-1\n\n\n\n\n\n","category":"function"},{"location":"base/strings/#Base.Unicode.textwidth","page":"字符串","title":"Base.Unicode.textwidth","text":"textwidth(c)\n\nGive the number of columns needed to print a character.\n\nExamples\n\njulia> textwidth('α')\n1\n\njulia> textwidth('⛵')\n2\n\n\n\n\n\ntextwidth(s::AbstractString)\n\nGive the number of columns needed to print a string.\n\nExamples\n\njulia> textwidth(\"March\")\n5\n\n\n\n\n\n","category":"function"},{"location":"base/strings/#Base.isascii","page":"字符串","title":"Base.isascii","text":"isascii(c::Union{AbstractChar,AbstractString}) -> Bool\n\nTest whether a character belongs to the ASCII character set, or whether this is true for all elements of a string.\n\nExamples\n\njulia> isascii('a')\ntrue\n\njulia> isascii('α')\nfalse\n\njulia> isascii(\"abc\")\ntrue\n\njulia> isascii(\"αβγ\")\nfalse\n\nFor example, isascii can be used as a predicate function for filter or replace to remove or replace non-ASCII characters, respectively:\n\njulia> filter(isascii, \"abcdeγfgh\") # discard non-ASCII chars\n\"abcdefgh\"\n\njulia> replace(\"abcdeγfgh\", !isascii=>' ') # replace non-ASCII chars with spaces\n\"abcde fgh\"\n\n\n\n\n\n","category":"function"},{"location":"base/strings/#Base.Unicode.iscntrl","page":"字符串","title":"Base.Unicode.iscntrl","text":"iscntrl(c::AbstractChar) -> Bool\n\nTests whether a character is a control character. Control characters are the non-printing characters of the Latin-1 subset of Unicode.\n\nExamples\n\njulia> iscntrl('\\x01')\ntrue\n\njulia> iscntrl('a')\nfalse\n\n\n\n\n\n","category":"function"},{"location":"base/strings/#Base.Unicode.isdigit","page":"字符串","title":"Base.Unicode.isdigit","text":"isdigit(c::AbstractChar) -> Bool\n\nTests whether a character is a decimal digit (0-9).\n\nExamples\n\njulia> isdigit('❤')\nfalse\n\njulia> isdigit('9')\ntrue\n\njulia> isdigit('α')\nfalse\n\n\n\n\n\n","category":"function"},{"location":"base/strings/#Base.Unicode.isletter","page":"字符串","title":"Base.Unicode.isletter","text":"isletter(c::AbstractChar) -> Bool\n\nTest whether a character is a letter. A character is classified as a letter if it belongs to the Unicode general category Letter, i.e. a character whose category code begins with 'L'.\n\nExamples\n\njulia> isletter('❤')\nfalse\n\njulia> isletter('α')\ntrue\n\njulia> isletter('9')\nfalse\n\n\n\n\n\n","category":"function"},{"location":"base/strings/#Base.Unicode.islowercase","page":"字符串","title":"Base.Unicode.islowercase","text":"islowercase(c::AbstractChar) -> Bool\n\nTests whether a character is a lowercase letter (according to the Unicode standard's Lowercase derived property).\n\nSee also isuppercase.\n\nExamples\n\njulia> islowercase('α')\ntrue\n\njulia> islowercase('Γ')\nfalse\n\njulia> islowercase('❤')\nfalse\n\n\n\n\n\n","category":"function"},{"location":"base/strings/#Base.Unicode.isnumeric","page":"字符串","title":"Base.Unicode.isnumeric","text":"isnumeric(c::AbstractChar) -> Bool\n\nTests whether a character is numeric. A character is classified as numeric if it belongs to the Unicode general category Number, i.e. a character whose category code begins with 'N'.\n\nNote that this broad category includes characters such as ¾ and ௰. Use isdigit to check whether a character a decimal digit between 0 and 9.\n\nExamples\n\njulia> isnumeric('௰')\ntrue\n\njulia> isnumeric('9')\ntrue\n\njulia> isnumeric('α')\nfalse\n\njulia> isnumeric('❤')\nfalse\n\n\n\n\n\n","category":"function"},{"location":"base/strings/#Base.Unicode.isprint","page":"字符串","title":"Base.Unicode.isprint","text":"isprint(c::AbstractChar) -> Bool\n\nTests whether a character is printable, including spaces, but not a control character.\n\nExamples\n\njulia> isprint('\\x01')\nfalse\n\njulia> isprint('A')\ntrue\n\n\n\n\n\n","category":"function"},{"location":"base/strings/#Base.Unicode.ispunct","page":"字符串","title":"Base.Unicode.ispunct","text":"ispunct(c::AbstractChar) -> Bool\n\nTests whether a character belongs to the Unicode general category Punctuation, i.e. a character whose category code begins with 'P'.\n\nExamples\n\njulia> ispunct('α')\nfalse\n\njulia> ispunct('/')\ntrue\n\njulia> ispunct(';')\ntrue\n\n\n\n\n\n","category":"function"},{"location":"base/strings/#Base.Unicode.isspace","page":"字符串","title":"Base.Unicode.isspace","text":"isspace(c::AbstractChar) -> Bool\n\nTests whether a character is any whitespace character. Includes ASCII characters '\\t', '\\n', '\\v', '\\f', '\\r', and ' ', Latin-1 character U+0085, and characters in Unicode category Zs.\n\nExamples\n\njulia> isspace('\\n')\ntrue\n\njulia> isspace('\\r')\ntrue\n\njulia> isspace(' ')\ntrue\n\njulia> isspace('\\x20')\ntrue\n\n\n\n\n\n","category":"function"},{"location":"base/strings/#Base.Unicode.isuppercase","page":"字符串","title":"Base.Unicode.isuppercase","text":"isuppercase(c::AbstractChar) -> Bool\n\nTests whether a character is an uppercase letter (according to the Unicode standard's Uppercase derived property).\n\nSee also islowercase.\n\nExamples\n\njulia> isuppercase('γ')\nfalse\n\njulia> isuppercase('Γ')\ntrue\n\njulia> isuppercase('❤')\nfalse\n\n\n\n\n\n","category":"function"},{"location":"base/strings/#Base.Unicode.isxdigit","page":"字符串","title":"Base.Unicode.isxdigit","text":"isxdigit(c::AbstractChar) -> Bool\n\nTest whether a character is a valid hexadecimal digit. Note that this does not include x (as in the standard 0x prefix).\n\nExamples\n\njulia> isxdigit('a')\ntrue\n\njulia> isxdigit('x')\nfalse\n\n\n\n\n\n","category":"function"},{"location":"base/strings/#Base.escape_string","page":"字符串","title":"Base.escape_string","text":"escape_string(str::AbstractString[, esc]; keep = ())::AbstractString\nescape_string(io, str::AbstractString[, esc]; keep = ())::Nothing\n\nGeneral escaping of traditional C and Unicode escape sequences. The first form returns the escaped string, the second prints the result to io.\n\nBackslashes (\\) are escaped with a double-backslash (\"\\\\\"). Non-printable characters are escaped either with their standard C escape codes, \"\\0\" for NUL (if unambiguous), unicode code point (\"\\u\" prefix) or hex (\"\\x\" prefix).\n\nThe optional esc argument specifies any additional characters that should also be escaped by a prepending backslash (\" is also escaped by default in the first form).\n\nThe argument keep specifies a collection of characters which are to be kept as they are. Notice that esc has precedence here.\n\nSee also unescape_string for the reverse operation.\n\ncompat: Julia 1.7\nThe keep argument is available as of Julia 1.7.\n\nExamples\n\njulia> escape_string(\"aaa\\nbbb\")\n\"aaa\\\\nbbb\"\n\njulia> escape_string(\"aaa\\nbbb\"; keep = '\\n')\n\"aaa\\nbbb\"\n\njulia> escape_string(\"\\xfe\\xff\") # invalid utf-8\n\"\\\\xfe\\\\xff\"\n\njulia> escape_string(string('\\u2135','\\0')) # unambiguous\n\"ℵ\\\\0\"\n\njulia> escape_string(string('\\u2135','\\0','0')) # \\0 would be ambiguous\n\"ℵ\\\\x000\"\n\n\n\n\n\n","category":"function"},{"location":"base/strings/#Base.unescape_string","page":"字符串","title":"Base.unescape_string","text":"unescape_string(str::AbstractString, keep = ())::AbstractString\nunescape_string(io, s::AbstractString, keep = ())::Nothing\n\nGeneral unescaping of traditional C and Unicode escape sequences. The first form returns the escaped string, the second prints the result to io. The argument keep specifies a collection of characters which (along with backlashes) are to be kept as they are.\n\nThe following escape sequences are recognised:\n\nEscaped backslash (\\\\)\nEscaped double-quote (\\\")\nStandard C escape sequences (\\a, \\b, \\t, \\n, \\v, \\f, \\r, \\e)\nUnicode BMP code points (\\u with 1-4 trailing hex digits)\nAll Unicode code points (\\U with 1-8 trailing hex digits; max value = 0010ffff)\nHex bytes (\\x with 1-2 trailing hex digits)\nOctal bytes (\\ with 1-3 trailing octal digits)\n\nSee also escape_string.\n\nExamples\n\njulia> unescape_string(\"aaa\\\\nbbb\") # C escape sequence\n\"aaa\\nbbb\"\n\njulia> unescape_string(\"\\\\u03c0\") # unicode\n\"π\"\n\njulia> unescape_string(\"\\\\101\") # octal\n\"A\"\n\njulia> unescape_string(\"aaa \\\\g \\\\n\", ['g']) # using `keep` argument\n\"aaa \\\\g \\n\"\n\n\n\n\n\n","category":"function"},{"location":"stdlib/Libdl/#动态链接器","page":"动态链接器","title":"动态链接器","text":"","category":"section"},{"location":"stdlib/Libdl/","page":"动态链接器","title":"动态链接器","text":"Libdl.dlopen\nLibdl.dlopen_e\nLibdl.RTLD_NOW\nLibdl.dlsym\nLibdl.dlsym_e\nLibdl.dlclose\nLibdl.dlext\nLibdl.dllist\nLibdl.dlpath\nLibdl.find_library\nLibdl.DL_LOAD_PATH","category":"page"},{"location":"stdlib/Libdl/#Base.Libc.Libdl.dlopen","page":"动态链接器","title":"Base.Libc.Libdl.dlopen","text":"dlopen(libfile::AbstractString [, flags::Integer]; throw_error:Bool = true)\n\nLoad a shared library, returning an opaque handle.\n\nThe extension given by the constant dlext (.so, .dll, or .dylib) can be omitted from the libfile string, as it is automatically appended if needed. If libfile is not an absolute path name, then the paths in the array DL_LOAD_PATH are searched for libfile, followed by the system load path.\n\nThe optional flags argument is a bitwise-or of zero or more of RTLD_LOCAL, RTLD_GLOBAL, RTLD_LAZY, RTLD_NOW, RTLD_NODELETE, RTLD_NOLOAD, RTLD_DEEPBIND, and RTLD_FIRST. These are converted to the corresponding flags of the POSIX (and/or GNU libc and/or MacOS) dlopen command, if possible, or are ignored if the specified functionality is not available on the current platform. The default flags are platform specific. On MacOS the default dlopen flags are RTLD_LAZY|RTLD_DEEPBIND|RTLD_GLOBAL while on other platforms the defaults are RTLD_LAZY|RTLD_DEEPBIND|RTLD_LOCAL. An important usage of these flags is to specify non default behavior for when the dynamic library loader binds library references to exported symbols and if the bound references are put into process local or global scope. For instance RTLD_LAZY|RTLD_DEEPBIND|RTLD_GLOBAL allows the library's symbols to be available for usage in other shared libraries, addressing situations where there are dependencies between shared libraries.\n\nIf the library cannot be found, this method throws an error, unless the keyword argument throw_error is set to false, in which case this method returns nothing.\n\nnote: Note\nFrom Julia 1.6 on, this method replaces paths starting with @executable_path/ with the path to the Julia executable, allowing for relocatable relative-path loads. In Julia 1.5 and earlier, this only worked on macOS.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/Libdl/#Base.Libc.Libdl.dlopen_e","page":"动态链接器","title":"Base.Libc.Libdl.dlopen_e","text":"dlopen_e(libfile::AbstractString [, flags::Integer])\n\nSimilar to dlopen, except returns C_NULL instead of raising errors. This method is now deprecated in favor of dlopen(libfile::AbstractString [, flags::Integer]; throw_error=false).\n\n\n\n\n\n","category":"function"},{"location":"stdlib/Libdl/#Base.Libc.Libdl.RTLD_NOW","page":"动态链接器","title":"Base.Libc.Libdl.RTLD_NOW","text":"RTLD_DEEPBIND\nRTLD_FIRST\nRTLD_GLOBAL\nRTLD_LAZY\nRTLD_LOCAL\nRTLD_NODELETE\nRTLD_NOLOAD\nRTLD_NOW\n\nEnum constant for dlopen. See your platform man page for details, if applicable.\n\n\n\n\n\n","category":"constant"},{"location":"stdlib/Libdl/#Base.Libc.Libdl.dlsym","page":"动态链接器","title":"Base.Libc.Libdl.dlsym","text":"dlsym(handle, sym; throw_error::Bool = true)\n\nLook up a symbol from a shared library handle, return callable function pointer on success.\n\nIf the symbol cannot be found, this method throws an error, unless the keyword argument throw_error is set to false, in which case this method returns nothing.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/Libdl/#Base.Libc.Libdl.dlsym_e","page":"动态链接器","title":"Base.Libc.Libdl.dlsym_e","text":"dlsym_e(handle, sym)\n\nLook up a symbol from a shared library handle, silently return C_NULL on lookup failure. This method is now deprecated in favor of dlsym(handle, sym; throw_error=false).\n\n\n\n\n\n","category":"function"},{"location":"stdlib/Libdl/#Base.Libc.Libdl.dlclose","page":"动态链接器","title":"Base.Libc.Libdl.dlclose","text":"dlclose(handle)\n\nClose shared library referenced by handle.\n\n\n\n\n\ndlclose(::Nothing)\n\nFor the very common pattern usage pattern of\n\ntry\n hdl = dlopen(library_name)\n ... do something\nfinally\n dlclose(hdl)\nend\n\nWe define a dlclose() method that accepts a parameter of type Nothing, so that user code does not have to change its behavior for the case that library_name was not found.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/Libdl/#Base.Libc.Libdl.dlext","page":"动态链接器","title":"Base.Libc.Libdl.dlext","text":"dlext\n\nFile extension for dynamic libraries (e.g. dll, dylib, so) on the current platform.\n\n\n\n\n\n","category":"constant"},{"location":"stdlib/Libdl/#Base.Libc.Libdl.dllist","page":"动态链接器","title":"Base.Libc.Libdl.dllist","text":"dllist()\n\nReturn the paths of dynamic libraries currently loaded in a Vector{String}.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/Libdl/#Base.Libc.Libdl.dlpath","page":"动态链接器","title":"Base.Libc.Libdl.dlpath","text":"dlpath(handle::Ptr{Cvoid})\n\nGiven a library handle from dlopen, return the full path.\n\n\n\n\n\ndlpath(libname::Union{AbstractString, Symbol})\n\nGet the full path of the library libname.\n\nExample\n\njulia> dlpath(\"libjulia\")\n\n\n\n\n\n","category":"function"},{"location":"stdlib/Libdl/#Base.Libc.Libdl.find_library","page":"动态链接器","title":"Base.Libc.Libdl.find_library","text":"find_library(names, locations)\n\nSearches for the first library in names in the paths in the locations list, DL_LOAD_PATH, or system library paths (in that order) which can successfully be dlopen'd. On success, the return value will be one of the names (potentially prefixed by one of the paths in locations). This string can be assigned to a global const and used as the library name in future ccall's. On failure, it returns the empty string.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/Libdl/#Base.DL_LOAD_PATH","page":"动态链接器","title":"Base.DL_LOAD_PATH","text":"DL_LOAD_PATH\n\nWhen calling dlopen, the paths in this list will be searched first, in order, before searching the system locations for a valid library handle.\n\n\n\n\n\n","category":"constant"},{"location":"base/arrays/#lib-arrays","page":"数组","title":"数组","text":"","category":"section"},{"location":"base/arrays/#构造函数与类型","page":"数组","title":"构造函数与类型","text":"","category":"section"},{"location":"base/arrays/","page":"数组","title":"数组","text":"Core.AbstractArray\nBase.AbstractVector\nBase.AbstractMatrix\nBase.AbstractVecOrMat\nCore.Array\nCore.Array(::UndefInitializer, ::Any)\nCore.Array(::Nothing, ::Any)\nCore.Array(::Missing, ::Any)\nCore.UndefInitializer\nCore.undef\nBase.Vector\nBase.Vector(::UndefInitializer, ::Any)\nBase.Vector(::Nothing, ::Any)\nBase.Vector(::Missing, ::Any)\nBase.Matrix\nBase.Matrix(::UndefInitializer, ::Any, ::Any)\nBase.Matrix(::Nothing, ::Any, ::Any)\nBase.Matrix(::Missing, ::Any, ::Any)\nBase.VecOrMat\nCore.DenseArray\nBase.DenseVector\nBase.DenseMatrix\nBase.DenseVecOrMat\nBase.StridedArray\nBase.StridedVector\nBase.StridedMatrix\nBase.StridedVecOrMat\nBase.getindex(::Type, ::Any...)\nBase.zeros\nBase.ones\nBase.BitArray\nBase.BitArray(::UndefInitializer, ::Integer...)\nBase.BitArray(::Any)\nBase.trues\nBase.falses\nBase.fill\nBase.fill!\nBase.empty\nBase.similar","category":"page"},{"location":"base/arrays/#Core.AbstractArray","page":"数组","title":"Core.AbstractArray","text":"AbstractArray{T,N}\n\nSupertype for N-dimensional arrays (or array-like types) with elements of type T. Array and other types are subtypes of this. See the manual section on the AbstractArray interface.\n\nSee also: AbstractVector, AbstractMatrix, eltype, ndims.\n\n\n\n\n\n","category":"type"},{"location":"base/arrays/#Base.AbstractVector","page":"数组","title":"Base.AbstractVector","text":"AbstractVector{T}\n\nSupertype for one-dimensional arrays (or array-like types) with elements of type T. Alias for AbstractArray{T,1}.\n\n\n\n\n\n","category":"type"},{"location":"base/arrays/#Base.AbstractMatrix","page":"数组","title":"Base.AbstractMatrix","text":"AbstractMatrix{T}\n\nSupertype for two-dimensional arrays (or array-like types) with elements of type T. Alias for AbstractArray{T,2}.\n\n\n\n\n\n","category":"type"},{"location":"base/arrays/#Base.AbstractVecOrMat","page":"数组","title":"Base.AbstractVecOrMat","text":"AbstractVecOrMat{T}\n\nUnion type of AbstractVector{T} and AbstractMatrix{T}.\n\n\n\n\n\n","category":"type"},{"location":"base/arrays/#Core.Array","page":"数组","title":"Core.Array","text":"Array{T,N} <: AbstractArray{T,N}\n\nN-dimensional dense array with elements of type T.\n\n\n\n\n\n","category":"type"},{"location":"base/arrays/#Core.Array-Tuple{UndefInitializer, Any}","page":"数组","title":"Core.Array","text":"Array{T}(undef, dims)\nArray{T,N}(undef, dims)\n\nConstruct an uninitialized N-dimensional Array containing elements of type T. N can either be supplied explicitly, as in Array{T,N}(undef, dims), or be determined by the length or number of dims. dims may be a tuple or a series of integer arguments corresponding to the lengths in each dimension. If the rank N is supplied explicitly, then it must match the length or number of dims. Here undef is the UndefInitializer.\n\nExamples\n\njulia> A = Array{Float64, 2}(undef, 2, 3) # N given explicitly\n2×3 Matrix{Float64}:\n 6.90198e-310 6.90198e-310 6.90198e-310\n 6.90198e-310 6.90198e-310 0.0\n\njulia> B = Array{Float64}(undef, 4) # N determined by the input\n4-element Vector{Float64}:\n 2.360075077e-314\n NaN\n 2.2671131793e-314\n 2.299821756e-314\n\njulia> similar(B, 2, 4, 1) # use typeof(B), and the given size\n2×4×1 Array{Float64, 3}:\n[:, :, 1] =\n 2.26703e-314 2.26708e-314 0.0 2.80997e-314\n 0.0 2.26703e-314 2.26708e-314 0.0\n\n\n\n\n\n","category":"method"},{"location":"base/arrays/#Core.Array-Tuple{Nothing, Any}","page":"数组","title":"Core.Array","text":"Array{T}(nothing, dims)\nArray{T,N}(nothing, dims)\n\nConstruct an N-dimensional Array containing elements of type T, initialized with nothing entries. Element type T must be able to hold these values, i.e. Nothing <: T.\n\nExamples\n\njulia> Array{Union{Nothing, String}}(nothing, 2)\n2-element Vector{Union{Nothing, String}}:\n nothing\n nothing\n\njulia> Array{Union{Nothing, Int}}(nothing, 2, 3)\n2×3 Matrix{Union{Nothing, Int64}}:\n nothing nothing nothing\n nothing nothing nothing\n\n\n\n\n\n","category":"method"},{"location":"base/arrays/#Core.Array-Tuple{Missing, Any}","page":"数组","title":"Core.Array","text":"Array{T}(missing, dims)\nArray{T,N}(missing, dims)\n\nConstruct an N-dimensional Array containing elements of type T, initialized with missing entries. Element type T must be able to hold these values, i.e. Missing <: T.\n\nExamples\n\njulia> Array{Union{Missing, String}}(missing, 2)\n2-element Vector{Union{Missing, String}}:\n missing\n missing\n\njulia> Array{Union{Missing, Int}}(missing, 2, 3)\n2×3 Matrix{Union{Missing, Int64}}:\n missing missing missing\n missing missing missing\n\n\n\n\n\n","category":"method"},{"location":"base/arrays/#Core.UndefInitializer","page":"数组","title":"Core.UndefInitializer","text":"UndefInitializer\n\nSingleton type used in array initialization, indicating the array-constructor-caller would like an uninitialized array. See also undef, an alias for UndefInitializer().\n\nExamples\n\njulia> Array{Float64, 1}(UndefInitializer(), 3)\n3-element Array{Float64, 1}:\n 2.2752528595e-314\n 2.202942107e-314\n 2.275252907e-314\n\n\n\n\n\n","category":"type"},{"location":"base/arrays/#Core.undef","page":"数组","title":"Core.undef","text":"undef\n\nAlias for UndefInitializer(), which constructs an instance of the singleton type UndefInitializer, used in array initialization to indicate the array-constructor-caller would like an uninitialized array.\n\nSee also: missing, similar.\n\nExamples\n\njulia> Array{Float64, 1}(undef, 3)\n3-element Vector{Float64}:\n 2.2752528595e-314\n 2.202942107e-314\n 2.275252907e-314\n\n\n\n\n\n","category":"constant"},{"location":"base/arrays/#Base.Vector","page":"数组","title":"Base.Vector","text":"Vector{T} <: AbstractVector{T}\n\nOne-dimensional dense array with elements of type T, often used to represent a mathematical vector. Alias for Array{T,1}.\n\nSee also empty, similar and zero for creating vectors.\n\n\n\n\n\n","category":"type"},{"location":"base/arrays/#Base.Vector-Tuple{UndefInitializer, Any}","page":"数组","title":"Base.Vector","text":"Vector{T}(undef, n)\n\nConstruct an uninitialized Vector{T} of length n.\n\nExamples\n\njulia> Vector{Float64}(undef, 3)\n3-element Array{Float64, 1}:\n 6.90966e-310\n 6.90966e-310\n 6.90966e-310\n\n\n\n\n\n","category":"method"},{"location":"base/arrays/#Base.Vector-Tuple{Nothing, Any}","page":"数组","title":"Base.Vector","text":"Vector{T}(nothing, m)\n\nConstruct a Vector{T} of length m, initialized with nothing entries. Element type T must be able to hold these values, i.e. Nothing <: T.\n\nExamples\n\njulia> Vector{Union{Nothing, String}}(nothing, 2)\n2-element Vector{Union{Nothing, String}}:\n nothing\n nothing\n\n\n\n\n\n","category":"method"},{"location":"base/arrays/#Base.Vector-Tuple{Missing, Any}","page":"数组","title":"Base.Vector","text":"Vector{T}(missing, m)\n\nConstruct a Vector{T} of length m, initialized with missing entries. Element type T must be able to hold these values, i.e. Missing <: T.\n\nExamples\n\njulia> Vector{Union{Missing, String}}(missing, 2)\n2-element Vector{Union{Missing, String}}:\n missing\n missing\n\n\n\n\n\n","category":"method"},{"location":"base/arrays/#Base.Matrix","page":"数组","title":"Base.Matrix","text":"Matrix{T} <: AbstractMatrix{T}\n\nTwo-dimensional dense array with elements of type T, often used to represent a mathematical matrix. Alias for Array{T,2}.\n\nSee also fill, zeros, undef and similar for creating matrices.\n\n\n\n\n\n","category":"type"},{"location":"base/arrays/#Base.Matrix-Tuple{UndefInitializer, Any, Any}","page":"数组","title":"Base.Matrix","text":"Matrix{T}(undef, m, n)\n\nConstruct an uninitialized Matrix{T} of size m×n.\n\nExamples\n\njulia> Matrix{Float64}(undef, 2, 3)\n2×3 Array{Float64, 2}:\n 2.36365e-314 2.28473e-314 5.0e-324\n 2.26704e-314 2.26711e-314 NaN\n\njulia> similar(ans, Int32, 2, 2)\n2×2 Matrix{Int32}:\n 490537216 1277177453\n 1 1936748399\n\n\n\n\n\n","category":"method"},{"location":"base/arrays/#Base.Matrix-Tuple{Nothing, Any, Any}","page":"数组","title":"Base.Matrix","text":"Matrix{T}(nothing, m, n)\n\nConstruct a Matrix{T} of size m×n, initialized with nothing entries. Element type T must be able to hold these values, i.e. Nothing <: T.\n\nExamples\n\njulia> Matrix{Union{Nothing, String}}(nothing, 2, 3)\n2×3 Matrix{Union{Nothing, String}}:\n nothing nothing nothing\n nothing nothing nothing\n\n\n\n\n\n","category":"method"},{"location":"base/arrays/#Base.Matrix-Tuple{Missing, Any, Any}","page":"数组","title":"Base.Matrix","text":"Matrix{T}(missing, m, n)\n\nConstruct a Matrix{T} of size m×n, initialized with missing entries. Element type T must be able to hold these values, i.e. Missing <: T.\n\nExamples\n\njulia> Matrix{Union{Missing, String}}(missing, 2, 3)\n2×3 Matrix{Union{Missing, String}}:\n missing missing missing\n missing missing missing\n\n\n\n\n\n","category":"method"},{"location":"base/arrays/#Base.VecOrMat","page":"数组","title":"Base.VecOrMat","text":"VecOrMat{T}\n\nUnion type of Vector{T} and Matrix{T} which allows functions to accept either a Matrix or a Vector.\n\nExamples\n\njulia> Vector{Float64} <: VecOrMat{Float64}\ntrue\n\njulia> Matrix{Float64} <: VecOrMat{Float64}\ntrue\n\njulia> Array{Float64, 3} <: VecOrMat{Float64}\nfalse\n\n\n\n\n\n","category":"type"},{"location":"base/arrays/#Core.DenseArray","page":"数组","title":"Core.DenseArray","text":"DenseArray{T, N} <: AbstractArray{T,N}\n\nN-dimensional dense array with elements of type T. The elements of a dense array are stored contiguously in memory.\n\n\n\n\n\n","category":"type"},{"location":"base/arrays/#Base.DenseVector","page":"数组","title":"Base.DenseVector","text":"DenseVector{T}\n\nOne-dimensional DenseArray with elements of type T. Alias for DenseArray{T,1}.\n\n\n\n\n\n","category":"type"},{"location":"base/arrays/#Base.DenseMatrix","page":"数组","title":"Base.DenseMatrix","text":"DenseMatrix{T}\n\nTwo-dimensional DenseArray with elements of type T. Alias for DenseArray{T,2}.\n\n\n\n\n\n","category":"type"},{"location":"base/arrays/#Base.DenseVecOrMat","page":"数组","title":"Base.DenseVecOrMat","text":"DenseVecOrMat{T}\n\nUnion type of DenseVector{T} and DenseMatrix{T}.\n\n\n\n\n\n","category":"type"},{"location":"base/arrays/#Base.StridedArray","page":"数组","title":"Base.StridedArray","text":"StridedArray{T, N}\n\nA hard-coded Union of common array types that follow the strided array interface, with elements of type T and N dimensions.\n\nIf A is a StridedArray, then its elements are stored in memory with offsets, which may vary between dimensions but are constant within a dimension. For example, A could have stride 2 in dimension 1, and stride 3 in dimension 2. Incrementing A along dimension d jumps in memory by [strides(A, d)] slots. Strided arrays are particularly important and useful because they can sometimes be passed directly as pointers to foreign language libraries like BLAS.\n\n\n\n\n\n","category":"type"},{"location":"base/arrays/#Base.StridedVector","page":"数组","title":"Base.StridedVector","text":"StridedVector{T}\n\nOne dimensional StridedArray with elements of type T.\n\n\n\n\n\n","category":"type"},{"location":"base/arrays/#Base.StridedMatrix","page":"数组","title":"Base.StridedMatrix","text":"StridedMatrix{T}\n\nTwo dimensional StridedArray with elements of type T.\n\n\n\n\n\n","category":"type"},{"location":"base/arrays/#Base.StridedVecOrMat","page":"数组","title":"Base.StridedVecOrMat","text":"StridedVecOrMat{T}\n\nUnion type of StridedVector and StridedMatrix with elements of type T.\n\n\n\n\n\n","category":"type"},{"location":"base/arrays/#Base.getindex-Tuple{Type, Vararg{Any}}","page":"数组","title":"Base.getindex","text":"getindex(type[, elements...])\n\nConstruct a 1-d array of the specified type. This is usually called with the syntax Type[]. Element values can be specified using Type[a,b,c,...].\n\nExamples\n\njulia> Int8[1, 2, 3]\n3-element Vector{Int8}:\n 1\n 2\n 3\n\njulia> getindex(Int8, 1, 2, 3)\n3-element Vector{Int8}:\n 1\n 2\n 3\n\n\n\n\n\n","category":"method"},{"location":"base/arrays/#Base.zeros","page":"数组","title":"Base.zeros","text":"zeros([T=Float64,] dims::Tuple)\nzeros([T=Float64,] dims...)\n\nCreate an Array, with element type T, of all zeros with size specified by dims. See also fill, ones, zero.\n\nExamples\n\njulia> zeros(1)\n1-element Vector{Float64}:\n 0.0\n\njulia> zeros(Int8, 2, 3)\n2×3 Matrix{Int8}:\n 0 0 0\n 0 0 0\n\n\n\n\n\n","category":"function"},{"location":"base/arrays/#Base.ones","page":"数组","title":"Base.ones","text":"ones([T=Float64,] dims::Tuple)\nones([T=Float64,] dims...)\n\nCreate an Array, with element type T, of all ones with size specified by dims. See also fill, zeros.\n\nExamples\n\njulia> ones(1,2)\n1×2 Matrix{Float64}:\n 1.0 1.0\n\njulia> ones(ComplexF64, 2, 3)\n2×3 Matrix{ComplexF64}:\n 1.0+0.0im 1.0+0.0im 1.0+0.0im\n 1.0+0.0im 1.0+0.0im 1.0+0.0im\n\n\n\n\n\n","category":"function"},{"location":"base/arrays/#Base.BitArray","page":"数组","title":"Base.BitArray","text":"BitArray{N} <: AbstractArray{Bool, N}\n\nSpace-efficient N-dimensional boolean array, using just one bit for each boolean value.\n\nBitArrays pack up to 64 values into every 8 bytes, resulting in an 8x space efficiency over Array{Bool, N} and allowing some operations to work on 64 values at once.\n\nBy default, Julia returns BitArrays from broadcasting operations that generate boolean elements (including dotted-comparisons like .==) as well as from the functions trues and falses.\n\nnote: Note\nDue to its packed storage format, concurrent access to the elements of a BitArray where at least one of them is a write is not thread safe.\n\n\n\n\n\n","category":"type"},{"location":"base/arrays/#Base.BitArray-Tuple{UndefInitializer, Vararg{Integer}}","page":"数组","title":"Base.BitArray","text":"BitArray(undef, dims::Integer...)\nBitArray{N}(undef, dims::NTuple{N,Int})\n\nConstruct an undef BitArray with the given dimensions. Behaves identically to the Array constructor. See undef.\n\nExamples\n\njulia> BitArray(undef, 2, 2)\n2×2 BitMatrix:\n 0 0\n 0 0\n\njulia> BitArray(undef, (3, 1))\n3×1 BitMatrix:\n 0\n 0\n 0\n\n\n\n\n\n","category":"method"},{"location":"base/arrays/#Base.BitArray-Tuple{Any}","page":"数组","title":"Base.BitArray","text":"BitArray(itr)\n\nConstruct a BitArray generated by the given iterable object. The shape is inferred from the itr object.\n\nExamples\n\njulia> BitArray([1 0; 0 1])\n2×2 BitMatrix:\n 1 0\n 0 1\n\njulia> BitArray(x+y == 3 for x = 1:2, y = 1:3)\n2×3 BitMatrix:\n 0 1 0\n 1 0 0\n\njulia> BitArray(x+y == 3 for x = 1:2 for y = 1:3)\n6-element BitVector:\n 0\n 1\n 0\n 1\n 0\n 0\n\n\n\n\n\n","category":"method"},{"location":"base/arrays/#Base.trues","page":"数组","title":"Base.trues","text":"trues(dims)\n\nCreate a BitArray with all values set to true.\n\nExamples\n\njulia> trues(2,3)\n2×3 BitMatrix:\n 1 1 1\n 1 1 1\n\n\n\n\n\n","category":"function"},{"location":"base/arrays/#Base.falses","page":"数组","title":"Base.falses","text":"falses(dims)\n\nCreate a BitArray with all values set to false.\n\nExamples\n\njulia> falses(2,3)\n2×3 BitMatrix:\n 0 0 0\n 0 0 0\n\n\n\n\n\n","category":"function"},{"location":"base/arrays/#Base.fill","page":"数组","title":"Base.fill","text":"fill(value, dims::Tuple)\nfill(value, dims...)\n\nCreate an array of size dims with every location set to value.\n\nFor example, fill(1.0, (5,5)) returns a 5×5 array of floats, with 1.0 in every location of the array.\n\nThe dimension lengths dims may be specified as either a tuple or a sequence of arguments. An N-length tuple or N arguments following the value specify an N-dimensional array. Thus, a common idiom for creating a zero-dimensional array with its only location set to x is fill(x).\n\nEvery location of the returned array is set to (and is thus === to) the value that was passed; this means that if the value is itself modified, all elements of the filled array will reflect that modification because they're still that very value. This is of no concern with fill(1.0, (5,5)) as the value 1.0 is immutable and cannot itself be modified, but can be unexpected with mutable values like — most commonly — arrays. For example, fill([], 3) places the very same empty array in all three locations of the returned vector:\n\njulia> v = fill([], 3)\n3-element Vector{Vector{Any}}:\n []\n []\n []\n\njulia> v[1] === v[2] === v[3]\ntrue\n\njulia> value = v[1]\nAny[]\n\njulia> push!(value, 867_5309)\n1-element Vector{Any}:\n 8675309\n\njulia> v\n3-element Vector{Vector{Any}}:\n [8675309]\n [8675309]\n [8675309]\n\nTo create an array of many independent inner arrays, use a comprehension instead. This creates a new and distinct array on each iteration of the loop:\n\njulia> v2 = [[] for _ in 1:3]\n3-element Vector{Vector{Any}}:\n []\n []\n []\n\njulia> v2[1] === v2[2] === v2[3]\nfalse\n\njulia> push!(v2[1], 8675309)\n1-element Vector{Any}:\n 8675309\n\njulia> v2\n3-element Vector{Vector{Any}}:\n [8675309]\n []\n []\n\nSee also: fill!, zeros, ones, similar.\n\nExamples\n\njulia> fill(1.0, (2,3))\n2×3 Matrix{Float64}:\n 1.0 1.0 1.0\n 1.0 1.0 1.0\n\njulia> fill(42)\n0-dimensional Array{Int64, 0}:\n42\n\njulia> A = fill(zeros(2), 2) # sets both elements to the same [0.0, 0.0] vector\n2-element Vector{Vector{Float64}}:\n [0.0, 0.0]\n [0.0, 0.0]\n\njulia> A[1][1] = 42; # modifies the filled value to be [42.0, 0.0]\n\njulia> A # both A[1] and A[2] are the very same vector\n2-element Vector{Vector{Float64}}:\n [42.0, 0.0]\n [42.0, 0.0]\n\n\n\n\n\n","category":"function"},{"location":"base/arrays/#Base.fill!","page":"数组","title":"Base.fill!","text":"fill!(A, x)\n\nFill array A with the value x. If x is an object reference, all elements will refer to the same object. fill!(A, Foo()) will return A filled with the result of evaluating Foo() once.\n\nExamples\n\njulia> A = zeros(2,3)\n2×3 Matrix{Float64}:\n 0.0 0.0 0.0\n 0.0 0.0 0.0\n\njulia> fill!(A, 2.)\n2×3 Matrix{Float64}:\n 2.0 2.0 2.0\n 2.0 2.0 2.0\n\njulia> a = [1, 1, 1]; A = fill!(Vector{Vector{Int}}(undef, 3), a); a[1] = 2; A\n3-element Vector{Vector{Int64}}:\n [2, 1, 1]\n [2, 1, 1]\n [2, 1, 1]\n\njulia> x = 0; f() = (global x += 1; x); fill!(Vector{Int}(undef, 3), f())\n3-element Vector{Int64}:\n 1\n 1\n 1\n\n\n\n\n\n","category":"function"},{"location":"base/arrays/#Base.empty","page":"数组","title":"Base.empty","text":"empty(x::Tuple)\n\nReturns an empty tuple, ().\n\n\n\n\n\nempty(v::AbstractVector, [eltype])\n\nCreate an empty vector similar to v, optionally changing the eltype.\n\nSee also: empty!, isempty, isassigned.\n\nExamples\n\njulia> empty([1.0, 2.0, 3.0])\nFloat64[]\n\njulia> empty([1.0, 2.0, 3.0], String)\nString[]\n\n\n\n\n\nempty(a::AbstractDict, [index_type=keytype(a)], [value_type=valtype(a)])\n\nCreate an empty AbstractDict container which can accept indices of type index_type and values of type value_type. The second and third arguments are optional and default to the input's keytype and valtype, respectively. (If only one of the two types is specified, it is assumed to be the value_type, and the index_type we default to keytype(a)).\n\nCustom AbstractDict subtypes may choose which specific dictionary type is best suited to return for the given index and value types, by specializing on the three-argument signature. The default is to return an empty Dict.\n\n\n\n\n\n","category":"function"},{"location":"base/arrays/#Base.similar","page":"数组","title":"Base.similar","text":"similar(array, [element_type=eltype(array)], [dims=size(array)])\n\nCreate an uninitialized mutable array with the given element type and size, based upon the given source array. The second and third arguments are both optional, defaulting to the given array's eltype and size. The dimensions may be specified either as a single tuple argument or as a series of integer arguments.\n\nCustom AbstractArray subtypes may choose which specific array type is best-suited to return for the given element type and dimensionality. If they do not specialize this method, the default is an Array{element_type}(undef, dims...).\n\nFor example, similar(1:10, 1, 4) returns an uninitialized Array{Int,2} since ranges are neither mutable nor support 2 dimensions:\n\njulia> similar(1:10, 1, 4)\n1×4 Matrix{Int64}:\n 4419743872 4374413872 4419743888 0\n\nConversely, similar(trues(10,10), 2) returns an uninitialized BitVector with two elements since BitArrays are both mutable and can support 1-dimensional arrays:\n\njulia> similar(trues(10,10), 2)\n2-element BitVector:\n 0\n 0\n\nSince BitArrays can only store elements of type Bool, however, if you request a different element type it will create a regular Array instead:\n\njulia> similar(falses(10), Float64, 2, 4)\n2×4 Matrix{Float64}:\n 2.18425e-314 2.18425e-314 2.18425e-314 2.18425e-314\n 2.18425e-314 2.18425e-314 2.18425e-314 2.18425e-314\n\nSee also: undef, isassigned.\n\n\n\n\n\nsimilar(storagetype, axes)\n\nCreate an uninitialized mutable array analogous to that specified by storagetype, but with axes specified by the last argument.\n\nExamples:\n\nsimilar(Array{Int}, axes(A))\n\ncreates an array that \"acts like\" an Array{Int} (and might indeed be backed by one), but which is indexed identically to A. If A has conventional indexing, this will be identical to Array{Int}(undef, size(A)), but if A has unconventional indexing then the indices of the result will match A.\n\nsimilar(BitArray, (axes(A, 2),))\n\nwould create a 1-dimensional logical array whose indices match those of the columns of A.\n\n\n\n\n\n","category":"function"},{"location":"base/arrays/#基础函数","page":"数组","title":"基础函数","text":"","category":"section"},{"location":"base/arrays/","page":"数组","title":"数组","text":"Base.ndims\nBase.size\nBase.axes(::Any)\nBase.axes(::AbstractArray, ::Any)\nBase.length(::AbstractArray)\nBase.keys(::AbstractArray)\nBase.eachindex\nBase.IndexStyle\nBase.IndexLinear\nBase.IndexCartesian\nBase.conj!\nBase.stride\nBase.strides","category":"page"},{"location":"base/arrays/#Base.ndims","page":"数组","title":"Base.ndims","text":"ndims(A::AbstractArray) -> Integer\n\nReturn the number of dimensions of A.\n\nSee also: size, axes.\n\nExamples\n\njulia> A = fill(1, (3,4,5));\n\njulia> ndims(A)\n3\n\n\n\n\n\n","category":"function"},{"location":"base/arrays/#Base.size","page":"数组","title":"Base.size","text":"size(A::AbstractArray, [dim])\n\nReturn a tuple containing the dimensions of A. Optionally you can specify a dimension to just get the length of that dimension.\n\nNote that size may not be defined for arrays with non-standard indices, in which case axes may be useful. See the manual chapter on arrays with custom indices.\n\nSee also: length, ndims, eachindex, sizeof.\n\nExamples\n\njulia> A = fill(1, (2,3,4));\n\njulia> size(A)\n(2, 3, 4)\n\njulia> size(A, 2)\n3\n\n\n\n\n\n","category":"function"},{"location":"base/arrays/#Base.axes-Tuple{Any}","page":"数组","title":"Base.axes","text":"axes(A)\n\nReturn the tuple of valid indices for array A.\n\nSee also: size, keys, eachindex.\n\nExamples\n\njulia> A = fill(1, (5,6,7));\n\njulia> axes(A)\n(Base.OneTo(5), Base.OneTo(6), Base.OneTo(7))\n\n\n\n\n\n","category":"method"},{"location":"base/arrays/#Base.axes-Tuple{AbstractArray, Any}","page":"数组","title":"Base.axes","text":"axes(A, d)\n\nReturn the valid range of indices for array A along dimension d.\n\nSee also size, and the manual chapter on arrays with custom indices.\n\nExamples\n\njulia> A = fill(1, (5,6,7));\n\njulia> axes(A, 2)\nBase.OneTo(6)\n\nUsage note\n\nEach of the indices has to be an AbstractUnitRange{<:Integer}, but at the same time can be a type that uses custom indices. So, for example, if you need a subset, use generalized indexing constructs like begin/end or firstindex/lastindex:\n\nix = axes(v, 1)\nix[2:end] # will work for eg Vector, but may fail in general\nix[(begin+1):end] # works for generalized indexes\n\n\n\n\n\n","category":"method"},{"location":"base/arrays/#Base.length-Tuple{AbstractArray}","page":"数组","title":"Base.length","text":"length(A::AbstractArray)\n\nReturn the number of elements in the array, defaults to prod(size(A)).\n\nExamples\n\njulia> length([1, 2, 3, 4])\n4\n\njulia> length([1 2; 3 4])\n4\n\n\n\n\n\n","category":"method"},{"location":"base/arrays/#Base.keys-Tuple{AbstractArray}","page":"数组","title":"Base.keys","text":"keys(a::AbstractArray)\n\nReturn an efficient array describing all valid indices for a arranged in the shape of a itself.\n\nThey keys of 1-dimensional arrays (vectors) are integers, whereas all other N-dimensional arrays use CartesianIndex to describe their locations. Often the special array types LinearIndices and CartesianIndices are used to efficiently represent these arrays of integers and CartesianIndexes, respectively.\n\nNote that the keys of an array might not be the most efficient index type; for maximum performance use eachindex instead.\n\n\n\n\n\n","category":"method"},{"location":"base/arrays/#Base.eachindex","page":"数组","title":"Base.eachindex","text":"eachindex(A...)\n\nCreate an iterable object for visiting each index of an AbstractArray A in an efficient manner. For array types that have opted into fast linear indexing (like Array), this is simply the range 1:length(A). For other array types, return a specialized Cartesian range to efficiently index into the array with indices specified for every dimension. For other iterables, including strings and dictionaries, return an iterator object supporting arbitrary index types (e.g. unevenly spaced or non-integer indices).\n\nIf you supply more than one AbstractArray argument, eachindex will create an iterable object that is fast for all arguments (a UnitRange if all inputs have fast linear indexing, a CartesianIndices otherwise). If the arrays have different sizes and/or dimensionalities, a DimensionMismatch exception will be thrown.\n\nExamples\n\njulia> A = [1 2; 3 4];\n\njulia> for i in eachindex(A) # linear indexing\n println(i)\n end\n1\n2\n3\n4\n\njulia> for i in eachindex(view(A, 1:2, 1:1)) # Cartesian indexing\n println(i)\n end\nCartesianIndex(1, 1)\nCartesianIndex(2, 1)\n\n\n\n\n\n","category":"function"},{"location":"base/arrays/#Base.IndexStyle","page":"数组","title":"Base.IndexStyle","text":"IndexStyle(A)\nIndexStyle(typeof(A))\n\nIndexStyle specifies the \"native indexing style\" for array A. When you define a new AbstractArray type, you can choose to implement either linear indexing (with IndexLinear) or cartesian indexing. If you decide to only implement linear indexing, then you must set this trait for your array type:\n\nBase.IndexStyle(::Type{<:MyArray}) = IndexLinear()\n\nThe default is IndexCartesian().\n\nJulia's internal indexing machinery will automatically (and invisibly) recompute all indexing operations into the preferred style. This allows users to access elements of your array using any indexing style, even when explicit methods have not been provided.\n\nIf you define both styles of indexing for your AbstractArray, this trait can be used to select the most performant indexing style. Some methods check this trait on their inputs, and dispatch to different algorithms depending on the most efficient access pattern. In particular, eachindex creates an iterator whose type depends on the setting of this trait.\n\n\n\n\n\n","category":"type"},{"location":"base/arrays/#Base.IndexLinear","page":"数组","title":"Base.IndexLinear","text":"IndexLinear()\n\nSubtype of IndexStyle used to describe arrays which are optimally indexed by one linear index.\n\nA linear indexing style uses one integer index to describe the position in the array (even if it's a multidimensional array) and column-major ordering is used to efficiently access the elements. This means that requesting eachindex from an array that is IndexLinear will return a simple one-dimensional range, even if it is multidimensional.\n\nA custom array that reports its IndexStyle as IndexLinear only needs to implement indexing (and indexed assignment) with a single Int index; all other indexing expressions — including multidimensional accesses — will be recomputed to the linear index. For example, if A were a 2×3 custom matrix with linear indexing, and we referenced A[1, 3], this would be recomputed to the equivalent linear index and call A[5] since 2*1 + 3 = 5.\n\nSee also IndexCartesian.\n\n\n\n\n\n","category":"type"},{"location":"base/arrays/#Base.IndexCartesian","page":"数组","title":"Base.IndexCartesian","text":"IndexCartesian()\n\nSubtype of IndexStyle used to describe arrays which are optimally indexed by a Cartesian index. This is the default for new custom AbstractArray subtypes.\n\nA Cartesian indexing style uses multiple integer indices to describe the position in a multidimensional array, with exactly one index per dimension. This means that requesting eachindex from an array that is IndexCartesian will return a range of CartesianIndices.\n\nA N-dimensional custom array that reports its IndexStyle as IndexCartesian needs to implement indexing (and indexed assignment) with exactly N Int indices; all other indexing expressions — including linear indexing — will be recomputed to the equivalent Cartesian location. For example, if A were a 2×3 custom matrix with cartesian indexing, and we referenced A[5], this would be recomputed to the equivalent Cartesian index and call A[1, 3] since 5 = 2*1 + 3.\n\nIt is significantly more expensive to compute Cartesian indices from a linear index than it is to go the other way. The former operation requires division — a very costly operation — whereas the latter only uses multiplication and addition and is essentially free. This asymmetry means it is far more costly to use linear indexing with an IndexCartesian array than it is to use Cartesian indexing with an IndexLinear array.\n\nSee also IndexLinear.\n\n\n\n\n\n","category":"type"},{"location":"base/arrays/#Base.conj!","page":"数组","title":"Base.conj!","text":"conj!(A)\n\nTransform an array to its complex conjugate in-place.\n\nSee also conj.\n\nExamples\n\njulia> A = [1+im 2-im; 2+2im 3+im]\n2×2 Matrix{Complex{Int64}}:\n 1+1im 2-1im\n 2+2im 3+1im\n\njulia> conj!(A);\n\njulia> A\n2×2 Matrix{Complex{Int64}}:\n 1-1im 2+1im\n 2-2im 3-1im\n\n\n\n\n\n","category":"function"},{"location":"base/arrays/#Base.stride","page":"数组","title":"Base.stride","text":"stride(A, k::Integer)\n\nReturn the distance in memory (in number of elements) between adjacent elements in dimension k.\n\nSee also: strides.\n\nExamples\n\njulia> A = fill(1, (3,4,5));\n\njulia> stride(A,2)\n3\n\njulia> stride(A,3)\n12\n\n\n\n\n\n","category":"function"},{"location":"base/arrays/#Base.strides","page":"数组","title":"Base.strides","text":"strides(A)\n\nReturn a tuple of the memory strides in each dimension.\n\nSee also: stride.\n\nExamples\n\njulia> A = fill(1, (3,4,5));\n\njulia> strides(A)\n(1, 3, 12)\n\n\n\n\n\n","category":"function"},{"location":"base/arrays/#广播与矢量化","page":"数组","title":"广播与矢量化","text":"","category":"section"},{"location":"base/arrays/","page":"数组","title":"数组","text":"也可参照 dot syntax for vectorizing functions; 例如,f.(args...) 隐式调用 broadcast(f, args...)。 与其依赖如 sin 函数的“已矢量化”方法,你应该使用 sin.(a) 来使用broadcast来矢量化。","category":"page"},{"location":"base/arrays/","page":"数组","title":"数组","text":"Base.broadcast\nBase.Broadcast.broadcast!\nBase.@__dot__","category":"page"},{"location":"base/arrays/#Base.Broadcast.broadcast","page":"数组","title":"Base.Broadcast.broadcast","text":"broadcast(f, As...)\n\nBroadcast the function f over the arrays, tuples, collections, Refs and/or scalars As.\n\nBroadcasting applies the function f over the elements of the container arguments and the scalars themselves in As. Singleton and missing dimensions are expanded to match the extents of the other arguments by virtually repeating the value. By default, only a limited number of types are considered scalars, including Numbers, Strings, Symbols, Types, Functions and some common singletons like missing and nothing. All other arguments are iterated over or indexed into elementwise.\n\nThe resulting container type is established by the following rules:\n\nIf all the arguments are scalars or zero-dimensional arrays, it returns an unwrapped scalar.\nIf at least one argument is a tuple and all others are scalars or zero-dimensional arrays, it returns a tuple.\nAll other combinations of arguments default to returning an Array, but custom container types can define their own implementation and promotion-like rules to customize the result when they appear as arguments.\n\nA special syntax exists for broadcasting: f.(args...) is equivalent to broadcast(f, args...), and nested f.(g.(args...)) calls are fused into a single broadcast loop.\n\nExamples\n\njulia> A = [1, 2, 3, 4, 5]\n5-element Vector{Int64}:\n 1\n 2\n 3\n 4\n 5\n\njulia> B = [1 2; 3 4; 5 6; 7 8; 9 10]\n5×2 Matrix{Int64}:\n 1 2\n 3 4\n 5 6\n 7 8\n 9 10\n\njulia> broadcast(+, A, B)\n5×2 Matrix{Int64}:\n 2 3\n 5 6\n 8 9\n 11 12\n 14 15\n\njulia> parse.(Int, [\"1\", \"2\"])\n2-element Vector{Int64}:\n 1\n 2\n\njulia> abs.((1, -2))\n(1, 2)\n\njulia> broadcast(+, 1.0, (0, -2.0))\n(1.0, -1.0)\n\njulia> (+).([[0,2], [1,3]], Ref{Vector{Int}}([1,-1]))\n2-element Vector{Vector{Int64}}:\n [1, 1]\n [2, 2]\n\njulia> string.((\"one\",\"two\",\"three\",\"four\"), \": \", 1:4)\n4-element Vector{String}:\n \"one: 1\"\n \"two: 2\"\n \"three: 3\"\n \"four: 4\"\n\n\n\n\n\n\n","category":"function"},{"location":"base/arrays/#Base.Broadcast.broadcast!","page":"数组","title":"Base.Broadcast.broadcast!","text":"broadcast!(f, dest, As...)\n\nLike broadcast, but store the result of broadcast(f, As...) in the dest array. Note that dest is only used to store the result, and does not supply arguments to f unless it is also listed in the As, as in broadcast!(f, A, A, B) to perform A[:] = broadcast(f, A, B).\n\nExamples\n\njulia> A = [1.0; 0.0]; B = [0.0; 0.0];\n\njulia> broadcast!(+, B, A, (0, -2.0));\n\njulia> B\n2-element Vector{Float64}:\n 1.0\n -2.0\n\njulia> A\n2-element Vector{Float64}:\n 1.0\n 0.0\n\njulia> broadcast!(+, A, A, (0, -2.0));\n\njulia> A\n2-element Vector{Float64}:\n 1.0\n -2.0\n\n\n\n\n\n","category":"function"},{"location":"base/arrays/#Base.Broadcast.@__dot__","page":"数组","title":"Base.Broadcast.@__dot__","text":"@. expr\n\nConvert every function call or operator in expr into a \"dot call\" (e.g. convert f(x) to f.(x)), and convert every assignment in expr to a \"dot assignment\" (e.g. convert += to .+=).\n\nIf you want to avoid adding dots for selected function calls in expr, splice those function calls in with $. For example, @. sqrt(abs($sort(x))) is equivalent to sqrt.(abs.(sort(x))) (no dot for sort).\n\n(@. is equivalent to a call to @__dot__.)\n\nExamples\n\njulia> x = 1.0:3.0; y = similar(x);\n\njulia> @. y = x + 3 * sin(x)\n3-element Vector{Float64}:\n 3.5244129544236893\n 4.727892280477045\n 3.4233600241796016\n\n\n\n\n\n","category":"macro"},{"location":"base/arrays/","page":"数组","title":"数组","text":"自定义类型的广播,请参照","category":"page"},{"location":"base/arrays/","page":"数组","title":"数组","text":"Base.BroadcastStyle\nBase.Broadcast.AbstractArrayStyle\nBase.Broadcast.ArrayStyle\nBase.Broadcast.DefaultArrayStyle\nBase.Broadcast.broadcastable\nBase.Broadcast.combine_axes\nBase.Broadcast.combine_styles\nBase.Broadcast.result_style","category":"page"},{"location":"base/arrays/#Base.Broadcast.BroadcastStyle","page":"数组","title":"Base.Broadcast.BroadcastStyle","text":"BroadcastStyle is an abstract type and trait-function used to determine behavior of objects under broadcasting. BroadcastStyle(typeof(x)) returns the style associated with x. To customize the broadcasting behavior of a type, one can declare a style by defining a type/method pair\n\nstruct MyContainerStyle <: BroadcastStyle end\nBase.BroadcastStyle(::Type{<:MyContainer}) = MyContainerStyle()\n\nOne then writes method(s) (at least similar) operating on Broadcasted{MyContainerStyle}. There are also several pre-defined subtypes of BroadcastStyle that you may be able to leverage; see the Interfaces chapter for more information.\n\n\n\n\n\n","category":"type"},{"location":"base/arrays/#Base.Broadcast.AbstractArrayStyle","page":"数组","title":"Base.Broadcast.AbstractArrayStyle","text":"Broadcast.AbstractArrayStyle{N} <: BroadcastStyle is the abstract supertype for any style associated with an AbstractArray type. The N parameter is the dimensionality, which can be handy for AbstractArray types that only support specific dimensionalities:\n\nstruct SparseMatrixStyle <: Broadcast.AbstractArrayStyle{2} end\nBase.BroadcastStyle(::Type{<:SparseMatrixCSC}) = SparseMatrixStyle()\n\nFor AbstractArray types that support arbitrary dimensionality, N can be set to Any:\n\nstruct MyArrayStyle <: Broadcast.AbstractArrayStyle{Any} end\nBase.BroadcastStyle(::Type{<:MyArray}) = MyArrayStyle()\n\nIn cases where you want to be able to mix multiple AbstractArrayStyles and keep track of dimensionality, your style needs to support a Val constructor:\n\nstruct MyArrayStyleDim{N} <: Broadcast.AbstractArrayStyle{N} end\n(::Type{<:MyArrayStyleDim})(::Val{N}) where N = MyArrayStyleDim{N}()\n\nNote that if two or more AbstractArrayStyle subtypes conflict, broadcasting machinery will fall back to producing Arrays. If this is undesirable, you may need to define binary BroadcastStyle rules to control the output type.\n\nSee also Broadcast.DefaultArrayStyle.\n\n\n\n\n\n","category":"type"},{"location":"base/arrays/#Base.Broadcast.ArrayStyle","page":"数组","title":"Base.Broadcast.ArrayStyle","text":"Broadcast.ArrayStyle{MyArrayType}() is a BroadcastStyle indicating that an object behaves as an array for broadcasting. It presents a simple way to construct Broadcast.AbstractArrayStyles for specific AbstractArray container types. Broadcast styles created this way lose track of dimensionality; if keeping track is important for your type, you should create your own custom Broadcast.AbstractArrayStyle.\n\n\n\n\n\n","category":"type"},{"location":"base/arrays/#Base.Broadcast.DefaultArrayStyle","page":"数组","title":"Base.Broadcast.DefaultArrayStyle","text":"Broadcast.DefaultArrayStyle{N}() is a BroadcastStyle indicating that an object behaves as an N-dimensional array for broadcasting. Specifically, DefaultArrayStyle is used for any AbstractArray type that hasn't defined a specialized style, and in the absence of overrides from other broadcast arguments the resulting output type is Array. When there are multiple inputs to broadcast, DefaultArrayStyle \"loses\" to any other Broadcast.ArrayStyle.\n\n\n\n\n\n","category":"type"},{"location":"base/arrays/#Base.Broadcast.broadcastable","page":"数组","title":"Base.Broadcast.broadcastable","text":"Broadcast.broadcastable(x)\n\nReturn either x or an object like x such that it supports axes, indexing, and its type supports ndims.\n\nIf x supports iteration, the returned value should have the same axes and indexing behaviors as collect(x).\n\nIf x is not an AbstractArray but it supports axes, indexing, and its type supports ndims, then broadcastable(::typeof(x)) may be implemented to just return itself. Further, if x defines its own BroadcastStyle, then it must define its broadcastable method to return itself for the custom style to have any effect.\n\nExamples\n\njulia> Broadcast.broadcastable([1,2,3]) # like `identity` since arrays already support axes and indexing\n3-element Vector{Int64}:\n 1\n 2\n 3\n\njulia> Broadcast.broadcastable(Int) # Types don't support axes, indexing, or iteration but are commonly used as scalars\nBase.RefValue{Type{Int64}}(Int64)\n\njulia> Broadcast.broadcastable(\"hello\") # Strings break convention of matching iteration and act like a scalar instead\nBase.RefValue{String}(\"hello\")\n\n\n\n\n\n","category":"function"},{"location":"base/arrays/#Base.Broadcast.combine_axes","page":"数组","title":"Base.Broadcast.combine_axes","text":"combine_axes(As...) -> Tuple\n\nDetermine the result axes for broadcasting across all values in As.\n\njulia> Broadcast.combine_axes([1], [1 2; 3 4; 5 6])\n(Base.OneTo(3), Base.OneTo(2))\n\njulia> Broadcast.combine_axes(1, 1, 1)\n()\n\n\n\n\n\n","category":"function"},{"location":"base/arrays/#Base.Broadcast.combine_styles","page":"数组","title":"Base.Broadcast.combine_styles","text":"combine_styles(cs...) -> BroadcastStyle\n\nDecides which BroadcastStyle to use for any number of value arguments. Uses BroadcastStyle to get the style for each argument, and uses result_style to combine styles.\n\nExamples\n\njulia> Broadcast.combine_styles([1], [1 2; 3 4])\nBase.Broadcast.DefaultArrayStyle{2}()\n\n\n\n\n\n","category":"function"},{"location":"base/arrays/#Base.Broadcast.result_style","page":"数组","title":"Base.Broadcast.result_style","text":"result_style(s1::BroadcastStyle[, s2::BroadcastStyle]) -> BroadcastStyle\n\nTakes one or two BroadcastStyles and combines them using BroadcastStyle to determine a common BroadcastStyle.\n\nExamples\n\njulia> Broadcast.result_style(Broadcast.DefaultArrayStyle{0}(), Broadcast.DefaultArrayStyle{3}())\nBase.Broadcast.DefaultArrayStyle{3}()\n\njulia> Broadcast.result_style(Broadcast.Unknown(), Broadcast.DefaultArrayStyle{1}())\nBase.Broadcast.DefaultArrayStyle{1}()\n\n\n\n\n\n","category":"function"},{"location":"base/arrays/#索引与赋值","page":"数组","title":"索引与赋值","text":"","category":"section"},{"location":"base/arrays/","page":"数组","title":"数组","text":"Base.getindex(::AbstractArray, ::Any...)\nBase.setindex!(::AbstractArray, ::Any, ::Any...)\nBase.copyto!(::AbstractArray, ::CartesianIndices, ::AbstractArray, ::CartesianIndices)\nBase.copy!\nBase.isassigned\nBase.Colon\nBase.CartesianIndex\nBase.CartesianIndices\nBase.Dims\nBase.LinearIndices\nBase.to_indices\nBase.checkbounds\nBase.checkindex\nBase.elsize","category":"page"},{"location":"base/arrays/#Base.getindex-Tuple{AbstractArray, Vararg{Any}}","page":"数组","title":"Base.getindex","text":"getindex(A, inds...)\n\nReturn a subset of array A as specified by inds, where each ind may be, for example, an Int, an AbstractRange, or a Vector. See the manual section on array indexing for details.\n\nExamples\n\njulia> A = [1 2; 3 4]\n2×2 Matrix{Int64}:\n 1 2\n 3 4\n\njulia> getindex(A, 1)\n1\n\njulia> getindex(A, [2, 1])\n2-element Vector{Int64}:\n 3\n 1\n\njulia> getindex(A, 2:4)\n3-element Vector{Int64}:\n 3\n 2\n 4\n\n\n\n\n\n","category":"method"},{"location":"base/arrays/#Base.setindex!-Tuple{AbstractArray, Any, Vararg{Any}}","page":"数组","title":"Base.setindex!","text":"setindex!(A, X, inds...)\nA[inds...] = X\n\nStore values from array X within some subset of A as specified by inds. The syntax A[inds...] = X is equivalent to (setindex!(A, X, inds...); X).\n\nExamples\n\njulia> A = zeros(2,2);\n\njulia> setindex!(A, [10, 20], [1, 2]);\n\njulia> A[[3, 4]] = [30, 40];\n\njulia> A\n2×2 Matrix{Float64}:\n 10.0 30.0\n 20.0 40.0\n\n\n\n\n\n","category":"method"},{"location":"base/arrays/#Base.copyto!-Tuple{AbstractArray, CartesianIndices, AbstractArray, CartesianIndices}","page":"数组","title":"Base.copyto!","text":"copyto!(dest, Rdest::CartesianIndices, src, Rsrc::CartesianIndices) -> dest\n\nCopy the block of src in the range of Rsrc to the block of dest in the range of Rdest. The sizes of the two regions must match.\n\nExamples\n\njulia> A = zeros(5, 5);\n\njulia> B = [1 2; 3 4];\n\njulia> Ainds = CartesianIndices((2:3, 2:3));\n\njulia> Binds = CartesianIndices(B);\n\njulia> copyto!(A, Ainds, B, Binds)\n5×5 Matrix{Float64}:\n 0.0 0.0 0.0 0.0 0.0\n 0.0 1.0 2.0 0.0 0.0\n 0.0 3.0 4.0 0.0 0.0\n 0.0 0.0 0.0 0.0 0.0\n 0.0 0.0 0.0 0.0 0.0\n\n\n\n\n\n","category":"method"},{"location":"base/arrays/#Base.copy!","page":"数组","title":"Base.copy!","text":"copy!(dst, src) -> dst\n\nIn-place copy of src into dst, discarding any pre-existing elements in dst. If dst and src are of the same type, dst == src should hold after the call. If dst and src are multidimensional arrays, they must have equal axes.\n\nSee also copyto!.\n\ncompat: Julia 1.1\nThis method requires at least Julia 1.1. In Julia 1.0 this method is available from the Future standard library as Future.copy!.\n\n\n\n\n\n","category":"function"},{"location":"base/arrays/#Base.isassigned","page":"数组","title":"Base.isassigned","text":"isassigned(array, i) -> Bool\n\nTest whether the given array has a value associated with index i. Return false if the index is out of bounds, or has an undefined reference.\n\nExamples\n\njulia> isassigned(rand(3, 3), 5)\ntrue\n\njulia> isassigned(rand(3, 3), 3 * 3 + 1)\nfalse\n\njulia> mutable struct Foo end\n\njulia> v = similar(rand(3), Foo)\n3-element Vector{Foo}:\n #undef\n #undef\n #undef\n\njulia> isassigned(v, 1)\nfalse\n\n\n\n\n\n","category":"function"},{"location":"base/arrays/#Base.Colon","page":"数组","title":"Base.Colon","text":"Colon()\n\nColons (:) are used to signify indexing entire objects or dimensions at once.\n\nVery few operations are defined on Colons directly; instead they are converted by to_indices to an internal vector type (Base.Slice) to represent the collection of indices they span before being used.\n\nThe singleton instance of Colon is also a function used to construct ranges; see :.\n\n\n\n\n\n","category":"type"},{"location":"base/arrays/#Base.IteratorsMD.CartesianIndex","page":"数组","title":"Base.IteratorsMD.CartesianIndex","text":"CartesianIndex(i, j, k...) -> I\nCartesianIndex((i, j, k...)) -> I\n\nCreate a multidimensional index I, which can be used for indexing a multidimensional array A. In particular, A[I] is equivalent to A[i,j,k...]. One can freely mix integer and CartesianIndex indices; for example, A[Ipre, i, Ipost] (where Ipre and Ipost are CartesianIndex indices and i is an Int) can be a useful expression when writing algorithms that work along a single dimension of an array of arbitrary dimensionality.\n\nA CartesianIndex is sometimes produced by eachindex, and always when iterating with an explicit CartesianIndices.\n\nExamples\n\njulia> A = reshape(Vector(1:16), (2, 2, 2, 2))\n2×2×2×2 Array{Int64, 4}:\n[:, :, 1, 1] =\n 1 3\n 2 4\n\n[:, :, 2, 1] =\n 5 7\n 6 8\n\n[:, :, 1, 2] =\n 9 11\n 10 12\n\n[:, :, 2, 2] =\n 13 15\n 14 16\n\njulia> A[CartesianIndex((1, 1, 1, 1))]\n1\n\njulia> A[CartesianIndex((1, 1, 1, 2))]\n9\n\njulia> A[CartesianIndex((1, 1, 2, 1))]\n5\n\n\n\n\n\n","category":"type"},{"location":"base/arrays/#Base.IteratorsMD.CartesianIndices","page":"数组","title":"Base.IteratorsMD.CartesianIndices","text":"CartesianIndices(sz::Dims) -> R\nCartesianIndices((istart:[istep:]istop, jstart:[jstep:]jstop, ...)) -> R\n\nDefine a region R spanning a multidimensional rectangular range of integer indices. These are most commonly encountered in the context of iteration, where for I in R ... end will return CartesianIndex indices I equivalent to the nested loops\n\nfor j = jstart:jstep:jstop\n for i = istart:istep:istop\n ...\n end\nend\n\nConsequently these can be useful for writing algorithms that work in arbitrary dimensions.\n\nCartesianIndices(A::AbstractArray) -> R\n\nAs a convenience, constructing a CartesianIndices from an array makes a range of its indices.\n\ncompat: Julia 1.6\nThe step range method CartesianIndices((istart:istep:istop, jstart:[jstep:]jstop, ...)) requires at least Julia 1.6.\n\nExamples\n\njulia> foreach(println, CartesianIndices((2, 2, 2)))\nCartesianIndex(1, 1, 1)\nCartesianIndex(2, 1, 1)\nCartesianIndex(1, 2, 1)\nCartesianIndex(2, 2, 1)\nCartesianIndex(1, 1, 2)\nCartesianIndex(2, 1, 2)\nCartesianIndex(1, 2, 2)\nCartesianIndex(2, 2, 2)\n\njulia> CartesianIndices(fill(1, (2,3)))\nCartesianIndices((2, 3))\n\nConversion between linear and cartesian indices\n\nLinear index to cartesian index conversion exploits the fact that a CartesianIndices is an AbstractArray and can be indexed linearly:\n\njulia> cartesian = CartesianIndices((1:3, 1:2))\nCartesianIndices((1:3, 1:2))\n\njulia> cartesian[4]\nCartesianIndex(1, 2)\n\njulia> cartesian = CartesianIndices((1:2:5, 1:2))\nCartesianIndices((1:2:5, 1:2))\n\njulia> cartesian[2, 2]\nCartesianIndex(3, 2)\n\nBroadcasting\n\nCartesianIndices support broadcasting arithmetic (+ and -) with a CartesianIndex.\n\ncompat: Julia 1.1\nBroadcasting of CartesianIndices requires at least Julia 1.1.\n\njulia> CIs = CartesianIndices((2:3, 5:6))\nCartesianIndices((2:3, 5:6))\n\njulia> CI = CartesianIndex(3, 4)\nCartesianIndex(3, 4)\n\njulia> CIs .+ CI\nCartesianIndices((5:6, 9:10))\n\nFor cartesian to linear index conversion, see LinearIndices.\n\n\n\n\n\n","category":"type"},{"location":"base/arrays/#Base.Dims","page":"数组","title":"Base.Dims","text":"Dims{N}\n\nAn NTuple of N Ints used to represent the dimensions of an AbstractArray.\n\n\n\n\n\n","category":"type"},{"location":"base/arrays/#Base.LinearIndices","page":"数组","title":"Base.LinearIndices","text":"LinearIndices(A::AbstractArray)\n\nReturn a LinearIndices array with the same shape and axes as A, holding the linear index of each entry in A. Indexing this array with cartesian indices allows mapping them to linear indices.\n\nFor arrays with conventional indexing (indices start at 1), or any multidimensional array, linear indices range from 1 to length(A). However, for AbstractVectors linear indices are axes(A, 1), and therefore do not start at 1 for vectors with unconventional indexing.\n\nCalling this function is the \"safe\" way to write algorithms that exploit linear indexing.\n\nExamples\n\njulia> A = fill(1, (5,6,7));\n\njulia> b = LinearIndices(A);\n\njulia> extrema(b)\n(1, 210)\n\nLinearIndices(inds::CartesianIndices) -> R\nLinearIndices(sz::Dims) -> R\nLinearIndices((istart:istop, jstart:jstop, ...)) -> R\n\nReturn a LinearIndices array with the specified shape or axes.\n\nExample\n\nThe main purpose of this constructor is intuitive conversion from cartesian to linear indexing:\n\njulia> linear = LinearIndices((1:3, 1:2))\n3×2 LinearIndices{2, Tuple{UnitRange{Int64}, UnitRange{Int64}}}:\n 1 4\n 2 5\n 3 6\n\njulia> linear[1,2]\n4\n\n\n\n\n\n","category":"type"},{"location":"base/arrays/#Base.to_indices","page":"数组","title":"Base.to_indices","text":"to_indices(A, I::Tuple)\n\nConvert the tuple I to a tuple of indices for use in indexing into array A.\n\nThe returned tuple must only contain either Ints or AbstractArrays of scalar indices that are supported by array A. It will error upon encountering a novel index type that it does not know how to process.\n\nFor simple index types, it defers to the unexported Base.to_index(A, i) to process each index i. While this internal function is not intended to be called directly, Base.to_index may be extended by custom array or index types to provide custom indexing behaviors.\n\nMore complicated index types may require more context about the dimension into which they index. To support those cases, to_indices(A, I) calls to_indices(A, axes(A), I), which then recursively walks through both the given tuple of indices and the dimensional indices of A in tandem. As such, not all index types are guaranteed to propagate to Base.to_index.\n\n\n\n\n\n","category":"function"},{"location":"base/arrays/#Base.checkbounds","page":"数组","title":"Base.checkbounds","text":"checkbounds(Bool, A, I...)\n\nReturn true if the specified indices I are in bounds for the given array A. Subtypes of AbstractArray should specialize this method if they need to provide custom bounds checking behaviors; however, in many cases one can rely on A's indices and checkindex.\n\nSee also checkindex.\n\nExamples\n\njulia> A = rand(3, 3);\n\njulia> checkbounds(Bool, A, 2)\ntrue\n\njulia> checkbounds(Bool, A, 3, 4)\nfalse\n\njulia> checkbounds(Bool, A, 1:3)\ntrue\n\njulia> checkbounds(Bool, A, 1:3, 2:4)\nfalse\n\n\n\n\n\ncheckbounds(A, I...)\n\nThrow an error if the specified indices I are not in bounds for the given array A.\n\n\n\n\n\n","category":"function"},{"location":"base/arrays/#Base.checkindex","page":"数组","title":"Base.checkindex","text":"checkindex(Bool, inds::AbstractUnitRange, index)\n\nReturn true if the given index is within the bounds of inds. Custom types that would like to behave as indices for all arrays can extend this method in order to provide a specialized bounds checking implementation.\n\nSee also checkbounds.\n\nExamples\n\njulia> checkindex(Bool, 1:20, 8)\ntrue\n\njulia> checkindex(Bool, 1:20, 21)\nfalse\n\n\n\n\n\n","category":"function"},{"location":"base/arrays/#Base.elsize","page":"数组","title":"Base.elsize","text":"elsize(type)\n\nCompute the memory stride in bytes between consecutive elements of eltype stored inside the given type, if the array elements are stored densely with a uniform linear stride.\n\nExamples\n\njulia> Base.elsize(rand(Float32, 10))\n4\n\n\n\n\n\n","category":"function"},{"location":"base/arrays/#Views-(SubArrays-以及其它-view-类型)","page":"数组","title":"Views (SubArrays 以及其它 view 类型)","text":"","category":"section"},{"location":"base/arrays/","page":"数组","title":"数组","text":"“视图”是一种表现和数组相似的数据结构(它是 AbstractArray 的子类型),但是它的底层数据实际上是另一个数组的一部分。","category":"page"},{"location":"base/arrays/","page":"数组","title":"数组","text":"例如,x 是一个数组,v = @view x[1:10],则 v 表现得就像一个含有 10 个元素的数组,但是它的数据实际上是访问 x 的前 10 个元素。对视图的写入,如 v[3] = 2,直接写入了底层的数组 x (这里是修改 x[3])。","category":"page"},{"location":"base/arrays/","page":"数组","title":"数组","text":"在 Julia 中,像 x[1:10] 这样的切片操作会创建一个副本。@view x[1:10] 将它变成创建一个视图。 @views 宏可以用于整个代码块(如 @views function foo() .... end 或 @views begin ... end)来将整个代码块中的切片操作变为使用视图。 如性能建议所描述的,有时候使用数据的副本更快,而有时候使用视图会更快。","category":"page"},{"location":"base/arrays/","page":"数组","title":"数组","text":"Base.view\nBase.@view\nBase.@views\nBase.parent\nBase.parentindices\nBase.selectdim\nBase.reinterpret\nBase.reshape\nBase.dropdims\nBase.vec\nBase.SubArray","category":"page"},{"location":"base/arrays/#Base.view","page":"数组","title":"Base.view","text":"view(A, inds...)\n\nLike getindex, but returns a lightweight array that lazily references (or is effectively a view into) the parent array A at the given index or indices inds instead of eagerly extracting elements or constructing a copied subset. Calling getindex or setindex! on the returned value (often a SubArray) computes the indices to access or modify the parent array on the fly. The behavior is undefined if the shape of the parent array is changed after view is called because there is no bound check for the parent array; e.g., it may cause a segmentation fault.\n\nSome immutable parent arrays (like ranges) may choose to simply recompute a new array in some circumstances instead of returning a SubArray if doing so is efficient and provides compatible semantics.\n\ncompat: Julia 1.6\nIn Julia 1.6 or later, view can be called on an AbstractString, returning a SubString.\n\nExamples\n\njulia> A = [1 2; 3 4]\n2×2 Matrix{Int64}:\n 1 2\n 3 4\n\njulia> b = view(A, :, 1)\n2-element view(::Matrix{Int64}, :, 1) with eltype Int64:\n 1\n 3\n\njulia> fill!(b, 0)\n2-element view(::Matrix{Int64}, :, 1) with eltype Int64:\n 0\n 0\n\njulia> A # Note A has changed even though we modified b\n2×2 Matrix{Int64}:\n 0 2\n 0 4\n\njulia> view(2:5, 2:3) # returns a range as type is immutable\n3:4\n\n\n\n\n\n","category":"function"},{"location":"base/arrays/#Base.@view","page":"数组","title":"Base.@view","text":"@view A[inds...]\n\nTransform the indexing expression A[inds...] into the equivalent view call.\n\nThis can only be applied directly to a single indexing expression and is particularly helpful for expressions that include the special begin or end indexing syntaxes like A[begin, 2:end-1] (as those are not supported by the normal view function).\n\nNote that @view cannot be used as the target of a regular assignment (e.g., @view(A[1, 2:end]) = ...), nor would the un-decorated indexed assignment (A[1, 2:end] = ...) or broadcasted indexed assignment (A[1, 2:end] .= ...) make a copy. It can be useful, however, for updating broadcasted assignments like @view(A[1, 2:end]) .+= 1 because this is a simple syntax for @view(A[1, 2:end]) .= @view(A[1, 2:end]) + 1, and the indexing expression on the right-hand side would otherwise make a copy without the @view.\n\nSee also @views to switch an entire block of code to use views for non-scalar indexing.\n\ncompat: Julia 1.5\nUsing begin in an indexing expression to refer to the first index requires at least Julia 1.5.\n\nExamples\n\njulia> A = [1 2; 3 4]\n2×2 Matrix{Int64}:\n 1 2\n 3 4\n\njulia> b = @view A[:, 1]\n2-element view(::Matrix{Int64}, :, 1) with eltype Int64:\n 1\n 3\n\njulia> fill!(b, 0)\n2-element view(::Matrix{Int64}, :, 1) with eltype Int64:\n 0\n 0\n\njulia> A\n2×2 Matrix{Int64}:\n 0 2\n 0 4\n\n\n\n\n\n","category":"macro"},{"location":"base/arrays/#Base.@views","page":"数组","title":"Base.@views","text":"@views expression\n\nConvert every array-slicing operation in the given expression (which may be a begin/end block, loop, function, etc.) to return a view. Scalar indices, non-array types, and explicit getindex calls (as opposed to array[...]) are unaffected.\n\nnote: Note\nThe @views macro only affects array[...] expressions that appear explicitly in the given expression, not array slicing that occurs in functions called by that code.\n\ncompat: Julia 1.5\nUsing begin in an indexing expression to refer to the first index requires at least Julia 1.5.\n\nExamples\n\njulia> A = zeros(3, 3);\n\njulia> @views for row in 1:3\n b = A[row, :]\n b[:] .= row\n end\n\njulia> A\n3×3 Matrix{Float64}:\n 1.0 1.0 1.0\n 2.0 2.0 2.0\n 3.0 3.0 3.0\n\n\n\n\n\n","category":"macro"},{"location":"base/arrays/#Base.parent","page":"数组","title":"Base.parent","text":"parent(A)\n\nReturn the underlying \"parent array”. This parent array of objects of types SubArray, ReshapedArray or LinearAlgebra.Transpose is what was passed as an argument to view, reshape, transpose, etc. during object creation. If the input is not a wrapped object, return the input itself. If the input is wrapped multiple times, only the outermost wrapper will be removed.\n\nExamples\n\njulia> A = [1 2; 3 4]\n2×2 Matrix{Int64}:\n 1 2\n 3 4\n\njulia> V = view(A, 1:2, :)\n2×2 view(::Matrix{Int64}, 1:2, :) with eltype Int64:\n 1 2\n 3 4\n\njulia> parent(V)\n2×2 Matrix{Int64}:\n 1 2\n 3 4\n\n\n\n\n\n","category":"function"},{"location":"base/arrays/#Base.parentindices","page":"数组","title":"Base.parentindices","text":"parentindices(A)\n\nReturn the indices in the parent which correspond to the array view A.\n\nExamples\n\njulia> A = [1 2; 3 4];\n\njulia> V = view(A, 1, :)\n2-element view(::Matrix{Int64}, 1, :) with eltype Int64:\n 1\n 2\n\njulia> parentindices(V)\n(1, Base.Slice(Base.OneTo(2)))\n\n\n\n\n\n","category":"function"},{"location":"base/arrays/#Base.selectdim","page":"数组","title":"Base.selectdim","text":"selectdim(A, d::Integer, i)\n\nReturn a view of all the data of A where the index for dimension d equals i.\n\nEquivalent to view(A,:,:,...,i,:,:,...) where i is in position d.\n\nSee also: eachslice.\n\nExamples\n\njulia> A = [1 2 3 4; 5 6 7 8]\n2×4 Matrix{Int64}:\n 1 2 3 4\n 5 6 7 8\n\njulia> selectdim(A, 2, 3)\n2-element view(::Matrix{Int64}, :, 3) with eltype Int64:\n 3\n 7\n\njulia> selectdim(A, 2, 3:4)\n2×2 view(::Matrix{Int64}, :, 3:4) with eltype Int64:\n 3 4\n 7 8\n\n\n\n\n\n","category":"function"},{"location":"base/arrays/#Base.reinterpret","page":"数组","title":"Base.reinterpret","text":"reinterpret(type, A)\n\nChange the type-interpretation of a block of memory. For arrays, this constructs a view of the array with the same binary data as the given array, but with the specified element type. For example, reinterpret(Float32, UInt32(7)) interprets the 4 bytes corresponding to UInt32(7) as a Float32.\n\nExamples\n\njulia> reinterpret(Float32, UInt32(7))\n1.0f-44\n\njulia> reinterpret(Float32, UInt32[1 2 3 4 5])\n1×5 reinterpret(Float32, ::Matrix{UInt32}):\n 1.0f-45 3.0f-45 4.0f-45 6.0f-45 7.0f-45\n\n\n\n\n\nreinterpret(reshape, T, A::AbstractArray{S}) -> B\n\nChange the type-interpretation of A while consuming or adding a \"channel dimension.\"\n\nIf sizeof(T) = n*sizeof(S) for n>1, A's first dimension must be of size n and B lacks A's first dimension. Conversely, if sizeof(S) = n*sizeof(T) for n>1, B gets a new first dimension of size n. The dimensionality is unchanged if sizeof(T) == sizeof(S).\n\ncompat: Julia 1.6\nThis method requires at least Julia 1.6.\n\nExamples\n\njulia> A = [1 2; 3 4]\n2×2 Matrix{Int64}:\n 1 2\n 3 4\n\njulia> reinterpret(reshape, Complex{Int}, A) # the result is a vector\n2-element reinterpret(reshape, Complex{Int64}, ::Matrix{Int64}) with eltype Complex{Int64}:\n 1 + 3im\n 2 + 4im\n\njulia> a = [(1,2,3), (4,5,6)]\n2-element Vector{Tuple{Int64, Int64, Int64}}:\n (1, 2, 3)\n (4, 5, 6)\n\njulia> reinterpret(reshape, Int, a) # the result is a matrix\n3×2 reinterpret(reshape, Int64, ::Vector{Tuple{Int64, Int64, Int64}}) with eltype Int64:\n 1 4\n 2 5\n 3 6\n\n\n\n\n\n","category":"function"},{"location":"base/arrays/#Base.reshape","page":"数组","title":"Base.reshape","text":"reshape(A, dims...) -> AbstractArray\nreshape(A, dims) -> AbstractArray\n\nReturn an array with the same data as A, but with different dimension sizes or number of dimensions. The two arrays share the same underlying data, so that the result is mutable if and only if A is mutable, and setting elements of one alters the values of the other.\n\nThe new dimensions may be specified either as a list of arguments or as a shape tuple. At most one dimension may be specified with a :, in which case its length is computed such that its product with all the specified dimensions is equal to the length of the original array A. The total number of elements must not change.\n\nExamples\n\njulia> A = Vector(1:16)\n16-element Vector{Int64}:\n 1\n 2\n 3\n 4\n 5\n 6\n 7\n 8\n 9\n 10\n 11\n 12\n 13\n 14\n 15\n 16\n\njulia> reshape(A, (4, 4))\n4×4 Matrix{Int64}:\n 1 5 9 13\n 2 6 10 14\n 3 7 11 15\n 4 8 12 16\n\njulia> reshape(A, 2, :)\n2×8 Matrix{Int64}:\n 1 3 5 7 9 11 13 15\n 2 4 6 8 10 12 14 16\n\njulia> reshape(1:6, 2, 3)\n2×3 reshape(::UnitRange{Int64}, 2, 3) with eltype Int64:\n 1 3 5\n 2 4 6\n\n\n\n\n\n","category":"function"},{"location":"base/arrays/#Base.dropdims","page":"数组","title":"Base.dropdims","text":"dropdims(A; dims)\n\nReturn an array with the same data as A, but with the dimensions specified by dims removed. size(A,d) must equal 1 for every d in dims, and repeated dimensions or numbers outside 1:ndims(A) are forbidden.\n\nThe result shares the same underlying data as A, such that the result is mutable if and only if A is mutable, and setting elements of one alters the values of the other.\n\nSee also: reshape, vec.\n\nExamples\n\njulia> a = reshape(Vector(1:4),(2,2,1,1))\n2×2×1×1 Array{Int64, 4}:\n[:, :, 1, 1] =\n 1 3\n 2 4\n\njulia> b = dropdims(a; dims=3)\n2×2×1 Array{Int64, 3}:\n[:, :, 1] =\n 1 3\n 2 4\n\njulia> b[1,1,1] = 5; a\n2×2×1×1 Array{Int64, 4}:\n[:, :, 1, 1] =\n 5 3\n 2 4\n\n\n\n\n\n","category":"function"},{"location":"base/arrays/#Base.vec","page":"数组","title":"Base.vec","text":"vec(a::AbstractArray) -> AbstractVector\n\nReshape the array a as a one-dimensional column vector. Return a if it is already an AbstractVector. The resulting array shares the same underlying data as a, so it will only be mutable if a is mutable, in which case modifying one will also modify the other.\n\nExamples\n\njulia> a = [1 2 3; 4 5 6]\n2×3 Matrix{Int64}:\n 1 2 3\n 4 5 6\n\njulia> vec(a)\n6-element Vector{Int64}:\n 1\n 4\n 2\n 5\n 3\n 6\n\njulia> vec(1:3)\n1:3\n\nSee also reshape, dropdims.\n\n\n\n\n\n","category":"function"},{"location":"base/arrays/#Base.SubArray","page":"数组","title":"Base.SubArray","text":"SubArray{T,N,P,I,L} <: AbstractArray{T,N}\n\nN-dimensional view into a parent array (of type P) with an element type T, restricted by a tuple of indices (of type I). L is true for types that support fast linear indexing, and false otherwise.\n\nConstruct SubArrays using the view function.\n\n\n\n\n\n","category":"type"},{"location":"base/arrays/#拼接与排列","page":"数组","title":"拼接与排列","text":"","category":"section"},{"location":"base/arrays/","page":"数组","title":"数组","text":"Base.cat\nBase.vcat\nBase.hcat\nBase.hvcat\nBase.hvncat\nBase.vect\nBase.circshift\nBase.circshift!\nBase.circcopy!\nBase.findall(::Any)\nBase.findall(::Function, ::Any)\nBase.findfirst(::Any)\nBase.findfirst(::Function, ::Any)\nBase.findlast(::Any)\nBase.findlast(::Function, ::Any)\nBase.findnext(::Any, ::Integer)\nBase.findnext(::Function, ::Any, ::Integer)\nBase.findprev(::Any, ::Integer)\nBase.findprev(::Function, ::Any, ::Integer)\nBase.permutedims\nBase.permutedims!\nBase.PermutedDimsArray\nBase.promote_shape","category":"page"},{"location":"base/arrays/#Base.cat","page":"数组","title":"Base.cat","text":"cat(A...; dims)\n\nConcatenate the input arrays along the specified dimensions in the iterable dims. For dimensions not in dims, all input arrays should have the same size, which will also be the size of the output array along that dimension. For dimensions in dims, the size of the output array is the sum of the sizes of the input arrays along that dimension. If dims is a single number, the different arrays are tightly stacked along that dimension. If dims is an iterable containing several dimensions, this allows one to construct block diagonal matrices and their higher-dimensional analogues by simultaneously increasing several dimensions for every new input array and putting zero blocks elsewhere. For example, cat(matrices...; dims=(1,2)) builds a block diagonal matrix, i.e. a block matrix with matrices[1], matrices[2], ... as diagonal blocks and matching zero blocks away from the diagonal.\n\nSee also hcat, vcat, hvcat, repeat.\n\nExamples\n\njulia> cat([1 2; 3 4], [pi, pi], fill(10, 2,3,1); dims=2)\n2×6×1 Array{Float64, 3}:\n[:, :, 1] =\n 1.0 2.0 3.14159 10.0 10.0 10.0\n 3.0 4.0 3.14159 10.0 10.0 10.0\n\njulia> cat(true, trues(2,2), trues(4)', dims=(1,2))\n4×7 Matrix{Bool}:\n 1 0 0 0 0 0 0\n 0 1 1 0 0 0 0\n 0 1 1 0 0 0 0\n 0 0 0 1 1 1 1\n\n\n\n\n\n","category":"function"},{"location":"base/arrays/#Base.vcat","page":"数组","title":"Base.vcat","text":"vcat(A...)\n\nConcatenate along dimension 1. To efficiently concatenate a large vector of arrays, use reduce(vcat, x).\n\nExamples\n\njulia> a = [1 2 3 4 5]\n1×5 Matrix{Int64}:\n 1 2 3 4 5\n\njulia> b = [6 7 8 9 10; 11 12 13 14 15]\n2×5 Matrix{Int64}:\n 6 7 8 9 10\n 11 12 13 14 15\n\njulia> vcat(a,b)\n3×5 Matrix{Int64}:\n 1 2 3 4 5\n 6 7 8 9 10\n 11 12 13 14 15\n\njulia> c = ([1 2 3], [4 5 6])\n([1 2 3], [4 5 6])\n\njulia> vcat(c...)\n2×3 Matrix{Int64}:\n 1 2 3\n 4 5 6\n\njulia> vs = [[1, 2], [3, 4], [5, 6]]\n3-element Vector{Vector{Int64}}:\n [1, 2]\n [3, 4]\n [5, 6]\n\njulia> reduce(vcat, vs)\n6-element Vector{Int64}:\n 1\n 2\n 3\n 4\n 5\n 6\n\n\n\n\n\n","category":"function"},{"location":"base/arrays/#Base.hcat","page":"数组","title":"Base.hcat","text":"hcat(A...)\n\nConcatenate along dimension 2. To efficiently concatenate a large vector of arrays, use reduce(hcat, x).\n\nExamples\n\njulia> a = [1; 2; 3; 4; 5]\n5-element Vector{Int64}:\n 1\n 2\n 3\n 4\n 5\n\njulia> b = [6 7; 8 9; 10 11; 12 13; 14 15]\n5×2 Matrix{Int64}:\n 6 7\n 8 9\n 10 11\n 12 13\n 14 15\n\njulia> hcat(a,b)\n5×3 Matrix{Int64}:\n 1 6 7\n 2 8 9\n 3 10 11\n 4 12 13\n 5 14 15\n\njulia> c = ([1; 2; 3], [4; 5; 6])\n([1, 2, 3], [4, 5, 6])\n\njulia> hcat(c...)\n3×2 Matrix{Int64}:\n 1 4\n 2 5\n 3 6\n\njulia> x = Matrix(undef, 3, 0) # x = [] would have created an Array{Any, 1}, but need an Array{Any, 2}\n3×0 Matrix{Any}\n\njulia> hcat(x, [1; 2; 3])\n3×1 Matrix{Any}:\n 1\n 2\n 3\n\njulia> vs = [[1, 2], [3, 4], [5, 6]]\n3-element Vector{Vector{Int64}}:\n [1, 2]\n [3, 4]\n [5, 6]\n\njulia> reduce(hcat, vs)\n2×3 Matrix{Int64}:\n 1 3 5\n 2 4 6\n\n\n\n\n\n","category":"function"},{"location":"base/arrays/#Base.hvcat","page":"数组","title":"Base.hvcat","text":"hvcat(rows::Tuple{Vararg{Int}}, values...)\n\nHorizontal and vertical concatenation in one call. This function is called for block matrix syntax. The first argument specifies the number of arguments to concatenate in each block row.\n\nExamples\n\njulia> a, b, c, d, e, f = 1, 2, 3, 4, 5, 6\n(1, 2, 3, 4, 5, 6)\n\njulia> [a b c; d e f]\n2×3 Matrix{Int64}:\n 1 2 3\n 4 5 6\n\njulia> hvcat((3,3), a,b,c,d,e,f)\n2×3 Matrix{Int64}:\n 1 2 3\n 4 5 6\n\njulia> [a b; c d; e f]\n3×2 Matrix{Int64}:\n 1 2\n 3 4\n 5 6\n\njulia> hvcat((2,2,2), a,b,c,d,e,f)\n3×2 Matrix{Int64}:\n 1 2\n 3 4\n 5 6\n\nIf the first argument is a single integer n, then all block rows are assumed to have n block columns.\n\n\n\n\n\n","category":"function"},{"location":"base/arrays/#Base.hvncat","page":"数组","title":"Base.hvncat","text":"hvncat(dim::Int, row_first, values...)\nhvncat(dims::Tuple{Vararg{Int}}, row_first, values...)\nhvncat(shape::Tuple{Vararg{Tuple}}, row_first, values...)\n\nHorizontal, vertical, and n-dimensional concatenation of many values in one call.\n\nThis function is called for block matrix syntax. The first argument either specifies the shape of the concatenation, similar to hvcat, as a tuple of tuples, or the dimensions that specify the key number of elements along each axis, and is used to determine the output dimensions. The dims form is more performant, and is used by default when the concatenation operation has the same number of elements along each axis (e.g., [a b; c d;;; e f ; g h]). The shape form is used when the number of elements along each axis is unbalanced (e.g., [a b ; c]). Unbalanced syntax needs additional validation overhead. The dim form is an optimization for concatenation along just one dimension. row_first indicates how values are ordered. The meaning of the first and second elements of shape are also swapped based on row_first.\n\nExamples\n\njulia> a, b, c, d, e, f = 1, 2, 3, 4, 5, 6\n(1, 2, 3, 4, 5, 6)\n\njulia> [a b c;;; d e f]\n1×3×2 Array{Int64, 3}:\n[:, :, 1] =\n 1 2 3\n\n[:, :, 2] =\n 4 5 6\n\njulia> hvncat((2,1,3), false, a,b,c,d,e,f)\n2×1×3 Array{Int64, 3}:\n[:, :, 1] =\n 1\n 2\n\n[:, :, 2] =\n 3\n 4\n\n[:, :, 3] =\n 5\n 6\n\njulia> [a b;;; c d;;; e f]\n1×2×3 Array{Int64, 3}:\n[:, :, 1] =\n 1 2\n\n[:, :, 2] =\n 3 4\n\n[:, :, 3] =\n 5 6\n\njulia> hvncat(((3, 3), (3, 3), (6,)), true, a, b, c, d, e, f)\n1×3×2 Array{Int64, 3}:\n[:, :, 1] =\n 1 2 3\n\n[:, :, 2] =\n 4 5 6\n\nExamples for construction of the arguments:\n\n[a b c ; d e f ;;;\n g h i ; j k l ;;;\n m n o ; p q r ;;;\n s t u ; v w x]\n=> dims = (2, 3, 4)\n\n[a b ; c ;;; d ;;;;]\n ___ _ _\n 2 1 1 = elements in each row (2, 1, 1)\n _______ _\n 3 1 = elements in each column (3, 1)\n _____________\n 4 = elements in each 3d slice (4,)\n _____________\n 4 = elements in each 4d slice (4,)\n => shape = ((2, 1, 1), (3, 1), (4,), (4,)) with `rowfirst` = true\n\n\n\n\n\n","category":"function"},{"location":"base/arrays/#Base.vect","page":"数组","title":"Base.vect","text":"vect(X...)\n\nCreate a Vector with element type computed from the promote_typeof of the argument, containing the argument list.\n\nExamples\n\njulia> a = Base.vect(UInt8(1), 2.5, 1//2)\n3-element Vector{Float64}:\n 1.0\n 2.5\n 0.5\n\n\n\n\n\n","category":"function"},{"location":"base/arrays/#Base.circshift","page":"数组","title":"Base.circshift","text":"circshift(A, shifts)\n\nCircularly shift, i.e. rotate, the data in an array. The second argument is a tuple or vector giving the amount to shift in each dimension, or an integer to shift only in the first dimension.\n\nSee also: circshift!, circcopy!, bitrotate, <<.\n\nExamples\n\njulia> b = reshape(Vector(1:16), (4,4))\n4×4 Matrix{Int64}:\n 1 5 9 13\n 2 6 10 14\n 3 7 11 15\n 4 8 12 16\n\njulia> circshift(b, (0,2))\n4×4 Matrix{Int64}:\n 9 13 1 5\n 10 14 2 6\n 11 15 3 7\n 12 16 4 8\n\njulia> circshift(b, (-1,0))\n4×4 Matrix{Int64}:\n 2 6 10 14\n 3 7 11 15\n 4 8 12 16\n 1 5 9 13\n\njulia> a = BitArray([true, true, false, false, true])\n5-element BitVector:\n 1\n 1\n 0\n 0\n 1\n\njulia> circshift(a, 1)\n5-element BitVector:\n 1\n 1\n 1\n 0\n 0\n\njulia> circshift(a, -1)\n5-element BitVector:\n 1\n 0\n 0\n 1\n 1\n\n\n\n\n\n","category":"function"},{"location":"base/arrays/#Base.circshift!","page":"数组","title":"Base.circshift!","text":"circshift!(dest, src, shifts)\n\nCircularly shift, i.e. rotate, the data in src, storing the result in dest. shifts specifies the amount to shift in each dimension.\n\nThe dest array must be distinct from the src array (they cannot alias each other).\n\nSee also circshift.\n\n\n\n\n\n","category":"function"},{"location":"base/arrays/#Base.circcopy!","page":"数组","title":"Base.circcopy!","text":"circcopy!(dest, src)\n\nCopy src to dest, indexing each dimension modulo its length. src and dest must have the same size, but can be offset in their indices; any offset results in a (circular) wraparound. If the arrays have overlapping indices, then on the domain of the overlap dest agrees with src.\n\nSee also: circshift.\n\nExamples\n\njulia> src = reshape(Vector(1:16), (4,4))\n4×4 Array{Int64,2}:\n 1 5 9 13\n 2 6 10 14\n 3 7 11 15\n 4 8 12 16\n\njulia> dest = OffsetArray{Int}(undef, (0:3,2:5))\n\njulia> circcopy!(dest, src)\nOffsetArrays.OffsetArray{Int64,2,Array{Int64,2}} with indices 0:3×2:5:\n 8 12 16 4\n 5 9 13 1\n 6 10 14 2\n 7 11 15 3\n\njulia> dest[1:3,2:4] == src[1:3,2:4]\ntrue\n\n\n\n\n\n","category":"function"},{"location":"base/arrays/#Base.findall-Tuple{Any}","page":"数组","title":"Base.findall","text":"findall(A)\n\nReturn a vector I of the true indices or keys of A. If there are no such elements of A, return an empty array. To search for other kinds of values, pass a predicate as the first argument.\n\nIndices or keys are of the same type as those returned by keys(A) and pairs(A).\n\nSee also: findfirst, searchsorted.\n\nExamples\n\njulia> A = [true, false, false, true]\n4-element Vector{Bool}:\n 1\n 0\n 0\n 1\n\njulia> findall(A)\n2-element Vector{Int64}:\n 1\n 4\n\njulia> A = [true false; false true]\n2×2 Matrix{Bool}:\n 1 0\n 0 1\n\njulia> findall(A)\n2-element Vector{CartesianIndex{2}}:\n CartesianIndex(1, 1)\n CartesianIndex(2, 2)\n\njulia> findall(falses(3))\nInt64[]\n\n\n\n\n\n","category":"method"},{"location":"base/arrays/#Base.findall-Tuple{Function, Any}","page":"数组","title":"Base.findall","text":"findall(f::Function, A)\n\nReturn a vector I of the indices or keys of A where f(A[I]) returns true. If there are no such elements of A, return an empty array.\n\nIndices or keys are of the same type as those returned by keys(A) and pairs(A).\n\nExamples\n\njulia> x = [1, 3, 4]\n3-element Vector{Int64}:\n 1\n 3\n 4\n\njulia> findall(isodd, x)\n2-element Vector{Int64}:\n 1\n 2\n\njulia> A = [1 2 0; 3 4 0]\n2×3 Matrix{Int64}:\n 1 2 0\n 3 4 0\njulia> findall(isodd, A)\n2-element Vector{CartesianIndex{2}}:\n CartesianIndex(1, 1)\n CartesianIndex(2, 1)\n\njulia> findall(!iszero, A)\n4-element Vector{CartesianIndex{2}}:\n CartesianIndex(1, 1)\n CartesianIndex(2, 1)\n CartesianIndex(1, 2)\n CartesianIndex(2, 2)\n\njulia> d = Dict(:A => 10, :B => -1, :C => 0)\nDict{Symbol, Int64} with 3 entries:\n :A => 10\n :B => -1\n :C => 0\n\njulia> findall(x -> x >= 0, d)\n2-element Vector{Symbol}:\n :A\n :C\n\n\n\n\n\n\n","category":"method"},{"location":"base/arrays/#Base.findfirst-Tuple{Any}","page":"数组","title":"Base.findfirst","text":"findfirst(A)\n\nReturn the index or key of the first true value in A. Return nothing if no such value is found. To search for other kinds of values, pass a predicate as the first argument.\n\nIndices or keys are of the same type as those returned by keys(A) and pairs(A).\n\nSee also: findall, findnext, findlast, searchsortedfirst.\n\nExamples\n\njulia> A = [false, false, true, false]\n4-element Vector{Bool}:\n 0\n 0\n 1\n 0\n\njulia> findfirst(A)\n3\n\njulia> findfirst(falses(3)) # returns nothing, but not printed in the REPL\n\njulia> A = [false false; true false]\n2×2 Matrix{Bool}:\n 0 0\n 1 0\n\njulia> findfirst(A)\nCartesianIndex(2, 1)\n\n\n\n\n\n","category":"method"},{"location":"base/arrays/#Base.findfirst-Tuple{Function, Any}","page":"数组","title":"Base.findfirst","text":"findfirst(predicate::Function, A)\n\nReturn the index or key of the first element of A for which predicate returns true. Return nothing if there is no such element.\n\nIndices or keys are of the same type as those returned by keys(A) and pairs(A).\n\nExamples\n\njulia> A = [1, 4, 2, 2]\n4-element Vector{Int64}:\n 1\n 4\n 2\n 2\n\njulia> findfirst(iseven, A)\n2\n\njulia> findfirst(x -> x>10, A) # returns nothing, but not printed in the REPL\n\njulia> findfirst(isequal(4), A)\n2\n\njulia> A = [1 4; 2 2]\n2×2 Matrix{Int64}:\n 1 4\n 2 2\n\njulia> findfirst(iseven, A)\nCartesianIndex(2, 1)\n\n\n\n\n\n","category":"method"},{"location":"base/arrays/#Base.findlast-Tuple{Any}","page":"数组","title":"Base.findlast","text":"findlast(A)\n\nReturn the index or key of the last true value in A. Return nothing if there is no true value in A.\n\nIndices or keys are of the same type as those returned by keys(A) and pairs(A).\n\nSee also: findfirst, findprev, findall.\n\nExamples\n\njulia> A = [true, false, true, false]\n4-element Vector{Bool}:\n 1\n 0\n 1\n 0\n\njulia> findlast(A)\n3\n\njulia> A = falses(2,2);\n\njulia> findlast(A) # returns nothing, but not printed in the REPL\n\njulia> A = [true false; true false]\n2×2 Matrix{Bool}:\n 1 0\n 1 0\n\njulia> findlast(A)\nCartesianIndex(2, 1)\n\n\n\n\n\n","category":"method"},{"location":"base/arrays/#Base.findlast-Tuple{Function, Any}","page":"数组","title":"Base.findlast","text":"findlast(predicate::Function, A)\n\nReturn the index or key of the last element of A for which predicate returns true. Return nothing if there is no such element.\n\nIndices or keys are of the same type as those returned by keys(A) and pairs(A).\n\nExamples\n\njulia> A = [1, 2, 3, 4]\n4-element Vector{Int64}:\n 1\n 2\n 3\n 4\n\njulia> findlast(isodd, A)\n3\n\njulia> findlast(x -> x > 5, A) # returns nothing, but not printed in the REPL\n\njulia> A = [1 2; 3 4]\n2×2 Matrix{Int64}:\n 1 2\n 3 4\n\njulia> findlast(isodd, A)\nCartesianIndex(2, 1)\n\n\n\n\n\n","category":"method"},{"location":"base/arrays/#Base.findnext-Tuple{Any, Integer}","page":"数组","title":"Base.findnext","text":"findnext(A, i)\n\nFind the next index after or including i of a true element of A, or nothing if not found.\n\nIndices are of the same type as those returned by keys(A) and pairs(A).\n\nExamples\n\njulia> A = [false, false, true, false]\n4-element Vector{Bool}:\n 0\n 0\n 1\n 0\n\njulia> findnext(A, 1)\n3\n\njulia> findnext(A, 4) # returns nothing, but not printed in the REPL\n\njulia> A = [false false; true false]\n2×2 Matrix{Bool}:\n 0 0\n 1 0\n\njulia> findnext(A, CartesianIndex(1, 1))\nCartesianIndex(2, 1)\n\n\n\n\n\n","category":"method"},{"location":"base/arrays/#Base.findnext-Tuple{Function, Any, Integer}","page":"数组","title":"Base.findnext","text":"findnext(predicate::Function, A, i)\n\nFind the next index after or including i of an element of A for which predicate returns true, or nothing if not found.\n\nIndices are of the same type as those returned by keys(A) and pairs(A).\n\nExamples\n\njulia> A = [1, 4, 2, 2];\n\njulia> findnext(isodd, A, 1)\n1\n\njulia> findnext(isodd, A, 2) # returns nothing, but not printed in the REPL\n\njulia> A = [1 4; 2 2];\n\njulia> findnext(isodd, A, CartesianIndex(1, 1))\nCartesianIndex(1, 1)\n\n\n\n\n\n","category":"method"},{"location":"base/arrays/#Base.findprev-Tuple{Any, Integer}","page":"数组","title":"Base.findprev","text":"findprev(A, i)\n\nFind the previous index before or including i of a true element of A, or nothing if not found.\n\nIndices are of the same type as those returned by keys(A) and pairs(A).\n\nSee also: findnext, findfirst, findall.\n\nExamples\n\njulia> A = [false, false, true, true]\n4-element Vector{Bool}:\n 0\n 0\n 1\n 1\n\njulia> findprev(A, 3)\n3\n\njulia> findprev(A, 1) # returns nothing, but not printed in the REPL\n\njulia> A = [false false; true true]\n2×2 Matrix{Bool}:\n 0 0\n 1 1\n\njulia> findprev(A, CartesianIndex(2, 1))\nCartesianIndex(2, 1)\n\n\n\n\n\n","category":"method"},{"location":"base/arrays/#Base.findprev-Tuple{Function, Any, Integer}","page":"数组","title":"Base.findprev","text":"findprev(predicate::Function, A, i)\n\nFind the previous index before or including i of an element of A for which predicate returns true, or nothing if not found.\n\nIndices are of the same type as those returned by keys(A) and pairs(A).\n\nExamples\n\njulia> A = [4, 6, 1, 2]\n4-element Vector{Int64}:\n 4\n 6\n 1\n 2\n\njulia> findprev(isodd, A, 1) # returns nothing, but not printed in the REPL\n\njulia> findprev(isodd, A, 3)\n3\n\njulia> A = [4 6; 1 2]\n2×2 Matrix{Int64}:\n 4 6\n 1 2\n\njulia> findprev(isodd, A, CartesianIndex(1, 2))\nCartesianIndex(2, 1)\n\n\n\n\n\n","category":"method"},{"location":"base/arrays/#Base.permutedims","page":"数组","title":"Base.permutedims","text":"permutedims(A::AbstractArray, perm)\n\nPermute the dimensions of array A. perm is a vector or a tuple of length ndims(A) specifying the permutation.\n\nSee also permutedims!, PermutedDimsArray, transpose, invperm.\n\nExamples\n\njulia> A = reshape(Vector(1:8), (2,2,2))\n2×2×2 Array{Int64, 3}:\n[:, :, 1] =\n 1 3\n 2 4\n\n[:, :, 2] =\n 5 7\n 6 8\n\njulia> permutedims(A, (3, 2, 1))\n2×2×2 Array{Int64, 3}:\n[:, :, 1] =\n 1 3\n 5 7\n\n[:, :, 2] =\n 2 4\n 6 8\n\njulia> B = randn(5, 7, 11, 13);\n\njulia> perm = [4,1,3,2];\n\njulia> size(permutedims(B, perm))\n(13, 5, 11, 7)\n\njulia> size(B)[perm] == ans\ntrue\n\n\n\n\n\npermutedims(m::AbstractMatrix)\n\nPermute the dimensions of the matrix m, by flipping the elements across the diagonal of the matrix. Differs from LinearAlgebra's transpose in that the operation is not recursive.\n\nExamples\n\njulia> a = [1 2; 3 4];\n\njulia> b = [5 6; 7 8];\n\njulia> c = [9 10; 11 12];\n\njulia> d = [13 14; 15 16];\n\njulia> X = [[a] [b]; [c] [d]]\n2×2 Matrix{Matrix{Int64}}:\n [1 2; 3 4] [5 6; 7 8]\n [9 10; 11 12] [13 14; 15 16]\n\njulia> permutedims(X)\n2×2 Matrix{Matrix{Int64}}:\n [1 2; 3 4] [9 10; 11 12]\n [5 6; 7 8] [13 14; 15 16]\n\njulia> transpose(X)\n2×2 transpose(::Matrix{Matrix{Int64}}) with eltype Transpose{Int64, Matrix{Int64}}:\n [1 3; 2 4] [9 11; 10 12]\n [5 7; 6 8] [13 15; 14 16]\n\n\n\n\n\npermutedims(v::AbstractVector)\n\nReshape vector v into a 1 × length(v) row matrix. Differs from LinearAlgebra's transpose in that the operation is not recursive.\n\nExamples\n\njulia> permutedims([1, 2, 3, 4])\n1×4 Matrix{Int64}:\n 1 2 3 4\n\njulia> V = [[[1 2; 3 4]]; [[5 6; 7 8]]]\n2-element Vector{Matrix{Int64}}:\n [1 2; 3 4]\n [5 6; 7 8]\n\njulia> permutedims(V)\n1×2 Matrix{Matrix{Int64}}:\n [1 2; 3 4] [5 6; 7 8]\n\njulia> transpose(V)\n1×2 transpose(::Vector{Matrix{Int64}}) with eltype Transpose{Int64, Matrix{Int64}}:\n [1 3; 2 4] [5 7; 6 8]\n\n\n\n\n\n","category":"function"},{"location":"base/arrays/#Base.permutedims!","page":"数组","title":"Base.permutedims!","text":"permutedims!(dest, src, perm)\n\nPermute the dimensions of array src and store the result in the array dest. perm is a vector specifying a permutation of length ndims(src). The preallocated array dest should have size(dest) == size(src)[perm] and is completely overwritten. No in-place permutation is supported and unexpected results will happen if src and dest have overlapping memory regions.\n\nSee also permutedims.\n\n\n\n\n\n","category":"function"},{"location":"base/arrays/#Base.PermutedDimsArrays.PermutedDimsArray","page":"数组","title":"Base.PermutedDimsArrays.PermutedDimsArray","text":"PermutedDimsArray(A, perm) -> B\n\nGiven an AbstractArray A, create a view B such that the dimensions appear to be permuted. Similar to permutedims, except that no copying occurs (B shares storage with A).\n\nSee also permutedims, invperm.\n\nExamples\n\njulia> A = rand(3,5,4);\n\njulia> B = PermutedDimsArray(A, (3,1,2));\n\njulia> size(B)\n(4, 3, 5)\n\njulia> B[3,1,2] == A[1,2,3]\ntrue\n\n\n\n\n\n","category":"type"},{"location":"base/arrays/#Base.promote_shape","page":"数组","title":"Base.promote_shape","text":"promote_shape(s1, s2)\n\nCheck two array shapes for compatibility, allowing trailing singleton dimensions, and return whichever shape has more dimensions.\n\nExamples\n\njulia> a = fill(1, (3,4,1,1,1));\n\njulia> b = fill(1, (3,4));\n\njulia> promote_shape(a,b)\n(Base.OneTo(3), Base.OneTo(4), Base.OneTo(1), Base.OneTo(1), Base.OneTo(1))\n\njulia> promote_shape((2,3,1,4), (2, 3, 1, 4, 1))\n(2, 3, 1, 4, 1)\n\n\n\n\n\n","category":"function"},{"location":"base/arrays/#数组函数","page":"数组","title":"数组函数","text":"","category":"section"},{"location":"base/arrays/","page":"数组","title":"数组","text":"Base.accumulate\nBase.accumulate!\nBase.cumprod\nBase.cumprod!\nBase.cumsum\nBase.cumsum!\nBase.diff\nBase.repeat\nBase.rot180\nBase.rotl90\nBase.rotr90\nBase.mapslices\nBase.eachrow\nBase.eachcol\nBase.eachslice","category":"page"},{"location":"base/arrays/#Base.accumulate","page":"数组","title":"Base.accumulate","text":"accumulate(op, A; dims::Integer, [init])\n\nCumulative operation op along the dimension dims of A (providing dims is optional for vectors). An initial value init may optionally be provided by a keyword argument. See also accumulate! to use a preallocated output array, both for performance and to control the precision of the output (e.g. to avoid overflow).\n\nFor common operations there are specialized variants of accumulate, see cumsum, cumprod. For a lazy version, see Iterators.accumulate.\n\ncompat: Julia 1.5\naccumulate on a non-array iterator requires at least Julia 1.5.\n\nExamples\n\njulia> accumulate(+, [1,2,3])\n3-element Vector{Int64}:\n 1\n 3\n 6\n\njulia> accumulate(min, (1, -2, 3, -4, 5), init=0)\n(0, -2, -2, -4, -4)\n\njulia> accumulate(/, (2, 4, Inf), init=100)\n(50.0, 12.5, 0.0)\n\njulia> accumulate(=>, i^2 for i in 1:3)\n3-element Vector{Any}:\n 1\n 1 => 4\n (1 => 4) => 9\n\njulia> accumulate(+, fill(1, 3, 4))\n3×4 Matrix{Int64}:\n 1 4 7 10\n 2 5 8 11\n 3 6 9 12\n\njulia> accumulate(+, fill(1, 2, 5), dims=2, init=100.0)\n2×5 Matrix{Float64}:\n 101.0 102.0 103.0 104.0 105.0\n 101.0 102.0 103.0 104.0 105.0\n\n\n\n\n\n","category":"function"},{"location":"base/arrays/#Base.accumulate!","page":"数组","title":"Base.accumulate!","text":"accumulate!(op, B, A; [dims], [init])\n\nCumulative operation op on A along the dimension dims, storing the result in B. Providing dims is optional for vectors. If the keyword argument init is given, its value is used to instantiate the accumulation.\n\nSee also accumulate, cumsum!, cumprod!.\n\nExamples\n\njulia> x = [1, 0, 2, 0, 3];\n\njulia> y = rand(5);\n\njulia> accumulate!(+, y, x);\n\njulia> y\n5-element Vector{Float64}:\n 1.0\n 1.0\n 3.0\n 3.0\n 6.0\n\njulia> A = [1 2 3; 4 5 6];\n\njulia> B = similar(A);\n\njulia> accumulate!(-, B, A, dims=1)\n2×3 Matrix{Int64}:\n 1 2 3\n -3 -3 -3\n\njulia> accumulate!(*, B, A, dims=2, init=10)\n2×3 Matrix{Int64}:\n 10 20 60\n 40 200 1200\n\n\n\n\n\n","category":"function"},{"location":"base/arrays/#Base.cumprod","page":"数组","title":"Base.cumprod","text":"cumprod(A; dims::Integer)\n\nCumulative product along the dimension dim. See also cumprod! to use a preallocated output array, both for performance and to control the precision of the output (e.g. to avoid overflow).\n\nExamples\n\njulia> a = Int8[1 2 3; 4 5 6];\n\njulia> cumprod(a, dims=1)\n2×3 Matrix{Int64}:\n 1 2 3\n 4 10 18\n\njulia> cumprod(a, dims=2)\n2×3 Matrix{Int64}:\n 1 2 6\n 4 20 120\n\n\n\n\n\ncumprod(itr)\n\nCumulative product of an iterator.\n\nSee also cumprod!, accumulate, cumsum.\n\ncompat: Julia 1.5\ncumprod on a non-array iterator requires at least Julia 1.5.\n\nExamples\n\njulia> cumprod(fill(1//2, 3))\n3-element Vector{Rational{Int64}}:\n 1//2\n 1//4\n 1//8\n\njulia> cumprod((1, 2, 1, 3, 1))\n(1, 2, 2, 6, 6)\n\njulia> cumprod(\"julia\")\n5-element Vector{String}:\n \"j\"\n \"ju\"\n \"jul\"\n \"juli\"\n \"julia\"\n\n\n\n\n\n","category":"function"},{"location":"base/arrays/#Base.cumprod!","page":"数组","title":"Base.cumprod!","text":"cumprod!(B, A; dims::Integer)\n\nCumulative product of A along the dimension dims, storing the result in B. See also cumprod.\n\n\n\n\n\ncumprod!(y::AbstractVector, x::AbstractVector)\n\nCumulative product of a vector x, storing the result in y. See also cumprod.\n\n\n\n\n\n","category":"function"},{"location":"base/arrays/#Base.cumsum","page":"数组","title":"Base.cumsum","text":"cumsum(A; dims::Integer)\n\nCumulative sum along the dimension dims. See also cumsum! to use a preallocated output array, both for performance and to control the precision of the output (e.g. to avoid overflow).\n\nExamples\n\njulia> a = [1 2 3; 4 5 6]\n2×3 Matrix{Int64}:\n 1 2 3\n 4 5 6\n\njulia> cumsum(a, dims=1)\n2×3 Matrix{Int64}:\n 1 2 3\n 5 7 9\n\njulia> cumsum(a, dims=2)\n2×3 Matrix{Int64}:\n 1 3 6\n 4 9 15\n\nnote: Note\nThe return array's eltype is Int for signed integers of less than system word size and UInt for unsigned integers of less than system word size. To preserve eltype of arrays with small signed or unsigned integer accumulate(+, A) should be used.julia> cumsum(Int8[100, 28])\n2-element Vector{Int64}:\n 100\n 128\n\njulia> accumulate(+,Int8[100, 28])\n2-element Vector{Int8}:\n 100\n -128In the former case, the integers are widened to system word size and therefore the result is Int64[100, 128]. In the latter case, no such widening happens and integer overflow results in Int8[100, -128].\n\n\n\n\n\ncumsum(itr)\n\nCumulative sum of an iterator.\n\nSee also accumulate to apply functions other than +.\n\ncompat: Julia 1.5\ncumsum on a non-array iterator requires at least Julia 1.5.\n\nExamples\n\njulia> cumsum(1:3)\n3-element Vector{Int64}:\n 1\n 3\n 6\n\njulia> cumsum((true, false, true, false, true))\n(1, 1, 2, 2, 3)\n\njulia> cumsum(fill(1, 2) for i in 1:3)\n3-element Vector{Vector{Int64}}:\n [1, 1]\n [2, 2]\n [3, 3]\n\n\n\n\n\n","category":"function"},{"location":"base/arrays/#Base.cumsum!","page":"数组","title":"Base.cumsum!","text":"cumsum!(B, A; dims::Integer)\n\nCumulative sum of A along the dimension dims, storing the result in B. See also cumsum.\n\n\n\n\n\n","category":"function"},{"location":"base/arrays/#Base.diff","page":"数组","title":"Base.diff","text":"diff(A::AbstractVector)\ndiff(A::AbstractArray; dims::Integer)\n\nFinite difference operator on a vector or a multidimensional array A. In the latter case the dimension to operate on needs to be specified with the dims keyword argument.\n\ncompat: Julia 1.1\ndiff for arrays with dimension higher than 2 requires at least Julia 1.1.\n\nExamples\n\njulia> a = [2 4; 6 16]\n2×2 Matrix{Int64}:\n 2 4\n 6 16\n\njulia> diff(a, dims=2)\n2×1 Matrix{Int64}:\n 2\n 10\n\njulia> diff(vec(a))\n3-element Vector{Int64}:\n 4\n -2\n 12\n\n\n\n\n\n","category":"function"},{"location":"base/arrays/#Base.repeat","page":"数组","title":"Base.repeat","text":"repeat(A::AbstractArray, counts::Integer...)\n\nConstruct an array by repeating array A a given number of times in each dimension, specified by counts.\n\nSee also: fill, Iterators.repeated, Iterators.cycle.\n\nExamples\n\njulia> repeat([1, 2, 3], 2)\n6-element Vector{Int64}:\n 1\n 2\n 3\n 1\n 2\n 3\n\njulia> repeat([1, 2, 3], 2, 3)\n6×3 Matrix{Int64}:\n 1 1 1\n 2 2 2\n 3 3 3\n 1 1 1\n 2 2 2\n 3 3 3\n\n\n\n\n\nrepeat(A::AbstractArray; inner=ntuple(Returns(1), ndims(A)), outer=ntuple(Returns(1), ndims(A)))\n\nConstruct an array by repeating the entries of A. The i-th element of inner specifies the number of times that the individual entries of the i-th dimension of A should be repeated. The i-th element of outer specifies the number of times that a slice along the i-th dimension of A should be repeated. If inner or outer are omitted, no repetition is performed.\n\nExamples\n\njulia> repeat(1:2, inner=2)\n4-element Vector{Int64}:\n 1\n 1\n 2\n 2\n\njulia> repeat(1:2, outer=2)\n4-element Vector{Int64}:\n 1\n 2\n 1\n 2\n\njulia> repeat([1 2; 3 4], inner=(2, 1), outer=(1, 3))\n4×6 Matrix{Int64}:\n 1 2 1 2 1 2\n 1 2 1 2 1 2\n 3 4 3 4 3 4\n 3 4 3 4 3 4\n\n\n\n\n\nrepeat(s::AbstractString, r::Integer)\n\nRepeat a string r times. This can be written as s^r.\n\nSee also ^.\n\nExamples\n\njulia> repeat(\"ha\", 3)\n\"hahaha\"\n\n\n\n\n\nrepeat(c::AbstractChar, r::Integer) -> String\n\nRepeat a character r times. This can equivalently be accomplished by calling c^r.\n\nExamples\n\njulia> repeat('A', 3)\n\"AAA\"\n\n\n\n\n\n","category":"function"},{"location":"base/arrays/#Base.rot180","page":"数组","title":"Base.rot180","text":"rot180(A)\n\nRotate matrix A 180 degrees.\n\nExamples\n\njulia> a = [1 2; 3 4]\n2×2 Matrix{Int64}:\n 1 2\n 3 4\n\njulia> rot180(a)\n2×2 Matrix{Int64}:\n 4 3\n 2 1\n\n\n\n\n\nrot180(A, k)\n\nRotate matrix A 180 degrees an integer k number of times. If k is even, this is equivalent to a copy.\n\nExamples\n\njulia> a = [1 2; 3 4]\n2×2 Matrix{Int64}:\n 1 2\n 3 4\n\njulia> rot180(a,1)\n2×2 Matrix{Int64}:\n 4 3\n 2 1\n\njulia> rot180(a,2)\n2×2 Matrix{Int64}:\n 1 2\n 3 4\n\n\n\n\n\n","category":"function"},{"location":"base/arrays/#Base.rotl90","page":"数组","title":"Base.rotl90","text":"rotl90(A)\n\nRotate matrix A left 90 degrees.\n\nExamples\n\njulia> a = [1 2; 3 4]\n2×2 Matrix{Int64}:\n 1 2\n 3 4\n\njulia> rotl90(a)\n2×2 Matrix{Int64}:\n 2 4\n 1 3\n\n\n\n\n\nrotl90(A, k)\n\nLeft-rotate matrix A 90 degrees counterclockwise an integer k number of times. If k is a multiple of four (including zero), this is equivalent to a copy.\n\nExamples\n\njulia> a = [1 2; 3 4]\n2×2 Matrix{Int64}:\n 1 2\n 3 4\n\njulia> rotl90(a,1)\n2×2 Matrix{Int64}:\n 2 4\n 1 3\n\njulia> rotl90(a,2)\n2×2 Matrix{Int64}:\n 4 3\n 2 1\n\njulia> rotl90(a,3)\n2×2 Matrix{Int64}:\n 3 1\n 4 2\n\njulia> rotl90(a,4)\n2×2 Matrix{Int64}:\n 1 2\n 3 4\n\n\n\n\n\n","category":"function"},{"location":"base/arrays/#Base.rotr90","page":"数组","title":"Base.rotr90","text":"rotr90(A)\n\nRotate matrix A right 90 degrees.\n\nExamples\n\njulia> a = [1 2; 3 4]\n2×2 Matrix{Int64}:\n 1 2\n 3 4\n\njulia> rotr90(a)\n2×2 Matrix{Int64}:\n 3 1\n 4 2\n\n\n\n\n\nrotr90(A, k)\n\nRight-rotate matrix A 90 degrees clockwise an integer k number of times. If k is a multiple of four (including zero), this is equivalent to a copy.\n\nExamples\n\njulia> a = [1 2; 3 4]\n2×2 Matrix{Int64}:\n 1 2\n 3 4\n\njulia> rotr90(a,1)\n2×2 Matrix{Int64}:\n 3 1\n 4 2\n\njulia> rotr90(a,2)\n2×2 Matrix{Int64}:\n 4 3\n 2 1\n\njulia> rotr90(a,3)\n2×2 Matrix{Int64}:\n 2 4\n 1 3\n\njulia> rotr90(a,4)\n2×2 Matrix{Int64}:\n 1 2\n 3 4\n\n\n\n\n\n","category":"function"},{"location":"base/arrays/#Base.mapslices","page":"数组","title":"Base.mapslices","text":"mapslices(f, A; dims)\n\nTransform the given dimensions of array A using function f. f is called on each slice of A of the form A[...,:,...,:,...]. dims is an integer vector specifying where the colons go in this expression. The results are concatenated along the remaining dimensions. For example, if dims is [1,2] and A is 4-dimensional, f is called on A[:,:,i,j] for all i and j.\n\nSee also eachcol, eachslice.\n\nExamples\n\njulia> a = reshape(Vector(1:16),(2,2,2,2))\n2×2×2×2 Array{Int64, 4}:\n[:, :, 1, 1] =\n 1 3\n 2 4\n\n[:, :, 2, 1] =\n 5 7\n 6 8\n\n[:, :, 1, 2] =\n 9 11\n 10 12\n\n[:, :, 2, 2] =\n 13 15\n 14 16\n\njulia> mapslices(sum, a, dims = [1,2])\n1×1×2×2 Array{Int64, 4}:\n[:, :, 1, 1] =\n 10\n\n[:, :, 2, 1] =\n 26\n\n[:, :, 1, 2] =\n 42\n\n[:, :, 2, 2] =\n 58\n\n\n\n\n\n","category":"function"},{"location":"base/arrays/#Base.eachrow","page":"数组","title":"Base.eachrow","text":"eachrow(A::AbstractVecOrMat)\n\nCreate a generator that iterates over the first dimension of vector or matrix A, returning the rows as AbstractVector views.\n\nSee also eachcol, eachslice, mapslices.\n\ncompat: Julia 1.1\nThis function requires at least Julia 1.1.\n\nExample\n\njulia> a = [1 2; 3 4]\n2×2 Matrix{Int64}:\n 1 2\n 3 4\n\njulia> first(eachrow(a))\n2-element view(::Matrix{Int64}, 1, :) with eltype Int64:\n 1\n 2\n\njulia> collect(eachrow(a))\n2-element Vector{SubArray{Int64, 1, Matrix{Int64}, Tuple{Int64, Base.Slice{Base.OneTo{Int64}}}, true}}:\n [1, 2]\n [3, 4]\n\n\n\n\n\n","category":"function"},{"location":"base/arrays/#Base.eachcol","page":"数组","title":"Base.eachcol","text":"eachcol(A::AbstractVecOrMat)\n\nCreate a generator that iterates over the second dimension of matrix A, returning the columns as AbstractVector views.\n\nSee also eachrow and eachslice.\n\ncompat: Julia 1.1\nThis function requires at least Julia 1.1.\n\nExample\n\njulia> a = [1 2; 3 4]\n2×2 Matrix{Int64}:\n 1 2\n 3 4\n\njulia> first(eachcol(a))\n2-element view(::Matrix{Int64}, :, 1) with eltype Int64:\n 1\n 3\n\njulia> collect(eachcol(a))\n2-element Vector{SubArray{Int64, 1, Matrix{Int64}, Tuple{Base.Slice{Base.OneTo{Int64}}, Int64}, true}}:\n [1, 3]\n [2, 4]\n\n\n\n\n\n","category":"function"},{"location":"base/arrays/#Base.eachslice","page":"数组","title":"Base.eachslice","text":"eachslice(A::AbstractArray; dims)\n\nCreate a generator that iterates over dimensions dims of A, returning views that select all the data from the other dimensions in A.\n\nOnly a single dimension in dims is currently supported. Equivalent to (view(A,:,:,...,i,:,: ...)) for i in axes(A, dims)), where i is in position dims.\n\nSee also eachrow, eachcol, mapslices, and selectdim.\n\ncompat: Julia 1.1\nThis function requires at least Julia 1.1.\n\nExample\n\njulia> M = [1 2 3; 4 5 6; 7 8 9]\n3×3 Matrix{Int64}:\n 1 2 3\n 4 5 6\n 7 8 9\n\njulia> first(eachslice(M, dims=1))\n3-element view(::Matrix{Int64}, 1, :) with eltype Int64:\n 1\n 2\n 3\n\njulia> collect(eachslice(M, dims=2))\n3-element Vector{SubArray{Int64, 1, Matrix{Int64}, Tuple{Base.Slice{Base.OneTo{Int64}}, Int64}, true}}:\n [1, 4, 7]\n [2, 5, 8]\n [3, 6, 9]\n\n\n\n\n\n","category":"function"},{"location":"base/arrays/#组合学","page":"数组","title":"组合学","text":"","category":"section"},{"location":"base/arrays/","page":"数组","title":"数组","text":"Base.invperm\nBase.isperm\nBase.permute!(::Any, ::AbstractVector)\nBase.invpermute!\nBase.reverse(::AbstractVector; kwargs...)\nBase.reverseind\nBase.reverse!","category":"page"},{"location":"base/arrays/#Base.invperm","page":"数组","title":"Base.invperm","text":"invperm(v)\n\nReturn the inverse permutation of v. If B = A[v], then A == B[invperm(v)].\n\nSee also sortperm, invpermute!, isperm, permutedims.\n\nExamples\n\njulia> p = (2, 3, 1);\n\njulia> invperm(p)\n(3, 1, 2)\n\njulia> v = [2; 4; 3; 1];\n\njulia> invperm(v)\n4-element Vector{Int64}:\n 4\n 1\n 3\n 2\n\njulia> A = ['a','b','c','d'];\n\njulia> B = A[v]\n4-element Vector{Char}:\n 'b': ASCII/Unicode U+0062 (category Ll: Letter, lowercase)\n 'd': ASCII/Unicode U+0064 (category Ll: Letter, lowercase)\n 'c': ASCII/Unicode U+0063 (category Ll: Letter, lowercase)\n 'a': ASCII/Unicode U+0061 (category Ll: Letter, lowercase)\n\njulia> B[invperm(v)]\n4-element Vector{Char}:\n 'a': ASCII/Unicode U+0061 (category Ll: Letter, lowercase)\n 'b': ASCII/Unicode U+0062 (category Ll: Letter, lowercase)\n 'c': ASCII/Unicode U+0063 (category Ll: Letter, lowercase)\n 'd': ASCII/Unicode U+0064 (category Ll: Letter, lowercase)\n\n\n\n\n\n","category":"function"},{"location":"base/arrays/#Base.isperm","page":"数组","title":"Base.isperm","text":"isperm(v) -> Bool\n\nReturn true if v is a valid permutation.\n\nExamples\n\njulia> isperm([1; 2])\ntrue\n\njulia> isperm([1; 3])\nfalse\n\n\n\n\n\n","category":"function"},{"location":"base/arrays/#Base.permute!-Tuple{Any, AbstractVector}","page":"数组","title":"Base.permute!","text":"permute!(v, p)\n\nPermute vector v in-place, according to permutation p. No checking is done to verify that p is a permutation.\n\nTo return a new permutation, use v[p]. Note that this is generally faster than permute!(v,p) for large vectors.\n\nSee also invpermute!.\n\nExamples\n\njulia> A = [1, 1, 3, 4];\n\njulia> perm = [2, 4, 3, 1];\n\njulia> permute!(A, perm);\n\njulia> A\n4-element Vector{Int64}:\n 1\n 4\n 3\n 1\n\n\n\n\n\n","category":"method"},{"location":"base/arrays/#Base.invpermute!","page":"数组","title":"Base.invpermute!","text":"invpermute!(v, p)\n\nLike permute!, but the inverse of the given permutation is applied.\n\nExamples\n\njulia> A = [1, 1, 3, 4];\n\njulia> perm = [2, 4, 3, 1];\n\njulia> invpermute!(A, perm);\n\njulia> A\n4-element Vector{Int64}:\n 4\n 1\n 3\n 1\n\n\n\n\n\n","category":"function"},{"location":"base/arrays/#Base.reverse-Tuple{AbstractVector}","page":"数组","title":"Base.reverse","text":"reverse(A; dims=:)\n\nReverse A along dimension dims, which can be an integer (a single dimension), a tuple of integers (a tuple of dimensions) or : (reverse along all the dimensions, the default). See also reverse! for in-place reversal.\n\nExamples\n\njulia> b = Int64[1 2; 3 4]\n2×2 Matrix{Int64}:\n 1 2\n 3 4\n\njulia> reverse(b, dims=2)\n2×2 Matrix{Int64}:\n 2 1\n 4 3\n\njulia> reverse(b)\n2×2 Matrix{Int64}:\n 4 3\n 2 1\n\ncompat: Julia 1.6\nPrior to Julia 1.6, only single-integer dims are supported in reverse.\n\n\n\n\n\n","category":"method"},{"location":"base/arrays/#Base.reverseind","page":"数组","title":"Base.reverseind","text":"reverseind(v, i)\n\nGiven an index i in reverse(v), return the corresponding index in v so that v[reverseind(v,i)] == reverse(v)[i]. (This can be nontrivial in cases where v contains non-ASCII characters.)\n\nExamples\n\njulia> s = \"Julia🚀\"\n\"Julia🚀\"\n\njulia> r = reverse(s)\n\"🚀ailuJ\"\n\njulia> for i in eachindex(s)\n print(r[reverseind(r, i)])\n end\nJulia🚀\n\n\n\n\n\n","category":"function"},{"location":"base/arrays/#Base.reverse!","page":"数组","title":"Base.reverse!","text":"reverse!(v [, start=1 [, stop=length(v) ]]) -> v\n\nIn-place version of reverse.\n\nExamples\n\njulia> A = Vector(1:5)\n5-element Vector{Int64}:\n 1\n 2\n 3\n 4\n 5\n\njulia> reverse!(A);\n\njulia> A\n5-element Vector{Int64}:\n 5\n 4\n 3\n 2\n 1\n\n\n\n\n\nreverse!(A; dims=:)\n\nLike reverse, but operates in-place in A.\n\ncompat: Julia 1.6\nMultidimensional reverse! requires Julia 1.6.\n\n\n\n\n\n","category":"function"},{"location":"manual/handling-operating-system-variation/#处理操作系统差异","page":"处理操作系统差异","title":"处理操作系统差异","text":"","category":"section"},{"location":"manual/handling-operating-system-variation/","page":"处理操作系统差异","title":"处理操作系统差异","text":"当编写跨平台的应用或库时,通常需要考虑到操作系统之间的差异。变量 Sys.KERNEL 可以用于这些场合。在 Sys 模块中有一些函数将会使这些事情更加简单:isunix、 islinux、isapple、isbsd、isfreebsd 以及 iswindows。这些函数可以按如下方式使用:","category":"page"},{"location":"manual/handling-operating-system-variation/","page":"处理操作系统差异","title":"处理操作系统差异","text":"if Sys.iswindows()\n windows_specific_thing(a)\nend","category":"page"},{"location":"manual/handling-operating-system-variation/","page":"处理操作系统差异","title":"处理操作系统差异","text":"注意,islinux、isapple 和 isfreebsd 是 isunix 完全互斥的子集。另外,有一个宏 @static 可以使用这些函数有条件地隐藏无效代码,如以下示例所示。","category":"page"},{"location":"manual/handling-operating-system-variation/","page":"处理操作系统差异","title":"处理操作系统差异","text":"简单例子:","category":"page"},{"location":"manual/handling-operating-system-variation/","page":"处理操作系统差异","title":"处理操作系统差异","text":"ccall((@static Sys.iswindows() ? :_fopen : :fopen), ...)","category":"page"},{"location":"manual/handling-operating-system-variation/","page":"处理操作系统差异","title":"处理操作系统差异","text":"复杂例子:","category":"page"},{"location":"manual/handling-operating-system-variation/","page":"处理操作系统差异","title":"处理操作系统差异","text":"@static if Sys.islinux()\n linux_specific_thing(a)\nelse\n generic_thing(a)\nend","category":"page"},{"location":"manual/handling-operating-system-variation/","page":"处理操作系统差异","title":"处理操作系统差异","text":"在链式嵌套的条件表达式中(包括 if/elseif/end),@static 必须在每一层都调用(括号是可选的,但是为了可读性,建议添加)。","category":"page"},{"location":"manual/handling-operating-system-variation/","page":"处理操作系统差异","title":"处理操作系统差异","text":"@static Sys.iswindows() ? :a : (@static Sys.isapple() ? :b : :c)","category":"page"},{"location":"manual/performance-tips/#man-performance-tips","page":"性能建议","title":"性能建议","text":"","category":"section"},{"location":"manual/performance-tips/","page":"性能建议","title":"性能建议","text":"下面几节简要地介绍了一些使 Julia 代码运行得尽可能快的技巧。","category":"page"},{"location":"manual/performance-tips/#影响性能的关键代码应该在函数内部","page":"性能建议","title":"影响性能的关键代码应该在函数内部","text":"","category":"section"},{"location":"manual/performance-tips/","page":"性能建议","title":"性能建议","text":"任何对性能至关重要的代码都应该在函数内部。 由于 Julia 编译器的工作方式,函数内部的代码往往比顶层代码运行得更快。","category":"page"},{"location":"manual/performance-tips/","page":"性能建议","title":"性能建议","text":"函数的使用不仅对性能很重要:函数更可重用和可测试,并阐明正在执行哪些步骤以及它们的输入和输出是什么,[编写函数,而不仅仅是脚本](@ref)也是 Julia 的风格指南。","category":"page"},{"location":"manual/performance-tips/","page":"性能建议","title":"性能建议","text":"函数应该接收参数,而不是直接对全局变量进行操作,请参阅下一点。","category":"page"},{"location":"manual/performance-tips/#避免全局变量","page":"性能建议","title":"避免全局变量","text":"","category":"section"},{"location":"manual/performance-tips/","page":"性能建议","title":"性能建议","text":"全局变量的值和类型随时都会发生变化, 这使编译器难以优化使用全局变量的代码。 变量应该是局部的,或者尽可能作为参数传递给函数。","category":"page"},{"location":"manual/performance-tips/","page":"性能建议","title":"性能建议","text":"我们发现全局变量经常是常量,将它们声明为常量可大幅提升性能。","category":"page"},{"location":"manual/performance-tips/","page":"性能建议","title":"性能建议","text":"const DEFAULT_VAL = 0","category":"page"},{"location":"manual/performance-tips/","page":"性能建议","title":"性能建议","text":"对于非常量的全局变量可以通过在使用的时候标注它们的类型来优化。","category":"page"},{"location":"manual/performance-tips/","page":"性能建议","title":"性能建议","text":"global x = rand(1000)\n\nfunction loop_over_global()\n s = 0.0\n for i in x::Vector{Float64}\n s += i\n end\n return s\nend","category":"page"},{"location":"manual/performance-tips/","page":"性能建议","title":"性能建议","text":"一个更好的编程风格是将变量作为参数传给函数。这样可以使得代码更易复用,以及清晰的展示函数的输入和输出。","category":"page"},{"location":"manual/performance-tips/","page":"性能建议","title":"性能建议","text":"note: Note\n所有的REPL中的代码都是在全局作用域中求值的,因此在顶层的变量的定义与赋值都会成为一个全局变量。在模块的顶层作用域定义的变量也是全局变量。","category":"page"},{"location":"manual/performance-tips/","page":"性能建议","title":"性能建议","text":"在下面的REPL会话中:","category":"page"},{"location":"manual/performance-tips/","page":"性能建议","title":"性能建议","text":"julia> x = 1.0","category":"page"},{"location":"manual/performance-tips/","page":"性能建议","title":"性能建议","text":"等价于:","category":"page"},{"location":"manual/performance-tips/","page":"性能建议","title":"性能建议","text":"julia> global x = 1.0","category":"page"},{"location":"manual/performance-tips/","page":"性能建议","title":"性能建议","text":"因此,所有上文关于性能问题的讨论都适用于它们。","category":"page"},{"location":"manual/performance-tips/#使用-[@time](@ref)评估性能以及注意内存分配","page":"性能建议","title":"使用 @time评估性能以及注意内存分配","text":"","category":"section"},{"location":"manual/performance-tips/","page":"性能建议","title":"性能建议","text":"@time 宏是一个有用的性能评估工具。这里我们将重复上面全局变量的例子,但是这次移除类型声明:","category":"page"},{"location":"manual/performance-tips/","page":"性能建议","title":"性能建议","text":"julia> x = rand(1000);\n\njulia> function sum_global()\n s = 0.0\n for i in x\n s += i\n end\n return s\n end;\n\njulia> @time sum_global()\n 0.010414 seconds (9.07 k allocations: 373.448 KiB, 98.40% compilation time)\n493.6199223951192\n\njulia> @time sum_global()\n 0.000108 seconds (3.49 k allocations: 70.156 KiB)\n493.6199223951192","category":"page"},{"location":"manual/performance-tips/","page":"性能建议","title":"性能建议","text":"在第一次调用(@time sum_global())时,函数被编译。 (如果不在此会话中使用 @time,它还会编译计时所需的函数。)你不用把此次运行的结果放在心上。对于第二次运行,请注意,除了报告时间外,它还表明分配了大量内存。 我们在这里只是计算 64 位浮点数向量中所有元素的总和,因此不需要分配内存(至少不是在堆上,这就是 @time 报告的内容)。","category":"page"},{"location":"manual/performance-tips/","page":"性能建议","title":"性能建议","text":"预料之外的内存分配几乎总是表示你的代码存在问题,通常是类型稳定性问题或创建了许多小的临时数组。 因此,除了分配本身之外,你的函数的代码很可能远非最优。请认真对待此类迹象并遵循以下建议。","category":"page"},{"location":"manual/performance-tips/","page":"性能建议","title":"性能建议","text":"如果我们改为将 x 作为参数传递给函数,它不再分配内存(下面报告的分配是由于在全局范围内运行 @time 宏)并且在第一次调用后明显更快:","category":"page"},{"location":"manual/performance-tips/","page":"性能建议","title":"性能建议","text":"julia> x = rand(1000);\n\njulia> function sum_arg(x)\n s = 0.0\n for i in x\n s += i\n end\n return s\n end;\n\njulia> @time sum_arg(x)\n 0.007971 seconds (3.96 k allocations: 200.171 KiB, 99.83% compilation time)\n493.6199223951192\n\njulia> @time sum_arg(x)\n 0.000003 seconds (1 allocation: 16 bytes)\n493.6199223951192","category":"page"},{"location":"manual/performance-tips/","page":"性能建议","title":"性能建议","text":"看到的 1 allocation 来自在全局范围内运行 @time 宏本身。 如果我们改为在函数中运行计时,我们可以看到确实没有执行任何分配:","category":"page"},{"location":"manual/performance-tips/","page":"性能建议","title":"性能建议","text":"julia> time_sum(x) = @time sum_arg(x);\n\njulia> time_sum(x)\n 0.000001 seconds\n493.6199223951192","category":"page"},{"location":"manual/performance-tips/","page":"性能建议","title":"性能建议","text":"在某些情况下,你的函数可能需要将分配内存作为其操作的一部分,这比上面的简单例子复杂的多。 在这种情况下,请考虑使用下面的 工具 之一来诊断问题,或者编写一个将分配内存与算法方面分开的函数版本(请参阅 输出预分配)。","category":"page"},{"location":"manual/performance-tips/","page":"性能建议","title":"性能建议","text":"note: Note\n对于更严格的基准测试,请考虑 BenchmarkTools.jl 包,该包会多次评估函数以减少噪音。","category":"page"},{"location":"manual/performance-tips/#tools","page":"性能建议","title":"工具","text":"","category":"section"},{"location":"manual/performance-tips/","page":"性能建议","title":"性能建议","text":"Julia 及其包生态系统包括可以帮助您诊断问题和提高代码性能的工具:","category":"page"},{"location":"manual/performance-tips/","page":"性能建议","title":"性能建议","text":"Profiling 允许你测量正在运行的代码的性能并识别作为瓶颈的行。对于复杂的项目,ProfileView 包可以帮助你可视化分析结果。\nTraceur 包可以帮助你找到代码中常见的性能问题。\n预期之外的大内存分配——正如 @time、@allocated 或 Profiler(通过调用垃圾收集例程)所报告的那样——暗示你的代码可能有问题。 如果你没有看到分配的其他原因,请怀疑是类型问题。还可以使用 --track allocation=user 选项启动 Julia 并检查生成的 *.mem 文件以查看有关这些分配发生位置的信息。 参见内存分配分析。\n@code_warntype 生成代码的表示形式,这有助于查找导致类型不确定性的表达式。 请参阅下面的 @code_warntype。","category":"page"},{"location":"manual/performance-tips/#man-performance-abstract-container","page":"性能建议","title":"避免使用抽象类型参数的容器","text":"","category":"section"},{"location":"manual/performance-tips/","page":"性能建议","title":"性能建议","text":"使用参数化类型(包括数组)时,最好尽可能避免使用抽象类型进行参数化。","category":"page"},{"location":"manual/performance-tips/","page":"性能建议","title":"性能建议","text":"考虑如下:","category":"page"},{"location":"manual/performance-tips/","page":"性能建议","title":"性能建议","text":"julia> a = Real[]\nReal[]\n\njulia> push!(a, 1); push!(a, 2.0); push!(a, π)\n3-element Vector{Real}:\n 1\n 2.0\n π = 3.1415926535897...","category":"page"},{"location":"manual/performance-tips/","page":"性能建议","title":"性能建议","text":"因为 a 是一个抽象类型 Real 的数组,所以它能够保存任何 Real 值。 由于Real对象允许具有任意大小和结构,因此a必须表示为指向单独分配的Real对象的指针数组。 但是,如果我们只允许相同类型的数字,例如 Float64, a 可以更有效地存储:","category":"page"},{"location":"manual/performance-tips/","page":"性能建议","title":"性能建议","text":"julia> a = Float64[]\nFloat64[]\n\njulia> push!(a, 1); push!(a, 2.0); push!(a, π)\n3-element Vector{Float64}:\n 1.0\n 2.0\n 3.141592653589793","category":"page"},{"location":"manual/performance-tips/","page":"性能建议","title":"性能建议","text":"把数字赋值给a会即时将数字转换成Float64并且a会按照64位浮点数值的连续的块来储存,这就能高效地处理。","category":"page"},{"location":"manual/performance-tips/","page":"性能建议","title":"性能建议","text":"如果无法避免使用抽象值类型的容器,有时最好使用Any参数化以避免运行时类型检查。 例如。 IdDict{Any, Any} 的性能优于 IdDict{Type, Vector}。","category":"page"},{"location":"manual/performance-tips/","page":"性能建议","title":"性能建议","text":"也请参见在参数类型下的讨论。","category":"page"},{"location":"manual/performance-tips/#类型声明","page":"性能建议","title":"类型声明","text":"","category":"section"},{"location":"manual/performance-tips/","page":"性能建议","title":"性能建议","text":"在有可选类型声明的语言中,添加声明是使代码运行更快的原则性方法。在Julia中并不是这种情况。在Julia中,编译器都知道所有的函数参数,局部变量和表达式的类型。但是,有一些特殊的情况下声明是有帮助的。","category":"page"},{"location":"manual/performance-tips/#避免有抽象类型的字段","page":"性能建议","title":"避免有抽象类型的字段","text":"","category":"section"},{"location":"manual/performance-tips/","page":"性能建议","title":"性能建议","text":"类型能在不指定其字段的类型的情况下被声明:","category":"page"},{"location":"manual/performance-tips/","page":"性能建议","title":"性能建议","text":"julia> struct MyAmbiguousType\n a\n end","category":"page"},{"location":"manual/performance-tips/","page":"性能建议","title":"性能建议","text":"这就允许a可以是任意类型。这经常很有用,但是有个缺点:对于类型MyAmbiguousType的对象,编译器不能够生成高性能的代码。原因是编译器使用对象的类型,而非值,来确定如何构建代码。不幸的是,几乎没有信息可以从类型MyAmbiguousType的对象中推导出来:","category":"page"},{"location":"manual/performance-tips/","page":"性能建议","title":"性能建议","text":"julia> b = MyAmbiguousType(\"Hello\")\nMyAmbiguousType(\"Hello\")\n\njulia> c = MyAmbiguousType(17)\nMyAmbiguousType(17)\n\njulia> typeof(b)\nMyAmbiguousType\n\njulia> typeof(c)\nMyAmbiguousType","category":"page"},{"location":"manual/performance-tips/","page":"性能建议","title":"性能建议","text":"b 和 c 的值具有相同类型,但它们在内存中的数据的底层表示十分不同。即使你只在字段 a 中存储数值,UInt8 的内存表示与 Float64 也是不同的,这也意味着 CPU 需要使用两种不同的指令来处理它们。因为该类型中不提供所需的信息,所以必须在运行时进行这些判断。而这会降低性能。","category":"page"},{"location":"manual/performance-tips/","page":"性能建议","title":"性能建议","text":"通过声明 a 的类型,你能够做得更好。这里我们关注 a 可能是几种类型中任意一种的情况,在这种情况下,自然的一个解决方法是使用参数。例如:","category":"page"},{"location":"manual/performance-tips/","page":"性能建议","title":"性能建议","text":"julia> mutable struct MyType{T<:AbstractFloat}\n a::T\n end","category":"page"},{"location":"manual/performance-tips/","page":"性能建议","title":"性能建议","text":"比下面这种更好","category":"page"},{"location":"manual/performance-tips/","page":"性能建议","title":"性能建议","text":"julia> mutable struct MyStillAmbiguousType\n a::AbstractFloat\n end","category":"page"},{"location":"manual/performance-tips/","page":"性能建议","title":"性能建议","text":"因为第一种通过包装对象的类型指定了 a 的类型。 例如:","category":"page"},{"location":"manual/performance-tips/","page":"性能建议","title":"性能建议","text":"julia> m = MyType(3.2)\nMyType{Float64}(3.2)\n\njulia> t = MyStillAmbiguousType(3.2)\nMyStillAmbiguousType(3.2)\n\njulia> typeof(m)\nMyType{Float64}\n\njulia> typeof(t)\nMyStillAmbiguousType","category":"page"},{"location":"manual/performance-tips/","page":"性能建议","title":"性能建议","text":"字段 a 的类型可以很容易地通过 m 的类型确定,而不是通过 t 的类型确定。事实上,在 t 中是可以改变字段 a 的类型的:","category":"page"},{"location":"manual/performance-tips/","page":"性能建议","title":"性能建议","text":"julia> typeof(t.a)\nFloat64\n\njulia> t.a = 4.5f0\n4.5f0\n\njulia> typeof(t.a)\nFloat32","category":"page"},{"location":"manual/performance-tips/","page":"性能建议","title":"性能建议","text":"反之,一旦 m 被构建出来,m.a 的类型就不能够更改了。","category":"page"},{"location":"manual/performance-tips/","page":"性能建议","title":"性能建议","text":"julia> m.a = 4.5f0\n4.5f0\n\njulia> typeof(m.a)\nFloat64","category":"page"},{"location":"manual/performance-tips/","page":"性能建议","title":"性能建议","text":"m.a 的类型是通过 m 的类型得知这一事实加上它的类型不能改变在函数中改变这一事实,这两者使得对于像 m 这样的对象编译器可以生成高度优化后的代码,但是对 t 这样的对象却不可以。 当然,如果我们将 m 构造成一个具体类型,那么这两者都可以。我们可以通过明确地使用一个抽象类型去构建它来破坏这一点:","category":"page"},{"location":"manual/performance-tips/","page":"性能建议","title":"性能建议","text":"julia> m = MyType{AbstractFloat}(3.2)\nMyType{AbstractFloat}(3.2)\n\njulia> typeof(m.a)\nFloat64\n\njulia> m.a = 4.5f0\n4.5f0\n\njulia> typeof(m.a)\nFloat32","category":"page"},{"location":"manual/performance-tips/","page":"性能建议","title":"性能建议","text":"对于一个实际的目的来说,这样的对象表现起来和那些 MyStillAmbiguousType 的对象一模一样。","category":"page"},{"location":"manual/performance-tips/","page":"性能建议","title":"性能建议","text":"比较为一个简单函数生成的代码的绝对数量是十分有指导意义的,","category":"page"},{"location":"manual/performance-tips/","page":"性能建议","title":"性能建议","text":"func(m::MyType) = m.a+1","category":"page"},{"location":"manual/performance-tips/","page":"性能建议","title":"性能建议","text":"使用","category":"page"},{"location":"manual/performance-tips/","page":"性能建议","title":"性能建议","text":"code_llvm(func, Tuple{MyType{Float64}})\ncode_llvm(func, Tuple{MyType{AbstractFloat}})","category":"page"},{"location":"manual/performance-tips/","page":"性能建议","title":"性能建议","text":"由于长度的原因,代码的结果没有在这里显示出来,但是你可能会希望自己去验证这一点。因为在第一种情况中,类型被完全指定了,在运行时,编译器不需要生成任何代码来决定类型。这就带来了更短和更快的代码。","category":"page"},{"location":"manual/performance-tips/#避免使用带抽象容器的字段","page":"性能建议","title":"避免使用带抽象容器的字段","text":"","category":"section"},{"location":"manual/performance-tips/","page":"性能建议","title":"性能建议","text":"上面的做法同样也适用于容器的类型:","category":"page"},{"location":"manual/performance-tips/","page":"性能建议","title":"性能建议","text":"julia> struct MySimpleContainer{A<:AbstractVector}\n a::A\n end\n\njulia> struct MyAmbiguousContainer{T}\n a::AbstractVector{T}\n end","category":"page"},{"location":"manual/performance-tips/","page":"性能建议","title":"性能建议","text":"例如:","category":"page"},{"location":"manual/performance-tips/","page":"性能建议","title":"性能建议","text":"julia> c = MySimpleContainer(1:3);\n\njulia> typeof(c)\nMySimpleContainer{UnitRange{Int64}}\n\njulia> c = MySimpleContainer([1:3;]);\n\njulia> typeof(c)\nMySimpleContainer{Vector{Int64}}\n\njulia> b = MyAmbiguousContainer(1:3);\n\njulia> typeof(b)\nMyAmbiguousContainer{Int64}\n\njulia> b = MyAmbiguousContainer([1:3;]);\n\njulia> typeof(b)\nMyAmbiguousContainer{Int64}","category":"page"},{"location":"manual/performance-tips/","page":"性能建议","title":"性能建议","text":"对于 MySimpleContainer 来说,它被它的类型和参数完全确定了,因此编译器能够生成优化过的代码。在大多数实例中,这点能够实现。","category":"page"},{"location":"manual/performance-tips/","page":"性能建议","title":"性能建议","text":"尽管编译器现在可以将它的工作做得非常好,但是还是有你可能希望你的代码能够能够根据 a 的元素类型做不同的事情的时候。通常达成这个目的最好的方式是将你的具体操作 (here, foo) 打包到一个独立的函数中。","category":"page"},{"location":"manual/performance-tips/","page":"性能建议","title":"性能建议","text":"julia> function sumfoo(c::MySimpleContainer)\n s = 0\n for x in c.a\n s += foo(x)\n end\n s\n end\nsumfoo (generic function with 1 method)\n\njulia> foo(x::Integer) = x\nfoo (generic function with 1 method)\n\njulia> foo(x::AbstractFloat) = round(x)\nfoo (generic function with 2 methods)","category":"page"},{"location":"manual/performance-tips/","page":"性能建议","title":"性能建议","text":"这使事情变得简单,同时也允许编译器在所有情况下生成经过优化的代码。","category":"page"},{"location":"manual/performance-tips/","page":"性能建议","title":"性能建议","text":"但是,在某些情况下,你可能需要声明外部函数的不同版本,这可能是为了不同的元素类型,也可能是为了 MySimpleContainer 中的字段 a 所具有的不同 AbstractVector 类型。你可以这样做:","category":"page"},{"location":"manual/performance-tips/","page":"性能建议","title":"性能建议","text":"julia> function myfunc(c::MySimpleContainer{<:AbstractArray{<:Integer}})\n return c.a[1]+1\n end\nmyfunc (generic function with 1 method)\n\njulia> function myfunc(c::MySimpleContainer{<:AbstractArray{<:AbstractFloat}})\n return c.a[1]+2\n end\nmyfunc (generic function with 2 methods)\n\njulia> function myfunc(c::MySimpleContainer{Vector{T}}) where T <: Integer\n return c.a[1]+3\n end\nmyfunc (generic function with 3 methods)","category":"page"},{"location":"manual/performance-tips/","page":"性能建议","title":"性能建议","text":"julia> myfunc(MySimpleContainer(1:3))\n2\n\njulia> myfunc(MySimpleContainer(1.0:3))\n3.0\n\njulia> myfunc(MySimpleContainer([1:3;]))\n4","category":"page"},{"location":"manual/performance-tips/#对从无类型位置获取的值进行类型注释","page":"性能建议","title":"对从无类型位置获取的值进行类型注释","text":"","category":"section"},{"location":"manual/performance-tips/","page":"性能建议","title":"性能建议","text":"使用可能包含任何类型的值的数据结构(如类型为 Array{Any} 的数组)经常是很方便的。但是,如果你正在使用这些数据结构之一,并且恰巧知道某个元素的类型,那么让编译器也知道这一点会有所帮助:","category":"page"},{"location":"manual/performance-tips/","page":"性能建议","title":"性能建议","text":"function foo(a::Array{Any,1})\n x = a[1]::Int32\n b = x+1\n ...\nend","category":"page"},{"location":"manual/performance-tips/","page":"性能建议","title":"性能建议","text":"在这里,我们恰巧知道 a 的第一个元素是个 Int32。留下这样的注释还有另外的好处,它将在该值不是预期类型时引发运行时错误,而这可能会更早地捕获某些错误。","category":"page"},{"location":"manual/performance-tips/","page":"性能建议","title":"性能建议","text":"在没有确切知道 a[1] 的类型的情况下,x 可以通过 x = convert(Int32, a[1])::Int32 来声明。使用 convert 函数则允许 a[1] 是可转换为 Int32 的任何对象(比如 UInt8),从而通过放松类型限制来提高代码的通用性。请注意,convert 本身在此上下文中需要类型注释才能实现类型稳定性。这是因为除非该函数所有参数的类型都已知,否则编译器无法推导出该函数返回值的类型,即使其为 convert。","category":"page"},{"location":"manual/performance-tips/","page":"性能建议","title":"性能建议","text":"如果类型是抽象的或在运行时构造的,则类型注释不会增强(实际上可能会阻碍)性能。 这是因为编译器无法使用注解来特例化后续代码,并且类型检查本身需要时间。 例如,在代码中:","category":"page"},{"location":"manual/performance-tips/","page":"性能建议","title":"性能建议","text":"function nr(a, prec)\n ctype = prec == 32 ? Float32 : Float64\n b = Complex{ctype}(a)\n c = (b + 1.0f0)::Complex{ctype}\n abs(c)\nend","category":"page"},{"location":"manual/performance-tips/","page":"性能建议","title":"性能建议","text":"c 的注释会损害性能。要编写涉及在运行时构造类型的高性能代码,请使用下面讨论的 函数障碍技巧,并确保构造的类型出现在内核函数的参数类型中,以便内核操作由编译器合理地特例化。例如,在上面的代码片段中,一旦构建了 b,它就可以传递给另一个函数 k,即内核。 例如,如果函数 k 将 b 声明为类型为 Complex{T} 的参数,其中 T 是一个类型参数,那么出现在k的赋值语句中的类型注释的形式:","category":"page"},{"location":"manual/performance-tips/","page":"性能建议","title":"性能建议","text":"c = (b + 1.0f0)::Complex{T}","category":"page"},{"location":"manual/performance-tips/","page":"性能建议","title":"性能建议","text":"不会降低性能(但也不会有帮助),因为编译器可以在编译 k 时确定 c 的类型。","category":"page"},{"location":"manual/performance-tips/#Be-aware-of-when-Julia-avoids-specializing","page":"性能建议","title":"注意Julia何时避免特例化","text":"","category":"section"},{"location":"manual/performance-tips/","page":"性能建议","title":"性能建议","text":"作为一种启发式方法,Julia 避免在三种特定情况下自动特例化参数类型参数:Type、Function 和 Vararg。 当在方法中使用参数时,Julia 将始终特例化,但如果参数只是传递给另一个函数,则不会。 这通常在运行时没有性能影响并且提高编译器性能。 如果你发现它在你的案例中在运行时确实有性能影响,您可以通过向方法声明添加类型参数来触发特例化。这里有些例子:","category":"page"},{"location":"manual/performance-tips/","page":"性能建议","title":"性能建议","text":"这不会特例化:","category":"page"},{"location":"manual/performance-tips/","page":"性能建议","title":"性能建议","text":"function f_type(t) # or t::Type\n x = ones(t, 10)\n return sum(map(sin, x))\nend","category":"page"},{"location":"manual/performance-tips/","page":"性能建议","title":"性能建议","text":"但是这会:","category":"page"},{"location":"manual/performance-tips/","page":"性能建议","title":"性能建议","text":"function g_type(t::Type{T}) where T\n x = ones(T, 10)\n return sum(map(sin, x))\nend","category":"page"},{"location":"manual/performance-tips/","page":"性能建议","title":"性能建议","text":"这些不会特例化:","category":"page"},{"location":"manual/performance-tips/","page":"性能建议","title":"性能建议","text":"f_func(f, num) = ntuple(f, div(num, 2))\ng_func(g::Function, num) = ntuple(g, div(num, 2))","category":"page"},{"location":"manual/performance-tips/","page":"性能建议","title":"性能建议","text":"但是这会:","category":"page"},{"location":"manual/performance-tips/","page":"性能建议","title":"性能建议","text":"h_func(h::H, num) where {H} = ntuple(h, div(num, 2))","category":"page"},{"location":"manual/performance-tips/","page":"性能建议","title":"性能建议","text":"这不会特例化:","category":"page"},{"location":"manual/performance-tips/","page":"性能建议","title":"性能建议","text":"f_vararg(x::Int...) = tuple(x...)","category":"page"},{"location":"manual/performance-tips/","page":"性能建议","title":"性能建议","text":"但是这会:","category":"page"},{"location":"manual/performance-tips/","page":"性能建议","title":"性能建议","text":"g_vararg(x::Vararg{Int, N}) where {N} = tuple(x...)","category":"page"},{"location":"manual/performance-tips/","page":"性能建议","title":"性能建议","text":"只需要引入一个类型参数就可以强制特例化,即使其他类型不受约束。比如下面这个例子,它会特例化,并且在参数不是全部相同类型时很有用:","category":"page"},{"location":"manual/performance-tips/","page":"性能建议","title":"性能建议","text":"h_vararg(x::Vararg{Any, N}) where {N} = tuple(x...)","category":"page"},{"location":"manual/performance-tips/","page":"性能建议","title":"性能建议","text":"请注意, @code_typed 和你的朋友给你的始终是特例化的代码,即使 Julia 通常不会特例化该方法调用。如果要查看更改参数类型时是否生成特例化,则需要检查 method internals,即是否 (@which f(...)).specializations 包含相关参数的特例化。","category":"page"},{"location":"manual/performance-tips/#将函数拆分为多个定义","page":"性能建议","title":"将函数拆分为多个定义","text":"","category":"section"},{"location":"manual/performance-tips/","page":"性能建议","title":"性能建议","text":"将一个函数写成许多小的定义能让编译器直接调用最适合的代码,甚至能够直接将它内联。","category":"page"},{"location":"manual/performance-tips/","page":"性能建议","title":"性能建议","text":"这是一个真的该被写成许多小的定义的复合函数的例子:","category":"page"},{"location":"manual/performance-tips/","page":"性能建议","title":"性能建议","text":"using LinearAlgebra\n\nfunction mynorm(A)\n if isa(A, Vector)\n return sqrt(real(dot(A,A)))\n elseif isa(A, Matrix)\n return maximum(svdvals(A))\n else\n error(\"mynorm: invalid argument\")\n end\nend","category":"page"},{"location":"manual/performance-tips/","page":"性能建议","title":"性能建议","text":"这可以更简洁有效地写成:","category":"page"},{"location":"manual/performance-tips/","page":"性能建议","title":"性能建议","text":"norm(x::Vector) = sqrt(real(dot(x, x)))\nnorm(A::Matrix) = maximum(svdvals(A))","category":"page"},{"location":"manual/performance-tips/","page":"性能建议","title":"性能建议","text":"然而,应该注意的是,编译器会十分高效地优化掉编写得如同 mynorm 例子的代码中的死分支。","category":"page"},{"location":"manual/performance-tips/#编写「类型稳定的」函数","page":"性能建议","title":"编写「类型稳定的」函数","text":"","category":"section"},{"location":"manual/performance-tips/","page":"性能建议","title":"性能建议","text":"如果可能,确保函数总是返回相同类型的值是有好处的。考虑以下定义:","category":"page"},{"location":"manual/performance-tips/","page":"性能建议","title":"性能建议","text":"pos(x) = x < 0 ? 0 : x","category":"page"},{"location":"manual/performance-tips/","page":"性能建议","title":"性能建议","text":"虽然这看起来挺合法的,但问题是 0 是一个(Int 类型的)整数而 x 可能是任何类型。于是,根据 x 的值,此函数可能返回两种类型中任何一种的值。这种行为是允许的,并且在某些情况下可能是合乎需要的。但它可以很容易地以如下方式修复:","category":"page"},{"location":"manual/performance-tips/","page":"性能建议","title":"性能建议","text":"pos(x) = x < 0 ? zero(x) : x","category":"page"},{"location":"manual/performance-tips/","page":"性能建议","title":"性能建议","text":"还有 oneunit 函数,以及更通用的 oftype(x, y) 函数,它返回被转换为 x 的类型的 y。","category":"page"},{"location":"manual/performance-tips/#避免更改变量类型","page":"性能建议","title":"避免更改变量类型","text":"","category":"section"},{"location":"manual/performance-tips/","page":"性能建议","title":"性能建议","text":"类似的「类型稳定性」问题存在于在函数内重复使用的变量:","category":"page"},{"location":"manual/performance-tips/","page":"性能建议","title":"性能建议","text":"function foo()\n x = 1\n for i = 1:10\n x /= rand()\n end\n return x\nend","category":"page"},{"location":"manual/performance-tips/","page":"性能建议","title":"性能建议","text":"局部变量 x 一开始是整数,在一次循环迭代后变为浮点数(/ 运算符的结果)。这使得编译器更难优化循环体。有几种可能的解决方法:","category":"page"},{"location":"manual/performance-tips/","page":"性能建议","title":"性能建议","text":"使用 x = 1.0 初始化 x\n显式声明 x 的类型:x::Float64 = 1\n使用 x = oneunit(Float64) 进行显式的类型转换\n使用第一个循环迭代初始化,即 x = 1 / rand(),接着循环 for i = 2:10","category":"page"},{"location":"manual/performance-tips/#kernel-functions","page":"性能建议","title":"分离核心函数(又称为函数屏障)","text":"","category":"section"},{"location":"manual/performance-tips/","page":"性能建议","title":"性能建议","text":"许多函数遵循这一模式:先执行一些设置工作,再通过多次迭代来执行核心计算。如果可行,将这些核心计算放在单独的函数中是个好主意。例如,以下做作的函数返回一个数组,其类型是随机选择的。","category":"page"},{"location":"manual/performance-tips/","page":"性能建议","title":"性能建议","text":"julia> function strange_twos(n)\n a = Vector{rand(Bool) ? Int64 : Float64}(undef, n)\n for i = 1:n\n a[i] = 2\n end\n return a\n end;\n\njulia> strange_twos(3)\n3-element Vector{Int64}:\n 2\n 2\n 2","category":"page"},{"location":"manual/performance-tips/","page":"性能建议","title":"性能建议","text":"它应该这么写:","category":"page"},{"location":"manual/performance-tips/","page":"性能建议","title":"性能建议","text":"julia> function fill_twos!(a)\n for i = eachindex(a)\n a[i] = 2\n end\n end;\n\njulia> function strange_twos(n)\n a = Vector{rand(Bool) ? Int64 : Float64}(undef, n)\n fill_twos!(a)\n return a\n end;\n\njulia> strange_twos(3)\n3-element Vector{Int64}:\n 2\n 2\n 2","category":"page"},{"location":"manual/performance-tips/","page":"性能建议","title":"性能建议","text":"Julia 的编译器会在函数边界处针对参数类型特化代码,因此在原始的实现中循环期间无法得知 a 的类型(因为它是随即选择的)。于是,第二个版本通常更快,因为对于不同类型的 a,内层循环都可被重新编译为 fill_twos! 的一部分。","category":"page"},{"location":"manual/performance-tips/","page":"性能建议","title":"性能建议","text":"第二种形式通常是更好的风格,并且可以带来更多的代码的重复利用。","category":"page"},{"location":"manual/performance-tips/","page":"性能建议","title":"性能建议","text":"这个模式在 Julia Base 的几个地方中有使用。相关的例子,请参阅 abstractarray.jl 中的 vcat 和 hcat,或者 fill! 函数,我们可使用该函数而不是编写自己的 fill_twos!。","category":"page"},{"location":"manual/performance-tips/","page":"性能建议","title":"性能建议","text":"诸如 strange_twos 的函数会在处理具有不确定类型的数据时出现,例如从可能包含整数、浮点数、字符串或其它内容的输入文件中加载的数据。","category":"page"},{"location":"manual/performance-tips/#man-performance-value-type","page":"性能建议","title":"具有值作为参数的类型","text":"","category":"section"},{"location":"manual/performance-tips/","page":"性能建议","title":"性能建议","text":"比方说你想创建一个每个维度大小都是3的 N 维数组。这种数组可以这样创建:","category":"page"},{"location":"manual/performance-tips/","page":"性能建议","title":"性能建议","text":"julia> A = fill(5.0, (3, 3))\n3×3 Matrix{Float64}:\n 5.0 5.0 5.0\n 5.0 5.0 5.0\n 5.0 5.0 5.0","category":"page"},{"location":"manual/performance-tips/","page":"性能建议","title":"性能建议","text":"这个方法工作得很好:编译器可以识别出来 A 是一个 Array{Float64,2} 因为它知道填充值 (5.0::Float64) 的类型和维度 ((3, 3)::NTuple{2,Int}).","category":"page"},{"location":"manual/performance-tips/","page":"性能建议","title":"性能建议","text":"但是现在打比方说你想写一个函数,在任何一个维度下,它都创建一个 3×3×... 的数组;你可能会心动地写下一个函数","category":"page"},{"location":"manual/performance-tips/","page":"性能建议","title":"性能建议","text":"julia> function array3(fillval, N)\n fill(fillval, ntuple(d->3, N))\n end\narray3 (generic function with 1 method)\n\njulia> array3(5.0, 2)\n3×3 Matrix{Float64}:\n 5.0 5.0 5.0\n 5.0 5.0 5.0\n 5.0 5.0 5.0","category":"page"},{"location":"manual/performance-tips/","page":"性能建议","title":"性能建议","text":"这确实有用,但是(你可以自己使用 @code_warntype array3(5.0, 2) 来验证)问题是输出地类型不能被推断出来:参数 N 是一个 Int 类型的值,而且类型推断不会(也不能)提前预测它的值。这意味着使用这个函数的结果的代码在每次获取 A 时都不得不保守地检查其类型;这样的代码将会是非常缓慢的。","category":"page"},{"location":"manual/performance-tips/","page":"性能建议","title":"性能建议","text":"现在,解决此类问题的一种很好的方法是使用 函数障碍技巧。 但是,在某些情况下,你可能希望完全消除类型不稳定性。 在这种情况下,一种方法是将维度作为参数传递,例如通过 Val{T}()(参见 \"Value types\"):","category":"page"},{"location":"manual/performance-tips/","page":"性能建议","title":"性能建议","text":"julia> function array3(fillval, ::Val{N}) where N\n fill(fillval, ntuple(d->3, Val(N)))\n end\narray3 (generic function with 1 method)\n\njulia> array3(5.0, Val(2))\n3×3 Matrix{Float64}:\n 5.0 5.0 5.0\n 5.0 5.0 5.0\n 5.0 5.0 5.0","category":"page"},{"location":"manual/performance-tips/","page":"性能建议","title":"性能建议","text":"Julia 有一个特别版本的 ntuple,它接受一个 Val{::Int} 实例作为第二个参数; 通过将 N 作为类型参数传递,你可以让编译器知道它的“值”。 因此,这个版本的 array3 允许编译器预测返回类型。","category":"page"},{"location":"manual/performance-tips/","page":"性能建议","title":"性能建议","text":"然而,使用这些技术可能非常微妙。 例如,如果你从这样的函数中调用 array3 将没有任何帮助:","category":"page"},{"location":"manual/performance-tips/","page":"性能建议","title":"性能建议","text":"function call_array3(fillval, n)\n A = array3(fillval, Val(n))\nend","category":"page"},{"location":"manual/performance-tips/","page":"性能建议","title":"性能建议","text":"在这里,你又一次创造了同样的问题:编译器无法猜测 n 是什么,所以它不知道 Val(n) 的 类型。 在许多情况下,尝试使用 Val 但不正确地使用很容易使性能变差。 (只有在有效地将 Val 与函数障碍技巧结合起来的情况下,为了使内核函数更有效,才应使用上述代码。)","category":"page"},{"location":"manual/performance-tips/","page":"性能建议","title":"性能建议","text":"一个正确使用 Val 的例子是这样的:","category":"page"},{"location":"manual/performance-tips/","page":"性能建议","title":"性能建议","text":"function filter3(A::AbstractArray{T,N}) where {T,N}\n kernel = array3(1, Val(N))\n filter(A, kernel)\nend","category":"page"},{"location":"manual/performance-tips/","page":"性能建议","title":"性能建议","text":"在此示例中,N 作为参数传递,因此编译器知道其“值”。 本质上,Val(T) 仅在 T 是硬编码/i字面量 (Val(3)) 或已在类型域中指定时才起作用。","category":"page"},{"location":"manual/performance-tips/#滥用多重派发的危险(也就是更多关于以值作为参数的类型)","page":"性能建议","title":"滥用多重派发的危险(也就是更多关于以值作为参数的类型)","text":"","category":"section"},{"location":"manual/performance-tips/","page":"性能建议","title":"性能建议","text":"一旦一个人理解了多重派发,就会有一个倾向,即过度使用它并尝试将其用于所有事情。 例如,您可能会想象使用它来存储信息,例如","category":"page"},{"location":"manual/performance-tips/","page":"性能建议","title":"性能建议","text":"struct Car{Make, Model}\n year::Int\n ...more fields...\nend","category":"page"},{"location":"manual/performance-tips/","page":"性能建议","title":"性能建议","text":"然后派发到像 Car{:Honda,:Accord}(year, args...) 的对象上。","category":"page"},{"location":"manual/performance-tips/","page":"性能建议","title":"性能建议","text":"当存在以下任一情况,这可能是值得做的:","category":"page"},{"location":"manual/performance-tips/","page":"性能建议","title":"性能建议","text":"你需要对每个 Car 进行 CPU 密集型处理,如果你在编译时知道 Make 和 Model,并且将使用的不同Make或Model的总数不太大,则效率会大大提高。\n你需要处理相同类型的 Car 的同类列表,因此可以将它们全部存储在一个数组{Car{:Honda,:Accord},N} 中。","category":"page"},{"location":"manual/performance-tips/","page":"性能建议","title":"性能建议","text":"当后者成立时,处理此类同型数组的函数可以高效地特例化:Julia 预先知道每个元素的类型(容器中的所有对象都具有相同的具体类型),因此当函数被编译时, Julia 可以“查找”正确的方法调用(不需要在运行时检查),从而产生有效的代码来处理整个列表。","category":"page"},{"location":"manual/performance-tips/","page":"性能建议","title":"性能建议","text":"当这些都不成立时,你很可能不会获得任何好处;更糟糕的是,由此产生的“类型组合爆炸”将适得其反。 如果 items[i+1] 与 item[i] 的类型不同,Julia 必须在运行时查找类型,在方法表中搜索适当的方法,决定(通过类型交集)哪一个匹配,确定它是否已经被 JIT 编译(如果没有,则执行),然后进行调用。 本质上,你是在要求完整的类型系统和 JIT 编译机制在你自己的代码中基本上执行相当于 switch 语句或字典查找的操作。","category":"page"},{"location":"manual/performance-tips/","page":"性能建议","title":"性能建议","text":"在邮件列表中 可以找到一些运行时基准比较 (1) 类型派发、(2) 字典查找和 (3) “switch”语句 ","category":"page"},{"location":"manual/performance-tips/","page":"性能建议","title":"性能建议","text":"也许比运行时影响更糟糕的是编译期影响:Julia 将为每个不同的 Car{Make, Model} 编译专门的函数; 如果你有成百上千个这样的类型,那么每个接受这样一个对象作为参数的函数(从你可能自己编写的自定义 get_year 函数,到 Julia Base 中的通用 push! 函数)都将成百上千个为它编译了的变体。 这些都会增加编译代码缓存的大小、内部方法列表的长度等。对值作为参数的过度热情很容易浪费大量资源。","category":"page"},{"location":"manual/performance-tips/#man-performance-column-major","page":"性能建议","title":"沿列按内存顺序访问数组","text":"","category":"section"},{"location":"manual/performance-tips/","page":"性能建议","title":"性能建议","text":"Julia 中的多维数组以列主序存储。这意味着数组一次堆叠一列。这可使用 vec 函数或语法 [:] 来验证,如下所示(请注意,数组的顺序是 [1 3 2 4],而不是 [1 2 3 4]):","category":"page"},{"location":"manual/performance-tips/","page":"性能建议","title":"性能建议","text":"julia> x = [1 2; 3 4]\n2×2 Matrix{Int64}:\n 1 2\n 3 4\n\njulia> x[:]\n4-element Vector{Int64}:\n 1\n 3\n 2\n 4","category":"page"},{"location":"manual/performance-tips/","page":"性能建议","title":"性能建议","text":"这种对数组进行排序的约定在许多语言中都很常见,例如 Fortran、Matlab 和 R(仅举几例)。 列优先排序的替代方法是行优先排序,在其它语言中,这是 C 和 Python (numpy) 采用的约定。 在遍历数组时,记住数组的顺序会对性能产生显着的影响。 要记住的一个经验法则是,对于列优先数组,第一个索引变化最快。 本质上,这意味着如果最内层的循环索引是第一个出现在切片表达式中的,则循环会更快。 请记住,使用 : 索引数组是一个隐式循环,它迭代访问特定维度内的所有元素; 例如,提取列比提取行更快。","category":"page"},{"location":"manual/performance-tips/","page":"性能建议","title":"性能建议","text":"考虑以下人为示例。假设我们想编写一个接收 Vector 并返回方阵 Matrix 的函数,所返回方阵的行或列都用输入向量的副本填充。并假设用这些副本填充的是行还是列并不重要(也许可以很容易地相应调整剩余代码)。我们至少可以想到四种方式(除了建议的调用内置函数 repeat):","category":"page"},{"location":"manual/performance-tips/","page":"性能建议","title":"性能建议","text":"function copy_cols(x::Vector{T}) where T\n inds = axes(x, 1)\n out = similar(Array{T}, inds, inds)\n for i = inds\n out[:, i] = x\n end\n return out\nend\n\nfunction copy_rows(x::Vector{T}) where T\n inds = axes(x, 1)\n out = similar(Array{T}, inds, inds)\n for i = inds\n out[i, :] = x\n end\n return out\nend\n\nfunction copy_col_row(x::Vector{T}) where T\n inds = axes(x, 1)\n out = similar(Array{T}, inds, inds)\n for col = inds, row = inds\n out[row, col] = x[row]\n end\n return out\nend\n\nfunction copy_row_col(x::Vector{T}) where T\n inds = axes(x, 1)\n out = similar(Array{T}, inds, inds)\n for row = inds, col = inds\n out[row, col] = x[col]\n end\n return out\nend","category":"page"},{"location":"manual/performance-tips/","page":"性能建议","title":"性能建议","text":"现在,我们使用相同的 10000 乘 1 的随机输入向量来对这些函数计时。","category":"page"},{"location":"manual/performance-tips/","page":"性能建议","title":"性能建议","text":"julia> x = randn(10000);\n\njulia> fmt(f) = println(rpad(string(f)*\": \", 14, ' '), @elapsed f(x))\n\njulia> map(fmt, [copy_cols, copy_rows, copy_col_row, copy_row_col]);\ncopy_cols: 0.331706323\ncopy_rows: 1.799009911\ncopy_col_row: 0.415630047\ncopy_row_col: 1.721531501","category":"page"},{"location":"manual/performance-tips/","page":"性能建议","title":"性能建议","text":"请注意,copy_cols 比 copy_rows 快得多。这与预料的一致,因为 copy_cols 尊重 Matrix 基于列的内存布局。另外,copy_col_row 比 copy_row_col 快得多,因为它遵循我们的经验法则,即切片表达式中出现的第一个元素应该与最内层循环耦合。","category":"page"},{"location":"manual/performance-tips/#Pre-allocating-outputs","page":"性能建议","title":"输出预分配","text":"","category":"section"},{"location":"manual/performance-tips/","page":"性能建议","title":"性能建议","text":"如果函数返回 Array 或其它复杂类型,则可能需要分配内存。不幸的是,内存分配及其反面垃圾收集通常是很大的瓶颈。","category":"page"},{"location":"manual/performance-tips/","page":"性能建议","title":"性能建议","text":"有时,你可以通过预分配输出结果来避免在每个函数调用上分配内存的需要。作为一个简单的例子,比较","category":"page"},{"location":"manual/performance-tips/","page":"性能建议","title":"性能建议","text":"julia> function xinc(x)\n return [x, x+1, x+2]\n end;\n\njulia> function loopinc()\n y = 0\n for i = 1:10^7\n ret = xinc(i)\n y += ret[2]\n end\n return y\n end;","category":"page"},{"location":"manual/performance-tips/","page":"性能建议","title":"性能建议","text":"和","category":"page"},{"location":"manual/performance-tips/","page":"性能建议","title":"性能建议","text":"julia> function xinc!(ret::AbstractVector{T}, x::T) where T\n ret[1] = x\n ret[2] = x+1\n ret[3] = x+2\n nothing\n end;\n\njulia> function loopinc_prealloc()\n ret = Vector{Int}(undef, 3)\n y = 0\n for i = 1:10^7\n xinc!(ret, i)\n y += ret[2]\n end\n return y\n end;","category":"page"},{"location":"manual/performance-tips/","page":"性能建议","title":"性能建议","text":"计时结果:","category":"page"},{"location":"manual/performance-tips/","page":"性能建议","title":"性能建议","text":"julia> @time loopinc()\n 0.529894 seconds (40.00 M allocations: 1.490 GiB, 12.14% gc time)\n50000015000000\n\njulia> @time loopinc_prealloc()\n 0.030850 seconds (6 allocations: 288 bytes)\n50000015000000","category":"page"},{"location":"manual/performance-tips/","page":"性能建议","title":"性能建议","text":"预分配还有其它优点,例如允许调用者在算法中控制「输出」类型。在上述例子中,我们如果需要,可以传递 SubArray 而不是 Array。","category":"page"},{"location":"manual/performance-tips/","page":"性能建议","title":"性能建议","text":"极端情况下,预分配可能会使你的代码更丑陋,所以可能需要做性能测试和一些判断。但是,对于「向量化」(逐元素)函数,方便的语法 x .= f.(y) 可用于具有融合循环的 in-place 操作且无需临时数组(请参阅向量化函数的点语法)。","category":"page"},{"location":"manual/performance-tips/#点语法:融合向量化操作","page":"性能建议","title":"点语法:融合向量化操作","text":"","category":"section"},{"location":"manual/performance-tips/","page":"性能建议","title":"性能建议","text":"Julia 有特殊的点语法,它可以将任何标量函数转换为「向量化」函数调用,将任何运算符转换为「向量化」运算符,其具有的特殊性质是嵌套「点调用」是融合的:它们在语法层级被组合为单个循环,无需分配临时数组。如果你使用 .= 和类似的赋值运算符,则结果也可以 in-place 存储在预分配的数组(参见上文)。","category":"page"},{"location":"manual/performance-tips/","page":"性能建议","title":"性能建议","text":"在线性代数的上下文中,这意味着即使诸如 vector + vector 和 vector * scalar 之类的运算,使用 vector .+ vector 和 vector .* scalar 来替代也可能是有利的,因为生成的循环可与周围的计算融合。例如,考虑两个函数:","category":"page"},{"location":"manual/performance-tips/","page":"性能建议","title":"性能建议","text":"julia> f(x) = 3x.^2 + 4x + 7x.^3;\n\njulia> fdot(x) = @. 3x^2 + 4x + 7x^3 # equivalent to 3 .* x.^2 .+ 4 .* x .+ 7 .* x.^3;","category":"page"},{"location":"manual/performance-tips/","page":"性能建议","title":"性能建议","text":"f 和 fdot 都做相同的计算。但是,fdot(在 @. 宏的帮助下定义)在作用于数组时明显更快:","category":"page"},{"location":"manual/performance-tips/","page":"性能建议","title":"性能建议","text":"julia> x = rand(10^6);\n\njulia> @time f(x);\n 0.019049 seconds (16 allocations: 45.777 MiB, 18.59% gc time)\n\njulia> @time fdot(x);\n 0.002790 seconds (6 allocations: 7.630 MiB)\n\njulia> @time f.(x);\n 0.002626 seconds (8 allocations: 7.630 MiB)","category":"page"},{"location":"manual/performance-tips/","page":"性能建议","title":"性能建议","text":"也就是说,fdot(x) 的速度是 f(x) 的 10 倍,分配的内存是 f(x) 的 1/6,因为 f(x) 中的每个 * 和 + 操作都会分配一个新的临时数组并在单独的循环中执行。 (当然,如果你只做 f.(x) 那么在这个例子中它和 fdot(x) 一样快,但在许多情况下,只在表达式中写一些点比为每个向量化操作定义单独的函数更方便。)","category":"page"},{"location":"manual/performance-tips/#man-performance-views","page":"性能建议","title":"考虑对切片使用视图","text":"","category":"section"},{"location":"manual/performance-tips/","page":"性能建议","title":"性能建议","text":"在 Julia 中,像 array[1:5, :] 这样的数组“切片”表达式会创建该数据的副本(赋值的左侧除外,其中 array[1:5, :] = ... 原地对 array 的那一部分进行赋值)。 如果你在切片上执行许多操作,这对性能有好处,因为使用较小的连续副本比索引原始数组更有效。 另一方面,如果你只是对切片进行一些简单的操作,那么分配和复制操作的成本可能会很高。","category":"page"},{"location":"manual/performance-tips/","page":"性能建议","title":"性能建议","text":"另一种方法是创建数组的“视图”,它是一个数组对象(一个SubArray),它实际上就地引用了原始数组的数据,而不进行复制。(如果你写入视图,它也会修改原始数组的数据。)这可以通过调用 view 对单个切片完成,或者更简单地通过将整个表达式或代码块放入 @views 在该表达式前面。 例如:","category":"page"},{"location":"manual/performance-tips/","page":"性能建议","title":"性能建议","text":"julia> fcopy(x) = sum(x[2:end-1]);\n\njulia> @views fview(x) = sum(x[2:end-1]);\n\njulia> x = rand(10^6);\n\njulia> @time fcopy(x);\n 0.003051 seconds (3 allocations: 7.629 MB)\n\njulia> @time fview(x);\n 0.001020 seconds (1 allocation: 16 bytes)","category":"page"},{"location":"manual/performance-tips/","page":"性能建议","title":"性能建议","text":"请注意,该函数的 fview 版本提速了 3 倍且减少了内存分配。","category":"page"},{"location":"manual/performance-tips/#复制数据不总是坏的","page":"性能建议","title":"复制数据不总是坏的","text":"","category":"section"},{"location":"manual/performance-tips/","page":"性能建议","title":"性能建议","text":"数组被连续地存储在内存中,这使其可被 CPU 向量化,并且会由于缓存减少内存访问。这与建议以列序优先方式访问数组的原因相同(请参见上文)。由于不按顺序访问内存,无规律的访问方式和不连续的视图可能会大大减慢数组上的计算速度。","category":"page"},{"location":"manual/performance-tips/","page":"性能建议","title":"性能建议","text":"在对无规律访问的数据进行操作前,将其复制到连续的数组中可能带来巨大的加速,正如下例所示。其中,矩阵和向量在相乘前会访问其 800,000 个已被随机混洗的索引处的值。将视图复制到普通数组会加速乘法,即使考虑了复制操作的成本。","category":"page"},{"location":"manual/performance-tips/","page":"性能建议","title":"性能建议","text":"julia> using Random\n\njulia> x = randn(1_000_000);\n\njulia> inds = shuffle(1:1_000_000)[1:800000];\n\njulia> A = randn(50, 1_000_000);\n\njulia> xtmp = zeros(800_000);\n\njulia> Atmp = zeros(50, 800_000);\n\njulia> @time sum(view(A, :, inds) * view(x, inds))\n 0.412156 seconds (14 allocations: 960 bytes)\n-4256.759568345458\n\njulia> @time begin\n copyto!(xtmp, view(x, inds))\n copyto!(Atmp, view(A, :, inds))\n sum(Atmp * xtmp)\n end\n 0.285923 seconds (14 allocations: 960 bytes)\n-4256.759568345134","category":"page"},{"location":"manual/performance-tips/","page":"性能建议","title":"性能建议","text":"倘若副本本身的内存足够大,那么将视图复制到数组的成本可能远远超过在连续数组上执行矩阵乘法所带来的加速。","category":"page"},{"location":"manual/performance-tips/#使用-StaticArrays.jl-进行小型固定大小的向量/矩阵运算","page":"性能建议","title":"使用 StaticArrays.jl 进行小型固定大小的向量/矩阵运算","text":"","category":"section"},{"location":"manual/performance-tips/","page":"性能建议","title":"性能建议","text":"如果您的应用程序涉及许多固定大小的小(< 100 个元素)数组(即在执行之前已知大小),那么你可能需要考虑使用 [StaticArrays.jl 包](https://github.com/JuliaArrays/StaticArrays.jl)。 这个包允许你以一种避免不必要的堆分配的方式来表示这样的数组,并允许编译器为数组的大小特例化代码,例如,通过完全展开向量操作(消除循环)并将元素存储在 CPU 寄存器中。","category":"page"},{"location":"manual/performance-tips/","page":"性能建议","title":"性能建议","text":"例如,如果你正在使用 2d 几何图形进行计算,你可能会使用 2-分量向量进行许多计算。 通过使用 StaticArrays.jl 中的 SVector 类型,你可以在向量 v 和 w 上使用方便的向量符号和操作,例如 norm(3v - w),同时允许编译器将代码展开到最小,计算等效于@inbounds hypot(3v[1]-w[1], 3v[2]-w[2])。","category":"page"},{"location":"manual/performance-tips/#避免-I/0-中的字符串插值","page":"性能建议","title":"避免 I/0 中的字符串插值","text":"","category":"section"},{"location":"manual/performance-tips/","page":"性能建议","title":"性能建议","text":"将数据写入到文件(或其他 I/0 设备)中时,生成额外的中间字符串会带来开销。请不要写成这样:","category":"page"},{"location":"manual/performance-tips/","page":"性能建议","title":"性能建议","text":"println(file, \"$a $b\")","category":"page"},{"location":"manual/performance-tips/","page":"性能建议","title":"性能建议","text":"请写成这样:","category":"page"},{"location":"manual/performance-tips/","page":"性能建议","title":"性能建议","text":"println(file, a, \" \", b)","category":"page"},{"location":"manual/performance-tips/","page":"性能建议","title":"性能建议","text":"第一个版本的代码生成一个字符串,然后将其写入到文件中,而第二个版本直接将值写入到文件中。另请注意,在某些情况下,字符串插值可能更难阅读。请考虑:","category":"page"},{"location":"manual/performance-tips/","page":"性能建议","title":"性能建议","text":"println(file, \"$(f(a))$(f(b))\")","category":"page"},{"location":"manual/performance-tips/","page":"性能建议","title":"性能建议","text":"与:","category":"page"},{"location":"manual/performance-tips/","page":"性能建议","title":"性能建议","text":"println(file, f(a), f(b))","category":"page"},{"location":"manual/performance-tips/#并发执行时优化网络-I/O","page":"性能建议","title":"并发执行时优化网络 I/O","text":"","category":"section"},{"location":"manual/performance-tips/","page":"性能建议","title":"性能建议","text":"当并发地执行一个远程函数时:","category":"page"},{"location":"manual/performance-tips/","page":"性能建议","title":"性能建议","text":"using Distributed\n\nresponses = Vector{Any}(undef, nworkers())\n@sync begin\n for (idx, pid) in enumerate(workers())\n @async responses[idx] = remotecall_fetch(foo, pid, args...)\n end\nend","category":"page"},{"location":"manual/performance-tips/","page":"性能建议","title":"性能建议","text":"会快于:","category":"page"},{"location":"manual/performance-tips/","page":"性能建议","title":"性能建议","text":"using Distributed\n\nrefs = Vector{Any}(undef, nworkers())\nfor (idx, pid) in enumerate(workers())\n refs[idx] = @spawnat pid foo(args...)\nend\nresponses = [fetch(r) for r in refs]","category":"page"},{"location":"manual/performance-tips/","page":"性能建议","title":"性能建议","text":"第一种方式导致每个worker一次网络往返,而第二种方式是两次网络调用:一次 @spawnat 一次fetch (甚至是 wait)。 fetch 和wait 都是同步执行,会导致较差的性能。","category":"page"},{"location":"manual/performance-tips/#修复过期警告","page":"性能建议","title":"修复过期警告","text":"","category":"section"},{"location":"manual/performance-tips/","page":"性能建议","title":"性能建议","text":"过期的函数在内部会执行查找,以便仅打印一次相关警告。 这种额外查找可能会显著影响性能,因此应根据警告建议修复掉过期函数的所有使用。","category":"page"},{"location":"manual/performance-tips/#小技巧","page":"性能建议","title":"小技巧","text":"","category":"section"},{"location":"manual/performance-tips/","page":"性能建议","title":"性能建议","text":"有一些小的注意事项可能会帮助改善循环性能。","category":"page"},{"location":"manual/performance-tips/","page":"性能建议","title":"性能建议","text":"避免使用不必要的数组。比如,使用 x+y+z 而不是 sum([x,y,z])。\n对于复数 z,使用 abs2(z) 而不是 abs(z)^2。一般的, 对于复数参数,用 abs2 代替abs。\n对于直接截断的整除,使用 div(x,y) 而不是 trunc(x/y),使用fld(x,y) 而不是 floor(x/y),使用 cld(x,y) 而不是 ceil(x/y)。","category":"page"},{"location":"manual/performance-tips/#man-performance-annotations","page":"性能建议","title":"性能标注","text":"","category":"section"},{"location":"manual/performance-tips/","page":"性能建议","title":"性能建议","text":"有时,你可以通过承诺某些程序性质来启用更好的优化。","category":"page"},{"location":"manual/performance-tips/","page":"性能建议","title":"性能建议","text":"使用 @inbounds 来取消表达式中的数组边界检查。使用前请再三确定,如果下标越界,可能会发生崩溃或潜在的故障。\n使用 @fastmath 来允许对于实数是正确的、但是对于 IEEE 数字会导致差异的浮点数优化。使用时请多多小心,因为这可能改变数值结果。这对应于 clang 的 -ffast-math 选项。\n在 for 循环前编写 @simd 来承诺迭代是相互独立且可以重新排序的。请注意,在许多情况下,Julia 可以在没有 @simd 宏的情况下自动向量化代码;只有在这种转换原本是非法的情况下才有用,包括允许浮点数重新结合和忽略相互依赖的内存访问(@simd ivdep)等情况。此外,在断言 @simd 时要十分小心,因为错误地标注一个具有相互依赖的迭代的循环可能导致意外结果。尤其要注意的是,某些 AbstractArray 子类型的 setindex! 本质上依赖于迭代顺序。此功能是实验性的,在 Julia 未来的版本中可能会更改或消失。","category":"page"},{"location":"manual/performance-tips/","page":"性能建议","title":"性能建议","text":"如果 Array 使用非常规索引,那么使用 1:n 索引到 AbstractArray 的常见习惯用法是不安全的,如果关闭边界检查,可能会导致段错误。请改用LinearIndices(x) 或eachindex(x)(另请参阅具有自定义索引的数组)。","category":"page"},{"location":"manual/performance-tips/","page":"性能建议","title":"性能建议","text":"note: Note\n虽然 @simd 需要直接放在最内层 for 循环前面,但 @inbounds 和 @fastmath 都可作用于单个表达式或在嵌套代码块中出现的所有表达式,例如,可使用 @inbounds begin 或 @inbounds for ...。","category":"page"},{"location":"manual/performance-tips/","page":"性能建议","title":"性能建议","text":"下面是一个具有 @inbounds 和 @simd 标记的例子(我们这里使用 @noinline 来防止因优化器过于智能而破坏我们的基准测试):","category":"page"},{"location":"manual/performance-tips/","page":"性能建议","title":"性能建议","text":"@noinline function inner(x, y)\n s = zero(eltype(x))\n for i=eachindex(x)\n @inbounds s += x[i]*y[i]\n end\n return s\nend\n\n@noinline function innersimd(x, y)\n s = zero(eltype(x))\n @simd for i = eachindex(x)\n @inbounds s += x[i] * y[i]\n end\n return s\nend\n\nfunction timeit(n, reps)\n x = rand(Float32, n)\n y = rand(Float32, n)\n s = zero(Float64)\n time = @elapsed for j in 1:reps\n s += inner(x, y)\n end\n println(\"GFlop/sec = \", 2n*reps / time*1E-9)\n time = @elapsed for j in 1:reps\n s += innersimd(x, y)\n end\n println(\"GFlop/sec (SIMD) = \", 2n*reps / time*1E-9)\nend\n\ntimeit(1000, 1000)","category":"page"},{"location":"manual/performance-tips/","page":"性能建议","title":"性能建议","text":"在配备 2.4GHz Intel Core i5 处理器的计算机上,其结果为:","category":"page"},{"location":"manual/performance-tips/","page":"性能建议","title":"性能建议","text":"GFlop/sec = 1.9467069505224963\nGFlop/sec (SIMD) = 17.578554163920018","category":"page"},{"location":"manual/performance-tips/","page":"性能建议","title":"性能建议","text":"(GFlop/sec 用来测试性能,数值越大越好。)","category":"page"},{"location":"manual/performance-tips/","page":"性能建议","title":"性能建议","text":"下面是一个具有三种标记的例子。此程序首先计算一个一维数组的有限差分,然后计算结果的 L2 范数:","category":"page"},{"location":"manual/performance-tips/","page":"性能建议","title":"性能建议","text":"function init!(u::Vector)\n n = length(u)\n dx = 1.0 / (n-1)\n @fastmath @inbounds @simd for i in 1:n # 通过断言 `u` 是一个 `Vector`,我们可以假定它具有 1-based 索引\n u[i] = sin(2pi*dx*i)\n end\nend\n\nfunction deriv!(u::Vector, du)\n n = length(u)\n dx = 1.0 / (n-1)\n @fastmath @inbounds du[1] = (u[2] - u[1]) / dx\n @fastmath @inbounds @simd for i in 2:n-1\n du[i] = (u[i+1] - u[i-1]) / (2*dx)\n end\n @fastmath @inbounds du[n] = (u[n] - u[n-1]) / dx\nend\n\nfunction mynorm(u::Vector)\n n = length(u)\n T = eltype(u)\n s = zero(T)\n @fastmath @inbounds @simd for i in 1:n\n s += u[i]^2\n end\n @fastmath @inbounds return sqrt(s)\nend\n\nfunction main()\n n = 2000\n u = Vector{Float64}(undef, n)\n init!(u)\n du = similar(u)\n\n deriv!(u, du)\n nu = mynorm(du)\n\n @time for i in 1:10^6\n deriv!(u, du)\n nu = mynorm(du)\n end\n\n println(nu)\nend\n\nmain()","category":"page"},{"location":"manual/performance-tips/","page":"性能建议","title":"性能建议","text":"在配备 2.7 GHz Intel Core i7 处理器的计算机上,其结果为:","category":"page"},{"location":"manual/performance-tips/","page":"性能建议","title":"性能建议","text":"$ julia wave.jl;\n 1.207814709 seconds\n4.443986180758249\n\n$ julia --math-mode=ieee wave.jl;\n 4.487083643 seconds\n4.443986180758249","category":"page"},{"location":"manual/performance-tips/","page":"性能建议","title":"性能建议","text":"在这里,选项 --math-mode=ieee 禁用 @fastmath 宏,好让我们可以比较结果。","category":"page"},{"location":"manual/performance-tips/","page":"性能建议","title":"性能建议","text":"在这种情况下,@fastmath 加速了大约 3.7 倍。这非常大——通常来说,加速会更小。(在这个特定的例子中,基准测试的工作集足够小,可以放在该处理器的 L1 缓存中,因此内存访问延迟不起作用,计算时间主要由 CPU 使用率决定。在许多现实世界的程序中,情况并非如此。)此外,在这种情况下,此优化不会改变计算结果——通常来说,结果会略有不同。在某些情况下,尤其是数值不稳定的算法,计算结果可能会差很多。","category":"page"},{"location":"manual/performance-tips/","page":"性能建议","title":"性能建议","text":"标注 @fastmath 会重新排列浮点数表达式,例如更改求值顺序,或者假设某些特殊情况(如 inf、nan)不出现。在这种情况中(以及在这个特定的计算机上),主要区别是函数 deriv 中的表达式 1 / (2*dx) 会被提升出循环(即在循环外计算),就像编写了 idx = 1 / (2*dx),然后,在循环中,表达式 ... / (2*dx) 变为 ... * idx,后者计算起来快得多。当然,编译器实际上采用的优化以及由此产生的加速都在很大程度上取决于硬件。你可以使用 Julia 的 code_native 函数来检查所生成代码的更改。","category":"page"},{"location":"manual/performance-tips/","page":"性能建议","title":"性能建议","text":"请注意,@fastmath 也假设了在计算中不会出现 NaN,这可能导致意想不到的行为:","category":"page"},{"location":"manual/performance-tips/","page":"性能建议","title":"性能建议","text":"julia> f(x) = isnan(x);\n\njulia> f(NaN)\ntrue\n\njulia> f_fast(x) = @fastmath isnan(x);\n\njulia> f_fast(NaN)\nfalse","category":"page"},{"location":"manual/performance-tips/#将次正规数视为零","page":"性能建议","title":"将次正规数视为零","text":"","category":"section"},{"location":"manual/performance-tips/","page":"性能建议","title":"性能建议","text":"次正规数,以前称为 非正规数,在许多情况下都很有用,但会在某些硬件上造成性能损失。 调用 set_zero_subnormals(true) 授予浮点运算权限,将次正规输入或输出视为零,这可能会提高某些硬件的性能。 调用 set_zero_subnormals(false) 对次正规数强制执行严格的 IEEE 行为。","category":"page"},{"location":"manual/performance-tips/","page":"性能建议","title":"性能建议","text":"下面是一个示例,其中次正规数显着影响某些硬件的性能:","category":"page"},{"location":"manual/performance-tips/","page":"性能建议","title":"性能建议","text":"function timestep(b::Vector{T}, a::Vector{T}, Δt::T) where T\n @assert length(a)==length(b)\n n = length(b)\n b[1] = 1 # Boundary condition\n for i=2:n-1\n b[i] = a[i] + (a[i-1] - T(2)*a[i] + a[i+1]) * Δt\n end\n b[n] = 0 # Boundary condition\nend\n\nfunction heatflow(a::Vector{T}, nstep::Integer) where T\n b = similar(a)\n for t=1:div(nstep,2) # Assume nstep is even\n timestep(b,a,T(0.1))\n timestep(a,b,T(0.1))\n end\nend\n\nheatflow(zeros(Float32,10),2) # Force compilation\nfor trial=1:6\n a = zeros(Float32,1000)\n set_zero_subnormals(iseven(trial)) # Odd trials use strict IEEE arithmetic\n @time heatflow(a,1000)\nend","category":"page"},{"location":"manual/performance-tips/","page":"性能建议","title":"性能建议","text":"它的输出类似于","category":"page"},{"location":"manual/performance-tips/","page":"性能建议","title":"性能建议","text":" 0.002202 seconds (1 allocation: 4.063 KiB)\n 0.001502 seconds (1 allocation: 4.063 KiB)\n 0.002139 seconds (1 allocation: 4.063 KiB)\n 0.001454 seconds (1 allocation: 4.063 KiB)\n 0.002115 seconds (1 allocation: 4.063 KiB)\n 0.001455 seconds (1 allocation: 4.063 KiB)","category":"page"},{"location":"manual/performance-tips/","page":"性能建议","title":"性能建议","text":"注意,每个偶数迭代的速度明显更快。","category":"page"},{"location":"manual/performance-tips/","page":"性能建议","title":"性能建议","text":"这个例子产生了许多次正规数,因为a中的值变成了一个指数递减的曲线,随着时间的推移慢慢渐进趋于0。","category":"page"},{"location":"manual/performance-tips/","page":"性能建议","title":"性能建议","text":"应谨慎使用将次正规数视为零,因为这样做会破坏某些等式,例如 x-y == 0 意味着 x == y:","category":"page"},{"location":"manual/performance-tips/","page":"性能建议","title":"性能建议","text":"julia> x = 3f-38; y = 2f-38;\n\njulia> set_zero_subnormals(true); (x - y, x == y)\n(0.0f0, false)\n\njulia> set_zero_subnormals(false); (x - y, x == y)\n(1.0000001f-38, false)","category":"page"},{"location":"manual/performance-tips/","page":"性能建议","title":"性能建议","text":"在某些应用程序中,将次正规数归零的另一种方法是加入一点点噪音。 例如,不是用零初始化a,而是用以下方法初始化它:","category":"page"},{"location":"manual/performance-tips/","page":"性能建议","title":"性能建议","text":"a = rand(Float32,1000) * 1.f-9","category":"page"},{"location":"manual/performance-tips/#man-code-warntype","page":"性能建议","title":"@code_warntype","text":"","category":"section"},{"location":"manual/performance-tips/","page":"性能建议","title":"性能建议","text":"宏 @code_warntype(或其函数变体 code_warntype)有时可以帮助诊断类型相关的问题。这是一个例子:","category":"page"},{"location":"manual/performance-tips/","page":"性能建议","title":"性能建议","text":"julia> @noinline pos(x) = x < 0 ? 0 : x;\n\njulia> function f(x)\n y = pos(x)\n return sin(y*x + 1)\n end;\n\njulia> @code_warntype f(3.2)\nVariables\n #self#::Core.Const(f)\n x::Float64\n y::UNION{FLOAT64, INT64}\n\nBody::Float64\n1 ─ (y = Main.pos(x))\n│ %2 = (y * x)::Float64\n│ %3 = (%2 + 1)::Float64\n│ %4 = Main.sin(%3)::Float64\n└── return %4","category":"page"},{"location":"manual/performance-tips/","page":"性能建议","title":"性能建议","text":"理解 @code_warntype 的输出,就像理解它的同类工具 @code_lowered, @code_typed, @code_llvm 和 @code_native 一样需要一些练习。你的代码以在生成编译机器代码的过程中经过大量摘要的形式呈现。大多数表达式都由类型注释,由 ::T 表示(例如,其中 T 可能是 Float64)。 @code_warntype 最大的特点就是非具体类型用红色显示; 由于本文档是用Markdown 编写的,没有颜色,所以本文档中红色文字用大写表示。","category":"page"},{"location":"manual/performance-tips/","page":"性能建议","title":"性能建议","text":"在顶部,该函数类型推导后的返回类型显示为 Body::Float64。下一行以 Julia 的 SSA IR 形式表示了 f 的主体。被数字标记的方块表示代码中(通过 goto)跳转的目标。查看主体,你会看到首先调用了 pos,其返回值经类型推导为 Union 类型 UNION{FLOAT64, INT64} 并以大写字母显示,因为它是非具体类型。这意味着我们无法根据输入类型知道 pos 的确切返回类型。但是,无论 y 是 Float64 还是 Int64,y*x 的结果都是 Float64。最终的结果是 f(x::Float64) 在其输出中不会是类型不稳定的,即使有些中间计算是类型不稳定的。","category":"page"},{"location":"manual/performance-tips/","page":"性能建议","title":"性能建议","text":"如何使用这些信息取决于你。显然,最好将 pos 修改为类型稳定的:如果这样做,f 中的所有变量都是具体的,其性能将是最佳的。但是,在某些情况下,这种短暂的类型不稳定性可能无关紧要:例如,如果 pos 从不单独使用,那么 f 的输出(对于 Float64 输入)是类型稳定的这一事实将保护之后的代码免受类型不稳定性的传播影响。这与类型不稳定性难以或不可能修复的情况密切相关。在这些情况下,上面的建议(例如,添加类型注释并/或分解函数)是你控制类型不稳定性的「损害」的最佳工具。另请注意,即使是 Julia Base 也有类型不稳定的函数。例如,函数 findfirst 如果找到键则返回数组索引,如果没有找到键则返回 nothing,这是明显的类型不稳定性。为了更易于找到可能很重要的类型不稳定性,包含 missing 或 nothing 的 Union 会用黄色着重显示,而不是用红色。","category":"page"},{"location":"manual/performance-tips/","page":"性能建议","title":"性能建议","text":"以下示例可以帮助你解释被标记为包含非叶类型的表达式:","category":"page"},{"location":"manual/performance-tips/","page":"性能建议","title":"性能建议","text":"函数体以 Body::UNION{T1,T2}) 开头\n解释:函数具有不稳定返回类型\n建议:使返回值类型稳定,即使你必须对其进行类型注释\ninvoke Main.g(%%x::Int64)::UNION{FLOAT64, INT64}\n解释:调用类型不稳定的函数 g。\n建议:修改该函数,或在必要时对其返回值进行类型注释\ninvoke Base.getindex(%%x::Array{Any,1}, 1::Int64)::ANY\n解释:访问缺乏类型信息的数组的元素\n建议:使用具有更佳定义的类型的数组,或在必要时对访问的单个元素进行类型注释\nBase.getfield(%%x, :(:data))::ARRAY{FLOAT64,N} WHERE N\n解释:获取一个非叶子类型的字段。 在这种情况下,x 的类型,比如说 ArrayContainer,有一个字段 data::Array{T}。 但是 Array 也需要维度 N 作为具体类型。\n建议:使用类似于 Array{T,3} 或 Array{T,N} 的具体类型,其中的 N 现在是 ArrayContainer 的参数","category":"page"},{"location":"manual/performance-tips/#man-performance-captured","page":"性能建议","title":"被捕获变量的性能","text":"","category":"section"},{"location":"manual/performance-tips/","page":"性能建议","title":"性能建议","text":"请考虑以下定义内部函数的示例:","category":"page"},{"location":"manual/performance-tips/","page":"性能建议","title":"性能建议","text":"function abmult(r::Int)\n if r < 0\n r = -r\n end\n f = x -> x * r\n return f\nend","category":"page"},{"location":"manual/performance-tips/","page":"性能建议","title":"性能建议","text":"函数 abmult 返回一个函数 f,它将其参数乘以 r 的绝对值。赋值给 f 的函数称为「闭包」。内部函数还被语言用于 do 代码块和生成器表达式。","category":"page"},{"location":"manual/performance-tips/","page":"性能建议","title":"性能建议","text":"这种代码风格为语言带来了性能挑战。解析器在将其转换为较低级别的指令时,基本上通过将内部函数提取到单独的代码块来重新组织上述代码。「被捕获的」变量,比如 r,被内部函数共享,且包含它们的作用域会被提取到内部函数和外部函数皆可访问的堆分配「box」中,这是因为语言指定内部作用域中的 r 必须与外部作用域中的 r 相同,就算在外部作用域(或另一个内部函数)修改 r 后也需如此。","category":"page"},{"location":"manual/performance-tips/","page":"性能建议","title":"性能建议","text":"前一段的讨论中提到了「解析器」,也就是,包含 abmult 的模块被首次加载时发生的编译前期,而不是首次调用它的编译后期。解析器不「知道」Int 是固定类型,也不知道语句 r = -r 将一个 Int 转换为另一个 Int。类型推断的魔力在编译后期生效。","category":"page"},{"location":"manual/performance-tips/","page":"性能建议","title":"性能建议","text":"因此,解析器不知道 r 具有固定类型(Int)。一旦内部函数被创建,r 的值也不会改变(因此也不需要 box)。因此,解析器向包含具有抽象类型(比如 Any)的对象的 box 发出代码,这对于每次出现的 r 都需要运行时类型分派。这可以通过在上述函数中使用 @code_warntype 来验证。装箱和运行时的类型分派都有可能导致性能损失。","category":"page"},{"location":"manual/performance-tips/","page":"性能建议","title":"性能建议","text":"如果捕获的变量用于代码的性能关键部分,那么以下提示有助于确保它们的使用具有高效性。首先,如果已经知道被捕获的变量不会改变类型,则可以使用类型注释来显式声明类型(在变量上,而不是在右侧):","category":"page"},{"location":"manual/performance-tips/","page":"性能建议","title":"性能建议","text":"function abmult2(r0::Int)\n r::Int = r0\n if r < 0\n r = -r\n end\n f = x -> x * r\n return f\nend","category":"page"},{"location":"manual/performance-tips/","page":"性能建议","title":"性能建议","text":"类型注释部分恢复由于捕获而导致的丢失性能,因为解析器可以将具体类型与 box 中的对象相关联。更进一步,如果被捕获的变量不再需要 box(因为它不会在闭包创建后被重新分配),就可以用 let 代码块表示,如下所示。","category":"page"},{"location":"manual/performance-tips/","page":"性能建议","title":"性能建议","text":"function abmult3(r::Int)\n if r < 0\n r = -r\n end\n f = let r = r\n x -> x * r\n end\n return f\nend","category":"page"},{"location":"manual/performance-tips/","page":"性能建议","title":"性能建议","text":"let 代码块创建了一个新的变量 r,它的作用域只是内部函数。第二种技术在捕获变量存在时完全恢复了语言性能。请注意,这是编译器的一个快速发展的方面,未来的版本可能不需要依靠这种程度的程序员注释来获得性能。与此同时,一些用户提供的包(如 FastClosures)会自动插入像在 abmult3 中那样的 let 语句。","category":"page"},{"location":"manual/strings/#man-strings","page":"字符串","title":"字符串","text":"","category":"section"},{"location":"manual/strings/","page":"字符串","title":"字符串","text":"字符串是由有限个字符组成的序列。而字符在英文中一般包括字母 A,B, C 等、数字和常用的标点符号。这些字符由 ASCII 标准统一标准化并且与 0 到 127 范围内的整数一一对应。当然,还有很多非英文字符,包括 ASCII 字符在注音或其他方面的变体,例如西里尔字母和希腊字母,以及与 ASCII 和英文均完全无关的字母系统,包括阿拉伯语,中文, 希伯来语,印度语, 日本语, 和韩语。Unicode 标准对这些复杂的字符做了统一的定义,是一种大家普遍接受标准。 根据需求,写代码时可以忽略这种复杂性而只处理 ASCII 字符,也可针对可能出现的非 ASCII 文本而处理所有的字符或编码。Julia 可以简单高效地处理纯粹的 ASCII 文本以及 Unicode 文本。 甚至,在 Julia 中用 C 语言风格的代码来处理 ASCII 字符串,可以在不失性能和易读性的前提下达到预期效果。当遇到非 ASCII 文本时,Julia会优雅明确地提示错误信息而不是引入乱码。 这时,直接修改代码使其可以处理非 ASCII 数据即可。","category":"page"},{"location":"manual/strings/","page":"字符串","title":"字符串","text":"关于 Julia 的字符串类型有一些值得注意的高级特性:","category":"page"},{"location":"manual/strings/","page":"字符串","title":"字符串","text":"Julia 中用于字符串(和字符串字面量)的内置具体类型是 String。 它支持全部 Unicode 字符 通过 UTF-8 编码。(transcode 函数是 提供 Unicode 编码和其他编码转换的函数。)\n所有的字符串类型都是抽象类型 AbstractString 的子类型,而一些外部包定义了别的 AbstractString 子类型(例如为其它的编码定义的子类型)。若要定义需要字符串参数的函数,你应当声明此类型为 AbstractString 来让这函数接受任何字符串类型。\n类似 C 和 Java,但是和大多数动态语言不同的是,Julia 有优秀的表示单字符的类型,即 AbstractChar。Char 是 AbstractChar 的内置子类型,它能表示任何 Unicode 字符的 32 位原始类型(基于 UTF-8 编码)。\n如 Java 中那样,字符串不可改——任何 AbstractString 对象的值不可改变。 若要构造不同的字符串值,应当从其它字符串的部分构造一个新的字符串。\n从概念上讲,字符串是从索引到字符的部分函数:对于某些索引值,它不返回字符值,而是引发异常。这允许通过编码表示形式的字节索引来实现高效的字符串索引,而不是通过字符索引——它不能简单高效地实现可变宽度的 Unicode 字符串编码。","category":"page"},{"location":"manual/strings/#man-characters","page":"字符串","title":"字符","text":"","category":"section"},{"location":"manual/strings/","page":"字符串","title":"字符串","text":"Char 类型的值代表单个字符:它只是带有特殊文本表示法和适当算术行为的 32 位原始类型,不能转化为代表 Unicode 代码 的数值。(Julia 的包可能会定义别的 AbstractChar 子类型,比如当为了优化对其它 字符编码 的操作时)Char 类型的值以这样的方式输入和显示:","category":"page"},{"location":"manual/strings/","page":"字符串","title":"字符串","text":"julia> c = 'x'\n'x': ASCII/Unicode U+0078 (category Ll: Letter, lowercase)\n\njulia> typeof(c)\nChar","category":"page"},{"location":"manual/strings/","page":"字符串","title":"字符串","text":"你可以轻松地将 Char 转换为其对应的整数值,即 Unicode 代码:","category":"page"},{"location":"manual/strings/","page":"字符串","title":"字符串","text":"julia> c = Int('x')\n120\n\njulia> typeof(c)\nInt64","category":"page"},{"location":"manual/strings/","page":"字符串","title":"字符串","text":"在 32 位的计算机中,typeof(c) 将显示为 Int32。你可以轻松地将一个整数值转回 Char:","category":"page"},{"location":"manual/strings/","page":"字符串","title":"字符串","text":"julia> Char(120)\n'x': ASCII/Unicode U+0078 (category Ll: Letter, lowercase)","category":"page"},{"location":"manual/strings/","page":"字符串","title":"字符串","text":"并非所有的整数值都是有效的 Unicode 代码,但是为了性能,Char 的转化不会检查每个值是否有效。如果你想检查每个转换的值是否为有效值,请使用 isvalid 函数:","category":"page"},{"location":"manual/strings/","page":"字符串","title":"字符串","text":"julia> Char(0x110000)\n'\\U110000': Unicode U+110000 (category In: Invalid, too high)\n\njulia> isvalid(Char, 0x110000)\nfalse","category":"page"},{"location":"manual/strings/","page":"字符串","title":"字符串","text":"目前,有效的 Unicode 码点为,从 U+0000 至 U+D7FF,以及从 U+E000 至 U+10FFFF。 它们还未全部被赋予明确的含义,也还没必要能被程序识别;然而,所有的这些值都被认为是有效的 Unicode 字符。","category":"page"},{"location":"manual/strings/","page":"字符串","title":"字符串","text":"你可以在单引号中输入任何 Unicode 字符,通过使用 \\u 加上至多 4 个十六进制数字或者 \\U 加上至多 8 个十六进制数(最长的有效值也只需要 6 个):","category":"page"},{"location":"manual/strings/","page":"字符串","title":"字符串","text":"julia> '\\u0'\n'\\0': ASCII/Unicode U+0000 (category Cc: Other, control)\n\njulia> '\\u78'\n'x': ASCII/Unicode U+0078 (category Ll: Letter, lowercase)\n\njulia> '\\u2200'\n'∀': Unicode U+2200 (category Sm: Symbol, math)\n\njulia> '\\U10ffff'\n'\\U10ffff': Unicode U+10FFFF (category Cn: Other, not assigned)","category":"page"},{"location":"manual/strings/","page":"字符串","title":"字符串","text":"Julia 使用系统默认的区域和语言设置来确定,哪些字符可以被正确显示,哪些需要用 \\u 或 \\U 的转义来显示。除 Unicode 转义格式之外,还可以使用所有的传统 C 语言转义输入形式:","category":"page"},{"location":"manual/strings/","page":"字符串","title":"字符串","text":"julia> Int('\\0')\n0\n\njulia> Int('\\t')\n9\n\njulia> Int('\\n')\n10\n\njulia> Int('\\e')\n27\n\njulia> Int('\\x7f')\n127\n\njulia> Int('\\177')\n127","category":"page"},{"location":"manual/strings/","page":"字符串","title":"字符串","text":"你可以对 Char 的值进行比较和有限的算术运算:","category":"page"},{"location":"manual/strings/","page":"字符串","title":"字符串","text":"julia> 'A' < 'a'\ntrue\n\njulia> 'A' <= 'a' <= 'Z'\nfalse\n\njulia> 'A' <= 'X' <= 'Z'\ntrue\n\njulia> 'x' - 'a'\n23\n\njulia> 'A' + 1\n'B': ASCII/Unicode U+0042 (category Lu: Letter, uppercase)","category":"page"},{"location":"manual/strings/#字符串基础","page":"字符串","title":"字符串基础","text":"","category":"section"},{"location":"manual/strings/","page":"字符串","title":"字符串","text":"字符串字面量由双引号或三重双引号分隔:","category":"page"},{"location":"manual/strings/","page":"字符串","title":"字符串","text":"julia> str = \"Hello, world.\\n\"\n\"Hello, world.\\n\"\n\njulia> \"\"\"Contains \"quote\" characters\"\"\"\n\"Contains \\\"quote\\\" characters\"","category":"page"},{"location":"manual/strings/","page":"字符串","title":"字符串","text":"Long lines in strings can be broken up by preceding the newline with a backslash (\\):","category":"page"},{"location":"manual/strings/","page":"字符串","title":"字符串","text":"julia> \"This is a long \\\n line\"\n\"This is a long line\"","category":"page"},{"location":"manual/strings/","page":"字符串","title":"字符串","text":"如果要字符串中提取字符,可以对其进行索引:","category":"page"},{"location":"manual/strings/","page":"字符串","title":"字符串","text":"julia> str[begin]\n'H': ASCII/Unicode U+0048 (category Lu: Letter, uppercase)\n\njulia> str[1]\n'H': ASCII/Unicode U+0048 (category Lu: Letter, uppercase)\n\njulia> str[6]\n',': ASCII/Unicode U+002C (category Po: Punctuation, other)\n\njulia> str[end]\n'\\n': ASCII/Unicode U+000A (category Cc: Other, control)","category":"page"},{"location":"manual/strings/","page":"字符串","title":"字符串","text":"许多的 Julia 对象,包括字符串,都可以用整数进行索引。第一个元素的索引(字符串的第一个字符)由 firstindex(str) 返回,最后一个元素(字符)的索引由 lastindex(str) 返回。关键字 begin 和 end 可以在索引操作中使用,它们分别表示给定维度上的第一个和最后一个索引。字符串索引就像 Julia 中的大多数索引一样,是从 1 开始的:对于任何 AbstractString, firstindex 方法总是返回 1。但是,下面我们将会看到,对于一个字符串来说 lastindex(str) 和 length(str) 的结果不一定相同,因为 Unicode 字符可能由多个编码单元组成。","category":"page"},{"location":"manual/strings/","page":"字符串","title":"字符串","text":"你可以用 end 进行算术以及其它操作,就像一个普通值一样:","category":"page"},{"location":"manual/strings/","page":"字符串","title":"字符串","text":"julia> str[end-1]\n'.': ASCII/Unicode U+002E (category Po: Punctuation, other)\n\njulia> str[end÷2]\n' ': ASCII/Unicode U+0020 (category Zs: Separator, space)","category":"page"},{"location":"manual/strings/","page":"字符串","title":"字符串","text":"使用小于 begin (1) 或大于 end 的索引会引发错误:","category":"page"},{"location":"manual/strings/","page":"字符串","title":"字符串","text":"julia> str[begin-1]\nERROR: BoundsError: attempt to access 14-codeunit String at index [0]\n[...]\n\njulia> str[end+1]\nERROR: BoundsError: attempt to access 14-codeunit String at index [15]\n[...]","category":"page"},{"location":"manual/strings/","page":"字符串","title":"字符串","text":"你也可以用范围索引来提取子字符串:","category":"page"},{"location":"manual/strings/","page":"字符串","title":"字符串","text":"julia> str[4:9]\n\"lo, wo\"","category":"page"},{"location":"manual/strings/","page":"字符串","title":"字符串","text":"注意,表达式 str[k] 和 str[k:k] 不会给出相同的结果:","category":"page"},{"location":"manual/strings/","page":"字符串","title":"字符串","text":"julia> str[6]\n',': ASCII/Unicode U+002C (category Po: Punctuation, other)\n\njulia> str[6:6]\n\",\"","category":"page"},{"location":"manual/strings/","page":"字符串","title":"字符串","text":"前者是一个 Char 类型的单个字符,而后者是一个恰好只包含一个字符的字符串。在 Julia 中,这些是不同的。","category":"page"},{"location":"manual/strings/","page":"字符串","title":"字符串","text":"范围索引复制原始字符串的选定部分。此外,可以使用类型 SubString,将视图创建为字符串, 例如:","category":"page"},{"location":"manual/strings/","page":"字符串","title":"字符串","text":"julia> str = \"long string\"\n\"long string\"\n\njulia> substr = SubString(str, 1, 4)\n\"long\"\n\njulia> typeof(substr)\nSubString{String}","category":"page"},{"location":"manual/strings/","page":"字符串","title":"字符串","text":"几个标准函数,像 chop, chomp 或者 strip 都会返回一个 SubString。","category":"page"},{"location":"manual/strings/#Unicode-和-UTF-8","page":"字符串","title":"Unicode 和 UTF-8","text":"","category":"section"},{"location":"manual/strings/","page":"字符串","title":"字符串","text":"Julia 完全支持 Unicode 字符和字符串。如上所述,在字符字面量中,Unicode 代码可以用 Unicode \\u 和 \\U 转义序列表示,也可以用所有标准 C 转义序列表示。这些同样可以用来写字符串字面量:","category":"page"},{"location":"manual/strings/","page":"字符串","title":"字符串","text":"julia> s = \"\\u2200 x \\u2203 y\"\n\"∀ x ∃ y\"","category":"page"},{"location":"manual/strings/","page":"字符串","title":"字符串","text":"这些 Unicode 字符是作为转义还是特殊字符显示,取决于你终端的语言环境设置以及它对 Unicode 的支持。字符串字面量用 UTF-8 编码。UTF-8 是一种可变长度的编码,也就是说并非所有字符都以相同的字节数(code units)编码。在 UTF-8 中,ASCII 字符(小于 0x80(128) 的那些)如它们在 ASCII 中一样使用单字节编码;而 0x80 及以上的字符使用最多 4 个字节编码。","category":"page"},{"location":"manual/strings/","page":"字符串","title":"字符串","text":"在 Julia 中字符串索引指的是代码单元(对于 UTF-8 来说等同于字节/byte),固定宽度的构建块用于编码任意字符(code point)。这意味着并非每个索引到 UTF-8 字符串的字节都必须是一个字符的有效索引。如果在这种无效字节索引处索引字符串,将会报错:","category":"page"},{"location":"manual/strings/","page":"字符串","title":"字符串","text":"julia> s[1]\n'∀': Unicode U+2200 (category Sm: Symbol, math)\n\njulia> s[2]\nERROR: StringIndexError: invalid index [2], valid nearby indices [1]=>'∀', [4]=>' '\nStacktrace:\n[...]\n\njulia> s[3]\nERROR: StringIndexError: invalid index [3], valid nearby indices [1]=>'∀', [4]=>' '\nStacktrace:\n[...]\n\njulia> s[4]\n' ': ASCII/Unicode U+0020 (category Zs: Separator, space)","category":"page"},{"location":"manual/strings/","page":"字符串","title":"字符串","text":"在这种情况下,字符 ∀ 是一个三字节字符,因此索引 2 和 3 都是无效的,而下一个字符的索引是 4;这个接下来的有效索引可以用 nextind(s,1) 来计算,再接下来的用 nextind(s,4),依此类推。","category":"page"},{"location":"manual/strings/","page":"字符串","title":"字符串","text":"如果倒数第二个字符是多字节字符,由于 end 总是集合中最后一个有效索引,这时 end-1 将会是无效索引。","category":"page"},{"location":"manual/strings/","page":"字符串","title":"字符串","text":"julia> s[end-1]\n' ': ASCII/Unicode U+0020 (category Zs: Separator, space)\n\njulia> s[end-2]\nERROR: StringIndexError: invalid index [9], valid nearby indices [7]=>'∃', [10]=>' '\nStacktrace:\n[...]\n\njulia> s[prevind(s, end, 2)]\n'∃': Unicode U+2203 (category Sm: Symbol, math)","category":"page"},{"location":"manual/strings/","page":"字符串","title":"字符串","text":"第一种情况可以,因为最后一个字符 y 和空格都是一字节的字符,而 end-2 索引到中间的 ∃ 由多字节表示。正确的方法是使用 prevind(s, lastindex(s), 2),或者,如果你使用该值来索引s,则可以写为s[prevind(s, end, 2) ] , end 展开为 lastindex(s)。","category":"page"},{"location":"manual/strings/","page":"字符串","title":"字符串","text":"使用范围索引提取子字符串也需要有效的字节索引,不然就会抛出错误:  ","category":"page"},{"location":"manual/strings/","page":"字符串","title":"字符串","text":"julia> s[1:1]\n\"∀\"\n\njulia> s[1:2]\nERROR: StringIndexError: invalid index [2], valid nearby indices [1]=>'∀', [4]=>' '\nStacktrace:\n[...]\n\njulia> s[1:4]\n\"∀ \"","category":"page"},{"location":"manual/strings/","page":"字符串","title":"字符串","text":"由于可变长度的编码,字符串中的字符数(由 length(s) 给出)并不总是等于最后一个索引的数字。如果你从 1 到 lastindex(s) 迭代并索引到 s,未报错时返回的字符序列是包含字符串 s 的字符序列。所以,总是有 length(s) <= lastindex(s),这是因为字符串中的每个字符必须有它自己的索引。下面是对 s 的字符进行迭代的一个冗长而低效的方式:","category":"page"},{"location":"manual/strings/","page":"字符串","title":"字符串","text":"julia> for i = firstindex(s):lastindex(s)\n try\n println(s[i])\n catch\n # ignore the index error\n end\n end\n∀\n\nx\n\n∃\n\ny","category":"page"},{"location":"manual/strings/","page":"字符串","title":"字符串","text":"空行上面其实是有空格的。幸运的是,上面的笨拙写法不是对字符串中字符进行迭代所必须的——因为你只需把字符串本身用作迭代对象,而不需要额外处理:","category":"page"},{"location":"manual/strings/","page":"字符串","title":"字符串","text":"julia> for c in s\n println(c)\n end\n∀\n\nx\n\n∃\n\ny","category":"page"},{"location":"manual/strings/","page":"字符串","title":"字符串","text":"如果需要为字符串获取有效索引,可以使用 nextind 和 prevind 函数递增/递减到下一个/前一个有效索引,如前所述。你也可以使用 eachindex 函数迭代有效的字符索引:","category":"page"},{"location":"manual/strings/","page":"字符串","title":"字符串","text":"julia> collect(eachindex(s))\n7-element Vector{Int64}:\n 1\n 4\n 5\n 6\n 7\n 10\n 11","category":"page"},{"location":"manual/strings/","page":"字符串","title":"字符串","text":"要访问编码的原始代码单位(UTF-8 的字节),可以使用 codeunit(s,i)函数,其中索引 i 从 1 连续运行到 ncodeunits(s)。 codeunits(s) 函数返回一个 AbstractVector{UInt8} 包装器,允许您以数组的形式访问这些原始代码单元(字节)。","category":"page"},{"location":"manual/strings/","page":"字符串","title":"字符串","text":"Julia 中的字符串可以包含无效的 UTF-8 代码单元序列。这个惯例允许把任何字序列当作 String。在这种情形下的一个规则是,当从左到右解析代码单元序列时,字符由匹配下面开头位模式之一的最长的 8 位代码单元序列组成(每个 x 可以是 0 或者 1):","category":"page"},{"location":"manual/strings/","page":"字符串","title":"字符串","text":"0xxxxxxx;\n110xxxxx 10xxxxxx;\n1110xxxx 10xxxxxx 10xxxxxx;\n11110xxx 10xxxxxx 10xxxxxx 10xxxxxx;\n10xxxxxx;\n11111xxx.","category":"page"},{"location":"manual/strings/","page":"字符串","title":"字符串","text":"特别地,这意味着过长和过高的代码单元序列及其前缀将被视为单个无效字符,而不是多个无效字符。这个规则最好用一个例子来解释:","category":"page"},{"location":"manual/strings/","page":"字符串","title":"字符串","text":"julia> s = \"\\xc0\\xa0\\xe2\\x88\\xe2|\"\n\"\\xc0\\xa0\\xe2\\x88\\xe2|\"\n\njulia> foreach(display, s)\n'\\xc0\\xa0': [overlong] ASCII/Unicode U+0020 (category Zs: Separator, space)\n'\\xe2\\x88': Malformed UTF-8 (category Ma: Malformed, bad data)\n'\\xe2': Malformed UTF-8 (category Ma: Malformed, bad data)\n'|': ASCII/Unicode U+007C (category Sm: Symbol, math)\n\njulia> isvalid.(collect(s))\n4-element BitArray{1}:\n 0\n 0\n 0\n 1\n\njulia> s2 = \"\\xf7\\xbf\\xbf\\xbf\"\n\"\\U1fffff\"\n\njulia> foreach(display, s2)\n'\\U1fffff': Unicode U+1FFFFF (category In: Invalid, too high)","category":"page"},{"location":"manual/strings/","page":"字符串","title":"字符串","text":"我们可以看到字符串 s 中的前两个代码单元形成了一个过长的空格字符编码。这是无效的,但是在字符串中作为单个字符是可以接受的。接下来的两个代码单元形成了一个有效的 3 位 UTF-8 序列开头。然而,第五个代码单元 \\xe2 不是它的有效延续,所以代码单元 3 和 4 在这个字符串中也被解释为格式错误的字符。同理,由于 | 不是它的有效延续,代码单元 5 形成了一个格式错误的字符。最后字符串 s2 包含了一个太高的代码。","category":"page"},{"location":"manual/strings/","page":"字符串","title":"字符串","text":"Julia 默认使用 UTF-8 编码,对于新编码的支持可以通过包加上。例如,LegacyStrings.jl 包实现了 UTF16String 和 UTF32String 类型。关于其它编码的额外讨论以及如何实现对它们的支持暂时超过了这篇文档的讨论范围。UTF-8 编码相关问题的进一步讨论参见下面的字节数组字面量章节。transcode 函数可在各种 UTF-xx 编码之间转换,主要用于外部数据和包。","category":"page"},{"location":"manual/strings/#man-concatenation","page":"字符串","title":"拼接","text":"","category":"section"},{"location":"manual/strings/","page":"字符串","title":"字符串","text":"最常见最有用的字符串操作是级联:","category":"page"},{"location":"manual/strings/","page":"字符串","title":"字符串","text":"julia> greet = \"Hello\"\n\"Hello\"\n\njulia> whom = \"world\"\n\"world\"\n\njulia> string(greet, \", \", whom, \".\\n\")\n\"Hello, world.\\n\"","category":"page"},{"location":"manual/strings/","page":"字符串","title":"字符串","text":"意识到像对无效 UTF-8 字符进行级联这样的潜在危险情形是非常重要的。生成的字符串可能会包含和输入字符串不同的字符,并且其中字符的数目也可能少于被级联字符串中字符数目之和,例如:","category":"page"},{"location":"manual/strings/","page":"字符串","title":"字符串","text":"julia> a, b = \"\\xe2\\x88\", \"\\x80\"\n(\"\\xe2\\x88\", \"\\x80\")\n\njulia> c = a*b\n\"∀\"\n\njulia> collect.([a, b, c])\n3-element Array{Array{Char,1},1}:\n ['\\xe2\\x88']\n ['\\x80']\n ['∀']\n\njulia> length.([a, b, c])\n3-element Array{Int64,1}:\n 1\n 1\n 1","category":"page"},{"location":"manual/strings/","page":"字符串","title":"字符串","text":"这种情形只可能发生于无效 UTF-8 字符串上。对于有效 UTF-8 字符串,级联保留字符串中的所有字符和字符串的总长度。","category":"page"},{"location":"manual/strings/","page":"字符串","title":"字符串","text":"Julia 也提供 * 用于字符串级联:","category":"page"},{"location":"manual/strings/","page":"字符串","title":"字符串","text":"julia> greet * \", \" * whom * \".\\n\"\n\"Hello, world.\\n\"","category":"page"},{"location":"manual/strings/","page":"字符串","title":"字符串","text":"尽管对于提供 + 函数用于字符串拼接的语言使用者而言,* 似乎是一个令人惊讶的选择,但 * 的这种用法在数学中早有先例,尤其是在抽象代数中。","category":"page"},{"location":"manual/strings/","page":"字符串","title":"字符串","text":"在数学上,+ 通常表示可交换运算(commutative operation)——运算对象的顺序不重要。一个例子是矩阵加法:对于任何形状相同的矩阵 A 和 B,都有 A + B == B + A。与之相反,* 通常表示不可交换运算——运算对象的顺序很重要。例如,对于矩阵乘法,一般 A * B != B * A。同矩阵乘法类似,字符串拼接是不可交换的:greet * whom != whom * greet。在这一点上,对于插入字符串的拼接操作,* 是一个自然而然的选择,与它在数学中的用法一致。","category":"page"},{"location":"manual/strings/","page":"字符串","title":"字符串","text":"更确切地说,有限长度字符串集合 S 和字符串拼接操作 * 构成了一个自由幺半群 (S, *)。该集合的单位元是空字符串,\"\"。当一个自由幺半群不是交换的时,它的运算通常表示为 \\cdot,*,或者类似的符号,而非暗示交换性的 +。","category":"page"},{"location":"manual/strings/#string-interpolation","page":"字符串","title":"插值","text":"","category":"section"},{"location":"manual/strings/","page":"字符串","title":"字符串","text":"拼接构造字符串的方式有时有些麻烦。为了减少对于 string 的冗余调用或者重复地做乘法,Julia 允许像 Perl 中一样使用 $ 对字符串字面量进行插值:","category":"page"},{"location":"manual/strings/","page":"字符串","title":"字符串","text":"julia> \"$greet, $whom.\\n\"\n\"Hello, world.\\n\"","category":"page"},{"location":"manual/strings/","page":"字符串","title":"字符串","text":"这更易读更方便,而且等效于上面的字符串拼接——系统把这个显然一行的字符串字面量重写成带参数的字符串字面量拼接 string(greet, \", \", whom, \".\\n\")。","category":"page"},{"location":"manual/strings/","page":"字符串","title":"字符串","text":"在 $ 之后最短的完整表达式被视为插入其值于字符串中的表达式。因此,你可以用括号向字符串中插入任何表达式:","category":"page"},{"location":"manual/strings/","page":"字符串","title":"字符串","text":"julia> \"1 + 2 = $(1 + 2)\"\n\"1 + 2 = 3\"","category":"page"},{"location":"manual/strings/","page":"字符串","title":"字符串","text":"拼接和插值都调用 string 以转换对象为字符串形式。 然而,string 实际上仅仅返回了 print 的输出,因此,新的类型应该添加 print 或 show 方法,而不是 string 方法。","category":"page"},{"location":"manual/strings/","page":"字符串","title":"字符串","text":"多数非 AbstractString 对象被转换为和它们作为文本表达式输入的方式密切对应的字符串:","category":"page"},{"location":"manual/strings/","page":"字符串","title":"字符串","text":"julia> v = [1,2,3]\n3-element Vector{Int64}:\n 1\n 2\n 3\n\njulia> \"v: $v\"\n\"v: [1, 2, 3]\"","category":"page"},{"location":"manual/strings/","page":"字符串","title":"字符串","text":"string 是 AbstractString 和 AbstractChar 值的标识,所以它们作为自身被插入字符串,无需引用,无需转义:","category":"page"},{"location":"manual/strings/","page":"字符串","title":"字符串","text":"julia> c = 'x'\n'x': ASCII/Unicode U+0078 (category Ll: Letter, lowercase)\n\njulia> \"hi, $c\"\n\"hi, x\"","category":"page"},{"location":"manual/strings/","page":"字符串","title":"字符串","text":"若要在字符串字面量中包含文本 $,就用反斜杠转义:","category":"page"},{"location":"manual/strings/","page":"字符串","title":"字符串","text":"julia> print(\"I have \\$100 in my account.\\n\")\nI have $100 in my account.","category":"page"},{"location":"manual/strings/#三引号字符串字面量","page":"字符串","title":"三引号字符串字面量","text":"","category":"section"},{"location":"manual/strings/","page":"字符串","title":"字符串","text":"当使用三引号(\"\"\"...\"\"\")创建字符串时,它们有一些在创建更长文本块时可能用到的特殊行为。","category":"page"},{"location":"manual/strings/","page":"字符串","title":"字符串","text":"首先,三引号字符串也被反缩进到最小缩进线的水平。这在定义包含缩进的字符串时很有用。例如:","category":"page"},{"location":"manual/strings/","page":"字符串","title":"字符串","text":"julia> str = \"\"\"\n Hello,\n world.\n \"\"\"\n\" Hello,\\n world.\\n\"","category":"page"},{"location":"manual/strings/","page":"字符串","title":"字符串","text":"在这里,后三引号 \"\"\" 前面的最后一(空)行设置了缩进级别。","category":"page"},{"location":"manual/strings/","page":"字符串","title":"字符串","text":"反缩进级别被确定为所有行中空格或制表符的最大公共起始序列,不包括前三引号 \"\"\" 后面的一行以及只包含空格或制表符的行(总包含结尾 \"\"\" 的行)。那么对于所有不包括前三引号 \"\"\" 后面文本的行而言,公共起始序列就被移除了(包括只含空格和制表符而以此序列开始的行),例如:","category":"page"},{"location":"manual/strings/","page":"字符串","title":"字符串","text":"julia> \"\"\" This\n is\n a test\"\"\"\n\" This\\nis\\n a test\"","category":"page"},{"location":"manual/strings/","page":"字符串","title":"字符串","text":"接下来,如果前三引号 \"\"\" 后面紧跟换行符,那么换行符就从生成的字符串中被剥离。","category":"page"},{"location":"manual/strings/","page":"字符串","title":"字符串","text":"\"\"\"hello\"\"\"","category":"page"},{"location":"manual/strings/","page":"字符串","title":"字符串","text":"等价于","category":"page"},{"location":"manual/strings/","page":"字符串","title":"字符串","text":"\"\"\"\nhello\"\"\"","category":"page"},{"location":"manual/strings/","page":"字符串","title":"字符串","text":"但是","category":"page"},{"location":"manual/strings/","page":"字符串","title":"字符串","text":"\"\"\"\n\nhello\"\"\"","category":"page"},{"location":"manual/strings/","page":"字符串","title":"字符串","text":"将在开头包含一个文本换行符。","category":"page"},{"location":"manual/strings/","page":"字符串","title":"字符串","text":"换行符的移除是在反缩进之后进行的。例如:","category":"page"},{"location":"manual/strings/","page":"字符串","title":"字符串","text":"julia> \"\"\"\n Hello,\n world.\"\"\"\n\"Hello,\\nworld.\"","category":"page"},{"location":"manual/strings/","page":"字符串","title":"字符串","text":"如果使用反斜杠消除换行符,下一行的缩进也会被消除:","category":"page"},{"location":"manual/strings/","page":"字符串","title":"字符串","text":"julia> \"\"\"\n Averylong\\\n word\"\"\"\n\"Averylongword\"","category":"page"},{"location":"manual/strings/","page":"字符串","title":"字符串","text":"尾随空格保持不变。","category":"page"},{"location":"manual/strings/","page":"字符串","title":"字符串","text":"三引号字符串字面量可不带转义地包含 \" 符号。","category":"page"},{"location":"manual/strings/","page":"字符串","title":"字符串","text":"注意,无论是用单引号还是三引号,在文本字符串中换行符都会生成一个换行 (LF) 字符 \\n,即使你的编辑器使用回车组合符 \\r (CR) 或 CRLF 来结束行。为了在字符串中包含 CR,总是应该使用显式转义符 \\r;比如,可以输入文本字符串 \"a CRLF line ending\\r\\n\"。","category":"page"},{"location":"manual/strings/#常见操作","page":"字符串","title":"常见操作","text":"","category":"section"},{"location":"manual/strings/","page":"字符串","title":"字符串","text":"你可以使用标准的比较操作符按照字典顺序比较字符串:","category":"page"},{"location":"manual/strings/","page":"字符串","title":"字符串","text":"julia> \"abracadabra\" < \"xylophone\"\ntrue\n\njulia> \"abracadabra\" == \"xylophone\"\nfalse\n\njulia> \"Hello, world.\" != \"Goodbye, world.\"\ntrue\n\njulia> \"1 + 2 = 3\" == \"1 + 2 = $(1 + 2)\"\ntrue","category":"page"},{"location":"manual/strings/","page":"字符串","title":"字符串","text":"你可以使用 findfirst 与 findlast 函数搜索特定字符的索引:","category":"page"},{"location":"manual/strings/","page":"字符串","title":"字符串","text":"julia> findfirst(isequal('o'), \"xylophone\")\n4\n\njulia> findlast(isequal('o'), \"xylophone\")\n7\n\njulia> findfirst(isequal('z'), \"xylophone\")","category":"page"},{"location":"manual/strings/","page":"字符串","title":"字符串","text":"你可以带上第三个参数,用 findnext 与 findprev 函数来在给定偏移量处搜索字符:","category":"page"},{"location":"manual/strings/","page":"字符串","title":"字符串","text":"julia> findnext(isequal('o'), \"xylophone\", 1)\n4\n\njulia> findnext(isequal('o'), \"xylophone\", 5)\n7\n\njulia> findprev(isequal('o'), \"xylophone\", 5)\n4\n\njulia> findnext(isequal('o'), \"xylophone\", 8)","category":"page"},{"location":"manual/strings/","page":"字符串","title":"字符串","text":"你可以用 occursin 函数检查在字符串中某子字符串可否找到。","category":"page"},{"location":"manual/strings/","page":"字符串","title":"字符串","text":"julia> occursin(\"world\", \"Hello, world.\")\ntrue\n\njulia> occursin(\"o\", \"Xylophon\")\ntrue\n\njulia> occursin(\"a\", \"Xylophon\")\nfalse\n\njulia> occursin('o', \"Xylophon\")\ntrue","category":"page"},{"location":"manual/strings/","page":"字符串","title":"字符串","text":"最后那个例子表明 occursin 也可用于搜寻字符字面量。","category":"page"},{"location":"manual/strings/","page":"字符串","title":"字符串","text":"另外还有两个方便的字符串函数 repeat 和 join:","category":"page"},{"location":"manual/strings/","page":"字符串","title":"字符串","text":"julia> repeat(\".:Z:.\", 10)\n\".:Z:..:Z:..:Z:..:Z:..:Z:..:Z:..:Z:..:Z:..:Z:..:Z:.\"\n\njulia> join([\"apples\", \"bananas\", \"pineapples\"], \", \", \" and \")\n\"apples, bananas and pineapples\"","category":"page"},{"location":"manual/strings/","page":"字符串","title":"字符串","text":"其它有用的函数还包括:","category":"page"},{"location":"manual/strings/","page":"字符串","title":"字符串","text":"firstindex(str) 给出可用来索引到 str 的最小(字节)索引(对字符串来说这总是 1,对于别的容器来说却不一定如此)。\nlastindex(str) 给出可用来索引到 str 的最大(字节)索引。\nlength(str),str 中的字符个数。\nlength(str, i, j),str 中从 i 到 j 的有效字符索引个数。\nncodeunits(str),字符串中代码单元(码元)的数目。\ncodeunit(str, i) 给出在字符串 str 中索引为 i 的代码单元值。\nthisind(str, i),给定一个字符串的任意索引,查找索引点所在的首个索引。\nnextind(str, i, n=1) 查找在索引 i 之后第 n 个字符的开头。\nprevind(str, i, n=1) 查找在索引 i 之前第 n 个字符的开始。","category":"page"},{"location":"manual/strings/#non-standard-string-literals","page":"字符串","title":"非标准字符串字面量","text":"","category":"section"},{"location":"manual/strings/","page":"字符串","title":"字符串","text":"有时当你想构造字符串或者使用字符串语义,标准的字符串构造却不能很好的满足需求。Julia 为这种情形提供了非标准字符串字面量。非标准字符串字面量看似常规双引号字符串字面量,但却直接加上了标识符前缀因而并不那么像普通的字符串字面量。","category":"page"},{"location":"manual/strings/","page":"字符串","title":"字符串","text":"下面将提到,正则表达式,字节数组字面量 和 版本号字面量 都是非标准字符串字面量的例子。 更详细的文档见 元编程 章。","category":"page"},{"location":"manual/strings/#man-regex-literals","page":"字符串","title":"正则表达式","text":"","category":"section"},{"location":"manual/strings/","page":"字符串","title":"字符串","text":"Julia 具有与 Perl 兼容的正则表达式 (regexes),就像 PCRE 包所提供的那样,详细信息参见 PCRE 的语法说明。 正则表达式以两种方式和字符串相关:一个显然的关联是,正则表达式被用于找到字符串中的正则模式;另一个关联是,正则表达式自身就是作为字符串输入,它们被解析到可用来高效搜索字符串中模式的状态机中。 在 Julia 中正则表达式的输入使用了前缀各类以 r 开头的标识符的非标准字符串字面量。最基本的不打开任何选项的正则表达式只用到了 r\"...\":","category":"page"},{"location":"manual/strings/","page":"字符串","title":"字符串","text":"julia> re = r\"^\\s*(?:#|$)\"\nr\"^\\s*(?:#|$)\"\n\njulia> typeof(re)\nRegex","category":"page"},{"location":"manual/strings/","page":"字符串","title":"字符串","text":"若要检查正则表达式是否匹配某字符串,就用 occursin:","category":"page"},{"location":"manual/strings/","page":"字符串","title":"字符串","text":"julia> occursin(r\"^\\s*(?:#|$)\", \"not a comment\")\nfalse\n\njulia> occursin(r\"^\\s*(?:#|$)\", \"# a comment\")\ntrue","category":"page"},{"location":"manual/strings/","page":"字符串","title":"字符串","text":"可以看到,occursin 只返回正确或错误,表明给定正则表达式是否在该字符串中出现。然而,通常我们不只想知道字符串是否匹配,更想了解它是如何匹配的。要捕获匹配的信息,可以改用 match 函数:","category":"page"},{"location":"manual/strings/","page":"字符串","title":"字符串","text":"julia> match(r\"^\\s*(?:#|$)\", \"not a comment\")\n\njulia> match(r\"^\\s*(?:#|$)\", \"# a comment\")\nRegexMatch(\"#\")","category":"page"},{"location":"manual/strings/","page":"字符串","title":"字符串","text":"若正则表达式与给定字符串不匹配,match 返回 nothing——在交互式提示框中不打印任何东西的特殊值。除了不打印,它是一个完全正常的值,这可以用程序来测试:","category":"page"},{"location":"manual/strings/","page":"字符串","title":"字符串","text":"m = match(r\"^\\s*(?:#|$)\", line)\nif m === nothing\n println(\"not a comment\")\nelse\n println(\"blank or comment\")\nend","category":"page"},{"location":"manual/strings/","page":"字符串","title":"字符串","text":"如果正则表达式匹配,match 的返回值是一个 RegexMatch 对象。这些对象记录了表达式是如何匹配的,包括该模式匹配的子字符串和任何可能被捕获的子字符串。上面的例子仅仅捕获了匹配的部分子字符串,但也许我们想要捕获的是注释字符后面的任何非空文本。我们可以这样做:","category":"page"},{"location":"manual/strings/","page":"字符串","title":"字符串","text":"julia> m = match(r\"^\\s*(?:#\\s*(.*?)\\s*$|$)\", \"# a comment \")\nRegexMatch(\"# a comment \", 1=\"a comment\")","category":"page"},{"location":"manual/strings/","page":"字符串","title":"字符串","text":"当调用 match 时,你可以选择指定开始搜索的索引。例如:","category":"page"},{"location":"manual/strings/","page":"字符串","title":"字符串","text":"julia> m = match(r\"[0-9]\",\"aaaa1aaaa2aaaa3\",1)\nRegexMatch(\"1\")\n\njulia> m = match(r\"[0-9]\",\"aaaa1aaaa2aaaa3\",6)\nRegexMatch(\"2\")\n\njulia> m = match(r\"[0-9]\",\"aaaa1aaaa2aaaa3\",11)\nRegexMatch(\"3\")","category":"page"},{"location":"manual/strings/","page":"字符串","title":"字符串","text":"你可以从 RegexMatch 对象中提取如下信息:","category":"page"},{"location":"manual/strings/","page":"字符串","title":"字符串","text":"匹配的整个子字符串:m.match\n作为字符串数组捕获的子字符串:m.captures\n整个匹配开始处的偏移:m.offset\n作为向量的捕获子字符串的偏移:m.offsets","category":"page"},{"location":"manual/strings/","page":"字符串","title":"字符串","text":"当捕获不匹配时,m.captures 在该处不再包含一个子字符串,而是 什么也不 包含;此外,m.offsets 的偏移量为 0(回想一下,Julia 的索引是从 1 开始的,因此字符串的零偏移是无效的)。下面是两个有些牵强的例子:","category":"page"},{"location":"manual/strings/","page":"字符串","title":"字符串","text":"julia> m = match(r\"(a|b)(c)?(d)\", \"acd\")\nRegexMatch(\"acd\", 1=\"a\", 2=\"c\", 3=\"d\")\n\njulia> m.match\n\"acd\"\n\njulia> m.captures\n3-element Vector{Union{Nothing, SubString{String}}}:\n \"a\"\n \"c\"\n \"d\"\n\njulia> m.offset\n1\n\njulia> m.offsets\n3-element Vector{Int64}:\n 1\n 2\n 3\n\njulia> m = match(r\"(a|b)(c)?(d)\", \"ad\")\nRegexMatch(\"ad\", 1=\"a\", 2=nothing, 3=\"d\")\n\njulia> m.match\n\"ad\"\n\njulia> m.captures\n3-element Vector{Union{Nothing, SubString{String}}}:\n \"a\"\n nothing\n \"d\"\n\njulia> m.offset\n1\n\njulia> m.offsets\n3-element Vector{Int64}:\n 1\n 0\n 2","category":"page"},{"location":"manual/strings/","page":"字符串","title":"字符串","text":"让捕获作为数组返回是很方便的,这样就可以用解构语法把它们和局域变量绑定起来。为了方便,RegexMatch 对象实现了传递到 captures 字段的迭代器方法,因此您可以直接解构匹配对象:","category":"page"},{"location":"manual/strings/","page":"字符串","title":"字符串","text":"julia> first, second, third = m; first\n\"a\"","category":"page"},{"location":"manual/strings/","page":"字符串","title":"字符串","text":"通过使用捕获组的编号或名称对 RegexMatch 对象进行索引,也可实现对捕获的访问:","category":"page"},{"location":"manual/strings/","page":"字符串","title":"字符串","text":"julia> m=match(r\"(?\\d+):(?\\d+)\",\"12:45\")\nRegexMatch(\"12:45\", hour=\"12\", minute=\"45\")\n\njulia> m[:minute]\n\"45\"\n\njulia> m[2]\n\"45\"","category":"page"},{"location":"manual/strings/","page":"字符串","title":"字符串","text":"使用 replace 时利用 \\n 引用第 n 个捕获组和给替换字符串加上 s 的前缀,可以实现替换字符串中对捕获的引用。捕获组 0 指的是整个匹配对象。可在替换中用 \\g 对命名捕获组进行引用。例如:","category":"page"},{"location":"manual/strings/","page":"字符串","title":"字符串","text":"julia> replace(\"first second\", r\"(\\w+) (?\\w+)\" => s\"\\g \\1\")\n\"second first\"","category":"page"},{"location":"manual/strings/","page":"字符串","title":"字符串","text":"为明确起见,编号捕获组也可用 \\g 进行引用,例如:","category":"page"},{"location":"manual/strings/","page":"字符串","title":"字符串","text":"julia> replace(\"a\", r\".\" => s\"\\g<0>1\")\n\"a1\"","category":"page"},{"location":"manual/strings/","page":"字符串","title":"字符串","text":"你可以在后双引号的后面加上 i, m, s 和 x 等标志对正则表达式进行修改。这些标志和 Perl 里面的含义一样,详见以下对 perlre 手册的摘录:","category":"page"},{"location":"manual/strings/","page":"字符串","title":"字符串","text":"i 不区分大小写的模式匹配。\n\n 若区域设置规则有效,相应映射中代码点小于 255 的部分取自当前区域设置,更大代码点的部分取自 Unicode 规则。然而,跨越 Unicode 规则(ords 255/256)和 非 Unicode 规则边界的匹配将失败。\n\nm 将字符串视为多行。也即更改 \"^\" 和 \"$\", 使其从匹配字符串的开头和结尾变为匹配字符串中任意一行的开头或结尾。\n\ns 将字符串视为单行。也即更改 \".\" 以匹配任何字符,即使是通常不能匹配的换行符。\n\n 像这样一起使用,r\"\"ms,它们让 \".\" 匹配任何字符,同时也支持分别在字符串中换行符的后面和前面用 \"^\" 和 \"$\" 进行匹配。\n\nx 令正则表达式解析器忽略多数既不是反斜杠也不属于字符类的空白。它可以用来把正则表达式分解成(略为)更易读的部分。和普通代码中一样,`#` 字符也被当作引入注释的元字符。","category":"page"},{"location":"manual/strings/","page":"字符串","title":"字符串","text":"例如,下面的正则表达式已打开所有三个标志:","category":"page"},{"location":"manual/strings/","page":"字符串","title":"字符串","text":"julia> r\"a+.*b+.*?d$\"ism\nr\"a+.*b+.*?d$\"ims\n\njulia> match(r\"a+.*b+.*?d$\"ism, \"Goodbye,\\nOh, angry,\\nBad world\\n\")\nRegexMatch(\"angry,\\nBad world\")","category":"page"},{"location":"manual/strings/","page":"字符串","title":"字符串","text":"r\"...\" 文本的构造没有插值和转义(除了引号 \" 仍然需要转义)。下面例子展示了它和标准字符串字面量之间的差别:","category":"page"},{"location":"manual/strings/","page":"字符串","title":"字符串","text":"julia> x = 10\n10\n\njulia> r\"$x\"\nr\"$x\"\n\njulia> \"$x\"\n\"10\"\n\njulia> r\"\\x\"\nr\"\\x\"\n\njulia> \"\\x\"\nERROR: syntax: invalid escape sequence","category":"page"},{"location":"manual/strings/","page":"字符串","title":"字符串","text":"Julia 也支持 r\"\"\"...\"\"\" 形式的三引号正则表达式字符串(或许便于处理包含引号和换行符的正则表达式)。","category":"page"},{"location":"manual/strings/","page":"字符串","title":"字符串","text":"Regex() 构造函数可以用于以编程方式创建合法的正则表达式字符串。这允许在构造正则表达式字符串时使用字符串变量的内容和其他字符串操作。上面的任何正则表达式代码可以在 Regex() 的单字符串参数中使用。下面是一些例子:","category":"page"},{"location":"manual/strings/","page":"字符串","title":"字符串","text":"julia> using Dates\n\njulia> d = Date(1962,7,10)\n1962-07-10\n\njulia> regex_d = Regex(\"Day \" * string(day(d)))\nr\"Day 10\"\n\njulia> match(regex_d, \"It happened on Day 10\")\nRegexMatch(\"Day 10\")\n\njulia> name = \"Jon\"\n\"Jon\"\n\njulia> regex_name = Regex(\"[\\\"( ]\\\\Q$name\\\\E[\\\") ]\") # interpolate value of name\nr\"[\\\"( ]\\QJon\\E[\\\") ]\"\n\njulia> match(regex_name, \" Jon \")\nRegexMatch(\" Jon \")\n\njulia> match(regex_name, \"[Jon]\") === nothing\ntrue","category":"page"},{"location":"manual/strings/","page":"字符串","title":"字符串","text":"注意 \\Q...\\E 转义序列的使用。 \\Q 和 \\E 之间的所有字符都被解释为字符字面量(在字符串插值之后)。在插入可能是恶意的用户输入时,此转义序列非常有用。","category":"page"},{"location":"manual/strings/#man-byte-array-literals","page":"字符串","title":"字节数组字面量","text":"","category":"section"},{"location":"manual/strings/","page":"字符串","title":"字符串","text":"另一个有用的非标准字符串字面量是字节数组字面量:b\"...\"。这种形式使你能够用字符串表示法来表达只读字面量字节数组,也即 UInt8 值的数组。字节数组字面量的规则如下:","category":"page"},{"location":"manual/strings/","page":"字符串","title":"字符串","text":"ASCII 字符和 ASCII 转义生成单个字节。\n\\x 和八进制转义序列生成与转义值对应的字节。\nUnicode 转义序列生成编码 UTF-8 中该代码点的字节序列。","category":"page"},{"location":"manual/strings/","page":"字符串","title":"字符串","text":"这些规则有一些重叠,这是因为 \\x 的行为和小于 0x80(128) 的八进制转义被前两个规则同时包括了;但这两个规则又是一致的。通过这些规则可以方便地同时使用 ASCII 字符,任意字节值,以及 UTF-8 序列来生成字节数组。下面是一个用到全部三个规则的例子:","category":"page"},{"location":"manual/strings/","page":"字符串","title":"字符串","text":"julia> b\"DATA\\xff\\u2200\"\n8-element Base.CodeUnits{UInt8, String}:\n 0x44\n 0x41\n 0x54\n 0x41\n 0xff\n 0xe2\n 0x88\n 0x80","category":"page"},{"location":"manual/strings/","page":"字符串","title":"字符串","text":"其中,ASCII 字符串 \"DATA\" 对应于字节 68, 65, 84, 65。\\xff 生成单个字节 255。Unicode 转义 \\u2200 在 UTF-8 中被编码为三个字节 226, 136, 128。注意生成的字节数组不对应任何有效 UTF-8 字符串。","category":"page"},{"location":"manual/strings/","page":"字符串","title":"字符串","text":"julia> isvalid(\"DATA\\xff\\u2200\")\nfalse","category":"page"},{"location":"manual/strings/","page":"字符串","title":"字符串","text":"正如前面所述,CodeUnits{UInt8,String} 类型的行为类似于只读 UInt8 数组。如果需要标准数组,你可使用 Vector{UInt8} 进行转换。","category":"page"},{"location":"manual/strings/","page":"字符串","title":"字符串","text":" ","category":"page"},{"location":"manual/strings/","page":"字符串","title":"字符串","text":"julia> x = b\"123\"\n3-element Base.CodeUnits{UInt8, String}:\n 0x31\n 0x32\n 0x33\n\njulia> x[1]\n0x31\n\njulia> x[1] = 0x32\nERROR: setindex! not defined for Base.CodeUnits{UInt8, String}\n[...]\n\njulia> Vector{UInt8}(x)\n3-element Vector{UInt8}:\n 0x31\n 0x32\n 0x33","category":"page"},{"location":"manual/strings/","page":"字符串","title":"字符串","text":"同时,要注意到 \\xff 和 \\uff 之间的显著差别:前面的转义序列编码为字节 255,而后者代表 代码 255,它在 UTF-8 中编码为两个字节:","category":"page"},{"location":"manual/strings/","page":"字符串","title":"字符串","text":"julia> b\"\\xff\"\n1-element Base.CodeUnits{UInt8, String}:\n 0xff\n\njulia> b\"\\uff\"\n2-element Base.CodeUnits{UInt8, String}:\n 0xc3\n 0xbf","category":"page"},{"location":"manual/strings/","page":"字符串","title":"字符串","text":"字符字面量也用到了相同的行为。","category":"page"},{"location":"manual/strings/","page":"字符串","title":"字符串","text":"对于小于 \\u80 的代码,每个代码的 UTF-8 编码恰好只是由相应 \\x 转义产生的单个字节,因此忽略两者的差别无伤大雅。然而,从 x80 到 \\xff 的转义比起从 u80 到 \\uff 的转义来,就有一个主要的差别:前者都只编码为一个字节,它没有形成任何有效 UTF-8 数据,除非它后面有非常特殊的连接字节;而后者则都代表 2 字节编码的 Unicode 代码。","category":"page"},{"location":"manual/strings/","page":"字符串","title":"字符串","text":"如果这些还是太难理解,试着读一下 \"每个软件开发人员绝对必须知道的最基础 Unicode 和字符集知识\"。它是一个优质的 Unicode 和 UTF-8 指南,或许能帮助解除一些这方面的疑惑。","category":"page"},{"location":"manual/strings/#man-version-number-literals","page":"字符串","title":"版本号字面量","text":"","category":"section"},{"location":"manual/strings/","page":"字符串","title":"字符串","text":"版本号很容易用 v\"...\" 形式的非标准字符串字面量表示。版本号字面量生成遵循语义版本规范的 VersionNumber 对象,因此由主、次、补丁号构成,后跟预发行 (pre-release) 和生成阿尔法数注释(build alpha-numeric)。例如,v\"0.2.1-rc1+win64\" 可分为主版本号 0,次版本号 2,补丁版本号 1,预发行版号 rc1,以及生成版本 win64。输入版本字面量时,除了主版本号以外所有内容都是可选的,因此 v\"0.2\" 等效于 v\"0.2.0\"(预发行号和生成注释为空),v\"2\" 等效于 v\"2.0.0\",等等。","category":"page"},{"location":"manual/strings/","page":"字符串","title":"字符串","text":"VersionNumber 对象在轻松正确地比较两个(或更多)版本时非常有用。例如,常数 VERSION 把 Julia 的版本号保留为一个 VersionNumber 对象,因此可以像下面这样用简单的声明定义一些特定版本的行为:","category":"page"},{"location":"manual/strings/","page":"字符串","title":"字符串","text":"if v\"0.2\" <= VERSION < v\"0.3-\"\n # 针对 0.2 发行版系列做些事情\nend","category":"page"},{"location":"manual/strings/","page":"字符串","title":"字符串","text":"注意在上例中用到了非标准版本号 v\"0.3-\",其中有尾随符 -:这个符号是 Julia 标准的扩展,它可以用来表明低于任何 0.3 发行版的版本,包括所有的预发行版。所以上例中代码只能在稳定版本 0.2 上运行,而不能在 v\"0.3.0-rc1\" 这样的版本上运行。为了支持非稳定(即预发行)的 0.2 版本,下限检查应像这样应该改为:v\"0.2-\" <= VERSION。","category":"page"},{"location":"manual/strings/","page":"字符串","title":"字符串","text":"另一个非标准版本规范扩展使得能够使用 + 来表示生成版本的上限,例如 VERSION > v\"0.2-rc1+\" 可以用来表示任意高于 0.2-rc1 和其任意生成版本的版本:它对 v\"0.2-rc1+win64\" 返回 false 而对 v\"0.2-rc2\" 返回 true。","category":"page"},{"location":"manual/strings/","page":"字符串","title":"字符串","text":"在比较中使用这样的特殊版本是个好办法(特别是,总是应该对高版本使用尾随 -,除非有好理由不这样),但它们不应该被用作任何内容的实际版本,因为它们在语义版本控制方案中无效。","category":"page"},{"location":"manual/strings/","page":"字符串","title":"字符串","text":"除了用于定义常数 VERSION,VersionNumber 对象在 Pkg 模块应用广泛,常用于指定软件包的版本及其依赖。","category":"page"},{"location":"manual/strings/#man-raw-string-literals","page":"字符串","title":"原始字符串字面量","text":"","category":"section"},{"location":"manual/strings/","page":"字符串","title":"字符串","text":"无插值和非转义的原始字符串可用 raw\"...\" 形式的非标准字符串字面量表示。原始字符串字面量生成普通的 String 对象,它无需插值和非转义地包含和输入完全一样的封闭式内容。这对于包含其他语言中使用 \" 或 \\\" 作为特殊字符的代码或标记的字符串很有用。","category":"page"},{"location":"manual/strings/","page":"字符串","title":"字符串","text":"例外的是,引号仍必须转义,例如 raw\"\\\"\" 等效于 \"\\\"\"。为了能够表达所有字符串,反斜杠也必须转义,不过只是当它刚好出现在引号前面时。","category":"page"},{"location":"manual/strings/","page":"字符串","title":"字符串","text":"julia> println(raw\"\\\\ \\\\\\\"\")\n\\\\ \\\"","category":"page"},{"location":"manual/strings/","page":"字符串","title":"字符串","text":"请注意,前两个反斜杠在输出中逐字显示,这是因为它们不是在引号前面。然而,接下来的一个反斜杠字符转义了后面的一个反斜杠;又由于这些反斜杠出现在引号前面,最后一个反斜杠转义了一个引号。","category":"page"},{"location":"base/base/#基本功能","page":"基本功能","title":"基本功能","text":"","category":"section"},{"location":"base/base/#介绍","page":"基本功能","title":"介绍","text":"","category":"section"},{"location":"base/base/","page":"基本功能","title":"基本功能","text":"Julia Base 中包含一系列适用于科学及数值计算的函数和宏,但也可以用于通用编程,其它功能则由 Julia 生态圈中的各种库来提供。函数按主题划分如下:","category":"page"},{"location":"base/base/","page":"基本功能","title":"基本功能","text":"一些通用的提示:","category":"page"},{"location":"base/base/","page":"基本功能","title":"基本功能","text":"可以通过 Import Module 导入想要使用的模块,并利用 Module.fn(x) 语句来实现对模块内函数的调用。\n此外,using Module 语句会将名为 Module 的模块中的所有可调函数引入当前的命名空间。\n按照约定,名字以感叹号(!)结尾的函数会改变其输入参数的内容。 一些函数同时拥有改变参数(例如 sort!)和不改变参数(sort)的版本","category":"page"},{"location":"base/base/","page":"基本功能","title":"基本功能","text":"The behaviors of Base and standard libraries are stable as defined in SemVer only if they are documented; i.e., included in the Julia documentation and not marked as unstable. See API FAQ for more information.","category":"page"},{"location":"base/base/#Getting-Around","page":"基本功能","title":"Getting Around","text":"","category":"section"},{"location":"base/base/","page":"基本功能","title":"基本功能","text":"Base.exit\nBase.atexit\nBase.isinteractive\nBase.summarysize\nBase.require\nBase.compilecache\nBase.__precompile__\nBase.include\nBase.MainInclude.include\nBase.include_string\nBase.include_dependency\nBase.which(::Any, ::Any)\nBase.methods\nBase.@show\nans\nBase.active_project","category":"page"},{"location":"base/base/#Base.exit","page":"基本功能","title":"Base.exit","text":"exit(code=0)\n\nStop the program with an exit code. The default exit code is zero, indicating that the program completed successfully. In an interactive session, exit() can be called with the keyboard shortcut ^D.\n\n\n\n\n\n","category":"function"},{"location":"base/base/#Base.atexit","page":"基本功能","title":"Base.atexit","text":"atexit(f)\n\nRegister a zero-argument function f() to be called at process exit. atexit() hooks are called in last in first out (LIFO) order and run before object finalizers.\n\nExit hooks are allowed to call exit(n), in which case Julia will exit with exit code n (instead of the original exit code). If more than one exit hook calls exit(n), then Julia will exit with the exit code corresponding to the last called exit hook that calls exit(n). (Because exit hooks are called in LIFO order, \"last called\" is equivalent to \"first registered\".)\n\n\n\n\n\n","category":"function"},{"location":"base/base/#Base.isinteractive","page":"基本功能","title":"Base.isinteractive","text":"isinteractive() -> Bool\n\nDetermine whether Julia is running an interactive session.\n\n\n\n\n\n","category":"function"},{"location":"base/base/#Base.summarysize","page":"基本功能","title":"Base.summarysize","text":"Base.summarysize(obj; exclude=Union{...}, chargeall=Union{...}) -> Int\n\nCompute the amount of memory, in bytes, used by all unique objects reachable from the argument.\n\nKeyword Arguments\n\nexclude: specifies the types of objects to exclude from the traversal.\nchargeall: specifies the types of objects to always charge the size of all of their fields, even if those fields would normally be excluded.\n\nSee also sizeof.\n\nExamples\n\njulia> Base.summarysize(1.0)\n8\n\njulia> Base.summarysize(Ref(rand(100)))\n848\n\njulia> sizeof(Ref(rand(100)))\n8\n\n\n\n\n\n","category":"function"},{"location":"base/base/#Base.require","page":"基本功能","title":"Base.require","text":"require(into::Module, module::Symbol)\n\nThis function is part of the implementation of using / import, if a module is not already defined in Main. It can also be called directly to force reloading a module, regardless of whether it has been loaded before (for example, when interactively developing libraries).\n\nLoads a source file, in the context of the Main module, on every active node, searching standard locations for files. require is considered a top-level operation, so it sets the current include path but does not use it to search for files (see help for include). This function is typically used to load library code, and is implicitly called by using to load packages.\n\nWhen searching for files, require first looks for package code in the global array LOAD_PATH. require is case-sensitive on all platforms, including those with case-insensitive filesystems like macOS and Windows.\n\nFor more details regarding code loading, see the manual sections on modules and parallel computing.\n\n\n\n\n\n","category":"function"},{"location":"base/base/#Base.compilecache","page":"基本功能","title":"Base.compilecache","text":"Base.compilecache(module::PkgId)\n\nCreates a precompiled cache file for a module and all of its dependencies. This can be used to reduce package load times. Cache files are stored in DEPOT_PATH[1]/compiled. See Module initialization and precompilation for important notes.\n\n\n\n\n\n","category":"function"},{"location":"base/base/#Base.__precompile__","page":"基本功能","title":"Base.__precompile__","text":"__precompile__(isprecompilable::Bool)\n\nSpecify whether the file calling this function is precompilable, defaulting to true. If a module or file is not safely precompilable, it should call __precompile__(false) in order to throw an error if Julia attempts to precompile it.\n\n\n\n\n\n","category":"function"},{"location":"base/base/#Base.include","page":"基本功能","title":"Base.include","text":"Base.include([mapexpr::Function,] [m::Module,] path::AbstractString)\n\nEvaluate the contents of the input source file in the global scope of module m. Every module (except those defined with baremodule) has its own definition of include omitting the m argument, which evaluates the file in that module. Returns the result of the last evaluated expression of the input file. During including, a task-local include path is set to the directory containing the file. Nested calls to include will search relative to that path. This function is typically used to load source interactively, or to combine files in packages that are broken into multiple source files.\n\nThe optional first argument mapexpr can be used to transform the included code before it is evaluated: for each parsed expression expr in path, the include function actually evaluates mapexpr(expr). If it is omitted, mapexpr defaults to identity.\n\ncompat: Julia 1.5\nJulia 1.5 is required for passing the mapexpr argument.\n\n\n\n\n\n","category":"function"},{"location":"base/base/#Base.MainInclude.include","page":"基本功能","title":"Base.MainInclude.include","text":"include([mapexpr::Function,] path::AbstractString)\n\nEvaluate the contents of the input source file in the global scope of the containing module. Every module (except those defined with baremodule) has its own definition of include, which evaluates the file in that module. Returns the result of the last evaluated expression of the input file. During including, a task-local include path is set to the directory containing the file. Nested calls to include will search relative to that path. This function is typically used to load source interactively, or to combine files in packages that are broken into multiple source files. The argument path is normalized using normpath which will resolve relative path tokens such as .. and convert / to the appropriate path separator.\n\nThe optional first argument mapexpr can be used to transform the included code before it is evaluated: for each parsed expression expr in path, the include function actually evaluates mapexpr(expr). If it is omitted, mapexpr defaults to identity.\n\nUse Base.include to evaluate a file into another module.\n\ncompat: Julia 1.5\nJulia 1.5 is required for passing the mapexpr argument.\n\n\n\n\n\n","category":"function"},{"location":"base/base/#Base.include_string","page":"基本功能","title":"Base.include_string","text":"include_string([mapexpr::Function,] m::Module, code::AbstractString, filename::AbstractString=\"string\")\n\nLike include, except reads code from the given string rather than from a file.\n\nThe optional first argument mapexpr can be used to transform the included code before it is evaluated: for each parsed expression expr in code, the include_string function actually evaluates mapexpr(expr). If it is omitted, mapexpr defaults to identity.\n\ncompat: Julia 1.5\nJulia 1.5 is required for passing the mapexpr argument.\n\n\n\n\n\n","category":"function"},{"location":"base/base/#Base.include_dependency","page":"基本功能","title":"Base.include_dependency","text":"include_dependency(path::AbstractString)\n\nIn a module, declare that the file specified by path (relative or absolute) is a dependency for precompilation; that is, the module will need to be recompiled if this file changes.\n\nThis is only needed if your module depends on a file that is not used via include. It has no effect outside of compilation.\n\n\n\n\n\n","category":"function"},{"location":"base/base/#Base.which-Tuple{Any, Any}","page":"基本功能","title":"Base.which","text":"which(f, types)\n\nReturns the method of f (a Method object) that would be called for arguments of the given types.\n\nIf types is an abstract type, then the method that would be called by invoke is returned.\n\nSee also: parentmodule, and @which and @edit in InteractiveUtils.\n\n\n\n\n\n","category":"method"},{"location":"base/base/#Base.methods","page":"基本功能","title":"Base.methods","text":"methods(f, [types], [module])\n\nReturn the method table for f.\n\nIf types is specified, return an array of methods whose types match. If module is specified, return an array of methods defined in that module. A list of modules can also be specified as an array.\n\ncompat: Julia 1.4\nAt least Julia 1.4 is required for specifying a module.\n\nSee also: which and @which.\n\n\n\n\n\n","category":"function"},{"location":"base/base/#Base.@show","page":"基本功能","title":"Base.@show","text":"@show exs...\n\nPrints one or more expressions, and their results, to stdout, and returns the last result.\n\nSee also: show, @info, println.\n\nExamples\n\njulia> x = @show 1+2\n1 + 2 = 3\n3\n\njulia> @show x^2 x/2;\nx ^ 2 = 9\nx / 2 = 1.5\n\n\n\n\n\n","category":"macro"},{"location":"base/base/#ans","page":"基本功能","title":"ans","text":"ans\n\nA variable referring to the last computed value, automatically set at the interactive prompt.\n\n\n\n\n\n","category":"keyword"},{"location":"base/base/#Base.active_project","page":"基本功能","title":"Base.active_project","text":"active_project()\n\nReturn the path of the active Project.toml file. See also Base.set_active_project.\n\n\n\n\n\n","category":"function"},{"location":"base/base/#Keywords","page":"基本功能","title":"Keywords","text":"","category":"section"},{"location":"base/base/","page":"基本功能","title":"基本功能","text":"This is the list of reserved keywords in 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. Those keywords are not allowed to be used as variable names.","category":"page"},{"location":"base/base/","page":"基本功能","title":"基本功能","text":"The following two-word sequences are reserved: abstract type, mutable struct, primitive type. However, you can create variables with names: abstract, mutable, primitive and type.","category":"page"},{"location":"base/base/","page":"基本功能","title":"基本功能","text":"Finally: where is parsed as an infix operator for writing parametric method and type definitions; in and isa are parsed as infix operators; and outer is parsed as a keyword when used to modify the scope of a variable in an iteration specification of a for loop or generator expression. Creation of variables named where, in, isa or outer is allowed though.","category":"page"},{"location":"base/base/","page":"基本功能","title":"基本功能","text":"module\nexport\nimport\nusing\nbaremodule\nfunction\nmacro\nreturn\ndo\nbegin\nend\nlet\nif\nfor\nwhile\nbreak\ncontinue\ntry\nfinally\nquote\nlocal\nglobal\nconst\nstruct\nmutable struct\nabstract type\nprimitive type\nwhere\n...\n;\n=\n?:","category":"page"},{"location":"base/base/#module","page":"基本功能","title":"module","text":"module\n\nmodule declares a Module, which is a separate global variable workspace. Within a module, you can control which names from other modules are visible (via importing), and specify which of your names are intended to be public (via exporting). Modules allow you to create top-level definitions without worrying about name conflicts when your code is used together with somebody else’s. See the manual section about modules for more details.\n\nExamples\n\nmodule Foo\nimport Base.show\nexport MyType, foo\n\nstruct MyType\n x\nend\n\nbar(x) = 2x\nfoo(a::MyType) = bar(a.x) + 1\nshow(io::IO, a::MyType) = print(io, \"MyType $(a.x)\")\nend\n\n\n\n\n\n","category":"keyword"},{"location":"base/base/#export","page":"基本功能","title":"export","text":"export\n\nexport is used within modules to tell Julia which functions should be made available to the user. For example: export foo makes the name foo available when using the module. See the manual section about modules for details.\n\n\n\n\n\n","category":"keyword"},{"location":"base/base/#import","page":"基本功能","title":"import","text":"import\n\nimport Foo will load the module or package Foo. Names from the imported Foo module can be accessed with dot syntax (e.g. Foo.foo to access the name foo). See the manual section about modules for details.\n\n\n\n\n\n","category":"keyword"},{"location":"base/base/#using","page":"基本功能","title":"using","text":"using\n\nusing Foo will load the module or package Foo and make its exported names available for direct use. Names can also be used via dot syntax (e.g. Foo.foo to access the name foo), whether they are exported or not. See the manual section about modules for details.\n\n\n\n\n\n","category":"keyword"},{"location":"base/base/#baremodule","page":"基本功能","title":"baremodule","text":"baremodule\n\nbaremodule declares a module that does not contain using Base or local definitions of eval and include. It does still import Core. In other words,\n\nmodule Mod\n\n...\n\nend\n\nis equivalent to\n\nbaremodule Mod\n\nusing Base\n\neval(x) = Core.eval(Mod, x)\ninclude(p) = Base.include(Mod, p)\n\n...\n\nend\n\n\n\n\n\n","category":"keyword"},{"location":"base/base/#function","page":"基本功能","title":"function","text":"function\n\nFunctions are defined with the function keyword:\n\nfunction add(a, b)\n return a + b\nend\n\nOr the short form notation:\n\nadd(a, b) = a + b\n\nThe use of the return keyword is exactly the same as in other languages, but is often optional. A function without an explicit return statement will return the last expression in the function body.\n\n\n\n\n\n","category":"keyword"},{"location":"base/base/#macro","page":"基本功能","title":"macro","text":"macro\n\nmacro defines a method for inserting generated code into a program. A macro maps a sequence of argument expressions to a returned expression, and the resulting expression is substituted directly into the program at the point where the macro is invoked. Macros are a way to run generated code without calling eval, since the generated code instead simply becomes part of the surrounding program. Macro arguments may include expressions, literal values, and symbols. Macros can be defined for variable number of arguments (varargs), but do not accept keyword arguments. Every macro also implicitly gets passed the arguments __source__, which contains the line number and file name the macro is called from, and __module__, which is the module the macro is expanded in.\n\nExamples\n\njulia> macro sayhello(name)\n return :( println(\"Hello, \", $name, \"!\") )\n end\n@sayhello (macro with 1 method)\n\njulia> @sayhello \"Charlie\"\nHello, Charlie!\n\njulia> macro saylots(x...)\n return :( println(\"Say: \", $(x...)) )\n end\n@saylots (macro with 1 method)\n\njulia> @saylots \"hey \" \"there \" \"friend\"\nSay: hey there friend\n\n\n\n\n\n","category":"keyword"},{"location":"base/base/#return","page":"基本功能","title":"return","text":"return\n\nreturn x causes the enclosing function to exit early, passing the given value x back to its caller. return by itself with no value is equivalent to return nothing (see nothing).\n\nfunction compare(a, b)\n a == b && return \"equal to\"\n a < b ? \"less than\" : \"greater than\"\nend\n\nIn general you can place a return statement anywhere within a function body, including within deeply nested loops or conditionals, but be careful with do blocks. For example:\n\nfunction test1(xs)\n for x in xs\n iseven(x) && return 2x\n end\nend\n\nfunction test2(xs)\n map(xs) do x\n iseven(x) && return 2x\n x\n end\nend\n\nIn the first example, the return breaks out of test1 as soon as it hits an even number, so test1([5,6,7]) returns 12.\n\nYou might expect the second example to behave the same way, but in fact the return there only breaks out of the inner function (inside the do block) and gives a value back to map. test2([5,6,7]) then returns [5,12,7].\n\nWhen used in a top-level expression (i.e. outside any function), return causes the entire current top-level expression to terminate early.\n\n\n\n\n\n","category":"keyword"},{"location":"base/base/#do","page":"基本功能","title":"do","text":"do\n\nCreate an anonymous function and pass it as the first argument to a function call. For example:\n\nmap(1:10) do x\n 2x\nend\n\nis equivalent to map(x->2x, 1:10).\n\nUse multiple arguments like so:\n\nmap(1:10, 11:20) do x, y\n x + y\nend\n\n\n\n\n\n","category":"keyword"},{"location":"base/base/#begin","page":"基本功能","title":"begin","text":"begin\n\nbegin...end denotes a block of code.\n\nbegin\n println(\"Hello, \")\n println(\"World!\")\nend\n\nUsually begin will not be necessary, since keywords such as function and let implicitly begin blocks of code. See also ;.\n\nbegin may also be used when indexing to represent the first index of a collection or the first index of a dimension of an array.\n\nExamples\n\njulia> A = [1 2; 3 4]\n2×2 Array{Int64,2}:\n 1 2\n 3 4\n\njulia> A[begin, :]\n2-element Array{Int64,1}:\n 1\n 2\n\n\n\n\n\n","category":"keyword"},{"location":"base/base/#end","page":"基本功能","title":"end","text":"end\n\nend marks the conclusion of a block of expressions, for example module, struct, mutable struct, begin, let, for etc.\n\nend may also be used when indexing to represent the last index of a collection or the last index of a dimension of an array.\n\nExamples\n\njulia> A = [1 2; 3 4]\n2×2 Array{Int64, 2}:\n 1 2\n 3 4\n\njulia> A[end, :]\n2-element Array{Int64, 1}:\n 3\n 4\n\n\n\n\n\n","category":"keyword"},{"location":"base/base/#let","page":"基本功能","title":"let","text":"let\n\nlet statements create a new hard scope block and introduce new variable bindings each time they run. Whereas assignments might reassign a new value to an existing value location, let always creates a new location. This difference is only detectable in the case of variables that outlive their scope via closures. The let syntax accepts a comma-separated series of assignments and variable names:\n\nlet var1 = value1, var2, var3 = value3\n code\nend\n\nThe assignments are evaluated in order, with each right-hand side evaluated in the scope before the new variable on the left-hand side has been introduced. Therefore it makes sense to write something like let x = x, since the two x variables are distinct and have separate storage.\n\n\n\n\n\n","category":"keyword"},{"location":"base/base/#if","page":"基本功能","title":"if","text":"if/elseif/else\n\nif/elseif/else performs conditional evaluation, which allows portions of code to be evaluated or not evaluated depending on the value of a boolean expression. Here is the anatomy of the if/elseif/else conditional syntax:\n\nif x < y\n println(\"x is less than y\")\nelseif x > y\n println(\"x is greater than y\")\nelse\n println(\"x is equal to y\")\nend\n\nIf the condition expression x < y is true, then the corresponding block is evaluated; otherwise the condition expression x > y is evaluated, and if it is true, the corresponding block is evaluated; if neither expression is true, the else block is evaluated. The elseif and else blocks are optional, and as many elseif blocks as desired can be used.\n\nIn contrast to some other languages conditions must be of type Bool. It does not suffice for conditions to be convertible to Bool.\n\njulia> if 1 end\nERROR: TypeError: non-boolean (Int64) used in boolean context\n\n\n\n\n\n","category":"keyword"},{"location":"base/base/#for","page":"基本功能","title":"for","text":"for\n\nfor loops repeatedly evaluate a block of statements while iterating over a sequence of values.\n\nExamples\n\njulia> for i in [1, 4, 0]\n println(i)\n end\n1\n4\n0\n\n\n\n\n\n","category":"keyword"},{"location":"base/base/#while","page":"基本功能","title":"while","text":"while\n\nwhile loops repeatedly evaluate a conditional expression, and continue evaluating the body of the while loop as long as the expression remains true. If the condition expression is false when the while loop is first reached, the body is never evaluated.\n\nExamples\n\njulia> i = 1\n1\n\njulia> while i < 5\n println(i)\n global i += 1\n end\n1\n2\n3\n4\n\n\n\n\n\n","category":"keyword"},{"location":"base/base/#break","page":"基本功能","title":"break","text":"break\n\nBreak out of a loop immediately.\n\nExamples\n\njulia> i = 0\n0\n\njulia> while true\n global i += 1\n i > 5 && break\n println(i)\n end\n1\n2\n3\n4\n5\n\n\n\n\n\n","category":"keyword"},{"location":"base/base/#continue","page":"基本功能","title":"continue","text":"continue\n\nSkip the rest of the current loop iteration.\n\nExamples\n\njulia> for i = 1:6\n iseven(i) && continue\n println(i)\n end\n1\n3\n5\n\n\n\n\n\n","category":"keyword"},{"location":"base/base/#try","page":"基本功能","title":"try","text":"try/catch\n\nA try/catch statement allows intercepting errors (exceptions) thrown by throw so that program execution can continue. For example, the following code attempts to write a file, but warns the user and proceeds instead of terminating execution if the file cannot be written:\n\ntry\n open(\"/danger\", \"w\") do f\n println(f, \"Hello\")\n end\ncatch\n @warn \"Could not write file.\"\nend\n\nor, when the file cannot be read into a variable:\n\nlines = try\n open(\"/danger\", \"r\") do f\n readlines(f)\n end\ncatch\n @warn \"File not found.\"\nend\n\nThe syntax catch e (where e is any variable) assigns the thrown exception object to the given variable within the catch block.\n\nThe power of the try/catch construct lies in the ability to unwind a deeply nested computation immediately to a much higher level in the stack of calling functions.\n\n\n\n\n\n","category":"keyword"},{"location":"base/base/#finally","page":"基本功能","title":"finally","text":"finally\n\nRun some code when a given block of code exits, regardless of how it exits. For example, here is how we can guarantee that an opened file is closed:\n\nf = open(\"file\")\ntry\n operate_on_file(f)\nfinally\n close(f)\nend\n\nWhen control leaves the try block (for example, due to a return, or just finishing normally), close(f) will be executed. If the try block exits due to an exception, the exception will continue propagating. A catch block may be combined with try and finally as well. In this case the finally block will run after catch has handled the error.\n\n\n\n\n\n","category":"keyword"},{"location":"base/base/#quote","page":"基本功能","title":"quote","text":"quote\n\nquote creates multiple expression objects in a block without using the explicit Expr constructor. For example:\n\nex = quote\n x = 1\n y = 2\n x + y\nend\n\nUnlike the other means of quoting, :( ... ), this form introduces QuoteNode elements to the expression tree, which must be considered when directly manipulating the tree. For other purposes, :( ... ) and quote .. end blocks are treated identically.\n\n\n\n\n\n","category":"keyword"},{"location":"base/base/#local","page":"基本功能","title":"local","text":"local\n\nlocal introduces a new local variable. See the manual section on variable scoping for more information.\n\nExamples\n\njulia> function foo(n)\n x = 0\n for i = 1:n\n local x # introduce a loop-local x\n x = i\n end\n x\n end\nfoo (generic function with 1 method)\n\njulia> foo(10)\n0\n\n\n\n\n\n","category":"keyword"},{"location":"base/base/#global","page":"基本功能","title":"global","text":"global\n\nglobal x makes x in the current scope and its inner scopes refer to the global variable of that name. See the manual section on variable scoping for more information.\n\nExamples\n\njulia> z = 3\n3\n\njulia> function foo()\n global z = 6 # use the z variable defined outside foo\n end\nfoo (generic function with 1 method)\n\njulia> foo()\n6\n\njulia> z\n6\n\n\n\n\n\n","category":"keyword"},{"location":"base/base/#const","page":"基本功能","title":"const","text":"const\n\nconst is used to declare global variables whose values will not change. In almost all code (and particularly performance sensitive code) global variables should be declared constant in this way.\n\nconst x = 5\n\nMultiple variables can be declared within a single const:\n\nconst y, z = 7, 11\n\nNote that const only applies to one = operation, therefore const x = y = 1 declares x to be constant but not y. On the other hand, const x = const y = 1 declares both x and y constant.\n\nNote that \"constant-ness\" does not extend into mutable containers; only the association between a variable and its value is constant. If x is an array or dictionary (for example) you can still modify, add, or remove elements.\n\nIn some cases changing the value of a const variable gives a warning instead of an error. However, this can produce unpredictable behavior or corrupt the state of your program, and so should be avoided. This feature is intended only for convenience during interactive use.\n\n\n\n\n\n","category":"keyword"},{"location":"base/base/#struct","page":"基本功能","title":"struct","text":"struct\n\nThe most commonly used kind of type in Julia is a struct, specified as a name and a set of fields.\n\nstruct Point\n x\n y\nend\n\nFields can have type restrictions, which may be parameterized:\n\nstruct Point{X}\n x::X\n y::Float64\nend\n\nA struct can also declare an abstract super type via <: syntax:\n\nstruct Point <: AbstractPoint\n x\n y\nend\n\nstructs are immutable by default; an instance of one of these types cannot be modified after construction. Use mutable struct instead to declare a type whose instances can be modified.\n\nSee the manual section on Composite Types for more details, such as how to define constructors.\n\n\n\n\n\n","category":"keyword"},{"location":"base/base/#mutable struct","page":"基本功能","title":"mutable struct","text":"mutable struct\n\nmutable struct is similar to struct, but additionally allows the fields of the type to be set after construction. See the manual section on Composite Types for more information.\n\n\n\n\n\n","category":"keyword"},{"location":"base/base/#abstract type","page":"基本功能","title":"abstract type","text":"abstract type\n\nabstract type declares a type that cannot be instantiated, and serves only as a node in the type graph, thereby describing sets of related concrete types: those concrete types which are their descendants. Abstract types form the conceptual hierarchy which makes Julia’s type system more than just a collection of object implementations. For example:\n\nabstract type Number end\nabstract type Real <: Number end\n\nNumber has no supertype, whereas Real is an abstract subtype of Number.\n\n\n\n\n\n","category":"keyword"},{"location":"base/base/#primitive type","page":"基本功能","title":"primitive type","text":"primitive type\n\nprimitive type declares a concrete type whose data consists only of a series of bits. Classic examples of primitive types are integers and floating-point values. Some example built-in primitive type declarations:\n\nprimitive type Char 32 end\nprimitive type Bool <: Integer 8 end\n\nThe number after the name indicates how many bits of storage the type requires. Currently, only sizes that are multiples of 8 bits are supported. The Bool declaration shows how a primitive type can be optionally declared to be a subtype of some supertype.\n\n\n\n\n\n","category":"keyword"},{"location":"base/base/#where","page":"基本功能","title":"where","text":"where\n\nThe where keyword creates a type that is an iterated union of other types, over all values of some variable. For example Vector{T} where T<:Real includes all Vectors where the element type is some kind of Real number.\n\nThe variable bound defaults to Any if it is omitted:\n\nVector{T} where T # short for `where T<:Any`\n\nVariables can also have lower bounds:\n\nVector{T} where T>:Int\nVector{T} where Int<:T<:Real\n\nThere is also a concise syntax for nested where expressions. For example, this:\n\nPair{T, S} where S<:Array{T} where T<:Number\n\ncan be shortened to:\n\nPair{T, S} where {T<:Number, S<:Array{T}}\n\nThis form is often found on method signatures.\n\nNote that in this form, the variables are listed outermost-first. This matches the order in which variables are substituted when a type is \"applied\" to parameter values using the syntax T{p1, p2, ...}.\n\n\n\n\n\n","category":"keyword"},{"location":"base/base/#...","page":"基本功能","title":"...","text":"...\n\nThe \"splat\" operator, ..., represents a sequence of arguments. ... can be used in function definitions, to indicate that the function accepts an arbitrary number of arguments. ... can also be used to apply a function to a sequence of arguments.\n\nExamples\n\njulia> add(xs...) = reduce(+, xs)\nadd (generic function with 1 method)\n\njulia> add(1, 2, 3, 4, 5)\n15\n\njulia> add([1, 2, 3]...)\n6\n\njulia> add(7, 1:100..., 1000:1100...)\n111107\n\n\n\n\n\n","category":"keyword"},{"location":"base/base/#;","page":"基本功能","title":";","text":";\n\n; has a similar role in Julia as in many C-like languages, and is used to delimit the end of the previous statement.\n\n; is not necessary at the end of a line, but can be used to separate statements on a single line or to join statements into a single expression.\n\nAdding ; at the end of a line in the REPL will suppress printing the result of that expression.\n\nIn function declarations, and optionally in calls, ; separates regular arguments from keywords.\n\nWhile constructing arrays, if the arguments inside the square brackets are separated by ; then their contents are vertically concatenated together.\n\nIn the standard REPL, typing ; on an empty line will switch to shell mode.\n\nExamples\n\njulia> function foo()\n x = \"Hello, \"; x *= \"World!\"\n return x\n end\nfoo (generic function with 1 method)\n\njulia> bar() = (x = \"Hello, Mars!\"; return x)\nbar (generic function with 1 method)\n\njulia> foo();\n\njulia> bar()\n\"Hello, Mars!\"\n\njulia> function plot(x, y; style=\"solid\", width=1, color=\"black\")\n ###\n end\n\njulia> [1 2; 3 4]\n2×2 Matrix{Int64}:\n 1 2\n 3 4\n\njulia> ; # upon typing ;, the prompt changes (in place) to: shell>\nshell> echo hello\nhello\n\n\n\n\n\n","category":"keyword"},{"location":"base/base/#=","page":"基本功能","title":"=","text":"=\n\n= is the assignment operator.\n\nFor variable a and expression b, a = b makes a refer to the value of b.\nFor functions f(x), f(x) = x defines a new function constant f, or adds a new method to f if f is already defined; this usage is equivalent to function f(x); x; end.\na[i] = v calls setindex!(a,v,i).\na.b = c calls setproperty!(a,:b,c).\nInside a function call, f(a=b) passes b as the value of keyword argument a.\nInside parentheses with commas, (a=1,) constructs a NamedTuple.\n\nExamples\n\nAssigning a to b does not create a copy of b; instead use copy or deepcopy.\n\njulia> b = [1]; a = b; b[1] = 2; a\n1-element Array{Int64, 1}:\n 2\n\njulia> b = [1]; a = copy(b); b[1] = 2; a\n1-element Array{Int64, 1}:\n 1\n\n\nCollections passed to functions are also not copied. Functions can modify (mutate) the contents of the objects their arguments refer to. (The names of functions which do this are conventionally suffixed with '!'.)\n\njulia> function f!(x); x[:] .+= 1; end\nf! (generic function with 1 method)\n\njulia> a = [1]; f!(a); a\n1-element Array{Int64, 1}:\n 2\n\n\nAssignment can operate on multiple variables in parallel, taking values from an iterable:\n\njulia> a, b = 4, 5\n(4, 5)\n\njulia> a, b = 1:3\n1:3\n\njulia> a, b\n(1, 2)\n\n\nAssignment can operate on multiple variables in series, and will return the value of the right-hand-most expression:\n\njulia> a = [1]; b = [2]; c = [3]; a = b = c\n1-element Array{Int64, 1}:\n 3\n\njulia> b[1] = 2; a, b, c\n([2], [2], [2])\n\n\nAssignment at out-of-bounds indices does not grow a collection. If the collection is a Vector it can instead be grown with push! or append!.\n\njulia> a = [1, 1]; a[3] = 2\nERROR: BoundsError: attempt to access 2-element Array{Int64, 1} at index [3]\n[...]\n\njulia> push!(a, 2, 3)\n4-element Array{Int64, 1}:\n 1\n 1\n 2\n 3\n\n\nAssigning [] does not eliminate elements from a collection; instead use filter!.\n\njulia> a = collect(1:3); a[a .<= 1] = []\nERROR: DimensionMismatch: tried to assign 0 elements to 1 destinations\n[...]\n\njulia> filter!(x -> x > 1, a) # in-place & thus more efficient than a = a[a .> 1]\n2-element Array{Int64, 1}:\n 2\n 3\n\n\n\n\n\n\n","category":"keyword"},{"location":"base/base/#?:","page":"基本功能","title":"?:","text":"a ? b : c\n\nShort form for conditionals; read \"if a, evaluate b otherwise evaluate c\". Also known as the ternary operator.\n\nThis syntax is equivalent to if a; b else c end, but is often used to emphasize the value b-or-c which is being used as part of a larger expression, rather than the side effects that evaluating b or c may have.\n\nSee the manual section on control flow for more details.\n\nExamples\n\njulia> x = 1; y = 2;\n\njulia> x > y ? println(\"x is larger\") : println(\"y is larger\")\ny is larger\n\n\n\n\n\n","category":"keyword"},{"location":"base/base/#Standard-Modules","page":"基本功能","title":"Standard Modules","text":"","category":"section"},{"location":"base/base/","page":"基本功能","title":"基本功能","text":"Main\nCore\nBase","category":"page"},{"location":"base/base/#Core","page":"基本功能","title":"Core","text":"Core\n\nCore is the module that contains all identifiers considered \"built in\" to the language, i.e. part of the core language and not libraries. Every module implicitly specifies using Core, since you can't do anything without those definitions.\n\n\n\n\n\n","category":"module"},{"location":"base/base/#Base","page":"基本功能","title":"Base","text":"Base\n\nThe base library of Julia. Base is a module that contains basic functionality (the contents of base/). All modules implicitly contain using Base, since this is needed in the vast majority of cases.\n\n\n\n\n\n","category":"module"},{"location":"base/base/#Base-Submodules","page":"基本功能","title":"Base Submodules","text":"","category":"section"},{"location":"base/base/","page":"基本功能","title":"基本功能","text":"Base.Broadcast\nBase.Docs\nBase.Iterators\nBase.Libc\nBase.Meta\nBase.StackTraces\nBase.Sys\nBase.Threads\nBase.GC","category":"page"},{"location":"base/base/#Base.Broadcast","page":"基本功能","title":"Base.Broadcast","text":"Base.Broadcast\n\nModule containing the broadcasting implementation.\n\n\n\n\n\n","category":"module"},{"location":"base/base/#Base.Docs","page":"基本功能","title":"Base.Docs","text":"Docs\n\nThe Docs module provides the @doc macro which can be used to set and retrieve documentation metadata for Julia objects.\n\nPlease see the manual section on documentation for more information.\n\n\n\n\n\n","category":"module"},{"location":"base/base/#Base.Iterators","page":"基本功能","title":"Base.Iterators","text":"Methods for working with Iterators.\n\n\n\n\n\n","category":"module"},{"location":"base/base/#Base.Libc","page":"基本功能","title":"Base.Libc","text":"Interface to libc, the C standard library.\n\n\n\n\n\n","category":"module"},{"location":"base/base/#Base.Meta","page":"基本功能","title":"Base.Meta","text":"Convenience functions for metaprogramming.\n\n\n\n\n\n","category":"module"},{"location":"base/base/#Base.StackTraces","page":"基本功能","title":"Base.StackTraces","text":"Tools for collecting and manipulating stack traces. Mainly used for building errors.\n\n\n\n\n\n","category":"module"},{"location":"base/base/#Base.Sys","page":"基本功能","title":"Base.Sys","text":"Provide methods for retrieving information about hardware and the operating system.\n\n\n\n\n\n","category":"module"},{"location":"base/base/#Base.Threads","page":"基本功能","title":"Base.Threads","text":"Multithreading support.\n\n\n\n\n\n","category":"module"},{"location":"base/base/#Base.GC","page":"基本功能","title":"Base.GC","text":"Base.GC\n\nModule with garbage collection utilities.\n\n\n\n\n\n","category":"module"},{"location":"base/base/#All-Objects","page":"基本功能","title":"All Objects","text":"","category":"section"},{"location":"base/base/","page":"基本功能","title":"基本功能","text":"Core.:(===)\nCore.isa\nBase.isequal\nBase.isless\nBase.ifelse\nCore.typeassert\nCore.typeof\nCore.tuple\nBase.ntuple\nBase.objectid\nBase.hash\nBase.finalizer\nBase.finalize\nBase.copy\nBase.deepcopy\nBase.getproperty\nBase.setproperty!\nBase.propertynames\nBase.hasproperty\nCore.getfield\nCore.setfield!\nCore.isdefined\nBase.@isdefined\nBase.convert\nBase.promote\nBase.oftype\nBase.widen\nBase.identity","category":"page"},{"location":"base/base/#Core.:===","page":"基本功能","title":"Core.:===","text":"===(x,y) -> Bool\n≡(x,y) -> Bool\n\nDetermine whether x and y are identical, in the sense that no program could distinguish them. First the types of x and y are compared. If those are identical, mutable objects are compared by address in memory and immutable objects (such as numbers) are compared by contents at the bit level. This function is sometimes called \"egal\". It always returns a Bool value.\n\nExamples\n\njulia> a = [1, 2]; b = [1, 2];\n\njulia> a == b\ntrue\n\njulia> a === b\nfalse\n\njulia> a === a\ntrue\n\n\n\n\n\n","category":"function"},{"location":"base/base/#Core.isa","page":"基本功能","title":"Core.isa","text":"isa(x, type) -> Bool\n\nDetermine whether x is of the given type. Can also be used as an infix operator, e.g. x isa type.\n\nExamples\n\njulia> isa(1, Int)\ntrue\n\njulia> isa(1, Matrix)\nfalse\n\njulia> isa(1, Char)\nfalse\n\njulia> isa(1, Number)\ntrue\n\njulia> 1 isa Number\ntrue\n\n\n\n\n\n","category":"function"},{"location":"base/base/#Base.isequal","page":"基本功能","title":"Base.isequal","text":"isequal(x, y)\n\nSimilar to ==, except for the treatment of floating point numbers and of missing values. isequal treats all floating-point NaN values as equal to each other, treats -0.0 as unequal to 0.0, and missing as equal to missing. Always returns a Bool value.\n\nisequal is an equivalence relation - it is reflexive (=== implies isequal), symmetric (isequal(a, b) implies isequal(b, a)) and transitive (isequal(a, b) and isequal(b, c) implies isequal(a, c)).\n\nImplementation\n\nThe default implementation of isequal calls ==, so a type that does not involve floating-point values generally only needs to define ==.\n\nisequal is the comparison function used by hash tables (Dict). isequal(x,y) must imply that hash(x) == hash(y).\n\nThis typically means that types for which a custom == or isequal method exists must implement a corresponding hash method (and vice versa). Collections typically implement isequal by calling isequal recursively on all contents.\n\nFurthermore, isequal is linked with isless, and they work together to define a fixed total ordering, where exactly one of isequal(x, y), isless(x, y), or isless(y, x) must be true (and the other two false).\n\nScalar types generally do not need to implement isequal separate from ==, unless they represent floating-point numbers amenable to a more efficient implementation than that provided as a generic fallback (based on isnan, signbit, and ==).\n\nExamples\n\njulia> isequal([1., NaN], [1., NaN])\ntrue\n\njulia> [1., NaN] == [1., NaN]\nfalse\n\njulia> 0.0 == -0.0\ntrue\n\njulia> isequal(0.0, -0.0)\nfalse\n\njulia> missing == missing\nmissing\n\njulia> isequal(missing, missing)\ntrue\n\n\n\n\n\nisequal(x)\n\nCreate a function that compares its argument to x using isequal, i.e. a function equivalent to y -> isequal(y, x).\n\nThe returned function is of type Base.Fix2{typeof(isequal)}, which can be used to implement specialized methods.\n\n\n\n\n\n","category":"function"},{"location":"base/base/#Base.isless","page":"基本功能","title":"Base.isless","text":"isless(x, y)\n\nTest whether x is less than y, according to a fixed total order (defined together with isequal). isless is not defined on all pairs of values (x, y). However, if it is defined, it is expected to satisfy the following:\n\nIf isless(x, y) is defined, then so is isless(y, x) and isequal(x, y), and exactly one of those three yields true.\nThe relation defined by isless is transitive, i.e., isless(x, y) && isless(y, z) implies isless(x, z).\n\nValues that are normally unordered, such as NaN, are ordered after regular values. missing values are ordered last.\n\nThis is the default comparison used by sort.\n\nImplementation\n\nNon-numeric types with a total order should implement this function. Numeric types only need to implement it if they have special values such as NaN. Types with a partial order should implement <. See the documentation on Alternate orderings for how to define alternate ordering methods that can be used in sorting and related functions.\n\nExamples\n\njulia> isless(1, 3)\ntrue\n\njulia> isless(\"Red\", \"Blue\")\nfalse\n\n\n\n\n\n","category":"function"},{"location":"base/base/#Base.ifelse","page":"基本功能","title":"Base.ifelse","text":"ifelse(condition::Bool, x, y)\n\nReturn x if condition is true, otherwise return y. This differs from ? or if in that it is an ordinary function, so all the arguments are evaluated first. In some cases, using ifelse instead of an if statement can eliminate the branch in generated code and provide higher performance in tight loops.\n\nExamples\n\njulia> ifelse(1 > 2, 1, 2)\n2\n\n\n\n\n\n","category":"function"},{"location":"base/base/#Core.typeassert","page":"基本功能","title":"Core.typeassert","text":"typeassert(x, type)\n\nThrow a TypeError unless x isa type. The syntax x::type calls this function.\n\nExamples\n\njulia> typeassert(2.5, Int)\nERROR: TypeError: in typeassert, expected Int64, got a value of type Float64\nStacktrace:\n[...]\n\n\n\n\n\n","category":"function"},{"location":"base/base/#Core.typeof","page":"基本功能","title":"Core.typeof","text":"typeof(x)\n\nGet the concrete type of x.\n\nSee also eltype.\n\nExamples\n\njulia> a = 1//2;\n\njulia> typeof(a)\nRational{Int64}\n\njulia> M = [1 2; 3.5 4];\n\njulia> typeof(M)\nMatrix{Float64} (alias for Array{Float64, 2})\n\n\n\n\n\n","category":"function"},{"location":"base/base/#Core.tuple","page":"基本功能","title":"Core.tuple","text":"tuple(xs...)\n\nConstruct a tuple of the given objects.\n\nSee also Tuple, NamedTuple.\n\nExamples\n\njulia> tuple(1, 'b', pi)\n(1, 'b', π)\n\njulia> ans === (1, 'b', π)\ntrue\n\njulia> Tuple(Real[1, 2, pi]) # takes a collection\n(1, 2, π)\n\n\n\n\n\n","category":"function"},{"location":"base/base/#Base.ntuple","page":"基本功能","title":"Base.ntuple","text":"ntuple(f::Function, n::Integer)\n\nCreate a tuple of length n, computing each element as f(i), where i is the index of the element.\n\nExamples\n\njulia> ntuple(i -> 2*i, 4)\n(2, 4, 6, 8)\n\n\n\n\n\nntuple(f, ::Val{N})\n\nCreate a tuple of length N, computing each element as f(i), where i is the index of the element. By taking a Val(N) argument, it is possible that this version of ntuple may generate more efficient code than the version taking the length as an integer. But ntuple(f, N) is preferable to ntuple(f, Val(N)) in cases where N cannot be determined at compile time.\n\nExamples\n\njulia> ntuple(i -> 2*i, Val(4))\n(2, 4, 6, 8)\n\n\n\n\n\n","category":"function"},{"location":"base/base/#Base.objectid","page":"基本功能","title":"Base.objectid","text":"objectid(x) -> UInt\n\nGet a hash value for x based on object identity. objectid(x)==objectid(y) if x === y.\n\nSee also hash, IdDict.\n\n\n\n\n\n","category":"function"},{"location":"base/base/#Base.hash","page":"基本功能","title":"Base.hash","text":"hash(x[, h::UInt]) -> UInt\n\nCompute an integer hash code such that isequal(x,y) implies hash(x)==hash(y). The optional second argument h is a hash code to be mixed with the result.\n\nNew types should implement the 2-argument form, typically by calling the 2-argument hash method recursively in order to mix hashes of the contents with each other (and with h). Typically, any type that implements hash should also implement its own == (hence isequal) to guarantee the property mentioned above. Types supporting subtraction (operator -) should also implement widen, which is required to hash values inside heterogeneous arrays.\n\nSee also: objectid, Dict, Set.\n\n\n\n\n\n","category":"function"},{"location":"base/base/#Base.finalizer","page":"基本功能","title":"Base.finalizer","text":"finalizer(f, x)\n\nRegister a function f(x) to be called when there are no program-accessible references to x, and return x. The type of x must be a mutable struct, otherwise the behavior of this function is unpredictable.\n\nf must not cause a task switch, which excludes most I/O operations such as println. Using the @async macro (to defer context switching to outside of the finalizer) or ccall to directly invoke IO functions in C may be helpful for debugging purposes.\n\nExamples\n\nfinalizer(my_mutable_struct) do x\n @async println(\"Finalizing $x.\")\nend\n\nfinalizer(my_mutable_struct) do x\n ccall(:jl_safe_printf, Cvoid, (Cstring, Cstring), \"Finalizing %s.\", repr(x))\nend\n\nA finalizer may be registered at object construction. In the following example note that we implicitly rely on the finalizer returning the newly created mutable struct x.\n\nExample\n\nmutable struct MyMutableStruct\n bar\n function MyMutableStruct(bar)\n x = new(bar)\n f(t) = @async println(\"Finalizing $t.\")\n finalizer(f, x)\n end\nend\n\n\n\n\n\n","category":"function"},{"location":"base/base/#Base.finalize","page":"基本功能","title":"Base.finalize","text":"finalize(x)\n\nImmediately run finalizers registered for object x.\n\n\n\n\n\n","category":"function"},{"location":"base/base/#Base.copy","page":"基本功能","title":"Base.copy","text":"copy(x)\n\nCreate a shallow copy of x: the outer structure is copied, but not all internal values. For example, copying an array produces a new array with identically-same elements as the original.\n\nSee also copy!, copyto!.\n\n\n\n\n\n","category":"function"},{"location":"base/base/#Base.deepcopy","page":"基本功能","title":"Base.deepcopy","text":"deepcopy(x)\n\nCreate a deep copy of x: everything is copied recursively, resulting in a fully independent object. For example, deep-copying an array produces a new array whose elements are deep copies of the original elements. Calling deepcopy on an object should generally have the same effect as serializing and then deserializing it.\n\nWhile it isn't normally necessary, user-defined types can override the default deepcopy behavior by defining a specialized version of the function deepcopy_internal(x::T, dict::IdDict) (which shouldn't otherwise be used), where T is the type to be specialized for, and dict keeps track of objects copied so far within the recursion. Within the definition, deepcopy_internal should be used in place of deepcopy, and the dict variable should be updated as appropriate before returning.\n\n\n\n\n\n","category":"function"},{"location":"base/base/#Base.getproperty","page":"基本功能","title":"Base.getproperty","text":"getproperty(value, name::Symbol)\ngetproperty(value, name::Symbol, order::Symbol)\n\nThe syntax a.b calls getproperty(a, :b). The syntax @atomic order a.b calls getproperty(a, :b, :order) and the syntax @atomic a.b calls getproperty(a, :b, :sequentially_consistent).\n\nExamples\n\njulia> struct MyType\n x\n end\n\njulia> function Base.getproperty(obj::MyType, sym::Symbol)\n if sym === :special\n return obj.x + 1\n else # fallback to getfield\n return getfield(obj, sym)\n end\n end\n\njulia> obj = MyType(1);\n\njulia> obj.special\n2\n\njulia> obj.x\n1\n\nSee also getfield, propertynames and setproperty!.\n\n\n\n\n\n","category":"function"},{"location":"base/base/#Base.setproperty!","page":"基本功能","title":"Base.setproperty!","text":"setproperty!(value, name::Symbol, x)\nsetproperty!(value, name::Symbol, x, order::Symbol)\n\nThe syntax a.b = c calls setproperty!(a, :b, c). The syntax @atomic order a.b = c calls setproperty!(a, :b, c, :order) and the syntax @atomic a.b = c calls getproperty(a, :b, :sequentially_consistent).\n\nSee also setfield!, propertynames and getproperty.\n\n\n\n\n\n","category":"function"},{"location":"base/base/#Base.propertynames","page":"基本功能","title":"Base.propertynames","text":"propertynames(x, private=false)\n\nGet a tuple or a vector of the properties (x.property) of an object x. This is typically the same as fieldnames(typeof(x)), but types that overload getproperty should generally overload propertynames as well to get the properties of an instance of the type.\n\npropertynames(x) may return only \"public\" property names that are part of the documented interface of x. If you want it to also return \"private\" fieldnames intended for internal use, pass true for the optional second argument. REPL tab completion on x. shows only the private=false properties.\n\nSee also: hasproperty, hasfield.\n\n\n\n\n\n","category":"function"},{"location":"base/base/#Base.hasproperty","page":"基本功能","title":"Base.hasproperty","text":"hasproperty(x, s::Symbol)\n\nReturn a boolean indicating whether the object x has s as one of its own properties.\n\ncompat: Julia 1.2\nThis function requires at least Julia 1.2.\n\nSee also: propertynames, hasfield.\n\n\n\n\n\n","category":"function"},{"location":"base/base/#Core.getfield","page":"基本功能","title":"Core.getfield","text":"getfield(value, name::Symbol, [order::Symbol])\ngetfield(value, i::Int, [order::Symbol])\n\nExtract a field from a composite value by name or position. Optionally, an ordering can be defined for the operation. If the field was declared @atomic, the specification is strongly recommended to be compatible with the stores to that location. Otherwise, if not declared as @atomic, this parameter must be :not_atomic if specified. See also getproperty and fieldnames.\n\nExamples\n\njulia> a = 1//2\n1//2\n\njulia> getfield(a, :num)\n1\n\njulia> a.num\n1\n\njulia> getfield(a, 1)\n1\n\n\n\n\n\n","category":"function"},{"location":"base/base/#Core.setfield!","page":"基本功能","title":"Core.setfield!","text":"setfield!(value, name::Symbol, x, [order::Symbol])\nsetfield!(value, i::Int, x, [order::Symbol])\n\nAssign x to a named field in value of composite type. The value must be mutable and x must be a subtype of fieldtype(typeof(value), name). Additionally, an ordering can be specified for this operation. If the field was declared @atomic, this specification is mandatory. Otherwise, if not declared as @atomic, it must be :not_atomic if specified. See also setproperty!.\n\nExamples\n\njulia> mutable struct MyMutableStruct\n field::Int\n end\n\njulia> a = MyMutableStruct(1);\n\njulia> setfield!(a, :field, 2);\n\njulia> getfield(a, :field)\n2\n\njulia> a = 1//2\n1//2\n\njulia> setfield!(a, :num, 3);\nERROR: setfield!: immutable struct of type Rational cannot be changed\n\n\n\n\n\n","category":"function"},{"location":"base/base/#Core.isdefined","page":"基本功能","title":"Core.isdefined","text":"isdefined(m::Module, s::Symbol, [order::Symbol])\nisdefined(object, s::Symbol, [order::Symbol])\nisdefined(object, index::Int, [order::Symbol])\n\nTests whether a global variable or object field is defined. The arguments can be a module and a symbol or a composite object and field name (as a symbol) or index. Optionally, an ordering can be defined for the operation. If the field was declared @atomic, the specification is strongly recommended to be compatible with the stores to that location. Otherwise, if not declared as @atomic, this parameter must be :not_atomic if specified.\n\nTo test whether an array element is defined, use isassigned instead.\n\nSee also @isdefined.\n\nExamples\n\njulia> isdefined(Base, :sum)\ntrue\n\njulia> isdefined(Base, :NonExistentMethod)\nfalse\n\njulia> a = 1//2;\n\njulia> isdefined(a, 2)\ntrue\n\njulia> isdefined(a, 3)\nfalse\n\njulia> isdefined(a, :num)\ntrue\n\njulia> isdefined(a, :numerator)\nfalse\n\n\n\n\n\n","category":"function"},{"location":"base/base/#Base.@isdefined","page":"基本功能","title":"Base.@isdefined","text":"@isdefined s -> Bool\n\nTests whether variable s is defined in the current scope.\n\nSee also isdefined for field properties and isassigned for array indexes or haskey for other mappings.\n\nExamples\n\njulia> @isdefined newvar\nfalse\n\njulia> newvar = 1\n1\n\njulia> @isdefined newvar\ntrue\n\njulia> function f()\n println(@isdefined x)\n x = 3\n println(@isdefined x)\n end\nf (generic function with 1 method)\n\njulia> f()\nfalse\ntrue\n\n\n\n\n\n","category":"macro"},{"location":"base/base/#Base.convert","page":"基本功能","title":"Base.convert","text":"convert(T, x)\n\nConvert x to a value of type T.\n\nIf T is an Integer type, an InexactError will be raised if x is not representable by T, for example if x is not integer-valued, or is outside the range supported by T.\n\nExamples\n\njulia> convert(Int, 3.0)\n3\n\njulia> convert(Int, 3.5)\nERROR: InexactError: Int64(3.5)\nStacktrace:\n[...]\n\nIf T is a AbstractFloat type, then it will return the closest value to x representable by T.\n\njulia> x = 1/3\n0.3333333333333333\n\njulia> convert(Float32, x)\n0.33333334f0\n\njulia> convert(BigFloat, x)\n0.333333333333333314829616256247390992939472198486328125\n\nIf T is a collection type and x a collection, the result of convert(T, x) may alias all or part of x.\n\njulia> x = Int[1, 2, 3];\n\njulia> y = convert(Vector{Int}, x);\n\njulia> y === x\ntrue\n\nSee also: round, trunc, oftype, reinterpret.\n\n\n\n\n\n","category":"function"},{"location":"base/base/#Base.promote","page":"基本功能","title":"Base.promote","text":"promote(xs...)\n\nConvert all arguments to a common type, and return them all (as a tuple). If no arguments can be converted, an error is raised.\n\nSee also: [promote_type], [promote_rule].\n\nExamples\n\njulia> promote(Int8(1), Float16(4.5), Float32(4.1))\n(1.0f0, 4.5f0, 4.1f0)\n\n\n\n\n\n","category":"function"},{"location":"base/base/#Base.oftype","page":"基本功能","title":"Base.oftype","text":"oftype(x, y)\n\nConvert y to the type of x (convert(typeof(x), y)).\n\nExamples\n\njulia> x = 4;\n\njulia> y = 3.;\n\njulia> oftype(x, y)\n3\n\njulia> oftype(y, x)\n4.0\n\n\n\n\n\n","category":"function"},{"location":"base/base/#Base.widen","page":"基本功能","title":"Base.widen","text":"widen(x)\n\nIf x is a type, return a \"larger\" type, defined so that arithmetic operations + and - are guaranteed not to overflow nor lose precision for any combination of values that type x can hold.\n\nFor fixed-size integer types less than 128 bits, widen will return a type with twice the number of bits.\n\nIf x is a value, it is converted to widen(typeof(x)).\n\nExamples\n\njulia> widen(Int32)\nInt64\n\njulia> widen(1.5f0)\n1.5\n\n\n\n\n\n","category":"function"},{"location":"base/base/#Base.identity","page":"基本功能","title":"Base.identity","text":"identity(x)\n\nThe identity function. Returns its argument.\n\nSee also: one, oneunit, and LinearAlgebra's I.\n\nExamples\n\njulia> identity(\"Well, what did you expect?\")\n\"Well, what did you expect?\"\n\n\n\n\n\n","category":"function"},{"location":"base/base/#Properties-of-Types","page":"基本功能","title":"Properties of Types","text":"","category":"section"},{"location":"base/base/#Type-relations","page":"基本功能","title":"Type relations","text":"","category":"section"},{"location":"base/base/","page":"基本功能","title":"基本功能","text":"Base.supertype\nCore.Type\nCore.DataType\nCore.:(<:)\nBase.:(>:)\nBase.typejoin\nBase.typeintersect\nBase.promote_type\nBase.promote_rule\nBase.promote_typejoin\nBase.isdispatchtuple","category":"page"},{"location":"base/base/#Base.supertype","page":"基本功能","title":"Base.supertype","text":"supertype(T::DataType)\n\nReturn the supertype of DataType T.\n\nExamples\n\njulia> supertype(Int32)\nSigned\n\n\n\n\n\n","category":"function"},{"location":"base/base/#Core.Type","page":"基本功能","title":"Core.Type","text":"Core.Type{T}\n\nCore.Type is an abstract type which has all type objects as its instances. The only instance of the singleton type Core.Type{T} is the object T.\n\nExamples\n\njulia> isa(Type{Float64}, Type)\ntrue\n\njulia> isa(Float64, Type)\ntrue\n\njulia> isa(Real, Type{Float64})\nfalse\n\njulia> isa(Real, Type{Real})\ntrue\n\n\n\n\n\n","category":"type"},{"location":"base/base/#Core.DataType","page":"基本功能","title":"Core.DataType","text":"DataType <: Type{T}\n\nDataType represents explicitly declared types that have names, explicitly declared supertypes, and, optionally, parameters. Every concrete value in the system is an instance of some DataType.\n\nExamples\n\njulia> typeof(Real)\nDataType\n\njulia> typeof(Int)\nDataType\n\njulia> struct Point\n x::Int\n y\n end\n\njulia> typeof(Point)\nDataType\n\n\n\n\n\n","category":"type"},{"location":"base/base/#Core.:<:","page":"基本功能","title":"Core.:<:","text":"<:(T1, T2)\n\nSubtype operator: returns true if and only if all values of type T1 are also of type T2.\n\nExamples\n\njulia> Float64 <: AbstractFloat\ntrue\n\njulia> Vector{Int} <: AbstractArray\ntrue\n\njulia> Matrix{Float64} <: Matrix{AbstractFloat}\nfalse\n\n\n\n\n\n","category":"function"},{"location":"base/base/#Base.:>:","page":"基本功能","title":"Base.:>:","text":">:(T1, T2)\n\nSupertype operator, equivalent to T2 <: T1.\n\n\n\n\n\n","category":"function"},{"location":"base/base/#Base.typejoin","page":"基本功能","title":"Base.typejoin","text":"typejoin(T, S)\n\nReturn the closest common ancestor of T and S, i.e. the narrowest type from which they both inherit.\n\n\n\n\n\n","category":"function"},{"location":"base/base/#Base.typeintersect","page":"基本功能","title":"Base.typeintersect","text":"typeintersect(T::Type, S::Type)\n\nCompute a type that contains the intersection of T and S. Usually this will be the smallest such type or one close to it.\n\n\n\n\n\n","category":"function"},{"location":"base/base/#Base.promote_type","page":"基本功能","title":"Base.promote_type","text":"promote_type(type1, type2)\n\nPromotion refers to converting values of mixed types to a single common type. promote_type represents the default promotion behavior in Julia when operators (usually mathematical) are given arguments of differing types. promote_type generally tries to return a type which can at least approximate most values of either input type without excessively widening. Some loss is tolerated; for example, promote_type(Int64, Float64) returns Float64 even though strictly, not all Int64 values can be represented exactly as Float64 values.\n\nSee also: promote, promote_typejoin, promote_rule.\n\nExamples\n\njulia> promote_type(Int64, Float64)\nFloat64\n\njulia> promote_type(Int32, Int64)\nInt64\n\njulia> promote_type(Float32, BigInt)\nBigFloat\n\njulia> promote_type(Int16, Float16)\nFloat16\n\njulia> promote_type(Int64, Float16)\nFloat16\n\njulia> promote_type(Int8, UInt16)\nUInt16\n\nwarning: Don't overload this directly\nTo overload promotion for your own types you should overload promote_rule. promote_type calls promote_rule internally to determine the type. Overloading promote_type directly can cause ambiguity errors.\n\n\n\n\n\n","category":"function"},{"location":"base/base/#Base.promote_rule","page":"基本功能","title":"Base.promote_rule","text":"promote_rule(type1, type2)\n\nSpecifies what type should be used by promote when given values of types type1 and type2. This function should not be called directly, but should have definitions added to it for new types as appropriate.\n\n\n\n\n\n","category":"function"},{"location":"base/base/#Base.promote_typejoin","page":"基本功能","title":"Base.promote_typejoin","text":"promote_typejoin(T, S)\n\nCompute a type that contains both T and S, which could be either a parent of both types, or a Union if appropriate. Falls back to typejoin.\n\nSee instead promote, promote_type.\n\nExamples\n\njulia> Base.promote_typejoin(Int, Float64)\nReal\n\njulia> Base.promote_type(Int, Float64)\nFloat64\n\n\n\n\n\n","category":"function"},{"location":"base/base/#Base.isdispatchtuple","page":"基本功能","title":"Base.isdispatchtuple","text":"isdispatchtuple(T)\n\nDetermine whether type T is a tuple \"leaf type\", meaning it could appear as a type signature in dispatch and has no subtypes (or supertypes) which could appear in a call.\n\n\n\n\n\n","category":"function"},{"location":"base/base/#Declared-structure","page":"基本功能","title":"Declared structure","text":"","category":"section"},{"location":"base/base/","page":"基本功能","title":"基本功能","text":"Base.ismutable\nBase.isimmutable\nBase.isabstracttype\nBase.isprimitivetype\nBase.issingletontype\nBase.isstructtype\nBase.nameof(::DataType)\nBase.fieldnames\nBase.fieldname\nBase.hasfield","category":"page"},{"location":"base/base/#Base.ismutable","page":"基本功能","title":"Base.ismutable","text":"ismutable(v) -> Bool\n\nReturn true if and only if value v is mutable. See Mutable Composite Types for a discussion of immutability. Note that this function works on values, so if you give it a type, it will tell you that a value of DataType is mutable.\n\nSee also isbits, isstructtype.\n\nExamples\n\njulia> ismutable(1)\nfalse\n\njulia> ismutable([1,2])\ntrue\n\ncompat: Julia 1.5\nThis function requires at least Julia 1.5.\n\n\n\n\n\n","category":"function"},{"location":"base/base/#Base.isimmutable","page":"基本功能","title":"Base.isimmutable","text":"isimmutable(v) -> Bool\n\nwarning: Warning\nConsider using !ismutable(v) instead, as isimmutable(v) will be replaced by !ismutable(v) in a future release. (Since Julia 1.5)\n\nReturn true iff value v is immutable. See Mutable Composite Types for a discussion of immutability. Note that this function works on values, so if you give it a type, it will tell you that a value of DataType is mutable.\n\nExamples\n\njulia> isimmutable(1)\ntrue\n\njulia> isimmutable([1,2])\nfalse\n\n\n\n\n\n","category":"function"},{"location":"base/base/#Base.isabstracttype","page":"基本功能","title":"Base.isabstracttype","text":"isabstracttype(T)\n\nDetermine whether type T was declared as an abstract type (i.e. using the abstract keyword).\n\nExamples\n\njulia> isabstracttype(AbstractArray)\ntrue\n\njulia> isabstracttype(Vector)\nfalse\n\n\n\n\n\n","category":"function"},{"location":"base/base/#Base.isprimitivetype","page":"基本功能","title":"Base.isprimitivetype","text":"isprimitivetype(T) -> Bool\n\nDetermine whether type T was declared as a primitive type (i.e. using the primitive keyword).\n\n\n\n\n\n","category":"function"},{"location":"base/base/#Base.issingletontype","page":"基本功能","title":"Base.issingletontype","text":"Base.issingletontype(T)\n\nDetermine whether type T has exactly one possible instance; for example, a struct type with no fields.\n\n\n\n\n\n","category":"function"},{"location":"base/base/#Base.isstructtype","page":"基本功能","title":"Base.isstructtype","text":"isstructtype(T) -> Bool\n\nDetermine whether type T was declared as a struct type (i.e. using the struct or mutable struct keyword).\n\n\n\n\n\n","category":"function"},{"location":"base/base/#Base.nameof-Tuple{DataType}","page":"基本功能","title":"Base.nameof","text":"nameof(t::DataType) -> Symbol\n\nGet the name of a (potentially UnionAll-wrapped) DataType (without its parent module) as a symbol.\n\nExamples\n\njulia> module Foo\n struct S{T}\n end\n end\nFoo\n\njulia> nameof(Foo.S{T} where T)\n:S\n\n\n\n\n\n","category":"method"},{"location":"base/base/#Base.fieldnames","page":"基本功能","title":"Base.fieldnames","text":"fieldnames(x::DataType)\n\nGet a tuple with the names of the fields of a DataType.\n\nSee also propertynames, hasfield.\n\nExamples\n\njulia> fieldnames(Rational)\n(:num, :den)\n\njulia> fieldnames(typeof(1+im))\n(:re, :im)\n\n\n\n\n\n","category":"function"},{"location":"base/base/#Base.fieldname","page":"基本功能","title":"Base.fieldname","text":"fieldname(x::DataType, i::Integer)\n\nGet the name of field i of a DataType.\n\nExamples\n\njulia> fieldname(Rational, 1)\n:num\n\njulia> fieldname(Rational, 2)\n:den\n\n\n\n\n\n","category":"function"},{"location":"base/base/#Base.hasfield","page":"基本功能","title":"Base.hasfield","text":"hasfield(T::Type, name::Symbol)\n\nReturn a boolean indicating whether T has name as one of its own fields.\n\nSee also fieldnames, fieldcount, hasproperty.\n\ncompat: Julia 1.2\nThis function requires at least Julia 1.2.\n\nExamples\n\njulia> struct Foo\n bar::Int\n end\n\njulia> hasfield(Foo, :bar)\ntrue\n\njulia> hasfield(Foo, :x)\nfalse\n\n\n\n\n\n","category":"function"},{"location":"base/base/#Memory-layout","page":"基本功能","title":"Memory layout","text":"","category":"section"},{"location":"base/base/","page":"基本功能","title":"基本功能","text":"Base.sizeof(::Type)\nBase.isconcretetype\nBase.isbits\nBase.isbitstype\nCore.fieldtype\nBase.fieldtypes\nBase.fieldcount\nBase.fieldoffset\nBase.datatype_alignment\nBase.datatype_haspadding\nBase.datatype_pointerfree","category":"page"},{"location":"base/base/#Base.sizeof-Tuple{Type}","page":"基本功能","title":"Base.sizeof","text":"sizeof(T::DataType)\nsizeof(obj)\n\nSize, in bytes, of the canonical binary representation of the given DataType T, if any. Or the size, in bytes, of object obj if it is not a DataType.\n\nSee also summarysize.\n\nExamples\n\njulia> sizeof(Float32)\n4\n\njulia> sizeof(ComplexF64)\n16\n\njulia> sizeof(1.0)\n8\n\njulia> sizeof(collect(1.0:10.0))\n80\n\nIf DataType T does not have a specific size, an error is thrown.\n\njulia> sizeof(AbstractArray)\nERROR: Abstract type AbstractArray does not have a definite size.\nStacktrace:\n[...]\n\n\n\n\n\n","category":"method"},{"location":"base/base/#Base.isconcretetype","page":"基本功能","title":"Base.isconcretetype","text":"isconcretetype(T)\n\nDetermine whether type T is a concrete type, meaning it could have direct instances (values x such that typeof(x) === T).\n\nSee also: isbits, isabstracttype, issingletontype.\n\nExamples\n\njulia> isconcretetype(Complex)\nfalse\n\njulia> isconcretetype(Complex{Float32})\ntrue\n\njulia> isconcretetype(Vector{Complex})\ntrue\n\njulia> isconcretetype(Vector{Complex{Float32}})\ntrue\n\njulia> isconcretetype(Union{})\nfalse\n\njulia> isconcretetype(Union{Int,String})\nfalse\n\n\n\n\n\n","category":"function"},{"location":"base/base/#Base.isbits","page":"基本功能","title":"Base.isbits","text":"isbits(x)\n\nReturn true if x is an instance of an isbitstype type.\n\n\n\n\n\n","category":"function"},{"location":"base/base/#Base.isbitstype","page":"基本功能","title":"Base.isbitstype","text":"isbitstype(T)\n\nReturn true if type T is a \"plain data\" type, meaning it is immutable and contains no references to other values, only primitive types and other isbitstype types. Typical examples are numeric types such as UInt8, Float64, and Complex{Float64}. This category of types is significant since they are valid as type parameters, may not track isdefined / isassigned status, and have a defined layout that is compatible with C.\n\nSee also isbits, isprimitivetype, ismutable.\n\nExamples\n\njulia> isbitstype(Complex{Float64})\ntrue\n\njulia> isbitstype(Complex)\nfalse\n\n\n\n\n\n","category":"function"},{"location":"base/base/#Core.fieldtype","page":"基本功能","title":"Core.fieldtype","text":"fieldtype(T, name::Symbol | index::Int)\n\nDetermine the declared type of a field (specified by name or index) in a composite DataType T.\n\nExamples\n\njulia> struct Foo\n x::Int64\n y::String\n end\n\njulia> fieldtype(Foo, :x)\nInt64\n\njulia> fieldtype(Foo, 2)\nString\n\n\n\n\n\n","category":"function"},{"location":"base/base/#Base.fieldtypes","page":"基本功能","title":"Base.fieldtypes","text":"fieldtypes(T::Type)\n\nThe declared types of all fields in a composite DataType T as a tuple.\n\ncompat: Julia 1.1\nThis function requires at least Julia 1.1.\n\nExamples\n\njulia> struct Foo\n x::Int64\n y::String\n end\n\njulia> fieldtypes(Foo)\n(Int64, String)\n\n\n\n\n\n","category":"function"},{"location":"base/base/#Base.fieldcount","page":"基本功能","title":"Base.fieldcount","text":"fieldcount(t::Type)\n\nGet the number of fields that an instance of the given type would have. An error is thrown if the type is too abstract to determine this.\n\n\n\n\n\n","category":"function"},{"location":"base/base/#Base.fieldoffset","page":"基本功能","title":"Base.fieldoffset","text":"fieldoffset(type, i)\n\nThe byte offset of field i of a type relative to the data start. For example, we could use it in the following manner to summarize information about a struct:\n\njulia> structinfo(T) = [(fieldoffset(T,i), fieldname(T,i), fieldtype(T,i)) for i = 1:fieldcount(T)];\n\njulia> structinfo(Base.Filesystem.StatStruct)\n13-element Vector{Tuple{UInt64, Symbol, Type}}:\n (0x0000000000000000, :desc, Union{RawFD, String})\n (0x0000000000000008, :device, UInt64)\n (0x0000000000000010, :inode, UInt64)\n (0x0000000000000018, :mode, UInt64)\n (0x0000000000000020, :nlink, Int64)\n (0x0000000000000028, :uid, UInt64)\n (0x0000000000000030, :gid, UInt64)\n (0x0000000000000038, :rdev, UInt64)\n (0x0000000000000040, :size, Int64)\n (0x0000000000000048, :blksize, Int64)\n (0x0000000000000050, :blocks, Int64)\n (0x0000000000000058, :mtime, Float64)\n (0x0000000000000060, :ctime, Float64)\n\n\n\n\n\n","category":"function"},{"location":"base/base/#Base.datatype_alignment","page":"基本功能","title":"Base.datatype_alignment","text":"Base.datatype_alignment(dt::DataType) -> Int\n\nMemory allocation minimum alignment for instances of this type. Can be called on any isconcretetype.\n\n\n\n\n\n","category":"function"},{"location":"base/base/#Base.datatype_haspadding","page":"基本功能","title":"Base.datatype_haspadding","text":"Base.datatype_haspadding(dt::DataType) -> Bool\n\nReturn whether the fields of instances of this type are packed in memory, with no intervening padding bytes. Can be called on any isconcretetype.\n\n\n\n\n\n","category":"function"},{"location":"base/base/#Base.datatype_pointerfree","page":"基本功能","title":"Base.datatype_pointerfree","text":"Base.datatype_pointerfree(dt::DataType) -> Bool\n\nReturn whether instances of this type can contain references to gc-managed memory. Can be called on any isconcretetype.\n\n\n\n\n\n","category":"function"},{"location":"base/base/#Special-values","page":"基本功能","title":"Special values","text":"","category":"section"},{"location":"base/base/","page":"基本功能","title":"基本功能","text":"Base.typemin\nBase.typemax\nBase.floatmin\nBase.floatmax\nBase.maxintfloat\nBase.eps(::Type{<:AbstractFloat})\nBase.eps(::AbstractFloat)\nBase.instances","category":"page"},{"location":"base/base/#Base.typemin","page":"基本功能","title":"Base.typemin","text":"typemin(T)\n\nThe lowest value representable by the given (real) numeric DataType T.\n\nExamples\n\njulia> typemin(Float16)\n-Inf16\n\njulia> typemin(Float32)\n-Inf32\n\n\n\n\n\n","category":"function"},{"location":"base/base/#Base.typemax","page":"基本功能","title":"Base.typemax","text":"typemax(T)\n\nThe highest value representable by the given (real) numeric DataType.\n\nSee also: floatmax, typemin, eps.\n\nExamples\n\njulia> typemax(Int8)\n127\n\njulia> typemax(UInt32)\n0xffffffff\n\njulia> typemax(Float64)\nInf\n\njulia> floatmax(Float32) # largest finite floating point number\n3.4028235f38\n\n\n\n\n\n","category":"function"},{"location":"base/base/#Base.floatmin","page":"基本功能","title":"Base.floatmin","text":"floatmin(T = Float64)\n\nReturn the smallest positive normal number representable by the floating-point type T.\n\nExamples\n\njulia> floatmin(Float16)\nFloat16(6.104e-5)\n\njulia> floatmin(Float32)\n1.1754944f-38\n\njulia> floatmin()\n2.2250738585072014e-308\n\n\n\n\n\n","category":"function"},{"location":"base/base/#Base.floatmax","page":"基本功能","title":"Base.floatmax","text":"floatmax(T = Float64)\n\nReturn the largest finite number representable by the floating-point type T.\n\nSee also: typemax, floatmin, eps.\n\nExamples\n\njulia> floatmax(Float16)\nFloat16(6.55e4)\n\njulia> floatmax(Float32)\n3.4028235f38\n\njulia> floatmax()\n1.7976931348623157e308\n\njulia> typemax(Float64)\nInf\n\n\n\n\n\n","category":"function"},{"location":"base/base/#Base.maxintfloat","page":"基本功能","title":"Base.maxintfloat","text":"maxintfloat(T=Float64)\n\nThe largest consecutive integer-valued floating-point number that is exactly represented in the given floating-point type T (which defaults to Float64).\n\nThat is, maxintfloat returns the smallest positive integer-valued floating-point number n such that n+1 is not exactly representable in the type T.\n\nWhen an Integer-type value is needed, use Integer(maxintfloat(T)).\n\n\n\n\n\nmaxintfloat(T, S)\n\nThe largest consecutive integer representable in the given floating-point type T that also does not exceed the maximum integer representable by the integer type S. Equivalently, it is the minimum of maxintfloat(T) and typemax(S).\n\n\n\n\n\n","category":"function"},{"location":"base/base/#Base.eps-Tuple{Type{<:AbstractFloat}}","page":"基本功能","title":"Base.eps","text":"eps(::Type{T}) where T<:AbstractFloat\neps()\n\nReturn the machine epsilon of the floating point type T (T = Float64 by default). This is defined as the gap between 1 and the next largest value representable by typeof(one(T)), and is equivalent to eps(one(T)). (Since eps(T) is a bound on the relative error of T, it is a \"dimensionless\" quantity like one.)\n\nExamples\n\njulia> eps()\n2.220446049250313e-16\n\njulia> eps(Float32)\n1.1920929f-7\n\njulia> 1.0 + eps()\n1.0000000000000002\n\njulia> 1.0 + eps()/2\n1.0\n\n\n\n\n\n","category":"method"},{"location":"base/base/#Base.eps-Tuple{AbstractFloat}","page":"基本功能","title":"Base.eps","text":"eps(x::AbstractFloat)\n\nReturn the unit in last place (ulp) of x. This is the distance between consecutive representable floating point values at x. In most cases, if the distance on either side of x is different, then the larger of the two is taken, that is\n\neps(x) == max(x-prevfloat(x), nextfloat(x)-x)\n\nThe exceptions to this rule are the smallest and largest finite values (e.g. nextfloat(-Inf) and prevfloat(Inf) for Float64), which round to the smaller of the values.\n\nThe rationale for this behavior is that eps bounds the floating point rounding error. Under the default RoundNearest rounding mode, if y is a real number and x is the nearest floating point number to y, then\n\ny-x leq operatornameeps(x)2\n\nSee also: nextfloat, issubnormal, floatmax.\n\nExamples\n\njulia> eps(1.0)\n2.220446049250313e-16\n\njulia> eps(prevfloat(2.0))\n2.220446049250313e-16\n\njulia> eps(2.0)\n4.440892098500626e-16\n\njulia> x = prevfloat(Inf) # largest finite Float64\n1.7976931348623157e308\n\njulia> x + eps(x)/2 # rounds up\nInf\n\njulia> x + prevfloat(eps(x)/2) # rounds down\n1.7976931348623157e308\n\n\n\n\n\n","category":"method"},{"location":"base/base/#Base.instances","page":"基本功能","title":"Base.instances","text":"instances(T::Type)\n\nReturn a collection of all instances of the given type, if applicable. Mostly used for enumerated types (see @enum).\n\nExample\n\njulia> @enum Color red blue green\n\njulia> instances(Color)\n(red, blue, green)\n\n\n\n\n\n","category":"function"},{"location":"base/base/#Special-Types","page":"基本功能","title":"Special Types","text":"","category":"section"},{"location":"base/base/","page":"基本功能","title":"基本功能","text":"Core.Any\nCore.Union\nUnion{}\nCore.UnionAll\nCore.Tuple\nCore.NTuple\nCore.NamedTuple\nBase.@NamedTuple\nBase.Val\nCore.Vararg\nCore.Nothing\nBase.isnothing\nBase.notnothing\nBase.Some\nBase.something\nBase.@something\nBase.Enums.Enum\nBase.Enums.@enum\nCore.Expr\nCore.Symbol\nCore.Symbol(x...)\nCore.Module","category":"page"},{"location":"base/base/#Core.Any","page":"基本功能","title":"Core.Any","text":"Any::DataType\n\nAny is the union of all types. It has the defining property isa(x, Any) == true for any x. Any therefore describes the entire universe of possible values. For example Integer is a subset of Any that includes Int, Int8, and other integer types.\n\n\n\n\n\n","category":"type"},{"location":"base/base/#Core.Union","page":"基本功能","title":"Core.Union","text":"Union{Types...}\n\nA type union is an abstract type which includes all instances of any of its argument types. The empty union Union{} is the bottom type of Julia.\n\nExamples\n\njulia> IntOrString = Union{Int,AbstractString}\nUnion{Int64, AbstractString}\n\njulia> 1 :: IntOrString\n1\n\njulia> \"Hello!\" :: IntOrString\n\"Hello!\"\n\njulia> 1.0 :: IntOrString\nERROR: TypeError: in typeassert, expected Union{Int64, AbstractString}, got a value of type Float64\n\n\n\n\n\n","category":"type"},{"location":"base/base/#Union{}","page":"基本功能","title":"Union{}","text":"Union{}\n\nUnion{}, the empty Union of types, is the type that has no values. That is, it has the defining property isa(x, Union{}) == false for any x. Base.Bottom is defined as its alias and the type of Union{} is Core.TypeofBottom.\n\nExamples\n\njulia> isa(nothing, Union{})\nfalse\n\n\n\n\n\n","category":"keyword"},{"location":"base/base/#Core.UnionAll","page":"基本功能","title":"Core.UnionAll","text":"UnionAll\n\nA union of types over all values of a type parameter. UnionAll is used to describe parametric types where the values of some parameters are not known.\n\nExamples\n\njulia> typeof(Vector)\nUnionAll\n\njulia> typeof(Vector{Int})\nDataType\n\n\n\n\n\n","category":"type"},{"location":"base/base/#Core.Tuple","page":"基本功能","title":"Core.Tuple","text":"Tuple{Types...}\n\nTuples are an abstraction of the arguments of a function – without the function itself. The salient aspects of a function's arguments are their order and their types. Therefore a tuple type is similar to a parameterized immutable type where each parameter is the type of one field. Tuple types may have any number of parameters.\n\nTuple types are covariant in their parameters: Tuple{Int} is a subtype of Tuple{Any}. Therefore Tuple{Any} is considered an abstract type, and tuple types are only concrete if their parameters are. Tuples do not have field names; fields are only accessed by index.\n\nSee the manual section on Tuple Types.\n\nSee also Vararg, NTuple, tuple, NamedTuple.\n\n\n\n\n\n","category":"type"},{"location":"base/base/#Core.NTuple","page":"基本功能","title":"Core.NTuple","text":"NTuple{N, T}\n\nA compact way of representing the type for a tuple of length N where all elements are of type T.\n\nExamples\n\njulia> isa((1, 2, 3, 4, 5, 6), NTuple{6, Int})\ntrue\n\n\n\n\n\n","category":"type"},{"location":"base/base/#Core.NamedTuple","page":"基本功能","title":"Core.NamedTuple","text":"NamedTuple\n\nNamedTuples are, as their name suggests, named Tuples. That is, they're a tuple-like collection of values, where each entry has a unique name, represented as a Symbol. Like Tuples, NamedTuples are immutable; neither the names nor the values can be modified in place after construction.\n\nAccessing the value associated with a name in a named tuple can be done using field access syntax, e.g. x.a, or using getindex, e.g. x[:a] or x[(:a, :b)]. A tuple of the names can be obtained using keys, and a tuple of the values can be obtained using values.\n\nnote: Note\nIteration over NamedTuples produces the values without the names. (See example below.) To iterate over the name-value pairs, use the pairs function.\n\nThe @NamedTuple macro can be used for conveniently declaring NamedTuple types.\n\nExamples\n\njulia> x = (a=1, b=2)\n(a = 1, b = 2)\n\njulia> x.a\n1\n\njulia> x[:a]\n1\n\njulia> x[(:a,)]\n(a = 1,)\n\njulia> keys(x)\n(:a, :b)\n\njulia> values(x)\n(1, 2)\n\njulia> collect(x)\n2-element Vector{Int64}:\n 1\n 2\n\njulia> collect(pairs(x))\n2-element Vector{Pair{Symbol, Int64}}:\n :a => 1\n :b => 2\n\nIn a similar fashion as to how one can define keyword arguments programmatically, a named tuple can be created by giving a pair name::Symbol => value or splatting an iterator yielding such pairs after a semicolon inside a tuple literal:\n\njulia> (; :a => 1)\n(a = 1,)\n\njulia> keys = (:a, :b, :c); values = (1, 2, 3);\n\njulia> (; zip(keys, values)...)\n(a = 1, b = 2, c = 3)\n\nAs in keyword arguments, identifiers and dot expressions imply names:\n\njulia> x = 0\n0\n\njulia> t = (; x)\n(x = 0,)\n\njulia> (; t.x)\n(x = 0,)\n\ncompat: Julia 1.5\nImplicit names from identifiers and dot expressions are available as of Julia 1.5.\n\ncompat: Julia 1.7\nUse of getindex methods with multiple Symbols is available as of Julia 1.7.\n\n\n\n\n\n","category":"type"},{"location":"base/base/#Base.@NamedTuple","page":"基本功能","title":"Base.@NamedTuple","text":"@NamedTuple{key1::Type1, key2::Type2, ...}\n@NamedTuple begin key1::Type1; key2::Type2; ...; end\n\nThis macro gives a more convenient syntax for declaring NamedTuple types. It returns a NamedTuple type with the given keys and types, equivalent to NamedTuple{(:key1, :key2, ...), Tuple{Type1,Type2,...}}. If the ::Type declaration is omitted, it is taken to be Any. The begin ... end form allows the declarations to be split across multiple lines (similar to a struct declaration), but is otherwise equivalent.\n\nFor example, the tuple (a=3.1, b=\"hello\") has a type NamedTuple{(:a, :b),Tuple{Float64,String}}, which can also be declared via @NamedTuple as:\n\njulia> @NamedTuple{a::Float64, b::String}\nNamedTuple{(:a, :b), Tuple{Float64, String}}\n\njulia> @NamedTuple begin\n a::Float64\n b::String\n end\nNamedTuple{(:a, :b), Tuple{Float64, String}}\n\ncompat: Julia 1.5\nThis macro is available as of Julia 1.5.\n\n\n\n\n\n","category":"macro"},{"location":"base/base/#Base.Val","page":"基本功能","title":"Base.Val","text":"Val(c)\n\nReturn Val{c}(), which contains no run-time data. Types like this can be used to pass the information between functions through the value c, which must be an isbits value or a Symbol. The intent of this construct is to be able to dispatch on constants directly (at compile time) without having to test the value of the constant at run time.\n\nExamples\n\njulia> f(::Val{true}) = \"Good\"\nf (generic function with 1 method)\n\njulia> f(::Val{false}) = \"Bad\"\nf (generic function with 2 methods)\n\njulia> f(Val(true))\n\"Good\"\n\n\n\n\n\n","category":"type"},{"location":"base/base/#Core.Vararg","page":"基本功能","title":"Core.Vararg","text":"Vararg{T,N}\n\nThe last parameter of a tuple type Tuple can be the special value Vararg, which denotes any number of trailing elements. Vararg{T,N} corresponds to exactly N elements of type T. Finally Vararg{T} corresponds to zero or more elements of type T. Vararg tuple types are used to represent the arguments accepted by varargs methods (see the section on Varargs Functions in the manual.)\n\nSee also NTuple.\n\nExamples\n\njulia> mytupletype = Tuple{AbstractString, Vararg{Int}}\nTuple{AbstractString, Vararg{Int64}}\n\njulia> isa((\"1\",), mytupletype)\ntrue\n\njulia> isa((\"1\",1), mytupletype)\ntrue\n\njulia> isa((\"1\",1,2), mytupletype)\ntrue\n\njulia> isa((\"1\",1,2,3.0), mytupletype)\nfalse\n\n\n\n\n\n","category":"constant"},{"location":"base/base/#Core.Nothing","page":"基本功能","title":"Core.Nothing","text":"Nothing\n\nA type with no fields that is the type of nothing.\n\nSee also: isnothing, Some, Missing.\n\n\n\n\n\n","category":"type"},{"location":"base/base/#Base.isnothing","page":"基本功能","title":"Base.isnothing","text":"isnothing(x)\n\nReturn true if x === nothing, and return false if not.\n\ncompat: Julia 1.1\nThis function requires at least Julia 1.1.\n\nSee also something, notnothing, ismissing.\n\n\n\n\n\n","category":"function"},{"location":"base/base/#Base.notnothing","page":"基本功能","title":"Base.notnothing","text":"notnothing(x)\n\nThrow an error if x === nothing, and return x if not.\n\n\n\n\n\n","category":"function"},{"location":"base/base/#Base.Some","page":"基本功能","title":"Base.Some","text":"Some{T}\n\nA wrapper type used in Union{Some{T}, Nothing} to distinguish between the absence of a value (nothing) and the presence of a nothing value (i.e. Some(nothing)).\n\nUse something to access the value wrapped by a Some object.\n\n\n\n\n\n","category":"type"},{"location":"base/base/#Base.something","page":"基本功能","title":"Base.something","text":"something(x...)\n\nReturn the first value in the arguments which is not equal to nothing, if any. Otherwise throw an error. Arguments of type Some are unwrapped.\n\nSee also coalesce, skipmissing, @something.\n\nExamples\n\njulia> something(nothing, 1)\n1\n\njulia> something(Some(1), nothing)\n1\n\njulia> something(missing, nothing)\nmissing\n\njulia> something(nothing, nothing)\nERROR: ArgumentError: No value arguments present\n\n\n\n\n\n","category":"function"},{"location":"base/base/#Base.@something","page":"基本功能","title":"Base.@something","text":"@something(x...)\n\nShort-circuiting version of something.\n\nExamples\n\njulia> f(x) = (println(\"f($x)\"); nothing);\n\njulia> a = 1;\n\njulia> a = @something a f(2) f(3) error(\"Unable to find default for `a`\")\n1\n\njulia> b = nothing;\n\njulia> b = @something b f(2) f(3) error(\"Unable to find default for `b`\")\nf(2)\nf(3)\nERROR: Unable to find default for `b`\n[...]\n\njulia> b = @something b f(2) f(3) Some(nothing)\nf(2)\nf(3)\n\njulia> b === nothing\ntrue\n\ncompat: Julia 1.7\nThis macro is available as of Julia 1.7.\n\n\n\n\n\n","category":"macro"},{"location":"base/base/#Base.Enums.Enum","page":"基本功能","title":"Base.Enums.Enum","text":"Enum{T<:Integer}\n\nThe abstract supertype of all enumerated types defined with @enum.\n\n\n\n\n\n","category":"type"},{"location":"base/base/#Base.Enums.@enum","page":"基本功能","title":"Base.Enums.@enum","text":"@enum EnumName[::BaseType] value1[=x] value2[=y]\n\nCreate an Enum{BaseType} subtype with name EnumName and enum member values of value1 and value2 with optional assigned values of x and y, respectively. EnumName can be used just like other types and enum member values as regular values, such as\n\nExamples\n\njulia> @enum Fruit apple=1 orange=2 kiwi=3\n\njulia> f(x::Fruit) = \"I'm a Fruit with value: $(Int(x))\"\nf (generic function with 1 method)\n\njulia> f(apple)\n\"I'm a Fruit with value: 1\"\n\njulia> Fruit(1)\napple::Fruit = 1\n\nValues can also be specified inside a begin block, e.g.\n\n@enum EnumName begin\n value1\n value2\nend\n\nBaseType, which defaults to Int32, must be a primitive subtype of Integer. Member values can be converted between the enum type and BaseType. read and write perform these conversions automatically. In case the enum is created with a non-default BaseType, Integer(value1) will return the integer value1 with the type BaseType.\n\nTo list all the instances of an enum use instances, e.g.\n\njulia> instances(Fruit)\n(apple, orange, kiwi)\n\n\n\n\n\n","category":"macro"},{"location":"base/base/#Core.Expr","page":"基本功能","title":"Core.Expr","text":"Expr(head::Symbol, args...)\n\nA type representing compound expressions in parsed julia code (ASTs). Each expression consists of a head Symbol identifying which kind of expression it is (e.g. a call, for loop, conditional statement, etc.), and subexpressions (e.g. the arguments of a call). The subexpressions are stored in a Vector{Any} field called args.\n\nSee the manual chapter on Metaprogramming and the developer documentation Julia ASTs.\n\nExamples\n\njulia> Expr(:call, :+, 1, 2)\n:(1 + 2)\n\njulia> dump(:(a ? b : c))\nExpr\n head: Symbol if\n args: Array{Any}((3,))\n 1: Symbol a\n 2: Symbol b\n 3: Symbol c\n\n\n\n\n\n","category":"type"},{"location":"base/base/#Core.Symbol","page":"基本功能","title":"Core.Symbol","text":"Symbol\n\nThe type of object used to represent identifiers in parsed julia code (ASTs). Also often used as a name or label to identify an entity (e.g. as a dictionary key). Symbols can be entered using the : quote operator:\n\njulia> :name\n:name\n\njulia> typeof(:name)\nSymbol\n\njulia> x = 42\n42\n\njulia> eval(:x)\n42\n\nSymbols can also be constructed from strings or other values by calling the constructor Symbol(x...).\n\nSymbols are immutable and should be compared using ===. The implementation re-uses the same object for all Symbols with the same name, so comparison tends to be efficient (it can just compare pointers).\n\nUnlike strings, Symbols are \"atomic\" or \"scalar\" entities that do not support iteration over characters.\n\n\n\n\n\n","category":"type"},{"location":"base/base/#Core.Symbol-Tuple","page":"基本功能","title":"Core.Symbol","text":"Symbol(x...) -> Symbol\n\nCreate a Symbol by concatenating the string representations of the arguments together.\n\nExamples\n\njulia> Symbol(\"my\", \"name\")\n:myname\n\njulia> Symbol(\"day\", 4)\n:day4\n\n\n\n\n\n","category":"method"},{"location":"base/base/#Core.Module","page":"基本功能","title":"Core.Module","text":"Module\n\nA Module is a separate global variable workspace. See module and the manual section about modules for details.\n\nModule(name::Symbol=:anonymous, std_imports=true, default_names=true)\n\nReturn a module with the specified name. A baremodule corresponds to Module(:ModuleName, false)\n\nAn empty module containing no names at all can be created with Module(:ModuleName, false, false). This module will not import Base or Core and does not contain a reference to itself.\n\n\n\n\n\n","category":"type"},{"location":"base/base/#Generic-Functions","page":"基本功能","title":"Generic Functions","text":"","category":"section"},{"location":"base/base/","page":"基本功能","title":"基本功能","text":"Core.Function\nBase.hasmethod\nCore.applicable\nBase.isambiguous\nCore.invoke\nBase.@invoke\nBase.invokelatest\nBase.@invokelatest\nnew\nBase.:(|>)\nBase.:(∘)\nBase.ComposedFunction\nBase.splat\nBase.Fix1\nBase.Fix2","category":"page"},{"location":"base/base/#Core.Function","page":"基本功能","title":"Core.Function","text":"Function\n\nAbstract type of all functions.\n\nExamples\n\njulia> isa(+, Function)\ntrue\n\njulia> typeof(sin)\ntypeof(sin) (singleton type of function sin, subtype of Function)\n\njulia> ans <: Function\ntrue\n\n\n\n\n\n","category":"type"},{"location":"base/base/#Base.hasmethod","page":"基本功能","title":"Base.hasmethod","text":"hasmethod(f, t::Type{<:Tuple}[, kwnames]; world=get_world_counter()) -> Bool\n\nDetermine whether the given generic function has a method matching the given Tuple of argument types with the upper bound of world age given by world.\n\nIf a tuple of keyword argument names kwnames is provided, this also checks whether the method of f matching t has the given keyword argument names. If the matching method accepts a variable number of keyword arguments, e.g. with kwargs..., any names given in kwnames are considered valid. Otherwise the provided names must be a subset of the method's keyword arguments.\n\nSee also applicable.\n\ncompat: Julia 1.2\nProviding keyword argument names requires Julia 1.2 or later.\n\nExamples\n\njulia> hasmethod(length, Tuple{Array})\ntrue\n\njulia> f(; oranges=0) = oranges;\n\njulia> hasmethod(f, Tuple{}, (:oranges,))\ntrue\n\njulia> hasmethod(f, Tuple{}, (:apples, :bananas))\nfalse\n\njulia> g(; xs...) = 4;\n\njulia> hasmethod(g, Tuple{}, (:a, :b, :c, :d)) # g accepts arbitrary kwargs\ntrue\n\n\n\n\n\n","category":"function"},{"location":"base/base/#Core.applicable","page":"基本功能","title":"Core.applicable","text":"applicable(f, args...) -> Bool\n\nDetermine whether the given generic function has a method applicable to the given arguments.\n\nSee also hasmethod.\n\nExamples\n\njulia> function f(x, y)\n x + y\n end;\n\njulia> applicable(f, 1)\nfalse\n\njulia> applicable(f, 1, 2)\ntrue\n\n\n\n\n\n","category":"function"},{"location":"base/base/#Base.isambiguous","page":"基本功能","title":"Base.isambiguous","text":"Base.isambiguous(m1, m2; ambiguous_bottom=false) -> Bool\n\nDetermine whether two methods m1 and m2 may be ambiguous for some call signature. This test is performed in the context of other methods of the same function; in isolation, m1 and m2 might be ambiguous, but if a third method resolving the ambiguity has been defined, this returns false. Alternatively, in isolation m1 and m2 might be ordered, but if a third method cannot be sorted with them, they may cause an ambiguity together.\n\nFor parametric types, the ambiguous_bottom keyword argument controls whether Union{} counts as an ambiguous intersection of type parameters – when true, it is considered ambiguous, when false it is not.\n\nExamples\n\njulia> foo(x::Complex{<:Integer}) = 1\nfoo (generic function with 1 method)\n\njulia> foo(x::Complex{<:Rational}) = 2\nfoo (generic function with 2 methods)\n\njulia> m1, m2 = collect(methods(foo));\n\njulia> typeintersect(m1.sig, m2.sig)\nTuple{typeof(foo), Complex{Union{}}}\n\njulia> Base.isambiguous(m1, m2, ambiguous_bottom=true)\ntrue\n\njulia> Base.isambiguous(m1, m2, ambiguous_bottom=false)\nfalse\n\n\n\n\n\n","category":"function"},{"location":"base/base/#Core.invoke","page":"基本功能","title":"Core.invoke","text":"invoke(f, argtypes::Type, args...; kwargs...)\n\nInvoke a method for the given generic function f matching the specified types argtypes on the specified arguments args and passing the keyword arguments kwargs. The arguments args must conform with the specified types in argtypes, i.e. conversion is not automatically performed. This method allows invoking a method other than the most specific matching method, which is useful when the behavior of a more general definition is explicitly needed (often as part of the implementation of a more specific method of the same function).\n\nBe careful when using invoke for functions that you don't write. What definition is used for given argtypes is an implementation detail unless the function is explicitly states that calling with certain argtypes is a part of public API. For example, the change between f1 and f2 in the example below is usually considered compatible because the change is invisible by the caller with a normal (non-invoke) call. However, the change is visible if you use invoke.\n\nExamples\n\njulia> f(x::Real) = x^2;\n\njulia> f(x::Integer) = 1 + invoke(f, Tuple{Real}, x);\n\njulia> f(2)\n5\n\njulia> f1(::Integer) = Integer\n f1(::Real) = Real;\n\njulia> f2(x::Real) = _f2(x)\n _f2(::Integer) = Integer\n _f2(_) = Real;\n\njulia> f1(1)\nInteger\n\njulia> f2(1)\nInteger\n\njulia> invoke(f1, Tuple{Real}, 1)\nReal\n\njulia> invoke(f2, Tuple{Real}, 1)\nInteger\n\n\n\n\n\n","category":"function"},{"location":"base/base/#Base.@invoke","page":"基本功能","title":"Base.@invoke","text":"@invoke f(arg::T, ...; kwargs...)\n\nProvides a convenient way to call invoke; @invoke f(arg1::T1, arg2::T2; kwargs...) will be expanded into invoke(f, Tuple{T1,T2}, arg1, arg2; kwargs...). When an argument's type annotation is omitted, it's specified as Any argument, e.g. @invoke f(arg1::T, arg2) will be expanded into invoke(f, Tuple{T,Any}, arg1, arg2).\n\ncompat: Julia 1.7\nThis macro requires Julia 1.7 or later.\n\n\n\n\n\n","category":"macro"},{"location":"base/base/#Base.invokelatest","page":"基本功能","title":"Base.invokelatest","text":"invokelatest(f, args...; kwargs...)\n\nCalls f(args...; kwargs...), but guarantees that the most recent method of f will be executed. This is useful in specialized circumstances, e.g. long-running event loops or callback functions that may call obsolete versions of a function f. (The drawback is that invokelatest is somewhat slower than calling f directly, and the type of the result cannot be inferred by the compiler.)\n\n\n\n\n\n","category":"function"},{"location":"base/base/#Base.@invokelatest","page":"基本功能","title":"Base.@invokelatest","text":"@invokelatest f(args...; kwargs...)\n\nProvides a convenient way to call Base.invokelatest. @invokelatest f(args...; kwargs...) will simply be expanded into Base.invokelatest(f, args...; kwargs...).\n\ncompat: Julia 1.7\nThis macro requires Julia 1.7 or later.\n\n\n\n\n\n","category":"macro"},{"location":"base/base/#new","page":"基本功能","title":"new","text":"new, or new{A,B,...}\n\nSpecial function available to inner constructors which creates a new object of the type. The form new{A,B,...} explicitly specifies values of parameters for parametric types. See the manual section on Inner Constructor Methods for more information.\n\n\n\n\n\n","category":"keyword"},{"location":"base/base/#Base.:|>","page":"基本功能","title":"Base.:|>","text":"|>(x, f)\n\nApplies a function to the preceding argument. This allows for easy function chaining.\n\nExamples\n\njulia> [1:5;] |> (x->x.^2) |> sum |> inv\n0.01818181818181818\n\n\n\n\n\n","category":"function"},{"location":"base/base/#Base.:∘","page":"基本功能","title":"Base.:∘","text":"f ∘ g\n\nCompose functions: i.e. (f ∘ g)(args...; kwargs...) means f(g(args...; kwargs...)). The ∘ symbol can be entered in the Julia REPL (and most editors, appropriately configured) by typing \\circ.\n\nFunction composition also works in prefix form: ∘(f, g) is the same as f ∘ g. The prefix form supports composition of multiple functions: ∘(f, g, h) = f ∘ g ∘ h and splatting ∘(fs...) for composing an iterable collection of functions.\n\ncompat: Julia 1.4\nMultiple function composition requires at least Julia 1.4.\n\ncompat: Julia 1.5\nComposition of one function ∘(f) requires at least Julia 1.5.\n\ncompat: Julia 1.7\nUsing keyword arguments requires at least Julia 1.7.\n\nExamples\n\njulia> map(uppercase∘first, [\"apple\", \"banana\", \"carrot\"])\n3-element Vector{Char}:\n 'A': ASCII/Unicode U+0041 (category Lu: Letter, uppercase)\n 'B': ASCII/Unicode U+0042 (category Lu: Letter, uppercase)\n 'C': ASCII/Unicode U+0043 (category Lu: Letter, uppercase)\n\njulia> fs = [\n x -> 2x\n x -> x/2\n x -> x-1\n x -> x+1\n ];\n\njulia> ∘(fs...)(3)\n3.0\n\nSee also ComposedFunction, !f::Function.\n\n\n\n\n\n","category":"function"},{"location":"base/base/#Base.ComposedFunction","page":"基本功能","title":"Base.ComposedFunction","text":"ComposedFunction{Outer,Inner} <: Function\n\nRepresents the composition of two callable objects outer::Outer and inner::Inner. That is\n\nComposedFunction(outer, inner)(args...; kw...) === outer(inner(args...; kw...))\n\nThe preferred way to construct instance of ComposedFunction is to use the composition operator ∘:\n\njulia> sin ∘ cos === ComposedFunction(sin, cos)\ntrue\n\njulia> typeof(sin∘cos)\nComposedFunction{typeof(sin), typeof(cos)}\n\nThe composed pieces are stored in the fields of ComposedFunction and can be retrieved as follows:\n\njulia> composition = sin ∘ cos\nsin ∘ cos\n\njulia> composition.outer === sin\ntrue\n\njulia> composition.inner === cos\ntrue\n\ncompat: Julia 1.6\nComposedFunction requires at least Julia 1.6. In earlier versions ∘ returns an anonymous function instead.\n\nSee also ∘.\n\n\n\n\n\n","category":"type"},{"location":"base/base/#Base.splat","page":"基本功能","title":"Base.splat","text":"splat(f)\n\nDefined as\n\n splat(f) = args->f(args...)\n\ni.e. given a function returns a new function that takes one argument and splats its argument into the original function. This is useful as an adaptor to pass a multi-argument function in a context that expects a single argument, but passes a tuple as that single argument.\n\nExample usage:\n\njulia> map(Base.splat(+), zip(1:3,4:6))\n3-element Vector{Int64}:\n 5\n 7\n 9\n\n\n\n\n\n","category":"function"},{"location":"base/base/#Base.Fix1","page":"基本功能","title":"Base.Fix1","text":"Fix1(f, x)\n\nA type representing a partially-applied version of the two-argument function f, with the first argument fixed to the value \"x\". In other words, Fix1(f, x) behaves similarly to y->f(x, y).\n\nSee also Fix2.\n\n\n\n\n\n","category":"type"},{"location":"base/base/#Base.Fix2","page":"基本功能","title":"Base.Fix2","text":"Fix2(f, x)\n\nA type representing a partially-applied version of the two-argument function f, with the second argument fixed to the value \"x\". In other words, Fix2(f, x) behaves similarly to y->f(y, x).\n\n\n\n\n\n","category":"type"},{"location":"base/base/#Syntax","page":"基本功能","title":"Syntax","text":"","category":"section"},{"location":"base/base/","page":"基本功能","title":"基本功能","text":"Core.eval\nBase.MainInclude.eval\nBase.@eval\nBase.evalfile\nBase.esc\nBase.@inbounds\nBase.@boundscheck\nBase.@propagate_inbounds\nBase.@inline\nBase.@noinline\nBase.@nospecialize\nBase.@specialize\nBase.gensym\nBase.@gensym\nvar\"name\"\nBase.@goto\nBase.@label\nBase.@simd\nBase.@polly\nBase.@generated\nBase.@pure\nBase.@deprecate","category":"page"},{"location":"base/base/#Core.eval","page":"基本功能","title":"Core.eval","text":"Core.eval(m::Module, expr)\n\nEvaluate an expression in the given module and return the result.\n\n\n\n\n\n","category":"function"},{"location":"base/base/#Base.MainInclude.eval","page":"基本功能","title":"Base.MainInclude.eval","text":"eval(expr)\n\nEvaluate an expression in the global scope of the containing module. Every Module (except those defined with baremodule) has its own 1-argument definition of eval, which evaluates expressions in that module.\n\n\n\n\n\n","category":"function"},{"location":"base/base/#Base.@eval","page":"基本功能","title":"Base.@eval","text":"@eval [mod,] ex\n\nEvaluate an expression with values interpolated into it using eval. If two arguments are provided, the first is the module to evaluate in.\n\n\n\n\n\n","category":"macro"},{"location":"base/base/#Base.evalfile","page":"基本功能","title":"Base.evalfile","text":"evalfile(path::AbstractString, args::Vector{String}=String[])\n\nLoad the file using include, evaluate all expressions, and return the value of the last one.\n\n\n\n\n\n","category":"function"},{"location":"base/base/#Base.esc","page":"基本功能","title":"Base.esc","text":"esc(e)\n\nOnly valid in the context of an Expr returned from a macro. Prevents the macro hygiene pass from turning embedded variables into gensym variables. See the Macros section of the Metaprogramming chapter of the manual for more details and examples.\n\n\n\n\n\n","category":"function"},{"location":"base/base/#Base.@inbounds","page":"基本功能","title":"Base.@inbounds","text":"@inbounds(blk)\n\nEliminates array bounds checking within expressions.\n\nIn the example below the in-range check for referencing element i of array A is skipped to improve performance.\n\nfunction sum(A::AbstractArray)\n r = zero(eltype(A))\n for i in eachindex(A)\n @inbounds r += A[i]\n end\n return r\nend\n\nwarning: Warning\nUsing @inbounds may return incorrect results/crashes/corruption for out-of-bounds indices. The user is responsible for checking it manually. Only use @inbounds when it is certain from the information locally available that all accesses are in bounds.\n\n\n\n\n\n","category":"macro"},{"location":"base/base/#Base.@boundscheck","page":"基本功能","title":"Base.@boundscheck","text":"@boundscheck(blk)\n\nAnnotates the expression blk as a bounds checking block, allowing it to be elided by @inbounds.\n\nnote: Note\nThe function in which @boundscheck is written must be inlined into its caller in order for @inbounds to have effect.\n\nExamples\n\njulia> @inline function g(A, i)\n @boundscheck checkbounds(A, i)\n return \"accessing ($A)[$i]\"\n end;\n\njulia> f1() = return g(1:2, -1);\n\njulia> f2() = @inbounds return g(1:2, -1);\n\njulia> f1()\nERROR: BoundsError: attempt to access 2-element UnitRange{Int64} at index [-1]\nStacktrace:\n [1] throw_boundserror(::UnitRange{Int64}, ::Tuple{Int64}) at ./abstractarray.jl:455\n [2] checkbounds at ./abstractarray.jl:420 [inlined]\n [3] g at ./none:2 [inlined]\n [4] f1() at ./none:1\n [5] top-level scope\n\njulia> f2()\n\"accessing (1:2)[-1]\"\n\nwarning: Warning\nThe @boundscheck annotation allows you, as a library writer, to opt-in to allowing other code to remove your bounds checks with @inbounds. As noted there, the caller must verify—using information they can access—that their accesses are valid before using @inbounds. For indexing into your AbstractArray subclasses, for example, this involves checking the indices against its axes. Therefore, @boundscheck annotations should only be added to a getindex or setindex! implementation after you are certain its behavior is correct.\n\n\n\n\n\n","category":"macro"},{"location":"base/base/#Base.@propagate_inbounds","page":"基本功能","title":"Base.@propagate_inbounds","text":"@propagate_inbounds\n\nTells the compiler to inline a function while retaining the caller's inbounds context.\n\n\n\n\n\n","category":"macro"},{"location":"base/base/#Base.@inline","page":"基本功能","title":"Base.@inline","text":"@inline\n\nGive a hint to the compiler that this function is worth inlining.\n\nSmall functions typically do not need the @inline annotation, as the compiler does it automatically. By using @inline on bigger functions, an extra nudge can be given to the compiler to inline it.\n\n@inline can be applied immediately before the definition or in its function body.\n\n# annotate long-form definition\n@inline function longdef(x)\n ...\nend\n\n# annotate short-form definition\n@inline shortdef(x) = ...\n\n# annotate anonymous function that a `do` block creates\nf() do\n @inline\n ...\nend\n\ncompat: Julia 1.8\nThe usage within a function body requires at least Julia 1.8.\n\n\n\n@inline block\n\nGive a hint to the compiler that calls within block are worth inlining.\n\n# The compiler will try to inline `f`\n@inline f(...)\n\n# The compiler will try to inline `f`, `g` and `+`\n@inline f(...) + g(...)\n\nnote: Note\nA callsite annotation always has the precedence over the annotation applied to the definition of the called function:@noinline function explicit_noinline(args...)\n # body\nend\n\nlet\n @inline explicit_noinline(args...) # will be inlined\nend\n\nnote: Note\nWhen there are nested callsite annotations, the innermost annotation has the precedence:@noinline let a0, b0 = ...\n a = @inline f(a0) # the compiler will try to inline this call\n b = f(b0) # the compiler will NOT try to inline this call\n return a, b\nend\n\nwarning: Warning\nAlthough a callsite annotation will try to force inlining in regardless of the cost model, there are still chances it can't succeed in it. Especially, recursive calls can not be inlined even if they are annotated as @inlined.\n\ncompat: Julia 1.8\nThe callsite annotation requires at least Julia 1.8.\n\n\n\n\n\n","category":"macro"},{"location":"base/base/#Base.@noinline","page":"基本功能","title":"Base.@noinline","text":"@noinline\n\nGive a hint to the compiler that it should not inline a function.\n\nSmall functions are typically inlined automatically. By using @noinline on small functions, auto-inlining can be prevented.\n\n@noinline can be applied immediately before the definition or in its function body.\n\n# annotate long-form definition\n@noinline function longdef(x)\n ...\nend\n\n# annotate short-form definition\n@noinline shortdef(x) = ...\n\n# annotate anonymous function that a `do` block creates\nf() do\n @noinline\n ...\nend\n\ncompat: Julia 1.8\nThe usage within a function body requires at least Julia 1.8.\n\n\n\n@noinline block\n\nGive a hint to the compiler that it should not inline the calls within block.\n\n# The compiler will try to not inline `f`\n@noinline f(...)\n\n# The compiler will try to not inline `f`, `g` and `+`\n@noinline f(...) + g(...)\n\nnote: Note\nA callsite annotation always has the precedence over the annotation applied to the definition of the called function:@inline function explicit_inline(args...)\n # body\nend\n\nlet\n @noinline explicit_inline(args...) # will not be inlined\nend\n\nnote: Note\nWhen there are nested callsite annotations, the innermost annotation has the precedence:@inline let a0, b0 = ...\n a = @noinline f(a0) # the compiler will NOT try to inline this call\n b = f(b0) # the compiler will try to inline this call\n return a, b\nend\n\ncompat: Julia 1.8\nThe callsite annotation requires at least Julia 1.8.\n\n\n\nnote: Note\nIf the function is trivial (for example returning a constant) it might get inlined anyway.\n\n\n\n\n\n","category":"macro"},{"location":"base/base/#Base.@nospecialize","page":"基本功能","title":"Base.@nospecialize","text":"@nospecialize\n\nApplied to a function argument name, hints to the compiler that the method should not be specialized for different types of that argument, but instead to use precisely the declared type for each argument. This is only a hint for avoiding excess code generation. Can be applied to an argument within a formal argument list, or in the function body. When applied to an argument, the macro must wrap the entire argument expression. When used in a function body, the macro must occur in statement position and before any code.\n\nWhen used without arguments, it applies to all arguments of the parent scope. In local scope, this means all arguments of the containing function. In global (top-level) scope, this means all methods subsequently defined in the current module.\n\nSpecialization can reset back to the default by using @specialize.\n\nfunction example_function(@nospecialize x)\n ...\nend\n\nfunction example_function(x, @nospecialize(y = 1))\n ...\nend\n\nfunction example_function(x, y, z)\n @nospecialize x y\n ...\nend\n\n@nospecialize\nf(y) = [x for x in y]\n@specialize\n\n\n\n\n\n","category":"macro"},{"location":"base/base/#Base.@specialize","page":"基本功能","title":"Base.@specialize","text":"@specialize\n\nReset the specialization hint for an argument back to the default. For details, see @nospecialize.\n\n\n\n\n\n","category":"macro"},{"location":"base/base/#Base.gensym","page":"基本功能","title":"Base.gensym","text":"gensym([tag])\n\nGenerates a symbol which will not conflict with other variable names.\n\n\n\n\n\n","category":"function"},{"location":"base/base/#Base.@gensym","page":"基本功能","title":"Base.@gensym","text":"@gensym\n\nGenerates a gensym symbol for a variable. For example, @gensym x y is transformed into x = gensym(\"x\"); y = gensym(\"y\").\n\n\n\n\n\n","category":"macro"},{"location":"base/base/#var\"name\"","page":"基本功能","title":"var\"name\"","text":"var\n\nThe syntax var\"#example#\" refers to a variable named Symbol(\"#example#\"), even though #example# is not a valid Julia identifier name.\n\nThis can be useful for interoperability with programming languages which have different rules for the construction of valid identifiers. For example, to refer to the R variable draw.segments, you can use var\"draw.segments\" in your Julia code.\n\nIt is also used to show julia source code which has gone through macro hygiene or otherwise contains variable names which can't be parsed normally.\n\nNote that this syntax requires parser support so it is expanded directly by the parser rather than being implemented as a normal string macro @var_str.\n\ncompat: Julia 1.3\nThis syntax requires at least Julia 1.3.\n\n\n\n\n\n","category":"keyword"},{"location":"base/base/#Base.@goto","page":"基本功能","title":"Base.@goto","text":"@goto name\n\n@goto name unconditionally jumps to the statement at the location @label name.\n\n@label and @goto cannot create jumps to different top-level statements. Attempts cause an error. To still use @goto, enclose the @label and @goto in a block.\n\n\n\n\n\n","category":"macro"},{"location":"base/base/#Base.@label","page":"基本功能","title":"Base.@label","text":"@label name\n\nLabels a statement with the symbolic label name. The label marks the end-point of an unconditional jump with @goto name.\n\n\n\n\n\n","category":"macro"},{"location":"base/base/#Base.SimdLoop.@simd","page":"基本功能","title":"Base.SimdLoop.@simd","text":"@simd\n\nAnnotate a for loop to allow the compiler to take extra liberties to allow loop re-ordering\n\nwarning: Warning\nThis feature is experimental and could change or disappear in future versions of Julia. Incorrect use of the @simd macro may cause unexpected results.\n\nThe object iterated over in a @simd for loop should be a one-dimensional range. By using @simd, you are asserting several properties of the loop:\n\nIt is safe to execute iterations in arbitrary or overlapping order, with special consideration for reduction variables.\nFloating-point operations on reduction variables can be reordered, possibly causing different results than without @simd.\n\nIn many cases, Julia is able to automatically vectorize inner for loops without the use of @simd. Using @simd gives the compiler a little extra leeway to make it possible in more situations. In either case, your inner loop should have the following properties to allow vectorization:\n\nThe loop must be an innermost loop\nThe loop body must be straight-line code. Therefore, @inbounds is currently needed for all array accesses. The compiler can sometimes turn short &&, ||, and ?: expressions into straight-line code if it is safe to evaluate all operands unconditionally. Consider using the ifelse function instead of ?: in the loop if it is safe to do so.\nAccesses must have a stride pattern and cannot be \"gathers\" (random-index reads) or \"scatters\" (random-index writes).\nThe stride should be unit stride.\n\nnote: Note\nThe @simd does not assert by default that the loop is completely free of loop-carried memory dependencies, which is an assumption that can easily be violated in generic code. If you are writing non-generic code, you can use @simd ivdep for ... end to also assert that:\n\nThere exists no loop-carried memory dependencies\nNo iteration ever waits on a previous iteration to make forward progress.\n\n\n\n\n\n","category":"macro"},{"location":"base/base/#Base.@polly","page":"基本功能","title":"Base.@polly","text":"@polly\n\nTells the compiler to apply the polyhedral optimizer Polly to a function.\n\n\n\n\n\n","category":"macro"},{"location":"base/base/#Base.@generated","page":"基本功能","title":"Base.@generated","text":"@generated f\n\n@generated is used to annotate a function which will be generated. In the body of the generated function, only types of arguments can be read (not the values). The function returns a quoted expression evaluated when the function is called. The @generated macro should not be used on functions mutating the global scope or depending on mutable elements.\n\nSee Metaprogramming for further details.\n\nExample:\n\njulia> @generated function bar(x)\n if x <: Integer\n return :(x ^ 2)\n else\n return :(x)\n end\n end\nbar (generic function with 1 method)\n\njulia> bar(4)\n16\n\njulia> bar(\"baz\")\n\"baz\"\n\n\n\n\n\n","category":"macro"},{"location":"base/base/#Base.@pure","page":"基本功能","title":"Base.@pure","text":"@pure ex\n\n@pure gives the compiler a hint for the definition of a pure function, helping for type inference.\n\nwarning: Warning\nThis macro is intended for internal compiler use and may be subject to changes.\n\nwarning: Warning\nIn Julia 1.8 and higher, it is favorable to use @assume_effects instead of @pure. This is because @assume_effects allows a finer grained control over Julia's purity modeling and the effect system enables a wider range of optimizations.\n\n\n\n\n\n","category":"macro"},{"location":"base/base/#Base.@deprecate","page":"基本功能","title":"Base.@deprecate","text":"@deprecate old new [export_old=true]\n\nDeprecate method old and specify the replacement call new. Prevent @deprecate from exporting old by setting export_old to false. @deprecate defines a new method with the same signature as old.\n\ncompat: Julia 1.5\nAs of Julia 1.5, functions defined by @deprecate do not print warning when julia is run without the --depwarn=yes flag set, as the default value of --depwarn option is no. The warnings are printed from tests run by Pkg.test().\n\nExamples\n\njulia> @deprecate old(x) new(x)\nold (generic function with 1 method)\n\njulia> @deprecate old(x) new(x) false\nold (generic function with 1 method)\n\n\n\n\n\n","category":"macro"},{"location":"base/base/#Missing-Values","page":"基本功能","title":"Missing Values","text":"","category":"section"},{"location":"base/base/","page":"基本功能","title":"基本功能","text":"Base.Missing\nBase.missing\nBase.coalesce\nBase.@coalesce\nBase.ismissing\nBase.skipmissing\nBase.nonmissingtype","category":"page"},{"location":"base/base/#Base.Missing","page":"基本功能","title":"Base.Missing","text":"Missing\n\nA type with no fields whose singleton instance missing is used to represent missing values.\n\nSee also: skipmissing, nonmissingtype, Nothing.\n\n\n\n\n\n","category":"type"},{"location":"base/base/#Base.missing","page":"基本功能","title":"Base.missing","text":"missing\n\nThe singleton instance of type Missing representing a missing value.\n\nSee also: NaN, skipmissing, nonmissingtype.\n\n\n\n\n\n","category":"constant"},{"location":"base/base/#Base.coalesce","page":"基本功能","title":"Base.coalesce","text":"coalesce(x...)\n\nReturn the first value in the arguments which is not equal to missing, if any. Otherwise return missing.\n\nSee also skipmissing, something, @coalesce.\n\nExamples\n\njulia> coalesce(missing, 1)\n1\n\njulia> coalesce(1, missing)\n1\n\njulia> coalesce(nothing, 1) # returns `nothing`\n\njulia> coalesce(missing, missing)\nmissing\n\n\n\n\n\n","category":"function"},{"location":"base/base/#Base.@coalesce","page":"基本功能","title":"Base.@coalesce","text":"@coalesce(x...)\n\nShort-circuiting version of coalesce.\n\nExamples\n\njulia> f(x) = (println(\"f($x)\"); missing);\n\njulia> a = 1;\n\njulia> a = @coalesce a f(2) f(3) error(\"`a` is still missing\")\n1\n\njulia> b = missing;\n\njulia> b = @coalesce b f(2) f(3) error(\"`b` is still missing\")\nf(2)\nf(3)\nERROR: `b` is still missing\n[...]\n\ncompat: Julia 1.7\nThis macro is available as of Julia 1.7.\n\n\n\n\n\n","category":"macro"},{"location":"base/base/#Base.ismissing","page":"基本功能","title":"Base.ismissing","text":"ismissing(x)\n\nIndicate whether x is missing.\n\nSee also: skipmissing, isnothing, isnan.\n\n\n\n\n\n","category":"function"},{"location":"base/base/#Base.skipmissing","page":"基本功能","title":"Base.skipmissing","text":"skipmissing(itr)\n\nReturn an iterator over the elements in itr skipping missing values. The returned object can be indexed using indices of itr if the latter is indexable. Indices corresponding to missing values are not valid: they are skipped by keys and eachindex, and a MissingException is thrown when trying to use them.\n\nUse collect to obtain an Array containing the non-missing values in itr. Note that even if itr is a multidimensional array, the result will always be a Vector since it is not possible to remove missings while preserving dimensions of the input.\n\nSee also coalesce, ismissing, something.\n\nExamples\n\njulia> x = skipmissing([1, missing, 2])\nskipmissing(Union{Missing, Int64}[1, missing, 2])\n\njulia> sum(x)\n3\n\njulia> x[1]\n1\n\njulia> x[2]\nERROR: MissingException: the value at index (2,) is missing\n[...]\n\njulia> argmax(x)\n3\n\njulia> collect(keys(x))\n2-element Vector{Int64}:\n 1\n 3\n\njulia> collect(skipmissing([1, missing, 2]))\n2-element Vector{Int64}:\n 1\n 2\n\njulia> collect(skipmissing([1 missing; 2 missing]))\n2-element Vector{Int64}:\n 1\n 2\n\n\n\n\n\n","category":"function"},{"location":"base/base/#Base.nonmissingtype","page":"基本功能","title":"Base.nonmissingtype","text":"nonmissingtype(T::Type)\n\nIf T is a union of types containing Missing, return a new type with Missing removed.\n\nExamples\n\njulia> nonmissingtype(Union{Int64,Missing})\nInt64\n\njulia> nonmissingtype(Any)\nAny\n\ncompat: Julia 1.3\nThis function is exported as of Julia 1.3.\n\n\n\n\n\n","category":"function"},{"location":"base/base/#System","page":"基本功能","title":"System","text":"","category":"section"},{"location":"base/base/","page":"基本功能","title":"基本功能","text":"Base.run\nBase.devnull\nBase.success\nBase.process_running\nBase.process_exited\nBase.kill(::Base.Process, ::Integer)\nBase.Sys.set_process_title\nBase.Sys.get_process_title\nBase.ignorestatus\nBase.detach\nBase.Cmd\nBase.setenv\nBase.addenv\nBase.withenv\nBase.pipeline(::Any, ::Any, ::Any, ::Any...)\nBase.pipeline(::Base.AbstractCmd)\nBase.Libc.gethostname\nBase.Libc.getpid\nBase.Libc.time()\nBase.time_ns\nBase.@time\nBase.@timev\nBase.@timed\nBase.@elapsed\nBase.@allocated\nBase.EnvDict\nBase.ENV\nBase.Sys.isunix\nBase.Sys.isapple\nBase.Sys.islinux\nBase.Sys.isbsd\nBase.Sys.isfreebsd\nBase.Sys.isopenbsd\nBase.Sys.isnetbsd\nBase.Sys.isdragonfly\nBase.Sys.iswindows\nBase.Sys.windows_version\nBase.Sys.free_memory\nBase.Sys.total_memory\nBase.@static","category":"page"},{"location":"base/base/#Base.run","page":"基本功能","title":"Base.run","text":"run(command, args...; wait::Bool = true)\n\nRun a command object, constructed with backticks (see the Running External Programs section in the manual). Throws an error if anything goes wrong, including the process exiting with a non-zero status (when wait is true).\n\nThe args... allow you to pass through file descriptors to the command, and are ordered like regular unix file descriptors (eg stdin, stdout, stderr, FD(3), FD(4)...).\n\nIf wait is false, the process runs asynchronously. You can later wait for it and check its exit status by calling success on the returned process object.\n\nWhen wait is false, the process' I/O streams are directed to devnull. When wait is true, I/O streams are shared with the parent process. Use pipeline to control I/O redirection.\n\n\n\n\n\n","category":"function"},{"location":"base/base/#Base.devnull","page":"基本功能","title":"Base.devnull","text":"devnull\n\nUsed in a stream redirect to discard all data written to it. Essentially equivalent to /dev/null on Unix or NUL on Windows. Usage:\n\nrun(pipeline(`cat test.txt`, devnull))\n\n\n\n\n\n","category":"constant"},{"location":"base/base/#Base.success","page":"基本功能","title":"Base.success","text":"success(command)\n\nRun a command object, constructed with backticks (see the Running External Programs section in the manual), and tell whether it was successful (exited with a code of 0). An exception is raised if the process cannot be started.\n\n\n\n\n\n","category":"function"},{"location":"base/base/#Base.process_running","page":"基本功能","title":"Base.process_running","text":"process_running(p::Process)\n\nDetermine whether a process is currently running.\n\n\n\n\n\n","category":"function"},{"location":"base/base/#Base.process_exited","page":"基本功能","title":"Base.process_exited","text":"process_exited(p::Process)\n\nDetermine whether a process has exited.\n\n\n\n\n\n","category":"function"},{"location":"base/base/#Base.kill-Tuple{Base.Process, Integer}","page":"基本功能","title":"Base.kill","text":"kill(p::Process, signum=Base.SIGTERM)\n\nSend a signal to a process. The default is to terminate the process. Returns successfully if the process has already exited, but throws an error if killing the process failed for other reasons (e.g. insufficient permissions).\n\n\n\n\n\n","category":"method"},{"location":"base/base/#Base.Sys.set_process_title","page":"基本功能","title":"Base.Sys.set_process_title","text":"Sys.set_process_title(title::AbstractString)\n\nSet the process title. No-op on some operating systems.\n\n\n\n\n\n","category":"function"},{"location":"base/base/#Base.Sys.get_process_title","page":"基本功能","title":"Base.Sys.get_process_title","text":"Sys.get_process_title()\n\nGet the process title. On some systems, will always return an empty string.\n\n\n\n\n\n","category":"function"},{"location":"base/base/#Base.ignorestatus","page":"基本功能","title":"Base.ignorestatus","text":"ignorestatus(command)\n\nMark a command object so that running it will not throw an error if the result code is non-zero.\n\n\n\n\n\n","category":"function"},{"location":"base/base/#Base.detach","page":"基本功能","title":"Base.detach","text":"detach(command)\n\nMark a command object so that it will be run in a new process group, allowing it to outlive the julia process, and not have Ctrl-C interrupts passed to it.\n\n\n\n\n\n","category":"function"},{"location":"base/base/#Base.Cmd","page":"基本功能","title":"Base.Cmd","text":"Cmd(cmd::Cmd; ignorestatus, detach, windows_verbatim, windows_hide, env, dir)\n\nConstruct a new Cmd object, representing an external program and arguments, from cmd, while changing the settings of the optional keyword arguments:\n\nignorestatus::Bool: If true (defaults to false), then the Cmd will not throw an error if the return code is nonzero.\ndetach::Bool: If true (defaults to false), then the Cmd will be run in a new process group, allowing it to outlive the julia process and not have Ctrl-C passed to it.\nwindows_verbatim::Bool: If true (defaults to false), then on Windows the Cmd will send a command-line string to the process with no quoting or escaping of arguments, even arguments containing spaces. (On Windows, arguments are sent to a program as a single \"command-line\" string, and programs are responsible for parsing it into arguments. By default, empty arguments and arguments with spaces or tabs are quoted with double quotes \" in the command line, and \\ or \" are preceded by backslashes. windows_verbatim=true is useful for launching programs that parse their command line in nonstandard ways.) Has no effect on non-Windows systems.\nwindows_hide::Bool: If true (defaults to false), then on Windows no new console window is displayed when the Cmd is executed. This has no effect if a console is already open or on non-Windows systems.\nenv: Set environment variables to use when running the Cmd. env is either a dictionary mapping strings to strings, an array of strings of the form \"var=val\", an array or tuple of \"var\"=>val pairs. In order to modify (rather than replace) the existing environment, initialize env with copy(ENV) and then set env[\"var\"]=val as desired. To add to an environment block within a Cmd object without replacing all elements, use addenv() which will return a Cmd object with the updated environment.\ndir::AbstractString: Specify a working directory for the command (instead of the current directory).\n\nFor any keywords that are not specified, the current settings from cmd are used. Normally, to create a Cmd object in the first place, one uses backticks, e.g.\n\nCmd(`echo \"Hello world\"`, ignorestatus=true, detach=false)\n\n\n\n\n\n","category":"type"},{"location":"base/base/#Base.setenv","page":"基本功能","title":"Base.setenv","text":"setenv(command::Cmd, env; dir)\n\nSet environment variables to use when running the given command. env is either a dictionary mapping strings to strings, an array of strings of the form \"var=val\", or zero or more \"var\"=>val pair arguments. In order to modify (rather than replace) the existing environment, create env through copy(ENV) and then setting env[\"var\"]=val as desired, or use addenv.\n\nThe dir keyword argument can be used to specify a working directory for the command. dir defaults to the currently set dir for command (which is the current working directory if not specified already).\n\nSee also Cmd, addenv, ENV, pwd.\n\n\n\n\n\n","category":"function"},{"location":"base/base/#Base.addenv","page":"基本功能","title":"Base.addenv","text":"addenv(command::Cmd, env...; inherit::Bool = true)\n\nMerge new environment mappings into the given Cmd object, returning a new Cmd object. Duplicate keys are replaced. If command does not contain any environment values set already, it inherits the current environment at time of addenv() call if inherit is true. Keys with value nothing are deleted from the env.\n\nSee also Cmd, setenv, ENV.\n\ncompat: Julia 1.6\nThis function requires Julia 1.6 or later.\n\n\n\n\n\n","category":"function"},{"location":"base/base/#Base.withenv","page":"基本功能","title":"Base.withenv","text":"withenv(f, kv::Pair...)\n\nExecute f in an environment that is temporarily modified (not replaced as in setenv) by zero or more \"var\"=>val arguments kv. withenv is generally used via the withenv(kv...) do ... end syntax. A value of nothing can be used to temporarily unset an environment variable (if it is set). When withenv returns, the original environment has been restored.\n\n\n\n\n\n","category":"function"},{"location":"base/base/#Base.pipeline-Tuple{Any, Any, Any, Vararg{Any}}","page":"基本功能","title":"Base.pipeline","text":"pipeline(from, to, ...)\n\nCreate a pipeline from a data source to a destination. The source and destination can be commands, I/O streams, strings, or results of other pipeline calls. At least one argument must be a command. Strings refer to filenames. When called with more than two arguments, they are chained together from left to right. For example, pipeline(a,b,c) is equivalent to pipeline(pipeline(a,b),c). This provides a more concise way to specify multi-stage pipelines.\n\nExamples:\n\nrun(pipeline(`ls`, `grep xyz`))\nrun(pipeline(`ls`, \"out.txt\"))\nrun(pipeline(\"out.txt\", `grep xyz`))\n\n\n\n\n\n","category":"method"},{"location":"base/base/#Base.pipeline-Tuple{Base.AbstractCmd}","page":"基本功能","title":"Base.pipeline","text":"pipeline(command; stdin, stdout, stderr, append=false)\n\nRedirect I/O to or from the given command. Keyword arguments specify which of the command's streams should be redirected. append controls whether file output appends to the file. This is a more general version of the 2-argument pipeline function. pipeline(from, to) is equivalent to pipeline(from, stdout=to) when from is a command, and to pipeline(to, stdin=from) when from is another kind of data source.\n\nExamples:\n\nrun(pipeline(`dothings`, stdout=\"out.txt\", stderr=\"errs.txt\"))\nrun(pipeline(`update`, stdout=\"log.txt\", append=true))\n\n\n\n\n\n","category":"method"},{"location":"base/base/#Base.Libc.gethostname","page":"基本功能","title":"Base.Libc.gethostname","text":"gethostname() -> AbstractString\n\nGet the local machine's host name.\n\n\n\n\n\n","category":"function"},{"location":"base/base/#Base.Libc.getpid","page":"基本功能","title":"Base.Libc.getpid","text":"getpid(process) -> Int32\n\nGet the child process ID, if it still exists.\n\ncompat: Julia 1.1\nThis function requires at least Julia 1.1.\n\n\n\n\n\ngetpid() -> Int32\n\nGet Julia's process ID.\n\n\n\n\n\n","category":"function"},{"location":"base/base/#Base.Libc.time-Tuple{}","page":"基本功能","title":"Base.Libc.time","text":"time()\n\nGet the system time in seconds since the epoch, with fairly high (typically, microsecond) resolution.\n\n\n\n\n\n","category":"method"},{"location":"base/base/#Base.time_ns","page":"基本功能","title":"Base.time_ns","text":"time_ns()\n\nGet the time in nanoseconds. The time corresponding to 0 is undefined, and wraps every 5.8 years.\n\n\n\n\n\n","category":"function"},{"location":"base/base/#Base.@time","page":"基本功能","title":"Base.@time","text":"@time expr\n@time \"description\" expr\n\nA macro to execute an expression, printing the time it took to execute, the number of allocations, and the total number of bytes its execution caused to be allocated, before returning the value of the expression. Any time spent garbage collecting (gc), compiling new code, or recompiling invalidated code is shown as a percentage.\n\nOptionally provide a description string to print before the time report.\n\nIn some cases the system will look inside the @time expression and compile some of the called code before execution of the top-level expression begins. When that happens, some compilation time will not be counted. To include this time you can run @time @eval ....\n\nSee also @showtime, @timev, @timed, @elapsed, and @allocated.\n\nnote: Note\nFor more serious benchmarking, consider the @btime macro from the BenchmarkTools.jl package which among other things evaluates the function multiple times in order to reduce noise.\n\ncompat: Julia 1.8\nThe option to add a description was introduced in Julia 1.8.Recompilation time being shown separately from compilation time was introduced in Julia 1.8\n\njulia> x = rand(10,10);\n\njulia> @time x * x;\n 0.606588 seconds (2.19 M allocations: 116.555 MiB, 3.75% gc time, 99.94% compilation time)\n\njulia> @time x * x;\n 0.000009 seconds (1 allocation: 896 bytes)\n\njulia> @time begin\n sleep(0.3)\n 1+1\n end\n 0.301395 seconds (8 allocations: 336 bytes)\n2\n\njulia> @time \"A one second sleep\" sleep(1)\nA one second sleep: 1.005750 seconds (5 allocations: 144 bytes)\n\njulia> for loop in 1:3\n @time loop sleep(1)\n end\n1: 1.006760 seconds (5 allocations: 144 bytes)\n2: 1.001263 seconds (5 allocations: 144 bytes)\n3: 1.003676 seconds (5 allocations: 144 bytes)\n\n\n\n\n\n","category":"macro"},{"location":"base/base/#Base.@timev","page":"基本功能","title":"Base.@timev","text":"@timev expr\n@timev \"description\" expr\n\nThis is a verbose version of the @time macro. It first prints the same information as @time, then any non-zero memory allocation counters, and then returns the value of the expression.\n\nOptionally provide a description string to print before the time report.\n\ncompat: Julia 1.8\nThe option to add a description was introduced in Julia 1.8.\n\nSee also @time, @timed, @elapsed, and @allocated.\n\njulia> x = rand(10,10);\n\njulia> @timev x * x;\n 0.546770 seconds (2.20 M allocations: 116.632 MiB, 4.23% gc time, 99.94% compilation time)\nelapsed time (ns): 546769547\ngc time (ns): 23115606\nbytes allocated: 122297811\npool allocs: 2197930\nnon-pool GC allocs:1327\nmalloc() calls: 36\nrealloc() calls: 5\nGC pauses: 3\n\njulia> @timev x * x;\n 0.000010 seconds (1 allocation: 896 bytes)\nelapsed time (ns): 9848\nbytes allocated: 896\npool allocs: 1\n\n\n\n\n\n","category":"macro"},{"location":"base/base/#Base.@timed","page":"基本功能","title":"Base.@timed","text":"@timed\n\nA macro to execute an expression, and return the value of the expression, elapsed time, total bytes allocated, garbage collection time, and an object with various memory allocation counters.\n\nIn some cases the system will look inside the @timed expression and compile some of the called code before execution of the top-level expression begins. When that happens, some compilation time will not be counted. To include this time you can run @timed @eval ....\n\nSee also @time, @timev, @elapsed, and @allocated.\n\njulia> stats = @timed rand(10^6);\n\njulia> stats.time\n0.006634834\n\njulia> stats.bytes\n8000256\n\njulia> stats.gctime\n0.0055765\n\njulia> propertynames(stats.gcstats)\n(:allocd, :malloc, :realloc, :poolalloc, :bigalloc, :freecall, :total_time, :pause, :full_sweep)\n\njulia> stats.gcstats.total_time\n5576500\n\ncompat: Julia 1.5\nThe return type of this macro was changed from Tuple to NamedTuple in Julia 1.5.\n\n\n\n\n\n","category":"macro"},{"location":"base/base/#Base.@elapsed","page":"基本功能","title":"Base.@elapsed","text":"@elapsed\n\nA macro to evaluate an expression, discarding the resulting value, instead returning the number of seconds it took to execute as a floating-point number.\n\nIn some cases the system will look inside the @elapsed expression and compile some of the called code before execution of the top-level expression begins. When that happens, some compilation time will not be counted. To include this time you can run @elapsed @eval ....\n\nSee also @time, @timev, @timed, and @allocated.\n\njulia> @elapsed sleep(0.3)\n0.301391426\n\n\n\n\n\n","category":"macro"},{"location":"base/base/#Base.@allocated","page":"基本功能","title":"Base.@allocated","text":"@allocated\n\nA macro to evaluate an expression, discarding the resulting value, instead returning the total number of bytes allocated during evaluation of the expression.\n\nSee also @time, @timev, @timed, and @elapsed.\n\njulia> @allocated rand(10^6)\n8000080\n\n\n\n\n\n","category":"macro"},{"location":"base/base/#Base.EnvDict","page":"基本功能","title":"Base.EnvDict","text":"EnvDict() -> EnvDict\n\nA singleton of this type provides a hash table interface to environment variables.\n\n\n\n\n\n","category":"type"},{"location":"base/base/#Base.ENV","page":"基本功能","title":"Base.ENV","text":"ENV\n\nReference to the singleton EnvDict, providing a dictionary interface to system environment variables.\n\n(On Windows, system environment variables are case-insensitive, and ENV correspondingly converts all keys to uppercase for display, iteration, and copying. Portable code should not rely on the ability to distinguish variables by case, and should beware that setting an ostensibly lowercase variable may result in an uppercase ENV key.)\n\n\n\n\n\n","category":"constant"},{"location":"base/base/#Base.Sys.isunix","page":"基本功能","title":"Base.Sys.isunix","text":"Sys.isunix([os])\n\nPredicate for testing if the OS provides a Unix-like interface. See documentation in Handling Operating System Variation.\n\n\n\n\n\n","category":"function"},{"location":"base/base/#Base.Sys.isapple","page":"基本功能","title":"Base.Sys.isapple","text":"Sys.isapple([os])\n\nPredicate for testing if the OS is a derivative of Apple Macintosh OS X or Darwin. See documentation in Handling Operating System Variation.\n\n\n\n\n\n","category":"function"},{"location":"base/base/#Base.Sys.islinux","page":"基本功能","title":"Base.Sys.islinux","text":"Sys.islinux([os])\n\nPredicate for testing if the OS is a derivative of Linux. See documentation in Handling Operating System Variation.\n\n\n\n\n\n","category":"function"},{"location":"base/base/#Base.Sys.isbsd","page":"基本功能","title":"Base.Sys.isbsd","text":"Sys.isbsd([os])\n\nPredicate for testing if the OS is a derivative of BSD. See documentation in Handling Operating System Variation.\n\nnote: Note\nThe Darwin kernel descends from BSD, which means that Sys.isbsd() is true on macOS systems. To exclude macOS from a predicate, use Sys.isbsd() && !Sys.isapple().\n\n\n\n\n\n","category":"function"},{"location":"base/base/#Base.Sys.isfreebsd","page":"基本功能","title":"Base.Sys.isfreebsd","text":"Sys.isfreebsd([os])\n\nPredicate for testing if the OS is a derivative of FreeBSD. See documentation in Handling Operating System Variation.\n\nnote: Note\nNot to be confused with Sys.isbsd(), which is true on FreeBSD but also on other BSD-based systems. Sys.isfreebsd() refers only to FreeBSD.\n\ncompat: Julia 1.1\nThis function requires at least Julia 1.1.\n\n\n\n\n\n","category":"function"},{"location":"base/base/#Base.Sys.isopenbsd","page":"基本功能","title":"Base.Sys.isopenbsd","text":"Sys.isopenbsd([os])\n\nPredicate for testing if the OS is a derivative of OpenBSD. See documentation in Handling Operating System Variation.\n\nnote: Note\nNot to be confused with Sys.isbsd(), which is true on OpenBSD but also on other BSD-based systems. Sys.isopenbsd() refers only to OpenBSD.\n\ncompat: Julia 1.1\nThis function requires at least Julia 1.1.\n\n\n\n\n\n","category":"function"},{"location":"base/base/#Base.Sys.isnetbsd","page":"基本功能","title":"Base.Sys.isnetbsd","text":"Sys.isnetbsd([os])\n\nPredicate for testing if the OS is a derivative of NetBSD. See documentation in Handling Operating System Variation.\n\nnote: Note\nNot to be confused with Sys.isbsd(), which is true on NetBSD but also on other BSD-based systems. Sys.isnetbsd() refers only to NetBSD.\n\ncompat: Julia 1.1\nThis function requires at least Julia 1.1.\n\n\n\n\n\n","category":"function"},{"location":"base/base/#Base.Sys.isdragonfly","page":"基本功能","title":"Base.Sys.isdragonfly","text":"Sys.isdragonfly([os])\n\nPredicate for testing if the OS is a derivative of DragonFly BSD. See documentation in Handling Operating System Variation.\n\nnote: Note\nNot to be confused with Sys.isbsd(), which is true on DragonFly but also on other BSD-based systems. Sys.isdragonfly() refers only to DragonFly.\n\ncompat: Julia 1.1\nThis function requires at least Julia 1.1.\n\n\n\n\n\n","category":"function"},{"location":"base/base/#Base.Sys.iswindows","page":"基本功能","title":"Base.Sys.iswindows","text":"Sys.iswindows([os])\n\nPredicate for testing if the OS is a derivative of Microsoft Windows NT. See documentation in Handling Operating System Variation.\n\n\n\n\n\n","category":"function"},{"location":"base/base/#Base.Sys.windows_version","page":"基本功能","title":"Base.Sys.windows_version","text":"Sys.windows_version()\n\nReturn the version number for the Windows NT Kernel as a VersionNumber, i.e. v\"major.minor.build\", or v\"0.0.0\" if this is not running on Windows.\n\n\n\n\n\n","category":"function"},{"location":"base/base/#Base.Sys.free_memory","page":"基本功能","title":"Base.Sys.free_memory","text":"Sys.free_memory()\n\nGet the total free memory in RAM in bytes.\n\n\n\n\n\n","category":"function"},{"location":"base/base/#Base.Sys.total_memory","page":"基本功能","title":"Base.Sys.total_memory","text":"Sys.total_memory()\n\nGet the total memory in RAM (including that which is currently used) in bytes. This amount may be constrained, e.g., by Linux control groups. For the unconstrained amount, see Sys.physical_memory().\n\n\n\n\n\n","category":"function"},{"location":"base/base/#Base.@static","page":"基本功能","title":"Base.@static","text":"@static\n\nPartially evaluate an expression at parse time.\n\nFor example, @static Sys.iswindows() ? foo : bar will evaluate Sys.iswindows() and insert either foo or bar into the expression. This is useful in cases where a construct would be invalid on other platforms, such as a ccall to a non-existent function. @static if Sys.isapple() foo end and @static foo <&&,||> bar are also valid syntax.\n\n\n\n\n\n","category":"macro"},{"location":"base/base/#Versioning","page":"基本功能","title":"Versioning","text":"","category":"section"},{"location":"base/base/","page":"基本功能","title":"基本功能","text":"Base.VersionNumber\nBase.@v_str","category":"page"},{"location":"base/base/#Base.VersionNumber","page":"基本功能","title":"Base.VersionNumber","text":"VersionNumber\n\nVersion number type which follows the specifications of semantic versioning (semver), composed of major, minor and patch numeric values, followed by pre-release and build alpha-numeric annotations.\n\nVersionNumber objects can be compared with all of the standard comparison operators (==, <, <=, etc.), with the result following semver rules.\n\nSee also @v_str to efficiently construct VersionNumber objects from semver-format literal strings, VERSION for the VersionNumber of Julia itself, and Version Number Literals in the manual.\n\nExamples\n\njulia> a = VersionNumber(1, 2, 3)\nv\"1.2.3\"\n\njulia> a >= v\"1.2\"\ntrue\n\njulia> b = VersionNumber(\"2.0.1-rc1\")\nv\"2.0.1-rc1\"\n\njulia> b >= v\"2.0.1\"\nfalse\n\n\n\n\n\n","category":"type"},{"location":"base/base/#Base.@v_str","page":"基本功能","title":"Base.@v_str","text":"@v_str\n\nString macro used to parse a string to a VersionNumber.\n\nExamples\n\njulia> v\"1.2.3\"\nv\"1.2.3\"\n\njulia> v\"2.0.1-rc1\"\nv\"2.0.1-rc1\"\n\n\n\n\n\n","category":"macro"},{"location":"base/base/#Errors","page":"基本功能","title":"Errors","text":"","category":"section"},{"location":"base/base/","page":"基本功能","title":"基本功能","text":"Base.error\nCore.throw\nBase.rethrow\nBase.backtrace\nBase.catch_backtrace\nBase.current_exceptions\nBase.@assert\nBase.Experimental.register_error_hint\nBase.Experimental.show_error_hints\nBase.ArgumentError\nBase.AssertionError\nCore.BoundsError\nBase.CompositeException\nBase.DimensionMismatch\nCore.DivideError\nCore.DomainError\nBase.EOFError\nCore.ErrorException\nCore.InexactError\nCore.InterruptException\nBase.KeyError\nBase.LoadError\nBase.MethodError\nBase.MissingException\nCore.OutOfMemoryError\nCore.ReadOnlyMemoryError\nCore.OverflowError\nBase.ProcessFailedException\nCore.StackOverflowError\nBase.SystemError\nCore.TypeError\nCore.UndefKeywordError\nCore.UndefRefError\nCore.UndefVarError\nBase.StringIndexError\nBase.InitError\nBase.retry\nBase.ExponentialBackOff","category":"page"},{"location":"base/base/#Base.error","page":"基本功能","title":"Base.error","text":"error(message::AbstractString)\n\nRaise an ErrorException with the given message.\n\n\n\n\n\nerror(msg...)\n\nRaise an ErrorException with the given message.\n\n\n\n\n\n","category":"function"},{"location":"base/base/#Core.throw","page":"基本功能","title":"Core.throw","text":"throw(e)\n\nThrow an object as an exception.\n\nSee also: rethrow, error.\n\n\n\n\n\n","category":"function"},{"location":"base/base/#Base.rethrow","page":"基本功能","title":"Base.rethrow","text":"rethrow()\n\nRethrow the current exception from within a catch block. The rethrown exception will continue propagation as if it had not been caught.\n\nnote: Note\nThe alternative form rethrow(e) allows you to associate an alternative exception object e with the current backtrace. However this misrepresents the program state at the time of the error so you're encouraged to instead throw a new exception using throw(e). In Julia 1.1 and above, using throw(e) will preserve the root cause exception on the stack, as described in current_exceptions.\n\n\n\n\n\n","category":"function"},{"location":"base/base/#Base.backtrace","page":"基本功能","title":"Base.backtrace","text":"backtrace()\n\nGet a backtrace object for the current program point.\n\n\n\n\n\n","category":"function"},{"location":"base/base/#Base.catch_backtrace","page":"基本功能","title":"Base.catch_backtrace","text":"catch_backtrace()\n\nGet the backtrace of the current exception, for use within catch blocks.\n\n\n\n\n\n","category":"function"},{"location":"base/base/#Base.current_exceptions","page":"基本功能","title":"Base.current_exceptions","text":"current_exceptions(task::Task=current_task(); [backtrace::Bool=true])\n\nGet the stack of exceptions currently being handled. For nested catch blocks there may be more than one current exception in which case the most recently thrown exception is last in the stack. The stack is returned as an ExceptionStack which is an AbstractVector of named tuples (exception,backtrace). If backtrace is false, the backtrace in each pair will be set to nothing.\n\nExplicitly passing task will return the current exception stack on an arbitrary task. This is useful for inspecting tasks which have failed due to uncaught exceptions.\n\ncompat: Julia 1.7\nThis function went by the experimental name catch_stack() in Julia 1.1–1.6, and had a plain Vector-of-tuples as a return type.\n\n\n\n\n\n","category":"function"},{"location":"base/base/#Base.@assert","page":"基本功能","title":"Base.@assert","text":"@assert cond [text]\n\nThrow an AssertionError if cond is false. Preferred syntax for writing assertions. Message text is optionally displayed upon assertion failure.\n\nwarning: Warning\nAn assert might be disabled at various optimization levels. Assert should therefore only be used as a debugging tool and not used for authentication verification (e.g., verifying passwords), nor should side effects needed for the function to work correctly be used inside of asserts.\n\nExamples\n\njulia> @assert iseven(3) \"3 is an odd number!\"\nERROR: AssertionError: 3 is an odd number!\n\njulia> @assert isodd(3) \"What even are numbers?\"\n\n\n\n\n\n","category":"macro"},{"location":"base/base/#Base.Experimental.register_error_hint","page":"基本功能","title":"Base.Experimental.register_error_hint","text":"Experimental.register_error_hint(handler, exceptiontype)\n\nRegister a \"hinting\" function handler(io, exception) that can suggest potential ways for users to circumvent errors. handler should examine exception to see whether the conditions appropriate for a hint are met, and if so generate output to io. Packages should call register_error_hint from within their __init__ function.\n\nFor specific exception types, handler is required to accept additional arguments:\n\nMethodError: provide handler(io, exc::MethodError, argtypes, kwargs), which splits the combined arguments into positional and keyword arguments.\n\nWhen issuing a hint, the output should typically start with \\n.\n\nIf you define custom exception types, your showerror method can support hints by calling Experimental.show_error_hints.\n\nExample\n\njulia> module Hinter\n\n only_int(x::Int) = 1\n any_number(x::Number) = 2\n\n function __init__()\n Base.Experimental.register_error_hint(MethodError) do io, exc, argtypes, kwargs\n if exc.f == only_int\n # Color is not necessary, this is just to show it's possible.\n print(io, \"\\nDid you mean to call \")\n printstyled(io, \"`any_number`?\", color=:cyan)\n end\n end\n end\n\n end\n\nThen if you call Hinter.only_int on something that isn't an Int (thereby triggering a MethodError), it issues the hint:\n\njulia> Hinter.only_int(1.0)\nERROR: MethodError: no method matching only_int(::Float64)\nDid you mean to call `any_number`?\nClosest candidates are:\n ...\n\ncompat: Julia 1.5\nCustom error hints are available as of Julia 1.5.\n\nwarning: Warning\nThis interface is experimental and subject to change or removal without notice. To insulate yourself against changes, consider putting any registrations inside an if isdefined(Base.Experimental, :register_error_hint) ... end block.\n\n\n\n\n\n","category":"function"},{"location":"base/base/#Base.Experimental.show_error_hints","page":"基本功能","title":"Base.Experimental.show_error_hints","text":"Experimental.show_error_hints(io, ex, args...)\n\nInvoke all handlers from Experimental.register_error_hint for the particular exception type typeof(ex). args must contain any other arguments expected by the handler for that type.\n\ncompat: Julia 1.5\nCustom error hints are available as of Julia 1.5.\n\nwarning: Warning\nThis interface is experimental and subject to change or removal without notice.\n\n\n\n\n\n","category":"function"},{"location":"base/base/#Core.ArgumentError","page":"基本功能","title":"Core.ArgumentError","text":"ArgumentError(msg)\n\nThe arguments passed to a function are invalid. msg is a descriptive error message.\n\n\n\n\n\n","category":"type"},{"location":"base/base/#Core.AssertionError","page":"基本功能","title":"Core.AssertionError","text":"AssertionError([msg])\n\nThe asserted condition did not evaluate to true. Optional argument msg is a descriptive error string.\n\nExamples\n\njulia> @assert false \"this is not true\"\nERROR: AssertionError: this is not true\n\nAssertionError is usually thrown from @assert.\n\n\n\n\n\n","category":"type"},{"location":"base/base/#Core.BoundsError","page":"基本功能","title":"Core.BoundsError","text":"BoundsError([a],[i])\n\nAn indexing operation into an array, a, tried to access an out-of-bounds element at index i.\n\nExamples\n\njulia> A = fill(1.0, 7);\n\njulia> A[8]\nERROR: BoundsError: attempt to access 7-element Vector{Float64} at index [8]\n\n\njulia> B = fill(1.0, (2,3));\n\njulia> B[2, 4]\nERROR: BoundsError: attempt to access 2×3 Matrix{Float64} at index [2, 4]\n\n\njulia> B[9]\nERROR: BoundsError: attempt to access 2×3 Matrix{Float64} at index [9]\n\n\n\n\n\n\n","category":"type"},{"location":"base/base/#Base.CompositeException","page":"基本功能","title":"Base.CompositeException","text":"CompositeException\n\nWrap a Vector of exceptions thrown by a Task (e.g. generated from a remote worker over a channel or an asynchronously executing local I/O write or a remote worker under pmap) with information about the series of exceptions. For example, if a group of workers are executing several tasks, and multiple workers fail, the resulting CompositeException will contain a \"bundle\" of information from each worker indicating where and why the exception(s) occurred.\n\n\n\n\n\n","category":"type"},{"location":"base/base/#Base.DimensionMismatch","page":"基本功能","title":"Base.DimensionMismatch","text":"DimensionMismatch([msg])\n\nThe objects called do not have matching dimensionality. Optional argument msg is a descriptive error string.\n\n\n\n\n\n","category":"type"},{"location":"base/base/#Core.DivideError","page":"基本功能","title":"Core.DivideError","text":"DivideError()\n\nInteger division was attempted with a denominator value of 0.\n\nExamples\n\njulia> 2/0\nInf\n\njulia> div(2, 0)\nERROR: DivideError: integer division error\nStacktrace:\n[...]\n\n\n\n\n\n","category":"type"},{"location":"base/base/#Core.DomainError","page":"基本功能","title":"Core.DomainError","text":"DomainError(val)\nDomainError(val, msg)\n\nThe argument val to a function or constructor is outside the valid domain.\n\nExamples\n\njulia> sqrt(-1)\nERROR: DomainError with -1.0:\nsqrt will only return a complex result if called with a complex argument. Try sqrt(Complex(x)).\nStacktrace:\n[...]\n\n\n\n\n\n","category":"type"},{"location":"base/base/#Base.EOFError","page":"基本功能","title":"Base.EOFError","text":"EOFError()\n\nNo more data was available to read from a file or stream.\n\n\n\n\n\n","category":"type"},{"location":"base/base/#Core.ErrorException","page":"基本功能","title":"Core.ErrorException","text":"ErrorException(msg)\n\nGeneric error type. The error message, in the .msg field, may provide more specific details.\n\nExamples\n\njulia> ex = ErrorException(\"I've done a bad thing\");\n\njulia> ex.msg\n\"I've done a bad thing\"\n\n\n\n\n\n","category":"type"},{"location":"base/base/#Core.InexactError","page":"基本功能","title":"Core.InexactError","text":"InexactError(name::Symbol, T, val)\n\nCannot exactly convert val to type T in a method of function name.\n\nExamples\n\njulia> convert(Float64, 1+2im)\nERROR: InexactError: Float64(1 + 2im)\nStacktrace:\n[...]\n\n\n\n\n\n","category":"type"},{"location":"base/base/#Core.InterruptException","page":"基本功能","title":"Core.InterruptException","text":"InterruptException()\n\nThe process was stopped by a terminal interrupt (CTRL+C).\n\nNote that, in Julia script started without -i (interactive) option, InterruptException is not thrown by default. Calling Base.exit_on_sigint(false) in the script can recover the behavior of the REPL. Alternatively, a Julia script can be started with\n\njulia -e \"include(popfirst!(ARGS))\" script.jl\n\nto let InterruptException be thrown by CTRL+C during the execution.\n\n\n\n\n\n","category":"type"},{"location":"base/base/#Base.KeyError","page":"基本功能","title":"Base.KeyError","text":"KeyError(key)\n\nAn indexing operation into an AbstractDict (Dict) or Set like object tried to access or delete a non-existent element.\n\n\n\n\n\n","category":"type"},{"location":"base/base/#Core.LoadError","page":"基本功能","title":"Core.LoadError","text":"LoadError(file::AbstractString, line::Int, error)\n\nAn error occurred while includeing, requireing, or using a file. The error specifics should be available in the .error field.\n\ncompat: Julia 1.7\nLoadErrors are no longer emitted by @macroexpand, @macroexpand1, and macroexpand as of Julia 1.7.\n\n\n\n\n\n","category":"type"},{"location":"base/base/#Core.MethodError","page":"基本功能","title":"Core.MethodError","text":"MethodError(f, args)\n\nA method with the required type signature does not exist in the given generic function. Alternatively, there is no unique most-specific method.\n\n\n\n\n\n","category":"type"},{"location":"base/base/#Base.MissingException","page":"基本功能","title":"Base.MissingException","text":"MissingException(msg)\n\nException thrown when a missing value is encountered in a situation where it is not supported. The error message, in the msg field may provide more specific details.\n\n\n\n\n\n","category":"type"},{"location":"base/base/#Core.OutOfMemoryError","page":"基本功能","title":"Core.OutOfMemoryError","text":"OutOfMemoryError()\n\nAn operation allocated too much memory for either the system or the garbage collector to handle properly.\n\n\n\n\n\n","category":"type"},{"location":"base/base/#Core.ReadOnlyMemoryError","page":"基本功能","title":"Core.ReadOnlyMemoryError","text":"ReadOnlyMemoryError()\n\nAn operation tried to write to memory that is read-only.\n\n\n\n\n\n","category":"type"},{"location":"base/base/#Core.OverflowError","page":"基本功能","title":"Core.OverflowError","text":"OverflowError(msg)\n\nThe result of an expression is too large for the specified type and will cause a wraparound.\n\n\n\n\n\n","category":"type"},{"location":"base/base/#Base.ProcessFailedException","page":"基本功能","title":"Base.ProcessFailedException","text":"ProcessFailedException\n\nIndicates problematic exit status of a process. When running commands or pipelines, this is thrown to indicate a nonzero exit code was returned (i.e. that the invoked process failed).\n\n\n\n\n\n","category":"type"},{"location":"base/base/#Core.StackOverflowError","page":"基本功能","title":"Core.StackOverflowError","text":"StackOverflowError()\n\nThe function call grew beyond the size of the call stack. This usually happens when a call recurses infinitely.\n\n\n\n\n\n","category":"type"},{"location":"base/base/#Base.SystemError","page":"基本功能","title":"Base.SystemError","text":"SystemError(prefix::AbstractString, [errno::Int32])\n\nA system call failed with an error code (in the errno global variable).\n\n\n\n\n\n","category":"type"},{"location":"base/base/#Core.TypeError","page":"基本功能","title":"Core.TypeError","text":"TypeError(func::Symbol, context::AbstractString, expected::Type, got)\n\nA type assertion failure, or calling an intrinsic function with an incorrect argument type.\n\n\n\n\n\n","category":"type"},{"location":"base/base/#Core.UndefKeywordError","page":"基本功能","title":"Core.UndefKeywordError","text":"UndefKeywordError(var::Symbol)\n\nThe required keyword argument var was not assigned in a function call.\n\nExamples\n\njulia> function my_func(;my_arg)\n return my_arg + 1\n end\nmy_func (generic function with 1 method)\n\njulia> my_func()\nERROR: UndefKeywordError: keyword argument my_arg not assigned\nStacktrace:\n [1] my_func() at ./REPL[1]:2\n [2] top-level scope at REPL[2]:1\n\n\n\n\n\n","category":"type"},{"location":"base/base/#Core.UndefRefError","page":"基本功能","title":"Core.UndefRefError","text":"UndefRefError()\n\nThe item or field is not defined for the given object.\n\nExamples\n\njulia> struct MyType\n a::Vector{Int}\n MyType() = new()\n end\n\njulia> A = MyType()\nMyType(#undef)\n\njulia> A.a\nERROR: UndefRefError: access to undefined reference\nStacktrace:\n[...]\n\n\n\n\n\n","category":"type"},{"location":"base/base/#Core.UndefVarError","page":"基本功能","title":"Core.UndefVarError","text":"UndefVarError(var::Symbol)\n\nA symbol in the current scope is not defined.\n\nExamples\n\njulia> a\nERROR: UndefVarError: a not defined\n\njulia> a = 1;\n\njulia> a\n1\n\n\n\n\n\n","category":"type"},{"location":"base/base/#Base.StringIndexError","page":"基本功能","title":"Base.StringIndexError","text":"StringIndexError(str, i)\n\nAn error occurred when trying to access str at index i that is not valid.\n\n\n\n\n\n","category":"type"},{"location":"base/base/#Core.InitError","page":"基本功能","title":"Core.InitError","text":"InitError(mod::Symbol, error)\n\nAn error occurred when running a module's __init__ function. The actual error thrown is available in the .error field.\n\n\n\n\n\n","category":"type"},{"location":"base/base/#Base.retry","page":"基本功能","title":"Base.retry","text":"retry(f; delays=ExponentialBackOff(), check=nothing) -> Function\n\nReturn an anonymous function that calls function f. If an exception arises, f is repeatedly called again, each time check returns true, after waiting the number of seconds specified in delays. check should input delays's current state and the Exception.\n\ncompat: Julia 1.2\nBefore Julia 1.2 this signature was restricted to f::Function.\n\nExamples\n\nretry(f, delays=fill(5.0, 3))\nretry(f, delays=rand(5:10, 2))\nretry(f, delays=Base.ExponentialBackOff(n=3, first_delay=5, max_delay=1000))\nretry(http_get, check=(s,e)->e.status == \"503\")(url)\nretry(read, check=(s,e)->isa(e, IOError))(io, 128; all=false)\n\n\n\n\n\n","category":"function"},{"location":"base/base/#Base.ExponentialBackOff","page":"基本功能","title":"Base.ExponentialBackOff","text":"ExponentialBackOff(; n=1, first_delay=0.05, max_delay=10.0, factor=5.0, jitter=0.1)\n\nA Float64 iterator of length n whose elements exponentially increase at a rate in the interval factor * (1 ± jitter). The first element is first_delay and all elements are clamped to max_delay.\n\n\n\n\n\n","category":"type"},{"location":"base/base/#Events","page":"基本功能","title":"Events","text":"","category":"section"},{"location":"base/base/","page":"基本功能","title":"基本功能","text":"Base.Timer(::Function, ::Real)\nBase.Timer\nBase.AsyncCondition\nBase.AsyncCondition(::Function)","category":"page"},{"location":"base/base/#Base.Timer-Tuple{Function, Real}","page":"基本功能","title":"Base.Timer","text":"Timer(callback::Function, delay; interval = 0)\n\nCreate a timer that runs the function callback at each timer expiration.\n\nWaiting tasks are woken and the function callback is called after an initial delay of delay seconds, and then repeating with the given interval in seconds. If interval is equal to 0, the callback is only run once. The function callback is called with a single argument, the timer itself. Stop a timer by calling close. The cb may still be run one final time, if the timer has already expired.\n\nExamples\n\nHere the first number is printed after a delay of two seconds, then the following numbers are printed quickly.\n\njulia> begin\n i = 0\n cb(timer) = (global i += 1; println(i))\n t = Timer(cb, 2, interval=0.2)\n wait(t)\n sleep(0.5)\n close(t)\n end\n1\n2\n3\n\n\n\n\n\n","category":"method"},{"location":"base/base/#Base.Timer","page":"基本功能","title":"Base.Timer","text":"Timer(delay; interval = 0)\n\nCreate a timer that wakes up tasks waiting for it (by calling wait on the timer object).\n\nWaiting tasks are woken after an initial delay of at least delay seconds, and then repeating after at least interval seconds again elapse. If interval is equal to 0, the timer is only triggered once. When the timer is closed (by close) waiting tasks are woken with an error. Use isopen to check whether a timer is still active.\n\nnote: Note\ninterval is subject to accumulating time skew. If you need precise events at a particular absolute time, create a new timer at each expiration with the difference to the next time computed.\n\nnote: Note\nA Timer requires yield points to update its state. For instance, isopen(t::Timer) cannot be used to timeout a non-yielding while loop.\n\n\n\n\n\n","category":"type"},{"location":"base/base/#Base.AsyncCondition","page":"基本功能","title":"Base.AsyncCondition","text":"AsyncCondition()\n\nCreate a async condition that wakes up tasks waiting for it (by calling wait on the object) when notified from C by a call to uv_async_send. Waiting tasks are woken with an error when the object is closed (by close). Use isopen to check whether it is still active.\n\nThis provides an implicit acquire & release memory ordering between the sending and waiting threads.\n\n\n\n\n\n","category":"type"},{"location":"base/base/#Base.AsyncCondition-Tuple{Function}","page":"基本功能","title":"Base.AsyncCondition","text":"AsyncCondition(callback::Function)\n\nCreate a async condition that calls the given callback function. The callback is passed one argument, the async condition object itself.\n\n\n\n\n\n","category":"method"},{"location":"base/base/#Reflection","page":"基本功能","title":"Reflection","text":"","category":"section"},{"location":"base/base/","page":"基本功能","title":"基本功能","text":"Base.nameof(::Module)\nBase.parentmodule\nBase.pathof(::Module)\nBase.pkgdir(::Module)\nBase.moduleroot\n__module__\n__source__\nBase.@__MODULE__\nBase.@__FILE__\nBase.@__DIR__\nBase.@__LINE__\nBase.fullname\nBase.names\nCore.nfields\nBase.isconst\nBase.nameof(::Function)\nBase.functionloc(::Any, ::Any)\nBase.functionloc(::Method)\nBase.@locals","category":"page"},{"location":"base/base/#Base.nameof-Tuple{Module}","page":"基本功能","title":"Base.nameof","text":"nameof(m::Module) -> Symbol\n\nGet the name of a Module as a Symbol.\n\nExamples\n\njulia> nameof(Base.Broadcast)\n:Broadcast\n\n\n\n\n\n","category":"method"},{"location":"base/base/#Base.parentmodule","page":"基本功能","title":"Base.parentmodule","text":"parentmodule(m::Module) -> Module\n\nGet a module's enclosing Module. Main is its own parent.\n\nSee also: names, nameof, fullname, @__MODULE__.\n\nExamples\n\njulia> parentmodule(Main)\nMain\n\njulia> parentmodule(Base.Broadcast)\nBase\n\n\n\n\n\nparentmodule(t::DataType) -> Module\n\nDetermine the module containing the definition of a (potentially UnionAll-wrapped) DataType.\n\nExamples\n\njulia> module Foo\n struct Int end\n end\nFoo\n\njulia> parentmodule(Int)\nCore\n\njulia> parentmodule(Foo.Int)\nFoo\n\n\n\n\n\nparentmodule(f::Function) -> Module\n\nDetermine the module containing the (first) definition of a generic function.\n\n\n\n\n\nparentmodule(f::Function, types) -> Module\n\nDetermine the module containing a given definition of a generic function.\n\n\n\n\n\n","category":"function"},{"location":"base/base/#Base.pathof-Tuple{Module}","page":"基本功能","title":"Base.pathof","text":"pathof(m::Module)\n\nReturn the path of the m.jl file that was used to import module m, or nothing if m was not imported from a package.\n\nUse dirname to get the directory part and basename to get the file name part of the path.\n\n\n\n\n\n","category":"method"},{"location":"base/base/#Base.pkgdir-Tuple{Module}","page":"基本功能","title":"Base.pkgdir","text":"pkgdir(m::Module[, paths::String...])\n\nReturn the root directory of the package that imported module m, or nothing if m was not imported from a package. Optionally further path component strings can be provided to construct a path within the package root.\n\njulia> pkgdir(Foo)\n\"/path/to/Foo.jl\"\n\njulia> pkgdir(Foo, \"src\", \"file.jl\")\n\"/path/to/Foo.jl/src/file.jl\"\n\ncompat: Julia 1.7\nThe optional argument paths requires at least Julia 1.7.\n\n\n\n\n\n","category":"method"},{"location":"base/base/#Base.moduleroot","page":"基本功能","title":"Base.moduleroot","text":"moduleroot(m::Module) -> Module\n\nFind the root module of a given module. This is the first module in the chain of parent modules of m which is either a registered root module or which is its own parent module.\n\n\n\n\n\n","category":"function"},{"location":"base/base/#__module__","page":"基本功能","title":"__module__","text":"__module__\n\nThe argument __module__ is only visible inside the macro, and it provides information (in the form of a Module object) about the expansion context of the macro invocation. See the manual section on Macro invocation for more information.\n\n\n\n\n\n","category":"keyword"},{"location":"base/base/#__source__","page":"基本功能","title":"__source__","text":"__source__\n\nThe argument __source__ is only visible inside the macro, and it provides information (in the form of a LineNumberNode object) about the parser location of the @ sign from the macro invocation. See the manual section on Macro invocation for more information.\n\n\n\n\n\n","category":"keyword"},{"location":"base/base/#Base.@__MODULE__","page":"基本功能","title":"Base.@__MODULE__","text":"@__MODULE__ -> Module\n\nGet the Module of the toplevel eval, which is the Module code is currently being read from.\n\n\n\n\n\n","category":"macro"},{"location":"base/base/#Base.@__FILE__","page":"基本功能","title":"Base.@__FILE__","text":"@__FILE__ -> AbstractString\n\nExpand to a string with the path to the file containing the macrocall, or an empty string if evaluated by julia -e . Return nothing if the macro was missing parser source information. Alternatively see PROGRAM_FILE.\n\n\n\n\n\n","category":"macro"},{"location":"base/base/#Base.@__DIR__","page":"基本功能","title":"Base.@__DIR__","text":"@__DIR__ -> AbstractString\n\nExpand to a string with the absolute path to the directory of the file containing the macrocall. Return the current working directory if run from a REPL or if evaluated by julia -e .\n\n\n\n\n\n","category":"macro"},{"location":"base/base/#Base.@__LINE__","page":"基本功能","title":"Base.@__LINE__","text":"@__LINE__ -> Int\n\nExpand to the line number of the location of the macrocall. Return 0 if the line number could not be determined.\n\n\n\n\n\n","category":"macro"},{"location":"base/base/#Base.fullname","page":"基本功能","title":"Base.fullname","text":"fullname(m::Module)\n\nGet the fully-qualified name of a module as a tuple of symbols. For example,\n\nExamples\n\njulia> fullname(Base.Iterators)\n(:Base, :Iterators)\n\njulia> fullname(Main)\n(:Main,)\n\n\n\n\n\n","category":"function"},{"location":"base/base/#Base.names","page":"基本功能","title":"Base.names","text":"names(x::Module; all::Bool = false, imported::Bool = false)\n\nGet an array of the names exported by a Module, excluding deprecated names. If all is true, then the list also includes non-exported names defined in the module, deprecated names, and compiler-generated names. If imported is true, then names explicitly imported from other modules are also included.\n\nAs a special case, all names defined in Main are considered \"exported\", since it is not idiomatic to explicitly export names from Main.\n\nSee also: @locals, @__MODULE__.\n\n\n\n\n\n","category":"function"},{"location":"base/base/#Core.nfields","page":"基本功能","title":"Core.nfields","text":"nfields(x) -> Int\n\nGet the number of fields in the given object.\n\nExamples\n\njulia> a = 1//2;\n\njulia> nfields(a)\n2\n\njulia> b = 1\n1\n\njulia> nfields(b)\n0\n\njulia> ex = ErrorException(\"I've done a bad thing\");\n\njulia> nfields(ex)\n1\n\nIn these examples, a is a Rational, which has two fields. b is an Int, which is a primitive bitstype with no fields at all. ex is an ErrorException, which has one field.\n\n\n\n\n\n","category":"function"},{"location":"base/base/#Base.isconst","page":"基本功能","title":"Base.isconst","text":"isconst(m::Module, s::Symbol) -> Bool\n\nDetermine whether a global is declared const in a given module m.\n\n\n\n\n\nisconst(t::DataType, s::Union{Int,Symbol}) -> Bool\n\nDetermine whether a field s is declared const in a given type t.\n\n\n\n\n\n","category":"function"},{"location":"base/base/#Base.nameof-Tuple{Function}","page":"基本功能","title":"Base.nameof","text":"nameof(f::Function) -> Symbol\n\nGet the name of a generic Function as a symbol. For anonymous functions, this is a compiler-generated name. For explicitly-declared subtypes of Function, it is the name of the function's type.\n\n\n\n\n\n","category":"method"},{"location":"base/base/#Base.functionloc-Tuple{Any, Any}","page":"基本功能","title":"Base.functionloc","text":"functionloc(f::Function, types)\n\nReturns a tuple (filename,line) giving the location of a generic Function definition.\n\n\n\n\n\n","category":"method"},{"location":"base/base/#Base.functionloc-Tuple{Method}","page":"基本功能","title":"Base.functionloc","text":"functionloc(m::Method)\n\nReturns a tuple (filename,line) giving the location of a Method definition.\n\n\n\n\n\n","category":"method"},{"location":"base/base/#Base.@locals","page":"基本功能","title":"Base.@locals","text":"@locals()\n\nConstruct a dictionary of the names (as symbols) and values of all local variables defined as of the call site.\n\ncompat: Julia 1.1\nThis macro requires at least Julia 1.1.\n\nExamples\n\njulia> let x = 1, y = 2\n Base.@locals\n end\nDict{Symbol, Any} with 2 entries:\n :y => 2\n :x => 1\n\njulia> function f(x)\n local y\n show(Base.@locals); println()\n for i = 1:1\n show(Base.@locals); println()\n end\n y = 2\n show(Base.@locals); println()\n nothing\n end;\n\njulia> f(42)\nDict{Symbol, Any}(:x => 42)\nDict{Symbol, Any}(:i => 1, :x => 42)\nDict{Symbol, Any}(:y => 2, :x => 42)\n\n\n\n\n\n","category":"macro"},{"location":"base/base/#Internals","page":"基本功能","title":"Internals","text":"","category":"section"},{"location":"base/base/","page":"基本功能","title":"基本功能","text":"Base.GC.gc\nBase.GC.enable\nBase.GC.@preserve\nBase.GC.safepoint\nMeta.lower\nMeta.@lower\nMeta.parse(::AbstractString, ::Int)\nMeta.parse(::AbstractString)\nMeta.ParseError\nCore.QuoteNode\nBase.macroexpand\nBase.@macroexpand\nBase.@macroexpand1\nBase.code_lowered\nBase.code_typed\nBase.precompile","category":"page"},{"location":"base/base/#Base.GC.gc","page":"基本功能","title":"Base.GC.gc","text":"GC.gc([full=true])\n\nPerform garbage collection. The argument full determines the kind of collection: A full collection (default) sweeps all objects, which makes the next GC scan much slower, while an incremental collection may only sweep so-called young objects.\n\nwarning: Warning\nExcessive use will likely lead to poor performance.\n\n\n\n\n\n","category":"function"},{"location":"base/base/#Base.GC.enable","page":"基本功能","title":"Base.GC.enable","text":"GC.enable(on::Bool)\n\nControl whether garbage collection is enabled using a boolean argument (true for enabled, false for disabled). Return previous GC state.\n\nwarning: Warning\nDisabling garbage collection should be used only with caution, as it can cause memory use to grow without bound.\n\n\n\n\n\n","category":"function"},{"location":"base/base/#Base.GC.@preserve","page":"基本功能","title":"Base.GC.@preserve","text":"GC.@preserve x1 x2 ... xn expr\n\nMark the objects x1, x2, ... as being in use during the evaluation of the expression expr. This is only required in unsafe code where expr implicitly uses memory or other resources owned by one of the xs.\n\nImplicit use of x covers any indirect use of resources logically owned by x which the compiler cannot see. Some examples:\n\nAccessing memory of an object directly via a Ptr\nPassing a pointer to x to ccall\nUsing resources of x which would be cleaned up in the finalizer.\n\n@preserve should generally not have any performance impact in typical use cases where it briefly extends object lifetime. In implementation, @preserve has effects such as protecting dynamically allocated objects from garbage collection.\n\nExamples\n\nWhen loading from a pointer with unsafe_load, the underlying object is implicitly used, for example x is implicitly used by unsafe_load(p) in the following:\n\njulia> let\n x = Ref{Int}(101)\n p = Base.unsafe_convert(Ptr{Int}, x)\n GC.@preserve x unsafe_load(p)\n end\n101\n\nWhen passing pointers to ccall, the pointed-to object is implicitly used and should be preserved. (Note however that you should normally just pass x directly to ccall which counts as an explicit use.)\n\njulia> let\n x = \"Hello\"\n p = pointer(x)\n Int(GC.@preserve x @ccall strlen(p::Cstring)::Csize_t)\n # Preferred alternative\n Int(@ccall strlen(x::Cstring)::Csize_t)\n end\n5\n\n\n\n\n\n","category":"macro"},{"location":"base/base/#Base.GC.safepoint","page":"基本功能","title":"Base.GC.safepoint","text":"GC.safepoint()\n\nInserts a point in the program where garbage collection may run. This can be useful in rare cases in multi-threaded programs where some threads are allocating memory (and hence may need to run GC) but other threads are doing only simple operations (no allocation, task switches, or I/O). Calling this function periodically in non-allocating threads allows garbage collection to run.\n\ncompat: Julia 1.4\nThis function is available as of Julia 1.4.\n\n\n\n\n\n","category":"function"},{"location":"base/base/#Base.Meta.lower","page":"基本功能","title":"Base.Meta.lower","text":"lower(m, x)\n\nTakes the expression x and returns an equivalent expression in lowered form for executing in module m. See also code_lowered.\n\n\n\n\n\n","category":"function"},{"location":"base/base/#Base.Meta.@lower","page":"基本功能","title":"Base.Meta.@lower","text":"@lower [m] x\n\nReturn lowered form of the expression x in module m. By default m is the module in which the macro is called. See also lower.\n\n\n\n\n\n","category":"macro"},{"location":"base/base/#Base.Meta.parse-Tuple{AbstractString, Int64}","page":"基本功能","title":"Base.Meta.parse","text":"parse(str, start; greedy=true, raise=true, depwarn=true)\n\nParse the expression string and return an expression (which could later be passed to eval for execution). start is the code unit index into str of the first character to start parsing at (as with all string indexing, these are not character indices). If greedy is true (default), parse will try to consume as much input as it can; otherwise, it will stop as soon as it has parsed a valid expression. Incomplete but otherwise syntactically valid expressions will return Expr(:incomplete, \"(error message)\"). If raise is true (default), syntax errors other than incomplete expressions will raise an error. If raise is false, parse will return an expression that will raise an error upon evaluation. If depwarn is false, deprecation warnings will be suppressed.\n\njulia> Meta.parse(\"(α, β) = 3, 5\", 1) # start of string\n(:((α, β) = (3, 5)), 16)\n\njulia> Meta.parse(\"(α, β) = 3, 5\", 1, greedy=false)\n(:((α, β)), 9)\n\njulia> Meta.parse(\"(α, β) = 3, 5\", 16) # end of string\n(nothing, 16)\n\njulia> Meta.parse(\"(α, β) = 3, 5\", 11) # index of 3\n(:((3, 5)), 16)\n\njulia> Meta.parse(\"(α, β) = 3, 5\", 11, greedy=false)\n(3, 13)\n\n\n\n\n\n","category":"method"},{"location":"base/base/#Base.Meta.parse-Tuple{AbstractString}","page":"基本功能","title":"Base.Meta.parse","text":"parse(str; raise=true, depwarn=true)\n\nParse the expression string greedily, returning a single expression. An error is thrown if there are additional characters after the first expression. If raise is true (default), syntax errors will raise an error; otherwise, parse will return an expression that will raise an error upon evaluation. If depwarn is false, deprecation warnings will be suppressed.\n\njulia> Meta.parse(\"x = 3\")\n:(x = 3)\n\njulia> Meta.parse(\"x = \")\n:($(Expr(:incomplete, \"incomplete: premature end of input\")))\n\njulia> Meta.parse(\"1.0.2\")\nERROR: Base.Meta.ParseError(\"invalid numeric constant \\\"1.0.\\\"\")\nStacktrace:\n[...]\n\njulia> Meta.parse(\"1.0.2\"; raise = false)\n:($(Expr(:error, \"invalid numeric constant \\\"1.0.\\\"\")))\n\n\n\n\n\n","category":"method"},{"location":"base/base/#Base.Meta.ParseError","page":"基本功能","title":"Base.Meta.ParseError","text":"ParseError(msg)\n\nThe expression passed to the parse function could not be interpreted as a valid Julia expression.\n\n\n\n\n\n","category":"type"},{"location":"base/base/#Core.QuoteNode","page":"基本功能","title":"Core.QuoteNode","text":"QuoteNode\n\nA quoted piece of code, that does not support interpolation. See the manual section about QuoteNodes for details.\n\n\n\n\n\n","category":"type"},{"location":"base/base/#Base.macroexpand","page":"基本功能","title":"Base.macroexpand","text":"macroexpand(m::Module, x; recursive=true)\n\nTake the expression x and return an equivalent expression with all macros removed (expanded) for executing in module m. The recursive keyword controls whether deeper levels of nested macros are also expanded. This is demonstrated in the example below:\n\njulia> module M\n macro m1()\n 42\n end\n macro m2()\n :(@m1())\n end\n end\nM\n\njulia> macroexpand(M, :(@m2()), recursive=true)\n42\n\njulia> macroexpand(M, :(@m2()), recursive=false)\n:(#= REPL[16]:6 =# M.@m1)\n\n\n\n\n\n","category":"function"},{"location":"base/base/#Base.@macroexpand","page":"基本功能","title":"Base.@macroexpand","text":"@macroexpand\n\nReturn equivalent expression with all macros removed (expanded).\n\nThere are differences between @macroexpand and macroexpand.\n\nWhile macroexpand takes a keyword argument recursive, @macroexpand is always recursive. For a non recursive macro version, see @macroexpand1.\nWhile macroexpand has an explicit module argument, @macroexpand always expands with respect to the module in which it is called.\n\nThis is best seen in the following example:\n\njulia> module M\n macro m()\n 1\n end\n function f()\n (@macroexpand(@m),\n macroexpand(M, :(@m)),\n macroexpand(Main, :(@m))\n )\n end\n end\nM\n\njulia> macro m()\n 2\n end\n@m (macro with 1 method)\n\njulia> M.f()\n(1, 1, 2)\n\nWith @macroexpand the expression expands where @macroexpand appears in the code (module M in the example). With macroexpand the expression expands in the module given as the first argument.\n\n\n\n\n\n","category":"macro"},{"location":"base/base/#Base.@macroexpand1","page":"基本功能","title":"Base.@macroexpand1","text":"@macroexpand1\n\nNon recursive version of @macroexpand.\n\n\n\n\n\n","category":"macro"},{"location":"base/base/#Base.code_lowered","page":"基本功能","title":"Base.code_lowered","text":"code_lowered(f, types; generated=true, debuginfo=:default)\n\nReturn an array of the lowered forms (IR) for the methods matching the given generic function and type signature.\n\nIf generated is false, the returned CodeInfo instances will correspond to fallback implementations. An error is thrown if no fallback implementation exists. If generated is true, these CodeInfo instances will correspond to the method bodies yielded by expanding the generators.\n\nThe keyword debuginfo controls the amount of code metadata present in the output.\n\nNote that an error will be thrown if types are not leaf types when generated is true and any of the corresponding methods are an @generated method.\n\n\n\n\n\n","category":"function"},{"location":"base/base/#Base.code_typed","page":"基本功能","title":"Base.code_typed","text":"code_typed(f, types; kw...)\n\nReturns an array of type-inferred lowered form (IR) for the methods matching the given generic function and type signature.\n\nKeyword Arguments\n\noptimize=true: controls whether additional optimizations, such as inlining, are also applied.\ndebuginfo=:default: controls the amount of code metadata present in the output,\n\npossible options are :source or :none.\n\nInternal Keyword Arguments\n\nThis section should be considered internal, and is only for who understands Julia compiler internals.\n\nworld=Base.get_world_counter(): optional, controls the world age to use when looking up methods,\n\nuse current world age if not specified.\n\ninterp=Core.Compiler.NativeInterpreter(world): optional, controls the interpreter to use,\n\nuse the native interpreter Julia uses if not specified.\n\nExample\n\nOne can put the argument types in a tuple to get the corresponding code_typed.\n\njulia> code_typed(+, (Float64, Float64))\n1-element Vector{Any}:\n CodeInfo(\n1 ─ %1 = Base.add_float(x, y)::Float64\n└── return %1\n) => Float64\n\n\n\n\n\n","category":"function"},{"location":"base/base/#Base.precompile","page":"基本功能","title":"Base.precompile","text":"precompile(f, args::Tuple{Vararg{Any}})\n\nCompile the given function f for the argument tuple (of types) args, but do not execute it.\n\n\n\n\n\n","category":"function"},{"location":"base/base/#Meta","page":"基本功能","title":"Meta","text":"","category":"section"},{"location":"base/base/","page":"基本功能","title":"基本功能","text":"Meta.quot\nMeta.isexpr\nMeta.isidentifier\nMeta.isoperator\nMeta.isunaryoperator\nMeta.isbinaryoperator\nMeta.show_sexpr","category":"page"},{"location":"base/base/#Base.Meta.quot","page":"基本功能","title":"Base.Meta.quot","text":"Meta.quot(ex)::Expr\n\nQuote expression ex to produce an expression with head quote. This can for instance be used to represent objects of type Expr in the AST. See also the manual section about QuoteNode.\n\nExamples\n\njulia> eval(Meta.quot(:x))\n:x\n\njulia> dump(Meta.quot(:x))\nExpr\n head: Symbol quote\n args: Array{Any}((1,))\n 1: Symbol x\n\njulia> eval(Meta.quot(:(1+2)))\n:(1 + 2)\n\n\n\n\n\n","category":"function"},{"location":"base/base/#Base.isexpr","page":"基本功能","title":"Base.isexpr","text":"Meta.isexpr(ex, head[, n])::Bool\n\nReturn true if ex is an Expr with the given type head and optionally that the argument list is of length n. head may be a Symbol or collection of Symbols. For example, to check that a macro was passed a function call expression, you might use isexpr(ex, :call).\n\nExamples\n\njulia> ex = :(f(x))\n:(f(x))\n\njulia> Meta.isexpr(ex, :block)\nfalse\n\njulia> Meta.isexpr(ex, :call)\ntrue\n\njulia> Meta.isexpr(ex, [:block, :call]) # multiple possible heads\ntrue\n\njulia> Meta.isexpr(ex, :call, 1)\nfalse\n\njulia> Meta.isexpr(ex, :call, 2)\ntrue\n\n\n\n\n\n","category":"function"},{"location":"base/base/#Base.isidentifier","page":"基本功能","title":"Base.isidentifier","text":" isidentifier(s) -> Bool\n\nReturn whether the symbol or string s contains characters that are parsed as a valid ordinary identifier (not a binary/unary operator) in Julia code; see also Base.isoperator.\n\nInternally Julia allows any sequence of characters in a Symbol (except \\0s), and macros automatically use variable names containing # in order to avoid naming collision with the surrounding code. In order for the parser to recognize a variable, it uses a limited set of characters (greatly extended by Unicode). isidentifier() makes it possible to query the parser directly whether a symbol contains valid characters.\n\nExamples\n\njulia> Meta.isidentifier(:x), Meta.isidentifier(\"1x\")\n(true, false)\n\n\n\n\n\n","category":"function"},{"location":"base/base/#Base.isoperator","page":"基本功能","title":"Base.isoperator","text":"isoperator(s::Symbol)\n\nReturn true if the symbol can be used as an operator, false otherwise.\n\nExamples\n\njulia> Meta.isoperator(:+), Meta.isoperator(:f)\n(true, false)\n\n\n\n\n\n","category":"function"},{"location":"base/base/#Base.isunaryoperator","page":"基本功能","title":"Base.isunaryoperator","text":"isunaryoperator(s::Symbol)\n\nReturn true if the symbol can be used as a unary (prefix) operator, false otherwise.\n\nExamples\n\njulia> Meta.isunaryoperator(:-), Meta.isunaryoperator(:√), Meta.isunaryoperator(:f)\n(true, true, false)\n\n\n\n\n\n","category":"function"},{"location":"base/base/#Base.isbinaryoperator","page":"基本功能","title":"Base.isbinaryoperator","text":"isbinaryoperator(s::Symbol)\n\nReturn true if the symbol can be used as a binary (infix) operator, false otherwise.\n\nExamples\n\njulia> Meta.isbinaryoperator(:-), Meta.isbinaryoperator(:√), Meta.isbinaryoperator(:f)\n(true, false, false)\n\n\n\n\n\n","category":"function"},{"location":"base/base/#Base.Meta.show_sexpr","page":"基本功能","title":"Base.Meta.show_sexpr","text":"Meta.show_sexpr([io::IO,], ex)\n\nShow expression ex as a lisp style S-expression.\n\nExamples\n\njulia> Meta.show_sexpr(:(f(x, g(y,z))))\n(:call, :f, :x, (:call, :g, :y, :z))\n\n\n\n\n\n","category":"function"},{"location":"manual/unicode-input/#Unicode-Input","page":"Unicode 输入表","title":"Unicode 输入表","text":"","category":"section"},{"location":"manual/unicode-input/","page":"Unicode 输入表","title":"Unicode 输入表","text":"在 Julia REPL 或其它编辑器中,可以像输入 LaTeX 符号一样,用 tab 补全下表列出的 Unicode 字符。在 REPL 中,可以先按 ? 进入帮助模式,然后将 Unicode 字符复制粘贴进去,一般在文档开头就会写输入方式。","category":"page"},{"location":"manual/unicode-input/","page":"Unicode 输入表","title":"Unicode 输入表","text":"warning: Warning\n此表第二列可能会缺失一些字符,对某些字符的显示效果也可能会与在 Julia REPL 中不一致。如果发生了这种状况,强烈建议用户检查一下浏览器或 REPL 的字体设置,目前已知很多字体都有显示问题。","category":"page"},{"location":"manual/unicode-input/","page":"Unicode 输入表","title":"Unicode 输入表","text":"#\n# Generate a table containing all LaTeX and Emoji tab completions available in the REPL.\n#\nimport REPL, Markdown\nconst NBSP = '\\u00A0'\n\nfunction tab_completions(symbols...)\n completions = Dict{String, Vector{String}}()\n for each in symbols, (k, v) in each\n completions[v] = push!(get!(completions, v, String[]), k)\n end\n return completions\nend\n\nfunction unicode_data()\n file = normpath(Sys.BINDIR, \"..\", \"UnicodeData.txt\")\n names = Dict{UInt32, String}()\n open(file) do unidata\n for line in readlines(unidata)\n id, name, desc = split(line, \";\")[[1, 2, 11]]\n codepoint = parse(UInt32, \"0x$id\")\n names[codepoint] = titlecase(lowercase(\n name == \"\" ? desc : desc == \"\" ? name : \"$name / $desc\"))\n end\n end\n return names\nend\n\n# Surround combining characters with no-break spaces (i.e '\\u00A0'). Follows the same format\n# for how unicode is displayed on the unicode.org website:\n# http://unicode.org/cldr/utility/character.jsp?a=0300\nfunction fix_combining_chars(char)\n cat = Base.Unicode.category_code(char)\n return cat == 6 || cat == 8 ? \"$NBSP$char$NBSP\" : \"$char\"\nend\n\n\nfunction table_entries(completions, unicode_dict)\n entries = [[\n \"Code point(s)\", \"Character(s)\",\n \"Tab completion sequence(s)\", \"Unicode name(s)\"\n ]]\n for (chars, inputs) in sort!(collect(completions), by = first)\n code_points, unicode_names, characters = String[], String[], String[]\n for char in chars\n push!(code_points, \"U+$(uppercase(string(UInt32(char), base = 16, pad = 5)))\")\n push!(unicode_names, get(unicode_dict, UInt32(char), \"(No Unicode name)\"))\n push!(characters, isempty(characters) ? fix_combining_chars(char) : \"$char\")\n end\n push!(entries, [\n join(code_points, \" + \"), join(characters),\n join(inputs, \", \"), join(unicode_names, \" + \")\n ])\n end\n return Markdown.Table(entries, [:l, :l, :l, :l])\nend\n\ntable_entries(\n tab_completions(\n REPL.REPLCompletions.latex_symbols,\n REPL.REPLCompletions.emoji_symbols\n ),\n unicode_data()\n)","category":"page"},{"location":"manual/integers-and-floating-point-numbers/#整数和浮点数","page":"整数和浮点数","title":"整数和浮点数","text":"","category":"section"},{"location":"manual/integers-and-floating-point-numbers/","page":"整数和浮点数","title":"整数和浮点数","text":"整数和浮点值是算术和计算的基础。这些数值的内置表示被称作原始数值类型(numeric primitive),且整数和浮点数在代码中作为立即数时称作数值字面量(numeric literal)。例如,1 是个整型字面量,1.0 是个浮点型字面量,它们在内存中作为对象的二进制表示就是原始数值类型。","category":"page"},{"location":"manual/integers-and-floating-point-numbers/","page":"整数和浮点数","title":"整数和浮点数","text":"Julia 提供了很丰富的原始数值类型,并基于它们定义了一整套算术操作,还提供按位运算符以及一些标准数学函数。这些函数能够直接映射到现代计算机原生支持的数值类型及运算上,因此 Julia 可以充分地利用运算资源。此外,Julia 还为任意精度算术提供了软件支持,对于无法使用原生硬件表示的数值类型,Julia 也能够高效地处理其数值运算。当然,这需要相对的牺牲一些性能。","category":"page"},{"location":"manual/integers-and-floating-point-numbers/","page":"整数和浮点数","title":"整数和浮点数","text":"以下是 Julia 的原始数值类型:","category":"page"},{"location":"manual/integers-and-floating-point-numbers/","page":"整数和浮点数","title":"整数和浮点数","text":"整数类型:","category":"page"},{"location":"manual/integers-and-floating-point-numbers/","page":"整数和浮点数","title":"整数和浮点数","text":"类型 带符号? 比特数 最小值 最大值\nInt8 ✓ 8 -2^7 2^7 - 1\nUInt8 8 0 2^8 - 1\nInt16 ✓ 16 -2^15 2^15 - 1\nUInt16 16 0 2^16 - 1\nInt32 ✓ 32 -2^31 2^31 - 1\nUInt32 32 0 2^32 - 1\nInt64 ✓ 64 -2^63 2^63 - 1\nUInt64 64 0 2^64 - 1\nInt128 ✓ 128 -2^127 2^127 - 1\nUInt128 128 0 2^128 - 1\nBool N/A 8 false (0) true (1)","category":"page"},{"location":"manual/integers-and-floating-point-numbers/","page":"整数和浮点数","title":"整数和浮点数","text":"浮点类型:","category":"page"},{"location":"manual/integers-and-floating-point-numbers/","page":"整数和浮点数","title":"整数和浮点数","text":"类型 精度 比特数\nFloat16 半精度 16\nFloat32 单精度 32\nFloat64 双精度 64","category":"page"},{"location":"manual/integers-and-floating-point-numbers/","page":"整数和浮点数","title":"整数和浮点数","text":"此外,对复数和有理数的完整支持是在这些原始数据类型之上建立起来的。多亏了 Julia 有一个很灵活的、用户可扩展的类型提升系统,所有的数值类型都无需显式转换就可以很自然地相互进行运算。","category":"page"},{"location":"manual/integers-and-floating-point-numbers/#整数","page":"整数和浮点数","title":"整数","text":"","category":"section"},{"location":"manual/integers-and-floating-point-numbers/","page":"整数和浮点数","title":"整数和浮点数","text":"整数字面量以标准形式表示:","category":"page"},{"location":"manual/integers-and-floating-point-numbers/","page":"整数和浮点数","title":"整数和浮点数","text":"julia> 1\n1\n\njulia> 1234\n1234","category":"page"},{"location":"manual/integers-and-floating-point-numbers/","page":"整数和浮点数","title":"整数和浮点数","text":"整型字面量的默认类型取决于目标系统是 32 位还是 64 位架构:","category":"page"},{"location":"manual/integers-and-floating-point-numbers/","page":"整数和浮点数","title":"整数和浮点数","text":"# 32 位系统:\njulia> typeof(1)\nInt32\n\n# 64 位系统:\njulia> typeof(1)\nInt64","category":"page"},{"location":"manual/integers-and-floating-point-numbers/","page":"整数和浮点数","title":"整数和浮点数","text":"Julia 的内置变量 Sys.WORD_SIZE 表明了目标系统是 32 位还是 64 位架构:","category":"page"},{"location":"manual/integers-and-floating-point-numbers/","page":"整数和浮点数","title":"整数和浮点数","text":"# 32 位系统:\njulia> Sys.WORD_SIZE\n32\n\n# 64 位系统:\njulia> Sys.WORD_SIZE\n64","category":"page"},{"location":"manual/integers-and-floating-point-numbers/","page":"整数和浮点数","title":"整数和浮点数","text":"Julia 也定义了 Int 与 UInt 类型,它们分别是系统有符号和无符号的原生整数类型的别名。","category":"page"},{"location":"manual/integers-and-floating-point-numbers/","page":"整数和浮点数","title":"整数和浮点数","text":"# 32 位系统:\njulia> Int\nInt32\njulia> UInt\nUInt32\n\n# 64 位系统:\njulia> Int\nInt64\njulia> UInt\nUInt64","category":"page"},{"location":"manual/integers-and-floating-point-numbers/","page":"整数和浮点数","title":"整数和浮点数","text":"那些超过 32 位表示范围的大整数,如果能用 64 位表示,那么无论是什么系统都会用 64 位表示:","category":"page"},{"location":"manual/integers-and-floating-point-numbers/","page":"整数和浮点数","title":"整数和浮点数","text":"# 32 位或 64 位系统:\njulia> typeof(3000000000)\nInt64","category":"page"},{"location":"manual/integers-and-floating-point-numbers/","page":"整数和浮点数","title":"整数和浮点数","text":"无符号整数会通过 0x 前缀以及十六进制数 0-9a-f 来输入和输出(输入也可以使用大写的 A-F)。无符号值的位数取决于十六进制数字使用的数量:","category":"page"},{"location":"manual/integers-and-floating-point-numbers/","page":"整数和浮点数","title":"整数和浮点数","text":"julia> x = 0x1\n0x01\n\njulia> typeof(x)\nUInt8\n\njulia> x = 0x123\n0x0123\n\njulia> typeof(x)\nUInt16\n\njulia> x = 0x1234567\n0x01234567\n\njulia> typeof(x)\nUInt32\n\njulia> x = 0x123456789abcdef\n0x0123456789abcdef\n\njulia> typeof(x)\nUInt64\n\njulia> x = 0x11112222333344445555666677778888\n0x11112222333344445555666677778888\n\njulia> typeof(x)\nUInt128","category":"page"},{"location":"manual/integers-and-floating-point-numbers/","page":"整数和浮点数","title":"整数和浮点数","text":"采用这种做法是因为,当人们使用无符号十六进制字面量表示整数值的时候,通常会用它们来表示一个固定的数值字节序列,而不仅仅是个整数值。","category":"page"},{"location":"manual/integers-and-floating-point-numbers/","page":"整数和浮点数","title":"整数和浮点数","text":"二进制和八进制字面量也是支持的:","category":"page"},{"location":"manual/integers-and-floating-point-numbers/","page":"整数和浮点数","title":"整数和浮点数","text":"julia> x = 0b10\n0x02\n\njulia> typeof(x)\nUInt8\n\njulia> x = 0o010\n0x08\n\njulia> typeof(x)\nUInt8\n\njulia> x = 0x00000000000000001111222233334444\n0x00000000000000001111222233334444\n\njulia> typeof(x)\nUInt128","category":"page"},{"location":"manual/integers-and-floating-point-numbers/","page":"整数和浮点数","title":"整数和浮点数","text":"二进制、八进制和十六进制的字面量都会产生无符号的整数类型。当字面量不是开头全是 0 时,它们二进制数据项的位数会是最少需要的位数。当开头都是 0 时,位数取决于一个字面量需要的最少位数,这里的字面量指的是一个有着同样长度但开头都为 1 的数。这样用户就可以控制位数了。那些无法使用 UInt128 类型存储下的值无法写成这样的字面量。","category":"page"},{"location":"manual/integers-and-floating-point-numbers/","page":"整数和浮点数","title":"整数和浮点数","text":"二进制、八进制和十六进制的字面量前面加一个负号 -,这样可以产生一个和原字面量有着同样位数而值为原数的补码的数(二补数):","category":"page"},{"location":"manual/integers-and-floating-point-numbers/","page":"整数和浮点数","title":"整数和浮点数","text":"julia> -0x2\n0xfe\n\njulia> -0x0002\n0xfffe","category":"page"},{"location":"manual/integers-and-floating-point-numbers/","page":"整数和浮点数","title":"整数和浮点数","text":"整型等原始数值类型的最小和最大可表示的值可用 typemin 和 typemax 函数得到:","category":"page"},{"location":"manual/integers-and-floating-point-numbers/","page":"整数和浮点数","title":"整数和浮点数","text":"julia> (typemin(Int32), typemax(Int32))\n(-2147483648, 2147483647)\n\njulia> for T in [Int8,Int16,Int32,Int64,Int128,UInt8,UInt16,UInt32,UInt64,UInt128]\n println(\"$(lpad(T,7)): [$(typemin(T)),$(typemax(T))]\")\n end\n Int8: [-128,127]\n Int16: [-32768,32767]\n Int32: [-2147483648,2147483647]\n Int64: [-9223372036854775808,9223372036854775807]\n Int128: [-170141183460469231731687303715884105728,170141183460469231731687303715884105727]\n UInt8: [0,255]\n UInt16: [0,65535]\n UInt32: [0,4294967295]\n UInt64: [0,18446744073709551615]\nUInt128: [0,340282366920938463463374607431768211455]","category":"page"},{"location":"manual/integers-and-floating-point-numbers/","page":"整数和浮点数","title":"整数和浮点数","text":"typemin 和 typemax 返回的值的类型总与所给参数的类型相同。(上面的表达式用了一些目前还没有介绍的功能,包括 for 循环、字符串和字符串插值,但这对于已有一些编程经验的用户应该是很容易理解的。)","category":"page"},{"location":"manual/integers-and-floating-point-numbers/#溢出行为","page":"整数和浮点数","title":"溢出行为","text":"","category":"section"},{"location":"manual/integers-and-floating-point-numbers/","page":"整数和浮点数","title":"整数和浮点数","text":"在 Julia 里,超出一个类型可表示的最大值会导致环绕 (wraparound) 行为:","category":"page"},{"location":"manual/integers-and-floating-point-numbers/","page":"整数和浮点数","title":"整数和浮点数","text":"julia> x = typemax(Int64)\n9223372036854775807\n\njulia> x + 1\n-9223372036854775808\n\njulia> x + 1 == typemin(Int64)\ntrue","category":"page"},{"location":"manual/integers-and-floating-point-numbers/","page":"整数和浮点数","title":"整数和浮点数","text":"因此,Julia 的整数算术实际上是模算数的一种形式,它反映了现代计算机实现底层算术的特点。在可能有溢出产生的程序中,对最值边界出现循环进行显式检查是必要的。否则,推荐使用任意精度算术中的 BigInt 类型作为替代。","category":"page"},{"location":"manual/integers-and-floating-point-numbers/","page":"整数和浮点数","title":"整数和浮点数","text":"下面是溢出行为的一个例子以及如何解决溢出:","category":"page"},{"location":"manual/integers-and-floating-point-numbers/","page":"整数和浮点数","title":"整数和浮点数","text":"julia> 10^19\n-8446744073709551616\n\njulia> big(10)^19\n10000000000000000000","category":"page"},{"location":"manual/integers-and-floating-point-numbers/#除法错误","page":"整数和浮点数","title":"除法错误","text":"","category":"section"},{"location":"manual/integers-and-floating-point-numbers/","page":"整数和浮点数","title":"整数和浮点数","text":"div 函数的整数除法有两种异常情况:除以零,以及使用 -1 去除最小的负数(typemin)。 这两种情况都会抛出一个 DivideError 错误。 rem 取余函数和 mod 取模函数在除零时抛出 DivideError 错误。","category":"page"},{"location":"manual/integers-and-floating-point-numbers/#浮点数","page":"整数和浮点数","title":"浮点数","text":"","category":"section"},{"location":"manual/integers-and-floating-point-numbers/","page":"整数和浮点数","title":"整数和浮点数","text":"浮点数字面量以标准格式表示,必要时可使用E-表示法。","category":"page"},{"location":"manual/integers-and-floating-point-numbers/","page":"整数和浮点数","title":"整数和浮点数","text":"julia> 1.0\n1.0\n\njulia> 1.\n1.0\n\njulia> 0.5\n0.5\n\njulia> .5\n0.5\n\njulia> -1.23\n-1.23\n\njulia> 1e10\n1.0e10\n\njulia> 2.5e-4\n0.00025","category":"page"},{"location":"manual/integers-and-floating-point-numbers/","page":"整数和浮点数","title":"整数和浮点数","text":"上面的结果都是 Float64 类型的值。使用 f 替代 e 可以得到 Float32 类型的字面量:","category":"page"},{"location":"manual/integers-and-floating-point-numbers/","page":"整数和浮点数","title":"整数和浮点数","text":"julia> x = 0.5f0\n0.5f0\n\njulia> typeof(x)\nFloat32\n\njulia> 2.5f-4\n0.00025f0","category":"page"},{"location":"manual/integers-and-floating-point-numbers/","page":"整数和浮点数","title":"整数和浮点数","text":"数值可以很容易地转换为 Float32 类型:","category":"page"},{"location":"manual/integers-and-floating-point-numbers/","page":"整数和浮点数","title":"整数和浮点数","text":"julia> x = Float32(-1.5)\n-1.5f0\n\njulia> typeof(x)\nFloat32","category":"page"},{"location":"manual/integers-and-floating-point-numbers/","page":"整数和浮点数","title":"整数和浮点数","text":"也存在十六进制的浮点数字面量,但只适用于 Float64 类型的值。一般使用 p 前缀及以 2 为底的指数来表示:","category":"page"},{"location":"manual/integers-and-floating-point-numbers/","page":"整数和浮点数","title":"整数和浮点数","text":"julia> 0x1p0\n1.0\n\njulia> 0x1.8p3\n12.0\n\njulia> x = 0x.4p-1\n0.125\n\njulia> typeof(x)\nFloat64","category":"page"},{"location":"manual/integers-and-floating-point-numbers/","page":"整数和浮点数","title":"整数和浮点数","text":"Julia 也支持半精度浮点数(Float16),但它们是使用 Float32 进行软件模拟实现的。","category":"page"},{"location":"manual/integers-and-floating-point-numbers/","page":"整数和浮点数","title":"整数和浮点数","text":"julia> sizeof(Float16(4.))\n2\n\njulia> 2*Float16(4.)\nFloat16(8.0)","category":"page"},{"location":"manual/integers-and-floating-point-numbers/","page":"整数和浮点数","title":"整数和浮点数","text":"下划线 _ 可用作数字分隔符:","category":"page"},{"location":"manual/integers-and-floating-point-numbers/","page":"整数和浮点数","title":"整数和浮点数","text":"julia> 10_000, 0.000_000_005, 0xdead_beef, 0b1011_0010\n(10000, 5.0e-9, 0xdeadbeef, 0xb2)","category":"page"},{"location":"manual/integers-and-floating-point-numbers/#浮点数中的零","page":"整数和浮点数","title":"浮点数中的零","text":"","category":"section"},{"location":"manual/integers-and-floating-point-numbers/","page":"整数和浮点数","title":"整数和浮点数","text":"浮点数有两种零,正零和负零。它们相互相等但有着不同的二进制表示,可以使用 bitstring 函数来查看:","category":"page"},{"location":"manual/integers-and-floating-point-numbers/","page":"整数和浮点数","title":"整数和浮点数","text":"julia> 0.0 == -0.0\ntrue\n\njulia> bitstring(0.0)\n\"0000000000000000000000000000000000000000000000000000000000000000\"\n\njulia> bitstring(-0.0)\n\"1000000000000000000000000000000000000000000000000000000000000000\"","category":"page"},{"location":"manual/integers-and-floating-point-numbers/#特殊的浮点值","page":"整数和浮点数","title":"特殊的浮点值","text":"","category":"section"},{"location":"manual/integers-and-floating-point-numbers/","page":"整数和浮点数","title":"整数和浮点数","text":"有三种特定的标准浮点值不和实数轴上任何一点对应:","category":"page"},{"location":"manual/integers-and-floating-point-numbers/","page":"整数和浮点数","title":"整数和浮点数","text":"Float16 Float32 Float64 名称 描述\nInf16 Inf32 Inf 正无穷 一个大于所有有限浮点数的数\n-Inf16 -Inf32 -Inf 负无穷 一个小于所有有限浮点数的数\nNaN16 NaN32 NaN 不是数(Not a Number) 一个不和任何浮点值(包括自己)相等(==)的值","category":"page"},{"location":"manual/integers-and-floating-point-numbers/","page":"整数和浮点数","title":"整数和浮点数","text":"对于这些非有限浮点值相互之间以及关于其它浮点值的顺序的更多讨论,请参见数值比较。根据 IEEE 754 标准,这些浮点值是某些算术运算的结果:","category":"page"},{"location":"manual/integers-and-floating-point-numbers/","page":"整数和浮点数","title":"整数和浮点数","text":"julia> 1/Inf\n0.0\n\njulia> 1/0\nInf\n\njulia> -5/0\n-Inf\n\njulia> 0.000001/0\nInf\n\njulia> 0/0\nNaN\n\njulia> 500 + Inf\nInf\n\njulia> 500 - Inf\n-Inf\n\njulia> Inf + Inf\nInf\n\njulia> Inf - Inf\nNaN\n\njulia> Inf * Inf\nInf\n\njulia> Inf / Inf\nNaN\n\njulia> 0 * Inf\nNaN\n\njulia> NaN == NaN\nfalse\n\njulia> NaN != NaN\ntrue\n\njulia> NaN < NaN\nfalse\n\njulia> NaN > NaN\nfalse","category":"page"},{"location":"manual/integers-and-floating-point-numbers/","page":"整数和浮点数","title":"整数和浮点数","text":"typemin 和 typemax 函数同样适用于浮点类型:","category":"page"},{"location":"manual/integers-and-floating-point-numbers/","page":"整数和浮点数","title":"整数和浮点数","text":"julia> (typemin(Float16),typemax(Float16))\n(-Inf16, Inf16)\n\njulia> (typemin(Float32),typemax(Float32))\n(-Inf32, Inf32)\n\njulia> (typemin(Float64),typemax(Float64))\n(-Inf, Inf)","category":"page"},{"location":"manual/integers-and-floating-point-numbers/#机器精度","page":"整数和浮点数","title":"机器精度","text":"","category":"section"},{"location":"manual/integers-and-floating-point-numbers/","page":"整数和浮点数","title":"整数和浮点数","text":"大多数实数都无法用浮点数准确地表示,因此有必要知道两个相邻可表示的浮点数间的距离。它通常被叫做机器精度。","category":"page"},{"location":"manual/integers-and-floating-point-numbers/","page":"整数和浮点数","title":"整数和浮点数","text":"Julia 提供了 eps 函数,它可以给出 1.0 与下一个 Julia 能表示的浮点数之间的差值:","category":"page"},{"location":"manual/integers-and-floating-point-numbers/","page":"整数和浮点数","title":"整数和浮点数","text":"julia> eps(Float32)\n1.1920929f-7\n\njulia> eps(Float64)\n2.220446049250313e-16\n\njulia> eps() # 与 eps(Float64) 相同\n2.220446049250313e-16","category":"page"},{"location":"manual/integers-and-floating-point-numbers/","page":"整数和浮点数","title":"整数和浮点数","text":"这些值分别是 Float32 中的 2.0^-23 和 Float64 中的 2.0^-52。eps 函数也可以接受一个浮点值作为参数,然后给出这个值与下一个可表示的浮点数值之间的绝对差。也就是说,eps(x) 产生一个和 x 类型相同的值,并且 x + eps(x) 恰好是比 x 更大的下一个可表示的浮点值:","category":"page"},{"location":"manual/integers-and-floating-point-numbers/","page":"整数和浮点数","title":"整数和浮点数","text":"julia> eps(1.0)\n2.220446049250313e-16\n\njulia> eps(1000.)\n1.1368683772161603e-13\n\njulia> eps(1e-27)\n1.793662034335766e-43\n\njulia> eps(0.0)\n5.0e-324","category":"page"},{"location":"manual/integers-and-floating-point-numbers/","page":"整数和浮点数","title":"整数和浮点数","text":"两个相邻可表示的浮点数之间的距离并不是常数,数值越小,间距越小,数值越大,间距越大。换句话说,可表示的浮点数在实数轴上的零点附近最稠密,并沿着远离零点的方向以指数型的速度变得越来越稀疏。根据定义,eps(1.0) 与 eps(Float64) 相等,因为 1.0 是个 64 位浮点值。","category":"page"},{"location":"manual/integers-and-floating-point-numbers/","page":"整数和浮点数","title":"整数和浮点数","text":"Julia 也提供了 nextfloat 和 prevfloat 两个函数分别返回基于参数的下一个更大或更小的可表示的浮点数:","category":"page"},{"location":"manual/integers-and-floating-point-numbers/","page":"整数和浮点数","title":"整数和浮点数","text":"julia> x = 1.25f0\n1.25f0\n\njulia> nextfloat(x)\n1.2500001f0\n\njulia> prevfloat(x)\n1.2499999f0\n\njulia> bitstring(prevfloat(x))\n\"00111111100111111111111111111111\"\n\njulia> bitstring(x)\n\"00111111101000000000000000000000\"\n\njulia> bitstring(nextfloat(x))\n\"00111111101000000000000000000001\"","category":"page"},{"location":"manual/integers-and-floating-point-numbers/","page":"整数和浮点数","title":"整数和浮点数","text":"这个例子体现了一般原则,即相邻可表示的浮点数也有着相邻的二进制整数表示。","category":"page"},{"location":"manual/integers-and-floating-point-numbers/#舍入模式","page":"整数和浮点数","title":"舍入模式","text":"","category":"section"},{"location":"manual/integers-and-floating-point-numbers/","page":"整数和浮点数","title":"整数和浮点数","text":"一个数如果没有精确的浮点表示,就必须被舍入到一个合适的可表示的值。然而,如果想的话,可以根据舍入模式改变舍入的方式,如 IEEE 754 标准 所述。 ","category":"page"},{"location":"manual/integers-and-floating-point-numbers/","page":"整数和浮点数","title":"整数和浮点数","text":"Julia 所使用的默认模式总是 RoundNearest,指舍入到最接近的可表示的值,这个被舍入的值会使用尽量少的有效位数。","category":"page"},{"location":"manual/integers-and-floating-point-numbers/#背景知识与参考文献","page":"整数和浮点数","title":"背景知识与参考文献","text":"","category":"section"},{"location":"manual/integers-and-floating-point-numbers/","page":"整数和浮点数","title":"整数和浮点数","text":"浮点算术带来了很多微妙之处,它们可能对于那些不熟悉底层实现细节的用户会是很出人意料的。然而,这些微妙之处在大部分科学计算的书籍中以及以下的参考资料中都有详细介绍:","category":"page"},{"location":"manual/integers-and-floating-point-numbers/","page":"整数和浮点数","title":"整数和浮点数","text":"浮点数算术的权威指南是 IEEE 754-2008 标准; 然而这篇标准在网上无法免费获得。\n关于浮点数是如何表示的,想要一个简单而明白的介绍的话,可以看 John D. Cook 的文章以及他关于从这种表示与实数理想的抽象化的差别中产生的一些问题的介绍\n同样推荐 Bruce Dawson 的一系列关于浮点数的博客文章。\n想要一个对浮点数和使用浮点数计算时产生的数值精度问题的极好的、有深度的讨论,可以参见 David Goldberg 的文章 What Every Computer Scientist Should Know About Floating-Point Arithmetic。\n更多延伸文档,包括浮点数的历史、基础理论、问题以及数值计算中很多其它主题的讨论,可以参见 William Kahan 的写作集。他以“浮点数之父”闻名。特别感兴趣的话可以看 An Interview with the Old Man of Floating-Point。","category":"page"},{"location":"manual/integers-and-floating-point-numbers/#Arbitrary-Precision-Arithmetic","page":"整数和浮点数","title":"任意精度算术","text":"","category":"section"},{"location":"manual/integers-and-floating-point-numbers/","page":"整数和浮点数","title":"整数和浮点数","text":"为了允许使用任意精度的整数与浮点数,Julia 分别包装了 GNU Multiple Precision Arithmetic Library (GMP) 以及 GNU MPFR Library。Julia 中的 BigInt 与 BigFloat 两种类型分别提供了任意精度的整数和浮点数。","category":"page"},{"location":"manual/integers-and-floating-point-numbers/","page":"整数和浮点数","title":"整数和浮点数","text":"可以使用构造函数从原始数据类型创建任意精度的整数和浮点数,或是使用字符串字面量 @big_str、parse函数从 AbstractString 类型来创建。当创建的整型字面量过大而无法被其它内置的整数类型表示时,也会被输入为 BigInt 类型。注意到 Julia 的Base中并没有无符号的任意精度的整型(BigInt在多数情况下已经够用了),(除十进制外)也可以使用十六进制、八进制、二进制的字面量。","category":"page"},{"location":"manual/integers-and-floating-point-numbers/","page":"整数和浮点数","title":"整数和浮点数","text":"得益于 Julia 的类型提升和类型转换机制,一旦被创建,它们就可以像其它数值类型一样参与算术运算。","category":"page"},{"location":"manual/integers-and-floating-point-numbers/","page":"整数和浮点数","title":"整数和浮点数","text":"julia> BigInt(typemax(Int64)) + 1\n9223372036854775808\n\njulia> big\"123456789012345678901234567890\" + 1\n123456789012345678901234567891\n\njulia> parse(BigInt, \"123456789012345678901234567890\") + 1\n123456789012345678901234567891\n\njulia> string(big\"2\"^200, base=16)\n\"100000000000000000000000000000000000000000000000000\"\n\njulia> 0x100000000000000000000000000000000-1 == typemax(UInt128)\ntrue\n\njulia> 0x000000000000000000000000000000000\n0\n\njulia> typeof(ans)\nBigInt\n\njulia> big\"1.23456789012345678901\"\n1.234567890123456789010000000000000000000000000000000000000000000000000000000004\n\njulia> parse(BigFloat, \"1.23456789012345678901\")\n1.234567890123456789010000000000000000000000000000000000000000000000000000000004\n\njulia> BigFloat(2.0^66) / 3\n2.459565876494606882133333333333333333333333333333333333333333333333333333333344e+19\n\njulia> factorial(BigInt(40))\n815915283247897734345611269596115894272000000000","category":"page"},{"location":"manual/integers-and-floating-point-numbers/","page":"整数和浮点数","title":"整数和浮点数","text":"然而,上面的原始类型与 BigInt/BigFloat 之间的类型提升并不是自动的,需要明确地指定:","category":"page"},{"location":"manual/integers-and-floating-point-numbers/","page":"整数和浮点数","title":"整数和浮点数","text":"julia> x = typemin(Int64)\n-9223372036854775808\n\njulia> x = x - 1\n9223372036854775807\n\njulia> typeof(x)\nInt64\n\njulia> y = BigInt(typemin(Int64))\n-9223372036854775808\n\njulia> y = y - 1\n-9223372036854775809\n\njulia> typeof(y)\nBigInt","category":"page"},{"location":"manual/integers-and-floating-point-numbers/","page":"整数和浮点数","title":"整数和浮点数","text":"BigFloat 的默认精度(有效数字的位数)和舍入模式可以通过调用 setprecision 和 setrounding 来全局地改变,所有之后的计算都会根据这些改变进行。还有一种方法,可以使用同样的函数以及 do-block 来只在运行一个特定代码块时改变精度和舍入模式:","category":"page"},{"location":"manual/integers-and-floating-point-numbers/","page":"整数和浮点数","title":"整数和浮点数","text":"julia> setrounding(BigFloat, RoundUp) do\n BigFloat(1) + parse(BigFloat, \"0.1\")\n end\n1.100000000000000000000000000000000000000000000000000000000000000000000000000003\n\njulia> setrounding(BigFloat, RoundDown) do\n BigFloat(1) + parse(BigFloat, \"0.1\")\n end\n1.099999999999999999999999999999999999999999999999999999999999999999999999999986\n\njulia> setprecision(40) do\n BigFloat(1) + parse(BigFloat, \"0.1\")\n end\n1.1000000000004","category":"page"},{"location":"manual/integers-and-floating-point-numbers/#man-numeric-literal-coefficients","page":"整数和浮点数","title":"数值字面量系数","text":"","category":"section"},{"location":"manual/integers-and-floating-point-numbers/","page":"整数和浮点数","title":"整数和浮点数","text":"为了让常见的数值公式和表达式更清楚,Julia 允许变量直接跟在一个数值字面量后,暗指乘法。这可以让写多项式变得很清楚:","category":"page"},{"location":"manual/integers-and-floating-point-numbers/","page":"整数和浮点数","title":"整数和浮点数","text":"julia> x = 3\n3\n\njulia> 2x^2 - 3x + 1\n10\n\njulia> 1.5x^2 - .5x + 1\n13.0","category":"page"},{"location":"manual/integers-and-floating-point-numbers/","page":"整数和浮点数","title":"整数和浮点数","text":"也会让写指数函数变得更加优雅:","category":"page"},{"location":"manual/integers-and-floating-point-numbers/","page":"整数和浮点数","title":"整数和浮点数","text":"julia> 2^2x\n64","category":"page"},{"location":"manual/integers-and-floating-point-numbers/","page":"整数和浮点数","title":"整数和浮点数","text":"数值字面量系数的优先级跟一元运算符相同,比如说取相反数。所以 2^3x 会被解析成 2^(3x),而 2x^3 会被解析成 2*(x^3)。","category":"page"},{"location":"manual/integers-and-floating-point-numbers/","page":"整数和浮点数","title":"整数和浮点数","text":"数值字面量也能作为被括号表达式的系数:","category":"page"},{"location":"manual/integers-and-floating-point-numbers/","page":"整数和浮点数","title":"整数和浮点数","text":"julia> 2(x-1)^2 - 3(x-1) + 1\n3","category":"page"},{"location":"manual/integers-and-floating-point-numbers/","page":"整数和浮点数","title":"整数和浮点数","text":"note: Note\n用于隐式乘法的数值字面量系数的优先级高于其它的二元运算符,例如乘法(*)和除法(/、\\ 以及 //)。这意味着,比如说,1 / 2im 等于 -0.5im 以及 6 // 2(2+1) 等于 1 // 1。","category":"page"},{"location":"manual/integers-and-floating-point-numbers/","page":"整数和浮点数","title":"整数和浮点数","text":"此外,括号表达式可以被用作变量的系数,暗指表达式与变量相乘:","category":"page"},{"location":"manual/integers-and-floating-point-numbers/","page":"整数和浮点数","title":"整数和浮点数","text":"julia> (x-1)x\n6","category":"page"},{"location":"manual/integers-and-floating-point-numbers/","page":"整数和浮点数","title":"整数和浮点数","text":"但是,无论是把两个括号表达式并列,还是把变量放在括号表达式之前,都不会被用作暗指乘法:","category":"page"},{"location":"manual/integers-and-floating-point-numbers/","page":"整数和浮点数","title":"整数和浮点数","text":"julia> (x-1)(x+1)\nERROR: MethodError: objects of type Int64 are not callable\n\njulia> x(x+1)\nERROR: MethodError: objects of type Int64 are not callable","category":"page"},{"location":"manual/integers-and-floating-point-numbers/","page":"整数和浮点数","title":"整数和浮点数","text":"这两种表达式都会被解释成函数调用:所有不是数值字面量的表达式,后面紧跟一个括号,就会被解释成使用括号内的值来调用函数(更多关于函数的信息请参见函数)。因此,在这两种情况中,都会因为左边的值并不是函数而产生错误。","category":"page"},{"location":"manual/integers-and-floating-point-numbers/","page":"整数和浮点数","title":"整数和浮点数","text":"上述的语法糖显著地降低了在写普通数学公式时的视觉干扰。注意数值字面量系数和后面用来相乘的标识符或括号表达式之间不能有空格。","category":"page"},{"location":"manual/integers-and-floating-point-numbers/#语法冲突","page":"整数和浮点数","title":"语法冲突","text":"","category":"section"},{"location":"manual/integers-and-floating-point-numbers/","page":"整数和浮点数","title":"整数和浮点数","text":"并列的字面量系数语法可能和两种数值字面量语法产生冲突:十六进制、八进制、二进制整数字面量以及浮点字面量的工程表示法。下面是几种会产生语法冲突的情况:","category":"page"},{"location":"manual/integers-and-floating-point-numbers/","page":"整数和浮点数","title":"整数和浮点数","text":"十六进制整数字面量 0xff 可能被解释成数值字面量 0 乘以变量 xff。类似的,像 0o777 或0b01001010 使用八进制或二进制表示法也会形成冲突。\n浮点字面量表达式 1e10 可以被解释成数值字面量 1 乘以变量 e10,与之等价的 E-表示法也存在类似的情况。\n32-bit 的浮点数字面量 1.5f22 被解释成数值字面量 1.5 乘以变量 f22。","category":"page"},{"location":"manual/integers-and-floating-point-numbers/","page":"整数和浮点数","title":"整数和浮点数","text":"在这些所有的情况中,歧义都优先解释为数值字面量:","category":"page"},{"location":"manual/integers-and-floating-point-numbers/","page":"整数和浮点数","title":"整数和浮点数","text":"0x /0o/0b 开头的表达式总是十六进制/八进制/二进制字面量。\n数值开头跟着 e 和 E 的表达式总是浮点字面量。\n数值开头跟着 f 的表达式总是 32-bit 浮点字面量。","category":"page"},{"location":"manual/integers-and-floating-point-numbers/","page":"整数和浮点数","title":"整数和浮点数","text":"由于历史原因 E 和 e 在数值字面量上是等价的,与之不同的是,F 只是一个行为和 f 不同的字母。因此开头为 F 的表达式将会被 解析为一个数值字面量乘以一个变量,例如 1.5F22等价于 1.5 * F22。","category":"page"},{"location":"manual/integers-and-floating-point-numbers/#零和一的字面量","page":"整数和浮点数","title":"零和一的字面量","text":"","category":"section"},{"location":"manual/integers-and-floating-point-numbers/","page":"整数和浮点数","title":"整数和浮点数","text":"Julia 提供了 0 和 1 的字面量函数,可以返回特定类型或所给变量的类型。","category":"page"},{"location":"manual/integers-and-floating-point-numbers/","page":"整数和浮点数","title":"整数和浮点数","text":"函数 描述\nzero(x) x 类型或变量 x 的类型的零字面量\none(x) x 类型或变量 x 的类型的一字面量","category":"page"},{"location":"manual/integers-and-floating-point-numbers/","page":"整数和浮点数","title":"整数和浮点数","text":"这些函数在数值比较中可以用来避免不必要的类型转换带来的开销。","category":"page"},{"location":"manual/integers-and-floating-point-numbers/","page":"整数和浮点数","title":"整数和浮点数","text":"例如:","category":"page"},{"location":"manual/integers-and-floating-point-numbers/","page":"整数和浮点数","title":"整数和浮点数","text":"julia> zero(Float32)\n0.0f0\n\njulia> zero(1.0)\n0.0\n\njulia> one(Int32)\n1\n\njulia> one(BigFloat)\n1.0","category":"page"},{"location":"stdlib/Statistics/#统计","page":"统计","title":"统计","text":"","category":"section"},{"location":"stdlib/Statistics/","page":"统计","title":"统计","text":"DocTestSetup = :(using Statistics)","category":"page"},{"location":"stdlib/Statistics/","page":"统计","title":"统计","text":"统计模块包含了基本的统计函数。","category":"page"},{"location":"stdlib/Statistics/","page":"统计","title":"统计","text":"Statistics.std\nStatistics.stdm\nStatistics.var\nStatistics.varm\nStatistics.cor\nStatistics.cov\nStatistics.mean!\nStatistics.mean\nStatistics.median!\nStatistics.median\nStatistics.middle\nStatistics.quantile!\nStatistics.quantile","category":"page"},{"location":"stdlib/Statistics/#Statistics.std","page":"统计","title":"Statistics.std","text":"std(itr; corrected::Bool=true, mean=nothing[, dims])\n\nCompute the sample standard deviation of collection itr.\n\nThe algorithm returns an estimator of the generative distribution's standard deviation under the assumption that each entry of itr is a sample drawn from the same unknown distribution, with the samples uncorrelated. For arrays, this computation is equivalent to calculating sqrt(sum((itr .- mean(itr)).^2) / (length(itr) - 1)). If corrected is true, then the sum is scaled with n-1, whereas the sum is scaled with n if corrected is false with n the number of elements in itr.\n\nIf itr is an AbstractArray, dims can be provided to compute the standard deviation over dimensions, and means may contain means for each dimension of itr.\n\nA pre-computed mean may be provided. When dims is specified, mean must be an array with the same shape as mean(itr, dims=dims) (additional trailing singleton dimensions are allowed).\n\nnote: Note\nIf array contains NaN or missing values, the result is also NaN or missing (missing takes precedence if array contains both). Use the skipmissing function to omit missing entries and compute the standard deviation of non-missing values.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/Statistics/#Statistics.stdm","page":"统计","title":"Statistics.stdm","text":"stdm(itr, mean; corrected::Bool=true[, dims])\n\nCompute the sample standard deviation of collection itr, with known mean(s) mean.\n\nThe algorithm returns an estimator of the generative distribution's standard deviation under the assumption that each entry of itr is a sample drawn from the same unknown distribution, with the samples uncorrelated. For arrays, this computation is equivalent to calculating sqrt(sum((itr .- mean(itr)).^2) / (length(itr) - 1)). If corrected is true, then the sum is scaled with n-1, whereas the sum is scaled with n if corrected is false with n the number of elements in itr.\n\nIf itr is an AbstractArray, dims can be provided to compute the standard deviation over dimensions. In that case, mean must be an array with the same shape as mean(itr, dims=dims) (additional trailing singleton dimensions are allowed).\n\nnote: Note\nIf array contains NaN or missing values, the result is also NaN or missing (missing takes precedence if array contains both). Use the skipmissing function to omit missing entries and compute the standard deviation of non-missing values.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/Statistics/#Statistics.var","page":"统计","title":"Statistics.var","text":"var(itr; corrected::Bool=true, mean=nothing[, dims])\n\nCompute the sample variance of collection itr.\n\nThe algorithm returns an estimator of the generative distribution's variance under the assumption that each entry of itr is a sample drawn from the same unknown distribution, with the samples uncorrelated. For arrays, this computation is equivalent to calculating sum((itr .- mean(itr)).^2) / (length(itr) - 1)). If corrected is true, then the sum is scaled with n-1, whereas the sum is scaled with n if corrected is false where n is the number of elements in itr.\n\nIf itr is an AbstractArray, dims can be provided to compute the variance over dimensions.\n\nA pre-computed mean may be provided. When dims is specified, mean must be an array with the same shape as mean(itr, dims=dims) (additional trailing singleton dimensions are allowed).\n\nnote: Note\nIf array contains NaN or missing values, the result is also NaN or missing (missing takes precedence if array contains both). Use the skipmissing function to omit missing entries and compute the variance of non-missing values.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/Statistics/#Statistics.varm","page":"统计","title":"Statistics.varm","text":"varm(itr, mean; dims, corrected::Bool=true)\n\nCompute the sample variance of collection itr, with known mean(s) mean.\n\nThe algorithm returns an estimator of the generative distribution's variance under the assumption that each entry of itr is a sample drawn from the same unknown distribution, with the samples uncorrelated. For arrays, this computation is equivalent to calculating sum((itr .- mean(itr)).^2) / (length(itr) - 1). If corrected is true, then the sum is scaled with n-1, whereas the sum is scaled with n if corrected is false with n the number of elements in itr.\n\nIf itr is an AbstractArray, dims can be provided to compute the variance over dimensions. In that case, mean must be an array with the same shape as mean(itr, dims=dims) (additional trailing singleton dimensions are allowed).\n\nnote: Note\nIf array contains NaN or missing values, the result is also NaN or missing (missing takes precedence if array contains both). Use the skipmissing function to omit missing entries and compute the variance of non-missing values.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/Statistics/#Statistics.cor","page":"统计","title":"Statistics.cor","text":"cor(x::AbstractVector)\n\nReturn the number one.\n\n\n\n\n\ncor(X::AbstractMatrix; dims::Int=1)\n\nCompute the Pearson correlation matrix of the matrix X along the dimension dims.\n\n\n\n\n\ncor(x::AbstractVector, y::AbstractVector)\n\nCompute the Pearson correlation between the vectors x and y.\n\n\n\n\n\ncor(X::AbstractVecOrMat, Y::AbstractVecOrMat; dims=1)\n\nCompute the Pearson correlation between the vectors or matrices X and Y along the dimension dims.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/Statistics/#Statistics.cov","page":"统计","title":"Statistics.cov","text":"cov(x::AbstractVector; corrected::Bool=true)\n\nCompute the variance of the vector x. If corrected is true (the default) then the sum is scaled with n-1, whereas the sum is scaled with n if corrected is false where n = length(x).\n\n\n\n\n\ncov(X::AbstractMatrix; dims::Int=1, corrected::Bool=true)\n\nCompute the covariance matrix of the matrix X along the dimension dims. If corrected is true (the default) then the sum is scaled with n-1, whereas the sum is scaled with n if corrected is false where n = size(X, dims).\n\n\n\n\n\ncov(x::AbstractVector, y::AbstractVector; corrected::Bool=true)\n\nCompute the covariance between the vectors x and y. If corrected is true (the default), computes frac1n-1sum_i=1^n (x_i-bar x) (y_i-bar y)^* where * denotes the complex conjugate and n = length(x) = length(y). If corrected is false, computes frac1nsum_i=1^n (x_i-bar x) (y_i-bar y)^*.\n\n\n\n\n\ncov(X::AbstractVecOrMat, Y::AbstractVecOrMat; dims::Int=1, corrected::Bool=true)\n\nCompute the covariance between the vectors or matrices X and Y along the dimension dims. If corrected is true (the default) then the sum is scaled with n-1, whereas the sum is scaled with n if corrected is false where n = size(X, dims) = size(Y, dims).\n\n\n\n\n\n","category":"function"},{"location":"stdlib/Statistics/#Statistics.mean!","page":"统计","title":"Statistics.mean!","text":"mean!(r, v)\n\nCompute the mean of v over the singleton dimensions of r, and write results to r.\n\nExamples\n\njulia> using Statistics\n\njulia> v = [1 2; 3 4]\n2×2 Matrix{Int64}:\n 1 2\n 3 4\n\njulia> mean!([1., 1.], v)\n2-element Vector{Float64}:\n 1.5\n 3.5\n\njulia> mean!([1. 1.], v)\n1×2 Matrix{Float64}:\n 2.0 3.0\n\n\n\n\n\n","category":"function"},{"location":"stdlib/Statistics/#Statistics.mean","page":"统计","title":"Statistics.mean","text":"mean(itr)\n\nCompute the mean of all elements in a collection.\n\nnote: Note\nIf itr contains NaN or missing values, the result is also NaN or missing (missing takes precedence if array contains both). Use the skipmissing function to omit missing entries and compute the mean of non-missing values.\n\nExamples\n\njulia> using Statistics\n\njulia> mean(1:20)\n10.5\n\njulia> mean([1, missing, 3])\nmissing\n\njulia> mean(skipmissing([1, missing, 3]))\n2.0\n\n\n\n\n\nmean(f::Function, itr)\n\nApply the function f to each element of collection itr and take the mean.\n\njulia> using Statistics\n\njulia> mean(√, [1, 2, 3])\n1.3820881233139908\n\njulia> mean([√1, √2, √3])\n1.3820881233139908\n\n\n\n\n\nmean(f::Function, A::AbstractArray; dims)\n\nApply the function f to each element of array A and take the mean over dimensions dims.\n\ncompat: Julia 1.3\nThis method requires at least Julia 1.3.\n\njulia> using Statistics\n\njulia> mean(√, [1, 2, 3])\n1.3820881233139908\n\njulia> mean([√1, √2, √3])\n1.3820881233139908\n\njulia> mean(√, [1 2 3; 4 5 6], dims=2)\n2×1 Matrix{Float64}:\n 1.3820881233139908\n 2.2285192400943226\n\n\n\n\n\nmean(A::AbstractArray; dims)\n\nCompute the mean of an array over the given dimensions.\n\ncompat: Julia 1.1\nmean for empty arrays requires at least Julia 1.1.\n\nExamples\n\njulia> using Statistics\n\njulia> A = [1 2; 3 4]\n2×2 Matrix{Int64}:\n 1 2\n 3 4\n\njulia> mean(A, dims=1)\n1×2 Matrix{Float64}:\n 2.0 3.0\n\njulia> mean(A, dims=2)\n2×1 Matrix{Float64}:\n 1.5\n 3.5\n\n\n\n\n\n","category":"function"},{"location":"stdlib/Statistics/#Statistics.median!","page":"统计","title":"Statistics.median!","text":"median!(v)\n\nLike median, but may overwrite the input vector.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/Statistics/#Statistics.median","page":"统计","title":"Statistics.median","text":"median(itr)\n\nCompute the median of all elements in a collection. For an even number of elements no exact median element exists, so the result is equivalent to calculating mean of two median elements.\n\nnote: Note\nIf itr contains NaN or missing values, the result is also NaN or missing (missing takes precedence if itr contains both). Use the skipmissing function to omit missing entries and compute the median of non-missing values.\n\nExamples\n\njulia> using Statistics\n\njulia> median([1, 2, 3])\n2.0\n\njulia> median([1, 2, 3, 4])\n2.5\n\njulia> median([1, 2, missing, 4])\nmissing\n\njulia> median(skipmissing([1, 2, missing, 4]))\n2.0\n\n\n\n\n\nmedian(A::AbstractArray; dims)\n\nCompute the median of an array along the given dimensions.\n\nExamples\n\njulia> using Statistics\n\njulia> median([1 2; 3 4], dims=1)\n1×2 Matrix{Float64}:\n 2.0 3.0\n\n\n\n\n\n","category":"function"},{"location":"stdlib/Statistics/#Statistics.middle","page":"统计","title":"Statistics.middle","text":"middle(x)\n\nCompute the middle of a scalar value, which is equivalent to x itself, but of the type of middle(x, x) for consistency.\n\n\n\n\n\nmiddle(x, y)\n\nCompute the middle of two numbers x and y, which is equivalent in both value and type to computing their mean ((x + y) / 2).\n\n\n\n\n\nmiddle(range)\n\nCompute the middle of a range, which consists of computing the mean of its extrema. Since a range is sorted, the mean is performed with the first and last element.\n\njulia> using Statistics\n\njulia> middle(1:10)\n5.5\n\n\n\n\n\nmiddle(a)\n\nCompute the middle of an array a, which consists of finding its extrema and then computing their mean.\n\njulia> using Statistics\n\njulia> a = [1,2,3.6,10.9]\n4-element Vector{Float64}:\n 1.0\n 2.0\n 3.6\n 10.9\n\njulia> middle(a)\n5.95\n\n\n\n\n\n","category":"function"},{"location":"stdlib/Statistics/#Statistics.quantile!","page":"统计","title":"Statistics.quantile!","text":"quantile!([q::AbstractArray, ] v::AbstractVector, p; sorted=false, alpha::Real=1.0, beta::Real=alpha)\n\nCompute the quantile(s) of a vector v at a specified probability or vector or tuple of probabilities p on the interval [0,1]. If p is a vector, an optional output array q may also be specified. (If not provided, a new output array is created.) The keyword argument sorted indicates whether v can be assumed to be sorted; if false (the default), then the elements of v will be partially sorted in-place.\n\nBy default (alpha = beta = 1), quantiles are computed via linear interpolation between the points ((k-1)/(n-1), v[k]), for k = 1:n where n = length(v). This corresponds to Definition 7 of Hyndman and Fan (1996), and is the same as the R and NumPy default.\n\nThe keyword arguments alpha and beta correspond to the same parameters in Hyndman and Fan, setting them to different values allows to calculate quantiles with any of the methods 4-9 defined in this paper:\n\nDef. 4: alpha=0, beta=1\nDef. 5: alpha=0.5, beta=0.5\nDef. 6: alpha=0, beta=0 (Excel PERCENTILE.EXC, Python default, Stata altdef)\nDef. 7: alpha=1, beta=1 (Julia, R and NumPy default, Excel PERCENTILE and PERCENTILE.INC, Python 'inclusive')\nDef. 8: alpha=1/3, beta=1/3\nDef. 9: alpha=3/8, beta=3/8\n\nnote: Note\nAn ArgumentError is thrown if v contains NaN or missing values.\n\nReferences\n\nHyndman, R.J and Fan, Y. (1996) \"Sample Quantiles in Statistical Packages\", The American Statistician, Vol. 50, No. 4, pp. 361-365\nQuantile on Wikipedia details the different quantile definitions\n\nExamples\n\njulia> using Statistics\n\njulia> x = [3, 2, 1];\n\njulia> quantile!(x, 0.5)\n2.0\n\njulia> x\n3-element Vector{Int64}:\n 1\n 2\n 3\n\njulia> y = zeros(3);\n\njulia> quantile!(y, x, [0.1, 0.5, 0.9]) === y\ntrue\n\njulia> y\n3-element Vector{Float64}:\n 1.2000000000000002\n 2.0\n 2.8000000000000003\n\n\n\n\n\n","category":"function"},{"location":"stdlib/Statistics/#Statistics.quantile","page":"统计","title":"Statistics.quantile","text":"quantile(itr, p; sorted=false, alpha::Real=1.0, beta::Real=alpha)\n\nCompute the quantile(s) of a collection itr at a specified probability or vector or tuple of probabilities p on the interval [0,1]. The keyword argument sorted indicates whether itr can be assumed to be sorted.\n\nSamples quantile are defined by Q(p) = (1-γ)*x[j] + γ*x[j+1], where xj is the j-th order statistic, and γ is a function of j = floor(n*p + m), m = alpha + p*(1 - alpha - beta) and g = n*p + m - j.\n\nBy default (alpha = beta = 1), quantiles are computed via linear interpolation between the points ((k-1)/(n-1), v[k]), for k = 1:n where n = length(itr). This corresponds to Definition 7 of Hyndman and Fan (1996), and is the same as the R and NumPy default.\n\nThe keyword arguments alpha and beta correspond to the same parameters in Hyndman and Fan, setting them to different values allows to calculate quantiles with any of the methods 4-9 defined in this paper:\n\nDef. 4: alpha=0, beta=1\nDef. 5: alpha=0.5, beta=0.5\nDef. 6: alpha=0, beta=0 (Excel PERCENTILE.EXC, Python default, Stata altdef)\nDef. 7: alpha=1, beta=1 (Julia, R and NumPy default, Excel PERCENTILE and PERCENTILE.INC, Python 'inclusive')\nDef. 8: alpha=1/3, beta=1/3\nDef. 9: alpha=3/8, beta=3/8\n\nnote: Note\nAn ArgumentError is thrown if v contains NaN or missing values. Use the skipmissing function to omit missing entries and compute the quantiles of non-missing values.\n\nReferences\n\nHyndman, R.J and Fan, Y. (1996) \"Sample Quantiles in Statistical Packages\", The American Statistician, Vol. 50, No. 4, pp. 361-365\nQuantile on Wikipedia details the different quantile definitions\n\nExamples\n\njulia> using Statistics\n\njulia> quantile(0:20, 0.5)\n10.0\n\njulia> quantile(0:20, [0.1, 0.5, 0.9])\n3-element Vector{Float64}:\n 2.0\n 10.0\n 18.000000000000004\n\njulia> quantile(skipmissing([1, 10, missing]), 0.5)\n5.5\n\n\n\n\n\n","category":"function"},{"location":"stdlib/Statistics/","page":"统计","title":"统计","text":"DocTestSetup = nothing","category":"page"},{"location":"devdocs/require/#Module-loading","page":"Module loading","title":"Module loading","text":"","category":"section"},{"location":"devdocs/require/","page":"Module loading","title":"Module loading","text":"Base.require is responsible for loading modules and it also manages the precompilation cache. It is the implementation of the import statement.","category":"page"},{"location":"devdocs/require/#Experimental-features","page":"Module loading","title":"Experimental features","text":"","category":"section"},{"location":"devdocs/require/","page":"Module loading","title":"Module loading","text":"The features below are experimental and not part of the stable Julia API. Before building upon them inform yourself about the current thinking and whether they might change soon.","category":"page"},{"location":"devdocs/require/#Module-loading-callbacks","page":"Module loading","title":"Module loading callbacks","text":"","category":"section"},{"location":"devdocs/require/","page":"Module loading","title":"Module loading","text":"It is possible to listen to the modules loaded by Base.require, by registering a callback.","category":"page"},{"location":"devdocs/require/","page":"Module loading","title":"Module loading","text":"loaded_packages = Channel{Symbol}()\ncallback = (mod::Symbol) -> put!(loaded_packages, mod)\npush!(Base.package_callbacks, callback)","category":"page"},{"location":"devdocs/require/","page":"Module loading","title":"Module loading","text":"Please note that the symbol given to the callback is a non-unique identifier and it is the responsibility of the callback provider to walk the module chain to determine the fully qualified name of the loaded binding.","category":"page"},{"location":"devdocs/require/","page":"Module loading","title":"Module loading","text":"The callback below is an example of how to do that:","category":"page"},{"location":"devdocs/require/","page":"Module loading","title":"Module loading","text":"# Get the fully-qualified name of a module.\nfunction module_fqn(name::Symbol)\n fqn = fullname(Base.root_module(name))\n return join(fqn, '.')\nend","category":"page"},{"location":"manual/embedding/#嵌入-Julia","page":"嵌入 Julia","title":"嵌入 Julia","text":"","category":"section"},{"location":"manual/embedding/","page":"嵌入 Julia","title":"嵌入 Julia","text":"正如我们在 调用 C 和 Fortran 代码 中看到的, Julia 有着简单高效的方法来调用 C 编写的函数。但有时恰恰相反,我们需要在 C 中调用 Julia 的函数。这可以将 Julia 代码集成到一个更大的 C/C++ 项目而无需在 C/C++ 中重写所有内容。Julia 有一个 C API 来实现这一目标。几乎所有编程语言都能以某种方式来调用 C 语言的函数,因此 Julia 的 C API 也就能够进行更多语言的桥接。(例如在 Python 或是 C# 中调用 Julia ).","category":"page"},{"location":"manual/embedding/#高级别嵌入","page":"嵌入 Julia","title":"高级别嵌入","text":"","category":"section"},{"location":"manual/embedding/","page":"嵌入 Julia","title":"嵌入 Julia","text":"Note: 本节包含可运行在类 Unix 系统上的、使用 C 编写的嵌入式 Julia 代码。Windows 平台请参阅下一节。","category":"page"},{"location":"manual/embedding/","page":"嵌入 Julia","title":"嵌入 Julia","text":"我们从一个简单的 C 程序开始初始化 Julia 并调用一些 Julia 代码:","category":"page"},{"location":"manual/embedding/","page":"嵌入 Julia","title":"嵌入 Julia","text":"#include \nJULIA_DEFINE_FAST_TLS // only define this once, in an executable (not in a shared library) if you want fast code.\n\nint main(int argc, char *argv[])\n{\n /* required: setup the Julia context */\n jl_init();\n\n /* run Julia commands */\n jl_eval_string(\"print(sqrt(2.0))\");\n\n /* strongly recommended: notify Julia that the\n program is about to terminate. this allows\n Julia time to cleanup pending write requests\n and run all finalizers\n */\n jl_atexit_hook(0);\n return 0;\n}","category":"page"},{"location":"manual/embedding/","page":"嵌入 Julia","title":"嵌入 Julia","text":"为构建这个程序,你必须将 Julia 头文件的路径放入 include 路径并链接 libjulia 。例如 Julia 被安装到 $JULIA_DIR,则可以用 gcc 来编译上面的测试程序 test.c:","category":"page"},{"location":"manual/embedding/","page":"嵌入 Julia","title":"嵌入 Julia","text":"gcc -o test -fPIC -I$JULIA_DIR/include/julia -L$JULIA_DIR/lib -Wl,-rpath,$JULIA_DIR/lib test.c -ljulia","category":"page"},{"location":"manual/embedding/","page":"嵌入 Julia","title":"嵌入 Julia","text":"或者,查看 test/embedding/ 文件夹中 Julia 源代码树中的 embedding.c 程序。 文件 cli/loader_exe.c 程序是另一个简单的例子,说明如何在链接 libjulia 时设置 jl_options 选项。","category":"page"},{"location":"manual/embedding/","page":"嵌入 Julia","title":"嵌入 Julia","text":"在调用任何其他 Julia C 函数之前第一件必须要做的事是初始化 Julia,通过调用 jl_init 尝试自动确定 Julia 的安装位置来实现。如果需要自定义位置或指定要加载的系统映像,请改用 jl_init_with_image。","category":"page"},{"location":"manual/embedding/","page":"嵌入 Julia","title":"嵌入 Julia","text":"测试程序中的第二个语句通过调用 jl_eval_string 来执行 Julia 语句。","category":"page"},{"location":"manual/embedding/","page":"嵌入 Julia","title":"嵌入 Julia","text":"在程序结束之前,强烈建议调用 jl_atexit_hook。上面的示例程序在 main 返回之前进行了调用。","category":"page"},{"location":"manual/embedding/","page":"嵌入 Julia","title":"嵌入 Julia","text":"note: Note\n现在,动态链接 libjulia 的共享库需要传递选项 RTLD_GLOBAL 。比如在 Python 中像这样调用:>>> julia=CDLL('./libjulia.dylib',RTLD_GLOBAL)\n>>> julia.jl_init.argtypes = []\n>>> julia.jl_init()\n250593296","category":"page"},{"location":"manual/embedding/","page":"嵌入 Julia","title":"嵌入 Julia","text":"note: Note\n如果 Julia 程序需要访问 主可执行文件 中的符号,那么除了下面描述的由 julia-config.jl 生成的标记之外,可能还需要在 Linux 上的编译时添加 -Wl,--export-dynamic 链接器标志。编译共享库时则不必要。","category":"page"},{"location":"manual/embedding/#使用-julia-config-自动确定构建参数","page":"嵌入 Julia","title":"使用 julia-config 自动确定构建参数","text":"","category":"section"},{"location":"manual/embedding/","page":"嵌入 Julia","title":"嵌入 Julia","text":"julia-config.jl 创建脚本是为了帮助确定使用嵌入的 Julia 程序所需的构建参数。此脚本使用由其调用的特定 Julia 分发的构建参数和系统配置来导出嵌入程序的必要编译器标志以与该分发交互。此脚本位于 Julia 的 share 目录中。","category":"page"},{"location":"manual/embedding/#例子","page":"嵌入 Julia","title":"例子","text":"","category":"section"},{"location":"manual/embedding/","page":"嵌入 Julia","title":"嵌入 Julia","text":"#include \n\nint main(int argc, char *argv[])\n{\n jl_init();\n (void)jl_eval_string(\"println(sqrt(2.0))\");\n jl_atexit_hook(0);\n return 0;\n}","category":"page"},{"location":"manual/embedding/#在命令行中","page":"嵌入 Julia","title":"在命令行中","text":"","category":"section"},{"location":"manual/embedding/","page":"嵌入 Julia","title":"嵌入 Julia","text":"命令行脚本简单用法:假设 julia-config.jl 位于 /usr/local/julia/share/julia,它可以直接在命令行上调用,并采用 3 个标志的任意组合:","category":"page"},{"location":"manual/embedding/","page":"嵌入 Julia","title":"嵌入 Julia","text":"/usr/local/julia/share/julia/julia-config.jl\nUsage: julia-config [--cflags|--ldflags|--ldlibs]","category":"page"},{"location":"manual/embedding/","page":"嵌入 Julia","title":"嵌入 Julia","text":"如果上面的示例源代码保存为文件 embed_example.c,则以下命令将其编译为 Linux 和 Windows 上运行的程序(MSYS2 环境),或者如果在 OS/X 上,则用 clang 替换 gcc。:","category":"page"},{"location":"manual/embedding/","page":"嵌入 Julia","title":"嵌入 Julia","text":"/usr/local/julia/share/julia/julia-config.jl --cflags --ldflags --ldlibs | xargs gcc embed_example.c","category":"page"},{"location":"manual/embedding/#在-Makefiles-中使用","page":"嵌入 Julia","title":"在 Makefiles 中使用","text":"","category":"section"},{"location":"manual/embedding/","page":"嵌入 Julia","title":"嵌入 Julia","text":"但通常来说,嵌入的项目会比上面更复杂,因此一般会提供 makefile 支持。由于使用了 shell 宏扩展,我们就假设用 GNU make 。 另外,尽管很多时候 julia-config.jl 会在目录 /usr/local 中出现多次,不过也未必如此,但 Julia 也定位 julia-config.jl,并且可以使用 makefile 来利用它。上面的示例程序使用 Makefile 来扩展。:","category":"page"},{"location":"manual/embedding/","page":"嵌入 Julia","title":"嵌入 Julia","text":"JL_SHARE = $(shell julia -e 'print(joinpath(Sys.BINDIR, Base.DATAROOTDIR, \"julia\"))')\nCFLAGS += $(shell $(JL_SHARE)/julia-config.jl --cflags)\nCXXFLAGS += $(shell $(JL_SHARE)/julia-config.jl --cflags)\nLDFLAGS += $(shell $(JL_SHARE)/julia-config.jl --ldflags)\nLDLIBS += $(shell $(JL_SHARE)/julia-config.jl --ldlibs)\n\nall: embed_example","category":"page"},{"location":"manual/embedding/","page":"嵌入 Julia","title":"嵌入 Julia","text":"现在构建的命令就只需要简简单单的make了。","category":"page"},{"location":"manual/embedding/#在-Windows-使用-Visual-Studio-进行高级别嵌入","page":"嵌入 Julia","title":"在 Windows 使用 Visual Studio 进行高级别嵌入","text":"","category":"section"},{"location":"manual/embedding/","page":"嵌入 Julia","title":"嵌入 Julia","text":"如果尚未设置JULIA_DIR环境变量,请在启动 Visual Studio 之前使用系统面板添加它。JULIA_DIR 下的bin 文件夹应该在系统路径上。","category":"page"},{"location":"manual/embedding/","page":"嵌入 Julia","title":"嵌入 Julia","text":"我们首先打开 Visual Studio 并创建一个新的控制台应用程序项目。 在stdafx.h头文件的末尾添加以下几行:","category":"page"},{"location":"manual/embedding/","page":"嵌入 Julia","title":"嵌入 Julia","text":"#include ","category":"page"},{"location":"manual/embedding/","page":"嵌入 Julia","title":"嵌入 Julia","text":"然后,将项目中的 main() 函数替换为以下代码:","category":"page"},{"location":"manual/embedding/","page":"嵌入 Julia","title":"嵌入 Julia","text":"int main(int argc, char *argv[])\n{\n /* required: setup the Julia context */\n jl_init();\n\n /* run Julia commands */\n jl_eval_string(\"print(sqrt(2.0))\");\n\n /* strongly recommended: notify Julia that the\n program is about to terminate. this allows\n Julia time to cleanup pending write requests\n and run all finalizers\n */\n jl_atexit_hook(0);\n return 0;\n}","category":"page"},{"location":"manual/embedding/","page":"嵌入 Julia","title":"嵌入 Julia","text":"下一步是设置项目以查找 Julia 包含的文件和库。 了解 Julia 安装的是 32 位还是 64 位非常重要。 在继续之前删除与 Julia 安装不对应的任何平台配置。","category":"page"},{"location":"manual/embedding/","page":"嵌入 Julia","title":"嵌入 Julia","text":"使用项目属性对话框,转到C/C++ | General 并将 $(JULIA_DIR)\\include\\julia\\ 添加到 Additional Include Directories 属性。 然后,转到Linker | General 部分并将 $(JULIA_DIR)\\lib 添加到 Additional Library Directories 属性。最后,在Linker| Input下,将libjulia.dll.a;libopenlibm.dll.a;添加到库列表中。","category":"page"},{"location":"manual/embedding/","page":"嵌入 Julia","title":"嵌入 Julia","text":"到这里,该项目应该成功构建和运行。","category":"page"},{"location":"manual/embedding/#转换类型","page":"嵌入 Julia","title":"转换类型","text":"","category":"section"},{"location":"manual/embedding/","page":"嵌入 Julia","title":"嵌入 Julia","text":"真正的应用程序不仅仅要执行表达式,还要返回表达式的值给宿主程序。jl_eval_string 返回 一个 jl_value_t*,它是指向堆分配的 Julia 对象的指针。存储像 Float64 这些简单数据类型叫做 装箱,然后提取存储的基础类型数据叫 拆箱。我们改进的示例程序在 Julia 中计算 2 的平方根,并在 C 中读取回结果,如下所示:","category":"page"},{"location":"manual/embedding/","page":"嵌入 Julia","title":"嵌入 Julia","text":"jl_value_t *ret = jl_eval_string(\"sqrt(2.0)\");\n\nif (jl_typeis(ret, jl_float64_type)) {\n double ret_unboxed = jl_unbox_float64(ret);\n printf(\"sqrt(2.0) in C: %e \\n\", ret_unboxed);\n}\nelse {\n printf(\"ERROR: unexpected return type from sqrt(::Float64)\\n\");\n}","category":"page"},{"location":"manual/embedding/","page":"嵌入 Julia","title":"嵌入 Julia","text":"为了检查 ret 是否为特定的 Julia 类型,我们可以使用 jl_isa,jl_typeis 或 jl_is_... 函数。通过输入 typeof(sqrt(2.0))到 Julia shell,我们可以看到返回类型是 Float64(在C中是 double 类型)。要将装箱的 Julia 值转换为 C 的double,上面的代码片段使用了 jl_unbox_float64函数。","category":"page"},{"location":"manual/embedding/","page":"嵌入 Julia","title":"嵌入 Julia","text":"相应的, 用 jl_box_... 函数是另一种转换的方式。","category":"page"},{"location":"manual/embedding/","page":"嵌入 Julia","title":"嵌入 Julia","text":"jl_value_t *a = jl_box_float64(3.0);\njl_value_t *b = jl_box_float32(3.0f);\njl_value_t *c = jl_box_int32(3);","category":"page"},{"location":"manual/embedding/","page":"嵌入 Julia","title":"嵌入 Julia","text":"正如我们将在下面看到的那样,装箱需要在调用 Julia 函数时使用特定参数。","category":"page"},{"location":"manual/embedding/#调用-Julia-函数","page":"嵌入 Julia","title":"调用 Julia 函数","text":"","category":"section"},{"location":"manual/embedding/","page":"嵌入 Julia","title":"嵌入 Julia","text":"虽然 jl_eval_string 允许 C 获取 Julia 表达式的结果,但它不允许将在 C 中计算的参数传递给 Julia。因此需要使用 jl_call 来直接调用Julia函数:","category":"page"},{"location":"manual/embedding/","page":"嵌入 Julia","title":"嵌入 Julia","text":"jl_function_t *func = jl_get_function(jl_base_module, \"sqrt\");\njl_value_t *argument = jl_box_float64(2.0);\njl_value_t *ret = jl_call1(func, argument);","category":"page"},{"location":"manual/embedding/","page":"嵌入 Julia","title":"嵌入 Julia","text":"在第一步中,通过调用 jl_get_function 检索出 Julia 函数 sqrt 的句柄(handle)。 传递给 jl_get_function 的第一个参数是 指向 定义sqrt所在的 Base 模块 的指针。 然后,double 值通过 jl_box_float64 被装箱。 最后,使用 jl_call1 调用该函数。也有 jl_call0,jl_call2和jl_call3 函数,方便地处理不同数量的参数。 要传递更多参数,使用 jl_call:","category":"page"},{"location":"manual/embedding/","page":"嵌入 Julia","title":"嵌入 Julia","text":"jl_value_t *jl_call(jl_function_t *f, jl_value_t **args, int32_t nargs)","category":"page"},{"location":"manual/embedding/","page":"嵌入 Julia","title":"嵌入 Julia","text":"它的第二个参数 args 是 jl_value_t* 类型的数组,nargs 是参数的个数 ","category":"page"},{"location":"manual/embedding/#内存管理","page":"嵌入 Julia","title":"内存管理","text":"","category":"section"},{"location":"manual/embedding/","page":"嵌入 Julia","title":"嵌入 Julia","text":"正如我们所见,Julia 对象在 C 中表示为指针。这就出现了 谁来负责释放这些对象的问题。","category":"page"},{"location":"manual/embedding/","page":"嵌入 Julia","title":"嵌入 Julia","text":"通常,Julia 对象由垃圾收集器(GC)释放,但 GC 不会自动就懂我们正C中保留对Julia值的引用。这意味着 GC 会在你的掌控之外释放对象,从而使指针无效。","category":"page"},{"location":"manual/embedding/","page":"嵌入 Julia","title":"嵌入 Julia","text":"GC 只能在分配 Julia 对象时运行。 像 jl_box_float64 这样的调用执行分配,分配可能发生在运行 Julia 代码的任何时候。 然而,在 jl_... 调用之间使用指针通常是安全的。 但是为了确保值可以在 jl_... 调用后留存下来,我们必须告诉 Julia 我们仍然持有对 Julia root 的引用,这个过程称为“GC rooting”。把一个值”扎根“将确保垃圾收集器不会意外地将此值识别为未使用并释放该值的内存。 这可以使用 JL_GC_PUSH 宏来完成:","category":"page"},{"location":"manual/embedding/","page":"嵌入 Julia","title":"嵌入 Julia","text":"jl_value_t *ret = jl_eval_string(\"sqrt(2.0)\");\nJL_GC_PUSH1(&ret);\n// Do something with ret\nJL_GC_POP();","category":"page"},{"location":"manual/embedding/","page":"嵌入 Julia","title":"嵌入 Julia","text":"JL_GC_POP 调用会释放之前的 JL_GC_PUSH 建立的引用。 请注意,JL_GC_PUSH 将引用存储在 C 堆栈上,因此在退出作用域之前,它必须与一个 JL_GC_POP 精确配对。 也就是说,在函数返回之前,或者流程控制以其他方式离开调用了JL_GC_PUSH 的块。","category":"page"},{"location":"manual/embedding/","page":"嵌入 Julia","title":"嵌入 Julia","text":"可以使用 JL_GC_PUSH2、JL_GC_PUSH3、JL_GC_PUSH4、JL_GC_PUSH5 和 JL_GC_PUSH6 宏一次推送多个 Julia 值。 要推送一个 Julia 数组,可以使用 JL_GC_PUSHARGS 宏,其用法如下:","category":"page"},{"location":"manual/embedding/","page":"嵌入 Julia","title":"嵌入 Julia","text":"jl_value_t **args;\nJL_GC_PUSHARGS(args, 2); // args can now hold 2 `jl_value_t*` objects\nargs[0] = some_value;\nargs[1] = some_other_value;\n// Do something with args (e.g. call jl_... functions)\nJL_GC_POP();","category":"page"},{"location":"manual/embedding/","page":"嵌入 Julia","title":"嵌入 Julia","text":"每个作用域必须只有一次对 JL_GC_PUSH* 的调用。 因此,如果不能通过一次调用JL_GC_PUSH* 一次推送所有变量,或者如果要推送的变量超过 6 个并且使用参数数组不是一种选择,那么可以使用内部块:","category":"page"},{"location":"manual/embedding/","page":"嵌入 Julia","title":"嵌入 Julia","text":"jl_value_t *ret1 = jl_eval_string(\"sqrt(2.0)\");\nJL_GC_PUSH1(&ret1);\njl_value_t *ret2 = 0;\n{\n jl_function_t *func = jl_get_function(jl_base_module, \"exp\");\n ret2 = jl_call1(func, ret1);\n JL_GC_PUSH1(&ret2);\n // Do something with ret2.\n JL_GC_POP(); // This pops ret2.\n}\nJL_GC_POP(); // This pops ret1.","category":"page"},{"location":"manual/embedding/","page":"嵌入 Julia","title":"嵌入 Julia","text":"如果需要在函数(或块作用域)之间保存指向变量的指针,则不能使用 JL_GC_PUSH*。 在这种情况下,有必要在 Julia 全局作用域内创建并保留对变量的引用。 实现这一点的一种简单方法是使用一个全局的IdDict来保存引用,避免 GC 释放。 但是,此方法仅适用于可变类型。","category":"page"},{"location":"manual/embedding/","page":"嵌入 Julia","title":"嵌入 Julia","text":"// This functions shall be executed only once, during the initialization.\njl_value_t* refs = jl_eval_string(\"refs = IdDict()\");\njl_function_t* setindex = jl_get_function(jl_base_module, \"setindex!\");\n\n...\n\n// `var` is the variable we want to protect between function calls.\njl_value_t* var = 0;\n\n...\n\n// `var` is a `Vector{Float64}`, which is mutable.\nvar = jl_eval_string(\"[sqrt(2.0); sqrt(4.0); sqrt(6.0)]\");\n\n// To protect `var`, add its reference to `refs`.\njl_call3(setindex, refs, var, var);","category":"page"},{"location":"manual/embedding/","page":"嵌入 Julia","title":"嵌入 Julia","text":"如果变量是不可变的,则需要将其包装在等效的可变容器中,或者最好在将其推送到IdDict之前包装在RefValue{Any}中。 在这种方法中,容器必须通过 C 代码创建或填充,例如使用函数jl_new_struct。 如果容器是由jl_call* 创建的,那么你将需要重新加载要在 C 代码中使用的指针。","category":"page"},{"location":"manual/embedding/","page":"嵌入 Julia","title":"嵌入 Julia","text":"// This functions shall be executed only once, during the initialization.\njl_value_t* refs = jl_eval_string(\"refs = IdDict()\");\njl_function_t* setindex = jl_get_function(jl_base_module, \"setindex!\");\njl_datatype_t* reft = (jl_datatype_t*)jl_eval_string(\"Base.RefValue{Any}\");\n\n...\n\n// `var` is the variable we want to protect between function calls.\njl_value_t* var = 0;\n\n...\n\n// `var` is a `Float64`, which is immutable.\nvar = jl_eval_string(\"sqrt(2.0)\");\n\n// Protect `var` until we add its reference to `refs`.\nJL_GC_PUSH1(&var);\n\n// Wrap `var` in `RefValue{Any}` and push to `refs` to protect it.\njl_value_t* rvar = jl_new_struct(reft, var);\nJL_GC_POP();\n\njl_call3(setindex, refs, rvar, rvar);","category":"page"},{"location":"manual/embedding/","page":"嵌入 Julia","title":"嵌入 Julia","text":"GC 可以通过使用函数delete! 从refs 中删除对变量的引用来释放变量,前提是没有其它对该变量的引用保留在任何地方:","category":"page"},{"location":"manual/embedding/","page":"嵌入 Julia","title":"嵌入 Julia","text":"jl_function_t* delete = jl_get_function(jl_base_module, \"delete!\");\njl_call2(delete, refs, rvar);","category":"page"},{"location":"manual/embedding/","page":"嵌入 Julia","title":"嵌入 Julia","text":"作为非常简单情况的替代方案,可以只创建一个类型为Vector{Any}的全局容器,并在必要时从中获取元素,甚至可以使用以下方法为每个指针创建一个全局变量","category":"page"},{"location":"manual/embedding/","page":"嵌入 Julia","title":"嵌入 Julia","text":"jl_set_global(jl_main_module, jl_symbol(\"var\"), var);","category":"page"},{"location":"manual/embedding/#更新-GC-管理对象的字段","page":"嵌入 Julia","title":"更新 GC 管理对象的字段","text":"","category":"section"},{"location":"manual/embedding/","page":"嵌入 Julia","title":"嵌入 Julia","text":"垃圾回收器的运行假设它知道每个年老代对象都指向一个年轻代对象。 任何时候一个指针被更新打破了这个假设,它必须用jl_gc_wb(写屏障)函数向回收器发出信号,如下所示:","category":"page"},{"location":"manual/embedding/","page":"嵌入 Julia","title":"嵌入 Julia","text":"jl_value_t *parent = some_old_value, *child = some_young_value;\n((some_specific_type*)parent)->field = child;\njl_gc_wb(parent, child);","category":"page"},{"location":"manual/embedding/","page":"嵌入 Julia","title":"嵌入 Julia","text":"通常情况下不可能在运行时预测 值是否是旧的,因此 写屏障 必须被插入在所有显式存储之后。一个需要注意的例外是如果 parent 对象刚分配,垃圾收集之后并不执行。请记住大多数 jl_... 函数有时候都会执行垃圾收集。","category":"page"},{"location":"manual/embedding/","page":"嵌入 Julia","title":"嵌入 Julia","text":"直接更新数据时,对于指针数组来说 写屏障 也是必需的 例如:","category":"page"},{"location":"manual/embedding/","page":"嵌入 Julia","title":"嵌入 Julia","text":"jl_array_t *some_array = ...; // e.g. a Vector{Any}\nvoid **data = (void**)jl_array_data(some_array);\njl_value_t *some_value = ...;\ndata[0] = some_value;\njl_gc_wb(some_array, some_value);","category":"page"},{"location":"manual/embedding/#控制垃圾收集器","page":"嵌入 Julia","title":"控制垃圾收集器","text":"","category":"section"},{"location":"manual/embedding/","page":"嵌入 Julia","title":"嵌入 Julia","text":"有一些函数能够控制GC。在正常使用情况下这些不是必要的。","category":"page"},{"location":"manual/embedding/","page":"嵌入 Julia","title":"嵌入 Julia","text":"函数 描述\njl_gc_collect() 强制执行 GC\njl_gc_enable(0) 禁用 GC, 返回前一个状态作为 int 类型\njl_gc_enable(1) 启用 GC, 返回前一个状态作为 int 类型\njl_gc_is_enabled() 返回当前状态作为 int 类型","category":"page"},{"location":"manual/embedding/#使用数组","page":"嵌入 Julia","title":"使用数组","text":"","category":"section"},{"location":"manual/embedding/","page":"嵌入 Julia","title":"嵌入 Julia","text":"Julia 和 C 可以不通过复制而共享数组数据。下面一个例子将展示它是如何工作的。","category":"page"},{"location":"manual/embedding/","page":"嵌入 Julia","title":"嵌入 Julia","text":"Julia数组用数据类型 jl_array_t * 表示。基本上,jl_array_t 是一个包含以下内容的结构:","category":"page"},{"location":"manual/embedding/","page":"嵌入 Julia","title":"嵌入 Julia","text":"关于数据类型的信息\n指向数据块的指针\n关于数组长度的信息","category":"page"},{"location":"manual/embedding/","page":"嵌入 Julia","title":"嵌入 Julia","text":"为了让事情比较简单,我们从一维数组开始,创建一个存有 10 个 FLoat64 类型的数组如下所示:","category":"page"},{"location":"manual/embedding/","page":"嵌入 Julia","title":"嵌入 Julia","text":"jl_value_t* array_type = jl_apply_array_type((jl_value_t*)jl_float64_type, 1);\njl_array_t* x = jl_alloc_array_1d(array_type, 10);","category":"page"},{"location":"manual/embedding/","page":"嵌入 Julia","title":"嵌入 Julia","text":"或者,如果您已经分配了数组,则可以生成一个简易的包装器来包裹其数据:","category":"page"},{"location":"manual/embedding/","page":"嵌入 Julia","title":"嵌入 Julia","text":"double *existingArray = (double*)malloc(sizeof(double)*10);\njl_array_t *x = jl_ptr_to_array_1d(array_type, existingArray, 10, 0);","category":"page"},{"location":"manual/embedding/","page":"嵌入 Julia","title":"嵌入 Julia","text":"最后一个参数是一个布尔值,表示 Julia 是否应该获取数据的所有权。 如果这个参数 不为零,当数组不再被引用时,GC 会在数据的指针上调用 free 。","category":"page"},{"location":"manual/embedding/","page":"嵌入 Julia","title":"嵌入 Julia","text":"为了访问 x 的数据,我们可以使用 jl_array_data:","category":"page"},{"location":"manual/embedding/","page":"嵌入 Julia","title":"嵌入 Julia","text":"double *xData = (double*)jl_array_data(x);","category":"page"},{"location":"manual/embedding/","page":"嵌入 Julia","title":"嵌入 Julia","text":"现在我们可以填充这个数组:","category":"page"},{"location":"manual/embedding/","page":"嵌入 Julia","title":"嵌入 Julia","text":"for(size_t i=0; i\n$ make debug","category":"page"},{"location":"devdocs/backtraces/","page":"报告和分析崩溃(段错误)","title":"报告和分析崩溃(段错误)","text":"Note that this process will likely fail with the same error as a normal make incantation, however this will create a debug executable that will offer gdb the debugging symbols needed to get accurate backtraces. Next, manually run the bootstrap process inside of gdb:","category":"page"},{"location":"devdocs/backtraces/","page":"报告和分析崩溃(段错误)","title":"报告和分析崩溃(段错误)","text":"$ cd base/\n$ gdb -x ../contrib/debug_bootstrap.gdb","category":"page"},{"location":"devdocs/backtraces/","page":"报告和分析崩溃(段错误)","title":"报告和分析崩溃(段错误)","text":"This will start gdb, attempt to run the bootstrap process using the debug build of Julia, and print out a backtrace if (when) it segfaults. You may need to hit a few times to get the full backtrace. Create a gist with the backtrace, the version info, and any other pertinent information you can think of and open a new issue on Github with a link to the gist.","category":"page"},{"location":"devdocs/backtraces/#Segfaults-when-running-a-script","page":"报告和分析崩溃(段错误)","title":"Segfaults when running a script","text":"","category":"section"},{"location":"devdocs/backtraces/","page":"报告和分析崩溃(段错误)","title":"报告和分析崩溃(段错误)","text":"The procedure is very similar to Segfaults during bootstrap (sysimg.jl). Create a debug build of Julia, and run your script inside of a debugged Julia process:","category":"page"},{"location":"devdocs/backtraces/","page":"报告和分析崩溃(段错误)","title":"报告和分析崩溃(段错误)","text":"$ cd \n$ make debug\n$ gdb --args usr/bin/julia-debug ","category":"page"},{"location":"devdocs/backtraces/","page":"报告和分析崩溃(段错误)","title":"报告和分析崩溃(段错误)","text":"Note that gdb will sit there, waiting for instructions. Type r to run the process, and bt to generate a backtrace once it segfaults:","category":"page"},{"location":"devdocs/backtraces/","page":"报告和分析崩溃(段错误)","title":"报告和分析崩溃(段错误)","text":"(gdb) r\nStarting program: /home/sabae/src/julia/usr/bin/julia-debug ./test.jl\n...\n(gdb) bt","category":"page"},{"location":"devdocs/backtraces/","page":"报告和分析崩溃(段错误)","title":"报告和分析崩溃(段错误)","text":"Create a gist with the backtrace, the version info, and any other pertinent information you can think of and open a new issue on Github with a link to the gist.","category":"page"},{"location":"devdocs/backtraces/#Errors-during-Julia-startup","page":"报告和分析崩溃(段错误)","title":"Errors during Julia startup","text":"","category":"section"},{"location":"devdocs/backtraces/","page":"报告和分析崩溃(段错误)","title":"报告和分析崩溃(段错误)","text":"Occasionally errors occur during Julia's startup process (especially when using binary distributions, as opposed to compiling from source) such as the following:","category":"page"},{"location":"devdocs/backtraces/","page":"报告和分析崩溃(段错误)","title":"报告和分析崩溃(段错误)","text":"$ julia\nexec: error -5","category":"page"},{"location":"devdocs/backtraces/","page":"报告和分析崩溃(段错误)","title":"报告和分析崩溃(段错误)","text":"These errors typically indicate something is not getting loaded properly very early on in the bootup phase, and our best bet in determining what's going wrong is to use external tools to audit the disk activity of the julia process:","category":"page"},{"location":"devdocs/backtraces/","page":"报告和分析崩溃(段错误)","title":"报告和分析崩溃(段错误)","text":"On Linux, use strace:\n$ strace julia\nOn OSX, use dtruss:\n$ dtruss -f julia","category":"page"},{"location":"devdocs/backtraces/","page":"报告和分析崩溃(段错误)","title":"报告和分析崩溃(段错误)","text":"Create a gist with the strace/ dtruss output, the version info, and any other pertinent information and open a new issue on Github with a link to the gist.","category":"page"},{"location":"devdocs/backtraces/#Other-generic-segfaults-or-unreachables-reached","page":"报告和分析崩溃(段错误)","title":"Other generic segfaults or unreachables reached","text":"","category":"section"},{"location":"devdocs/backtraces/","page":"报告和分析崩溃(段错误)","title":"报告和分析崩溃(段错误)","text":"As mentioned elsewhere, julia has good integration with rr for generating traces; this includes, on Linux, the ability to automatically run julia under rr and share the trace after a crash. This can be immensely helpful when debugging such crashes and is strongly encouraged when reporting crash issues to the JuliaLang/julia repo. To run julia under rr automatically, do:","category":"page"},{"location":"devdocs/backtraces/","page":"报告和分析崩溃(段错误)","title":"报告和分析崩溃(段错误)","text":"julia --bug-report=rr","category":"page"},{"location":"devdocs/backtraces/","page":"报告和分析崩溃(段错误)","title":"报告和分析崩溃(段错误)","text":"To generate the rr trace locally, but not share, you can do:","category":"page"},{"location":"devdocs/backtraces/","page":"报告和分析崩溃(段错误)","title":"报告和分析崩溃(段错误)","text":"julia --bug-report=rr-local","category":"page"},{"location":"devdocs/backtraces/","page":"报告和分析崩溃(段错误)","title":"报告和分析崩溃(段错误)","text":"Note that this is only works on Linux. The blog post on Time Travelling Bug Reporting has many more details.","category":"page"},{"location":"devdocs/backtraces/#Glossary","page":"报告和分析崩溃(段错误)","title":"Glossary","text":"","category":"section"},{"location":"devdocs/backtraces/","page":"报告和分析崩溃(段错误)","title":"报告和分析崩溃(段错误)","text":"A few terms have been used as shorthand in this guide:","category":"page"},{"location":"devdocs/backtraces/","page":"报告和分析崩溃(段错误)","title":"报告和分析崩溃(段错误)","text":" refers to the root directory of the Julia source tree; e.g. it should contain folders such as base, deps, src, test, etc.....","category":"page"},{"location":"devdocs/init/#Julia-运行时的初始化","page":"Julia 运行时的初始化","title":"Julia 运行时的初始化","text":"","category":"section"},{"location":"devdocs/init/","page":"Julia 运行时的初始化","title":"Julia 运行时的初始化","text":"How does the Julia runtime execute julia -e 'println(\"Hello World!\")' ?","category":"page"},{"location":"devdocs/init/#main()","page":"Julia 运行时的初始化","title":"main()","text":"","category":"section"},{"location":"devdocs/init/","page":"Julia 运行时的初始化","title":"Julia 运行时的初始化","text":"Execution starts at main() in cli/loader_exe.c, which calls jl_load_repl() in cli/loader_lib.c which loads a few libraries, eventually calling repl_entrypoint() in src/jlapi.c.","category":"page"},{"location":"devdocs/init/","page":"Julia 运行时的初始化","title":"Julia 运行时的初始化","text":"repl_entrypoint() calls libsupport_init() to set the C library locale and to initialize the \"ios\" library (see ios_init_stdstreams() and Legacy ios.c library).","category":"page"},{"location":"devdocs/init/","page":"Julia 运行时的初始化","title":"Julia 运行时的初始化","text":"Next jl_parse_opts() is called to process command line options. Note that jl_parse_opts() only deals with options that affect code generation or early initialization. Other options are handled later by process_options() in base/client.jl.","category":"page"},{"location":"devdocs/init/","page":"Julia 运行时的初始化","title":"Julia 运行时的初始化","text":"jl_parse_opts() stores command line options in the global jl_options struct.","category":"page"},{"location":"devdocs/init/#julia_init()","page":"Julia 运行时的初始化","title":"julia_init()","text":"","category":"section"},{"location":"devdocs/init/","page":"Julia 运行时的初始化","title":"Julia 运行时的初始化","text":"julia_init() in task.c is called by main() and calls _julia_init() in init.c.","category":"page"},{"location":"devdocs/init/","page":"Julia 运行时的初始化","title":"Julia 运行时的初始化","text":"_julia_init() begins by calling libsupport_init() again (it does nothing the second time).","category":"page"},{"location":"devdocs/init/","page":"Julia 运行时的初始化","title":"Julia 运行时的初始化","text":"restore_signals() is called to zero the signal handler mask.","category":"page"},{"location":"devdocs/init/","page":"Julia 运行时的初始化","title":"Julia 运行时的初始化","text":"jl_resolve_sysimg_location() searches configured paths for the base system image. See Building the Julia system image.","category":"page"},{"location":"devdocs/init/","page":"Julia 运行时的初始化","title":"Julia 运行时的初始化","text":"jl_gc_init() sets up allocation pools and lists for weak refs, preserved values and finalization.","category":"page"},{"location":"devdocs/init/","page":"Julia 运行时的初始化","title":"Julia 运行时的初始化","text":"jl_init_frontend() loads and initializes a pre-compiled femtolisp image containing the scanner/parser.","category":"page"},{"location":"devdocs/init/","page":"Julia 运行时的初始化","title":"Julia 运行时的初始化","text":"jl_init_types() creates jl_datatype_t type description objects for the built-in types defined in julia.h. e.g.","category":"page"},{"location":"devdocs/init/","page":"Julia 运行时的初始化","title":"Julia 运行时的初始化","text":"jl_any_type = jl_new_abstracttype(jl_symbol(\"Any\"), core, NULL, jl_emptysvec);\njl_any_type->super = jl_any_type;\n\njl_type_type = jl_new_abstracttype(jl_symbol(\"Type\"), core, jl_any_type, jl_emptysvec);\n\njl_int32_type = jl_new_primitivetype(jl_symbol(\"Int32\"), core,\n jl_any_type, jl_emptysvec, 32);","category":"page"},{"location":"devdocs/init/","page":"Julia 运行时的初始化","title":"Julia 运行时的初始化","text":"jl_init_tasks() creates the jl_datatype_t* jl_task_type object; initializes the global jl_root_task struct; and sets jl_current_task to the root task.","category":"page"},{"location":"devdocs/init/","page":"Julia 运行时的初始化","title":"Julia 运行时的初始化","text":"jl_init_codegen() initializes the LLVM library.","category":"page"},{"location":"devdocs/init/","page":"Julia 运行时的初始化","title":"Julia 运行时的初始化","text":"jl_init_serializer() initializes 8-bit serialization tags for builtin jl_value_t values.","category":"page"},{"location":"devdocs/init/","page":"Julia 运行时的初始化","title":"Julia 运行时的初始化","text":"If there is no sysimg file (!jl_options.image_file) then the Core and Main modules are created and boot.jl is evaluated:","category":"page"},{"location":"devdocs/init/","page":"Julia 运行时的初始化","title":"Julia 运行时的初始化","text":"jl_core_module = jl_new_module(jl_symbol(\"Core\")) creates the Julia Core module.","category":"page"},{"location":"devdocs/init/","page":"Julia 运行时的初始化","title":"Julia 运行时的初始化","text":"jl_init_intrinsic_functions() creates a new Julia module Intrinsics containing constant jl_intrinsic_type symbols. These define an integer code for each intrinsic function. emit_intrinsic() translates these symbols into LLVM instructions during code generation.","category":"page"},{"location":"devdocs/init/","page":"Julia 运行时的初始化","title":"Julia 运行时的初始化","text":"jl_init_primitives() hooks C functions up to Julia function symbols. e.g. the symbol Core.:(===)() is bound to C function pointer jl_f_is() by calling add_builtin_func(\"===\", jl_f_is).","category":"page"},{"location":"devdocs/init/","page":"Julia 运行时的初始化","title":"Julia 运行时的初始化","text":"jl_new_main_module() creates the global \"Main\" module and sets jl_current_task->current_module = jl_main_module.","category":"page"},{"location":"devdocs/init/","page":"Julia 运行时的初始化","title":"Julia 运行时的初始化","text":"Note: _julia_init() then sets jl_root_task->current_module = jl_core_module. jl_root_task is an alias of jl_current_task at this point, so the current_module set by jl_new_main_module() above is overwritten.","category":"page"},{"location":"devdocs/init/","page":"Julia 运行时的初始化","title":"Julia 运行时的初始化","text":"jl_load(\"boot.jl\", sizeof(\"boot.jl\")) calls jl_parse_eval_all which repeatedly calls jl_toplevel_eval_flex() to execute boot.jl. ","category":"page"},{"location":"devdocs/init/","page":"Julia 运行时的初始化","title":"Julia 运行时的初始化","text":"jl_get_builtin_hooks() initializes global C pointers to Julia globals defined in boot.jl.","category":"page"},{"location":"devdocs/init/","page":"Julia 运行时的初始化","title":"Julia 运行时的初始化","text":"jl_init_box_caches() pre-allocates global boxed integer value objects for values up to 1024. This speeds up allocation of boxed ints later on. e.g.:","category":"page"},{"location":"devdocs/init/","page":"Julia 运行时的初始化","title":"Julia 运行时的初始化","text":"jl_value_t *jl_box_uint8(uint32_t x)\n{\n return boxed_uint8_cache[(uint8_t)x];\n}","category":"page"},{"location":"devdocs/init/","page":"Julia 运行时的初始化","title":"Julia 运行时的初始化","text":"_julia_init() iterates over the jl_core_module->bindings.table looking for jl_datatype_t values and sets the type name's module prefix to jl_core_module.","category":"page"},{"location":"devdocs/init/","page":"Julia 运行时的初始化","title":"Julia 运行时的初始化","text":"jl_add_standard_imports(jl_main_module) does \"using Base\" in the \"Main\" module.","category":"page"},{"location":"devdocs/init/","page":"Julia 运行时的初始化","title":"Julia 运行时的初始化","text":"Note: _julia_init() now reverts to jl_root_task->current_module = jl_main_module as it was before being set to jl_core_module above.","category":"page"},{"location":"devdocs/init/","page":"Julia 运行时的初始化","title":"Julia 运行时的初始化","text":"Platform specific signal handlers are initialized for SIGSEGV (OSX, Linux), and SIGFPE (Windows).","category":"page"},{"location":"devdocs/init/","page":"Julia 运行时的初始化","title":"Julia 运行时的初始化","text":"Other signals (SIGINFO, SIGBUS, SIGILL, SIGTERM, SIGABRT, SIGQUIT, SIGSYS and SIGPIPE) are hooked up to sigdie_handler() which prints a backtrace.","category":"page"},{"location":"devdocs/init/","page":"Julia 运行时的初始化","title":"Julia 运行时的初始化","text":"jl_init_restored_modules() calls jl_module_run_initializer() for each deserialized module to run the __init__() function.","category":"page"},{"location":"devdocs/init/","page":"Julia 运行时的初始化","title":"Julia 运行时的初始化","text":"Finally sigint_handler() is hooked up to SIGINT and calls jl_throw(jl_interrupt_exception).","category":"page"},{"location":"devdocs/init/","page":"Julia 运行时的初始化","title":"Julia 运行时的初始化","text":"_julia_init() then returns back to main() in cli/loader_exe.c and main() calls repl_entrypoint(argc, (char**)argv).","category":"page"},{"location":"devdocs/init/","page":"Julia 运行时的初始化","title":"Julia 运行时的初始化","text":"sidebar: sysimg\nIf there is a sysimg file, it contains a pre-cooked image of the Core and Main modules (and whatever else is created by boot.jl). See Building the Julia system image.jl_restore_system_image() deserializes the saved sysimg into the current Julia runtime environment and initialization continues after jl_init_box_caches() below...Note: jl_restore_system_image() (and staticdata.c in general) uses the Legacy ios.c library.","category":"page"},{"location":"devdocs/init/#repl_entrypoint()","page":"Julia 运行时的初始化","title":"repl_entrypoint()","text":"","category":"section"},{"location":"devdocs/init/","page":"Julia 运行时的初始化","title":"Julia 运行时的初始化","text":"repl_entrypoint() loads the contents of argv[] into Base.ARGS.","category":"page"},{"location":"devdocs/init/","page":"Julia 运行时的初始化","title":"Julia 运行时的初始化","text":"If a .jl \"program\" file was supplied on the command line, then exec_program() calls jl_load(program,len) which calls jl_parse_eval_all which repeatedly calls jl_toplevel_eval_flex() to execute the program.","category":"page"},{"location":"devdocs/init/","page":"Julia 运行时的初始化","title":"Julia 运行时的初始化","text":"However, in our example (julia -e 'println(\"Hello World!\")'), jl_get_global(jl_base_module, jl_symbol(\"_start\")) looks up Base._start and jl_apply() executes it.","category":"page"},{"location":"devdocs/init/#Base._start","page":"Julia 运行时的初始化","title":"Base._start","text":"","category":"section"},{"location":"devdocs/init/","page":"Julia 运行时的初始化","title":"Julia 运行时的初始化","text":"Base._start calls Base.process_options which calls jl_parse_input_line(\"println(\"Hello World!\")\") to create an expression object and Base.eval() to execute it.","category":"page"},{"location":"devdocs/init/#Base.eval","page":"Julia 运行时的初始化","title":"Base.eval","text":"","category":"section"},{"location":"devdocs/init/","page":"Julia 运行时的初始化","title":"Julia 运行时的初始化","text":"Base.eval() was mapped to jl_f_top_eval by jl_init_primitives().","category":"page"},{"location":"devdocs/init/","page":"Julia 运行时的初始化","title":"Julia 运行时的初始化","text":"jl_f_top_eval() calls jl_toplevel_eval_in(jl_main_module, ex), where ex is the parsed expression println(\"Hello World!\").","category":"page"},{"location":"devdocs/init/","page":"Julia 运行时的初始化","title":"Julia 运行时的初始化","text":"jl_toplevel_eval_in() calls jl_toplevel_eval_flex() which calls eval() in interpreter.c.","category":"page"},{"location":"devdocs/init/","page":"Julia 运行时的初始化","title":"Julia 运行时的初始化","text":"The stack dump below shows how the interpreter works its way through various methods of Base.println() and Base.print() before arriving at write(s::IO, a::Array{T}) where T which does ccall(jl_uv_write()).","category":"page"},{"location":"devdocs/init/","page":"Julia 运行时的初始化","title":"Julia 运行时的初始化","text":"jl_uv_write() calls uv_write() to write \"Hello World!\" to JL_STDOUT. See Libuv wrappers for stdio.:","category":"page"},{"location":"devdocs/init/","page":"Julia 运行时的初始化","title":"Julia 运行时的初始化","text":"Hello World!","category":"page"},{"location":"devdocs/init/","page":"Julia 运行时的初始化","title":"Julia 运行时的初始化","text":"Stack frame Source code Notes\njl_uv_write() jl_uv.c called though ccall\njulia_write_282942 stream.jl function write!(s::IO, a::Array{T}) where T\njulia_print_284639 ascii.jl print(io::IO, s::String) = (write(io, s); nothing)\njlcall_print_284639 \njl_apply() julia.h \njl_trampoline() builtins.c \njl_apply() julia.h \njl_apply_generic() gf.c Base.print(Base.TTY, String)\njl_apply() julia.h \njl_trampoline() builtins.c \njl_apply() julia.h \njl_apply_generic() gf.c Base.print(Base.TTY, String, Char, Char...)\njl_apply() julia.h \njl_f_apply() builtins.c \njl_apply() julia.h \njl_trampoline() builtins.c \njl_apply() julia.h \njl_apply_generic() gf.c Base.println(Base.TTY, String, String...)\njl_apply() julia.h \njl_trampoline() builtins.c \njl_apply() julia.h \njl_apply_generic() gf.c Base.println(String,)\njl_apply() julia.h \ndo_call() interpreter.c \neval() interpreter.c \njl_interpret_toplevel_expr() interpreter.c \njl_toplevel_eval_flex() toplevel.c \njl_toplevel_eval() toplevel.c \njl_toplevel_eval_in() builtins.c \njl_f_top_eval() builtins.c ","category":"page"},{"location":"devdocs/init/","page":"Julia 运行时的初始化","title":"Julia 运行时的初始化","text":"Since our example has just one function call, which has done its job of printing \"Hello World!\", the stack now rapidly unwinds back to main().","category":"page"},{"location":"devdocs/init/#jl_atexit_hook()","page":"Julia 运行时的初始化","title":"jl_atexit_hook()","text":"","category":"section"},{"location":"devdocs/init/","page":"Julia 运行时的初始化","title":"Julia 运行时的初始化","text":"main() calls jl_atexit_hook(). This calls Base._atexit, then calls jl_gc_run_all_finalizers() and cleans up libuv handles.","category":"page"},{"location":"devdocs/init/#julia_save()","page":"Julia 运行时的初始化","title":"julia_save()","text":"","category":"section"},{"location":"devdocs/init/","page":"Julia 运行时的初始化","title":"Julia 运行时的初始化","text":"Finally, main() calls julia_save(), which if requested on the command line, saves the runtime state to a new system image. See jl_compile_all() and jl_save_system_image().","category":"page"},{"location":"manual/workflow-tips/#man-workflow-tips","page":"工作流程建议","title":"工作流程建议","text":"","category":"section"},{"location":"manual/workflow-tips/","page":"工作流程建议","title":"工作流程建议","text":"这里是高效使用 Julia 的一些建议。","category":"page"},{"location":"manual/workflow-tips/#基于-REPL-的工作流程","page":"工作流程建议","title":"基于 REPL 的工作流程","text":"","category":"section"},{"location":"manual/workflow-tips/","page":"工作流程建议","title":"工作流程建议","text":"正如在 Julia REPL 中演示的那样,Julia 的 REPL 为高效的交互式工作流程提供了丰富的功能。这里是一些可能进一步提升你在命令行下的体验的建议。","category":"page"},{"location":"manual/workflow-tips/#一个基本的编辑器-/-REPL-工作流程","page":"工作流程建议","title":"一个基本的编辑器 / REPL 工作流程","text":"","category":"section"},{"location":"manual/workflow-tips/","page":"工作流程建议","title":"工作流程建议","text":"最基本的 Julia 工作流程是将一个文本编辑器配合 julia 的命令行使用。一般会包含下面一些步骤:","category":"page"},{"location":"manual/workflow-tips/","page":"工作流程建议","title":"工作流程建议","text":"把还在开发中的代码放到一个临时的模块中。新建一个文件,例如 Tmp.jl,并放到模块中。\nmodule Tmp\nexport say_hello\n\nsay_hello() = println(\"Hello!\")\n\n# your other definitions here\n\nend\n把测试代码放到另一个文件中。新建另一个文件,例如 tst.jl,开头为\ninclude(\"Tmp.jl\")\nimport .Tmp\n# using .Tmp # we can use `using` to bring the exported symbols in `Tmp` into our namespace\n\nTmp.say_hello()\n# say_hello()\n\n# your other test code here\n并把测试作为 Tmp 的内容。或者,你可以把测试文件的内容打包到一个模块中,例如\nmodule Tst\n include(\"Tmp.jl\")\n import .Tmp\n #using .Tmp\n\n Tmp.say_hello()\n # say_hello()\n\n # your other test code here\nend\n优点是你的测试代码现在包含在一个模块中,并且不会在 Main 的全局作用域中引入新定义,这样更加整洁。\n使用 include(\"tst.jl\") 来在 Julia REPL 中 include tst.jl 文件。\n打肥皂,冲洗,重复。(译者注:此为英语幽默,被称为“洗发算法”在 julia REPL 中摸索不同的想法,把好的想法存入 tst.jl。要在 tst.jl 被更改后执行它,只需再次 include 它。","category":"page"},{"location":"manual/workflow-tips/#基于浏览器的工作流程","page":"工作流程建议","title":"基于浏览器的工作流程","text":"","category":"section"},{"location":"manual/workflow-tips/","page":"工作流程建议","title":"工作流程建议","text":"也可以通过 IJulia 在浏览器中与 Julia REPL 进行交互,请到该库的主页查看详细用法。","category":"page"},{"location":"manual/workflow-tips/#基于Revise的工作流程","page":"工作流程建议","title":"基于Revise的工作流程","text":"","category":"section"},{"location":"manual/workflow-tips/","page":"工作流程建议","title":"工作流程建议","text":"无论你是在REPL还是在IJulia,你通常可以通过 Revise优化 你的开发经历。 通常情况,无论何时启动Julia,就请按照Revise文档中的说明配置好Revise。 一旦配置好,Revise将跟踪任何加载模块中的文件变化。 和任何用includet加载到 REPL 的文件 (但不包括普通的include); 然后你就可以编辑这些文件,并且更改会在不重新启动julia会话的情况下生效。 标准工作流与上面基于 REPL 的工作流类似,区别如下:","category":"page"},{"location":"manual/workflow-tips/","page":"工作流程建议","title":"工作流程建议","text":"把你的代码放到一个在你的加载路径里的模块中。 要这样做有很多种方法,通常推荐以下两种选择:\n对于长期的项目,使用PkgTemplates:\nusing PkgTemplates\nt = Template()\nt(\"MyPkg\")\n这将在 .julia/dev 目录中创建一个空白包\"MyPkg\"。 请注意,通过它的 Template 构造器,PkgTemplates 允许控制许多不同的选项。\n在下面的第 2 步中,编辑 MyPkg/src/MyPkg.jl 以更改源代码,并编辑 MyPkg/test/runtests.jl 以进行测试。\n对于“一次性”项目,您可以通过在临时目录(例如 /tmp)中进行工作来避免任何清理需求。\n切换到临时目录并启动 Julia,然后执行以下操作:\npkg> generate MyPkg # type ] to enter pkg mode\njulia> push!(LOAD_PATH, pwd()) # hit backspace to exit pkg mode\n如果你重新启动 Julia 会话,则必须重新发出修改 LOAD_PATH 的命令。\n在下面的第 2 步中,编辑 MyPkg/src/MyPkg.jl 以更改源代码,并创建你选择的任何测试文件。\n构建你自己的包\n在加载任何代码之前, 确保 Revise 已经被启用: using Revise 或者按照教程设置自动加载。\n然后切换到包含测试文件(假设文件为\"runtests.jl\")的目录下,并:\njulia> using MyPkg\n\njulia> include(\"runtests.jl\")\n你可以修改在 MyPkg 文件夹中的代码然后用include(\"runtests.jl\")重新跑一遍测试。 通常,你可能需要重新启动Julia 会话来使得这些变化生效(受一些 限制)。","category":"page"},{"location":"stdlib/LazyArtifacts/#Lazy-Artifacts","page":"Lazy Artifacts","title":"Lazy Artifacts","text":"","category":"section"},{"location":"stdlib/LazyArtifacts/","page":"Lazy Artifacts","title":"Lazy Artifacts","text":"DocTestSetup = :(using LazyArtifacts)","category":"page"},{"location":"stdlib/LazyArtifacts/","page":"Lazy Artifacts","title":"Lazy Artifacts","text":"In order for a package to download artifacts lazily, LazyArtifacts must be explicitly listed as a dependency of that package.","category":"page"},{"location":"stdlib/LazyArtifacts/","page":"Lazy Artifacts","title":"Lazy Artifacts","text":"For further information on artifacts, see Artifacts.","category":"page"},{"location":"base/numbers/#lib-numbers","page":"Numbers","title":"Numbers","text":"","category":"section"},{"location":"base/numbers/#标准数值类型","page":"Numbers","title":"标准数值类型","text":"","category":"section"},{"location":"base/numbers/#抽象数值类型","page":"Numbers","title":"抽象数值类型","text":"","category":"section"},{"location":"base/numbers/","page":"Numbers","title":"Numbers","text":"Core.Number\nCore.Real\nCore.AbstractFloat\nCore.Integer\nCore.Signed\nCore.Unsigned\nBase.AbstractIrrational","category":"page"},{"location":"base/numbers/#Core.Number","page":"Numbers","title":"Core.Number","text":"Number\n\nAbstract supertype for all number types.\n\n\n\n\n\n","category":"type"},{"location":"base/numbers/#Core.Real","page":"Numbers","title":"Core.Real","text":"Real <: Number\n\nAbstract supertype for all real numbers.\n\n\n\n\n\n","category":"type"},{"location":"base/numbers/#Core.AbstractFloat","page":"Numbers","title":"Core.AbstractFloat","text":"AbstractFloat <: Real\n\nAbstract supertype for all floating point numbers.\n\n\n\n\n\n","category":"type"},{"location":"base/numbers/#Core.Integer","page":"Numbers","title":"Core.Integer","text":"Integer <: Real\n\nAbstract supertype for all integers.\n\n\n\n\n\n","category":"type"},{"location":"base/numbers/#Core.Signed","page":"Numbers","title":"Core.Signed","text":"Signed <: Integer\n\nAbstract supertype for all signed integers.\n\n\n\n\n\n","category":"type"},{"location":"base/numbers/#Core.Unsigned","page":"Numbers","title":"Core.Unsigned","text":"Unsigned <: Integer\n\nAbstract supertype for all unsigned integers.\n\n\n\n\n\n","category":"type"},{"location":"base/numbers/#Base.AbstractIrrational","page":"Numbers","title":"Base.AbstractIrrational","text":"AbstractIrrational <: Real\n\nNumber type representing an exact irrational value, which is automatically rounded to the correct precision in arithmetic operations with other numeric quantities.\n\nSubtypes MyIrrational <: AbstractIrrational should implement at least ==(::MyIrrational, ::MyIrrational), hash(x::MyIrrational, h::UInt), and convert(::Type{F}, x::MyIrrational) where {F <: Union{BigFloat,Float32,Float64}}.\n\nIf a subtype is used to represent values that may occasionally be rational (e.g. a square-root type that represents √n for integers n will give a rational result when n is a perfect square), then it should also implement isinteger, iszero, isone, and == with Real values (since all of these default to false for AbstractIrrational types), as well as defining hash to equal that of the corresponding Rational.\n\n\n\n\n\n","category":"type"},{"location":"base/numbers/#具象数值类型","page":"Numbers","title":"具象数值类型","text":"","category":"section"},{"location":"base/numbers/","page":"Numbers","title":"Numbers","text":"Core.Float16\nCore.Float32\nCore.Float64\nBase.BigFloat\nCore.Bool\nCore.Int8\nCore.UInt8\nCore.Int16\nCore.UInt16\nCore.Int32\nCore.UInt32\nCore.Int64\nCore.UInt64\nCore.Int128\nCore.UInt128\nBase.BigInt\nBase.Complex\nBase.Rational\nBase.Irrational","category":"page"},{"location":"base/numbers/#Core.Float16","page":"Numbers","title":"Core.Float16","text":"Float16 <: AbstractFloat\n\n16-bit floating point number type (IEEE 754 standard).\n\nBinary format: 1 sign, 5 exponent, 10 fraction bits.\n\n\n\n\n\n","category":"type"},{"location":"base/numbers/#Core.Float32","page":"Numbers","title":"Core.Float32","text":"Float32 <: AbstractFloat\n\n32-bit floating point number type (IEEE 754 standard).\n\nBinary format: 1 sign, 8 exponent, 23 fraction bits.\n\n\n\n\n\n","category":"type"},{"location":"base/numbers/#Core.Float64","page":"Numbers","title":"Core.Float64","text":"Float64 <: AbstractFloat\n\n64-bit floating point number type (IEEE 754 standard).\n\nBinary format: 1 sign, 11 exponent, 52 fraction bits.\n\n\n\n\n\n","category":"type"},{"location":"base/numbers/#Base.MPFR.BigFloat","page":"Numbers","title":"Base.MPFR.BigFloat","text":"BigFloat <: AbstractFloat\n\nArbitrary precision floating point number type.\n\n\n\n\n\n","category":"type"},{"location":"base/numbers/#Core.Bool","page":"Numbers","title":"Core.Bool","text":"Bool <: Integer\n\nBoolean type, containing the values true and false.\n\nBool is a kind of number: false is numerically equal to 0 and true is numerically equal to 1. Moreover, false acts as a multiplicative \"strong zero\":\n\njulia> false == 0\ntrue\n\njulia> true == 1\ntrue\n\njulia> 0 * NaN\nNaN\n\njulia> false * NaN\n0.0\n\nSee also: digits, iszero, NaN.\n\n\n\n\n\n","category":"type"},{"location":"base/numbers/#Core.Int8","page":"Numbers","title":"Core.Int8","text":"Int8 <: Signed\n\n8-bit signed integer type.\n\n\n\n\n\n","category":"type"},{"location":"base/numbers/#Core.UInt8","page":"Numbers","title":"Core.UInt8","text":"UInt8 <: Unsigned\n\n8-bit unsigned integer type.\n\n\n\n\n\n","category":"type"},{"location":"base/numbers/#Core.Int16","page":"Numbers","title":"Core.Int16","text":"Int16 <: Signed\n\n16-bit signed integer type.\n\n\n\n\n\n","category":"type"},{"location":"base/numbers/#Core.UInt16","page":"Numbers","title":"Core.UInt16","text":"UInt16 <: Unsigned\n\n16-bit unsigned integer type.\n\n\n\n\n\n","category":"type"},{"location":"base/numbers/#Core.Int32","page":"Numbers","title":"Core.Int32","text":"Int32 <: Signed\n\n32-bit signed integer type.\n\n\n\n\n\n","category":"type"},{"location":"base/numbers/#Core.UInt32","page":"Numbers","title":"Core.UInt32","text":"UInt32 <: Unsigned\n\n32-bit unsigned integer type.\n\n\n\n\n\n","category":"type"},{"location":"base/numbers/#Core.Int64","page":"Numbers","title":"Core.Int64","text":"Int64 <: Signed\n\n64-bit signed integer type.\n\n\n\n\n\n","category":"type"},{"location":"base/numbers/#Core.UInt64","page":"Numbers","title":"Core.UInt64","text":"UInt64 <: Unsigned\n\n64-bit unsigned integer type.\n\n\n\n\n\n","category":"type"},{"location":"base/numbers/#Core.Int128","page":"Numbers","title":"Core.Int128","text":"Int128 <: Signed\n\n128-bit signed integer type.\n\n\n\n\n\n","category":"type"},{"location":"base/numbers/#Core.UInt128","page":"Numbers","title":"Core.UInt128","text":"UInt128 <: Unsigned\n\n128-bit unsigned integer type.\n\n\n\n\n\n","category":"type"},{"location":"base/numbers/#Base.GMP.BigInt","page":"Numbers","title":"Base.GMP.BigInt","text":"BigInt <: Signed\n\nArbitrary precision integer type.\n\n\n\n\n\n","category":"type"},{"location":"base/numbers/#Base.Complex","page":"Numbers","title":"Base.Complex","text":"Complex{T<:Real} <: Number\n\nComplex number type with real and imaginary part of type T.\n\nComplexF16, ComplexF32 and ComplexF64 are aliases for Complex{Float16}, Complex{Float32} and Complex{Float64} respectively.\n\nSee also: Real, complex, real.\n\n\n\n\n\n","category":"type"},{"location":"base/numbers/#Base.Rational","page":"Numbers","title":"Base.Rational","text":"Rational{T<:Integer} <: Real\n\nRational number type, with numerator and denominator of type T. Rationals are checked for overflow.\n\n\n\n\n\n","category":"type"},{"location":"base/numbers/#Base.Irrational","page":"Numbers","title":"Base.Irrational","text":"Irrational{sym} <: AbstractIrrational\n\nNumber type representing an exact irrational value denoted by the symbol sym, such as π, ℯ and γ.\n\nSee also [@irrational], AbstractIrrational.\n\n\n\n\n\n","category":"type"},{"location":"base/numbers/#数据格式","page":"Numbers","title":"数据格式","text":"","category":"section"},{"location":"base/numbers/","page":"Numbers","title":"Numbers","text":"Base.digits\nBase.digits!\nBase.bitstring\nBase.parse\nBase.tryparse\nBase.big\nBase.signed\nBase.unsigned\nBase.float(::Any)\nBase.Math.significand\nBase.Math.exponent\nBase.complex(::Complex)\nBase.bswap\nBase.hex2bytes\nBase.hex2bytes!\nBase.bytes2hex","category":"page"},{"location":"base/numbers/#Base.digits","page":"Numbers","title":"Base.digits","text":"digits([T<:Integer], n::Integer; base::T = 10, pad::Integer = 1)\n\nReturn an array with element type T (default Int) of the digits of n in the given base, optionally padded with zeros to a specified size. More significant digits are at higher indices, such that n == sum(digits[k]*base^(k-1) for k=1:length(digits)).\n\nSee also ndigits, digits!, and for base 2 also bitstring, count_ones.\n\nExamples\n\njulia> digits(10)\n2-element Vector{Int64}:\n 0\n 1\n\njulia> digits(10, base = 2)\n4-element Vector{Int64}:\n 0\n 1\n 0\n 1\n\njulia> digits(-256, base = 10, pad = 5)\n5-element Vector{Int64}:\n -6\n -5\n -2\n 0\n 0\n\njulia> n = rand(-999:999);\n\njulia> n == evalpoly(13, digits(n, base = 13))\ntrue\n\n\n\n\n\n","category":"function"},{"location":"base/numbers/#Base.digits!","page":"Numbers","title":"Base.digits!","text":"digits!(array, n::Integer; base::Integer = 10)\n\nFills an array of the digits of n in the given base. More significant digits are at higher indices. If the array length is insufficient, the least significant digits are filled up to the array length. If the array length is excessive, the excess portion is filled with zeros.\n\nExamples\n\njulia> digits!([2, 2, 2, 2], 10, base = 2)\n4-element Vector{Int64}:\n 0\n 1\n 0\n 1\n\njulia> digits!([2, 2, 2, 2, 2, 2], 10, base = 2)\n6-element Vector{Int64}:\n 0\n 1\n 0\n 1\n 0\n 0\n\n\n\n\n\n","category":"function"},{"location":"base/numbers/#Base.bitstring","page":"Numbers","title":"Base.bitstring","text":"bitstring(n)\n\nA string giving the literal bit representation of a primitive type.\n\nSee also count_ones, count_zeros, digits.\n\nExamples\n\njulia> bitstring(Int32(4))\n\"00000000000000000000000000000100\"\n\njulia> bitstring(2.2)\n\"0100000000000001100110011001100110011001100110011001100110011010\"\n\n\n\n\n\n","category":"function"},{"location":"base/numbers/#Base.parse","page":"Numbers","title":"Base.parse","text":"parse(type, str; base)\n\nParse a string as a number. For Integer types, a base can be specified (the default is 10). For floating-point types, the string is parsed as a decimal floating-point number. Complex types are parsed from decimal strings of the form \"R±Iim\" as a Complex(R,I) of the requested type; \"i\" or \"j\" can also be used instead of \"im\", and \"R\" or \"Iim\" are also permitted. If the string does not contain a valid number, an error is raised.\n\ncompat: Julia 1.1\nparse(Bool, str) requires at least Julia 1.1.\n\nExamples\n\njulia> parse(Int, \"1234\")\n1234\n\njulia> parse(Int, \"1234\", base = 5)\n194\n\njulia> parse(Int, \"afc\", base = 16)\n2812\n\njulia> parse(Float64, \"1.2e-3\")\n0.0012\n\njulia> parse(Complex{Float64}, \"3.2e-1 + 4.5im\")\n0.32 + 4.5im\n\n\n\n\n\nparse(::Type{Platform}, triplet::AbstractString)\n\nParses a string platform triplet back into a Platform object.\n\n\n\n\n\n","category":"function"},{"location":"base/numbers/#Base.tryparse","page":"Numbers","title":"Base.tryparse","text":"tryparse(type, str; base)\n\nLike parse, but returns either a value of the requested type, or nothing if the string does not contain a valid number.\n\n\n\n\n\n","category":"function"},{"location":"base/numbers/#Base.big","page":"Numbers","title":"Base.big","text":"big(x)\n\nConvert a number to a maximum precision representation (typically BigInt or BigFloat). See BigFloat for information about some pitfalls with floating-point numbers.\n\n\n\n\n\n","category":"function"},{"location":"base/numbers/#Base.signed","page":"Numbers","title":"Base.signed","text":"signed(T::Integer)\n\nConvert an integer bitstype to the signed type of the same size.\n\nExamples\n\njulia> signed(UInt16)\nInt16\njulia> signed(UInt64)\nInt64\n\n\n\n\n\nsigned(x)\n\nConvert a number to a signed integer. If the argument is unsigned, it is reinterpreted as signed without checking for overflow.\n\nSee also: unsigned, sign, signbit.\n\n\n\n\n\n","category":"function"},{"location":"base/numbers/#Base.unsigned","page":"Numbers","title":"Base.unsigned","text":"unsigned(T::Integer)\n\nConvert an integer bitstype to the unsigned type of the same size.\n\nExamples\n\njulia> unsigned(Int16)\nUInt16\njulia> unsigned(UInt64)\nUInt64\n\n\n\n\n\n","category":"function"},{"location":"base/numbers/#Base.float-Tuple{Any}","page":"Numbers","title":"Base.float","text":"float(x)\n\nConvert a number or array to a floating point data type.\n\nSee also: complex, oftype, convert.\n\nExamples\n\njulia> float(1:1000)\n1.0:1.0:1000.0\n\njulia> float(typemax(Int32))\n2.147483647e9\n\n\n\n\n\n","category":"method"},{"location":"base/numbers/#Base.Math.significand","page":"Numbers","title":"Base.Math.significand","text":"significand(x)\n\nExtract the significand (a.k.a. mantissa) of a floating-point number. If x is a non-zero finite number, then the result will be a number of the same type and sign as x, and whose absolute value is on the interval 12). Otherwise x is returned.\n\nExamples\n\njulia> significand(15.2)\n1.9\n\njulia> significand(-15.2)\n-1.9\n\njulia> significand(-15.2) * 2^3\n-15.2\n\njulia> significand(-Inf), significand(Inf), significand(NaN)\n(-Inf, Inf, NaN)\n\n\n\n\n\n","category":"function"},{"location":"base/numbers/#Base.Math.exponent","page":"Numbers","title":"Base.Math.exponent","text":"exponent(x::AbstractFloat) -> Int\n\nGet the exponent of a normalized floating-point number. Returns the largest integer y such that 2^y ≤ abs(x).\n\nExamples\n\njulia> exponent(6.5)\n2\n\njulia> exponent(16.0)\n4\n\n\n\n\n\n","category":"function"},{"location":"base/numbers/#Base.complex-Tuple{Complex}","page":"Numbers","title":"Base.complex","text":"complex(r, [i])\n\nConvert real numbers or arrays to complex. i defaults to zero.\n\nExamples\n\njulia> complex(7)\n7 + 0im\n\njulia> complex([1, 2, 3])\n3-element Vector{Complex{Int64}}:\n 1 + 0im\n 2 + 0im\n 3 + 0im\n\n\n\n\n\n","category":"method"},{"location":"base/numbers/#Base.bswap","page":"Numbers","title":"Base.bswap","text":"bswap(n)\n\nReverse the byte order of n.\n\n(See also ntoh and hton to convert between the current native byte order and big-endian order.)\n\nExamples\n\njulia> a = bswap(0x10203040)\n0x40302010\n\njulia> bswap(a)\n0x10203040\n\njulia> string(1, base = 2)\n\"1\"\n\njulia> string(bswap(1), base = 2)\n\"100000000000000000000000000000000000000000000000000000000\"\n\n\n\n\n\n","category":"function"},{"location":"base/numbers/#Base.hex2bytes","page":"Numbers","title":"Base.hex2bytes","text":"hex2bytes(itr)\n\nGiven an iterable itr of ASCII codes for a sequence of hexadecimal digits, returns a Vector{UInt8} of bytes corresponding to the binary representation: each successive pair of hexadecimal digits in itr gives the value of one byte in the return vector.\n\nThe length of itr must be even, and the returned array has half of the length of itr. See also hex2bytes! for an in-place version, and bytes2hex for the inverse.\n\ncompat: Julia 1.7\nCalling hex2bytes with iterators producing UInt8 values requires Julia 1.7 or later. In earlier versions, you can collect the iterator before calling hex2bytes.\n\nExamples\n\njulia> s = string(12345, base = 16)\n\"3039\"\n\njulia> hex2bytes(s)\n2-element Vector{UInt8}:\n 0x30\n 0x39\n\njulia> a = b\"01abEF\"\n6-element Base.CodeUnits{UInt8, String}:\n 0x30\n 0x31\n 0x61\n 0x62\n 0x45\n 0x46\n\njulia> hex2bytes(a)\n3-element Vector{UInt8}:\n 0x01\n 0xab\n 0xef\n\n\n\n\n\n","category":"function"},{"location":"base/numbers/#Base.hex2bytes!","page":"Numbers","title":"Base.hex2bytes!","text":"hex2bytes!(dest::AbstractVector{UInt8}, itr)\n\nConvert an iterable itr of bytes representing a hexadecimal string to its binary representation, similar to hex2bytes except that the output is written in-place to dest. The length of dest must be half the length of itr.\n\ncompat: Julia 1.7\nCalling hex2bytes! with iterators producing UInt8 requires version 1.7. In earlier versions, you can collect the iterable before calling instead.\n\n\n\n\n\n","category":"function"},{"location":"base/numbers/#Base.bytes2hex","page":"Numbers","title":"Base.bytes2hex","text":"bytes2hex(itr) -> String\nbytes2hex(io::IO, itr)\n\nConvert an iterator itr of bytes to its hexadecimal string representation, either returning a String via bytes2hex(itr) or writing the string to an io stream via bytes2hex(io, itr). The hexadecimal characters are all lowercase.\n\ncompat: Julia 1.7\nCalling bytes2hex with arbitrary iterators producing UInt8 values requires Julia 1.7 or later. In earlier versions, you can collect the iterator before calling bytes2hex.\n\nExamples\n\njulia> a = string(12345, base = 16)\n\"3039\"\n\njulia> b = hex2bytes(a)\n2-element Vector{UInt8}:\n 0x30\n 0x39\n\njulia> bytes2hex(b)\n\"3039\"\n\n\n\n\n\n","category":"function"},{"location":"base/numbers/#常用数值函数和常量","page":"Numbers","title":"常用数值函数和常量","text":"","category":"section"},{"location":"base/numbers/","page":"Numbers","title":"Numbers","text":"Base.one\nBase.oneunit\nBase.zero\nBase.im\nBase.MathConstants.pi\nBase.MathConstants.ℯ\nBase.MathConstants.catalan\nBase.MathConstants.eulergamma\nBase.MathConstants.golden\nBase.Inf\nBase.Inf32\nBase.Inf16\nBase.NaN\nBase.NaN32\nBase.NaN16\nBase.issubnormal\nBase.isfinite\nBase.isinf\nBase.isnan\nBase.iszero\nBase.isone\nBase.nextfloat\nBase.prevfloat\nBase.isinteger\nBase.isreal\nCore.Float32(::Any)\nCore.Float64(::Any)\nBase.Rounding.rounding\nBase.Rounding.setrounding(::Type, ::Any)\nBase.Rounding.setrounding(::Function, ::Type, ::RoundingMode)\nBase.Rounding.get_zero_subnormals\nBase.Rounding.set_zero_subnormals","category":"page"},{"location":"base/numbers/#Base.one","page":"Numbers","title":"Base.one","text":"one(x)\none(T::type)\n\nReturn a multiplicative identity for x: a value such that one(x)*x == x*one(x) == x. Alternatively one(T) can take a type T, in which case one returns a multiplicative identity for any x of type T.\n\nIf possible, one(x) returns a value of the same type as x, and one(T) returns a value of type T. However, this may not be the case for types representing dimensionful quantities (e.g. time in days), since the multiplicative identity must be dimensionless. In that case, one(x) should return an identity value of the same precision (and shape, for matrices) as x.\n\nIf you want a quantity that is of the same type as x, or of type T, even if x is dimensionful, use oneunit instead.\n\nSee also the identity function, and I in LinearAlgebra for the identity matrix.\n\nExamples\n\njulia> one(3.7)\n1.0\n\njulia> one(Int)\n1\n\njulia> import Dates; one(Dates.Day(1))\n1\n\n\n\n\n\n","category":"function"},{"location":"base/numbers/#Base.oneunit","page":"Numbers","title":"Base.oneunit","text":"oneunit(x::T)\noneunit(T::Type)\n\nReturns T(one(x)), where T is either the type of the argument or (if a type is passed) the argument. This differs from one for dimensionful quantities: one is dimensionless (a multiplicative identity) while oneunit is dimensionful (of the same type as x, or of type T).\n\nExamples\n\njulia> oneunit(3.7)\n1.0\n\njulia> import Dates; oneunit(Dates.Day)\n1 day\n\n\n\n\n\n","category":"function"},{"location":"base/numbers/#Base.zero","page":"Numbers","title":"Base.zero","text":"zero(x)\nzero(::Type)\n\nGet the additive identity element for the type of x (x can also specify the type itself).\n\nSee also iszero, one, oneunit, oftype.\n\nExamples\n\njulia> zero(1)\n0\n\njulia> zero(big\"2.0\")\n0.0\n\njulia> zero(rand(2,2))\n2×2 Matrix{Float64}:\n 0.0 0.0\n 0.0 0.0\n\n\n\n\n\n","category":"function"},{"location":"base/numbers/#Base.im","page":"Numbers","title":"Base.im","text":"im\n\nThe imaginary unit.\n\nSee also: imag, angle, complex.\n\nExamples\n\njulia> im * im\n-1 + 0im\n\njulia> (2.0 + 3im)^2\n-5.0 + 12.0im\n\n\n\n\n\n","category":"constant"},{"location":"base/numbers/#Base.MathConstants.pi","page":"Numbers","title":"Base.MathConstants.pi","text":"π\npi\n\nThe constant pi.\n\nUnicode π can be typed by writing \\pi then pressing tab in the Julia REPL, and in many editors.\n\nSee also: sinpi, sincospi, deg2rad.\n\nExamples\n\njulia> pi\nπ = 3.1415926535897...\n\njulia> 1/2pi\n0.15915494309189535\n\n\n\n\n\n","category":"constant"},{"location":"base/numbers/#Base.MathConstants.ℯ","page":"Numbers","title":"Base.MathConstants.ℯ","text":"ℯ\ne\n\nThe constant ℯ.\n\nUnicode ℯ can be typed by writing \\euler and pressing tab in the Julia REPL, and in many editors.\n\nSee also: exp, cis, cispi.\n\nExamples\n\njulia> ℯ\nℯ = 2.7182818284590...\n\njulia> log(ℯ)\n1\n\njulia> ℯ^(im)π ≈ -1\ntrue\n\n\n\n\n\n","category":"constant"},{"location":"base/numbers/#Base.MathConstants.catalan","page":"Numbers","title":"Base.MathConstants.catalan","text":"catalan\n\nCatalan's constant.\n\nExamples\n\njulia> Base.MathConstants.catalan\ncatalan = 0.9159655941772...\n\njulia> sum(log(x)/(1+x^2) for x in 1:0.01:10^6) * 0.01\n0.9159466120554123\n\n\n\n\n\n","category":"constant"},{"location":"base/numbers/#Base.MathConstants.eulergamma","page":"Numbers","title":"Base.MathConstants.eulergamma","text":"γ\neulergamma\n\nEuler's constant.\n\nExamples\n\njulia> Base.MathConstants.eulergamma\nγ = 0.5772156649015...\n\njulia> dx = 10^-6;\n\njulia> sum(-exp(-x) * log(x) for x in dx:dx:100) * dx\n0.5772078382499133\n\n\n\n\n\n","category":"constant"},{"location":"base/numbers/#Base.MathConstants.golden","page":"Numbers","title":"Base.MathConstants.golden","text":"φ\ngolden\n\nThe golden ratio.\n\nExamples\n\njulia> Base.MathConstants.golden\nφ = 1.6180339887498...\n\njulia> (2ans - 1)^2 ≈ 5\ntrue\n\n\n\n\n\n","category":"constant"},{"location":"base/numbers/#Base.Inf","page":"Numbers","title":"Base.Inf","text":"Inf, Inf64\n\nPositive infinity of type Float64.\n\nSee also: isfinite, typemax, NaN, Inf32.\n\nExamples\n\njulia> π/0\nInf\n\njulia> +1.0 / -0.0\n-Inf\n\njulia> ℯ^-Inf\n0.0\n\n\n\n\n\n","category":"constant"},{"location":"base/numbers/#Base.Inf32","page":"Numbers","title":"Base.Inf32","text":"Inf32\n\nPositive infinity of type Float32.\n\n\n\n\n\n","category":"constant"},{"location":"base/numbers/#Base.Inf16","page":"Numbers","title":"Base.Inf16","text":"Inf16\n\nPositive infinity of type Float16.\n\n\n\n\n\n","category":"constant"},{"location":"base/numbers/#Base.NaN","page":"Numbers","title":"Base.NaN","text":"NaN, NaN64\n\nA not-a-number value of type Float64.\n\nSee also: isnan, missing, NaN32, Inf.\n\nExamples\n\njulia> 0/0\nNaN\n\njulia> Inf - Inf\nNaN\n\njulia> NaN == NaN, isequal(NaN, NaN), NaN === NaN\n(false, true, true)\n\n\n\n\n\n","category":"constant"},{"location":"base/numbers/#Base.NaN32","page":"Numbers","title":"Base.NaN32","text":"NaN32\n\nA not-a-number value of type Float32.\n\n\n\n\n\n","category":"constant"},{"location":"base/numbers/#Base.NaN16","page":"Numbers","title":"Base.NaN16","text":"NaN16\n\nA not-a-number value of type Float16.\n\n\n\n\n\n","category":"constant"},{"location":"base/numbers/#Base.issubnormal","page":"Numbers","title":"Base.issubnormal","text":"issubnormal(f) -> Bool\n\nTest whether a floating point number is subnormal.\n\n\n\n\n\n","category":"function"},{"location":"base/numbers/#Base.isfinite","page":"Numbers","title":"Base.isfinite","text":"isfinite(f) -> Bool\n\nTest whether a number is finite.\n\nExamples\n\njulia> isfinite(5)\ntrue\n\njulia> isfinite(NaN32)\nfalse\n\n\n\n\n\n","category":"function"},{"location":"base/numbers/#Base.isinf","page":"Numbers","title":"Base.isinf","text":"isinf(f) -> Bool\n\nTest whether a number is infinite.\n\nSee also: Inf, iszero, isfinite, isnan.\n\n\n\n\n\n","category":"function"},{"location":"base/numbers/#Base.isnan","page":"Numbers","title":"Base.isnan","text":"isnan(f) -> Bool\n\nTest whether a number value is a NaN, an indeterminate value which is neither an infinity nor a finite number (\"not a number\").\n\nSee also: iszero, isone, isinf, ismissing.\n\n\n\n\n\n","category":"function"},{"location":"base/numbers/#Base.iszero","page":"Numbers","title":"Base.iszero","text":"iszero(x)\n\nReturn true if x == zero(x); if x is an array, this checks whether all of the elements of x are zero.\n\nSee also: isone, isinteger, isfinite, isnan.\n\nExamples\n\njulia> iszero(0.0)\ntrue\n\njulia> iszero([1, 9, 0])\nfalse\n\njulia> iszero([false, 0, 0])\ntrue\n\n\n\n\n\n","category":"function"},{"location":"base/numbers/#Base.isone","page":"Numbers","title":"Base.isone","text":"isone(x)\n\nReturn true if x == one(x); if x is an array, this checks whether x is an identity matrix.\n\nExamples\n\njulia> isone(1.0)\ntrue\n\njulia> isone([1 0; 0 2])\nfalse\n\njulia> isone([1 0; 0 true])\ntrue\n\n\n\n\n\n","category":"function"},{"location":"base/numbers/#Base.nextfloat","page":"Numbers","title":"Base.nextfloat","text":"nextfloat(x::AbstractFloat, n::Integer)\n\nThe result of n iterative applications of nextfloat to x if n >= 0, or -n applications of prevfloat if n < 0.\n\n\n\n\n\nnextfloat(x::AbstractFloat)\n\nReturn the smallest floating point number y of the same type as x such x < y. If no such y exists (e.g. if x is Inf or NaN), then return x.\n\nSee also: prevfloat, eps, issubnormal.\n\n\n\n\n\n","category":"function"},{"location":"base/numbers/#Base.prevfloat","page":"Numbers","title":"Base.prevfloat","text":"prevfloat(x::AbstractFloat, n::Integer)\n\nThe result of n iterative applications of prevfloat to x if n >= 0, or -n applications of nextfloat if n < 0.\n\n\n\n\n\nprevfloat(x::AbstractFloat)\n\nReturn the largest floating point number y of the same type as x such y < x. If no such y exists (e.g. if x is -Inf or NaN), then return x.\n\n\n\n\n\n","category":"function"},{"location":"base/numbers/#Base.isinteger","page":"Numbers","title":"Base.isinteger","text":"isinteger(x) -> Bool\n\nTest whether x is numerically equal to some integer.\n\nExamples\n\njulia> isinteger(4.0)\ntrue\n\n\n\n\n\n","category":"function"},{"location":"base/numbers/#Base.isreal","page":"Numbers","title":"Base.isreal","text":"isreal(x) -> Bool\n\nTest whether x or all its elements are numerically equal to some real number including infinities and NaNs. isreal(x) is true if isequal(x, real(x)) is true.\n\nExamples\n\njulia> isreal(5.)\ntrue\n\njulia> isreal(Inf + 0im)\ntrue\n\njulia> isreal([4.; complex(0,1)])\nfalse\n\n\n\n\n\n","category":"function"},{"location":"base/numbers/#Core.Float32-Tuple{Any}","page":"Numbers","title":"Core.Float32","text":"Float32(x [, mode::RoundingMode])\n\nCreate a Float32 from x. If x is not exactly representable then mode determines how x is rounded.\n\nExamples\n\njulia> Float32(1/3, RoundDown)\n0.3333333f0\n\njulia> Float32(1/3, RoundUp)\n0.33333334f0\n\nSee RoundingMode for available rounding modes.\n\n\n\n\n\n","category":"method"},{"location":"base/numbers/#Core.Float64-Tuple{Any}","page":"Numbers","title":"Core.Float64","text":"Float64(x [, mode::RoundingMode])\n\nCreate a Float64 from x. If x is not exactly representable then mode determines how x is rounded.\n\nExamples\n\njulia> Float64(pi, RoundDown)\n3.141592653589793\n\njulia> Float64(pi, RoundUp)\n3.1415926535897936\n\nSee RoundingMode for available rounding modes.\n\n\n\n\n\n","category":"method"},{"location":"base/numbers/#Base.Rounding.rounding","page":"Numbers","title":"Base.Rounding.rounding","text":"rounding(T)\n\nGet the current floating point rounding mode for type T, controlling the rounding of basic arithmetic functions (+, -, *, / and sqrt) and type conversion.\n\nSee RoundingMode for available modes.\n\n\n\n\n\n","category":"function"},{"location":"base/numbers/#Base.Rounding.setrounding-Tuple{Type, Any}","page":"Numbers","title":"Base.Rounding.setrounding","text":"setrounding(T, mode)\n\nSet the rounding mode of floating point type T, controlling the rounding of basic arithmetic functions (+, -, *, / and sqrt) and type conversion. Other numerical functions may give incorrect or invalid values when using rounding modes other than the default RoundNearest.\n\nNote that this is currently only supported for T == BigFloat.\n\nwarning: Warning\nThis function is not thread-safe. It will affect code running on all threads, but its behavior is undefined if called concurrently with computations that use the setting.\n\n\n\n\n\n","category":"method"},{"location":"base/numbers/#Base.Rounding.setrounding-Tuple{Function, Type, RoundingMode}","page":"Numbers","title":"Base.Rounding.setrounding","text":"setrounding(f::Function, T, mode)\n\nChange the rounding mode of floating point type T for the duration of f. It is logically equivalent to:\n\nold = rounding(T)\nsetrounding(T, mode)\nf()\nsetrounding(T, old)\n\nSee RoundingMode for available rounding modes.\n\n\n\n\n\n","category":"method"},{"location":"base/numbers/#Base.Rounding.get_zero_subnormals","page":"Numbers","title":"Base.Rounding.get_zero_subnormals","text":"get_zero_subnormals() -> Bool\n\nReturn false if operations on subnormal floating-point values (\"denormals\") obey rules for IEEE arithmetic, and true if they might be converted to zeros.\n\nwarning: Warning\nThis function only affects the current thread.\n\n\n\n\n\n","category":"function"},{"location":"base/numbers/#Base.Rounding.set_zero_subnormals","page":"Numbers","title":"Base.Rounding.set_zero_subnormals","text":"set_zero_subnormals(yes::Bool) -> Bool\n\nIf yes is false, subsequent floating-point operations follow rules for IEEE arithmetic on subnormal values (\"denormals\"). Otherwise, floating-point operations are permitted (but not required) to convert subnormal inputs or outputs to zero. Returns true unless yes==true but the hardware does not support zeroing of subnormal numbers.\n\nset_zero_subnormals(true) can speed up some computations on some hardware. However, it can break identities such as (x-y==0) == (x==y).\n\nwarning: Warning\nThis function only affects the current thread.\n\n\n\n\n\n","category":"function"},{"location":"base/numbers/#整型","page":"Numbers","title":"整型","text":"","category":"section"},{"location":"base/numbers/","page":"Numbers","title":"Numbers","text":"Base.count_ones\nBase.count_zeros\nBase.leading_zeros\nBase.leading_ones\nBase.trailing_zeros\nBase.trailing_ones\nBase.isodd\nBase.iseven\nBase.@int128_str\nBase.@uint128_str","category":"page"},{"location":"base/numbers/#Base.count_ones","page":"Numbers","title":"Base.count_ones","text":"count_ones(x::Integer) -> Integer\n\nNumber of ones in the binary representation of x.\n\nExamples\n\njulia> count_ones(7)\n3\n\njulia> count_ones(Int32(-1))\n32\n\n\n\n\n\n","category":"function"},{"location":"base/numbers/#Base.count_zeros","page":"Numbers","title":"Base.count_zeros","text":"count_zeros(x::Integer) -> Integer\n\nNumber of zeros in the binary representation of x.\n\nExamples\n\njulia> count_zeros(Int32(2 ^ 16 - 1))\n16\n\njulia> count_zeros(-1)\n0\n\n\n\n\n\n","category":"function"},{"location":"base/numbers/#Base.leading_zeros","page":"Numbers","title":"Base.leading_zeros","text":"leading_zeros(x::Integer) -> Integer\n\nNumber of zeros leading the binary representation of x.\n\nExamples\n\njulia> leading_zeros(Int32(1))\n31\n\n\n\n\n\n","category":"function"},{"location":"base/numbers/#Base.leading_ones","page":"Numbers","title":"Base.leading_ones","text":"leading_ones(x::Integer) -> Integer\n\nNumber of ones leading the binary representation of x.\n\nExamples\n\njulia> leading_ones(UInt32(2 ^ 32 - 2))\n31\n\n\n\n\n\n","category":"function"},{"location":"base/numbers/#Base.trailing_zeros","page":"Numbers","title":"Base.trailing_zeros","text":"trailing_zeros(x::Integer) -> Integer\n\nNumber of zeros trailing the binary representation of x.\n\nExamples\n\njulia> trailing_zeros(2)\n1\n\n\n\n\n\n","category":"function"},{"location":"base/numbers/#Base.trailing_ones","page":"Numbers","title":"Base.trailing_ones","text":"trailing_ones(x::Integer) -> Integer\n\nNumber of ones trailing the binary representation of x.\n\nExamples\n\njulia> trailing_ones(3)\n2\n\n\n\n\n\n","category":"function"},{"location":"base/numbers/#Base.isodd","page":"Numbers","title":"Base.isodd","text":"isodd(x::Number) -> Bool\n\nReturn true if x is an odd integer (that is, an integer not divisible by 2), and false otherwise.\n\ncompat: Julia 1.7\nNon-Integer arguments require Julia 1.7 or later.\n\nExamples\n\njulia> isodd(9)\ntrue\n\njulia> isodd(10)\nfalse\n\n\n\n\n\n","category":"function"},{"location":"base/numbers/#Base.iseven","page":"Numbers","title":"Base.iseven","text":"iseven(x::Number) -> Bool\n\nReturn true if x is an even integer (that is, an integer divisible by 2), and false otherwise.\n\ncompat: Julia 1.7\nNon-Integer arguments require Julia 1.7 or later.\n\nExamples\n\njulia> iseven(9)\nfalse\n\njulia> iseven(10)\ntrue\n\n\n\n\n\n","category":"function"},{"location":"base/numbers/#Core.@int128_str","page":"Numbers","title":"Core.@int128_str","text":"@int128_str str\n@int128_str(str)\n\n@int128_str parses a string into a Int128. Throws an ArgumentError if the string is not a valid integer.\n\n\n\n\n\n","category":"macro"},{"location":"base/numbers/#Core.@uint128_str","page":"Numbers","title":"Core.@uint128_str","text":"@uint128_str str\n@uint128_str(str)\n\n@uint128_str parses a string into a UInt128. Throws an ArgumentError if the string is not a valid integer.\n\n\n\n\n\n","category":"macro"},{"location":"base/numbers/#BigFloats-and-BigInts","page":"Numbers","title":"BigFloats and BigInts","text":"","category":"section"},{"location":"base/numbers/","page":"Numbers","title":"Numbers","text":"The BigFloat and BigInt types implements arbitrary-precision floating point and integer arithmetic, respectively. For BigFloat the GNU MPFR library is used, and for BigInt the GNU Multiple Precision Arithmetic Library (GMP) is used.","category":"page"},{"location":"base/numbers/","page":"Numbers","title":"Numbers","text":"Base.MPFR.BigFloat(::Any, rounding::RoundingMode)\nBase.precision\nBase.MPFR.precision(::Type{BigFloat})\nBase.MPFR.setprecision\nBase.GMP.BigInt(::Any)\nBase.@big_str","category":"page"},{"location":"base/numbers/#Base.MPFR.BigFloat-Tuple{Any, RoundingMode}","page":"Numbers","title":"Base.MPFR.BigFloat","text":"BigFloat(x::Union{Real, AbstractString} [, rounding::RoundingMode=rounding(BigFloat)]; [precision::Integer=precision(BigFloat)])\n\nCreate an arbitrary precision floating point number from x, with precision precision. The rounding argument specifies the direction in which the result should be rounded if the conversion cannot be done exactly. If not provided, these are set by the current global values.\n\nBigFloat(x::Real) is the same as convert(BigFloat,x), except if x itself is already BigFloat, in which case it will return a value with the precision set to the current global precision; convert will always return x.\n\nBigFloat(x::AbstractString) is identical to parse. This is provided for convenience since decimal literals are converted to Float64 when parsed, so BigFloat(2.1) may not yield what you expect.\n\nSee also:\n\n@big_str\nrounding and setrounding\nprecision and setprecision\n\ncompat: Julia 1.1\nprecision as a keyword argument requires at least Julia 1.1. In Julia 1.0 precision is the second positional argument (BigFloat(x, precision)).\n\nExamples\n\njulia> BigFloat(2.1) # 2.1 here is a Float64\n2.100000000000000088817841970012523233890533447265625\n\njulia> BigFloat(\"2.1\") # the closest BigFloat to 2.1\n2.099999999999999999999999999999999999999999999999999999999999999999999999999986\n\njulia> BigFloat(\"2.1\", RoundUp)\n2.100000000000000000000000000000000000000000000000000000000000000000000000000021\n\njulia> BigFloat(\"2.1\", RoundUp, precision=128)\n2.100000000000000000000000000000000000007\n\n\n\n\n\n","category":"method"},{"location":"base/numbers/#Base.precision","page":"Numbers","title":"Base.precision","text":"precision(num::AbstractFloat; base::Integer=2)\nprecision(T::Type; base::Integer=2)\n\nGet the precision of a floating point number, as defined by the effective number of bits in the significand, or the precision of a floating-point type T (its current default, if T is a variable-precision type like BigFloat).\n\nIf base is specified, then it returns the maximum corresponding number of significand digits in that base.\n\ncompat: Julia 1.8\nThe base keyword requires at least Julia 1.8.\n\n\n\n\n\n","category":"function"},{"location":"base/numbers/#Base.MPFR.setprecision","page":"Numbers","title":"Base.MPFR.setprecision","text":"setprecision([T=BigFloat,] precision::Int; base=2)\n\nSet the precision (in bits, by default) to be used for T arithmetic. If base is specified, then the precision is the minimum required to give at least precision digits in the given base.\n\nwarning: Warning\nThis function is not thread-safe. It will affect code running on all threads, but its behavior is undefined if called concurrently with computations that use the setting.\n\ncompat: Julia 1.8\nThe base keyword requires at least Julia 1.8.\n\n\n\n\n\nsetprecision(f::Function, [T=BigFloat,] precision::Integer; base=2)\n\nChange the T arithmetic precision (in the given base) for the duration of f. It is logically equivalent to:\n\nold = precision(BigFloat)\nsetprecision(BigFloat, precision)\nf()\nsetprecision(BigFloat, old)\n\nOften used as setprecision(T, precision) do ... end\n\nNote: nextfloat(), prevfloat() do not use the precision mentioned by setprecision.\n\ncompat: Julia 1.8\nThe base keyword requires at least Julia 1.8.\n\n\n\n\n\n","category":"function"},{"location":"base/numbers/#Base.GMP.BigInt-Tuple{Any}","page":"Numbers","title":"Base.GMP.BigInt","text":"BigInt(x)\n\nCreate an arbitrary precision integer. x may be an Int (or anything that can be converted to an Int). The usual mathematical operators are defined for this type, and results are promoted to a BigInt.\n\nInstances can be constructed from strings via parse, or using the big string literal.\n\nExamples\n\njulia> parse(BigInt, \"42\")\n42\n\njulia> big\"313\"\n313\n\njulia> BigInt(10)^19\n10000000000000000000\n\n\n\n\n\n","category":"method"},{"location":"base/numbers/#Core.@big_str","page":"Numbers","title":"Core.@big_str","text":"@big_str str\n@big_str(str)\n\nParse a string into a BigInt or BigFloat, and throw an ArgumentError if the string is not a valid number. For integers _ is allowed in the string as a separator.\n\nExamples\n\njulia> big\"123_456\"\n123456\n\njulia> big\"7891.5\"\n7891.5\n\n\n\n\n\n","category":"macro"},{"location":"manual/missing/#missing","page":"缺失值","title":"缺失值","text":"","category":"section"},{"location":"manual/missing/","page":"缺失值","title":"缺失值","text":"Julia 支持表示统计意义上的缺失值,即某个变量在观察中没有可用值,但在理论上存在有效值的情况。缺失值由 missing 对象表示,该对象是 Missing 类型的唯一实例。missing 等价于 SQL 中的 NULL 以及 R 中的 NA,并在大多数情况下表现得与它们一样。","category":"page"},{"location":"manual/missing/#缺失值的传播","page":"缺失值","title":"缺失值的传播","text":"","category":"section"},{"location":"manual/missing/","page":"缺失值","title":"缺失值","text":"missing 值会自动在标准数学运算符和函数中传播。对于这类函数,其某个运算对象的值的不确定性会导致其结果的不确定性。在应用中,上述情形意味着若在数学操作中包括 missing 值,其结果也常常返回 missing 值。","category":"page"},{"location":"manual/missing/","page":"缺失值","title":"缺失值","text":"julia> missing + 1\nmissing\n\njulia> \"a\" * missing\nmissing\n\njulia> abs(missing)\nmissing","category":"page"},{"location":"manual/missing/","page":"缺失值","title":"缺失值","text":"由于missing 是 Julia 中的正常对象,此传播规则仅在可实现该对象的函数中应用。这可通过定义包含 Missing 类的实参的特定方法,或是简单地让函数可接受此类实参,并将该它们传入已具备传播规则的函数(如标准数学运算符)中实现。在包中定义新传播规则时,应考虑缺失值的传播是否具有实际意义,并在传播有意义时定义合适的方法。在某个不包含接受 Missing 类实参方法的函数中传递缺失值,则抛出 MethodError的报错,正如其它类型一样。","category":"page"},{"location":"manual/missing/","page":"缺失值","title":"缺失值","text":"若希望函数不传播缺失值,可将其按照 Missings.jl 库中的 passmissing 函数封装起来。例如,将 f(x) 封装为 passmissing(f)(x)。","category":"page"},{"location":"manual/missing/#相等和比较运算符","page":"缺失值","title":"相等和比较运算符","text":"","category":"section"},{"location":"manual/missing/","page":"缺失值","title":"缺失值","text":"标准相等和比较运算符遵循上面给出的传播规则:如果任何操作数是 missing,那么结果是 missing。这是一些例子","category":"page"},{"location":"manual/missing/","page":"缺失值","title":"缺失值","text":"julia> missing == 1\nmissing\n\njulia> missing == missing\nmissing\n\njulia> missing < 1\nmissing\n\njulia> 2 >= missing\nmissing","category":"page"},{"location":"manual/missing/","page":"缺失值","title":"缺失值","text":"特别要注意,missing == missing 返回 missing,所以 == 不能用于测试值是否为缺失值。要测试 x 是否为 missing,请用 ismissing(x)。","category":"page"},{"location":"manual/missing/","page":"缺失值","title":"缺失值","text":"特殊的比较运算符 isequal 和 === 是传播规则的例外:它们总返回一个 Bool 值,即使存在 missing 值,并认为 missing 与 missing 相等且其与任何其它值不同。因此,它们可用于测试某个值是否为 missing。","category":"page"},{"location":"manual/missing/","page":"缺失值","title":"缺失值","text":"julia> missing === 1\nfalse\n\njulia> isequal(missing, 1)\nfalse\n\njulia> missing === missing\ntrue\n\njulia> isequal(missing, missing)\ntrue","category":"page"},{"location":"manual/missing/","page":"缺失值","title":"缺失值","text":"isless 运算符是另一个例外:missing 被认为比任何其它值大。此运算符被用于 sort,因此 missing 值被放置在所有其它值之后。","category":"page"},{"location":"manual/missing/","page":"缺失值","title":"缺失值","text":"julia> isless(1, missing)\ntrue\n\njulia> isless(missing, Inf)\nfalse\n\njulia> isless(missing, missing)\nfalse","category":"page"},{"location":"manual/missing/#逻辑运算符","page":"缺失值","title":"逻辑运算符","text":"","category":"section"},{"location":"manual/missing/","page":"缺失值","title":"缺失值","text":"逻辑(或布尔)运算符 |、& 和 xor 是另一种特殊情况,因为它们只有在逻辑上是必需的时传递 missing 值。对于这些运算符来说,结果是否不确定取决于具体操作,其遵循三值逻辑的既定规则,这些规则也由 SQL 中的 NULL 以及 R 中的 NA 实现。这个抽象的定义实际上对应于一系列相对自然的行为,这最好通过具体的例子来解释。","category":"page"},{"location":"manual/missing/","page":"缺失值","title":"缺失值","text":"让我们用逻辑「或」运算符 | 来说明这个原理。按照布尔逻辑的规则,如果其中一个操作数是 true,则另一个操作数对结果没影响,结果总是 true。","category":"page"},{"location":"manual/missing/","page":"缺失值","title":"缺失值","text":"julia> true | true\ntrue\n\njulia> true | false\ntrue\n\njulia> false | true\ntrue","category":"page"},{"location":"manual/missing/","page":"缺失值","title":"缺失值","text":"基于观察,我们可以得出结论,如果其中一个操作数是 true 而另一个是 missing,我们知道结果为 true,尽管另一个参数的实际值存在不确定性。如果我们能观察到第二个操作数的实际值,那么它只能是 true 或 false,在两种情况下结果都是 true。因此,在这种特殊情况下,值的缺失不会传播","category":"page"},{"location":"manual/missing/","page":"缺失值","title":"缺失值","text":"julia> true | missing\ntrue\n\njulia> missing | true\ntrue","category":"page"},{"location":"manual/missing/","page":"缺失值","title":"缺失值","text":"相反地,如果其中一个操作数是 false,结果可能是 true 或 false,这取决于另一个操作数的值。因此,如果一个操作数是 missing,那么结果也是 missing。","category":"page"},{"location":"manual/missing/","page":"缺失值","title":"缺失值","text":"julia> false | true\ntrue\n\njulia> true | false\ntrue\n\njulia> false | false\nfalse\n\njulia> false | missing\nmissing\n\njulia> missing | false\nmissing","category":"page"},{"location":"manual/missing/","page":"缺失值","title":"缺失值","text":"逻辑「且」运算符 & 的行为与 | 运算符相似,区别在于当其中一个操作数为 false 时,值的缺失不会传播。例如,当第一个操作数是 false 时","category":"page"},{"location":"manual/missing/","page":"缺失值","title":"缺失值","text":"julia> false & false\nfalse\n\njulia> false & true\nfalse\n\njulia> false & missing\nfalse","category":"page"},{"location":"manual/missing/","page":"缺失值","title":"缺失值","text":"另一方面,当其中一个操作数为 true 时,值的缺失会传播,例如,当第一个操作数是 true 时","category":"page"},{"location":"manual/missing/","page":"缺失值","title":"缺失值","text":"julia> true & true\ntrue\n\njulia> true & false\nfalse\n\njulia> true & missing\nmissing","category":"page"},{"location":"manual/missing/","page":"缺失值","title":"缺失值","text":"最后,逻辑「异或」运算符 xor 总传播 missing 值,因为两个操作数都总是对结果产生影响。还要注意,否定运算符 ! 在操作数是 missing 时返回 missing,这就像其它一元运算符。","category":"page"},{"location":"manual/missing/#流程控制和短路运算符","page":"缺失值","title":"流程控制和短路运算符","text":"","category":"section"},{"location":"manual/missing/","page":"缺失值","title":"缺失值","text":"流程控制操作符,包括 if、while 和三元运算符 x ? y : z,不允许缺失值。这是因为如果我们能够观察实际值,它是 true 还是 false 是不确定的,这意味着我们不知道程序应该如何运行。一旦在以下上下文中遇到 missing 值,就会抛出 TypeError","category":"page"},{"location":"manual/missing/","page":"缺失值","title":"缺失值","text":"julia> if missing\n println(\"here\")\n end\nERROR: TypeError: non-boolean (Missing) used in boolean context","category":"page"},{"location":"manual/missing/","page":"缺失值","title":"缺失值","text":"出于同样的原因,并与上面给出的逻辑运算符相反,短路布尔运算符 && 和 || 在当前操作数的值决定下一个操作数是否求值时不允许 missing 值。例如","category":"page"},{"location":"manual/missing/","page":"缺失值","title":"缺失值","text":"julia> missing || false\nERROR: TypeError: non-boolean (Missing) used in boolean context\n\njulia> missing && false\nERROR: TypeError: non-boolean (Missing) used in boolean context\n\njulia> true && missing && false\nERROR: TypeError: non-boolean (Missing) used in boolean context","category":"page"},{"location":"manual/missing/","page":"缺失值","title":"缺失值","text":"另一方面,如果无需 missing 值即可确定结果,则不会引发错误。代码在对 missing 操作数求值前短路,以及 missing 是最后一个操作数都是这种情况。","category":"page"},{"location":"manual/missing/","page":"缺失值","title":"缺失值","text":"julia> true && missing\nmissing\n\njulia> false && missing\nfalse","category":"page"},{"location":"manual/missing/#包含缺失值的数组","page":"缺失值","title":"包含缺失值的数组","text":"","category":"section"},{"location":"manual/missing/","page":"缺失值","title":"缺失值","text":"包含缺失值的数组的创建就像其它数组","category":"page"},{"location":"manual/missing/","page":"缺失值","title":"缺失值","text":"julia> [1, missing]\n2-element Vector{Union{Missing, Int64}}:\n 1\n missing","category":"page"},{"location":"manual/missing/","page":"缺失值","title":"缺失值","text":"如此示例所示,此类数组的元素类型为 Union{Missing, T},其中 T 为非缺失值的类型。这简单地反映了以下事实:数组条目可以具有类型 T(此处为 Int64)或类型 Missing。此类数组使用高效的内存存储,其等价于一个 Array{T} 和一个 Array{UInt8} 的组合,前者保存实际值,后者表示条目类型(即它是 Missing 还是 T)。","category":"page"},{"location":"manual/missing/","page":"缺失值","title":"缺失值","text":"允许缺失值的数组可以使用标准语法构造。使用 Array{Union{Missing, T}}(missing, dims) 来创建填充缺失值的数组:","category":"page"},{"location":"manual/missing/","page":"缺失值","title":"缺失值","text":"julia> Array{Union{Missing, String}}(missing, 2, 3)\n2×3 Matrix{Union{Missing, String}}:\n missing missing missing\n missing missing missing","category":"page"},{"location":"manual/missing/","page":"缺失值","title":"缺失值","text":"note: Note\n使用 undef 或 similar 目前可能会给出一个填充有 missing 的数组,但这不是获得这样一个数组的正确方法。 请使用如上所示的 missing 构造函数。","category":"page"},{"location":"manual/missing/","page":"缺失值","title":"缺失值","text":"允许但不包含 missing 值的数组可使用 convert 转换回不允许缺失值的数组。如果该数组包含 missing 值,在类型转换时会抛出 MethodError","category":"page"},{"location":"manual/missing/","page":"缺失值","title":"缺失值","text":"julia> x = Union{Missing, String}[\"a\", \"b\"]\n2-element Vector{Union{Missing, String}}:\n \"a\"\n \"b\"\n\njulia> convert(Array{String}, x)\n2-element Vector{String}:\n \"a\"\n \"b\"\n\njulia> y = Union{Missing, String}[missing, \"b\"]\n2-element Vector{Union{Missing, String}}:\n missing\n \"b\"\n\njulia> convert(Array{String}, y)\nERROR: MethodError: Cannot `convert` an object of type Missing to an object of type String","category":"page"},{"location":"manual/missing/#跳过缺失值","page":"缺失值","title":"跳过缺失值","text":"","category":"section"},{"location":"manual/missing/","page":"缺失值","title":"缺失值","text":"由于 missing 会随着标准数学运算符传播,归约函数会在调用的数组包含缺失值时返回 missing","category":"page"},{"location":"manual/missing/","page":"缺失值","title":"缺失值","text":"julia> sum([1, missing])\nmissing","category":"page"},{"location":"manual/missing/","page":"缺失值","title":"缺失值","text":"在这种情况下,使用 skipmissing 即可跳过缺失值","category":"page"},{"location":"manual/missing/","page":"缺失值","title":"缺失值","text":"julia> sum(skipmissing([1, missing]))\n1","category":"page"},{"location":"manual/missing/","page":"缺失值","title":"缺失值","text":"此函数方便地返回一个可高效滤除 missing 值的迭代器。因此,它可应用于所有支持迭代器的函数 ","category":"page"},{"location":"manual/missing/","page":"缺失值","title":"缺失值","text":"julia> x = skipmissing([3, missing, 2, 1])\nskipmissing(Union{Missing, Int64}[3, missing, 2, 1])\n\njulia> maximum(x)\n3\n\njulia> mean(x)\n2.0\n\njulia> mapreduce(sqrt, +, x)\n4.146264369941973\n","category":"page"},{"location":"manual/missing/","page":"缺失值","title":"缺失值","text":"通过在某数组中调用 skipmissing 生成的对象能以其在所属数组中的位置进行索引。对应缺失值的指标并不有效,若尝试使用之会丢出报错(它们在 keys 和 eachindex 中同样是被跳过的)。","category":"page"},{"location":"manual/missing/","page":"缺失值","title":"缺失值","text":"julia> x[1]\n3\n\njulia> x[2]\nERROR: MissingException: the value at index (2,) is missing\n[...]","category":"page"},{"location":"manual/missing/","page":"缺失值","title":"缺失值","text":"这允许对索引进行操作的函数与skipmissing结合使用。搜索和查找函数尤其如此,它们返回对skipmissing 函数返回的对象有效的索引,这些索引也是在父数组中匹配条目的索引。","category":"page"},{"location":"manual/missing/","page":"缺失值","title":"缺失值","text":"julia> findall(==(1), x)\n1-element Vector{Int64}:\n 4\n\njulia> findfirst(!iszero, x)\n1\n\njulia> argmax(x)\n1","category":"page"},{"location":"manual/missing/","page":"缺失值","title":"缺失值","text":"使用 collect 提取非 missing 值并将它们存储在一个数组里","category":"page"},{"location":"manual/missing/","page":"缺失值","title":"缺失值","text":"julia> collect(x)\n3-element Vector{Int64}:\n 3\n 2\n 1","category":"page"},{"location":"manual/missing/#数组上的逻辑运算","page":"缺失值","title":"数组上的逻辑运算","text":"","category":"section"},{"location":"manual/missing/","page":"缺失值","title":"缺失值","text":"上面描述的逻辑运算符的三值逻辑也适用于针对数组的函数。因此,使用 == 运算符的数组相等性测试中,若在未知 missing 条目实际值时无法确定结果,就返回 missing。在实际应用中意味着,在待比较数组中所有非缺失值都相等,且某个或全部数组包含缺失值(也许在不同位置)时会返回 missing。","category":"page"},{"location":"manual/missing/","page":"缺失值","title":"缺失值","text":"julia> [1, missing] == [2, missing]\nfalse\n\njulia> [1, missing] == [1, missing]\nmissing\n\njulia> [1, 2, missing] == [1, missing, 2]\nmissing","category":"page"},{"location":"manual/missing/","page":"缺失值","title":"缺失值","text":"对于单个值,isequal 会将 missing 值视为与其它 missing 值相等但与非缺失值不同。","category":"page"},{"location":"manual/missing/","page":"缺失值","title":"缺失值","text":"julia> isequal([1, missing], [1, missing])\ntrue\n\njulia> isequal([1, 2, missing], [1, missing, 2])\nfalse","category":"page"},{"location":"manual/missing/","page":"缺失值","title":"缺失值","text":"函数 any 和 all 遵循三值逻辑的规则,会在结果无法被确定时返回 missing。","category":"page"},{"location":"manual/missing/","page":"缺失值","title":"缺失值","text":"julia> all([true, missing])\nmissing\n\njulia> all([false, missing])\nfalse\n\njulia> any([true, missing])\ntrue\n\njulia> any([false, missing])\nmissing","category":"page"},{"location":"base/multi-threading/#lib-multithreading","page":"Multi-Threading","title":"Multi-Threading","text":"","category":"section"},{"location":"base/multi-threading/","page":"Multi-Threading","title":"Multi-Threading","text":"Base.Threads.@threads\nBase.Threads.foreach\nBase.Threads.@spawn\nBase.Threads.threadid\nBase.Threads.nthreads","category":"page"},{"location":"base/multi-threading/#Base.Threads.@threads","page":"Multi-Threading","title":"Base.Threads.@threads","text":"Threads.@threads [schedule] for ... end\n\nA macro to execute a for loop in parallel. The iteration space is distributed to coarse-grained tasks. This policy can be specified by the schedule argument. The execution of the loop waits for the evaluation of all iterations.\n\nSee also: @spawn and pmap in Distributed.\n\nExtended help\n\nSemantics\n\nUnless stronger guarantees are specified by the scheduling option, the loop executed by @threads macro have the following semantics.\n\nThe @threads macro executes the loop body in an unspecified order and potentially concurrently. It does not specify the exact assignments of the tasks and the worker threads. The assignments can be different for each execution. The loop body code (including any code transitively called from it) must not make any assumptions about the distribution of iterations to tasks or the worker thread in which they are executed. The loop body for each iteration must be able to make forward progress independent of other iterations and be free from data races. As such, invalid synchronizations across iterations may deadlock while unsynchronized memory accesses may result in undefined behavior.\n\nFor example, the above conditions imply that:\n\nThe lock taken in an iteration must be released within the same iteration.\nCommunicating between iterations using blocking primitives like Channels is incorrect.\nWrite only to locations not shared across iterations (unless a lock or atomic operation is used).\nThe value of threadid() may change even within a single iteration.\n\nSchedulers\n\nWithout the scheduler argument, the exact scheduling is unspecified and varies across Julia releases. Currently, :dynamic is used when the scheduler is not specified.\n\ncompat: Julia 1.5\nThe schedule argument is available as of Julia 1.5.\n\n:dynamic (default)\n\n:dynamic scheduler executes iterations dynamically to available worker threads. Current implementation assumes that the workload for each iteration is uniform. However, this assumption may be removed in the future.\n\nThis scheduling option is merely a hint to the underlying execution mechanism. However, a few properties can be expected. The number of Tasks used by :dynamic scheduler is bounded by a small constant multiple of the number of available worker threads (nthreads()). Each task processes contiguous regions of the iteration space. Thus, @threads :dynamic for x in xs; f(x); end is typically more efficient than @sync for x in xs; @spawn f(x); end if length(xs) is significantly larger than the number of the worker threads and the run-time of f(x) is relatively smaller than the cost of spawning and synchronizaing a task (typically less than 10 microseconds).\n\ncompat: Julia 1.8\nThe :dynamic option for the schedule argument is available and the default as of Julia 1.8.\n\n:static\n\n:static scheduler creates one task per thread and divides the iterations equally among them, assigning each task specifically to each thread. In particular, the value of threadid() is guranteed to be constant within one iteration. Specifying :static is an error if used from inside another @threads loop or from a thread other than 1.\n\nnote: Note\n:static scheduling exists for supporting transition of code written before Julia 1.3. In newly written library functions, :static scheduling is discouraged because the functions using this option cannot be called from arbitrary worker threads.\n\nExample\n\nTo illustrate of the different scheduling strategies, consider the following function busywait containing a non-yielding timed loop that runs for a given number of seconds.\n\njulia> function busywait(seconds)\n tstart = time_ns()\n while (time_ns() - tstart) / 1e9 < seconds\n end\n end\n\njulia> @time begin\n Threads.@spawn busywait(5)\n Threads.@threads :static for i in 1:Threads.nthreads()\n busywait(1)\n end\n end\n6.003001 seconds (16.33 k allocations: 899.255 KiB, 0.25% compilation time)\n\njulia> @time begin\n Threads.@spawn busywait(5)\n Threads.@threads :dynamic for i in 1:Threads.nthreads()\n busywait(1)\n end\n end\n2.012056 seconds (16.05 k allocations: 883.919 KiB, 0.66% compilation time)\n\nThe :dynamic example takes 2 seconds since one of the non-occupied threads is able to run two of the 1-second iterations to complete the for loop.\n\n\n\n\n\n","category":"macro"},{"location":"base/multi-threading/#Base.Threads.foreach","page":"Multi-Threading","title":"Base.Threads.foreach","text":"Threads.foreach(f, channel::Channel;\n schedule::Threads.AbstractSchedule=Threads.FairSchedule(),\n ntasks=Threads.nthreads())\n\nSimilar to foreach(f, channel), but iteration over channel and calls to f are split across ntasks tasks spawned by Threads.@spawn. This function will wait for all internally spawned tasks to complete before returning.\n\nIf schedule isa FairSchedule, Threads.foreach will attempt to spawn tasks in a manner that enables Julia's scheduler to more freely load-balance work items across threads. This approach generally has higher per-item overhead, but may perform better than StaticSchedule in concurrence with other multithreaded workloads.\n\nIf schedule isa StaticSchedule, Threads.foreach will spawn tasks in a manner that incurs lower per-item overhead than FairSchedule, but is less amenable to load-balancing. This approach thus may be more suitable for fine-grained, uniform workloads, but may perform worse than FairSchedule in concurrence with other multithreaded workloads.\n\ncompat: Julia 1.6\nThis function requires Julia 1.6 or later.\n\n\n\n\n\n","category":"function"},{"location":"base/multi-threading/#Base.Threads.@spawn","page":"Multi-Threading","title":"Base.Threads.@spawn","text":"Threads.@spawn expr\n\nCreate a Task and schedule it to run on any available thread. The task is allocated to a thread after it becomes available. To wait for the task to finish, call wait on the result of this macro, or call fetch to wait and then obtain its return value.\n\nValues can be interpolated into @spawn via $, which copies the value directly into the constructed underlying closure. This allows you to insert the value of a variable, isolating the asynchronous code from changes to the variable's value in the current task.\n\nnote: Note\nSee the manual chapter on threading for important caveats.\n\ncompat: Julia 1.3\nThis macro is available as of Julia 1.3.\n\ncompat: Julia 1.4\nInterpolating values via $ is available as of Julia 1.4.\n\n\n\n\n\n","category":"macro"},{"location":"base/multi-threading/#Base.Threads.threadid","page":"Multi-Threading","title":"Base.Threads.threadid","text":"Threads.threadid()\n\nGet the ID number of the current thread of execution. The master thread has ID 1.\n\n\n\n\n\n","category":"function"},{"location":"base/multi-threading/#Base.Threads.nthreads","page":"Multi-Threading","title":"Base.Threads.nthreads","text":"Threads.nthreads()\n\nGet the number of threads available to the Julia process. This is the inclusive upper bound on threadid().\n\nSee also: BLAS.get_num_threads and BLAS.set_num_threads in the LinearAlgebra standard library, and nprocs() in the Distributed standard library.\n\n\n\n\n\n","category":"function"},{"location":"base/multi-threading/#同步","page":"Multi-Threading","title":"同步","text":"","category":"section"},{"location":"base/multi-threading/","page":"Multi-Threading","title":"Multi-Threading","text":"Base.Threads.Condition\nBase.Threads.Event","category":"page"},{"location":"base/multi-threading/#Base.Threads.Condition","page":"Multi-Threading","title":"Base.Threads.Condition","text":"Threads.Condition([lock])\n\nA thread-safe version of Base.Condition.\n\nTo call wait or notify on a Threads.Condition, you must first call lock on it. When wait is called, the lock is atomically released during blocking, and will be reacquired before wait returns. Therefore idiomatic use of a Threads.Condition c looks like the following:\n\nlock(c)\ntry\n while !thing_we_are_waiting_for\n wait(c)\n end\nfinally\n unlock(c)\nend\n\ncompat: Julia 1.2\nThis functionality requires at least Julia 1.2.\n\n\n\n\n\n","category":"type"},{"location":"base/multi-threading/#Base.Event","page":"Multi-Threading","title":"Base.Event","text":"Event([autoreset=false])\n\nCreate a level-triggered event source. Tasks that call wait on an Event are suspended and queued until notify is called on the Event. After notify is called, the Event remains in a signaled state and tasks will no longer block when waiting for it, until reset is called.\n\nIf autoreset is true, at most one task will be released from wait for each call to notify.\n\nThis provides an acquire & release memory ordering on notify/wait.\n\ncompat: Julia 1.1\nThis functionality requires at least Julia 1.1.\n\ncompat: Julia 1.8\nThe autoreset functionality and memory ordering guarantee requires at least Julia 1.8.\n\n\n\n\n\n","category":"type"},{"location":"base/multi-threading/","page":"Multi-Threading","title":"Multi-Threading","text":"另见 同步 。","category":"page"},{"location":"base/multi-threading/#原子操作","page":"Multi-Threading","title":"原子操作","text":"","category":"section"},{"location":"base/multi-threading/","page":"Multi-Threading","title":"Multi-Threading","text":"Base.@atomic\nBase.@atomicswap\nBase.@atomicreplace","category":"page"},{"location":"base/multi-threading/#Base.@atomic","page":"Multi-Threading","title":"Base.@atomic","text":"@atomic var\n@atomic order ex\n\nMark var or ex as being performed atomically, if ex is a supported expression.\n\n@atomic a.b.x = new\n@atomic a.b.x += addend\n@atomic :release a.b.x = new\n@atomic :acquire_release a.b.x += addend\n\nPerform the store operation expressed on the right atomically and return the new value.\n\nWith =, this operation translates to a setproperty!(a.b, :x, new) call. With any operator also, this operation translates to a modifyproperty!(a.b, :x, +, addend)[2] call.\n\n@atomic a.b.x max arg2\n@atomic a.b.x + arg2\n@atomic max(a.b.x, arg2)\n@atomic :acquire_release max(a.b.x, arg2)\n@atomic :acquire_release a.b.x + arg2\n@atomic :acquire_release a.b.x max arg2\n\nPerform the binary operation expressed on the right atomically. Store the result into the field in the first argument and return the values (old, new).\n\nThis operation translates to a modifyproperty!(a.b, :x, func, arg2) call.\n\nSee Per-field atomics section in the manual for more details.\n\njulia> mutable struct Atomic{T}; @atomic x::T; end\n\njulia> a = Atomic(1)\nAtomic{Int64}(1)\n\njulia> @atomic a.x # fetch field x of a, with sequential consistency\n1\n\njulia> @atomic :sequentially_consistent a.x = 2 # set field x of a, with sequential consistency\n2\n\njulia> @atomic a.x += 1 # increment field x of a, with sequential consistency\n3\n\njulia> @atomic a.x + 1 # increment field x of a, with sequential consistency\n3 => 4\n\njulia> @atomic a.x # fetch field x of a, with sequential consistency\n4\n\njulia> @atomic max(a.x, 10) # change field x of a to the max value, with sequential consistency\n4 => 10\n\njulia> @atomic a.x max 5 # again change field x of a to the max value, with sequential consistency\n10 => 10\n\ncompat: Julia 1.7\nThis functionality requires at least Julia 1.7.\n\n\n\n\n\n","category":"macro"},{"location":"base/multi-threading/#Base.@atomicswap","page":"Multi-Threading","title":"Base.@atomicswap","text":"@atomicswap a.b.x = new\n@atomicswap :sequentially_consistent a.b.x = new\n\nStores new into a.b.x and returns the old value of a.b.x.\n\nThis operation translates to a swapproperty!(a.b, :x, new) call.\n\nSee Per-field atomics section in the manual for more details.\n\njulia> mutable struct Atomic{T}; @atomic x::T; end\n\njulia> a = Atomic(1)\nAtomic{Int64}(1)\n\njulia> @atomicswap a.x = 2+2 # replace field x of a with 4, with sequential consistency\n1\n\njulia> @atomic a.x # fetch field x of a, with sequential consistency\n4\n\ncompat: Julia 1.7\nThis functionality requires at least Julia 1.7.\n\n\n\n\n\n","category":"macro"},{"location":"base/multi-threading/#Base.@atomicreplace","page":"Multi-Threading","title":"Base.@atomicreplace","text":"@atomicreplace a.b.x expected => desired\n@atomicreplace :sequentially_consistent a.b.x expected => desired\n@atomicreplace :sequentially_consistent :monotonic a.b.x expected => desired\n\nPerform the conditional replacement expressed by the pair atomically, returning the values (old, success::Bool). Where success indicates whether the replacement was completed.\n\nThis operation translates to a replaceproperty!(a.b, :x, expected, desired) call.\n\nSee Per-field atomics section in the manual for more details.\n\njulia> mutable struct Atomic{T}; @atomic x::T; end\n\njulia> a = Atomic(1)\nAtomic{Int64}(1)\n\njulia> @atomicreplace a.x 1 => 2 # replace field x of a with 2 if it was 1, with sequential consistency\n(old = 1, success = true)\n\njulia> @atomic a.x # fetch field x of a, with sequential consistency\n2\n\njulia> @atomicreplace a.x 1 => 2 # replace field x of a with 2 if it was 1, with sequential consistency\n(old = 2, success = false)\n\njulia> xchg = 2 => 0; # replace field x of a with 0 if it was 1, with sequential consistency\n\njulia> @atomicreplace a.x xchg\n(old = 2, success = true)\n\njulia> @atomic a.x # fetch field x of a, with sequential consistency\n0\n\ncompat: Julia 1.7\nThis functionality requires at least Julia 1.7.\n\n\n\n\n\n","category":"macro"},{"location":"base/multi-threading/","page":"Multi-Threading","title":"Multi-Threading","text":"note: Note\nThe following APIs are fairly primitive, and will likely be exposed through an unsafe_*-like wrapper.","category":"page"},{"location":"base/multi-threading/","page":"Multi-Threading","title":"Multi-Threading","text":"Core.Intrinsics.atomic_pointerref(pointer::Ptr{T}, order::Symbol) --> T\nCore.Intrinsics.atomic_pointerset(pointer::Ptr{T}, new::T, order::Symbol) --> pointer\nCore.Intrinsics.atomic_pointerswap(pointer::Ptr{T}, new::T, order::Symbol) --> old\nCore.Intrinsics.atomic_pointermodify(pointer::Ptr{T}, function::(old::T,arg::S)->T, arg::S, order::Symbol) --> old\nCore.Intrinsics.atomic_pointerreplace(pointer::Ptr{T}, expected::Any, new::T, success_order::Symbol, failure_order::Symbol) --> (old, cmp)","category":"page"},{"location":"base/multi-threading/","page":"Multi-Threading","title":"Multi-Threading","text":"warning: Warning\nThe following APIs are deprecated, though support for them is likely to remain for several releases.","category":"page"},{"location":"base/multi-threading/","page":"Multi-Threading","title":"Multi-Threading","text":"Base.Threads.Atomic\nBase.Threads.atomic_cas!\nBase.Threads.atomic_xchg!\nBase.Threads.atomic_add!\nBase.Threads.atomic_sub!\nBase.Threads.atomic_and!\nBase.Threads.atomic_nand!\nBase.Threads.atomic_or!\nBase.Threads.atomic_xor!\nBase.Threads.atomic_max!\nBase.Threads.atomic_min!\nBase.Threads.atomic_fence","category":"page"},{"location":"base/multi-threading/#Base.Threads.Atomic","page":"Multi-Threading","title":"Base.Threads.Atomic","text":"Threads.Atomic{T}\n\nHolds a reference to an object of type T, ensuring that it is only accessed atomically, i.e. in a thread-safe manner.\n\nOnly certain \"simple\" types can be used atomically, namely the primitive boolean, integer, and float-point types. These are Bool, Int8...Int128, UInt8...UInt128, and Float16...Float64.\n\nNew atomic objects can be created from a non-atomic values; if none is specified, the atomic object is initialized with zero.\n\nAtomic objects can be accessed using the [] notation:\n\nExamples\n\njulia> x = Threads.Atomic{Int}(3)\nBase.Threads.Atomic{Int64}(3)\n\njulia> x[] = 1\n1\n\njulia> x[]\n1\n\nAtomic operations use an atomic_ prefix, such as atomic_add!, atomic_xchg!, etc.\n\n\n\n\n\n","category":"type"},{"location":"base/multi-threading/#Base.Threads.atomic_cas!","page":"Multi-Threading","title":"Base.Threads.atomic_cas!","text":"Threads.atomic_cas!(x::Atomic{T}, cmp::T, newval::T) where T\n\nAtomically compare-and-set x\n\nAtomically compares the value in x with cmp. If equal, write newval to x. Otherwise, leaves x unmodified. Returns the old value in x. By comparing the returned value to cmp (via ===) one knows whether x was modified and now holds the new value newval.\n\nFor further details, see LLVM's cmpxchg instruction.\n\nThis function can be used to implement transactional semantics. Before the transaction, one records the value in x. After the transaction, the new value is stored only if x has not been modified in the mean time.\n\nExamples\n\njulia> x = Threads.Atomic{Int}(3)\nBase.Threads.Atomic{Int64}(3)\n\njulia> Threads.atomic_cas!(x, 4, 2);\n\njulia> x\nBase.Threads.Atomic{Int64}(3)\n\njulia> Threads.atomic_cas!(x, 3, 2);\n\njulia> x\nBase.Threads.Atomic{Int64}(2)\n\n\n\n\n\n","category":"function"},{"location":"base/multi-threading/#Base.Threads.atomic_xchg!","page":"Multi-Threading","title":"Base.Threads.atomic_xchg!","text":"Threads.atomic_xchg!(x::Atomic{T}, newval::T) where T\n\nAtomically exchange the value in x\n\nAtomically exchanges the value in x with newval. Returns the old value.\n\nFor further details, see LLVM's atomicrmw xchg instruction.\n\nExamples\n\njulia> x = Threads.Atomic{Int}(3)\nBase.Threads.Atomic{Int64}(3)\n\njulia> Threads.atomic_xchg!(x, 2)\n3\n\njulia> x[]\n2\n\n\n\n\n\n","category":"function"},{"location":"base/multi-threading/#Base.Threads.atomic_add!","page":"Multi-Threading","title":"Base.Threads.atomic_add!","text":"Threads.atomic_add!(x::Atomic{T}, val::T) where T <: ArithmeticTypes\n\nAtomically add val to x\n\nPerforms x[] += val atomically. Returns the old value. Not defined for Atomic{Bool}.\n\nFor further details, see LLVM's atomicrmw add instruction.\n\nExamples\n\njulia> x = Threads.Atomic{Int}(3)\nBase.Threads.Atomic{Int64}(3)\n\njulia> Threads.atomic_add!(x, 2)\n3\n\njulia> x[]\n5\n\n\n\n\n\n","category":"function"},{"location":"base/multi-threading/#Base.Threads.atomic_sub!","page":"Multi-Threading","title":"Base.Threads.atomic_sub!","text":"Threads.atomic_sub!(x::Atomic{T}, val::T) where T <: ArithmeticTypes\n\nAtomically subtract val from x\n\nPerforms x[] -= val atomically. Returns the old value. Not defined for Atomic{Bool}.\n\nFor further details, see LLVM's atomicrmw sub instruction.\n\nExamples\n\njulia> x = Threads.Atomic{Int}(3)\nBase.Threads.Atomic{Int64}(3)\n\njulia> Threads.atomic_sub!(x, 2)\n3\n\njulia> x[]\n1\n\n\n\n\n\n","category":"function"},{"location":"base/multi-threading/#Base.Threads.atomic_and!","page":"Multi-Threading","title":"Base.Threads.atomic_and!","text":"Threads.atomic_and!(x::Atomic{T}, val::T) where T\n\nAtomically bitwise-and x with val\n\nPerforms x[] &= val atomically. Returns the old value.\n\nFor further details, see LLVM's atomicrmw and instruction.\n\nExamples\n\njulia> x = Threads.Atomic{Int}(3)\nBase.Threads.Atomic{Int64}(3)\n\njulia> Threads.atomic_and!(x, 2)\n3\n\njulia> x[]\n2\n\n\n\n\n\n","category":"function"},{"location":"base/multi-threading/#Base.Threads.atomic_nand!","page":"Multi-Threading","title":"Base.Threads.atomic_nand!","text":"Threads.atomic_nand!(x::Atomic{T}, val::T) where T\n\nAtomically bitwise-nand (not-and) x with val\n\nPerforms x[] = ~(x[] & val) atomically. Returns the old value.\n\nFor further details, see LLVM's atomicrmw nand instruction.\n\nExamples\n\njulia> x = Threads.Atomic{Int}(3)\nBase.Threads.Atomic{Int64}(3)\n\njulia> Threads.atomic_nand!(x, 2)\n3\n\njulia> x[]\n-3\n\n\n\n\n\n","category":"function"},{"location":"base/multi-threading/#Base.Threads.atomic_or!","page":"Multi-Threading","title":"Base.Threads.atomic_or!","text":"Threads.atomic_or!(x::Atomic{T}, val::T) where T\n\nAtomically bitwise-or x with val\n\nPerforms x[] |= val atomically. Returns the old value.\n\nFor further details, see LLVM's atomicrmw or instruction.\n\nExamples\n\njulia> x = Threads.Atomic{Int}(5)\nBase.Threads.Atomic{Int64}(5)\n\njulia> Threads.atomic_or!(x, 7)\n5\n\njulia> x[]\n7\n\n\n\n\n\n","category":"function"},{"location":"base/multi-threading/#Base.Threads.atomic_xor!","page":"Multi-Threading","title":"Base.Threads.atomic_xor!","text":"Threads.atomic_xor!(x::Atomic{T}, val::T) where T\n\nAtomically bitwise-xor (exclusive-or) x with val\n\nPerforms x[] $= val atomically. Returns the old value.\n\nFor further details, see LLVM's atomicrmw xor instruction.\n\nExamples\n\njulia> x = Threads.Atomic{Int}(5)\nBase.Threads.Atomic{Int64}(5)\n\njulia> Threads.atomic_xor!(x, 7)\n5\n\njulia> x[]\n2\n\n\n\n\n\n","category":"function"},{"location":"base/multi-threading/#Base.Threads.atomic_max!","page":"Multi-Threading","title":"Base.Threads.atomic_max!","text":"Threads.atomic_max!(x::Atomic{T}, val::T) where T\n\nAtomically store the maximum of x and val in x\n\nPerforms x[] = max(x[], val) atomically. Returns the old value.\n\nFor further details, see LLVM's atomicrmw max instruction.\n\nExamples\n\njulia> x = Threads.Atomic{Int}(5)\nBase.Threads.Atomic{Int64}(5)\n\njulia> Threads.atomic_max!(x, 7)\n5\n\njulia> x[]\n7\n\n\n\n\n\n","category":"function"},{"location":"base/multi-threading/#Base.Threads.atomic_min!","page":"Multi-Threading","title":"Base.Threads.atomic_min!","text":"Threads.atomic_min!(x::Atomic{T}, val::T) where T\n\nAtomically store the minimum of x and val in x\n\nPerforms x[] = min(x[], val) atomically. Returns the old value.\n\nFor further details, see LLVM's atomicrmw min instruction.\n\nExamples\n\njulia> x = Threads.Atomic{Int}(7)\nBase.Threads.Atomic{Int64}(7)\n\njulia> Threads.atomic_min!(x, 5)\n7\n\njulia> x[]\n5\n\n\n\n\n\n","category":"function"},{"location":"base/multi-threading/#Base.Threads.atomic_fence","page":"Multi-Threading","title":"Base.Threads.atomic_fence","text":"Threads.atomic_fence()\n\nInsert a sequential-consistency memory fence\n\nInserts a memory fence with sequentially-consistent ordering semantics. There are algorithms where this is needed, i.e. where an acquire/release ordering is insufficient.\n\nThis is likely a very expensive operation. Given that all other atomic operations in Julia already have acquire/release semantics, explicit fences should not be necessary in most cases.\n\nFor further details, see LLVM's fence instruction.\n\n\n\n\n\n","category":"function"},{"location":"base/multi-threading/#ccall-using-a-threadpool-(Experimental)","page":"Multi-Threading","title":"ccall using a threadpool (Experimental)","text":"","category":"section"},{"location":"base/multi-threading/","page":"Multi-Threading","title":"Multi-Threading","text":"Base.@threadcall","category":"page"},{"location":"base/multi-threading/#Base.@threadcall","page":"Multi-Threading","title":"Base.@threadcall","text":"@threadcall((cfunc, clib), rettype, (argtypes...), argvals...)\n\nThe @threadcall macro is called in the same way as ccall but does the work in a different thread. This is useful when you want to call a blocking C function without causing the main julia thread to become blocked. Concurrency is limited by size of the libuv thread pool, which defaults to 4 threads but can be increased by setting the UV_THREADPOOL_SIZE environment variable and restarting the julia process.\n\nNote that the called function should never call back into Julia.\n\n\n\n\n\n","category":"macro"},{"location":"base/multi-threading/#Low-level-synchronization-primitives","page":"Multi-Threading","title":"Low-level synchronization primitives","text":"","category":"section"},{"location":"base/multi-threading/","page":"Multi-Threading","title":"Multi-Threading","text":"These building blocks are used to create the regular synchronization objects.","category":"page"},{"location":"base/multi-threading/","page":"Multi-Threading","title":"Multi-Threading","text":"Base.Threads.SpinLock","category":"page"},{"location":"base/multi-threading/#Base.Threads.SpinLock","page":"Multi-Threading","title":"Base.Threads.SpinLock","text":"SpinLock()\n\nCreate a non-reentrant, test-and-test-and-set spin lock. Recursive use will result in a deadlock. This kind of lock should only be used around code that takes little time to execute and does not block (e.g. perform I/O). In general, ReentrantLock should be used instead.\n\nEach lock must be matched with an unlock.\n\nTest-and-test-and-set spin locks are quickest up to about 30ish contending threads. If you have more contention than that, different synchronization approaches should be considered.\n\n\n\n\n\n","category":"type"},{"location":"devdocs/callconv/#Calling-Conventions","page":"Calling Conventions","title":"Calling Conventions","text":"","category":"section"},{"location":"devdocs/callconv/","page":"Calling Conventions","title":"Calling Conventions","text":"Julia uses three calling conventions for four distinct purposes:","category":"page"},{"location":"devdocs/callconv/","page":"Calling Conventions","title":"Calling Conventions","text":"Name Prefix Purpose\nNative julia_ Speed via specialized signatures\nJL Call jlcall_ Wrapper for generic calls\nJL Call jl_ Builtins\nC ABI jlcapi_ Wrapper callable from C","category":"page"},{"location":"devdocs/callconv/#Julia-Native-Calling-Convention","page":"Calling Conventions","title":"Julia Native Calling Convention","text":"","category":"section"},{"location":"devdocs/callconv/","page":"Calling Conventions","title":"Calling Conventions","text":"The native calling convention is designed for fast non-generic calls. It usually uses a specialized signature.","category":"page"},{"location":"devdocs/callconv/","page":"Calling Conventions","title":"Calling Conventions","text":"LLVM ghosts (zero-length types) are omitted.\nLLVM scalars and vectors are passed by value.\nLLVM aggregates (arrays and structs) are passed by reference.","category":"page"},{"location":"devdocs/callconv/","page":"Calling Conventions","title":"Calling Conventions","text":"A small return values is returned as LLVM return values. A large return values is returned via the \"structure return\" (sret) convention, where the caller provides a pointer to a return slot.","category":"page"},{"location":"devdocs/callconv/","page":"Calling Conventions","title":"Calling Conventions","text":"An argument or return values that is a homogeneous tuple is sometimes represented as an LLVM vector instead of an LLVM array.","category":"page"},{"location":"devdocs/callconv/#JL-Call-Convention","page":"Calling Conventions","title":"JL Call Convention","text":"","category":"section"},{"location":"devdocs/callconv/","page":"Calling Conventions","title":"Calling Conventions","text":"The JL Call convention is for builtins and generic dispatch. Hand-written functions using this convention are declared via the macro JL_CALLABLE. The convention uses exactly 3 parameters:","category":"page"},{"location":"devdocs/callconv/","page":"Calling Conventions","title":"Calling Conventions","text":"F - Julia representation of function that is being applied\nargs - pointer to array of pointers to boxes\nnargs - length of the array","category":"page"},{"location":"devdocs/callconv/","page":"Calling Conventions","title":"Calling Conventions","text":"The return value is a pointer to a box.","category":"page"},{"location":"devdocs/callconv/#C-ABI","page":"Calling Conventions","title":"C ABI","text":"","category":"section"},{"location":"devdocs/callconv/","page":"Calling Conventions","title":"Calling Conventions","text":"C ABI wrappers enable calling Julia from C. The wrapper calls a function using the native calling convention.","category":"page"},{"location":"devdocs/callconv/","page":"Calling Conventions","title":"Calling Conventions","text":"Tuples are always represented as C arrays.","category":"page"},{"location":"devdocs/compiler/#本机代码生成过程的高级概述","page":"本机代码生成过程的高级概述","title":"本机代码生成过程的高级概述","text":"","category":"section"},{"location":"devdocs/compiler/#指针的表示","page":"本机代码生成过程的高级概述","title":"指针的表示","text":"","category":"section"},{"location":"devdocs/compiler/","page":"本机代码生成过程的高级概述","title":"本机代码生成过程的高级概述","text":"When emitting code to an object file, pointers will be emitted as relocations. The deserialization code will ensure any object that pointed to one of these constants gets recreated and contains the right runtime pointer.","category":"page"},{"location":"devdocs/compiler/","page":"本机代码生成过程的高级概述","title":"本机代码生成过程的高级概述","text":"Otherwise, they will be emitted as literal constants.","category":"page"},{"location":"devdocs/compiler/","page":"本机代码生成过程的高级概述","title":"本机代码生成过程的高级概述","text":"To emit one of these objects, call literal_pointer_val. It'll handle tracking the Julia value and the LLVM global, ensuring they are valid both for the current runtime and after deserialization.","category":"page"},{"location":"devdocs/compiler/","page":"本机代码生成过程的高级概述","title":"本机代码生成过程的高级概述","text":"When emitted into the object file, these globals are stored as references in a large gvals table. This allows the deserializer to reference them by index, and implement a custom manual mechanism similar to a Global Offset Table (GOT) to restore them.","category":"page"},{"location":"devdocs/compiler/","page":"本机代码生成过程的高级概述","title":"本机代码生成过程的高级概述","text":"Function pointers are handled similarly. They are stored as values in a large fvals table. Like globals, this allows the deserializer to reference them by index.","category":"page"},{"location":"devdocs/compiler/","page":"本机代码生成过程的高级概述","title":"本机代码生成过程的高级概述","text":"Note that extern functions are handled separately, with names, via the usual symbol resolution mechanism in the linker.","category":"page"},{"location":"devdocs/compiler/","page":"本机代码生成过程的高级概述","title":"本机代码生成过程的高级概述","text":"Note too that ccall functions are also handled separately, via a manual GOT and Procedure Linkage Table (PLT).","category":"page"},{"location":"devdocs/compiler/#Representation-of-Intermediate-Values","page":"本机代码生成过程的高级概述","title":"Representation of Intermediate Values","text":"","category":"section"},{"location":"devdocs/compiler/","page":"本机代码生成过程的高级概述","title":"本机代码生成过程的高级概述","text":"Values are passed around in a jl_cgval_t struct. This represents an R-value, and includes enough information to determine how to assign or pass it somewhere.","category":"page"},{"location":"devdocs/compiler/","page":"本机代码生成过程的高级概述","title":"本机代码生成过程的高级概述","text":"They are created via one of the helper constructors, usually: mark_julia_type (for immediate values) and mark_julia_slot (for pointers to values).","category":"page"},{"location":"devdocs/compiler/","page":"本机代码生成过程的高级概述","title":"本机代码生成过程的高级概述","text":"The function convert_julia_type can transform between any two types. It returns an R-value with cgval.typ set to typ. It'll cast the object to the requested representation, making heap boxes, allocating stack copies, and computing tagged unions as needed to change the representation.","category":"page"},{"location":"devdocs/compiler/","page":"本机代码生成过程的高级概述","title":"本机代码生成过程的高级概述","text":"By contrast update_julia_type will change cgval.typ to typ, only if it can be done at zero-cost (i.e. without emitting any code).","category":"page"},{"location":"devdocs/compiler/#Union-representation","page":"本机代码生成过程的高级概述","title":"Union representation","text":"","category":"section"},{"location":"devdocs/compiler/","page":"本机代码生成过程的高级概述","title":"本机代码生成过程的高级概述","text":"Inferred union types may be stack allocated via a tagged type representation.","category":"page"},{"location":"devdocs/compiler/","page":"本机代码生成过程的高级概述","title":"本机代码生成过程的高级概述","text":"The primitive routines that need to be able to handle tagged unions are:","category":"page"},{"location":"devdocs/compiler/","page":"本机代码生成过程的高级概述","title":"本机代码生成过程的高级概述","text":"mark-type\nload-local\nstore-local\nisa\nis\nemit_typeof\nemit_sizeof\nboxed\nunbox\nspecialized cc-ret","category":"page"},{"location":"devdocs/compiler/","page":"本机代码生成过程的高级概述","title":"本机代码生成过程的高级概述","text":"Everything else should be possible to handle in inference by using these primitives to implement union-splitting.","category":"page"},{"location":"devdocs/compiler/","page":"本机代码生成过程的高级概述","title":"本机代码生成过程的高级概述","text":"The representation of the tagged-union is as a pair of < void* union, byte selector >. The selector is fixed-size as byte & 0x7f, and will union-tag the first 126 isbits. It records the one-based depth-first count into the type-union of the isbits objects inside. An index of zero indicates that the union* is actually a tagged heap-allocated jl_value_t*, and needs to be treated as normal for a boxed object rather than as a tagged union.","category":"page"},{"location":"devdocs/compiler/","page":"本机代码生成过程的高级概述","title":"本机代码生成过程的高级概述","text":"The high bit of the selector (byte & 0x80) can be tested to determine if the void* is actually a heap-allocated (jl_value_t*) box, thus avoiding the cost of re-allocating a box, while maintaining the ability to efficiently handle union-splitting based on the low bits.","category":"page"},{"location":"devdocs/compiler/","page":"本机代码生成过程的高级概述","title":"本机代码生成过程的高级概述","text":"It is guaranteed that byte & 0x7f is an exact test for the type, if the value can be represented by a tag – it will never be marked byte = 0x80. It is not necessary to also test the type-tag when testing isa.","category":"page"},{"location":"devdocs/compiler/","page":"本机代码生成过程的高级概述","title":"本机代码生成过程的高级概述","text":"The union* memory region may be allocated at any size. The only constraint is that it is big enough to contain the data currently specified by selector. It might not be big enough to contain the union of all types that could be stored there according to the associated Union type field. Use appropriate care when copying.","category":"page"},{"location":"devdocs/compiler/#Specialized-Calling-Convention-Signature-Representation","page":"本机代码生成过程的高级概述","title":"Specialized Calling Convention Signature Representation","text":"","category":"section"},{"location":"devdocs/compiler/","page":"本机代码生成过程的高级概述","title":"本机代码生成过程的高级概述","text":"A jl_returninfo_t object describes the calling convention details of any callable.","category":"page"},{"location":"devdocs/compiler/","page":"本机代码生成过程的高级概述","title":"本机代码生成过程的高级概述","text":"If any of the arguments or return type of a method can be represented unboxed, and the method is not varargs, it'll be given an optimized calling convention signature based on its specTypes and rettype fields.","category":"page"},{"location":"devdocs/compiler/","page":"本机代码生成过程的高级概述","title":"本机代码生成过程的高级概述","text":"The general principles are that:","category":"page"},{"location":"devdocs/compiler/","page":"本机代码生成过程的高级概述","title":"本机代码生成过程的高级概述","text":"Primitive types get passed in int/float registers.\nTuples of VecElement types get passed in vector registers.\nStructs get passed on the stack.\nReturn values are handle similarly to arguments, with a size-cutoff at which they will instead be returned via a hidden sret argument.","category":"page"},{"location":"devdocs/compiler/","page":"本机代码生成过程的高级概述","title":"本机代码生成过程的高级概述","text":"The total logic for this is implemented by get_specsig_function and deserves_sret.","category":"page"},{"location":"devdocs/compiler/","page":"本机代码生成过程的高级概述","title":"本机代码生成过程的高级概述","text":"Additionally, if the return type is a union, it may be returned as a pair of values (a pointer and a tag). If the union values can be stack-allocated, then sufficient space to store them will also be passed as a hidden first argument. It is up to the callee whether the returned pointer will point to this space, a boxed object, or even other constant memory.","category":"page"},{"location":"base/parallel/#Tasks","page":"Tasks","title":"Tasks","text":"","category":"section"},{"location":"base/parallel/","page":"Tasks","title":"Tasks","text":"Core.Task\nBase.@task\nBase.@async\nBase.asyncmap\nBase.asyncmap!\nBase.current_task\nBase.istaskdone\nBase.istaskstarted\nBase.istaskfailed\nBase.task_local_storage(::Any)\nBase.task_local_storage(::Any, ::Any)\nBase.task_local_storage(::Function, ::Any, ::Any)","category":"page"},{"location":"base/parallel/#Core.Task","page":"Tasks","title":"Core.Task","text":"Task(func)\n\nCreate a Task (i.e. coroutine) to execute the given function func (which must be callable with no arguments). The task exits when this function returns. The task will run in the \"world age\" from the parent at construction when scheduled.\n\nExamples\n\njulia> a() = sum(i for i in 1:1000);\n\njulia> b = Task(a);\n\nIn this example, b is a runnable Task that hasn't started yet.\n\n\n\n\n\n","category":"type"},{"location":"base/parallel/#Base.@task","page":"Tasks","title":"Base.@task","text":"@task\n\nWrap an expression in a Task without executing it, and return the Task. This only creates a task, and does not run it.\n\nExamples\n\njulia> a1() = sum(i for i in 1:1000);\n\njulia> b = @task a1();\n\njulia> istaskstarted(b)\nfalse\n\njulia> schedule(b);\n\njulia> yield();\n\njulia> istaskdone(b)\ntrue\n\n\n\n\n\n","category":"macro"},{"location":"base/parallel/#Base.@async","page":"Tasks","title":"Base.@async","text":"@async\n\nWrap an expression in a Task and add it to the local machine's scheduler queue.\n\nValues can be interpolated into @async via $, which copies the value directly into the constructed underlying closure. This allows you to insert the value of a variable, isolating the asynchronous code from changes to the variable's value in the current task.\n\ncompat: Julia 1.4\nInterpolating values via $ is available as of Julia 1.4.\n\n\n\n\n\n","category":"macro"},{"location":"base/parallel/#Base.asyncmap","page":"Tasks","title":"Base.asyncmap","text":"asyncmap(f, c...; ntasks=0, batch_size=nothing)\n\nUses multiple concurrent tasks to map f over a collection (or multiple equal length collections). For multiple collection arguments, f is applied elementwise.\n\nntasks specifies the number of tasks to run concurrently. Depending on the length of the collections, if ntasks is unspecified, up to 100 tasks will be used for concurrent mapping.\n\nntasks can also be specified as a zero-arg function. In this case, the number of tasks to run in parallel is checked before processing every element and a new task started if the value of ntasks_func is greater than the current number of tasks.\n\nIf batch_size is specified, the collection is processed in batch mode. f must then be a function that must accept a Vector of argument tuples and must return a vector of results. The input vector will have a length of batch_size or less.\n\nThe following examples highlight execution in different tasks by returning the objectid of the tasks in which the mapping function is executed.\n\nFirst, with ntasks undefined, each element is processed in a different task.\n\njulia> tskoid() = objectid(current_task());\n\njulia> asyncmap(x->tskoid(), 1:5)\n5-element Array{UInt64,1}:\n 0x6e15e66c75c75853\n 0x440f8819a1baa682\n 0x9fb3eeadd0c83985\n 0xebd3e35fe90d4050\n 0x29efc93edce2b961\n\njulia> length(unique(asyncmap(x->tskoid(), 1:5)))\n5\n\nWith ntasks=2 all elements are processed in 2 tasks.\n\njulia> asyncmap(x->tskoid(), 1:5; ntasks=2)\n5-element Array{UInt64,1}:\n 0x027ab1680df7ae94\n 0xa23d2f80cd7cf157\n 0x027ab1680df7ae94\n 0xa23d2f80cd7cf157\n 0x027ab1680df7ae94\n\njulia> length(unique(asyncmap(x->tskoid(), 1:5; ntasks=2)))\n2\n\nWith batch_size defined, the mapping function needs to be changed to accept an array of argument tuples and return an array of results. map is used in the modified mapping function to achieve this.\n\njulia> batch_func(input) = map(x->string(\"args_tuple: \", x, \", element_val: \", x[1], \", task: \", tskoid()), input)\nbatch_func (generic function with 1 method)\n\njulia> asyncmap(batch_func, 1:5; ntasks=2, batch_size=2)\n5-element Array{String,1}:\n \"args_tuple: (1,), element_val: 1, task: 9118321258196414413\"\n \"args_tuple: (2,), element_val: 2, task: 4904288162898683522\"\n \"args_tuple: (3,), element_val: 3, task: 9118321258196414413\"\n \"args_tuple: (4,), element_val: 4, task: 4904288162898683522\"\n \"args_tuple: (5,), element_val: 5, task: 9118321258196414413\"\n\nnote: Note\nCurrently, all tasks in Julia are executed in a single OS thread co-operatively. Consequently, asyncmap is beneficial only when the mapping function involves any I/O - disk, network, remote worker invocation, etc.\n\n\n\n\n\n","category":"function"},{"location":"base/parallel/#Base.asyncmap!","page":"Tasks","title":"Base.asyncmap!","text":"asyncmap!(f, results, c...; ntasks=0, batch_size=nothing)\n\nLike asyncmap, but stores output in results rather than returning a collection.\n\n\n\n\n\n","category":"function"},{"location":"base/parallel/#Base.current_task","page":"Tasks","title":"Base.current_task","text":"current_task()\n\nGet the currently running Task.\n\n\n\n\n\n","category":"function"},{"location":"base/parallel/#Base.istaskdone","page":"Tasks","title":"Base.istaskdone","text":"istaskdone(t::Task) -> Bool\n\nDetermine whether a task has exited.\n\nExamples\n\njulia> a2() = sum(i for i in 1:1000);\n\njulia> b = Task(a2);\n\njulia> istaskdone(b)\nfalse\n\njulia> schedule(b);\n\njulia> yield();\n\njulia> istaskdone(b)\ntrue\n\n\n\n\n\n","category":"function"},{"location":"base/parallel/#Base.istaskstarted","page":"Tasks","title":"Base.istaskstarted","text":"istaskstarted(t::Task) -> Bool\n\nDetermine whether a task has started executing.\n\nExamples\n\njulia> a3() = sum(i for i in 1:1000);\n\njulia> b = Task(a3);\n\njulia> istaskstarted(b)\nfalse\n\n\n\n\n\n","category":"function"},{"location":"base/parallel/#Base.istaskfailed","page":"Tasks","title":"Base.istaskfailed","text":"istaskfailed(t::Task) -> Bool\n\nDetermine whether a task has exited because an exception was thrown.\n\nExamples\n\njulia> a4() = error(\"task failed\");\n\njulia> b = Task(a4);\n\njulia> istaskfailed(b)\nfalse\n\njulia> schedule(b);\n\njulia> yield();\n\njulia> istaskfailed(b)\ntrue\n\ncompat: Julia 1.3\nThis function requires at least Julia 1.3.\n\n\n\n\n\n","category":"function"},{"location":"base/parallel/#Base.task_local_storage-Tuple{Any}","page":"Tasks","title":"Base.task_local_storage","text":"task_local_storage(key)\n\nLook up the value of a key in the current task's task-local storage.\n\n\n\n\n\n","category":"method"},{"location":"base/parallel/#Base.task_local_storage-Tuple{Any, Any}","page":"Tasks","title":"Base.task_local_storage","text":"task_local_storage(key, value)\n\nAssign a value to a key in the current task's task-local storage.\n\n\n\n\n\n","category":"method"},{"location":"base/parallel/#Base.task_local_storage-Tuple{Function, Any, Any}","page":"Tasks","title":"Base.task_local_storage","text":"task_local_storage(body, key, value)\n\nCall the function body with a modified task-local storage, in which value is assigned to key; the previous value of key, or lack thereof, is restored afterwards. Useful for emulating dynamic scoping.\n\n\n\n\n\n","category":"method"},{"location":"base/parallel/#Scheduling","page":"Tasks","title":"Scheduling","text":"","category":"section"},{"location":"base/parallel/","page":"Tasks","title":"Tasks","text":"Base.yield\nBase.yieldto\nBase.sleep\nBase.schedule","category":"page"},{"location":"base/parallel/#Base.yield","page":"Tasks","title":"Base.yield","text":"yield()\n\nSwitch to the scheduler to allow another scheduled task to run. A task that calls this function is still runnable, and will be restarted immediately if there are no other runnable tasks.\n\n\n\n\n\nyield(t::Task, arg = nothing)\n\nA fast, unfair-scheduling version of schedule(t, arg); yield() which immediately yields to t before calling the scheduler.\n\n\n\n\n\n","category":"function"},{"location":"base/parallel/#Base.yieldto","page":"Tasks","title":"Base.yieldto","text":"yieldto(t::Task, arg = nothing)\n\nSwitch to the given task. The first time a task is switched to, the task's function is called with no arguments. On subsequent switches, arg is returned from the task's last call to yieldto. This is a low-level call that only switches tasks, not considering states or scheduling in any way. Its use is discouraged.\n\n\n\n\n\n","category":"function"},{"location":"base/parallel/#Base.sleep","page":"Tasks","title":"Base.sleep","text":"sleep(seconds)\n\nBlock the current task for a specified number of seconds. The minimum sleep time is 1 millisecond or input of 0.001.\n\n\n\n\n\n","category":"function"},{"location":"base/parallel/#Base.schedule","page":"Tasks","title":"Base.schedule","text":"schedule(t::Task, [val]; error=false)\n\nAdd a Task to the scheduler's queue. This causes the task to run constantly when the system is otherwise idle, unless the task performs a blocking operation such as wait.\n\nIf a second argument val is provided, it will be passed to the task (via the return value of yieldto) when it runs again. If error is true, the value is raised as an exception in the woken task.\n\nwarning: Warning\nIt is incorrect to use schedule on an arbitrary Task that has already been started. See the API reference for more information.\n\nExamples\n\njulia> a5() = sum(i for i in 1:1000);\n\njulia> b = Task(a5);\n\njulia> istaskstarted(b)\nfalse\n\njulia> schedule(b);\n\njulia> yield();\n\njulia> istaskstarted(b)\ntrue\n\njulia> istaskdone(b)\ntrue\n\n\n\n\n\n","category":"function"},{"location":"base/parallel/#lib-task-sync","page":"Tasks","title":"Synchronization","text":"","category":"section"},{"location":"base/parallel/","page":"Tasks","title":"Tasks","text":"Base.errormonitor\nBase.@sync\nBase.wait\nBase.fetch(t::Task)\nBase.timedwait\n\nBase.Condition\nBase.notify\n\nBase.Semaphore\nBase.acquire\nBase.release\n\nBase.AbstractLock\nBase.lock\nBase.unlock\nBase.trylock\nBase.islocked\nBase.ReentrantLock","category":"page"},{"location":"base/parallel/#Base.errormonitor","page":"Tasks","title":"Base.errormonitor","text":"errormonitor(t::Task)\n\nPrint an error log to stderr if task t fails.\n\n\n\n\n\n","category":"function"},{"location":"base/parallel/#Base.@sync","page":"Tasks","title":"Base.@sync","text":"@sync\n\nWait until all lexically-enclosed uses of @async, @spawn, @spawnat and @distributed are complete. All exceptions thrown by enclosed async operations are collected and thrown as a CompositeException.\n\n\n\n\n\n","category":"macro"},{"location":"base/parallel/#Base.wait","page":"Tasks","title":"Base.wait","text":"Special note for Threads.Condition:\n\nThe caller must be holding the lock that owns a Threads.Condition before calling this method. The calling task will be blocked until some other task wakes it, usually by calling notify on the same Threads.Condition object. The lock will be atomically released when blocking (even if it was locked recursively), and will be reacquired before returning.\n\n\n\n\n\nwait([x])\n\nBlock the current task until some event occurs, depending on the type of the argument:\n\nChannel: Wait for a value to be appended to the channel.\nCondition: Wait for notify on a condition and return the val parameter passed to notify.\nProcess: Wait for a process or process chain to exit. The exitcode field of a process can be used to determine success or failure.\nTask: Wait for a Task to finish. If the task fails with an exception, a TaskFailedException (which wraps the failed task) is thrown.\nRawFD: Wait for changes on a file descriptor (see the FileWatching package).\n\nIf no argument is passed, the task blocks for an undefined period. A task can only be restarted by an explicit call to schedule or yieldto.\n\nOften wait is called within a while loop to ensure a waited-for condition is met before proceeding.\n\n\n\n\n\nwait(r::Future)\n\nWait for a value to become available for the specified Future.\n\n\n\n\n\nwait(r::RemoteChannel, args...)\n\nWait for a value to become available on the specified RemoteChannel.\n\n\n\n\n\n","category":"function"},{"location":"base/parallel/#Base.fetch-Tuple{Task}","page":"Tasks","title":"Base.fetch","text":"fetch(t::Task)\n\nWait for a Task to finish, then return its result value. If the task fails with an exception, a TaskFailedException (which wraps the failed task) is thrown.\n\n\n\n\n\n","category":"method"},{"location":"base/parallel/#Base.timedwait","page":"Tasks","title":"Base.timedwait","text":"timedwait(callback::Function, timeout::Real; pollint::Real=0.1)\n\nWaits until callback returns true or timeout seconds have passed, whichever is earlier. callback is polled every pollint seconds. The minimum value for timeout and pollint is 0.001, that is, 1 millisecond.\n\nReturns :ok or :timed_out\n\n\n\n\n\n","category":"function"},{"location":"base/parallel/#Base.Condition","page":"Tasks","title":"Base.Condition","text":"Condition()\n\nCreate an edge-triggered event source that tasks can wait for. Tasks that call wait on a Condition are suspended and queued. Tasks are woken up when notify is later called on the Condition. Edge triggering means that only tasks waiting at the time notify is called can be woken up. For level-triggered notifications, you must keep extra state to keep track of whether a notification has happened. The Channel and Threads.Event types do this, and can be used for level-triggered events.\n\nThis object is NOT thread-safe. See Threads.Condition for a thread-safe version.\n\n\n\n\n\n","category":"type"},{"location":"base/parallel/#Base.notify","page":"Tasks","title":"Base.notify","text":"notify(condition, val=nothing; all=true, error=false)\n\nWake up tasks waiting for a condition, passing them val. If all is true (the default), all waiting tasks are woken, otherwise only one is. If error is true, the passed value is raised as an exception in the woken tasks.\n\nReturn the count of tasks woken up. Return 0 if no tasks are waiting on condition.\n\n\n\n\n\n","category":"function"},{"location":"base/parallel/#Base.Semaphore","page":"Tasks","title":"Base.Semaphore","text":"Semaphore(sem_size)\n\nCreate a counting semaphore that allows at most sem_size acquires to be in use at any time. Each acquire must be matched with a release.\n\nThis provides a acquire & release memory ordering on acquire/release calls.\n\n\n\n\n\n","category":"type"},{"location":"base/parallel/#Base.acquire","page":"Tasks","title":"Base.acquire","text":"acquire(s::Semaphore)\n\nWait for one of the sem_size permits to be available, blocking until one can be acquired.\n\n\n\n\n\nacquire(f, s::Semaphore)\n\nExecute f after acquiring from Semaphore s, and release on completion or error.\n\nFor example, a do-block form that ensures only 2 calls of foo will be active at the same time:\n\ns = Base.Semaphore(2)\n@sync for _ in 1:100\n Threads.@spawn begin\n Base.acquire(s) do\n foo()\n end\n end\nend\n\ncompat: Julia 1.8\nThis method requires at least Julia 1.8.\n\n\n\n\n\n","category":"function"},{"location":"base/parallel/#Base.release","page":"Tasks","title":"Base.release","text":"release(s::Semaphore)\n\nReturn one permit to the pool, possibly allowing another task to acquire it and resume execution.\n\n\n\n\n\n","category":"function"},{"location":"base/parallel/#Base.AbstractLock","page":"Tasks","title":"Base.AbstractLock","text":"AbstractLock\n\nAbstract supertype describing types that implement the synchronization primitives: lock, trylock, unlock, and islocked.\n\n\n\n\n\n","category":"type"},{"location":"base/parallel/#Base.lock","page":"Tasks","title":"Base.lock","text":"lock(lock)\n\nAcquire the lock when it becomes available. If the lock is already locked by a different task/thread, wait for it to become available.\n\nEach lock must be matched by an unlock.\n\n\n\n\n\nlock(f::Function, lock)\n\nAcquire the lock, execute f with the lock held, and release the lock when f returns. If the lock is already locked by a different task/thread, wait for it to become available.\n\nWhen this function returns, the lock has been released, so the caller should not attempt to unlock it.\n\ncompat: Julia 1.7\nUsing a Channel as the second argument requires Julia 1.7 or later.\n\n\n\n\n\n","category":"function"},{"location":"base/parallel/#Base.unlock","page":"Tasks","title":"Base.unlock","text":"unlock(lock)\n\nReleases ownership of the lock.\n\nIf this is a recursive lock which has been acquired before, decrement an internal counter and return immediately.\n\n\n\n\n\n","category":"function"},{"location":"base/parallel/#Base.trylock","page":"Tasks","title":"Base.trylock","text":"trylock(lock) -> Success (Boolean)\n\nAcquire the lock if it is available, and return true if successful. If the lock is already locked by a different task/thread, return false.\n\nEach successful trylock must be matched by an unlock.\n\n\n\n\n\n","category":"function"},{"location":"base/parallel/#Base.islocked","page":"Tasks","title":"Base.islocked","text":"islocked(lock) -> Status (Boolean)\n\nCheck whether the lock is held by any task/thread. This should not be used for synchronization (see instead trylock).\n\n\n\n\n\n","category":"function"},{"location":"base/parallel/#Base.ReentrantLock","page":"Tasks","title":"Base.ReentrantLock","text":"ReentrantLock()\n\nCreates a re-entrant lock for synchronizing Tasks. The same task can acquire the lock as many times as required. Each lock must be matched with an unlock.\n\nCalling 'lock' will also inhibit running of finalizers on that thread until the corresponding 'unlock'. Use of the standard lock pattern illustrated below should naturally be supported, but beware of inverting the try/lock order or missing the try block entirely (e.g. attempting to return with the lock still held):\n\nThis provides a acquire/release memory ordering on lock/unlock calls.\n\nlock(l)\ntry\n \nfinally\n unlock(l)\nend\n\n\n\n\n\n","category":"type"},{"location":"base/parallel/#Channels","page":"Tasks","title":"Channels","text":"","category":"section"},{"location":"base/parallel/","page":"Tasks","title":"Tasks","text":"Base.Channel\nBase.Channel(::Function)\nBase.put!(::Channel, ::Any)\nBase.take!(::Channel)\nBase.isready(::Channel)\nBase.fetch(::Channel)\nBase.close(::Channel)\nBase.bind(c::Channel, task::Task)","category":"page"},{"location":"base/parallel/#Base.Channel","page":"Tasks","title":"Base.Channel","text":"Channel{T=Any}(size::Int=0)\n\nConstructs a Channel with an internal buffer that can hold a maximum of size objects of type T. put! calls on a full channel block until an object is removed with take!.\n\nChannel(0) constructs an unbuffered channel. put! blocks until a matching take! is called. And vice-versa.\n\nOther constructors:\n\nChannel(): default constructor, equivalent to Channel{Any}(0)\nChannel(Inf): equivalent to Channel{Any}(typemax(Int))\nChannel(sz): equivalent to Channel{Any}(sz)\n\ncompat: Julia 1.3\nThe default constructor Channel() and default size=0 were added in Julia 1.3.\n\n\n\n\n\n","category":"type"},{"location":"base/parallel/#Base.Channel-Tuple{Function}","page":"Tasks","title":"Base.Channel","text":"Channel{T=Any}(func::Function, size=0; taskref=nothing, spawn=false)\n\nCreate a new task from func, bind it to a new channel of type T and size size, and schedule the task, all in a single call. The channel is automatically closed when the task terminates.\n\nfunc must accept the bound channel as its only argument.\n\nIf you need a reference to the created task, pass a Ref{Task} object via the keyword argument taskref.\n\nIf spawn = true, the Task created for func may be scheduled on another thread in parallel, equivalent to creating a task via Threads.@spawn.\n\nReturn a Channel.\n\nExamples\n\njulia> chnl = Channel() do ch\n foreach(i -> put!(ch, i), 1:4)\n end;\n\njulia> typeof(chnl)\nChannel{Any}\n\njulia> for i in chnl\n @show i\n end;\ni = 1\ni = 2\ni = 3\ni = 4\n\nReferencing the created task:\n\njulia> taskref = Ref{Task}();\n\njulia> chnl = Channel(taskref=taskref) do ch\n println(take!(ch))\n end;\n\njulia> istaskdone(taskref[])\nfalse\n\njulia> put!(chnl, \"Hello\");\nHello\n\njulia> istaskdone(taskref[])\ntrue\n\ncompat: Julia 1.3\nThe spawn= parameter was added in Julia 1.3. This constructor was added in Julia 1.3. In earlier versions of Julia, Channel used keyword arguments to set size and T, but those constructors are deprecated.\n\njulia> chnl = Channel{Char}(1, spawn=true) do ch\n for c in \"hello world\"\n put!(ch, c)\n end\n end\nChannel{Char}(1) (2 items available)\n\njulia> String(collect(chnl))\n\"hello world\"\n\n\n\n\n\n","category":"method"},{"location":"base/parallel/#Base.put!-Tuple{Channel, Any}","page":"Tasks","title":"Base.put!","text":"put!(c::Channel, v)\n\nAppend an item v to the channel c. Blocks if the channel is full.\n\nFor unbuffered channels, blocks until a take! is performed by a different task.\n\ncompat: Julia 1.1\nv now gets converted to the channel's type with convert as put! is called.\n\n\n\n\n\n","category":"method"},{"location":"base/parallel/#Base.take!-Tuple{Channel}","page":"Tasks","title":"Base.take!","text":"take!(c::Channel)\n\nRemove and return a value from a Channel. Blocks until data is available.\n\nFor unbuffered channels, blocks until a put! is performed by a different task.\n\n\n\n\n\n","category":"method"},{"location":"base/parallel/#Base.isready-Tuple{Channel}","page":"Tasks","title":"Base.isready","text":"isready(c::Channel)\n\nDetermine whether a Channel has a value stored to it. Returns immediately, does not block.\n\nFor unbuffered channels returns true if there are tasks waiting on a put!.\n\n\n\n\n\n","category":"method"},{"location":"base/parallel/#Base.fetch-Tuple{Channel}","page":"Tasks","title":"Base.fetch","text":"fetch(c::Channel)\n\nWait for and get the first available item from the channel. Does not remove the item. fetch is unsupported on an unbuffered (0-size) channel.\n\n\n\n\n\n","category":"method"},{"location":"base/parallel/#Base.close-Tuple{Channel}","page":"Tasks","title":"Base.close","text":"close(c::Channel[, excp::Exception])\n\nClose a channel. An exception (optionally given by excp), is thrown by:\n\nput! on a closed channel.\ntake! and fetch on an empty, closed channel.\n\n\n\n\n\n","category":"method"},{"location":"base/parallel/#Base.bind-Tuple{Channel, Task}","page":"Tasks","title":"Base.bind","text":"bind(chnl::Channel, task::Task)\n\nAssociate the lifetime of chnl with a task. Channel chnl is automatically closed when the task terminates. Any uncaught exception in the task is propagated to all waiters on chnl.\n\nThe chnl object can be explicitly closed independent of task termination. Terminating tasks have no effect on already closed Channel objects.\n\nWhen a channel is bound to multiple tasks, the first task to terminate will close the channel. When multiple channels are bound to the same task, termination of the task will close all of the bound channels.\n\nExamples\n\njulia> c = Channel(0);\n\njulia> task = @async foreach(i->put!(c, i), 1:4);\n\njulia> bind(c,task);\n\njulia> for i in c\n @show i\n end;\ni = 1\ni = 2\ni = 3\ni = 4\n\njulia> isopen(c)\nfalse\n\njulia> c = Channel(0);\n\njulia> task = @async (put!(c, 1); error(\"foo\"));\n\njulia> bind(c, task);\n\njulia> take!(c)\n1\n\njulia> put!(c, 1);\nERROR: TaskFailedException\nStacktrace:\n[...]\n nested task error: foo\n[...]\n\n\n\n\n\n","category":"method"},{"location":"manual/arrays/#man-multi-dim-arrays","page":"多维数组","title":"多维数组","text":"","category":"section"},{"location":"manual/arrays/","page":"多维数组","title":"多维数组","text":"与大多数科学计算语言一样,Julia 提供原生的数组实现。 大多数科学计算语言非常重视其数组实现,而牺牲了其他容器。Julia 没有以任何特殊方式处理数组。就像和其它用 Julia 写的代码一样,Julia 的数组库几乎完全是用 Julia 自身实现的,并且由编译器保证其性能。因此,也可以通过继承 AbstractArray 来定义自定义数组类型。 有关实现自定义数组类型的更多详细信息,请参阅 AbstractArray 接口的手册部分。","category":"page"},{"location":"manual/arrays/","page":"多维数组","title":"多维数组","text":"数组是存储在多维网格中对象的集合。在最一般的情况下, 数组中的对象可能是 Any 类型。 对于大多数计算上的需求,数组中对象的类型应该更加具体,例如 Float64 或 Int32。","category":"page"},{"location":"manual/arrays/","page":"多维数组","title":"多维数组","text":"一般来说,与许多其他科学计算语言不同,Julia 不希望为了性能而以向量化的方式编写程序。Julia 的编译器使用类型推断,并为标量数组索引生成优化的代码,从而能够令用户方便地编写可读性良好的程序,而不牺牲性能,并且时常会减少内存使用。","category":"page"},{"location":"manual/arrays/","page":"多维数组","title":"多维数组","text":"在 Julia 中,所有函数的参数都是 非复制的方式进行传递的(比如说,通过指针传递)。一些科学计算语言用传值的方式传递数组,尽管这样做可以防止数组在被调函数中被意外地篡改,但这也会导致不必要的数组拷贝。作为 Julia 的一个惯例,以一个 ! 结尾的函数名它会对自己的一个或者多个参数的值进行修改或者销毁(例如,请比较 sort 和 sort!)。被调函数必须进行显式拷贝,以确保它们不会无意中修改输入参数。很多不以!结尾的函数在实现的时候,都会先进行显式拷贝,然后调用一个以 ! 结尾的同名函数,最后返回之前拷贝的副本。","category":"page"},{"location":"manual/arrays/#基本函数","page":"多维数组","title":"基本函数","text":"","category":"section"},{"location":"manual/arrays/","page":"多维数组","title":"多维数组","text":"函数 描述\neltype(A) A 中元素的类型\nlength(A) A 中元素的数量\nndims(A) A 的维数\nsize(A) 一个包含 A 各个维度上元素数量的元组\nsize(A,n) A 第 n 维中的元素数量\naxes(A) 一个包含 A 有效索引的元组\naxes(A,n) 第 n 维有效索引的范围\neachindex(A) 一个访问 A 中每一个位置的高效迭代器\nstride(A,k) 在第 k 维上的间隔(stride)(相邻元素间的线性索引距离)\nstrides(A) 包含每一维上的间隔(stride)的元组","category":"page"},{"location":"manual/arrays/#构造和初始化","page":"多维数组","title":"构造和初始化","text":"","category":"section"},{"location":"manual/arrays/","page":"多维数组","title":"多维数组","text":"Julia 提供了许多用于构造和初始化数组的函数。在下列函数中,参数 dims ... 可以是一个元组 tuple 来表示维数,也可以是一个可变长度的整数值作为维数。大部分函数的第一个参数都表示数组的元素类型 T 。如果类型 T 被省略,那么将默认为 Float64。","category":"page"},{"location":"manual/arrays/","page":"多维数组","title":"多维数组","text":"函数 描述\nArray{T}(undef, dims...) 一个没有初始化的密集 Array\nzeros(T, dims...) 一个全零 Array\nones(T, dims...) 一个元素均为 1 的 Array\ntrues(dims...) 一个每个元素都为 true 的 BitArray\nfalses(dims...) 一个每个元素都为 false 的 BitArray\nreshape(A, dims...) 一个包含跟 A 相同数据但维数不同的数组\ncopy(A) 拷贝 A\ndeepcopy(A) 深拷贝,即拷贝 A,并递归地拷贝其元素\nsimilar(A, T, dims...) 一个与A具有相同类型(这里指的是密集,稀疏等)的未初始化数组,但具有指定的元素类型和维数。第二个和第三个参数都是可选的,如果省略则默认为元素类型和 A 的维数。\nreinterpret(T, A) 与 A 具有相同二进制数据的数组,但元素类型为 T\nrand(T, dims...) 一个随机 Array,元素值是 0 1) 半开区间中的均匀分布且服从一阶独立同分布 [1]\nrandn(T, dims...) 一个随机 Array,元素为标准正态分布,服从独立同分布\nMatrix{T}(I, m, n) m 行 n 列的单位矩阵 (需要先执行 using LinearAlgebra 来才能使用 I)\nrange(start, stop=stop, length=n) 从 start 到 stop 的带有 n 个线性间隔元素的范围\nfill!(A, x) 用值 x 填充数组 A\nfill(x, dims...) 一个被值 x 填充的 Array","category":"page"},{"location":"manual/arrays/","page":"多维数组","title":"多维数组","text":"[1]: iid,独立同分布","category":"page"},{"location":"manual/arrays/","page":"多维数组","title":"多维数组","text":"要查看各种方法,我们可以将不同维数传递给这些构造函数,请考虑以下示例:","category":"page"},{"location":"manual/arrays/","page":"多维数组","title":"多维数组","text":"julia> zeros(Int8, 2, 3)\n2×3 Matrix{Int8}:\n 0 0 0\n 0 0 0\n\njulia> zeros(Int8, (2, 3))\n2×3 Matrix{Int8}:\n 0 0 0\n 0 0 0\n\njulia> zeros((2, 3))\n2×3 Matrix{Float64}:\n 0.0 0.0 0.0\n 0.0 0.0 0.0","category":"page"},{"location":"manual/arrays/","page":"多维数组","title":"多维数组","text":"此处, (2, 3) 是一个元组 Tuple 并且第一个参数——元素类型是可选的, 默认值为 Float64.","category":"page"},{"location":"manual/arrays/#man-array-literals","page":"多维数组","title":"数组常量","text":"","category":"section"},{"location":"manual/arrays/","page":"多维数组","title":"多维数组","text":"数组也可以直接用方括号来构造; 语法为 [A, B, C, ...] 创建一个一维数组(即一个向量),该一维数组的元素用逗号分隔。所创建的数组中元素的类型(eltype) 自动由括号内参数的类型确定。如果所有参数类型都相同,则该类型称为数组的 eltype。 如果所有元素都有相同的promotion type,那么个元素都由convert转换成该类型并且该类型为数组的 eltype. 否则, 生成一个可以包含任意类型的异构数组—— Vector{Any} ;该构造方法包含字符 [],此时构造过程无参数给出。","category":"page"},{"location":"manual/arrays/","page":"多维数组","title":"多维数组","text":"julia> [1,2,3] # 元素类型为 Int 的向量\n3-element Vector{Int64}:\n 1\n 2\n 3\n\njulia> promote(1, 2.3, 4//5) # Int, Float64 以及 Rational 类型放在一起则会提升到 Float64\n(1.0, 2.3, 0.8)\n\njulia> [1, 2.3, 4//5] # 从而它就是这个矩阵的元素类型\n3-element Vector{Float64}:\n 1.0\n 2.3\n 0.8\n\njulia> []\nAny[]","category":"page"},{"location":"manual/arrays/#man-array-concatenation","page":"多维数组","title":"数组拼接","text":"","category":"section"},{"location":"manual/arrays/","page":"多维数组","title":"多维数组","text":"如果方括号里的参数不是由逗号分隔,而是由单个分号(;) 或者换行符分隔,那么每一个参数就不再解析为一个单独的数组元素,而是纵向拼接起来。  ","category":"page"},{"location":"manual/arrays/","page":"多维数组","title":"多维数组","text":"julia> [1:2, 4:5] # 这里有一个逗号,因此并不会发生矩阵的拼接。这里居然的元素本身就是这些 range\n2-element Vector{UnitRange{Int64}}:\n 1:2\n 4:5\n\njulia> [1:2; 4:5]\n4-element Vector{Int64}:\n 1\n 2\n 4\n 5\n\njulia> [1:2\n 4:5\n 6]\n5-element Vector{Int64}:\n 1\n 2\n 4\n 5\n 6","category":"page"},{"location":"manual/arrays/","page":"多维数组","title":"多维数组","text":"类似的,如果这些参数是被制表符、空格符或者两个分号所分隔,那么它们的内容就横向拼接在一起。","category":"page"},{"location":"manual/arrays/","page":"多维数组","title":"多维数组","text":"julia> [1:2 4:5 7:8]\n2×3 Matrix{Int64}:\n 1 4 7\n 2 5 8\n\njulia> [[1,2] [4,5] [7,8]]\n2×3 Matrix{Int64}:\n 1 4 7\n 2 5 8\n\njulia> [1 2 3] # 数字可以被横向拼接\n1×3 Matrix{Int64}:\n 1 2 3\n\njulia> [1;; 2;; 3;; 4]\n1×4 Matrix{Int64}:\n 1 2 3 4","category":"page"},{"location":"manual/arrays/","page":"多维数组","title":"多维数组","text":"单个分号(或换行符)和空格(或制表符)可以被结合起来使用进行横向或者纵向的拼接。","category":"page"},{"location":"manual/arrays/","page":"多维数组","title":"多维数组","text":"julia> [1 2\n 3 4]\n2×2 Matrix{Int64}:\n 1 2\n 3 4\n\njulia> [zeros(Int, 2, 2) [1; 2]\n [3 4] 5]\n3×3 Matrix{Int64}:\n 0 0 1\n 0 0 2\n 3 4 5\n\njulia> [[1 1]; 2 3; [4 4]]\n3×2 Matrix{Int64}:\n 1 1\n 2 3\n 4 4","category":"page"},{"location":"manual/arrays/","page":"多维数组","title":"多维数组","text":"空格(和制表符)的优先级高于分号,首先执行任何纵向拼接,然后拼接结果。 另一方面,使用双分号进行水平连接时,先纵向拼接再横向拼接。","category":"page"},{"location":"manual/arrays/","page":"多维数组","title":"多维数组","text":"julia> [zeros(Int, 2, 2) ; [3 4] ;; [1; 2] ; 5]\n3×3 Matrix{Int64}:\n 0 0 1\n 0 0 2\n 3 4 5\n\njulia> [1:2; 4;; 1; 3:4]\n3×2 Matrix{Int64}:\n 1 1\n 2 3\n 4 4","category":"page"},{"location":"manual/arrays/","page":"多维数组","title":"多维数组","text":"正如 ; 和 ;; 在第一维和第二维中拼接一样,使用更多的分号扩展了相同的通用方案。 分隔符中的分号数指定了特定的维度,因此;;; 在第三个维度中拼接,;;;; 在第四个维度中,依此类推。 较少的分号优先级高,因此较低的维度通常首先拼接。","category":"page"},{"location":"manual/arrays/","page":"多维数组","title":"多维数组","text":"julia> [1; 2;; 3; 4;; 5; 6;;;\n 7; 8;; 9; 10;; 11; 12]\n2×3×2 Array{Int64, 3}:\n[:, :, 1] =\n 1 3 5\n 2 4 6\n\n[:, :, 2] =\n 7 9 11\n 8 10 12","category":"page"},{"location":"manual/arrays/","page":"多维数组","title":"多维数组","text":"像之前一样,用于水平拼接的空格(和制表符)的优先级高于任何数量的分号。 因此,高维数组也可以通过首先指定它们的行来编写,它们的元素以类似于它们的布局的方式进行文本排列:","category":"page"},{"location":"manual/arrays/","page":"多维数组","title":"多维数组","text":"julia> [1 3 5\n 2 4 6;;;\n 7 9 11\n 8 10 12]\n2×3×2 Array{Int64, 3}:\n[:, :, 1] =\n 1 3 5\n 2 4 6\n\n[:, :, 2] =\n 7 9 11\n 8 10 12\n\njulia> [1 2;;; 3 4;;;; 5 6;;; 7 8]\n1×2×2×2 Array{Int64, 4}:\n[:, :, 1, 1] =\n 1 2\n\n[:, :, 2, 1] =\n 3 4\n\n[:, :, 1, 2] =\n 5 6\n\n[:, :, 2, 2] =\n 7 8\n\njulia> [[1 2;;; 3 4];;;; [5 6];;; [7 8]]\n1×2×2×2 Array{Int64, 4}:\n[:, :, 1, 1] =\n 1 2\n\n[:, :, 2, 1] =\n 3 4\n\n[:, :, 1, 2] =\n 5 6\n\n[:, :, 2, 2] =\n 7 8","category":"page"},{"location":"manual/arrays/","page":"多维数组","title":"多维数组","text":"尽管它们都表示第二维中的连接,但空格(或制表符)和 ;; 不能出现在同一个数组表达式中,除非双分号只是作为“行继续”字符。 这允许单个水平拼接跨越多行(不会将换行符解释为垂直拼接)。","category":"page"},{"location":"manual/arrays/","page":"多维数组","title":"多维数组","text":"julia> [1 2 ;;\n 3 4]\n1×4 Matrix{Int64}:\n 1 2 3 4","category":"page"},{"location":"manual/arrays/","page":"多维数组","title":"多维数组","text":"终止分号也可用于在最后添加 1 个长度为1的维度。","category":"page"},{"location":"manual/arrays/","page":"多维数组","title":"多维数组","text":"julia> [1;;]\n1×1 Matrix{Int64}:\n 1\n\njulia> [2; 3;;;]\n2×1×1 Array{Int64, 3}:\n[:, :, 1] =\n 2\n 3","category":"page"},{"location":"manual/arrays/","page":"多维数组","title":"多维数组","text":"更一般地,可以通过cat 函数来实现数组元素的拼接功能。 以下这些的语法为这些函数的简写形式,它们本身也是非常方便使用的:","category":"page"},{"location":"manual/arrays/","page":"多维数组","title":"多维数组","text":"语法 函数 描述\n cat 沿着 s 的第 k 维拼接数组\n[A; B; C; ...] vcat `cat(A...; dims=1) 的简写\n[A B C ...] hcat `cat(A...; dims=2) 的简写\n[A B; C D; ...] hvcat 同时沿垂直和水平方向拼接\n[A; C;; B; D;;; ...] hvncat 同时进行 n 维拼接,其中分号的数量表示拼接所在的维度","category":"page"},{"location":"manual/arrays/#指定类型的数组字面量","page":"多维数组","title":"指定类型的数组字面量","text":"","category":"section"},{"location":"manual/arrays/","page":"多维数组","title":"多维数组","text":"可以用 T[A, B, C, ...] 的方式声明一个元素为某种特定类型的数组。该方法定义一个元素类型为 T 的一维数组并且初始化元素为 A, B, C, ....。比如,Any[x, y, z] 会构建一个异构数组,该数组可以包含任意类型的元素。","category":"page"},{"location":"manual/arrays/","page":"多维数组","title":"多维数组","text":"类似的,拼接也可以用类型为前缀来指定结果的元素类型。","category":"page"},{"location":"manual/arrays/","page":"多维数组","title":"多维数组","text":"julia> [[1 2] [3 4]]\n1×4 Matrix{Int64}:\n 1 2 3 4\n\njulia> Int8[[1 2] [3 4]]\n1×4 Matrix{Int8}:\n 1 2 3 4","category":"page"},{"location":"manual/arrays/#man-comprehensions","page":"多维数组","title":"数组推导","text":"","category":"section"},{"location":"manual/arrays/","page":"多维数组","title":"多维数组","text":"(数组)推导提供了构造数组的通用且强大的方法。其语法类似于数学中的集合构造的写法:","category":"page"},{"location":"manual/arrays/","page":"多维数组","title":"多维数组","text":"A = [ F(x,y,...) for x=rx, y=ry, ... ]","category":"page"},{"location":"manual/arrays/","page":"多维数组","title":"多维数组","text":"这种形式的含义是 F(x,y,...) 取其给定列表中变量 x,y 等的每个值进行计算。值可以指定为任何可迭代对象,但通常是 1:n 或 2:(n-1) 之类的范围,或者像 [1.2, 3.4, 5.7] 这样的显式数组值。结果是一个 N 维密集数组,将变量范围 rx,ry 等的维数拼接起来得到其维数,并且每次 F(x,y,...) 计算返回一个标量。","category":"page"},{"location":"manual/arrays/","page":"多维数组","title":"多维数组","text":"下面的示例计算当前元素和沿一维网格其左,右相邻元素的加权平均值:","category":"page"},{"location":"manual/arrays/","page":"多维数组","title":"多维数组","text":"julia> x = rand(8)\n8-element Array{Float64,1}:\n 0.843025\n 0.869052\n 0.365105\n 0.699456\n 0.977653\n 0.994953\n 0.41084\n 0.809411\n\njulia> [ 0.25*x[i-1] + 0.5*x[i] + 0.25*x[i+1] for i=2:length(x)-1 ]\n6-element Array{Float64,1}:\n 0.736559\n 0.57468\n 0.685417\n 0.912429\n 0.8446\n 0.656511","category":"page"},{"location":"manual/arrays/","page":"多维数组","title":"多维数组","text":"生成的数组的类型取决于参与计算元素的类型,就像数组字面量一样。为了显式地控制类型,可以在数组推导之前指定类型。例如,我们可以要求推导的结果为单精度类型:","category":"page"},{"location":"manual/arrays/","page":"多维数组","title":"多维数组","text":"Float32[ 0.25*x[i-1] + 0.5*x[i] + 0.25*x[i+1] for i=2:length(x)-1 ]","category":"page"},{"location":"manual/arrays/#生成器表达式","page":"多维数组","title":"生成器表达式","text":"","category":"section"},{"location":"manual/arrays/","page":"多维数组","title":"多维数组","text":"也可以在没有方括号的情况下编写(数组)推导,从而产生称为生成器的对象。可以迭代此对象以按需生成值,而不是预先分配数组并存储它们(请参阅 迭代)。例如,以下表达式在不分配内存的情况下对一个序列进行求和:","category":"page"},{"location":"manual/arrays/","page":"多维数组","title":"多维数组","text":"julia> sum(1/n^2 for n=1:1000)\n1.6439345666815615","category":"page"},{"location":"manual/arrays/","page":"多维数组","title":"多维数组","text":"在参数列表中使用具有多个维度的生成器表达式时,需要使用括号将生成器与后续参数分开:","category":"page"},{"location":"manual/arrays/","page":"多维数组","title":"多维数组","text":"julia> map(tuple, 1/(i+j) for i=1:2, j=1:2, [1:4;])\nERROR: syntax: invalid iteration specification","category":"page"},{"location":"manual/arrays/","page":"多维数组","title":"多维数组","text":"for 后面所有逗号分隔的表达式都被解释为范围。 添加括号让我们可以向 map 中添加第三个参数:","category":"page"},{"location":"manual/arrays/","page":"多维数组","title":"多维数组","text":"julia> map(tuple, (1/(i+j) for i=1:2, j=1:2), [1 3; 2 4])\n2×2 Matrix{Tuple{Float64, Int64}}:\n (0.5, 1) (0.333333, 3)\n (0.333333, 2) (0.25, 4)","category":"page"},{"location":"manual/arrays/","page":"多维数组","title":"多维数组","text":"生成器是通过内部函数实现。 与本语言中别处使用的内部函数一样,封闭作用域中的变量可以在内部函数中被「捕获」。例如,sum(p[i] - q[i] for i=1:n) 从封闭作用域中捕获三个变量 p、q 和 n。但是变量捕获可能会带来性能挑战;请参阅 性能提示。","category":"page"},{"location":"manual/arrays/","page":"多维数组","title":"多维数组","text":"通过编写多个 for 关键字,生成器和推导中的范围可以取决于之前的范围:","category":"page"},{"location":"manual/arrays/","page":"多维数组","title":"多维数组","text":"julia> [(i,j) for i=1:3 for j=1:i]\n6-element Vector{Tuple{Int64, Int64}}:\n (1, 1)\n (2, 1)\n (2, 2)\n (3, 1)\n (3, 2)\n (3, 3)","category":"page"},{"location":"manual/arrays/","page":"多维数组","title":"多维数组","text":"在这些情况下,结果都是一维的。","category":"page"},{"location":"manual/arrays/","page":"多维数组","title":"多维数组","text":"可以使用 if 关键字过滤生成的值:","category":"page"},{"location":"manual/arrays/","page":"多维数组","title":"多维数组","text":"julia> [(i,j) for i=1:3 for j=1:i if i+j == 4]\n2-element Vector{Tuple{Int64, Int64}}:\n (2, 2)\n (3, 1)","category":"page"},{"location":"manual/arrays/#man-array-indexing","page":"多维数组","title":"索引","text":"","category":"section"},{"location":"manual/arrays/","page":"多维数组","title":"多维数组","text":"索引 n 维数组 A 的一般语法是:","category":"page"},{"location":"manual/arrays/","page":"多维数组","title":"多维数组","text":"X = A[I_1, I_2, ..., I_n]","category":"page"},{"location":"manual/arrays/","page":"多维数组","title":"多维数组","text":"其中每个 I_k 可以是标量整数,整数数组或任何其他支持的索引类型。这包括 Colon (:) 来选择整个维度中的所有索引,形式为 a:c 或 a:b:c 的范围来选择连续或跨步的子区间,以及布尔数组以选择索引为 true 的元素。","category":"page"},{"location":"manual/arrays/","page":"多维数组","title":"多维数组","text":"如果所有索引都是标量,则结果 X 是数组 A 中的单个元素。否则,X 是一个数组,其维数与所有索引的维数之和相同。","category":"page"},{"location":"manual/arrays/","page":"多维数组","title":"多维数组","text":"如果所有索引 I_k 都是向量,则 X 的形状将是 (length(I_1), length(I_2), ..., length(I_n)),其中,X 中位于 i_1, i_2, ..., i_n 处的元素为 A[I_1[i_1], I_2[i_2], ..., I_n[i_n]]。","category":"page"},{"location":"manual/arrays/","page":"多维数组","title":"多维数组","text":"例如:","category":"page"},{"location":"manual/arrays/","page":"多维数组","title":"多维数组","text":"julia> A = reshape(collect(1:16), (2, 2, 2, 2))\n2×2×2×2 Array{Int64, 4}:\n[:, :, 1, 1] =\n 1 3\n 2 4\n\n[:, :, 2, 1] =\n 5 7\n 6 8\n\n[:, :, 1, 2] =\n 9 11\n 10 12\n\n[:, :, 2, 2] =\n 13 15\n 14 16\n\njulia> A[1, 2, 1, 1] # 全部为标量索引\n3\n\njulia> A[[1, 2], [1], [1, 2], [1]] # 全部为向量索引\n2×1×2×1 Array{Int64, 4}:\n[:, :, 1, 1] =\n 1\n 2\n\n[:, :, 2, 1] =\n 5\n 6\n\njulia> A[[1, 2], [1], [1, 2], 1] # 标量与向量索引的混合使用\n2×1×2 Array{Int64, 3}:\n[:, :, 1] =\n 1\n 2\n\n[:, :, 2] =\n 5\n 6","category":"page"},{"location":"manual/arrays/","page":"多维数组","title":"多维数组","text":"请注意最后两种情况下得到的数组大小为何是不同的。","category":"page"},{"location":"manual/arrays/","page":"多维数组","title":"多维数组","text":"如果 I_1 是二维矩阵,则 X 是 n+1 维数组,其形状为 (size(I_1, 1), size(I_1, 2), length(I_2), ..., length(I_n))。矩阵会添加一个维度。","category":"page"},{"location":"manual/arrays/","page":"多维数组","title":"多维数组","text":"例如:","category":"page"},{"location":"manual/arrays/","page":"多维数组","title":"多维数组","text":"julia> A = reshape(collect(1:16), (2, 2, 2, 2));\n\njulia> A[[1 2; 1 2]]\n2×2 Matrix{Int64}:\n 1 2\n 1 2\n\njulia> A[[1 2; 1 2], 1, 2, 1]\n2×2 Matrix{Int64}:\n 5 6\n 5 6","category":"page"},{"location":"manual/arrays/","page":"多维数组","title":"多维数组","text":"位于 i_1, i_2, i_3, ..., i_{n+1} 处的元素值是 A[I_1[i_1, i_2], I_2[i_3], ..., I_n[i_{n+1}]]。所有使用标量索引的维度都将被丢弃,例如,假设 J 是索引数组,那么 A[2,J,3] 的结果是一个大小为 size(J) 的数组、其第 j 个元素由 A[2, J[j], 3] 填充。","category":"page"},{"location":"manual/arrays/","page":"多维数组","title":"多维数组","text":"作为此语法的特殊部分,end 关键字可用于表示索引括号内每个维度的最后一个索引,由索引的最内层数组的大小决定。没有 end 关键字的索引语法相当于调用getindex:","category":"page"},{"location":"manual/arrays/","page":"多维数组","title":"多维数组","text":"X = getindex(A, I_1, I_2, ..., I_n)","category":"page"},{"location":"manual/arrays/","page":"多维数组","title":"多维数组","text":"例如:","category":"page"},{"location":"manual/arrays/","page":"多维数组","title":"多维数组","text":"julia> x = reshape(1:16, 4, 4)\n4×4 reshape(::UnitRange{Int64}, 4, 4) with eltype Int64:\n 1 5 9 13\n 2 6 10 14\n 3 7 11 15\n 4 8 12 16\n\njulia> x[2:3, 2:end-1]\n2×2 Matrix{Int64}:\n 6 10\n 7 11\n\njulia> x[1, [2 3; 4 1]]\n2×2 Matrix{Int64}:\n 5 9\n 13 1","category":"page"},{"location":"manual/arrays/#man-indexed-assignment","page":"多维数组","title":"索引赋值","text":"","category":"section"},{"location":"manual/arrays/","page":"多维数组","title":"多维数组","text":"在 n 维数组 A 中赋值的一般语法是:","category":"page"},{"location":"manual/arrays/","page":"多维数组","title":"多维数组","text":"A[I_1, I_2, ..., I_n] = X","category":"page"},{"location":"manual/arrays/","page":"多维数组","title":"多维数组","text":"其中每个 I_k 可以是标量整数,整数数组或任何其他支持的索引类型。这包括 Colon (:) 来选择整个维度中的所有索引,形式为 a:c 或 a:b:c 的范围来选择连续或跨步的子区间,以及布尔数组以选择索引为 true 的元素。","category":"page"},{"location":"manual/arrays/","page":"多维数组","title":"多维数组","text":"如果所有 I_k 都为整数,则数组 A 中 I_1, I_2, ..., I_n 位置的值将被 X 的值覆盖,必要时将 convert 为数组 A 的 eltype。","category":"page"},{"location":"manual/arrays/","page":"多维数组","title":"多维数组","text":"如果索引 I_k 本身就是一个数组,那么右侧的 X 也必须是一个与索引 A[I_1, I_2, ..., I_n] 的结果具有相同形状的数组或是具有相同数量元素的向量。 A 的位置 I_1[i_1], I_2[i_2], ..., I_n[i_n] 中的值被值 X[I_1, I_2, ..., I_n] 覆盖,如果必要也会进行类型转换。 元素分配运算符 .= 可以用于沿着所选区域 广播 X:","category":"page"},{"location":"manual/arrays/","page":"多维数组","title":"多维数组","text":"A[I_1, I_2, ..., I_n] .= X","category":"page"},{"location":"manual/arrays/","page":"多维数组","title":"多维数组","text":"就像在索引中一样,end关键字可用于表示索引括号中每个维度的最后一个索引,由被赋值的数组大小决定。 没有end关键字的索引赋值语法相当于调用setindex!:","category":"page"},{"location":"manual/arrays/","page":"多维数组","title":"多维数组","text":"setindex!(A, X, I_1, I_2, ..., I_n)","category":"page"},{"location":"manual/arrays/","page":"多维数组","title":"多维数组","text":"例如:","category":"page"},{"location":"manual/arrays/","page":"多维数组","title":"多维数组","text":"julia> x = collect(reshape(1:9, 3, 3))\n3×3 Matrix{Int64}:\n 1 4 7\n 2 5 8\n 3 6 9\n\njulia> x[3, 3] = -9;\n\njulia> x[1:2, 1:2] = [-1 -4; -2 -5];\n\njulia> x\n3×3 Matrix{Int64}:\n -1 -4 7\n -2 -5 8\n 3 6 -9","category":"page"},{"location":"manual/arrays/#man-supported-index-types","page":"多维数组","title":"支持的索引类型","text":"","category":"section"},{"location":"manual/arrays/","page":"多维数组","title":"多维数组","text":"在表达式 A[I_1, I_2, ..., I_n] 中,每个 I_k 可以是标量索引,标量索引数组,或者用 to_indices 转换成的表示标量索引数组的对象:","category":"page"},{"location":"manual/arrays/","page":"多维数组","title":"多维数组","text":"标量索引。默认情况下,这包括:\n非布尔的整数\nCartesianIndex{N} 用来表达多个维度的信息(详见下文),其内部实际为 N个整数组成的元组。\n标量索引数组。这包括:\n整数向量和多维整数数组\n像 [] 这样的空数组,它不选择任何元素\n如 a:c 或 a:b:c 的范围,从 a 到 c(包括)选择连续或间隔的部分元素\n任何自定义标量索引数组,它是 AbstractArray 的子类型\nCartesianIndex{N} 数组(详见下文)\n一个表示标量索引数组的对象,可以通过to_indices转换为这样的对象。 默认情况下,这包括:\nColon() (:),表示整个维度内或整个数组中的所有索引\n布尔数组,选择其中值为 true 的索引对应的元素(更多细节见下文)","category":"page"},{"location":"manual/arrays/","page":"多维数组","title":"多维数组","text":"一些例子:","category":"page"},{"location":"manual/arrays/","page":"多维数组","title":"多维数组","text":"julia> A = reshape(collect(1:2:18), (3, 3))\n3×3 Matrix{Int64}:\n 1 7 13\n 3 9 15\n 5 11 17\n\njulia> A[4]\n7\n\njulia> A[[2, 5, 8]]\n3-element Vector{Int64}:\n 3\n 9\n 15\n\njulia> A[[1 4; 3 8]]\n2×2 Matrix{Int64}:\n 1 7\n 5 15\n\njulia> A[[]]\nInt64[]\n\njulia> A[1:2:5]\n3-element Vector{Int64}:\n 1\n 5\n 9\n\njulia> A[2, :]\n3-element Vector{Int64}:\n 3\n 9\n 15\n\njulia> A[:, 3]\n3-element Vector{Int64}:\n 13\n 15\n 17","category":"page"},{"location":"manual/arrays/#笛卡尔索引","page":"多维数组","title":"笛卡尔索引","text":"","category":"section"},{"location":"manual/arrays/","page":"多维数组","title":"多维数组","text":"特殊的 CartesianIndex{N} 对象表示一个标量索引,其行为类似于张成多个维度的 N 维整数元组。例如:","category":"page"},{"location":"manual/arrays/","page":"多维数组","title":"多维数组","text":"julia> A = reshape(1:32, 4, 4, 2);\n\njulia> A[3, 2, 1]\n7\n\njulia> A[CartesianIndex(3, 2, 1)] == A[3, 2, 1] == 7\ntrue","category":"page"},{"location":"manual/arrays/","page":"多维数组","title":"多维数组","text":"单独来看的话,这看起来很平凡:CartesianIndex 单纯只是将多个整数捆绑在一起作为一个对象来表示一个多维下标。当与其他取下标方式和生成 CartesianIndex 的迭代器进行工作的时候,它才真正能展现出它的简洁与高效。关于这个你可以参考 迭代器 这一部分,你也可以参考 关于多维算法和迭代器的介绍 这篇博客来了解更进阶的用法。","category":"page"},{"location":"manual/arrays/","page":"多维数组","title":"多维数组","text":"元素类型为 CartesianIndex{N} 的矩阵也是支持的。每一个元素都单独表示一个 N 维空间的 索引下标,作为一个整体这样一个矩阵则表示一些 N 维空间的点的坐标,因此这种形式有时 也称为逐点索引。例如:你可以通过它来访问上面所定义的三维矩阵 A 的第一页 (第三维指标为1)的对角线元素:","category":"page"},{"location":"manual/arrays/","page":"多维数组","title":"多维数组","text":"julia> page = A[:,:,1]\n4×4 Matrix{Int64}:\n 1 5 9 13\n 2 6 10 14\n 3 7 11 15\n 4 8 12 16\n\njulia> page[[CartesianIndex(1,1),\n CartesianIndex(2,2),\n CartesianIndex(3,3),\n CartesianIndex(4,4)]]\n4-element Vector{Int64}:\n 1\n 6\n 11\n 16","category":"page"},{"location":"manual/arrays/","page":"多维数组","title":"多维数组","text":"这可以通过 dot broadcasting 以及普通整数索引(而不是把从 A 中提取第一“页”作为单独的步骤)更加简单地表达。它甚至可以与 : 结合使用,同时从两个页面中提取两个对角线:","category":"page"},{"location":"manual/arrays/","page":"多维数组","title":"多维数组","text":"julia> A[CartesianIndex.(axes(A, 1), axes(A, 2)), 1]\n4-element Vector{Int64}:\n 1\n 6\n 11\n 16\n\njulia> A[CartesianIndex.(axes(A, 1), axes(A, 2)), :]\n4×2 Matrix{Int64}:\n 1 17\n 6 22\n 11 27\n 16 32","category":"page"},{"location":"manual/arrays/","page":"多维数组","title":"多维数组","text":"warning: Warning\nCartesianIndex 和 CartesianIndex 数组与用来表示维度的最后一个索引的 end 关键字不兼容。 不要在可能包含CartesianIndex或其数组的索引表达式中使用end。","category":"page"},{"location":"manual/arrays/#逻辑索引","page":"多维数组","title":"逻辑索引","text":"","category":"section"},{"location":"manual/arrays/","page":"多维数组","title":"多维数组","text":"通常被称为逻辑索引或带有逻辑掩码的索引,通过布尔数组进行索引选择其值为true的索引处的元素。 通过布尔向量B进行索引实际上与通过findall(B)返回的整数向量进行索引相同。 类似地,通过N维布尔数组进行索引与通过其值为true的CartesianIndex{N}的向量进行索引实际上是相同的。 一个逻辑索引必须是一个与它所索引的维度长度相同的向量,或者它必须是唯一提供的索引并且匹配它所索引到的数组的大小和维度。 通常直接使用布尔数组作为索引更有效,而不是调用 findall。","category":"page"},{"location":"manual/arrays/","page":"多维数组","title":"多维数组","text":"julia> x = reshape(1:16, 4, 4)\n4×4 reshape(::UnitRange{Int64}, 4, 4) with eltype Int64:\n 1 5 9 13\n 2 6 10 14\n 3 7 11 15\n 4 8 12 16\n\njulia> x[[false, true, true, false], :]\n2×4 Matrix{Int64}:\n 2 6 10 14\n 3 7 11 15\n\njulia> mask = map(ispow2, x)\n4×4 Matrix{Bool}:\n 1 0 0 0\n 1 0 0 0\n 0 0 0 0\n 1 1 0 1\n\njulia> x[mask]\n5-element Vector{Int64}:\n 1\n 2\n 4\n 8\n 16","category":"page"},{"location":"manual/arrays/#索引数","page":"多维数组","title":"索引数","text":"","category":"section"},{"location":"manual/arrays/#笛卡尔索引-2","page":"多维数组","title":"笛卡尔索引","text":"","category":"section"},{"location":"manual/arrays/","page":"多维数组","title":"多维数组","text":"通常,为一个N维数组元素使用索引的方式是使用N个数字作为索引,每一个索引值确定一个具体的维度。例如,一个三维数组A = rand(4, 3, 2), A[2, 3, 1] 将选择的第二行第三列第一“页”中的元素。这种方式通常也被成为笛卡尔索引。","category":"page"},{"location":"manual/arrays/#线性索引","page":"多维数组","title":"线性索引","text":"","category":"section"},{"location":"manual/arrays/","page":"多维数组","title":"多维数组","text":"当恰好提供了一个索引i时,该索引不再表示数组特定维度中的位置。 相反,它使用线性遍历整个数组的列主迭代顺序选择第 i 个元素。 这称为线性索引。 它本质上将数组视为使用 vec 将其重新整形为一维向量。","category":"page"},{"location":"manual/arrays/","page":"多维数组","title":"多维数组","text":"julia> A = [2 6; 4 7; 3 1]\n3×2 Matrix{Int64}:\n 2 6\n 4 7\n 3 1\n\njulia> A[5]\n7\n\njulia> vec(A)[5]\n7","category":"page"},{"location":"manual/arrays/","page":"多维数组","title":"多维数组","text":"数组 A 中的线性索引可以转换为 CartesianIndex 以使用 CartesianIndices(A)[i] 进行笛卡尔索引(参见 CartesianIndices),一组 N 维笛卡尔索引可以通过LinearIndices(A)[i_1, i_2, ..., i_N] 转换为线性索引(参见LinearIndices)。","category":"page"},{"location":"manual/arrays/","page":"多维数组","title":"多维数组","text":"julia> CartesianIndices(A)[5]\nCartesianIndex(2, 2)\n\njulia> LinearIndices(A)[2, 2]\n5","category":"page"},{"location":"manual/arrays/","page":"多维数组","title":"多维数组","text":"需要注意的是,这些转换的性能存在很大的不对称性。 将线性索引转换为一组笛卡尔索引需要做除法取余数,而相反的转换只是相乘和相加。 在现代处理器中,整数除法比乘法慢 10-50 倍。 虽然一些数组——比如 Array 本身——是使用线性内存块实现的,并在它们的实现中直接使用线性索引,但其他数组——比如 Diagonal——需要完整的笛卡尔索引集进行查找(请参阅 IndexStyle 以仔细推敲)。 因此,当遍历整个数组时,最好遍历 eachindex(A) 而不是 1:length(A)。 在 A 是 IndexCartesian 的情况下,前者不仅会快得多,而且它还支持 OffsetArrays(译者注:OffsetArrays.jl是Julia的一个包,支持矩阵的下标不从1开始)。","category":"page"},{"location":"manual/arrays/#Omitted-and-extra-indices","page":"多维数组","title":"省略和额外的索引","text":"","category":"section"},{"location":"manual/arrays/","page":"多维数组","title":"多维数组","text":"除了线性索引,在某些情况下, N 维数组的可能少于或多余 N 。","category":"page"},{"location":"manual/arrays/","page":"多维数组","title":"多维数组","text":"如果未索引的剩余维度的长度均为 1,则可以省略索引。 换句话说,只有当那些省略的索引对于索引表达式只有一个可能的值时,才可以省略剩余索引。 例如,一个大小为(3, 4, 2, 1)的四维数组可能只用三个索引进行索引,因为被跳过的维度(第四维)的长度为 1。 请注意,线性索引优先级高于此规则。","category":"page"},{"location":"manual/arrays/","page":"多维数组","title":"多维数组","text":"julia> A = reshape(1:24, 3, 4, 2, 1)\n3×4×2×1 reshape(::UnitRange{Int64}, 3, 4, 2, 1) with eltype Int64:\n[:, :, 1, 1] =\n 1 4 7 10\n 2 5 8 11\n 3 6 9 12\n\n[:, :, 2, 1] =\n 13 16 19 22\n 14 17 20 23\n 15 18 21 24\n\njulia> A[1, 3, 2] # Omits the fourth dimension (length 1)\n19\n\njulia> A[1, 3] # Attempts to omit dimensions 3 & 4 (lengths 2 and 1)\nERROR: BoundsError: attempt to access 3×4×2×1 reshape(::UnitRange{Int64}, 3, 4, 2, 1) with eltype Int64 at index [1, 3]\n\njulia> A[19] # Linear indexing\n19","category":"page"},{"location":"manual/arrays/","page":"多维数组","title":"多维数组","text":"当用A[] 省略全部 索引时,这种语义提供了一种简单的习惯用法来检索数组中的唯一元素,同时确保只有一个元素。","category":"page"},{"location":"manual/arrays/","page":"多维数组","title":"多维数组","text":"类似地,如果超出数组维数的所有索引都是1(或更一般地说是axes(A, d)的第一个也是唯一的元素,其中d是特定的维数),可以使用超过N维的索引。这允许向量像一列矩阵一样被索引,例如:","category":"page"},{"location":"manual/arrays/","page":"多维数组","title":"多维数组","text":"julia> A = [8,6,7]\n3-element Vector{Int64}:\n 8\n 6\n 7\n\njulia> A[2,1]\n6","category":"page"},{"location":"manual/arrays/#Iteration","page":"多维数组","title":"迭代","text":"","category":"section"},{"location":"manual/arrays/","page":"多维数组","title":"多维数组","text":"迭代整个数组的推荐方法是","category":"page"},{"location":"manual/arrays/","page":"多维数组","title":"多维数组","text":"for a in A\n # Do something with the element a\nend\n\nfor i in eachindex(A)\n # Do something with i and/or A[i]\nend","category":"page"},{"location":"manual/arrays/","page":"多维数组","title":"多维数组","text":"当你需要每个元素的值而不是索引时,使用第一个构造。 在第二个构造中,如果 A 是具有快速线性索引的数组类型,i 将是 Int; 否则,它将是一个 CartesianIndex:","category":"page"},{"location":"manual/arrays/","page":"多维数组","title":"多维数组","text":"julia> A = rand(4,3);\n\njulia> B = view(A, 1:3, 2:3);\n\njulia> for i in eachindex(B)\n @show i\n end\ni = CartesianIndex(1, 1)\ni = CartesianIndex(2, 1)\ni = CartesianIndex(3, 1)\ni = CartesianIndex(1, 2)\ni = CartesianIndex(2, 2)\ni = CartesianIndex(3, 2)","category":"page"},{"location":"manual/arrays/","page":"多维数组","title":"多维数组","text":"与 for i = 1:length(A) 相比,eachindex 提供了一种迭代任何数组类型的有效方法。","category":"page"},{"location":"manual/arrays/#Array-traits","page":"多维数组","title":"Array traits","text":"","category":"section"},{"location":"manual/arrays/","page":"多维数组","title":"多维数组","text":"如果你编写一个自定义的 AbstractArray 类型,你可以用以下代码指定它使用快速线性索引","category":"page"},{"location":"manual/arrays/","page":"多维数组","title":"多维数组","text":"Base.IndexStyle(::Type{<:MyArray}) = IndexLinear()","category":"page"},{"location":"manual/arrays/","page":"多维数组","title":"多维数组","text":"此设置将导致 myArray 上的 eachindex 迭代使用整数。如果未指定此特征,则使用默认值 IndexCartesian()。","category":"page"},{"location":"manual/arrays/#man-array-and-vectorized-operators-and-functions","page":"多维数组","title":"数组和向量化的算子与函数","text":"","category":"section"},{"location":"manual/arrays/","page":"多维数组","title":"多维数组","text":"以下运算符支持对数组操作","category":"page"},{"location":"manual/arrays/","page":"多维数组","title":"多维数组","text":"一元运算符 – -, +\n二元运算符 – -, +, *, /, \\, ^\n比较操作符 – ==, !=, ≈ (isapprox), ≉","category":"page"},{"location":"manual/arrays/","page":"多维数组","title":"多维数组","text":"另外,为了便于数学上和其他运算的向量化,Julia 提供了点语法(dot syntax) f.(args...),例如,sin.(x) 或 min.(x,y),用于数组或数组和标量的混合上的按元素运算(广播运算);当与其他点调用(dot call)结合使用时,它们的额外优点是能「融合」到单个循环中,例如,sin.(cos.(x))。","category":"page"},{"location":"manual/arrays/","page":"多维数组","title":"多维数组","text":"此外,每个二元运算符支持相应的点操作版本,可以应用于此类融合 broadcasting 操作的数组(以及数组和标量的组合),例如 z .== sin.(x .* y)。","category":"page"},{"location":"manual/arrays/","page":"多维数组","title":"多维数组","text":"请注意,类似 == 的比较运算在作用于整个数组时,得到一个布尔结果。使用像 .== 这样的点运算符进行按元素的比较。(对于像 < 这样的比较操作,只有按元素运算的版本 .< 适用于数组。)","category":"page"},{"location":"manual/arrays/","page":"多维数组","title":"多维数组","text":"还要注意 max.(a,b) 和 maximum(a) 之间的区别,max.(a,b) 对 a 和 b 的每个元素 broadcasts max,maximum(a) 寻找在 a 中的最大值。min.(a,b) 和 minimum(a) 也有同样的关系。","category":"page"},{"location":"manual/arrays/#Broadcasting","page":"多维数组","title":"广播","text":"","category":"section"},{"location":"manual/arrays/","page":"多维数组","title":"多维数组","text":"有时需要在不同尺寸的数组上执行元素对元素的操作,例如将矩阵的每一列加一个向量。一种低效的方法是将向量复制成矩阵的大小:","category":"page"},{"location":"manual/arrays/","page":"多维数组","title":"多维数组","text":"julia> a = rand(2,1); A = rand(2,3);\n\njulia> repeat(a,1,3)+A\n2×3 Array{Float64,2}:\n 1.20813 1.82068 1.25387\n 1.56851 1.86401 1.67846","category":"page"},{"location":"manual/arrays/","page":"多维数组","title":"多维数组","text":"当维度较大的时候,这种方法将会十分浪费,所以 Julia 提供了广播 broadcast,它将会将参数中低维度的参数扩展,使得其与其他维度匹配,且不会使用额外的内存,并将所给的函数逐元素地应用。","category":"page"},{"location":"manual/arrays/","page":"多维数组","title":"多维数组","text":"julia> broadcast(+, a, A)\n2×3 Array{Float64,2}:\n 1.20813 1.82068 1.25387\n 1.56851 1.86401 1.67846\n\njulia> b = rand(1,2)\n1×2 Array{Float64,2}:\n 0.867535 0.00457906\n\njulia> broadcast(+, a, b)\n2×2 Array{Float64,2}:\n 1.71056 0.847604\n 1.73659 0.873631","category":"page"},{"location":"manual/arrays/","page":"多维数组","title":"多维数组","text":"点运算符 如.+ 和.* 等价于broadcast 调用(除了它们结合使用,如上所述)。 还有一个 broadcast! 函数来指定一个明确的方式(也可以通过.= 赋值以融合方式访问)。 事实上,f.(args...) 等价于broadcast(f, args...),提供了一种方便的语法来广播任何函数(dot syntax)。 嵌套的“点运算符调用”f.(...)(包括对.+ 等的调用)自动融合 到单个broadcast 调用中。","category":"page"},{"location":"manual/arrays/","page":"多维数组","title":"多维数组","text":"此外,broadcast 不限于数组(参见函数文档); 它还处理标量、元组和其它容器。 默认情况下,只有一些参数类型被认为是标量,包括(但不限于)Numbers、Strings、Symbols、Types、Functions 和一些常见的单例,如 missing 和nothing。 所有其他参数都被迭代或逐个索引。","category":"page"},{"location":"manual/arrays/","page":"多维数组","title":"多维数组","text":"julia> convert.(Float32, [1, 2])\n2-element Vector{Float32}:\n 1.0\n 2.0\n\njulia> ceil.(UInt8, [1.2 3.4; 5.6 6.7])\n2×2 Matrix{UInt8}:\n 0x02 0x04\n 0x06 0x07\n\njulia> string.(1:3, \". \", [\"First\", \"Second\", \"Third\"])\n3-element Vector{String}:\n \"1. First\"\n \"2. Second\"\n \"3. Third\"","category":"page"},{"location":"manual/arrays/","page":"多维数组","title":"多维数组","text":"有时,你希望一个通常参与广播的容器(如数组)受到“保护”,使其免受广播迭代其所有元素的行为的影响。 通过将其放置在另一个容器中(如单个元素 Tuple),广播会将其视为单个值。","category":"page"},{"location":"manual/arrays/","page":"多维数组","title":"多维数组","text":"julia> ([1, 2, 3], [4, 5, 6]) .+ ([1, 2, 3],)\n([2, 4, 6], [5, 7, 9])\n\njulia> ([1, 2, 3], [4, 5, 6]) .+ tuple([1, 2, 3])\n([2, 4, 6], [5, 7, 9])","category":"page"},{"location":"manual/arrays/#实现","page":"多维数组","title":"实现","text":"","category":"section"},{"location":"manual/arrays/","page":"多维数组","title":"多维数组","text":"Julia 中的基本数组类型是抽象类型 AbstractArray{T,N}。它通过维数 N 和元素类型 T 进行参数化。AbstractVector 和 AbstractMatrix 是一维和二维情况下的别名。AbstractArray 对象的操作是使用更高级别的运算符和函数定义的,其方式独立于底层存储。这些操作可以正确地被用于任何特定数组实现的回退操作。","category":"page"},{"location":"manual/arrays/","page":"多维数组","title":"多维数组","text":"AbstractArray 类型包括任何类似数组的东西,它的实现可能与传统数组完全不同。例如,元素可能根据请求计算而不是存储。然而,任何具体的 AbstractArray{T,N} 类型通常应该至少实现 size(A)(返回一个 Int 元组),getindex(A,i) 和 getindex(A,i1,...,iN);可变数组也应该实现 setindex!。建议这些操作具有常数时间复杂度,否则某些数组函数可能会出乎意料的慢。具体类型通常还应该提供一个 similar(A,T=eltype(A),dims=size(A)) 方法,用于为 copy 和其他不合适的操作。无论 AbstractArray{T,N} 在内部如何表示,T 都是由 整数 索引(A[1, ..., 1],当 A 非空) 返回的对象类型并且 N 应该是 size 返回的元组的长度。有关自定义 AbstractArray 实现的更多详细信息,请参阅 接口章节中的数组接口指南。","category":"page"},{"location":"manual/arrays/","page":"多维数组","title":"多维数组","text":"DenseArray 是 AbstractArray 的抽象子类型,旨在包括元素以列优先顺序连续存储的所有数组(请参阅 性能提示中的附加说明)。 Array 类型是DenseArray 的一个特定实例; Vector 和 Matrix 是一维和二维情况的别名。 除了所有AbstractArrays所需的操作之外,很少有专门为Array实现的操作;大部分数组库都是以泛型方式实现的,允许所有自定义数组的行为类似。","category":"page"},{"location":"manual/arrays/","page":"多维数组","title":"多维数组","text":"SubArray 是 AbstractArray 的特例,它通过与原始数组共享内存而不是复制它来执行索引。 使用view 函数创建 SubArray,它的调用方式与getindex 相同(作用于数组和一系列索引参数)。 view 的结果看起来与 getindex 的结果相同,只是数据保持不变。 view 将输入索引向量存储在 SubArray 对象中,该对象稍后可用于间接索引原始数组。 通过将 @views 宏放在表达式或代码块之前,该表达式中的任何 array [...] 切片将被转换为创建一个 SubArray 视图。","category":"page"},{"location":"manual/arrays/","page":"多维数组","title":"多维数组","text":"BitArray 是节省空间“压缩”的布尔数组,每个比特(bit)存储一个布尔值。 它们可以类似于 Array{Bool} 数组(每个字节(byte)存储一个布尔值),并且可以分别通过 Array(bitarray) 和 BitArray(array) 相互转换。","category":"page"},{"location":"manual/arrays/","page":"多维数组","title":"多维数组","text":"如果数组存储在内存中,其元素之间具有明确定义的间距(步长),则该数组是“等步长的”的。 通过简单地传递其 pointer 和每个维度的步长,可以将有支持元素类型的等步长数组传递给外部(非 Julia)库,如 BLAS 或 LAPACK。 stride(A, d) 是元素之间沿维度 d 的距离。 例如,rand(5,7,2) 返回的内置 Array 的元素按列优先顺序连续排列。 这意味着第一个维度的步长——同一列中元素之间的间距——是1:","category":"page"},{"location":"manual/arrays/","page":"多维数组","title":"多维数组","text":"julia> A = rand(5,7,2);\n\njulia> stride(A,1)\n1","category":"page"},{"location":"manual/arrays/","page":"多维数组","title":"多维数组","text":"第二个维度的步长是同一行中元素之间的间距,跳过与单列(5)中的元素一样多的元素。 类似地,在两个“页面”(在第三维中)之间跳转需要跳过 5*7 == 35 元素。 这个数组的 strides 是这三个数字组成的元组:","category":"page"},{"location":"manual/arrays/","page":"多维数组","title":"多维数组","text":"julia> strides(A)\n(1, 5, 35)","category":"page"},{"location":"manual/arrays/","page":"多维数组","title":"多维数组","text":"在这种特殊情况下,在内存中跳过的元素数与跳过的线性索引数相匹配。 这仅适用于像 Array(和其他 DenseArray 子类型)这样的连续数组,通常情况下并非如此。 具有范围索引的视图是 非连续 等步长数组的一个很好的例子; 考虑V = @view A[1:3:4, 2:2:6, 2:-1:1]。 这个视图 V 与 A 引用了相同的内存,但它跳过并重新排列了它的一些元素。 V 的第一维的步幅是 3,因为我们只从原始数组中选择每第三行:","category":"page"},{"location":"manual/arrays/","page":"多维数组","title":"多维数组","text":"julia> V = @view A[1:3:4, 2:2:6, 2:-1:1];\n\njulia> stride(V, 1)\n3","category":"page"},{"location":"manual/arrays/","page":"多维数组","title":"多维数组","text":"这个视图类似于从我们原来的A中每隔一列选择一列——因此当在第二维的索引之间移动时,它需要跳过相当于两个五元素列的内容:","category":"page"},{"location":"manual/arrays/","page":"多维数组","title":"多维数组","text":"julia> stride(V, 2)\n10","category":"page"},{"location":"manual/arrays/","page":"多维数组","title":"多维数组","text":"第三维很有趣因为它的顺序颠倒了! 因此从第一 \"页\" 到第二页它必须在内存中到 backwards,所以它在这一维的 strides 是负的!","category":"page"},{"location":"manual/arrays/","page":"多维数组","title":"多维数组","text":"julia> stride(V, 3)\n-35","category":"page"},{"location":"manual/arrays/","page":"多维数组","title":"多维数组","text":"这意味着V 的pointer 实际上指向A 的内存块的中间,并且它在内存中指向元素是同时向后和向前的。 有关定义你自己的跨距数组的更多详细信息,请参阅 等步长数组的接口指南。 StridedVector 和 StridedMatrix 被认为是等步长数组的内置数组类型的方便别名,允许它们仅使用指针和步幅,来分派选择调用调整和优化后的 BLAS 和 LAPACK 函数。","category":"page"},{"location":"manual/arrays/","page":"多维数组","title":"多维数组","text":"需要强调的是 strides 是关于内存而不是索引中的偏移。如果你在找在线性(单索引)索引和笛卡尔(多索引)索引间切换的方法,见 LinearIndices 和 CartesianIndices.","category":"page"},{"location":"base/file/#文件系统","page":"文件系统","title":"文件系统","text":"","category":"section"},{"location":"base/file/","page":"文件系统","title":"文件系统","text":"Base.Filesystem.pwd\nBase.Filesystem.cd(::AbstractString)\nBase.Filesystem.cd(::Function)\nBase.Filesystem.readdir\nBase.Filesystem.walkdir\nBase.Filesystem.mkdir\nBase.Filesystem.mkpath\nBase.Filesystem.symlink\nBase.Filesystem.readlink\nBase.Filesystem.chmod\nBase.Filesystem.chown\nBase.RawFD\nBase.stat\nBase.Filesystem.lstat\nBase.Filesystem.ctime\nBase.Filesystem.mtime\nBase.Filesystem.filemode\nBase.Filesystem.filesize\nBase.Filesystem.uperm\nBase.Filesystem.gperm\nBase.Filesystem.operm\nBase.Filesystem.cp\nBase.download\nBase.Filesystem.mv\nBase.Filesystem.rm\nBase.Filesystem.touch\nBase.Filesystem.tempname\nBase.Filesystem.tempdir\nBase.Filesystem.mktemp(::AbstractString)\nBase.Filesystem.mktemp(::Function, ::AbstractString)\nBase.Filesystem.mktempdir(::AbstractString)\nBase.Filesystem.mktempdir(::Function, ::AbstractString)\nBase.Filesystem.isblockdev\nBase.Filesystem.ischardev\nBase.Filesystem.isdir\nBase.Filesystem.isfifo\nBase.Filesystem.isfile\nBase.Filesystem.islink\nBase.Filesystem.ismount\nBase.Filesystem.ispath\nBase.Filesystem.issetgid\nBase.Filesystem.issetuid\nBase.Filesystem.issocket\nBase.Filesystem.issticky\nBase.Filesystem.homedir\nBase.Filesystem.dirname\nBase.Filesystem.basename\nBase.Filesystem.isabspath\nBase.Filesystem.isdirpath\nBase.Filesystem.joinpath\nBase.Filesystem.abspath\nBase.Filesystem.normpath\nBase.Filesystem.realpath\nBase.Filesystem.relpath\nBase.Filesystem.expanduser\nBase.Filesystem.splitdir\nBase.Filesystem.splitdrive\nBase.Filesystem.splitext\nBase.Filesystem.splitpath","category":"page"},{"location":"base/file/#Base.Filesystem.pwd","page":"文件系统","title":"Base.Filesystem.pwd","text":"pwd() -> AbstractString\n\nGet the current working directory.\n\nSee also: cd, tempdir.\n\nExamples\n\njulia> pwd()\n\"/home/JuliaUser\"\n\njulia> cd(\"/home/JuliaUser/Projects/julia\")\n\njulia> pwd()\n\"/home/JuliaUser/Projects/julia\"\n\n\n\n\n\n","category":"function"},{"location":"base/file/#Base.Filesystem.cd-Tuple{AbstractString}","page":"文件系统","title":"Base.Filesystem.cd","text":"cd(dir::AbstractString=homedir())\n\nSet the current working directory.\n\nSee also: pwd, mkdir, mkpath, mktempdir.\n\nExamples\n\njulia> cd(\"/home/JuliaUser/Projects/julia\")\n\njulia> pwd()\n\"/home/JuliaUser/Projects/julia\"\n\njulia> cd()\n\njulia> pwd()\n\"/home/JuliaUser\"\n\n\n\n\n\n","category":"method"},{"location":"base/file/#Base.Filesystem.cd-Tuple{Function}","page":"文件系统","title":"Base.Filesystem.cd","text":"cd(f::Function, dir::AbstractString=homedir())\n\nTemporarily change the current working directory to dir, apply function f and finally return to the original directory.\n\nExamples\n\njulia> pwd()\n\"/home/JuliaUser\"\n\njulia> cd(readdir, \"/home/JuliaUser/Projects/julia\")\n34-element Array{String,1}:\n \".circleci\"\n \".freebsdci.sh\"\n \".git\"\n \".gitattributes\"\n \".github\"\n ⋮\n \"test\"\n \"ui\"\n \"usr\"\n \"usr-staging\"\n\njulia> pwd()\n\"/home/JuliaUser\"\n\n\n\n\n\n","category":"method"},{"location":"base/file/#Base.Filesystem.readdir","page":"文件系统","title":"Base.Filesystem.readdir","text":"readdir(dir::AbstractString=pwd();\n join::Bool = false,\n sort::Bool = true,\n) -> Vector{String}\n\nReturn the names in the directory dir or the current working directory if not given. When join is false, readdir returns just the names in the directory as is; when join is true, it returns joinpath(dir, name) for each name so that the returned strings are full paths. If you want to get absolute paths back, call readdir with an absolute directory path and join set to true.\n\nBy default, readdir sorts the list of names it returns. If you want to skip sorting the names and get them in the order that the file system lists them, you can use readdir(dir, sort=false) to opt out of sorting.\n\ncompat: Julia 1.4\nThe join and sort keyword arguments require at least Julia 1.4.\n\nExamples\n\njulia> cd(\"/home/JuliaUser/dev/julia\")\n\njulia> readdir()\n30-element Array{String,1}:\n \".appveyor.yml\"\n \".git\"\n \".gitattributes\"\n ⋮\n \"ui\"\n \"usr\"\n \"usr-staging\"\n\njulia> readdir(join=true)\n30-element Array{String,1}:\n \"/home/JuliaUser/dev/julia/.appveyor.yml\"\n \"/home/JuliaUser/dev/julia/.git\"\n \"/home/JuliaUser/dev/julia/.gitattributes\"\n ⋮\n \"/home/JuliaUser/dev/julia/ui\"\n \"/home/JuliaUser/dev/julia/usr\"\n \"/home/JuliaUser/dev/julia/usr-staging\"\n\njulia> readdir(\"base\")\n145-element Array{String,1}:\n \".gitignore\"\n \"Base.jl\"\n \"Enums.jl\"\n ⋮\n \"version_git.sh\"\n \"views.jl\"\n \"weakkeydict.jl\"\n\njulia> readdir(\"base\", join=true)\n145-element Array{String,1}:\n \"base/.gitignore\"\n \"base/Base.jl\"\n \"base/Enums.jl\"\n ⋮\n \"base/version_git.sh\"\n \"base/views.jl\"\n \"base/weakkeydict.jl\"```\n\njulia> readdir(abspath(\"base\"), join=true)\n145-element Array{String,1}:\n \"/home/JuliaUser/dev/julia/base/.gitignore\"\n \"/home/JuliaUser/dev/julia/base/Base.jl\"\n \"/home/JuliaUser/dev/julia/base/Enums.jl\"\n ⋮\n \"/home/JuliaUser/dev/julia/base/version_git.sh\"\n \"/home/JuliaUser/dev/julia/base/views.jl\"\n \"/home/JuliaUser/dev/julia/base/weakkeydict.jl\"\n\n\n\n\n\n","category":"function"},{"location":"base/file/#Base.Filesystem.walkdir","page":"文件系统","title":"Base.Filesystem.walkdir","text":"walkdir(dir; topdown=true, follow_symlinks=false, onerror=throw)\n\nReturn an iterator that walks the directory tree of a directory. The iterator returns a tuple containing (rootpath, dirs, files). The directory tree can be traversed top-down or bottom-up. If walkdir or stat encounters a IOError it will rethrow the error by default. A custom error handling function can be provided through onerror keyword argument. onerror is called with a IOError as argument.\n\nExamples\n\nfor (root, dirs, files) in walkdir(\".\")\n println(\"Directories in $root\")\n for dir in dirs\n println(joinpath(root, dir)) # path to directories\n end\n println(\"Files in $root\")\n for file in files\n println(joinpath(root, file)) # path to files\n end\nend\n\njulia> mkpath(\"my/test/dir\");\n\njulia> itr = walkdir(\"my\");\n\njulia> (root, dirs, files) = first(itr)\n(\"my\", [\"test\"], String[])\n\njulia> (root, dirs, files) = first(itr)\n(\"my/test\", [\"dir\"], String[])\n\njulia> (root, dirs, files) = first(itr)\n(\"my/test/dir\", String[], String[])\n\n\n\n\n\n","category":"function"},{"location":"base/file/#Base.Filesystem.mkdir","page":"文件系统","title":"Base.Filesystem.mkdir","text":"mkdir(path::AbstractString; mode::Unsigned = 0o777)\n\nMake a new directory with name path and permissions mode. mode defaults to 0o777, modified by the current file creation mask. This function never creates more than one directory. If the directory already exists, or some intermediate directories do not exist, this function throws an error. See mkpath for a function which creates all required intermediate directories. Return path.\n\nExamples\n\njulia> mkdir(\"testingdir\")\n\"testingdir\"\n\njulia> cd(\"testingdir\")\n\njulia> pwd()\n\"/home/JuliaUser/testingdir\"\n\n\n\n\n\n","category":"function"},{"location":"base/file/#Base.Filesystem.mkpath","page":"文件系统","title":"Base.Filesystem.mkpath","text":"mkpath(path::AbstractString; mode::Unsigned = 0o777)\n\nCreate all intermediate directories in the path as required. Directories are created with the permissions mode which defaults to 0o777 and is modified by the current file creation mask. Unlike mkdir, mkpath does not error if path (or parts of it) already exists. However, an error will be thrown if path (or parts of it) points to an existing file. Return path.\n\nIf path includes a filename you will probably want to use mkpath(dirname(path)) to avoid creating a directory using the filename.\n\nExamples\n\njulia> cd(mktempdir())\n\njulia> mkpath(\"my/test/dir\") # creates three directories\n\"my/test/dir\"\n\njulia> readdir()\n1-element Array{String,1}:\n \"my\"\n\njulia> cd(\"my\")\n\njulia> readdir()\n1-element Array{String,1}:\n \"test\"\n\njulia> readdir(\"test\")\n1-element Array{String,1}:\n \"dir\"\n\njulia> mkpath(\"intermediate_dir/actually_a_directory.txt\") # creates two directories\n\"intermediate_dir/actually_a_directory.txt\"\n\njulia> isdir(\"intermediate_dir/actually_a_directory.txt\")\ntrue\n\n\n\n\n\n\n","category":"function"},{"location":"base/file/#Base.Filesystem.symlink","page":"文件系统","title":"Base.Filesystem.symlink","text":"symlink(target::AbstractString, link::AbstractString; dir_target = false)\n\nCreates a symbolic link to target with the name link.\n\nOn Windows, symlinks must be explicitly declared as referring to a directory or not. If target already exists, by default the type of link will be auto- detected, however if target does not exist, this function defaults to creating a file symlink unless dir_target is set to true. Note that if the user sets dir_target but target exists and is a file, a directory symlink will still be created, but dereferencing the symlink will fail, just as if the user creates a file symlink (by calling symlink() with dir_target set to false before the directory is created) and tries to dereference it to a directory.\n\nAdditionally, there are two methods of making a link on Windows; symbolic links and junction points. Junction points are slightly more efficient, but do not support relative paths, so if a relative directory symlink is requested (as denoted by isabspath(target) returning false) a symlink will be used, else a junction point will be used. Best practice for creating symlinks on Windows is to create them only after the files/directories they reference are already created.\n\nSee also: hardlink.\n\nnote: Note\nThis function raises an error under operating systems that do not support soft symbolic links, such as Windows XP.\n\ncompat: Julia 1.6\nThe dir_target keyword argument was added in Julia 1.6. Prior to this, symlinks to nonexistant paths on windows would always be file symlinks, and relative symlinks to directories were not supported.\n\n\n\n\n\n","category":"function"},{"location":"base/file/#Base.Filesystem.readlink","page":"文件系统","title":"Base.Filesystem.readlink","text":"readlink(path::AbstractString) -> AbstractString\n\nReturn the target location a symbolic link path points to.\n\n\n\n\n\n","category":"function"},{"location":"base/file/#Base.Filesystem.chmod","page":"文件系统","title":"Base.Filesystem.chmod","text":"chmod(path::AbstractString, mode::Integer; recursive::Bool=false)\n\nChange the permissions mode of path to mode. Only integer modes (e.g. 0o777) are currently supported. If recursive=true and the path is a directory all permissions in that directory will be recursively changed. Return path.\n\nnote: Note\nPrior to Julia 1.6, this did not correctly manipulate filesystem ACLs on Windows, therefore it would only set read-only bits on files. It now is able to manipulate ACLs.\n\n\n\n\n\n","category":"function"},{"location":"base/file/#Base.Filesystem.chown","page":"文件系统","title":"Base.Filesystem.chown","text":"chown(path::AbstractString, owner::Integer, group::Integer=-1)\n\nChange the owner and/or group of path to owner and/or group. If the value entered for owner or group is -1 the corresponding ID will not change. Only integer owners and groups are currently supported. Return path.\n\n\n\n\n\n","category":"function"},{"location":"base/file/#Base.Libc.RawFD","page":"文件系统","title":"Base.Libc.RawFD","text":"RawFD\n\nPrimitive type which wraps the native OS file descriptor. RawFDs can be passed to methods like stat to discover information about the underlying file, and can also be used to open streams, with the RawFD describing the OS file backing the stream.\n\n\n\n\n\n","category":"type"},{"location":"base/file/#Base.stat","page":"文件系统","title":"Base.stat","text":"stat(file)\n\nReturns a structure whose fields contain information about the file. The fields of the structure are:\n\nName Description\ndesc The path or OS file descriptor\nsize The size (in bytes) of the file\ndevice ID of the device that contains the file\ninode The inode number of the file\nmode The protection mode of the file\nnlink The number of hard links to the file\nuid The user id of the owner of the file\ngid The group id of the file owner\nrdev If this file refers to a device, the ID of the device it refers to\nblksize The file-system preferred block size for the file\nblocks The number of such blocks allocated\nmtime Unix timestamp of when the file was last modified\nctime Unix timestamp of when the file's metadata was changed\n\n\n\n\n\n","category":"function"},{"location":"base/file/#Base.Filesystem.lstat","page":"文件系统","title":"Base.Filesystem.lstat","text":"lstat(file)\n\nLike stat, but for symbolic links gets the info for the link itself rather than the file it refers to. This function must be called on a file path rather than a file object or a file descriptor.\n\n\n\n\n\n","category":"function"},{"location":"base/file/#Base.Filesystem.ctime","page":"文件系统","title":"Base.Filesystem.ctime","text":"ctime(file)\n\nEquivalent to stat(file).ctime.\n\n\n\n\n\n","category":"function"},{"location":"base/file/#Base.Filesystem.mtime","page":"文件系统","title":"Base.Filesystem.mtime","text":"mtime(file)\n\nEquivalent to stat(file).mtime.\n\n\n\n\n\n","category":"function"},{"location":"base/file/#Base.Filesystem.filemode","page":"文件系统","title":"Base.Filesystem.filemode","text":"filemode(file)\n\nEquivalent to stat(file).mode.\n\n\n\n\n\n","category":"function"},{"location":"base/file/#Base.filesize","page":"文件系统","title":"Base.filesize","text":"filesize(path...)\n\nEquivalent to stat(file).size.\n\n\n\n\n\n","category":"function"},{"location":"base/file/#Base.Filesystem.uperm","page":"文件系统","title":"Base.Filesystem.uperm","text":"uperm(file)\n\nGet the permissions of the owner of the file as a bitfield of\n\nValue Description\n01 Execute Permission\n02 Write Permission\n04 Read Permission\n\nFor allowed arguments, see stat.\n\n\n\n\n\n","category":"function"},{"location":"base/file/#Base.Filesystem.gperm","page":"文件系统","title":"Base.Filesystem.gperm","text":"gperm(file)\n\nLike uperm but gets the permissions of the group owning the file.\n\n\n\n\n\n","category":"function"},{"location":"base/file/#Base.Filesystem.operm","page":"文件系统","title":"Base.Filesystem.operm","text":"operm(file)\n\nLike uperm but gets the permissions for people who neither own the file nor are a member of the group owning the file\n\n\n\n\n\n","category":"function"},{"location":"base/file/#Base.Filesystem.cp","page":"文件系统","title":"Base.Filesystem.cp","text":"cp(src::AbstractString, dst::AbstractString; force::Bool=false, follow_symlinks::Bool=false)\n\nCopy the file, link, or directory from src to dst. force=true will first remove an existing dst.\n\nIf follow_symlinks=false, and src is a symbolic link, dst will be created as a symbolic link. If follow_symlinks=true and src is a symbolic link, dst will be a copy of the file or directory src refers to. Return dst.\n\nnote: Note\nThe cp function is different from the cp command. The cp function always operates on the assumption that dst is a file, while the command does different things depending on whether dst is a directory or a file. Using force=true when dst is a directory will result in loss of all the contents present in the dst directory, and dst will become a file that has the contents of src instead.\n\n\n\n\n\n","category":"function"},{"location":"base/file/#Base.download","page":"文件系统","title":"Base.download","text":"download(url::AbstractString, [path::AbstractString = tempname()]) -> path\n\nDownload a file from the given url, saving it to the location path, or if not specified, a temporary path. Returns the path of the downloaded file.\n\nnote: Note\nSince Julia 1.6, this function is deprecated and is just a thin wrapper around Downloads.download. In new code, you should use that function directly instead of calling this.\n\n\n\n\n\n","category":"function"},{"location":"base/file/#Base.Filesystem.mv","page":"文件系统","title":"Base.Filesystem.mv","text":"mv(src::AbstractString, dst::AbstractString; force::Bool=false)\n\nMove the file, link, or directory from src to dst. force=true will first remove an existing dst. Return dst.\n\nExamples\n\njulia> write(\"hello.txt\", \"world\");\n\njulia> mv(\"hello.txt\", \"goodbye.txt\")\n\"goodbye.txt\"\n\njulia> \"hello.txt\" in readdir()\nfalse\n\njulia> readline(\"goodbye.txt\")\n\"world\"\n\njulia> write(\"hello.txt\", \"world2\");\n\njulia> mv(\"hello.txt\", \"goodbye.txt\")\nERROR: ArgumentError: 'goodbye.txt' exists. `force=true` is required to remove 'goodbye.txt' before moving.\nStacktrace:\n [1] #checkfor_mv_cp_cptree#10(::Bool, ::Function, ::String, ::String, ::String) at ./file.jl:293\n[...]\n\njulia> mv(\"hello.txt\", \"goodbye.txt\", force=true)\n\"goodbye.txt\"\n\njulia> rm(\"goodbye.txt\");\n\n\n\n\n\n\n","category":"function"},{"location":"base/file/#Base.Filesystem.rm","page":"文件系统","title":"Base.Filesystem.rm","text":"rm(path::AbstractString; force::Bool=false, recursive::Bool=false)\n\nDelete the file, link, or empty directory at the given path. If force=true is passed, a non-existing path is not treated as error. If recursive=true is passed and the path is a directory, then all contents are removed recursively.\n\nExamples\n\njulia> mkpath(\"my/test/dir\");\n\njulia> rm(\"my\", recursive=true)\n\njulia> rm(\"this_file_does_not_exist\", force=true)\n\njulia> rm(\"this_file_does_not_exist\")\nERROR: IOError: unlink(\"this_file_does_not_exist\"): no such file or directory (ENOENT)\nStacktrace:\n[...]\n\n\n\n\n\n","category":"function"},{"location":"base/file/#Base.Filesystem.touch","page":"文件系统","title":"Base.Filesystem.touch","text":"touch(path::AbstractString)\n\nUpdate the last-modified timestamp on a file to the current time.\n\nIf the file does not exist a new file is created.\n\nReturn path.\n\nExamples\n\njulia> write(\"my_little_file\", 2);\n\njulia> mtime(\"my_little_file\")\n1.5273815391135583e9\n\njulia> touch(\"my_little_file\");\n\njulia> mtime(\"my_little_file\")\n1.527381559163435e9\n\nWe can see the mtime has been modified by touch.\n\n\n\n\n\n","category":"function"},{"location":"base/file/#Base.Filesystem.tempname","page":"文件系统","title":"Base.Filesystem.tempname","text":"tempname(parent=tempdir(); cleanup=true) -> String\n\nGenerate a temporary file path. This function only returns a path; no file is created. The path is likely to be unique, but this cannot be guaranteed due to the very remote posibility of two simultaneous calls to tempname generating the same file name. The name is guaranteed to differ from all files already existing at the time of the call to tempname.\n\nWhen called with no arguments, the temporary name will be an absolute path to a temporary name in the system temporary directory as given by tempdir(). If a parent directory argument is given, the temporary path will be in that directory instead.\n\nThe cleanup option controls whether the process attempts to delete the returned path automatically when the process exits. Note that the tempname function does not create any file or directory at the returned location, so there is nothing to cleanup unless you create a file or directory there. If you do and clean is true it will be deleted upon process termination.\n\ncompat: Julia 1.4\nThe parent and cleanup arguments were added in 1.4. Prior to Julia 1.4 the path tempname would never be cleaned up at process termination.\n\nwarning: Warning\nThis can lead to security holes if another process obtains the same file name and creates the file before you are able to. Open the file with JL_O_EXCL if this is a concern. Using mktemp() is also recommended instead.\n\n\n\n\n\n","category":"function"},{"location":"base/file/#Base.Filesystem.tempdir","page":"文件系统","title":"Base.Filesystem.tempdir","text":"tempdir()\n\nGets the path of the temporary directory. On Windows, tempdir() uses the first environment variable found in the ordered list TMP, TEMP, USERPROFILE. On all other operating systems, tempdir() uses the first environment variable found in the ordered list TMPDIR, TMP, TEMP, and TEMPDIR. If none of these are found, the path \"/tmp\" is used.\n\n\n\n\n\n","category":"function"},{"location":"base/file/#Base.Filesystem.mktemp-Tuple{AbstractString}","page":"文件系统","title":"Base.Filesystem.mktemp","text":"mktemp(parent=tempdir(); cleanup=true) -> (path, io)\n\nReturn (path, io), where path is the path of a new temporary file in parent and io is an open file object for this path. The cleanup option controls whether the temporary file is automatically deleted when the process exits.\n\ncompat: Julia 1.3\nThe cleanup keyword argument was added in Julia 1.3. Relatedly, starting from 1.3, Julia will remove the temporary paths created by mktemp when the Julia process exits, unless cleanup is explicitly set to false.\n\n\n\n\n\n","category":"method"},{"location":"base/file/#Base.Filesystem.mktemp-Tuple{Function, AbstractString}","page":"文件系统","title":"Base.Filesystem.mktemp","text":"mktemp(f::Function, parent=tempdir())\n\nApply the function f to the result of mktemp(parent) and remove the temporary file upon completion.\n\nSee also: mktempdir.\n\n\n\n\n\n","category":"method"},{"location":"base/file/#Base.Filesystem.mktempdir-Tuple{AbstractString}","page":"文件系统","title":"Base.Filesystem.mktempdir","text":"mktempdir(parent=tempdir(); prefix=\"jl_\", cleanup=true) -> path\n\nCreate a temporary directory in the parent directory with a name constructed from the given prefix and a random suffix, and return its path. Additionally, any trailing X characters may be replaced with random characters. If parent does not exist, throw an error. The cleanup option controls whether the temporary directory is automatically deleted when the process exits.\n\ncompat: Julia 1.2\nThe prefix keyword argument was added in Julia 1.2.\n\ncompat: Julia 1.3\nThe cleanup keyword argument was added in Julia 1.3. Relatedly, starting from 1.3, Julia will remove the temporary paths created by mktempdir when the Julia process exits, unless cleanup is explicitly set to false.\n\nSee also: mktemp, mkdir.\n\n\n\n\n\n","category":"method"},{"location":"base/file/#Base.Filesystem.mktempdir-Tuple{Function, AbstractString}","page":"文件系统","title":"Base.Filesystem.mktempdir","text":"mktempdir(f::Function, parent=tempdir(); prefix=\"jl_\")\n\nApply the function f to the result of mktempdir(parent; prefix) and remove the temporary directory all of its contents upon completion.\n\nSee also: mktemp, mkdir.\n\ncompat: Julia 1.2\nThe prefix keyword argument was added in Julia 1.2.\n\n\n\n\n\n","category":"method"},{"location":"base/file/#Base.Filesystem.isblockdev","page":"文件系统","title":"Base.Filesystem.isblockdev","text":"isblockdev(path) -> Bool\n\nReturn true if path is a block device, false otherwise.\n\n\n\n\n\n","category":"function"},{"location":"base/file/#Base.Filesystem.ischardev","page":"文件系统","title":"Base.Filesystem.ischardev","text":"ischardev(path) -> Bool\n\nReturn true if path is a character device, false otherwise.\n\n\n\n\n\n","category":"function"},{"location":"base/file/#Base.Filesystem.isdir","page":"文件系统","title":"Base.Filesystem.isdir","text":"isdir(path) -> Bool\n\nReturn true if path is a directory, false otherwise.\n\nExamples\n\njulia> isdir(homedir())\ntrue\n\njulia> isdir(\"not/a/directory\")\nfalse\n\nSee also isfile and ispath.\n\n\n\n\n\n","category":"function"},{"location":"base/file/#Base.Filesystem.isfifo","page":"文件系统","title":"Base.Filesystem.isfifo","text":"isfifo(path) -> Bool\n\nReturn true if path is a FIFO, false otherwise.\n\n\n\n\n\n","category":"function"},{"location":"base/file/#Base.Filesystem.isfile","page":"文件系统","title":"Base.Filesystem.isfile","text":"isfile(path) -> Bool\n\nReturn true if path is a regular file, false otherwise.\n\nExamples\n\njulia> isfile(homedir())\nfalse\n\njulia> f = open(\"test_file.txt\", \"w\");\n\njulia> isfile(f)\ntrue\n\njulia> close(f); rm(\"test_file.txt\")\n\nSee also isdir and ispath.\n\n\n\n\n\n","category":"function"},{"location":"base/file/#Base.Filesystem.islink","page":"文件系统","title":"Base.Filesystem.islink","text":"islink(path) -> Bool\n\nReturn true if path is a symbolic link, false otherwise.\n\n\n\n\n\n","category":"function"},{"location":"base/file/#Base.Filesystem.ismount","page":"文件系统","title":"Base.Filesystem.ismount","text":"ismount(path) -> Bool\n\nReturn true if path is a mount point, false otherwise.\n\n\n\n\n\n","category":"function"},{"location":"base/file/#Base.Filesystem.ispath","page":"文件系统","title":"Base.Filesystem.ispath","text":"ispath(path) -> Bool\n\nReturn true if a valid filesystem entity exists at path, otherwise returns false. This is the generalization of isfile, isdir etc.\n\n\n\n\n\n","category":"function"},{"location":"base/file/#Base.Filesystem.issetgid","page":"文件系统","title":"Base.Filesystem.issetgid","text":"issetgid(path) -> Bool\n\nReturn true if path has the setgid flag set, false otherwise.\n\n\n\n\n\n","category":"function"},{"location":"base/file/#Base.Filesystem.issetuid","page":"文件系统","title":"Base.Filesystem.issetuid","text":"issetuid(path) -> Bool\n\nReturn true if path has the setuid flag set, false otherwise.\n\n\n\n\n\n","category":"function"},{"location":"base/file/#Base.Filesystem.issocket","page":"文件系统","title":"Base.Filesystem.issocket","text":"issocket(path) -> Bool\n\nReturn true if path is a socket, false otherwise.\n\n\n\n\n\n","category":"function"},{"location":"base/file/#Base.Filesystem.issticky","page":"文件系统","title":"Base.Filesystem.issticky","text":"issticky(path) -> Bool\n\nReturn true if path has the sticky bit set, false otherwise.\n\n\n\n\n\n","category":"function"},{"location":"base/file/#Base.Filesystem.homedir","page":"文件系统","title":"Base.Filesystem.homedir","text":"homedir() -> String\n\nReturn the current user's home directory.\n\nnote: Note\nhomedir determines the home directory via libuv's uv_os_homedir. For details (for example on how to specify the home directory via environment variables), see the uv_os_homedir documentation.\n\n\n\n\n\n","category":"function"},{"location":"base/file/#Base.Filesystem.dirname","page":"文件系统","title":"Base.Filesystem.dirname","text":"dirname(path::AbstractString) -> AbstractString\n\nGet the directory part of a path. Trailing characters ('/' or '\\') in the path are counted as part of the path.\n\nExamples\n\njulia> dirname(\"/home/myuser\")\n\"/home\"\n\njulia> dirname(\"/home/myuser/\")\n\"/home/myuser\"\n\nSee also basename.\n\n\n\n\n\n","category":"function"},{"location":"base/file/#Base.Filesystem.basename","page":"文件系统","title":"Base.Filesystem.basename","text":"basename(path::AbstractString) -> AbstractString\n\nGet the file name part of a path.\n\nnote: Note\nThis function differs slightly from the Unix basename program, where trailing slashes are ignored, i.e. $ basename /foo/bar/ returns bar, whereas basename in Julia returns an empty string \"\".\n\nExamples\n\njulia> basename(\"/home/myuser/example.jl\")\n\"example.jl\"\n\njulia> basename(\"/home/myuser/\")\n\"\"\n\nSee also dirname.\n\n\n\n\n\n","category":"function"},{"location":"base/file/#Base.Filesystem.isabspath","page":"文件系统","title":"Base.Filesystem.isabspath","text":"isabspath(path::AbstractString) -> Bool\n\nDetermine whether a path is absolute (begins at the root directory).\n\nExamples\n\njulia> isabspath(\"/home\")\ntrue\n\njulia> isabspath(\"home\")\nfalse\n\n\n\n\n\n","category":"function"},{"location":"base/file/#Base.Filesystem.isdirpath","page":"文件系统","title":"Base.Filesystem.isdirpath","text":"isdirpath(path::AbstractString) -> Bool\n\nDetermine whether a path refers to a directory (for example, ends with a path separator).\n\nExamples\n\njulia> isdirpath(\"/home\")\nfalse\n\njulia> isdirpath(\"/home/\")\ntrue\n\n\n\n\n\n","category":"function"},{"location":"base/file/#Base.Filesystem.joinpath","page":"文件系统","title":"Base.Filesystem.joinpath","text":"joinpath(parts::AbstractString...) -> String\njoinpath(parts::Vector{AbstractString}) -> String\njoinpath(parts::Tuple{AbstractString}) -> String\n\nJoin path components into a full path. If some argument is an absolute path or (on Windows) has a drive specification that doesn't match the drive computed for the join of the preceding paths, then prior components are dropped.\n\nNote on Windows since there is a current directory for each drive, joinpath(\"c:\", \"foo\") represents a path relative to the current directory on drive \"c:\" so this is equal to \"c:foo\", not \"c:\\foo\". Furthermore, joinpath treats this as a non-absolute path and ignores the drive letter casing, hence joinpath(\"C:\\A\",\"c:b\") = \"C:\\A\\b\".\n\nExamples\n\njulia> joinpath(\"/home/myuser\", \"example.jl\")\n\"/home/myuser/example.jl\"\n\njulia> joinpath([\"/home/myuser\", \"example.jl\"])\n\"/home/myuser/example.jl\"\n\n\n\n\n\n","category":"function"},{"location":"base/file/#Base.Filesystem.abspath","page":"文件系统","title":"Base.Filesystem.abspath","text":"abspath(path::AbstractString) -> String\n\nConvert a path to an absolute path by adding the current directory if necessary. Also normalizes the path as in normpath.\n\n\n\n\n\nabspath(path::AbstractString, paths::AbstractString...) -> String\n\nConvert a set of paths to an absolute path by joining them together and adding the current directory if necessary. Equivalent to abspath(joinpath(path, paths...)).\n\n\n\n\n\n","category":"function"},{"location":"base/file/#Base.Filesystem.normpath","page":"文件系统","title":"Base.Filesystem.normpath","text":"normpath(path::AbstractString) -> String\n\nNormalize a path, removing \".\" and \"..\" entries and changing \"/\" to the canonical path separator for the system.\n\nExamples\n\njulia> normpath(\"/home/myuser/../example.jl\")\n\"/home/example.jl\"\n\njulia> normpath(\"Documents/Julia\") == joinpath(\"Documents\", \"Julia\")\ntrue\n\n\n\n\n\nnormpath(path::AbstractString, paths::AbstractString...) -> String\n\nConvert a set of paths to a normalized path by joining them together and removing \".\" and \"..\" entries. Equivalent to normpath(joinpath(path, paths...)).\n\n\n\n\n\n","category":"function"},{"location":"base/file/#Base.Filesystem.realpath","page":"文件系统","title":"Base.Filesystem.realpath","text":"realpath(path::AbstractString) -> String\n\nCanonicalize a path by expanding symbolic links and removing \".\" and \"..\" entries. On case-insensitive case-preserving filesystems (typically Mac and Windows), the filesystem's stored case for the path is returned.\n\n(This function throws an exception if path does not exist in the filesystem.)\n\n\n\n\n\n","category":"function"},{"location":"base/file/#Base.Filesystem.relpath","page":"文件系统","title":"Base.Filesystem.relpath","text":"relpath(path::AbstractString, startpath::AbstractString = \".\") -> AbstractString\n\nReturn a relative filepath to path either from the current directory or from an optional start directory. This is a path computation: the filesystem is not accessed to confirm the existence or nature of path or startpath.\n\nOn Windows, case sensitivity is applied to every part of the path except drive letters. If path and startpath refer to different drives, the absolute path of path is returned.\n\n\n\n\n\n","category":"function"},{"location":"base/file/#Base.Filesystem.expanduser","page":"文件系统","title":"Base.Filesystem.expanduser","text":"expanduser(path::AbstractString) -> AbstractString\n\nOn Unix systems, replace a tilde character at the start of a path with the current user's home directory.\n\n\n\n\n\n","category":"function"},{"location":"base/file/#Base.Filesystem.splitdir","page":"文件系统","title":"Base.Filesystem.splitdir","text":"splitdir(path::AbstractString) -> (AbstractString, AbstractString)\n\nSplit a path into a tuple of the directory name and file name.\n\nExamples\n\njulia> splitdir(\"/home/myuser\")\n(\"/home\", \"myuser\")\n\n\n\n\n\n","category":"function"},{"location":"base/file/#Base.Filesystem.splitdrive","page":"文件系统","title":"Base.Filesystem.splitdrive","text":"splitdrive(path::AbstractString) -> (AbstractString, AbstractString)\n\nOn Windows, split a path into the drive letter part and the path part. On Unix systems, the first component is always the empty string.\n\n\n\n\n\n","category":"function"},{"location":"base/file/#Base.Filesystem.splitext","page":"文件系统","title":"Base.Filesystem.splitext","text":"splitext(path::AbstractString) -> (AbstractString, AbstractString)\n\nIf the last component of a path contains one or more dots, split the path into everything before the last dot and everything including and after the dot. Otherwise, return a tuple of the argument unmodified and the empty string. \"splitext\" is short for \"split extension\".\n\nExamples\n\njulia> splitext(\"/home/myuser/example.jl\")\n(\"/home/myuser/example\", \".jl\")\n\njulia> splitext(\"/home/myuser/example.tar.gz\")\n(\"/home/myuser/example.tar\", \".gz\")\n\njulia> splitext(\"/home/my.user/example\")\n(\"/home/my.user/example\", \"\")\n\n\n\n\n\n","category":"function"},{"location":"base/file/#Base.Filesystem.splitpath","page":"文件系统","title":"Base.Filesystem.splitpath","text":"splitpath(path::AbstractString) -> Vector{String}\n\nSplit a file path into all its path components. This is the opposite of joinpath. Returns an array of substrings, one for each directory or file in the path, including the root directory if present.\n\ncompat: Julia 1.1\nThis function requires at least Julia 1.1.\n\nExamples\n\njulia> splitpath(\"/home/myuser/example.jl\")\n4-element Vector{String}:\n \"/\"\n \"home\"\n \"myuser\"\n \"example.jl\"\n\n\n\n\n\n","category":"function"},{"location":"manual/functions/#man-functions","page":"函数","title":"函数","text":"","category":"section"},{"location":"manual/functions/","page":"函数","title":"函数","text":"在 Julia 里,函数是将参数值组成的元组映射到返回值的一个对象。Julia 的函数不是纯粹的数学函数,因为这些函数可以改变程序的全局状态并且可能受其影响。在Julia中定义函数的基本语法是:","category":"page"},{"location":"manual/functions/","page":"函数","title":"函数","text":"julia> function f(x,y)\n x + y\n end\nf (generic function with 1 method)","category":"page"},{"location":"manual/functions/","page":"函数","title":"函数","text":"这个函数接收两个参数 x 和 y 并返回最后一个表达式的值,这里是 x + y。","category":"page"},{"location":"manual/functions/","page":"函数","title":"函数","text":"在 Julia 中定义函数还有第二种更简洁的语法。上述的传统函数声明语法等效于以下紧凑性的“赋值形式”:","category":"page"},{"location":"manual/functions/","page":"函数","title":"函数","text":"julia> f(x,y) = x + y\nf (generic function with 1 method)","category":"page"},{"location":"manual/functions/","page":"函数","title":"函数","text":"尽管函数可以是复合表达式 (见 复合表达式),但在赋值形式下,函数体必须是一个一行的表达式。简短的函数定义在 Julia 中是很常见的。非常惯用的短函数语法大大减少了打字和视觉方面的干扰。","category":"page"},{"location":"manual/functions/","page":"函数","title":"函数","text":"使用传统的括号语法调用函数:","category":"page"},{"location":"manual/functions/","page":"函数","title":"函数","text":"julia> f(2,3)\n5","category":"page"},{"location":"manual/functions/","page":"函数","title":"函数","text":"没有括号时,表达式 f 指的是函数对象,可以像任何值一样被传递:","category":"page"},{"location":"manual/functions/","page":"函数","title":"函数","text":"julia> g = f;\n\njulia> g(2,3)\n5","category":"page"},{"location":"manual/functions/","page":"函数","title":"函数","text":"和变量名一样,Unicode 字符也可以用作函数名:","category":"page"},{"location":"manual/functions/","page":"函数","title":"函数","text":"julia> ∑(x,y) = x + y\n∑ (generic function with 1 method)\n\njulia> ∑(2, 3)\n5","category":"page"},{"location":"manual/functions/#参数传递行为","page":"函数","title":"参数传递行为","text":"","category":"section"},{"location":"manual/functions/","page":"函数","title":"函数","text":"Julia 函数参数遵循有时称为 “pass-by-sharing” 的约定,这意味着变量在被传递给函数时其值并不会被复制。函数参数本身充当新的变量绑定(指向变量值的新地址),它们所指向的值与所传递变量的值完全相同。调用者可以看到对函数内可变值(如数组)的修改。这与 Scheme,大多数 Lisps,Python,Ruby 和 Perl 以及其他动态语言中的行为相同。","category":"page"},{"location":"manual/functions/#参数类型声明","page":"函数","title":"参数类型声明","text":"","category":"section"},{"location":"manual/functions/","page":"函数","title":"函数","text":"您可以通过将 ::TypeName 附加到参数名称来声明函数参数的类型,就像 Julia 中的 类型声明 一样。 例如,以下函数递归计算 斐波那契数列:","category":"page"},{"location":"manual/functions/","page":"函数","title":"函数","text":"fib(n::Integer) = n ≤ 2 ? one(n) : fib(n-1) + fib(n-2)","category":"page"},{"location":"manual/functions/","page":"函数","title":"函数","text":"并且 ::Integer 规范意味着它只有在 n 是 抽象 Integer 类型的子类型时才可调用。","category":"page"},{"location":"manual/functions/","page":"函数","title":"函数","text":"参数类型声明通常对性能没有影响:无论声明什么参数类型(如果有),Julia 都会为实际参数类型编译函数的特例版本。 例如,调用 fib(1) 将触发专门为 Int 参数优化的特例化的fib 的编译,它会在 fib(7) 或 fib(15) 调用时重新使用。 (参数类型声明不触发额外的编译器特化的情况很少;请参阅:注意 Julia 何时不触发特例化。)在 Julia 中声明参数类型的最常见原因是:","category":"page"},{"location":"manual/functions/","page":"函数","title":"函数","text":"派发: 如 方法 中所述,对于不同的参数类型,你可以有不同版本(“方法”)的函数,在这种情况下,参数类型用于确定调用哪个版本的函数。例如,你可以使用 Binet 公式 实现一个完全不同的算法 fib(x::Number) = ...,该算法扩展为了非整数值,适用于任何 Number 类型。\n正确性: 如果函数只为某些参数类型返回正确的结果,则类型声明会很有用。例如,如果我们省略参数类型并写成 fib(n) = n ≤ 2 ? one(n) : fib(n-1) + fib(n-2),然后fib(1.5)会默默地给我们无意义的答案1.0。\n清晰性: 类型声明可以作为一种关于预期参数的文档形式。","category":"page"},{"location":"manual/functions/","page":"函数","title":"函数","text":"但是,过分限制参数类型是常见的错误,这会不必要地限制函数的适用性,并防止它在未预料到的情况下被重用。例如,上面的 fib(n::Integer) 函数同样适用于 Int 参数(机器整数)和 BigInt 任意精度整数(参见 BigFloats 和 BigInts),这样十分有效,因为斐波那契数以指数方式快速增长,并且会迅速溢出任何固定精度类型,如 Int(参见 溢出行为)。但是,如果我们将函数声明为 fib(n::Int),那么 BigInt 的应用就会被阻止。通常,应该对参数使用最通用的适用抽象类型,并且如有不确定,就省略参数类型。如果有必要,你可以随时添加参数类型规范,并且不会因为省略它们而牺牲性能或功能。","category":"page"},{"location":"manual/functions/#return-关键字","page":"函数","title":"return 关键字","text":"","category":"section"},{"location":"manual/functions/","page":"函数","title":"函数","text":"函数返回的值是最后计算的表达式的值,默认情况下,它是函数定义主体中的最后一个表达式。在上一小节的示例函数 f 中,返回值是表达式的 x + y 值。与在 C 语言和大多数其他命令式或函数式语言中一样,return 关键字会让函数立即返回,从而提供返回值的表达式:","category":"page"},{"location":"manual/functions/","page":"函数","title":"函数","text":"function g(x,y)\n return x * y\n x + y\nend","category":"page"},{"location":"manual/functions/","page":"函数","title":"函数","text":"由于函数定义可以输入到交互式会话中,因此可以很容易的比较这些定义:","category":"page"},{"location":"manual/functions/","page":"函数","title":"函数","text":"julia> f(x,y) = x + y\nf (generic function with 1 method)\n\njulia> function g(x,y)\n return x * y\n x + y\n end\ng (generic function with 1 method)\n\njulia> f(2,3)\n5\n\njulia> g(2,3)\n6","category":"page"},{"location":"manual/functions/","page":"函数","title":"函数","text":"当然,在一个单纯的线性执行的函数体内,例如 g,使用 return 是没有意义的,因为表达式 x + y 永远不会被执行到,我们可以简单地把 x * y 写为最后一个表达式从而省略掉 return。 然而在使用其他控制流程的函数体内,return 却是有用的。 例如,在计算两条边长分别为 x 和 y 的三角形的斜边长度时可以避免溢出:","category":"page"},{"location":"manual/functions/","page":"函数","title":"函数","text":"julia> function hypot(x,y)\n x = abs(x)\n y = abs(y)\n if x > y\n r = y/x\n return x*sqrt(1+r*r)\n end\n if y == 0\n return zero(x)\n end\n r = x/y\n return y*sqrt(1+r*r)\n end\nhypot (generic function with 1 method)\n\njulia> hypot(3, 4)\n5.0","category":"page"},{"location":"manual/functions/","page":"函数","title":"函数","text":"这个函数有三个可能的返回处,返回三个不同表达式的值,具体取决于 x 和 y 的值。 最后一行的 return 可以省略,因为它是最后一个表达式。","category":"page"},{"location":"manual/functions/#返回类型","page":"函数","title":"返回类型","text":"","category":"section"},{"location":"manual/functions/","page":"函数","title":"函数","text":"也可以使用 :: 运算符在函数声明中指定返回类型。 这可以将返回值转换为指定的类型。","category":"page"},{"location":"manual/functions/","page":"函数","title":"函数","text":"julia> function g(x, y)::Int8\n return x * y\n end;\n\njulia> typeof(g(1, 2))\nInt8","category":"page"},{"location":"manual/functions/","page":"函数","title":"函数","text":"这个函数将忽略 x 和 y 的类型,返回 Int8 类型的值。有关返回类型的更多信息,请参见类型声明。","category":"page"},{"location":"manual/functions/","page":"函数","title":"函数","text":"返回类型声明在 Julia 中很少使用:通常,你应该编写“类型稳定”的函数,Julia 的编译器可以在其中自动推断返回类型。更多信息请参阅 性能提示 一章。","category":"page"},{"location":"manual/functions/#返回-nothing","page":"函数","title":"返回 nothing","text":"","category":"section"},{"location":"manual/functions/","page":"函数","title":"函数","text":"对于不需要任何返回值的函数(只用来产生副作用的函数), Julia 中的写法为返回值nothing:","category":"page"},{"location":"manual/functions/","page":"函数","title":"函数","text":"function printx(x)\n println(\"x = $x\")\n return nothing\nend","category":"page"},{"location":"manual/functions/","page":"函数","title":"函数","text":"这在某种意义上是一个“惯例”,在 Julia 中 nothing 不是一个关键字,而是 Nothing 类型的一个单例(singleton)。 也许你已经注意到 printx 函数有点不自然,因为 println 实际上已经会返回 nothing,所以 return 语句是多余的。","category":"page"},{"location":"manual/functions/","page":"函数","title":"函数","text":"有两种比 return nothing 更短的写法:一种是直接写 return 这会隐式的返回 nothing。 另一种是在函数的会后一行写上 nothing,因为函数会隐式的返回最后一个表达式的值。 三种写法使用哪一种取决于代码风格的偏好。","category":"page"},{"location":"manual/functions/#操作符也是函数","page":"函数","title":"操作符也是函数","text":"","category":"section"},{"location":"manual/functions/","page":"函数","title":"函数","text":"在 Julia中,大多数操作符只不过是支持特殊语法的函数( && 和|| 等具有特殊评估语义的操作符除外,他们不能是函数,因为短路求值要求在计算整个表达式的值之前不计算每个操作数)。因此,您也可以使用带括号的参数列表来使用它们,就和任何其他函数一样:","category":"page"},{"location":"manual/functions/","page":"函数","title":"函数","text":"julia> 1 + 2 + 3\n6\n\njulia> +(1,2,3)\n6","category":"page"},{"location":"manual/functions/","page":"函数","title":"函数","text":"中缀表达式和函数形式完全等价。—— 事实上,前一种形式会被编译器转换为函数调用。这也意味着你可以对操作符,例如 + 和 * ,进行赋值和传参,就像其它函数传参一样。","category":"page"},{"location":"manual/functions/","page":"函数","title":"函数","text":"julia> f = +;\n\njulia> f(1,2,3)\n6","category":"page"},{"location":"manual/functions/","page":"函数","title":"函数","text":"然而,函数以f命名时不再支持中缀表达式。","category":"page"},{"location":"manual/functions/#具有特殊名称的操作符","page":"函数","title":"具有特殊名称的操作符","text":"","category":"section"},{"location":"manual/functions/","page":"函数","title":"函数","text":"有一些特殊的表达式对应的函数调用没有显示的函数名称,它们是:","category":"page"},{"location":"manual/functions/","page":"函数","title":"函数","text":"表达式 函数调用\n[A B C ...] hcat\n[A; B; C; ...] vcat\n[A B; C D; ...] hvcat\nA' adjoint\nA[i] getindex\nA[i] = x setindex!\nA.n getproperty\nA.n = x setproperty!","category":"page"},{"location":"manual/functions/#man-anonymous-functions","page":"函数","title":"匿名函数","text":"","category":"section"},{"location":"manual/functions/","page":"函数","title":"函数","text":"函数在Julia里是一等公民:可以指定给变量,并使用标准函数调用语法通过被指定的变量调用。函数可以用作参数,也可以当作返回值。函数也可以不带函数名称地匿名创建,使用语法如下:","category":"page"},{"location":"manual/functions/","page":"函数","title":"函数","text":"julia> x -> x^2 + 2x - 1\n#1 (generic function with 1 method)\n\njulia> function (x)\n x^2 + 2x - 1\n end\n#3 (generic function with 1 method)","category":"page"},{"location":"manual/functions/","page":"函数","title":"函数","text":"这样就创建了一个接受一个参数 x 并返回当前值的多项式 x^2+2x-1 的函数。注意结果是个泛型函数,但是带了编译器生成的连续编号的名字。","category":"page"},{"location":"manual/functions/","page":"函数","title":"函数","text":"匿名函数最主要的用法是传递给接收函数作为参数的函数。一个经典的例子是 map ,为数组的每个元素应用一次函数,然后返回一个包含结果值的新数组:","category":"page"},{"location":"manual/functions/","page":"函数","title":"函数","text":"julia> map(round, [1.2, 3.5, 1.7])\n3-element Vector{Float64}:\n 1.0\n 4.0\n 2.0","category":"page"},{"location":"manual/functions/","page":"函数","title":"函数","text":"如果做为第一个参数传递给 map 的转换函数已经存在,那直接使用函数名称是没问题的。但是通常要使用的函数还没有定义好,这样使用匿名函数就更加方便:","category":"page"},{"location":"manual/functions/","page":"函数","title":"函数","text":"julia> map(x -> x^2 + 2x - 1, [1, 3, -1])\n3-element Vector{Int64}:\n 2\n 14\n -2","category":"page"},{"location":"manual/functions/","page":"函数","title":"函数","text":"接受多个参数的匿名函数写法可以使用语法 (x,y,z)->2x+y-z,而无参匿名函数写作 ()->3 。无参函数的这种写法看起来可能有些奇怪,不过它对于延迟计算很有必要。这种用法会把代码块包进一个无参函数中,后续把它当做 f 调用。","category":"page"},{"location":"manual/functions/","page":"函数","title":"函数","text":"例如,考虑对 get 的调用:","category":"page"},{"location":"manual/functions/","page":"函数","title":"函数","text":"get(dict, key) do\n # default value calculated here\n time()\nend","category":"page"},{"location":"manual/functions/","page":"函数","title":"函数","text":"上面的代码等效于使用包含代码的匿名函数调用get。 被包围在do和end之间,如下所示","category":"page"},{"location":"manual/functions/","page":"函数","title":"函数","text":"get(()->time(), dict, key)","category":"page"},{"location":"manual/functions/","page":"函数","title":"函数","text":"这里对 time 的调用,被包裹了它的一个无参数的匿名函数延迟了。该匿名函数只当 dict 缺少被请求的键时,才被调用。","category":"page"},{"location":"manual/functions/#元组","page":"函数","title":"元组","text":"","category":"section"},{"location":"manual/functions/","page":"函数","title":"函数","text":"Julia 有一个和函数参数与返回值密切相关的内置数据结构叫做元组(tuple)。 一个元组是一个固定长度的容器,可以容纳任何值,但不可以被修改(是immutable的)。 元组通过圆括号和逗号来构造,其内容可以通过索引来访问:","category":"page"},{"location":"manual/functions/","page":"函数","title":"函数","text":"julia> (1, 1+1)\n(1, 2)\n\njulia> (1,)\n(1,)\n\njulia> x = (0.0, \"hello\", 6*7)\n(0.0, \"hello\", 42)\n\njulia> x[2]\n\"hello\"","category":"page"},{"location":"manual/functions/","page":"函数","title":"函数","text":"注意,长度为1的元组必须使用逗号 (1,),而 (1) 只是一个带括号的值。() 表示空元组(长度为0)。","category":"page"},{"location":"manual/functions/#具名元组","page":"函数","title":"具名元组","text":"","category":"section"},{"location":"manual/functions/","page":"函数","title":"函数","text":"元组的元素可以有名字,这时候就有了具名元组:","category":"page"},{"location":"manual/functions/","page":"函数","title":"函数","text":"julia> x = (a=2, b=1+2)\n(a = 2, b = 3)\n\njulia> x[1]\n2\n\njulia> x.a\n2","category":"page"},{"location":"manual/functions/","page":"函数","title":"函数","text":"具名元组和元组十分类似,区别在于除了一般的下标语法(x[1]),还可以使用点运算符语法(x.a)通过元素的名字来访问它的元素。","category":"page"},{"location":"manual/functions/#destructuring-assignment","page":"函数","title":"解构赋值和多返回值","text":"","category":"section"},{"location":"manual/functions/","page":"函数","title":"函数","text":"逗号分隔的变量列表(可选地用括号括起来)可以出现在赋值的左侧:右侧的值通过迭代并依次分配给每个变量来解构:","category":"page"},{"location":"manual/functions/","page":"函数","title":"函数","text":"julia> (a,b,c) = 1:3\n1:3\n\njulia> b\n2","category":"page"},{"location":"manual/functions/","page":"函数","title":"函数","text":"右边的值应该是一个至少与左边的变量数量一样长的迭代器(参见迭代接口)(迭代器的任何多余元素会被忽略)。","category":"page"},{"location":"manual/functions/","page":"函数","title":"函数","text":"可用于通过返回元组或其他可迭代值从函数返回多个值。例如,以下函数返回两个值:","category":"page"},{"location":"manual/functions/","page":"函数","title":"函数","text":"julia> function foo(a,b)\n a+b, a*b\n end\nfoo (generic function with 1 method)","category":"page"},{"location":"manual/functions/","page":"函数","title":"函数","text":"如果你在交互式会话中调用它且不把返回值赋值给任何变量,你会看到返回的元组:","category":"page"},{"location":"manual/functions/","page":"函数","title":"函数","text":"julia> foo(2,3)\n(5, 6)","category":"page"},{"location":"manual/functions/","page":"函数","title":"函数","text":"解构赋值将每个值提取到一个变量中:","category":"page"},{"location":"manual/functions/","page":"函数","title":"函数","text":"julia> x, y = foo(2,3)\n(5, 6)\n\njulia> x\n5\n\njulia> y\n6","category":"page"},{"location":"manual/functions/","page":"函数","title":"函数","text":"另一个常见用途是交换变量:","category":"page"},{"location":"manual/functions/","page":"函数","title":"函数","text":"julia> y, x = x, y\n(5, 6)\n\njulia> x\n6\n\njulia> y\n5","category":"page"},{"location":"manual/functions/","page":"函数","title":"函数","text":"如果只需要迭代器元素的一个子集,一个常见的惯例是将忽略的元素分配给一个只包含下划线 _ 的变量(这是一个无效的变量名,请参阅 [合法的变量名](@ref man -allowed-variable-names)):","category":"page"},{"location":"manual/functions/","page":"函数","title":"函数","text":"julia> _, _, _, d = 1:10\n1:10\n\njulia> d\n4","category":"page"},{"location":"manual/functions/","page":"函数","title":"函数","text":"其他有效的左侧表达式可以用作赋值列表的元素,它们将调用 setindex! 或 setproperty!,或者递归地解构迭代器的各个元素:","category":"page"},{"location":"manual/functions/","page":"函数","title":"函数","text":"julia> X = zeros(3);\n\njulia> X[1], (a,b) = (1, (2, 3))\n(1, (2, 3))\n\njulia> X\n3-element Vector{Float64}:\n 1.0\n 0.0\n 0.0\n\njulia> a\n2\n\njulia> b\n3","category":"page"},{"location":"manual/functions/","page":"函数","title":"函数","text":"compat: Julia 1.6\n带 ... 的赋值需要 Julia 1.6","category":"page"},{"location":"manual/functions/","page":"函数","title":"函数","text":"如果赋值列表中的最后一个符号后缀为 ...(称为 slurping),那么它将被分配给右侧迭代器剩余元素的集合或其惰性迭代器:","category":"page"},{"location":"manual/functions/","page":"函数","title":"函数","text":"julia> a, b... = \"hello\"\n\"hello\"\n\njulia> a\n'h': ASCII/Unicode U+0068 (category Ll: Letter, lowercase)\n\njulia> b\n\"ello\"\n\njulia> a, b... = Iterators.map(abs2, 1:4)\nBase.Generator{UnitRange{Int64}, typeof(abs2)}(abs2, 1:4)\n\njulia> a\n1\n\njulia> b\nBase.Iterators.Rest{Base.Generator{UnitRange{Int64}, typeof(abs2)}, Int64}(Base.Generator{UnitRange{Int64}, typeof(abs2)}(abs2, 1:4), 1)","category":"page"},{"location":"manual/functions/","page":"函数","title":"函数","text":"有关特定迭代器的精确处理和自定义的详细信息,请参阅 Base.rest。","category":"page"},{"location":"manual/functions/#参数解构","page":"函数","title":"参数解构","text":"","category":"section"},{"location":"manual/functions/","page":"函数","title":"函数","text":"析构特性也可以被用在函数参数中。 如果一个函数的参数被写成了元组形式 (如 (x, y)) 而不是简单的符号,那么一个赋值运算 (x, y) = argument 将会被默认插入:","category":"page"},{"location":"manual/functions/","page":"函数","title":"函数","text":"julia> minmax(x, y) = (y < x) ? (y, x) : (x, y)\n\njulia> gap((min, max)) = max - min\n\njulia> gap(minmax(10, 2))\n8","category":"page"},{"location":"manual/functions/","page":"函数","title":"函数","text":"注意在定义函数 gap 时额外的括号。 没有它们,gap 函数将会是一个双参数函数,这个例子也会无法正常运行。","category":"page"},{"location":"manual/functions/","page":"函数","title":"函数","text":"对于匿名函数,解构单个元组需要一个额外的逗号:","category":"page"},{"location":"manual/functions/","page":"函数","title":"函数","text":"julia> map(((x,y),) -> x + y, [(1,2), (3,4)])\n2-element Array{Int64,1}:\n 3\n 7","category":"page"},{"location":"manual/functions/#变参函数","page":"函数","title":"变参函数","text":"","category":"section"},{"location":"manual/functions/","page":"函数","title":"函数","text":"定义有任意个参数的函数会带来很多便利。这类函数通常被称为“变参”函数,即“参数数量可变”的简称。你可以通过在最后一个参数后增加省略号来定义一个变参函数:","category":"page"},{"location":"manual/functions/","page":"函数","title":"函数","text":"julia> bar(a,b,x...) = (a,b,x)\nbar (generic function with 1 method)","category":"page"},{"location":"manual/functions/","page":"函数","title":"函数","text":"变量 a 和 b 和以前一样被绑定给前两个参数,后面的参数整个做为迭代集合被绑定到变量 x 上 :","category":"page"},{"location":"manual/functions/","page":"函数","title":"函数","text":"julia> bar(1,2)\n(1, 2, ())\n\njulia> bar(1,2,3)\n(1, 2, (3,))\n\njulia> bar(1, 2, 3, 4)\n(1, 2, (3, 4))\n\njulia> bar(1,2,3,4,5,6)\n(1, 2, (3, 4, 5, 6))","category":"page"},{"location":"manual/functions/","page":"函数","title":"函数","text":"在所有这些情况下,x 被绑定到传递给 bar 的尾随值的元组。","category":"page"},{"location":"manual/functions/","page":"函数","title":"函数","text":"也可以限制可以传递给函数的参数的数量,这部分内容稍后在 参数化约束的可变参数方法 中讨论。","category":"page"},{"location":"manual/functions/","page":"函数","title":"函数","text":"另一方面,将可迭代集中包含的值拆解为单独的参数进行函数调用通常很方便。 要实现这一点,需要在函数调用中额外使用 ... 而不仅仅只是变量:","category":"page"},{"location":"manual/functions/","page":"函数","title":"函数","text":"julia> x = (3, 4)\n(3, 4)\n\njulia> bar(1,2,x...)\n(1, 2, (3, 4))","category":"page"},{"location":"manual/functions/","page":"函数","title":"函数","text":"在这个情况下一组值会被精确切片成一个可变参数调用,这里参数的数量是可变的。但是并不需要成为这种情况:","category":"page"},{"location":"manual/functions/","page":"函数","title":"函数","text":"julia> x = (2, 3, 4)\n(2, 3, 4)\n\njulia> bar(1,x...)\n(1, 2, (3, 4))\n\njulia> x = (1, 2, 3, 4)\n(1, 2, 3, 4)\n\njulia> bar(x...)\n(1, 2, (3, 4))","category":"page"},{"location":"manual/functions/","page":"函数","title":"函数","text":"进一步,拆解给函数调用中的可迭代对象不需要是个元组:","category":"page"},{"location":"manual/functions/","page":"函数","title":"函数","text":"julia> x = [3,4]\n2-element Vector{Int64}:\n 3\n 4\n\njulia> bar(1,2,x...)\n(1, 2, (3, 4))\n\njulia> x = [1,2,3,4]\n4-element Vector{Int64}:\n 1\n 2\n 3\n 4\n\njulia> bar(x...)\n(1, 2, (3, 4))","category":"page"},{"location":"manual/functions/","page":"函数","title":"函数","text":"此外,参数被放入的函数不一定是可变参数函数(尽管经常是):","category":"page"},{"location":"manual/functions/","page":"函数","title":"函数","text":"julia> baz(a,b) = a + b;\n\njulia> args = [1,2]\n2-element Vector{Int64}:\n 1\n 2\n\njulia> baz(args...)\n3\n\njulia> args = [1,2,3]\n3-element Vector{Int64}:\n 1\n 2\n 3\n\njulia> baz(args...)\nERROR: MethodError: no method matching baz(::Int64, ::Int64, ::Int64)\nClosest candidates are:\n baz(::Any, ::Any) at none:1","category":"page"},{"location":"manual/functions/","page":"函数","title":"函数","text":"正如你所见,如果要拆解的容器(比如元组或数组)元素数量不匹配就会报错,和直接给多个参数报错一样。","category":"page"},{"location":"manual/functions/#可选参数","page":"函数","title":"可选参数","text":"","category":"section"},{"location":"manual/functions/","page":"函数","title":"函数","text":"在很多情况下,函数参数有合理的默认值,因此也许不需要显式地传递。例如,Dates 模块中的 Date(y, [m, d]) 函数对于给定的年(year)y、月(mouth)m、日(data)d 构造了 Date 类型。但是,m 和 d 参数都是可选的,默认值都是 1。这行为可以简述为:","category":"page"},{"location":"manual/functions/","page":"函数","title":"函数","text":"function Date(y::Int64, m::Int64=1, d::Int64=1)\n err = validargs(Date, y, m, d)\n err === nothing || throw(err)\n return Date(UTD(totaldays(y, m, d)))\nend","category":"page"},{"location":"manual/functions/","page":"函数","title":"函数","text":"注意,这个定义调用了 Date 函数的另一个方法,该方法带有一个 UTInstant{Day} 类型的参数。","category":"page"},{"location":"manual/functions/","page":"函数","title":"函数","text":"通过此定义,函数调用时可以带有一个、两个或三个参数,并且在只有一个或两个参数被指定时后,自动传递 1 为未指定参数值:","category":"page"},{"location":"manual/functions/","page":"函数","title":"函数","text":"julia> using Dates\n\njulia> Date(2000, 12, 12)\n2000-12-12\n\njulia> Date(2000, 12)\n2000-12-01\n\njulia> Date(2000)\n2000-01-01","category":"page"},{"location":"manual/functions/","page":"函数","title":"函数","text":"可选参数实际上只是一种方便的语法,用于编写多种具有不同数量参数的方法定义(请参阅 可选参数和关键字的参数的注意事项)。这可通过调用 methods 函数来检查我们的 Date 函数示例。","category":"page"},{"location":"manual/functions/#关键字参数","page":"函数","title":"关键字参数","text":"","category":"section"},{"location":"manual/functions/","page":"函数","title":"函数","text":"某些函数需要大量参数,或者具有大量行为。记住如何调用这样的函数可能很困难。关键字参数允许通过名称而不是仅通过位置来识别参数,使得这些复杂接口易于使用和扩展。","category":"page"},{"location":"manual/functions/","page":"函数","title":"函数","text":"例如,考虑绘制一条线的函数 plot。这个函数可能有很多选项,用来控制线条的样式、宽度、颜色等。如果它接受关键字参数,一个可行的调用可能看起来像 plot(x, y, width=2),这里我们仅指定线的宽度。请注意,这样做有两个目的。调用更可读,因为我们能以其意义标记参数。也使得大量参数的任意子集都能以任意次序传递。","category":"page"},{"location":"manual/functions/","page":"函数","title":"函数","text":"具有关键字参数的函数在签名中使用分号定义:","category":"page"},{"location":"manual/functions/","page":"函数","title":"函数","text":"function plot(x, y; style=\"solid\", width=1, color=\"black\")\n ###\nend","category":"page"},{"location":"manual/functions/","page":"函数","title":"函数","text":"在函数调用时,分号是可选的:可以调用 plot(x, y, width=2) 或 plot(x, y; width=2),但前者的风格更为常见。显式的分号只有在传递可变参数或下文中描述的需计算的关键字时是必要的。","category":"page"},{"location":"manual/functions/","page":"函数","title":"函数","text":"关键字参数的默认值只在必需时求值(当相应的关键字参数没有被传入),并且按从左到右的顺序求值,因为默认值的表达式可能会参照先前的关键字参数。","category":"page"},{"location":"manual/functions/","page":"函数","title":"函数","text":"关键字参数的类型可以通过如下的方式显式指定:","category":"page"},{"location":"manual/functions/","page":"函数","title":"函数","text":"function f(;x::Int=1)\n ###\nend","category":"page"},{"location":"manual/functions/","page":"函数","title":"函数","text":"关键字参数也可以在变参函数中使用:","category":"page"},{"location":"manual/functions/","page":"函数","title":"函数","text":"function plot(x...; style=\"solid\")\n ###\nend","category":"page"},{"location":"manual/functions/","page":"函数","title":"函数","text":"附加的关键字参数可用 ... 收集,正如在变参函数中:","category":"page"},{"location":"manual/functions/","page":"函数","title":"函数","text":"function f(x; y=0, kwargs...)\n ###\nend","category":"page"},{"location":"manual/functions/","page":"函数","title":"函数","text":"在 f 中,kwargs 将是一个在命名元组上的不可变键值迭代器。 具名元组(以及带有Symbol键的字典)可以在调用中使用分号作为关键字参数传递,例如 f(x, z=1; kwargs...)。","category":"page"},{"location":"manual/functions/","page":"函数","title":"函数","text":"如果一个关键字参数在方法定义中未指定默认值,那么它就是必需的:如果调用者没有为其赋值,那么将会抛出一个 UndefKeywordError 异常:","category":"page"},{"location":"manual/functions/","page":"函数","title":"函数","text":"function f(x; y)\n ###\nend\nf(3, y=5) # ok, y is assigned\nf(3) # throws UndefKeywordError(:y)","category":"page"},{"location":"manual/functions/","page":"函数","title":"函数","text":"在分号后也可传递 key => value 表达式。例如,plot(x, y; :width => 2) 等价于 plot(x, y, width=2)。当关键字名称需要在运行时被计算时,这就很实用了。","category":"page"},{"location":"manual/functions/","page":"函数","title":"函数","text":"当分号后出现裸标识符或点表达式时,标识符或字段名称隐含关键字参数名称。 例如plot(x, y; width) 等价于plot(x, y; width=width),plot(x, y; options.width) 等价于plot(x, y; width=options.width)。","category":"page"},{"location":"manual/functions/","page":"函数","title":"函数","text":"可选参数的性质使得可以多次指定同一参数的值。例如,在调用 plot(x, y; options..., width=2) 的过程中,options 结构也能包含一个 width 的值。在这种情况下,最右边的值优先级最高;在此例中,width 的值可以确定是 2。但是,显式地多次指定同一参数的值是不允许的,例如 plot(x, y, width=2, width=3),这会导致语法错误。","category":"page"},{"location":"manual/functions/#默认值作用域的计算","page":"函数","title":"默认值作用域的计算","text":"","category":"section"},{"location":"manual/functions/","page":"函数","title":"函数","text":"当计算可选和关键字参数的默认值表达式时,只有先前的参数才在作用域内。例如,给出以下定义:","category":"page"},{"location":"manual/functions/","page":"函数","title":"函数","text":"function f(x, a=b, b=1)\n ###\nend","category":"page"},{"location":"manual/functions/","page":"函数","title":"函数","text":"a=b 中的 b 指的是外部作用域内的 b,而不是后续参数中的 b。","category":"page"},{"location":"manual/functions/#Do-Block-Syntax-for-Function-Arguments","page":"函数","title":"函数参数中的 Do 结构","text":"","category":"section"},{"location":"manual/functions/","page":"函数","title":"函数","text":"把函数作为参数传递给其他函数是一种强大的技术,但它的语法并不总是很方便。当函数参数占据多行时,这样的调用便特别难以编写。例如,考虑在具有多种情况的函数上调用 map:","category":"page"},{"location":"manual/functions/","page":"函数","title":"函数","text":"map(x->begin\n if x < 0 && iseven(x)\n return 0\n elseif x == 0\n return 1\n else\n return x\n end\n end,\n [A, B, C])","category":"page"},{"location":"manual/functions/","page":"函数","title":"函数","text":"Julia 提供了一个保留字 do,用于更清楚地重写此代码:","category":"page"},{"location":"manual/functions/","page":"函数","title":"函数","text":"map([A, B, C]) do x\n if x < 0 && iseven(x)\n return 0\n elseif x == 0\n return 1\n else\n return x\n end\nend","category":"page"},{"location":"manual/functions/","page":"函数","title":"函数","text":"do x 语法创建一个带有参数 x 的匿名函数,并将其作为第一个参数传递给 map。 类似地,do a,b 将创建一个有两个参数的匿名函数。 请注意,do (a,b) 将创建一个单参数匿名函数,其参数是一个要解构的元组。 一个简单的 do 会声明接下来是一个形式为 () -> ... 的匿名函数。","category":"page"},{"location":"manual/functions/","page":"函数","title":"函数","text":"这些参数如何初始化取决于「外部」函数;在这里,map 将会依次将 x 设置为 A、B、C,再分别调用调用匿名函数,正如在 map(func, [A, B, C]) 语法中所发生的。","category":"page"},{"location":"manual/functions/","page":"函数","title":"函数","text":"这种语法使得更容易使用函数来有效地扩展语言,因为调用看起来就像普通代码块。有许多可能的用法与 map 完全不同,比如管理系统状态。例如,有一个版本的 open 可以通过运行代码来确保已经打开的文件最终会被关闭:","category":"page"},{"location":"manual/functions/","page":"函数","title":"函数","text":"open(\"outfile\", \"w\") do io\n write(io, data)\nend","category":"page"},{"location":"manual/functions/","page":"函数","title":"函数","text":"这是通过以下定义实现的:","category":"page"},{"location":"manual/functions/","page":"函数","title":"函数","text":"function open(f::Function, args...)\n io = open(args...)\n try\n f(io)\n finally\n close(io)\n end\nend","category":"page"},{"location":"manual/functions/","page":"函数","title":"函数","text":"在这里,open 首先打开要写入的文件,接着将结果输出流传递给你在 do ... end 代码快中定义的匿名函数。在你的函数退出后,open 将确保流被正确关闭,无论你的函数是正常退出还是抛出了一个异常(try/finally 结构会在 流程控制 中描述)。","category":"page"},{"location":"manual/functions/","page":"函数","title":"函数","text":"使用 do 代码块语法时,查阅文档或实现有助于了解用户函数的参数是如何初始化的。","category":"page"},{"location":"manual/functions/","page":"函数","title":"函数","text":"类似于其他的内部函数, do 代码块也可以“捕获”上一个作用域的变量。例如,上一个 open...do 的例子中变量 data 是从外部作用域捕获的。捕获变量可能会给性能优化带来挑战,详见 性能建议。","category":"page"},{"location":"manual/functions/#函数的复合与链式调用","page":"函数","title":"函数的复合与链式调用","text":"","category":"section"},{"location":"manual/functions/","page":"函数","title":"函数","text":"Julia中的多个函数可以用函数复合或管道连接(链式调用)组合起来。","category":"page"},{"location":"manual/functions/","page":"函数","title":"函数","text":"函数的复合指的是把多个函数绑定到一起,然后作用于最先调用那个函数的参数。 你可以使用函数复合运算符 (∘) 来组合函数,这样一来 (f ∘ g)(args...) 就等价于 f(g(args...)).","category":"page"},{"location":"manual/functions/","page":"函数","title":"函数","text":"你可以在REPL和合理配置的编辑器中用 \\circ 输入函数复合运算符。","category":"page"},{"location":"manual/functions/","page":"函数","title":"函数","text":"例如, sqrt 和 + 可以用下面这种方式组合:","category":"page"},{"location":"manual/functions/","page":"函数","title":"函数","text":"julia> (sqrt ∘ +)(3, 6)\n3.0","category":"page"},{"location":"manual/functions/","page":"函数","title":"函数","text":"这个语句先把数字相加,再对结果求平方根。","category":"page"},{"location":"manual/functions/","page":"函数","title":"函数","text":"下一个例子组合了三个函数并把新函数作用到一个字符串组成的数组上:","category":"page"},{"location":"manual/functions/","page":"函数","title":"函数","text":"julia> map(first ∘ reverse ∘ uppercase, split(\"you can compose functions like this\"))\n6-element Vector{Char}:\n 'U': ASCII/Unicode U+0055 (category Lu: Letter, uppercase)\n 'N': ASCII/Unicode U+004E (category Lu: Letter, uppercase)\n 'E': ASCII/Unicode U+0045 (category Lu: Letter, uppercase)\n 'S': ASCII/Unicode U+0053 (category Lu: Letter, uppercase)\n 'E': ASCII/Unicode U+0045 (category Lu: Letter, uppercase)\n 'S': ASCII/Unicode U+0053 (category Lu: Letter, uppercase)","category":"page"},{"location":"manual/functions/","page":"函数","title":"函数","text":"函数的链式调用(有时也称“使用管道”把数据送到一系列函数中去)指的是把一个函数作用到前一个函数的输出上:","category":"page"},{"location":"manual/functions/","page":"函数","title":"函数","text":"julia> 1:10 |> sum |> sqrt\n7.416198487095663","category":"page"},{"location":"manual/functions/","page":"函数","title":"函数","text":"在这里, sum 函数求出的和被传递到 sqrt 函数作为参数。等价的函数复合写法是:","category":"page"},{"location":"manual/functions/","page":"函数","title":"函数","text":"julia> (sqrt ∘ sum)(1:10)\n7.416198487095663","category":"page"},{"location":"manual/functions/","page":"函数","title":"函数","text":"管道运算符还可以和广播一起使用(.|>),这提供了一个有用的链式调用/管道+向量化运算的组合语法(接下来将描述)。","category":"page"},{"location":"manual/functions/","page":"函数","title":"函数","text":"julia> [\"a\", \"list\", \"of\", \"strings\"] .|> [uppercase, reverse, titlecase, length]\n4-element Vector{Any}:\n \"A\"\n \"tsil\"\n \"Of\"\n 7","category":"page"},{"location":"manual/functions/#man-vectorized","page":"函数","title":"向量化函数的点语法","text":"","category":"section"},{"location":"manual/functions/","page":"函数","title":"函数","text":"在科学计算语言中,通常会有函数的「向量化」版本,它简单地将给定函数 f(x) 作用于数组 A 的每个元素,接着通过 f(A) 生成一个新数组。这种语法便于数据处理,但在其它语言中,向量化通常也是性能所需要的:如果循环很慢,函数的「向量化」版本可以调用由低级语言编写的、快速的库代码。在 Julia 中,向量化函数不是性能所必需的,实际上编写自己的循环通常也是有益的(请参阅 Performance Tips),但它们仍然很方便。因此,任何 Julia 函数 f 能够以元素方式作用于任何数组(或者其它集合),这通过语法 f.(A) 实现。例如,sin 可以作用于向量 A 中的所有元素,如下所示:","category":"page"},{"location":"manual/functions/","page":"函数","title":"函数","text":"julia> A = [1.0, 2.0, 3.0]\n3-element Vector{Float64}:\n 1.0\n 2.0\n 3.0\n\njulia> sin.(A)\n3-element Vector{Float64}:\n 0.8414709848078965\n 0.9092974268256817\n 0.1411200080598672","category":"page"},{"location":"manual/functions/","page":"函数","title":"函数","text":"当然,你如果为 f 编写了一个专门的「向量化」方法,例如通过 f(A::AbstractArray) = map(f, A),可以省略点号,这和 f.(A) 一样高效。但这种方法要求你事先决定要进行向量化的函数。","category":"page"},{"location":"manual/functions/","page":"函数","title":"函数","text":"更一般地,f.(args...) 实际上等价于 broadcast(f, args...),它允许你操作多个数组(甚至是不同形状的),或是数组和标量的混合(请参阅 Broadcasting)。例如,如果有 f(x,y) = 3x + 4y,那么 f.(pi,A) 将为 A 中的每个 a 返回一个由 f(pi,a) 组成的新数组,而 f.(vector1,vector2) 将为每个索引 i 返回一个由 f(vector1[i],vector2[i]) 组成的新向量(如果向量具有不同的长度则会抛出异常)。","category":"page"},{"location":"manual/functions/","page":"函数","title":"函数","text":"julia> f(x,y) = 3x + 4y;\n\njulia> A = [1.0, 2.0, 3.0];\n\njulia> B = [4.0, 5.0, 6.0];\n\njulia> f.(pi, A)\n3-element Vector{Float64}:\n 13.42477796076938\n 17.42477796076938\n 21.42477796076938\n\njulia> f.(A, B)\n3-element Vector{Float64}:\n 19.0\n 26.0\n 33.0","category":"page"},{"location":"manual/functions/","page":"函数","title":"函数","text":"此外,嵌套的 f.(args...) 调用会被融合到一个 broadcast 循环中。例如,sin.(cos.(X)) 等价于 broadcast(x -> sin(cos(x)), X),类似于 [sin(cos(x)) for x in X]:在 X 上只有一个循环,并且只为结果分配了一个数组。[ 相反,在典型的「向量化」语言中,sin(cos(X)) 首先会为 tmp=cos(X) 分配第一个临时数组,然后在单独的循环中计算 sin(tmp),再分配第二个数组。] 这种循环融合不是可能发生也可能不发生的编译器优化,只要遇到了嵌套的 f.(args...) 调用,它就是一个语法保证。技术上,一旦遇到「非点」函数调用,融合就会停止;例如,在 sin.(sort(cos.(X))) 中,由于插入的 sort 函数,sin 和 cos 无法被合并。","category":"page"},{"location":"manual/functions/","page":"函数","title":"函数","text":"最后,最大效率通常在向量化操作的输出数组被预分配时实现,这样重复调用就不会一次又一次地为结果分配新数组(请参阅 输出预分配)。一个方便的语法是 X .= ...,它等价于 broadcast!(identity, X, ...),除了上面提到的,broadcast! 循环可与任何嵌套的「点」调用融合。例如,X .= sin.(Y) 等价于 broadcast!(sin, X, Y),用 sin.(Y) in-place 覆盖 X。如果左边是数组索引表达式,例如 X[2:end] .= sin.(Y),那就将 broadcast! 转换在一个 view 上,例如 broadcast!(sin, view(X, 2:lastindex(X)), Y),这样左侧就被 in-place 更新了。","category":"page"},{"location":"manual/functions/","page":"函数","title":"函数","text":"由于在表达式中为许多操作和函数调用添加点可能很乏味并导致难以阅读的代码,宏 @. 用于将表达式中的每个函数调用、操作和赋值转换为「点」版本。","category":"page"},{"location":"manual/functions/","page":"函数","title":"函数","text":"julia> Y = [1.0, 2.0, 3.0, 4.0];\n\njulia> X = similar(Y); # pre-allocate output array\n\njulia> @. X = sin(cos(Y)) # equivalent to X .= sin.(cos.(Y))\n4-element Vector{Float64}:\n 0.5143952585235492\n -0.4042391538522658\n -0.8360218615377305\n -0.6080830096407656","category":"page"},{"location":"manual/functions/","page":"函数","title":"函数","text":"像 .+ 这样的二元(或一元)运算符使用相同的机制进行管理:它们等价于 broadcast 调用且可与其它嵌套的「点」调用融合。X .+= Y 等等价于 X .= X .+ Y,结果为一个融合的 in-place 赋值;另见 dot operators。","category":"page"},{"location":"manual/functions/","page":"函数","title":"函数","text":"您也可以使用 |> 将点操作与函数链组合在一起,如本例所示:","category":"page"},{"location":"manual/functions/","page":"函数","title":"函数","text":"julia> [1:5;] .|> [x->x^2, inv, x->2*x, -, isodd]\n5-element Vector{Real}:\n 1\n 0.5\n 6\n -4\n true","category":"page"},{"location":"manual/functions/#更多阅读","page":"函数","title":"更多阅读","text":"","category":"section"},{"location":"manual/functions/","page":"函数","title":"函数","text":"我们应该在这里提到,这远不是定义函数的完整图景。Julia 拥有一个复杂的类型系统并且允许对参数类型进行多重分派。这里给出的示例都没有为它们的参数提供任何类型注释,意味着它们可以作用于任何类型的参数。类型系统在类型中描述,而方法则描述了根据运行时参数类型上的多重分派所选择的方法定义函数。","category":"page"},{"location":"stdlib/Mmap/#内存映射-I/O","page":"内存映射 I/O","title":"内存映射 I/O","text":"","category":"section"},{"location":"stdlib/Mmap/","page":"内存映射 I/O","title":"内存映射 I/O","text":"Mmap.Anonymous\nMmap.mmap\nMmap.sync!","category":"page"},{"location":"stdlib/Mmap/#Mmap.Anonymous","page":"内存映射 I/O","title":"Mmap.Anonymous","text":"Mmap.Anonymous(name::AbstractString=\"\", readonly::Bool=false, create::Bool=true)\n\nCreate an IO-like object for creating zeroed-out mmapped-memory that is not tied to a file for use in mmap. Used by SharedArray for creating shared memory arrays.\n\nExamples\n\njulia> using Mmap\n\njulia> anon = Mmap.Anonymous();\n\njulia> isreadable(anon)\ntrue\n\njulia> iswritable(anon)\ntrue\n\njulia> isopen(anon)\ntrue\n\n\n\n\n\n","category":"type"},{"location":"stdlib/Mmap/#Mmap.mmap","page":"内存映射 I/O","title":"Mmap.mmap","text":"mmap(io::Union{IOStream,AbstractString,Mmap.AnonymousMmap}[, type::Type{Array{T,N}}, dims, offset]; grow::Bool=true, shared::Bool=true)\nmmap(type::Type{Array{T,N}}, dims)\n\nCreate an Array whose values are linked to a file, using memory-mapping. This provides a convenient way of working with data too large to fit in the computer's memory.\n\nThe type is an Array{T,N} with a bits-type element of T and dimension N that determines how the bytes of the array are interpreted. Note that the file must be stored in binary format, and no format conversions are possible (this is a limitation of operating systems, not Julia).\n\ndims is a tuple or single Integer specifying the size or length of the array.\n\nThe file is passed via the stream argument, either as an open IOStream or filename string. When you initialize the stream, use \"r\" for a \"read-only\" array, and \"w+\" to create a new array used to write values to disk.\n\nIf no type argument is specified, the default is Vector{UInt8}.\n\nOptionally, you can specify an offset (in bytes) if, for example, you want to skip over a header in the file. The default value for the offset is the current stream position for an IOStream.\n\nThe grow keyword argument specifies whether the disk file should be grown to accommodate the requested size of array (if the total file size is < requested array size). Write privileges are required to grow the file.\n\nThe shared keyword argument specifies whether the resulting Array and changes made to it will be visible to other processes mapping the same file.\n\nFor example, the following code\n\n# Create a file for mmapping\n# (you could alternatively use mmap to do this step, too)\nusing Mmap\nA = rand(1:20, 5, 30)\ns = open(\"/tmp/mmap.bin\", \"w+\")\n# We'll write the dimensions of the array as the first two Ints in the file\nwrite(s, size(A,1))\nwrite(s, size(A,2))\n# Now write the data\nwrite(s, A)\nclose(s)\n\n# Test by reading it back in\ns = open(\"/tmp/mmap.bin\") # default is read-only\nm = read(s, Int)\nn = read(s, Int)\nA2 = mmap(s, Matrix{Int}, (m,n))\n\ncreates a m-by-n Matrix{Int}, linked to the file associated with stream s.\n\nA more portable file would need to encode the word size – 32 bit or 64 bit – and endianness information in the header. In practice, consider encoding binary data using standard formats like HDF5 (which can be used with memory-mapping).\n\n\n\n\n\nmmap(io, BitArray, [dims, offset])\n\nCreate a BitArray whose values are linked to a file, using memory-mapping; it has the same purpose, works in the same way, and has the same arguments, as mmap, but the byte representation is different.\n\nExamples\n\njulia> using Mmap\n\njulia> io = open(\"mmap.bin\", \"w+\");\n\njulia> B = mmap(io, BitArray, (25,30000));\n\njulia> B[3, 4000] = true;\n\njulia> Mmap.sync!(B);\n\njulia> close(io);\n\njulia> io = open(\"mmap.bin\", \"r+\");\n\njulia> C = mmap(io, BitArray, (25,30000));\n\njulia> C[3, 4000]\ntrue\n\njulia> C[2, 4000]\nfalse\n\njulia> close(io)\n\njulia> rm(\"mmap.bin\")\n\nThis creates a 25-by-30000 BitArray, linked to the file associated with stream io.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/Mmap/#Mmap.sync!","page":"内存映射 I/O","title":"Mmap.sync!","text":"Mmap.sync!(array)\n\nForces synchronization between the in-memory version of a memory-mapped Array or BitArray and the on-disk version.\n\n\n\n\n\n","category":"function"},{"location":"devdocs/sysimg/#System-Image-Building","page":"System Image Building","title":"System Image Building","text":"","category":"section"},{"location":"devdocs/sysimg/#Building-the-Julia-system-image","page":"System Image Building","title":"Building the Julia system image","text":"","category":"section"},{"location":"devdocs/sysimg/","page":"System Image Building","title":"System Image Building","text":"Julia ships with a preparsed system image containing the contents of the Base module, named sys.ji. This file is also precompiled into a shared library called sys.{so,dll,dylib} on as many platforms as possible, so as to give vastly improved startup times. On systems that do not ship with a precompiled system image file, one can be generated from the source files shipped in Julia's DATAROOTDIR/julia/base folder.","category":"page"},{"location":"devdocs/sysimg/","page":"System Image Building","title":"System Image Building","text":"This operation is useful for multiple reasons. A user may:","category":"page"},{"location":"devdocs/sysimg/","page":"System Image Building","title":"System Image Building","text":"Build a precompiled shared library system image on a platform that did not ship with one, thereby improving startup times.\nModify Base, rebuild the system image and use the new Base next time Julia is started.\nInclude a userimg.jl file that includes packages into the system image, thereby creating a system image that has packages embedded into the startup environment.","category":"page"},{"location":"devdocs/sysimg/","page":"System Image Building","title":"System Image Building","text":"The PackageCompiler.jl package contains convenient wrapper functions to automate this process.","category":"page"},{"location":"devdocs/sysimg/#System-image-optimized-for-multiple-microarchitectures","page":"System Image Building","title":"System image optimized for multiple microarchitectures","text":"","category":"section"},{"location":"devdocs/sysimg/","page":"System Image Building","title":"System Image Building","text":"The system image can be compiled simultaneously for multiple CPU microarchitectures under the same instruction set architecture (ISA). Multiple versions of the same function may be created with minimum dispatch point inserted into shared functions in order to take advantage of different ISA extensions or other microarchitecture features. The version that offers the best performance will be selected automatically at runtime based on available CPU features.","category":"page"},{"location":"devdocs/sysimg/#Specifying-multiple-system-image-targets","page":"System Image Building","title":"Specifying multiple system image targets","text":"","category":"section"},{"location":"devdocs/sysimg/","page":"System Image Building","title":"System Image Building","text":"A multi-microarchitecture system image can be enabled by passing multiple targets during system image compilation. This can be done either with the JULIA_CPU_TARGET make option or with the -C command line option when running the compilation command manually. Multiple targets are separated by ; in the option string. The syntax for each target is a CPU name followed by multiple features separated by ,. All features supported by LLVM are supported and a feature can be disabled with a - prefix. (+ prefix is also allowed and ignored to be consistent with LLVM syntax). Additionally, a few special features are supported to control the function cloning behavior.","category":"page"},{"location":"devdocs/sysimg/","page":"System Image Building","title":"System Image Building","text":"clone_all\nBy default, only functions that are the most likely to benefit from the microarchitecture features will be cloned. When clone_all is specified for a target, however, all functions in the system image will be cloned for the target. The negative form -clone_all can be used to prevent the built-in heuristic from cloning all functions.\nbase()\nWhere is a placeholder for a non-negative number (e.g. base(0), base(1)). By default, a partially cloned (i.e. not clone_all) target will use functions from the default target (first one specified) if a function is not cloned. This behavior can be changed by specifying a different base with the base() option. The nth target (0-based) will be used as the base target instead of the default (0th) one. The base target has to be either 0 or another clone_all target. Specifying a non-clone_all target as the base target will cause an error.\nopt_size\nThis causes the function for the target to be optimized for size when there isn't a significant runtime performance impact. This corresponds to -Os GCC and Clang option.\nmin_size\nThis causes the function for the target to be optimized for size that might have a significant runtime performance impact. This corresponds to -Oz Clang option.","category":"page"},{"location":"devdocs/sysimg/","page":"System Image Building","title":"System Image Building","text":"As an example, at the time of this writing, the following string is used in the creation of the official x86_64 Julia binaries downloadable from julialang.org:","category":"page"},{"location":"devdocs/sysimg/","page":"System Image Building","title":"System Image Building","text":"generic;sandybridge,-xsaveopt,clone_all;haswell,-rdrnd,base(1)","category":"page"},{"location":"devdocs/sysimg/","page":"System Image Building","title":"System Image Building","text":"This creates a system image with three separate targets; one for a generic x86_64 processor, one with a sandybridge ISA (explicitly excluding xsaveopt) that explicitly clones all functions, and one targeting the haswell ISA, based off of the sandybridge sysimg version, and also excluding rdrnd. When a Julia implementation loads the generated sysimg, it will check the host processor for matching CPU capability flags, enabling the highest ISA level possible. Note that the base level (generic) requires the cx16 instruction, which is disabled in some virtualization software and must be enabled for the generic target to be loaded. Alternatively, a sysimg could be generated with the target generic,-cx16 for greater compatibility, however note that this may cause performance and stability problems in some code.","category":"page"},{"location":"devdocs/sysimg/#Implementation-overview","page":"System Image Building","title":"Implementation overview","text":"","category":"section"},{"location":"devdocs/sysimg/","page":"System Image Building","title":"System Image Building","text":"This is a brief overview of different part involved in the implementation. See code comments for each components for more implementation details.","category":"page"},{"location":"devdocs/sysimg/","page":"System Image Building","title":"System Image Building","text":"System image compilation\nThe parsing and cloning decision are done in src/processor*. We currently support cloning of function based on the present of loops, simd instructions, or other math operations (e.g. fastmath, fma, muladd). This information is passed on to src/llvm-multiversioning.cpp which does the actual cloning. In addition to doing the cloning and insert dispatch slots (see comments in MultiVersioning::runOnModule for how this is done), the pass also generates metadata so that the runtime can load and initialize the system image correctly. A detail description of the metadata is available in src/processor.h.\nSystem image loading\nThe loading and initialization of the system image is done in src/processor* by parsing the metadata saved during system image generation. Host feature detection and selection decision are done in src/processor_*.cpp depending on the ISA. The target selection will prefer exact CPU name match, larger vector register size, and larger number of features. An overview of this process is in src/processor.cpp.","category":"page"},{"location":"devdocs/functions/#Julia-函数","page":"Julia 函数","title":"Julia 函数","text":"","category":"section"},{"location":"devdocs/functions/","page":"Julia 函数","title":"Julia 函数","text":"本文档将解释函数、方法定义以及方法表是如何工作的。","category":"page"},{"location":"devdocs/functions/#方法表","page":"Julia 函数","title":"方法表","text":"","category":"section"},{"location":"devdocs/functions/","page":"Julia 函数","title":"Julia 函数","text":"Julia 中的每个函数都是泛型函数。泛型函数在概念上是单个函数,但由许多定义或方法组成。泛型函数的方法储存在方法表中。方法表(类型 MethodTable)与 TypeName 相关。TypeName 描述了一系列参数化类型。例如,Complex{Float32} 和 Complex{Float64} 共享相同的 type name 对象 Complex。","category":"page"},{"location":"devdocs/functions/","page":"Julia 函数","title":"Julia 函数","text":"Julia 中的所有对象都可能是可调用的,因为每个对象都有类型,而类型又有 TypeName。","category":"page"},{"location":"devdocs/functions/#函数调用","page":"Julia 函数","title":"函数调用","text":"","category":"section"},{"location":"devdocs/functions/","page":"Julia 函数","title":"Julia 函数","text":"给定调用 f(x,y),会执行以下步骤:首先,用 typeof(f).name.mt 访问要使用的方法表。其次,生成一个参数元组类型 Tuple{typeof(f), typeof(x), typeof(y)}。请注意,函数本身的类型是第一个元素。这因为该类型可能有参数,所以需要参与派发。这个元组类型会在方法表中查找。","category":"page"},{"location":"devdocs/functions/","page":"Julia 函数","title":"Julia 函数","text":"这个派发过程由 jl_apply_generic 执行,它有两个参数:一个指向由值 f、x 和 y 组成的数组的指针,以及值的数量(此例中是 3)。","category":"page"},{"location":"devdocs/functions/","page":"Julia 函数","title":"Julia 函数","text":"在整个系统中,处理函数和参数列表的 API 有两种:一种单独接收函数和参数,一种接收一个单独的参数结构。在第一种 API 中,「参数」部分不包含函数的相关信息,因为它是单独传递的。在第二种 API 中,函数是参数结构的第一个元素。","category":"page"},{"location":"devdocs/functions/","page":"Julia 函数","title":"Julia 函数","text":"例如,以下用于执行调用的函数只接收 args 指针,因此 args 数组的第一个元素将会是要调用的函数:","category":"page"},{"location":"devdocs/functions/","page":"Julia 函数","title":"Julia 函数","text":"jl_value_t *jl_apply(jl_value_t **args, uint32_t nargs)","category":"page"},{"location":"devdocs/functions/","page":"Julia 函数","title":"Julia 函数","text":"这个用于相同功能的入口点单独接收该函数,因此 args 数组中不包含该函数:","category":"page"},{"location":"devdocs/functions/","page":"Julia 函数","title":"Julia 函数","text":"jl_value_t *jl_call(jl_function_t *f, jl_value_t **args, int32_t nargs);","category":"page"},{"location":"devdocs/functions/#添加方法","page":"Julia 函数","title":"添加方法","text":"","category":"section"},{"location":"devdocs/functions/","page":"Julia 函数","title":"Julia 函数","text":"在上述派发过程中,添加一个新方法在概念上所需的只是(1)一个元组类型,以及(2)方法体的代码。jl_method_def 实现了此操作。jl_first_argument_datatype 会被调用,用来从第一个参数的类型中提取相关的方法表。这比派发期间的相应过程复杂得多,因为参数元组类型可能是抽象类型。例如,我们可以定义:","category":"page"},{"location":"devdocs/functions/","page":"Julia 函数","title":"Julia 函数","text":"(::Union{Foo{Int},Foo{Int8}})(x) = 0","category":"page"},{"location":"devdocs/functions/","page":"Julia 函数","title":"Julia 函数","text":"这是可行的,因为所有可能的匹配方法都属于同一方法表。","category":"page"},{"location":"devdocs/functions/#创建泛型函数","page":"Julia 函数","title":"创建泛型函数","text":"","category":"section"},{"location":"devdocs/functions/","page":"Julia 函数","title":"Julia 函数","text":"因为每个对象都是可调用的,所以创建泛型函数不需要特殊的东西。因此,jl_new_generic_function 只是创建一个新的 Function 的单态类型(大小为 0)并返回它的实例。函数可有一个帮助记忆的「显示名称」,用于调试信息和打印对象。例如,Base.sin 的名称为 sin。按照约定,所创建类型的名称与函数名称相同,带前缀 #。所以 typeof(sin) 即 Base.#sin。","category":"page"},{"location":"devdocs/functions/#闭包","page":"Julia 函数","title":"闭包","text":"","category":"section"},{"location":"devdocs/functions/","page":"Julia 函数","title":"Julia 函数","text":"闭包只是一个可调用对象,其字段名称对应于被捕获的变量。例如,以下代码:","category":"page"},{"location":"devdocs/functions/","page":"Julia 函数","title":"Julia 函数","text":"function adder(x)\n return y->x+y\nend","category":"page"},{"location":"devdocs/functions/","page":"Julia 函数","title":"Julia 函数","text":"(大致)降低为:","category":"page"},{"location":"devdocs/functions/","page":"Julia 函数","title":"Julia 函数","text":"struct ##1{T}\n x::T\nend\n\n(_::##1)(y) = _.x + y\n\nfunction adder(x)\n return ##1(x)\nend","category":"page"},{"location":"devdocs/functions/#构造函数","page":"Julia 函数","title":"构造函数","text":"","category":"section"},{"location":"devdocs/functions/","page":"Julia 函数","title":"Julia 函数","text":"构造函数调用只是对类型的调用。Type 的方法表包含所有的构造函数定义。Type 的所有子类型(Type、UnionAll、Union 和 DataType)目前通过特殊的安排方式共享一个方法表。","category":"page"},{"location":"devdocs/functions/#内置函数","page":"Julia 函数","title":"内置函数","text":"","category":"section"},{"location":"devdocs/functions/","page":"Julia 函数","title":"Julia 函数","text":"「内置」函数定义在 Core 模块中,有:","category":"page"},{"location":"devdocs/functions/","page":"Julia 函数","title":"Julia 函数","text":"=== typeof sizeof <: isa typeassert throw tuple getfield setfield! fieldtype\nnfields isdefined arrayref arrayset arraysize applicable invoke apply_type _apply\n_expr svec","category":"page"},{"location":"devdocs/functions/","page":"Julia 函数","title":"Julia 函数","text":"这些都是单态对象,其类型为 Builtin 的子类型,而或后者为 Function 的子类型。它们的用处是在运行时暴露遵循「jlcall」调用约定的入口点。","category":"page"},{"location":"devdocs/functions/","page":"Julia 函数","title":"Julia 函数","text":"jl_value_t *(jl_value_t*, jl_value_t**, uint32_t)","category":"page"},{"location":"devdocs/functions/","page":"Julia 函数","title":"Julia 函数","text":"内建函数的方法表是空的。相反地,它们具有单独的 catch-all 方法缓存条目(Tuple{Vararg{Any}}),其 jlcall fptr 指向正确的函数。这是一种 hack,但效果相当不错。","category":"page"},{"location":"devdocs/functions/#关键字参数","page":"Julia 函数","title":"关键字参数","text":"","category":"section"},{"location":"devdocs/functions/","page":"Julia 函数","title":"Julia 函数","text":"关键字参数的工作方式是将每个具有关键字参数的方法表与一个特殊的隐藏函数对象相关联。该函数称为「keyword argument sorter」、「keyword sorter」或「kwsorter」,存储在 MethodTable 对象的 kwsorter 字段中。在 kwsorter 函数的每个定义与通常的方法表中的某个函数具有相同的参数,除了前面还有一个 NamedTuple 参数,该参数给出所传递关键字参数的名称和值。kwsorter 的作用是根据名称将关键字参数移到预先要求的位置,并对任何所需的默认值表达式进行求值和替换。其返回结果是一个通常的位置参数列表,接着会被传递给另一个由编译器生成的函数。","category":"page"},{"location":"devdocs/functions/","page":"Julia 函数","title":"Julia 函数","text":"理解该过程的最简单方法是查看关键字参数方法的定义的降低方式。代码:","category":"page"},{"location":"devdocs/functions/","page":"Julia 函数","title":"Julia 函数","text":"function circle(center, radius; color = black, fill::Bool = true, options...)\n # draw\nend","category":"page"},{"location":"devdocs/functions/","page":"Julia 函数","title":"Julia 函数","text":"实际上生成三个方法定义。第一个方法是一个接收所有参数(包括关键字参数)作为其位置参数的函数,其代码包含该方法体。它有一个自动生成的名称:","category":"page"},{"location":"devdocs/functions/","page":"Julia 函数","title":"Julia 函数","text":"function #circle#1(color, fill::Bool, options, circle, center, radius)\n # draw\nend","category":"page"},{"location":"devdocs/functions/","page":"Julia 函数","title":"Julia 函数","text":"第二个方法是原始 circle 函数的普通定义,负责处理没有传递关键字参数的情况:","category":"page"},{"location":"devdocs/functions/","page":"Julia 函数","title":"Julia 函数","text":"function circle(center, radius)\n #circle#1(black, true, pairs(NamedTuple()), circle, center, radius)\nend","category":"page"},{"location":"devdocs/functions/","page":"Julia 函数","title":"Julia 函数","text":"这只是派发到第一个方法,传递默认值。pairs 应用于其余的参数组成的具名元组,以提供键值对迭代。请注意,如果方法不接受其余的关键字参数,那么此参数不存在。","category":"page"},{"location":"devdocs/functions/","page":"Julia 函数","title":"Julia 函数","text":"最后,kwsorter 定义为:","category":"page"},{"location":"devdocs/functions/","page":"Julia 函数","title":"Julia 函数","text":"function (::Core.kwftype(typeof(circle)))(kws, circle, center, radius)\n if haskey(kws, :color)\n color = kws.color\n else\n color = black\n end\n # etc.\n\n # put remaining kwargs in `options`\n options = structdiff(kws, NamedTuple{(:color, :fill)})\n\n # if the method doesn't accept rest keywords, throw an error\n # unless `options` is empty\n\n #circle#1(color, fill, pairs(options), circle, center, radius)\nend","category":"page"},{"location":"devdocs/functions/","page":"Julia 函数","title":"Julia 函数","text":"函数 Core.kwftype(t) 创建字段 t.name.mt.kwsorter(如果它未被创建),并返回该函数的类型。","category":"page"},{"location":"devdocs/functions/","page":"Julia 函数","title":"Julia 函数","text":"此设计的特点是不使用关键字参数的调用点不需要特殊处理;这一切的工作方式好像它们根本不是语言的一部分。不使用关键字参数的调用点直接派发到被调用函数的 kwsorter。例如,调用:","category":"page"},{"location":"devdocs/functions/","page":"Julia 函数","title":"Julia 函数","text":"circle((0,0), 1.0, color = red; other...)","category":"page"},{"location":"devdocs/functions/","page":"Julia 函数","title":"Julia 函数","text":"降低为:","category":"page"},{"location":"devdocs/functions/","page":"Julia 函数","title":"Julia 函数","text":"kwfunc(circle)(merge((color = red,), other), circle, (0,0), 1.0)","category":"page"},{"location":"devdocs/functions/","page":"Julia 函数","title":"Julia 函数","text":"kwfunc(也在 Core 中)可获取被调用函数的 kwsorter。关键字 splatting 函数(编写为 other...)调用具名元组 merge 函数。此函数进一步解包了 other 的每个元素,预期中每个元素包含两个值(一个符号和一个值)。当然,如果所有 splatted 参数都是具名元组,则可使用更高效的实现。请注意,原来的 circle 被传递,以处理闭包。","category":"page"},{"location":"devdocs/functions/#compiler-efficiency-issues","page":"Julia 函数","title":"Compiler efficiency issues","text":"","category":"section"},{"location":"devdocs/functions/","page":"Julia 函数","title":"Julia 函数","text":"为每个函数生成新类型在与 Julia 的「默认专门化所有参数」这一设计理念结合使用时,可能对编译器资源的使用产生严重后果。实际上,此设计的初始实现经历了更长的测试和构造时间、高内存占用以及比基线大近乎 2 倍的系统镜像。在一个幼稚的实现中,该问题非常严重,以至于系统几乎无法使用。需要进行几项重要的优化才能使设计变得可行。","category":"page"},{"location":"devdocs/functions/","page":"Julia 函数","title":"Julia 函数","text":"第一个问题是函数值参数的不同值导致函数的过度专门化。许多函数只是将参数「传递」到其它地方,例如,到另一个函数或存储位置。这种函数不需要为每个可能传入的闭包专门化。幸运的是,这种情况很容易区分,只需考虑函数是否调用它的某个参数(即,参数出现在某处的「头部位置」)。性能关键的高阶函数,如 map,肯定会直接调用它们的参数函数,因此仍然会按预期进行专门化。此优化通过在前端记录 analyze-variables 传递期间所调用的参数来实现。当 cache_method 看到某个在 Function 类型层次结构的参数传递到声明为 Any 或 Function 的槽时,它的行为就好像应用了 @nospecialize 注释一样。这种启发式方法在实践中似乎非常有效。","category":"page"},{"location":"devdocs/functions/","page":"Julia 函数","title":"Julia 函数","text":"下一个问题涉及方法缓存哈希表的结构。经验研究表明,绝大多数动态分派调用只涉及一个或两个元素。反过来看,只考虑第一个元素便可解决许多这些情况。(旁白:单派发的支持者根本不会对此感到惊讶。但是,这个观点意味着「多重派发在实践中很容易优化」,因此我们应该使用它,而不是「我们应该使用单派发」!)因此,方法缓存使用第一个参数作为其主键。但请注意,这对应于函数调用的元组类型的第二个元素(第一个元素是函数本身的类型)。通常,头部位置的类型非常少变化——实际上,大多数函数属于没有参数的单态类型。但是,构造函数不是这种情况,一个方法表便保存了所有类型的构造函数。因此,Type 方法表是特殊的,使用元组类型的第一个元素而不是第二个。","category":"page"},{"location":"devdocs/functions/","page":"Julia 函数","title":"Julia 函数","text":"前端为所有闭包生成类型声明。起初,这通过生成通常的类型声明来实现。但是,这产生了大量的构造函数,这些构造函数全都很简单(只是将所有参数传递给 new)。因为方法是部分排序的,所以插入所有这些方法是 O(n^2),此外要保留的方法实在太多了。这可通过直接生成 struct_type 表达式(绕过默认的构造函数生成)并直接使用 new 来创建闭包的实例来优化。这事并不漂亮,但你需要做你该做的。","category":"page"},{"location":"devdocs/functions/","page":"Julia 函数","title":"Julia 函数","text":"下个问题是 @test 宏,它为每个测试用例生成一个 0 参数闭包。这不是必需的,因为每个用例只需运行一次。因此,@test 被改写以展开到一个 try-catch 块中,该块记录测试结果(true、false 或所引发的异常)并对它调用测试套件处理程序。","category":"page"},{"location":"stdlib/Profile/#lib-profiling","page":"性能分析","title":"性能分析","text":"","category":"section"},{"location":"stdlib/Profile/","page":"性能分析","title":"性能分析","text":"Profile.@profile","category":"page"},{"location":"stdlib/Profile/#Profile.@profile","page":"性能分析","title":"Profile.@profile","text":"@profile\n\n@profile runs your expression while taking periodic backtraces. These are appended to an internal buffer of backtraces.\n\n\n\n\n\n","category":"macro"},{"location":"stdlib/Profile/","page":"性能分析","title":"性能分析","text":"Profile 里的方法均未导出,需要通过 Profile.print() 的方式调用。","category":"page"},{"location":"stdlib/Profile/","page":"性能分析","title":"性能分析","text":"Profile.clear\nProfile.print\nProfile.init\nProfile.fetch\nProfile.retrieve\nProfile.callers\nProfile.clear_malloc_data","category":"page"},{"location":"stdlib/Profile/#Profile.clear","page":"性能分析","title":"Profile.clear","text":"clear()\n\nClear any existing backtraces from the internal buffer.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/Profile/#Profile.print","page":"性能分析","title":"Profile.print","text":"print([io::IO = stdout,] [data::Vector = fetch()], [lidict::Union{LineInfoDict, LineInfoFlatDict} = getdict(data)]; kwargs...)\n\nPrints profiling results to io (by default, stdout). If you do not supply a data vector, the internal buffer of accumulated backtraces will be used.\n\nThe keyword arguments can be any combination of:\n\nformat – Determines whether backtraces are printed with (default, :tree) or without (:flat) indentation indicating tree structure.\nC – If true, backtraces from C and Fortran code are shown (normally they are excluded).\ncombine – If true (default), instruction pointers are merged that correspond to the same line of code.\nmaxdepth – Limits the depth higher than maxdepth in the :tree format.\nsortedby – Controls the order in :flat format. :filefuncline (default) sorts by the source line, :count sorts in order of number of collected samples, and :overhead sorts by the number of samples incurred by each function by itself.\ngroupby – Controls grouping over tasks and threads, or no grouping. Options are :none (default), :thread, :task, [:thread, :task], or [:task, :thread] where the last two provide nested grouping.\nnoisefloor – Limits frames that exceed the heuristic noise floor of the sample (only applies to format :tree). A suggested value to try for this is 2.0 (the default is 0). This parameter hides samples for which n <= noisefloor * √N, where n is the number of samples on this line, and N is the number of samples for the callee.\nmincount – Limits the printout to only those lines with at least mincount occurrences.\nrecur – Controls the recursion handling in :tree format. :off (default) prints the tree as normal. :flat instead compresses any recursion (by ip), showing the approximate effect of converting any self-recursion into an iterator. :flatc does the same but also includes collapsing of C frames (may do odd things around jl_apply).\nthreads::Union{Int,AbstractVector{Int}} – Specify which threads to include snapshots from in the report. Note that this does not control which threads samples are collected on (which may also have been collected on another machine).\ntasks::Union{Int,AbstractVector{Int}} – Specify which tasks to include snapshots from in the report. Note that this does not control which tasks samples are collected within.\n\n\n\n\n\nprint([io::IO = stdout,] data::Vector, lidict::LineInfoDict; kwargs...)\n\nPrints profiling results to io. This variant is used to examine results exported by a previous call to retrieve. Supply the vector data of backtraces and a dictionary lidict of line information.\n\nSee Profile.print([io], data) for an explanation of the valid keyword arguments.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/Profile/#Profile.init","page":"性能分析","title":"Profile.init","text":"init(; n::Integer, delay::Real)\n\nConfigure the delay between backtraces (measured in seconds), and the number n of instruction pointers that may be stored per thread. Each instruction pointer corresponds to a single line of code; backtraces generally consist of a long list of instruction pointers. Note that 6 spaces for instruction pointers per backtrace are used to store metadata and two NULL end markers. Current settings can be obtained by calling this function with no arguments, and each can be set independently using keywords or in the order (n, delay).\n\ncompat: Julia 1.8\nAs of Julia 1.8, this function allocates space for n instruction pointers per thread being profiled. Previously this was n total.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/Profile/#Profile.fetch","page":"性能分析","title":"Profile.fetch","text":"fetch(;include_meta = true) -> data\n\nReturns a copy of the buffer of profile backtraces. Note that the values in data have meaning only on this machine in the current session, because it depends on the exact memory addresses used in JIT-compiling. This function is primarily for internal use; retrieve may be a better choice for most users. By default metadata such as threadid and taskid is included. Set include_meta to false to strip metadata.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/Profile/#Profile.retrieve","page":"性能分析","title":"Profile.retrieve","text":"retrieve(; kwargs...) -> data, lidict\n\n\"Exports\" profiling results in a portable format, returning the set of all backtraces (data) and a dictionary that maps the (session-specific) instruction pointers in data to LineInfo values that store the file name, function name, and line number. This function allows you to save profiling results for future analysis.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/Profile/#Profile.callers","page":"性能分析","title":"Profile.callers","text":"callers(funcname, [data, lidict], [filename=], [linerange=]) -> Vector{Tuple{count, lineinfo}}\n\nGiven a previous profiling run, determine who called a particular function. Supplying the filename (and optionally, range of line numbers over which the function is defined) allows you to disambiguate an overloaded method. The returned value is a vector containing a count of the number of calls and line information about the caller. One can optionally supply backtrace data obtained from retrieve; otherwise, the current internal profile buffer is used.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/Profile/#Profile.clear_malloc_data","page":"性能分析","title":"Profile.clear_malloc_data","text":"clear_malloc_data()\n\nClears any stored memory allocation data when running julia with --track-allocation. Execute the command(s) you want to test (to force JIT-compilation), then call clear_malloc_data. Then execute your command(s) again, quit Julia, and examine the resulting *.mem files.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/UUIDs/#UUIDs","page":"UUIDs","title":"UUIDs","text":"","category":"section"},{"location":"stdlib/UUIDs/","page":"UUIDs","title":"UUIDs","text":"UUIDs.uuid1\nUUIDs.uuid4\nUUIDs.uuid5\nUUIDs.uuid_version","category":"page"},{"location":"stdlib/UUIDs/#UUIDs.uuid1","page":"UUIDs","title":"UUIDs.uuid1","text":"uuid1([rng::AbstractRNG]) -> UUID\n\nGenerates a version 1 (time-based) universally unique identifier (UUID), as specified by RFC 4122. Note that the Node ID is randomly generated (does not identify the host) according to section 4.5 of the RFC.\n\nThe default rng used by uuid1 is not GLOBAL_RNG and every invocation of uuid1() without an argument should be expected to return a unique identifier. Importantly, the outputs of uuid1 do not repeat even when Random.seed!(seed) is called. Currently (as of Julia 1.6), uuid1 uses Random.RandomDevice as the default rng. However, this is an implementation detail that may change in the future.\n\ncompat: Julia 1.6\nThe output of uuid1 does not depend on GLOBAL_RNG as of Julia 1.6.\n\nExamples\n\njulia> rng = MersenneTwister(1234);\n\njulia> uuid1(rng)\nUUID(\"cfc395e8-590f-11e8-1f13-43a2532b2fa8\")\n\n\n\n\n\n","category":"function"},{"location":"stdlib/UUIDs/#UUIDs.uuid4","page":"UUIDs","title":"UUIDs.uuid4","text":"uuid4([rng::AbstractRNG]) -> UUID\n\nGenerates a version 4 (random or pseudo-random) universally unique identifier (UUID), as specified by RFC 4122.\n\nThe default rng used by uuid4 is not GLOBAL_RNG and every invocation of uuid4() without an argument should be expected to return a unique identifier. Importantly, the outputs of uuid4 do not repeat even when Random.seed!(seed) is called. Currently (as of Julia 1.6), uuid4 uses Random.RandomDevice as the default rng. However, this is an implementation detail that may change in the future.\n\ncompat: Julia 1.6\nThe output of uuid4 does not depend on GLOBAL_RNG as of Julia 1.6.\n\nExamples\n\njulia> rng = MersenneTwister(1234);\n\njulia> uuid4(rng)\nUUID(\"7a052949-c101-4ca3-9a7e-43a2532b2fa8\")\n\n\n\n\n\n","category":"function"},{"location":"stdlib/UUIDs/#UUIDs.uuid5","page":"UUIDs","title":"UUIDs.uuid5","text":"uuid5(ns::UUID, name::String) -> UUID\n\nGenerates a version 5 (namespace and domain-based) universally unique identifier (UUID), as specified by RFC 4122.\n\ncompat: Julia 1.1\nThis function requires at least Julia 1.1.\n\nExamples\n\njulia> rng = MersenneTwister(1234);\n\njulia> u4 = uuid4(rng)\nUUID(\"7a052949-c101-4ca3-9a7e-43a2532b2fa8\")\n\njulia> u5 = uuid5(u4, \"julia\")\nUUID(\"086cc5bb-2461-57d8-8068-0aed7f5b5cd1\")\n\n\n\n\n\n","category":"function"},{"location":"stdlib/UUIDs/#UUIDs.uuid_version","page":"UUIDs","title":"UUIDs.uuid_version","text":"uuid_version(u::UUID) -> Int\n\nInspects the given UUID and returns its version (see RFC 4122).\n\nExamples\n\njulia> uuid_version(uuid4())\n4\n\n\n\n\n\n","category":"function"},{"location":"base/iterators/#迭代相关","page":"迭代相关","title":"迭代相关","text":"","category":"section"},{"location":"base/iterators/","page":"迭代相关","title":"迭代相关","text":"Base.Iterators.Stateful\nBase.Iterators.zip\nBase.Iterators.enumerate\nBase.Iterators.rest\nBase.Iterators.countfrom\nBase.Iterators.take\nBase.Iterators.takewhile\nBase.Iterators.drop\nBase.Iterators.dropwhile\nBase.Iterators.cycle\nBase.Iterators.repeated\nBase.Iterators.product\nBase.Iterators.flatten\nBase.Iterators.partition\nBase.Iterators.map\nBase.Iterators.filter\nBase.Iterators.accumulate\nBase.Iterators.reverse\nBase.Iterators.only\nBase.Iterators.peel","category":"page"},{"location":"base/iterators/#Base.Iterators.Stateful","page":"迭代相关","title":"Base.Iterators.Stateful","text":"Stateful(itr)\n\nThere are several different ways to think about this iterator wrapper:\n\nIt provides a mutable wrapper around an iterator and its iteration state.\nIt turns an iterator-like abstraction into a Channel-like abstraction.\nIt's an iterator that mutates to become its own rest iterator whenever an item is produced.\n\nStateful provides the regular iterator interface. Like other mutable iterators (e.g. Channel), if iteration is stopped early (e.g. by a break in a for loop), iteration can be resumed from the same spot by continuing to iterate over the same iterator object (in contrast, an immutable iterator would restart from the beginning).\n\nExamples\n\njulia> a = Iterators.Stateful(\"abcdef\");\n\njulia> isempty(a)\nfalse\n\njulia> popfirst!(a)\n'a': ASCII/Unicode U+0061 (category Ll: Letter, lowercase)\n\njulia> collect(Iterators.take(a, 3))\n3-element Vector{Char}:\n 'b': ASCII/Unicode U+0062 (category Ll: Letter, lowercase)\n 'c': ASCII/Unicode U+0063 (category Ll: Letter, lowercase)\n 'd': ASCII/Unicode U+0064 (category Ll: Letter, lowercase)\n\njulia> collect(a)\n2-element Vector{Char}:\n 'e': ASCII/Unicode U+0065 (category Ll: Letter, lowercase)\n 'f': ASCII/Unicode U+0066 (category Ll: Letter, lowercase)\n\njulia> Iterators.reset!(a); popfirst!(a)\n'a': ASCII/Unicode U+0061 (category Ll: Letter, lowercase)\n\njulia> Iterators.reset!(a, \"hello\"); popfirst!(a)\n'h': ASCII/Unicode U+0068 (category Ll: Letter, lowercase)\n\njulia> a = Iterators.Stateful([1,1,1,2,3,4]);\n\njulia> for x in a; x == 1 || break; end\n\njulia> peek(a)\n3\n\njulia> sum(a) # Sum the remaining elements\n7\n\n\n\n\n\n","category":"type"},{"location":"base/iterators/#Base.Iterators.zip","page":"迭代相关","title":"Base.Iterators.zip","text":"zip(iters...)\n\nRun multiple iterators at the same time, until any of them is exhausted. The value type of the zip iterator is a tuple of values of its subiterators.\n\nnote: Note\nzip orders the calls to its subiterators in such a way that stateful iterators will not advance when another iterator finishes in the current iteration.\n\nSee also: enumerate, splat.\n\nExamples\n\njulia> a = 1:5\n1:5\n\njulia> b = [\"e\",\"d\",\"b\",\"c\",\"a\"]\n5-element Vector{String}:\n \"e\"\n \"d\"\n \"b\"\n \"c\"\n \"a\"\n\njulia> c = zip(a,b)\nzip(1:5, [\"e\", \"d\", \"b\", \"c\", \"a\"])\n\njulia> length(c)\n5\n\njulia> first(c)\n(1, \"e\")\n\n\n\n\n\n","category":"function"},{"location":"base/iterators/#Base.Iterators.enumerate","page":"迭代相关","title":"Base.Iterators.enumerate","text":"enumerate(iter)\n\nAn iterator that yields (i, x) where i is a counter starting at 1, and x is the ith value from the given iterator. It's useful when you need not only the values x over which you are iterating, but also the number of iterations so far. Note that i may not be valid for indexing iter; it's also possible that x != iter[i], if iter has indices that do not start at 1. See the pairs(IndexLinear(), iter) method if you want to ensure that i is an index.\n\nExamples\n\njulia> a = [\"a\", \"b\", \"c\"];\n\njulia> for (index, value) in enumerate(a)\n println(\"$index $value\")\n end\n1 a\n2 b\n3 c\n\n\n\n\n\n","category":"function"},{"location":"base/iterators/#Base.Iterators.rest","page":"迭代相关","title":"Base.Iterators.rest","text":"rest(iter, state)\n\nAn iterator that yields the same elements as iter, but starting at the given state.\n\nSee also: Iterators.drop, Iterators.peel, Base.rest.\n\nExamples\n\njulia> collect(Iterators.rest([1,2,3,4], 2))\n3-element Vector{Int64}:\n 2\n 3\n 4\n\n\n\n\n\n","category":"function"},{"location":"base/iterators/#Base.Iterators.countfrom","page":"迭代相关","title":"Base.Iterators.countfrom","text":"countfrom(start=1, step=1)\n\nAn iterator that counts forever, starting at start and incrementing by step.\n\nExamples\n\njulia> for v in Iterators.countfrom(5, 2)\n v > 10 && break\n println(v)\n end\n5\n7\n9\n\n\n\n\n\n","category":"function"},{"location":"base/iterators/#Base.Iterators.take","page":"迭代相关","title":"Base.Iterators.take","text":"take(iter, n)\n\nAn iterator that generates at most the first n elements of iter.\n\nSee also: drop, peel, first, take!.\n\nExamples\n\njulia> a = 1:2:11\n1:2:11\n\njulia> collect(a)\n6-element Vector{Int64}:\n 1\n 3\n 5\n 7\n 9\n 11\n\njulia> collect(Iterators.take(a,3))\n3-element Vector{Int64}:\n 1\n 3\n 5\n\n\n\n\n\n","category":"function"},{"location":"base/iterators/#Base.Iterators.takewhile","page":"迭代相关","title":"Base.Iterators.takewhile","text":"takewhile(pred, iter)\n\nAn iterator that generates element from iter as long as predicate pred is true, afterwards, drops every element.\n\ncompat: Julia 1.4\nThis function requires at least Julia 1.4.\n\nExamples\n\njulia> s = collect(1:5)\n5-element Vector{Int64}:\n 1\n 2\n 3\n 4\n 5\n\njulia> collect(Iterators.takewhile(<(3),s))\n2-element Vector{Int64}:\n 1\n 2\n\n\n\n\n\n","category":"function"},{"location":"base/iterators/#Base.Iterators.drop","page":"迭代相关","title":"Base.Iterators.drop","text":"drop(iter, n)\n\nAn iterator that generates all but the first n elements of iter.\n\nExamples\n\njulia> a = 1:2:11\n1:2:11\n\njulia> collect(a)\n6-element Vector{Int64}:\n 1\n 3\n 5\n 7\n 9\n 11\n\njulia> collect(Iterators.drop(a,4))\n2-element Vector{Int64}:\n 9\n 11\n\n\n\n\n\n","category":"function"},{"location":"base/iterators/#Base.Iterators.dropwhile","page":"迭代相关","title":"Base.Iterators.dropwhile","text":"dropwhile(pred, iter)\n\nAn iterator that drops element from iter as long as predicate pred is true, afterwards, returns every element.\n\ncompat: Julia 1.4\nThis function requires at least Julia 1.4.\n\nExamples\n\njulia> s = collect(1:5)\n5-element Vector{Int64}:\n 1\n 2\n 3\n 4\n 5\n\njulia> collect(Iterators.dropwhile(<(3),s))\n3-element Vector{Int64}:\n 3\n 4\n 5\n\n\n\n\n\n","category":"function"},{"location":"base/iterators/#Base.Iterators.cycle","page":"迭代相关","title":"Base.Iterators.cycle","text":"cycle(iter)\n\nAn iterator that cycles through iter forever. If iter is empty, so is cycle(iter).\n\nSee also: Iterators.repeated, repeat.\n\nExamples\n\njulia> for (i, v) in enumerate(Iterators.cycle(\"hello\"))\n print(v)\n i > 10 && break\n end\nhellohelloh\n\n\n\n\n\n","category":"function"},{"location":"base/iterators/#Base.Iterators.repeated","page":"迭代相关","title":"Base.Iterators.repeated","text":"repeated(x[, n::Int])\n\nAn iterator that generates the value x forever. If n is specified, generates x that many times (equivalent to take(repeated(x), n)).\n\nSee also: Iterators.cycle, repeat.\n\nExamples\n\njulia> a = Iterators.repeated([1 2], 4);\n\njulia> collect(a)\n4-element Vector{Matrix{Int64}}:\n [1 2]\n [1 2]\n [1 2]\n [1 2]\n\n\n\n\n\n","category":"function"},{"location":"base/iterators/#Base.Iterators.product","page":"迭代相关","title":"Base.Iterators.product","text":"product(iters...)\n\nReturn an iterator over the product of several iterators. Each generated element is a tuple whose ith element comes from the ith argument iterator. The first iterator changes the fastest.\n\nSee also: zip, Iterators.flatten.\n\nExamples\n\njulia> collect(Iterators.product(1:2, 3:5))\n2×3 Matrix{Tuple{Int64, Int64}}:\n (1, 3) (1, 4) (1, 5)\n (2, 3) (2, 4) (2, 5)\n\njulia> ans == [(x,y) for x in 1:2, y in 3:5] # collects a generator involving Iterators.product\ntrue\n\n\n\n\n\n","category":"function"},{"location":"base/iterators/#Base.Iterators.flatten","page":"迭代相关","title":"Base.Iterators.flatten","text":"flatten(iter)\n\nGiven an iterator that yields iterators, return an iterator that yields the elements of those iterators. Put differently, the elements of the argument iterator are concatenated.\n\nExamples\n\njulia> collect(Iterators.flatten((1:2, 8:9)))\n4-element Vector{Int64}:\n 1\n 2\n 8\n 9\n\njulia> [(x,y) for x in 0:1 for y in 'a':'c'] # collects generators involving Iterators.flatten\n6-element Vector{Tuple{Int64, Char}}:\n (0, 'a')\n (0, 'b')\n (0, 'c')\n (1, 'a')\n (1, 'b')\n (1, 'c')\n\n\n\n\n\n","category":"function"},{"location":"base/iterators/#Base.Iterators.partition","page":"迭代相关","title":"Base.Iterators.partition","text":"partition(collection, n)\n\nIterate over a collection n elements at a time.\n\nExamples\n\njulia> collect(Iterators.partition([1,2,3,4,5], 2))\n3-element Vector{SubArray{Int64, 1, Vector{Int64}, Tuple{UnitRange{Int64}}, true}}:\n [1, 2]\n [3, 4]\n [5]\n\n\n\n\n\n","category":"function"},{"location":"base/iterators/#Base.Iterators.map","page":"迭代相关","title":"Base.Iterators.map","text":"Iterators.map(f, iterators...)\n\nCreate a lazy mapping. This is another syntax for writing (f(args...) for args in zip(iterators...)).\n\ncompat: Julia 1.6\nThis function requires at least Julia 1.6.\n\nExamples\n\njulia> collect(Iterators.map(x -> x^2, 1:3))\n3-element Vector{Int64}:\n 1\n 4\n 9\n\n\n\n\n\n","category":"function"},{"location":"base/iterators/#Base.Iterators.filter","page":"迭代相关","title":"Base.Iterators.filter","text":"Iterators.filter(flt, itr)\n\nGiven a predicate function flt and an iterable object itr, return an iterable object which upon iteration yields the elements x of itr that satisfy flt(x). The order of the original iterator is preserved.\n\nThis function is lazy; that is, it is guaranteed to return in Θ(1) time and use Θ(1) additional space, and flt will not be called by an invocation of filter. Calls to flt will be made when iterating over the returned iterable object. These calls are not cached and repeated calls will be made when reiterating.\n\nSee Base.filter for an eager implementation of filtering for arrays.\n\nExamples\n\njulia> f = Iterators.filter(isodd, [1, 2, 3, 4, 5])\nBase.Iterators.Filter{typeof(isodd), Vector{Int64}}(isodd, [1, 2, 3, 4, 5])\n\njulia> foreach(println, f)\n1\n3\n5\n\njulia> [x for x in [1, 2, 3, 4, 5] if isodd(x)] # collects a generator over Iterators.filter\n3-element Vector{Int64}:\n 1\n 3\n 5\n\n\n\n\n\n","category":"function"},{"location":"base/iterators/#Base.Iterators.accumulate","page":"迭代相关","title":"Base.Iterators.accumulate","text":"Iterators.accumulate(f, itr; [init])\n\nGiven a 2-argument function f and an iterator itr, return a new iterator that successively applies f to the previous value and the next element of itr.\n\nThis is effectively a lazy version of Base.accumulate.\n\ncompat: Julia 1.5\nKeyword argument init is added in Julia 1.5.\n\nExamples\n\njulia> a = Iterators.accumulate(+, [1,2,3,4]);\n\njulia> foreach(println, a)\n1\n3\n6\n10\n\njulia> b = Iterators.accumulate(/, (2, 5, 2, 5); init = 100);\n\njulia> collect(b)\n4-element Vector{Float64}:\n 50.0\n 10.0\n 5.0\n 1.0\n\n\n\n\n\n","category":"function"},{"location":"base/iterators/#Base.Iterators.reverse","page":"迭代相关","title":"Base.Iterators.reverse","text":"Iterators.reverse(itr)\n\nGiven an iterator itr, then reverse(itr) is an iterator over the same collection but in the reverse order.\n\nThis iterator is \"lazy\" in that it does not make a copy of the collection in order to reverse it; see Base.reverse for an eager implementation.\n\nNot all iterator types T support reverse-order iteration. If T doesn't, then iterating over Iterators.reverse(itr::T) will throw a MethodError because of the missing iterate methods for Iterators.Reverse{T}. (To implement these methods, the original iterator itr::T can be obtained from r = Iterators.reverse(itr) by r.itr.)\n\nExamples\n\njulia> foreach(println, Iterators.reverse(1:5))\n5\n4\n3\n2\n1\n\n\n\n\n\n","category":"function"},{"location":"base/iterators/#Base.Iterators.only","page":"迭代相关","title":"Base.Iterators.only","text":"only(x)\n\nReturn the one and only element of collection x, or throw an ArgumentError if the collection has zero or multiple elements.\n\nSee also first, last.\n\ncompat: Julia 1.4\nThis method requires at least Julia 1.4.\n\nExamples\n\njulia> only([\"a\"])\n\"a\"\n\njulia> only(\"a\")\n'a': ASCII/Unicode U+0061 (category Ll: Letter, lowercase)\n\njulia> only(())\nERROR: ArgumentError: Tuple contains 0 elements, must contain exactly 1 element\nStacktrace:\n[...]\n\njulia> only(('a', 'b'))\nERROR: ArgumentError: Tuple contains 2 elements, must contain exactly 1 element\nStacktrace:\n[...]\n\n\n\n\n\n","category":"function"},{"location":"base/iterators/#Base.Iterators.peel","page":"迭代相关","title":"Base.Iterators.peel","text":"peel(iter)\n\nReturns the first element and an iterator over the remaining elements.\n\nIf the iterator is empty return nothing (like iterate).\n\ncompat: Julia 1.7\nPrior versions throw a BoundsError if the iterator is empty.\n\nSee also: Iterators.drop, Iterators.take.\n\nExamples\n\njulia> (a, rest) = Iterators.peel(\"abc\");\n\njulia> a\n'a': ASCII/Unicode U+0061 (category Ll: Letter, lowercase)\n\njulia> collect(rest)\n2-element Vector{Char}:\n 'b': ASCII/Unicode U+0062 (category Ll: Letter, lowercase)\n 'c': ASCII/Unicode U+0063 (category Ll: Letter, lowercase)\n\n\n\n\n\n","category":"function"},{"location":"#Julia-1.7-中文文档","page":"主页","title":"Julia 1.7 中文文档","text":"","category":"section"},{"location":"","page":"主页","title":"主页","text":"欢迎来到 Julia 1.7 中文文档(PDF版本)!","category":"page"},{"location":"","page":"主页","title":"主页","text":"请先阅读 Julia 1.0 正式发布博文 以获得对这门语言的总体概观。我们推荐刚刚开始学习 Julia 语言的朋友阅读中文社区提供的 Julia入门指引,也推荐你在中文论坛对遇到的问题进行提问。","category":"page"},{"location":"","page":"主页","title":"主页","text":"tip: 镜像加速\n使用镜像站来加速下载几乎是每个国内用户都需要了解的事情,关于镜像站的使用说明及汇总可以在 Julia PkgServer 镜像服务及镜像站索引 中可以看到。","category":"page"},{"location":"","page":"主页","title":"主页","text":"note: 关于中文文档\nJulia 语言相关的本地化工作是一个由社区驱动的开源项目 JuliaZH.jl,旨在方便 Julia 的中文用户。我们目前使用 Transifex 作为翻译平台。翻译工作正在进行,有任何疑问或建议请到社区论坛文档区反馈。若有意参与翻译工作,请参考翻译指南。","category":"page"},{"location":"#鸣谢","page":"主页","title":"鸣谢","text":"","category":"section"},{"location":"","page":"主页","title":"主页","text":"\n\n","category":"page"},{"location":"","page":"主页","title":"主页","text":"特别感谢集智俱乐部对Julia中文文档和Julia中文论坛相关服务器资源的赞助!","category":"page"},{"location":"","page":"主页","title":"主页","text":"❤❤❤如果您或您所属的组织有意资助Julia中文社区的发展,欢迎前往论坛的社区板块发帖咨询。❤❤❤","category":"page"},{"location":"#其它中文资料","page":"主页","title":"其它中文资料","text":"","category":"section"},{"location":"","page":"主页","title":"主页","text":"Julia Data Science 中文版","category":"page"},{"location":"#man-introduction","page":"主页","title":"简介","text":"","category":"section"},{"location":"","page":"主页","title":"主页","text":"科学计算对性能一直有着最高的需求,但目前各领域的专家却大量使用较慢的动态语言来开展他们的日常工作。 偏爱动态语言有很多很好的理由,因此我们不会舍弃动态的特性。 幸运的是,现代编程语言设计与编译器技术可以大大消除性能折衷(trade-off),并提供有足够生产力的单一环境进行原型设计,而且能高效地部署性能密集型应用程序。 Julia 语言在这其中扮演了这样一个角色:它是一门灵活的动态语言,适合用于科学计算和数值计算,并且性能可与传统的静态类型语言媲美。","category":"page"},{"location":"","page":"主页","title":"主页","text":"由于 Julia 的编译器和其它语言比如 Python 或 R 的解释器有所不同,一开始你可能发现 Julia 的性能并不是很突出。 如果你觉得速度有点慢,我们强烈建议在尝试其他功能前,先读一读文档中的提高性能的窍门。 在理解了 Julia 的运作方式后,写出和 C 一样快的代码对你而言就是小菜一碟。","category":"page"},{"location":"","page":"主页","title":"主页","text":"Julia 拥有可选类型标注和多重派发这两个特性,同时还拥有很棒的性能。 这些都得归功于使用 LLVM 实现的类型推导和即时编译(JIT)技术。Julia 是一门支持过程式、函数式和面向对象的多范式语言。 它像 R、MATLAB 和 Python 一样简单,在高级数值计算方面有丰富的表现力,并且支持通用编程。 为了实现这个目标,Julia 以数学编程语言(mathematical programming languages)为基础,同时也参考了不少流行的动态语言,例如 Lisp、Perl、Python、Lua、和 Ruby。","category":"page"},{"location":"","page":"主页","title":"主页","text":"Julia 与传统动态语言最重要的区别是:","category":"page"},{"location":"","page":"主页","title":"主页","text":"核心语言很小:标准库是用 Julia 自身写的,包括整数运算这样的基础运算\n丰富的基础类型:既可用于定义和描述对象,也可用于做可选的类型标注\n通过多重派发,可以根据类型的不同,来调用同名函数的不同实现\n为不同的参数类型,自动生成高效、专用的代码\n接近 C 语言的性能","category":"page"},{"location":"","page":"主页","title":"主页","text":"尽管人们有时会说动态语言是“无类型的”,但实际上绝对不是这样的:每一个对象都有一个类型,无论它是基础的类型(primitive)还是用户自定义的类型。 大多数的动态语言都缺乏类型声明,这意味着程序员无法告诉编译器值的类型,也就无法显式地讨论类型。 另一方面,在静态语言中,往往必须标注对象的类型。但类型只在编译期才存在,而无法在运行时进行操作和表达。 而在 Julia 中,类型本身是运行时的对象,并可用于向编译器传达信息。","category":"page"},{"location":"","page":"主页","title":"主页","text":"类型系统和多重派发是 Julia 语言最主要的特征,但一般不需要显式地手动标注或使用:函数通过函数名称和不同类型参数的组合进行定义,在调用时会派发到最接近(most specific)的定义上去。这样的编程模型非常适合数学化的编程,尤其是在传统的面向对象派发中,一些函数的第一个变量理论上并不“拥有”这样一个操作时。 在 Julia 中运算符只是函数的一个特殊标记——例如,为用户定义的新类型添加加法运算,你只要为 + 函数定义一个新的方法就可以了。 已有的代码就可以无缝接入这个新的类型。","category":"page"},{"location":"","page":"主页","title":"主页","text":"Julia 在设计之初就非常看重性能,再加上它的动态类型推导(可以被可选的类型标注增强),使得 Julia 的计算性能超过了其它的动态语言,甚至能够与静态编译语言竞争。对于大型数值问题,速度一直都是,也一直会是一个重要的关注点:在过去的几十年里,需要处理的数据量很容易与摩尔定律保持同步。","category":"page"},{"location":"","page":"主页","title":"主页","text":"Julia 的目标是创建一个前所未有的集易用、强大、高效于一体的语言。除此之外,Julia 还拥有以下优势:","category":"page"},{"location":"","page":"主页","title":"主页","text":"采用 MIT 许可证:免费又开源\n用户自定义类型的速度与兼容性和内建类型一样好\n无需特意编写向量化的代码:非向量化的代码就很快\n为并行计算和分布式计算设计\n轻量级的“绿色”线程:协程\n低调又牛逼的类型系统\n优雅、可扩展的类型转换和类型提升\n对 Unicode 的有效支持,包括但不限于 UTF-8\n直接调用 C 函数,无需封装或调用特别的 API\n像 Shell 一样强大的管理其他进程的能力\n像 Lisp 一样的宏和其他元编程工具","category":"page"},{"location":"devdocs/isbitsunionarrays/#isbits-Union-Optimizations","page":"isbits Union Optimizations","title":"isbits Union Optimizations","text":"","category":"section"},{"location":"devdocs/isbitsunionarrays/","page":"isbits Union Optimizations","title":"isbits Union Optimizations","text":"In Julia, the Array type holds both \"bits\" values as well as heap-allocated \"boxed\" values. The distinction is whether the value itself is stored inline (in the direct allocated memory of the array), or if the memory of the array is simply a collection of pointers to objects allocated elsewhere. In terms of performance, accessing values inline is clearly an advantage over having to follow a pointer to the actual value. The definition of \"isbits\" generally means any Julia type with a fixed, determinate size, meaning no \"pointer\" fields, see ?isbitstype.","category":"page"},{"location":"devdocs/isbitsunionarrays/","page":"isbits Union Optimizations","title":"isbits Union Optimizations","text":"Julia also supports Union types, quite literally the union of a set of types. Custom Union type definitions can be extremely handy for applications wishing to \"cut across\" the nominal type system (i.e. explicit subtype relationships) and define methods or functionality on these, otherwise unrelated, set of types. A compiler challenge, however, is in determining how to treat these Union types. The naive approach (and indeed, what Julia itself did pre-0.7), is to simply make a \"box\" and then a pointer in the box to the actual value, similar to the previously mentioned \"boxed\" values. This is unfortunate, however, because of the number of small, primitive \"bits\" types (think UInt8, Int32, Float64, etc.) that would easily fit themselves inline in this \"box\" without needing any indirection for value access. There are two main ways Julia can take advantage of this optimization as of 0.7: isbits Union fields in types, and isbits Union Arrays.","category":"page"},{"location":"devdocs/isbitsunionarrays/#isbits-Union-Structs","page":"isbits Union Optimizations","title":"isbits Union Structs","text":"","category":"section"},{"location":"devdocs/isbitsunionarrays/","page":"isbits Union Optimizations","title":"isbits Union Optimizations","text":"Julia now includes an optimization wherein \"isbits Union\" fields in types (mutable struct, struct, etc.) will be stored inline. This is accomplished by determining the \"inline size\" of the Union type (e.g. Union{UInt8, Int16} will have a size of two bytes, which represents the size needed of the largest Union type Int16), and in addition, allocating an extra \"type tag byte\" (UInt8), whose value signals the type of the actual value stored inline of the \"Union bytes\". The type tag byte value is the index of the actual value's type in the Union type's order of types. For example, a type tag value of 0x02 for a field with type Union{Nothing, UInt8, Int16} would indicate that an Int16 value is stored in the 16 bits of the field in the structure's memory; a 0x01 value would indicate that a UInt8 value was stored in the first 8 bits of the 16 bits of the field's memory. Lastly, a value of 0x00 signals that the nothing value will be returned for this field, even though, as a singleton type with a single type instance, it technically has a size of 0. The type tag byte for a type's Union field is stored directly after the field's computed Union memory.","category":"page"},{"location":"devdocs/isbitsunionarrays/#isbits-Union-Arrays","page":"isbits Union Optimizations","title":"isbits Union Arrays","text":"","category":"section"},{"location":"devdocs/isbitsunionarrays/","page":"isbits Union Optimizations","title":"isbits Union Optimizations","text":"Julia can now also store \"isbits Union\" values inline in an Array, as opposed to requiring an indirection box. The optimization is accomplished by storing an extra \"type tag array\" of bytes, one byte per array element, alongside the bytes of the actual array data. This type tag array serves the same function as the type field case: its value signals the type of the actual stored Union value in the array. In terms of layout, a Julia Array can include extra \"buffer\" space before and after its actual data values, which are tracked in the a->offset and a->maxsize fields of the jl_array_t* type. The \"type tag array\" is treated exactly as another jl_array_t*, but which shares the same a->offset, a->maxsize, and a->len fields. So the formula to access an isbits Union Array's type tag bytes is a->data + (a->maxsize - a->offset) * a->elsize + a->offset; i.e. the Array's a->data pointer is already shifted by a->offset, so correcting for that, we follow the data all the way to the max of what it can hold a->maxsize, then adjust by a->offset more bytes to account for any present \"front buffering\" the array might be doing. This layout in particular allows for very efficient resizing operations as the type tag data only ever has to move when the actual array's data has to move.","category":"page"},{"location":"manual/environment-variables/#环境变量","page":"环境变量","title":"环境变量","text":"","category":"section"},{"location":"manual/environment-variables/","page":"环境变量","title":"环境变量","text":"Julia 可以配置许多环境变量,一种常见的方式是直接配置操作系统环境变量,另一种更便携的方式是在 Julia 中配置。假设你要将环境变量 JULIA_EDITOR 设置为 vim,可以直接在 REPL 中输入 ENV[\"JULIA_EDITOR\"] = \"vim\"(请根据具体情况对此进行修改),也可以将其添加到用户主目录中的配置文件 ~/.julia/config/startup.jl,这样做会使其永久生效。环境变量的当前值是通过执行 ENV[\"JULIA_EDITOR\"] 来确定的。","category":"page"},{"location":"manual/environment-variables/","page":"环境变量","title":"环境变量","text":"Julia 使用的环境变量通常以 JULIA 开头。如果调用 InteractiveUtils.versioninfo 时使用关键字参数 verbose = true,那么输出结果将列出与 Julia 相关的已定义环境变量,即包括那些名称中包含 JULIA 的环境变量。","category":"page"},{"location":"manual/environment-variables/","page":"环境变量","title":"环境变量","text":"note: Note\n某些变量需要在 Julia 启动之前设置,比如 JULIA_NUM_THREADS 和 JULIA_PROJECT,因为在启动过程中将这些变量添加到 ~/.julia/config/startup.jl 中为时已晚。在 Bash 中,环境变量可以手动设置,这可通过在 Julia 启动前运行诸如 export JULIA_NUM_THREADS=4 的命令,亦可通过向 ~/.bashrc 或 ~/.bash_profile 添加相同命令来在 Bash 每次启动时设置该变量。","category":"page"},{"location":"manual/environment-variables/#文件位置","page":"环境变量","title":"文件位置","text":"","category":"section"},{"location":"manual/environment-variables/#JULIA_BINDIR","page":"环境变量","title":"JULIA_BINDIR","text":"","category":"section"},{"location":"manual/environment-variables/","page":"环境变量","title":"环境变量","text":"包含 Julia 可执行文件的目录的绝对路径,它会设置全局变量 Sys.BINDIR。$JULIA_BINDIR 如果没有设置,那么 Julia 会在运行时确定 Sys.BINDIR 的值。","category":"page"},{"location":"manual/environment-variables/","page":"环境变量","title":"环境变量","text":"在默认情况下,可执行文件是指:","category":"page"},{"location":"manual/environment-variables/","page":"环境变量","title":"环境变量","text":"$JULIA_BINDIR/julia\n$JULIA_BINDIR/julia-debug","category":"page"},{"location":"manual/environment-variables/","page":"环境变量","title":"环境变量","text":"全局变量 Base.DATAROOTDIR 是一个从 Sys.BINDIR 到 Julia 数据目录的相对路径。","category":"page"},{"location":"manual/environment-variables/","page":"环境变量","title":"环境变量","text":"$JULIA_BINDIR/$DATAROOTDIR/julia/base","category":"page"},{"location":"manual/environment-variables/","page":"环境变量","title":"环境变量","text":"上述路径是 Julia 最初搜索源文件的路径(通过 Base.find_source_file())。","category":"page"},{"location":"manual/environment-variables/","page":"环境变量","title":"环境变量","text":"同样,全局变量 Base.SYSCONFDIR 是一个到配置文件目录的相对路径。在默认情况下,Julia 会在下列文件中搜索 startup.jl 文件(通过 Base.load_julia_startup())","category":"page"},{"location":"manual/environment-variables/","page":"环境变量","title":"环境变量","text":"$JULIA_BINDIR/$SYSCONFDIR/julia/startup.jl\n$JULIA_BINDIR/../etc/julia/startup.jl","category":"page"},{"location":"manual/environment-variables/","page":"环境变量","title":"环境变量","text":"例如,在 Linux 下安装的 Julia 可执行文件位于 /bin/julia,DATAROOTDIR 为 ../share,SYSCONFDIR 为 ../etc,JULIA_BINDIR 会被设置为 /bin,会有一个源文件搜索路径:","category":"page"},{"location":"manual/environment-variables/","page":"环境变量","title":"环境变量","text":"/share/julia/base","category":"page"},{"location":"manual/environment-variables/","page":"环境变量","title":"环境变量","text":"和一个全局配置文件搜索路径:","category":"page"},{"location":"manual/environment-variables/","page":"环境变量","title":"环境变量","text":"/etc/julia/startup.jl","category":"page"},{"location":"manual/environment-variables/#JULIA_PROJECT","page":"环境变量","title":"JULIA_PROJECT","text":"","category":"section"},{"location":"manual/environment-variables/","page":"环境变量","title":"环境变量","text":"指示哪个项目应该是初始活动项目的目录路径。 设置这个环境变量和指定--project启动选项效果一样,但是--project优先级更高。 如果变量设置为 @.,那么 Julia 会尝试从当前目录及其父目录中查找包含 Project.toml 或 JuliaProject.toml 文件的项目目录。 另请参阅有关 代码加载 的章节。","category":"page"},{"location":"manual/environment-variables/","page":"环境变量","title":"环境变量","text":"note: Note\nJULIA_PROJECT 必须在启动 julia 前定义;于 startup.jl 中定义它对于启动的过程为时已晚。","category":"page"},{"location":"manual/environment-variables/#JULIA_LOAD_PATH","page":"环境变量","title":"JULIA_LOAD_PATH","text":"","category":"section"},{"location":"manual/environment-variables/","page":"环境变量","title":"环境变量","text":"JULIA_LOAD_PATH 环境变量用于补充全局的 Julia 变量 LOAD_PATH ,该变量可用于确定通过 import 和 using 可以加载哪些包(请参阅 Code Loading)。","category":"page"},{"location":"manual/environment-variables/","page":"环境变量","title":"环境变量","text":"与 shell 使用的 PATH 变量不同, 在 JULIA_LOAD_PATH 中的空条目将会在填充 LOAD_PATH 时被扩展为 LOAD_PATH 的默认值 [\"@\", \"@v#.#\", \"@stdlib\"] 。这样,无论 JULIA_LOAD_PATH 是否已被设置,均可以使用 shell 脚本轻松地在加载路径前面或后面添加值。例如要将 /foo/bar 添加到 LOAD_PATH 之前,只需要使用下列脚本:","category":"page"},{"location":"manual/environment-variables/","page":"环境变量","title":"环境变量","text":"export JULIA_LOAD_PATH=\"/foo/bar:$JULIA_LOAD_PATH\"","category":"page"},{"location":"manual/environment-variables/","page":"环境变量","title":"环境变量","text":"如果已经设置了 JULIA_LOAD_PATH 环境变量,那么 /foo/bar 将被添加在原有值之前。另一方面,如果 JULIA_LOAD_PATH 尚未设置,那么它会被设置为 /foo/bar: ,而这将使用 LOAD_PATH 的值扩展为 [\"/foo/bar\", \"@\", \"@v#.#\", \"@stdlib\"] 。如果 JULIA_LOAD_PATH 被设置为空字符串,那么它将被扩展为一个空的 LOAD_PATH 数组。换句话说,这个空字符串数组将被认为是零元素的数组,而非是一个空字符串单元素的数组。使用这样的加载行为是为了可以通过环境变量设置空的加载路径。如果你需要使用默认的加载路径,请不要设置这一环境变量,如果它必须有值,那么可将其设置为字符串 : 。","category":"page"},{"location":"manual/environment-variables/","page":"环境变量","title":"环境变量","text":"note: Note\n在 Windows 上,路径元素由 ; 字符分隔,就像 Windows 上的大多数路径列表一样。 将上一段中的 : 替换为 ;。","category":"page"},{"location":"manual/environment-variables/#JULIA_DEPOT_PATH","page":"环境变量","title":"JULIA_DEPOT_PATH","text":"","category":"section"},{"location":"manual/environment-variables/","page":"环境变量","title":"环境变量","text":"JULIA_DEPOT_PATH 环境变量用于填充全局的 Julia 变量 DEPOT_PATH ,该变量用于控制包管理器以及 Juila 代码加载机制在何处查找包注册表、已安装的包、命名环境、克隆的存储库、缓存的预编译包映像、配置文件和 REPL 历史记录文件的默认位置。","category":"page"},{"location":"manual/environment-variables/","page":"环境变量","title":"环境变量","text":"与 shell 使用的 PATH 变量不同,但与 JULIA_LOAD_PATH 类似, 在 JULIA_DEPOT_PATH 中的空条目将会被扩展为 DEPOT_PATH 的默认值。这样,无论 JULIA_DEPOT_PATH 是否已被设置,均可以使用 shell 脚本轻松地在仓库路径前面或后面添加值。例如要将 /foo/bar 添加到 DEPOT_PATH 之前,只需要使用下列脚本:","category":"page"},{"location":"manual/environment-variables/","page":"环境变量","title":"环境变量","text":"export JULIA_DEPOT_PATH=\"/foo/bar:$JULIA_DEPOT_PATH\"","category":"page"},{"location":"manual/environment-variables/","page":"环境变量","title":"环境变量","text":"如果已经设置了 JULIA_DEPOT_PATH 环境变量,那么 /foo/bar 将被添加在原有值之前。另一方面,如果 JULIA_DEPOT_PATH 尚未设置,那么它会被设置为 /foo/bar: ,而这将使 /foo/bar 被添加到默认仓库路径之前。如果 JULIA_DEPOT_PATH 被设置为空字符串,那么它将扩展为一个空的 DEPOT_PATH 数组。换句话说,这个空字符串数组将被认为是零元素的数组,而非是一个空字符串单元素的数组。使用这样的加载行为是为了可以通过环境变量设置空的仓库路径。如果你需要使用默认的仓库路径,请不要设置这一环境变量,如果它必须有值,那么可将其设置为字符串 : 。","category":"page"},{"location":"manual/environment-variables/","page":"环境变量","title":"环境变量","text":"note: Note\n在 Windows 上,路径元素由 ; 字符分隔,就像 Windows 上的大多数路径列表一样。 将上一段中的 : 替换为 ;。","category":"page"},{"location":"manual/environment-variables/#JULIA_HISTORY","page":"环境变量","title":"JULIA_HISTORY","text":"","category":"section"},{"location":"manual/environment-variables/","page":"环境变量","title":"环境变量","text":"REPL 历史文件中 REPL.find_hist_file() 的绝对路径。如果没有设置 $JULIA_HISTORY,那么 REPL.find_hist_file() 默认为","category":"page"},{"location":"manual/environment-variables/","page":"环境变量","title":"环境变量","text":"$(DEPOT_PATH[1])/logs/repl_history.jl","category":"page"},{"location":"manual/environment-variables/#JULIA_PKG_SERVER","page":"环境变量","title":"JULIA_PKG_SERVER","text":"","category":"section"},{"location":"manual/environment-variables/","page":"环境变量","title":"环境变量","text":"由Pkg.jl 使用,用于下载软件包和更新注册表。默认情况下,Pkg 使用 https://pkg.julialang.org 来获取 Julia 包。你可以使用此环境变量来选择不同的服务器。 此外,你可以禁用 PkgServer 协议的使用,并通过设置直接从它们的主机(GitHub、GitLab 等)访问包:","category":"page"},{"location":"manual/environment-variables/","page":"环境变量","title":"环境变量","text":"export JULIA_PKG_SERVER=\"\"","category":"page"},{"location":"manual/environment-variables/#外部应用","page":"环境变量","title":"外部应用","text":"","category":"section"},{"location":"manual/environment-variables/#JULIA_SHELL","page":"环境变量","title":"JULIA_SHELL","text":"","category":"section"},{"location":"manual/environment-variables/","page":"环境变量","title":"环境变量","text":"Julia 用来执行外部命令的 shell 的绝对路径(通过 Base.repl_cmd())。默认为环境变量 $SHELL,如果 $SHELL 未设置,则为 /bin/sh。","category":"page"},{"location":"manual/environment-variables/","page":"环境变量","title":"环境变量","text":"note: Note\n在 Windows 上,此环境变量将被忽略,并且外部命令会直接被执行。","category":"page"},{"location":"manual/environment-variables/#JULIA_EDITOR","page":"环境变量","title":"JULIA_EDITOR","text":"","category":"section"},{"location":"manual/environment-variables/","page":"环境变量","title":"环境变量","text":"InteractiveUtils.editor() 的返回值–编辑器,例如,InteractiveUtils.edit,会启动偏好编辑器,比如 vim。","category":"page"},{"location":"manual/environment-variables/","page":"环境变量","title":"环境变量","text":"$JULIA_EDITOR 优先于 $VISUAL,而后者优先于 $EDITOR。如果这些环境变量都没有设置,那么在 Windows 和 OS X 上会设置为 open,或者 /etc/alternatives/editor(如果存在的话),否则为 emacs。","category":"page"},{"location":"manual/environment-variables/#并行","page":"环境变量","title":"并行","text":"","category":"section"},{"location":"manual/environment-variables/#JULIA_CPU_THREADS","page":"环境变量","title":"JULIA_CPU_THREADS","text":"","category":"section"},{"location":"manual/environment-variables/","page":"环境变量","title":"环境变量","text":"改写全局变量 Base.Sys.CPU_THREADS,逻辑 CPU 核心数。","category":"page"},{"location":"manual/environment-variables/#JULIA_WORKER_TIMEOUT","page":"环境变量","title":"JULIA_WORKER_TIMEOUT","text":"","category":"section"},{"location":"manual/environment-variables/","page":"环境变量","title":"环境变量","text":"一个 Float64 值,用来确定 Distributed.worker_timeout() 的值(默认:60.0)。此函数提供 worker 进程在死亡之前等待 master 进程建立连接的秒数。","category":"page"},{"location":"manual/environment-variables/#JULIA_NUM_THREADS","page":"环境变量","title":"JULIA_NUM_THREADS","text":"","category":"section"},{"location":"manual/environment-variables/","page":"环境变量","title":"环境变量","text":"一个无符号 64 位整数 (uint64_t),用于设置 Julia 可用的最大线程数。 如果$JULIA_NUM_THREADS 不为正数或未设置,或者无法通过系统调用确定CPU 线程数,则将线程数设置为1。","category":"page"},{"location":"manual/environment-variables/","page":"环境变量","title":"环境变量","text":"如果$JULIA_NUM_THREADS 设置为auto,则线程数将设置为CPU线程数。","category":"page"},{"location":"manual/environment-variables/","page":"环境变量","title":"环境变量","text":"note: Note\nJULIA_NUM_THREADS 必须在启动 julia 之前定义; 启动过程中在startup.jl 中定义它是不能奏效的。","category":"page"},{"location":"manual/environment-variables/","page":"环境变量","title":"环境变量","text":"compat: Julia 1.5\n在 Julia 1.5 和更高版本中,也可在启动时使用 -t/--threads 命令行参数指定线程数。","category":"page"},{"location":"manual/environment-variables/","page":"环境变量","title":"环境变量","text":"compat: Julia 1.7\n$JULIA_NUM_THREADS 的 auto 值需要 Julia 1.7 或更高版本。","category":"page"},{"location":"manual/environment-variables/#JULIA_THREAD_SLEEP_THRESHOLD","page":"环境变量","title":"JULIA_THREAD_SLEEP_THRESHOLD","text":"","category":"section"},{"location":"manual/environment-variables/","page":"环境变量","title":"环境变量","text":"如果被设置为字符串,并且以大小写敏感的子字符串 \"infinite\" 开头,那么自旋线程从不睡眠。否则,$JULIA_THREAD_SLEEP_THRESHOLD 被解释为一个无符号 64 位整数(uint64_t),并且提供以纳秒为单位的自旋线程睡眠的时间量。","category":"page"},{"location":"manual/environment-variables/#JULIA_EXCLUSIVE","page":"环境变量","title":"JULIA_EXCLUSIVE","text":"","category":"section"},{"location":"manual/environment-variables/","page":"环境变量","title":"环境变量","text":"如果设置为 0 以外的任何值,那么 Julia 的线程策略与在专用计算机上一致:主线程在 proc 0 上且线程间是关联的。否则,Julia 让操作系统处理线程策略。","category":"page"},{"location":"manual/environment-variables/#REPL-格式化输出","page":"环境变量","title":"REPL 格式化输出","text":"","category":"section"},{"location":"manual/environment-variables/","page":"环境变量","title":"环境变量","text":"决定 REPL 应当如何格式化输出的环境变量。通常,这些变量应当被设置为 ANSI 终端转义序列。Julia 提供了具有相同功能的高级接口;请参阅 Julia REPL 章节。","category":"page"},{"location":"manual/environment-variables/#JULIA_ERROR_COLOR","page":"环境变量","title":"JULIA_ERROR_COLOR","text":"","category":"section"},{"location":"manual/environment-variables/","page":"环境变量","title":"环境变量","text":"Base.error_color()(默认值:亮红,\"\\033[91m\"),errors 在终端中的格式。","category":"page"},{"location":"manual/environment-variables/#JULIA_WARN_COLOR","page":"环境变量","title":"JULIA_WARN_COLOR","text":"","category":"section"},{"location":"manual/environment-variables/","page":"环境变量","title":"环境变量","text":"Base.warn_color()(默认值:黄,\"\\033[93m\"),warnings 在终端中的格式。","category":"page"},{"location":"manual/environment-variables/#JULIA_INFO_COLOR","page":"环境变量","title":"JULIA_INFO_COLOR","text":"","category":"section"},{"location":"manual/environment-variables/","page":"环境变量","title":"环境变量","text":"Base.info_color()(默认值:青,\"\\033[36m\"),info 在终端中的格式。","category":"page"},{"location":"manual/environment-variables/#JULIA_INPUT_COLOR","page":"环境变量","title":"JULIA_INPUT_COLOR","text":"","category":"section"},{"location":"manual/environment-variables/","page":"环境变量","title":"环境变量","text":"Base.input_color()(默认值:标准,\"\\033[0m\"),在终端中,输入应有的格式。","category":"page"},{"location":"manual/environment-variables/#JULIA_ANSWER_COLOR","page":"环境变量","title":"JULIA_ANSWER_COLOR","text":"","category":"section"},{"location":"manual/environment-variables/","page":"环境变量","title":"环境变量","text":"Base.answer_color()(默认值:标准,\"\\033[0m\"),在终端中,输出应有的格式。","category":"page"},{"location":"manual/environment-variables/#调试和性能分析","page":"环境变量","title":"调试和性能分析","text":"","category":"section"},{"location":"manual/environment-variables/#JULIA_DEBUG","page":"环境变量","title":"JULIA_DEBUG","text":"","category":"section"},{"location":"manual/environment-variables/","page":"环境变量","title":"环境变量","text":"为文件或模块启动调试日志记录,请参阅 日志 了解更多信息。","category":"page"},{"location":"manual/environment-variables/#JULIA_GC_ALLOC_POOL,-JULIA_GC_ALLOC_OTHER,-JULIA_GC_ALLOC_PRINT","page":"环境变量","title":"JULIA_GC_ALLOC_POOL, JULIA_GC_ALLOC_OTHER, JULIA_GC_ALLOC_PRINT","text":"","category":"section"},{"location":"manual/environment-variables/","page":"环境变量","title":"环境变量","text":"这些环境变量取值为字符串,可以以字符 ‘r’ 开头,后接一个由三个带符号 64 位整数(int64_t)组成的、以冒号分割的列表的插值字符串。这个整数的三元组 a:b:c 代表算术序列 a, a + b, a + 2*b, ... c。","category":"page"},{"location":"manual/environment-variables/","page":"环境变量","title":"环境变量","text":"如果是第 n 次调用 jl_gc_pool_alloc(),并且 n 属于 $JULIA_GC_ALLOC_POOL 代表的算术序列, 那么垃圾回收是强制的。\n如果是第 n 次调用 maybe_collect(),并且 n 属于 $JULIA_GC_ALLOC_OTHER 代表的算术序列,那么垃圾 回收是强制的。\n如果是第 n 次调用 jl_gc_alloc(),并且 n 属于 $JULIA_GC_ALLOC_PRINT 代表的算术序列,那么 调用 jl_gc_pool_alloc() 和 maybe_collect() 的次数会 被打印。","category":"page"},{"location":"manual/environment-variables/","page":"环境变量","title":"环境变量","text":"如果这些环境变量的值以字符 ‘r' 开头,那么垃圾回收事件间的间隔是随机的。","category":"page"},{"location":"manual/environment-variables/","page":"环境变量","title":"环境变量","text":"note: Note\n这些环境变量生效要求 Julia 在编译时带有垃圾收集调试支持(也就是,在构建配置中将 WITH_GC_DEBUG_ENV 设置为 1)。","category":"page"},{"location":"manual/environment-variables/#JULIA_GC_NO_GENERATIONAL","page":"环境变量","title":"JULIA_GC_NO_GENERATIONAL","text":"","category":"section"},{"location":"manual/environment-variables/","page":"环境变量","title":"环境变量","text":"如果设置为 0 以外的任何值,那么 Julia 的垃圾收集器将从不执行「快速扫描」内存。","category":"page"},{"location":"manual/environment-variables/","page":"环境变量","title":"环境变量","text":"note: Note\n此环境变量生效要求 Julia 在编译时带有垃圾收集调试支持(也就是,在构建配置中将 WITH_GC_DEBUG_ENV 设置为 1)。","category":"page"},{"location":"manual/environment-variables/#JULIA_GC_WAIT_FOR_DEBUGGER","page":"环境变量","title":"JULIA_GC_WAIT_FOR_DEBUGGER","text":"","category":"section"},{"location":"manual/environment-variables/","page":"环境变量","title":"环境变量","text":"如果设置为 0 以外的任何值,Julia 的垃圾收集器每当出现严重错误时将等待调试器连接而不是中止。","category":"page"},{"location":"manual/environment-variables/","page":"环境变量","title":"环境变量","text":"note: Note\n此环境变量生效要求 Julia 在编译时带有垃圾收集调试支持(也就是,在构建配置中将 WITH_GC_DEBUG_ENV 设置为 1)。","category":"page"},{"location":"manual/environment-variables/#ENABLE_JITPROFILING","page":"环境变量","title":"ENABLE_JITPROFILING","text":"","category":"section"},{"location":"manual/environment-variables/","page":"环境变量","title":"环境变量","text":"如果设置为 0 以外的任何值,那么编译器将为即时(JIT)性能分析创建并注册一个事件监听器。","category":"page"},{"location":"manual/environment-variables/","page":"环境变量","title":"环境变量","text":"note: Note\n此环境变量仅在使用 JIT 性能分析支持编译 Julia 时有效,使用如下之一:Intel's VTune™ Amplifier(USE_INTEL_JITEVENTS 在配置中设置为1), 或\nOProfile(USE_OPROFILE_JITEVENTS 在配置中设置为1)。\nPerf (USE_PERF_JITEVENTS 在构建配置中设置为 1)。 默认情况下启用此集成。","category":"page"},{"location":"manual/environment-variables/#ENABLE_GDBLISTENER","page":"环境变量","title":"ENABLE_GDBLISTENER","text":"","category":"section"},{"location":"manual/environment-variables/","page":"环境变量","title":"环境变量","text":"如果设置为除0之外的任何内容,则在发布版本上启用 Julia 代码的 GDB 注册。 在 Julia 的调试版本中,这始终处于启用状态。 推荐与 -g 2 一起使用。","category":"page"},{"location":"manual/environment-variables/#JULIA_LLVM_ARGS","page":"环境变量","title":"JULIA_LLVM_ARGS","text":"","category":"section"},{"location":"manual/environment-variables/","page":"环境变量","title":"环境变量","text":"传递给 LLVM 后端的参数。","category":"page"},{"location":"manual/faq/#常见问题","page":"常见问题","title":"常见问题","text":"","category":"section"},{"location":"manual/faq/#概述","page":"常见问题","title":"概述","text":"","category":"section"},{"location":"manual/faq/#Julia-的名字来源于某人或某事物吗?","page":"常见问题","title":"Julia 的名字来源于某人或某事物吗?","text":"","category":"section"},{"location":"manual/faq/","page":"常见问题","title":"常见问题","text":"不。","category":"page"},{"location":"manual/faq/#为什么不把-Matlab/Python/R-或者其他语言的代码编译为-Julia-呢?","page":"常见问题","title":"为什么不把 Matlab/Python/R 或者其他语言的代码编译为 Julia 呢?","text":"","category":"section"},{"location":"manual/faq/","page":"常见问题","title":"常见问题","text":"由于大多数人对其他动态语言的语法很熟悉,而且已经在这些动态语言中编写了很多代码,人们也许会问:为什么我们不直接设计以Julia为后端的Matlab或是Python前端(也就是把其他代码“转译”到Julia)?这样既能获得Julia的高性能,也能避免程序员花费精力来学一门新的语言。这是一个简单的解决方案,不是吗?","category":"page"},{"location":"manual/faq/","page":"常见问题","title":"常见问题","text":"总的来说,我们这样做是因为 Julia 编译器没有什么特别之处:我们使用的是普通的编译器(LLVM),这里面没有什么其他语言开发者所不知道的“独家秘方”。诚然,Julia编译器在许多地方比其他动态语言的编译器更简单(比如 PyPy 和 LuaJIT)。Julia 的性能优势几乎完全来自其前端:它的语义学使得 高质量的 Julia 程序 能够给予编译器更多的机会来产生高效的代码和内存结构。如果你尝试将 Matlab 或 Python 代码编译为 Julia,我们的编译器会被其语义学限制而不能产生相对现有编译器更好的代码(甚至更差)。语义学的关键角色也正是一些现存的 Python 编译器(像 Numba 和 Pythran)仅仅尝试优化语言的一小部分(比如 Numpy 的矢量与标量运算)的原因,而这些部分已经至少在相同的语义学上与我们做的一样好。致力于这些项目的人员难以置信得聪明并且已经取得了令人惊叹的成就,但为被解释而设计的语言加装编译器是十分困难的。","category":"page"},{"location":"manual/faq/","page":"常见问题","title":"常见问题","text":"Julia 的优势在于好的性能不止被限制在一小部分的内置类型与操作,用户能够写出使用任意自定义类型的高级泛型代码,同时也能保证很高的运行与内存效率。在如 Python 一般的语言中,类型没有给编译器提供太多的信息来达成这样的目的,当你试图像使用 Julia 前端一样使用这些语言时,你会遇到困难。","category":"page"},{"location":"manual/faq/","page":"常见问题","title":"常见问题","text":"出于类似的原因,自动翻译为 Julia 的代码一般来说会是可读性差、缓慢且违反习惯的代码。这些代码不是从其他语言迁移到 Julia 的好的起点。","category":"page"},{"location":"manual/faq/","page":"常见问题","title":"常见问题","text":"另一方面,语言可迁移性是极其有用的:我们会在一些时候想要将其他语言的高质量代码迁移到 Julia 中(也可能相反)。这一工作的最佳实践不是翻译器,而是使用简单的跨语言调用。我们对此有许多工作,从内置的 ccall (来调用 C 和 Fortran 模块)到JuliaInterop 包来链接 Julia 和 Python、Matlab、C++ 以及更多语言。","category":"page"},{"location":"manual/faq/#man-api","page":"常见问题","title":"公共 API","text":"","category":"section"},{"location":"manual/faq/#Julia-如何定义其公共-API?","page":"常见问题","title":"Julia 如何定义其公共 API?","text":"","category":"section"},{"location":"manual/faq/","page":"常见问题","title":"常见问题","text":"对于 julia 版本的 SemVer,唯一稳定的接口是 Julia 的 Base 和 文档 中的标准库接口中且未标记为不稳定(例如,实验性的和内部性的)的部分。 如果函数、类型和常量未包含在文档中,则它们不是公共 API 的一部分,即使它们具有文档。","category":"page"},{"location":"manual/faq/#有一个有用的非官方的函数/类型/常量。我可以使用它吗?","page":"常见问题","title":"有一个有用的非官方的函数/类型/常量。我可以使用它吗?","text":"","category":"section"},{"location":"manual/faq/","page":"常见问题","title":"常见问题","text":"如果您使用非公共 API,更新 Julia 可能会使你的代码失效。 如果代码是自洽的,最好将其复制到你的项目中。 如果你想依赖一个复杂的非公共 API,尤其是从稳定的包中使用它时,最好打开发起 issue 或 pull request 开始讨论将其转换为公共 API。 尽管你可以在下游自己开发一个包来封装这个内部实现,并且屏蔽不同的 Julia 版本差异,但我们并不鼓励这样做。","category":"page"},{"location":"manual/faq/#文档不够准确。-我可以依赖现有的行为吗?","page":"常见问题","title":"文档不够准确。 我可以依赖现有的行为吗?","text":"","category":"section"},{"location":"manual/faq/","page":"常见问题","title":"常见问题","text":"请发起一个 issue 或 pull request 开始讨论将现有行为转换为公共 API。","category":"page"},{"location":"manual/faq/#会话和-REPL","page":"常见问题","title":"会话和 REPL","text":"","category":"section"},{"location":"manual/faq/#如何从内存中删除某个对象?","page":"常见问题","title":"如何从内存中删除某个对象?","text":"","category":"section"},{"location":"manual/faq/","page":"常见问题","title":"常见问题","text":"Julia 没有类似于 MATLAB 的 clear 函数,某个名称一旦定义在 Julia 的会话中(准确地说,在 Main 模块中),它就会一直存在下去。","category":"page"},{"location":"manual/faq/","page":"常见问题","title":"常见问题","text":"如果关心内存使用情况,你可以用消耗较少内存的对象替换原对象。 例如,如果 A 是一个你不再需要的千兆字节大小的数组,你可以使用 A = nothing 来释放内存。 下次垃圾收集器运行时会释放内存; 您可以使用 GC.gc() 强制执行此操作。 此外,尝试使用 A 可能会导致错误,因为大多数方法都没有在类型 Nothing 上定义。","category":"page"},{"location":"manual/faq/#如何在会话中修改某个类型的声明?","page":"常见问题","title":"如何在会话中修改某个类型的声明?","text":"","category":"section"},{"location":"manual/faq/","page":"常见问题","title":"常见问题","text":"也许你定义了某个类型,后来发现需要向其中增加一个新的域。如果在 REPL 中尝试这样做,会得到一个错误:","category":"page"},{"location":"manual/faq/","page":"常见问题","title":"常见问题","text":"ERROR: invalid redefinition of constant MyType","category":"page"},{"location":"manual/faq/","page":"常见问题","title":"常见问题","text":"模块 Main 中的类型不能重新定义。","category":"page"},{"location":"manual/faq/","page":"常见问题","title":"常见问题","text":"尽管这在开发新代码时会造成不便,但是这个问题仍然有一个不错的解决办法:可以用重新定义的模块替换原有的模块,把所有新代码封装在一个模块里,这样就能重新定义类型和常量了。虽说不能将类型名称导入到 Main 模块中再去重新定义,但是可以用模块名来改变作用范围。换言之,开发时的工作流可能类似这样:","category":"page"},{"location":"manual/faq/","page":"常见问题","title":"常见问题","text":"include(\"mynewcode.jl\") # this defines a module MyModule\nobj1 = MyModule.ObjConstructor(a, b)\nobj2 = MyModule.somefunction(obj1)\n# Got an error. Change something in \"mynewcode.jl\"\ninclude(\"mynewcode.jl\") # reload the module\nobj1 = MyModule.ObjConstructor(a, b) # old objects are no longer valid, must reconstruct\nobj2 = MyModule.somefunction(obj1) # this time it worked!\nobj3 = MyModule.someotherfunction(obj2, c)\n...","category":"page"},{"location":"manual/faq/#man-scripting","page":"常见问题","title":"脚本","text":"","category":"section"},{"location":"manual/faq/#该如何检查当前文件是否正在以主脚本运行?","page":"常见问题","title":"该如何检查当前文件是否正在以主脚本运行?","text":"","category":"section"},{"location":"manual/faq/","page":"常见问题","title":"常见问题","text":"当一个文件通过使用 julia file.jl 来当做主脚本运行时,有人也希望激活另外的功能例如命令行参数操作。确定文件是以这个方式运行的一个方法是检查 abspath(PROGRAM_FILE) == @__FILE__ 是不是 true。","category":"page"},{"location":"manual/faq/#catch-ctrl-c","page":"常见问题","title":"怎样在脚本中捕获 CTRL-C ?","text":"","category":"section"},{"location":"manual/faq/","page":"常见问题","title":"常见问题","text":"通过 julia file.jl 方式运行的 Julia 脚本,在你尝试按 CTRL-C (SIGINT) 中止它时,并不会抛出 InterruptException。如果希望在脚本终止之后运行一些代码,请使用 atexit,注意:脚本的中止不一定是由 CTRL-C 导致的。 另外你也可以通过 julia -e 'include(popfirst!(ARGS))' file.jl 命令运行脚本,然后可以通过 try 捕获 InterruptException。","category":"page"},{"location":"manual/faq/#怎样通过-#!/usr/bin/env-传递参数给-julia?","page":"常见问题","title":"怎样通过 #!/usr/bin/env 传递参数给 julia?","text":"","category":"section"},{"location":"manual/faq/","page":"常见问题","title":"常见问题","text":"通过类似 #!/usr/bin/env julia --startup-file=no 的方式,使用 shebang 传递选项给 Julia 的方法,可能在像 Linux 这样的平台上无法正常工作。这是因为各平台上 shebang 的参数解析是平台相关的,并且尚未标准化。 在类 Unix 的环境中,可以通过以 bash 脚本作为可执行脚本的开头,并使用 exec 代替给 julia 传递选项的过程,来可靠的为 julia 传递选项。","category":"page"},{"location":"manual/faq/","page":"常见问题","title":"常见问题","text":"#!/bin/bash\n#=\nexec julia --color=yes --startup-file=no \"${BASH_SOURCE[0]}\" \"$@\"\n=#\n\n@show ARGS # put any Julia code here","category":"page"},{"location":"manual/faq/","page":"常见问题","title":"常见问题","text":"在以上例子中,位于 #= 和 =# 之间的代码可以当作一个 bash 脚本。 因为这些代码放在 Julia 的多行注释中,所以 Julia 会忽略它们。 在 =# 之后的 Julia 代码会被 bash 忽略,J因为当文件解析到 exec 语句时会停止解析,开始执行命令。","category":"page"},{"location":"manual/faq/","page":"常见问题","title":"常见问题","text":"note: Note\n为了在脚本中捕获 catch CTRL-C ,我们可以使用#!/bin/bash\n#=\nexec julia --color=yes --startup-file=no -e 'include(popfirst!(ARGS))' \\\n \"${BASH_SOURCE[0]}\" \"$@\"\n=#\n\n@show ARGS # put any Julia code hereinstead. Note that with this strategy PROGRAM_FILE will not be set.","category":"page"},{"location":"manual/faq/#函数","page":"常见问题","title":"函数","text":"","category":"section"},{"location":"manual/faq/#向函数传递了参数-x,在函数中做了修改,但是在函数外变量-x-的值还是没有变。为什么?","page":"常见问题","title":"向函数传递了参数 x,在函数中做了修改,但是在函数外变量 x 的值还是没有变。为什么?","text":"","category":"section"},{"location":"manual/faq/","page":"常见问题","title":"常见问题","text":"假设函数被如此调用:","category":"page"},{"location":"manual/faq/","page":"常见问题","title":"常见问题","text":"julia> x = 10\n10\n\njulia> function change_value!(y)\n y = 17\n end\nchange_value! (generic function with 1 method)\n\njulia> change_value!(x)\n17\n\njulia> x # x is unchanged!\n10","category":"page"},{"location":"manual/faq/","page":"常见问题","title":"常见问题","text":"在 Julia 中,通过将 x 作为参数传递给函数,不能改变变量 x 的绑定。在上例中,调用 change_value!(x) 时,y 是一个新建变量,初始时与 x 的值绑定,即 10。然后 y 与常量 17 重新绑定,此时变量外作用域中的 x 并没有变动。","category":"page"},{"location":"manual/faq/","page":"常见问题","title":"常见问题","text":"假设 x 被绑定至 Array 类型 (也有可能是其他 可变 的类型)。在函数中,你无法将 x 与 Array 解绑,但是你可以改变其内容。","category":"page"},{"location":"manual/faq/","page":"常见问题","title":"常见问题","text":"julia> x = [1,2,3]\n3-element Vector{Int64}:\n 1\n 2\n 3\n\njulia> function change_array!(A)\n A[1] = 5\n end\nchange_array! (generic function with 1 method)\n\njulia> change_array!(x)\n5\n\njulia> x\n3-element Vector{Int64}:\n 5\n 2\n 3","category":"page"},{"location":"manual/faq/","page":"常见问题","title":"常见问题","text":"这里我们新建了一个函数 chang_array!,它把 5 赋值给传入的数组(在调用处与 x 绑定,在函数中与 A 绑定)的第一个元素。注意,在函数调用之后,x 依旧与同一个数组绑定,但是数组的内容变化了:变量 A 和 x 是不同的绑定,引用同一个可变的 Array 对象。","category":"page"},{"location":"manual/faq/#函数内部能否使用-using-或-import?","page":"常见问题","title":"函数内部能否使用 using 或 import?","text":"","category":"section"},{"location":"manual/faq/","page":"常见问题","title":"常见问题","text":"不可以,不能在函数内部使用 using 或 import 语句。如果你希望导入一个模块,但只在特定的一个或一组函数中使用它的符号,有以下两种方式:","category":"page"},{"location":"manual/faq/","page":"常见问题","title":"常见问题","text":"使用 import:\nimport Foo\nfunction bar(...)\n # ... refer to Foo symbols via Foo.baz ...\nend\n这会加载 Foo 模块,同时定义一个变量 Foo 引用该模块,但并不会 将其他任何符号从该模块中导入当前的命名空间。 Foo 等符号可以由限定的名称 Foo.bar 等引用。\n将函数封装到模块中:\nmodule Bar\nexport bar\nusing Foo\nfunction bar(...)\n # ... refer to Foo.baz as simply baz ....\nend\nend\nusing Bar\n这会从 Foo 中导入所有符号,但仅限于 Bar 模块内。","category":"page"},{"location":"manual/faq/#运算符-...-有何作用?","page":"常见问题","title":"运算符 ... 有何作用?","text":"","category":"section"},{"location":"manual/faq/#...-运算符的两个用法:slurping-和-splatting","page":"常见问题","title":"... 运算符的两个用法:slurping 和 splatting","text":"","category":"section"},{"location":"manual/faq/","page":"常见问题","title":"常见问题","text":"很多 Julia 的新手会对运算符 ... 的用法感到困惑。让 ... 用法如此困惑的部分原因是根据上下文它有两种不同的含义。","category":"page"},{"location":"manual/faq/#...-在函数定义中将多个参数组合成一个参数","page":"常见问题","title":"... 在函数定义中将多个参数组合成一个参数","text":"","category":"section"},{"location":"manual/faq/","page":"常见问题","title":"常见问题","text":"在函数定义的上下文中,...运算符用来将多个不同的参数组合成单个参数。...运算符的这种将多个不同参数组合成单个参数的用法称为slurping:","category":"page"},{"location":"manual/faq/","page":"常见问题","title":"常见问题","text":"julia> function printargs(args...)\n println(typeof(args))\n for (i, arg) in enumerate(args)\n println(\"Arg #$i = $arg\")\n end\n end\nprintargs (generic function with 1 method)\n\njulia> printargs(1, 2, 3)\nTuple{Int64, Int64, Int64}\nArg #1 = 1\nArg #2 = 2\nArg #3 = 3","category":"page"},{"location":"manual/faq/","page":"常见问题","title":"常见问题","text":"如果Julia是一个使用ASCII字符更加自由的语言的话,slurping运算符可能会写作<-...而非...。","category":"page"},{"location":"manual/faq/#...在函数调用中将一个参数分解成多个不同参数","page":"常见问题","title":"...在函数调用中将一个参数分解成多个不同参数","text":"","category":"section"},{"location":"manual/faq/","page":"常见问题","title":"常见问题","text":"与在定义函数时表示将多个不同参数组合成一个参数的...运算符用法相对,当用在函数调用的上下文中...运算符也用来将单个的函数参数分成多个不同的参数。...函数的这个用法叫做splatting:","category":"page"},{"location":"manual/faq/","page":"常见问题","title":"常见问题","text":"julia> function threeargs(a, b, c)\n println(\"a = $a::$(typeof(a))\")\n println(\"b = $b::$(typeof(b))\")\n println(\"c = $c::$(typeof(c))\")\n end\nthreeargs (generic function with 1 method)\n\njulia> x = [1, 2, 3]\n3-element Vector{Int64}:\n 1\n 2\n 3\n\njulia> threeargs(x...)\na = 1::Int64\nb = 2::Int64\nc = 3::Int64","category":"page"},{"location":"manual/faq/","page":"常见问题","title":"常见问题","text":"如果Julia是一个使用ASCII字符更加自由的语言的话,splatting运算符可能会写作...->而非...。","category":"page"},{"location":"manual/faq/#赋值语句的返回值是什么?","page":"常见问题","title":"赋值语句的返回值是什么?","text":"","category":"section"},{"location":"manual/faq/","page":"常见问题","title":"常见问题","text":"=运算符始终返回右侧的值,所以:","category":"page"},{"location":"manual/faq/","page":"常见问题","title":"常见问题","text":"julia> function threeint()\n x::Int = 3.0\n x # returns variable x\n end\nthreeint (generic function with 1 method)\n\njulia> function threefloat()\n x::Int = 3.0 # returns 3.0\n end\nthreefloat (generic function with 1 method)\n\njulia> threeint()\n3\n\njulia> threefloat()\n3.0","category":"page"},{"location":"manual/faq/","page":"常见问题","title":"常见问题","text":"相似地:","category":"page"},{"location":"manual/faq/","page":"常见问题","title":"常见问题","text":"julia> function twothreetup()\n x, y = [2, 3] # assigns 2 to x and 3 to y\n x, y # returns a tuple\n end\ntwothreetup (generic function with 1 method)\n\njulia> function twothreearr()\n x, y = [2, 3] # returns an array\n end\ntwothreearr (generic function with 1 method)\n\njulia> twothreetup()\n(2, 3)\n\njulia> twothreearr()\n2-element Vector{Int64}:\n 2\n 3","category":"page"},{"location":"manual/faq/#类型,类型声明和构造函数","page":"常见问题","title":"类型,类型声明和构造函数","text":"","category":"section"},{"location":"manual/faq/#man-type-stability","page":"常见问题","title":"何谓“类型稳定”?","text":"","category":"section"},{"location":"manual/faq/","page":"常见问题","title":"常见问题","text":"这意味着输出的类型可以由输入的类型预测出来。特别地,这意味着输出的类型不会因输入的值的不同而变化。以下代码不是类型稳定的:","category":"page"},{"location":"manual/faq/","page":"常见问题","title":"常见问题","text":"julia> function unstable(flag::Bool)\n if flag\n return 1\n else\n return 1.0\n end\n end\nunstable (generic function with 1 method)","category":"page"},{"location":"manual/faq/","page":"常见问题","title":"常见问题","text":"根据参数值的不同,该函数可能返回 Int 或 Float64。由于 Julia 无法在编译期预测该函数的返回值类型,任何使用该函数的计算都需要考虑这两种可能的返回类型,这样难以生成高效的机器码。","category":"page"},{"location":"manual/faq/#faq-domain-errors","page":"常见问题","title":"为何 Julia 对某个看似合理的操作返回 DomainError?","text":"","category":"section"},{"location":"manual/faq/","page":"常见问题","title":"常见问题","text":"某些运算在数学上有意义,但会产生错误:","category":"page"},{"location":"manual/faq/","page":"常见问题","title":"常见问题","text":"julia> sqrt(-2.0)\nERROR: DomainError with -2.0:\nsqrt will only return a complex result if called with a complex argument. Try sqrt(Complex(x)).\nStacktrace:\n[...]","category":"page"},{"location":"manual/faq/","page":"常见问题","title":"常见问题","text":"这一行为是为了保证类型稳定而带来的不便。对于 sqrt,许多用户会希望 sqrt(2.0) 产生一个实数,如果得到了复数 1.4142135623730951 + 0.0im 则会不高兴。也可以编写 sqrt 函数,只有当传递一个负数时才切换到复值输出,但结果将不是类型稳定的,而且 sqrt 函数的性能会很差。","category":"page"},{"location":"manual/faq/","page":"常见问题","title":"常见问题","text":"在这样那样的情况下,若你想得到希望的结果,你可以选择一个输入类型,它可以使根据你的想法接受一个输出类型,从而结果可以这样表示:","category":"page"},{"location":"manual/faq/","page":"常见问题","title":"常见问题","text":"julia> sqrt(-2.0+0im)\n0.0 + 1.4142135623730951im","category":"page"},{"location":"manual/faq/#怎样限制或计算类型参数?","page":"常见问题","title":"怎样限制或计算类型参数?","text":"","category":"section"},{"location":"manual/faq/","page":"常见问题","title":"常见问题","text":"参数类型 的参数可以包含类型或比特值,并且类型本身选择如何使用这些参数。例如,Array{Float64, 2} 由类型 Float64 参数化以表示其元素类型,并通过整数值 2 来表示其维度数。在定义自己的参数类型时,可以使用子类型约束来声明某个参数必须是某个抽象类型的子类型 (<:) 或以前的类型参数。但是,没有专用的语法来声明参数必须是给定类型的值 — 也就是说,例如,你不能在struct定义中直接声明一个维度参数 isa Int。同样,你不能对类型参数进行计算(包括简单的加法或减法)。相反,这些类型的约束和关系可以通过在类型的 构造函数 中计算和强制执行的附加类型参数来表达。","category":"page"},{"location":"manual/faq/","page":"常见问题","title":"常见问题","text":"例如,考虑","category":"page"},{"location":"manual/faq/","page":"常见问题","title":"常见问题","text":"struct ConstrainedType{T,N,N+1} # NOTE: INVALID SYNTAX\n A::Array{T,N}\n B::Array{T,N+1}\nend","category":"page"},{"location":"manual/faq/","page":"常见问题","title":"常见问题","text":"其中,用户希望强制第三个类型参数始终是第二个参数加一。 这可以使用显式类型参数来实现,该参数由 内部构造函数方法(可以与其他检查结合使用)进行检查:","category":"page"},{"location":"manual/faq/","page":"常见问题","title":"常见问题","text":"struct ConstrainedType{T,N,M}\n A::Array{T,N}\n B::Array{T,M}\n function ConstrainedType(A::Array{T,N}, B::Array{T,M}) where {T,N,M}\n N + 1 == M || throw(ArgumentError(\"second argument should have one more axis\" ))\n new{T,N,M}(A, B)\n end\nend","category":"page"},{"location":"manual/faq/","page":"常见问题","title":"常见问题","text":"这种检查通常是无成本的,因为编译器可以省略对有效具体类型的检查。 如果还计算了第二个参数,则提供执行此计算的 外部构造函数方法 可能更好:","category":"page"},{"location":"manual/faq/","page":"常见问题","title":"常见问题","text":"ConstrainedType(A) = ConstrainedType(A, compute_B(A))","category":"page"},{"location":"manual/faq/#faq-integer-arithmetic","page":"常见问题","title":"为什么Julia使用机器算法进行整数运算?","text":"","category":"section"},{"location":"manual/faq/","page":"常见问题","title":"常见问题","text":"Julia使用机器算法进行整数计算。这意味着Int的范围是有界的,值在范围的两端循环,也就是说整数的加法,减法和乘法会出现上溢或者下溢,导致出现某些从开始就令人不安的结果:","category":"page"},{"location":"manual/faq/","page":"常见问题","title":"常见问题","text":"julia> x = typemax(Int)\n9223372036854775807\n\njulia> y = x+1\n-9223372036854775808\n\njulia> z = -y\n-9223372036854775808\n\njulia> 2*z\n0","category":"page"},{"location":"manual/faq/","page":"常见问题","title":"常见问题","text":"无疑,这与数学上的整数的行为很不一样,并且你会想对于高阶编程语言来说把这个暴露给用户难称完美。然而,对于效率优先和透明度优先的数值计算来说,其他的备选方案可谓更糟。","category":"page"},{"location":"manual/faq/","page":"常见问题","title":"常见问题","text":"一个备选方案是去检查每个整数运算是否溢出,如果溢出则将结果提升到更大的整数类型比如Int128或者BigInt。 不幸的是,这会给所有的整数操作(比如让循环计数器自增)带来巨大的额外开销 — 这需要生成代码去在算法指令后进行运行溢出检测,并生成分支去处理潜在的溢出。更糟糕的是,这会让涉及整数的所有运算变得类型不稳定。如同上面提到的,对于高效生成高效的代码类型稳定很重要。如果不指望整数运算的结果是整数,就无法想C和Fortran编译器一样生成快速简单的代码。","category":"page"},{"location":"manual/faq/","page":"常见问题","title":"常见问题","text":"这个方法有个变体可以避免类型不稳定的出现,这个变体是将类型Int和BigInt合并成单个混合整数类型,当结果不再满足机器整数的大小时会内部自动切换表示。虽然表面上在Julia代码层面解决了类型不稳定,但是这个只是通过将所有的困难硬塞给实现混合整数类型的C代码而掩盖了这个问题。这个方法可能有用,甚至在很多情况下速度很快,但是它有很多缺点。一个缺点是整数和整数数组的内存上的表示不再与C、Fortran和其他使用原生机器整数的怨言所使用的自然表示一样。所以,为了与那些语言协作,我们无论如何最终都需要引入原生整数类型。任何整数的无界表示都不会占用固定的比特数,所以无法使用固定大小的槽来内联地存储在数组中 — 大的整数值通常需要单独的堆分配的存储。并且无论使用的混合整数实现多么智能,总会存在性能陷阱 — 无法预期的性能下降的情况。复杂的表示,与C和Fortran协作能力的缺乏,无法在不使用另外的堆存储的情况下表示整数数组,和无法预测的性能特性让即使是最智能化的混合整数实现对于高性能数值计算来说也是个很差的选择。","category":"page"},{"location":"manual/faq/","page":"常见问题","title":"常见问题","text":"除了使用混合整数和提升到BigInt,另一个备选方案是使用饱和整数算法,此时最大整数值加一个数时值保持不变,最小整数值减一个数时也是同样的。这就是Matlab™的做法:","category":"page"},{"location":"manual/faq/","page":"常见问题","title":"常见问题","text":">> int64(9223372036854775807)\n\nans =\n\n 9223372036854775807\n\n>> int64(9223372036854775807) + 1\n\nans =\n\n 9223372036854775807\n\n>> int64(-9223372036854775808)\n\nans =\n\n -9223372036854775808\n\n>> int64(-9223372036854775808) - 1\n\nans =\n\n -9223372036854775808","category":"page"},{"location":"manual/faq/","page":"常见问题","title":"常见问题","text":"乍一看,这个似乎足够合理,因为9223372036854775807比-9223372036854775808更接近于9223372036854775808并且整数还是以固定大小的自然方式表示的,这与C和Fortran相兼容。但是饱和整数算法是很有问题的。首先最明显的问题是这并不是机器整数算法的工作方式,所以实现饱和整数算法需要生成指令,在每个机器整数运算后检查上溢或者下溢并正确地讲这些结果用typemin(Int)或者typemax(Int)取代。单单这个就将整数运算从单语句的快速的指令扩展成六个指令,还可能包括分支。哎呦喂~~但是还有更糟的 — 饱和整数算法并不满足结合律。考虑下列的Matlab计算:","category":"page"},{"location":"manual/faq/","page":"常见问题","title":"常见问题","text":">> n = int64(2)^62\n4611686018427387904\n\n>> n + (n - 1)\n9223372036854775807\n\n>> (n + n) - 1\n9223372036854775806","category":"page"},{"location":"manual/faq/","page":"常见问题","title":"常见问题","text":"这就让写很多基础整数算法变得困难因为很多常用技术都是基于有溢出的机器加法是满足结合律这一事实的。考虑一下在Julia中求整数值lo和hi之间的中点值,使用表达式(lo + hi) >>> 1:","category":"page"},{"location":"manual/faq/","page":"常见问题","title":"常见问题","text":"julia> n = 2^62\n4611686018427387904\n\njulia> (n + 2n) >>> 1\n6917529027641081856","category":"page"},{"location":"manual/faq/","page":"常见问题","title":"常见问题","text":"看到了吗?没有任何问题。那就是2^62和2^63之间的正确地中点值,虽然n + 2n的值是 -4611686018427387904。现在使用Matlab试一下:","category":"page"},{"location":"manual/faq/","page":"常见问题","title":"常见问题","text":">> (n + 2*n)/2\n\nans =\n\n 4611686018427387904","category":"page"},{"location":"manual/faq/","page":"常见问题","title":"常见问题","text":"哎呦喂。在Matlab中添加>>>运算符没有任何作用,因为在将n与2n相加时已经破坏了能计算出正确地中点值的必要信息,已经出现饱和。","category":"page"},{"location":"manual/faq/","page":"常见问题","title":"常见问题","text":"没有结合性不但对于不能依靠像这样的技术的程序员是不幸的,并且让几乎所有的希望优化整数算法的编译器铩羽而归。例如,因为Julia中的整数使用平常的机器整数算法,LLVM就可以自由地激进地优化像f(k) = 5k-1这样的简单地小函数。这个函数的机器码如下所示:","category":"page"},{"location":"manual/faq/","page":"常见问题","title":"常见问题","text":"julia> code_native(f, Tuple{Int})\n .text\nFilename: none\n pushq %rbp\n movq %rsp, %rbp\nSource line: 1\n leaq -1(%rdi,%rdi,4), %rax\n popq %rbp\n retq\n nopl (%rax,%rax)","category":"page"},{"location":"manual/faq/","page":"常见问题","title":"常见问题","text":"这个函数的实际函数体只是一个简单地leap指令,可以立马计算整数乘法与加法。当f内联在其他函数中的时候这个更加有益:","category":"page"},{"location":"manual/faq/","page":"常见问题","title":"常见问题","text":"julia> function g(k, n)\n for i = 1:n\n k = f(k)\n end\n return k\n end\ng (generic function with 1 methods)\n\njulia> code_native(g, Tuple{Int,Int})\n .text\nFilename: none\n pushq %rbp\n movq %rsp, %rbp\nSource line: 2\n testq %rsi, %rsi\n jle L26\n nopl (%rax)\nSource line: 3\nL16:\n leaq -1(%rdi,%rdi,4), %rdi\nSource line: 2\n decq %rsi\n jne L16\nSource line: 5\nL26:\n movq %rdi, %rax\n popq %rbp\n retq\n nop","category":"page"},{"location":"manual/faq/","page":"常见问题","title":"常见问题","text":"因为f的调用内联化,循环体就只是简单地leap指令。接着,考虑一下如果循环迭代的次数固定的时候会发生什么:","category":"page"},{"location":"manual/faq/","page":"常见问题","title":"常见问题","text":"julia> function g(k)\n for i = 1:10\n k = f(k)\n end\n return k\n end\ng (generic function with 2 methods)\n\njulia> code_native(g,(Int,))\n .text\nFilename: none\n pushq %rbp\n movq %rsp, %rbp\nSource line: 3\n imulq $9765625, %rdi, %rax # imm = 0x9502F9\n addq $-2441406, %rax # imm = 0xFFDABF42\nSource line: 5\n popq %rbp\n retq\n nopw %cs:(%rax,%rax)","category":"page"},{"location":"manual/faq/","page":"常见问题","title":"常见问题","text":"因为编译器知道整数加法和乘法是满足结合律的并且乘法可以在加法上使用分配律 — 两者在饱和算法中都不成立 — 所以编译器就可以把整个循环优化到只有一个乘法和一个加法。饱和算法完全无法使用这种优化,因为在每个循环迭代中结合律和分配律都会失效导致不同的失效位置会得到不同的结果。编译器可以展开循环,但是不能代数上将多个操作简化到更少的等效操作。","category":"page"},{"location":"manual/faq/","page":"常见问题","title":"常见问题","text":"让整数算术沉默地溢出的最合理替代方法是在任何地方进行检查算术,在加法、减法和乘法溢出时引发错误,产生不正确的值。 在这篇博文中,Dan Luu 对此进行了分析,并发现这种方法在理论上应该具有的微不足道的成本,但由于编译器(LLVM 和 GCC)没有优雅地围绕添加的溢出检查进行优化,它最终会产生大量成本。 如果这在未来有所改善,我们可以考虑在 Julia 中默认使用检查整数算法,但现在,我们必须忍受可能会溢出这一现状。","category":"page"},{"location":"manual/faq/","page":"常见问题","title":"常见问题","text":"同时,可以通过使用SaferIntegers.jl等外部库来实现溢出安全的整数运算。 请注意,如前所述,使用这些库会显着增加使用已检查整数类型的代码的执行时间。 但是,对于有限的使用,这远比将其用于所有整数运算时的问题要小得多。你可以在 此处 中关注讨论的状态。","category":"page"},{"location":"manual/faq/#在远程执行中UndefVarError的可能原因有哪些?","page":"常见问题","title":"在远程执行中UndefVarError的可能原因有哪些?","text":"","category":"section"},{"location":"manual/faq/","page":"常见问题","title":"常见问题","text":"如同这个错误表述的,远程结点上的UndefVarError的直接原因是变量名的绑定并不存在。让我们探索一下一些可能的原因。","category":"page"},{"location":"manual/faq/","page":"常见问题","title":"常见问题","text":"julia> module Foo\n foo() = remotecall_fetch(x->x, 2, \"Hello\")\n end\n\njulia> Foo.foo()\nERROR: On worker 2:\nUndefVarError: Foo not defined\nStacktrace:\n[...]","category":"page"},{"location":"manual/faq/","page":"常见问题","title":"常见问题","text":"闭包x->x中有Foo的引用,因为Foo在节点2上不存在,所以UndefVarError被扔出。","category":"page"},{"location":"manual/faq/","page":"常见问题","title":"常见问题","text":"在模块中而非Main中的全局变量不会在远程节点上按值序列化。只传递了一个引用。新建全局绑定的函数(除了Main中)可能会导致之后扔出UndefVarError。","category":"page"},{"location":"manual/faq/","page":"常见问题","title":"常见问题","text":"julia> @everywhere module Foo\n function foo()\n global gvar = \"Hello\"\n remotecall_fetch(()->gvar, 2)\n end\n end\n\njulia> Foo.foo()\nERROR: On worker 2:\nUndefVarError: gvar not defined\nStacktrace:\n[...]","category":"page"},{"location":"manual/faq/","page":"常见问题","title":"常见问题","text":"在上面的例子中,@everywhere module Foo在所有节点上定义了Foo。但是调用Foo.foo()在本地节点上新建了新的全局绑定gvar,但是节点2中并没有找到这个绑定,这会导致UndefVarError错误。","category":"page"},{"location":"manual/faq/","page":"常见问题","title":"常见问题","text":"注意着并不适用于在模块Main下新建的全局变量。模块Main下的全局变量会被序列化并且在远程节点的Main下新建新的绑定。","category":"page"},{"location":"manual/faq/","page":"常见问题","title":"常见问题","text":"julia> gvar_self = \"Node1\"\n\"Node1\"\n\njulia> remotecall_fetch(()->gvar_self, 2)\n\"Node1\"\n\njulia> remotecall_fetch(varinfo, 2)\nname size summary\n––––––––– –––––––– –––––––\nBase Module\nCore Module\nMain Module\ngvar_self 13 bytes String","category":"page"},{"location":"manual/faq/","page":"常见问题","title":"常见问题","text":"这并不适用于函数或者结构体声明。但是绑定到全局变量的匿名函数被序列化,如下例所示。","category":"page"},{"location":"manual/faq/","page":"常见问题","title":"常见问题","text":"julia> bar() = 1\nbar (generic function with 1 method)\n\njulia> remotecall_fetch(bar, 2)\nERROR: On worker 2:\nUndefVarError: #bar not defined\n[...]\n\njulia> anon_bar = ()->1\n(::#21) (generic function with 1 method)\n\njulia> remotecall_fetch(anon_bar, 2)\n1","category":"page"},{"location":"manual/faq/#“method-not-matched”故障排除:参数类型不变性和MethodError","page":"常见问题","title":"“method not matched”故障排除:参数类型不变性和MethodError","text":"","category":"section"},{"location":"manual/faq/#为什么声明-foo(bar::Vector{Real})-42-然后调用-foo([1])-不起作用?","page":"常见问题","title":"为什么声明 foo(bar::Vector{Real}) = 42 然后调用 foo([1]) 不起作用?","text":"","category":"section"},{"location":"manual/faq/","page":"常见问题","title":"常见问题","text":"如果你尝试了,结果就会看到MethodError:","category":"page"},{"location":"manual/faq/","page":"常见问题","title":"常见问题","text":"julia> foo(x::Vector{Real}) = 42\nfoo (generic function with 1 method)\n\njulia> foo([1])\nERROR: MethodError: no method matching foo(::Vector{Int64})\nClosest candidates are:\n foo(!Matched::Vector{Real}) at none:1","category":"page"},{"location":"manual/faq/","page":"常见问题","title":"常见问题","text":"这是因为 Vector{Real} 不是 Vector{Int} 的超类型! 您可以使用类似 foo(bar::Vector{T}) where {T<:Real}(或缩写 foo(bar::Vector{<:Real}) 如果静态参数函数体中不需要T)。T 是一个通配符:首先指定它必须是 Real 的子类型,然后指定函数采用具有该类型元素的 Vector 。","category":"page"},{"location":"manual/faq/","page":"常见问题","title":"常见问题","text":"同样的问题适用于任何复合类型Comp,而不仅仅是Vector。 如果Comp 有一个声明为Y 类型的参数,那么另一个带有X<:Y 类型参数的类型Comp2 不是Comp 的子类型。 这是类型不变性(相比之下,元组在其参数中是类型协变的)。 有关这些的更多解释,请参阅 参数复合类型。","category":"page"},{"location":"manual/faq/#为什么-Julia-使用-*-进行字符串拼接?而不是使用-或其他符号?","page":"常见问题","title":"为什么 Julia 使用 * 进行字符串拼接?而不是使用 + 或其他符号?","text":"","category":"section"},{"location":"manual/faq/","page":"常见问题","title":"常见问题","text":"使用 + 的主要依据是:字符串拼接是不可交换的操作,而 + 通常是一个具有可交换性的操作符。Julia 社区也意识到其他语言使用了不同的操作符,一些用户也可能不熟悉 * 包含的特定代数性值。","category":"page"},{"location":"manual/faq/","page":"常见问题","title":"常见问题","text":"注意:你也可以用 string(...) 来拼接字符串和其他能转换成字符串的值; 类似的 repeat 函数可以用于替代用于重复字符串的 ^ 操作符。 字符串插值语法在构造字符串时也很常用。","category":"page"},{"location":"manual/faq/#包和模块","page":"常见问题","title":"包和模块","text":"","category":"section"},{"location":"manual/faq/#\"using\"和\"import\"的区别是什么?","page":"常见问题","title":"\"using\"和\"import\"的区别是什么?","text":"","category":"section"},{"location":"manual/faq/","page":"常见问题","title":"常见问题","text":"只有一个区别,并且在表面上(语法层面)这个区别看来很小。using和import的区别是使用using时你需要写function Foo.bar(..来用一个新方法来扩展模块Foo的函数bar,但是使用import Foo.bar时,你只需要写function bar(...,会自动扩展模块Foo的函数bar。","category":"page"},{"location":"manual/faq/","page":"常见问题","title":"常见问题","text":"这个区别足够重要以至于提供不同的语法的原因是你不希望意外地扩展一个你根本不知道其存在的函数,因为这很容易造成bug。对于使用像字符串后者整数这样的常用类型的方法最有可能出现这个问题,因为你和其他模块都可能定义了方法来处理这样的常用类型。如果你使用import,你会用你自己的新实现覆盖别的函数的bar(s::AbstractString)实现,这会导致做的事情天差地别(并且破坏模块Foo中其他的依赖于调用bar的函数的所有/大部分的将来的使用)。","category":"page"},{"location":"manual/faq/#空值与缺失值","page":"常见问题","title":"空值与缺失值","text":"","category":"section"},{"location":"manual/faq/#faq-nothing","page":"常见问题","title":"在Julia中\"null\",\"空\"或者\"缺失\"是怎么工作的?","text":"","category":"section"},{"location":"manual/faq/","page":"常见问题","title":"常见问题","text":"不像其它很多语言(例如 C 和 Java),Julia 对象默认不能为\"null\"。当一个引用(变量,对象域,或者数组元素)没有被初始化,访问它会立即扔出一个错误。这种情况可以使用函数 isdefined 或者 isassigned 检测到。","category":"page"},{"location":"manual/faq/","page":"常见问题","title":"常见问题","text":"一些函数只为了其副作用使用,并不需要返回一个值。在这些情况下,约定的是返回 nothing 这个值,这只是 Nothing 类型的一个单例对象。这是一个没有域的一般类型;除了这个约定之外没有任何特殊点,REPL 不会为它打印任何东西。有些语言结构不会有值,也产生 nothing,例如 if false; end。","category":"page"},{"location":"manual/faq/","page":"常见问题","title":"常见问题","text":"对于类型T的值x只会有时存在的情况,Union{T,Nothing}类型可以用作函数参数,对象域和数组元素的类型,与其他语言中的Nullable, Option or Maybe相等。如果值本身可以是nothing(显然当T是Any时),Union{Some{T}, Nothing}类型更加准确因为x == nothing表示值的缺失,x == Some(nothing)表示与nothing相等的值的存在。something函数允许使用默认值的展开的Some对象,而非nothing参数。注意在使用Union{T,Nothing}参数或者域时编译器能够生成高效的代码。","category":"page"},{"location":"manual/faq/","page":"常见问题","title":"常见问题","text":"在统计环境下表示缺失的数据(R 中的 NA 或者 SQL 中的 NULL)请使用 missing 对象。请参照缺失值章节来获取详细信息。","category":"page"},{"location":"manual/faq/","page":"常见问题","title":"常见问题","text":"在某些语言中,空元组 (()) 被认为是\"没有“的规范形式。但是,在 julia 中,最好将其视为恰好包含零个值的常规元组。","category":"page"},{"location":"manual/faq/","page":"常见问题","title":"常见问题","text":"空(或者\"底层\")类型,写作Union{}(空的union类型)是没有值和子类型(除了自己)的类型。通常你没有必要用这个类型。","category":"page"},{"location":"manual/faq/#内存","page":"常见问题","title":"内存","text":"","category":"section"},{"location":"manual/faq/#为什么当x和y都是数组时x-y还会申请内存?","page":"常见问题","title":"为什么当x和y都是数组时x += y还会申请内存?","text":"","category":"section"},{"location":"manual/faq/","page":"常见问题","title":"常见问题","text":"在 Julia 中,x += y 在语法分析中会用 x = x + y 代替。对于数组,结果就是它会申请一个新数组来存储结果,而非把结果存在 x 同一位置的内存上。","category":"page"},{"location":"manual/faq/","page":"常见问题","title":"常见问题","text":"这个行为可能会让一些人吃惊,但是这个结果是经过深思熟虑的。主要原因是Julia中的不可变对象,这些对象一旦新建就不能改变他们的值。实际上,数字是不可变对象,语句x = 5; x += 1不会改变5的意义,改变的是与x绑定的值。对于不可变对象,改变其值的唯一方法是重新赋值。","category":"page"},{"location":"manual/faq/","page":"常见问题","title":"常见问题","text":"为了稍微详细一点,考虑下列的函数:","category":"page"},{"location":"manual/faq/","page":"常见问题","title":"常见问题","text":"function power_by_squaring(x, n::Int)\n ispow2(n) || error(\"此实现只适用于2的幂\")\n while n >= 2\n x *= x\n n >>= 1\n end\n x\nend","category":"page"},{"location":"manual/faq/","page":"常见问题","title":"常见问题","text":"在x = 5; y = power_by_squaring(x, 4)调用后,你可以得到期望的结果x == 5 && y == 625。然而,现在假设当*=与矩阵一起使用时会改变左边的值,这会有两个问题:","category":"page"},{"location":"manual/faq/","page":"常见问题","title":"常见问题","text":"对于普通的方阵,A = A*B 不能在没有临时存储的情况下实现:A[1,1] 会被计算并且在被右边使用完之前存储在左边。\n假设你愿意申请一个计算的临时存储(这会消除 *=就地计算的大部分要点);如果你利用了x的可变性, 这个函数会对于可变和不可变的输入有不同的行为。特别地, 对于不可变的x,在调用后(通常)你会得到y != x,而对可变的x,你会有y == x。","category":"page"},{"location":"manual/faq/","page":"常见问题","title":"常见问题","text":"因为支持范用计算被认为比能使用其他方法完成的潜在的性能优化(比如使用显式循环)更加重要,所以像+=和*=运算符以绑定新值的方式工作。","category":"page"},{"location":"manual/faq/#faq-async-io","page":"常见问题","title":"异步 IO 与并发同步写入","text":"","category":"section"},{"location":"manual/faq/#为什么对于同一个流的并发写入会导致相互混合的输出?","page":"常见问题","title":"为什么对于同一个流的并发写入会导致相互混合的输出?","text":"","category":"section"},{"location":"manual/faq/","page":"常见问题","title":"常见问题","text":"虽然流式 I/O 的 API 是同步的,底层的实现是完全异步的。","category":"page"},{"location":"manual/faq/","page":"常见问题","title":"常见问题","text":"思考一下下面的输出:","category":"page"},{"location":"manual/faq/","page":"常见问题","title":"常见问题","text":"julia> @sync for i in 1:3\n @async write(stdout, string(i), \" Foo \", \" Bar \")\n end\n123 Foo Foo Foo Bar Bar Bar","category":"page"},{"location":"manual/faq/","page":"常见问题","title":"常见问题","text":"这是因为,虽然write调用是同步的,每个参数的写入在等待那一部分I/O完成时会生成其他的Tasks。","category":"page"},{"location":"manual/faq/","page":"常见问题","title":"常见问题","text":"print和println在调用中会\"锁定\"该流。因此把上例中的write改成println会导致:","category":"page"},{"location":"manual/faq/","page":"常见问题","title":"常见问题","text":"julia> @sync for i in 1:3\n @async println(stdout, string(i), \" Foo \", \" Bar \")\n end\n1 Foo Bar\n2 Foo Bar\n3 Foo Bar","category":"page"},{"location":"manual/faq/","page":"常见问题","title":"常见问题","text":"你可以使用ReentrantLock来锁定你的写入,就像这样:","category":"page"},{"location":"manual/faq/","page":"常见问题","title":"常见问题","text":"julia> l = ReentrantLock();\n\njulia> @sync for i in 1:3\n @async begin\n lock(l)\n try\n write(stdout, string(i), \" Foo \", \" Bar \")\n finally\n unlock(l)\n end\n end\n end\n1 Foo Bar 2 Foo Bar 3 Foo Bar","category":"page"},{"location":"manual/faq/#数组","page":"常见问题","title":"数组","text":"","category":"section"},{"location":"manual/faq/#零维数组和标量之间的有什么差别?","page":"常见问题","title":"零维数组和标量之间的有什么差别?","text":"","category":"section"},{"location":"manual/faq/","page":"常见问题","title":"常见问题","text":"零维数组是Array{T,0}形式的数组,它与标量的行为相似,但是有很多重要的不同。这值得一提,因为这是使用数组的范用定义来解释也符合逻辑的特殊情况,虽然最开始看起来有些非直觉。下面一行定义了一个零维数组:","category":"page"},{"location":"manual/faq/","page":"常见问题","title":"常见问题","text":"julia> A = zeros()\n0-dimensional Array{Float64,0}:\n0.0","category":"page"},{"location":"manual/faq/","page":"常见问题","title":"常见问题","text":"在这个例子中,A是一个含有一个元素的可变容器,这个元素可以通过A[] = 1.0来设置,通过A[]来读取。所有的零维数组都有同样的大小(size(A) == ())和长度(length(A) == 1)。特别地,零维数组不是空数组。如果你觉得这个非直觉,这里有些想法可以帮助理解Julia的这个定义。","category":"page"},{"location":"manual/faq/","page":"常见问题","title":"常见问题","text":"类比的话,零维数组是\"点\",向量是\"线\"而矩阵 是\"面\"。就像线没有面积一样(但是也能代表事物的一个集合), 点没有长度和任意一个维度(但是也能表示一个事物)。\n我们定义prod(())为1,一个数组中的所有的元素个数是 大小的乘积。零维数组的大小为(),所以 它的长度为1。\n零维数组没有任何你可以索引的维度——它们仅仅是A[]。我们可以给它们应用同样的\"尾一\"规则就像对其它维度数组那样,比如A[1],A[1,1],等;参见Omitted and extra indices.","category":"page"},{"location":"manual/faq/","page":"常见问题","title":"常见问题","text":"理解它与普通的标量之间的区别也很重要。标量不是一个可变的容器(尽管它们是可迭代的,可以定义像length,getindex这样的东西,例如1[] == 1)。特别地,如果x = 0.0是以一个标量来定义,尝试通过x[] = 1.0来改变它的值会报错。标量x能够通过fill(x)转化成包含它的零维数组,并且相对地,一个零维数组a可以通过a[]转化成其包含的标量。另外一个区别是标量可以参与到线性代数运算中,比如2 * rand(2,2),但是零维数组的相似操作fill(2) * rand(2,2)会报错。","category":"page"},{"location":"manual/faq/#为什么我的Julia的线性代数操作测试与其他的语言不同。","page":"常见问题","title":"为什么我的Julia的线性代数操作测试与其他的语言不同。","text":"","category":"section"},{"location":"manual/faq/","page":"常见问题","title":"常见问题","text":"你可能找到一些简单的线性代数测试,比如,","category":"page"},{"location":"manual/faq/","page":"常见问题","title":"常见问题","text":"using BenchmarkTools\nA = randn(1000, 1000)\nB = randn(1000, 1000)\n@btime $A \\ $B\n@btime $A * $B","category":"page"},{"location":"manual/faq/","page":"常见问题","title":"常见问题","text":"也许和其他语言不同比如Matlab或R。","category":"page"},{"location":"manual/faq/","page":"常见问题","title":"常见问题","text":"由于像这样的操作都非常直接地从相关的BLAS函数调用,这样做的原因是,","category":"page"},{"location":"manual/faq/","page":"常见问题","title":"常见问题","text":"在每种语言中使用的BLAS库\n并发线程的数量","category":"page"},{"location":"manual/faq/","page":"常见问题","title":"常见问题","text":"Julia 编译并使用自己的 OpenBLAS 副本,当前线程数上限为 8(或内核数)。","category":"page"},{"location":"manual/faq/","page":"常见问题","title":"常见问题","text":"修改 OpenBLAS 设置或使用不同的 BLAS 库编译 Julia,例如 Intel MKL,可能会提高性能。 你可以使用 MKL.jl,这是一个使 Julia 的线性代数使用英特尔 MKL BLAS 和 LAPACK 而不是 OpenBLAS 的包,或搜索论坛以获取有关如何使用的建议。 请注意,英特尔 MKL 不能与 Julia 捆绑在一起,因为它不是开源的。","category":"page"},{"location":"manual/faq/#计算集群","page":"常见问题","title":"计算集群","text":"","category":"section"},{"location":"manual/faq/#我该如何管理分布式文件系统的预编译缓存?","page":"常见问题","title":"我该如何管理分布式文件系统的预编译缓存?","text":"","category":"section"},{"location":"manual/faq/","page":"常见问题","title":"常见问题","text":"在高性能计算 (HPC) 设施中使用 julia 时,同时调用 n 个 julia 进程最多会创建 n 个预编译缓存文件的临时副本。 如果这是一个问题(缓慢和/或小型分布式文件系统),你可以:","category":"page"},{"location":"manual/faq/","page":"常见问题","title":"常见问题","text":"使用 julia的 --compiled-modules=no 标志来关掉预编译。\n使用 pushfirst!(DEPOT_PATH, private_path) 配置一个私有的可写仓库 在这里private_path是一个路径单独地到这个julia进程 也可以通过设置环境变量 JULIA_DEPOT_PATH 到 $private_path:$HOME/.julia.\n在scratch里创建到 ~/.julia/compiled的符号链接。","category":"page"},{"location":"manual/faq/#Julia-版本发布","page":"常见问题","title":"Julia 版本发布","text":"","category":"section"},{"location":"manual/faq/#你希望使用稳定的、长期支持的或是每日构建版本的Julia?","page":"常见问题","title":"你希望使用稳定的、长期支持的或是每日构建版本的Julia?","text":"","category":"section"},{"location":"manual/faq/","page":"常见问题","title":"常见问题","text":"Julia 的稳定版是最新发布的 Julia 版本,这是大多数人想要运行的版本。 它具有最新的功能,包括改进的性能。 Julia 的稳定版本根据 SemVer 版本化为 v1.x.y。 在作为候选版本进行几周的测试后,大约每 4-5 个月就会发布一个与新稳定版本相对应的新 Julia 次要版本。 与 LTS 版本不同,在 Julia 的另一个稳定版本发布后,稳定版本通常不会收到错误修正。 但是,始终可以升级到下一个稳定版本,因为 Julia v1.x 的每个版本都将继续运行为早期版本编写的代码。","category":"page"},{"location":"manual/faq/","page":"常见问题","title":"常见问题","text":"如果正在寻找非常稳定的代码库,你可能更喜欢 Julia 的 LTS(长期支持)版本。 Julia 当前的 LTS 版本根据 SemVer 版本为 v1.0.x; 此分支将继续接收错误修复,直到选择新的 LTS 分支,此时 v1.0.x 系列将不再收到常规错误修复,建议除最保守的用户之外的所有用户升级到新的 LTS 版本系列。作为软件包开发人员,你可能更喜欢针对 LTS 版本进行开发,以最大限度地增加可以使用你的软件包的用户数量。 根据 SemVer,为 v1.0 编写的代码将继续适用于所有未来的 LTS 和稳定版本。 一般来说,即使针对 LTS,也可以在最新的 Stable 版本中开发和运行代码,以利用改进的性能; 只要避免使用新功能(例如添加的库函数或新方法)。","category":"page"},{"location":"manual/faq/","page":"常见问题","title":"常见问题","text":"如果您想利用该语言的最新更新,您可能更喜欢 Julia 的每日构建版本,并且不介意今天可用的版本是否偶尔无法正常工作。 顾名思义,每日构建版本的发布大约每晚发布一次(取决于构建基础设施的稳定性)。 一般来说,每日构建的发布是相当安全的——你的代码不会着火。 然而,它们可能出现偶尔的版本倒退和问题,直到更彻底的预发布测试才会发现。 你可能希望针对每日构建版本进行测试,以确保在发布之前捕获影响你的用例的版本倒退。","category":"page"},{"location":"manual/faq/","page":"常见问题","title":"常见问题","text":"最后,您也可以考虑为自己从源代码构建 Julia。 此选项主要适用于那些熟悉命令行或对学习感兴趣的人。 如果你是这样的人,你可能也有兴趣阅读我们的 贡献指南。","category":"page"},{"location":"manual/faq/","page":"常见问题","title":"常见问题","text":"可以在https://julialang.org/downloads/的下载页面上找到每种下载类型的链接。 请注意,并非所有版本的Julia都适用于所有平台。","category":"page"},{"location":"manual/faq/#更新我的-Julia-版本后,如何转移已安装软件包的列表?","page":"常见问题","title":"更新我的 Julia 版本后,如何转移已安装软件包的列表?","text":"","category":"section"},{"location":"manual/faq/","page":"常见问题","title":"常见问题","text":"julia 的每个次要版本都有自己的默认 环境。 因此,在安装新的 Julia 次要版本时,默认情况下你使用先前次要版本添加的包将不可用。 给定 julia 版本的环境由文件Project.toml和Manifest.toml定义,文件夹中的文件与.julia/environments/中的版本号匹配,例如.julia/environments/v1.3。","category":"page"},{"location":"manual/faq/","page":"常见问题","title":"常见问题","text":"如果你安装了一个新的 Julia 次要版本,比如 1.4,并且想要在它的默认环境中使用与以前版本(例如 1.3)相同的包,你可以从1.3 文件夹复制文件 Project.toml 的内容到1.4。然后,在新的 Julia 版本的会话中,输入] 键进入“包管理模式”,并运行命令 instantiate。","category":"page"},{"location":"manual/faq/","page":"常见问题","title":"常见问题","text":"此操作将从复制的文件中解析一组与目标 Julia 版本兼容的可行包,并在合适时安装或更新它们。 如果你不仅要重现软件包,还要重现在以前的 Julia 版本中使用的版本,您还应该在运行 Pkg 命令 instantiate 之前复制 Manifest.toml 文件。 但是,请注意,包可能定义了兼容性约束,这些约束可能会受到更改 Julia 版本的影响,因此你在1.3中拥有的确切版本集可能不适用于1.4。","category":"page"},{"location":"devdocs/eval/#Julia-代码的-eval","page":"Julia 代码的 eval","title":"Julia 代码的 eval","text":"","category":"section"},{"location":"devdocs/eval/","page":"Julia 代码的 eval","title":"Julia 代码的 eval","text":"学习 Julia 语言如何运行代码的最难的一部分是 学习如何让所有的小部分工作协同工作来执行一段代码。 ","category":"page"},{"location":"devdocs/eval/","page":"Julia 代码的 eval","title":"Julia 代码的 eval","text":"每个代码块通常会通过许多步骤来执行,在转变为期望的结果之前(但愿如此)。并且你可能不熟悉它们的名称,例如(非特定顺序): flisp,AST,C++,LLVM,eval,typeinf,macroexpand,sysimg(或 system image),启动,变异,解析,执行,即时编译器,解释器解释,装箱,拆箱,内部函数,原始函数","category":"page"},{"location":"devdocs/eval/","page":"Julia 代码的 eval","title":"Julia 代码的 eval","text":"sidebar: Definitions\nREPL\nREPL 表示 读取-求值-输出-循环(Read-Eval-Print Loop)。 我们管这个命令行环境的简称就叫REPL。\nAST\n抽象语法树(Abstract Syntax Tree)是代码结构的数据表现。在这种表现形式下代码被符号化,因此更加方便操作和执行。","category":"page"},{"location":"devdocs/eval/#Julia-Execution","page":"Julia 代码的 eval","title":"Julia Execution","text":"","category":"section"},{"location":"devdocs/eval/","page":"Julia 代码的 eval","title":"Julia 代码的 eval","text":"整个进程的千里之行如下:","category":"page"},{"location":"devdocs/eval/","page":"Julia 代码的 eval","title":"Julia 代码的 eval","text":"用户打开了 julia。\nThe C function main() from cli/loader_exe.c gets called. This function processes the command line arguments, filling in the jl_options struct and setting the variable ARGS. It then initializes 在 ui/repl.c 中的 C 语言的函数 main() 被调用。这个函数处理命令行参数,填充到 jl_options 结构图并且设置变了 ARGS 。接下来初始化 Julia (通过调用 julia_init in task.c which may load a previously compiled sysimg). Finally, it passes off control to Julia by calling Base._start().\nWhen _start() takes over control, the subsequent sequence of commands depends on the command line arguments given. For example, if a filename was supplied, it will proceed to execute that file. Otherwise, it will start an interactive REPL.\nSkipping the details about how the REPL interacts with the user, let's just say the program ends up with a block of code that it wants to run.\nIf the block of code to run is in a file, jl_load(char *filename) gets invoked to load the file and parse it. Each fragment of code is then passed to eval to execute.\nEach fragment of code (or AST), is handed off to eval() to turn into results.\neval() takes each code fragment and tries to run it in jl_toplevel_eval_flex().\njl_toplevel_eval_flex() decides whether the code is a \"toplevel\" action (such as using or module), which would be invalid inside a function. If so, it passes off the code to the toplevel interpreter.\njl_toplevel_eval_flex() then expands the code to eliminate any macros and to \"lower\" the AST to make it simpler to execute.\njl_toplevel_eval_flex() then uses some simple heuristics to decide whether to JIT compiler the AST or to interpret it directly.\nThe bulk of the work to interpret code is handled by eval in interpreter.c.\nIf instead, the code is compiled, the bulk of the work is handled by codegen.cpp. Whenever a Julia function is called for the first time with a given set of argument types, type inference will be run on that function. This information is used by the codegen step to generate faster code.\nEventually, the user quits the REPL, or the end of the program is reached, and the _start() method returns.\nJust before exiting, main() calls jl_atexit_hook(exit_code). This calls Base._atexit() (which calls any functions registered to atexit() inside Julia). Then it calls jl_gc_run_all_finalizers(). Finally, it gracefully cleans up all libuv handles and waits for them to flush and close.","category":"page"},{"location":"devdocs/eval/#dev-parsing","page":"Julia 代码的 eval","title":"Parsing","text":"","category":"section"},{"location":"devdocs/eval/","page":"Julia 代码的 eval","title":"Julia 代码的 eval","text":"The Julia parser is a small lisp program written in femtolisp, the source-code for which is distributed inside Julia in src/flisp.","category":"page"},{"location":"devdocs/eval/","page":"Julia 代码的 eval","title":"Julia 代码的 eval","text":"The interface functions for this are primarily defined in jlfrontend.scm. The code in ast.c handles this handoff on the Julia side.","category":"page"},{"location":"devdocs/eval/","page":"Julia 代码的 eval","title":"Julia 代码的 eval","text":"The other relevant files at this stage are julia-parser.scm, which handles tokenizing Julia code and turning it into an AST, and julia-syntax.scm, which handles transforming complex AST representations into simpler, \"lowered\" AST representations which are more suitable for analysis and execution.","category":"page"},{"location":"devdocs/eval/","page":"Julia 代码的 eval","title":"Julia 代码的 eval","text":"If you want to test the parser without re-building Julia in its entirety, you can run the frontend on its own as follows:","category":"page"},{"location":"devdocs/eval/","page":"Julia 代码的 eval","title":"Julia 代码的 eval","text":"$ cd src\n$ flisp/flisp\n> (load \"jlfrontend.scm\")\n> (jl-parse-file \"\")","category":"page"},{"location":"devdocs/eval/#dev-macro-expansion","page":"Julia 代码的 eval","title":"Macro Expansion","text":"","category":"section"},{"location":"devdocs/eval/","page":"Julia 代码的 eval","title":"Julia 代码的 eval","text":"When eval() encounters a macro, it expands that AST node before attempting to evaluate the expression. Macro expansion involves a handoff from eval() (in Julia), to the parser function jl_macroexpand() (written in flisp) to the Julia macro itself (written in - what else - Julia) via fl_invoke_julia_macro(), and back.","category":"page"},{"location":"devdocs/eval/","page":"Julia 代码的 eval","title":"Julia 代码的 eval","text":"Typically, macro expansion is invoked as a first step during a call to Meta.lower()/jl_expand(), although it can also be invoked directly by a call to macroexpand()/jl_macroexpand().","category":"page"},{"location":"devdocs/eval/#dev-type-inference","page":"Julia 代码的 eval","title":"Type Inference","text":"","category":"section"},{"location":"devdocs/eval/","page":"Julia 代码的 eval","title":"Julia 代码的 eval","text":"Type inference is implemented in Julia by typeinf() in compiler/typeinfer.jl. Type inference is the process of examining a Julia function and determining bounds for the types of each of its variables, as well as bounds on the type of the return value from the function. This enables many future optimizations, such as unboxing of known immutable values, and compile-time hoisting of various run-time operations such as computing field offsets and function pointers. Type inference may also include other steps such as constant propagation and inlining.","category":"page"},{"location":"devdocs/eval/","page":"Julia 代码的 eval","title":"Julia 代码的 eval","text":"sidebar: More Definitions\nJIT\nJust-In-Time Compilation The process of generating native-machine code into memory right when it is needed.\nLLVM\nLow-Level Virtual Machine (a compiler) The Julia JIT compiler is a program/library called libLLVM. Codegen in Julia refers both to the process of taking a Julia AST and turning it into LLVM instructions, and the process of LLVM optimizing that and turning it into native assembly instructions.\nC++\nThe programming language that LLVM is implemented in, which means that codegen is also implemented in this language. The rest of Julia's library is implemented in C, in part because its smaller feature set makes it more usable as a cross-language interface layer.\nbox\nThis term is used to describe the process of taking a value and allocating a wrapper around the data that is tracked by the garbage collector (gc) and is tagged with the object's type.\nunbox\nThe reverse of boxing a value. This operation enables more efficient manipulation of data when the type of that data is fully known at compile-time (through type inference).\ngeneric function\nA Julia function composed of multiple \"methods\" that are selected for dynamic dispatch based on the argument type-signature\nanonymous function or \"method\"\nA Julia function without a name and without type-dispatch capabilities\nprimitive function\nA function implemented in C but exposed in Julia as a named function \"method\" (albeit without generic function dispatch capabilities, similar to a anonymous function)\nintrinsic function\nA low-level operation exposed as a function in Julia. These pseudo-functions implement operations on raw bits such as add and sign extend that cannot be expressed directly in any other way. Since they operate on bits directly, they must be compiled into a function and surrounded by a call to Core.Intrinsics.box(T, ...) to reassign type information to the value.","category":"page"},{"location":"devdocs/eval/#dev-codegen","page":"Julia 代码的 eval","title":"JIT Code Generation","text":"","category":"section"},{"location":"devdocs/eval/","page":"Julia 代码的 eval","title":"Julia 代码的 eval","text":"Codegen is the process of turning a Julia AST into native machine code.","category":"page"},{"location":"devdocs/eval/","page":"Julia 代码的 eval","title":"Julia 代码的 eval","text":"The JIT environment is initialized by an early call to jl_init_codegen in codegen.cpp.","category":"page"},{"location":"devdocs/eval/","page":"Julia 代码的 eval","title":"Julia 代码的 eval","text":"On demand, a Julia method is converted into a native function by the function emit_function(jl_method_instance_t*). (note, when using the MCJIT (in LLVM v3.4+), each function must be JIT into a new module.) This function recursively calls emit_expr() until the entire function has been emitted.","category":"page"},{"location":"devdocs/eval/","page":"Julia 代码的 eval","title":"Julia 代码的 eval","text":"Much of the remaining bulk of this file is devoted to various manual optimizations of specific code patterns. For example, emit_known_call() knows how to inline many of the primitive functions (defined in builtins.c) for various combinations of argument types.","category":"page"},{"location":"devdocs/eval/","page":"Julia 代码的 eval","title":"Julia 代码的 eval","text":"Other parts of codegen are handled by various helper files:","category":"page"},{"location":"devdocs/eval/","page":"Julia 代码的 eval","title":"Julia 代码的 eval","text":"debuginfo.cpp\nHandles backtraces for JIT functions\nccall.cpp\nHandles the ccall and llvmcall FFI, along with various abi_*.cpp files\nintrinsics.cpp\nHandles the emission of various low-level intrinsic functions","category":"page"},{"location":"devdocs/eval/","page":"Julia 代码的 eval","title":"Julia 代码的 eval","text":"sidebar: Bootstrapping\nThe process of creating a new system image is called \"bootstrapping\".The etymology of this word comes from the phrase \"pulling oneself up by the bootstraps\", and refers to the idea of starting from a very limited set of available functions and definitions and ending with the creation of a full-featured environment.","category":"page"},{"location":"devdocs/eval/#dev-sysimg","page":"Julia 代码的 eval","title":"System Image","text":"","category":"section"},{"location":"devdocs/eval/","page":"Julia 代码的 eval","title":"Julia 代码的 eval","text":"The system image is a precompiled archive of a set of Julia files. The sys.ji file distributed with Julia is one such system image, generated by executing the file sysimg.jl, and serializing the resulting environment (including Types, Functions, Modules, and all other defined values) into a file. Therefore, it contains a frozen version of the Main, Core, and Base modules (and whatever else was in the environment at the end of bootstrapping). This serializer/deserializer is implemented by jl_save_system_image/jl_restore_system_image in staticdata.c.","category":"page"},{"location":"devdocs/eval/","page":"Julia 代码的 eval","title":"Julia 代码的 eval","text":"If there is no sysimg file (jl_options.image_file == NULL), this also implies that --build was given on the command line, so the final result should be a new sysimg file. During Julia initialization, minimal Core and Main modules are created. Then a file named boot.jl is evaluated from the current directory. Julia then evaluates any file given as a command line argument until it reaches the end. Finally, it saves the resulting environment to a \"sysimg\" file for use as a starting point for a future Julia run.","category":"page"},{"location":"devdocs/gc-sa/#Static-analyzer-annotations-for-GC-correctness-in-C-code","page":"Static analyzer annotations for GC correctness in C code","title":"Static analyzer annotations for GC correctness in C code","text":"","category":"section"},{"location":"devdocs/gc-sa/#Running-the-analysis","page":"Static analyzer annotations for GC correctness in C code","title":"Running the analysis","text":"","category":"section"},{"location":"devdocs/gc-sa/","page":"Static analyzer annotations for GC correctness in C code","title":"Static analyzer annotations for GC correctness in C code","text":"The analyzer plugin that drives the anlysis ships with julia. Its source code can be found in src/clangsa. Running it requires the clang dependency to be build. Set the BUILD_LLVM_CLANG variable in your Make.user in order to build an appropriate version of clang. You may also want to use the prebuilt binaries using the USE_BINARYBUILDER_LLVM options. Afterwards, running the analysis over the source tree is as simple as running make -C src analyzegc.","category":"page"},{"location":"devdocs/gc-sa/#General-Overview","page":"Static analyzer annotations for GC correctness in C code","title":"General Overview","text":"","category":"section"},{"location":"devdocs/gc-sa/","page":"Static analyzer annotations for GC correctness in C code","title":"Static analyzer annotations for GC correctness in C code","text":"Since Julia's GC is precise, it needs to maintain correct rooting information for any value that may be referenced at any time GC may occur. These places are known as safepoints and in the function local context, we extend this designation to any function call that may recursively end up at a safepoint.","category":"page"},{"location":"devdocs/gc-sa/","page":"Static analyzer annotations for GC correctness in C code","title":"Static analyzer annotations for GC correctness in C code","text":"In generated code, this is taken care of automatically by the GC root placement pass (see the chapter on GC rooting in the LLVM codegen devdocs). However, in C code, we need to inform the runtime of any GC roots manually. This is done using the following macros:","category":"page"},{"location":"devdocs/gc-sa/","page":"Static analyzer annotations for GC correctness in C code","title":"Static analyzer annotations for GC correctness in C code","text":"// The value assigned to any slot passed as an argument to these\n// is rooted for the duration of this GC frame.\nJL_GC_PUSH{1,...,6}(args...)\n// The values assigned into the size `n` array `rts` are rooted\n// for the duration of this GC frame.\nJL_GC_PUSHARGS(rts, n)\n// Pop a GC frame\nJL_GC_POP","category":"page"},{"location":"devdocs/gc-sa/","page":"Static analyzer annotations for GC correctness in C code","title":"Static analyzer annotations for GC correctness in C code","text":"If these macros are not used where they need to be, or they are used incorrectly, the result is silent memory corruption. As such it is very important that they are placed correctly in all applicable code.","category":"page"},{"location":"devdocs/gc-sa/","page":"Static analyzer annotations for GC correctness in C code","title":"Static analyzer annotations for GC correctness in C code","text":"As such, we employ static analysis (and in particular the clang static analyzer) to help ensure that these macros are used correctly. The remainder of this document gives an overview of this static analysis and describes the support needed in the julia code base to make things work.","category":"page"},{"location":"devdocs/gc-sa/#GC-Invariants","page":"Static analyzer annotations for GC correctness in C code","title":"GC Invariants","text":"","category":"section"},{"location":"devdocs/gc-sa/","page":"Static analyzer annotations for GC correctness in C code","title":"Static analyzer annotations for GC correctness in C code","text":"There is two simple invariants correctness:","category":"page"},{"location":"devdocs/gc-sa/","page":"Static analyzer annotations for GC correctness in C code","title":"Static analyzer annotations for GC correctness in C code","text":"All GC_PUSH calls need to be followed by an appropriate GC_POP (in practice we enforce this at the function level)\nIf a value was previously not rooted at any safepoint, it may no longer be referenced afterwards","category":"page"},{"location":"devdocs/gc-sa/","page":"Static analyzer annotations for GC correctness in C code","title":"Static analyzer annotations for GC correctness in C code","text":"Of course the devil is in the details here. In particular to satisfy the second of the above conditions, we need to know:","category":"page"},{"location":"devdocs/gc-sa/","page":"Static analyzer annotations for GC correctness in C code","title":"Static analyzer annotations for GC correctness in C code","text":"Which calls are safepoints and which are not\nWhich values are rooted at any given safepoint and which are not\nWhen is a value referenced","category":"page"},{"location":"devdocs/gc-sa/","page":"Static analyzer annotations for GC correctness in C code","title":"Static analyzer annotations for GC correctness in C code","text":"For the second point in particular, we need to know which memory locations will be considered rooting at runtime (i.e. values assigned to such locations are rooted). This includes locations explicitly designated as such by passing them to one of the GC_PUSH macros, globally rooted locations and values, as well as any location recursively reachable from one of those locations.","category":"page"},{"location":"devdocs/gc-sa/#Static-Analysis-Algorithm","page":"Static analyzer annotations for GC correctness in C code","title":"Static Analysis Algorithm","text":"","category":"section"},{"location":"devdocs/gc-sa/","page":"Static analyzer annotations for GC correctness in C code","title":"Static analyzer annotations for GC correctness in C code","text":"The idea itself is very simple, although the implementation is quite a bit more complicated (mainly due to a large number of special cases and intricacies of C and C++). In essence, we keep track of all locations that are rooting, all values that are rootable and any expression (assignments, allocations, etc) affect the rootedness of any rootable values. Then, at any safepoint, we perform a \"symbolic GC\" and poison any values that are not rooted at said location. If these values are later referenced, we emit an error.","category":"page"},{"location":"devdocs/gc-sa/","page":"Static analyzer annotations for GC correctness in C code","title":"Static analyzer annotations for GC correctness in C code","text":"The clang static analyzer works by constructing a graph of states and exploring this graph for sources of errors. Several nodes in this graph are generated by the analyzer itself (e.g. for control flow), but the definitions above augment this graph with our own state.","category":"page"},{"location":"devdocs/gc-sa/","page":"Static analyzer annotations for GC correctness in C code","title":"Static analyzer annotations for GC correctness in C code","text":"The static analyzer is interprocedural and can analyze control flow across function boundaries. However, the static analyzer is not fully recursive and makes heuristic decisions about which calls to explore (additionally some calls are cross-translation unit and invisible to the analyzer). In our case, our definition of correctness requires total information. As such, we need to annotate the prototypes of all function calls with whatever information the analysis required, even if that information would otherwise be available by interprocedural static analysis.","category":"page"},{"location":"devdocs/gc-sa/","page":"Static analyzer annotations for GC correctness in C code","title":"Static analyzer annotations for GC correctness in C code","text":"Luckily however, we can still use this interprocedural analysis to ensure that the annotations we place on a given function are indeed correct given the implementation of said function.","category":"page"},{"location":"devdocs/gc-sa/#The-analyzer-annotations","page":"Static analyzer annotations for GC correctness in C code","title":"The analyzer annotations","text":"","category":"section"},{"location":"devdocs/gc-sa/","page":"Static analyzer annotations for GC correctness in C code","title":"Static analyzer annotations for GC correctness in C code","text":"These annotations are found in src/support/analyzer_annotations.h. The are only active when the analyzer is being used and expand either to nothing (for prototype annotations) or to no-ops (for function like annotations).","category":"page"},{"location":"devdocs/gc-sa/#JL_NOTSAFEPOINT","page":"Static analyzer annotations for GC correctness in C code","title":"JL_NOTSAFEPOINT","text":"","category":"section"},{"location":"devdocs/gc-sa/","page":"Static analyzer annotations for GC correctness in C code","title":"Static analyzer annotations for GC correctness in C code","text":"This is perhaps the most common annotation, and should be placed on any function that is known not to possibly lead to reaching a GC safepoint. In general, it is only safe for such a function to perform arithmetic, memory accesses and calls to functions either annotated JL_NOTSAFEPOINT or otherwise known not to be safepoints (e.g. function in the C standard library, which are hardcoded as such in the analyzer)","category":"page"},{"location":"devdocs/gc-sa/","page":"Static analyzer annotations for GC correctness in C code","title":"Static analyzer annotations for GC correctness in C code","text":"It is valid to keep values unrooted across calls to any function annotated with this attribute:","category":"page"},{"location":"devdocs/gc-sa/","page":"Static analyzer annotations for GC correctness in C code","title":"Static analyzer annotations for GC correctness in C code","text":"Usage Example:","category":"page"},{"location":"devdocs/gc-sa/","page":"Static analyzer annotations for GC correctness in C code","title":"Static analyzer annotations for GC correctness in C code","text":"void jl_get_one() JL_NOTSAFEPOINT {\n return 1;\n}\n\njl_value_t *example() {\n jl_value_t *val = jl_alloc_whatever();\n // This is valid, even though `val` is unrooted, because\n // jl_get_one is not a safepoint\n jl_get_one();\n return val;\n}","category":"page"},{"location":"devdocs/gc-sa/#JL_MAYBE_UNROOTED/JL_ROOTS_TEMPORARILY","page":"Static analyzer annotations for GC correctness in C code","title":"JL_MAYBE_UNROOTED/JL_ROOTS_TEMPORARILY","text":"","category":"section"},{"location":"devdocs/gc-sa/","page":"Static analyzer annotations for GC correctness in C code","title":"Static analyzer annotations for GC correctness in C code","text":"When JL_MAYBE_UNROOTED is annotated as an argument on a function, indicates that said argument may be passed, even if it is not rooted. In the ordinary course of events, the julia ABI guarantees that callers root values before passing them to callees. However, some functions do not follow this ABI and allow values to be passed to them even though they are not rooted. Note however, that this does not automatically imply that said argument will be preserved. The ROOTS_TEMPORARILY annotation provides the stronger guarantee that, not only may the value be unrooted when passed, it will also be preserved across any internal safepoints by the callee.","category":"page"},{"location":"devdocs/gc-sa/","page":"Static analyzer annotations for GC correctness in C code","title":"Static analyzer annotations for GC correctness in C code","text":"Note that JL_NOTSAFEPOINT essentially implies JL_MAYBE_UNROOTED/JL_ROOTS_TEMPORARILY, because the rootedness of an argument is irrelevant if the function contains no safepoints.","category":"page"},{"location":"devdocs/gc-sa/","page":"Static analyzer annotations for GC correctness in C code","title":"Static analyzer annotations for GC correctness in C code","text":"One additional point to note is that these annotations apply on both the caller and the callee side. On the caller side, they lift rootedness restrictions that are normally required for julia ABI functions. On the callee side, they have the reverse effect of preventing these arguments from being considered implicitly rooted.","category":"page"},{"location":"devdocs/gc-sa/","page":"Static analyzer annotations for GC correctness in C code","title":"Static analyzer annotations for GC correctness in C code","text":"If either of these annotations is applied to the function as a whole, it applies to all arguments of the function. This should generally only be necessary for varargs functions.","category":"page"},{"location":"devdocs/gc-sa/","page":"Static analyzer annotations for GC correctness in C code","title":"Static analyzer annotations for GC correctness in C code","text":"Usage example:","category":"page"},{"location":"devdocs/gc-sa/","page":"Static analyzer annotations for GC correctness in C code","title":"Static analyzer annotations for GC correctness in C code","text":"JL_DLLEXPORT void JL_NORETURN jl_throw(jl_value_t *e JL_MAYBE_UNROOTED);\njl_value_t *jl_alloc_error();\n\nvoid example() {\n // The return value of the allocation is unrooted. This would normally\n // be an error, but is allowed because of the above annotation.\n jl_throw(jl_alloc_error());\n}","category":"page"},{"location":"devdocs/gc-sa/#JL_PROPAGATES_ROOT","page":"Static analyzer annotations for GC correctness in C code","title":"JL_PROPAGATES_ROOT","text":"","category":"section"},{"location":"devdocs/gc-sa/","page":"Static analyzer annotations for GC correctness in C code","title":"Static analyzer annotations for GC correctness in C code","text":"This annotation is commonly found on accessor functions that return one rootable object stored within another. When annotated on a function argument, it tells the analyzer that the root for that argument also applies to the value returned by the function.","category":"page"},{"location":"devdocs/gc-sa/","page":"Static analyzer annotations for GC correctness in C code","title":"Static analyzer annotations for GC correctness in C code","text":"Usage Example:","category":"page"},{"location":"devdocs/gc-sa/","page":"Static analyzer annotations for GC correctness in C code","title":"Static analyzer annotations for GC correctness in C code","text":"jl_value_t *jl_svecref(jl_svec_t *t JL_PROPAGATES_ROOT, size_t i) JL_NOTSAFEPOINT;\n\nsize_t example(jl_svec_t *svec) {\n jl_value_t *val = jl_svecref(svec, 1)\n // This is valid, because, as annotated by the PROPAGATES_ROOT annotation,\n // jl_svecref propagates the rooted-ness from `svec` to `val`\n jl_gc_safepoint();\n return jl_unbox_long(val);\n}","category":"page"},{"location":"devdocs/gc-sa/#JL_ROOTING_ARGUMENT/JL_ROOTED_ARGUMENT","page":"Static analyzer annotations for GC correctness in C code","title":"JL_ROOTING_ARGUMENT/JL_ROOTED_ARGUMENT","text":"","category":"section"},{"location":"devdocs/gc-sa/","page":"Static analyzer annotations for GC correctness in C code","title":"Static analyzer annotations for GC correctness in C code","text":"This is essentially the assignment counterpart to JL_PROPAGATES_ROOT. When assigning a value to a field of another value that is already rooted, the assigned value will inherit the root of the value it is assigned into.","category":"page"},{"location":"devdocs/gc-sa/","page":"Static analyzer annotations for GC correctness in C code","title":"Static analyzer annotations for GC correctness in C code","text":"Usage Example:","category":"page"},{"location":"devdocs/gc-sa/","page":"Static analyzer annotations for GC correctness in C code","title":"Static analyzer annotations for GC correctness in C code","text":"void jl_svecset(void *t JL_ROOTING_ARGUMENT, size_t i, void *x JL_ROOTED_ARGUMENT) JL_NOTSAFEPOINT\n\n\nsize_t example(jl_svec_t *svec) {\n jl_value_t *val = jl_box_long(10000);\n jl_svecset(svec, val);\n // This is valid, because the annotations imply that the\n // jl_svecset propagates the rooted-ness from `svec` to `val`\n jl_gc_safepoint();\n return jl_unbox_long(val);\n}","category":"page"},{"location":"devdocs/gc-sa/#JL_GC_DISABLED","page":"Static analyzer annotations for GC correctness in C code","title":"JL_GC_DISABLED","text":"","category":"section"},{"location":"devdocs/gc-sa/","page":"Static analyzer annotations for GC correctness in C code","title":"Static analyzer annotations for GC correctness in C code","text":"This annotation implies that this function is only called with the GC runtime-disabled. Functions of this kind are most often encountered during startup and in the GC code itself. Note that this annotation is checked against the runtime enable/disable calls, so clang will know if you lie. This is not a good way to disable processing of a given function if the GC is not actually disabled (use ifdef __clang_analyzer__ for that if you must).","category":"page"},{"location":"devdocs/gc-sa/","page":"Static analyzer annotations for GC correctness in C code","title":"Static analyzer annotations for GC correctness in C code","text":"Usage example:","category":"page"},{"location":"devdocs/gc-sa/","page":"Static analyzer annotations for GC correctness in C code","title":"Static analyzer annotations for GC correctness in C code","text":"void jl_do_magic() JL_GC_DISABLED {\n // Wildly allocate here with no regard for roots\n}\n\nvoid example() {\n int en = jl_gc_enable(0);\n jl_do_magic();\n jl_gc_enable(en);\n}","category":"page"},{"location":"devdocs/gc-sa/#JL_REQUIRE_ROOTED_SLOT","page":"Static analyzer annotations for GC correctness in C code","title":"JL_REQUIRE_ROOTED_SLOT","text":"","category":"section"},{"location":"devdocs/gc-sa/","page":"Static analyzer annotations for GC correctness in C code","title":"Static analyzer annotations for GC correctness in C code","text":"This annotation requires the caller to pass in a slot that is rooted (i.e. values assigned to this slot will be rooted).","category":"page"},{"location":"devdocs/gc-sa/","page":"Static analyzer annotations for GC correctness in C code","title":"Static analyzer annotations for GC correctness in C code","text":"Usage example:","category":"page"},{"location":"devdocs/gc-sa/","page":"Static analyzer annotations for GC correctness in C code","title":"Static analyzer annotations for GC correctness in C code","text":"void jl_do_processing(jl_value_t **slot JL_REQUIRE_ROOTED_SLOT) {\n *slot = jl_box_long(1);\n // Ok, only, because the slot was annotated as rooting\n jl_gc_safepoint();\n}\n\nvoid example() {\n jl_value_t *slot = NULL;\n JL_GC_PUSH1(&slot);\n jl_do_processing(&slot);\n JL_GC_POP();\n}","category":"page"},{"location":"devdocs/gc-sa/#JL_GLOBALLY_ROOTED","page":"Static analyzer annotations for GC correctness in C code","title":"JL_GLOBALLY_ROOTED","text":"","category":"section"},{"location":"devdocs/gc-sa/","page":"Static analyzer annotations for GC correctness in C code","title":"Static analyzer annotations for GC correctness in C code","text":"This annotation implies that a given value is always globally rooted. It can be applied to global variable declarations, in which case it will apply to the value of those variables (or values if the declaration if for an array), or to functions, in which case it will apply to the return value of such functions (e.g. for functions that always return some private, globally rooted value).","category":"page"},{"location":"devdocs/gc-sa/","page":"Static analyzer annotations for GC correctness in C code","title":"Static analyzer annotations for GC correctness in C code","text":"Usage example:","category":"page"},{"location":"devdocs/gc-sa/","page":"Static analyzer annotations for GC correctness in C code","title":"Static analyzer annotations for GC correctness in C code","text":"extern JL_DLLEXPORT jl_datatype_t *jl_any_type JL_GLOBALLY_ROOTED;\njl_ast_context_t *jl_ast_ctx(fl_context_t *fl) JL_GLOBALLY_ROOTED;","category":"page"},{"location":"devdocs/gc-sa/#JL_ALWAYS_LEAFTYPE","page":"Static analyzer annotations for GC correctness in C code","title":"JL_ALWAYS_LEAFTYPE","text":"","category":"section"},{"location":"devdocs/gc-sa/","page":"Static analyzer annotations for GC correctness in C code","title":"Static analyzer annotations for GC correctness in C code","text":"This annotations is essentially equivalent to JL_GLOBALLY_ROOTED, except that is should only be used if those values are globally rooted by virtue of being a leaftype. The rooting of leaftypes is a bit complicated. They are generally rooted through cache field of the corresponding TypeName, which itself is rooted by the containing module (so they're rooted as long as the containing module is ok) and we can generally assume that leaftypes are rooted where they are used, but we may refine this property in the future, so the separate annotation helps split out the reason for being globally rooted.","category":"page"},{"location":"devdocs/gc-sa/","page":"Static analyzer annotations for GC correctness in C code","title":"Static analyzer annotations for GC correctness in C code","text":"The analyzer also automatically detects checks for leaftype-ness and will not complain about missing GC roots on these paths.","category":"page"},{"location":"devdocs/gc-sa/","page":"Static analyzer annotations for GC correctness in C code","title":"Static analyzer annotations for GC correctness in C code","text":"JL_DLLEXPORT jl_value_t *jl_apply_array_type(jl_value_t *type, size_t dim) JL_ALWAYS_LEAFTYPE;","category":"page"},{"location":"devdocs/gc-sa/#JL_GC_PROMISE_ROOTED","page":"Static analyzer annotations for GC correctness in C code","title":"JL_GC_PROMISE_ROOTED","text":"","category":"section"},{"location":"devdocs/gc-sa/","page":"Static analyzer annotations for GC correctness in C code","title":"Static analyzer annotations for GC correctness in C code","text":"This is a function-like annotation. Any value passed to this annotation will be considered rooted for the scope of the current function. It is designed as an escape hatch for analyzer inadequacy or complicated situations. However, it should be used sparingly, in favor of improving the analyzer itself.","category":"page"},{"location":"devdocs/gc-sa/","page":"Static analyzer annotations for GC correctness in C code","title":"Static analyzer annotations for GC correctness in C code","text":"void example() {\n jl_value_t *val = jl_alloc_something();\n if (some_condition) {\n // We happen to know for complicated external reasons\n // that val is rooted under these conditions\n JL_GC_PROMISE_ROOTED(val);\n }\n}","category":"page"},{"location":"devdocs/gc-sa/#Completeness-of-analysis","page":"Static analyzer annotations for GC correctness in C code","title":"Completeness of analysis","text":"","category":"section"},{"location":"devdocs/gc-sa/","page":"Static analyzer annotations for GC correctness in C code","title":"Static analyzer annotations for GC correctness in C code","text":"The analyzer only looks at local information. In particular, e.g. in the PROPAGATES_ROOT case above, it assumes that such memory is only modified in ways it can see, not in any called functions (unless it happens to decide to consider them in its analysis) and not in any concurrently running threads. As such, it may miss a few problematic cases, though in practice such concurrent modification is fairly rare. Improving the analyzer to handle more such cases may be an interesting topic for future work.","category":"page"},{"location":"devdocs/llvm/#Working-with-LLVM","page":"Working with LLVM","title":"Working with LLVM","text":"","category":"section"},{"location":"devdocs/llvm/","page":"Working with LLVM","title":"Working with LLVM","text":"This is not a replacement for the LLVM documentation, but a collection of tips for working on LLVM for Julia.","category":"page"},{"location":"devdocs/llvm/#Overview-of-Julia-to-LLVM-Interface","page":"Working with LLVM","title":"Overview of Julia to LLVM Interface","text":"","category":"section"},{"location":"devdocs/llvm/","page":"Working with LLVM","title":"Working with LLVM","text":"Julia dynamically links against LLVM by default. Build with USE_LLVM_SHLIB=0 to link statically.","category":"page"},{"location":"devdocs/llvm/","page":"Working with LLVM","title":"Working with LLVM","text":"The code for lowering Julia AST to LLVM IR or interpreting it directly is in directory src/.","category":"page"},{"location":"devdocs/llvm/","page":"Working with LLVM","title":"Working with LLVM","text":"File Description\nbuiltins.c Builtin functions\nccall.cpp Lowering ccall\ncgutils.cpp Lowering utilities, notably for array and tuple accesses\ncodegen.cpp Top-level of code generation, pass list, lowering builtins\ndebuginfo.cpp Tracks debug information for JIT code\ndisasm.cpp Handles native object file and JIT code diassembly\ngf.c Generic functions\nintrinsics.cpp Lowering intrinsics\nllvm-simdloop.cpp Custom LLVM pass for @simd\nsys.c I/O and operating system utility functions","category":"page"},{"location":"devdocs/llvm/","page":"Working with LLVM","title":"Working with LLVM","text":"Some of the .cpp files form a group that compile to a single object.","category":"page"},{"location":"devdocs/llvm/","page":"Working with LLVM","title":"Working with LLVM","text":"The difference between an intrinsic and a builtin is that a builtin is a first class function that can be used like any other Julia function. An intrinsic can operate only on unboxed data, and therefore its arguments must be statically typed.","category":"page"},{"location":"devdocs/llvm/#Alias-Analysis","page":"Working with LLVM","title":"Alias Analysis","text":"","category":"section"},{"location":"devdocs/llvm/","page":"Working with LLVM","title":"Working with LLVM","text":"Julia currently uses LLVM's Type Based Alias Analysis. To find the comments that document the inclusion relationships, look for static MDNode* in src/codegen.cpp.","category":"page"},{"location":"devdocs/llvm/","page":"Working with LLVM","title":"Working with LLVM","text":"The -O option enables LLVM's Basic Alias Analysis.","category":"page"},{"location":"devdocs/llvm/#Building-Julia-with-a-different-version-of-LLVM","page":"Working with LLVM","title":"Building Julia with a different version of LLVM","text":"","category":"section"},{"location":"devdocs/llvm/","page":"Working with LLVM","title":"Working with LLVM","text":"The default version of LLVM is specified in deps/Versions.make. You can override it by creating a file called Make.user in the top-level directory and adding a line to it such as:","category":"page"},{"location":"devdocs/llvm/","page":"Working with LLVM","title":"Working with LLVM","text":"LLVM_VER = 12.0.1","category":"page"},{"location":"devdocs/llvm/","page":"Working with LLVM","title":"Working with LLVM","text":"Besides the LLVM release numerals, you can also use LLVM_VER = svn to build against the latest development version of LLVM.","category":"page"},{"location":"devdocs/llvm/","page":"Working with LLVM","title":"Working with LLVM","text":"You can also specify to build a debug version of LLVM, by setting either LLVM_DEBUG = 1 or LLVM_DEBUG = Release in your Make.user file. The former will be a fully unoptimized build of LLVM and the latter will produce an optimized build of LLVM. Depending on your needs the latter will suffice and it quite a bit faster. If you use LLVM_DEBUG = Release you will also want to set LLVM_ASSERTIONS = 1 to enable diagnostics for different passes. Only LLVM_DEBUG = 1 implies that option by default.","category":"page"},{"location":"devdocs/llvm/#Passing-options-to-LLVM","page":"Working with LLVM","title":"Passing options to LLVM","text":"","category":"section"},{"location":"devdocs/llvm/","page":"Working with LLVM","title":"Working with LLVM","text":"You can pass options to LLVM via the environment variable JULIA_LLVM_ARGS. Here are example settings using bash syntax:","category":"page"},{"location":"devdocs/llvm/","page":"Working with LLVM","title":"Working with LLVM","text":"export JULIA_LLVM_ARGS=-print-after-all dumps IR after each pass.\nexport JULIA_LLVM_ARGS=-debug-only=loop-vectorize dumps LLVM DEBUG(...) diagnostics for loop vectorizer. If you get warnings about \"Unknown command line argument\", rebuild LLVM with LLVM_ASSERTIONS = 1.","category":"page"},{"location":"devdocs/llvm/#Debugging-LLVM-transformations-in-isolation","page":"Working with LLVM","title":"Debugging LLVM transformations in isolation","text":"","category":"section"},{"location":"devdocs/llvm/","page":"Working with LLVM","title":"Working with LLVM","text":"On occasion, it can be useful to debug LLVM's transformations in isolation from the rest of the Julia system, e.g. because reproducing the issue inside julia would take too long, or because one wants to take advantage of LLVM's tooling (e.g. bugpoint). To get unoptimized IR for the entire system image, pass the --output-unopt-bc unopt.bc option to the system image build process, which will output the unoptimized IR to an unopt.bc file. This file can then be passed to LLVM tools as usual. libjulia can function as an LLVM pass plugin and can be loaded into LLVM tools, to make julia-specific passes available in this environment. In addition, it exposes the -julia meta-pass, which runs the entire Julia pass-pipeline over the IR. As an example, to generate a system image, one could do:","category":"page"},{"location":"devdocs/llvm/","page":"Working with LLVM","title":"Working with LLVM","text":"opt -load libjulia-internal.so -julia -o opt.bc unopt.bc\nllc -o sys.o opt.bc\ncc -shared -o sys.so sys.o","category":"page"},{"location":"devdocs/llvm/","page":"Working with LLVM","title":"Working with LLVM","text":"This system image can then be loaded by julia as usual.","category":"page"},{"location":"devdocs/llvm/","page":"Working with LLVM","title":"Working with LLVM","text":"It is also possible to dump an LLVM IR module for just one Julia function, using:","category":"page"},{"location":"devdocs/llvm/","page":"Working with LLVM","title":"Working with LLVM","text":"fun, T = +, Tuple{Int,Int} # Substitute your function of interest here\noptimize = false\nopen(\"plus.ll\", \"w\") do file\n println(file, InteractiveUtils._dump_function(fun, T, false, false, false, true, :att, optimize, :default))\nend","category":"page"},{"location":"devdocs/llvm/","page":"Working with LLVM","title":"Working with LLVM","text":"These files can be processed the same way as the unoptimized sysimg IR shown above.","category":"page"},{"location":"devdocs/llvm/#Improving-LLVM-optimizations-for-Julia","page":"Working with LLVM","title":"Improving LLVM optimizations for Julia","text":"","category":"section"},{"location":"devdocs/llvm/","page":"Working with LLVM","title":"Working with LLVM","text":"Improving LLVM code generation usually involves either changing Julia lowering to be more friendly to LLVM's passes, or improving a pass.","category":"page"},{"location":"devdocs/llvm/","page":"Working with LLVM","title":"Working with LLVM","text":"If you are planning to improve a pass, be sure to read the LLVM developer policy. The best strategy is to create a code example in a form where you can use LLVM's opt tool to study it and the pass of interest in isolation.","category":"page"},{"location":"devdocs/llvm/","page":"Working with LLVM","title":"Working with LLVM","text":"Create an example Julia code of interest.\nUse JULIA_LLVM_ARGS=-print-after-all to dump the IR.\nPick out the IR at the point just before the pass of interest runs.\nStrip the debug metadata and fix up the TBAA metadata by hand.","category":"page"},{"location":"devdocs/llvm/","page":"Working with LLVM","title":"Working with LLVM","text":"The last step is labor intensive. Suggestions on a better way would be appreciated.","category":"page"},{"location":"devdocs/llvm/#The-jlcall-calling-convention","page":"Working with LLVM","title":"The jlcall calling convention","text":"","category":"section"},{"location":"devdocs/llvm/","page":"Working with LLVM","title":"Working with LLVM","text":"Julia has a generic calling convention for unoptimized code, which looks somewhat as follows:","category":"page"},{"location":"devdocs/llvm/","page":"Working with LLVM","title":"Working with LLVM","text":"jl_value_t *any_unoptimized_call(jl_value_t *, jl_value_t **, int);","category":"page"},{"location":"devdocs/llvm/","page":"Working with LLVM","title":"Working with LLVM","text":"where the first argument is the boxed function object, the second argument is an on-stack array of arguments and the third is the number of arguments. Now, we could perform a straightforward lowering and emit an alloca for the argument array. However, this would betray the SSA nature of the uses at the call site, making optimizations (including GC root placement), significantly harder. Instead, we emit it as follows:","category":"page"},{"location":"devdocs/llvm/","page":"Working with LLVM","title":"Working with LLVM","text":"%bitcast = bitcast @any_unoptimized_call to %jl_value_t *(*)(%jl_value_t *, %jl_value_t *)\ncall cc 37 %jl_value_t *%bitcast(%jl_value_t *%arg1, %jl_value_t *%arg2)","category":"page"},{"location":"devdocs/llvm/","page":"Working with LLVM","title":"Working with LLVM","text":"The special cc 37 annotation marks the fact that this call site is really using the jlcall calling convention. This allows us to retain the SSA-ness of the uses throughout the optimizer. GC root placement will later lower this call to the original C ABI. In the code the calling convention number is represented by the JLCALL_F_CC constant. In addition, there is the JLCALL_CC calling convention which functions similarly, but omits the first argument.","category":"page"},{"location":"devdocs/llvm/#GC-root-placement","page":"Working with LLVM","title":"GC root placement","text":"","category":"section"},{"location":"devdocs/llvm/","page":"Working with LLVM","title":"Working with LLVM","text":"GC root placement is done by an LLVM pass late in the pass pipeline. Doing GC root placement this late enables LLVM to make more aggressive optimizations around code that requires GC roots, as well as allowing us to reduce the number of required GC roots and GC root store operations (since LLVM doesn't understand our GC, it wouldn't otherwise know what it is and is not allowed to do with values stored to the GC frame, so it'll conservatively do very little). As an example, consider an error path","category":"page"},{"location":"devdocs/llvm/","page":"Working with LLVM","title":"Working with LLVM","text":"if some_condition()\n #= Use some variables maybe =#\n error(\"An error occurred\")\nend","category":"page"},{"location":"devdocs/llvm/","page":"Working with LLVM","title":"Working with LLVM","text":"During constant folding, LLVM may discover that the condition is always false, and can remove the basic block. However, if GC root lowering is done early, the GC root slots used in the deleted block, as well as any values kept alive in those slots only because they were used in the error path, would be kept alive by LLVM. By doing GC root lowering late, we give LLVM the license to do any of its usual optimizations (constant folding, dead code elimination, etc.), without having to worry (too much) about which values may or may not be GC tracked.","category":"page"},{"location":"devdocs/llvm/","page":"Working with LLVM","title":"Working with LLVM","text":"However, in order to be able to do late GC root placement, we need to be able to identify a) which pointers are GC tracked and b) all uses of such pointers. The goal of the GC placement pass is thus simple:","category":"page"},{"location":"devdocs/llvm/","page":"Working with LLVM","title":"Working with LLVM","text":"Minimize the number of needed GC roots/stores to them subject to the constraint that at every safepoint, any live GC-tracked pointer (i.e. for which there is a path after this point that contains a use of this pointer) is in some GC slot.","category":"page"},{"location":"devdocs/llvm/#Representation","page":"Working with LLVM","title":"Representation","text":"","category":"section"},{"location":"devdocs/llvm/","page":"Working with LLVM","title":"Working with LLVM","text":"The primary difficulty is thus choosing an IR representation that allows us to identify GC-tracked pointers and their uses, even after the program has been run through the optimizer. Our design makes use of three LLVM features to achieve this:","category":"page"},{"location":"devdocs/llvm/","page":"Working with LLVM","title":"Working with LLVM","text":"Custom address spaces\nOperand Bundles\nNon-integral pointers","category":"page"},{"location":"devdocs/llvm/","page":"Working with LLVM","title":"Working with LLVM","text":"Custom address spaces allow us to tag every point with an integer that needs to be preserved through optimizations. The compiler may not insert casts between address spaces that did not exist in the original program and it must never change the address space of a pointer on a load/store/etc operation. This allows us to annotate which pointers are GC-tracked in an optimizer-resistant way. Note that metadata would not be able to achieve the same purpose. Metadata is supposed to always be discardable without altering the semantics of the program. However, failing to identify a GC-tracked pointer alters the resulting program behavior dramatically - it'll probably crash or return wrong results. We currently use three different address spaces (their numbers are defined in src/codegen_shared.cpp):","category":"page"},{"location":"devdocs/llvm/","page":"Working with LLVM","title":"Working with LLVM","text":"GC Tracked Pointers (currently 10): These are pointers to boxed values that may be put into a GC frame. It is loosely equivalent to a jl_value_t* pointer on the C side. N.B. It is illegal to ever have a pointer in this address space that may not be stored to a GC slot.\nDerived Pointers (currently 11): These are pointers that are derived from some GC tracked pointer. Uses of these pointers generate uses of the original pointer. However, they need not themselves be known to the GC. The GC root placement pass MUST always find the GC tracked pointer from which this pointer is derived and use that as the pointer to root.\nCallee Rooted Pointers (currently 12): This is a utility address space to express the notion of a callee rooted value. All values of this address space MUST be storable to a GC root (though it is possible to relax this condition in the future), but unlike the other pointers need not be rooted if passed to a call (they do still need to be rooted if they are live across another safepoint between the definition and the call).\nPointers loaded from tracked object (currently 13): This is used by arrays, which themselves contain a pointer to the managed data. This data area is owned by the array, but is not a GC-tracked object by itself. The compiler guarantees that as long as this pointer is live, the object that this pointer was loaded from will keep being live.","category":"page"},{"location":"devdocs/llvm/#Invariants","page":"Working with LLVM","title":"Invariants","text":"","category":"section"},{"location":"devdocs/llvm/","page":"Working with LLVM","title":"Working with LLVM","text":"The GC root placement pass makes use of several invariants, which need to be observed by the frontend and are preserved by the optimizer.","category":"page"},{"location":"devdocs/llvm/","page":"Working with LLVM","title":"Working with LLVM","text":"First, only the following address space casts are allowed:","category":"page"},{"location":"devdocs/llvm/","page":"Working with LLVM","title":"Working with LLVM","text":"0->{Tracked,Derived,CalleeRooted}: It is allowable to decay an untracked pointer to any of the others. However, do note that the optimizer has broad license to not root such a value. It is never safe to have a value in address space 0 in any part of the program if it is (or is derived from) a value that requires a GC root.\nTracked->Derived: This is the standard decay route for interior values. The placement pass will look for these to identify the base pointer for any use.\nTracked->CalleeRooted: Addrspace CalleeRooted serves merely as a hint that a GC root is not required. However, do note that the Derived->CalleeRooted decay is prohibited, since pointers should generally be storable to a GC slot, even in this address space.","category":"page"},{"location":"devdocs/llvm/","page":"Working with LLVM","title":"Working with LLVM","text":"Now let us consider what constitutes a use:","category":"page"},{"location":"devdocs/llvm/","page":"Working with LLVM","title":"Working with LLVM","text":"Loads whose loaded values is in one of the address spaces\nStores of a value in one of the address spaces to a location\nStores to a pointer in one of the address spaces\nCalls for which a value in one of the address spaces is an operand\nCalls in jlcall ABI, for which the argument array contains a value\nReturn instructions.","category":"page"},{"location":"devdocs/llvm/","page":"Working with LLVM","title":"Working with LLVM","text":"We explicitly allow load/stores and simple calls in address spaces Tracked/Derived. Elements of jlcall argument arrays must always be in address space Tracked (it is required by the ABI that they are valid jl_value_t* pointers). The same is true for return instructions (though note that struct return arguments are allowed to have any of the address spaces). The only allowable use of an address space CalleeRooted pointer is to pass it to a call (which must have an appropriately typed operand).","category":"page"},{"location":"devdocs/llvm/","page":"Working with LLVM","title":"Working with LLVM","text":"Further, we disallow getelementptr in addrspace Tracked. This is because unless the operation is a noop, the resulting pointer will not be validly storable to a GC slot and may thus not be in this address space. If such a pointer is required, it should be decayed to addrspace Derived first.","category":"page"},{"location":"devdocs/llvm/","page":"Working with LLVM","title":"Working with LLVM","text":"Lastly, we disallow inttoptr/ptrtoint instructions in these address spaces. Having these instructions would mean that some i64 values are really GC tracked. This is problematic, because it breaks that stated requirement that we're able to identify GC-relevant pointers. This invariant is accomplished using the LLVM \"non-integral pointers\" feature, which is new in LLVM 5.0. It prohibits the optimizer from making optimizations that would introduce these operations. Note we can still insert static constants at JIT time by using inttoptr in address space 0 and then decaying to the appropriate address space afterwards.","category":"page"},{"location":"devdocs/llvm/#Supporting-[ccall](@ref)","page":"Working with LLVM","title":"Supporting ccall","text":"","category":"section"},{"location":"devdocs/llvm/","page":"Working with LLVM","title":"Working with LLVM","text":"One important aspect missing from the discussion so far is the handling of ccall. ccall has the peculiar feature that the location and scope of a use do not coincide. As an example consider:","category":"page"},{"location":"devdocs/llvm/","page":"Working with LLVM","title":"Working with LLVM","text":"A = randn(1024)\nccall(:foo, Cvoid, (Ptr{Float64},), A)","category":"page"},{"location":"devdocs/llvm/","page":"Working with LLVM","title":"Working with LLVM","text":"In lowering, the compiler will insert a conversion from the array to the pointer which drops the reference to the array value. However, we of course need to make sure that the array does stay alive while we're doing the ccall. To understand how this is done, first recall the lowering of the above code:","category":"page"},{"location":"devdocs/llvm/","page":"Working with LLVM","title":"Working with LLVM","text":"return $(Expr(:foreigncall, :(:foo), Cvoid, svec(Ptr{Float64}), 0, :(:ccall), Expr(:foreigncall, :(:jl_array_ptr), Ptr{Float64}, svec(Any), 0, :(:ccall), :(A)), :(A)))","category":"page"},{"location":"devdocs/llvm/","page":"Working with LLVM","title":"Working with LLVM","text":"The last :(A), is an extra argument list inserted during lowering that informs the code generator which Julia level values need to be kept alive for the duration of this ccall. We then take this information and represent it in an \"operand bundle\" at the IR level. An operand bundle is essentially a fake use that is attached to the call site. At the IR level, this looks like so:","category":"page"},{"location":"devdocs/llvm/","page":"Working with LLVM","title":"Working with LLVM","text":"call void inttoptr (i64 ... to void (double*)*)(double* %5) [ \"jl_roots\"(%jl_value_t addrspace(10)* %A) ]","category":"page"},{"location":"devdocs/llvm/","page":"Working with LLVM","title":"Working with LLVM","text":"The GC root placement pass will treat the jl_roots operand bundle as if it were a regular operand. However, as a final step, after the GC roots are inserted, it will drop the operand bundle to avoid confusing instruction selection.","category":"page"},{"location":"devdocs/llvm/#Supporting-[pointer_from_objref](@ref)","page":"Working with LLVM","title":"Supporting pointer_from_objref","text":"","category":"section"},{"location":"devdocs/llvm/","page":"Working with LLVM","title":"Working with LLVM","text":"pointer_from_objref is special because it requires the user to take explicit control of GC rooting. By our above invariants, this function is illegal, because it performs an address space cast from 10 to 0. However, it can be useful, in certain situations, so we provide a special intrinsic:","category":"page"},{"location":"devdocs/llvm/","page":"Working with LLVM","title":"Working with LLVM","text":"declared %jl_value_t *julia.pointer_from_objref(%jl_value_t addrspace(10)*)","category":"page"},{"location":"devdocs/llvm/","page":"Working with LLVM","title":"Working with LLVM","text":"which is lowered to the corresponding address space cast after GC root lowering. Do note however that by using this intrinsic, the caller assumes all responsibility for making sure that the value in question is rooted. Further this intrinsic is not considered a use, so the GC root placement pass will not provide a GC root for the function. As a result, the external rooting must be arranged while the value is still tracked by the system. I.e. it is not valid to attempt to use the result of this operation to establish a global root - the optimizer may have already dropped the value.","category":"page"},{"location":"devdocs/llvm/#Keeping-values-alive-in-the-absence-of-uses","page":"Working with LLVM","title":"Keeping values alive in the absence of uses","text":"","category":"section"},{"location":"devdocs/llvm/","page":"Working with LLVM","title":"Working with LLVM","text":"In certain cases it is necessary to keep an object alive, even though there is no compiler-visible use of said object. This may be case for low level code that operates on the memory-representation of an object directly or code that needs to interface with C code. In order to allow this, we provide the following intrinsics at the LLVM level:","category":"page"},{"location":"devdocs/llvm/","page":"Working with LLVM","title":"Working with LLVM","text":"token @llvm.julia.gc_preserve_begin(...)\nvoid @llvm.julia.gc_preserve_end(token)","category":"page"},{"location":"devdocs/llvm/","page":"Working with LLVM","title":"Working with LLVM","text":"(The llvm. in the name is required in order to be able to use the token type). The semantics of these intrinsics are as follows: At any safepoint that is dominated by a gc_preserve_begin call, but that is not not dominated by a corresponding gc_preserve_end call (i.e. a call whose argument is the token returned by a gc_preserve_begin call), the values passed as arguments to that gc_preserve_begin will be kept live. Note that the gc_preserve_begin still counts as a regular use of those values, so the standard lifetime semantics will ensure that the values will be kept alive before entering the preserve region.","category":"page"},{"location":"manual/variables-and-scoping/#scope-of-variables","page":"变量作用域","title":"变量作用域","text":"","category":"section"},{"location":"manual/variables-and-scoping/","page":"变量作用域","title":"变量作用域","text":"变量的 作用域 是代码的一个区域,在这个区域中这个变量是可见的。给变量划分作用域有助于解决变量命名冲突。这个概念是符合直觉的:两个函数可能同时都有叫做 x 的参量,而这两个 x 并不指向同一个东西。 相似地,也有很多其他的情况,代码的不同块会使用同样名字,但并不指向同一个东西。相同的变量名是否指向同一个东西的规则被称为作用域规则;这一节会详细地把这个规则讲清楚。","category":"page"},{"location":"manual/variables-and-scoping/","page":"变量作用域","title":"变量作用域","text":"语言中的某些结构会引入作用域块,这是可以成为一些变量集合的作用域的代码区域。一个变量的作用域不是源代码行的任意集合;相反,它始终与这些块之一关系密切。在 Julia 中主要有两种作用域,全局作用域 与 局部作用域,后者可以嵌套。 在 Julia 中还存在引入“硬作用域”的构造和只引入“软作用域”的构造之间的区别,这影响到是否允许以相同的名称遮蔽全局变量。","category":"page"},{"location":"manual/variables-and-scoping/#man-scope-table","page":"变量作用域","title":"作用域结构","text":"","category":"section"},{"location":"manual/variables-and-scoping/","page":"变量作用域","title":"变量作用域","text":"引入作用域块的结构有:","category":"page"},{"location":"manual/variables-and-scoping/","page":"变量作用域","title":"变量作用域","text":"结构 作用域类型 允许使用在\nmodule, baremodule 全局 全局\nstruct 局部(软) 全局\nfor, while, try 局部(软) global, local\nmacro 局部(硬) 全局\n函数, do 语句块, let语句块, 数组推导, 生成器 局部(硬) global, local","category":"page"},{"location":"manual/variables-and-scoping/","page":"变量作用域","title":"变量作用域","text":"值得注意的是,这个表内没有的是 begin 块和 if 块,这两个块不会引进新的作用域块。这两种作用域遵循的规则有点不一样,会在下面解释。","category":"page"},{"location":"manual/variables-and-scoping/","page":"变量作用域","title":"变量作用域","text":"Julia 使用词法作用域,也就是说一个函数的作用域不继承自调用了函数的调用者作用域,而继承自该函数定义处作用域。举例如下,foo 中的 x 指向模块 Bar 的全局作用域中 x。","category":"page"},{"location":"manual/variables-and-scoping/","page":"变量作用域","title":"变量作用域","text":"julia> module Bar\n x = 1\n foo() = x\n end;","category":"page"},{"location":"manual/variables-and-scoping/","page":"变量作用域","title":"变量作用域","text":"而非调用了 foo 的作用域中的 x:","category":"page"},{"location":"manual/variables-and-scoping/","page":"变量作用域","title":"变量作用域","text":"julia> import .Bar\n\njulia> x = -1;\n\njulia> Bar.foo()\n1","category":"page"},{"location":"manual/variables-and-scoping/","page":"变量作用域","title":"变量作用域","text":"因此词法作用域意味着,某段代码内某变量的指向只从它出现之处就可以推断出来,而不依赖于程序的执行方式。在嵌套的作用域结构里,内层作用域能”看“到所有外层作用域内变量。相对地,外层作用域不能看到内层作用域的变量。","category":"page"},{"location":"manual/variables-and-scoping/#全局作用域","page":"变量作用域","title":"全局作用域","text":"","category":"section"},{"location":"manual/variables-and-scoping/","page":"变量作用域","title":"变量作用域","text":"每个模块会引进一个新全局作用域,与其他所有模块的全局作用域分开;无所不包的全局作用域不存在。模块可以把其他模块的变量引入到它的作用域中,通过using 或者 import语句或者通过点符号这种有资格的通路,也就是说每个模块都是所谓的命名空间或者关联着含值的名字的第一类数据结构。值得注意的是,即便变量绑定能在外部被读取,变量绑定也只能在它们的全局作用域中改变。 作为一个逃生窗口,你总是可以执行该模块内代码来修改一个变量;这特别保证了不调用 eval 的外部代码绝不会修改模块绑定。","category":"page"},{"location":"manual/variables-and-scoping/","page":"变量作用域","title":"变量作用域","text":"julia> module A\n a = 1 # a global in A's scope\n end;\n\njulia> module B\n module C\n c = 2\n end\n b = C.c # can access the namespace of a nested global scope\n # through a qualified access\n import ..A # makes module A available\n d = A.a\n end;\n\njulia> module D\n b = a # errors as D's global scope is separate from A's\n end;\nERROR: UndefVarError: a not defined\n\njulia> module E\n import ..A # make module A available\n A.a = 2 # throws below error\n end;\nERROR: cannot assign variables in other modules","category":"page"},{"location":"manual/variables-and-scoping/","page":"变量作用域","title":"变量作用域","text":"注意交互式提示行(即REPL)是在模块Main的全局作用域中。","category":"page"},{"location":"manual/variables-and-scoping/#局部作用域","page":"变量作用域","title":"局部作用域","text":"","category":"section"},{"location":"manual/variables-and-scoping/","page":"变量作用域","title":"变量作用域","text":"大多数代码块都引入了新的局部作用域(完整列表请参见上表)。如果这样的代码块在语法上嵌套在另一个局部作用域内,则它创建的作用域嵌套在它出现的所有局部作用域内,这些局部作用域最终都嵌套在评估代码的模块的全局作用域内。 外部作用域中的变量在它们包含的任何作用域中都是可见的——这意味着它们可以在内部作用域中读取和写入——除非有一个同名的局部变量“遮蔽”了同名的外部变量。 即使外部的本地变量是在内部块之后(在下面的文本意义上)声明的,也是如此。 当我们说一个变量在给定范围内“存在”时,这意味着具有该名称的变量存在于当前范围嵌套在其中的任何范围内,包括当前范围。","category":"page"},{"location":"manual/variables-and-scoping/","page":"变量作用域","title":"变量作用域","text":"一些编程语言需要在使用新变量之前显式声明它们。显式声明也适用于 Julia:在任何局部作用域中,编写 local x 都会在该作用域中声明一个新的局部变量,无论外部作用域中是否已经存在名为 x 的变量。像这样声明每个新变量有点冗长乏味,但是,与许多其他语言一样,Julia 考虑对不存在的变量名称进行赋值以隐式声明该变量。如果当前作用域是全局的,则新变量是全局的;如果当前作用域是局部的,则新变量对最内部的局部作用域是局部的,并且在该作用域内可见,但在该作用域外不可见。如果你给现有的局部变量赋值,它总是更新现有的局部变量:你只能通过使用 local 关键字在嵌套范围内显式声明新的局部变量来隐藏原局部变量。特别是,这适用于在内部函数中分配的变量,这可能会让来自 Python 的用户感到惊讶,其中内部函数中的赋值会创建一个新的局部变量,除非该变量被明确声明为非局部变量。","category":"page"},{"location":"manual/variables-and-scoping/","page":"变量作用域","title":"变量作用域","text":"大多数情况下,这是非常直观的,但与许多直觉行为一样,细节比人们天真地想象的要微妙得多。","category":"page"},{"location":"manual/variables-and-scoping/","page":"变量作用域","title":"变量作用域","text":"当 x = 出现在某局部作用域,Julia 根据赋值表达式出现位置、 x 在此处已经引用的内容,采取如下规则确定表达式的意义:","category":"page"},{"location":"manual/variables-and-scoping/","page":"变量作用域","title":"变量作用域","text":"现存的局部变量:如果 x 已经是一个局部变量,那现存的局部变量 x 将被 赋值;\n**硬作用域:如果 x 还不是局部变量并且赋值发生的作用域结构是硬作用域(即在 let 语句块、函数体、宏、推导式或生成器中),则会在赋值作用域中创建一个名为 x 的新局部变量;\n软作用域:如果 x 并非已经是局部变量,并且所有包含 此次赋值的作用域结构是软作用域(循环、try/catch 块、或者 struct 块), 最后行为取决于全局变量 x 是否被定义:\n如果全局变量 x 是未定义,最终此次赋值会在该作用域创建一个名为 x 的新局部变量 ;\n如果全局变量 x 是已定义,此次赋值会被认为是有歧义的:\n在非交互的上下文(文件、eval)中,会打印一个有歧义警告,同时创建一个新 局部变量;\n在交互的上下文(REPL, notebooks)中,会向全局变量 x 赋值。","category":"page"},{"location":"manual/variables-and-scoping/","page":"变量作用域","title":"变量作用域","text":"你或许注意到,当某隐性局部变量(比如未经 local x 声明)遮掩某全局变量,非交互的上下文中硬作用域和软作用域有相同行为,除了会输出警告。方便起见,交互的上下文遵从一套更复杂的启发式规则。下面的例子将会深入讲解。","category":"page"},{"location":"manual/variables-and-scoping/","page":"变量作用域","title":"变量作用域","text":"既然你知道这个规则,那就看看一些例子。每个例子都是一个新的REPL会话中进行的,因此每个片段中唯一的全局变量就是在该代码块中分配的全局变量。","category":"page"},{"location":"manual/variables-and-scoping/","page":"变量作用域","title":"变量作用域","text":"我们将从一个良好且明确的情况开始——在一个硬作用域内赋值,在这个情况下是一个函数体,当同名的局部变量不存在时:","category":"page"},{"location":"manual/variables-and-scoping/","page":"变量作用域","title":"变量作用域","text":"julia> function greet()\n x = \"hello\" # new local\n println(x)\n end\ngreet (generic function with 1 method)\n\njulia> greet()\nhello\n\njulia> x # global\nERROR: UndefVarError: x not defined","category":"page"},{"location":"manual/variables-and-scoping/","page":"变量作用域","title":"变量作用域","text":"在 greet 函数内部,赋值 x = \"hello\" 导致 x 成为函数作用域中的一个新局部变量。 有两个相关的事实:赋值发生在局部作用域内,并且没有现有的局部 x 变量。 由于 x 是局部的,所以是否存在名为 x 的全局变量并不重要。 例如,我们在定义和调用 greet 之前定义了 x = 123:","category":"page"},{"location":"manual/variables-and-scoping/","page":"变量作用域","title":"变量作用域","text":"julia> x = 123 # global\n123\n\njulia> function greet()\n x = \"hello\" # new local\n println(x)\n end\ngreet (generic function with 1 method)\n\njulia> greet()\nhello\n\njulia> x # global\n123","category":"page"},{"location":"manual/variables-and-scoping/","page":"变量作用域","title":"变量作用域","text":"由于 greet 中的 x 是局部的,全局 x 的值(或缺少值)不会受到调用 greet 的影响。 硬作用域规则不关心名为 x 的全局变量是否存在:在硬作用域中对 x 的赋值是局部的(除非 x 被声明为全局的)。","category":"page"},{"location":"manual/variables-and-scoping/","page":"变量作用域","title":"变量作用域","text":"我们将考虑的下一个明确的情况是已经有一个名为x的局部变量,在这种情况下,x = 1总是赋值给这个现有的局部x。 无论赋值发生在同一局部作用域、同一函数体的内部局部作用域,还是嵌套在另一个函数内部的函数体(也称为 闭包)。","category":"page"},{"location":"manual/variables-and-scoping/","page":"变量作用域","title":"变量作用域","text":"我们将使用 sum_to 函数,它计算从 1 到 n 的整数之和,例如:","category":"page"},{"location":"manual/variables-and-scoping/","page":"变量作用域","title":"变量作用域","text":"function sum_to(n)\n s = 0 # new local\n for i = 1:n\n s = s + i # assign existing local\n end\n return s # same local\nend","category":"page"},{"location":"manual/variables-and-scoping/","page":"变量作用域","title":"变量作用域","text":"与前面的示例一样,在 sum_to 函数先对 s 的第一次赋值导致 s 成为函数体中的一个新局部变量。 for 循环在函数作用域内有自己的内部局部作用域。 在 s = s + i 出现的地方,s 已经是一个局部变量,所以赋值更新了现有的 s 而不是创建一个新的局部变量。 我们可以通过在 REPL 中调用 sum_to 来测试:","category":"page"},{"location":"manual/variables-and-scoping/","page":"变量作用域","title":"变量作用域","text":"julia> function sum_to(n)\n s = 0 # new local\n for i = 1:n\n s = s + i # assign existing local\n end\n return s # same local\n end\nsum_to (generic function with 1 method)\n\njulia> sum_to(10)\n55\n\njulia> s # global\nERROR: UndefVarError: s not defined","category":"page"},{"location":"manual/variables-and-scoping/","page":"变量作用域","title":"变量作用域","text":"由于 s 是函数 sum_to 的局部变量,调用该函数对全局变量 s 没有影响。 我们还可以看到,for 循环中的更新 s = s + i 必须更新由初始化 s = 0 创建的相同 s,因为我们得到了整数 1 到 10 的正确总和 55。","category":"page"},{"location":"manual/variables-and-scoping/","page":"变量作用域","title":"变量作用域","text":"让我们通过编写一个稍微详细一点的变体来深入了解一下 for 循环体有自己的作用域,我们将其称为 sum_to_def,其中,在更新 s 之前,我们将和 s + i 保存在一个变量中t :","category":"page"},{"location":"manual/variables-and-scoping/","page":"变量作用域","title":"变量作用域","text":"julia> function sum_to_def(n)\n s = 0 # new local\n for i = 1:n\n t = s + i # new local `t`\n s = t # assign existing local `s`\n end\n return s, @isdefined(t)\n end\nsum_to_def (generic function with 1 method)\n\njulia> sum_to_def(10)\n(55, false)","category":"page"},{"location":"manual/variables-and-scoping/","page":"变量作用域","title":"变量作用域","text":"这个版本像先前一样返回 s,但它也使用 @isdefined 宏返回一个布尔值,指示是否在函数的最外层局部作用域中定义了一个名为 t 的局部变量。 正如你所看到的,在 for 循环体之外没有定义 t。 这又是因为硬作用域规则:由于对 t 的赋值发生在一个函数内部,这引入了一个硬作用域,赋值导致 t 在它出现的局部作用域中成为一个新的局部变量,即循环体内部。 即使有一个名为 t 的全局变量,它也没有任何区别——硬作用域规则不受全局作用域中的任何内容的影响。","category":"page"},{"location":"manual/variables-and-scoping/","page":"变量作用域","title":"变量作用域","text":"请注意,for 循环体的局部作用域与内部函数的局部作用域没有区别。 这意味着我们可以重写此示例,以便将循环体实现为对内部辅助函数的调用,并且其行为方式相同:","category":"page"},{"location":"manual/variables-and-scoping/","page":"变量作用域","title":"变量作用域","text":"julia> function sum_to_def_closure(n)\n function loop_body(i)\n t = s + i # new local `t`\n s = t # assign same local `s` as below\n end\n s = 0 # new local\n for i = 1:n\n loop_body(i)\n end\n return s, @isdefined(t)\n end\nsum_to_def_closure (generic function with 1 method)\n\njulia> sum_to_def_closure(10)\n(55, false)","category":"page"},{"location":"manual/variables-and-scoping/","page":"变量作用域","title":"变量作用域","text":"这个例子说明了几个要点:","category":"page"},{"location":"manual/variables-and-scoping/","page":"变量作用域","title":"变量作用域","text":"内部函数作用域就像任何其他嵌套的局部作用域一样。 特别是,如果一个变量已经是内部函数之外的局部变量,并且你在内部函数中为其赋值,则外部局部变量会被更新。\n外部的局部变量的定义是否发生在更新位置的下方并不重要,规则保持不变。在解析内部的局部变量含义之前,解析整个封闭局部作用域并确定其局部变量。","category":"page"},{"location":"manual/variables-and-scoping/","page":"变量作用域","title":"变量作用域","text":"这种设计意味着你通常可以将代码移入或移出内部函数而不改变其含义,这给使用闭包语言中的许多常见习语提供了便利。(参见 do blocks)。","category":"page"},{"location":"manual/variables-and-scoping/","page":"变量作用域","title":"变量作用域","text":"让我们继续讨论软作用域规则涵盖的一些更模糊的情况。 我们将通过将 greet 和 sum_to_def函数的主体提取到软作用域上下文中来探索这一点。 首先,让我们将 greet 的主体放在一个 for 循环中——它是软的,而不是硬的——并在 REPL 中运行:","category":"page"},{"location":"manual/variables-and-scoping/","page":"变量作用域","title":"变量作用域","text":"julia> for i = 1:3\n x = \"hello\" # new local\n println(x)\n end\nhello\nhello\nhello\n\njulia> x\nERROR: UndefVarError: x not defined","category":"page"},{"location":"manual/variables-and-scoping/","page":"变量作用域","title":"变量作用域","text":"由于在执行for循环时未定义全局变量x,因此软作用域规则的第一个子句适用,并且x被创建为for循环内的局部变量,因此循环执行完后全局变量x一直没有定义 。 接下来,让我们考虑提取到全局作用域内的 sum_to_def 的函数体,将其参数固定为 n = 10","category":"page"},{"location":"manual/variables-and-scoping/","page":"变量作用域","title":"变量作用域","text":"s = 0\nfor i = 1:10\n t = s + i\n s = t\nend\ns\n@isdefined(t)","category":"page"},{"location":"manual/variables-and-scoping/","page":"变量作用域","title":"变量作用域","text":"这段代码有什么作用? 提示:这是一个小把戏。 答案是“视情况而定”。 如果此代码以交互方式输入,则其行为方式与在函数体中的行为方式相同。 但是如果代码出现在文件中,它会打印一个歧义警告并抛出一个未定义的变量错误。 让我们先看看它在 REPL 中的情况:","category":"page"},{"location":"manual/variables-and-scoping/","page":"变量作用域","title":"变量作用域","text":"julia> s = 0 # global\n0\n\njulia> for i = 1:10\n t = s + i # new local `t`\n s = t # assign global `s`\n end\n\njulia> s # global\n55\n\njulia> @isdefined(t) # global\nfalse","category":"page"},{"location":"manual/variables-and-scoping/","page":"变量作用域","title":"变量作用域","text":"REPL 内行为接近于函数体内,决定循环内部的赋值是分配给一个全局变量还是创建新的局部变量,取决于是否定义了具有该名称的全局变量。 如果存在同名的全局变量,则赋值会更新它。 如果不存在全局变量,则赋值会创建一个新的局部变量。 在这个例子中,我们看到两种情况都在起作用:","category":"page"},{"location":"manual/variables-and-scoping/","page":"变量作用域","title":"变量作用域","text":"没有名为 t 的全局变量,因此 t = s + i 创建了一个新的 t,它是 for 循环的局部变量;\n有一个名为 s 的全局变量,因此将 s = t 赋值给它。","category":"page"},{"location":"manual/variables-and-scoping/","page":"变量作用域","title":"变量作用域","text":"第二个情况解释了为什么循环的执行会改变 s 的全局值,第一个情况解释了为什么在循环执行后 t 仍未定义。 现在,让我们尝试运行相同的代码,就像它在文件中一样:","category":"page"},{"location":"manual/variables-and-scoping/","page":"变量作用域","title":"变量作用域","text":"julia> code = \"\"\"\n s = 0 # global\n for i = 1:10\n t = s + i # new local `t`\n s = t # new local `s` with warning\n end\n s, # global\n @isdefined(t) # global\n \"\"\";\n\njulia> include_string(Main, code)\n┌ Warning: Assignment to `s` in soft scope is ambiguous because a global variable by the same name exists: `s` will be treated as a new local. Disambiguate by using `local s` to suppress this warning or `global s` to assign to the existing global variable.\n└ @ string:4\nERROR: LoadError: UndefVarError: s not defined","category":"page"},{"location":"manual/variables-and-scoping/","page":"变量作用域","title":"变量作用域","text":"这里我们使用 include_string 来评估 code,就好像它是文件的内容一样。 我们也可以将 code 保存到一个文件中,然后对该文件调用 include——结果是一样的。 如你所见,这与在 REPL 中评估相同代码的行为完全不同。 让我们分解一下这里发生的事情:","category":"page"},{"location":"manual/variables-and-scoping/","page":"变量作用域","title":"变量作用域","text":"在循环运行之前,全局 s 被定义为值 0\n赋值 s = t 发生在软作用域中——任何函数体或其他硬作用域结构之外的 for 循环\n因此软作用域规则的第二个子句适用,并且分配不明确,因此发出警告\n继续执行,使 s 成为 for 循环体中的局部作用域\n由于 s 是 for 循环的局部变量,所以在计算 t = s + i 时它是未定义的,从而导致错误\n求值到此就结束了,但如果到了 s 和 @isdefined(t),它将返回 0 和 false。","category":"page"},{"location":"manual/variables-and-scoping/","page":"变量作用域","title":"变量作用域","text":"这展示了作用域的一些重要方面:在一个作用域中,每个变量只能有一个含义,而该含义的确定与表达式的顺序无关。 循环中表达式 s = t 的存在导致 s 在循环中是局部的,这意味着当它出现在 t = s + i 的右侧时它也是局部的,即使该表达式首先出现并首先计算。 有人可能会想象循环第一行上的 s 可以是全局的,而循环第二行上的 s 是局部的,但这是不可能的,因为这两行在同一个作用域块中并且每个变量 在给定的作用域内只能有一种含义。","category":"page"},{"location":"manual/variables-and-scoping/#在软作用域","page":"变量作用域","title":"在软作用域","text":"","category":"section"},{"location":"manual/variables-and-scoping/","page":"变量作用域","title":"变量作用域","text":"我们现在已经涵盖了所有局部作用域规则,但在结束本节之前,也许应该说几句关于为什么在交互式和非交互式上下文中处理模糊软作用域的情况不同。 人们可以问两个明显的问题:","category":"page"},{"location":"manual/variables-and-scoping/","page":"变量作用域","title":"变量作用域","text":"为什么不都像REPL那样?\n为什么不都表现得像在文件中那样?并跳过警告?","category":"page"},{"location":"manual/variables-and-scoping/","page":"变量作用域","title":"变量作用域","text":"在 Julia ≤ 0.6 的版本中,所有全局作用域确实像当前的 REPL 一样工作:当 x = 发生在循环中(或 try/catch ,struct内)但在函数体(或 let 语句块或推导式)之外时,它根据是否定义了一个名为 x 的全局变量来决定 x 是否应该是循环的局部变量。这种行为具有直观和方便的优点,因为它尽可能接近函数体内部的行为。特别是,当尝试调试函数时,它可以轻松地在函数体和 REPL 之间来回移动代码。 但是,它有一些缺点。首先,这是一种相当复杂的行为:多年来,许多人对这种行为感到困惑,并抱怨说它既复杂又难以解释和理解。这是有道理的。其次,可以说更糟的是,它不利于“大规模”编程。 当你在这样的地方看到一小段代码时,很清楚发生了什么:","category":"page"},{"location":"manual/variables-and-scoping/","page":"变量作用域","title":"变量作用域","text":"s = 0\nfor i = 1:10\n s += i\nend","category":"page"},{"location":"manual/variables-and-scoping/","page":"变量作用域","title":"变量作用域","text":"显然,代码的意图是修改现有的全局变量s。 这还能是什么意思? 然而,并非所有现实世界的代码都如此简短或清晰。 我们发现像下面这样的代码经常出现:","category":"page"},{"location":"manual/variables-and-scoping/","page":"变量作用域","title":"变量作用域","text":"x = 123\n\n# much later\n# maybe in a different file\n\nfor i = 1:10\n x = \"hello\"\n println(x)\nend\n\n# much later\n# maybe in yet another file\n# or maybe back in the first one where `x = 123`\n\ny = x + 234","category":"page"},{"location":"manual/variables-and-scoping/","page":"变量作用域","title":"变量作用域","text":"我们非常不清楚这里应该发生什么。 由于 x + \"hello\" 是一个方法错误,似乎意图是让 x 在 for 循环中是局部的。 但是运行时值和碰巧存在的方法不能用于确定变量的范围。 对于 Julia ≤ 0.6 的行为,尤其令人担忧的是,有人可能先编写了 for 循环,让它工作得很好,但后来当其他人在远处添加了一个新的全局时——可能是在不同的文件——代码突然改变了含义,要么中断,要么更糟糕的是,默默地做执行了错误的命令。 这种 “幽灵般的远距离动作” 是好的编程语言设计应该防止的。","category":"page"},{"location":"manual/variables-and-scoping/","page":"变量作用域","title":"变量作用域","text":"因此,在 Julia 1.0 中,我们简化了作用域的规则:在任何局部作用域中,对一个还不是局部变量的名称进行赋值会创建一个新的局部变量。 这完全消除了软作用域的概念,并消除了幽灵行为的可能性。 由于移除了软作用域,我们发现并修复了大量错误,证明我们选择摆脱它是正确的。我们有很多的欣喜! 嗯,不,不是真的。 因为有些人很生气,他们现在不得不写:","category":"page"},{"location":"manual/variables-and-scoping/","page":"变量作用域","title":"变量作用域","text":"s = 0\nfor i = 1:10\n global s += i\nend","category":"page"},{"location":"manual/variables-and-scoping/","page":"变量作用域","title":"变量作用域","text":"你看到那里的global注解了吗?非常令人讨厌。 显然,这种情况是不能容忍的。但更严重的是,这种需要global顶层代码的情况有两个主要问题:","category":"page"},{"location":"manual/variables-and-scoping/","page":"变量作用域","title":"变量作用域","text":"从函数体内部复制和粘贴代码到 REPL 来debug不再方便——你必须加上global注释,然后把它删了再复制回去。\n初学者编写这种代码往往不会加 global ,并且不知道为什么他们的代码不起作用 - 他们得到的错误是 s 未定义,这似乎并没有启发犯错的人。","category":"page"},{"location":"manual/variables-and-scoping/","page":"变量作用域","title":"变量作用域","text":"从 Julia 1.5 开始,此代码在 REPL 或 Jupyter 笔记本(就像 Julia 0.6)等交互式上下文中无需global注解即可正确执行,同时,在文件和其他非交互式上下文中,它会打印出以下非常直接的警告:","category":"page"},{"location":"manual/variables-and-scoping/","page":"变量作用域","title":"变量作用域","text":"在软作用域中对 s 的赋值是不明确的,因为存在同名的全局变量:s 将被视为新的局部变量。 通过使用 local s 来消除此警告或使用 global s 赋值给现有的全局变量来消除歧义。","category":"page"},{"location":"manual/variables-and-scoping/","page":"变量作用域","title":"变量作用域","text":"这解决了这两个问题,同时保留了 1.0 行为的“大规模编程”好处:全局变量对可能很远的代码的含义没有幽灵般的影响; 在 REPL 复制粘贴调试工作,初学者没有任何问题; 任何时候有人忘记global注解或不小心用软作用域中的局部变量遮蔽了现有的全局变量,这无论如何都会令人困惑,他们会得到一个很好的明确警告。","category":"page"},{"location":"manual/variables-and-scoping/","page":"变量作用域","title":"变量作用域","text":"这种设计的一个重要特点是,在没有警告的情况下在文件中执行的任何代码在新的 REPL 中的行为方式相同。 另一方面,如果您使用 REPL 会话并将其保存到文件中,如果它的行为与 REPL 中的行为不同,那么您将收到警告。","category":"page"},{"location":"manual/variables-and-scoping/#Let-块","page":"变量作用域","title":"Let 块","text":"","category":"section"},{"location":"manual/variables-and-scoping/","page":"变量作用域","title":"变量作用域","text":"let 语句创建一个新的 硬作用域 块(见上文)并在每次运行时引入新的变量绑定。 赋值可能会为现有值地址重新分配一个新值,而 let 总是会创建一个新地址。 这种差异通常并不重要,并且只有在通过闭包超出其作用域的变量的情况下才能检测到。 let 语法接受以逗号分隔的一系列赋值和变量名:","category":"page"},{"location":"manual/variables-and-scoping/","page":"变量作用域","title":"变量作用域","text":"julia> x, y, z = -1, -1, -1;\n\njulia> let x = 1, z\n println(\"x: $x, y: $y\") # x is local variable, y the global\n println(\"z: $z\") # errors as z has not been assigned yet but is local\n end\nx: 1, y: -1\nERROR: UndefVarError: z not defined","category":"page"},{"location":"manual/variables-and-scoping/","page":"变量作用域","title":"变量作用域","text":"赋值将按次序执行:作用域右侧先于左侧引入新变量前被执行。这使得类似 let x = x 的写法是有意义的,因为这两个 x 变量并不一样,拥有不同存储位置。let 的行为在如下例子中是必要的:","category":"page"},{"location":"manual/variables-and-scoping/","page":"变量作用域","title":"变量作用域","text":"julia> Fs = Vector{Any}(undef, 2); i = 1;\n\njulia> while i <= 2\n Fs[i] = ()->i\n global i += 1\n end\n\njulia> Fs[1]()\n3\n\njulia> Fs[2]()\n3","category":"page"},{"location":"manual/variables-and-scoping/","page":"变量作用域","title":"变量作用域","text":"在这里,我们创建并存储了两个返回变量 i 的闭包。但是因为始终是同一个变量i,所以这两个闭包行为是相同的。我们可以使用 let 为 i 创建新绑定:","category":"page"},{"location":"manual/variables-and-scoping/","page":"变量作用域","title":"变量作用域","text":"julia> Fs = Vector{Any}(undef, 2); i = 1;\n\njulia> while i <= 2\n let i = i\n Fs[i] = ()->i\n end\n global i += 1\n end\n\njulia> Fs[1]()\n1\n\njulia> Fs[2]()\n2","category":"page"},{"location":"manual/variables-and-scoping/","page":"变量作用域","title":"变量作用域","text":"由于 begin 结构不会引入新的作用域,使用零参数 let 来引入一个新的作用域块而不立即创建任何新的绑定是很有用的:","category":"page"},{"location":"manual/variables-and-scoping/","page":"变量作用域","title":"变量作用域","text":"julia> let\n local x = 1\n let\n local x = 2\n end\n x\n end\n1","category":"page"},{"location":"manual/variables-and-scoping/","page":"变量作用域","title":"变量作用域","text":"由于let 引入了一个新的作用域块,内部局部变量x 与外部局部变量x 是一个不同的变量。这个特定的例子相当于:","category":"page"},{"location":"manual/variables-and-scoping/","page":"变量作用域","title":"变量作用域","text":"julia> let x = 1\n let x = 2\n end\n x\n end\n1","category":"page"},{"location":"manual/variables-and-scoping/#循环和数组推导","page":"变量作用域","title":"循环和数组推导","text":"","category":"section"},{"location":"manual/variables-and-scoping/","page":"变量作用域","title":"变量作用域","text":"对于循环和数组推导:在其内部作用域中引入的新变量在每次循环迭代中都会被新分配一块内存,如同被 let 块包围。","category":"page"},{"location":"manual/variables-and-scoping/","page":"变量作用域","title":"变量作用域","text":"julia> Fs = Vector{Any}(undef, 2);\n\njulia> for j = 1:2\n Fs[j] = ()->j\n end\n\njulia> Fs[1]()\n1\n\njulia> Fs[2]()\n2","category":"page"},{"location":"manual/variables-and-scoping/","page":"变量作用域","title":"变量作用域","text":"for 循环或者推导式的迭代变量始终是个新变量:","category":"page"},{"location":"manual/variables-and-scoping/","page":"变量作用域","title":"变量作用域","text":"julia> function f()\n i = 0\n for i = 1:3\n # empty\n end\n return i\n end;\n\njulia> f()\n0","category":"page"},{"location":"manual/variables-and-scoping/","page":"变量作用域","title":"变量作用域","text":"但是偶然地,把一个已有的局部变量作为迭代变量也是有用的。 添加关键字 outer 就能方便地做到:","category":"page"},{"location":"manual/variables-and-scoping/","page":"变量作用域","title":"变量作用域","text":"julia> function f()\n i = 0\n for outer i = 1:3\n # empty\n end\n return i\n end;\n\njulia> f()\n3","category":"page"},{"location":"manual/variables-and-scoping/#常量","page":"变量作用域","title":"常量","text":"","category":"section"},{"location":"manual/variables-and-scoping/","page":"变量作用域","title":"变量作用域","text":"变量普遍地用于命名一个特定、不变的值。这些变量只被赋值一次。向编译器传递 const 关键字,即可声明这个意图:","category":"page"},{"location":"manual/variables-and-scoping/","page":"变量作用域","title":"变量作用域","text":"julia> const e = 2.71828182845904523536;\n\njulia> const pi = 3.14159265358979323846;","category":"page"},{"location":"manual/variables-and-scoping/","page":"变量作用域","title":"变量作用域","text":"单个 const 关键字能同时声明多个变量:","category":"page"},{"location":"manual/variables-and-scoping/","page":"变量作用域","title":"变量作用域","text":"julia> const a, b = 1, 2\n(1, 2)","category":"page"},{"location":"manual/variables-and-scoping/","page":"变量作用域","title":"变量作用域","text":"const 声明只应使用在全局作用域中的全局变量。因为全局变量的值(甚至类型)可以随时改变,编译器很难优化包含全局变量的代码。而用 const 声明一个不变的全局变量,就能处理这个问题。","category":"page"},{"location":"manual/variables-and-scoping/","page":"变量作用域","title":"变量作用域","text":"局部常量却大有不同。编译器能够自动确定一个局部变量什么时候是不变的,所以局部常量声明是不必要的,其实现在也并不支持。","category":"page"},{"location":"manual/variables-and-scoping/","page":"变量作用域","title":"变量作用域","text":"一些特殊的顶层赋值,比如用了 function 和 structure 关键字,默认就是常量。","category":"page"},{"location":"manual/variables-and-scoping/","page":"变量作用域","title":"变量作用域","text":"注意 const 只会影响变量绑定;变量可能会绑定到一个可变的对象上(比如一个数组)使得其仍然能被改变。另外当尝试给一个声明为常量的变量赋值时,可能出现下列情景:","category":"page"},{"location":"manual/variables-and-scoping/","page":"变量作用域","title":"变量作用域","text":"如果新赋值的类型与原常量类型不一样,会扔出一个错误:","category":"page"},{"location":"manual/variables-and-scoping/","page":"变量作用域","title":"变量作用域","text":"julia> const x = 1.0\n1.0\n\njulia> x = 1\nERROR: invalid redefinition of constant x","category":"page"},{"location":"manual/variables-and-scoping/","page":"变量作用域","title":"变量作用域","text":"如果新赋值的类型与原常量一样,会打印一个警告:","category":"page"},{"location":"manual/variables-and-scoping/","page":"变量作用域","title":"变量作用域","text":"julia> const y = 1.0\n1.0\n\njulia> y = 2.0\nWARNING: redefinition of constant y. This may fail, cause incorrect answers, or produce other errors.\n2.0","category":"page"},{"location":"manual/variables-and-scoping/","page":"变量作用域","title":"变量作用域","text":"如果赋值不导致原变量值变化,则不会给出任何信息:","category":"page"},{"location":"manual/variables-and-scoping/","page":"变量作用域","title":"变量作用域","text":"julia> const z = 100\n100\n\njulia> z = 100\n100","category":"page"},{"location":"manual/variables-and-scoping/","page":"变量作用域","title":"变量作用域","text":"最后一条规则也适用于不可变对象,即使变量绑定的地址改变了,例如:","category":"page"},{"location":"manual/variables-and-scoping/","page":"变量作用域","title":"变量作用域","text":"julia> const s1 = \"1\"\n\"1\"\n\njulia> s2 = \"1\"\n\"1\"\n\njulia> pointer.([s1, s2], 1)\n2-element Array{Ptr{UInt8},1}:\n Ptr{UInt8} @0x00000000132c9638\n Ptr{UInt8} @0x0000000013dd3d18\n\njulia> s1 = s2\n\"1\"\n\njulia> pointer.([s1, s2], 1)\n2-element Array{Ptr{UInt8},1}:\n Ptr{UInt8} @0x0000000013dd3d18\n Ptr{UInt8} @0x0000000013dd3d18","category":"page"},{"location":"manual/variables-and-scoping/","page":"变量作用域","title":"变量作用域","text":"然而对于可变对象,警告会如预期出现:","category":"page"},{"location":"manual/variables-and-scoping/","page":"变量作用域","title":"变量作用域","text":"julia> const a = [1]\n1-element Vector{Int64}:\n 1\n\njulia> a = [1]\nWARNING: redefinition of constant a. This may fail, cause incorrect answers, or produce other errors.\n1-element Vector{Int64}:\n 1","category":"page"},{"location":"manual/variables-and-scoping/","page":"变量作用域","title":"变量作用域","text":"注意,虽然有时是可能更改常量的值,但是十分不推荐这样做。这样做仅仅是为了便于交互式使用。更改常量可引发多种问题或者非预期行为。举个例子,如果一个方法引用了一个常量并且在常量被更改前已经被编译了,那么该函数很有可能继续使用旧值:","category":"page"},{"location":"manual/variables-and-scoping/","page":"变量作用域","title":"变量作用域","text":"julia> const x = 1\n1\n\njulia> f() = x\nf (generic function with 1 method)\n\njulia> f()\n1\n\njulia> x = 2\nWARNING: redefinition of constant x. This may fail, cause incorrect answers, or produce other errors.\n2\n\njulia> f()\n1","category":"page"},{"location":"base/simd-types/#SIMD-支持","page":"SIMD 支持","title":"SIMD 支持","text":"","category":"section"},{"location":"base/simd-types/","page":"SIMD 支持","title":"SIMD 支持","text":"VecElement{T} 类型是为了构建 SIMD 运算符的库。实际使用中要求使用 llvmcall。类型按下文定义:","category":"page"},{"location":"base/simd-types/","page":"SIMD 支持","title":"SIMD 支持","text":"struct VecElement{T}\n value::T\nend","category":"page"},{"location":"base/simd-types/","page":"SIMD 支持","title":"SIMD 支持","text":"It has a special compilation rule: a homogeneous tuple of VecElement{T} maps to an LLVM vector type when T is a primitive bits type.","category":"page"},{"location":"base/simd-types/","page":"SIMD 支持","title":"SIMD 支持","text":"使用 -O3 参数时,编译器 可能 自动为这样的元组向量化运算符。 例如接下来的程序,使用 julia -O3 编译,在x86系统中会生成两个 SIMD 附加指令(addps):","category":"page"},{"location":"base/simd-types/","page":"SIMD 支持","title":"SIMD 支持","text":"const m128 = NTuple{4,VecElement{Float32}}\n\nfunction add(a::m128, b::m128)\n (VecElement(a[1].value+b[1].value),\n VecElement(a[2].value+b[2].value),\n VecElement(a[3].value+b[3].value),\n VecElement(a[4].value+b[4].value))\nend\n\ntriple(c::m128) = add(add(c,c),c)\n\ncode_native(triple,(m128,))","category":"page"},{"location":"base/simd-types/","page":"SIMD 支持","title":"SIMD 支持","text":"然而,因为无法依靠自动向量化,以后将主要通过使用基于 llvmcall 的库来提供 SIMD 支持。","category":"page"},{"location":"stdlib/Artifacts/#Artifacts","page":"Artifacts","title":"Artifacts","text":"","category":"section"},{"location":"stdlib/Artifacts/","page":"Artifacts","title":"Artifacts","text":"DocTestSetup = :(using Artifacts)","category":"page"},{"location":"stdlib/Artifacts/","page":"Artifacts","title":"Artifacts","text":"Starting with Julia 1.6, the artifacts support has moved from Pkg.jl to Julia itself. Until proper documentation can be added here, you can learn more about artifacts in the Pkg.jl manual at https://julialang.github.io/Pkg.jl/v1/artifacts/.","category":"page"},{"location":"stdlib/Artifacts/","page":"Artifacts","title":"Artifacts","text":"compat: Julia 1.6\nJulia's artifacts API requires at least Julia 1.6. In Julia versions 1.3 to 1.5, you can use Pkg.Artifacts instead.","category":"page"},{"location":"stdlib/Artifacts/","page":"Artifacts","title":"Artifacts","text":"Artifacts.artifact_meta\nArtifacts.artifact_hash\nArtifacts.find_artifacts_toml\nArtifacts.@artifact_str","category":"page"},{"location":"stdlib/Artifacts/#Artifacts.artifact_meta","page":"Artifacts","title":"Artifacts.artifact_meta","text":"artifact_meta(name::String, artifacts_toml::String;\n platform::AbstractPlatform = HostPlatform(),\n pkg_uuid::Union{Base.UUID,Nothing}=nothing)\n\nGet metadata about a given artifact (identified by name) stored within the given (Julia)Artifacts.toml file. If the artifact is platform-specific, use platform to choose the most appropriate mapping. If none is found, return nothing.\n\ncompat: Julia 1.3\nThis function requires at least Julia 1.3.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/Artifacts/#Artifacts.artifact_hash","page":"Artifacts","title":"Artifacts.artifact_hash","text":"artifact_hash(name::String, artifacts_toml::String;\n platform::AbstractPlatform = HostPlatform())\n\nThin wrapper around artifact_meta() to return the hash of the specified, platform- collapsed artifact. Returns nothing if no mapping can be found.\n\ncompat: Julia 1.3\nThis function requires at least Julia 1.3.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/Artifacts/#Artifacts.find_artifacts_toml","page":"Artifacts","title":"Artifacts.find_artifacts_toml","text":"find_artifacts_toml(path::String)\n\nGiven the path to a .jl file, (such as the one returned by __source__.file in a macro context), find the (Julia)Artifacts.toml that is contained within the containing project (if it exists), otherwise return nothing.\n\ncompat: Julia 1.3\nThis function requires at least Julia 1.3.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/Artifacts/#Artifacts.@artifact_str","page":"Artifacts","title":"Artifacts.@artifact_str","text":"macro artifact_str(name)\n\nReturn the on-disk path to an artifact. Automatically looks the artifact up by name in the project's (Julia)Artifacts.toml file. Throws an error on if the requested artifact is not present. If run in the REPL, searches for the toml file starting in the current directory, see find_artifacts_toml() for more.\n\nIf the artifact is marked \"lazy\" and the package has using LazyArtifacts defined, the artifact will be downloaded on-demand with Pkg the first time this macro tries to compute the path. The files will then be left installed locally for later.\n\nIf name contains a forward or backward slash, all elements after the first slash will be taken to be path names indexing into the artifact, allowing for an easy one-liner to access a single file/directory within an artifact. Example:\n\nffmpeg_path = @artifact\"FFMPEG/bin/ffmpeg\"\n\ncompat: Julia 1.3\nThis macro requires at least Julia 1.3.\n\ncompat: Julia 1.6\nSlash-indexing requires at least Julia 1.6.\n\n\n\n\n\n","category":"macro"},{"location":"devdocs/inference/#类型推导","page":"类型推导","title":"类型推导","text":"","category":"section"},{"location":"devdocs/inference/#类型推导是如何工作的","page":"类型推导","title":"类型推导是如何工作的","text":"","category":"section"},{"location":"devdocs/inference/","page":"类型推导","title":"类型推导","text":"Type inference refers to the process of deducing the types of later values from the types of input values. Julia's approach to inference has been described in blog posts (1, 2).","category":"page"},{"location":"devdocs/inference/#调试-compiler.jl","page":"类型推导","title":"调试 compiler.jl","text":"","category":"section"},{"location":"devdocs/inference/","page":"类型推导","title":"类型推导","text":"You can start a Julia session, edit compiler/*.jl (for example to insert print statements), and then replace Core.Compiler in your running session by navigating to base and executing include(\"compiler/compiler.jl\"). This trick typically leads to much faster development than if you rebuild Julia for each change.","category":"page"},{"location":"devdocs/inference/","page":"类型推导","title":"类型推导","text":"Alternatively, you can use the Revise.jl package to track the compiler changes by using the command Revise.track(Core.Compiler) at the beginning of your Julia session. As explained in the Revise documentation, the modifications to the compiler will be reflected when the modified files are saved.","category":"page"},{"location":"devdocs/inference/","page":"类型推导","title":"类型推导","text":"A convenient entry point into inference is typeinf_code. Here's a demo running inference on convert(Int, UInt(1)):","category":"page"},{"location":"devdocs/inference/","page":"类型推导","title":"类型推导","text":"# Get the method\natypes = Tuple{Type{Int}, UInt} # argument types\nmths = methods(convert, atypes) # worth checking that there is only one\nm = first(mths)\n\n# Create variables needed to call `typeinf_code`\ninterp = Core.Compiler.NativeInterpreter()\nsparams = Core.svec() # this particular method doesn't have type-parameters\noptimize = true # run all inference optimizations\ntypes = Tuple{typeof(convert), atypes.parameters...} # Tuple{typeof(convert), Type{Int}, UInt}\nCore.Compiler.typeinf_code(interp, m, types, sparams, optimize)","category":"page"},{"location":"devdocs/inference/","page":"类型推导","title":"类型推导","text":"If your debugging adventures require a MethodInstance, you can look it up by calling Core.Compiler.specialize_method using many of the variables above. A CodeInfo object may be obtained with","category":"page"},{"location":"devdocs/inference/","page":"类型推导","title":"类型推导","text":"# Returns the CodeInfo object for `convert(Int, ::UInt)`:\nci = (@code_typed convert(Int, UInt(1)))[1]","category":"page"},{"location":"devdocs/inference/#The-inlining-algorithm-(inline_worthy)","page":"类型推导","title":"The inlining algorithm (inline_worthy)","text":"","category":"section"},{"location":"devdocs/inference/","page":"类型推导","title":"类型推导","text":"Much of the hardest work for inlining runs in inlining_pass. However, if your question is \"why didn't my function inline?\" then you will most likely be interested in isinlineable and its primary callee, inline_worthy. isinlineable handles a number of special cases (e.g., critical functions like next and done, incorporating a bonus for functions that return tuples, etc.). The main decision-making happens in inline_worthy, which returns true if the function should be inlined.","category":"page"},{"location":"devdocs/inference/","page":"类型推导","title":"类型推导","text":"inline_worthy implements a cost-model, where \"cheap\" functions get inlined; more specifically, we inline functions if their anticipated run-time is not large compared to the time it would take to issue a call to them if they were not inlined. The cost-model is extremely simple and ignores many important details: for example, all for loops are analyzed as if they will be executed once, and the cost of an if...else...end includes the summed cost of all branches. It's also worth acknowledging that we currently lack a suite of functions suitable for testing how well the cost model predicts the actual run-time cost, although BaseBenchmarks provides a great deal of indirect information about the successes and failures of any modification to the inlining algorithm.","category":"page"},{"location":"devdocs/inference/","page":"类型推导","title":"类型推导","text":"The foundation of the cost-model is a lookup table, implemented in add_tfunc and its callers, that assigns an estimated cost (measured in CPU cycles) to each of Julia's intrinsic functions. These costs are based on standard ranges for common architectures (see Agner Fog's analysis for more detail).","category":"page"},{"location":"devdocs/inference/","page":"类型推导","title":"类型推导","text":"We supplement this low-level lookup table with a number of special cases. For example, an :invoke expression (a call for which all input and output types were inferred in advance) is assigned a fixed cost (currently 20 cycles). In contrast, a :call expression, for functions other than intrinsics/builtins, indicates that the call will require dynamic dispatch, in which case we assign a cost set by Params.inline_nonleaf_penalty (currently set at 1000). Note that this is not a \"first-principles\" estimate of the raw cost of dynamic dispatch, but a mere heuristic indicating that dynamic dispatch is extremely expensive.","category":"page"},{"location":"devdocs/inference/","page":"类型推导","title":"类型推导","text":"Each statement gets analyzed for its total cost in a function called statement_cost. You can display the cost associated with each statement as follows:","category":"page"},{"location":"devdocs/inference/","page":"类型推导","title":"类型推导","text":"julia> Base.print_statement_costs(stdout, map, (typeof(sqrt), Tuple{Int},)) # map(sqrt, (2,))\nmap(f, t::Tuple{Any}) in Base at tuple.jl:179\n 0 1 ─ %1 = Base.getfield(_3, 1, true)::Int64\n 1 │ %2 = Base.sitofp(Float64, %1)::Float64\n 2 │ %3 = Base.lt_float(%2, 0.0)::Bool\n 0 └── goto #3 if not %3\n 0 2 ─ invoke Base.Math.throw_complex_domainerror(:sqrt::Symbol, %2::Float64)::Union{}\n 0 └── unreachable\n 20 3 ─ %7 = Base.Math.sqrt_llvm(%2)::Float64\n 0 └── goto #4\n 0 4 ─ goto #5\n 0 5 ─ %10 = Core.tuple(%7)::Tuple{Float64}\n 0 └── return %10","category":"page"},{"location":"devdocs/inference/","page":"类型推导","title":"类型推导","text":"The line costs are in the left column. This includes the consequences of inlining and other forms of optimization.","category":"page"},{"location":"manual/complex-and-rational-numbers/#复数和有理数","page":"复数和有理数","title":"复数和有理数","text":"","category":"section"},{"location":"manual/complex-and-rational-numbers/","page":"复数和有理数","title":"复数和有理数","text":"Julia 语言包含了预定义的复数和有理数类型,并且支持它们的各种标准数学运算和初等函数。由于也定义了复数与分数的类型转换与类型提升,因此对预定义数值类型(无论是原始的还是复合的)的任意组合进行的操作都会表现得如预期的一样。","category":"page"},{"location":"manual/complex-and-rational-numbers/#复数","page":"复数和有理数","title":"复数","text":"","category":"section"},{"location":"manual/complex-and-rational-numbers/","page":"复数和有理数","title":"复数和有理数","text":"全局常量 im 被绑定到复数 i,表示 -1 的主平方根。(不应使用数学家习惯的 i 或工程师习惯的 j 来表示此全局常量,因为它们是非常常用的索引变量名。)由于 Julia 允许数值字面量作为数值字面量系数,这种绑定就足以为复数提供很方便的语法,类似于传统的数学记法:","category":"page"},{"location":"manual/complex-and-rational-numbers/","page":"复数和有理数","title":"复数和有理数","text":"julia> 1+2im\n1 + 2im","category":"page"},{"location":"manual/complex-and-rational-numbers/","page":"复数和有理数","title":"复数和有理数","text":"你可以对复数进行各种标准算术操作:","category":"page"},{"location":"manual/complex-and-rational-numbers/","page":"复数和有理数","title":"复数和有理数","text":"julia> (1 + 2im)*(2 - 3im)\n8 + 1im\n\njulia> (1 + 2im)/(1 - 2im)\n-0.6 + 0.8im\n\njulia> (1 + 2im) + (1 - 2im)\n2 + 0im\n\njulia> (-3 + 2im) - (5 - 1im)\n-8 + 3im\n\njulia> (-1 + 2im)^2\n-3 - 4im\n\njulia> (-1 + 2im)^2.5\n2.729624464784009 - 6.9606644595719im\n\njulia> (-1 + 2im)^(1 + 1im)\n-0.27910381075826657 + 0.08708053414102428im\n\njulia> 3(2 - 5im)\n6 - 15im\n\njulia> 3(2 - 5im)^2\n-63 - 60im\n\njulia> 3(2 - 5im)^-1.0\n0.20689655172413796 + 0.5172413793103449im","category":"page"},{"location":"manual/complex-and-rational-numbers/","page":"复数和有理数","title":"复数和有理数","text":"类型提升机制也确保你可以使用不同类型的操作数的组合:","category":"page"},{"location":"manual/complex-and-rational-numbers/","page":"复数和有理数","title":"复数和有理数","text":"julia> 2(1 - 1im)\n2 - 2im\n\njulia> (2 + 3im) - 1\n1 + 3im\n\njulia> (1 + 2im) + 0.5\n1.5 + 2.0im\n\njulia> (2 + 3im) - 0.5im\n2.0 + 2.5im\n\njulia> 0.75(1 + 2im)\n0.75 + 1.5im\n\njulia> (2 + 3im) / 2\n1.0 + 1.5im\n\njulia> (1 - 3im) / (2 + 2im)\n-0.5 - 1.0im\n\njulia> 2im^2\n-2 + 0im\n\njulia> 1 + 3/4im\n1.0 - 0.75im","category":"page"},{"location":"manual/complex-and-rational-numbers/","page":"复数和有理数","title":"复数和有理数","text":"注意 3/4im == 3/(4*im) == -(3/4*im),因为系数比除法的优先级更高。","category":"page"},{"location":"manual/complex-and-rational-numbers/","page":"复数和有理数","title":"复数和有理数","text":"Julia 提供了一些操作复数的标准函数:","category":"page"},{"location":"manual/complex-and-rational-numbers/","page":"复数和有理数","title":"复数和有理数","text":"julia> z = 1 + 2im\n1 + 2im\n\njulia> real(1 + 2im) # z 的实部\n1\n\njulia> imag(1 + 2im) # z 的虚部\n2\n\njulia> conj(1 + 2im) # z 的复共轭\n1 - 2im\n\njulia> abs(1 + 2im) # z 的绝对值\n2.23606797749979\n\njulia> abs2(1 + 2im) # 取平方后的绝对值\n5\n\njulia> angle(1 + 2im) # 以弧度为单位的相位角\n1.1071487177940904","category":"page"},{"location":"manual/complex-and-rational-numbers/","page":"复数和有理数","title":"复数和有理数","text":"按照惯例,复数的绝对值(abs)是从零点到它的距离。abs2 给出绝对值的平方,作用于复数上时非常有用,因为它避免了取平方根。angle 返回以弧度为单位的相位角(也被称为辐角函数)。所有其它的初等函数在复数上也都有完整的定义:","category":"page"},{"location":"manual/complex-and-rational-numbers/","page":"复数和有理数","title":"复数和有理数","text":"julia> sqrt(1im)\n0.7071067811865476 + 0.7071067811865475im\n\njulia> sqrt(1 + 2im)\n1.272019649514069 + 0.7861513777574233im\n\njulia> cos(1 + 2im)\n2.0327230070196656 - 3.0518977991517997im\n\njulia> exp(1 + 2im)\n-1.1312043837568135 + 2.4717266720048188im\n\njulia> sinh(1 + 2im)\n-0.4890562590412937 + 1.4031192506220405im","category":"page"},{"location":"manual/complex-and-rational-numbers/","page":"复数和有理数","title":"复数和有理数","text":"注意数学函数通常应用于实数就返回实数值,应用于复数就返回复数值。例如,当 sqrt 应用于 -1 与 -1 + 0im 会有不同的表现,虽然 -1 == -1 + 0im:","category":"page"},{"location":"manual/complex-and-rational-numbers/","page":"复数和有理数","title":"复数和有理数","text":"julia> sqrt(-1)\nERROR: DomainError with -1.0:\nsqrt will only return a complex result if called with a complex argument. Try sqrt(Complex(x)).\nStacktrace:\n[...]\n\njulia> sqrt(-1 + 0im)\n0.0 + 1.0im","category":"page"},{"location":"manual/complex-and-rational-numbers/","page":"复数和有理数","title":"复数和有理数","text":"从变量构建复数时,文本型数值系数记法不再适用。相反地,乘法必须显式地写出:","category":"page"},{"location":"manual/complex-and-rational-numbers/","page":"复数和有理数","title":"复数和有理数","text":"julia> a = 1; b = 2; a + b*im\n1 + 2im","category":"page"},{"location":"manual/complex-and-rational-numbers/","page":"复数和有理数","title":"复数和有理数","text":"然而,我们并不推荐这样做,而应改为使用更高效的 complex 函数直接通过实部与虚部构建一个复数值:","category":"page"},{"location":"manual/complex-and-rational-numbers/","page":"复数和有理数","title":"复数和有理数","text":"julia> a = 1; b = 2; complex(a, b)\n1 + 2im","category":"page"},{"location":"manual/complex-and-rational-numbers/","page":"复数和有理数","title":"复数和有理数","text":"这种构建避免了乘法和加法操作。","category":"page"},{"location":"manual/complex-and-rational-numbers/","page":"复数和有理数","title":"复数和有理数","text":"Inf 和 NaN 可能出现在复数的实部和虚部,正如特殊的浮点值章节所描述的:","category":"page"},{"location":"manual/complex-and-rational-numbers/","page":"复数和有理数","title":"复数和有理数","text":"julia> 1 + Inf*im\n1.0 + Inf*im\n\njulia> 1 + NaN*im\n1.0 + NaN*im","category":"page"},{"location":"manual/complex-and-rational-numbers/#有理数","page":"复数和有理数","title":"有理数","text":"","category":"section"},{"location":"manual/complex-and-rational-numbers/","page":"复数和有理数","title":"复数和有理数","text":"Julia 有一个用于表示整数精确比值的分数类型。分数通过 // 运算符构建:","category":"page"},{"location":"manual/complex-and-rational-numbers/","page":"复数和有理数","title":"复数和有理数","text":"julia> 2//3\n2//3","category":"page"},{"location":"manual/complex-and-rational-numbers/","page":"复数和有理数","title":"复数和有理数","text":"如果一个分数的分子和分母含有公因子,它们会被约分到最简形式且分母非负:","category":"page"},{"location":"manual/complex-and-rational-numbers/","page":"复数和有理数","title":"复数和有理数","text":"julia> 6//9\n2//3\n\njulia> -4//8\n-1//2\n\njulia> 5//-15\n-1//3\n\njulia> -4//-12\n1//3","category":"page"},{"location":"manual/complex-and-rational-numbers/","page":"复数和有理数","title":"复数和有理数","text":"整数比值的这种标准化形式是唯一的,所以分数值的相等性可由校验分子与分母都相等来测试。分数值的标准化分子和分母可以使用 numerator 和 denominator 函数得到:","category":"page"},{"location":"manual/complex-and-rational-numbers/","page":"复数和有理数","title":"复数和有理数","text":"julia> numerator(2//3)\n2\n\njulia> denominator(2//3)\n3","category":"page"},{"location":"manual/complex-and-rational-numbers/","page":"复数和有理数","title":"复数和有理数","text":"分子和分母的直接比较通常是不必要的,因为标准算术和比较操作对分数值也有定义:","category":"page"},{"location":"manual/complex-and-rational-numbers/","page":"复数和有理数","title":"复数和有理数","text":"julia> 2//3 == 6//9\ntrue\n\njulia> 2//3 == 9//27\nfalse\n\njulia> 3//7 < 1//2\ntrue\n\njulia> 3//4 > 2//3\ntrue\n\njulia> 2//4 + 1//6\n2//3\n\njulia> 5//12 - 1//4\n1//6\n\njulia> 5//8 * 3//12\n5//32\n\njulia> 6//5 / 10//7\n21//25","category":"page"},{"location":"manual/complex-and-rational-numbers/","page":"复数和有理数","title":"复数和有理数","text":"分数可以很容易地转换成浮点数:","category":"page"},{"location":"manual/complex-and-rational-numbers/","page":"复数和有理数","title":"复数和有理数","text":"julia> float(3//4)\n0.75","category":"page"},{"location":"manual/complex-and-rational-numbers/","page":"复数和有理数","title":"复数和有理数","text":"对任意整数值 a 和 b(除了 a == 0 且 b == 0 时),从分数到浮点数的转换遵从以下的一致性:","category":"page"},{"location":"manual/complex-and-rational-numbers/","page":"复数和有理数","title":"复数和有理数","text":"julia> a = 1; b = 2;\n\njulia> isequal(float(a//b), a/b)\ntrue","category":"page"},{"location":"manual/complex-and-rational-numbers/","page":"复数和有理数","title":"复数和有理数","text":"Julia接受构建无穷分数值:","category":"page"},{"location":"manual/complex-and-rational-numbers/","page":"复数和有理数","title":"复数和有理数","text":"julia> 5//0\n1//0\n\njulia> x = -3//0\n-1//0\n\njulia> typeof(x)\nRational{Int64}","category":"page"},{"location":"manual/complex-and-rational-numbers/","page":"复数和有理数","title":"复数和有理数","text":"但不接受试图构建一个 NaN 分数值:","category":"page"},{"location":"manual/complex-and-rational-numbers/","page":"复数和有理数","title":"复数和有理数","text":"julia> 0//0\nERROR: ArgumentError: invalid rational: zero(Int64)//zero(Int64)\nStacktrace:\n[...]","category":"page"},{"location":"manual/complex-and-rational-numbers/","page":"复数和有理数","title":"复数和有理数","text":"像往常一样,类型提升系统使得分数可以轻松地同其它数值类型进行交互:","category":"page"},{"location":"manual/complex-and-rational-numbers/","page":"复数和有理数","title":"复数和有理数","text":"julia> 3//5 + 1\n8//5\n\njulia> 3//5 - 0.5\n0.09999999999999998\n\njulia> 2//7 * (1 + 2im)\n2//7 + 4//7*im\n\njulia> 2//7 * (1.5 + 2im)\n0.42857142857142855 + 0.5714285714285714im\n\njulia> 3//2 / (1 + 2im)\n3//10 - 3//5*im\n\njulia> 1//2 + 2im\n1//2 + 2//1*im\n\njulia> 1 + 2//3im\n1//1 - 2//3*im\n\njulia> 0.5 == 1//2\ntrue\n\njulia> 0.33 == 1//3\nfalse\n\njulia> 0.33 < 1//3\ntrue\n\njulia> 1//3 - 0.33\n0.0033333333333332993","category":"page"},{"location":"devdocs/types/#More-about-types","page":"More about types","title":"More about types","text":"","category":"section"},{"location":"devdocs/types/","page":"More about types","title":"More about types","text":"使用Julia一段时间之后,你就会体会到类型在其中的基础性作用。本部分我们将深入到类型体系的内部,并着重关注 Parametric Types。","category":"page"},{"location":"devdocs/types/#Types-and-sets-(and-Any-and-Union{}/Bottom)","page":"More about types","title":"Types and sets (and Any and Union{}/Bottom)","text":"","category":"section"},{"location":"devdocs/types/","page":"More about types","title":"More about types","text":"Julia的类型系统很容易会被看作是一种集合(set)。程序处理个体值,类型处理值的集合。但是集合与类型是两个不同的概念。一组值组成的集合 Set 本身也是一个值的集合。而类型描述的是一个组可能值组成的集合,即类型的值是不确定的。 ","category":"page"},{"location":"devdocs/types/","page":"More about types","title":"More about types","text":"函数 typeof 可以返回具体类型 T 包含的值的直接标签 T。而抽象类型描述的集合则可能会更大。","category":"page"},{"location":"devdocs/types/","page":"More about types","title":"More about types","text":"类型 Any 包含所有可能值。类型 Integer 是 Any 的一个子类型,而 Integer的子类型有包括 Int,Int8 等其他具体类型。在内部表征上,Julia 类型系统还非常依赖类型 Bottom,也记做Union{}。这对应于集合中的空集。","category":"page"},{"location":"devdocs/types/","page":"More about types","title":"More about types","text":"Julia类型系统支持集合理论的标准操作:你可以用 T1 <: T2 来判断类型 T1 是否是T2 的子集(子类型)。 typeintersect 和 typejoin 可用来计算两个类型的交集和合集;用 Union 用于集合所有列出的类型。","category":"page"},{"location":"devdocs/types/","page":"More about types","title":"More about types","text":"julia> typeintersect(Int, Float64)\nUnion{}\n\njulia> Union{Int, Float64}\nUnion{Float64, Int64}\n\njulia> typejoin(Int, Float64)\nReal\n\njulia> typeintersect(Signed, Union{UInt8, Int8})\nInt8\n\njulia> Union{Signed, Union{UInt8, Int8}}\nUnion{UInt8, Signed}\n\njulia> typejoin(Signed, Union{UInt8, Int8})\nInteger\n\njulia> typeintersect(Tuple{Integer, Float64}, Tuple{Int, Real})\nTuple{Int64, Float64}\n\njulia> Union{Tuple{Integer, Float64}, Tuple{Int, Real}}\nUnion{Tuple{Int64, Real}, Tuple{Integer, Float64}}\n\njulia> typejoin(Tuple{Integer, Float64}, Tuple{Int, Real})\nTuple{Integer, Real}","category":"page"},{"location":"devdocs/types/","page":"More about types","title":"More about types","text":"这些操作看起来很抽象,但是他们处于 Julia 语言的核心位置。例如,方法的派发过程就是对方法列表中的项目进行逐步搜索,直到找到一个其类型是方法标签子类型的参数元组为止。该算法有效的前提是方法必须按照特异性(specificity)进行排序,搜索过程必须从最具特异性的开始。所以,Julia 也需要对类型进行偏序排序(partial order),该函数与 <: 类似但又不完全相同。","category":"page"},{"location":"devdocs/types/#UnionAll类型","page":"More about types","title":"UnionAll类型","text":"","category":"section"},{"location":"devdocs/types/","page":"More about types","title":"More about types","text":"Julia 的类型系统也可以表征类型的迭代合集(iterated union),即某个变量的所有值的集合。当参数化类型的某些参数值是未知数时,迭代合集是非常有用的。","category":"page"},{"location":"devdocs/types/","page":"More about types","title":"More about types","text":"例如,下面这个数组 Array{Int,2} 有两个参数。如果其成分类型未知,该数组可以写成 Array{T,2} where T。该数组是取所有不同 T 值后的所有数组Array{T,2} 的合集:Union{Array{Int8,2}, Array{Int16,2}, ...}。","category":"page"},{"location":"devdocs/types/","page":"More about types","title":"More about types","text":"类型的迭代集合由类型为UnionAll的对象表征。UnionAll对象有一个类型为 TypeVar 的变量,此处为T,和一个包裹化的类型,此处为 Array{T,2}。","category":"page"},{"location":"devdocs/types/","page":"More about types","title":"More about types","text":"考虑下面的例子:","category":"page"},{"location":"devdocs/types/","page":"More about types","title":"More about types","text":"f1(A::Array) = 1\nf2(A::Array{Int}) = 2\nf3(A::Array{T}) where {T<:Any} = 3\nf4(A::Array{Any}) = 4","category":"page"},{"location":"devdocs/types/","page":"More about types","title":"More about types","text":"如 Function calls 中描述的,函数 f3 的签名是元组类型的 UnionAll 类型包裹:Tuple{typeof(f3), Array{T}} where T。此处除 f4 外所有函数都可以被a = [1,2]调用;除 f2 外所有函数都可以被 b = Any[1,2] 调用。","category":"page"},{"location":"devdocs/types/","page":"More about types","title":"More about types","text":"dump() 函数可用于进一步查看这些类型:","category":"page"},{"location":"devdocs/types/","page":"More about types","title":"More about types","text":"julia> dump(Array)\nUnionAll\n var: TypeVar\n name: Symbol T\n lb: Union{}\n ub: Any\n body: UnionAll\n var: TypeVar\n name: Symbol N\n lb: Union{}\n ub: Any\n body: Array{T, N} <: DenseArray{T, N}","category":"page"},{"location":"devdocs/types/","page":"More about types","title":"More about types","text":"这说明数组 Array 实际上命名了一个 UnionAll 类型。嵌套其中的参数也都是 UnionAll 类型。句法 Array{Int,2} 等价于Array{Int}{2}。UnionAll 在内部会被实例化为变量的特定值,每次一个,从最外侧开始。这使得省略尾端参数是自然而有意义的:类型 Array{Int} 与类型 Array{Int, N} where N。 ","category":"page"},{"location":"devdocs/types/","page":"More about types","title":"More about types","text":"TypeVar 本身不是类型,而是 UnionAll 类型的一个内部结构成分。类型变量的值会有上界和下界,分别由字段lb 和 ub 表示。符号 name 是纯装饰性的(cosmetic)。在内部 TypeVar 是通过地址比较的。所以为了区分“不同”变量类型,TypeVar 是一个可更改类型,但通常不应修改它们。","category":"page"},{"location":"devdocs/types/","page":"More about types","title":"More about types","text":"你也可以手动创建 TypeVar:","category":"page"},{"location":"devdocs/types/","page":"More about types","title":"More about types","text":"julia> TypeVar(:V, Signed, Real)\nSigned<:V<:Real","category":"page"},{"location":"devdocs/types/","page":"More about types","title":"More about types","text":"你可以用更简便的方式省掉除 name 之外的任意参数。","category":"page"},{"location":"devdocs/types/","page":"More about types","title":"More about types","text":"句法 Array{T} where T<:Integer 会被降级为如下格式。","category":"page"},{"location":"devdocs/types/","page":"More about types","title":"More about types","text":"let T = TypeVar(:T,Integer)\n UnionAll(T, Array{T})\nend","category":"page"},{"location":"devdocs/types/","page":"More about types","title":"More about types","text":"所以极少需要手动建构 TypeVar(实际上这也应该是尽量避免的)。","category":"page"},{"location":"devdocs/types/#自由变量","page":"More about types","title":"自由变量","text":"","category":"section"},{"location":"devdocs/types/","page":"More about types","title":"More about types","text":"自由类型变量在类型系统中是至关重要的。如果类型 T 不包含一个引入变量 V 的 UnionAll 类型,那么类型 T 中的变量 V 就是自由的 (free)。例如,类型 Array{Array{V} where V<:Integer} 没有自由变量,但该类型的子成分 Array{V} 则包含了一个自由变量 V。","category":"page"},{"location":"devdocs/types/","page":"More about types","title":"More about types","text":"从某种程度上讲,一个包含自由变量的类型根本就不是一个类型。例如,类型 Array{Array{T}} where T 是一个成分为数组的数组,且所有子数组元素的类型都相同。其内部类型 Array{T} 乍一看似乎包含所有数组类型。但外部数组的成分必须有相同类型,所以 Array{T} 不能指向所有数组。我们可以说 Array{T} 出现了很多次,但每次 T 值都必须相同。","category":"page"},{"location":"devdocs/types/","page":"More about types","title":"More about types","text":"故此, C 应用程序接口函数 jl_has_free_typevars 是非常重要的。若该函数的返回值为真,则说明类型中存在自由变量。此时子类型判断和其他类型函数中的返回结果没有太多意义。","category":"page"},{"location":"devdocs/types/#类型名称TypeNames","page":"More about types","title":"类型名称TypeNames","text":"","category":"section"},{"location":"devdocs/types/","page":"More about types","title":"More about types","text":"下面两个数组 Array 类型在功能上是相同的,但有不同的打印方式:","category":"page"},{"location":"devdocs/types/","page":"More about types","title":"More about types","text":"julia> TV, NV = TypeVar(:T), TypeVar(:N)\n(T, N)\n\njulia> Array\nArray\n\njulia> Array{TV, NV}\nArray{T, N}","category":"page"},{"location":"devdocs/types/","page":"More about types","title":"More about types","text":"二者之间的差别可以通过类型的名称 name 字段来区分。名称 name 字段是一个类型为 TypeName 的对象。 ","category":"page"},{"location":"devdocs/types/","page":"More about types","title":"More about types","text":"julia> dump(Array{Int,1}.name)\nTypeName\n name: Symbol Array\n module: Module Core\n names: empty SimpleVector\n wrapper: UnionAll\n var: TypeVar\n name: Symbol T\n lb: Union{}\n ub: Any\n body: UnionAll\n var: TypeVar\n name: Symbol N\n lb: Union{}\n ub: Any\n body: Array{T, N} <: DenseArray{T, N}\n cache: SimpleVector\n ...\n\n linearcache: SimpleVector\n ...\n\n hash: Int64 -7900426068641098781\n mt: MethodTable\n name: Symbol Array\n defs: Nothing nothing\n cache: Nothing nothing\n max_args: Int64 0\n kwsorter: #undef\n module: Module Core\n : Int64 0\n : Int64 0","category":"page"},{"location":"devdocs/types/","page":"More about types","title":"More about types","text":"与此相关的字段是包装器 wrapper,该字段存储了一个指向顶层类型(tip-level)的引用,用以产生新的数组 Array 类型。","category":"page"},{"location":"devdocs/types/","page":"More about types","title":"More about types","text":"julia> pointer_from_objref(Array)\nPtr{Cvoid} @0x00007fcc7de64850\n\njulia> pointer_from_objref(Array.body.body.name.wrapper)\nPtr{Cvoid} @0x00007fcc7de64850\n\njulia> pointer_from_objref(Array{TV,NV})\nPtr{Cvoid} @0x00007fcc80c4d930\n\njulia> pointer_from_objref(Array{TV,NV}.name.wrapper)\nPtr{Cvoid} @0x00007fcc7de64850","category":"page"},{"location":"devdocs/types/","page":"More about types","title":"More about types","text":"数组 Array 的包装器 wrapper 字段指向它自己,而在数组 Array{TV,NV} 中,该字段则指回该类型的原始定义。","category":"page"},{"location":"devdocs/types/","page":"More about types","title":"More about types","text":"那其他字段都是什么作用呢?字段hash 会给每个类型指派一个整数。要查看 cache 字段的内容,最好选不像数组那么常用的类型。我们可以自己创造一个类型:","category":"page"},{"location":"devdocs/types/","page":"More about types","title":"More about types","text":"julia> struct MyType{T,N} end\n\njulia> MyType{Int,2}\nMyType{Int64, 2}\n\njulia> MyType{Float32, 5}\nMyType{Float32, 5}","category":"page"},{"location":"devdocs/types/","page":"More about types","title":"More about types","text":"当参数类型被实例化时,每个具体类型都会被存储到类型缓存中(MyType.body.body.name.cache)。不过含有自由变量的实例是不会被缓存的。","category":"page"},{"location":"devdocs/types/#元组类型","page":"More about types","title":"元组类型","text":"","category":"section"},{"location":"devdocs/types/","page":"More about types","title":"More about types","text":"元组类型是一个有趣的特例。为了使派发在诸如 x::Tuple 之类的声明中正常工作,该类型必须能包含所有元组。我们可以查看一下元组的参数:","category":"page"},{"location":"devdocs/types/","page":"More about types","title":"More about types","text":"julia> Tuple\nTuple\n\njulia> Tuple.parameters\nsvec(Vararg{Any})","category":"page"},{"location":"devdocs/types/","page":"More about types","title":"More about types","text":"与其他类型不同,元组类型的参数是共变的(covariant),所以类型 Tuple 能与任何类型的元组相匹配。","category":"page"},{"location":"devdocs/types/","page":"More about types","title":"More about types","text":"julia> typeintersect(Tuple, Tuple{Int,Float64})\nTuple{Int64, Float64}\n\njulia> typeintersect(Tuple{Vararg{Any}}, Tuple{Int,Float64})\nTuple{Int64, Float64}","category":"page"},{"location":"devdocs/types/","page":"More about types","title":"More about types","text":"但是,如果一个可变元组 (Vararg) 类型含有自由变量,那么他描述的元组类型则可能就是不同的:","category":"page"},{"location":"devdocs/types/","page":"More about types","title":"More about types","text":"julia> typeintersect(Tuple{Vararg{T} where T}, Tuple{Int,Float64})\nTuple{Int64, Float64}\n\njulia> typeintersect(Tuple{Vararg{T}} where T, Tuple{Int,Float64})\nUnion{}","category":"page"},{"location":"devdocs/types/","page":"More about types","title":"More about types","text":"当 T 绑定的 UnionAll 类型位于元组 Tuple 之外,即 T 是元组 Tuple 的自由变量时,一个唯一的 T 值必须作用与整个类型。此时异质的元组是不匹配的。","category":"page"},{"location":"devdocs/types/","page":"More about types","title":"More about types","text":"最后,意识到元组 Tuple{} 的独特性是有意义的:","category":"page"},{"location":"devdocs/types/","page":"More about types","title":"More about types","text":"julia> Tuple{}\nTuple{}\n\njulia> Tuple{}.parameters\nsvec()\n\njulia> typeintersect(Tuple{}, Tuple{Int})\nUnion{}","category":"page"},{"location":"devdocs/types/","page":"More about types","title":"More about types","text":"那么什么是元组类型的基本(primary)类型呢?","category":"page"},{"location":"devdocs/types/","page":"More about types","title":"More about types","text":"julia> pointer_from_objref(Tuple)\nPtr{Cvoid} @0x00007f5998a04370\n\njulia> pointer_from_objref(Tuple{})\nPtr{Cvoid} @0x00007f5998a570d0\n\njulia> pointer_from_objref(Tuple.name.wrapper)\nPtr{Cvoid} @0x00007f5998a04370\n\njulia> pointer_from_objref(Tuple{}.name.wrapper)\nPtr{Cvoid} @0x00007f5998a04370","category":"page"},{"location":"devdocs/types/","page":"More about types","title":"More about types","text":"所以 Tuple == Tuple{Vararg{Any}} 事实上就是其基本类型。","category":"page"},{"location":"devdocs/types/#对角变量","page":"More about types","title":"对角变量","text":"","category":"section"},{"location":"devdocs/types/","page":"More about types","title":"More about types","text":"考虑类型 Tuple{T,T} where T。使用该标签的方法看起来会是下面的样子:","category":"page"},{"location":"devdocs/types/","page":"More about types","title":"More about types","text":"f(x::T, y::T) where {T} = ...","category":"page"},{"location":"devdocs/types/","page":"More about types","title":"More about types","text":"根据对类型 UnionAll 的通常理解, T 将覆盖所有的类型,包括 T,所以此类型应该等价于 Tuple{Any,Any}。但是这种理解会面临很多实际的问题。","category":"page"},{"location":"devdocs/types/","page":"More about types","title":"More about types","text":"首先,T 值需要在方法定之内可及。对诸如 f(1, 1.0) 的调用来说,T 的值是不明确的。T 可以是 Union{Int,Float64} 或 Real。直觉上,声明 x::T 意味着 T 应该为 x 的类型,即 T === typeof(x)。为了保有这种不变性, 该方法应满足如下关系: typeof(x) === typeof(y) === T。 这说明该方法只能被拥有相同类型的参数元组调用。","category":"page"},{"location":"devdocs/types/","page":"More about types","title":"More about types","text":"能依据两个值的类型是否相同进行派发是非常有用的(例如类型提升系统就用到了该机制)。所以我们有很多理由给 Tuple{T,T} where T 一个不同的含义。为此,我们在子类型系统中增加了如下规则:\\textbf{如果一个变量在共变位置上出现了不止一次,那么其作用范围将仅局限于具体类型}。共变位置指在一个变量和引入该变量的 UnionAll 类型之间,只出现了元组 Tuple 类型和联合 Union 类型。这些变量被称为对角变量(diagonal variables)或具体变量(concrete variables)。","category":"page"},{"location":"devdocs/types/","page":"More about types","title":"More about types","text":"例如,元组 Tuple{T,T} where T 可以被看作是如下元组的集合 Union{Tuple{Int8,Int8}, Tuple{Int16,Int16}, ...}, 即 T 包括所有的具体类型。该规则会产生一些有趣的子类型结果。例如 Tuple{Real,Real} 不是 Tuple{T,T} where T 的子类型,因为前者包含了诸如 Tuple{Int8,Int16} 的子类型,该子类型的元素类型是不同的。Tuple{Real,Real} 和 Tuple{T,T} where T 又一个不容小视的交集 Tuple{T,T} where T<:Real。但是 Tuple{Real} 是 Tuple{T} where T 的子集,因为此时 T 只出现了一次,所以是不对角的。","category":"page"},{"location":"devdocs/types/","page":"More about types","title":"More about types","text":"现在考虑如下签名:","category":"page"},{"location":"devdocs/types/","page":"More about types","title":"More about types","text":"f(a::Array{T}, x::T, y::T) where {T} = ...","category":"page"},{"location":"devdocs/types/","page":"More about types","title":"More about types","text":"此例中, T 出现在了非共变位置,即 Array{T} 之内。 这意味着无论数组传递的类型是什么,该类型都会无歧义的决定 T,即 T 又一个等价性限制(equality constraint)。此时是不需要对角规则的,因为数组决定了 T,然后 x 和 y 则可以是 T 的任何子类型。所以非共变位置的变量均不受对角线规则的限制。上述定义的行为选择有一点矛盾,或许应该写成:","category":"page"},{"location":"devdocs/types/","page":"More about types","title":"More about types","text":"f(a::Array{T}, x::S, y::S) where {T, S<:T} = ...","category":"page"},{"location":"devdocs/types/","page":"More about types","title":"More about types","text":"为明确 x 和 y 应该有相同的类型。如果 x 和 y 可以有不同类型,这个版本的签名可以引入针对类型 y 的第三个变量。","category":"page"},{"location":"devdocs/types/","page":"More about types","title":"More about types","text":"下面一个难题是合集 Union{} 和对角线变量的交互作用,例如","category":"page"},{"location":"devdocs/types/","page":"More about types","title":"More about types","text":"f(x::Union{Nothing,T}, y::T) where {T} = ...","category":"page"},{"location":"devdocs/types/","page":"More about types","title":"More about types","text":"考虑一下这个生命的含义。y 的类型是 T。 而 x 的类型或者与 y 相同 T 或类型为空 Nothing。下面调用都是匹配的。","category":"page"},{"location":"devdocs/types/","page":"More about types","title":"More about types","text":"f(1, 1)\nf(\"\", \"\")\nf(2.0, 2.0)\nf(nothing, 1)\nf(nothing, \"\")\nf(nothing, 2.0)","category":"page"},{"location":"devdocs/types/","page":"More about types","title":"More about types","text":"上述例子告诉我们:当 x 的类型是空集 nothing::Nothing 时,y 的类型就没有任何限制了。此时方法标签中字段 y 可以是任何类型,即 y::Any。确实,下面两个类型是等价的:","category":"page"},{"location":"devdocs/types/","page":"More about types","title":"More about types","text":"(Tuple{Union{Nothing,T},T} where T) == Union{Tuple{Nothing,Any}, Tuple{T,T} where T}","category":"page"},{"location":"devdocs/types/","page":"More about types","title":"More about types","text":"一般的规则是:如果出现在共变位置的一个具体变量只被子类型算法(subtyping algorithm)使用一次,则该具体变量的行为就会像一个抽象变量。上例中,当 x 类型为空时 Nothing,集合 Union{Nothing,T} 中的类型 T 不起作用,即 T 只在第二个槽中被用到。此时,无论把 Tuple{T} where T 中的 T 限制为具体类型还是不限制,该类型都等价于 Tuple{Any}。","category":"page"},{"location":"devdocs/types/","page":"More about types","title":"More about types","text":"当变量出现在非共变 位置时,无论是否被使用,该变量都不再是具体变量。否则类型的行为就会因为比较对象类型的不同而不同,从而违反传递律(transitive)。例如,","category":"page"},{"location":"devdocs/types/","page":"More about types","title":"More about types","text":"Tuple{Int,Int8,Vector{Integer}} <: Tuple{T,T,Vector{Union{Integer,T}}} where T","category":"page"},{"location":"devdocs/types/","page":"More about types","title":"More about types","text":"如果忽略掉合集 Union 内部的 T,则 T 就是具体的,且上述判断结果是 “否”,因为左侧元组前两个成分的类型是不同的。这两个类型不相同。再看下例:","category":"page"},{"location":"devdocs/types/","page":"More about types","title":"More about types","text":"Tuple{Int,Int8,Vector{Any}} <: Tuple{T,T,Vector{Union{Integer,T}}} where T","category":"page"},{"location":"devdocs/types/","page":"More about types","title":"More about types","text":"此处合集 Union 内的 T 是不能被忽略的,因为 T 必须等于 Any,即 T == Any。所以 T 不能是具体的,且判断结果为“真”。所以,类型 T 的具体还是抽象是受制于其他类型特征的。这是不被接受的,因为类型的含义必须是清晰和自洽的。所以,向量 Vector 之内的 T 需要同时考虑这两种情况。","category":"page"},{"location":"devdocs/types/#对角变量的子类型","page":"More about types","title":"对角变量的子类型","text":"","category":"section"},{"location":"devdocs/types/","page":"More about types","title":"More about types","text":"对角变量的子系统算法(substyping algorithm)有两个成分:(1)确定变量出现次数;(2)确保对角变量只包含具体类型。","category":"page"},{"location":"devdocs/types/","page":"More about types","title":"More about types","text":"第一个任务由两个计数器完成。环境中的每个自由变量都有两个计数器 occurs_inv 和 occurs_cov (在文件 src/subtype.c 中),分别用于追踪不变和共变的出现次数。如果 occurs_inv == 0 && occurs_cov > 1 则这个变量就是对角的。","category":"page"},{"location":"devdocs/types/","page":"More about types","title":"More about types","text":"第二个任务通过在变量下界添加一个条件实现。子类型算法在运行过程中会逐渐压缩每个变量的界限(提高下界和降低上界),以保证子类型关系在该变量范围内能继续保持。评估完对角变量合集类型 UnionAll 后,可以查看边界的最终值。因为变量必须是具体的,所以如果其下边界不是具体类型的子类型,就会产生矛盾。例如,抽象类型 AbstractArray 不可能是一个具体类型的子类型,而具体类型 Int 则可以,空类型 Bottom 也可以。如果下边界没通过该测试,算法将终止并返回 false。","category":"page"},{"location":"devdocs/types/","page":"More about types","title":"More about types","text":"例如,如果 T 是 Union{Int,String} 的上位类型,则 Tuple{Int,String} 将是 Tuple{T,T} where T 的子集,即 Tuple{Int,String} <: Tuple{T,T} where T 的返回值将为真。但 Union{Int,String} 是一个抽象类型,所以上述关系不成立。","category":"page"},{"location":"devdocs/types/","page":"More about types","title":"More about types","text":"具体性判断是由函数 is_leaf_bound 完成的。注意该函数与函数 jl_is_leaf_type 稍微有点不同,因为其对类型 Bottom 的返回值也为真 true。该函数目前是启发式的,无法捕获所有的具体类型。该函数的困难在于,其他变量类型的界限会影响当下变量下界限的具体与否。例如,只有当 T 的上界限和下界限都是 Int 时,类型 Vector{T} 才和具体类型 Vector{Int} 相同。目前,设计者还没有想出一个完备的算法来解决该问题。","category":"page"},{"location":"devdocs/types/#内部机制","page":"More about types","title":"内部机制","text":"","category":"section"},{"location":"devdocs/types/","page":"More about types","title":"More about types","text":"大部分类型处理操作都存储在 jltypes.c 和 subtype.c 这两个文件中。了解自类型系统的最好方式是查看其工作方式。用 make debug 创建且在调试器中运行程序。手册gdb debugging tips章中有一些有用的建议。","category":"page"},{"location":"devdocs/types/","page":"More about types","title":"More about types","text":"因为 REPL 中也经常使用子类型代码 – 这些代码中的断点也经常被触发。所以定义下面函数并在 jl_breakpoint 中设定一个断点将非常方便:","category":"page"},{"location":"devdocs/types/","page":"More about types","title":"More about types","text":"julia> function mysubtype(a,b)\n ccall(:jl_breakpoint, Cvoid, (Any,), nothing)\n a <: b\n end","category":"page"},{"location":"devdocs/types/","page":"More about types","title":"More about types","text":"一旦该断点被触发,你就可以在其他函数中设定断点了。","category":"page"},{"location":"devdocs/types/","page":"More about types","title":"More about types","text":"作为热身,试一下下面代码","category":"page"},{"location":"devdocs/types/","page":"More about types","title":"More about types","text":"mysubtype(Tuple{Int, Float64}, Tuple{Integer, Real})","category":"page"},{"location":"devdocs/types/","page":"More about types","title":"More about types","text":"你也可以用一个更复杂的例子让其变得更有趣:","category":"page"},{"location":"devdocs/types/","page":"More about types","title":"More about types","text":"mysubtype(Tuple{Array{Int,2}, Int8}, Tuple{Array{T}, T} where T)","category":"page"},{"location":"devdocs/types/#子类型和方法排序","page":"More about types","title":"子类型和方法排序","text":"","category":"section"},{"location":"devdocs/types/","page":"More about types","title":"More about types","text":"函数 type_morespecific 可用来对函数的方法列表从最具特异行到最不具特异性进行部分排序(partial order)。特异性是严格的:如果 a 比 b 更特异,则 b 就不比 a 更特异。","category":"page"},{"location":"devdocs/types/","page":"More about types","title":"More about types","text":"如果 a 是 b 的严格子类型(strict subtype),那么 a 就自动的比 b 更特异。接下来,函数 type_morespecific 还引进了一些不太形式化的规则。例如,子类型 subtype 对参数的数量敏感,而函数 type_morespecific 则不敏感。特别的,Tuple{Int,AbstractFloat} 比 Tuple{Integer} 更特异,虽然前者不是后者的子类型。此外, Tuple{Int,AbstractFloat} 和 Tuple{Integer,Float64} 不存在特异性关系。类似的,Tuple{Int,Vararg{Int}} 不是 Tuple{Integer} 的子类型,但前者比后者更特异。但是,长度确实也影响特异性关系morespecific,如 Tuple{Int,Int} 比 Tuple{Int,Vararg{Int}} 更特异。","category":"page"},{"location":"devdocs/types/","page":"More about types","title":"More about types","text":"要调试方法的排序,定义下面的函数很方便:","category":"page"},{"location":"devdocs/types/","page":"More about types","title":"More about types","text":"type_morespecific(a, b) = ccall(:jl_type_morespecific, Cint, (Any,Any), a, b)","category":"page"},{"location":"devdocs/types/","page":"More about types","title":"More about types","text":"它可以被用来测试元组 a 是否比元组 b 更特异。","category":"page"},{"location":"devdocs/locks/#Proper-maintenance-and-care-of-multi-threading-locks","page":"Proper maintenance and care of multi-threading locks","title":"Proper maintenance and care of multi-threading locks","text":"","category":"section"},{"location":"devdocs/locks/","page":"Proper maintenance and care of multi-threading locks","title":"Proper maintenance and care of multi-threading locks","text":"The following strategies are used to ensure that the code is dead-lock free (generally by addressing the 4th Coffman condition: circular wait).","category":"page"},{"location":"devdocs/locks/","page":"Proper maintenance and care of multi-threading locks","title":"Proper maintenance and care of multi-threading locks","text":"structure code such that only one lock will need to be acquired at a time\nalways acquire shared locks in the same order, as given by the table below\navoid constructs that expect to need unrestricted recursion","category":"page"},{"location":"devdocs/locks/#Locks","page":"Proper maintenance and care of multi-threading locks","title":"Locks","text":"","category":"section"},{"location":"devdocs/locks/","page":"Proper maintenance and care of multi-threading locks","title":"Proper maintenance and care of multi-threading locks","text":"Below are all of the locks that exist in the system and the mechanisms for using them that avoid the potential for deadlocks (no Ostrich algorithm allowed here):","category":"page"},{"location":"devdocs/locks/","page":"Proper maintenance and care of multi-threading locks","title":"Proper maintenance and care of multi-threading locks","text":"The following are definitely leaf locks (level 1), and must not try to acquire any other lock:","category":"page"},{"location":"devdocs/locks/","page":"Proper maintenance and care of multi-threading locks","title":"Proper maintenance and care of multi-threading locks","text":"safepoint\nNote that this lock is acquired implicitly by JL_LOCK and JL_UNLOCK. use the _NOGC variants to avoid that for level 1 locks.While holding this lock, the code must not do any allocation or hit any safepoints. Note that there are safepoints when doing allocation, enabling / disabling GC, entering / restoring exception frames, and taking / releasing locks.\nshared_map\nfinalizers\npagealloc\ngcpermlock\nflisp\njlinstackwalk (Win32)\nflisp itself is already threadsafe, this lock only protects the jl_ast_context_list_t pool","category":"page"},{"location":"devdocs/locks/","page":"Proper maintenance and care of multi-threading locks","title":"Proper maintenance and care of multi-threading locks","text":"The following is a leaf lock (level 2), and only acquires level 1 locks (safepoint) internally:","category":"page"},{"location":"devdocs/locks/","page":"Proper maintenance and care of multi-threading locks","title":"Proper maintenance and care of multi-threading locks","text":"typecache\nModule->lock","category":"page"},{"location":"devdocs/locks/","page":"Proper maintenance and care of multi-threading locks","title":"Proper maintenance and care of multi-threading locks","text":"The following is a level 3 lock, which can only acquire level 1 or level 2 locks internally:","category":"page"},{"location":"devdocs/locks/","page":"Proper maintenance and care of multi-threading locks","title":"Proper maintenance and care of multi-threading locks","text":"Method->writelock","category":"page"},{"location":"devdocs/locks/","page":"Proper maintenance and care of multi-threading locks","title":"Proper maintenance and care of multi-threading locks","text":"The following is a level 4 lock, which can only recurse to acquire level 1, 2, or 3 locks:","category":"page"},{"location":"devdocs/locks/","page":"Proper maintenance and care of multi-threading locks","title":"Proper maintenance and care of multi-threading locks","text":"MethodTable->writelock","category":"page"},{"location":"devdocs/locks/","page":"Proper maintenance and care of multi-threading locks","title":"Proper maintenance and care of multi-threading locks","text":"No Julia code may be called while holding a lock above this point.","category":"page"},{"location":"devdocs/locks/","page":"Proper maintenance and care of multi-threading locks","title":"Proper maintenance and care of multi-threading locks","text":"The following are a level 6 lock, which can only recurse to acquire locks at lower levels:","category":"page"},{"location":"devdocs/locks/","page":"Proper maintenance and care of multi-threading locks","title":"Proper maintenance and care of multi-threading locks","text":"codegen\njlmodulesmutex","category":"page"},{"location":"devdocs/locks/","page":"Proper maintenance and care of multi-threading locks","title":"Proper maintenance and care of multi-threading locks","text":"The following is an almost root lock (level end-1), meaning only the root look may be held when trying to acquire it:","category":"page"},{"location":"devdocs/locks/","page":"Proper maintenance and care of multi-threading locks","title":"Proper maintenance and care of multi-threading locks","text":"typeinf\nthis one is perhaps one of the most tricky ones, since type-inference can be invoked from many pointscurrently the lock is merged with the codegen lock, since they call each other recursively","category":"page"},{"location":"devdocs/locks/","page":"Proper maintenance and care of multi-threading locks","title":"Proper maintenance and care of multi-threading locks","text":"The following lock synchronizes IO operation. Be aware that doing any I/O (for example, printing warning messages or debug information) while holding any other lock listed above may result in pernicious and hard-to-find deadlocks. BE VERY CAREFUL!","category":"page"},{"location":"devdocs/locks/","page":"Proper maintenance and care of multi-threading locks","title":"Proper maintenance and care of multi-threading locks","text":"iolock\nIndividual ThreadSynchronizers locks\nthis may continue to be held after releasing the iolock, or acquired without it, but be very careful to never attempt to acquire the iolock while holding it","category":"page"},{"location":"devdocs/locks/","page":"Proper maintenance and care of multi-threading locks","title":"Proper maintenance and care of multi-threading locks","text":"The following is the root lock, meaning no other lock shall be held when trying to acquire it:","category":"page"},{"location":"devdocs/locks/","page":"Proper maintenance and care of multi-threading locks","title":"Proper maintenance and care of multi-threading locks","text":"toplevel\nthis should be held while attempting a top-level action (such as making a new type or defining a new method): trying to obtain this lock inside a staged function will cause a deadlock condition!additionally, it's unclear if any code can safely run in parallel with an arbitrary toplevel expression, so it may require all threads to get to a safepoint first","category":"page"},{"location":"devdocs/locks/#Broken-Locks","page":"Proper maintenance and care of multi-threading locks","title":"Broken Locks","text":"","category":"section"},{"location":"devdocs/locks/","page":"Proper maintenance and care of multi-threading locks","title":"Proper maintenance and care of multi-threading locks","text":"The following locks are broken:","category":"page"},{"location":"devdocs/locks/","page":"Proper maintenance and care of multi-threading locks","title":"Proper maintenance and care of multi-threading locks","text":"toplevel\ndoesn't exist right nowfix: create it\nModule->lock\nThis is vulnerable to deadlocks since it can't be certain it is acquired in sequence. Some operations (such as import_module) are missing a lock.fix: replace with jl_modules_mutex?\nloading.jl: require and register_root_module\nThis file potentially has numerous problems.fix: needs locks","category":"page"},{"location":"devdocs/locks/#Shared-Global-Data-Structures","page":"Proper maintenance and care of multi-threading locks","title":"Shared Global Data Structures","text":"","category":"section"},{"location":"devdocs/locks/","page":"Proper maintenance and care of multi-threading locks","title":"Proper maintenance and care of multi-threading locks","text":"These data structures each need locks due to being shared mutable global state. It is the inverse list for the above lock priority list. This list does not include level 1 leaf resources due to their simplicity.","category":"page"},{"location":"devdocs/locks/","page":"Proper maintenance and care of multi-threading locks","title":"Proper maintenance and care of multi-threading locks","text":"MethodTable modifications (def, cache, kwsorter type) : MethodTable->writelock","category":"page"},{"location":"devdocs/locks/","page":"Proper maintenance and care of multi-threading locks","title":"Proper maintenance and care of multi-threading locks","text":"Type declarations : toplevel lock","category":"page"},{"location":"devdocs/locks/","page":"Proper maintenance and care of multi-threading locks","title":"Proper maintenance and care of multi-threading locks","text":"Type application : typecache lock","category":"page"},{"location":"devdocs/locks/","page":"Proper maintenance and care of multi-threading locks","title":"Proper maintenance and care of multi-threading locks","text":"Global variable tables : Module->lock","category":"page"},{"location":"devdocs/locks/","page":"Proper maintenance and care of multi-threading locks","title":"Proper maintenance and care of multi-threading locks","text":"Module serializer : toplevel lock","category":"page"},{"location":"devdocs/locks/","page":"Proper maintenance and care of multi-threading locks","title":"Proper maintenance and care of multi-threading locks","text":"JIT & type-inference : codegen lock","category":"page"},{"location":"devdocs/locks/","page":"Proper maintenance and care of multi-threading locks","title":"Proper maintenance and care of multi-threading locks","text":"MethodInstance/CodeInstance updates : Method->writelock, codegen lock","category":"page"},{"location":"devdocs/locks/","page":"Proper maintenance and care of multi-threading locks","title":"Proper maintenance and care of multi-threading locks","text":"These are set at construction and immutable:\nspecTypes\nsparam_vals\ndef","category":"page"},{"location":"devdocs/locks/","page":"Proper maintenance and care of multi-threading locks","title":"Proper maintenance and care of multi-threading locks","text":"These are set by jl_type_infer (while holding codegen lock):\ncache\nrettype\ninferred","category":"page"},{"location":"devdocs/locks/","page":"Proper maintenance and care of multi-threading locks","title":"Proper maintenance and care of multi-threading locks","text":" * valid ages","category":"page"},{"location":"devdocs/locks/","page":"Proper maintenance and care of multi-threading locks","title":"Proper maintenance and care of multi-threading locks","text":"inInference flag:\noptimization to quickly avoid recurring into jl_type_infer while it is already running\nactual state (of setting inferred, then fptr) is protected by codegen lock","category":"page"},{"location":"devdocs/locks/","page":"Proper maintenance and care of multi-threading locks","title":"Proper maintenance and care of multi-threading locks","text":"Function pointers:\nthese transition once, from NULL to a value, while the codegen lock is held\nCode-generator cache (the contents of functionObjectsDecls):\nthese can transition multiple times, but only while the codegen lock is held\nit is valid to use old version of this, or block for new versions of this, so races are benign, as long as the code is careful not to reference other data in the method instance (such as rettype) and assume it is coordinated, unless also holding the codegen lock","category":"page"},{"location":"devdocs/locks/","page":"Proper maintenance and care of multi-threading locks","title":"Proper maintenance and care of multi-threading locks","text":"LLVMContext : codegen lock","category":"page"},{"location":"devdocs/locks/","page":"Proper maintenance and care of multi-threading locks","title":"Proper maintenance and care of multi-threading locks","text":"Method : Method->writelock","category":"page"},{"location":"devdocs/locks/","page":"Proper maintenance and care of multi-threading locks","title":"Proper maintenance and care of multi-threading locks","text":"roots array (serializer and codegen)\ninvoke / specializations / tfunc modifications","category":"page"},{"location":"manual/parallel-computing/#并行计算","page":"并行计算","title":"并行计算","text":"","category":"section"},{"location":"manual/parallel-computing/","page":"并行计算","title":"并行计算","text":"Julia 支持这四类并发和并行编程:","category":"page"},{"location":"manual/parallel-computing/","page":"并行计算","title":"并行计算","text":"异步“任务”或协程:\nJulia Tasks 允许暂停和恢复 I/O、事件处理、生产者-消费者进程和类似模式的计算。 Tasks 可以通过wail 和fetch 等操作进行同步,并通过 Channel 进行通信。 虽然严格来说不是并行计算,但 Julia 允许在多个线程上调度任务。\n多线程:\nJulia 的多线程提供了在多个线程、CPU 内核或共享内存上同时调度任务的能力。这通常是在个人 PC 或单个大型多核服务器上获得并行性的最简单方法。 Julia 的多线程是可组合的。当一个多线程函数调用另一个多线程函数时,Julia 将在可用资源上全局调度所有线程,而不会超额使用。\n分布式计算:\n分布式计算运行多个具有独立内存空间的 Julia 进程。 这些可以在同一台计算机或多台计算机上。 Distributed 标准库提供了远程执行 Julia 函数的能力。 使用这个基本构建块,可以构建许多不同类型的分布式计算抽象。 像 DistributedArrays.jl 这样的包就是这种抽象的一个示例。 另一方面,像 MPI.jl 和 Elemental.jl 这样的包提供对现有 MPI 生态库的访问。\nGPU 计算:\nJulia GPU 编译器提供了在 GPU 上本地运行 Julia 代码的能力。 有一个针对 GPU 的丰富的 Julia 软件包生态系统。 JuliaGPU.org 网站提供了功能列表、支持的 GPU、相关包和文档。","category":"page"},{"location":"manual/style-guide/#代码风格指南","page":"代码风格指南","title":"代码风格指南","text":"","category":"section"},{"location":"manual/style-guide/","page":"代码风格指南","title":"代码风格指南","text":"接下来的部分将介绍如何写出具有 Julia 风格的代码。当然,这些规则并不是绝对的,它们只是一些建议,以便更好地帮助你熟悉这门语言,以及在不同的代码设计中做出选择。","category":"page"},{"location":"manual/style-guide/#缩进","page":"代码风格指南","title":"缩进","text":"","category":"section"},{"location":"manual/style-guide/","page":"代码风格指南","title":"代码风格指南","text":"每个缩进级别使用 4 个空格。","category":"page"},{"location":"manual/style-guide/#写函数,而不是仅仅写脚本","page":"代码风格指南","title":"写函数,而不是仅仅写脚本","text":"","category":"section"},{"location":"manual/style-guide/","page":"代码风格指南","title":"代码风格指南","text":"一开始解决问题的时候,直接从最外层一步步写代码的确很便捷,但你应该尽早地将代码组织成函数。函数有更强的复用性和可测试性,并且能更清楚地让人知道哪些步骤做完了,以及每一步骤的输入输出分别是什么。此外,由于 Julia 编译器特殊的工作方式,写在函数中的代码往往要比最外层的代码运行地快得多。","category":"page"},{"location":"manual/style-guide/","page":"代码风格指南","title":"代码风格指南","text":"此外值得一提的是,函数应当接受参数,而不是直接使用全局变量进行操作(pi 等常数除外)。","category":"page"},{"location":"manual/style-guide/#类型不要写得过于具体","page":"代码风格指南","title":"类型不要写得过于具体","text":"","category":"section"},{"location":"manual/style-guide/","page":"代码风格指南","title":"代码风格指南","text":"代码应该写得尽可能通用。例如,下面这段代码:","category":"page"},{"location":"manual/style-guide/","page":"代码风格指南","title":"代码风格指南","text":"Complex{Float64}(x)","category":"page"},{"location":"manual/style-guide/","page":"代码风格指南","title":"代码风格指南","text":"更好的写法是写成下面的通用函数:","category":"page"},{"location":"manual/style-guide/","page":"代码风格指南","title":"代码风格指南","text":"complex(float(x))","category":"page"},{"location":"manual/style-guide/","page":"代码风格指南","title":"代码风格指南","text":"第二个版本会把 x 转换成合适的类型,而不是某个写死的类型。","category":"page"},{"location":"manual/style-guide/","page":"代码风格指南","title":"代码风格指南","text":"这种代码风格与函数的参数尤其相关。例如,当一个参数可以是任何整型时,不要将它的类型声明为 Int 或 Int32,而要使用抽象类型(abstract type)Integer 来表示。事实上,除非确实需要将其与其它的方法定义区分开,很多情况下你可以干脆完全省略掉参数的类型,因为如果你的操作中有不支持某种参数类型的操作的话,反正都会抛出 MethodError 的。这也称作 鸭子类型)。","category":"page"},{"location":"manual/style-guide/","page":"代码风格指南","title":"代码风格指南","text":"例如,考虑这样的一个叫做 addone 的函数,其返回值为它的参数加 1 :","category":"page"},{"location":"manual/style-guide/","page":"代码风格指南","title":"代码风格指南","text":"addone(x::Int) = x + 1 # works only for Int\naddone(x::Integer) = x + oneunit(x) # any integer type\naddone(x::Number) = x + oneunit(x) # any numeric type\naddone(x) = x + oneunit(x) # any type supporting + and oneunit","category":"page"},{"location":"manual/style-guide/","page":"代码风格指南","title":"代码风格指南","text":"最后一种定义可以处理所有支持 oneunit (返回和 x 相同类型的 1,以避免不需要的类型提升(type promotion))以及 + 函数的类型。这里的关键点在于,只定义通用的 addone(x) = x + oneunit(x) 并不会带来性能上的损失,因为 Julia 会在需要的时候自动编译特定的版本。比如说,当第一次调用 addone(12) 时,Julia 会自动编译一个特定的 addone 函数,它接受一个 x::Int 的参数,并把调用的 oneunit 替换为内连的值 1。因此,上述的前三种 addone 的定义对于第四种来说是完全多余的。","category":"page"},{"location":"manual/style-guide/#让调用者处理多余的参数多样性","page":"代码风格指南","title":"让调用者处理多余的参数多样性","text":"","category":"section"},{"location":"manual/style-guide/","page":"代码风格指南","title":"代码风格指南","text":"如下的代码:","category":"page"},{"location":"manual/style-guide/","page":"代码风格指南","title":"代码风格指南","text":"function foo(x, y)\n x = Int(x); y = Int(y)\n ...\nend\nfoo(x, y)","category":"page"},{"location":"manual/style-guide/","page":"代码风格指南","title":"代码风格指南","text":"请写成这样:","category":"page"},{"location":"manual/style-guide/","page":"代码风格指南","title":"代码风格指南","text":"function foo(x::Int, y::Int)\n ...\nend\nfoo(Int(x), Int(y))","category":"page"},{"location":"manual/style-guide/","page":"代码风格指南","title":"代码风格指南","text":"这种风格更好,因为 foo 函数其实不需要接受所有类型的数,而只需要接受 Int。","category":"page"},{"location":"manual/style-guide/","page":"代码风格指南","title":"代码风格指南","text":"这里的关键在于,如果一个函数需要处理的是整数,强制让调用者来决定非整数如何被转换(比如说向下还是向上取整)会更好。同时,把类型声明得具体一些的话可以为以后的方法定义留有更多的空间。","category":"page"},{"location":"manual/style-guide/#bang-convention","page":"代码风格指南","title":"在修改其参数的函数名称后加 !","text":"","category":"section"},{"location":"manual/style-guide/","page":"代码风格指南","title":"代码风格指南","text":"如下的代码:","category":"page"},{"location":"manual/style-guide/","page":"代码风格指南","title":"代码风格指南","text":"function double(a::AbstractArray{<:Number})\n for i = firstindex(a):lastindex(a)\n a[i] *= 2\n end\n return a\nend","category":"page"},{"location":"manual/style-guide/","page":"代码风格指南","title":"代码风格指南","text":"请写成这样:","category":"page"},{"location":"manual/style-guide/","page":"代码风格指南","title":"代码风格指南","text":"function double!(a::AbstractArray{<:Number})\n for i = firstindex(a):lastindex(a)\n a[i] *= 2\n end\n return a\nend","category":"page"},{"location":"manual/style-guide/","page":"代码风格指南","title":"代码风格指南","text":"Julia 的 Base 模块中的函数都遵循了这种规范,且包含很多例子:有的函数同时有拷贝和修改的形式(比如 sort 和 sort!),还有一些只有修改(比如 push!,pop! 和 splice!)。为了方便起见,这类函数通常也会把修改后的数组作为返回值。","category":"page"},{"location":"manual/style-guide/#避免使用奇怪的-Union-类型","page":"代码风格指南","title":"避免使用奇怪的 Union 类型","text":"","category":"section"},{"location":"manual/style-guide/","page":"代码风格指南","title":"代码风格指南","text":"使用 Union{Function,AbstractString} 这样的类型的时候通常意味着设计还不够清晰。","category":"page"},{"location":"manual/style-guide/#避免复杂的容器类型","page":"代码风格指南","title":"避免复杂的容器类型","text":"","category":"section"},{"location":"manual/style-guide/","page":"代码风格指南","title":"代码风格指南","text":"像下面这样构造数组通常没有什么好处:","category":"page"},{"location":"manual/style-guide/","page":"代码风格指南","title":"代码风格指南","text":"a = Vector{Union{Int,AbstractString,Tuple,Array}}(undef, n)","category":"page"},{"location":"manual/style-guide/","page":"代码风格指南","title":"代码风格指南","text":"这种情况下,Vector{Any}(undef, n)更合适些。此外,相比将所有可能的类型都打包在一起,直接在使用时标注具体的数据类型(比如:a[i]::Int)对编译器来说更有用。","category":"page"},{"location":"manual/style-guide/#方法导出优先于直接字段访问","page":"代码风格指南","title":"方法导出优先于直接字段访问","text":"","category":"section"},{"location":"manual/style-guide/","page":"代码风格指南","title":"代码风格指南","text":"惯例上,Julia 代码通常应将模块的导出方法视为其类型的接口。 一个对象的字段通常被认为是实现细节,如果这被声明为 API,用户代码应该只直接访问它们。 这有几个好处:","category":"page"},{"location":"manual/style-guide/","page":"代码风格指南","title":"代码风格指南","text":"包开发人员可以更自由地更改实现而不会破坏用户代码。","category":"page"},{"location":"manual/style-guide/","page":"代码风格指南","title":"代码风格指南","text":"\n方法可以传递给高阶结构,如 map(例如 map(imag, zs))而不是 [z.im for z in zs])。\n方法可以定义在抽象类型上。\n方法可以描述可以在不同类型之间共享的概念操作(例如 real(z) 适用于复数或四元数)。","category":"page"},{"location":"manual/style-guide/","page":"代码风格指南","title":"代码风格指南","text":"Julia 的调度系统鼓励这种风格,因为 play(x::MyType) 只在该特定类型上定义了 play 方法,其它类型有自己的实现。","category":"page"},{"location":"manual/style-guide/","page":"代码风格指南","title":"代码风格指南","text":"同样,除非文档另有说明,否则非导出函数通常是内部的并且可能会发生变化。 名称有时会被赋予一个 _ 前缀(或后缀)以进一步暗示某些是“内部”或实现细节,但这不是规则。","category":"page"},{"location":"manual/style-guide/","page":"代码风格指南","title":"代码风格指南","text":"该规则的反例包括 NamedTuple、RegexMatch、StatStruct。","category":"page"},{"location":"manual/style-guide/#使用和-Julia-base/-文件夹中的代码一致的命名习惯","page":"代码风格指南","title":"使用和 Julia base/ 文件夹中的代码一致的命名习惯","text":"","category":"section"},{"location":"manual/style-guide/","page":"代码风格指南","title":"代码风格指南","text":"module 和 type 的名字使用大写开头的驼峰命名法:module SparseArrays,struct UnitRange。\n函数名使用小写字母,且当可读时可以将多个单词拼在一起。必要的时候,可以使用下划线作为单词分隔符。下划线也被用于指明概念的组合(比如 remotecall_fetch 作为 fetch(remotecall(...)) 的一个更高效的实现)或者变化。\n至少改变其中一个参数的函数名称以!结尾。\n虽然简洁性很重要,但避免使用缩写(用 indexin 而不是 indxin),因为这会让记住单词有没有被缩写或如何被缩写变得十分困难。","category":"page"},{"location":"manual/style-guide/","page":"代码风格指南","title":"代码风格指南","text":"如果一个函数名需要多个单词,请考虑这个函数是否代表了超过一个概念,是不是分成几个更小的部分更好。","category":"page"},{"location":"manual/style-guide/#使用与-Julia-Base-中的函数类似的参数顺序","page":"代码风格指南","title":"使用与 Julia Base 中的函数类似的参数顺序","text":"","category":"section"},{"location":"manual/style-guide/","page":"代码风格指南","title":"代码风格指南","text":"一般来说,Base 库使用以下的函数参数顺序(如适用):","category":"page"},{"location":"manual/style-guide/","page":"代码风格指南","title":"代码风格指南","text":"函数参数. 函数的第一个参数可以接受 Function 类型,以便使用 do blocks 来传递多行匿名函数。\nI/O stream. 函数的第一个参数可以接受 IO 对象,以便将函数传递给 sprint 之类的函数,例如 sprint(show, x)。\n在输入参数的内容会被更改的情况下. 比如,在 fill!(x, v) 中,x 是要被修改的对象,所以放在要被插入 x 中的值前面。\nType. 把类型作为参数传入函数通常意味着返回值也会是同样的类型。 在 parse(Int, \"1\") 中,类型在需要解析的字符串之前。 还有很多类似的将类型作为函数第一个参数的例子,但是同时也需要注意到例如 read(io, String) 这样的函数中,会把 IO 参数放在类型的更前面,这样还是保持着这里描述的顺序。\n在输入参数的内容不会被更改的情况下. 比如在 fill!(x, v) 中的不被修改的 v,会放在 x 之后传入。\nKey. 对于关联集合来说,指的是键值对的键。 对于其它有索引的集合来说,指的是索引。\nValue. 对于关联集合来说,指的是键值对的值。 像fill!(x, v)这样的情况, 是v。\nEverything else. 任何的其它参数。\nVarargs. 指的是在函数调用时可以被无限列在后面的参数。 比如在 Matrix{T}(uninitialized, dims) 中,维数(dims)可以作为 Tuple 被传入(如 Matrix{T}(uninitialized, (1,2))),也可以作为可变参数(Vararg,如 Matrix{T}(uninitialized, 1, 2)。\nKeyword arguments. 在 Julia 中,关键字参数本来就不得不定义在函数定义的最后,列在这里仅仅是为了完整性。","category":"page"},{"location":"manual/style-guide/","page":"代码风格指南","title":"代码风格指南","text":"大多数函数并不会接受上述所有种类的参数,这些数字仅仅是表示当适用时的优先权。","category":"page"},{"location":"manual/style-guide/","page":"代码风格指南","title":"代码风格指南","text":"当然,在一些情况下有例外。例如,convert 函数总是把类型作为第一个参数。setindex! 函数的值参数在索引参数之前,这样可以让索引作为可变参数传入。","category":"page"},{"location":"manual/style-guide/","page":"代码风格指南","title":"代码风格指南","text":"设计 API 时,尽可能秉承着这种一般顺序会让函数的使用者有一种更一致的体验。","category":"page"},{"location":"manual/style-guide/#不要过度使用-try-catch","page":"代码风格指南","title":"不要过度使用 try-catch","text":"","category":"section"},{"location":"manual/style-guide/","page":"代码风格指南","title":"代码风格指南","text":"比起依赖于捕获错误,更好的是避免错误。","category":"page"},{"location":"manual/style-guide/#不要给条件语句加括号","page":"代码风格指南","title":"不要给条件语句加括号","text":"","category":"section"},{"location":"manual/style-guide/","page":"代码风格指南","title":"代码风格指南","text":"Julia 不要求在 if 和 while 后的条件两边加括号。使用如下写法:","category":"page"},{"location":"manual/style-guide/","page":"代码风格指南","title":"代码风格指南","text":"if a == b","category":"page"},{"location":"manual/style-guide/","page":"代码风格指南","title":"代码风格指南","text":"而不是:","category":"page"},{"location":"manual/style-guide/","page":"代码风格指南","title":"代码风格指南","text":"if (a == b)","category":"page"},{"location":"manual/style-guide/#不要过度使用-...","page":"代码风格指南","title":"不要过度使用 ...","text":"","category":"section"},{"location":"manual/style-guide/","page":"代码风格指南","title":"代码风格指南","text":"拼接函数参数是会上瘾的。请用简单的 [a; b] 来代替 [a..., b...],因为前者已经是被拼接的数组了。collect(a) 也比 [a...] 更好,但因为 a 已经是一个可迭代的变量了,通常不把它转换成数组就直接使用甚至更好。","category":"page"},{"location":"manual/style-guide/#不要使用不必要的静态参数","page":"代码风格指南","title":"不要使用不必要的静态参数","text":"","category":"section"},{"location":"manual/style-guide/","page":"代码风格指南","title":"代码风格指南","text":"如下的函数签名:","category":"page"},{"location":"manual/style-guide/","page":"代码风格指南","title":"代码风格指南","text":"foo(x::T) where {T<:Real} = ...","category":"page"},{"location":"manual/style-guide/","page":"代码风格指南","title":"代码风格指南","text":"应当被写作:","category":"page"},{"location":"manual/style-guide/","page":"代码风格指南","title":"代码风格指南","text":"foo(x::Real) = ...","category":"page"},{"location":"manual/style-guide/","page":"代码风格指南","title":"代码风格指南","text":"尤其是当 T 没有被用在函数体中时格外有意义。即使 T 被用到了,通常也可以被替换为 typeof(x),后者不会导致性能上的差别。注意这并不是针对静态参数的一般警告,而仅仅是针对那些不必要的情况。","category":"page"},{"location":"manual/style-guide/","page":"代码风格指南","title":"代码风格指南","text":"同样需要注意的是,容器类型在函数调用中可能明确地需要类型参数。详情参见避免使用带抽象容器的字段。","category":"page"},{"location":"manual/style-guide/#避免判断变量是实例还是类型的混乱","page":"代码风格指南","title":"避免判断变量是实例还是类型的混乱","text":"","category":"section"},{"location":"manual/style-guide/","page":"代码风格指南","title":"代码风格指南","text":"如下的一组定义容易令人困惑:","category":"page"},{"location":"manual/style-guide/","page":"代码风格指南","title":"代码风格指南","text":"foo(::Type{MyType}) = ...\nfoo(::MyType) = foo(MyType)","category":"page"},{"location":"manual/style-guide/","page":"代码风格指南","title":"代码风格指南","text":"请决定问题里的概念应当是 MyType 还是 MyType(),然后坚持使用其一。","category":"page"},{"location":"manual/style-guide/","page":"代码风格指南","title":"代码风格指南","text":"首选风格应是默认使用实例,只有在需要解决某些问题时才添加涉及Type{MyType}的方法。","category":"page"},{"location":"manual/style-guide/","page":"代码风格指南","title":"代码风格指南","text":"如果一个类型实际上是个枚举,它应该被定义成一个单一的类型(理想的情况是不可变结构或原始类型),把枚举值作为它的实例。构造器和转换器可以检查那些值是否有效。这种设计比把枚举做成抽象类型,并把“值”做成子类型来得更受推崇。","category":"page"},{"location":"manual/style-guide/#不要过度使用宏","page":"代码风格指南","title":"不要过度使用宏","text":"","category":"section"},{"location":"manual/style-guide/","page":"代码风格指南","title":"代码风格指南","text":"请注意有的宏实际上可以被写成一个函数。","category":"page"},{"location":"manual/style-guide/","page":"代码风格指南","title":"代码风格指南","text":"在宏内部调用 eval 是一个特别危险的警告标志,它意味着这个宏仅在被最外层调用时起作用。如果这样的宏被写成函数,它会自然地访问得到它所需要的运行时值。","category":"page"},{"location":"manual/style-guide/#不要把不安全的操作暴露在接口层","page":"代码风格指南","title":"不要把不安全的操作暴露在接口层","text":"","category":"section"},{"location":"manual/style-guide/","page":"代码风格指南","title":"代码风格指南","text":"如果你有一个使用本地指针的类型:","category":"page"},{"location":"manual/style-guide/","page":"代码风格指南","title":"代码风格指南","text":"mutable struct NativeType\n p::Ptr{UInt8}\n ...\nend","category":"page"},{"location":"manual/style-guide/","page":"代码风格指南","title":"代码风格指南","text":"不要定义类似如下的函数:","category":"page"},{"location":"manual/style-guide/","page":"代码风格指南","title":"代码风格指南","text":"getindex(x::NativeType, i) = unsafe_load(x.p, i)","category":"page"},{"location":"manual/style-guide/","page":"代码风格指南","title":"代码风格指南","text":"这里的问题在于,这个类型的用户可能会在意识不到这个操作不安全的情况下写出 x[i],然后容易遇到内存错误。","category":"page"},{"location":"manual/style-guide/","page":"代码风格指南","title":"代码风格指南","text":"在这样的函数中,可以加上对操作的检查来确保安全,或者可以在名字的某处加上 unsafe 来警告调用者。","category":"page"},{"location":"manual/style-guide/#不要重载基础容器类型的方法","page":"代码风格指南","title":"不要重载基础容器类型的方法","text":"","category":"section"},{"location":"manual/style-guide/","page":"代码风格指南","title":"代码风格指南","text":"有时可能会想要写这样的定义:","category":"page"},{"location":"manual/style-guide/","page":"代码风格指南","title":"代码风格指南","text":"show(io::IO, v::Vector{MyType}) = ...","category":"page"},{"location":"manual/style-guide/","page":"代码风格指南","title":"代码风格指南","text":"这样可以提供对特定的某种新元素类型的向量的自定义显示。这种做法虽然很诱人,但应当被避免。这里的问题在于用户会想着一个像 Vector() 这样熟知的类型以某种方式表现,但过度自定义的行为会让使用变得更难。","category":"page"},{"location":"manual/style-guide/#避免类型盗版","page":"代码风格指南","title":"避免类型盗版","text":"","category":"section"},{"location":"manual/style-guide/","page":"代码风格指南","title":"代码风格指南","text":"“类型盗版”(type piracy)指的是扩展或是重定义 Base 或其它包中的并不是你所定义的类型的方法。在某些情况下,你可以几乎毫无副作用地逃避类型盗版。但在极端情况下,你甚至会让 Julia 崩溃(比如说你的方法扩展或重定义造成了对 ccall 传入了无效的输入)。类型盗版也让代码推导变得更复杂,且可能会引入难以预料和诊断的不兼容性。","category":"page"},{"location":"manual/style-guide/","page":"代码风格指南","title":"代码风格指南","text":"例如,你也许想在一个模块中定义符号上的乘法:","category":"page"},{"location":"manual/style-guide/","page":"代码风格指南","title":"代码风格指南","text":"module A\nimport Base.*\n*(x::Symbol, y::Symbol) = Symbol(x,y)\nend","category":"page"},{"location":"manual/style-guide/","page":"代码风格指南","title":"代码风格指南","text":"这里的问题时现在其它用到 Base.* 的模块同样会看到这个定义。由于 Symbol 是定义在 Base 里再被其它模块所使用的,这可能不可预料地改变无关代码的行为。这里有几种替代的方式,包括使用一个不同的函数名称,或是把 Symbol 给包在另一个你自己定义的类型中。","category":"page"},{"location":"manual/style-guide/","page":"代码风格指南","title":"代码风格指南","text":"有时候,耦合的包可能会使用类型盗版,以此来从定义分隔特性,尤其是当那些包是一些合作的作者设计的时候,且那些定义是可重用的时候。例如,一个包可能提供一些对处理色彩有用的类型,另一个包可能为那些类型定义色彩空间之间转换的方法。再举一个例子,一个包可能是一些 C 代码的简易包装,另一个包可能就“盗版”来实现一些更高级别的、对 Julia 友好的 API。","category":"page"},{"location":"manual/style-guide/#注意类型相等","page":"代码风格指南","title":"注意类型相等","text":"","category":"section"},{"location":"manual/style-guide/","page":"代码风格指南","title":"代码风格指南","text":"通常会用 isa 和 <: 来对类型进行测试,而不会用到 ==。检测类型的相等通常只对和一个已知的具体类型比较有意义(例如 T == Float64),或者你真的真的知道自己在做什么。","category":"page"},{"location":"manual/style-guide/#不要写-x-f(x)","page":"代码风格指南","title":"不要写 x->f(x)","text":"","category":"section"},{"location":"manual/style-guide/","page":"代码风格指南","title":"代码风格指南","text":"因为调用高阶函数时经常会用到匿名函数,很容易认为这是合理甚至必要的。但任何函数都可以被直接传递,并不需要被“包\"在一个匿名函数中。比如 map(x->f(x), a) 应当被写成 map(f, a)。","category":"page"},{"location":"manual/style-guide/#尽可能避免使用浮点数作为通用代码的字面量","page":"代码风格指南","title":"尽可能避免使用浮点数作为通用代码的字面量","text":"","category":"section"},{"location":"manual/style-guide/","page":"代码风格指南","title":"代码风格指南","text":"当写处理数字,且可以处理多种不同数字类型的参数的通用代码时,请使用对参数影响(通过类型提升)尽可能少的类型的字面量。","category":"page"},{"location":"manual/style-guide/","page":"代码风格指南","title":"代码风格指南","text":"例如,","category":"page"},{"location":"manual/style-guide/","page":"代码风格指南","title":"代码风格指南","text":"julia> f(x) = 2.0 * x\nf (generic function with 1 method)\n\njulia> f(1//2)\n1.0\n\njulia> f(1/2)\n1.0\n\njulia> f(1)\n2.0","category":"page"},{"location":"manual/style-guide/","page":"代码风格指南","title":"代码风格指南","text":"而应当被写作:","category":"page"},{"location":"manual/style-guide/","page":"代码风格指南","title":"代码风格指南","text":"julia> g(x) = 2 * x\ng (generic function with 1 method)\n\njulia> g(1//2)\n1//1\n\njulia> g(1/2)\n1.0\n\njulia> g(1)\n2","category":"page"},{"location":"manual/style-guide/","page":"代码风格指南","title":"代码风格指南","text":"如你所见,使用了 Int 字面量的第二个版本保留了输入参数的类型,而第一个版本没有。这是因为例如 promote_type(Int, Float64) == Float64,且做乘法时会需要类型提升。类似地,Rational 字面量比 Float64 字面量对类型有着更小的破坏性,但比 Int 大。","category":"page"},{"location":"manual/style-guide/","page":"代码风格指南","title":"代码风格指南","text":"julia> h(x) = 2//1 * x\nh (generic function with 1 method)\n\njulia> h(1//2)\n1//1\n\njulia> h(1/2)\n1.0\n\njulia> h(1)\n2//1","category":"page"},{"location":"manual/style-guide/","page":"代码风格指南","title":"代码风格指南","text":"所以,可能时尽量使用 Int 字面量,对非整数字面量使用 Rational{Int},这样可以让代码变得更容易使用。","category":"page"},{"location":"base/math/#数学相关","page":"数学相关","title":"数学相关","text":"","category":"section"},{"location":"base/math/#math-ops","page":"数学相关","title":"数学运算符","text":"","category":"section"},{"location":"base/math/","page":"数学相关","title":"数学相关","text":"Base.:-(::Any)\nBase.:(+)\nBase.:-(::Any, ::Any)\nBase.:*(::Any, ::Any...)\nBase.:(/)\nBase.:\\(::Any, ::Any)\nBase.:^(::Number, ::Number)\nBase.fma\nBase.muladd\nBase.inv(::Number)\nBase.div\nBase.fld\nBase.cld\nBase.mod\nBase.rem\nBase.rem2pi\nBase.Math.mod2pi\nBase.divrem\nBase.fldmod\nBase.fld1\nBase.mod1\nBase.fldmod1\nBase.:(//)\nBase.rationalize\nBase.numerator\nBase.denominator\nBase.:(<<)\nBase.:(>>)\nBase.:(>>>)\nBase.bitrotate\nBase.:(:)\nBase.range\nBase.OneTo\nBase.StepRangeLen\nBase.:(==)\nBase.:(!=)\nBase.:(!==)\nBase.:(<)\nBase.:(<=)\nBase.:(>)\nBase.:(>=)\nBase.cmp\nBase.:(~)\nBase.:(&)\nBase.:(|)\nBase.xor\nBase.nand\nBase.nor\nBase.:(!)\n&&\n||","category":"page"},{"location":"base/math/#Base.:--Tuple{Any}","page":"数学相关","title":"Base.:-","text":"-(x)\n\nUnary minus operator.\n\nSee also: abs, flipsign.\n\nExamples\n\njulia> -1\n-1\n\njulia> -(2)\n-2\n\njulia> -[1 2; 3 4]\n2×2 Matrix{Int64}:\n -1 -2\n -3 -4\n\n\n\n\n\n","category":"method"},{"location":"base/math/#Base.:+","page":"数学相关","title":"Base.:+","text":"dt::Date + t::Time -> DateTime\n\nThe addition of a Date with a Time produces a DateTime. The hour, minute, second, and millisecond parts of the Time are used along with the year, month, and day of the Date to create the new DateTime. Non-zero microseconds or nanoseconds in the Time type will result in an InexactError being thrown.\n\n\n\n\n\n+(x, y...)\n\nAddition operator. x+y+z+... calls this function with all arguments, i.e. +(x, y, z, ...).\n\nExamples\n\njulia> 1 + 20 + 4\n25\n\njulia> +(1, 20, 4)\n25\n\n\n\n\n\n","category":"function"},{"location":"base/math/#Base.:--Tuple{Any, Any}","page":"数学相关","title":"Base.:-","text":"-(x, y)\n\nSubtraction operator.\n\nExamples\n\njulia> 2 - 3\n-1\n\njulia> -(2, 4.5)\n-2.5\n\n\n\n\n\n","category":"method"},{"location":"base/math/#Base.:*-Tuple{Any, Vararg{Any}}","page":"数学相关","title":"Base.:*","text":"*(x, y...)\n\nMultiplication operator. x*y*z*... calls this function with all arguments, i.e. *(x, y, z, ...).\n\nExamples\n\njulia> 2 * 7 * 8\n112\n\njulia> *(2, 7, 8)\n112\n\n\n\n\n\n","category":"method"},{"location":"base/math/#Base.:/","page":"数学相关","title":"Base.:/","text":"A / B\n\nMatrix right-division: A / B is equivalent to (B' \\ A')' where \\ is the left-division operator. For square matrices, the result X is such that A == X*B.\n\nSee also: rdiv!.\n\nExamples\n\njulia> A = Float64[1 4 5; 3 9 2]; B = Float64[1 4 2; 3 4 2; 8 7 1];\n\njulia> X = A / B\n2×3 Matrix{Float64}:\n -0.65 3.75 -1.2\n 3.25 -2.75 1.0\n\njulia> isapprox(A, X*B)\ntrue\n\njulia> isapprox(X, A*pinv(B))\ntrue\n\n\n\n\n\n/(x, y)\n\nRight division operator: multiplication of x by the inverse of y on the right. Gives floating-point results for integer arguments.\n\nExamples\n\njulia> 1/2\n0.5\n\njulia> 4/2\n2.0\n\njulia> 4.5/2\n2.25\n\n\n\n\n\n","category":"function"},{"location":"base/math/#Base.:\\-Tuple{Any, Any}","page":"数学相关","title":"Base.:\\","text":"\\(x, y)\n\nLeft division operator: multiplication of y by the inverse of x on the left. Gives floating-point results for integer arguments.\n\nExamples\n\njulia> 3 \\ 6\n2.0\n\njulia> inv(3) * 6\n2.0\n\njulia> A = [4 3; 2 1]; x = [5, 6];\n\njulia> A \\ x\n2-element Vector{Float64}:\n 6.5\n -7.0\n\njulia> inv(A) * x\n2-element Vector{Float64}:\n 6.5\n -7.0\n\n\n\n\n\n","category":"method"},{"location":"base/math/#Base.:^-Tuple{Number, Number}","page":"数学相关","title":"Base.:^","text":"^(x, y)\n\nExponentiation operator. If x is a matrix, computes matrix exponentiation.\n\nIf y is an Int literal (e.g. 2 in x^2 or -3 in x^-3), the Julia code x^y is transformed by the compiler to Base.literal_pow(^, x, Val(y)), to enable compile-time specialization on the value of the exponent. (As a default fallback we have Base.literal_pow(^, x, Val(y)) = ^(x,y), where usually ^ == Base.^ unless ^ has been defined in the calling namespace.) If y is a negative integer literal, then Base.literal_pow transforms the operation to inv(x)^-y by default, where -y is positive.\n\nExamples\n\njulia> 3^5\n243\n\njulia> A = [1 2; 3 4]\n2×2 Matrix{Int64}:\n 1 2\n 3 4\n\njulia> A^3\n2×2 Matrix{Int64}:\n 37 54\n 81 118\n\n\n\n\n\n","category":"method"},{"location":"base/math/#Base.fma","page":"数学相关","title":"Base.fma","text":"fma(x, y, z)\n\nComputes x*y+z without rounding the intermediate result x*y. On some systems this is significantly more expensive than x*y+z. fma is used to improve accuracy in certain algorithms. See muladd.\n\n\n\n\n\n","category":"function"},{"location":"base/math/#Base.muladd","page":"数学相关","title":"Base.muladd","text":"muladd(x, y, z)\n\nCombined multiply-add: computes x*y+z, but allowing the add and multiply to be merged with each other or with surrounding operations for performance. For example, this may be implemented as an fma if the hardware supports it efficiently. The result can be different on different machines and can also be different on the same machine due to constant propagation or other optimizations. See fma.\n\nExamples\n\njulia> muladd(3, 2, 1)\n7\n\njulia> 3 * 2 + 1\n7\n\n\n\n\n\nmuladd(A, y, z)\n\nCombined multiply-add, A*y .+ z, for matrix-matrix or matrix-vector multiplication. The result is always the same size as A*y, but z may be smaller, or a scalar.\n\ncompat: Julia 1.6\nThese methods require Julia 1.6 or later.\n\nExamples\n\njulia> A=[1.0 2.0; 3.0 4.0]; B=[1.0 1.0; 1.0 1.0]; z=[0, 100];\n\njulia> muladd(A, B, z)\n2×2 Matrix{Float64}:\n 3.0 3.0\n 107.0 107.0\n\n\n\n\n\n","category":"function"},{"location":"base/math/#Base.inv-Tuple{Number}","page":"数学相关","title":"Base.inv","text":"inv(x)\n\nReturn the multiplicative inverse of x, such that x*inv(x) or inv(x)*x yields one(x) (the multiplicative identity) up to roundoff errors.\n\nIf x is a number, this is essentially the same as one(x)/x, but for some types inv(x) may be slightly more efficient.\n\nExamples\n\njulia> inv(2)\n0.5\n\njulia> inv(1 + 2im)\n0.2 - 0.4im\n\njulia> inv(1 + 2im) * (1 + 2im)\n1.0 + 0.0im\n\njulia> inv(2//3)\n3//2\n\ncompat: Julia 1.2\ninv(::Missing) requires at least Julia 1.2.\n\n\n\n\n\n","category":"method"},{"location":"base/math/#Base.div","page":"数学相关","title":"Base.div","text":"div(x, y)\n÷(x, y)\n\nThe quotient from Euclidean (integer) division. Generally equivalent to a mathematical operation x/y without a fractional part.\n\nSee also: cld, fld, rem, divrem.\n\nExamples\n\njulia> 9 ÷ 4\n2\n\njulia> -5 ÷ 3\n-1\n\njulia> 5.0 ÷ 2\n2.0\n\njulia> div.(-5:5, 3)'\n1×11 adjoint(::Vector{Int64}) with eltype Int64:\n -1 -1 -1 0 0 0 0 0 1 1 1\n\n\n\n\n\n","category":"function"},{"location":"base/math/#Base.fld","page":"数学相关","title":"Base.fld","text":"fld(x, y)\n\nLargest integer less than or equal to x/y. Equivalent to div(x, y, RoundDown).\n\nSee also div, cld, fld1.\n\nExamples\n\njulia> fld(7.3,5.5)\n1.0\n\njulia> fld.(-5:5, 3)'\n1×11 adjoint(::Vector{Int64}) with eltype Int64:\n -2 -2 -1 -1 -1 0 0 0 1 1 1\n\nBecause fld(x, y) implements strictly correct floored rounding based on the true value of floating-point numbers, unintuitive situations can arise. For example:\n\njulia> fld(6.0,0.1)\n59.0\njulia> 6.0/0.1\n60.0\njulia> 6.0/big(0.1)\n59.99999999999999666933092612453056361837965690217069245739573412231113406246995\n\nWhat is happening here is that the true value of the floating-point number written as 0.1 is slightly larger than the numerical value 1/10 while 6.0 represents the number 6 precisely. Therefore the true value of 6.0 / 0.1 is slightly less than 60. When doing division, this is rounded to precisely 60.0, but fld(6.0, 0.1) always takes the floor of the true value, so the result is 59.0.\n\n\n\n\n\n","category":"function"},{"location":"base/math/#Base.cld","page":"数学相关","title":"Base.cld","text":"cld(x, y)\n\nSmallest integer larger than or equal to x/y. Equivalent to div(x, y, RoundUp).\n\nSee also div, fld.\n\nExamples\n\njulia> cld(5.5,2.2)\n3.0\n\njulia> cld.(-5:5, 3)'\n1×11 adjoint(::Vector{Int64}) with eltype Int64:\n -1 -1 -1 0 0 0 1 1 1 2 2\n\n\n\n\n\n","category":"function"},{"location":"base/math/#Base.mod","page":"数学相关","title":"Base.mod","text":"mod(x::Integer, r::AbstractUnitRange)\n\nFind y in the range r such that x y (mod n), where n = length(r), i.e. y = mod(x - first(r), n) + first(r).\n\nSee also mod1.\n\nExamples\n\njulia> mod(0, Base.OneTo(3)) # mod1(0, 3)\n3\n\njulia> mod(3, 0:2) # mod(3, 3)\n0\n\ncompat: Julia 1.3\nThis method requires at least Julia 1.3.\n\n\n\n\n\nmod(x, y)\nrem(x, y, RoundDown)\n\nThe reduction of x modulo y, or equivalently, the remainder of x after floored division by y, i.e. x - y*fld(x,y) if computed without intermediate rounding.\n\nThe result will have the same sign as y, and magnitude less than abs(y) (with some exceptions, see note below).\n\nnote: Note\nWhen used with floating point values, the exact result may not be representable by the type, and so rounding error may occur. In particular, if the exact result is very close to y, then it may be rounded to y.\n\nSee also: rem, div, fld, mod1, invmod.\n\njulia> mod(8, 3)\n2\n\njulia> mod(9, 3)\n0\n\njulia> mod(8.9, 3)\n2.9000000000000004\n\njulia> mod(eps(), 3)\n2.220446049250313e-16\n\njulia> mod(-eps(), 3)\n3.0\n\njulia> mod.(-5:5, 3)'\n1×11 adjoint(::Vector{Int64}) with eltype Int64:\n 1 2 0 1 2 0 1 2 0 1 2\n\n\n\n\n\nrem(x::Integer, T::Type{<:Integer}) -> T\nmod(x::Integer, T::Type{<:Integer}) -> T\n%(x::Integer, T::Type{<:Integer}) -> T\n\nFind y::T such that x ≡ y (mod n), where n is the number of integers representable in T, and y is an integer in [typemin(T),typemax(T)]. If T can represent any integer (e.g. T == BigInt), then this operation corresponds to a conversion to T.\n\nExamples\n\njulia> 129 % Int8\n-127\n\n\n\n\n\n","category":"function"},{"location":"base/math/#Base.rem","page":"数学相关","title":"Base.rem","text":"rem(x, y)\n%(x, y)\n\nRemainder from Euclidean division, returning a value of the same sign as x, and smaller in magnitude than y. This value is always exact.\n\nSee also: div, mod, mod1, divrem.\n\nExamples\n\njulia> x = 15; y = 4;\n\njulia> x % y\n3\n\njulia> x == div(x, y) * y + rem(x, y)\ntrue\n\njulia> rem.(-5:5, 3)'\n1×11 adjoint(::Vector{Int64}) with eltype Int64:\n -2 -1 0 -2 -1 0 1 2 0 1 2\n\n\n\n\n\n","category":"function"},{"location":"base/math/#Base.Math.rem2pi","page":"数学相关","title":"Base.Math.rem2pi","text":"rem2pi(x, r::RoundingMode)\n\nCompute the remainder of x after integer division by 2π, with the quotient rounded according to the rounding mode r. In other words, the quantity\n\nx - 2π*round(x/(2π),r)\n\nwithout any intermediate rounding. This internally uses a high precision approximation of 2π, and so will give a more accurate result than rem(x,2π,r)\n\nif r == RoundNearest, then the result is in the interval -π π. This will generally be the most accurate result. See also RoundNearest.\nif r == RoundToZero, then the result is in the interval 0 2π if x is positive,. or -2π 0 otherwise. See also RoundToZero.\nif r == RoundDown, then the result is in the interval 0 2π. See also RoundDown.\nif r == RoundUp, then the result is in the interval -2π 0. See also RoundUp.\n\nExamples\n\njulia> rem2pi(7pi/4, RoundNearest)\n-0.7853981633974485\n\njulia> rem2pi(7pi/4, RoundDown)\n5.497787143782138\n\n\n\n\n\n","category":"function"},{"location":"base/math/#Base.Math.mod2pi","page":"数学相关","title":"Base.Math.mod2pi","text":"mod2pi(x)\n\nModulus after division by 2π, returning in the range 02π).\n\nThis function computes a floating point representation of the modulus after division by numerically exact 2π, and is therefore not exactly the same as mod(x,2π), which would compute the modulus of x relative to division by the floating-point number 2π.\n\nnote: Note\nDepending on the format of the input value, the closest representable value to 2π may be less than 2π. For example, the expression mod2pi(2π) will not return 0, because the intermediate value of 2*π is a Float64 and 2*Float64(π) < 2*big(π). See rem2pi for more refined control of this behavior.\n\nExamples\n\njulia> mod2pi(9*pi/4)\n0.7853981633974481\n\n\n\n\n\n","category":"function"},{"location":"base/math/#Base.divrem","page":"数学相关","title":"Base.divrem","text":"divrem(x, y, r::RoundingMode=RoundToZero)\n\nThe quotient and remainder from Euclidean division. Equivalent to (div(x,y,r), rem(x,y,r)). Equivalently, with the default value of r, this call is equivalent to (x÷y, x%y).\n\nSee also: fldmod, cld.\n\nExamples\n\njulia> divrem(3,7)\n(0, 3)\n\njulia> divrem(7,3)\n(2, 1)\n\n\n\n\n\n","category":"function"},{"location":"base/math/#Base.fldmod","page":"数学相关","title":"Base.fldmod","text":"fldmod(x, y)\n\nThe floored quotient and modulus after division. A convenience wrapper for divrem(x, y, RoundDown). Equivalent to (fld(x,y), mod(x,y)).\n\nSee also: fld, cld, fldmod1.\n\n\n\n\n\n","category":"function"},{"location":"base/math/#Base.fld1","page":"数学相关","title":"Base.fld1","text":"fld1(x, y)\n\nFlooring division, returning a value consistent with mod1(x,y)\n\nSee also mod1, fldmod1.\n\nExamples\n\njulia> x = 15; y = 4;\n\njulia> fld1(x, y)\n4\n\njulia> x == fld(x, y) * y + mod(x, y)\ntrue\n\njulia> x == (fld1(x, y) - 1) * y + mod1(x, y)\ntrue\n\n\n\n\n\n","category":"function"},{"location":"base/math/#Base.mod1","page":"数学相关","title":"Base.mod1","text":"mod1(x, y)\n\nModulus after flooring division, returning a value r such that mod(r, y) == mod(x, y) in the range (0 y for positive y and in the range y0) for negative y.\n\nWith integer arguments and positive y, this is equal to mod(x, 1:y), and hence natural for 1-based indexing. By comparison, mod(x, y) == mod(x, 0:y-1) is natural for computations with offsets or strides.\n\nSee also mod, fld1, fldmod1.\n\nExamples\n\njulia> mod1(4, 2)\n2\n\njulia> mod1.(-5:5, 3)'\n1×11 adjoint(::Vector{Int64}) with eltype Int64:\n 1 2 3 1 2 3 1 2 3 1 2\n\njulia> mod1.([-0.1, 0, 0.1, 1, 2, 2.9, 3, 3.1]', 3)\n1×8 Matrix{Float64}:\n 2.9 3.0 0.1 1.0 2.0 2.9 3.0 0.1\n\n\n\n\n\n","category":"function"},{"location":"base/math/#Base.fldmod1","page":"数学相关","title":"Base.fldmod1","text":"fldmod1(x, y)\n\nReturn (fld1(x,y), mod1(x,y)).\n\nSee also fld1, mod1.\n\n\n\n\n\n","category":"function"},{"location":"base/math/#Base.://","page":"数学相关","title":"Base.://","text":"//(num, den)\n\nDivide two integers or rational numbers, giving a Rational result.\n\nExamples\n\njulia> 3 // 5\n3//5\n\njulia> (3 // 5) // (2 // 1)\n3//10\n\n\n\n\n\n","category":"function"},{"location":"base/math/#Base.rationalize","page":"数学相关","title":"Base.rationalize","text":"rationalize([T<:Integer=Int,] x; tol::Real=eps(x))\n\nApproximate floating point number x as a Rational number with components of the given integer type. The result will differ from x by no more than tol.\n\nExamples\n\njulia> rationalize(5.6)\n28//5\n\njulia> a = rationalize(BigInt, 10.3)\n103//10\n\njulia> typeof(numerator(a))\nBigInt\n\n\n\n\n\n","category":"function"},{"location":"base/math/#Base.numerator","page":"数学相关","title":"Base.numerator","text":"numerator(x)\n\nNumerator of the rational representation of x.\n\nExamples\n\njulia> numerator(2//3)\n2\n\njulia> numerator(4)\n4\n\n\n\n\n\n","category":"function"},{"location":"base/math/#Base.denominator","page":"数学相关","title":"Base.denominator","text":"denominator(x)\n\nDenominator of the rational representation of x.\n\nExamples\n\njulia> denominator(2//3)\n3\n\njulia> denominator(4)\n1\n\n\n\n\n\n","category":"function"},{"location":"base/math/#Base.:<<","page":"数学相关","title":"Base.:<<","text":"<<(x, n)\n\nLeft bit shift operator, x << n. For n >= 0, the result is x shifted left by n bits, filling with 0s. This is equivalent to x * 2^n. For n < 0, this is equivalent to x >> -n.\n\nExamples\n\njulia> Int8(3) << 2\n12\n\njulia> bitstring(Int8(3))\n\"00000011\"\n\njulia> bitstring(Int8(12))\n\"00001100\"\n\nSee also >>, >>>, exp2, ldexp.\n\n\n\n\n\n<<(B::BitVector, n) -> BitVector\n\nLeft bit shift operator, B << n. For n >= 0, the result is B with elements shifted n positions backwards, filling with false values. If n < 0, elements are shifted forwards. Equivalent to B >> -n.\n\nExamples\n\njulia> B = BitVector([true, false, true, false, false])\n5-element BitVector:\n 1\n 0\n 1\n 0\n 0\n\njulia> B << 1\n5-element BitVector:\n 0\n 1\n 0\n 0\n 0\n\njulia> B << -1\n5-element BitVector:\n 0\n 1\n 0\n 1\n 0\n\n\n\n\n\n","category":"function"},{"location":"base/math/#Base.:>>","page":"数学相关","title":"Base.:>>","text":">>(x, n)\n\nRight bit shift operator, x >> n. For n >= 0, the result is x shifted right by n bits, where n >= 0, filling with 0s if x >= 0, 1s if x < 0, preserving the sign of x. This is equivalent to fld(x, 2^n). For n < 0, this is equivalent to x << -n.\n\nExamples\n\njulia> Int8(13) >> 2\n3\n\njulia> bitstring(Int8(13))\n\"00001101\"\n\njulia> bitstring(Int8(3))\n\"00000011\"\n\njulia> Int8(-14) >> 2\n-4\n\njulia> bitstring(Int8(-14))\n\"11110010\"\n\njulia> bitstring(Int8(-4))\n\"11111100\"\n\nSee also >>>, <<.\n\n\n\n\n\n>>(B::BitVector, n) -> BitVector\n\nRight bit shift operator, B >> n. For n >= 0, the result is B with elements shifted n positions forward, filling with false values. If n < 0, elements are shifted backwards. Equivalent to B << -n.\n\nExamples\n\njulia> B = BitVector([true, false, true, false, false])\n5-element BitVector:\n 1\n 0\n 1\n 0\n 0\n\njulia> B >> 1\n5-element BitVector:\n 0\n 1\n 0\n 1\n 0\n\njulia> B >> -1\n5-element BitVector:\n 0\n 1\n 0\n 0\n 0\n\n\n\n\n\n","category":"function"},{"location":"base/math/#Base.:>>>","page":"数学相关","title":"Base.:>>>","text":">>>(x, n)\n\nUnsigned right bit shift operator, x >>> n. For n >= 0, the result is x shifted right by n bits, where n >= 0, filling with 0s. For n < 0, this is equivalent to x << -n.\n\nFor Unsigned integer types, this is equivalent to >>. For Signed integer types, this is equivalent to signed(unsigned(x) >> n).\n\nExamples\n\njulia> Int8(-14) >>> 2\n60\n\njulia> bitstring(Int8(-14))\n\"11110010\"\n\njulia> bitstring(Int8(60))\n\"00111100\"\n\nBigInts are treated as if having infinite size, so no filling is required and this is equivalent to >>.\n\nSee also >>, <<.\n\n\n\n\n\n>>>(B::BitVector, n) -> BitVector\n\nUnsigned right bitshift operator, B >>> n. Equivalent to B >> n. See >> for details and examples.\n\n\n\n\n\n","category":"function"},{"location":"base/math/#Base.bitrotate","page":"数学相关","title":"Base.bitrotate","text":"bitrotate(x::Base.BitInteger, k::Integer)\n\nbitrotate(x, k) implements bitwise rotation. It returns the value of x with its bits rotated left k times. A negative value of k will rotate to the right instead.\n\ncompat: Julia 1.5\nThis function requires Julia 1.5 or later.\n\nSee also: <<, circshift, BitArray.\n\njulia> bitrotate(UInt8(114), 2)\n0xc9\n\njulia> bitstring(bitrotate(0b01110010, 2))\n\"11001001\"\n\njulia> bitstring(bitrotate(0b01110010, -2))\n\"10011100\"\n\njulia> bitstring(bitrotate(0b01110010, 8))\n\"01110010\"\n\n\n\n\n\n","category":"function"},{"location":"base/math/#Base.::","page":"数学相关","title":"Base.::","text":"(:)(start, [step], stop)\n\nRange operator. a:b constructs a range from a to b with a step size of 1 (a UnitRange) , and a:s:b is similar but uses a step size of s (a StepRange).\n\n: is also used in indexing to select whole dimensions and for Symbol literals, as in e.g. :hello.\n\n\n\n\n\n(:)(start::CartesianIndex, [step::CartesianIndex], stop::CartesianIndex)\n\nConstruct CartesianIndices from two CartesianIndex and an optional step.\n\ncompat: Julia 1.1\nThis method requires at least Julia 1.1.\n\ncompat: Julia 1.6\nThe step range method start:step:stop requires at least Julia 1.6.\n\nExamples\n\njulia> I = CartesianIndex(2,1);\n\njulia> J = CartesianIndex(3,3);\n\njulia> I:J\nCartesianIndices((2:3, 1:3))\n\njulia> I:CartesianIndex(1, 2):J\nCartesianIndices((2:1:3, 1:2:3))\n\n\n\n\n\n","category":"function"},{"location":"base/math/#Base.range","page":"数学相关","title":"Base.range","text":"range(start, stop, length)\nrange(start, stop; length, step)\nrange(start; length, stop, step)\nrange(;start, length, stop, step)\n\nConstruct a specialized array with evenly spaced elements and optimized storage (an AbstractRange) from the arguments. Mathematically a range is uniquely determined by any three of start, step, stop and length. Valid invocations of range are:\n\nCall range with any three of start, step, stop, length.\nCall range with two of start, stop, length. In this case step will be assumed to be one. If both arguments are Integers, a UnitRange will be returned.\nCall range with one of stop or length. start and step will be assumed to be one.\n\nSee Extended Help for additional details on the returned type.\n\nExamples\n\njulia> range(1, length=100)\n1:100\n\njulia> range(1, stop=100)\n1:100\n\njulia> range(1, step=5, length=100)\n1:5:496\n\njulia> range(1, step=5, stop=100)\n1:5:96\n\njulia> range(1, 10, length=101)\n1.0:0.09:10.0\n\njulia> range(1, 100, step=5)\n1:5:96\n\njulia> range(stop=10, length=5)\n6:10\n\njulia> range(stop=10, step=1, length=5)\n6:1:10\n\njulia> range(start=1, step=1, stop=10)\n1:1:10\n\njulia> range(; length = 10)\nBase.OneTo(10)\n\njulia> range(; stop = 6)\nBase.OneTo(6)\n\njulia> range(; stop = 6.5)\n1.0:1.0:6.0\n\nIf length is not specified and stop - start is not an integer multiple of step, a range that ends before stop will be produced.\n\njulia> range(1, 3.5, step=2)\n1.0:2.0:3.0\n\nSpecial care is taken to ensure intermediate values are computed rationally. To avoid this induced overhead, see the LinRange constructor.\n\ncompat: Julia 1.1\nstop as a positional argument requires at least Julia 1.1.\n\ncompat: Julia 1.7\nThe versions without keyword arguments and start as a keyword argument require at least Julia 1.7.\n\ncompat: Julia 1.8\nThe versions with stop as a sole keyword argument, or length as a sole keyword argument require at least Julia 1.8.\n\nExtended Help\n\nrange will produce a Base.OneTo when the arguments are Integers and\n\nOnly length is provided\nOnly stop is provided\n\nrange will produce a UnitRange when the arguments are Integers and\n\nOnly start and stop are provided\nOnly length and stop are provided\n\nA UnitRange is not produced if step is provided even if specified as one.\n\n\n\n\n\n","category":"function"},{"location":"base/math/#Base.OneTo","page":"数学相关","title":"Base.OneTo","text":"Base.OneTo(n)\n\nDefine an AbstractUnitRange that behaves like 1:n, with the added distinction that the lower limit is guaranteed (by the type system) to be 1.\n\n\n\n\n\n","category":"type"},{"location":"base/math/#Base.StepRangeLen","page":"数学相关","title":"Base.StepRangeLen","text":"StepRangeLen( ref::R, step::S, len, [offset=1]) where { R,S}\nStepRangeLen{T,R,S}( ref::R, step::S, len, [offset=1]) where {T,R,S}\nStepRangeLen{T,R,S,L}(ref::R, step::S, len, [offset=1]) where {T,R,S,L}\n\nA range r where r[i] produces values of type T (in the first form, T is deduced automatically), parameterized by a reference value, a step, and the length. By default ref is the starting value r[1], but alternatively you can supply it as the value of r[offset] for some other index 1 <= offset <= len. In conjunction with TwicePrecision this can be used to implement ranges that are free of roundoff error.\n\n\n\n\n\n","category":"type"},{"location":"base/math/#Base.:==","page":"数学相关","title":"Base.:==","text":"==(x, y)\n\nGeneric equality operator. Falls back to ===. Should be implemented for all types with a notion of equality, based on the abstract value that an instance represents. For example, all numeric types are compared by numeric value, ignoring type. Strings are compared as sequences of characters, ignoring encoding. For collections, == is generally called recursively on all contents, though other properties (like the shape for arrays) may also be taken into account.\n\nThis operator follows IEEE semantics for floating-point numbers: 0.0 == -0.0 and NaN != NaN.\n\nThe result is of type Bool, except when one of the operands is missing, in which case missing is returned (three-valued logic). For collections, missing is returned if at least one of the operands contains a missing value and all non-missing values are equal. Use isequal or === to always get a Bool result.\n\nImplementation\n\nNew numeric types should implement this function for two arguments of the new type, and handle comparison to other types via promotion rules where possible.\n\nisequal falls back to ==, so new methods of == will be used by the Dict type to compare keys. If your type will be used as a dictionary key, it should therefore also implement hash.\n\nIf some type defines ==, isequal, and isless then it should also implement < to ensure consistency of comparisons.\n\n\n\n\n\n","category":"function"},{"location":"base/math/#Base.:!=","page":"数学相关","title":"Base.:!=","text":"!=(x, y)\n≠(x,y)\n\nNot-equals comparison operator. Always gives the opposite answer as ==.\n\nImplementation\n\nNew types should generally not implement this, and rely on the fallback definition !=(x,y) = !(x==y) instead.\n\nExamples\n\njulia> 3 != 2\ntrue\n\njulia> \"foo\" ≠ \"foo\"\nfalse\n\n\n\n\n\n!=(x)\n\nCreate a function that compares its argument to x using !=, i.e. a function equivalent to y -> y != x. The returned function is of type Base.Fix2{typeof(!=)}, which can be used to implement specialized methods.\n\ncompat: Julia 1.2\nThis functionality requires at least Julia 1.2.\n\n\n\n\n\n","category":"function"},{"location":"base/math/#Base.:!==","page":"数学相关","title":"Base.:!==","text":"!==(x, y)\n≢(x,y)\n\nAlways gives the opposite answer as ===.\n\nExamples\n\njulia> a = [1, 2]; b = [1, 2];\n\njulia> a ≢ b\ntrue\n\njulia> a ≢ a\nfalse\n\n\n\n\n\n","category":"function"},{"location":"base/math/#Base.:<","page":"数学相关","title":"Base.:<","text":"<(x, y)\n\nLess-than comparison operator. Falls back to isless. Because of the behavior of floating-point NaN values, this operator implements a partial order.\n\nImplementation\n\nNew numeric types with a canonical partial order should implement this function for two arguments of the new type. Types with a canonical total order should implement isless instead.\n\nExamples\n\njulia> 'a' < 'b'\ntrue\n\njulia> \"abc\" < \"abd\"\ntrue\n\njulia> 5 < 3\nfalse\n\n\n\n\n\n<(x)\n\nCreate a function that compares its argument to x using <, i.e. a function equivalent to y -> y < x. The returned function is of type Base.Fix2{typeof(<)}, which can be used to implement specialized methods.\n\ncompat: Julia 1.2\nThis functionality requires at least Julia 1.2.\n\n\n\n\n\n","category":"function"},{"location":"base/math/#Base.:<=","page":"数学相关","title":"Base.:<=","text":"<=(x, y)\n≤(x,y)\n\nLess-than-or-equals comparison operator. Falls back to (x < y) | (x == y).\n\nExamples\n\njulia> 'a' <= 'b'\ntrue\n\njulia> 7 ≤ 7 ≤ 9\ntrue\n\njulia> \"abc\" ≤ \"abc\"\ntrue\n\njulia> 5 <= 3\nfalse\n\n\n\n\n\n<=(x)\n\nCreate a function that compares its argument to x using <=, i.e. a function equivalent to y -> y <= x. The returned function is of type Base.Fix2{typeof(<=)}, which can be used to implement specialized methods.\n\ncompat: Julia 1.2\nThis functionality requires at least Julia 1.2.\n\n\n\n\n\n","category":"function"},{"location":"base/math/#Base.:>","page":"数学相关","title":"Base.:>","text":">(x, y)\n\nGreater-than comparison operator. Falls back to y < x.\n\nImplementation\n\nGenerally, new types should implement < instead of this function, and rely on the fallback definition >(x, y) = y < x.\n\nExamples\n\njulia> 'a' > 'b'\nfalse\n\njulia> 7 > 3 > 1\ntrue\n\njulia> \"abc\" > \"abd\"\nfalse\n\njulia> 5 > 3\ntrue\n\n\n\n\n\n>(x)\n\nCreate a function that compares its argument to x using >, i.e. a function equivalent to y -> y > x. The returned function is of type Base.Fix2{typeof(>)}, which can be used to implement specialized methods.\n\ncompat: Julia 1.2\nThis functionality requires at least Julia 1.2.\n\n\n\n\n\n","category":"function"},{"location":"base/math/#Base.:>=","page":"数学相关","title":"Base.:>=","text":">=(x, y)\n≥(x,y)\n\nGreater-than-or-equals comparison operator. Falls back to y <= x.\n\nExamples\n\njulia> 'a' >= 'b'\nfalse\n\njulia> 7 ≥ 7 ≥ 3\ntrue\n\njulia> \"abc\" ≥ \"abc\"\ntrue\n\njulia> 5 >= 3\ntrue\n\n\n\n\n\n>=(x)\n\nCreate a function that compares its argument to x using >=, i.e. a function equivalent to y -> y >= x. The returned function is of type Base.Fix2{typeof(>=)}, which can be used to implement specialized methods.\n\ncompat: Julia 1.2\nThis functionality requires at least Julia 1.2.\n\n\n\n\n\n","category":"function"},{"location":"base/math/#Base.cmp","page":"数学相关","title":"Base.cmp","text":"cmp(x,y)\n\nReturn -1, 0, or 1 depending on whether x is less than, equal to, or greater than y, respectively. Uses the total order implemented by isless.\n\nExamples\n\njulia> cmp(1, 2)\n-1\n\njulia> cmp(2, 1)\n1\n\njulia> cmp(2+im, 3-im)\nERROR: MethodError: no method matching isless(::Complex{Int64}, ::Complex{Int64})\n[...]\n\n\n\n\n\ncmp(<, x, y)\n\nReturn -1, 0, or 1 depending on whether x is less than, equal to, or greater than y, respectively. The first argument specifies a less-than comparison function to use.\n\n\n\n\n\ncmp(a::AbstractString, b::AbstractString) -> Int\n\nCompare two strings. Return 0 if both strings have the same length and the character at each index is the same in both strings. Return -1 if a is a prefix of b, or if a comes before b in alphabetical order. Return 1 if b is a prefix of a, or if b comes before a in alphabetical order (technically, lexicographical order by Unicode code points).\n\nExamples\n\njulia> cmp(\"abc\", \"abc\")\n0\n\njulia> cmp(\"ab\", \"abc\")\n-1\n\njulia> cmp(\"abc\", \"ab\")\n1\n\njulia> cmp(\"ab\", \"ac\")\n-1\n\njulia> cmp(\"ac\", \"ab\")\n1\n\njulia> cmp(\"α\", \"a\")\n1\n\njulia> cmp(\"b\", \"β\")\n-1\n\n\n\n\n\n","category":"function"},{"location":"base/math/#Base.:~","page":"数学相关","title":"Base.:~","text":"~(x)\n\nBitwise not.\n\nSee also: !, &, |.\n\nExamples\n\njulia> ~4\n-5\n\njulia> ~10\n-11\n\njulia> ~true\nfalse\n\n\n\n\n\n","category":"function"},{"location":"base/math/#Base.:&","page":"数学相关","title":"Base.:&","text":"x & y\n\nBitwise and. Implements three-valued logic, returning missing if one operand is missing and the other is true. Add parentheses for function application form: (&)(x, y).\n\nSee also: |, xor, &&.\n\nExamples\n\njulia> 4 & 10\n0\n\njulia> 4 & 12\n4\n\njulia> true & missing\nmissing\n\njulia> false & missing\nfalse\n\n\n\n\n\n","category":"function"},{"location":"base/math/#Base.:|","page":"数学相关","title":"Base.:|","text":"x | y\n\nBitwise or. Implements three-valued logic, returning missing if one operand is missing and the other is false.\n\nSee also: &, xor, ||.\n\nExamples\n\njulia> 4 | 10\n14\n\njulia> 4 | 1\n5\n\njulia> true | missing\ntrue\n\njulia> false | missing\nmissing\n\n\n\n\n\n","category":"function"},{"location":"base/math/#Base.xor","page":"数学相关","title":"Base.xor","text":"xor(x, y)\n⊻(x, y)\n\nBitwise exclusive or of x and y. Implements three-valued logic, returning missing if one of the arguments is missing.\n\nThe infix operation a ⊻ b is a synonym for xor(a,b), and ⊻ can be typed by tab-completing \\xor or \\veebar in the Julia REPL.\n\nExamples\n\njulia> xor(true, false)\ntrue\n\njulia> xor(true, true)\nfalse\n\njulia> xor(true, missing)\nmissing\n\njulia> false ⊻ false\nfalse\n\njulia> [true; true; false] .⊻ [true; false; false]\n3-element BitVector:\n 0\n 1\n 0\n\n\n\n\n\n","category":"function"},{"location":"base/math/#Base.nand","page":"数学相关","title":"Base.nand","text":"nand(x, y)\n⊼(x, y)\n\nBitwise nand (not and) of x and y. Implements three-valued logic, returning missing if one of the arguments is missing.\n\nThe infix operation a ⊼ b is a synonym for nand(a,b), and ⊼ can be typed by tab-completing \\nand or \\barwedge in the Julia REPL.\n\nExamples\n\njulia> nand(true, false)\ntrue\n\njulia> nand(true, true)\nfalse\n\njulia> nand(true, missing)\nmissing\n\njulia> false ⊼ false\ntrue\n\njulia> [true; true; false] .⊼ [true; false; false]\n3-element BitVector:\n 0\n 1\n 1\n\n\n\n\n\n","category":"function"},{"location":"base/math/#Base.nor","page":"数学相关","title":"Base.nor","text":"nor(x, y)\n⊽(x, y)\n\nBitwise nor (not or) of x and y. Implements three-valued logic, returning missing if one of the arguments is missing.\n\nThe infix operation a ⊽ b is a synonym for nor(a,b), and ⊽ can be typed by tab-completing \\nor or \\barvee in the Julia REPL.\n\nExamples\n\njulia> nor(true, false)\nfalse\n\njulia> nor(true, true)\nfalse\n\njulia> nor(true, missing)\nfalse\n\njulia> false ⊽ false\ntrue\n\njulia> [true; true; false] .⊽ [true; false; false]\n3-element BitVector:\n 0\n 0\n 1\n\n\n\n\n\n","category":"function"},{"location":"base/math/#Base.:!","page":"数学相关","title":"Base.:!","text":"!(x)\n\nBoolean not. Implements three-valued logic, returning missing if x is missing.\n\nSee also ~ for bitwise not.\n\nExamples\n\njulia> !true\nfalse\n\njulia> !false\ntrue\n\njulia> !missing\nmissing\n\njulia> .![true false true]\n1×3 BitMatrix:\n 0 1 0\n\n\n\n\n\n!f::Function\n\nPredicate function negation: when the argument of ! is a function, it returns a function which computes the boolean negation of f.\n\nSee also ∘.\n\nExamples\n\njulia> str = \"∀ ε > 0, ∃ δ > 0: |x-y| < δ ⇒ |f(x)-f(y)| < ε\"\n\"∀ ε > 0, ∃ δ > 0: |x-y| < δ ⇒ |f(x)-f(y)| < ε\"\n\njulia> filter(isletter, str)\n\"εδxyδfxfyε\"\n\njulia> filter(!isletter, str)\n\"∀ > 0, ∃ > 0: |-| < ⇒ |()-()| < \"\n\n\n\n\n\n","category":"function"},{"location":"base/math/#&&","page":"数学相关","title":"&&","text":"x && y\n\nShort-circuiting boolean AND.\n\nSee also &, the ternary operator ? :, and the manual section on control flow.\n\nExamples\n\njulia> x = 3;\n\njulia> x > 1 && x < 10 && x isa Int\ntrue\n\njulia> x < 0 && error(\"expected positive x\")\nfalse\n\n\n\n\n\n","category":"keyword"},{"location":"base/math/#||","page":"数学相关","title":"||","text":"x || y\n\nShort-circuiting boolean OR.\n\nSee also: |, xor, &&.\n\nExamples\n\njulia> pi < 3 || ℯ < 3\ntrue\n\njulia> false || true || println(\"neither is true!\")\ntrue\n\n\n\n\n\n","category":"keyword"},{"location":"base/math/#数学函数","page":"数学相关","title":"数学函数","text":"","category":"section"},{"location":"base/math/","page":"数学相关","title":"数学相关","text":"Base.isapprox\nBase.sin(::Number)\nBase.cos(::Number)\nBase.sincos(::Float64)\nBase.tan(::Number)\nBase.Math.sind\nBase.Math.cosd\nBase.Math.tand\nBase.Math.sincosd\nBase.Math.sinpi\nBase.Math.cospi\nBase.Math.sincospi\nBase.sinh(::Number)\nBase.cosh(::Number)\nBase.tanh(::Number)\nBase.asin(::Number)\nBase.acos(::Number)\nBase.atan(::Number)\nBase.Math.asind\nBase.Math.acosd\nBase.Math.atand\nBase.Math.sec(::Number)\nBase.Math.csc(::Number)\nBase.Math.cot(::Number)\nBase.Math.secd\nBase.Math.cscd\nBase.Math.cotd\nBase.Math.asec(::Number)\nBase.Math.acsc(::Number)\nBase.Math.acot(::Number)\nBase.Math.asecd\nBase.Math.acscd\nBase.Math.acotd\nBase.Math.sech(::Number)\nBase.Math.csch(::Number)\nBase.Math.coth(::Number)\nBase.asinh(::Number)\nBase.acosh(::Number)\nBase.atanh(::Number)\nBase.Math.asech(::Number)\nBase.Math.acsch(::Number)\nBase.Math.acoth(::Number)\nBase.Math.sinc\nBase.Math.cosc\nBase.Math.deg2rad\nBase.Math.rad2deg\nBase.Math.hypot\nBase.log(::Number)\nBase.log(::Number, ::Number)\nBase.log2\nBase.log10\nBase.log1p\nBase.Math.frexp\nBase.exp(::Float64)\nBase.exp2\nBase.exp10\nBase.Math.ldexp\nBase.Math.modf\nBase.expm1\nBase.round(::Type, ::Any)\nBase.Rounding.RoundingMode\nBase.Rounding.RoundNearest\nBase.Rounding.RoundNearestTiesAway\nBase.Rounding.RoundNearestTiesUp\nBase.Rounding.RoundToZero\nBase.Rounding.RoundFromZero\nBase.Rounding.RoundUp\nBase.Rounding.RoundDown\nBase.round(::Complex{<: AbstractFloat}, ::RoundingMode, ::RoundingMode)\nBase.ceil\nBase.floor\nBase.trunc\nBase.unsafe_trunc\nBase.min\nBase.max\nBase.minmax\nBase.Math.clamp\nBase.Math.clamp!\nBase.abs\nBase.Checked.checked_abs\nBase.Checked.checked_neg\nBase.Checked.checked_add\nBase.Checked.checked_sub\nBase.Checked.checked_mul\nBase.Checked.checked_div\nBase.Checked.checked_rem\nBase.Checked.checked_fld\nBase.Checked.checked_mod\nBase.Checked.checked_cld\nBase.Checked.add_with_overflow\nBase.Checked.sub_with_overflow\nBase.Checked.mul_with_overflow\nBase.abs2\nBase.copysign\nBase.sign\nBase.signbit\nBase.flipsign\nBase.sqrt(::Real)\nBase.isqrt\nBase.Math.cbrt\nBase.real(::Complex)\nBase.imag\nBase.reim\nBase.conj\nBase.angle\nBase.cis\nBase.cispi\nBase.binomial\nBase.factorial\nBase.gcd\nBase.lcm\nBase.gcdx\nBase.ispow2\nBase.nextpow\nBase.prevpow\nBase.nextprod\nBase.invmod\nBase.powermod\nBase.ndigits\nBase.add_sum\nBase.widemul\nBase.Math.evalpoly\nBase.Math.@evalpoly\nBase.FastMath.@fastmath","category":"page"},{"location":"base/math/#Base.isapprox","page":"数学相关","title":"Base.isapprox","text":"isapprox(x, y; atol::Real=0, rtol::Real=atol>0 ? 0 : √eps, nans::Bool=false[, norm::Function])\n\nInexact equality comparison. Two numbers compare equal if their relative distance or their absolute distance is within tolerance bounds: isapprox returns true if norm(x-y) <= max(atol, rtol*max(norm(x), norm(y))). The default atol is zero and the default rtol depends on the types of x and y. The keyword argument nans determines whether or not NaN values are considered equal (defaults to false).\n\nFor real or complex floating-point values, if an atol > 0 is not specified, rtol defaults to the square root of eps of the type of x or y, whichever is bigger (least precise). This corresponds to requiring equality of about half of the significant digits. Otherwise, e.g. for integer arguments or if an atol > 0 is supplied, rtol defaults to zero.\n\nThe norm keyword defaults to abs for numeric (x,y) and to LinearAlgebra.norm for arrays (where an alternative norm choice is sometimes useful). When x and y are arrays, if norm(x-y) is not finite (i.e. ±Inf or NaN), the comparison falls back to checking whether all elements of x and y are approximately equal component-wise.\n\nThe binary operator ≈ is equivalent to isapprox with the default arguments, and x ≉ y is equivalent to !isapprox(x,y).\n\nNote that x ≈ 0 (i.e., comparing to zero with the default tolerances) is equivalent to x == 0 since the default atol is 0. In such cases, you should either supply an appropriate atol (or use norm(x) ≤ atol) or rearrange your code (e.g. use x ≈ y rather than x - y ≈ 0). It is not possible to pick a nonzero atol automatically because it depends on the overall scaling (the \"units\") of your problem: for example, in x - y ≈ 0, atol=1e-9 is an absurdly small tolerance if x is the radius of the Earth in meters, but an absurdly large tolerance if x is the radius of a Hydrogen atom in meters.\n\ncompat: Julia 1.6\nPassing the norm keyword argument when comparing numeric (non-array) arguments requires Julia 1.6 or later.\n\nExamples\n\njulia> isapprox(0.1, 0.15; atol=0.05)\ntrue\n\njulia> isapprox(0.1, 0.15; rtol=0.34)\ntrue\n\njulia> isapprox(0.1, 0.15; rtol=0.33)\nfalse\n\njulia> 0.1 + 1e-10 ≈ 0.1\ntrue\n\njulia> 1e-10 ≈ 0\nfalse\n\njulia> isapprox(1e-10, 0, atol=1e-8)\ntrue\n\njulia> isapprox([10.0^9, 1.0], [10.0^9, 2.0]) # using `norm`\ntrue\n\n\n\n\n\nisapprox(x; kwargs...) / ≈(x; kwargs...)\n\nCreate a function that compares its argument to x using ≈, i.e. a function equivalent to y -> y ≈ x.\n\nThe keyword arguments supported here are the same as those in the 2-argument isapprox.\n\ncompat: Julia 1.5\nThis method requires Julia 1.5 or later.\n\n\n\n\n\n","category":"function"},{"location":"base/math/#Base.sin-Tuple{Number}","page":"数学相关","title":"Base.sin","text":"sin(x)\n\nCompute sine of x, where x is in radians.\n\nSee also [sind], [sinpi], [sincos], [cis].\n\n\n\n\n\n","category":"method"},{"location":"base/math/#Base.cos-Tuple{Number}","page":"数学相关","title":"Base.cos","text":"cos(x)\n\nCompute cosine of x, where x is in radians.\n\nSee also [cosd], [cospi], [sincos], [cis].\n\n\n\n\n\n","category":"method"},{"location":"base/math/#Base.Math.sincos-Tuple{Float64}","page":"数学相关","title":"Base.Math.sincos","text":"sincos(x)\n\nSimultaneously compute the sine and cosine of x, where x is in radians, returning a tuple (sine, cosine).\n\nSee also cis, sincospi, sincosd.\n\n\n\n\n\n","category":"method"},{"location":"base/math/#Base.tan-Tuple{Number}","page":"数学相关","title":"Base.tan","text":"tan(x)\n\nCompute tangent of x, where x is in radians.\n\n\n\n\n\n","category":"method"},{"location":"base/math/#Base.Math.sind","page":"数学相关","title":"Base.Math.sind","text":"sind(x)\n\nCompute sine of x, where x is in degrees. If x is a matrix, x needs to be a square matrix.\n\ncompat: Julia 1.7\nMatrix arguments require Julia 1.7 or later.\n\n\n\n\n\n","category":"function"},{"location":"base/math/#Base.Math.cosd","page":"数学相关","title":"Base.Math.cosd","text":"cosd(x)\n\nCompute cosine of x, where x is in degrees. If x is a matrix, x needs to be a square matrix.\n\ncompat: Julia 1.7\nMatrix arguments require Julia 1.7 or later.\n\n\n\n\n\n","category":"function"},{"location":"base/math/#Base.Math.tand","page":"数学相关","title":"Base.Math.tand","text":"tand(x)\n\nCompute tangent of x, where x is in degrees. If x is a matrix, x needs to be a square matrix.\n\ncompat: Julia 1.7\nMatrix arguments require Julia 1.7 or later.\n\n\n\n\n\n","category":"function"},{"location":"base/math/#Base.Math.sincosd","page":"数学相关","title":"Base.Math.sincosd","text":"sincosd(x)\n\nSimultaneously compute the sine and cosine of x, where x is in degrees.\n\ncompat: Julia 1.3\nThis function requires at least Julia 1.3.\n\n\n\n\n\n","category":"function"},{"location":"base/math/#Base.Math.sinpi","page":"数学相关","title":"Base.Math.sinpi","text":"sinpi(x)\n\nCompute sin(pi x) more accurately than sin(pi*x), especially for large x.\n\nSee also sind, cospi, sincospi.\n\n\n\n\n\n","category":"function"},{"location":"base/math/#Base.Math.cospi","page":"数学相关","title":"Base.Math.cospi","text":"cospi(x)\n\nCompute cos(pi x) more accurately than cos(pi*x), especially for large x.\n\n\n\n\n\n","category":"function"},{"location":"base/math/#Base.Math.sincospi","page":"数学相关","title":"Base.Math.sincospi","text":"sincospi(x)\n\nSimultaneously compute sinpi(x) and cospi(x) (the sine and cosine of π*x, where x is in radians), returning a tuple (sine, cosine).\n\ncompat: Julia 1.6\nThis function requires Julia 1.6 or later.\n\nSee also: cispi, sincosd, sinpi.\n\n\n\n\n\n","category":"function"},{"location":"base/math/#Base.sinh-Tuple{Number}","page":"数学相关","title":"Base.sinh","text":"sinh(x)\n\nCompute hyperbolic sine of x.\n\n\n\n\n\n","category":"method"},{"location":"base/math/#Base.cosh-Tuple{Number}","page":"数学相关","title":"Base.cosh","text":"cosh(x)\n\nCompute hyperbolic cosine of x.\n\n\n\n\n\n","category":"method"},{"location":"base/math/#Base.tanh-Tuple{Number}","page":"数学相关","title":"Base.tanh","text":"tanh(x)\n\nCompute hyperbolic tangent of x.\n\n\n\n\n\n","category":"method"},{"location":"base/math/#Base.asin-Tuple{Number}","page":"数学相关","title":"Base.asin","text":"asin(x)\n\nCompute the inverse sine of x, where the output is in radians.\n\n\n\n\n\n","category":"method"},{"location":"base/math/#Base.acos-Tuple{Number}","page":"数学相关","title":"Base.acos","text":"acos(x)\n\nCompute the inverse cosine of x, where the output is in radians\n\n\n\n\n\n","category":"method"},{"location":"base/math/#Base.atan-Tuple{Number}","page":"数学相关","title":"Base.atan","text":"atan(y)\natan(y, x)\n\nCompute the inverse tangent of y or y/x, respectively.\n\nFor one argument, this is the angle in radians between the positive x-axis and the point (1, y), returning a value in the interval -pi2 pi2.\n\nFor two arguments, this is the angle in radians between the positive x-axis and the point (x, y), returning a value in the interval -pi pi. This corresponds to a standard atan2 function. Note that by convention atan(0.0,x) is defined as pi and atan(-0.0,x) is defined as -pi when x < 0.\n\n\n\n\n\n","category":"method"},{"location":"base/math/#Base.Math.asind","page":"数学相关","title":"Base.Math.asind","text":"asind(x)\n\nCompute the inverse sine of x, where the output is in degrees. If x is a matrix, x needs to be a square matrix.\n\ncompat: Julia 1.7\nMatrix arguments require Julia 1.7 or later.\n\n\n\n\n\n","category":"function"},{"location":"base/math/#Base.Math.acosd","page":"数学相关","title":"Base.Math.acosd","text":"acosd(x)\n\nCompute the inverse cosine of x, where the output is in degrees. If x is a matrix, x needs to be a square matrix.\n\ncompat: Julia 1.7\nMatrix arguments require Julia 1.7 or later.\n\n\n\n\n\n","category":"function"},{"location":"base/math/#Base.Math.atand","page":"数学相关","title":"Base.Math.atand","text":"atand(y)\natand(y,x)\n\nCompute the inverse tangent of y or y/x, respectively, where the output is in degrees.\n\ncompat: Julia 1.7\nThe one-argument method supports square matrix arguments as of Julia 1.7.\n\n\n\n\n\n","category":"function"},{"location":"base/math/#Base.Math.sec-Tuple{Number}","page":"数学相关","title":"Base.Math.sec","text":"sec(x)\n\nCompute the secant of x, where x is in radians.\n\n\n\n\n\n","category":"method"},{"location":"base/math/#Base.Math.csc-Tuple{Number}","page":"数学相关","title":"Base.Math.csc","text":"csc(x)\n\nCompute the cosecant of x, where x is in radians.\n\n\n\n\n\n","category":"method"},{"location":"base/math/#Base.Math.cot-Tuple{Number}","page":"数学相关","title":"Base.Math.cot","text":"cot(x)\n\nCompute the cotangent of x, where x is in radians.\n\n\n\n\n\n","category":"method"},{"location":"base/math/#Base.Math.secd","page":"数学相关","title":"Base.Math.secd","text":"secd(x)\n\nCompute the secant of x, where x is in degrees.\n\n\n\n\n\n","category":"function"},{"location":"base/math/#Base.Math.cscd","page":"数学相关","title":"Base.Math.cscd","text":"cscd(x)\n\nCompute the cosecant of x, where x is in degrees.\n\n\n\n\n\n","category":"function"},{"location":"base/math/#Base.Math.cotd","page":"数学相关","title":"Base.Math.cotd","text":"cotd(x)\n\nCompute the cotangent of x, where x is in degrees.\n\n\n\n\n\n","category":"function"},{"location":"base/math/#Base.Math.asec-Tuple{Number}","page":"数学相关","title":"Base.Math.asec","text":"asec(x)\n\nCompute the inverse secant of x, where the output is in radians. \n\n\n\n\n\n","category":"method"},{"location":"base/math/#Base.Math.acsc-Tuple{Number}","page":"数学相关","title":"Base.Math.acsc","text":"acsc(x)\n\nCompute the inverse cosecant of x, where the output is in radians. \n\n\n\n\n\n","category":"method"},{"location":"base/math/#Base.Math.acot-Tuple{Number}","page":"数学相关","title":"Base.Math.acot","text":"acot(x)\n\nCompute the inverse cotangent of x, where the output is in radians. \n\n\n\n\n\n","category":"method"},{"location":"base/math/#Base.Math.asecd","page":"数学相关","title":"Base.Math.asecd","text":"asecd(x)\n\nCompute the inverse secant of x, where the output is in degrees. If x is a matrix, x needs to be a square matrix.\n\ncompat: Julia 1.7\nMatrix arguments require Julia 1.7 or later.\n\n\n\n\n\n","category":"function"},{"location":"base/math/#Base.Math.acscd","page":"数学相关","title":"Base.Math.acscd","text":"acscd(x)\n\nCompute the inverse cosecant of x, where the output is in degrees. If x is a matrix, x needs to be a square matrix.\n\ncompat: Julia 1.7\nMatrix arguments require Julia 1.7 or later.\n\n\n\n\n\n","category":"function"},{"location":"base/math/#Base.Math.acotd","page":"数学相关","title":"Base.Math.acotd","text":"acotd(x)\n\nCompute the inverse cotangent of x, where the output is in degrees. If x is a matrix, x needs to be a square matrix.\n\ncompat: Julia 1.7\nMatrix arguments require Julia 1.7 or later.\n\n\n\n\n\n","category":"function"},{"location":"base/math/#Base.Math.sech-Tuple{Number}","page":"数学相关","title":"Base.Math.sech","text":"sech(x)\n\nCompute the hyperbolic secant of x.\n\n\n\n\n\n","category":"method"},{"location":"base/math/#Base.Math.csch-Tuple{Number}","page":"数学相关","title":"Base.Math.csch","text":"csch(x)\n\nCompute the hyperbolic cosecant of x.\n\n\n\n\n\n","category":"method"},{"location":"base/math/#Base.Math.coth-Tuple{Number}","page":"数学相关","title":"Base.Math.coth","text":"coth(x)\n\nCompute the hyperbolic cotangent of x.\n\n\n\n\n\n","category":"method"},{"location":"base/math/#Base.asinh-Tuple{Number}","page":"数学相关","title":"Base.asinh","text":"asinh(x)\n\nCompute the inverse hyperbolic sine of x.\n\n\n\n\n\n","category":"method"},{"location":"base/math/#Base.acosh-Tuple{Number}","page":"数学相关","title":"Base.acosh","text":"acosh(x)\n\nCompute the inverse hyperbolic cosine of x.\n\n\n\n\n\n","category":"method"},{"location":"base/math/#Base.atanh-Tuple{Number}","page":"数学相关","title":"Base.atanh","text":"atanh(x)\n\nCompute the inverse hyperbolic tangent of x.\n\n\n\n\n\n","category":"method"},{"location":"base/math/#Base.Math.asech-Tuple{Number}","page":"数学相关","title":"Base.Math.asech","text":"asech(x)\n\nCompute the inverse hyperbolic secant of x. \n\n\n\n\n\n","category":"method"},{"location":"base/math/#Base.Math.acsch-Tuple{Number}","page":"数学相关","title":"Base.Math.acsch","text":"acsch(x)\n\nCompute the inverse hyperbolic cosecant of x. \n\n\n\n\n\n","category":"method"},{"location":"base/math/#Base.Math.acoth-Tuple{Number}","page":"数学相关","title":"Base.Math.acoth","text":"acoth(x)\n\nCompute the inverse hyperbolic cotangent of x. \n\n\n\n\n\n","category":"method"},{"location":"base/math/#Base.Math.sinc","page":"数学相关","title":"Base.Math.sinc","text":"sinc(x)\n\nCompute sin(pi x) (pi x) if x neq 0, and 1 if x = 0.\n\nSee also cosc, its derivative.\n\n\n\n\n\n","category":"function"},{"location":"base/math/#Base.Math.cosc","page":"数学相关","title":"Base.Math.cosc","text":"cosc(x)\n\nCompute cos(pi x) x - sin(pi x) (pi x^2) if x neq 0, and 0 if x = 0. This is the derivative of sinc(x).\n\n\n\n\n\n","category":"function"},{"location":"base/math/#Base.Math.deg2rad","page":"数学相关","title":"Base.Math.deg2rad","text":"deg2rad(x)\n\nConvert x from degrees to radians.\n\nSee also: rad2deg, sind.\n\nExamples\n\njulia> deg2rad(90)\n1.5707963267948966\n\n\n\n\n\n","category":"function"},{"location":"base/math/#Base.Math.rad2deg","page":"数学相关","title":"Base.Math.rad2deg","text":"rad2deg(x)\n\nConvert x from radians to degrees.\n\nExamples\n\njulia> rad2deg(pi)\n180.0\n\n\n\n\n\n","category":"function"},{"location":"base/math/#Base.Math.hypot","page":"数学相关","title":"Base.Math.hypot","text":"hypot(x, y)\n\nCompute the hypotenuse sqrtx^2+y^2 avoiding overflow and underflow.\n\nThis code is an implementation of the algorithm described in: An Improved Algorithm for hypot(a,b) by Carlos F. Borges The article is available online at ArXiv at the link https://arxiv.org/abs/1904.09481\n\nhypot(x...)\n\nCompute the hypotenuse sqrtsum x_i^2 avoiding overflow and underflow.\n\nSee also norm in the LinearAlgebra standard library.\n\nExamples\n\njulia> a = Int64(10)^10;\n\njulia> hypot(a, a)\n1.4142135623730951e10\n\njulia> √(a^2 + a^2) # a^2 overflows\nERROR: DomainError with -2.914184810805068e18:\nsqrt will only return a complex result if called with a complex argument. Try sqrt(Complex(x)).\nStacktrace:\n[...]\n\njulia> hypot(3, 4im)\n5.0\n\njulia> hypot(-5.7)\n5.7\n\njulia> hypot(3, 4im, 12.0)\n13.0\n\njulia> using LinearAlgebra\n\njulia> norm([a, a, a, a]) == hypot(a, a, a, a)\ntrue\n\n\n\n\n\n","category":"function"},{"location":"base/math/#Base.log-Tuple{Number}","page":"数学相关","title":"Base.log","text":"log(x)\n\nCompute the natural logarithm of x. Throws DomainError for negative Real arguments. Use complex negative arguments to obtain complex results.\n\nSee also [log1p], [log2], [log10].\n\nExamples\n\njulia> log(2)\n0.6931471805599453\n\njulia> log(-3)\nERROR: DomainError with -3.0:\nlog will only return a complex result if called with a complex argument. Try log(Complex(x)).\nStacktrace:\n [1] throw_complex_domainerror(::Symbol, ::Float64) at ./math.jl:31\n[...]\n\n\n\n\n\n","category":"method"},{"location":"base/math/#Base.log-Tuple{Number, Number}","page":"数学相关","title":"Base.log","text":"log(b,x)\n\nCompute the base b logarithm of x. Throws DomainError for negative Real arguments.\n\nExamples\n\njulia> log(4,8)\n1.5\n\njulia> log(4,2)\n0.5\n\njulia> log(-2, 3)\nERROR: DomainError with -2.0:\nlog will only return a complex result if called with a complex argument. Try log(Complex(x)).\nStacktrace:\n [1] throw_complex_domainerror(::Symbol, ::Float64) at ./math.jl:31\n[...]\n\njulia> log(2, -3)\nERROR: DomainError with -3.0:\nlog will only return a complex result if called with a complex argument. Try log(Complex(x)).\nStacktrace:\n [1] throw_complex_domainerror(::Symbol, ::Float64) at ./math.jl:31\n[...]\n\nnote: Note\nIf b is a power of 2 or 10, log2 or log10 should be used, as these will typically be faster and more accurate. For example,julia> log(100,1000000)\n2.9999999999999996\n\njulia> log10(1000000)/2\n3.0\n\n\n\n\n\n","category":"method"},{"location":"base/math/#Base.log2","page":"数学相关","title":"Base.log2","text":"log2(x)\n\nCompute the logarithm of x to base 2. Throws DomainError for negative Real arguments.\n\nSee also: exp2, ldexp, ispow2.\n\nExamples\n\njulia> log2(4)\n2.0\n\njulia> log2(10)\n3.321928094887362\n\njulia> log2(-2)\nERROR: DomainError with -2.0:\nlog2 will only return a complex result if called with a complex argument. Try log2(Complex(x)).\nStacktrace:\n [1] throw_complex_domainerror(f::Symbol, x::Float64) at ./math.jl:31\n[...]\n\n\n\n\n\n","category":"function"},{"location":"base/math/#Base.log10","page":"数学相关","title":"Base.log10","text":"log10(x)\n\nCompute the logarithm of x to base 10. Throws DomainError for negative Real arguments.\n\nExamples\n\njulia> log10(100)\n2.0\n\njulia> log10(2)\n0.3010299956639812\n\njulia> log10(-2)\nERROR: DomainError with -2.0:\nlog10 will only return a complex result if called with a complex argument. Try log10(Complex(x)).\nStacktrace:\n [1] throw_complex_domainerror(f::Symbol, x::Float64) at ./math.jl:31\n[...]\n\n\n\n\n\n","category":"function"},{"location":"base/math/#Base.log1p","page":"数学相关","title":"Base.log1p","text":"log1p(x)\n\nAccurate natural logarithm of 1+x. Throws DomainError for Real arguments less than -1.\n\nExamples\n\njulia> log1p(-0.5)\n-0.6931471805599453\n\njulia> log1p(0)\n0.0\n\njulia> log1p(-2)\nERROR: DomainError with -2.0:\nlog1p will only return a complex result if called with a complex argument. Try log1p(Complex(x)).\nStacktrace:\n [1] throw_complex_domainerror(::Symbol, ::Float64) at ./math.jl:31\n[...]\n\n\n\n\n\n","category":"function"},{"location":"base/math/#Base.Math.frexp","page":"数学相关","title":"Base.Math.frexp","text":"frexp(val)\n\nReturn (x,exp) such that x has a magnitude in the interval 12 1) or 0, and val is equal to x times 2^exp.\n\nExamples\n\njulia> frexp(12.8)\n(0.8, 4)\n\n\n\n\n\n","category":"function"},{"location":"base/math/#Base.exp-Tuple{Float64}","page":"数学相关","title":"Base.exp","text":"exp(x)\n\nCompute the natural base exponential of x, in other words ℯ^x.\n\nSee also exp2, exp10 and cis.\n\nExamples\n\njulia> exp(1.0)\n2.718281828459045\n\njulia> exp(im * pi) ≈ cis(pi)\ntrue\n\n\n\n\n\n","category":"method"},{"location":"base/math/#Base.exp2","page":"数学相关","title":"Base.exp2","text":"exp2(x)\n\nCompute the base 2 exponential of x, in other words 2^x.\n\nSee also ldexp, <<.\n\nExamples\n\njulia> exp2(5)\n32.0\n\njulia> 2^5\n32\n\njulia> exp2(63) > typemax(Int)\ntrue\n\n\n\n\n\n","category":"function"},{"location":"base/math/#Base.exp10","page":"数学相关","title":"Base.exp10","text":"exp10(x)\n\nCompute the base 10 exponential of x, in other words 10^x.\n\nExamples\n\njulia> exp10(2)\n100.0\n\njulia> 10^2\n100\n\n\n\n\n\n","category":"function"},{"location":"base/math/#Base.Math.ldexp","page":"数学相关","title":"Base.Math.ldexp","text":"ldexp(x, n)\n\nCompute x times 2^n.\n\nExamples\n\njulia> ldexp(5., 2)\n20.0\n\n\n\n\n\n","category":"function"},{"location":"base/math/#Base.Math.modf","page":"数学相关","title":"Base.Math.modf","text":"modf(x)\n\nReturn a tuple (fpart, ipart) of the fractional and integral parts of a number. Both parts have the same sign as the argument.\n\nExamples\n\njulia> modf(3.5)\n(0.5, 3.0)\n\njulia> modf(-3.5)\n(-0.5, -3.0)\n\n\n\n\n\n","category":"function"},{"location":"base/math/#Base.expm1","page":"数学相关","title":"Base.expm1","text":"expm1(x)\n\nAccurately compute e^x-1. It avoids the loss of precision involved in the direct evaluation of exp(x)-1 for small values of x.\n\nExamples\n\njulia> expm1(1e-16)\n1.0e-16\n\njulia> exp(1e-16) - 1\n0.0\n\n\n\n\n\n","category":"function"},{"location":"base/math/#Base.round-Tuple{Type, Any}","page":"数学相关","title":"Base.round","text":"round([T,] x, [r::RoundingMode])\nround(x, [r::RoundingMode]; digits::Integer=0, base = 10)\nround(x, [r::RoundingMode]; sigdigits::Integer, base = 10)\n\nRounds the number x.\n\nWithout keyword arguments, x is rounded to an integer value, returning a value of type T, or of the same type of x if no T is provided. An InexactError will be thrown if the value is not representable by T, similar to convert.\n\nIf the digits keyword argument is provided, it rounds to the specified number of digits after the decimal place (or before if negative), in base base.\n\nIf the sigdigits keyword argument is provided, it rounds to the specified number of significant digits, in base base.\n\nThe RoundingMode r controls the direction of the rounding; the default is RoundNearest, which rounds to the nearest integer, with ties (fractional values of 0.5) being rounded to the nearest even integer. Note that round may give incorrect results if the global rounding mode is changed (see rounding).\n\nExamples\n\njulia> round(1.7)\n2.0\n\njulia> round(Int, 1.7)\n2\n\njulia> round(1.5)\n2.0\n\njulia> round(2.5)\n2.0\n\njulia> round(pi; digits=2)\n3.14\n\njulia> round(pi; digits=3, base=2)\n3.125\n\njulia> round(123.456; sigdigits=2)\n120.0\n\njulia> round(357.913; sigdigits=4, base=2)\n352.0\n\nnote: Note\nRounding to specified digits in bases other than 2 can be inexact when operating on binary floating point numbers. For example, the Float64 value represented by 1.15 is actually less than 1.15, yet will be rounded to 1.2. For example:julia> x = 1.15\n1.15\n\njulia> @sprintf \"%.20f\" x\n\"1.14999999999999991118\"\n\njulia> x < 115//100\ntrue\n\njulia> round(x, digits=1)\n1.2\n\nExtensions\n\nTo extend round to new numeric types, it is typically sufficient to define Base.round(x::NewType, r::RoundingMode).\n\n\n\n\n\n","category":"method"},{"location":"base/math/#Base.Rounding.RoundingMode","page":"数学相关","title":"Base.Rounding.RoundingMode","text":"RoundingMode\n\nA type used for controlling the rounding mode of floating point operations (via rounding/setrounding functions), or as optional arguments for rounding to the nearest integer (via the round function).\n\nCurrently supported rounding modes are:\n\nRoundNearest (default)\nRoundNearestTiesAway\nRoundNearestTiesUp\nRoundToZero\nRoundFromZero (BigFloat only)\nRoundUp\nRoundDown\n\n\n\n\n\n","category":"type"},{"location":"base/math/#Base.Rounding.RoundNearest","page":"数学相关","title":"Base.Rounding.RoundNearest","text":"RoundNearest\n\nThe default rounding mode. Rounds to the nearest integer, with ties (fractional values of 0.5) being rounded to the nearest even integer.\n\n\n\n\n\n","category":"constant"},{"location":"base/math/#Base.Rounding.RoundNearestTiesAway","page":"数学相关","title":"Base.Rounding.RoundNearestTiesAway","text":"RoundNearestTiesAway\n\nRounds to nearest integer, with ties rounded away from zero (C/C++ round behaviour).\n\n\n\n\n\n","category":"constant"},{"location":"base/math/#Base.Rounding.RoundNearestTiesUp","page":"数学相关","title":"Base.Rounding.RoundNearestTiesUp","text":"RoundNearestTiesUp\n\nRounds to nearest integer, with ties rounded toward positive infinity (Java/JavaScript round behaviour).\n\n\n\n\n\n","category":"constant"},{"location":"base/math/#Base.Rounding.RoundToZero","page":"数学相关","title":"Base.Rounding.RoundToZero","text":"RoundToZero\n\nround using this rounding mode is an alias for trunc.\n\n\n\n\n\n","category":"constant"},{"location":"base/math/#Base.Rounding.RoundFromZero","page":"数学相关","title":"Base.Rounding.RoundFromZero","text":"RoundFromZero\n\nRounds away from zero. This rounding mode may only be used with T == BigFloat inputs to round.\n\nExamples\n\njulia> BigFloat(\"1.0000000000000001\", 5, RoundFromZero)\n1.06\n\n\n\n\n\n","category":"constant"},{"location":"base/math/#Base.Rounding.RoundUp","page":"数学相关","title":"Base.Rounding.RoundUp","text":"RoundUp\n\nround using this rounding mode is an alias for ceil.\n\n\n\n\n\n","category":"constant"},{"location":"base/math/#Base.Rounding.RoundDown","page":"数学相关","title":"Base.Rounding.RoundDown","text":"RoundDown\n\nround using this rounding mode is an alias for floor.\n\n\n\n\n\n","category":"constant"},{"location":"base/math/#Base.round-Tuple{Complex{<:AbstractFloat}, RoundingMode, RoundingMode}","page":"数学相关","title":"Base.round","text":"round(z::Complex[, RoundingModeReal, [RoundingModeImaginary]])\nround(z::Complex[, RoundingModeReal, [RoundingModeImaginary]]; digits=, base=10)\nround(z::Complex[, RoundingModeReal, [RoundingModeImaginary]]; sigdigits=, base=10)\n\nReturn the nearest integral value of the same type as the complex-valued z to z, breaking ties using the specified RoundingModes. The first RoundingMode is used for rounding the real components while the second is used for rounding the imaginary components.\n\nExample\n\njulia> round(3.14 + 4.5im)\n3.0 + 4.0im\n\n\n\n\n\n","category":"method"},{"location":"base/math/#Base.ceil","page":"数学相关","title":"Base.ceil","text":"ceil([T,] x)\nceil(x; digits::Integer= [, base = 10])\nceil(x; sigdigits::Integer= [, base = 10])\n\nceil(x) returns the nearest integral value of the same type as x that is greater than or equal to x.\n\nceil(T, x) converts the result to type T, throwing an InexactError if the value is not representable.\n\nKeywords digits, sigdigits and base work as for round.\n\n\n\n\n\n","category":"function"},{"location":"base/math/#Base.floor","page":"数学相关","title":"Base.floor","text":"floor([T,] x)\nfloor(x; digits::Integer= [, base = 10])\nfloor(x; sigdigits::Integer= [, base = 10])\n\nfloor(x) returns the nearest integral value of the same type as x that is less than or equal to x.\n\nfloor(T, x) converts the result to type T, throwing an InexactError if the value is not representable.\n\nKeywords digits, sigdigits and base work as for round.\n\n\n\n\n\n","category":"function"},{"location":"base/math/#Base.trunc","page":"数学相关","title":"Base.trunc","text":"trunc([T,] x)\ntrunc(x; digits::Integer= [, base = 10])\ntrunc(x; sigdigits::Integer= [, base = 10])\n\ntrunc(x) returns the nearest integral value of the same type as x whose absolute value is less than or equal to the absolute value of x.\n\ntrunc(T, x) converts the result to type T, throwing an InexactError if the value is not representable.\n\nKeywords digits, sigdigits and base work as for round.\n\nSee also: %, floor, unsigned, unsafe_trunc.\n\nExamples\n\njulia> trunc(2.22)\n2.0\n\njulia> trunc(-2.22, digits=1)\n-2.2\n\njulia> trunc(Int, -2.22)\n-2\n\n\n\n\n\n","category":"function"},{"location":"base/math/#Base.unsafe_trunc","page":"数学相关","title":"Base.unsafe_trunc","text":"unsafe_trunc(T, x)\n\nReturn the nearest integral value of type T whose absolute value is less than or equal to the absolute value of x. If the value is not representable by T, an arbitrary value will be returned. See also trunc.\n\nExamples\n\njulia> unsafe_trunc(Int, -2.2)\n-2\n\njulia> unsafe_trunc(Int, NaN)\n-9223372036854775808\n\n\n\n\n\n","category":"function"},{"location":"base/math/#Base.min","page":"数学相关","title":"Base.min","text":"min(x, y, ...)\n\nReturn the minimum of the arguments (with respect to isless). See also the minimum function to take the minimum element from a collection.\n\nExamples\n\njulia> min(2, 5, 1)\n1\n\n\n\n\n\n","category":"function"},{"location":"base/math/#Base.max","page":"数学相关","title":"Base.max","text":"max(x, y, ...)\n\nReturn the maximum of the arguments (with respect to isless). See also the maximum function to take the maximum element from a collection.\n\nExamples\n\njulia> max(2, 5, 1)\n5\n\n\n\n\n\n","category":"function"},{"location":"base/math/#Base.minmax","page":"数学相关","title":"Base.minmax","text":"minmax(x, y)\n\nReturn (min(x,y), max(x,y)).\n\nSee also extrema that returns (minimum(x), maximum(x)).\n\nExamples\n\njulia> minmax('c','b')\n('b', 'c')\n\n\n\n\n\n","category":"function"},{"location":"base/math/#Base.Math.clamp","page":"数学相关","title":"Base.Math.clamp","text":"clamp(x, lo, hi)\n\nReturn x if lo <= x <= hi. If x > hi, return hi. If x < lo, return lo. Arguments are promoted to a common type.\n\nSee also clamp!, min, max.\n\ncompat: Julia 1.3\nmissing as the first argument requires at least Julia 1.3.\n\nExamples\n\njulia> clamp.([pi, 1.0, big(10)], 2.0, 9.0)\n3-element Vector{BigFloat}:\n 3.141592653589793238462643383279502884197169399375105820974944592307816406286198\n 2.0\n 9.0\n\njulia> clamp.([11, 8, 5], 10, 6) # an example where lo > hi\n3-element Vector{Int64}:\n 6\n 6\n 10\n\n\n\n\n\nclamp(x, T)::T\n\nClamp x between typemin(T) and typemax(T) and convert the result to type T.\n\nSee also trunc.\n\nExamples\n\njulia> clamp(200, Int8)\n127\n\njulia> clamp(-200, Int8)\n-128\n\njulia> trunc(Int, 4pi^2)\n39\n\n\n\n\n\nclamp(x::Integer, r::AbstractUnitRange)\n\nClamp x to lie within range r.\n\ncompat: Julia 1.6\nThis method requires at least Julia 1.6.\n\n\n\n\n\n","category":"function"},{"location":"base/math/#Base.Math.clamp!","page":"数学相关","title":"Base.Math.clamp!","text":"clamp!(array::AbstractArray, lo, hi)\n\nRestrict values in array to the specified range, in-place. See also clamp.\n\ncompat: Julia 1.3\nmissing entries in array require at least Julia 1.3.\n\nExamples\n\njulia> row = collect(-4:4)';\n\njulia> clamp!(row, 0, Inf)\n1×9 adjoint(::Vector{Int64}) with eltype Int64:\n 0 0 0 0 0 1 2 3 4\n\njulia> clamp.((-4:4)', 0, Inf)\n1×9 Matrix{Float64}:\n 0.0 0.0 0.0 0.0 0.0 1.0 2.0 3.0 4.0\n\n\n\n\n\n","category":"function"},{"location":"base/math/#Base.abs","page":"数学相关","title":"Base.abs","text":"abs(x)\n\nThe absolute value of x.\n\nWhen abs is applied to signed integers, overflow may occur, resulting in the return of a negative value. This overflow occurs only when abs is applied to the minimum representable value of a signed integer. That is, when x == typemin(typeof(x)), abs(x) == x < 0, not -x as might be expected.\n\nSee also: abs2, unsigned, sign.\n\nExamples\n\njulia> abs(-3)\n3\n\njulia> abs(1 + im)\n1.4142135623730951\n\njulia> abs(typemin(Int64))\n-9223372036854775808\n\n\n\n\n\n","category":"function"},{"location":"base/math/#Base.Checked.checked_abs","page":"数学相关","title":"Base.Checked.checked_abs","text":"Base.checked_abs(x)\n\nCalculates abs(x), checking for overflow errors where applicable. For example, standard two's complement signed integers (e.g. Int) cannot represent abs(typemin(Int)), thus leading to an overflow.\n\nThe overflow protection may impose a perceptible performance penalty.\n\n\n\n\n\n","category":"function"},{"location":"base/math/#Base.Checked.checked_neg","page":"数学相关","title":"Base.Checked.checked_neg","text":"Base.checked_neg(x)\n\nCalculates -x, checking for overflow errors where applicable. For example, standard two's complement signed integers (e.g. Int) cannot represent -typemin(Int), thus leading to an overflow.\n\nThe overflow protection may impose a perceptible performance penalty.\n\n\n\n\n\n","category":"function"},{"location":"base/math/#Base.Checked.checked_add","page":"数学相关","title":"Base.Checked.checked_add","text":"Base.checked_add(x, y)\n\nCalculates x+y, checking for overflow errors where applicable.\n\nThe overflow protection may impose a perceptible performance penalty.\n\n\n\n\n\n","category":"function"},{"location":"base/math/#Base.Checked.checked_sub","page":"数学相关","title":"Base.Checked.checked_sub","text":"Base.checked_sub(x, y)\n\nCalculates x-y, checking for overflow errors where applicable.\n\nThe overflow protection may impose a perceptible performance penalty.\n\n\n\n\n\n","category":"function"},{"location":"base/math/#Base.Checked.checked_mul","page":"数学相关","title":"Base.Checked.checked_mul","text":"Base.checked_mul(x, y)\n\nCalculates x*y, checking for overflow errors where applicable.\n\nThe overflow protection may impose a perceptible performance penalty.\n\n\n\n\n\n","category":"function"},{"location":"base/math/#Base.Checked.checked_div","page":"数学相关","title":"Base.Checked.checked_div","text":"Base.checked_div(x, y)\n\nCalculates div(x,y), checking for overflow errors where applicable.\n\nThe overflow protection may impose a perceptible performance penalty.\n\n\n\n\n\n","category":"function"},{"location":"base/math/#Base.Checked.checked_rem","page":"数学相关","title":"Base.Checked.checked_rem","text":"Base.checked_rem(x, y)\n\nCalculates x%y, checking for overflow errors where applicable.\n\nThe overflow protection may impose a perceptible performance penalty.\n\n\n\n\n\n","category":"function"},{"location":"base/math/#Base.Checked.checked_fld","page":"数学相关","title":"Base.Checked.checked_fld","text":"Base.checked_fld(x, y)\n\nCalculates fld(x,y), checking for overflow errors where applicable.\n\nThe overflow protection may impose a perceptible performance penalty.\n\n\n\n\n\n","category":"function"},{"location":"base/math/#Base.Checked.checked_mod","page":"数学相关","title":"Base.Checked.checked_mod","text":"Base.checked_mod(x, y)\n\nCalculates mod(x,y), checking for overflow errors where applicable.\n\nThe overflow protection may impose a perceptible performance penalty.\n\n\n\n\n\n","category":"function"},{"location":"base/math/#Base.Checked.checked_cld","page":"数学相关","title":"Base.Checked.checked_cld","text":"Base.checked_cld(x, y)\n\nCalculates cld(x,y), checking for overflow errors where applicable.\n\nThe overflow protection may impose a perceptible performance penalty.\n\n\n\n\n\n","category":"function"},{"location":"base/math/#Base.Checked.add_with_overflow","page":"数学相关","title":"Base.Checked.add_with_overflow","text":"Base.add_with_overflow(x, y) -> (r, f)\n\nCalculates r = x+y, with the flag f indicating whether overflow has occurred.\n\n\n\n\n\n","category":"function"},{"location":"base/math/#Base.Checked.sub_with_overflow","page":"数学相关","title":"Base.Checked.sub_with_overflow","text":"Base.sub_with_overflow(x, y) -> (r, f)\n\nCalculates r = x-y, with the flag f indicating whether overflow has occurred.\n\n\n\n\n\n","category":"function"},{"location":"base/math/#Base.Checked.mul_with_overflow","page":"数学相关","title":"Base.Checked.mul_with_overflow","text":"Base.mul_with_overflow(x, y) -> (r, f)\n\nCalculates r = x*y, with the flag f indicating whether overflow has occurred.\n\n\n\n\n\n","category":"function"},{"location":"base/math/#Base.abs2","page":"数学相关","title":"Base.abs2","text":"abs2(x)\n\nSquared absolute value of x.\n\nExamples\n\njulia> abs2(-3)\n9\n\n\n\n\n\n","category":"function"},{"location":"base/math/#Base.copysign","page":"数学相关","title":"Base.copysign","text":"copysign(x, y) -> z\n\nReturn z which has the magnitude of x and the same sign as y.\n\nExamples\n\njulia> copysign(1, -2)\n-1\n\njulia> copysign(-1, 2)\n1\n\n\n\n\n\n","category":"function"},{"location":"base/math/#Base.sign","page":"数学相关","title":"Base.sign","text":"sign(x)\n\nReturn zero if x==0 and xx otherwise (i.e., ±1 for real x).\n\nSee also signbit, zero, copysign, flipsign.\n\nExamples\n\njulia> sign(-4.0)\n-1.0\n\njulia> sign(99)\n1\n\njulia> sign(-0.0)\n-0.0\n\njulia> sign(0 + im)\n0.0 + 1.0im\n\n\n\n\n\n","category":"function"},{"location":"base/math/#Base.signbit","page":"数学相关","title":"Base.signbit","text":"signbit(x)\n\nReturns true if the value of the sign of x is negative, otherwise false.\n\nSee also sign and copysign.\n\nExamples\n\njulia> signbit(-4)\ntrue\n\njulia> signbit(5)\nfalse\n\njulia> signbit(5.5)\nfalse\n\njulia> signbit(-4.1)\ntrue\n\n\n\n\n\n","category":"function"},{"location":"base/math/#Base.flipsign","page":"数学相关","title":"Base.flipsign","text":"flipsign(x, y)\n\nReturn x with its sign flipped if y is negative. For example abs(x) = flipsign(x,x).\n\nExamples\n\njulia> flipsign(5, 3)\n5\n\njulia> flipsign(5, -3)\n-5\n\n\n\n\n\n","category":"function"},{"location":"base/math/#Base.sqrt-Tuple{Real}","page":"数学相关","title":"Base.sqrt","text":"sqrt(x)\n\nReturn sqrtx. Throws DomainError for negative Real arguments. Use complex negative arguments instead. The prefix operator √ is equivalent to sqrt.\n\nSee also: hypot.\n\nExamples\n\njulia> sqrt(big(81))\n9.0\n\njulia> sqrt(big(-81))\nERROR: DomainError with -81.0:\nNaN result for non-NaN input.\nStacktrace:\n [1] sqrt(::BigFloat) at ./mpfr.jl:501\n[...]\n\njulia> sqrt(big(complex(-81)))\n0.0 + 9.0im\n\njulia> .√(1:4)\n4-element Vector{Float64}:\n 1.0\n 1.4142135623730951\n 1.7320508075688772\n 2.0\n\n\n\n\n\n","category":"method"},{"location":"base/math/#Base.isqrt","page":"数学相关","title":"Base.isqrt","text":"isqrt(n::Integer)\n\nInteger square root: the largest integer m such that m*m <= n.\n\njulia> isqrt(5)\n2\n\n\n\n\n\n","category":"function"},{"location":"base/math/#Base.Math.cbrt","page":"数学相关","title":"Base.Math.cbrt","text":"cbrt(x::Real)\n\nReturn the cube root of x, i.e. x^13. Negative values are accepted (returning the negative real root when x 0).\n\nThe prefix operator ∛ is equivalent to cbrt.\n\nExamples\n\njulia> cbrt(big(27))\n3.0\n\njulia> cbrt(big(-27))\n-3.0\n\n\n\n\n\n","category":"function"},{"location":"base/math/#Base.real-Tuple{Complex}","page":"数学相关","title":"Base.real","text":"real(z)\n\nReturn the real part of the complex number z.\n\nSee also: imag, reim, complex, isreal, Real.\n\nExamples\n\njulia> real(1 + 3im)\n1\n\n\n\n\n\n","category":"method"},{"location":"base/math/#Base.imag","page":"数学相关","title":"Base.imag","text":"imag(z)\n\nReturn the imaginary part of the complex number z.\n\nSee also: conj, reim, adjoint, angle.\n\nExamples\n\njulia> imag(1 + 3im)\n3\n\n\n\n\n\nimag(A::AbstractArray)\n\nReturn an array containing the imaginary part of each entry in array A.\n\nEquivalent to imag.(A), except that when A has zero dimensions, a 0-dimensional array is returned (rather than a scalar).\n\nExamples\n\njulia> imag([1, 2im, 3 + 4im])\n3-element Vector{Int64}:\n 0\n 2\n 4\n\njulia> imag(fill(2 - im))\n0-dimensional Array{Int64, 0}:\n-1\n\n\n\n\n\n","category":"function"},{"location":"base/math/#Base.reim","page":"数学相关","title":"Base.reim","text":"reim(z)\n\nReturn a tuple of the real and imaginary parts of the complex number z.\n\nExamples\n\njulia> reim(1 + 3im)\n(1, 3)\n\n\n\n\n\nreim(A::AbstractArray)\n\nReturn a tuple of two arrays containing respectively the real and the imaginary part of each entry in A.\n\nEquivalent to (real.(A), imag.(A)), except that when eltype(A) <: Real A is returned without copying to represent the real part, and that when A has zero dimensions, a 0-dimensional array is returned (rather than a scalar).\n\nExamples\n\njulia> reim([1, 2im, 3 + 4im])\n([1, 0, 3], [0, 2, 4])\n\njulia> reim(fill(2 - im))\n(fill(2), fill(-1))\n\n\n\n\n\n","category":"function"},{"location":"base/math/#Base.conj","page":"数学相关","title":"Base.conj","text":"conj(z)\n\nCompute the complex conjugate of a complex number z.\n\nSee also: angle, adjoint.\n\nExamples\n\njulia> conj(1 + 3im)\n1 - 3im\n\n\n\n\n\nconj(A::AbstractArray)\n\nReturn an array containing the complex conjugate of each entry in array A.\n\nEquivalent to conj.(A), except that when eltype(A) <: Real A is returned without copying, and that when A has zero dimensions, a 0-dimensional array is returned (rather than a scalar).\n\nExamples\n\njulia> conj([1, 2im, 3 + 4im])\n3-element Vector{Complex{Int64}}:\n 1 + 0im\n 0 - 2im\n 3 - 4im\n\njulia> conj(fill(2 - im))\n0-dimensional Array{Complex{Int64}, 0}:\n2 + 1im\n\n\n\n\n\n","category":"function"},{"location":"base/math/#Base.angle","page":"数学相关","title":"Base.angle","text":"angle(z)\n\nCompute the phase angle in radians of a complex number z.\n\nSee also: atan, cis.\n\nExamples\n\njulia> rad2deg(angle(1 + im))\n45.0\n\njulia> rad2deg(angle(1 - im))\n-45.0\n\njulia> rad2deg(angle(-1 - im))\n-135.0\n\n\n\n\n\n","category":"function"},{"location":"base/math/#Base.cis","page":"数学相关","title":"Base.cis","text":"cis(x)\n\nMore efficient method for exp(im*x) by using Euler's formula: cos(x) + i sin(x) = exp(i x).\n\nSee also cispi, sincos, exp, angle.\n\nExamples\n\njulia> cis(π) ≈ -1\ntrue\n\n\n\n\n\n","category":"function"},{"location":"base/math/#Base.cispi","page":"数学相关","title":"Base.cispi","text":"cispi(x)\n\nMore accurate method for cis(pi*x) (especially for large x).\n\nSee also cis, sincospi, exp, angle.\n\nExamples\n\njulia> cispi(10000)\n1.0 + 0.0im\n\njulia> cispi(0.25 + 1im)\n0.030556854645952924 + 0.030556854645952924im\n\ncompat: Julia 1.6\nThis function requires Julia 1.6 or later.\n\n\n\n\n\n","category":"function"},{"location":"base/math/#Base.binomial","page":"数学相关","title":"Base.binomial","text":"binomial(n::Integer, k::Integer)\n\nThe binomial coefficient binomnk, being the coefficient of the kth term in the polynomial expansion of (1+x)^n.\n\nIf n is non-negative, then it is the number of ways to choose k out of n items:\n\nbinomnk = fracnk (n-k)\n\nwhere n is the factorial function.\n\nIf n is negative, then it is defined in terms of the identity\n\nbinomnk = (-1)^k binomk-n-1k\n\nSee also factorial.\n\nExamples\n\njulia> binomial(5, 3)\n10\n\njulia> factorial(5) ÷ (factorial(5-3) * factorial(3))\n10\n\njulia> binomial(-5, 3)\n-35\n\nExternal links\n\nBinomial coefficient on Wikipedia.\n\n\n\n\n\n","category":"function"},{"location":"base/math/#Base.factorial","page":"数学相关","title":"Base.factorial","text":"factorial(n::Integer)\n\nFactorial of n. If n is an Integer, the factorial is computed as an integer (promoted to at least 64 bits). Note that this may overflow if n is not small, but you can use factorial(big(n)) to compute the result exactly in arbitrary precision.\n\nSee also binomial.\n\nExamples\n\njulia> factorial(6)\n720\n\njulia> factorial(21)\nERROR: OverflowError: 21 is too large to look up in the table; consider using `factorial(big(21))` instead\nStacktrace:\n[...]\n\njulia> factorial(big(21))\n51090942171709440000\n\nExternal links\n\nFactorial on Wikipedia.\n\n\n\n\n\n","category":"function"},{"location":"base/math/#Base.gcd","page":"数学相关","title":"Base.gcd","text":"gcd(x, y...)\n\nGreatest common (positive) divisor (or zero if all arguments are zero). The arguments may be integer and rational numbers.\n\ncompat: Julia 1.4\nRational arguments require Julia 1.4 or later.\n\nExamples\n\njulia> gcd(6, 9)\n3\n\njulia> gcd(6, -9)\n3\n\njulia> gcd(6, 0)\n6\n\njulia> gcd(0, 0)\n0\n\njulia> gcd(1//3, 2//3)\n1//3\n\njulia> gcd(1//3, -2//3)\n1//3\n\njulia> gcd(1//3, 2)\n1//3\n\njulia> gcd(0, 0, 10, 15)\n5\n\n\n\n\n\n","category":"function"},{"location":"base/math/#Base.lcm","page":"数学相关","title":"Base.lcm","text":"lcm(x, y...)\n\nLeast common (positive) multiple (or zero if any argument is zero). The arguments may be integer and rational numbers.\n\ncompat: Julia 1.4\nRational arguments require Julia 1.4 or later.\n\nExamples\n\njulia> lcm(2, 3)\n6\n\njulia> lcm(-2, 3)\n6\n\njulia> lcm(0, 3)\n0\n\njulia> lcm(0, 0)\n0\n\njulia> lcm(1//3, 2//3)\n2//3\n\njulia> lcm(1//3, -2//3)\n2//3\n\njulia> lcm(1//3, 2)\n2//1\n\njulia> lcm(1, 3, 5, 7)\n105\n\n\n\n\n\n","category":"function"},{"location":"base/math/#Base.gcdx","page":"数学相关","title":"Base.gcdx","text":"gcdx(a, b)\n\nComputes the greatest common (positive) divisor of a and b and their Bézout coefficients, i.e. the integer coefficients u and v that satisfy ua+vb = d = gcd(a b). gcdx(a b) returns (d u v).\n\nThe arguments may be integer and rational numbers.\n\ncompat: Julia 1.4\nRational arguments require Julia 1.4 or later.\n\nExamples\n\njulia> gcdx(12, 42)\n(6, -3, 1)\n\njulia> gcdx(240, 46)\n(2, -9, 47)\n\nnote: Note\nBézout coefficients are not uniquely defined. gcdx returns the minimal Bézout coefficients that are computed by the extended Euclidean algorithm. (Ref: D. Knuth, TAoCP, 2/e, p. 325, Algorithm X.) For signed integers, these coefficients u and v are minimal in the sense that u yd and v xd. Furthermore, the signs of u and v are chosen so that d is positive. For unsigned integers, the coefficients u and v might be near their typemax, and the identity then holds only via the unsigned integers' modulo arithmetic.\n\n\n\n\n\n","category":"function"},{"location":"base/math/#Base.ispow2","page":"数学相关","title":"Base.ispow2","text":"ispow2(n::Number) -> Bool\n\nTest whether n is an integer power of two.\n\nSee also count_ones, prevpow, nextpow.\n\nExamples\n\njulia> ispow2(4)\ntrue\n\njulia> ispow2(5)\nfalse\n\njulia> ispow2(4.5)\nfalse\n\njulia> ispow2(0.25)\ntrue\n\njulia> ispow2(1//8)\ntrue\n\ncompat: Julia 1.6\nSupport for non-Integer arguments was added in Julia 1.6.\n\n\n\n\n\n","category":"function"},{"location":"base/math/#Base.nextpow","page":"数学相关","title":"Base.nextpow","text":"nextpow(a, x)\n\nThe smallest a^n not less than x, where n is a non-negative integer. a must be greater than 1, and x must be greater than 0.\n\nSee also prevpow.\n\nExamples\n\njulia> nextpow(2, 7)\n8\n\njulia> nextpow(2, 9)\n16\n\njulia> nextpow(5, 20)\n25\n\njulia> nextpow(4, 16)\n16\n\n\n\n\n\n","category":"function"},{"location":"base/math/#Base.prevpow","page":"数学相关","title":"Base.prevpow","text":"prevpow(a, x)\n\nThe largest a^n not greater than x, where n is a non-negative integer. a must be greater than 1, and x must not be less than 1.\n\nSee also nextpow, isqrt.\n\nExamples\n\njulia> prevpow(2, 7)\n4\n\njulia> prevpow(2, 9)\n8\n\njulia> prevpow(5, 20)\n5\n\njulia> prevpow(4, 16)\n16\n\n\n\n\n\n","category":"function"},{"location":"base/math/#Base.nextprod","page":"数学相关","title":"Base.nextprod","text":"nextprod(factors::Union{Tuple,AbstractVector}, n)\n\nNext integer greater than or equal to n that can be written as prod k_i^p_i for integers p_1, p_2, etcetera, for factors k_i in factors.\n\nExamples\n\njulia> nextprod((2, 3), 105)\n108\n\njulia> 2^2 * 3^3\n108\n\ncompat: Julia 1.6\nThe method that accepts a tuple requires Julia 1.6 or later.\n\n\n\n\n\n","category":"function"},{"location":"base/math/#Base.invmod","page":"数学相关","title":"Base.invmod","text":"invmod(n, m)\n\nTake the inverse of n modulo m: y such that n y = 1 pmod m, and div(ym) = 0. This will throw an error if m = 0, or if gcd(nm) neq 1.\n\nExamples\n\njulia> invmod(2, 5)\n3\n\njulia> invmod(2, 3)\n2\n\njulia> invmod(5, 6)\n5\n\n\n\n\n\n","category":"function"},{"location":"base/math/#Base.powermod","page":"数学相关","title":"Base.powermod","text":"powermod(x::Integer, p::Integer, m)\n\nCompute x^p pmod m.\n\nExamples\n\njulia> powermod(2, 6, 5)\n4\n\njulia> mod(2^6, 5)\n4\n\njulia> powermod(5, 2, 20)\n5\n\njulia> powermod(5, 2, 19)\n6\n\njulia> powermod(5, 3, 19)\n11\n\n\n\n\n\n","category":"function"},{"location":"base/math/#Base.ndigits","page":"数学相关","title":"Base.ndigits","text":"ndigits(n::Integer; base::Integer=10, pad::Integer=1)\n\nCompute the number of digits in integer n written in base base (base must not be in [-1, 0, 1]), optionally padded with zeros to a specified size (the result will never be less than pad).\n\nSee also digits, count_ones.\n\nExamples\n\njulia> ndigits(12345)\n5\n\njulia> ndigits(1022, base=16)\n3\n\njulia> string(1022, base=16)\n\"3fe\"\n\njulia> ndigits(123, pad=5)\n5\n\njulia> ndigits(-123)\n3\n\n\n\n\n\n","category":"function"},{"location":"base/math/#Base.add_sum","page":"数学相关","title":"Base.add_sum","text":"Base.add_sum(x, y)\n\nThe reduction operator used in sum. The main difference from + is that small integers are promoted to Int/UInt.\n\n\n\n\n\n","category":"function"},{"location":"base/math/#Base.widemul","page":"数学相关","title":"Base.widemul","text":"widemul(x, y)\n\nMultiply x and y, giving the result as a larger type.\n\nSee also promote, Base.add_sum.\n\nExamples\n\njulia> widemul(Float32(3.0), 4.0) isa BigFloat\ntrue\n\njulia> typemax(Int8) * typemax(Int8)\n1\n\njulia> widemul(typemax(Int8), typemax(Int8)) # == 127^2\n16129\n\n\n\n\n\n","category":"function"},{"location":"base/math/#Base.Math.evalpoly","page":"数学相关","title":"Base.Math.evalpoly","text":"evalpoly(x, p)\n\nEvaluate the polynomial sum_k x^k-1 pk for the coefficients p[1], p[2], ...; that is, the coefficients are given in ascending order by power of x. Loops are unrolled at compile time if the number of coefficients is statically known, i.e. when p is a Tuple. This function generates efficient code using Horner's method if x is real, or using a Goertzel-like [DK62] algorithm if x is complex.\n\n[DK62]: Donald Knuth, Art of Computer Programming, Volume 2: Seminumerical Algorithms, Sec. 4.6.4.\n\ncompat: Julia 1.4\nThis function requires Julia 1.4 or later.\n\nExample\n\njulia> evalpoly(2, (1, 2, 3))\n17\n\n\n\n\n\n","category":"function"},{"location":"base/math/#Base.Math.@evalpoly","page":"数学相关","title":"Base.Math.@evalpoly","text":"@evalpoly(z, c...)\n\nEvaluate the polynomial sum_k z^k-1 ck for the coefficients c[1], c[2], ...; that is, the coefficients are given in ascending order by power of z. This macro expands to efficient inline code that uses either Horner's method or, for complex z, a more efficient Goertzel-like algorithm.\n\nSee also evalpoly.\n\nExamples\n\njulia> @evalpoly(3, 1, 0, 1)\n10\n\njulia> @evalpoly(2, 1, 0, 1)\n5\n\njulia> @evalpoly(2, 1, 1, 1)\n7\n\n\n\n\n\n","category":"macro"},{"location":"base/math/#Base.FastMath.@fastmath","page":"数学相关","title":"Base.FastMath.@fastmath","text":"@fastmath expr\n\nExecute a transformed version of the expression, which calls functions that may violate strict IEEE semantics. This allows the fastest possible operation, but results are undefined – be careful when doing this, as it may change numerical results.\n\nThis sets the LLVM Fast-Math flags, and corresponds to the -ffast-math option in clang. See the notes on performance annotations for more details.\n\nExamples\n\njulia> @fastmath 1+2\n3\n\njulia> @fastmath(sin(3))\n0.1411200080598672\n\n\n\n\n\n","category":"macro"},{"location":"base/math/#自定义二元运算符","page":"数学相关","title":"自定义二元运算符","text":"","category":"section"},{"location":"base/math/","page":"数学相关","title":"数学相关","text":"某些 unicode 字符可用于定义新的支持中缀表示法的二元运算符。 例如, ⊗(x,y) = kron(x,y) 定义 ⊗ (otimes) 为 Kronecker 积, 并且可以通过中缀语法将它作为一个二元运算符调用: C = A ⊗ B 也可以使用常用的前缀语法 C = ⊗(A,B)。","category":"page"},{"location":"base/math/","page":"数学相关","title":"数学相关","text":"其他支持这种扩展的字符包括 \\odot ⊙ 和 \\oplus ⊕","category":"page"},{"location":"base/math/","page":"数学相关","title":"数学相关","text":"The complete list is in the parser code: https://github.com/JuliaLang/julia/blob/master/src/julia-parser.scm","category":"page"},{"location":"base/math/","page":"数学相关","title":"数学相关","text":"像 * 一样解析的包括(按优先级排列) * / ÷ % & ⋅ ∘ × |\\\\| ∩ ∧ ⊗ ⊘ ⊙ ⊚ ⊛ ⊠ ⊡ ⊓ ∗ ∙ ∤ ⅋ ≀ ⊼ ⋄ ⋆ ⋇ ⋉ ⋊ ⋋ ⋌ ⋏ ⋒ ⟑ ⦸ ⦼ ⦾ ⦿ ⧶ ⧷ ⨇ ⨰ ⨱ ⨲ ⨳ ⨴ ⨵ ⨶ ⨷ ⨸ ⨻ ⨼ ⨽ ⩀ ⩃ ⩄ ⩋ ⩍ ⩎ ⩑ ⩓ ⩕ ⩘ ⩚ ⩜ ⩞ ⩟ ⩠ ⫛ ⊍ ▷ ⨝ ⟕ ⟖ ⟗ 像 + 一样解析的包括 + - |\\|| ⊕ ⊖ ⊞ ⊟ |++| ∪ ∨ ⊔ ± ∓ ∔ ∸ ≏ ⊎ ⊻ ⊽ ⋎ ⋓ ⧺ ⧻ ⨈ ⨢ ⨣ ⨤ ⨥ ⨦ ⨧ ⨨ ⨩ ⨪ ⨫ ⨬ ⨭ ⨮ ⨹ ⨺ ⩁ ⩂ ⩅ ⩊ ⩌ ⩏ ⩐ ⩒ ⩔ ⩖ ⩗ ⩛ ⩝ ⩡ ⩢ ⩣ 还有许多其他的与箭头、比较和幂相关的符号。","category":"page"},{"location":"stdlib/Markdown/#markdown_stdlib","page":"Markdown","title":"Markdown","text":"","category":"section"},{"location":"stdlib/Markdown/","page":"Markdown","title":"Markdown","text":"本节描述 Julia 的 markdown 语法,它是由 Markdown 标准库启用的。它支持以下的 Markdown 元素:","category":"page"},{"location":"stdlib/Markdown/#内联元素","page":"Markdown","title":"内联元素","text":"","category":"section"},{"location":"stdlib/Markdown/","page":"Markdown","title":"Markdown","text":"此处的“内联”指可以在段落中找到的元素。包括下面的元素。","category":"page"},{"location":"stdlib/Markdown/#粗体","page":"Markdown","title":"粗体","text":"","category":"section"},{"location":"stdlib/Markdown/","page":"Markdown","title":"Markdown","text":"用两个 ** 包围来将其内部的文本显示为粗体。","category":"page"},{"location":"stdlib/Markdown/","page":"Markdown","title":"Markdown","text":"A paragraph containing a **bold** word.","category":"page"},{"location":"stdlib/Markdown/#斜体","page":"Markdown","title":"斜体","text":"","category":"section"},{"location":"stdlib/Markdown/","page":"Markdown","title":"Markdown","text":"用单个 * 包围来将其内部的文本显示为斜体。","category":"page"},{"location":"stdlib/Markdown/","page":"Markdown","title":"Markdown","text":"A paragraph containing an *italicized* word.","category":"page"},{"location":"stdlib/Markdown/#文字","page":"Markdown","title":"文字","text":"","category":"section"},{"location":"stdlib/Markdown/","page":"Markdown","title":"Markdown","text":"用一个重音符号 ` 包围的文本将会原封不动地显示出来。","category":"page"},{"location":"stdlib/Markdown/","page":"Markdown","title":"Markdown","text":"A paragraph containing a `literal` word.","category":"page"},{"location":"stdlib/Markdown/","page":"Markdown","title":"Markdown","text":"当文本指代变量名、函数名或者 Julia 程序的其他部分时,应当使用字面量。","category":"page"},{"location":"stdlib/Markdown/","page":"Markdown","title":"Markdown","text":"tip: Tip\n为了在字面量中包含一个重音符,需要使用三个重音符而不是一个来包围文本。A paragraph containing ``` `backtick` characters ```.通过扩展,可以使用任何奇数个反引号来包围较少数量的反引号。","category":"page"},{"location":"stdlib/Markdown/#\\LaTeX","page":"Markdown","title":"LaTeX","text":"","category":"section"},{"location":"stdlib/Markdown/","page":"Markdown","title":"Markdown","text":"使用两个重音符的 LaTeX 语法来包围那些是数学表达式的文本, `` .","category":"page"},{"location":"stdlib/Markdown/","page":"Markdown","title":"Markdown","text":"A paragraph containing some ``\\LaTeX`` markup.","category":"page"},{"location":"stdlib/Markdown/","page":"Markdown","title":"Markdown","text":"tip: Tip\nAs with literals in the previous section, if literal backticks need to be written within double backticks use an even number greater than two. Note that if a single literal backtick needs to be included within LaTeX markup then two enclosing backticks is sufficient.","category":"page"},{"location":"stdlib/Markdown/","page":"Markdown","title":"Markdown","text":"note: Note\nThe \\ character should be escaped appropriately if the text is embedded in a Julia source code, for example, \"``\\\\LaTeX`` syntax in a docstring.\", since it is interpreted as a string literal. Alternatively, in order to avoid escaping, it is possible to use the raw string macro together with the @doc macro:@doc raw\"``\\LaTeX`` syntax in a docstring.\" functionname","category":"page"},{"location":"stdlib/Markdown/#Links","page":"Markdown","title":"Links","text":"","category":"section"},{"location":"stdlib/Markdown/","page":"Markdown","title":"Markdown","text":"Links to either external or internal targets can be written using the following syntax, where the text enclosed in square brackets, [ ], is the name of the link and the text enclosed in parentheses, ( ), is the URL.","category":"page"},{"location":"stdlib/Markdown/","page":"Markdown","title":"Markdown","text":"A paragraph containing a link to [Julia](http://www.julialang.org).","category":"page"},{"location":"stdlib/Markdown/","page":"Markdown","title":"Markdown","text":"It's also possible to add cross-references to other documented functions/methods/variables within the Julia documentation itself. For example:","category":"page"},{"location":"stdlib/Markdown/","page":"Markdown","title":"Markdown","text":"\"\"\"\n tryparse(type, str; base)\n\nLike [`parse`](@ref), but returns either a value of the requested type,\nor [`nothing`](@ref) if the string does not contain a valid number.\n\"\"\"","category":"page"},{"location":"stdlib/Markdown/","page":"Markdown","title":"Markdown","text":"This will create a link in the generated docs to the parse documentation (which has more information about what this function actually does), and to the nothing documentation. It's good to include cross references to mutating/non-mutating versions of a function, or to highlight a difference between two similar-seeming functions.","category":"page"},{"location":"stdlib/Markdown/","page":"Markdown","title":"Markdown","text":"note: Note\nThe above cross referencing is not a Markdown feature, and relies on Documenter.jl, which is used to build base Julia's documentation.","category":"page"},{"location":"stdlib/Markdown/#Footnote-references","page":"Markdown","title":"Footnote references","text":"","category":"section"},{"location":"stdlib/Markdown/","page":"Markdown","title":"Markdown","text":"Named and numbered footnote references can be written using the following syntax. A footnote name must be a single alphanumeric word containing no punctuation.","category":"page"},{"location":"stdlib/Markdown/","page":"Markdown","title":"Markdown","text":"A paragraph containing a numbered footnote [^1] and a named one [^named].","category":"page"},{"location":"stdlib/Markdown/","page":"Markdown","title":"Markdown","text":"note: Note\nThe text associated with a footnote can be written anywhere within the same page as the footnote reference. The syntax used to define the footnote text is discussed in the Footnotes section below.","category":"page"},{"location":"stdlib/Markdown/#Toplevel-elements","page":"Markdown","title":"Toplevel elements","text":"","category":"section"},{"location":"stdlib/Markdown/","page":"Markdown","title":"Markdown","text":"The following elements can be written either at the \"toplevel\" of a document or within another \"toplevel\" element.","category":"page"},{"location":"stdlib/Markdown/#Paragraphs","page":"Markdown","title":"Paragraphs","text":"","category":"section"},{"location":"stdlib/Markdown/","page":"Markdown","title":"Markdown","text":"A paragraph is a block of plain text, possibly containing any number of inline elements defined in the Inline elements section above, with one or more blank lines above and below it.","category":"page"},{"location":"stdlib/Markdown/","page":"Markdown","title":"Markdown","text":"This is a paragraph.\n\nAnd this is *another* paragraph containing some emphasized text.\nA new line, but still part of the same paragraph.","category":"page"},{"location":"stdlib/Markdown/#Headers","page":"Markdown","title":"Headers","text":"","category":"section"},{"location":"stdlib/Markdown/","page":"Markdown","title":"Markdown","text":"A document can be split up into different sections using headers. Headers use the following syntax:","category":"page"},{"location":"stdlib/Markdown/","page":"Markdown","title":"Markdown","text":"# Level One\n## Level Two\n### Level Three\n#### Level Four\n##### Level Five\n###### Level Six","category":"page"},{"location":"stdlib/Markdown/","page":"Markdown","title":"Markdown","text":"A header line can contain any inline syntax in the same way as a paragraph can.","category":"page"},{"location":"stdlib/Markdown/","page":"Markdown","title":"Markdown","text":"tip: Tip\nTry to avoid using too many levels of header within a single document. A heavily nested document may be indicative of a need to restructure it or split it into several pages covering separate topics.","category":"page"},{"location":"stdlib/Markdown/#Code-blocks","page":"Markdown","title":"Code blocks","text":"","category":"section"},{"location":"stdlib/Markdown/","page":"Markdown","title":"Markdown","text":"Source code can be displayed as a literal block using an indent of four spaces as shown in the following example.","category":"page"},{"location":"stdlib/Markdown/","page":"Markdown","title":"Markdown","text":"This is a paragraph.\n\n function func(x)\n # ...\n end\n\nAnother paragraph.","category":"page"},{"location":"stdlib/Markdown/","page":"Markdown","title":"Markdown","text":"Additionally, code blocks can be enclosed using triple backticks with an optional \"language\" to specify how a block of code should be highlighted.","category":"page"},{"location":"stdlib/Markdown/","page":"Markdown","title":"Markdown","text":"A code block without a \"language\":\n\n```\nfunction func(x)\n # ...\nend\n```\n\nand another one with the \"language\" specified as `julia`:\n\n```julia\nfunction func(x)\n # ...\nend\n```","category":"page"},{"location":"stdlib/Markdown/","page":"Markdown","title":"Markdown","text":"note: Note\n\"Fenced\" code blocks, as shown in the last example, should be preferred over indented code blocks since there is no way to specify what language an indented code block is written in.","category":"page"},{"location":"stdlib/Markdown/#Block-quotes","page":"Markdown","title":"Block quotes","text":"","category":"section"},{"location":"stdlib/Markdown/","page":"Markdown","title":"Markdown","text":"Text from external sources, such as quotations from books or websites, can be quoted using > characters prepended to each line of the quote as follows.","category":"page"},{"location":"stdlib/Markdown/","page":"Markdown","title":"Markdown","text":"Here's a quote:\n\n> Julia is a high-level, high-performance dynamic programming language for\n> technical computing, with syntax that is familiar to users of other\n> technical computing environments.","category":"page"},{"location":"stdlib/Markdown/","page":"Markdown","title":"Markdown","text":"Note that a single space must appear after the > character on each line. Quoted blocks may themselves contain other toplevel or inline elements.","category":"page"},{"location":"stdlib/Markdown/#Images","page":"Markdown","title":"Images","text":"","category":"section"},{"location":"stdlib/Markdown/","page":"Markdown","title":"Markdown","text":"The syntax for images is similar to the link syntax mentioned above. Prepending a ! character to a link will display an image from the specified URL rather than a link to it.","category":"page"},{"location":"stdlib/Markdown/","page":"Markdown","title":"Markdown","text":"![alternative text](link/to/image.png)","category":"page"},{"location":"stdlib/Markdown/#Lists","page":"Markdown","title":"Lists","text":"","category":"section"},{"location":"stdlib/Markdown/","page":"Markdown","title":"Markdown","text":"Unordered lists can be written by prepending each item in a list with either *, +, or -.","category":"page"},{"location":"stdlib/Markdown/","page":"Markdown","title":"Markdown","text":"A list of items:\n\n * item one\n * item two\n * item three","category":"page"},{"location":"stdlib/Markdown/","page":"Markdown","title":"Markdown","text":"Note the two spaces before each * and the single space after each one.","category":"page"},{"location":"stdlib/Markdown/","page":"Markdown","title":"Markdown","text":"Lists can contain other nested toplevel elements such as lists, code blocks, or quoteblocks. A blank line should be left between each list item when including any toplevel elements within a list.","category":"page"},{"location":"stdlib/Markdown/","page":"Markdown","title":"Markdown","text":"Another list:\n\n * item one\n\n * item two\n\n ```\n f(x) = x\n ```\n\n * And a sublist:\n\n + sub-item one\n + sub-item two","category":"page"},{"location":"stdlib/Markdown/","page":"Markdown","title":"Markdown","text":"note: Note\nThe contents of each item in the list must line up with the first line of the item. In the above example the fenced code block must be indented by four spaces to align with the i in item two.","category":"page"},{"location":"stdlib/Markdown/","page":"Markdown","title":"Markdown","text":"Ordered lists are written by replacing the \"bullet\" character, either *, +, or -, with a positive integer followed by either . or ).","category":"page"},{"location":"stdlib/Markdown/","page":"Markdown","title":"Markdown","text":"Two ordered lists:\n\n 1. item one\n 2. item two\n 3. item three\n\n 5) item five\n 6) item six\n 7) item seven","category":"page"},{"location":"stdlib/Markdown/","page":"Markdown","title":"Markdown","text":"An ordered list may start from a number other than one, as in the second list of the above example, where it is numbered from five. As with unordered lists, ordered lists can contain nested toplevel elements.","category":"page"},{"location":"stdlib/Markdown/#Display-equations","page":"Markdown","title":"Display equations","text":"","category":"section"},{"location":"stdlib/Markdown/","page":"Markdown","title":"Markdown","text":"Large LaTeX equations that do not fit inline within a paragraph may be written as display equations using a fenced code block with the \"language\" math as in the example below.","category":"page"},{"location":"stdlib/Markdown/","page":"Markdown","title":"Markdown","text":"```math\nf(a) = \\frac{1}{2\\pi}\\int_{0}^{2\\pi} (\\alpha+R\\cos(\\theta))d\\theta\n```","category":"page"},{"location":"stdlib/Markdown/#Footnotes","page":"Markdown","title":"Footnotes","text":"","category":"section"},{"location":"stdlib/Markdown/","page":"Markdown","title":"Markdown","text":"This syntax is paired with the inline syntax for Footnote references. Make sure to read that section as well.","category":"page"},{"location":"stdlib/Markdown/","page":"Markdown","title":"Markdown","text":"Footnote text is defined using the following syntax, which is similar to footnote reference syntax, aside from the : character that is appended to the footnote label.","category":"page"},{"location":"stdlib/Markdown/","page":"Markdown","title":"Markdown","text":"[^1]: Numbered footnote text.\n\n[^note]:\n\n Named footnote text containing several toplevel elements.\n\n * item one\n * item two\n * item three\n\n ```julia\n function func(x)\n # ...\n end\n ```","category":"page"},{"location":"stdlib/Markdown/","page":"Markdown","title":"Markdown","text":"note: Note\nNo checks are done during parsing to make sure that all footnote references have matching footnotes.","category":"page"},{"location":"stdlib/Markdown/#Horizontal-rules","page":"Markdown","title":"Horizontal rules","text":"","category":"section"},{"location":"stdlib/Markdown/","page":"Markdown","title":"Markdown","text":"The equivalent of an
        HTML tag can be achieved using three hyphens (---). For example:","category":"page"},{"location":"stdlib/Markdown/","page":"Markdown","title":"Markdown","text":"Text above the line.\n\n---\n\nAnd text below the line.","category":"page"},{"location":"stdlib/Markdown/#Tables","page":"Markdown","title":"Tables","text":"","category":"section"},{"location":"stdlib/Markdown/","page":"Markdown","title":"Markdown","text":"Basic tables can be written using the syntax described below. Note that markdown tables have limited features and cannot contain nested toplevel elements unlike other elements discussed above – only inline elements are allowed. Tables must always contain a header row with column names. Cells cannot span multiple rows or columns of the table.","category":"page"},{"location":"stdlib/Markdown/","page":"Markdown","title":"Markdown","text":"| Column One | Column Two | Column Three |\n|:---------- | ---------- |:------------:|\n| Row `1` | Column `2` | |\n| *Row* 2 | **Row** 2 | Column ``3`` |","category":"page"},{"location":"stdlib/Markdown/","page":"Markdown","title":"Markdown","text":"note: Note\nAs illustrated in the above example each column of | characters must be aligned vertically.A : character on either end of a column's header separator (the row containing - characters) specifies whether the row is left-aligned, right-aligned, or (when : appears on both ends) center-aligned. Providing no : characters will default to right-aligning the column.","category":"page"},{"location":"stdlib/Markdown/#Admonitions","page":"Markdown","title":"Admonitions","text":"","category":"section"},{"location":"stdlib/Markdown/","page":"Markdown","title":"Markdown","text":"Specially formatted blocks, known as admonitions, can be used to highlight particular remarks. They can be defined using the following !!! syntax:","category":"page"},{"location":"stdlib/Markdown/","page":"Markdown","title":"Markdown","text":"!!! note\n\n This is the content of the note.\n\n!!! warning \"Beware!\"\n\n And this is another one.\n\n This warning admonition has a custom title: `\"Beware!\"`.","category":"page"},{"location":"stdlib/Markdown/","page":"Markdown","title":"Markdown","text":"The first word after !!! declares the type of the admonition. There are standard admonition types that should produce special styling. Namely (in order of decreasing severity): danger, warning, info/note, and tip.","category":"page"},{"location":"stdlib/Markdown/","page":"Markdown","title":"Markdown","text":"You can also use your own admonition types, as long as the type name only contains lowercase Latin characters (a-z). For example, you could have a terminology block like this:","category":"page"},{"location":"stdlib/Markdown/","page":"Markdown","title":"Markdown","text":"!!! terminology \"julia vs Julia\"\n\n Strictly speaking, \"Julia\" refers to the language,\n and \"julia\" to the standard implementation.","category":"page"},{"location":"stdlib/Markdown/","page":"Markdown","title":"Markdown","text":"However, unless the code rendering the Markdown special-cases that particular admonition type, it will get the default styling.","category":"page"},{"location":"stdlib/Markdown/","page":"Markdown","title":"Markdown","text":"A custom title for the box can be provided as a string (in double quotes) after the admonition type. If no title text is specified after the admonition type, then the type name will be used as the title (e.g. \"Note\" for the note admonition).","category":"page"},{"location":"stdlib/Markdown/","page":"Markdown","title":"Markdown","text":"Admonitions, like most other toplevel elements, can contain other toplevel elements (e.g. lists, images).","category":"page"},{"location":"stdlib/Markdown/#Markdown-Syntax-Extensions","page":"Markdown","title":"Markdown Syntax Extensions","text":"","category":"section"},{"location":"stdlib/Markdown/","page":"Markdown","title":"Markdown","text":"Julia's markdown supports interpolation in a very similar way to basic string literals, with the difference that it will store the object itself in the Markdown tree (as opposed to converting it to a string). When the Markdown content is rendered the usual show methods will be called, and these can be overridden as usual. This design allows the Markdown to be extended with arbitrarily complex features (such as references) without cluttering the basic syntax.","category":"page"},{"location":"stdlib/Markdown/","page":"Markdown","title":"Markdown","text":"In principle, the Markdown parser itself can also be arbitrarily extended by packages, or an entirely custom flavour of Markdown can be used, but this should generally be unnecessary.","category":"page"},{"location":"devdocs/subarrays/#子数组","page":"子数组","title":"子数组","text":"","category":"section"},{"location":"devdocs/subarrays/","page":"子数组","title":"子数组","text":"Julia 的 SubArray 类型是编码父类型 AbstractArray 的“视图”的一个容器。本页介绍了 SubArray 的一些设计原则和实现。","category":"page"},{"location":"devdocs/subarrays/","page":"子数组","title":"子数组","text":"One of the major design goals is to ensure high performance for views of both IndexLinear and IndexCartesian arrays. Furthermore, views of IndexLinear arrays should themselves be IndexLinear to the extent that it is possible.","category":"page"},{"location":"devdocs/subarrays/#Index-replacement","page":"子数组","title":"Index replacement","text":"","category":"section"},{"location":"devdocs/subarrays/","page":"子数组","title":"子数组","text":"Consider making 2d slices of a 3d array:","category":"page"},{"location":"devdocs/subarrays/","page":"子数组","title":"子数组","text":"DocTestSetup = :(import Random; Random.seed!(1234))","category":"page"},{"location":"devdocs/subarrays/","page":"子数组","title":"子数组","text":"julia> A = rand(2,3,4);\n\njulia> S1 = view(A, :, 1, 2:3)\n2×2 view(::Array{Float64, 3}, :, 1, 2:3) with eltype Float64:\n 0.342284 0.831961\n 0.237287 0.435938\n\njulia> S2 = view(A, 1, :, 2:3)\n3×2 view(::Array{Float64, 3}, 1, :, 2:3) with eltype Float64:\n 0.342284 0.831961\n 0.988944 0.927795\n 0.178426 0.404876","category":"page"},{"location":"devdocs/subarrays/","page":"子数组","title":"子数组","text":"DocTestSetup = nothing","category":"page"},{"location":"devdocs/subarrays/","page":"子数组","title":"子数组","text":"view drops \"singleton\" dimensions (ones that are specified by an Int), so both S1 and S2 are two-dimensional SubArrays. Consequently, the natural way to index these is with S1[i,j]. To extract the value from the parent array A, the natural approach is to replace S1[i,j] with A[i,1,(2:3)[j]] and S2[i,j] with A[1,i,(2:3)[j]].","category":"page"},{"location":"devdocs/subarrays/","page":"子数组","title":"子数组","text":"The key feature of the design of SubArrays is that this index replacement can be performed without any runtime overhead.","category":"page"},{"location":"devdocs/subarrays/#SubArray-design","page":"子数组","title":"SubArray design","text":"","category":"section"},{"location":"devdocs/subarrays/#Type-parameters-and-fields","page":"子数组","title":"Type parameters and fields","text":"","category":"section"},{"location":"devdocs/subarrays/","page":"子数组","title":"子数组","text":"The strategy adopted is first and foremost expressed in the definition of the type:","category":"page"},{"location":"devdocs/subarrays/","page":"子数组","title":"子数组","text":"struct SubArray{T,N,P,I,L} <: AbstractArray{T,N}\n parent::P\n indices::I\n offset1::Int # for linear indexing and pointer, only valid when L==true\n stride1::Int # used only for linear indexing\n ...\nend","category":"page"},{"location":"devdocs/subarrays/","page":"子数组","title":"子数组","text":"SubArray has 5 type parameters. The first two are the standard element type and dimensionality. The next is the type of the parent AbstractArray. The most heavily-used is the fourth parameter, a Tuple of the types of the indices for each dimension. The final one, L, is only provided as a convenience for dispatch; it's a boolean that represents whether the index types support fast linear indexing. More on that later.","category":"page"},{"location":"devdocs/subarrays/","page":"子数组","title":"子数组","text":"If in our example above A is a Array{Float64, 3}, our S1 case above would be a SubArray{Float64,2,Array{Float64,3},Tuple{Base.Slice{Base.OneTo{Int64}},Int64,UnitRange{Int64}},false}. Note in particular the tuple parameter, which stores the types of the indices used to create S1. Likewise,","category":"page"},{"location":"devdocs/subarrays/","page":"子数组","title":"子数组","text":"julia> S1.indices\n(Base.Slice(Base.OneTo(2)), 1, 2:3)","category":"page"},{"location":"devdocs/subarrays/","page":"子数组","title":"子数组","text":"Storing these values allows index replacement, and having the types encoded as parameters allows one to dispatch to efficient algorithms.","category":"page"},{"location":"devdocs/subarrays/#Index-translation","page":"子数组","title":"Index translation","text":"","category":"section"},{"location":"devdocs/subarrays/","page":"子数组","title":"子数组","text":"Performing index translation requires that you do different things for different concrete SubArray types. For example, for S1, one needs to apply the i,j indices to the first and third dimensions of the parent array, whereas for S2 one needs to apply them to the second and third. The simplest approach to indexing would be to do the type-analysis at runtime:","category":"page"},{"location":"devdocs/subarrays/","page":"子数组","title":"子数组","text":"parentindices = Vector{Any}()\nfor thisindex in S.indices\n ...\n if isa(thisindex, Int)\n # Don't consume one of the input indices\n push!(parentindices, thisindex)\n elseif isa(thisindex, AbstractVector)\n # Consume an input index\n push!(parentindices, thisindex[inputindex[j]])\n j += 1\n elseif isa(thisindex, AbstractMatrix)\n # Consume two input indices\n push!(parentindices, thisindex[inputindex[j], inputindex[j+1]])\n j += 2\n elseif ...\nend\nS.parent[parentindices...]","category":"page"},{"location":"devdocs/subarrays/","page":"子数组","title":"子数组","text":"Unfortunately, this would be disastrous in terms of performance: each element access would allocate memory, and involves the running of a lot of poorly-typed code.","category":"page"},{"location":"devdocs/subarrays/","page":"子数组","title":"子数组","text":"The better approach is to dispatch to specific methods to handle each type of stored index. That's what reindex does: it dispatches on the type of the first stored index and consumes the appropriate number of input indices, and then it recurses on the remaining indices. In the case of S1, this expands to","category":"page"},{"location":"devdocs/subarrays/","page":"子数组","title":"子数组","text":"Base.reindex(S1, S1.indices, (i, j)) == (i, S1.indices[2], S1.indices[3][j])","category":"page"},{"location":"devdocs/subarrays/","page":"子数组","title":"子数组","text":"for any pair of indices (i,j) (except CartesianIndexs and arrays thereof, see below).","category":"page"},{"location":"devdocs/subarrays/","page":"子数组","title":"子数组","text":"This is the core of a SubArray; indexing methods depend upon reindex to do this index translation. Sometimes, though, we can avoid the indirection and make it even faster.","category":"page"},{"location":"devdocs/subarrays/#Linear-indexing","page":"子数组","title":"Linear indexing","text":"","category":"section"},{"location":"devdocs/subarrays/","page":"子数组","title":"子数组","text":"Linear indexing can be implemented efficiently when the entire array has a single stride that separates successive elements, starting from some offset. This means that we can pre-compute these values and represent linear indexing simply as an addition and multiplication, avoiding the indirection of reindex and (more importantly) the slow computation of the cartesian coordinates entirely.","category":"page"},{"location":"devdocs/subarrays/","page":"子数组","title":"子数组","text":"For SubArray types, the availability of efficient linear indexing is based purely on the types of the indices, and does not depend on values like the size of the parent array. You can ask whether a given set of indices supports fast linear indexing with the internal Base.viewindexing function:","category":"page"},{"location":"devdocs/subarrays/","page":"子数组","title":"子数组","text":"julia> Base.viewindexing(S1.indices)\nIndexCartesian()\n\njulia> Base.viewindexing(S2.indices)\nIndexLinear()","category":"page"},{"location":"devdocs/subarrays/","page":"子数组","title":"子数组","text":"This is computed during construction of the SubArray and stored in the L type parameter as a boolean that encodes fast linear indexing support. While not strictly necessary, it means that we can define dispatch directly on SubArray{T,N,A,I,true} without any intermediaries.","category":"page"},{"location":"devdocs/subarrays/","page":"子数组","title":"子数组","text":"Since this computation doesn't depend on runtime values, it can miss some cases in which the stride happens to be uniform:","category":"page"},{"location":"devdocs/subarrays/","page":"子数组","title":"子数组","text":"julia> A = reshape(1:4*2, 4, 2)\n4×2 reshape(::UnitRange{Int64}, 4, 2) with eltype Int64:\n 1 5\n 2 6\n 3 7\n 4 8\n\njulia> diff(A[2:2:4,:][:])\n3-element Vector{Int64}:\n 2\n 2\n 2","category":"page"},{"location":"devdocs/subarrays/","page":"子数组","title":"子数组","text":"A view constructed as view(A, 2:2:4, :) happens to have uniform stride, and therefore linear indexing indeed could be performed efficiently. However, success in this case depends on the size of the array: if the first dimension instead were odd,","category":"page"},{"location":"devdocs/subarrays/","page":"子数组","title":"子数组","text":"julia> A = reshape(1:5*2, 5, 2)\n5×2 reshape(::UnitRange{Int64}, 5, 2) with eltype Int64:\n 1 6\n 2 7\n 3 8\n 4 9\n 5 10\n\njulia> diff(A[2:2:4,:][:])\n3-element Vector{Int64}:\n 2\n 3\n 2","category":"page"},{"location":"devdocs/subarrays/","page":"子数组","title":"子数组","text":"then A[2:2:4,:] does not have uniform stride, so we cannot guarantee efficient linear indexing. Since we have to base this decision based purely on types encoded in the parameters of the SubArray, S = view(A, 2:2:4, :) cannot implement efficient linear indexing.","category":"page"},{"location":"devdocs/subarrays/#A-few-details","page":"子数组","title":"A few details","text":"","category":"section"},{"location":"devdocs/subarrays/","page":"子数组","title":"子数组","text":"Note that the Base.reindex function is agnostic to the types of the input indices; it simply determines how and where the stored indices should be reindexed. It not only supports integer indices, but it supports non-scalar indexing, too. This means that views of views don't need two levels of indirection; they can simply re-compute the indices into the original parent array!\nHopefully by now it's fairly clear that supporting slices means that the dimensionality, given by the parameter N, is not necessarily equal to the dimensionality of the parent array or the length of the indices tuple. Neither do user-supplied indices necessarily line up with entries in the indices tuple (e.g., the second user-supplied index might correspond to the third dimension of the parent array, and the third element in the indices tuple).\nWhat might be less obvious is that the dimensionality of the stored parent array must be equal to the number of effective indices in the indices tuple. Some examples:\nA = reshape(1:35, 5, 7) # A 2d parent Array\nS = view(A, 2:7) # A 1d view created by linear indexing\nS = view(A, :, :, 1:1) # Appending extra indices is supported\nNaively, you'd think you could just set S.parent = A and S.indices = (:,:,1:1), but supporting this dramatically complicates the reindexing process, especially for views of views. Not only do you need to dispatch on the types of the stored indices, but you need to examine whether a given index is the final one and \"merge\" any remaining stored indices together. This is not an easy task, and even worse: it's slow since it implicitly depends upon linear indexing.\nFortunately, this is precisely the computation that ReshapedArray performs, and it does so linearly if possible. Consequently, view ensures that the parent array is the appropriate dimensionality for the given indices by reshaping it if needed. The inner SubArray constructor ensures that this invariant is satisfied.\nCartesianIndex and arrays thereof throw a nasty wrench into the reindex scheme. Recall that reindex simply dispatches on the type of the stored indices in order to determine how many passed indices should be used and where they should go. But with CartesianIndex, there's no longer a one-to-one correspondence between the number of passed arguments and the number of dimensions that they index into. If we return to the above example of Base.reindex(S1, S1.indices, (i, j)), you can see that the expansion is incorrect for i, j = CartesianIndex(), CartesianIndex(2,1). It should skip the CartesianIndex() entirely and return:\n(CartesianIndex(2,1)[1], S1.indices[2], S1.indices[3][CartesianIndex(2,1)[2]])\nInstead, though, we get:\n(CartesianIndex(), S1.indices[2], S1.indices[3][CartesianIndex(2,1)])\nDoing this correctly would require combined dispatch on both the stored and passed indices across all combinations of dimensionalities in an intractable manner. As such, reindex must never be called with CartesianIndex indices. Fortunately, the scalar case is easily handled by first flattening the CartesianIndex arguments to plain integers. Arrays of CartesianIndex, however, cannot be split apart into orthogonal pieces so easily. Before attempting to use reindex, view must ensure that there are no arrays of CartesianIndex in the argument list. If there are, it can simply \"punt\" by avoiding the reindex calculation entirely, constructing a nested SubArray with two levels of indirection instead.","category":"page"},{"location":"devdocs/object/#Memory-layout-of-Julia-Objects","page":"Memory layout of Julia Objects","title":"Memory layout of Julia Objects","text":"","category":"section"},{"location":"devdocs/object/#Object-layout-(jl_value_t)","page":"Memory layout of Julia Objects","title":"Object layout (jl_value_t)","text":"","category":"section"},{"location":"devdocs/object/","page":"Memory layout of Julia Objects","title":"Memory layout of Julia Objects","text":"The jl_value_t struct is the name for a block of memory owned by the Julia Garbage Collector, representing the data associated with a Julia object in memory. Absent any type information, it is simply an opaque pointer:","category":"page"},{"location":"devdocs/object/","page":"Memory layout of Julia Objects","title":"Memory layout of Julia Objects","text":"typedef struct jl_value_t* jl_pvalue_t;","category":"page"},{"location":"devdocs/object/","page":"Memory layout of Julia Objects","title":"Memory layout of Julia Objects","text":"Each jl_value_t struct is contained in a jl_typetag_t struct that contains metadata information about the Julia object, such as its type and garbage collector (gc) reachability:","category":"page"},{"location":"devdocs/object/","page":"Memory layout of Julia Objects","title":"Memory layout of Julia Objects","text":"typedef struct {\n opaque metadata;\n jl_value_t value;\n} jl_typetag_t;","category":"page"},{"location":"devdocs/object/","page":"Memory layout of Julia Objects","title":"Memory layout of Julia Objects","text":"The type of any Julia object is an instance of a leaf jl_datatype_t object. The jl_typeof() function can be used to query for it:","category":"page"},{"location":"devdocs/object/","page":"Memory layout of Julia Objects","title":"Memory layout of Julia Objects","text":"jl_value_t *jl_typeof(jl_value_t *v);","category":"page"},{"location":"devdocs/object/","page":"Memory layout of Julia Objects","title":"Memory layout of Julia Objects","text":"The layout of the object depends on its type. Reflection methods can be used to inspect that layout. A field can be accessed by calling one of the get-field methods:","category":"page"},{"location":"devdocs/object/","page":"Memory layout of Julia Objects","title":"Memory layout of Julia Objects","text":"jl_value_t *jl_get_nth_field_checked(jl_value_t *v, size_t i);\njl_value_t *jl_get_field(jl_value_t *o, char *fld);","category":"page"},{"location":"devdocs/object/","page":"Memory layout of Julia Objects","title":"Memory layout of Julia Objects","text":"If the field types are known, a priori, to be all pointers, the values can also be extracted directly as an array access:","category":"page"},{"location":"devdocs/object/","page":"Memory layout of Julia Objects","title":"Memory layout of Julia Objects","text":"jl_value_t *v = value->fieldptr[n];","category":"page"},{"location":"devdocs/object/","page":"Memory layout of Julia Objects","title":"Memory layout of Julia Objects","text":"As an example, a \"boxed\" uint16_t is stored as follows:","category":"page"},{"location":"devdocs/object/","page":"Memory layout of Julia Objects","title":"Memory layout of Julia Objects","text":"struct {\n opaque metadata;\n struct {\n uint16_t data; // -- 2 bytes\n } jl_value_t;\n};","category":"page"},{"location":"devdocs/object/","page":"Memory layout of Julia Objects","title":"Memory layout of Julia Objects","text":"This object is created by jl_box_uint16(). Note that the jl_value_t pointer references the data portion, not the metadata at the top of the struct.","category":"page"},{"location":"devdocs/object/","page":"Memory layout of Julia Objects","title":"Memory layout of Julia Objects","text":"A value may be stored \"unboxed\" in many circumstances (just the data, without the metadata, and possibly not even stored but just kept in registers), so it is unsafe to assume that the address of a box is a unique identifier. The \"egal\" test (corresponding to the === function in Julia), should instead be used to compare two unknown objects for equivalence:","category":"page"},{"location":"devdocs/object/","page":"Memory layout of Julia Objects","title":"Memory layout of Julia Objects","text":"int jl_egal(jl_value_t *a, jl_value_t *b);","category":"page"},{"location":"devdocs/object/","page":"Memory layout of Julia Objects","title":"Memory layout of Julia Objects","text":"This optimization should be relatively transparent to the API, since the object will be \"boxed\" on-demand, whenever a jl_value_t pointer is needed.","category":"page"},{"location":"devdocs/object/","page":"Memory layout of Julia Objects","title":"Memory layout of Julia Objects","text":"Note that modification of a jl_value_t pointer in memory is permitted only if the object is mutable. Otherwise, modification of the value may corrupt the program and the result will be undefined. The mutability property of a value can be queried for with:","category":"page"},{"location":"devdocs/object/","page":"Memory layout of Julia Objects","title":"Memory layout of Julia Objects","text":"int jl_is_mutable(jl_value_t *v);","category":"page"},{"location":"devdocs/object/","page":"Memory layout of Julia Objects","title":"Memory layout of Julia Objects","text":"If the object being stored is a jl_value_t, the Julia garbage collector must be notified also:","category":"page"},{"location":"devdocs/object/","page":"Memory layout of Julia Objects","title":"Memory layout of Julia Objects","text":"void jl_gc_wb(jl_value_t *parent, jl_value_t *ptr);","category":"page"},{"location":"devdocs/object/","page":"Memory layout of Julia Objects","title":"Memory layout of Julia Objects","text":"However, the Embedding Julia section of the manual is also required reading at this point, for covering other details of boxing and unboxing various types, and understanding the gc interactions.","category":"page"},{"location":"devdocs/object/","page":"Memory layout of Julia Objects","title":"Memory layout of Julia Objects","text":"Mirror structs for some of the built-in types are defined in julia.h. The corresponding global jl_datatype_t objects are created by jl_init_types in jltypes.c.","category":"page"},{"location":"devdocs/object/#Garbage-collector-mark-bits","page":"Memory layout of Julia Objects","title":"Garbage collector mark bits","text":"","category":"section"},{"location":"devdocs/object/","page":"Memory layout of Julia Objects","title":"Memory layout of Julia Objects","text":"The garbage collector uses several bits from the metadata portion of the jl_typetag_t to track each object in the system. Further details about this algorithm can be found in the comments of the garbage collector implementation in gc.c.","category":"page"},{"location":"devdocs/object/#Object-allocation","page":"Memory layout of Julia Objects","title":"Object allocation","text":"","category":"section"},{"location":"devdocs/object/","page":"Memory layout of Julia Objects","title":"Memory layout of Julia Objects","text":"Most new objects are allocated by jl_new_structv():","category":"page"},{"location":"devdocs/object/","page":"Memory layout of Julia Objects","title":"Memory layout of Julia Objects","text":"jl_value_t *jl_new_struct(jl_datatype_t *type, ...);\njl_value_t *jl_new_structv(jl_datatype_t *type, jl_value_t **args, uint32_t na);","category":"page"},{"location":"devdocs/object/","page":"Memory layout of Julia Objects","title":"Memory layout of Julia Objects","text":"Although, isbits objects can be also constructed directly from memory:","category":"page"},{"location":"devdocs/object/","page":"Memory layout of Julia Objects","title":"Memory layout of Julia Objects","text":"jl_value_t *jl_new_bits(jl_value_t *bt, void *data)","category":"page"},{"location":"devdocs/object/","page":"Memory layout of Julia Objects","title":"Memory layout of Julia Objects","text":"And some objects have special constructors that must be used instead of the above functions:","category":"page"},{"location":"devdocs/object/","page":"Memory layout of Julia Objects","title":"Memory layout of Julia Objects","text":"Types:","category":"page"},{"location":"devdocs/object/","page":"Memory layout of Julia Objects","title":"Memory layout of Julia Objects","text":"jl_datatype_t *jl_apply_type(jl_datatype_t *tc, jl_tuple_t *params);\njl_datatype_t *jl_apply_array_type(jl_datatype_t *type, size_t dim);","category":"page"},{"location":"devdocs/object/","page":"Memory layout of Julia Objects","title":"Memory layout of Julia Objects","text":"While these are the most commonly used options, there are more low-level constructors too, which you can find declared in julia.h. These are used in jl_init_types() to create the initial types needed to bootstrap the creation of the Julia system image.","category":"page"},{"location":"devdocs/object/","page":"Memory layout of Julia Objects","title":"Memory layout of Julia Objects","text":"Tuples:","category":"page"},{"location":"devdocs/object/","page":"Memory layout of Julia Objects","title":"Memory layout of Julia Objects","text":"jl_tuple_t *jl_tuple(size_t n, ...);\njl_tuple_t *jl_tuplev(size_t n, jl_value_t **v);\njl_tuple_t *jl_alloc_tuple(size_t n);","category":"page"},{"location":"devdocs/object/","page":"Memory layout of Julia Objects","title":"Memory layout of Julia Objects","text":"The representation of tuples is highly unique in the Julia object representation ecosystem. In some cases, a Base.tuple() object may be an array of pointers to the objects contained by the tuple equivalent to:","category":"page"},{"location":"devdocs/object/","page":"Memory layout of Julia Objects","title":"Memory layout of Julia Objects","text":"typedef struct {\n size_t length;\n jl_value_t *data[length];\n} jl_tuple_t;","category":"page"},{"location":"devdocs/object/","page":"Memory layout of Julia Objects","title":"Memory layout of Julia Objects","text":"However, in other cases, the tuple may be converted to an anonymous isbits type and stored unboxed, or it may not stored at all (if it is not being used in a generic context as a jl_value_t*).","category":"page"},{"location":"devdocs/object/","page":"Memory layout of Julia Objects","title":"Memory layout of Julia Objects","text":"Symbols:","category":"page"},{"location":"devdocs/object/","page":"Memory layout of Julia Objects","title":"Memory layout of Julia Objects","text":"jl_sym_t *jl_symbol(const char *str);","category":"page"},{"location":"devdocs/object/","page":"Memory layout of Julia Objects","title":"Memory layout of Julia Objects","text":"Functions and MethodInstance:","category":"page"},{"location":"devdocs/object/","page":"Memory layout of Julia Objects","title":"Memory layout of Julia Objects","text":"jl_function_t *jl_new_generic_function(jl_sym_t *name);\njl_method_instance_t *jl_new_method_instance(jl_value_t *ast, jl_tuple_t *sparams);","category":"page"},{"location":"devdocs/object/","page":"Memory layout of Julia Objects","title":"Memory layout of Julia Objects","text":"Arrays:","category":"page"},{"location":"devdocs/object/","page":"Memory layout of Julia Objects","title":"Memory layout of Julia Objects","text":"jl_array_t *jl_new_array(jl_value_t *atype, jl_tuple_t *dims);\njl_array_t *jl_new_arrayv(jl_value_t *atype, ...);\njl_array_t *jl_alloc_array_1d(jl_value_t *atype, size_t nr);\njl_array_t *jl_alloc_array_2d(jl_value_t *atype, size_t nr, size_t nc);\njl_array_t *jl_alloc_array_3d(jl_value_t *atype, size_t nr, size_t nc, size_t z);\njl_array_t *jl_alloc_vec_any(size_t n);","category":"page"},{"location":"devdocs/object/","page":"Memory layout of Julia Objects","title":"Memory layout of Julia Objects","text":"Note that many of these have alternative allocation functions for various special-purposes. The list here reflects the more common usages, but a more complete list can be found by reading the julia.h header file.","category":"page"},{"location":"devdocs/object/","page":"Memory layout of Julia Objects","title":"Memory layout of Julia Objects","text":"Internal to Julia, storage is typically allocated by newstruct() (or newobj() for the special types):","category":"page"},{"location":"devdocs/object/","page":"Memory layout of Julia Objects","title":"Memory layout of Julia Objects","text":"jl_value_t *newstruct(jl_value_t *type);\njl_value_t *newobj(jl_value_t *type, size_t nfields);","category":"page"},{"location":"devdocs/object/","page":"Memory layout of Julia Objects","title":"Memory layout of Julia Objects","text":"And at the lowest level, memory is getting allocated by a call to the garbage collector (in gc.c), then tagged with its type:","category":"page"},{"location":"devdocs/object/","page":"Memory layout of Julia Objects","title":"Memory layout of Julia Objects","text":"jl_value_t *jl_gc_allocobj(size_t nbytes);\nvoid jl_set_typeof(jl_value_t *v, jl_datatype_t *type);","category":"page"},{"location":"devdocs/object/","page":"Memory layout of Julia Objects","title":"Memory layout of Julia Objects","text":"Note that all objects are allocated in multiples of 4 bytes and aligned to the platform pointer size. Memory is allocated from a pool for smaller objects, or directly with malloc() for large objects.","category":"page"},{"location":"devdocs/object/","page":"Memory layout of Julia Objects","title":"Memory layout of Julia Objects","text":"sidebar: Singleton Types\nSingleton types have only one instance and no data fields. Singleton instances have a size of 0 bytes, and consist only of their metadata. e.g. nothing::Nothing.See Singleton Types and Nothingness and missing values","category":"page"},{"location":"devdocs/reflection/#反射-与-自我检查","page":"反射 与 自我检查","title":"反射 与 自我检查","text":"","category":"section"},{"location":"devdocs/reflection/","page":"反射 与 自我检查","title":"反射 与 自我检查","text":"Julia 提供了多种运行时的反射功能。","category":"page"},{"location":"devdocs/reflection/#模块绑定","page":"反射 与 自我检查","title":"模块绑定","text":"","category":"section"},{"location":"devdocs/reflection/","page":"反射 与 自我检查","title":"反射 与 自我检查","text":"由 Module 导出的名称可用 names(m::Module) 获得,它会返回一个元素为 Symbol 的数组来表示模块导出的绑定。不管导出状态如何,names(m::Module, all = true) 返回 m 中所有绑定的符号。","category":"page"},{"location":"devdocs/reflection/#DateType-字段","page":"反射 与 自我检查","title":"DateType 字段","text":"","category":"section"},{"location":"devdocs/reflection/","page":"反射 与 自我检查","title":"反射 与 自我检查","text":"DataType 的所有字段名称可以使用 fieldnames 来获取。例如,对于下面给定的类型,fieldnames(Point) 会返回一个表示字段名称的 Symbol 元组:","category":"page"},{"location":"devdocs/reflection/","page":"反射 与 自我检查","title":"反射 与 自我检查","text":"julia> struct Point\n x::Int\n y\n end\n\njulia> fieldnames(Point)\n(:x, :y)","category":"page"},{"location":"devdocs/reflection/","page":"反射 与 自我检查","title":"反射 与 自我检查","text":"Point 对象中每个字段的类型存储在 Point 本身的 types 变量中:","category":"page"},{"location":"devdocs/reflection/","page":"反射 与 自我检查","title":"反射 与 自我检查","text":"julia> Point.types\nsvec(Int64, Any)","category":"page"},{"location":"devdocs/reflection/","page":"反射 与 自我检查","title":"反射 与 自我检查","text":"虽然 x 被注释为 Int,但 y 在类型定义里没有注释,因此 y 默认为 Any 类型。","category":"page"},{"location":"devdocs/reflection/","page":"反射 与 自我检查","title":"反射 与 自我检查","text":"类型本身表示为一个叫做 DataType 的结构:","category":"page"},{"location":"devdocs/reflection/","page":"反射 与 自我检查","title":"反射 与 自我检查","text":"julia> typeof(Point)\nDataType","category":"page"},{"location":"devdocs/reflection/","page":"反射 与 自我检查","title":"反射 与 自我检查","text":"Note that fieldnames(DataType) gives the names for each field of DataType itself, and one of these fields is the types field observed in the example above.","category":"page"},{"location":"devdocs/reflection/#Subtypes","page":"反射 与 自我检查","title":"Subtypes","text":"","category":"section"},{"location":"devdocs/reflection/","page":"反射 与 自我检查","title":"反射 与 自我检查","text":"The direct subtypes of any DataType may be listed using subtypes. For example, the abstract DataType AbstractFloat has four (concrete) subtypes:","category":"page"},{"location":"devdocs/reflection/","page":"反射 与 自我检查","title":"反射 与 自我检查","text":"julia> subtypes(AbstractFloat)\n4-element Vector{Any}:\n BigFloat\n Float16\n Float32\n Float64","category":"page"},{"location":"devdocs/reflection/","page":"反射 与 自我检查","title":"反射 与 自我检查","text":"任何抽象子类型也包括此列表中,但子类型的子类型不在其中。递归使用 subtypes 可以遍历出整个类型树。","category":"page"},{"location":"devdocs/reflection/#DataType-布局","page":"反射 与 自我检查","title":"DataType 布局","text":"","category":"section"},{"location":"devdocs/reflection/","page":"反射 与 自我检查","title":"反射 与 自我检查","text":"用 C 代码接口时,DataType 的内部表现非常重要。有几个函数可以检查这些细节。","category":"page"},{"location":"devdocs/reflection/","page":"反射 与 自我检查","title":"反射 与 自我检查","text":"isbits(T::DataType) 如果 T 类型是以 C 兼容的对齐方式存储,则为 true。 fieldoffset(T::DataType, i::Integer) 返回字段 i 相对于类型开始的 (字节) 偏移量。","category":"page"},{"location":"devdocs/reflection/#函数方法","page":"反射 与 自我检查","title":"函数方法","text":"","category":"section"},{"location":"devdocs/reflection/","page":"反射 与 自我检查","title":"反射 与 自我检查","text":"任何泛型函数的方法都可以使用 methods 来列出。用 methodswith 搜索 方法调度表 来查找 接收给定类型的方法。","category":"page"},{"location":"devdocs/reflection/#扩展和更底层","page":"反射 与 自我检查","title":"扩展和更底层","text":"","category":"section"},{"location":"devdocs/reflection/","page":"反射 与 自我检查","title":"反射 与 自我检查","text":"As discussed in the Metaprogramming section, the macroexpand function gives the unquoted and interpolated expression (Expr) form for a given macro. To use macroexpand, quote the expression block itself (otherwise, the macro will be evaluated and the result will be passed instead!). For example:","category":"page"},{"location":"devdocs/reflection/","page":"反射 与 自我检查","title":"反射 与 自我检查","text":"julia> macroexpand(@__MODULE__, :(@edit println(\"\")) )\n:(InteractiveUtils.edit(println, (Base.typesof)(\"\")))","category":"page"},{"location":"devdocs/reflection/","page":"反射 与 自我检查","title":"反射 与 自我检查","text":"The functions Base.Meta.show_sexpr and dump are used to display S-expr style views and depth-nested detail views for any expression.","category":"page"},{"location":"devdocs/reflection/","page":"反射 与 自我检查","title":"反射 与 自我检查","text":"Finally, the Meta.lower function gives the lowered form of any expression and is of particular interest for understanding how language constructs map to primitive operations such as assignments, branches, and calls:","category":"page"},{"location":"devdocs/reflection/","page":"反射 与 自我检查","title":"反射 与 自我检查","text":"julia> Meta.lower(@__MODULE__, :( [1+2, sin(0.5)] ))\n:($(Expr(:thunk, CodeInfo(\n @ none within `top-level scope`\n1 ─ %1 = 1 + 2\n│ %2 = sin(0.5)\n│ %3 = Base.vect(%1, %2)\n└── return %3\n))))","category":"page"},{"location":"devdocs/reflection/#中间表示和编译后表示","page":"反射 与 自我检查","title":"中间表示和编译后表示","text":"","category":"section"},{"location":"devdocs/reflection/","page":"反射 与 自我检查","title":"反射 与 自我检查","text":"检查函数的底层形式 需要选择所要显示的特定方法,因为泛型函数可能会有许多具有不同类型签名的方法。为此, 用 code_lowered 可以指定代码底层中的方法。 并且可以用 code_typed 来进行类型推断。 code_warntype 增加 code_typed 输出的高亮。","category":"page"},{"location":"devdocs/reflection/","page":"反射 与 自我检查","title":"反射 与 自我检查","text":"更加接近于机器, 一个函数的 LLVM-IR 可以通过使用 code_llvm 打印出。 最终编译的机器码使用 code_native 查看(这将触发 之前未调用过的任何函数的 JIT 编译/代码生成)。","category":"page"},{"location":"devdocs/reflection/","page":"反射 与 自我检查","title":"反射 与 自我检查","text":"为方便起见,上述函数有 宏的版本,它们接受标准函数调用并自动展开参数类型:","category":"page"},{"location":"devdocs/reflection/","page":"反射 与 自我检查","title":"反射 与 自我检查","text":"julia> @code_llvm +(1,1)\n\ndefine i64 @\"julia_+_130862\"(i64, i64) {\ntop:\n %2 = add i64 %1, %0\n ret i64 %2\n}","category":"page"},{"location":"devdocs/reflection/","page":"反射 与 自我检查","title":"反射 与 自我检查","text":"For more informations see @code_lowered, @code_typed, @code_warntype, @code_llvm, and @code_native.","category":"page"},{"location":"devdocs/reflection/#Printing-of-debug-information","page":"反射 与 自我检查","title":"Printing of debug information","text":"","category":"section"},{"location":"devdocs/reflection/","page":"反射 与 自我检查","title":"反射 与 自我检查","text":"The aforementioned functions and macros take the keyword argument debuginfo that controls the level debug information printed.","category":"page"},{"location":"devdocs/reflection/","page":"反射 与 自我检查","title":"反射 与 自我检查","text":"julia> @code_typed debuginfo=:source +(1,1)\nCodeInfo(\n @ int.jl:53 within `+'\n1 ─ %1 = Base.add_int(x, y)::Int64\n└── return %1\n) => Int64","category":"page"},{"location":"devdocs/reflection/","page":"反射 与 自我检查","title":"反射 与 自我检查","text":"Possible values for debuginfo are: :none, :source, and:default. Per default debug information is not printed, but that can be changed by setting Base.IRShow.default_debuginfo[] = :source.","category":"page"},{"location":"manual/code-loading/#code-loading","page":"代码加载","title":"代码加载","text":"","category":"section"},{"location":"manual/code-loading/","page":"代码加载","title":"代码加载","text":"note: Note\n这一章包含了加载包的技术细节。如果要安装包,使用 Julia 的内置包管理器Pkg将包加入到你的活跃环境中。如果要使用已经在你的活跃环境中的包,使用 import X 或 using X,正如在模块中所描述的那样。","category":"page"},{"location":"manual/code-loading/#定义","page":"代码加载","title":"定义","text":"","category":"section"},{"location":"manual/code-loading/","page":"代码加载","title":"代码加载","text":"Julia加载代码有两种机制:","category":"page"},{"location":"manual/code-loading/","page":"代码加载","title":"代码加载","text":"代码包含:例如 include(\"source.jl\")。包含允许你把一个程序拆分为多个源文件。表达式 include(\"source.jl\") 使得文件 source.jl 的内容在出现 include 调用的模块的全局作用域中执行。如果多次调用 include(\"source.jl\"),source.jl 就被执行多次。source.jl 的包含路径解释为相对于出现 include 调用的文件路径。重定位源文件子树因此变得简单。在 REPL 中,包含路径为当前工作目录,即 pwd()。\n加载包:例如 import X 或 using X。import 通过加载包(一个独立的,可重用的 Julia 代码集合,包含在一个模块中),并导入模块内部的名称 X,使得模块 X 可用。 如果在同一个 Julia 会话中,多次导入包 X,那么后续导入模块为第一次导入模块的引用。但请注意,import X 可以在不同的上下文中加载不同的包:X 可以引用主工程中名为 X 的一个包,但它在各个依赖中可以引用不同的、名称同为 X 的包。更多机制说明如下。","category":"page"},{"location":"manual/code-loading/","page":"代码加载","title":"代码加载","text":"代码包含是非常直接和简单的:其在调用者的上下文中解释运行给定的源文件。包加载是建立在代码包含之上的,它具有不同的用途。本章的其余部分将重点介绍程序包加载的行为和机制。","category":"page"},{"location":"manual/code-loading/","page":"代码加载","title":"代码加载","text":"一个 包(package) 就是一个源码树,其标准布局中提供了其他 Julia 项目可以复用的功能。包可以使用 import X 或 using X 语句加载,名为 X 的模块在加载包代码时生成,并在包含该 import 语句的模块中可用。import X 中 X 的含义与上下文有关:程序加载哪个 X 包取决于 import 语句出现的位置。因此,处理 import X 分为两步:首先,确定在此上下文中是哪个包被定义为 X;其次,确定到哪里找特定的 X 包。","category":"page"},{"location":"manual/code-loading/","page":"代码加载","title":"代码加载","text":"这些问题可通过查询各项目文件(Project.toml 或 JuliaProject.toml)、清单文件(Manifest.toml 或 JuliaManifest.toml),或是源文件的文件夹列在LOAD_PATH 中的项目环境解决。","category":"page"},{"location":"manual/code-loading/#Federation-of-packages","page":"代码加载","title":"包的联合生态","text":"","category":"section"},{"location":"manual/code-loading/","page":"代码加载","title":"代码加载","text":"大多数时候,一个包可以通过它的名字唯一确定。但有时在一个项目中,可能需要使用两个有着相同名字的不同的包。尽管你可以通过重命名其中一个包来解决这个问题,但在一个大型的、共享的代码库中被迫做这件事可能是有高度破坏性的。相反,Julia的包加载机制允许相同的包名在一个应用的不同部分指向不同的包。","category":"page"},{"location":"manual/code-loading/","page":"代码加载","title":"代码加载","text":"Julia 支持联合的包管理,这意味着多个独立的部分可以维护公有包、私有包以及包的注册表,并且项目可以依赖于一系列来自不同注册表的公有包和私有包。您也可以使用一组通用工具和工作流(workflow)来安装和管理来自各种注册表的包。Julia 附带的 Pkg 软件包管理器允许安装和管理项目的依赖项,它会帮助创建并操作项目文件(其描述了项目所依赖的其他项目)和清单文件(其为项目完整依赖库的确切版本的快照)。","category":"page"},{"location":"manual/code-loading/","page":"代码加载","title":"代码加载","text":"联合管理的一个可能后果是没有包命名的中央权限。不同组织可以使用相同的名称来引用不相关的包。这并不是没有可能的,因为这些组织可能没有协作,甚至不知道彼此。由于缺乏中央命名权限,单个项目可能最终依赖着具有相同名称的不同包。Julia 的包加载机制不要求包名称是全局唯一的,即使在单个项目的依赖关系图中也是如此。相反,包由通用唯一标识符 (UUID)进行标识,它在每个包创建时进行分配。通常,您不必直接使用这些有点麻烦的 128 位标识符,因为 Pkg 将负责生成和跟踪它们。但是,这些 UUID 为问题「X 所指的包是什么?」提供了确定的答案","category":"page"},{"location":"manual/code-loading/","page":"代码加载","title":"代码加载","text":"由于去中心化的命名问题有些抽象,因此可以通过具体情境来理解问题。假设你正在开发一个名为 App 的应用程序,它使用两个包:Pub 和 Priv。Priv 是你创建的私有包,而 Pub 是你使用但不控制的公共包。当你创建 Priv 时,没有名为 Priv 的公共包。然而,随后一个名为 Priv 的不相关软件包发布并变得流行起来,而且 Pub 包已经开始使用它了。因此,当你下次升级 Pub 以获取最新的错误修复和特性时,App 将依赖于两个名为 Priv 的不同包——尽管你除了升级之外什么都没做。App 直接依赖于你的私有 Priv 包,以及通过 Pub 在新的公共 Priv 包上的间接依赖。由于这两个 Priv 包是不同的,但是 App 继续正常工作依赖于他们两者,因此表达式 import Priv 必须引用不同的 Priv 包,具体取决于它是出现在 App 的代码中还是出现在 Pub 的代码中。为了处理这种情况,Julia 的包加载机制通过 UUID 区分两个 Priv 包并根据它(调用 import 的模块)的上下文选择正确的包。这种区分的工作原理取决于环境,如以下各节所述。","category":"page"},{"location":"manual/code-loading/#环境(Environments)","page":"代码加载","title":"环境(Environments)","text":"","category":"section"},{"location":"manual/code-loading/","page":"代码加载","title":"代码加载","text":"环境决定了 import X 和 using X 语句在不同的代码上下文中的含义以及什么文件会被加载。Julia 有两类环境(environment):","category":"page"},{"location":"manual/code-loading/","page":"代码加载","title":"代码加载","text":"项目环境(project environment)是包含项目文件和清单文件(可选)的目录,并形成一个显式环境。项目文件确定项目的直接依赖项的名称和标识。清单文件(如果存在)提供完整的依赖关系图,包括所有直接和间接依赖关系,每个依赖的确切版本以及定位和加载正确版本的足够信息。\n包目录(package directory)是包含一组包的源码树子目录的目录,并形成一个隐式环境。如果 X 是包目录的子目录并且存在 X/src/X.jl,那么程序包 X 在包目录环境中可用,而 X/src/X.jl 是加载它使用的源文件。","category":"page"},{"location":"manual/code-loading/","page":"代码加载","title":"代码加载","text":"这些环境可以混合并用来创建堆栈环境(stacked environment):是一组有序的项目环境和包目录,重叠为一个复合环境。然后,结合优先级规则和可见性规则,确定哪些包是可用的以及从哪里加载它们。例如,Julia 的负载路径是一个堆栈环境。","category":"page"},{"location":"manual/code-loading/","page":"代码加载","title":"代码加载","text":"这些环境各有不同的用途:","category":"page"},{"location":"manual/code-loading/","page":"代码加载","title":"代码加载","text":"项目环境提供可迁移性。通过将项目环境以及项目源代码的其余部分存放到版本控制(例如一个 git 存储库),您可以重现项目的确切状态和所有依赖项。特别是,清单文件会记录每个依赖项的确切版本,而依赖项由其源码树的加密哈希值标识;这使得 Pkg 可以检索出正确的版本,并确保你正在运行准确的已记录的所有依赖项的代码。\n当不需要完全仔细跟踪的项目环境时,包目录更方便。当你想要把一组包放在某处,并且希望能够直接使用它们而不必为之创建项目环境时,包目录是很实用的。\n堆栈环境允许向基本环境添加工具。您可以将包含开发工具在内的环境堆到堆栈环境的末尾,使它们在 REPL 和脚本中可用,但在包内部不可用。","category":"page"},{"location":"manual/code-loading/","page":"代码加载","title":"代码加载","text":"从更高层次上,每个环境在概念上定义了三个映射:roots、graph 和 paths。当解析 import X 的含义时,roots 和 graph 映射用于确定 X 的身份,同时 paths 映射用于定位 X 的源代码。这三个映射的具体作用是:","category":"page"},{"location":"manual/code-loading/","page":"代码加载","title":"代码加载","text":"roots: name::Symbol ⟶ uuid::UUID\n环境的 roots 映射将包名称分配给UUID,以获取环境可用于主项目的所有顶级依赖项(即可以在 Main 中加载的那些依赖项)。当 Julia 在主项目中遇到 import X 时,它会将 X 的标识作为 roots[:X]。\ngraph: context::UUID ⟶ name::Symbol ⟶ uuid::UUID\n环境的 graph 是一个多级映射,它为每个 context UUID 分配一个从名称到 UUID 的映射——类似于 roots 映射,但专一于那个 context。当 Julia 在 UUID 为 context 的包代码中运行到 import X 时,它会将 X 的标识看作为 graph[context][:X]。正是因为如此,import X 可以根据 context 引用不同的包。\npaths: uuid::UUID × name::Symbol ⟶ path::String\npaths 映射会为每个包分配 UUID-name 对,即该包的入口点源文件的位置。在 import X 中,X 的标识已经通过 roots 或 graph 解析为 UUID(取决于它是从主项目还是从依赖项加载),Julia 确定要加载哪个文件来获取 X 是通过在环境中查找 paths[uuid,:X]。要包含此文件应该定义一个名为 X 的模块。一旦加载了此包,任何解析为相同的 uuid 的后续导入只会创建一个到同一个已加载的包模块的绑定。","category":"page"},{"location":"manual/code-loading/","page":"代码加载","title":"代码加载","text":"每种环境都以不同的方式定义这三种映射,详见以下各节。","category":"page"},{"location":"manual/code-loading/","page":"代码加载","title":"代码加载","text":"note: Note\n为了清楚地说明,本章中的示例包括 roots、graph 和 paths 的完整数据结构。但是,为了提高效率,Julia 的包加载代码并没有显式地创建它们。相反,加载一个给定包只会简单地计算所需的结构。","category":"page"},{"location":"manual/code-loading/#项目环境(Project-environments)","page":"代码加载","title":"项目环境(Project environments)","text":"","category":"section"},{"location":"manual/code-loading/","page":"代码加载","title":"代码加载","text":"项目环境由包含名为 Project.toml 的项目文件的目录以及名为 Manifest.toml 的清单文件(可选)确定。这些文件也可以命名为 JuliaProject.toml 和 JuliaManifest.toml,此时 Project.toml 和 Manifest.toml 被忽略——这允许项目与可能需要名为 Project.toml 和 Manifest.toml 文件的其他重要工具共存。但是对于纯 Julia 项目,名称 Project.toml 和 Manifest.toml 是首选。","category":"page"},{"location":"manual/code-loading/","page":"代码加载","title":"代码加载","text":"项目环境的 roots、graph 和 paths 映射定义如下:","category":"page"},{"location":"manual/code-loading/","page":"代码加载","title":"代码加载","text":"roots 映射 在环境中由其项目文件的内容决定,特别是它的顶级 name 和 uuid 条目及其 [deps] 部分(全部是可选的)。考虑以下一个假想的应用程序 App 的示例项目文件,如先前所述:","category":"page"},{"location":"manual/code-loading/","page":"代码加载","title":"代码加载","text":"name = \"App\"\nuuid = \"8f986787-14fe-4607-ba5d-fbff2944afa9\"\n\n[deps]\nPriv = \"ba13f791-ae1d-465a-978b-69c3ad90f72b\"\nPub = \"c07ecb7d-0dc9-4db7-8803-fadaaeaf08e1\"","category":"page"},{"location":"manual/code-loading/","page":"代码加载","title":"代码加载","text":"如果将它表示为 Julia 字典,那么这个项目文件意味着以下 roots 映射:","category":"page"},{"location":"manual/code-loading/","page":"代码加载","title":"代码加载","text":"roots = Dict(\n :App => UUID(\"8f986787-14fe-4607-ba5d-fbff2944afa9\"),\n :Priv => UUID(\"ba13f791-ae1d-465a-978b-69c3ad90f72b\"),\n :Pub => UUID(\"c07ecb7d-0dc9-4db7-8803-fadaaeaf08e1\"),\n)","category":"page"},{"location":"manual/code-loading/","page":"代码加载","title":"代码加载","text":"基于这个 root 映射,在 App 的代码中,语句 import Priv 将使 Julia 查找 roots[:Priv],这将得到 ba13f791-ae1d-465a-978b-69c3ad90f72b,也就是要在这一部分加载的 Priv 包的 UUID。当主应用程序解释运行到 import Priv 时,此 UUID 标识了要加载和使用的 Priv 包。","category":"page"},{"location":"manual/code-loading/","page":"代码加载","title":"代码加载","text":"依赖图(dependency graph) 在项目环境中其清单文件的内容决定,如果其存在。如果没有清单文件,则 graph 为空。清单文件包含项目的直接或间接依赖项的节(stanza)。对于每个依赖项,该文件列出该包的 UUID 以及源码树的哈希值或源代码的显式路径。考虑以下 App 的示例清单文件:","category":"page"},{"location":"manual/code-loading/","page":"代码加载","title":"代码加载","text":"[[Priv]] # 私有的那个\ndeps = [\"Pub\", \"Zebra\"]\nuuid = \"ba13f791-ae1d-465a-978b-69c3ad90f72b\"\npath = \"deps/Priv\"\n\n[[Priv]] # 公共的那个\nuuid = \"2d15fe94-a1f7-436c-a4d8-07a9a496e01c\"\ngit-tree-sha1 = \"1bf63d3be994fe83456a03b874b409cfd59a6373\"\nversion = \"0.1.5\"\n\n[[Pub]]\nuuid = \"c07ecb7d-0dc9-4db7-8803-fadaaeaf08e1\"\ngit-tree-sha1 = \"9ebd50e2b0dd1e110e842df3b433cb5869b0dd38\"\nversion = \"2.1.4\"\n\n [Pub.deps]\n Priv = \"2d15fe94-a1f7-436c-a4d8-07a9a496e01c\"\n Zebra = \"f7a24cb4-21fc-4002-ac70-f0e3a0dd3f62\"\n\n[[Zebra]]\nuuid = \"f7a24cb4-21fc-4002-ac70-f0e3a0dd3f62\"\ngit-tree-sha1 = \"e808e36a5d7173974b90a15a353b564f3494092f\"\nversion = \"3.4.2\"","category":"page"},{"location":"manual/code-loading/","page":"代码加载","title":"代码加载","text":"这个清单文件描述了 App 项目可能的完整依赖关系图:","category":"page"},{"location":"manual/code-loading/","page":"代码加载","title":"代码加载","text":"应用程序使用两个名为 Priv 的不同包,一个作为根依赖项的私有包,以及一个通过 Pub 作为间接依赖项的公共包。它们通过不同 UUID 来区分,并且有不同的依赖项:\n私有的 Priv 依赖于 Pub 和 Zebra 包。\n公有的 Priv 没有依赖关系。\n该应用程序还依赖于 Pub 包,而后者依赖于公有的 Priv 以及私有的 Priv 包所依赖的那个 Zebra 包。","category":"page"},{"location":"manual/code-loading/","page":"代码加载","title":"代码加载","text":"此依赖图以字典表示后如下所示:","category":"page"},{"location":"manual/code-loading/","page":"代码加载","title":"代码加载","text":"graph = Dict(\n # Priv——私有的那个:\n UUID(\"ba13f791-ae1d-465a-978b-69c3ad90f72b\") => Dict(\n :Pub => UUID(\"c07ecb7d-0dc9-4db7-8803-fadaaeaf08e1\"),\n :Zebra => UUID(\"f7a24cb4-21fc-4002-ac70-f0e3a0dd3f62\"),\n ),\n # Priv——公共的那个:\n UUID(\"2d15fe94-a1f7-436c-a4d8-07a9a496e01c\") => Dict(),\n # Pub:\n UUID(\"c07ecb7d-0dc9-4db7-8803-fadaaeaf08e1\") => Dict(\n :Priv => UUID(\"2d15fe94-a1f7-436c-a4d8-07a9a496e01c\"),\n :Zebra => UUID(\"f7a24cb4-21fc-4002-ac70-f0e3a0dd3f62\"),\n ),\n # Zebra:\n UUID(\"f7a24cb4-21fc-4002-ac70-f0e3a0dd3f62\") => Dict(),\n)","category":"page"},{"location":"manual/code-loading/","page":"代码加载","title":"代码加载","text":"给定这个依赖图,当 Julia 看到 Pub 包中的 import Priv ——它有 UUIDc07ecb7d-0dc9-4db7-8803-fadaaeaf08e1 时,它会查找:","category":"page"},{"location":"manual/code-loading/","page":"代码加载","title":"代码加载","text":"graph[UUID(\"c07ecb7d-0dc9-4db7-8803-fadaaeaf08e1\")][:Priv]","category":"page"},{"location":"manual/code-loading/","page":"代码加载","title":"代码加载","text":"会得到 2d15fe94-a1f7-436c-a4d8-07a9a496e01c,这意味着 Pub 包中的内容,import Priv 指代的是公有的 Priv 内容,而非应用程序直接依赖的私有包。这也是为何 Priv 在主项目中可指代不同的包,而不像其在某个依赖包中另有含义。在包生态中,该特性允许重名的出现。","category":"page"},{"location":"manual/code-loading/","page":"代码加载","title":"代码加载","text":"如果在 App 主代码库中 import Zebra 会如何?因为Zebra 不存在于项目文件,即使它 确实 存在于清单文件中,其导入会是失败的。此外,import Zebra 这个行为若发生在公有的 Priv 包——UUID 为 2d15fe94-a1f7-436c-a4d8-07a9a496e01c 的包中,同样会失败。因为公有的 Priv 包未在清单文件中声明依赖,故而无法加载包。仅有在清单文件:Pub 包和一个 Priv 包中作为显式依赖的包可用于加载 Zebra。","category":"page"},{"location":"manual/code-loading/","page":"代码加载","title":"代码加载","text":"项目环境的 路径映射 从 manifest 文件中提取得到。而包的路径 uuid 和名称 X 则 (循序) 依据这些规则确定。","category":"page"},{"location":"manual/code-loading/","page":"代码加载","title":"代码加载","text":"如果目录中的项目文件与要求的 uuid 以及名称 X 匹配,那么可能出现以下情况的一种:\n若该文件具有顶层 路径 入口,则 uuid 会被映射到该路径,文件的执行与包含项目文件的目录相关。\n此外,uuid 依照包含项目文件的目录,映射至与src/X.jl。\n若非上述情况,且项目文件具有对应的清单文件,且该清单文件包含匹配 uuid 的节(stanza),那么:\n若其具有一个 路径 入口,则使用该路径(与包含清单文件的目录相关)。\n若其具有一个 git-tree-sha1 入口,计算一个确定的 uuid 与 git-tree-sha1 函数——我们把这个函数称为 slug——并在每个 Julia DEPOT_PATH 的全局序列中的目录查询名为 packages/X/$slug 的目录。使用存在的第一个此类目录。","category":"page"},{"location":"manual/code-loading/","page":"代码加载","title":"代码加载","text":"若某些结果成功,源码入口点的路径会是这些结果中的某个,结果的相对路径+src/X.jl;否则,uuid 不存在路径映射。当加载 X 时,如果没找到源码路径,查找即告失败,用户可能会被提示安装适当的包版本或采取其他纠正措施(例如,将 X 声明为某种依赖性)。","category":"page"},{"location":"manual/code-loading/","page":"代码加载","title":"代码加载","text":"在上述样例清单文件中,为找到首个 Priv 包的路径——该包 UUID 为 ba13f791-ae1d-465a-978b-69c3ad90f72b——Julia 寻找其在清单中的节(stanza)。发现其有 路径入口,查看App项目目录中相关的deps/Priv——不妨设App代码在/home/me/projects/App中—则 Julia 发现/home/me/projects/App/deps/Priv存在,并因此从中加载Priv`。","category":"page"},{"location":"manual/code-loading/","page":"代码加载","title":"代码加载","text":"另一方面,如果Julia加载的是带有other Priv 包——即UUID为2d15fe94-a1f7-436c-a4d8-07a9a496e01c——它在清单中找到了它的节,请注意它没有path条目,但是它有一个git-tree-sha1 条目。然后计算这个slug 的UUID/SHA-1对,具体是HDkrT(这个计算的确切细节并不重要,但它是始终一致的和确定的)。这意味着这个Priv包的路径packages/Priv/HDkrT/src/Priv.jl将在其中一个包仓库中。假设DEPOT_PATH 的内容是[\"/home/me/.julia\", \"/usr/local/julia\"],Julia将根据下面的路径来查看它们是否存在:","category":"page"},{"location":"manual/code-loading/","page":"代码加载","title":"代码加载","text":"/home/me/.julia/packages/Priv/HDkrT\n/usr/local/julia/packages/Priv/HDkrT","category":"page"},{"location":"manual/code-loading/","page":"代码加载","title":"代码加载","text":"Julia使用以上路径信息在仓库里依次查找 packages/Priv/HDKrT/src/Priv.jl文件,并从第一个查找到的文件中加载公共的 Priv包。","category":"page"},{"location":"manual/code-loading/","page":"代码加载","title":"代码加载","text":"这是我们的示例App项目环境的可能路径映射的表示, 如上面Manifest 中所提供的依赖关系图, 在 搜索本地文件系统后:","category":"page"},{"location":"manual/code-loading/","page":"代码加载","title":"代码加载","text":"paths = Dict(\n # Priv – the private one:\n (UUID(\"ba13f791-ae1d-465a-978b-69c3ad90f72b\"), :Priv) =>\n # relative entry-point inside `App` repo:\n \"/home/me/projects/App/deps/Priv/src/Priv.jl\",\n # Priv – the public one:\n (UUID(\"2d15fe94-a1f7-436c-a4d8-07a9a496e01c\"), :Priv) =>\n # package installed in the system depot:\n \"/usr/local/julia/packages/Priv/HDkr/src/Priv.jl\",\n # Pub:\n (UUID(\"c07ecb7d-0dc9-4db7-8803-fadaaeaf08e1\"), :Pub) =>\n # package installed in the user depot:\n \"/home/me/.julia/packages/Pub/oKpw/src/Pub.jl\",\n # Zebra:\n (UUID(\"f7a24cb4-21fc-4002-ac70-f0e3a0dd3f62\"), :Zebra) =>\n # package installed in the system depot:\n \"/usr/local/julia/packages/Zebra/me9k/src/Zebra.jl\",\n)","category":"page"},{"location":"manual/code-loading/","page":"代码加载","title":"代码加载","text":"这个例子包含三种不同类型的包位置信息(第一个和第三个是默认加载路径的一部分)","category":"page"},{"location":"manual/code-loading/","page":"代码加载","title":"代码加载","text":"私有 Priv 包 \"vendored\"包括在App仓库中。\n公共 Priv 与 Zebra 包位于系统仓库,系统管理员在此对相关包进行实时安装与管理。这些包允许系统上的所有用户使用。\nPub 包位于用户仓库,用户实时安装的包都储存在此。 这些包仅限原安装用户使用。","category":"page"},{"location":"manual/code-loading/#包目录","page":"代码加载","title":"包目录","text":"","category":"section"},{"location":"manual/code-loading/","page":"代码加载","title":"代码加载","text":"包目录提供了一种更简单的环境,但不能处理名称冲突。在包目录中, 顶层包集合是“类似”包的子目录集合。X包存在于包目录中的条件,是目录包含下列“入口点”文件之一:","category":"page"},{"location":"manual/code-loading/","page":"代码加载","title":"代码加载","text":"X.jl\nX/src/X.jl\nX.jl/src/X.jl","category":"page"},{"location":"manual/code-loading/","page":"代码加载","title":"代码加载","text":"包目录中的包可以导入哪些依赖项,取决于该包是否含有项目文件:","category":"page"},{"location":"manual/code-loading/","page":"代码加载","title":"代码加载","text":"如果它有一个项目文件,那么它只能导入那些在项目文件的[deps] 部分中已标识的包。\n如果没有项目文件,它可以导入任何顶层包,即与在Main 或者 REPL中可加载的包相同。","category":"page"},{"location":"manual/code-loading/","page":"代码加载","title":"代码加载","text":"根图是根据包目录的所有内容而形成的一个列表,包含所有已存在的包。 此外,一个UUID 将被赋予给每一个条目,例如对一个在文件夹X中找到的包","category":"page"},{"location":"manual/code-loading/","page":"代码加载","title":"代码加载","text":"如果X/Project.toml文件存在并且有一个uuid 条目,那么这个 uuid就是上述所要赋予的值。\n如果X/Project.toml文件存在,但没有包含一个顶层UUID条目, 该uuid将是一个虚构的UUID,是对X/Project.toml文件所在的规范(真实的)路径信息进行哈希处理而生成。\n否则(如果Project.toml文件不存在), uuid将是一个全零值 nil UUID。","category":"page"},{"location":"manual/code-loading/","page":"代码加载","title":"代码加载","text":"项目目录的依赖关系图是根据每个包的子目录中其项目文件的存在与否以及内容而形成。规则是:","category":"page"},{"location":"manual/code-loading/","page":"代码加载","title":"代码加载","text":"如果包子目录没有项目文件,则在该图中忽略它, 其代码中的import语句按顶层处理,与main项目和REPL相同。\n如果包子目录有一个项目文件,那么图条目的UUID是项目文件的[deps]映射, 如果该信息项不存在,则视为空。","category":"page"},{"location":"manual/code-loading/","page":"代码加载","title":"代码加载","text":"作为一个例子,假设包目录具有以下结构和内容:","category":"page"},{"location":"manual/code-loading/","page":"代码加载","title":"代码加载","text":"Aardvark/\n src/Aardvark.jl:\n import Bobcat\n import Cobra\n\nBobcat/\n Project.toml:\n [deps]\n Cobra = \"4725e24d-f727-424b-bca0-c4307a3456fa\"\n Dingo = \"7a7925be-828c-4418-bbeb-bac8dfc843bc\"\n\n src/Bobcat.jl:\n import Cobra\n import Dingo\n\nCobra/\n Project.toml:\n uuid = \"4725e24d-f727-424b-bca0-c4307a3456fa\"\n [deps]\n Dingo = \"7a7925be-828c-4418-bbeb-bac8dfc843bc\"\n\n src/Cobra.jl:\n import Dingo\n\nDingo/\n Project.toml:\n uuid = \"7a7925be-828c-4418-bbeb-bac8dfc843bc\"\n\n src/Dingo.jl:\n # no imports","category":"page"},{"location":"manual/code-loading/","page":"代码加载","title":"代码加载","text":"下面是相应的根结构,表示为字典:","category":"page"},{"location":"manual/code-loading/","page":"代码加载","title":"代码加载","text":"roots = Dict(\n :Aardvark => UUID(\"00000000-0000-0000-0000-000000000000\"), # no project file, nil UUID\n :Bobcat => UUID(\"85ad11c7-31f6-5d08-84db-0a4914d4cadf\"), # dummy UUID based on path\n :Cobra => UUID(\"4725e24d-f727-424b-bca0-c4307a3456fa\"), # UUID from project file\n :Dingo => UUID(\"7a7925be-828c-4418-bbeb-bac8dfc843bc\"), # UUID from project file\n)","category":"page"},{"location":"manual/code-loading/","page":"代码加载","title":"代码加载","text":"下面是对应的图结构,表示为字典:","category":"page"},{"location":"manual/code-loading/","page":"代码加载","title":"代码加载","text":"graph = Dict(\n # Bobcat:\n UUID(\"85ad11c7-31f6-5d08-84db-0a4914d4cadf\") => Dict(\n :Cobra => UUID(\"4725e24d-f727-424b-bca0-c4307a3456fa\"),\n :Dingo => UUID(\"7a7925be-828c-4418-bbeb-bac8dfc843bc\"),\n ),\n # Cobra:\n UUID(\"4725e24d-f727-424b-bca0-c4307a3456fa\") => Dict(\n :Dingo => UUID(\"7a7925be-828c-4418-bbeb-bac8dfc843bc\"),\n ),\n # Dingo:\n UUID(\"7a7925be-828c-4418-bbeb-bac8dfc843bc\") => Dict(),\n)","category":"page"},{"location":"manual/code-loading/","page":"代码加载","title":"代码加载","text":"值得注意的一些通用规则:","category":"page"},{"location":"manual/code-loading/","page":"代码加载","title":"代码加载","text":"缺少项目文件的包能依赖于任何顶层依赖项, 并且由于包目录中的每个包在顶层依赖中可用,因此它可以导入在环境中的所有包。\n含有项目文件的包不能依赖于缺少项目文件的包。 因为有项目文件的包只能加载那些在graph中的包,而没有项目文件的包不会出现在graph。\n具有项目文件但没有明确UUID的包只能被由没有项目文件的包所依赖, since dummy UUIDs assigned to these packages are strictly internal.","category":"page"},{"location":"manual/code-loading/","page":"代码加载","title":"代码加载","text":",因为赋予给这些包的虚构UUID全是项目内部的。","category":"page"},{"location":"manual/code-loading/","page":"代码加载","title":"代码加载","text":"Observe the following specific instances of these rules in our example: 请注意以下我们例子中的规则具体实例:","category":"page"},{"location":"manual/code-loading/","page":"代码加载","title":"代码加载","text":"Aardvark 包可以导入Bobcat、Cobra 或Dingo中的所有包;它确实导入Bobcat and Cobra包.\nBobcat 包能导入Cobra与Dingo包。因为它们都有带有UUID的项目文件,并在Bobcat包的[deps]信息项声明为依赖项。\nBobcat包不能依赖于Aardvark包,因为Aardvark包缺少项目文件。\nCobra包能导入Dingo包。因为Dingo包有项目文件和UUID,并在Cobra的[deps] 信息项中声明为依赖项。\nCobra包不能依赖Aardvark或Bobcat包, 因为两者都没有真实的UUID。\nDingo包不能导入任何包,因为它的项目文件中缺少[deps]信息项。","category":"page"},{"location":"manual/code-loading/","page":"代码加载","title":"代码加载","text":"包目录中的路径映射很简单: 它将子目录名映射到相应的入口点路径。换句话说,如果指向我们示例项目目录的路径是/home/me/animals,那么路径映射可以用此字典表示:","category":"page"},{"location":"manual/code-loading/","page":"代码加载","title":"代码加载","text":"paths = Dict(\n (UUID(\"00000000-0000-0000-0000-000000000000\"), :Aardvark) =>\n \"/home/me/AnimalPackages/Aardvark/src/Aardvark.jl\",\n (UUID(\"85ad11c7-31f6-5d08-84db-0a4914d4cadf\"), :Bobcat) =>\n \"/home/me/AnimalPackages/Bobcat/src/Bobcat.jl\",\n (UUID(\"4725e24d-f727-424b-bca0-c4307a3456fa\"), :Cobra) =>\n \"/home/me/AnimalPackages/Cobra/src/Cobra.jl\",\n (UUID(\"7a7925be-828c-4418-bbeb-bac8dfc843bc\"), :Dingo) =>\n \"/home/me/AnimalPackages/Dingo/src/Dingo.jl\",\n)","category":"page"},{"location":"manual/code-loading/","page":"代码加载","title":"代码加载","text":"根据定义,包目录环境中的所有包都是具有预期入口点文件的子目录,因此它们的路径 映射条目始终具有此格式。","category":"page"},{"location":"manual/code-loading/#环境堆栈","page":"代码加载","title":"环境堆栈","text":"","category":"section"},{"location":"manual/code-loading/","page":"代码加载","title":"代码加载","text":"第三种也是最后一种环境是通过覆盖其中的几个环境来组合其他环境,使每个环境中的包在单个组合环境中可用。这些复合环境称为环境堆栈。Julia的LOAD_PATH全局定义一个环境堆栈——Julia进程在其中运行的环境。如果希望Julia进程只能访问一个项目或包目录中的包,请将其设置为LOAD_PATH中的唯一条目。然而,访问一些您喜爱的工具(标准库、探查器、调试器、个人实用程序等)通常是非常有用的,即使它们不是您正在处理的项目的依赖项。通过将包含这些工具的环境添加到加载路径,您可以立即在顶层代码中访问它们,而无需将它们添加到项目中。","category":"page"},{"location":"manual/code-loading/","page":"代码加载","title":"代码加载","text":"组合环境堆栈组件中根、图和路径的数据结构的机制很简单:它们被作为字典进行合并, 在发生键冲突时,优先使用前面的条目而不是后面的条目。换言之,如果我们有stack = [env₁, env₂, …],那么我们有:","category":"page"},{"location":"manual/code-loading/","page":"代码加载","title":"代码加载","text":"roots = reduce(merge, reverse([roots₁, roots₂, …]))\ngraph = reduce(merge, reverse([graph₁, graph₂, …]))\npaths = reduce(merge, reverse([paths₁, paths₂, …]))","category":"page"},{"location":"manual/code-loading/","page":"代码加载","title":"代码加载","text":"带下标的 rootsᵢ, graphᵢ and pathsᵢ变量对应于在stack中包含的下标环境变量envᵢ。 使用reverse 是因为当参数字典中的键之间发生冲突时,使merge 倾向于使用最后一个参数,而不是第一个参数。这种设计有几个值得注意的特点:","category":"page"},{"location":"manual/code-loading/","page":"代码加载","title":"代码加载","text":"主环境——即堆栈中的第一个环境,被准确地嵌入到堆栈环境中。堆栈中第一个环境的完整依赖关系图是必然被完整包括在含有所有相同版本的依赖项的堆栈环境中。\n非主环境中的包能最终使用与其依赖项不兼容的版本,即使它们自己的环境是完全兼容。这种情况可能发生,当它们的一个依赖项被堆栈(通过图或路径,或两者)中某个早期环境中的版本所覆盖。","category":"page"},{"location":"manual/code-loading/","page":"代码加载","title":"代码加载","text":"由于主环境通常是您正在处理的项目所在的环境,而堆栈中稍后的环境包含其他工具, 因此这是正确的权衡:最好改进您的开发工具,但保持项目能工作。当这种不兼容发生时,你通常要将开发工具升级到与主项目兼容的版本。","category":"page"},{"location":"manual/code-loading/#总结","page":"代码加载","title":"总结","text":"","category":"section"},{"location":"manual/code-loading/","page":"代码加载","title":"代码加载","text":"在软件包系统中,联邦软件包管理和精确的软件可复制性是困难但有价值的目标。结合起来,这些目标导致了一个比大多数动态语言更加复杂的包加载机制,但它也产生了通常与静态语言相关的可伸缩性和可复制性。通常,Julia用户应该能够使用内置的包管理器来管理他们的项目,而无需精确理解这些交互细节。通过调用Pkg.add(\"X\")添加X包到对应的项目,并清晰显示相关文件,选择Pkg.activate(\"Y\")后, 可调用import X 即可加载X包,而无需作过多考虑。","category":"page"},{"location":"base/io-network/#I/O-与网络","page":"I/O 与网络","title":"I/O 与网络","text":"","category":"section"},{"location":"base/io-network/#通用-I/O","page":"I/O 与网络","title":"通用 I/O","text":"","category":"section"},{"location":"base/io-network/","page":"I/O 与网络","title":"I/O 与网络","text":"Base.stdout\nBase.stderr\nBase.stdin\nBase.open\nBase.IOStream\nBase.IOBuffer\nBase.take!(::Base.GenericIOBuffer)\nBase.fdio\nBase.flush\nBase.close\nBase.write\nBase.read\nBase.read!\nBase.readbytes!\nBase.unsafe_read\nBase.unsafe_write\nBase.readeach\nBase.peek\nBase.position\nBase.seek\nBase.seekstart\nBase.seekend\nBase.skip\nBase.mark\nBase.unmark\nBase.reset\nBase.ismarked\nBase.eof\nBase.isreadonly\nBase.iswritable\nBase.isreadable\nBase.isopen\nBase.fd\nBase.redirect_stdio\nBase.redirect_stdout\nBase.redirect_stdout(::Function, ::Any)\nBase.redirect_stderr\nBase.redirect_stderr(::Function, ::Any)\nBase.redirect_stdin\nBase.redirect_stdin(::Function, ::Any)\nBase.readchomp\nBase.truncate\nBase.skipchars\nBase.countlines\nBase.PipeBuffer\nBase.readavailable\nBase.IOContext\nBase.IOContext(::IO, ::Pair)\nBase.IOContext(::IO, ::IOContext)","category":"page"},{"location":"base/io-network/#Base.stdout","page":"I/O 与网络","title":"Base.stdout","text":"stdout::IO\n\nGlobal variable referring to the standard out stream.\n\n\n\n\n\n","category":"constant"},{"location":"base/io-network/#Base.stderr","page":"I/O 与网络","title":"Base.stderr","text":"stderr::IO\n\nGlobal variable referring to the standard error stream.\n\n\n\n\n\n","category":"constant"},{"location":"base/io-network/#Base.stdin","page":"I/O 与网络","title":"Base.stdin","text":"stdin::IO\n\nGlobal variable referring to the standard input stream.\n\n\n\n\n\n","category":"constant"},{"location":"base/io-network/#Base.open","page":"I/O 与网络","title":"Base.open","text":"open(f::Function, args...; kwargs...)\n\nApply the function f to the result of open(args...; kwargs...) and close the resulting file descriptor upon completion.\n\nExamples\n\njulia> open(\"myfile.txt\", \"w\") do io\n write(io, \"Hello world!\")\n end;\n\njulia> open(f->read(f, String), \"myfile.txt\")\n\"Hello world!\"\n\njulia> rm(\"myfile.txt\")\n\n\n\n\n\nopen(filename::AbstractString; lock = true, keywords...) -> IOStream\n\nOpen a file in a mode specified by five boolean keyword arguments:\n\nKeyword Description Default\nread open for reading !write\nwrite open for writing truncate | append\ncreate create if non-existent !read & write | truncate | append\ntruncate truncate to zero size !read & write\nappend seek to end false\n\nThe default when no keywords are passed is to open files for reading only. Returns a stream for accessing the opened file.\n\nThe lock keyword argument controls whether operations will be locked for safe multi-threaded access.\n\ncompat: Julia 1.5\nThe lock argument is available as of Julia 1.5.\n\n\n\n\n\nopen(filename::AbstractString, [mode::AbstractString]; lock = true) -> IOStream\n\nAlternate syntax for open, where a string-based mode specifier is used instead of the five booleans. The values of mode correspond to those from fopen(3) or Perl open, and are equivalent to setting the following boolean groups:\n\nMode Description Keywords\nr read none\nw write, create, truncate write = true\na write, create, append append = true\nr+ read, write read = true, write = true\nw+ read, write, create, truncate truncate = true, read = true\na+ read, write, create, append append = true, read = true\n\nThe lock keyword argument controls whether operations will be locked for safe multi-threaded access.\n\nExamples\n\njulia> io = open(\"myfile.txt\", \"w\");\n\njulia> write(io, \"Hello world!\");\n\njulia> close(io);\n\njulia> io = open(\"myfile.txt\", \"r\");\n\njulia> read(io, String)\n\"Hello world!\"\n\njulia> write(io, \"This file is read only\")\nERROR: ArgumentError: write failed, IOStream is not writeable\n[...]\n\njulia> close(io)\n\njulia> io = open(\"myfile.txt\", \"a\");\n\njulia> write(io, \"This stream is not read only\")\n28\n\njulia> close(io)\n\njulia> rm(\"myfile.txt\")\n\ncompat: Julia 1.5\nThe lock argument is available as of Julia 1.5.\n\n\n\n\n\nopen(fd::OS_HANDLE) -> IO\n\nTake a raw file descriptor wrap it in a Julia-aware IO type, and take ownership of the fd handle. Call open(Libc.dup(fd)) to avoid the ownership capture of the original handle.\n\nwarning: Warning\nDo not call this on a handle that's already owned by some other part of the system.\n\n\n\n\n\nopen(command, mode::AbstractString, stdio=devnull)\n\nRun command asynchronously. Like open(command, stdio; read, write) except specifying the read and write flags via a mode string instead of keyword arguments. Possible mode strings are:\n\nMode Description Keywords\nr read none\nw write write = true\nr+ read, write read = true, write = true\nw+ read, write read = true, write = true\n\n\n\n\n\nopen(command, stdio=devnull; write::Bool = false, read::Bool = !write)\n\nStart running command asynchronously, and return a process::IO object. If read is true, then reads from the process come from the process's standard output and stdio optionally specifies the process's standard input stream. If write is true, then writes go to the process's standard input and stdio optionally specifies the process's standard output stream. The process's standard error stream is connected to the current global stderr.\n\n\n\n\n\nopen(f::Function, command, args...; kwargs...)\n\nSimilar to open(command, args...; kwargs...), but calls f(stream) on the resulting process stream, then closes the input stream and waits for the process to complete. Return the value returned by f on success. Throw an error if the process failed, or if the process attempts to print anything to stdout.\n\n\n\n\n\n","category":"function"},{"location":"base/io-network/#Base.IOStream","page":"I/O 与网络","title":"Base.IOStream","text":"IOStream\n\nA buffered IO stream wrapping an OS file descriptor. Mostly used to represent files returned by open.\n\n\n\n\n\n","category":"type"},{"location":"base/io-network/#Base.IOBuffer","page":"I/O 与网络","title":"Base.IOBuffer","text":"IOBuffer([data::AbstractVector{UInt8}]; keywords...) -> IOBuffer\n\nCreate an in-memory I/O stream, which may optionally operate on a pre-existing array.\n\nIt may take optional keyword arguments:\n\nread, write, append: restricts operations to the buffer; see open for details.\ntruncate: truncates the buffer size to zero length.\nmaxsize: specifies a size beyond which the buffer may not be grown.\nsizehint: suggests a capacity of the buffer (data must implement sizehint!(data, size)).\n\nWhen data is not given, the buffer will be both readable and writable by default.\n\nExamples\n\njulia> io = IOBuffer();\n\njulia> write(io, \"JuliaLang is a GitHub organization.\", \" It has many members.\")\n56\n\njulia> String(take!(io))\n\"JuliaLang is a GitHub organization. It has many members.\"\n\njulia> io = IOBuffer(b\"JuliaLang is a GitHub organization.\")\nIOBuffer(data=UInt8[...], readable=true, writable=false, seekable=true, append=false, size=35, maxsize=Inf, ptr=1, mark=-1)\n\njulia> read(io, String)\n\"JuliaLang is a GitHub organization.\"\n\njulia> write(io, \"This isn't writable.\")\nERROR: ArgumentError: ensureroom failed, IOBuffer is not writeable\n\njulia> io = IOBuffer(UInt8[], read=true, write=true, maxsize=34)\nIOBuffer(data=UInt8[...], readable=true, writable=true, seekable=true, append=false, size=0, maxsize=34, ptr=1, mark=-1)\n\njulia> write(io, \"JuliaLang is a GitHub organization.\")\n34\n\njulia> String(take!(io))\n\"JuliaLang is a GitHub organization\"\n\njulia> length(read(IOBuffer(b\"data\", read=true, truncate=false)))\n4\n\njulia> length(read(IOBuffer(b\"data\", read=true, truncate=true)))\n0\n\n\n\n\n\nIOBuffer(string::String)\n\nCreate a read-only IOBuffer on the data underlying the given string.\n\nExamples\n\njulia> io = IOBuffer(\"Haho\");\n\njulia> String(take!(io))\n\"Haho\"\n\njulia> String(take!(io))\n\"Haho\"\n\n\n\n\n\n","category":"type"},{"location":"base/io-network/#Base.take!-Tuple{Base.GenericIOBuffer}","page":"I/O 与网络","title":"Base.take!","text":"take!(b::IOBuffer)\n\nObtain the contents of an IOBuffer as an array. Afterwards, the IOBuffer is reset to its initial state.\n\nExamples\n\njulia> io = IOBuffer();\n\njulia> write(io, \"JuliaLang is a GitHub organization.\", \" It has many members.\")\n56\n\njulia> String(take!(io))\n\"JuliaLang is a GitHub organization. It has many members.\"\n\n\n\n\n\n","category":"method"},{"location":"base/io-network/#Base.fdio","page":"I/O 与网络","title":"Base.fdio","text":"fdio([name::AbstractString, ]fd::Integer[, own::Bool=false]) -> IOStream\n\nCreate an IOStream object from an integer file descriptor. If own is true, closing this object will close the underlying descriptor. By default, an IOStream is closed when it is garbage collected. name allows you to associate the descriptor with a named file.\n\n\n\n\n\n","category":"function"},{"location":"base/io-network/#Base.flush","page":"I/O 与网络","title":"Base.flush","text":"flush(stream)\n\nCommit all currently buffered writes to the given stream.\n\n\n\n\n\n","category":"function"},{"location":"base/io-network/#Base.close","page":"I/O 与网络","title":"Base.close","text":"close(stream)\n\nClose an I/O stream. Performs a flush first.\n\n\n\n\n\n","category":"function"},{"location":"base/io-network/#Base.write","page":"I/O 与网络","title":"Base.write","text":"write(io::IO, x)\nwrite(filename::AbstractString, x)\n\nWrite the canonical binary representation of a value to the given I/O stream or file. Return the number of bytes written into the stream. See also print to write a text representation (with an encoding that may depend upon io).\n\nThe endianness of the written value depends on the endianness of the host system. Convert to/from a fixed endianness when writing/reading (e.g. using htol and ltoh) to get results that are consistent across platforms.\n\nYou can write multiple values with the same write call. i.e. the following are equivalent:\n\nwrite(io, x, y...)\nwrite(io, x) + write(io, y...)\n\nExamples\n\nConsistent serialization:\n\njulia> fname = tempname(); # random temporary filename\n\njulia> open(fname,\"w\") do f\n # Make sure we write 64bit integer in little-endian byte order\n write(f,htol(Int64(42)))\n end\n8\n\njulia> open(fname,\"r\") do f\n # Convert back to host byte order and host integer type\n Int(ltoh(read(f,Int64)))\n end\n42\n\nMerging write calls:\n\njulia> io = IOBuffer();\n\njulia> write(io, \"JuliaLang is a GitHub organization.\", \" It has many members.\")\n56\n\njulia> String(take!(io))\n\"JuliaLang is a GitHub organization. It has many members.\"\n\njulia> write(io, \"Sometimes those members\") + write(io, \" write documentation.\")\n44\n\njulia> String(take!(io))\n\"Sometimes those members write documentation.\"\n\nUser-defined plain-data types without write methods can be written when wrapped in a Ref:\n\njulia> struct MyStruct; x::Float64; end\n\njulia> io = IOBuffer()\nIOBuffer(data=UInt8[...], readable=true, writable=true, seekable=true, append=false, size=0, maxsize=Inf, ptr=1, mark=-1)\n\njulia> write(io, Ref(MyStruct(42.0)))\n8\n\njulia> seekstart(io); read!(io, Ref(MyStruct(NaN)))\nBase.RefValue{MyStruct}(MyStruct(42.0))\n\n\n\n\n\n","category":"function"},{"location":"base/io-network/#Base.read","page":"I/O 与网络","title":"Base.read","text":"read(io::IO, T)\n\nRead a single value of type T from io, in canonical binary representation.\n\nNote that Julia does not convert the endianness for you. Use ntoh or ltoh for this purpose.\n\nread(io::IO, String)\n\nRead the entirety of io, as a String (see also readchomp).\n\nExamples\n\njulia> io = IOBuffer(\"JuliaLang is a GitHub organization\");\n\njulia> read(io, Char)\n'J': ASCII/Unicode U+004A (category Lu: Letter, uppercase)\n\njulia> io = IOBuffer(\"JuliaLang is a GitHub organization\");\n\njulia> read(io, String)\n\"JuliaLang is a GitHub organization\"\n\n\n\n\n\nread(filename::AbstractString, args...)\n\nOpen a file and read its contents. args is passed to read: this is equivalent to open(io->read(io, args...), filename).\n\nread(filename::AbstractString, String)\n\nRead the entire contents of a file as a string.\n\n\n\n\n\nread(s::IO, nb=typemax(Int))\n\nRead at most nb bytes from s, returning a Vector{UInt8} of the bytes read.\n\n\n\n\n\nread(s::IOStream, nb::Integer; all=true)\n\nRead at most nb bytes from s, returning a Vector{UInt8} of the bytes read.\n\nIf all is true (the default), this function will block repeatedly trying to read all requested bytes, until an error or end-of-file occurs. If all is false, at most one read call is performed, and the amount of data returned is device-dependent. Note that not all stream types support the all option.\n\n\n\n\n\nread(command::Cmd)\n\nRun command and return the resulting output as an array of bytes.\n\n\n\n\n\nread(command::Cmd, String)\n\nRun command and return the resulting output as a String.\n\n\n\n\n\n","category":"function"},{"location":"base/io-network/#Base.read!","page":"I/O 与网络","title":"Base.read!","text":"read!(stream::IO, array::AbstractArray)\nread!(filename::AbstractString, array::AbstractArray)\n\nRead binary data from an I/O stream or file, filling in array.\n\n\n\n\n\n","category":"function"},{"location":"base/io-network/#Base.readbytes!","page":"I/O 与网络","title":"Base.readbytes!","text":"readbytes!(stream::IO, b::AbstractVector{UInt8}, nb=length(b))\n\nRead at most nb bytes from stream into b, returning the number of bytes read. The size of b will be increased if needed (i.e. if nb is greater than length(b) and enough bytes could be read), but it will never be decreased.\n\n\n\n\n\nreadbytes!(stream::IOStream, b::AbstractVector{UInt8}, nb=length(b); all::Bool=true)\n\nRead at most nb bytes from stream into b, returning the number of bytes read. The size of b will be increased if needed (i.e. if nb is greater than length(b) and enough bytes could be read), but it will never be decreased.\n\nIf all is true (the default), this function will block repeatedly trying to read all requested bytes, until an error or end-of-file occurs. If all is false, at most one read call is performed, and the amount of data returned is device-dependent. Note that not all stream types support the all option.\n\n\n\n\n\n","category":"function"},{"location":"base/io-network/#Base.unsafe_read","page":"I/O 与网络","title":"Base.unsafe_read","text":"unsafe_read(io::IO, ref, nbytes::UInt)\n\nCopy nbytes from the IO stream object into ref (converted to a pointer).\n\nIt is recommended that subtypes T<:IO override the following method signature to provide more efficient implementations: unsafe_read(s::T, p::Ptr{UInt8}, n::UInt)\n\n\n\n\n\n","category":"function"},{"location":"base/io-network/#Base.unsafe_write","page":"I/O 与网络","title":"Base.unsafe_write","text":"unsafe_write(io::IO, ref, nbytes::UInt)\n\nCopy nbytes from ref (converted to a pointer) into the IO object.\n\nIt is recommended that subtypes T<:IO override the following method signature to provide more efficient implementations: unsafe_write(s::T, p::Ptr{UInt8}, n::UInt)\n\n\n\n\n\n","category":"function"},{"location":"base/io-network/#Base.readeach","page":"I/O 与网络","title":"Base.readeach","text":"readeach(io::IO, T)\n\nReturn an iterable object yielding read(io, T).\n\nSee also skipchars, eachline, readuntil.\n\ncompat: Julia 1.6\nreadeach requires Julia 1.6 or later.\n\nExamples\n\njulia> io = IOBuffer(\"JuliaLang is a GitHub organization.\\n It has many members.\\n\");\n\njulia> for c in readeach(io, Char)\n c == '\\n' && break\n print(c)\n end\nJuliaLang is a GitHub organization.\n\n\n\n\n\n","category":"function"},{"location":"base/io-network/#Base.peek","page":"I/O 与网络","title":"Base.peek","text":"peek(stream[, T=UInt8])\n\nRead and return a value of type T from a stream without advancing the current position in the stream.\n\nExamples\n\njulia> b = IOBuffer(\"julia\");\n\njulia> peek(b)\n0x6a\n\njulia> position(b)\n0\n\njulia> peek(b, Char)\n'j': ASCII/Unicode U+006A (category Ll: Letter, lowercase)\n\ncompat: Julia 1.5\nThe method which accepts a type requires Julia 1.5 or later.\n\n\n\n\n\n","category":"function"},{"location":"base/io-network/#Base.position","page":"I/O 与网络","title":"Base.position","text":"position(s)\n\nGet the current position of a stream.\n\nExamples\n\njulia> io = IOBuffer(\"JuliaLang is a GitHub organization.\");\n\njulia> seek(io, 5);\n\njulia> position(io)\n5\n\njulia> skip(io, 10);\n\njulia> position(io)\n15\n\njulia> seekend(io);\n\njulia> position(io)\n35\n\n\n\n\n\n","category":"function"},{"location":"base/io-network/#Base.seek","page":"I/O 与网络","title":"Base.seek","text":"seek(s, pos)\n\nSeek a stream to the given position.\n\nExamples\n\njulia> io = IOBuffer(\"JuliaLang is a GitHub organization.\");\n\njulia> seek(io, 5);\n\njulia> read(io, Char)\n'L': ASCII/Unicode U+004C (category Lu: Letter, uppercase)\n\n\n\n\n\n","category":"function"},{"location":"base/io-network/#Base.seekstart","page":"I/O 与网络","title":"Base.seekstart","text":"seekstart(s)\n\nSeek a stream to its beginning.\n\nExamples\n\njulia> io = IOBuffer(\"JuliaLang is a GitHub organization.\");\n\njulia> seek(io, 5);\n\njulia> read(io, Char)\n'L': ASCII/Unicode U+004C (category Lu: Letter, uppercase)\n\njulia> seekstart(io);\n\njulia> read(io, Char)\n'J': ASCII/Unicode U+004A (category Lu: Letter, uppercase)\n\n\n\n\n\n","category":"function"},{"location":"base/io-network/#Base.seekend","page":"I/O 与网络","title":"Base.seekend","text":"seekend(s)\n\nSeek a stream to its end.\n\n\n\n\n\n","category":"function"},{"location":"base/io-network/#Base.skip","page":"I/O 与网络","title":"Base.skip","text":"skip(s, offset)\n\nSeek a stream relative to the current position.\n\nExamples\n\njulia> io = IOBuffer(\"JuliaLang is a GitHub organization.\");\n\njulia> seek(io, 5);\n\njulia> skip(io, 10);\n\njulia> read(io, Char)\n'G': ASCII/Unicode U+0047 (category Lu: Letter, uppercase)\n\n\n\n\n\n","category":"function"},{"location":"base/io-network/#Base.mark","page":"I/O 与网络","title":"Base.mark","text":"mark(s::IO)\n\nAdd a mark at the current position of stream s. Return the marked position.\n\nSee also unmark, reset, ismarked.\n\n\n\n\n\n","category":"function"},{"location":"base/io-network/#Base.unmark","page":"I/O 与网络","title":"Base.unmark","text":"unmark(s::IO)\n\nRemove a mark from stream s. Return true if the stream was marked, false otherwise.\n\nSee also mark, reset, ismarked.\n\n\n\n\n\n","category":"function"},{"location":"base/io-network/#Base.reset","page":"I/O 与网络","title":"Base.reset","text":"reset(s::IO)\n\nReset a stream s to a previously marked position, and remove the mark. Return the previously marked position. Throw an error if the stream is not marked.\n\nSee also mark, unmark, ismarked.\n\n\n\n\n\nreset(::Event)\n\nReset an Event back into an un-set state. Then any future calls to wait will block until notify is called again.\n\n\n\n\n\n","category":"function"},{"location":"base/io-network/#Base.ismarked","page":"I/O 与网络","title":"Base.ismarked","text":"ismarked(s::IO)\n\nReturn true if stream s is marked.\n\nSee also mark, unmark, reset.\n\n\n\n\n\n","category":"function"},{"location":"base/io-network/#Base.eof","page":"I/O 与网络","title":"Base.eof","text":"eof(stream) -> Bool\n\nTest whether an I/O stream is at end-of-file. If the stream is not yet exhausted, this function will block to wait for more data if necessary, and then return false. Therefore it is always safe to read one byte after seeing eof return false. eof will return false as long as buffered data is still available, even if the remote end of a connection is closed.\n\n\n\n\n\n","category":"function"},{"location":"base/io-network/#Base.isreadonly","page":"I/O 与网络","title":"Base.isreadonly","text":"isreadonly(io) -> Bool\n\nDetermine whether a stream is read-only.\n\nExamples\n\njulia> io = IOBuffer(\"JuliaLang is a GitHub organization\");\n\njulia> isreadonly(io)\ntrue\n\njulia> io = IOBuffer();\n\njulia> isreadonly(io)\nfalse\n\n\n\n\n\n","category":"function"},{"location":"base/io-network/#Base.iswritable","page":"I/O 与网络","title":"Base.iswritable","text":"iswritable(io) -> Bool\n\nReturn false if the specified IO object is not writable.\n\nExamples\n\njulia> open(\"myfile.txt\", \"w\") do io\n print(io, \"Hello world!\");\n iswritable(io)\n end\ntrue\n\njulia> open(\"myfile.txt\", \"r\") do io\n iswritable(io)\n end\nfalse\n\njulia> rm(\"myfile.txt\")\n\n\n\n\n\n","category":"function"},{"location":"base/io-network/#Base.isreadable","page":"I/O 与网络","title":"Base.isreadable","text":"isreadable(io) -> Bool\n\nReturn false if the specified IO object is not readable.\n\nExamples\n\njulia> open(\"myfile.txt\", \"w\") do io\n print(io, \"Hello world!\");\n isreadable(io)\n end\nfalse\n\njulia> open(\"myfile.txt\", \"r\") do io\n isreadable(io)\n end\ntrue\n\njulia> rm(\"myfile.txt\")\n\n\n\n\n\n","category":"function"},{"location":"base/io-network/#Base.isopen","page":"I/O 与网络","title":"Base.isopen","text":"isopen(object) -> Bool\n\nDetermine whether an object - such as a stream or timer – is not yet closed. Once an object is closed, it will never produce a new event. However, since a closed stream may still have data to read in its buffer, use eof to check for the ability to read data. Use the FileWatching package to be notified when a stream might be writable or readable.\n\nExamples\n\njulia> io = open(\"my_file.txt\", \"w+\");\n\njulia> isopen(io)\ntrue\n\njulia> close(io)\n\njulia> isopen(io)\nfalse\n\n\n\n\n\n","category":"function"},{"location":"base/io-network/#Base.fd","page":"I/O 与网络","title":"Base.fd","text":"fd(stream)\n\nReturn the file descriptor backing the stream or file. Note that this function only applies to synchronous File's and IOStream's not to any of the asynchronous streams.\n\n\n\n\n\n","category":"function"},{"location":"base/io-network/#Base.redirect_stdio","page":"I/O 与网络","title":"Base.redirect_stdio","text":"redirect_stdio(;stdin=stdin, stderr=stderr, stdout=stdout)\n\nRedirect a subset of the streams stdin, stderr, stdout. Each argument must be an IOStream, TTY, Pipe, socket, or devnull.\n\ncompat: Julia 1.7\nredirect_stdio requires Julia 1.7 or later.\n\n\n\n\n\nredirect_stdio(f; stdin=nothing, stderr=nothing, stdout=nothing)\n\nRedirect a subset of the streams stdin, stderr, stdout, call f() and restore each stream.\n\nPossible values for each stream are:\n\nnothing indicating the stream should not be redirected.\npath::AbstractString redirecting the stream to the file at path.\nio an IOStream, TTY, Pipe, socket, or devnull.\n\nExamples\n\njulia> redirect_stdio(stdout=\"stdout.txt\", stderr=\"stderr.txt\") do\n print(\"hello stdout\")\n print(stderr, \"hello stderr\")\n end\n\njulia> read(\"stdout.txt\", String)\n\"hello stdout\"\n\njulia> read(\"stderr.txt\", String)\n\"hello stderr\"\n\nEdge cases\n\nIt is possible to pass the same argument to stdout and stderr:\n\njulia> redirect_stdio(stdout=\"log.txt\", stderr=\"log.txt\", stdin=devnull) do\n ...\nend\n\nHowever it is not supported to pass two distinct descriptors of the same file.\n\njulia> io1 = open(\"same/path\", \"w\")\n\njulia> io2 = open(\"same/path\", \"w\")\n\njulia> redirect_stdio(f, stdout=io1, stderr=io2) # not suppored\n\nAlso the stdin argument may not be the same descriptor as stdout or stderr.\n\njulia> io = open(...)\n\njulia> redirect_stdio(f, stdout=io, stdin=io) # not supported\n\ncompat: Julia 1.7\nredirect_stdio requires Julia 1.7 or later.\n\n\n\n\n\n","category":"function"},{"location":"base/io-network/#Base.redirect_stdout","page":"I/O 与网络","title":"Base.redirect_stdout","text":"redirect_stdout([stream]) -> stream\n\nCreate a pipe to which all C and Julia level stdout output will be redirected. Return a stream representing the pipe ends. Data written to stdout may now be read from the rd end of the pipe.\n\nnote: Note\nstream must be a compatible objects, such as an IOStream, TTY, Pipe, socket, or devnull.\n\nSee also redirect_stdio.\n\n\n\n\n\n","category":"function"},{"location":"base/io-network/#Base.redirect_stdout-Tuple{Function, Any}","page":"I/O 与网络","title":"Base.redirect_stdout","text":"redirect_stdout(f::Function, stream)\n\nRun the function f while redirecting stdout to stream. Upon completion, stdout is restored to its prior setting.\n\n\n\n\n\n","category":"method"},{"location":"base/io-network/#Base.redirect_stderr","page":"I/O 与网络","title":"Base.redirect_stderr","text":"redirect_stderr([stream]) -> stream\n\nLike redirect_stdout, but for stderr.\n\nnote: Note\nstream must be a compatible objects, such as an IOStream, TTY, Pipe, socket, or devnull.\n\nSee also redirect_stdio.\n\n\n\n\n\n","category":"function"},{"location":"base/io-network/#Base.redirect_stderr-Tuple{Function, Any}","page":"I/O 与网络","title":"Base.redirect_stderr","text":"redirect_stderr(f::Function, stream)\n\nRun the function f while redirecting stderr to stream. Upon completion, stderr is restored to its prior setting.\n\n\n\n\n\n","category":"method"},{"location":"base/io-network/#Base.redirect_stdin","page":"I/O 与网络","title":"Base.redirect_stdin","text":"redirect_stdin([stream]) -> stream\n\nLike redirect_stdout, but for stdin. Note that the direction of the stream is reversed.\n\nnote: Note\nstream must be a compatible objects, such as an IOStream, TTY, Pipe, socket, or devnull.\n\nSee also redirect_stdio.\n\n\n\n\n\n","category":"function"},{"location":"base/io-network/#Base.redirect_stdin-Tuple{Function, Any}","page":"I/O 与网络","title":"Base.redirect_stdin","text":"redirect_stdin(f::Function, stream)\n\nRun the function f while redirecting stdin to stream. Upon completion, stdin is restored to its prior setting.\n\n\n\n\n\n","category":"method"},{"location":"base/io-network/#Base.readchomp","page":"I/O 与网络","title":"Base.readchomp","text":"readchomp(x)\n\nRead the entirety of x as a string and remove a single trailing newline if there is one. Equivalent to chomp(read(x, String)).\n\nExamples\n\njulia> open(\"my_file.txt\", \"w\") do io\n write(io, \"JuliaLang is a GitHub organization.\\nIt has many members.\\n\");\n end;\n\njulia> readchomp(\"my_file.txt\")\n\"JuliaLang is a GitHub organization.\\nIt has many members.\"\n\njulia> rm(\"my_file.txt\");\n\n\n\n\n\n","category":"function"},{"location":"base/io-network/#Base.truncate","page":"I/O 与网络","title":"Base.truncate","text":"truncate(file, n)\n\nResize the file or buffer given by the first argument to exactly n bytes, filling previously unallocated space with '\\0' if the file or buffer is grown.\n\nExamples\n\njulia> io = IOBuffer();\n\njulia> write(io, \"JuliaLang is a GitHub organization.\")\n35\n\njulia> truncate(io, 15)\nIOBuffer(data=UInt8[...], readable=true, writable=true, seekable=true, append=false, size=15, maxsize=Inf, ptr=16, mark=-1)\n\njulia> String(take!(io))\n\"JuliaLang is a \"\n\njulia> io = IOBuffer();\n\njulia> write(io, \"JuliaLang is a GitHub organization.\");\n\njulia> truncate(io, 40);\n\njulia> String(take!(io))\n\"JuliaLang is a GitHub organization.\\0\\0\\0\\0\\0\"\n\n\n\n\n\n","category":"function"},{"location":"base/io-network/#Base.skipchars","page":"I/O 与网络","title":"Base.skipchars","text":"skipchars(predicate, io::IO; linecomment=nothing)\n\nAdvance the stream io such that the next-read character will be the first remaining for which predicate returns false. If the keyword argument linecomment is specified, all characters from that character until the start of the next line are ignored.\n\nExamples\n\njulia> buf = IOBuffer(\" text\")\nIOBuffer(data=UInt8[...], readable=true, writable=false, seekable=true, append=false, size=8, maxsize=Inf, ptr=1, mark=-1)\n\njulia> skipchars(isspace, buf)\nIOBuffer(data=UInt8[...], readable=true, writable=false, seekable=true, append=false, size=8, maxsize=Inf, ptr=5, mark=-1)\n\njulia> String(readavailable(buf))\n\"text\"\n\n\n\n\n\n","category":"function"},{"location":"base/io-network/#Base.countlines","page":"I/O 与网络","title":"Base.countlines","text":"countlines(io::IO; eol::AbstractChar = '\\n')\n\nRead io until the end of the stream/file and count the number of lines. To specify a file pass the filename as the first argument. EOL markers other than '\\n' are supported by passing them as the second argument. The last non-empty line of io is counted even if it does not end with the EOL, matching the length returned by eachline and readlines.\n\nTo count lines of a String, countlines(IOBuffer(str)) can be used.\n\nExamples\n\njulia> io = IOBuffer(\"JuliaLang is a GitHub organization.\\n\");\n\njulia> countlines(io)\n1\n\njulia> io = IOBuffer(\"JuliaLang is a GitHub organization.\");\n\njulia> countlines(io)\n1\n\njulia> eof(io) # counting lines moves the file pointer\ntrue\n\njulia> io = IOBuffer(\"JuliaLang is a GitHub organization.\");\n\njulia> countlines(io, eol = '.')\n1\n\n\n\n\n\n","category":"function"},{"location":"base/io-network/#Base.PipeBuffer","page":"I/O 与网络","title":"Base.PipeBuffer","text":"PipeBuffer(data::Vector{UInt8}=UInt8[]; maxsize::Integer = typemax(Int))\n\nAn IOBuffer that allows reading and performs writes by appending. Seeking and truncating are not supported. See IOBuffer for the available constructors. If data is given, creates a PipeBuffer to operate on a data vector, optionally specifying a size beyond which the underlying Array may not be grown.\n\n\n\n\n\n","category":"function"},{"location":"base/io-network/#Base.readavailable","page":"I/O 与网络","title":"Base.readavailable","text":"readavailable(stream)\n\nRead available buffered data from a stream. Actual I/O is performed only if no data has already been buffered. The result is a Vector{UInt8}.\n\nwarning: Warning\nThe amount of data returned is implementation-dependent; for example it can depend on the internal choice of buffer size. Other functions such as read should generally be used instead.\n\n\n\n\n\n","category":"function"},{"location":"base/io-network/#Base.IOContext","page":"I/O 与网络","title":"Base.IOContext","text":"IOContext\n\nIOContext provides a mechanism for passing output configuration settings among show methods.\n\nIn short, it is an immutable dictionary that is a subclass of IO. It supports standard dictionary operations such as getindex, and can also be used as an I/O stream.\n\n\n\n\n\n","category":"type"},{"location":"base/io-network/#Base.IOContext-Tuple{IO, Pair}","page":"I/O 与网络","title":"Base.IOContext","text":"IOContext(io::IO, KV::Pair...)\n\nCreate an IOContext that wraps a given stream, adding the specified key=>value pairs to the properties of that stream (note that io can itself be an IOContext).\n\nuse (key => value) in io to see if this particular combination is in the properties set\nuse get(io, key, default) to retrieve the most recent value for a particular key\n\nThe following properties are in common use:\n\n:compact: Boolean specifying that values should be printed more compactly, e.g. that numbers should be printed with fewer digits. This is set when printing array elements. :compact output should not contain line breaks.\n:limit: Boolean specifying that containers should be truncated, e.g. showing … in place of most elements.\n:displaysize: A Tuple{Int,Int} giving the size in rows and columns to use for text output. This can be used to override the display size for called functions, but to get the size of the screen use the displaysize function.\n:typeinfo: a Type characterizing the information already printed concerning the type of the object about to be displayed. This is mainly useful when displaying a collection of objects of the same type, so that redundant type information can be avoided (e.g. [Float16(0)] can be shown as \"Float16[0.0]\" instead of \"Float16[Float16(0.0)]\" : while displaying the elements of the array, the :typeinfo property will be set to Float16).\n:color: Boolean specifying whether ANSI color/escape codes are supported/expected. By default, this is determined by whether io is a compatible terminal and by any --color command-line flag when julia was launched.\n\nExamples\n\njulia> io = IOBuffer();\n\njulia> printstyled(IOContext(io, :color => true), \"string\", color=:red)\n\njulia> String(take!(io))\n\"\\e[31mstring\\e[39m\"\n\njulia> printstyled(io, \"string\", color=:red)\n\njulia> String(take!(io))\n\"string\"\n\njulia> print(IOContext(stdout, :compact => false), 1.12341234)\n1.12341234\njulia> print(IOContext(stdout, :compact => true), 1.12341234)\n1.12341\n\njulia> function f(io::IO)\n if get(io, :short, false)\n print(io, \"short\")\n else\n print(io, \"loooooong\")\n end\n end\nf (generic function with 1 method)\n\njulia> f(stdout)\nloooooong\njulia> f(IOContext(stdout, :short => true))\nshort\n\n\n\n\n\n","category":"method"},{"location":"base/io-network/#Base.IOContext-Tuple{IO, IOContext}","page":"I/O 与网络","title":"Base.IOContext","text":"IOContext(io::IO, context::IOContext)\n\nCreate an IOContext that wraps an alternate IO but inherits the properties of context.\n\n\n\n\n\n","category":"method"},{"location":"base/io-network/#文本-I/O","page":"I/O 与网络","title":"文本 I/O","text":"","category":"section"},{"location":"base/io-network/","page":"I/O 与网络","title":"I/O 与网络","text":"Base.show(::IO, ::Any)\nBase.summary\nBase.print\nBase.println\nBase.printstyled\nBase.sprint\nBase.showerror\nBase.dump\nMeta.@dump\nBase.readline\nBase.readuntil\nBase.readlines\nBase.eachline\nBase.displaysize","category":"page"},{"location":"base/io-network/#Base.show-Tuple{IO, Any}","page":"I/O 与网络","title":"Base.show","text":"show([io::IO = stdout], x)\n\nWrite a text representation of a value x to the output stream io. New types T should overload show(io::IO, x::T). The representation used by show generally includes Julia-specific formatting and type information, and should be parseable Julia code when possible.\n\nrepr returns the output of show as a string.\n\nTo customize human-readable text output for objects of type T, define show(io::IO, ::MIME\"text/plain\", ::T) instead. Checking the :compact IOContext property of io in such methods is recommended, since some containers show their elements by calling this method with :compact => true.\n\nSee also print, which writes un-decorated representations.\n\nExamples\n\njulia> show(\"Hello World!\")\n\"Hello World!\"\njulia> print(\"Hello World!\")\nHello World!\n\n\n\n\n\n","category":"method"},{"location":"base/io-network/#Base.summary","page":"I/O 与网络","title":"Base.summary","text":"summary(io::IO, x)\nstr = summary(x)\n\nPrint to a stream io, or return a string str, giving a brief description of a value. By default returns string(typeof(x)), e.g. Int64.\n\nFor arrays, returns a string of size and type info, e.g. 10-element Array{Int64,1}.\n\nExamples\n\njulia> summary(1)\n\"Int64\"\n\njulia> summary(zeros(2))\n\"2-element Vector{Float64}\"\n\n\n\n\n\n","category":"function"},{"location":"base/io-network/#Base.print","page":"I/O 与网络","title":"Base.print","text":"print([io::IO], xs...)\n\nWrite to io (or to the default output stream stdout if io is not given) a canonical (un-decorated) text representation. The representation used by print includes minimal formatting and tries to avoid Julia-specific details.\n\nprint falls back to calling show, so most types should just define show. Define print if your type has a separate \"plain\" representation. For example, show displays strings with quotes, and print displays strings without quotes.\n\nSee also println, string, printstyled.\n\nExamples\n\njulia> print(\"Hello World!\")\nHello World!\njulia> io = IOBuffer();\n\njulia> print(io, \"Hello\", ' ', :World!)\n\njulia> String(take!(io))\n\"Hello World!\"\n\n\n\n\n\n","category":"function"},{"location":"base/io-network/#Base.println","page":"I/O 与网络","title":"Base.println","text":"println([io::IO], xs...)\n\nPrint (using print) xs to io followed by a newline. If io is not supplied, prints to the default output stream stdout.\n\nSee also printstyled to add colors etc.\n\nExamples\n\njulia> println(\"Hello, world\")\nHello, world\n\njulia> io = IOBuffer();\n\njulia> println(io, \"Hello\", ',', \" world.\")\n\njulia> String(take!(io))\n\"Hello, world.\\n\"\n\n\n\n\n\n","category":"function"},{"location":"base/io-network/#Base.printstyled","page":"I/O 与网络","title":"Base.printstyled","text":"printstyled([io], xs...; bold::Bool=false, underline::Bool=false, blink::Bool=false, reverse::Bool=false, hidden::Bool=false, color::Union{Symbol,Int}=:normal)\n\nPrint xs in a color specified as a symbol or integer, optionally in bold.\n\nKeyword color may take any of the values :normal, :default, :bold, :black, :blink, :blue, :cyan, :green, :hidden, :light_black, :light_blue, :light_cyan, :light_green, :light_magenta, :light_red, :light_white, :light_yellow, :magenta, :nothing, :red, :reverse, :underline, :white, or :yellow or an integer between 0 and 255 inclusive. Note that not all terminals support 256 colors.\n\nKeywords bold=true, underline=true, blink=true are self-explanatory. Keyword reverse=true prints with foreground and background colors exchanged, and hidden=true should be invisibe in the terminal but can still be copied. These properties can be used in any combination.\n\nSee also print, println, show.\n\ncompat: Julia 1.7\nKeywords except color and bold were added in Julia 1.7.\n\n\n\n\n\n","category":"function"},{"location":"base/io-network/#Base.sprint","page":"I/O 与网络","title":"Base.sprint","text":"sprint(f::Function, args...; context=nothing, sizehint=0)\n\nCall the given function with an I/O stream and the supplied extra arguments. Everything written to this I/O stream is returned as a string. context can be an IOContext whose properties will be used, a Pair specifying a property and its value, or a tuple of Pair specifying multiple properties and their values. sizehint suggests the capacity of the buffer (in bytes).\n\nThe optional keyword argument context can be set to a :key=>value pair, a tuple of :key=>value pairs, or an IO or IOContext object whose attributes are used for the I/O stream passed to f. The optional sizehint is a suggested size (in bytes) to allocate for the buffer used to write the string.\n\ncompat: Julia 1.7\nPassing a tuple to keyword context requires Julia 1.7 or later.\n\nExamples\n\njulia> sprint(show, 66.66666; context=:compact => true)\n\"66.6667\"\n\njulia> sprint(showerror, BoundsError([1], 100))\n\"BoundsError: attempt to access 1-element Vector{Int64} at index [100]\"\n\n\n\n\n\n","category":"function"},{"location":"base/io-network/#Base.showerror","page":"I/O 与网络","title":"Base.showerror","text":"showerror(io, e)\n\nShow a descriptive representation of an exception object e. This method is used to display the exception after a call to throw.\n\nExamples\n\njulia> struct MyException <: Exception\n msg::String\n end\n\njulia> function Base.showerror(io::IO, err::MyException)\n print(io, \"MyException: \")\n print(io, err.msg)\n end\n\njulia> err = MyException(\"test exception\")\nMyException(\"test exception\")\n\njulia> sprint(showerror, err)\n\"MyException: test exception\"\n\njulia> throw(MyException(\"test exception\"))\nERROR: MyException: test exception\n\n\n\n\n\n","category":"function"},{"location":"base/io-network/#Base.dump","page":"I/O 与网络","title":"Base.dump","text":"dump(x; maxdepth=8)\n\nShow every part of the representation of a value. The depth of the output is truncated at maxdepth.\n\nExamples\n\njulia> struct MyStruct\n x\n y\n end\n\njulia> x = MyStruct(1, (2,3));\n\njulia> dump(x)\nMyStruct\n x: Int64 1\n y: Tuple{Int64, Int64}\n 1: Int64 2\n 2: Int64 3\n\njulia> dump(x; maxdepth = 1)\nMyStruct\n x: Int64 1\n y: Tuple{Int64, Int64}\n\n\n\n\n\n","category":"function"},{"location":"base/io-network/#Base.Meta.@dump","page":"I/O 与网络","title":"Base.Meta.@dump","text":"@dump expr\n\nShow every part of the representation of the given expression. Equivalent to dump(:(expr)).\n\n\n\n\n\n","category":"macro"},{"location":"base/io-network/#Base.readline","page":"I/O 与网络","title":"Base.readline","text":"readline(io::IO=stdin; keep::Bool=false)\nreadline(filename::AbstractString; keep::Bool=false)\n\nRead a single line of text from the given I/O stream or file (defaults to stdin). When reading from a file, the text is assumed to be encoded in UTF-8. Lines in the input end with '\\n' or \"\\r\\n\" or the end of an input stream. When keep is false (as it is by default), these trailing newline characters are removed from the line before it is returned. When keep is true, they are returned as part of the line.\n\nExamples\n\njulia> open(\"my_file.txt\", \"w\") do io\n write(io, \"JuliaLang is a GitHub organization.\\nIt has many members.\\n\");\n end\n57\n\njulia> readline(\"my_file.txt\")\n\"JuliaLang is a GitHub organization.\"\n\njulia> readline(\"my_file.txt\", keep=true)\n\"JuliaLang is a GitHub organization.\\n\"\n\njulia> rm(\"my_file.txt\")\n\njulia> print(\"Enter your name: \")\nEnter your name:\n\njulia> your_name = readline()\nLogan\n\"Logan\"\n\n\n\n\n\n","category":"function"},{"location":"base/io-network/#Base.readuntil","page":"I/O 与网络","title":"Base.readuntil","text":"readuntil(stream::IO, delim; keep::Bool = false)\nreaduntil(filename::AbstractString, delim; keep::Bool = false)\n\nRead a string from an I/O stream or a file, up to the given delimiter. The delimiter can be a UInt8, AbstractChar, string, or vector. Keyword argument keep controls whether the delimiter is included in the result. The text is assumed to be encoded in UTF-8.\n\nExamples\n\njulia> open(\"my_file.txt\", \"w\") do io\n write(io, \"JuliaLang is a GitHub organization.\\nIt has many members.\\n\");\n end\n57\n\njulia> readuntil(\"my_file.txt\", 'L')\n\"Julia\"\n\njulia> readuntil(\"my_file.txt\", '.', keep = true)\n\"JuliaLang is a GitHub organization.\"\n\njulia> rm(\"my_file.txt\")\n\n\n\n\n\n","category":"function"},{"location":"base/io-network/#Base.readlines","page":"I/O 与网络","title":"Base.readlines","text":"readlines(io::IO=stdin; keep::Bool=false)\nreadlines(filename::AbstractString; keep::Bool=false)\n\nRead all lines of an I/O stream or a file as a vector of strings. Behavior is equivalent to saving the result of reading readline repeatedly with the same arguments and saving the resulting lines as a vector of strings. See also eachline to iterate over the lines without reading them all at once.\n\nExamples\n\njulia> open(\"my_file.txt\", \"w\") do io\n write(io, \"JuliaLang is a GitHub organization.\\nIt has many members.\\n\");\n end\n57\n\njulia> readlines(\"my_file.txt\")\n2-element Vector{String}:\n \"JuliaLang is a GitHub organization.\"\n \"It has many members.\"\n\njulia> readlines(\"my_file.txt\", keep=true)\n2-element Vector{String}:\n \"JuliaLang is a GitHub organization.\\n\"\n \"It has many members.\\n\"\n\njulia> rm(\"my_file.txt\")\n\n\n\n\n\n","category":"function"},{"location":"base/io-network/#Base.eachline","page":"I/O 与网络","title":"Base.eachline","text":"eachline(io::IO=stdin; keep::Bool=false)\neachline(filename::AbstractString; keep::Bool=false)\n\nCreate an iterable EachLine object that will yield each line from an I/O stream or a file. Iteration calls readline on the stream argument repeatedly with keep passed through, determining whether trailing end-of-line characters are retained. When called with a file name, the file is opened once at the beginning of iteration and closed at the end. If iteration is interrupted, the file will be closed when the EachLine object is garbage collected.\n\nTo iterate over each line of a String, eachline(IOBuffer(str)) can be used.\n\nIterators.reverse can be used on an EachLine object to read the lines in reverse order (for files, buffers, and other I/O streams supporting seek), and first or last can be used to extract the initial or final lines, respectively.\n\nExamples\n\njulia> open(\"my_file.txt\", \"w\") do io\n write(io, \"JuliaLang is a GitHub organization.\\n It has many members.\\n\");\n end;\n\njulia> for line in eachline(\"my_file.txt\")\n print(line)\n end\nJuliaLang is a GitHub organization. It has many members.\n\njulia> rm(\"my_file.txt\");\n\ncompat: Julia 1.8\nJulia 1.8 is required to use Iterators.reverse or last with eachline iterators.\n\n\n\n\n\n","category":"function"},{"location":"base/io-network/#Base.displaysize","page":"I/O 与网络","title":"Base.displaysize","text":"displaysize([io::IO]) -> (lines, columns)\n\nReturn the nominal size of the screen that may be used for rendering output to this IO object. If no input is provided, the environment variables LINES and COLUMNS are read. If those are not set, a default size of (24, 80) is returned.\n\nExamples\n\njulia> withenv(\"LINES\" => 30, \"COLUMNS\" => 100) do\n displaysize()\n end\n(30, 100)\n\nTo get your TTY size,\n\njulia> displaysize(stdout)\n(34, 147)\n\n\n\n\n\n","category":"function"},{"location":"base/io-network/#多媒体-I/O","page":"I/O 与网络","title":"多媒体 I/O","text":"","category":"section"},{"location":"base/io-network/","page":"I/O 与网络","title":"I/O 与网络","text":"就像文本输出用 print 实现,用户自定义类型可以通过重载 show 来指定其文本化表示, Julia 提供了一个应用于富多媒体输出的标准化机制 (例如图片、格式化文本、甚至音频和视频),由以下三部分组成:","category":"page"},{"location":"base/io-network/","page":"I/O 与网络","title":"I/O 与网络","text":"函数 display(x) 来请求一个 Julia 对象 x 最丰富的多媒体展示,并以纯文本作为后备模式。\n重载 show 允许指定用户自定义类型的任意多媒体表现形式(以标准MIME类型为键值)。\nMultimedia-capable display backends may be registered by subclassing a generic AbstractDisplay type 并通过 pushdisplay 将其压进显示后端的栈中。","category":"page"},{"location":"base/io-network/","page":"I/O 与网络","title":"I/O 与网络","text":"基础 Julia 运行环境只提供纯文本显示, 但是更富的显示可以通过加载外部模块或者使用图形化 Julia 环境 (比如基于 IPython 的 IJulia notebook)来实现。","category":"page"},{"location":"base/io-network/","page":"I/O 与网络","title":"I/O 与网络","text":"Base.AbstractDisplay\nBase.Multimedia.display\nBase.Multimedia.redisplay\nBase.Multimedia.displayable\nBase.show(::IO, ::Any, ::Any)\nBase.Multimedia.showable\nBase.repr(::MIME, ::Any)\nBase.MIME\nBase.@MIME_str","category":"page"},{"location":"base/io-network/#Base.Multimedia.AbstractDisplay","page":"I/O 与网络","title":"Base.Multimedia.AbstractDisplay","text":"AbstractDisplay\n\nAbstract supertype for rich display output devices. TextDisplay is a subtype of this.\n\n\n\n\n\n","category":"type"},{"location":"base/io-network/#Base.Multimedia.display","page":"I/O 与网络","title":"Base.Multimedia.display","text":"display(x)\ndisplay(d::AbstractDisplay, x)\ndisplay(mime, x)\ndisplay(d::AbstractDisplay, mime, x)\n\nDisplay x using the topmost applicable display in the display stack, typically using the richest supported multimedia output for x, with plain-text stdout output as a fallback. The display(d, x) variant attempts to display x on the given display d only, throwing a MethodError if d cannot display objects of this type.\n\nIn general, you cannot assume that display output goes to stdout (unlike print(x) or show(x)). For example, display(x) may open up a separate window with an image. display(x) means \"show x in the best way you can for the current output device(s).\" If you want REPL-like text output that is guaranteed to go to stdout, use show(stdout, \"text/plain\", x) instead.\n\nThere are also two variants with a mime argument (a MIME type string, such as \"image/png\"), which attempt to display x using the requested MIME type only, throwing a MethodError if this type is not supported by either the display(s) or by x. With these variants, one can also supply the \"raw\" data in the requested MIME type by passing x::AbstractString (for MIME types with text-based storage, such as text/html or application/postscript) or x::Vector{UInt8} (for binary MIME types).\n\nTo customize how instances of a type are displayed, overload show rather than display, as explained in the manual section on custom pretty-printing.\n\n\n\n\n\n","category":"function"},{"location":"base/io-network/#Base.Multimedia.redisplay","page":"I/O 与网络","title":"Base.Multimedia.redisplay","text":"redisplay(x)\nredisplay(d::AbstractDisplay, x)\nredisplay(mime, x)\nredisplay(d::AbstractDisplay, mime, x)\n\nBy default, the redisplay functions simply call display. However, some display backends may override redisplay to modify an existing display of x (if any). Using redisplay is also a hint to the backend that x may be redisplayed several times, and the backend may choose to defer the display until (for example) the next interactive prompt.\n\n\n\n\n\n","category":"function"},{"location":"base/io-network/#Base.Multimedia.displayable","page":"I/O 与网络","title":"Base.Multimedia.displayable","text":"displayable(mime) -> Bool\ndisplayable(d::AbstractDisplay, mime) -> Bool\n\nReturns a boolean value indicating whether the given mime type (string) is displayable by any of the displays in the current display stack, or specifically by the display d in the second variant.\n\n\n\n\n\n","category":"function"},{"location":"base/io-network/#Base.show-Tuple{IO, Any, Any}","page":"I/O 与网络","title":"Base.show","text":"show(io::IO, mime, x)\n\nThe display functions ultimately call show in order to write an object x as a given mime type to a given I/O stream io (usually a memory buffer), if possible. In order to provide a rich multimedia representation of a user-defined type T, it is only necessary to define a new show method for T, via: show(io, ::MIME\"mime\", x::T) = ..., where mime is a MIME-type string and the function body calls write (or similar) to write that representation of x to io. (Note that the MIME\"\" notation only supports literal strings; to construct MIME types in a more flexible manner use MIME{Symbol(\"\")}.)\n\nFor example, if you define a MyImage type and know how to write it to a PNG file, you could define a function show(io, ::MIME\"image/png\", x::MyImage) = ... to allow your images to be displayed on any PNG-capable AbstractDisplay (such as IJulia). As usual, be sure to import Base.show in order to add new methods to the built-in Julia function show.\n\nTechnically, the MIME\"mime\" macro defines a singleton type for the given mime string, which allows us to exploit Julia's dispatch mechanisms in determining how to display objects of any given type.\n\nThe default MIME type is MIME\"text/plain\". There is a fallback definition for text/plain output that calls show with 2 arguments, so it is not always necessary to add a method for that case. If a type benefits from custom human-readable output though, show(::IO, ::MIME\"text/plain\", ::T) should be defined. For example, the Day type uses 1 day as the output for the text/plain MIME type, and Day(1) as the output of 2-argument show.\n\nContainer types generally implement 3-argument show by calling show(io, MIME\"text/plain\"(), x) for elements x, with :compact => true set in an IOContext passed as the first argument.\n\n\n\n\n\n","category":"method"},{"location":"base/io-network/#Base.Multimedia.showable","page":"I/O 与网络","title":"Base.Multimedia.showable","text":"showable(mime, x)\n\nReturns a boolean value indicating whether or not the object x can be written as the given mime type.\n\n(By default, this is determined automatically by the existence of the corresponding show method for typeof(x). Some types provide custom showable methods; for example, if the available MIME formats depend on the value of x.)\n\nExamples\n\njulia> showable(MIME(\"text/plain\"), rand(5))\ntrue\n\njulia> showable(\"image/png\", rand(5))\nfalse\n\n\n\n\n\n","category":"function"},{"location":"base/io-network/#Base.repr-Tuple{MIME, Any}","page":"I/O 与网络","title":"Base.repr","text":"repr(mime, x; context=nothing)\n\nReturns an AbstractString or Vector{UInt8} containing the representation of x in the requested mime type, as written by show(io, mime, x) (throwing a MethodError if no appropriate show is available). An AbstractString is returned for MIME types with textual representations (such as \"text/html\" or \"application/postscript\"), whereas binary data is returned as Vector{UInt8}. (The function istextmime(mime) returns whether or not Julia treats a given mime type as text.)\n\nThe optional keyword argument context can be set to :key=>value pair or an IO or IOContext object whose attributes are used for the I/O stream passed to show.\n\nAs a special case, if x is an AbstractString (for textual MIME types) or a Vector{UInt8} (for binary MIME types), the repr function assumes that x is already in the requested mime format and simply returns x. This special case does not apply to the \"text/plain\" MIME type. This is useful so that raw data can be passed to display(m::MIME, x).\n\nIn particular, repr(\"text/plain\", x) is typically a \"pretty-printed\" version of x designed for human consumption. See also repr(x) to instead return a string corresponding to show(x) that may be closer to how the value of x would be entered in Julia.\n\nExamples\n\njulia> A = [1 2; 3 4];\n\njulia> repr(\"text/plain\", A)\n\"2×2 Matrix{Int64}:\\n 1 2\\n 3 4\"\n\n\n\n\n\n","category":"method"},{"location":"base/io-network/#Base.Multimedia.MIME","page":"I/O 与网络","title":"Base.Multimedia.MIME","text":"MIME\n\nA type representing a standard internet data format. \"MIME\" stands for \"Multipurpose Internet Mail Extensions\", since the standard was originally used to describe multimedia attachments to email messages.\n\nA MIME object can be passed as the second argument to show to request output in that format.\n\nExamples\n\njulia> show(stdout, MIME(\"text/plain\"), \"hi\")\n\"hi\"\n\n\n\n\n\n","category":"type"},{"location":"base/io-network/#Base.Multimedia.@MIME_str","page":"I/O 与网络","title":"Base.Multimedia.@MIME_str","text":"@MIME_str\n\nA convenience macro for writing MIME types, typically used when adding methods to show. For example the syntax show(io::IO, ::MIME\"text/html\", x::MyType) = ... could be used to define how to write an HTML representation of MyType.\n\n\n\n\n\n","category":"macro"},{"location":"base/io-network/","page":"I/O 与网络","title":"I/O 与网络","text":"如上面提到的,用户可以定义新的显示后端。 例如,可以在窗口显示 PNG 图片的模块可以在 Julia 中注册这个能力, 以便为有 PNG 表示的类型调用 display(x) 时可以在模块窗口中自动显示图片。","category":"page"},{"location":"base/io-network/","page":"I/O 与网络","title":"I/O 与网络","text":"In order to define a new display backend, one should first create a subtype D of the abstract class AbstractDisplay. Then, for each MIME type (mime string) that can be displayed on D, one should define a function display(d::D, ::MIME\"mime\", x) = ... that displays x as that MIME type, usually by calling show(io, mime, x) or repr(io, mime, x). A MethodError should be thrown if x cannot be displayed as that MIME type; this is automatic if one calls show or repr. Finally, one should define a function display(d::D, x) that queries showable(mime, x) for the mime types supported by D and displays the \"best\" one; a MethodError should be thrown if no supported MIME types are found for x. Similarly, some subtypes may wish to override redisplay(d::D, ...). (Again, one should import Base.display to add new methods to display.) The return values of these functions are up to the implementation (since in some cases it may be useful to return a display \"handle\" of some type). The display functions for D can then be called directly, but they can also be invoked automatically from display(x) simply by pushing a new display onto the display-backend stack with:","category":"page"},{"location":"base/io-network/","page":"I/O 与网络","title":"I/O 与网络","text":"Base.Multimedia.pushdisplay\nBase.Multimedia.popdisplay\nBase.Multimedia.TextDisplay\nBase.Multimedia.istextmime","category":"page"},{"location":"base/io-network/#Base.Multimedia.pushdisplay","page":"I/O 与网络","title":"Base.Multimedia.pushdisplay","text":"pushdisplay(d::AbstractDisplay)\n\nPushes a new display d on top of the global display-backend stack. Calling display(x) or display(mime, x) will display x on the topmost compatible backend in the stack (i.e., the topmost backend that does not throw a MethodError).\n\n\n\n\n\n","category":"function"},{"location":"base/io-network/#Base.Multimedia.popdisplay","page":"I/O 与网络","title":"Base.Multimedia.popdisplay","text":"popdisplay()\npopdisplay(d::AbstractDisplay)\n\nPop the topmost backend off of the display-backend stack, or the topmost copy of d in the second variant.\n\n\n\n\n\n","category":"function"},{"location":"base/io-network/#Base.Multimedia.TextDisplay","page":"I/O 与网络","title":"Base.Multimedia.TextDisplay","text":"TextDisplay(io::IO)\n\nReturns a TextDisplay <: AbstractDisplay, which displays any object as the text/plain MIME type (by default), writing the text representation to the given I/O stream. (This is how objects are printed in the Julia REPL.)\n\n\n\n\n\n","category":"type"},{"location":"base/io-network/#Base.Multimedia.istextmime","page":"I/O 与网络","title":"Base.Multimedia.istextmime","text":"istextmime(m::MIME)\n\nDetermine whether a MIME type is text data. MIME types are assumed to be binary data except for a set of types known to be text data (possibly Unicode).\n\nExamples\n\njulia> istextmime(MIME(\"text/plain\"))\ntrue\n\njulia> istextmime(MIME(\"image/png\"))\nfalse\n\n\n\n\n\n","category":"function"},{"location":"base/io-network/#网络-I/O","page":"I/O 与网络","title":"网络 I/O","text":"","category":"section"},{"location":"base/io-network/","page":"I/O 与网络","title":"I/O 与网络","text":"Base.bytesavailable\nBase.ntoh\nBase.hton\nBase.ltoh\nBase.htol\nBase.ENDIAN_BOM","category":"page"},{"location":"base/io-network/#Base.bytesavailable","page":"I/O 与网络","title":"Base.bytesavailable","text":"bytesavailable(io)\n\nReturn the number of bytes available for reading before a read from this stream or buffer will block.\n\nExamples\n\njulia> io = IOBuffer(\"JuliaLang is a GitHub organization\");\n\njulia> bytesavailable(io)\n34\n\n\n\n\n\n","category":"function"},{"location":"base/io-network/#Base.ntoh","page":"I/O 与网络","title":"Base.ntoh","text":"ntoh(x)\n\nConvert the endianness of a value from Network byte order (big-endian) to that used by the Host.\n\n\n\n\n\n","category":"function"},{"location":"base/io-network/#Base.hton","page":"I/O 与网络","title":"Base.hton","text":"hton(x)\n\nConvert the endianness of a value from that used by the Host to Network byte order (big-endian).\n\n\n\n\n\n","category":"function"},{"location":"base/io-network/#Base.ltoh","page":"I/O 与网络","title":"Base.ltoh","text":"ltoh(x)\n\nConvert the endianness of a value from Little-endian to that used by the Host.\n\n\n\n\n\n","category":"function"},{"location":"base/io-network/#Base.htol","page":"I/O 与网络","title":"Base.htol","text":"htol(x)\n\nConvert the endianness of a value from that used by the Host to Little-endian.\n\n\n\n\n\n","category":"function"},{"location":"base/io-network/#Base.ENDIAN_BOM","page":"I/O 与网络","title":"Base.ENDIAN_BOM","text":"ENDIAN_BOM\n\nThe 32-bit byte-order-mark indicates the native byte order of the host machine. Little-endian machines will contain the value 0x04030201. Big-endian machines will contain the value 0x01020304.\n\n\n\n\n\n","category":"constant"},{"location":"base/c/#C-接口","page":"C 接口","title":"C 接口","text":"","category":"section"},{"location":"base/c/","page":"C 接口","title":"C 接口","text":"@ccall\nccall\nCore.Intrinsics.cglobal\nBase.@cfunction\nBase.CFunction\nBase.unsafe_convert\nBase.cconvert\nBase.unsafe_load\nBase.unsafe_store!\nBase.unsafe_copyto!{T}(::Ptr{T}, ::Ptr{T}, ::Any)\nBase.unsafe_copyto!{T}(::Array{T}, ::Any, ::Array{T}, ::Any, ::Any)\nBase.copyto!\nBase.pointer\nBase.unsafe_wrap{T,N}(::Union{Type{Array},Type{Array{T}},Type{Array{T,N}}}, ::Ptr{T}, ::NTuple{N,Int})\nBase.pointer_from_objref\nBase.unsafe_pointer_to_objref\nBase.disable_sigint\nBase.reenable_sigint\nBase.exit_on_sigint\nBase.systemerror\nBase.windowserror\nCore.Ptr\nCore.Ref\nBase.isassigned(::Base.RefValue)\nBase.Cchar\nBase.Cuchar\nBase.Cshort\nBase.Cstring\nBase.Cushort\nBase.Cint\nBase.Cuint\nBase.Clong\nBase.Culong\nBase.Clonglong\nBase.Culonglong\nBase.Cintmax_t\nBase.Cuintmax_t\nBase.Csize_t\nBase.Cssize_t\nBase.Cptrdiff_t\nBase.Cwchar_t\nBase.Cwstring\nBase.Cfloat\nBase.Cdouble","category":"page"},{"location":"base/c/#Base.@ccall","page":"C 接口","title":"Base.@ccall","text":"@ccall library.function_name(argvalue1::argtype1, ...)::returntype\n@ccall function_name(argvalue1::argtype1, ...)::returntype\n@ccall $function_pointer(argvalue1::argtype1, ...)::returntype\n\nCall a function in a C-exported shared library, specified by library.function_name, where library is a string constant or literal. The library may be omitted, in which case the function_name is resolved in the current process. Alternatively, @ccall may also be used to call a function pointer $function_pointer, such as one returned by dlsym.\n\nEach argvalue to @ccall is converted to the corresponding argtype, by automatic insertion of calls to unsafe_convert(argtype, cconvert(argtype, argvalue)). (See also the documentation for unsafe_convert and cconvert for further details.) In most cases, this simply results in a call to convert(argtype, argvalue).\n\nExamples\n\n@ccall strlen(s::Cstring)::Csize_t\n\nThis calls the C standard library function:\n\nsize_t strlen(char *)\n\nwith a Julia variable named s. See also ccall.\n\nVarargs are supported with the following convention:\n\n@ccall printf(\"%s = %d\"::Cstring ; \"foo\"::Cstring, foo::Cint)::Cint\n\nThe semicolon is used to separate required arguments (of which there must be at least one) from variadic arguments.\n\nExample using an external library:\n\n# C signature of g_uri_escape_string:\n# char *g_uri_escape_string(const char *unescaped, const char *reserved_chars_allowed, gboolean allow_utf8);\n\nconst glib = \"libglib-2.0\"\n@ccall glib.g_uri_escape_string(my_uri::Cstring, \":/\"::Cstring, true::Cint)::Cstring\n\nThe string literal could also be used directly before the function name, if desired \"libglib-2.0\".g_uri_escape_string(...\n\n\n\n\n\n","category":"macro"},{"location":"base/c/#ccall","page":"C 接口","title":"ccall","text":"ccall((function_name, library), returntype, (argtype1, ...), argvalue1, ...)\nccall(function_name, returntype, (argtype1, ...), argvalue1, ...)\nccall(function_pointer, returntype, (argtype1, ...), argvalue1, ...)\n\nCall a function in a C-exported shared library, specified by the tuple (function_name, library), where each component is either a string or symbol. Instead of specifying a library, one can also use a function_name symbol or string, which is resolved in the current process. Alternatively, ccall may also be used to call a function pointer function_pointer, such as one returned by dlsym.\n\nNote that the argument type tuple must be a literal tuple, and not a tuple-valued variable or expression.\n\nEach argvalue to the ccall will be converted to the corresponding argtype, by automatic insertion of calls to unsafe_convert(argtype, cconvert(argtype, argvalue)). (See also the documentation for unsafe_convert and cconvert for further details.) In most cases, this simply results in a call to convert(argtype, argvalue).\n\n\n\n\n\n","category":"keyword"},{"location":"base/c/#Core.Intrinsics.cglobal","page":"C 接口","title":"Core.Intrinsics.cglobal","text":"cglobal((symbol, library) [, type=Cvoid])\n\nObtain a pointer to a global variable in a C-exported shared library, specified exactly as in ccall. Returns a Ptr{Type}, defaulting to Ptr{Cvoid} if no Type argument is supplied. The values can be read or written by unsafe_load or unsafe_store!, respectively.\n\n\n\n\n\n","category":"function"},{"location":"base/c/#Base.@cfunction","page":"C 接口","title":"Base.@cfunction","text":"@cfunction(callable, ReturnType, (ArgumentTypes...,)) -> Ptr{Cvoid}\n@cfunction($callable, ReturnType, (ArgumentTypes...,)) -> CFunction\n\nGenerate a C-callable function pointer from the Julia function callable for the given type signature. To pass the return value to a ccall, use the argument type Ptr{Cvoid} in the signature.\n\nNote that the argument type tuple must be a literal tuple, and not a tuple-valued variable or expression (although it can include a splat expression). And that these arguments will be evaluated in global scope during compile-time (not deferred until runtime). Adding a '$' in front of the function argument changes this to instead create a runtime closure over the local variable callable (this is not supported on all architectures).\n\nSee manual section on ccall and cfunction usage.\n\nExamples\n\njulia> function foo(x::Int, y::Int)\n return x + y\n end\n\njulia> @cfunction(foo, Int, (Int, Int))\nPtr{Cvoid} @0x000000001b82fcd0\n\n\n\n\n\n","category":"macro"},{"location":"base/c/#Base.CFunction","page":"C 接口","title":"Base.CFunction","text":"CFunction struct\n\nGarbage-collection handle for the return value from @cfunction when the first argument is annotated with '$'. Like all cfunction handles, it should be passed to ccall as a Ptr{Cvoid}, and will be converted automatically at the call site to the appropriate type.\n\nSee @cfunction.\n\n\n\n\n\n","category":"type"},{"location":"base/c/#Base.unsafe_convert","page":"C 接口","title":"Base.unsafe_convert","text":"unsafe_convert(T, x)\n\nConvert x to a C argument of type T where the input x must be the return value of cconvert(T, ...).\n\nIn cases where convert would need to take a Julia object and turn it into a Ptr, this function should be used to define and perform that conversion.\n\nBe careful to ensure that a Julia reference to x exists as long as the result of this function will be used. Accordingly, the argument x to this function should never be an expression, only a variable name or field reference. For example, x=a.b.c is acceptable, but x=[a,b,c] is not.\n\nThe unsafe prefix on this function indicates that using the result of this function after the x argument to this function is no longer accessible to the program may cause undefined behavior, including program corruption or segfaults, at any later time.\n\nSee also cconvert\n\n\n\n\n\n","category":"function"},{"location":"base/c/#Base.cconvert","page":"C 接口","title":"Base.cconvert","text":"cconvert(T,x)\n\nConvert x to a value to be passed to C code as type T, typically by calling convert(T, x).\n\nIn cases where x cannot be safely converted to T, unlike convert, cconvert may return an object of a type different from T, which however is suitable for unsafe_convert to handle. The result of this function should be kept valid (for the GC) until the result of unsafe_convert is not needed anymore. This can be used to allocate memory that will be accessed by the ccall. If multiple objects need to be allocated, a tuple of the objects can be used as return value.\n\nNeither convert nor cconvert should take a Julia object and turn it into a Ptr.\n\n\n\n\n\n","category":"function"},{"location":"base/c/#Base.unsafe_load","page":"C 接口","title":"Base.unsafe_load","text":"unsafe_load(p::Ptr{T}, i::Integer=1)\n\nLoad a value of type T from the address of the ith element (1-indexed) starting at p. This is equivalent to the C expression p[i-1].\n\nThe unsafe prefix on this function indicates that no validation is performed on the pointer p to ensure that it is valid. Incorrect usage may segfault your program or return garbage answers, in the same manner as C.\n\n\n\n\n\n","category":"function"},{"location":"base/c/#Base.unsafe_store!","page":"C 接口","title":"Base.unsafe_store!","text":"unsafe_store!(p::Ptr{T}, x, i::Integer=1)\n\nStore a value of type T to the address of the ith element (1-indexed) starting at p. This is equivalent to the C expression p[i-1] = x.\n\nThe unsafe prefix on this function indicates that no validation is performed on the pointer p to ensure that it is valid. Incorrect usage may corrupt or segfault your program, in the same manner as C.\n\n\n\n\n\n","category":"function"},{"location":"base/c/#Base.unsafe_copyto!-Union{Tuple{T}, Tuple{Ptr{T}, Ptr{T}, Any}} where T","page":"C 接口","title":"Base.unsafe_copyto!","text":"unsafe_copyto!(dest::Ptr{T}, src::Ptr{T}, N)\n\nCopy N elements from a source pointer to a destination, with no checking. The size of an element is determined by the type of the pointers.\n\nThe unsafe prefix on this function indicates that no validation is performed on the pointers dest and src to ensure that they are valid. Incorrect usage may corrupt or segfault your program, in the same manner as C.\n\n\n\n\n\n","category":"method"},{"location":"base/c/#Base.unsafe_copyto!-Union{Tuple{T}, Tuple{Array{T}, Any, Array{T}, Any, Any}} where T","page":"C 接口","title":"Base.unsafe_copyto!","text":"unsafe_copyto!(dest::Array, do, src::Array, so, N)\n\nCopy N elements from a source array to a destination, starting at offset so in the source and do in the destination (1-indexed).\n\nThe unsafe prefix on this function indicates that no validation is performed to ensure that N is inbounds on either array. Incorrect usage may corrupt or segfault your program, in the same manner as C.\n\n\n\n\n\n","category":"method"},{"location":"base/c/#Base.copyto!","page":"C 接口","title":"Base.copyto!","text":"copyto!(dest, do, src, so, N)\n\nCopy N elements from collection src starting at offset so, to array dest starting at offset do. Return dest.\n\n\n\n\n\ncopyto!(dest::AbstractArray, src) -> dest\n\nCopy all elements from collection src to array dest, whose length must be greater than or equal to the length n of src. The first n elements of dest are overwritten, the other elements are left untouched.\n\nSee also copy!, copy.\n\nExamples\n\njulia> x = [1., 0., 3., 0., 5.];\n\njulia> y = zeros(7);\n\njulia> copyto!(y, x);\n\njulia> y\n7-element Vector{Float64}:\n 1.0\n 0.0\n 3.0\n 0.0\n 5.0\n 0.0\n 0.0\n\n\n\n\n\ncopyto!(dest, Rdest::CartesianIndices, src, Rsrc::CartesianIndices) -> dest\n\nCopy the block of src in the range of Rsrc to the block of dest in the range of Rdest. The sizes of the two regions must match.\n\nExamples\n\njulia> A = zeros(5, 5);\n\njulia> B = [1 2; 3 4];\n\njulia> Ainds = CartesianIndices((2:3, 2:3));\n\njulia> Binds = CartesianIndices(B);\n\njulia> copyto!(A, Ainds, B, Binds)\n5×5 Matrix{Float64}:\n 0.0 0.0 0.0 0.0 0.0\n 0.0 1.0 2.0 0.0 0.0\n 0.0 3.0 4.0 0.0 0.0\n 0.0 0.0 0.0 0.0 0.0\n 0.0 0.0 0.0 0.0 0.0\n\n\n\n\n\ncopyto!(dest::AbstractMatrix, src::UniformScaling)\n\nCopies a UniformScaling onto a matrix.\n\ncompat: Julia 1.1\nIn Julia 1.0 this method only supported a square destination matrix. Julia 1.1. added support for a rectangular matrix.\n\n\n\n\n\n","category":"function"},{"location":"base/c/#Base.pointer","page":"C 接口","title":"Base.pointer","text":"pointer(array [, index])\n\nGet the native address of an array or string, optionally at a given location index.\n\nThis function is \"unsafe\". Be careful to ensure that a Julia reference to array exists as long as this pointer will be used. The GC.@preserve macro should be used to protect the array argument from garbage collection within a given block of code.\n\nCalling Ref(array[, index]) is generally preferable to this function as it guarantees validity.\n\n\n\n\n\n","category":"function"},{"location":"base/c/#Base.unsafe_wrap-Union{Tuple{N}, Tuple{T}, Tuple{Union{Type{Array}, Type{Array{T}}, Type{Array{T, N}}}, Ptr{T}, Tuple{Vararg{Int64, N}}}} where {T, N}","page":"C 接口","title":"Base.unsafe_wrap","text":"unsafe_wrap(Array, pointer::Ptr{T}, dims; own = false)\n\nWrap a Julia Array object around the data at the address given by pointer, without making a copy. The pointer element type T determines the array element type. dims is either an integer (for a 1d array) or a tuple of the array dimensions. own optionally specifies whether Julia should take ownership of the memory, calling free on the pointer when the array is no longer referenced.\n\nThis function is labeled \"unsafe\" because it will crash if pointer is not a valid memory address to data of the requested length.\n\n\n\n\n\n","category":"method"},{"location":"base/c/#Base.pointer_from_objref","page":"C 接口","title":"Base.pointer_from_objref","text":"pointer_from_objref(x)\n\nGet the memory address of a Julia object as a Ptr. The existence of the resulting Ptr will not protect the object from garbage collection, so you must ensure that the object remains referenced for the whole time that the Ptr will be used.\n\nThis function may not be called on immutable objects, since they do not have stable memory addresses.\n\nSee also unsafe_pointer_to_objref.\n\n\n\n\n\n","category":"function"},{"location":"base/c/#Base.unsafe_pointer_to_objref","page":"C 接口","title":"Base.unsafe_pointer_to_objref","text":"unsafe_pointer_to_objref(p::Ptr)\n\nConvert a Ptr to an object reference. Assumes the pointer refers to a valid heap-allocated Julia object. If this is not the case, undefined behavior results, hence this function is considered \"unsafe\" and should be used with care.\n\nSee also pointer_from_objref.\n\n\n\n\n\n","category":"function"},{"location":"base/c/#Base.disable_sigint","page":"C 接口","title":"Base.disable_sigint","text":"disable_sigint(f::Function)\n\nDisable Ctrl-C handler during execution of a function on the current task, for calling external code that may call julia code that is not interrupt safe. Intended to be called using do block syntax as follows:\n\ndisable_sigint() do\n # interrupt-unsafe code\n ...\nend\n\nThis is not needed on worker threads (Threads.threadid() != 1) since the InterruptException will only be delivered to the master thread. External functions that do not call julia code or julia runtime automatically disable sigint during their execution.\n\n\n\n\n\n","category":"function"},{"location":"base/c/#Base.reenable_sigint","page":"C 接口","title":"Base.reenable_sigint","text":"reenable_sigint(f::Function)\n\nRe-enable Ctrl-C handler during execution of a function. Temporarily reverses the effect of disable_sigint.\n\n\n\n\n\n","category":"function"},{"location":"base/c/#Base.exit_on_sigint","page":"C 接口","title":"Base.exit_on_sigint","text":"exit_on_sigint(on::Bool)\n\nSet exit_on_sigint flag of the julia runtime. If false, Ctrl-C (SIGINT) is capturable as InterruptException in try block. This is the default behavior in REPL, any code run via -e and -E and in Julia script run with -i option.\n\nIf true, InterruptException is not thrown by Ctrl-C. Running code upon such event requires atexit. This is the default behavior in Julia script run without -i option.\n\ncompat: Julia 1.5\nFunction exit_on_sigint requires at least Julia 1.5.\n\n\n\n\n\n","category":"function"},{"location":"base/c/#Base.systemerror","page":"C 接口","title":"Base.systemerror","text":"systemerror(sysfunc[, errno::Cint=Libc.errno()])\nsystemerror(sysfunc, iftrue::Bool)\n\nRaises a SystemError for errno with the descriptive string sysfunc if iftrue is true\n\n\n\n\n\n","category":"function"},{"location":"base/c/#Base.windowserror","page":"C 接口","title":"Base.windowserror","text":"windowserror(sysfunc[, code::UInt32=Libc.GetLastError()])\nwindowserror(sysfunc, iftrue::Bool)\n\nLike systemerror, but for Windows API functions that use GetLastError to return an error code instead of setting errno.\n\n\n\n\n\n","category":"function"},{"location":"base/c/#Core.Ptr","page":"C 接口","title":"Core.Ptr","text":"Ptr{T}\n\nA memory address referring to data of type T. However, there is no guarantee that the memory is actually valid, or that it actually represents data of the specified type.\n\n\n\n\n\n","category":"type"},{"location":"base/c/#Core.Ref","page":"C 接口","title":"Core.Ref","text":"Ref{T}\n\nAn object that safely references data of type T. This type is guaranteed to point to valid, Julia-allocated memory of the correct type. The underlying data is protected from freeing by the garbage collector as long as the Ref itself is referenced.\n\nIn Julia, Ref objects are dereferenced (loaded or stored) with [].\n\nCreation of a Ref to a value x of type T is usually written Ref(x). Additionally, for creating interior pointers to containers (such as Array or Ptr), it can be written Ref(a, i) for creating a reference to the i-th element of a.\n\nRef{T}() creates a reference to a value of type T without initialization. For a bitstype T, the value will be whatever currently resides in the memory allocated. For a non-bitstype T, the reference will be undefined and attempting to dereference it will result in an error, \"UndefRefError: access to undefined reference\".\n\nTo check if a Ref is an undefined reference, use isassigned(ref::RefValue). For example, isassigned(Ref{T}()) is false if T is not a bitstype. If T is a bitstype, isassigned(Ref{T}()) will always be true.\n\nWhen passed as a ccall argument (either as a Ptr or Ref type), a Ref object will be converted to a native pointer to the data it references. For most T, or when converted to a Ptr{Cvoid}, this is a pointer to the object data. When T is an isbits type, this value may be safely mutated, otherwise mutation is strictly undefined behavior.\n\nAs a special case, setting T = Any will instead cause the creation of a pointer to the reference itself when converted to a Ptr{Any} (a jl_value_t const* const* if T is immutable, else a jl_value_t *const *). When converted to a Ptr{Cvoid}, it will still return a pointer to the data region as for any other T.\n\nA C_NULL instance of Ptr can be passed to a ccall Ref argument to initialize it.\n\nUse in broadcasting\n\nRef is sometimes used in broadcasting in order to treat the referenced values as a scalar.\n\nExamples\n\njulia> Ref(5)\nBase.RefValue{Int64}(5)\n\njulia> isa.(Ref([1,2,3]), [Array, Dict, Int]) # Treat reference values as scalar during broadcasting\n3-element BitVector:\n 1\n 0\n 0\n\njulia> Ref{Function}() # Undefined reference to a non-bitstype, Function\nBase.RefValue{Function}(#undef)\n\njulia> try\n Ref{Function}()[] # Dereferencing an undefined reference will result in an error\n catch e\n println(e)\n end\nUndefRefError()\n\njulia> Ref{Int64}()[]; # A reference to a bitstype refers to an undetermined value if not given\n\njulia> isassigned(Ref{Int64}()) # A reference to a bitstype is always assigned\ntrue\n\njulia> Ref{Int64}(0)[] == 0 # Explicitly give a value for a bitstype reference\ntrue\n\n\n\n\n\n","category":"type"},{"location":"base/c/#Base.isassigned-Tuple{Base.RefValue}","page":"C 接口","title":"Base.isassigned","text":"isassigned(ref::RefValue) -> Bool\n\nTest whether the given Ref is associated with a value. This is always true for a Ref of a bitstype object. Return false if the reference is undefined.\n\nExamples\n\njulia> ref = Ref{Function}()\nBase.RefValue{Function}(#undef)\n\njulia> isassigned(ref)\nfalse\n\njulia> ref[] = (foobar(x) = x)\nfoobar (generic function with 1 method)\n\njulia> isassigned(ref)\ntrue\n\njulia> isassigned(Ref{Int}())\ntrue\n\n\n\n\n\n","category":"method"},{"location":"base/c/#Base.Cchar","page":"C 接口","title":"Base.Cchar","text":"Cchar\n\nEquivalent to the native char c-type.\n\n\n\n\n\n","category":"type"},{"location":"base/c/#Base.Cuchar","page":"C 接口","title":"Base.Cuchar","text":"Cuchar\n\nEquivalent to the native unsigned char c-type (UInt8).\n\n\n\n\n\n","category":"type"},{"location":"base/c/#Base.Cshort","page":"C 接口","title":"Base.Cshort","text":"Cshort\n\nEquivalent to the native signed short c-type (Int16).\n\n\n\n\n\n","category":"type"},{"location":"base/c/#Base.Cstring","page":"C 接口","title":"Base.Cstring","text":"Cstring\n\nA C-style string composed of the native character type Cchars. Cstrings are NUL-terminated. For C-style strings composed of the native wide character type, see Cwstring. For more information about string interopability with C, see the manual.\n\n\n\n\n\n","category":"type"},{"location":"base/c/#Base.Cushort","page":"C 接口","title":"Base.Cushort","text":"Cushort\n\nEquivalent to the native unsigned short c-type (UInt16).\n\n\n\n\n\n","category":"type"},{"location":"base/c/#Base.Cint","page":"C 接口","title":"Base.Cint","text":"Cint\n\nEquivalent to the native signed int c-type (Int32).\n\n\n\n\n\n","category":"type"},{"location":"base/c/#Base.Cuint","page":"C 接口","title":"Base.Cuint","text":"Cuint\n\nEquivalent to the native unsigned int c-type (UInt32).\n\n\n\n\n\n","category":"type"},{"location":"base/c/#Base.Clong","page":"C 接口","title":"Base.Clong","text":"Clong\n\nEquivalent to the native signed long c-type.\n\n\n\n\n\n","category":"type"},{"location":"base/c/#Base.Culong","page":"C 接口","title":"Base.Culong","text":"Culong\n\nEquivalent to the native unsigned long c-type.\n\n\n\n\n\n","category":"type"},{"location":"base/c/#Base.Clonglong","page":"C 接口","title":"Base.Clonglong","text":"Clonglong\n\nEquivalent to the native signed long long c-type (Int64).\n\n\n\n\n\n","category":"type"},{"location":"base/c/#Base.Culonglong","page":"C 接口","title":"Base.Culonglong","text":"Culonglong\n\nEquivalent to the native unsigned long long c-type (UInt64).\n\n\n\n\n\n","category":"type"},{"location":"base/c/#Base.Cintmax_t","page":"C 接口","title":"Base.Cintmax_t","text":"Cintmax_t\n\nEquivalent to the native intmax_t c-type (Int64).\n\n\n\n\n\n","category":"type"},{"location":"base/c/#Base.Cuintmax_t","page":"C 接口","title":"Base.Cuintmax_t","text":"Cuintmax_t\n\nEquivalent to the native uintmax_t c-type (UInt64).\n\n\n\n\n\n","category":"type"},{"location":"base/c/#Base.Csize_t","page":"C 接口","title":"Base.Csize_t","text":"Csize_t\n\nEquivalent to the native size_t c-type (UInt).\n\n\n\n\n\n","category":"type"},{"location":"base/c/#Base.Cssize_t","page":"C 接口","title":"Base.Cssize_t","text":"Cssize_t\n\nEquivalent to the native ssize_t c-type.\n\n\n\n\n\n","category":"type"},{"location":"base/c/#Base.Cptrdiff_t","page":"C 接口","title":"Base.Cptrdiff_t","text":"Cptrdiff_t\n\nEquivalent to the native ptrdiff_t c-type (Int).\n\n\n\n\n\n","category":"type"},{"location":"base/c/#Base.Cwchar_t","page":"C 接口","title":"Base.Cwchar_t","text":"Cwchar_t\n\nEquivalent to the native wchar_t c-type (Int32).\n\n\n\n\n\n","category":"type"},{"location":"base/c/#Base.Cwstring","page":"C 接口","title":"Base.Cwstring","text":"Cwstring\n\nA C-style string composed of the native wide character type Cwchar_ts. Cwstrings are NUL-terminated. For C-style strings composed of the native character type, see Cstring. For more information about string interopability with C, see the manual.\n\n\n\n\n\n","category":"type"},{"location":"base/c/#Base.Cfloat","page":"C 接口","title":"Base.Cfloat","text":"Cfloat\n\nEquivalent to the native float c-type (Float32).\n\n\n\n\n\n","category":"type"},{"location":"base/c/#Base.Cdouble","page":"C 接口","title":"Base.Cdouble","text":"Cdouble\n\nEquivalent to the native double c-type (Float64).\n\n\n\n\n\n","category":"type"},{"location":"base/c/#LLVM-接口","page":"C 接口","title":"LLVM 接口","text":"","category":"section"},{"location":"base/c/","page":"C 接口","title":"C 接口","text":"Core.Intrinsics.llvmcall","category":"page"},{"location":"base/c/#Core.Intrinsics.llvmcall","page":"C 接口","title":"Core.Intrinsics.llvmcall","text":"llvmcall(fun_ir::String, returntype, Tuple{argtype1, ...}, argvalue1, ...)\nllvmcall((mod_ir::String, entry_fn::String), returntype, Tuple{argtype1, ...}, argvalue1, ...)\nllvmcall((mod_bc::Vector{UInt8}, entry_fn::String), returntype, Tuple{argtype1, ...}, argvalue1, ...)\n\nCall the LLVM code provided in the first argument. There are several ways to specify this first argument:\n\nas a literal string, representing function-level IR (similar to an LLVM define block), with arguments are available as consecutive unnamed SSA variables (%0, %1, etc.);\nas a 2-element tuple, containing a string of module IR and a string representing the name of the entry-point function to call;\nas a 2-element tuple, but with the module provided as an Vector{UINt8} with bitcode.\n\nNote that contrary to ccall, the argument types must be specified as a tuple type, and not a tuple of types. All types, as well as the LLVM code, should be specified as literals, and not as variables or expressions (it may be necessary to use @eval to generate these literals).\n\nSee test/llvmcall.jl for usage examples.\n\n\n\n\n\n","category":"function"},{"location":"manual/mathematical-operations/#数学运算和初等函数","page":"数学运算和初等函数","title":"数学运算和初等函数","text":"","category":"section"},{"location":"manual/mathematical-operations/","page":"数学运算和初等函数","title":"数学运算和初等函数","text":"Julia 为它所有的基础数值类型,提供了整套的基础算术和位运算,也提供了一套高效、可移植的标准数学函数。","category":"page"},{"location":"manual/mathematical-operations/#算术运算符","page":"数学运算和初等函数","title":"算术运算符","text":"","category":"section"},{"location":"manual/mathematical-operations/","page":"数学运算和初等函数","title":"数学运算和初等函数","text":"以下算术运算符支持所有的原始数值类型:","category":"page"},{"location":"manual/mathematical-operations/","page":"数学运算和初等函数","title":"数学运算和初等函数","text":"表达式 名称 描述\n+x 一元加法运算符 全等操作\n-x 一元减法运算符 将值变为其相反数\nx + y 二元加法运算符 执行加法\nx - y 二元减法运算符 执行减法\nx * y 乘法运算符 执行乘法\nx / y 除法运算符 执行除法\nx ÷ y 整除 取 x / y 的整数部分\nx \\ y 反向除法 等价于 y / x\nx ^ y 幂操作符 x 的 y 次幂\nx % y 取余 等价于 rem(x,y)","category":"page"},{"location":"manual/mathematical-operations/","page":"数学运算和初等函数","title":"数学运算和初等函数","text":"除了优先级比二元操作符高以外,直接放在标识符或括号前的数字,如 2x 或 2(x+y) 还会被视为乘法。详见数值字面量系数。","category":"page"},{"location":"manual/mathematical-operations/","page":"数学运算和初等函数","title":"数学运算和初等函数","text":"Julia 的类型提升系统使得混合参数类型上的代数运算也能顺其自然的工作,请参考类型提升系统来了解更多内容。","category":"page"},{"location":"manual/mathematical-operations/","page":"数学运算和初等函数","title":"数学运算和初等函数","text":"符号 ÷ 可以通过输入 \\div 到 REPL 或 Julia IDE 的方式来打出. 更多信息参见 Unicode 输入表。","category":"page"},{"location":"manual/mathematical-operations/","page":"数学运算和初等函数","title":"数学运算和初等函数","text":"这里是使用算术运算符的一些简单例子:","category":"page"},{"location":"manual/mathematical-operations/","page":"数学运算和初等函数","title":"数学运算和初等函数","text":"julia> 1 + 2 + 3\n6\n\njulia> 1 - 2\n-1\n\njulia> 3*2/12\n0.5","category":"page"},{"location":"manual/mathematical-operations/","page":"数学运算和初等函数","title":"数学运算和初等函数","text":"习惯上我们会把优先运算的操作符紧邻操作数,比如 -x + 2 表示先要给 x 取反,然后再加 2 。","category":"page"},{"location":"manual/mathematical-operations/","page":"数学运算和初等函数","title":"数学运算和初等函数","text":"在乘法操作中,false 被视作 零。","category":"page"},{"location":"manual/mathematical-operations/","page":"数学运算和初等函数","title":"数学运算和初等函数","text":"julia> NaN * false\n0.0\n\njulia> false * Inf\n0.0","category":"page"},{"location":"manual/mathematical-operations/","page":"数学运算和初等函数","title":"数学运算和初等函数","text":"这在已知某些量为零时,可以避免 NaN 的传播。详细的动机参见:Knuth (1992)。","category":"page"},{"location":"manual/mathematical-operations/#布尔运算符","page":"数学运算和初等函数","title":"布尔运算符","text":"","category":"section"},{"location":"manual/mathematical-operations/","page":"数学运算和初等函数","title":"数学运算和初等函数","text":"Bool 类型支持以下布尔运算符:","category":"page"},{"location":"manual/mathematical-operations/","page":"数学运算和初等函数","title":"数学运算和初等函数","text":"表达式 名称\n!x 否定\nx && y 短路与\nx || y 短路或","category":"page"},{"location":"manual/mathematical-operations/","page":"数学运算和初等函数","title":"数学运算和初等函数","text":"否定将 true 更改为 false,反之亦然。链接页面上解释了逻辑短路。","category":"page"},{"location":"manual/mathematical-operations/","page":"数学运算和初等函数","title":"数学运算和初等函数","text":"请注意,Bool 是一个整数类型,所有常用的类型提升规则和数字运算符仍然对它适用。","category":"page"},{"location":"manual/mathematical-operations/#位运算符","page":"数学运算和初等函数","title":"位运算符","text":"","category":"section"},{"location":"manual/mathematical-operations/","page":"数学运算和初等函数","title":"数学运算和初等函数","text":"所有原始整数类型都支持以下位运算符:","category":"page"},{"location":"manual/mathematical-operations/","page":"数学运算和初等函数","title":"数学运算和初等函数","text":"表达式 名称\n~x 按位取反\nx & y 按位与\nx | y 按位或\nx ⊻ y 按位异或(逻辑异或)\nx ⊼ y 按位与(非与)\nx ⊽ y 按位或(非或)\nx >>> y 逻辑右移\nx >> y 算术右移\nx << y 逻辑/算术左移","category":"page"},{"location":"manual/mathematical-operations/","page":"数学运算和初等函数","title":"数学运算和初等函数","text":"以下是位运算符的一些示例:","category":"page"},{"location":"manual/mathematical-operations/","page":"数学运算和初等函数","title":"数学运算和初等函数","text":"julia> ~123\n-124\n\njulia> 123 & 234\n106\n\njulia> 123 | 234\n251\n\njulia> 123 ⊻ 234\n145\n\njulia> xor(123, 234)\n145\n\njulia> nand(123, 123)\n-124\n\njulia> 123 ⊼ 123\n-124\n\njulia> nor(123, 124)\n-128\n\njulia> 123 ⊽ 124\n-128\n\njulia> ~UInt32(123)\n0xffffff84\n\njulia> ~UInt8(123)\n0x84","category":"page"},{"location":"manual/mathematical-operations/#复合赋值运算符","page":"数学运算和初等函数","title":"复合赋值运算符","text":"","category":"section"},{"location":"manual/mathematical-operations/","page":"数学运算和初等函数","title":"数学运算和初等函数","text":"每一个二元运算符和位运算符都可以给左操作数复合赋值:方法是把 = 直接放在二元运算符后面。比如,x += 3 等价于 x = x + 3 。","category":"page"},{"location":"manual/mathematical-operations/","page":"数学运算和初等函数","title":"数学运算和初等函数","text":"julia> x = 1\n1\n\njulia> x += 3\n4\n\njulia> x\n4","category":"page"},{"location":"manual/mathematical-operations/","page":"数学运算和初等函数","title":"数学运算和初等函数","text":"二元运算符和位运算符的复合赋值操作符有下面几种:","category":"page"},{"location":"manual/mathematical-operations/","page":"数学运算和初等函数","title":"数学运算和初等函数","text":"+= -= *= /= \\= ÷= %= ^= &= |= ⊻= >>>= >>= <<=","category":"page"},{"location":"manual/mathematical-operations/","page":"数学运算和初等函数","title":"数学运算和初等函数","text":"note: Note\n复合赋值后会把变量重新绑定到左操作数上,所以变量的类型可能会改变。julia> x = 0x01; typeof(x)\nUInt8\n\njulia> x *= 2 # 与 x = x * 2 相同\n2\n\njulia> typeof(x)\nInt64","category":"page"},{"location":"manual/mathematical-operations/#man-dot-operators","page":"数学运算和初等函数","title":"向量化 “点” 运算符","text":"","category":"section"},{"location":"manual/mathematical-operations/","page":"数学运算和初等函数","title":"数学运算和初等函数","text":"Julia 中,每个二元运算符都有一个 “点” 运算符与之对应,例如 ^ 就有对应的 .^ 存在。这个对应的 .^ 被 Julia 自动地定义为逐元素地执行 ^ 运算。比如 [1,2,3] ^ 3 是非法的,因为数学上没有给(长宽不一样的)数组的立方下过定义。但是 [1,2,3] .^ 3 在 Julia 里是合法的,它会逐元素地执行 ^ 运算(或称向量化运算),得到 [1^3, 2^3, 3^3]。类似地,! 或 √ 这样的一元运算符,也都有一个对应的 .√ 用于执行逐元素运算。","category":"page"},{"location":"manual/mathematical-operations/","page":"数学运算和初等函数","title":"数学运算和初等函数","text":"julia> [1,2,3] .^ 3\n3-element Vector{Int64}:\n 1\n 8\n 27","category":"page"},{"location":"manual/mathematical-operations/","page":"数学运算和初等函数","title":"数学运算和初等函数","text":"更确切地说,a .^b 被解析为 “点运算” 调用 (^).(a,b),这会执行 广播 操作:该操作能结合数组和标量、相同大小的数组(进行元素之间的运算),甚至不同形状的数组(例如行、列向量结合生成矩阵)。此外,就像所有向量化的点运算调用一样,这些点运算符是融合的。例如,在计算关于数组 A 的表达式 2 .* A.^2 .+ sin.(A)(或者等价地,使用@. 宏,@. 2A^2 + sin(A)),Julia 只对 A 进行做一次循环,遍历 A 中的每个元素 a 并计算 2a^2 + sin(a)。特别的,类似 f.(g.(x)) 的嵌套点运算调用也是融合的,并且“相邻的”二元运算符表达式 x .+ 3 .* x.^2 可以等价转换为嵌套 dot 调用:(+).(x, (*).(3, (^).(x, 2)))。","category":"page"},{"location":"manual/mathematical-operations/","page":"数学运算和初等函数","title":"数学运算和初等函数","text":"除了点运算符,我们还有逐点赋值运算符,类似 a .+= b(或者 @. a += b)会被解析成 a .= a .+ b,这里的 .= 是一个融合的 in-place 运算,更多信息请查看 dot 文档)。","category":"page"},{"location":"manual/mathematical-operations/","page":"数学运算和初等函数","title":"数学运算和初等函数","text":"这个点语法,也能用在用户自定义的运算符上。例如,通过定义 ⊗(A,B) = kron(A,B) 可以为 Kronecker 积(kron)提供一个方便的中缀语法 A ⊗ B,那么配合点语法 [A,B] .⊗ [C,D] 就等价于 [A⊗C, B⊗D]。","category":"page"},{"location":"manual/mathematical-operations/","page":"数学运算和初等函数","title":"数学运算和初等函数","text":"将点运算符用于数值字面量可能会导致歧义。例如,1.+x 到底是表示 1. + x 还是 1 .+ x?这会令人疑惑。因此不允许使用这种语法,遇到这种情况时,必须明确地用空格消除歧义。","category":"page"},{"location":"manual/mathematical-operations/#数值比较","page":"数学运算和初等函数","title":"数值比较","text":"","category":"section"},{"location":"manual/mathematical-operations/","page":"数学运算和初等函数","title":"数学运算和初等函数","text":"标准的比较操作对所有原始数值类型有定义:","category":"page"},{"location":"manual/mathematical-operations/","page":"数学运算和初等函数","title":"数学运算和初等函数","text":"操作符 名称\n== 相等\n!=, ≠ 不等\n< 小于\n<=, ≤ 小于等于\n> 大于\n>=, ≥ 大于等于","category":"page"},{"location":"manual/mathematical-operations/","page":"数学运算和初等函数","title":"数学运算和初等函数","text":"下面是一些简单的例子:","category":"page"},{"location":"manual/mathematical-operations/","page":"数学运算和初等函数","title":"数学运算和初等函数","text":"julia> 1 == 1\ntrue\n\njulia> 1 == 2\nfalse\n\njulia> 1 != 2\ntrue\n\njulia> 1 == 1.0\ntrue\n\njulia> 1 < 2\ntrue\n\njulia> 1.0 > 3\nfalse\n\njulia> 1 >= 1.0\ntrue\n\njulia> -1 <= 1\ntrue\n\njulia> -1 <= -1\ntrue\n\njulia> -1 <= -2\nfalse\n\njulia> 3 < -0.5\nfalse","category":"page"},{"location":"manual/mathematical-operations/","page":"数学运算和初等函数","title":"数学运算和初等函数","text":"整数的比较方式是标准的按位比较,而浮点数的比较方式则遵循 IEEE 754 标准。","category":"page"},{"location":"manual/mathematical-operations/","page":"数学运算和初等函数","title":"数学运算和初等函数","text":"有限数的大小顺序,和我们所熟知的相同。\n+0 等于但不大于 -0.\nInf 等于自身,并且大于除了 NaN 外的所有数。\n-Inf 等于自身,并且小于除了 NaN 外的所有数。\nNaN 不等于、不小于且不大于任何数值,包括它自己。","category":"page"},{"location":"manual/mathematical-operations/","page":"数学运算和初等函数","title":"数学运算和初等函数","text":"NaN 不等于它自己这一点可能会令人感到惊奇,所以需要注意:","category":"page"},{"location":"manual/mathematical-operations/","page":"数学运算和初等函数","title":"数学运算和初等函数","text":"julia> NaN == NaN\nfalse\n\njulia> NaN != NaN\ntrue\n\njulia> NaN < NaN\nfalse\n\njulia> NaN > NaN\nfalse","category":"page"},{"location":"manual/mathematical-operations/","page":"数学运算和初等函数","title":"数学运算和初等函数","text":"当你将 NaN 和 数组 一起连用时,你就会感到头疼:","category":"page"},{"location":"manual/mathematical-operations/","page":"数学运算和初等函数","title":"数学运算和初等函数","text":"julia> [1 NaN] == [1 NaN]\nfalse","category":"page"},{"location":"manual/mathematical-operations/","page":"数学运算和初等函数","title":"数学运算和初等函数","text":"为此,Julia 给这些特别的数提供了下面几个额外的测试函数。这些函数在某些情况下很有用处,比如在做 hash 比较时。","category":"page"},{"location":"manual/mathematical-operations/","page":"数学运算和初等函数","title":"数学运算和初等函数","text":"函数 测试是否满足如下性质\nisequal(x, y) x 与 y 是完全相同的\nisfinite(x) x 是有限大的数字\nisinf(x) x 是(正/负)无穷大\nisnan(x) x 是 NaN","category":"page"},{"location":"manual/mathematical-operations/","page":"数学运算和初等函数","title":"数学运算和初等函数","text":"isequal 认为 NaN 之间是相等的:","category":"page"},{"location":"manual/mathematical-operations/","page":"数学运算和初等函数","title":"数学运算和初等函数","text":"julia> isequal(NaN, NaN)\ntrue\n\njulia> isequal([1 NaN], [1 NaN])\ntrue\n\njulia> isequal(NaN, NaN32)\ntrue","category":"page"},{"location":"manual/mathematical-operations/","page":"数学运算和初等函数","title":"数学运算和初等函数","text":"isequal 也能用来区分带符号的零:","category":"page"},{"location":"manual/mathematical-operations/","page":"数学运算和初等函数","title":"数学运算和初等函数","text":"julia> -0.0 == 0.0\ntrue\n\njulia> isequal(-0.0, 0.0)\nfalse","category":"page"},{"location":"manual/mathematical-operations/","page":"数学运算和初等函数","title":"数学运算和初等函数","text":"有符号整数、无符号整数以及浮点数之间的混合类型比较是很棘手的。开发者费了很大精力来确保 Julia 在这个问题上做的是正确的。","category":"page"},{"location":"manual/mathematical-operations/","page":"数学运算和初等函数","title":"数学运算和初等函数","text":"对于其它类型,isequal 会默认调用 ==,所以如果你想给自己的类型定义相等,那么就只需要为 == 增加一个方法。如果你想定义一个你自己的相等函数,你可能需要定义一个对应的 hash 方法,用于确保 isequal(x,y) 隐含着 hash(x) == hash(y)。","category":"page"},{"location":"manual/mathematical-operations/#链式比较","page":"数学运算和初等函数","title":"链式比较","text":"","category":"section"},{"location":"manual/mathematical-operations/","page":"数学运算和初等函数","title":"数学运算和初等函数","text":"与其他多数语言不同,就像 notable exception of Python 一样,Julia 允许链式比较:","category":"page"},{"location":"manual/mathematical-operations/","page":"数学运算和初等函数","title":"数学运算和初等函数","text":"julia> 1 < 2 <= 2 < 3 == 3 > 2 >= 1 == 1 < 3 != 5\ntrue","category":"page"},{"location":"manual/mathematical-operations/","page":"数学运算和初等函数","title":"数学运算和初等函数","text":"链式比较在写数值代码时特别方便,它使用 && 运算符比较标量,数组则用 & 进行按元素比较。比如,0 .< A .< 1 会得到一个 boolean 数组,如果 A 的元素都在 0 和 1 之间则数组元素就都是 true。","category":"page"},{"location":"manual/mathematical-operations/","page":"数学运算和初等函数","title":"数学运算和初等函数","text":"注意链式比较的执行顺序:","category":"page"},{"location":"manual/mathematical-operations/","page":"数学运算和初等函数","title":"数学运算和初等函数","text":"julia> v(x) = (println(x); x)\nv (generic function with 1 method)\n\njulia> v(1) < v(2) <= v(3)\n2\n1\n3\ntrue\n\njulia> v(1) > v(2) <= v(3)\n2\n1\nfalse","category":"page"},{"location":"manual/mathematical-operations/","page":"数学运算和初等函数","title":"数学运算和初等函数","text":"中间的表达式只会计算一次,而如果写成 v(1) < v(2) && v(2) <= v(3) 是计算了两次的。然而,链式比较中的顺序是不确定的。强烈建议不要在表达式中使用有副作用(比如 printing)的函数。如果的确需要,请使用短路运算符 &&(请参考短路求值)。","category":"page"},{"location":"manual/mathematical-operations/#初等函数","page":"数学运算和初等函数","title":"初等函数","text":"","category":"section"},{"location":"manual/mathematical-operations/","page":"数学运算和初等函数","title":"数学运算和初等函数","text":"Julia 提供了强大的数学函数和运算符集合。这些数学运算定义在各种合理的数值上,包括整型、浮点数、分数和复数,只要这些定义有数学意义就行。","category":"page"},{"location":"manual/mathematical-operations/","page":"数学运算和初等函数","title":"数学运算和初等函数","text":"而且,和其它 Julia 函数一样,这些函数也能通过 点语法 f.(A) 以“向量化”的方式作用于数组和其它集合上。 比如,sin.(A) 会计算 A 中每个元素的 sin 值。","category":"page"},{"location":"manual/mathematical-operations/#运算符的优先级与结合性","page":"数学运算和初等函数","title":"运算符的优先级与结合性","text":"","category":"section"},{"location":"manual/mathematical-operations/","page":"数学运算和初等函数","title":"数学运算和初等函数","text":"从高到低,Julia 运算符的优先级与结合性为:","category":"page"},{"location":"manual/mathematical-operations/","page":"数学运算和初等函数","title":"数学运算和初等函数","text":"分类 运算符 结合性\n语法 . followed by :: 左结合\n幂运算 ^ 右结合\n一元运算符 + - √ 右结合[1]\n移位运算 << >> >>> 左结合\n除法 // 左结合\n乘法 * / % & \\ ÷ 左结合[2]\n加法 + - | ⊻ 左结合[2]\n语法 : .. 左结合\n语法 |> 左结合\n语法 <| 右结合\n比较 > < >= <= == === != !== <: 无结合性\n流程控制 && followed by || followed by ? 右结合\nPair 操作 => 右结合\n赋值 = += -= *= /= //= \\= ^= ÷= %= |= &= ⊻= <<= >>= >>>= 右结合","category":"page"},{"location":"manual/mathematical-operations/","page":"数学运算和初等函数","title":"数学运算和初等函数","text":"[1]: 一元运算符 + 和 - 需要显式调用,即给它们的参数加上括号,以免和 ++ 等运算符混淆。其它一元运算符的混合使用都被解析为右结合的,比如 √√-a 解析为 √(√(-a))。","category":"page"},{"location":"manual/mathematical-operations/","page":"数学运算和初等函数","title":"数学运算和初等函数","text":"[2]: The operators +, ++ and * are non-associative. a + b + c is parsed as +(a, b, c) not +(+(a, b), c). However, the fallback methods for +(a, b, c, d...) and *(a, b, c, d...) both default to left-associative evaluation.","category":"page"},{"location":"manual/mathematical-operations/","page":"数学运算和初等函数","title":"数学运算和初等函数","text":"想查看 每个 Julia 运算符的优先级,可以参考这个文件:src/julia-parser.scm。注意到有一些运算符在 Base 模块中没有定义但是可能是在标准库、包或者用户代码中定义的。","category":"page"},{"location":"manual/mathematical-operations/","page":"数学运算和初等函数","title":"数学运算和初等函数","text":"你也可以通过内置函数 Base.operator_precedence 查看任何给定运算符的优先级数值,数值越大优先级越高:","category":"page"},{"location":"manual/mathematical-operations/","page":"数学运算和初等函数","title":"数学运算和初等函数","text":"julia> Base.operator_precedence(:+), Base.operator_precedence(:*), Base.operator_precedence(:.)\n(11, 12, 17)\n\njulia> Base.operator_precedence(:sin), Base.operator_precedence(:+=), Base.operator_precedence(:(=)) # (注意:等号前后必须有括号 `:(=)`)\n(0, 1, 1)","category":"page"},{"location":"manual/mathematical-operations/","page":"数学运算和初等函数","title":"数学运算和初等函数","text":"另外,内置函数 Base.operator_associativity 可以返回运算符结合性的符号表示:","category":"page"},{"location":"manual/mathematical-operations/","page":"数学运算和初等函数","title":"数学运算和初等函数","text":"julia> Base.operator_associativity(:-), Base.operator_associativity(:+), Base.operator_associativity(:^)\n(:left, :none, :right)\n\njulia> Base.operator_associativity(:⊗), Base.operator_associativity(:sin), Base.operator_associativity(:→)\n(:left, :none, :right)","category":"page"},{"location":"manual/mathematical-operations/","page":"数学运算和初等函数","title":"数学运算和初等函数","text":"注意诸如 :sin 这样的符号返回优先级 0,此值代表无效的运算符或非最低优先级运算符。类似地,它们的结合性被认为是 :none。","category":"page"},{"location":"manual/mathematical-operations/","page":"数学运算和初等函数","title":"数学运算和初等函数","text":"数字字面量系数,例如 2x 被视为比任何其他二元运算具有更高优先级的乘法,除了^,指数计算具有更高的优先级。","category":"page"},{"location":"manual/mathematical-operations/","page":"数学运算和初等函数","title":"数学运算和初等函数","text":"julia> x = 3; 2x^2\n18\n\njulia> x = 3; 2^2x\n64","category":"page"},{"location":"manual/mathematical-operations/","page":"数学运算和初等函数","title":"数学运算和初等函数","text":"并列解析就像一元运算符,它在指数周围具有相同的自然不对称性:-x^y 和 2x^y解析为 -(x^y) 和 2(x^y) 而 x^-y 和 x^2y 解析为x^(-y) 和 x^(2y)。","category":"page"},{"location":"manual/mathematical-operations/#数值转换","page":"数学运算和初等函数","title":"数值转换","text":"","category":"section"},{"location":"manual/mathematical-operations/","page":"数学运算和初等函数","title":"数学运算和初等函数","text":"Julia 支持三种数值转换,它们在处理不精确转换上有所不同。","category":"page"},{"location":"manual/mathematical-operations/","page":"数学运算和初等函数","title":"数学运算和初等函数","text":"T(x) 和 convert(T,x) 都会把 x 转换为 T类型。\n如果 T 是浮点类型,转换的结果就是最近的可表示值, 可能会是正负无穷大。\n如果 T 为整数类型,当 x 不能由 T 类型表示时,会抛出 InexactError。\nx % T 将整数 x 转换为整型 T,与 x 模 2^n 的结果一致,其中 n 是 T 的位数。换句话说,在二进制表示下被截掉了一部分。\n舍入函数 接收一个 T 类型的可选参数。比如,round(Int,x) 是 Int(round(x)) 的简写版。","category":"page"},{"location":"manual/mathematical-operations/","page":"数学运算和初等函数","title":"数学运算和初等函数","text":"下面的例子展示了不同的形式","category":"page"},{"location":"manual/mathematical-operations/","page":"数学运算和初等函数","title":"数学运算和初等函数","text":"julia> Int8(127)\n127\n\njulia> Int8(128)\nERROR: InexactError: trunc(Int8, 128)\nStacktrace:\n[...]\n\njulia> Int8(127.0)\n127\n\njulia> Int8(3.14)\nERROR: InexactError: Int8(3.14)\nStacktrace:\n[...]\n\njulia> Int8(128.0)\nERROR: InexactError: Int8(128.0)\nStacktrace:\n[...]\n\njulia> 127 % Int8\n127\n\njulia> 128 % Int8\n-128\n\njulia> round(Int8,127.4)\n127\n\njulia> round(Int8,127.6)\nERROR: InexactError: trunc(Int8, 128.0)\nStacktrace:\n[...]","category":"page"},{"location":"manual/mathematical-operations/","page":"数学运算和初等函数","title":"数学运算和初等函数","text":"请参考类型转换与类型提升一节来定义你自己的类型转换和提升规则。","category":"page"},{"location":"manual/mathematical-operations/#舍入函数","page":"数学运算和初等函数","title":"舍入函数","text":"","category":"section"},{"location":"manual/mathematical-operations/","page":"数学运算和初等函数","title":"数学运算和初等函数","text":"函数 描述 返回类型\nround(x) x 舍到最接近的整数 typeof(x)\nround(T, x) x 舍到最接近的整数 T\nfloor(x) x 向 -Inf 舍入 typeof(x)\nfloor(T, x) x 向 -Inf 舍入 T\nceil(x) x 向 +Inf 方向取整 typeof(x)\nceil(T, x) x 向 +Inf 方向取整 T\ntrunc(x) x 向 0 取整 typeof(x)\ntrunc(T, x) x 向 0 取整 T","category":"page"},{"location":"manual/mathematical-operations/#除法函数","page":"数学运算和初等函数","title":"除法函数","text":"","category":"section"},{"location":"manual/mathematical-operations/","page":"数学运算和初等函数","title":"数学运算和初等函数","text":"函数 描述\ndiv(x,y), x÷y 截断除法;商向零近似\nfld(x,y) 向下取整除法;商向 -Inf 近似\ncld(x,y) 向上取整除法;商向 +Inf 近似\nrem(x,y) 取余;满足 x == div(x,y)*y + rem(x,y);符号与 x 一致\nmod(x,y) 取模;满足 x == fld(x,y)*y + mod(x,y);符号与 y 一致\nmod1(x,y) 偏移 1 的 mod;若 y>0,则返回 r∈(0,y],若 y<0,则 r∈[y,0) 且满足 mod(r, y) == mod(x, y)\nmod2pi(x) 对 2pi 取模;0 <= mod2pi(x) < 2pi\ndivrem(x,y) 返回 (div(x,y),rem(x,y))\nfldmod(x,y) 返回 (fld(x,y),mod(x,y))\ngcd(x,y...) x, y,... 的最大公约数\nlcm(x,y...) x, y,... 的最小公倍数","category":"page"},{"location":"manual/mathematical-operations/#符号和绝对值函数","page":"数学运算和初等函数","title":"符号和绝对值函数","text":"","category":"section"},{"location":"manual/mathematical-operations/","page":"数学运算和初等函数","title":"数学运算和初等函数","text":"函数 描述\nabs(x) x 的模\nabs2(x) x 的模的平方\nsign(x) 表示 x 的符号,返回 -1,0,或 +1\nsignbit(x) 表示符号位是 true 或 false\ncopysign(x,y) 返回一个数,其值等于 x 的模,符号与 y 一致\nflipsign(x,y) 返回一个数,其值等于 x 的模,符号与 x*y 一致","category":"page"},{"location":"manual/mathematical-operations/#幂、对数与平方根","page":"数学运算和初等函数","title":"幂、对数与平方根","text":"","category":"section"},{"location":"manual/mathematical-operations/","page":"数学运算和初等函数","title":"数学运算和初等函数","text":"函数 描述\nsqrt(x), √x x 的平方根\ncbrt(x), ∛x x 的立方根\nhypot(x,y) 当直角边的长度为 x 和 y时,直角三角形斜边的长度\nexp(x) 自然指数函数在 x 处的值\nexpm1(x) 当 x 接近 0 时的 exp(x)-1 的精确值\nldexp(x,n) x*2^n 的高效算法,n 为整数\nlog(x) x 的自然对数\nlog(b,x) 以 b 为底 x 的对数\nlog2(x) 以 2 为底 x 的对数\nlog10(x) 以 10 为底 x 的对数\nlog1p(x) 当 x接近 0 时的 log(1+x) 的精确值\nexponent(x) x 的二进制指数\nsignificand(x) 浮点数 x 的二进制有效数(也就是尾数)","category":"page"},{"location":"manual/mathematical-operations/","page":"数学运算和初等函数","title":"数学运算和初等函数","text":"想大概了解一下为什么诸如 hypot、expm1和 log1p 函数是必要和有用的,可以看一下 John D. Cook 关于这些主题的两篇优秀博文:expm1, log1p, erfc, 和 hypot。","category":"page"},{"location":"manual/mathematical-operations/#三角和双曲函数","page":"数学运算和初等函数","title":"三角和双曲函数","text":"","category":"section"},{"location":"manual/mathematical-operations/","page":"数学运算和初等函数","title":"数学运算和初等函数","text":"所有标准的三角和双曲函数也都已经定义了:","category":"page"},{"location":"manual/mathematical-operations/","page":"数学运算和初等函数","title":"数学运算和初等函数","text":"sin cos tan cot sec csc\nsinh cosh tanh coth sech csch\nasin acos atan acot asec acsc\nasinh acosh atanh acoth asech acsch\nsinc cosc","category":"page"},{"location":"manual/mathematical-operations/","page":"数学运算和初等函数","title":"数学运算和初等函数","text":"所有这些函数都是单参数函数,不过 atan 也可以接收两个参数 来表示传统的 atan2 函数。","category":"page"},{"location":"manual/mathematical-operations/","page":"数学运算和初等函数","title":"数学运算和初等函数","text":"另外,sinpi(x) 和 cospi(x) 分别用来对 sin(pi*x) 和 cos(pi*x) 进行更精确的计算。","category":"page"},{"location":"manual/mathematical-operations/","page":"数学运算和初等函数","title":"数学运算和初等函数","text":"要计算角度而非弧度的三角函数,以 d 做后缀。 比如,sind(x) 计算 x 的 sine 值,其中 x 是一个角度值。 下面是角度变量的三角函数完整列表:","category":"page"},{"location":"manual/mathematical-operations/","page":"数学运算和初等函数","title":"数学运算和初等函数","text":"sind cosd tand cotd secd cscd\nasind acosd atand acotd asecd acscd","category":"page"},{"location":"manual/mathematical-operations/#特殊函数","page":"数学运算和初等函数","title":"特殊函数","text":"","category":"section"},{"location":"manual/mathematical-operations/","page":"数学运算和初等函数","title":"数学运算和初等函数","text":"SpecialFunctions.jl 提供了许多其他的特殊数学函数。","category":"page"},{"location":"stdlib/DelimitedFiles/#分隔符文件","page":"分隔符文件","title":"分隔符文件","text":"","category":"section"},{"location":"stdlib/DelimitedFiles/","page":"分隔符文件","title":"分隔符文件","text":"DelimitedFiles.readdlm(::Any, ::AbstractChar, ::Type, ::AbstractChar)\nDelimitedFiles.readdlm(::Any, ::AbstractChar, ::AbstractChar)\nDelimitedFiles.readdlm(::Any, ::AbstractChar, ::Type)\nDelimitedFiles.readdlm(::Any, ::AbstractChar)\nDelimitedFiles.readdlm(::Any, ::Type)\nDelimitedFiles.readdlm(::Any)\nDelimitedFiles.writedlm","category":"page"},{"location":"stdlib/DelimitedFiles/#DelimitedFiles.readdlm-Tuple{Any, AbstractChar, Type, AbstractChar}","page":"分隔符文件","title":"DelimitedFiles.readdlm","text":"readdlm(source, delim::AbstractChar, T::Type, eol::AbstractChar; header=false, skipstart=0, skipblanks=true, use_mmap, quotes=true, dims, comments=false, comment_char='#')\n\nRead a matrix from the source where each line (separated by eol) gives one row, with elements separated by the given delimiter. The source can be a text file, stream or byte array. Memory mapped files can be used by passing the byte array representation of the mapped segment as source.\n\nIf T is a numeric type, the result is an array of that type, with any non-numeric elements as NaN for floating-point types, or zero. Other useful values of T include String, AbstractString, and Any.\n\nIf header is true, the first row of data will be read as header and the tuple (data_cells, header_cells) is returned instead of only data_cells.\n\nSpecifying skipstart will ignore the corresponding number of initial lines from the input.\n\nIf skipblanks is true, blank lines in the input will be ignored.\n\nIf use_mmap is true, the file specified by source is memory mapped for potential speedups if the file is large. Default is false. On a Windows filesystem, use_mmap should not be set to true unless the file is only read once and is also not written to. Some edge cases exist where an OS is Unix-like but the filesystem is Windows-like.\n\nIf quotes is true, columns enclosed within double-quote (\") characters are allowed to contain new lines and column delimiters. Double-quote characters within a quoted field must be escaped with another double-quote. Specifying dims as a tuple of the expected rows and columns (including header, if any) may speed up reading of large files. If comments is true, lines beginning with comment_char and text following comment_char in any line are ignored.\n\nExamples\n\njulia> using DelimitedFiles\n\njulia> x = [1; 2; 3; 4];\n\njulia> y = [5; 6; 7; 8];\n\njulia> open(\"delim_file.txt\", \"w\") do io\n writedlm(io, [x y])\n end\n\njulia> readdlm(\"delim_file.txt\", '\\t', Int, '\\n')\n4×2 Matrix{Int64}:\n 1 5\n 2 6\n 3 7\n 4 8\n\njulia> rm(\"delim_file.txt\")\n\n\n\n\n\n","category":"method"},{"location":"stdlib/DelimitedFiles/#DelimitedFiles.readdlm-Tuple{Any, AbstractChar, AbstractChar}","page":"分隔符文件","title":"DelimitedFiles.readdlm","text":"readdlm(source, delim::AbstractChar, eol::AbstractChar; options...)\n\nIf all data is numeric, the result will be a numeric array. If some elements cannot be parsed as numbers, a heterogeneous array of numbers and strings is returned.\n\n\n\n\n\n","category":"method"},{"location":"stdlib/DelimitedFiles/#DelimitedFiles.readdlm-Tuple{Any, AbstractChar, Type}","page":"分隔符文件","title":"DelimitedFiles.readdlm","text":"readdlm(source, delim::AbstractChar, T::Type; options...)\n\nThe end of line delimiter is taken as \\n.\n\nExamples\n\njulia> using DelimitedFiles\n\njulia> x = [1; 2; 3; 4];\n\njulia> y = [1.1; 2.2; 3.3; 4.4];\n\njulia> open(\"delim_file.txt\", \"w\") do io\n writedlm(io, [x y], ',')\n end;\n\njulia> readdlm(\"delim_file.txt\", ',', Float64)\n4×2 Matrix{Float64}:\n 1.0 1.1\n 2.0 2.2\n 3.0 3.3\n 4.0 4.4\n\njulia> rm(\"delim_file.txt\")\n\n\n\n\n\n","category":"method"},{"location":"stdlib/DelimitedFiles/#DelimitedFiles.readdlm-Tuple{Any, AbstractChar}","page":"分隔符文件","title":"DelimitedFiles.readdlm","text":"readdlm(source, delim::AbstractChar; options...)\n\nThe end of line delimiter is taken as \\n. If all data is numeric, the result will be a numeric array. If some elements cannot be parsed as numbers, a heterogeneous array of numbers and strings is returned.\n\nExamples\n\njulia> using DelimitedFiles\n\njulia> x = [1; 2; 3; 4];\n\njulia> y = [1.1; 2.2; 3.3; 4.4];\n\njulia> open(\"delim_file.txt\", \"w\") do io\n writedlm(io, [x y], ',')\n end;\n\njulia> readdlm(\"delim_file.txt\", ',')\n4×2 Matrix{Float64}:\n 1.0 1.1\n 2.0 2.2\n 3.0 3.3\n 4.0 4.4\n\njulia> z = [\"a\"; \"b\"; \"c\"; \"d\"];\n\njulia> open(\"delim_file.txt\", \"w\") do io\n writedlm(io, [x z], ',')\n end;\n\njulia> readdlm(\"delim_file.txt\", ',')\n4×2 Matrix{Any}:\n 1 \"a\"\n 2 \"b\"\n 3 \"c\"\n 4 \"d\"\n\njulia> rm(\"delim_file.txt\")\n\n\n\n\n\n","category":"method"},{"location":"stdlib/DelimitedFiles/#DelimitedFiles.readdlm-Tuple{Any, Type}","page":"分隔符文件","title":"DelimitedFiles.readdlm","text":"readdlm(source, T::Type; options...)\n\nThe columns are assumed to be separated by one or more whitespaces. The end of line delimiter is taken as \\n.\n\nExamples\n\njulia> using DelimitedFiles\n\njulia> x = [1; 2; 3; 4];\n\njulia> y = [5; 6; 7; 8];\n\njulia> open(\"delim_file.txt\", \"w\") do io\n writedlm(io, [x y])\n end;\n\njulia> readdlm(\"delim_file.txt\", Int64)\n4×2 Matrix{Int64}:\n 1 5\n 2 6\n 3 7\n 4 8\n\njulia> readdlm(\"delim_file.txt\", Float64)\n4×2 Matrix{Float64}:\n 1.0 5.0\n 2.0 6.0\n 3.0 7.0\n 4.0 8.0\n\njulia> rm(\"delim_file.txt\")\n\n\n\n\n\n","category":"method"},{"location":"stdlib/DelimitedFiles/#DelimitedFiles.readdlm-Tuple{Any}","page":"分隔符文件","title":"DelimitedFiles.readdlm","text":"readdlm(source; options...)\n\nThe columns are assumed to be separated by one or more whitespaces. The end of line delimiter is taken as \\n. If all data is numeric, the result will be a numeric array. If some elements cannot be parsed as numbers, a heterogeneous array of numbers and strings is returned.\n\nExamples\n\njulia> using DelimitedFiles\n\njulia> x = [1; 2; 3; 4];\n\njulia> y = [\"a\"; \"b\"; \"c\"; \"d\"];\n\njulia> open(\"delim_file.txt\", \"w\") do io\n writedlm(io, [x y])\n end;\n\njulia> readdlm(\"delim_file.txt\")\n4×2 Matrix{Any}:\n 1 \"a\"\n 2 \"b\"\n 3 \"c\"\n 4 \"d\"\n\njulia> rm(\"delim_file.txt\")\n\n\n\n\n\n","category":"method"},{"location":"stdlib/DelimitedFiles/#DelimitedFiles.writedlm","page":"分隔符文件","title":"DelimitedFiles.writedlm","text":"writedlm(f, A, delim='\\t'; opts)\n\nWrite A (a vector, matrix, or an iterable collection of iterable rows) as text to f (either a filename string or an IO stream) using the given delimiter delim (which defaults to tab, but can be any printable Julia object, typically a Char or AbstractString).\n\nFor example, two vectors x and y of the same length can be written as two columns of tab-delimited text to f by either writedlm(f, [x y]) or by writedlm(f, zip(x, y)).\n\nExamples\n\njulia> using DelimitedFiles\n\njulia> x = [1; 2; 3; 4];\n\njulia> y = [5; 6; 7; 8];\n\njulia> open(\"delim_file.txt\", \"w\") do io\n writedlm(io, [x y])\n end\n\njulia> readdlm(\"delim_file.txt\", '\\t', Int, '\\n')\n4×2 Matrix{Int64}:\n 1 5\n 2 6\n 3 7\n 4 8\n\njulia> rm(\"delim_file.txt\")\n\n\n\n\n\n","category":"function"},{"location":"manual/calling-c-and-fortran-code/#Calling-C-and-Fortran-Code","page":"调用 C 和 Fortran 代码","title":"调用 C 和 Fortran 代码","text":"","category":"section"},{"location":"manual/calling-c-and-fortran-code/","page":"调用 C 和 Fortran 代码","title":"调用 C 和 Fortran 代码","text":"在数值计算领域,尽管有很多用 C 语言或 Fortran 写的高质量且成熟的库都可以用 Julia 重写,但为了便捷利用现有的 C 或 Fortran 代码,Julia 提供简洁且高效的调用方式。Julia 的哲学是 no boilerplate: Julia 可以直接调用 C/Fortran 的函数,不需要任何\"胶水\"代码,代码生成或其它编译过程 – 即使在交互式会话 (REPL/Jupyter notebook) 中使用也一样. 在 Julia 中,上述特性可以仅仅通过调用 ccall 实现,它的语法看起来就像是普通的函数调用。","category":"page"},{"location":"manual/calling-c-and-fortran-code/","page":"调用 C 和 Fortran 代码","title":"调用 C 和 Fortran 代码","text":"被调用的代码必须是一个共享库(.so, .dylib, .dll)。大多数 C 和 Fortran 库都已经是以共享库的形式发布的,但在用 GCC 或 Clang 编译自己的代码时,需要添加 -shared 和 -fPIC 编译器选项。由于 Julia 的 JIT 生成的机器码跟原生 C 代码的调用是一样,所以在 Julia 里调用 C/Fortran 库的额外开销与直接从 C 里调用是一样的。[1]","category":"page"},{"location":"manual/calling-c-and-fortran-code/","page":"调用 C 和 Fortran 代码","title":"调用 C 和 Fortran 代码","text":"可以通过元组 (:function, \"library\") 或 (\"function\", \"library\") 这两种形式来索引库中的函数,其中 function 是函数名,library 是库名。(特定平台/操作系统的)加载路径中可用的共享库将按名称解析。 也可以指定库的完整路径。","category":"page"},{"location":"manual/calling-c-and-fortran-code/","page":"调用 C 和 Fortran 代码","title":"调用 C 和 Fortran 代码","text":"可以单独使用函数名来代替元组(只用 :function 或 \"function\")。在这种情况下,函数名在当前进程中进行解析。这一调用形式可用于调用 C 库函数、Julia 运行时中的函数或链接到 Julia 的应用程序中的函数。","category":"page"},{"location":"manual/calling-c-and-fortran-code/","page":"调用 C 和 Fortran 代码","title":"调用 C 和 Fortran 代码","text":"默认情况下,Fortran 编译器会进行名称修饰(例如,将函数名转换为小写或大写,通常会添加下划线),要通过 ccall 调用 Fortran 函数,传递的标识符必须与 Fortran 编译器名称修饰之后的一致。此外,在调用 Fortran 函数时,所有输入必须以指针形式传递,并已在堆或栈上分配内存。这不仅适用于通常是堆分配的数组及可变对象,而且适用于整数和浮点数等标量值,尽管这些值通常是栈分配的,且在使用 C 或 Julia 调用约定时通常是通过寄存器传递的。","category":"page"},{"location":"manual/calling-c-and-fortran-code/","page":"调用 C 和 Fortran 代码","title":"调用 C 和 Fortran 代码","text":"最终,你能使用 ccall 来实际生成一个对库函数的调用。ccall 的参数是:","category":"page"},{"location":"manual/calling-c-and-fortran-code/","page":"调用 C 和 Fortran 代码","title":"调用 C 和 Fortran 代码","text":"一对 (:function, \"library\") (最常见)\n或\n一个名称符号 :function 或名称字符串 \"function\"(用于当前进程或 libc 中的符号),\n或\n一个函数指针(例如,从 dlsym 获得的指针)。\n函数的返回值类型\n输入类型的元组,对应于函数签名\n要传递给函数的实际参数值,如果有的话; 每个都是一个单独的参数。","category":"page"},{"location":"manual/calling-c-and-fortran-code/","page":"调用 C 和 Fortran 代码","title":"调用 C 和 Fortran 代码","text":"note: Note\n(:function, \"library\") 对、返回类型和输入类型必须是字面量(即,它们不能是变量,但请参阅下面的 非常量函数规范)。当定义包含方法时,将在编译时评估其余参数。","category":"page"},{"location":"manual/calling-c-and-fortran-code/","page":"调用 C 和 Fortran 代码","title":"调用 C 和 Fortran 代码","text":"note: Note\n请参阅下文了解如何 将 C 类型映射到 Julia 类型。","category":"page"},{"location":"manual/calling-c-and-fortran-code/","page":"调用 C 和 Fortran 代码","title":"调用 C 和 Fortran 代码","text":"作为一个完整但简单的例子,下面从大多数 Unix 派生系统上的标准 C 库中调用 clock 函数:","category":"page"},{"location":"manual/calling-c-and-fortran-code/","page":"调用 C 和 Fortran 代码","title":"调用 C 和 Fortran 代码","text":"julia> t = ccall(:clock, Int32, ())\n2292761\n\njulia> t\n2292761\n\njulia> typeof(t)\nInt32","category":"page"},{"location":"manual/calling-c-and-fortran-code/","page":"调用 C 和 Fortran 代码","title":"调用 C 和 Fortran 代码","text":"clock 不接受任何参数并返回一个 Int32。 一个常见的错误是忘记了参数类型的单元组必须用逗号结尾。 例如,要调用 getenv 函数来获取指向环境变量值的指针,可以这样调用:","category":"page"},{"location":"manual/calling-c-and-fortran-code/","page":"调用 C 和 Fortran 代码","title":"调用 C 和 Fortran 代码","text":"julia> path = ccall(:getenv, Cstring, (Cstring,), \"SHELL\")\nCstring(@0x00007fff5fbffc45)\n\njulia> unsafe_string(path)\n\"/bin/bash\"","category":"page"},{"location":"manual/calling-c-and-fortran-code/","page":"调用 C 和 Fortran 代码","title":"调用 C 和 Fortran 代码","text":"请注意,参数类型元组必须是 (Cstring,),而不是 (Cstring) 。这是因为 (Cstring) 只是括号括起来的表达式 Cstring,而不是包含 Cstring 的单元组:","category":"page"},{"location":"manual/calling-c-and-fortran-code/","page":"调用 C 和 Fortran 代码","title":"调用 C 和 Fortran 代码","text":"julia> (Cstring)\nCstring\n\njulia> (Cstring,)\n(Cstring,)","category":"page"},{"location":"manual/calling-c-and-fortran-code/","page":"调用 C 和 Fortran 代码","title":"调用 C 和 Fortran 代码","text":"在实践中,尤其是在提供可重用功能时,通常会在 Julia 函数中包装 ccall 使用,这些函数设置参数,然后以 C 或 Fortran 函数指定的任何方式检查错误。 如果发生错误,它会作为普通的 Julia 异常抛出。 这一点尤其重要,因为 C 和 Fortran API 在它们指示错误条件的方式上是出了名的不一致。 例如,getenv C 库函数被包裹在下面的 Julia 函数中,它是 env.jl 实际定义的简化版本:","category":"page"},{"location":"manual/calling-c-and-fortran-code/","page":"调用 C 和 Fortran 代码","title":"调用 C 和 Fortran 代码","text":"function getenv(var::AbstractString)\n val = ccall(:getenv, Cstring, (Cstring,), var)\n if val == C_NULL\n error(\"getenv: undefined variable: \", var)\n end\n return unsafe_string(val)\nend","category":"page"},{"location":"manual/calling-c-and-fortran-code/","page":"调用 C 和 Fortran 代码","title":"调用 C 和 Fortran 代码","text":"C 函数 getenv 通过返回 NULL 的方式进行报错,但是其他 C 标准库函数也会通过多种不同的方式来报错,这包括返回 -1,0,1 以及其它特殊值。此封装能够明确地抛出异常信息,即是否调用者在尝试获取一个不存在的环境变量:","category":"page"},{"location":"manual/calling-c-and-fortran-code/","page":"调用 C 和 Fortran 代码","title":"调用 C 和 Fortran 代码","text":"julia> getenv(\"SHELL\")\n\"/bin/bash\"\n\njulia> getenv(\"FOOBAR\")\ngetenv: undefined variable: FOOBAR","category":"page"},{"location":"manual/calling-c-and-fortran-code/","page":"调用 C 和 Fortran 代码","title":"调用 C 和 Fortran 代码","text":"这是一个稍微复杂的示例,用于发现本地计算机的主机名。 在此示例中,假设网络库代码位于名为“libc”的共享库中。 在实践中,这个函数通常是 C 标准库的一部分,因此“libc”部分应该被省略,但我们希望在这里展示这个语法的用法。","category":"page"},{"location":"manual/calling-c-and-fortran-code/","page":"调用 C 和 Fortran 代码","title":"调用 C 和 Fortran 代码","text":"function gethostname()\n hostname = Vector{UInt8}(undef, 256) # MAXHOSTNAMELEN\n err = ccall((:gethostname, \"libc\"), Int32,\n (Ptr{UInt8}, Csize_t),\n hostname, sizeof(hostname))\n Base.systemerror(\"gethostname\", err != 0)\n hostname[end] = 0 # ensure null-termination\n return GC.@preserve hostname unsafe_string(pointer(hostname))\nend","category":"page"},{"location":"manual/calling-c-and-fortran-code/","page":"调用 C 和 Fortran 代码","title":"调用 C 和 Fortran 代码","text":"此示例首先分配一个字节数组。 然后它调用 C 库函数 gethostname 以使用主机名填充数组。 最后,它接受一个指向主机名缓冲区的指针,并将该指针转换为一个 Julia 字符串,假设它是一个以 NUL 结尾的 C 字符串。","category":"page"},{"location":"manual/calling-c-and-fortran-code/","page":"调用 C 和 Fortran 代码","title":"调用 C 和 Fortran 代码","text":"C 库通常使用这种模式,要求调用者分配要传递给被调用者并填充的内存。 像这样从 Julia 分配内存通常是通过创建一个未初始化的数组并将指向其数据的指针传递给 C 函数来完成的。 这就是我们在这里不使用 Cstring 类型的原因:由于数组未初始化,它可能包含 NUL 字节。 作为 ccall 的一部分,转换为 Cstring 会检查包含的 NUL 字节,因此可能会引发类型转换错误。","category":"page"},{"location":"manual/calling-c-and-fortran-code/","page":"调用 C 和 Fortran 代码","title":"调用 C 和 Fortran 代码","text":"用 unsafe_string 取消引用 pointer(hostname) 是一种不安全的操作,因为它需要访问为 hostname 分配的内存,而这些内存可能在同时被垃圾收集。 宏 GC.@preserve 防止这种情况发生,从而防止访问无效的内存位置。","category":"page"},{"location":"manual/calling-c-and-fortran-code/#创建和C兼容的Julia函数指针","page":"调用 C 和 Fortran 代码","title":"创建和C兼容的Julia函数指针","text":"","category":"section"},{"location":"manual/calling-c-and-fortran-code/","page":"调用 C 和 Fortran 代码","title":"调用 C 和 Fortran 代码","text":"可以将Julia函数传递给接受函数指针参数的原生C函数。例如,要匹配满足下面的C原型:","category":"page"},{"location":"manual/calling-c-and-fortran-code/","page":"调用 C 和 Fortran 代码","title":"调用 C 和 Fortran 代码","text":"typedef returntype (*functiontype)(argumenttype, ...)","category":"page"},{"location":"manual/calling-c-and-fortran-code/","page":"调用 C 和 Fortran 代码","title":"调用 C 和 Fortran 代码","text":"宏 @cfunction 为调用 Julia 函数生成 C 兼容函数指针。 @cfunction 的参数是:","category":"page"},{"location":"manual/calling-c-and-fortran-code/","page":"调用 C 和 Fortran 代码","title":"调用 C 和 Fortran 代码","text":"一个Julia函数\n函数的返回值类型\n输入类型的元组,对应于函数签名","category":"page"},{"location":"manual/calling-c-and-fortran-code/","page":"调用 C 和 Fortran 代码","title":"调用 C 和 Fortran 代码","text":"note: Note\n与 ccall 一样,返回类型和输入类型的元组必须是字面量常量。","category":"page"},{"location":"manual/calling-c-and-fortran-code/","page":"调用 C 和 Fortran 代码","title":"调用 C 和 Fortran 代码","text":"note: Note\n目前,仅支持平台默认的C调用约定。这意味着,@cfunction生成的指针不能用于WINAPI要求在32位Windows上使用stdcall函数的调用中,但可以在WIN64上使用(其中stdcall与C调用约定统一)。","category":"page"},{"location":"manual/calling-c-and-fortran-code/","page":"调用 C 和 Fortran 代码","title":"调用 C 和 Fortran 代码","text":"一个典型的例子就是标准C库函数qsort,定义为:","category":"page"},{"location":"manual/calling-c-and-fortran-code/","page":"调用 C 和 Fortran 代码","title":"调用 C 和 Fortran 代码","text":"void qsort(void *base, size_t nmemb, size_t size,\n int (*compare)(const void*, const void*));","category":"page"},{"location":"manual/calling-c-and-fortran-code/","page":"调用 C 和 Fortran 代码","title":"调用 C 和 Fortran 代码","text":"base 参数是一个指向长度为 nmemb 的数组的指针,每个元素都有 size 字节。 compare 是一个回调函数,它采用指向两个元素 a 和 b 的指针,如果 a 出现在 b 之前/之后,则返回小于/大于零的整数(如果允许任何顺序,则返回零) 。","category":"page"},{"location":"manual/calling-c-and-fortran-code/","page":"调用 C 和 Fortran 代码","title":"调用 C 和 Fortran 代码","text":"现在,假设我们在 Julia 中有一个 1 维数组 A,我们希望使用qsort函数(而不是 Julia 的内置sort函数)对其进行排序。 在我们考虑调用 qsort 并传递参数之前,我们需要编写一个比较函数:","category":"page"},{"location":"manual/calling-c-and-fortran-code/","page":"调用 C 和 Fortran 代码","title":"调用 C 和 Fortran 代码","text":"julia> function mycompare(a, b)::Cint\n return (a < b) ? -1 : ((a > b) ? +1 : 0)\n end\nmycompare (generic function with 1 method)","category":"page"},{"location":"manual/calling-c-and-fortran-code/","page":"调用 C 和 Fortran 代码","title":"调用 C 和 Fortran 代码","text":"qsort 需要一个返回 C int 的比较函数,因此我们将返回类型注释为 Cint。","category":"page"},{"location":"manual/calling-c-and-fortran-code/","page":"调用 C 和 Fortran 代码","title":"调用 C 和 Fortran 代码","text":"为了将此函数传递给 C,我们使用宏@cfunction 获取它的地址:","category":"page"},{"location":"manual/calling-c-and-fortran-code/","page":"调用 C 和 Fortran 代码","title":"调用 C 和 Fortran 代码","text":"julia> mycompare_c = @cfunction(mycompare, Cint, (Ref{Cdouble}, Ref{Cdouble}));","category":"page"},{"location":"manual/calling-c-and-fortran-code/","page":"调用 C 和 Fortran 代码","title":"调用 C 和 Fortran 代码","text":"@cfunction 需要三个参数: Julia函数 (mycompare), 返回值类型(Cint), 和一个输入参数类型的字面量元组, 此处是要排序的Cdouble(Float64) 元素的数组.","category":"page"},{"location":"manual/calling-c-and-fortran-code/","page":"调用 C 和 Fortran 代码","title":"调用 C 和 Fortran 代码","text":"qsort的最终调用看起来是这样的:","category":"page"},{"location":"manual/calling-c-and-fortran-code/","page":"调用 C 和 Fortran 代码","title":"调用 C 和 Fortran 代码","text":"julia> A = [1.3, -2.7, 4.4, 3.1]\n4-element Vector{Float64}:\n 1.3\n -2.7\n 4.4\n 3.1\n\njulia> ccall(:qsort, Cvoid, (Ptr{Cdouble}, Csize_t, Csize_t, Ptr{Cvoid}),\n A, length(A), sizeof(eltype(A)), mycompare_c)\n\njulia> A\n4-element Vector{Float64}:\n -2.7\n 1.3\n 3.1\n 4.4","category":"page"},{"location":"manual/calling-c-and-fortran-code/","page":"调用 C 和 Fortran 代码","title":"调用 C 和 Fortran 代码","text":"如示例所示,原始 Julia 数组 A 现在已排序:[-2.7, 1.3, 3.1, 4.4]。 请注意,Julia 负责将数组转换为Ptr{Cdouble}),计算元素类型的大小(以字节为单位),等等。","category":"page"},{"location":"manual/calling-c-and-fortran-code/","page":"调用 C 和 Fortran 代码","title":"调用 C 和 Fortran 代码","text":"为了好玩,尝试在 mycompare 中插入一行 println(\"mycompare($a, $b)\"),这将允许你查看 qsort 正在执行的比较(并验证它是否真的在调用你传递给它的 Julia 函数)。","category":"page"},{"location":"manual/calling-c-and-fortran-code/#mapping-c-types-to-julia","page":"调用 C 和 Fortran 代码","title":"将 C 类型映射到 Julia","text":"","category":"section"},{"location":"manual/calling-c-and-fortran-code/","page":"调用 C 和 Fortran 代码","title":"调用 C 和 Fortran 代码","text":"将声明的 C 类型与其在 Julia 中的声明完全匹配至关重要。 不一致会导致在一个系统上正常工作的代码在另一个系统上失败或产生不确定的结果。","category":"page"},{"location":"manual/calling-c-and-fortran-code/","page":"调用 C 和 Fortran 代码","title":"调用 C 和 Fortran 代码","text":"请注意,在调用 C 函数的过程中没有任何地方使用 C 头文件:您有责任确保您的 Julia 类型和调用签名准确反映 C 头文件中的那些。[2]","category":"page"},{"location":"manual/calling-c-and-fortran-code/#automatic-type-conversion","page":"调用 C 和 Fortran 代码","title":"自动类型转换","text":"","category":"section"},{"location":"manual/calling-c-and-fortran-code/","page":"调用 C 和 Fortran 代码","title":"调用 C 和 Fortran 代码","text":"Julia 会自动插入对 Base.cconvert 函数的调用,以将每个参数转换为指定的类型。 例如,以下调用:","category":"page"},{"location":"manual/calling-c-and-fortran-code/","page":"调用 C 和 Fortran 代码","title":"调用 C 和 Fortran 代码","text":"ccall((:foo, \"libfoo\"), Cvoid, (Int32, Float64), x, y)","category":"page"},{"location":"manual/calling-c-and-fortran-code/","page":"调用 C 和 Fortran 代码","title":"调用 C 和 Fortran 代码","text":"将表现得好像它是这样写的:","category":"page"},{"location":"manual/calling-c-and-fortran-code/","page":"调用 C 和 Fortran 代码","title":"调用 C 和 Fortran 代码","text":"ccall((:foo, \"libfoo\"), Cvoid, (Int32, Float64),\n Base.unsafe_convert(Int32, Base.cconvert(Int32, x)),\n Base.unsafe_convert(Float64, Base.cconvert(Float64, y)))","category":"page"},{"location":"manual/calling-c-and-fortran-code/","page":"调用 C 和 Fortran 代码","title":"调用 C 和 Fortran 代码","text":"Base.cconvert 通常只调用 convert,但可以定义为返回一个更适合传递给 C 的任意新对象。这应该用于执行 C 代码将访问的内存。 例如,这用于将对象(例如字符串)的 Array 转换为指针数组。","category":"page"},{"location":"manual/calling-c-and-fortran-code/","page":"调用 C 和 Fortran 代码","title":"调用 C 和 Fortran 代码","text":"Base.unsafe_convert 处理到 Ptr 类型转换。 它被认为是不安全的,因为将对象转换为本地指针会隐藏垃圾收集器中的对象,导致它过早地被释放。","category":"page"},{"location":"manual/calling-c-and-fortran-code/#类型对应","page":"调用 C 和 Fortran 代码","title":"类型对应","text":"","category":"section"},{"location":"manual/calling-c-and-fortran-code/","page":"调用 C 和 Fortran 代码","title":"调用 C 和 Fortran 代码","text":"首先,让我们回顾一些相关的 Julia 类型术语:","category":"page"},{"location":"manual/calling-c-and-fortran-code/","page":"调用 C 和 Fortran 代码","title":"调用 C 和 Fortran 代码","text":"语法 / 关键字 例子 描述\nmutable struct BitSet Leaf Type:包含 type-tag 的一组相关数据,由 Julia GC 管理,通过 object-identity 来定义。为了保证实例可以被构造,Leaf Type 必须是完整定义的,即不允许使用 TypeVars。\nabstract type Any, AbstractArray{T, N}, Complex{T} Super Type:用于描述一组类型,它不是 Leaf-Type,也无法被实例化。\nT{A} Vector{Int} Type Parameter:某种类型的一种具体化,通常用于分派或存储优化。\n TypeVar:Type parameter 声明中的 T 是一个 TypeVar,它是类型变量的简称。\nprimitive type Int, Float64 Primitive Type:一种没有成员变量的类型,但是它有大小。它是按值存储和定义的。\nstruct Pair{Int, Int} \"Struct\" :: 所有字段都定义为常量的类型。 它是按值定义的,并且可以与类型标签一起存储。\n ComplexF64 (isbits) \"Is-Bits\" :: 一个 primitive type,或者一个 struct 类型,其中所有字段都是其他 isbits 类型。 它是按值定义的,并且在没有类型标签的情况下存储。\nstruct ...; end nothing Singleton:没有成员变量的 Leaf Type 或 Struct。\n(...) or tuple(...) (1, 2, 3) “元组” :: 类似于匿名结构类型或常量数组的不可变数据结构。 表示为数组或结构。","category":"page"},{"location":"manual/calling-c-and-fortran-code/#man-bits-types","page":"调用 C 和 Fortran 代码","title":"Bits Types","text":"","category":"section"},{"location":"manual/calling-c-and-fortran-code/","page":"调用 C 和 Fortran 代码","title":"调用 C 和 Fortran 代码","text":"有几种特殊类型需要注意,因为没有其他类型可以定义为具有相同的行为:","category":"page"},{"location":"manual/calling-c-and-fortran-code/","page":"调用 C 和 Fortran 代码","title":"调用 C 和 Fortran 代码","text":"Float32\n和C语言中的 float 类型完全对应(以及Fortran中的 REAL*4 )\nFloat64\n和C语言中的 double 类型完全对应(以及Fortran中的 REAL*8 )\nComplexF32\n和C语言中的 complex float 类型完全对应(以及Fortran中的 COMPLEX*8 )\nComplexF64\n和C语言中的 complex double 类型完全对应(以及Fortran中的 COMPLEX*16 )\nSigned\n和C语言中的 signed 类型标识完全对应(以及Fortran中的任意 INTEGER 类型) Julia中任何不是Signed 的子类型的类型,都会被认为是unsigned类型。","category":"page"},{"location":"manual/calling-c-and-fortran-code/","page":"调用 C 和 Fortran 代码","title":"调用 C 和 Fortran 代码","text":"Ref{T}\n和 Ptr{T} 行为相同,能通过Julia的GC管理其内存。","category":"page"},{"location":"manual/calling-c-and-fortran-code/","page":"调用 C 和 Fortran 代码","title":"调用 C 和 Fortran 代码","text":"Array{T,N}\n当数组作为 Ptr{T} 参数传递给 C 时,它不是重新解释转换:Julia 要求数组的元素类型与 T 匹配,并传递第一个元素的地址。\n因此,如果一个 Array 中的数据格式不正确,它必须被显式地转换 ,通过类似 trunc(Int32, a) 的函数。\n若要将一个数组 A 以不同类型的指针传递,而不提前转换数据, (比如,将一个 Float64 数组传给一个处理原生字节的函数时),你 可以将这一参数声明为 Ptr{Cvoid} 。\n如果一个元素类型为 Ptr{T} 的数组作为 Ptr{Ptr{T}} 类型的参数传递, Base.cconvert 将会首先尝试进行 null-terminated copy(即直到下一个元素为null才停止复制),并将每一个元素使用其通过 Base.cconvert 转换后的版本替换。 这允许,比如,将一个 argv 的指针数组,其类型为 Vector{String} ,传递给一个类型为 Ptr{Ptr{Cchar}} 的参数。","category":"page"},{"location":"manual/calling-c-and-fortran-code/","page":"调用 C 和 Fortran 代码","title":"调用 C 和 Fortran 代码","text":"在我们目前支持的所有系统上,基本的 C/C++ 值类型可以转换为 Julia 类型,如下所示。 每个 C 类型还有一个对应的同名 Julia 类型,以 C 为前缀。这在编写可移植代码时很有帮助(记住 C 中的 int 与 Julia 中的 Int 不同)。","category":"page"},{"location":"manual/calling-c-and-fortran-code/","page":"调用 C 和 Fortran 代码","title":"调用 C 和 Fortran 代码","text":"独立于系统的类型","category":"page"},{"location":"manual/calling-c-and-fortran-code/","page":"调用 C 和 Fortran 代码","title":"调用 C 和 Fortran 代码","text":"C 类型 Fortran 类型 标准 Julia 别名 Julia 基本类型\nunsigned char CHARACTER Cuchar UInt8\nbool (_Bool in C99+) Cuchar UInt8\nshort INTEGER*2, LOGICAL*2 Cshort Int16\nunsigned short Cushort UInt16\nint, BOOL (C, typical) INTEGER*4, LOGICAL*4 Cint Int32\nunsigned int Cuint UInt32\nlong long INTEGER*8, LOGICAL*8 Clonglong Int64\nunsigned long long Culonglong UInt64\nintmax_t Cintmax_t Int64\nuintmax_t Cuintmax_t UInt64\nfloat REAL*4i Cfloat Float32\ndouble REAL*8 Cdouble Float64\ncomplex float COMPLEX*8 ComplexF32 Complex{Float32}\ncomplex double COMPLEX*16 ComplexF64 Complex{Float64}\nptrdiff_t Cptrdiff_t Int\nssize_t Cssize_t Int\nsize_t Csize_t UInt\nvoid Cvoid\nvoid and [[noreturn]] or _Noreturn Union{}\nvoid* Ptr{Cvoid} (或类似的 Ref{Cvoid})\nT* (where T represents an appropriately defined type) Ref{T} (只有当 T 是 isbits 类型时,T 才可以安全地转变)\nchar* (or char[], e.g. a string) CHARACTER*N Cstring if NUL-terminated, or Ptr{UInt8} if not\nchar** (or *char[]) Ptr{Ptr{UInt8}}\njl_value_t* (any Julia Type) Any\njl_value_t* const* (一个 Julia 值的引用) Ref{Any}(常量,因为转变需要写屏障,不可能正确插入)\nva_arg Not supported\n... (variadic function specification) T...(其中 T 是上述类型之一,当使用 ccall 函数时)\n... (variadic function specification) ; va_arg1::T、va_arg2::S 等(仅支持@ccall 宏)","category":"page"},{"location":"manual/calling-c-and-fortran-code/","page":"调用 C 和 Fortran 代码","title":"调用 C 和 Fortran 代码","text":"Cstring 类型本质上是Ptr{UInt8}的同义词,但如果Julia字符串包含任何嵌入的NUL字符,则类型转换为Cstring会引发错误(如果C例程将NUL视为终止符,则会导致字符串被静默截断)。如果要将char*传递给不采用NUL终止的C例程(例如,因为传递的是显式字符串长度),或者如果确定Julia字符串不包含NUL并希望跳过检查,则可以使用Ptr{UInt8}作为参数类型。Cstring也可以用作 ccall 返回类型,但在这种情况下,它显然不会引入任何额外的检查,只是为了提高调用的可读性。","category":"page"},{"location":"manual/calling-c-and-fortran-code/","page":"调用 C 和 Fortran 代码","title":"调用 C 和 Fortran 代码","text":"系统独立类型","category":"page"},{"location":"manual/calling-c-and-fortran-code/","page":"调用 C 和 Fortran 代码","title":"调用 C 和 Fortran 代码","text":"C 类型 标准 Julia 别名 Julia 基本类型\nchar Cchar Int8 (x86, x86_64), UInt8 (powerpc, arm)\nlong Clong Int (UNIX), Int32 (Windows)\nunsigned long Culong UInt (UNIX), UInt32 (Windows)\nwchar_t Cwchar_t Int32 (UNIX), UInt16 (Windows)","category":"page"},{"location":"manual/calling-c-and-fortran-code/","page":"调用 C 和 Fortran 代码","title":"调用 C 和 Fortran 代码","text":"note: Note\n调用 Fortran 时,所有输入都必须通过指向堆分配或堆栈分配值的指针传递,因此上述所有类型对应都应在其类型规范周围包含一个额外的 Ptr{..} 或 Ref{..} 包装器。","category":"page"},{"location":"manual/calling-c-and-fortran-code/","page":"调用 C 和 Fortran 代码","title":"调用 C 和 Fortran 代码","text":"warning: Warning\n对于字符串参数 (char*),Julia 类型应该是 Cstring(如果需要以 NUL 结尾的数据),否则为 Ptr{Cchar} 或 Ptr{UInt8}(这两种指针类型具有相同的效果),如上所述,而不是 String。 类似地,对于数组参数(T[] 或 T*),Julia 类型应该还是 Ptr{T},而不是 Vector{T}。","category":"page"},{"location":"manual/calling-c-and-fortran-code/","page":"调用 C 和 Fortran 代码","title":"调用 C 和 Fortran 代码","text":"warning: Warning\nJulia 的 Char 类型是 32 位,这与所有平台上的宽字符类型(wchar_t 或 wint_t)不同。","category":"page"},{"location":"manual/calling-c-and-fortran-code/","page":"调用 C 和 Fortran 代码","title":"调用 C 和 Fortran 代码","text":"warning: Warning\nUnion{} 的返回类型意味着函数不会返回,即 C++11 [[noreturn]] 或 C11 _Noreturn(例如 jl_throw 或 longjmp)。 不要将此用于不返回值(void)但返回的函数,而是使用Cvoid。","category":"page"},{"location":"manual/calling-c-and-fortran-code/","page":"调用 C 和 Fortran 代码","title":"调用 C 和 Fortran 代码","text":"note: Note\n对于 wchar_t* 参数,Julia 类型应为 Cwstring(如果 C 例程需要以 NUL 结尾的字符串),否则为 Ptr{Cwchar_t}。 另请注意,Julia 中的 UTF-8 字符串数据在内部以 NUL 结尾,因此可以将其传递给需要以 NUL 结尾的数据的 C 函数,而无需进行复制(但使用 Cwstring 类型将导致抛出错误,如果字符串本身包含 NUL 字符)。","category":"page"},{"location":"manual/calling-c-and-fortran-code/","page":"调用 C 和 Fortran 代码","title":"调用 C 和 Fortran 代码","text":"note: Note\n可以在 Julia 中使用 Ptr{Ptr{UInt8}} 类型调用采用 char** 类型参数的 C 函数。 例如,以下形式的 C 函数:int main(int argc, char **argv);可以通过以下 Julia 代码调用:argv = [ \"a.out\", \"arg1\", \"arg2\" ]\nccall(:main, Int32, (Int32, Ptr{Ptr{UInt8}}), length(argv), argv)","category":"page"},{"location":"manual/calling-c-and-fortran-code/","page":"调用 C 和 Fortran 代码","title":"调用 C 和 Fortran 代码","text":"note: Note\n对于采用 character(len=*) 类型的可变长度字符串的 Fortran 函数,字符串长度作为隐藏参数提供。 这些参数在列表中的类型和位置是特定于编译器的,编译器供应商通常默认使用 Csize_t 作为类型并将隐藏的参数附加到参数列表的末尾。 虽然此行为对于某些编译器 (GNU) 是固定的,但其他编译器可选 允许将隐藏参数直接放置在字符参数(Intel、PGI)之后。 例如,如下的 Fortran 子程序subroutine test(str1, str2)\ncharacter(len=*) :: str1,str2can be called via the following Julia code, where the lengths are appendedstr1 = \"foo\"\nstr2 = \"bar\"\nccall(:test, Cvoid, (Ptr{UInt8}, Ptr{UInt8}, Csize_t, Csize_t),\n str1, str2, sizeof(str1), sizeof(str2))","category":"page"},{"location":"manual/calling-c-and-fortran-code/","page":"调用 C 和 Fortran 代码","title":"调用 C 和 Fortran 代码","text":"warning: Warning\nFortran 编译器还可以为指针、假定形状(:)和假定大小(*)数组添加其他隐藏参数。 这种行为可以通过使用ISO_C_BINDING并在子例程的定义中包含bind(c)来避免,强烈推荐用于可互操作的代码。 在这种情况下,将没有隐藏的参数,代价是一些语言特性(例如,只允许 character(len=1) 传递字符串)。","category":"page"},{"location":"manual/calling-c-and-fortran-code/","page":"调用 C 和 Fortran 代码","title":"调用 C 和 Fortran 代码","text":"note: Note\n声明为返回 Cvoid 的 C 函数将在 Julia 中返回值 nothing。","category":"page"},{"location":"manual/calling-c-and-fortran-code/#结构类型对应","page":"调用 C 和 Fortran 代码","title":"结构类型对应","text":"","category":"section"},{"location":"manual/calling-c-and-fortran-code/","page":"调用 C 和 Fortran 代码","title":"调用 C 和 Fortran 代码","text":"复合类型,例如 C 中的struct或 Fortran90 中的TYPE(或 F77 的某些变体中的STRUCTURE/RECORD),可以通过创建具有相同字段布局的struct定义在 Julia 中进行镜像复制。","category":"page"},{"location":"manual/calling-c-and-fortran-code/","page":"调用 C 和 Fortran 代码","title":"调用 C 和 Fortran 代码","text":"当递归使用时,isbits 类型被内联存储。 所有其他类型都存储为指向数据的指针。 在 C 中的另一个结构中镜像复制按值使用的结构时,不要尝试手动复制字段,因为这不会保留正确的字段对齐。 相反,建议声明一个 isbits 结构类型并使用它。 未命名的结构在翻译为 Julia 时是不可能的。","category":"page"},{"location":"manual/calling-c-and-fortran-code/","page":"调用 C 和 Fortran 代码","title":"调用 C 和 Fortran 代码","text":"Julia不支持压缩结构和联合声明。","category":"page"},{"location":"manual/calling-c-and-fortran-code/","page":"调用 C 和 Fortran 代码","title":"调用 C 和 Fortran 代码","text":"如果你事先地知道将具有最大大小(可能包括填充)的字段,则可以获得 union 的近似。 将你的字段转换为 Julia 时,将 Julia 字段声明为仅属于该类型。","category":"page"},{"location":"manual/calling-c-and-fortran-code/","page":"调用 C 和 Fortran 代码","title":"调用 C 和 Fortran 代码","text":"参数数组可以用 NTuple 表示。例如,C 符号中的 struct 写成","category":"page"},{"location":"manual/calling-c-and-fortran-code/","page":"调用 C 和 Fortran 代码","title":"调用 C 和 Fortran 代码","text":"struct B {\n int A[3];\n};\n\nb_a_2 = B.A[2];","category":"page"},{"location":"manual/calling-c-and-fortran-code/","page":"调用 C 和 Fortran 代码","title":"调用 C 和 Fortran 代码","text":"可以用 Julia 写成","category":"page"},{"location":"manual/calling-c-and-fortran-code/","page":"调用 C 和 Fortran 代码","title":"调用 C 和 Fortran 代码","text":"struct B\n A::NTuple{3, Cint}\nend\n\nb_a_2 = B.A[3] # note the difference in indexing (1-based in Julia, 0-based in C)","category":"page"},{"location":"manual/calling-c-and-fortran-code/","page":"调用 C 和 Fortran 代码","title":"调用 C 和 Fortran 代码","text":"不直接支持未知大小的数组(由[] 或[0] 指定的符合C99 的可变长度结构)。 通常处理这些的最好方法是直接处理字节偏移量。 例如,如果一个 C 库声明了一个正确的字符串类型并返回一个指向它的指针:","category":"page"},{"location":"manual/calling-c-and-fortran-code/","page":"调用 C 和 Fortran 代码","title":"调用 C 和 Fortran 代码","text":"struct String {\n int strlen;\n char data[];\n};","category":"page"},{"location":"manual/calling-c-and-fortran-code/","page":"调用 C 和 Fortran 代码","title":"调用 C 和 Fortran 代码","text":"在 Julia 中,我们可以独立访问这些部分以制作该字符串的副本:","category":"page"},{"location":"manual/calling-c-and-fortran-code/","page":"调用 C 和 Fortran 代码","title":"调用 C 和 Fortran 代码","text":"str = from_c::Ptr{Cvoid}\nlen = unsafe_load(Ptr{Cint}(str))\nunsafe_string(str + Core.sizeof(Cint), len)","category":"page"},{"location":"manual/calling-c-and-fortran-code/#类型参数","page":"调用 C 和 Fortran 代码","title":"类型参数","text":"","category":"section"},{"location":"manual/calling-c-and-fortran-code/","page":"调用 C 和 Fortran 代码","title":"调用 C 和 Fortran 代码","text":"当定义了方法时,ccall 和 @cfunction 的类型参数被静态地评估。 因此,它们必须采用字面量元组的形式,而不是变量,并且不能引用局部变量。","category":"page"},{"location":"manual/calling-c-and-fortran-code/","page":"调用 C 和 Fortran 代码","title":"调用 C 和 Fortran 代码","text":"这听起来像是一个奇怪的限制,但请记住,由于 C 不是像 Julia 那样的动态语言,它的函数只能接受具有静态已知的固定签名的参数类型。","category":"page"},{"location":"manual/calling-c-and-fortran-code/","page":"调用 C 和 Fortran 代码","title":"调用 C 和 Fortran 代码","text":"然而,虽然必须静态地知道类型布局才能计算预期的 C ABI,但函数的静态参数被视为此静态环境的一部分。函数的静态参数可以用作调用签名中的类型参数,只要它们不影响类型的布局即可。例如, f(x::T) where {T} = ccall(:valid, Ptr{T}, (Ptr{T},), x) 是有效的,因为 Ptr 始终是字大小的原始类型。但是, g(x::T) where {T} = ccall(:notvalid, T, (T,), x) 是无效的,因为 T 的类型布局不是静态已知的。","category":"page"},{"location":"manual/calling-c-and-fortran-code/#SIMD-值","page":"调用 C 和 Fortran 代码","title":"SIMD 值","text":"","category":"section"},{"location":"manual/calling-c-and-fortran-code/","page":"调用 C 和 Fortran 代码","title":"调用 C 和 Fortran 代码","text":"注意:此功能目前仅在 64 位 x86 和 AArch64 平台上实现。","category":"page"},{"location":"manual/calling-c-and-fortran-code/","page":"调用 C 和 Fortran 代码","title":"调用 C 和 Fortran 代码","text":"如果 C/C++ 例程具有本机 SIMD 类型的参数或返回值,则相应的 Julia 类型是自然映射到 SIMD 类型的VecElement 的同构元组。 具体来说:","category":"page"},{"location":"manual/calling-c-and-fortran-code/","page":"调用 C 和 Fortran 代码","title":"调用 C 和 Fortran 代码","text":"元组的大小必须与 SIMD 类型相同。 例如,一个表示 __m128 的元组在 x86 上必须有 16 字节的大小。元组的元素类型必须是 VecElement{T} 的一个实例,其中 T 是一个原始类型是 1、2、4 或 8 个字节。","category":"page"},{"location":"manual/calling-c-and-fortran-code/","page":"调用 C 和 Fortran 代码","title":"调用 C 和 Fortran 代码","text":"例如,考虑这个使用 AVX 内在函数的 C 例程:","category":"page"},{"location":"manual/calling-c-and-fortran-code/","page":"调用 C 和 Fortran 代码","title":"调用 C 和 Fortran 代码","text":"#include \n\n__m256 dist( __m256 a, __m256 b ) {\n return _mm256_sqrt_ps(_mm256_add_ps(_mm256_mul_ps(a, a),\n _mm256_mul_ps(b, b)));\n}","category":"page"},{"location":"manual/calling-c-and-fortran-code/","page":"调用 C 和 Fortran 代码","title":"调用 C 和 Fortran 代码","text":"以下 Julia 代码使用 ccall 调用 dist:","category":"page"},{"location":"manual/calling-c-and-fortran-code/","page":"调用 C 和 Fortran 代码","title":"调用 C 和 Fortran 代码","text":"const m256 = NTuple{8, VecElement{Float32}}\n\na = m256(ntuple(i -> VecElement(sin(Float32(i))), 8))\nb = m256(ntuple(i -> VecElement(cos(Float32(i))), 8))\n\nfunction call_dist(a::m256, b::m256)\n ccall((:dist, \"libdist\"), m256, (m256, m256), a, b)\nend\n\nprintln(call_dist(a,b))","category":"page"},{"location":"manual/calling-c-and-fortran-code/","page":"调用 C 和 Fortran 代码","title":"调用 C 和 Fortran 代码","text":"主机必须具有必要的 SIMD 寄存器。 例如,上面的代码将无法在没有 AVX 支持的主机上运行。","category":"page"},{"location":"manual/calling-c-and-fortran-code/#内存所有权","page":"调用 C 和 Fortran 代码","title":"内存所有权","text":"","category":"section"},{"location":"manual/calling-c-and-fortran-code/","page":"调用 C 和 Fortran 代码","title":"调用 C 和 Fortran 代码","text":"malloc/free","category":"page"},{"location":"manual/calling-c-and-fortran-code/","page":"调用 C 和 Fortran 代码","title":"调用 C 和 Fortran 代码","text":"此类对象的内存分配和释放必须通过调用正在使用的库中的适当清理例程来处理,就像在任何 C 程序中一样。 不要尝试在 Julia 中使用 Libc.free 释放从 C 库接收的对象,因为这可能会导致通过错误的库调用 free 函数并导致进程中止。 反过来(传递在 Julia 中分配的对象以供外部库释放)同样无效。","category":"page"},{"location":"manual/calling-c-and-fortran-code/#何时使用-T、Ptr{T}-以及-Ref{T}","page":"调用 C 和 Fortran 代码","title":"何时使用 T、Ptr{T} 以及 Ref{T}","text":"","category":"section"},{"location":"manual/calling-c-and-fortran-code/","page":"调用 C 和 Fortran 代码","title":"调用 C 和 Fortran 代码","text":"在对外部C例程的Julia代码包装调用中,普通(非指针)数据应该在ccall 中声明为T类型,因为它们是通过值传递的。对于接受指针的C代码,Ref{T} 通常应用于输入参数的类型,允许通过对Base.cconvert 的隐式调用使用指向Julia或C管理的内存的指针。相反,被调用的C函数返回的指针应该声明为输出类型Ptr{T},这反映了指向的内存仅由C管理。C结构中包含的指针应在相应的Julia结构类型中表示为Ptr{T}类型的字段,这些结构类型旨在模拟相应C结构的内部结构。","category":"page"},{"location":"manual/calling-c-and-fortran-code/","page":"调用 C 和 Fortran 代码","title":"调用 C 和 Fortran 代码","text":"在 Julia 代码包装对外部 Fortran 例程的调用中,所有输入参数都应声明为Ref{T}类型,因为 Fortran 通过指向内存位置的指针传递所有变量。 Fortran 子程序的返回类型应该是 Cvoid,或者 Fortran 函数的返回类型应该是 T,返回类型是 T。","category":"page"},{"location":"manual/calling-c-and-fortran-code/#将-C-函数映射到-Julia","page":"调用 C 和 Fortran 代码","title":"将 C 函数映射到 Julia","text":"","category":"section"},{"location":"manual/calling-c-and-fortran-code/#ccall-/-@cfunction-参数翻译指南","page":"调用 C 和 Fortran 代码","title":"ccall / @cfunction 参数翻译指南","text":"","category":"section"},{"location":"manual/calling-c-and-fortran-code/","page":"调用 C 和 Fortran 代码","title":"调用 C 和 Fortran 代码","text":"将 C 参数列表翻译为 Julia:","category":"page"},{"location":"manual/calling-c-and-fortran-code/","page":"调用 C 和 Fortran 代码","title":"调用 C 和 Fortran 代码","text":"T,其中 T 取值为:char、int、long、short、float、double、complex、enum 或其等价的 typedef 类型\nT,其中 T 是等价的 Julia Bits 类型(参见上表)\n如果 T 是 enum,则参数类型应等价于 Cint 或 Cuint\n参数值将被复制(按值传递)\nstruct T (包括 struct 的 typedef)\nT,其中 T 是 Julia 叶类型\n参数值将被复制(按值传递)\nvoid*","category":"page"},{"location":"manual/calling-c-and-fortran-code/","page":"调用 C 和 Fortran 代码","title":"调用 C 和 Fortran 代码","text":" * 取决于如何使用此参数,首先将其翻译为所需的指针类型,然后使用此列表中的其余规则确定 Julia 等价项\n * 这个参数可以声明为 `Ptr{Cvoid}`,如果它真的只是一个未知的指针","category":"page"},{"location":"manual/calling-c-and-fortran-code/","page":"调用 C 和 Fortran 代码","title":"调用 C 和 Fortran 代码","text":"jl_value_t*\nAny\n参数值必须是有效的 Julia 对象\njl_value_t* const*\nRef{Any}\n参数列表必须是有效的 Julia 对象(或 C_NULL)\n不能用于输出参数,除非用户能够单独安排要GC保留的对象\nT* \nRef{T},其中 T 是与 T 对应的 Julia 类型\n如果它是 inlinealloc 类型,则将复制参数值(包括 isbits,否则,值必须是有效的 Julia 对象)\nT (*)(...) (例如,指向函数的指针)\nPtr{Cvoid}(您可能需要显式使用 @cfunction 来创建此指针)\n... (例如,可变参数)\n[对于 ccall]:T...,其中 T 是所有剩余参数的单个 Julia 类型\n[对于 @ccall]:; va_arg1::T, va_arg2::S, etc,其中 T 和 S 是 Julia 类型(即,使用 ; 将常规参数与可变参数分开)\n目前不支持 @cfunction\nva_arg\nccall 或 @cfunction 不支持","category":"page"},{"location":"manual/calling-c-and-fortran-code/#ccall-/-@cfunction-返回类型翻译指南","page":"调用 C 和 Fortran 代码","title":"ccall / @cfunction 返回类型翻译指南","text":"","category":"section"},{"location":"manual/calling-c-and-fortran-code/","page":"调用 C 和 Fortran 代码","title":"调用 C 和 Fortran 代码","text":"将 C 返回类型翻译为 Julia:","category":"page"},{"location":"manual/calling-c-and-fortran-code/","page":"调用 C 和 Fortran 代码","title":"调用 C 和 Fortran 代码","text":"void\nCvoid(这将返回单例实例 nothing::Cvoid)\nT,其中 T 是原始类型之一:char,int,long,short,float,double,complex,enum 或任何等效的 typedef\nT, 其中 T 是等效的 Julia Bits 类型(请参阅上表)\n如果 T 是 enum,则参数类型应等效于 Cint 或 Cuint\n参数值将被复制(按值返回)\nstruct T (包括 typedef 到结构体)\nT,其中 T 是 Julia 叶类型\n参数值将被复制(按值返回)\nvoid*\n* 取决于如何使用此参数,首先将其翻译为所需的指针类型,然后使用此列表中的其余规则确定 Julia 等效项\n* 如果它确实只是一个未知指针,则可以将此参数声明为 `Ptr{Cvoid}`\njl_value_t*\nAny\n参数值必须是有效的 Julia 对象\njl_value_t**\nPtr{Any}(Ref{Any} 是无效的返回类型)\nT*\n如果内存已由 Julia 拥有,或者是 isbits 类型,并且已知为非空:\nRef{T},其中 T 是对应于 T 的 Julia 类型\n返回类型 Ref{Any} 无效,它应该是 Any(对应于 jl_value_t*)或 Ptr{Any}(对应于 jl_value_t**)\nC 不得 修改通过 Ref{T} 返回的内存,如果 T 是 isbits 类型\n如果内存由 C 拥有:\nPtr{T},其中 T 是对应于 T 的 Julia 类型\nT (*)(...)(例如,指向函数的指针)\nPtr{Cvoid},以便从 Julia 直接调用此函数,你需要将此作为 ccall 的第一个参数传递。 请参阅 间接调用。","category":"page"},{"location":"manual/calling-c-and-fortran-code/#传递修改输入的指针","page":"调用 C 和 Fortran 代码","title":"传递修改输入的指针","text":"","category":"section"},{"location":"manual/calling-c-and-fortran-code/","page":"调用 C 和 Fortran 代码","title":"调用 C 和 Fortran 代码","text":"因为 C 不支持多个返回值,所以 C 函数通常会使用指向函数将修改的数据的指针。 要在 ccall 中完成此操作,你需要首先将值封装在适当类型的 Ref{T} 中。 当你将这个 Ref 对象作为参数传递时,Julia 会自动传递一个指向封装数据的 C 指针:","category":"page"},{"location":"manual/calling-c-and-fortran-code/","page":"调用 C 和 Fortran 代码","title":"调用 C 和 Fortran 代码","text":"width = Ref{Cint}(0)\nrange = Ref{Cfloat}(0)\nccall(:foo, Cvoid, (Ref{Cint}, Ref{Cfloat}), width, range)","category":"page"},{"location":"manual/calling-c-and-fortran-code/","page":"调用 C 和 Fortran 代码","title":"调用 C 和 Fortran 代码","text":"返回时,可以通过width[]和range[]检索width和range的内容(如果它们被foo改变的话); 也就是说,它们就像零维数组。","category":"page"},{"location":"manual/calling-c-and-fortran-code/#C-包装器示例","page":"调用 C 和 Fortran 代码","title":"C 包装器示例","text":"","category":"section"},{"location":"manual/calling-c-and-fortran-code/","page":"调用 C 和 Fortran 代码","title":"调用 C 和 Fortran 代码","text":"让我们从一个返回 Ptr 类型的 C 包装器的简单示例开始:","category":"page"},{"location":"manual/calling-c-and-fortran-code/","page":"调用 C 和 Fortran 代码","title":"调用 C 和 Fortran 代码","text":"mutable struct gsl_permutation\nend\n\n# The corresponding C signature is\n# gsl_permutation * gsl_permutation_alloc (size_t n);\nfunction permutation_alloc(n::Integer)\n output_ptr = ccall(\n (:gsl_permutation_alloc, :libgsl), # name of C function and library\n Ptr{gsl_permutation}, # output type\n (Csize_t,), # tuple of input types\n n # name of Julia variable to pass in\n )\n if output_ptr == C_NULL # Could not allocate memory\n throw(OutOfMemoryError())\n end\n return output_ptr\nend","category":"page"},{"location":"manual/calling-c-and-fortran-code/","page":"调用 C 和 Fortran 代码","title":"调用 C 和 Fortran 代码","text":"GNU 科学图书馆(这里假设可以通过:libgsl 访问)定义了一个不透明的指针,gsl_permutation *,作为 C 函数gsl_permutation_alloc 的返回类型。 由于用户代码永远不必查看 gsl_permutation 结构内部,相应的 Julia 包装器只需要一个新的类型声明 gsl_permutation,它没有内部字段,其唯一目的是放置在 Ptr类型的类型参数中。 ccall 的返回类型声明为 Ptr{gsl_permutation},因为 output_ptr 分配和指向的内存由 C 控制。","category":"page"},{"location":"manual/calling-c-and-fortran-code/","page":"调用 C 和 Fortran 代码","title":"调用 C 和 Fortran 代码","text":"输入 n 是按值传递的,因此函数的输入签名被简单地声明为 (Csize_t,),不需要任何 Ref 或 Ptr。 (如果包装器改为调用 Fortran 函数,则相应的函数输入签名将改为 (Ref{Csize_t},),因为 Fortran 变量是通过指针传递的。)此外,n 可以是任何可转换的类型 到一个 Csize_t 整数; ccall 隐式调用 Base.cconvert(Csize_t, n)。","category":"page"},{"location":"manual/calling-c-and-fortran-code/","page":"调用 C 和 Fortran 代码","title":"调用 C 和 Fortran 代码","text":"这是包装相应析构函数的第二个示例:","category":"page"},{"location":"manual/calling-c-and-fortran-code/","page":"调用 C 和 Fortran 代码","title":"调用 C 和 Fortran 代码","text":"# The corresponding C signature is\n# void gsl_permutation_free (gsl_permutation * p);\nfunction permutation_free(p::Ref{gsl_permutation})\n ccall(\n (:gsl_permutation_free, :libgsl), # name of C function and library\n Cvoid, # output type\n (Ref{gsl_permutation},), # tuple of input types\n p # name of Julia variable to pass in\n )\nend","category":"page"},{"location":"manual/calling-c-and-fortran-code/","page":"调用 C 和 Fortran 代码","title":"调用 C 和 Fortran 代码","text":"这里,输入p被声明为Ref{gsl_permutation}类型,这意味着p指向的内存可以由Julia或C管理。由C分配的内存指针应该是类型 Ptr{gsl_permutation},但它可以使用 Base.cconvert 进行转换,因此","category":"page"},{"location":"manual/calling-c-and-fortran-code/","page":"调用 C 和 Fortran 代码","title":"调用 C 和 Fortran 代码","text":"现在,如果你仔细观察这个例子,你可能会注意到它是不正确的,因为我们上面对首选声明类型的解释。 你看到了吗? 我们正在调用的函数将释放内存。 这种类型的操作不能被赋予 Julia 对象(它会崩溃或导致内存损坏)。因此,将 p 类型声明为 Ptr{gsl_permutation } 可能更可取,这样用户就更难错误地传递另一种对象,而不是通过 gsl_permutation_alloc 获得的对象。","category":"page"},{"location":"manual/calling-c-and-fortran-code/","page":"调用 C 和 Fortran 代码","title":"调用 C 和 Fortran 代码","text":"如果 C 包装器从不希望用户将指针传递给 Julia 管理的内存,那么使用 p::Ptr{gsl_permutation} 作为包装器的方法签名,类似地在 ccall 中也是可以接受。","category":"page"},{"location":"manual/calling-c-and-fortran-code/","page":"调用 C 和 Fortran 代码","title":"调用 C 和 Fortran 代码","text":"这是传递 Julia 数组的第三个示例:","category":"page"},{"location":"manual/calling-c-and-fortran-code/","page":"调用 C 和 Fortran 代码","title":"调用 C 和 Fortran 代码","text":"# The corresponding C signature is\n# int gsl_sf_bessel_Jn_array (int nmin, int nmax, double x,\n# double result_array[])\nfunction sf_bessel_Jn_array(nmin::Integer, nmax::Integer, x::Real)\n if nmax < nmin\n throw(DomainError())\n end\n result_array = Vector{Cdouble}(undef, nmax - nmin + 1)\n errorcode = ccall(\n (:gsl_sf_bessel_Jn_array, :libgsl), # name of C function and library\n Cint, # output type\n (Cint, Cint, Cdouble, Ref{Cdouble}),# tuple of input types\n nmin, nmax, x, result_array # names of Julia variables to pass in\n )\n if errorcode != 0\n error(\"GSL error code $errorcode\")\n end\n return result_array\nend","category":"page"},{"location":"manual/calling-c-and-fortran-code/","page":"调用 C 和 Fortran 代码","title":"调用 C 和 Fortran 代码","text":"包装的 C 函数返回一个整数错误代码; Bessel J 函数的实际评估结果填充 Julia 数组 result_array。 这个变量被声明为一个 Ref{Cdouble},因为它的内存是由 Julia 分配和管理的。 对 Base.cconvert(Ref{Cdouble}, result_array) 的隐式调用将指向 Julia 数组数据结构的 Julia 指针解包为 C 可以理解的形式。","category":"page"},{"location":"manual/calling-c-and-fortran-code/#Fortran-包装器示例","page":"调用 C 和 Fortran 代码","title":"Fortran 包装器示例","text":"","category":"section"},{"location":"manual/calling-c-and-fortran-code/","page":"调用 C 和 Fortran 代码","title":"调用 C 和 Fortran 代码","text":"以下示例利用 ccall 调用通用 Fortran 库 (libBLAS) 中的函数来计算点积。 请注意,这里的参数映射与上面的有点不同,因为我们需要从 Julia 映射到 Fortran。 在每个参数类型上,我们指定 Ref 或 Ptr。 此修改约定可能特定于你的 Fortran 编译器和操作系统,并且可能未记录在案。 但是,将每个包装在一个 Ref(或 Ptr,等效地)中是 Fortran 编译器实现的一个常见要求:","category":"page"},{"location":"manual/calling-c-and-fortran-code/","page":"调用 C 和 Fortran 代码","title":"调用 C 和 Fortran 代码","text":"function compute_dot(DX::Vector{Float64}, DY::Vector{Float64})\n @assert length(DX) == length(DY)\n n = length(DX)\n incx = incy = 1\n product = ccall((:ddot_, \"libLAPACK\"),\n Float64,\n (Ref{Int32}, Ptr{Float64}, Ref{Int32}, Ptr{Float64}, Ref{Int32}),\n n, DX, incx, DY, incy)\n return product\nend","category":"page"},{"location":"manual/calling-c-and-fortran-code/#垃圾回收安全","page":"调用 C 和 Fortran 代码","title":"垃圾回收安全","text":"","category":"section"},{"location":"manual/calling-c-and-fortran-code/","page":"调用 C 和 Fortran 代码","title":"调用 C 和 Fortran 代码","text":"将数据传递给 ccall 时,最好避免使用 pointer 函数。 而是定义一个转换方法并将变量直接传递给 ccall。 ccall 自动安排它的所有参数都将从垃圾收集中保留,直到调用返回。 如果 C API 将存储对 Julia 分配的内存的引用,则在 ccall 返回后,你必须确保该对象对垃圾收集器保持可见。 建议的方法是创建一个类型为 Array{Ref,1} 的全局变量来保存这些值,直到 C 库通知你它已完成使用它们。","category":"page"},{"location":"manual/calling-c-and-fortran-code/","page":"调用 C 和 Fortran 代码","title":"调用 C 和 Fortran 代码","text":"每当你创建了一个指向 Julia 数据的指针时,你必须确保原始数据存在,直到你完成使用该指针。 Julia 中的许多方法,例如 unsafe_load 和 String 复制数据而不是获取缓冲区的所有权,因此可以安全地释放(或更改)原始数而不影响 Julia。 一个值得注意的例外是 unsafe_wrap,出于性能原因,它共享(或可以被告知拥有)底层缓冲区。","category":"page"},{"location":"manual/calling-c-and-fortran-code/","page":"调用 C 和 Fortran 代码","title":"调用 C 和 Fortran 代码","text":"垃圾收集器不保证任何终结顺序。 也就是说,如果 a 包含对 b 的引用,并且 a 和 b 都需要进行垃圾回收,则不能保证 b 会在 a 之后完成。 如果 a 的正确终结取决于 b 是否有效,则必须以其他方式处理。","category":"page"},{"location":"manual/calling-c-and-fortran-code/#Non-constant-Function-Specifications","page":"调用 C 和 Fortran 代码","title":"非常数函数规范","text":"","category":"section"},{"location":"manual/calling-c-and-fortran-code/","page":"调用 C 和 Fortran 代码","title":"调用 C 和 Fortran 代码","text":"在某些情况下,所需库的确切名称或路径是事先未知的,必须在运行时计算。 为了处理这种情况,(name, library) 规范的库组件可以是一个函数调用,例如 (:dgemm_, find_blas())。 调用表达式将在执行 ccall 本身时执行。 但是,假设库位置一旦确定就不会改变,因此调用的结果可以被缓存和重用。 因此,表达式执行的次数是未指定的,多次调用返回不同的值会导致未指定的行为。","category":"page"},{"location":"manual/calling-c-and-fortran-code/","page":"调用 C 和 Fortran 代码","title":"调用 C 和 Fortran 代码","text":"如果需要更大的灵活性,可以通过 eval 分段使用计算值作为函数名称,如下所示:","category":"page"},{"location":"manual/calling-c-and-fortran-code/","page":"调用 C 和 Fortran 代码","title":"调用 C 和 Fortran 代码","text":"@eval ccall(($(string(\"a\", \"b\")), \"lib\"), ...","category":"page"},{"location":"manual/calling-c-and-fortran-code/","page":"调用 C 和 Fortran 代码","title":"调用 C 和 Fortran 代码","text":"此表达式使用 string 构造一个名称,然后将此名称替换为一个新的 ccall 表达式,然后对其进行评估。 请记住,eval 仅在顶层运行,因此在此表达式中局部变量将不可用(除非它们的值被替换为 $)。 出于这个原因,eval 通常仅用于形成顶级定义,例如在包装包含许多类似函数的库时。 可以为 @cfunction 构造一个类似的示例。","category":"page"},{"location":"manual/calling-c-and-fortran-code/","page":"调用 C 和 Fortran 代码","title":"调用 C 和 Fortran 代码","text":"但是,这样做也会很慢并且会泄漏内存,因此你通常应该避免这种情况,而是继续阅读。 下一节讨论如何使用间接调用来有效地实现类似的效果。","category":"page"},{"location":"manual/calling-c-and-fortran-code/#非直接调用","page":"调用 C 和 Fortran 代码","title":"非直接调用","text":"","category":"section"},{"location":"manual/calling-c-and-fortran-code/","page":"调用 C 和 Fortran 代码","title":"调用 C 和 Fortran 代码","text":"ccall 的第一个参数也可以是在运行时计算的表达式。 在这种情况下,表达式的计算结果必须为 Ptr,它将用作要调用的本地函数的地址。 当第一个 ccall 参数包含对非常量(例如局部变量、函数参数或非常量全局变量)的引用时,会发生此行为。","category":"page"},{"location":"manual/calling-c-and-fortran-code/","page":"调用 C 和 Fortran 代码","title":"调用 C 和 Fortran 代码","text":"例如,你可以通过 dlsym 查找函数,然后将其缓存在该会话的共享引用中。 例如:","category":"page"},{"location":"manual/calling-c-and-fortran-code/","page":"调用 C 和 Fortran 代码","title":"调用 C 和 Fortran 代码","text":"macro dlsym(func, lib)\n z = Ref{Ptr{Cvoid}}(C_NULL)\n quote\n let zlocal = $z[]\n if zlocal == C_NULL\n zlocal = dlsym($(esc(lib))::Ptr{Cvoid}, $(esc(func)))::Ptr{Cvoid}\n $z[] = zlocal\n end\n zlocal\n end\n end\nend\n\nmylibvar = Libdl.dlopen(\"mylib\")\nccall(@dlsym(\"myfunc\", mylibvar), Cvoid, ())","category":"page"},{"location":"manual/calling-c-and-fortran-code/#cfunction-闭包","page":"调用 C 和 Fortran 代码","title":"cfunction 闭包","text":"","category":"section"},{"location":"manual/calling-c-and-fortran-code/","page":"调用 C 和 Fortran 代码","title":"调用 C 和 Fortran 代码","text":"@cfunction 的第一个参数可以用 $ 标记,在这种情况下,返回值将改为结束参数的 struct CFunction。 你必须确保此返回对象保持活动状态,直到完成对它的所有使用。 当这个引用被删除和 atexit 时,cfunction 指针处的内容和代码将通过 finalizer 删除。 这通常不是必需的,因为此功能在 C 中不存在,但对于处理不提供单独的闭包环境参数的设计不良的 API 很有用。","category":"page"},{"location":"manual/calling-c-and-fortran-code/","page":"调用 C 和 Fortran 代码","title":"调用 C 和 Fortran 代码","text":"function qsort(a::Vector{T}, cmp) where T\n isbits(T) || throw(ArgumentError(\"this method can only qsort isbits arrays\"))\n callback = @cfunction $cmp Cint (Ref{T}, Ref{T})\n # Here, `callback` isa Base.CFunction, which will be converted to Ptr{Cvoid}\n # (and protected against finalization) by the ccall\n ccall(:qsort, Cvoid, (Ptr{T}, Csize_t, Csize_t, Ptr{Cvoid}),\n a, length(a), Base.elsize(a), callback)\n # We could instead use:\n # GC.@preserve callback begin\n # use(Base.unsafe_convert(Ptr{Cvoid}, callback))\n # end\n # if we needed to use it outside of a `ccall`\n return a\nend","category":"page"},{"location":"manual/calling-c-and-fortran-code/","page":"调用 C 和 Fortran 代码","title":"调用 C 和 Fortran 代码","text":"note: Note\n闭包 @cfunction 依赖于 LLVM Trampolines,并非在所有平台(例如 ARM 和 PowerPC)上都可用。","category":"page"},{"location":"manual/calling-c-and-fortran-code/#关闭库","page":"调用 C 和 Fortran 代码","title":"关闭库","text":"","category":"section"},{"location":"manual/calling-c-and-fortran-code/","page":"调用 C 和 Fortran 代码","title":"调用 C 和 Fortran 代码","text":"关闭(卸载)库以便重新加载有时很有用。 例如,在开发与 Julia 一起使用的 C 代码时,可能需要编译、从 Julia 调用 C 代码,然后关闭库、进行编辑、重新编译并加载新的更改。 可以重新启动 Julia 或使用 Libdl 函数来显式管理库,例如:","category":"page"},{"location":"manual/calling-c-and-fortran-code/","page":"调用 C 和 Fortran 代码","title":"调用 C 和 Fortran 代码","text":"lib = Libdl.dlopen(\"./my_lib.so\") # 显式打开库\nsym = Libdl.dlsym(lib, :my_fcn) # 获得用于调用函数的符号\nccall(sym, ...) # 直接用指针 `sym` 而不是 (symbol, library) 元组,其余参数保持不变\nLibdl.dlclose(lib) # 显式关闭库","category":"page"},{"location":"manual/calling-c-and-fortran-code/","page":"调用 C 和 Fortran 代码","title":"调用 C 和 Fortran 代码","text":"请注意,当将 ccall 与输入元组(例如,ccall((:my_fcn, \"./my_lib.so\"), ...))一起使用时,库会隐式打开,并且可能不会显式关闭。","category":"page"},{"location":"manual/calling-c-and-fortran-code/#调用规约","page":"调用 C 和 Fortran 代码","title":"调用规约","text":"","category":"section"},{"location":"manual/calling-c-and-fortran-code/","page":"调用 C 和 Fortran 代码","title":"调用 C 和 Fortran 代码","text":"ccall 的第二个参数可以选择是调用约定说明符(直接在返回类型之前)。 没有任何说明符,使用平台默认的 C 调用约定。 其他支持的约定是:stdcall、cdecl、fastcall 和thiscall(64 位Windows 上无操作)。 例如(来自base/libc.jl)我们看到与上面相同的gethostnameccall,但具有正确的Windows签名:","category":"page"},{"location":"manual/calling-c-and-fortran-code/","page":"调用 C 和 Fortran 代码","title":"调用 C 和 Fortran 代码","text":"hn = Vector{UInt8}(undef, 256)\nerr = ccall(:gethostname, stdcall, Int32, (Ptr{UInt8}, UInt32), hn, length(hn))","category":"page"},{"location":"manual/calling-c-and-fortran-code/","page":"调用 C 和 Fortran 代码","title":"调用 C 和 Fortran 代码","text":"请参阅 LLVM Language Reference 来获得更多信息。","category":"page"},{"location":"manual/calling-c-and-fortran-code/","page":"调用 C 和 Fortran 代码","title":"调用 C 和 Fortran 代码","text":"还有一个额外的特殊调用约定 llvmcall,它允许直接插入对 LLVM 内部函数的调用。 这在针对不常见的平台(例如 GPGPU)时特别有用。 例如,对于CUDA,我们需要能够读取线程索引:","category":"page"},{"location":"manual/calling-c-and-fortran-code/","page":"调用 C 和 Fortran 代码","title":"调用 C 和 Fortran 代码","text":"ccall(\"llvm.nvvm.read.ptx.sreg.tid.x\", llvmcall, Int32, ())","category":"page"},{"location":"manual/calling-c-and-fortran-code/","page":"调用 C 和 Fortran 代码","title":"调用 C 和 Fortran 代码","text":"与任何 ccall 一样,参数签名必须完全正确。另外,请注意,与Core.Intrinsics开放的等效Julia函数不同,没有兼容层级可以确保内在函数有意义并在当前目标上工作。","category":"page"},{"location":"manual/calling-c-and-fortran-code/#访问全局变量","page":"调用 C 和 Fortran 代码","title":"访问全局变量","text":"","category":"section"},{"location":"manual/calling-c-and-fortran-code/","page":"调用 C 和 Fortran 代码","title":"调用 C 和 Fortran 代码","text":"可以使用 cglobal 函数按名称访问本地库导出的全局变量。 cglobal 的参数与 ccall 使用相同的符号规范,以及描述存储在变量中的值的类型:","category":"page"},{"location":"manual/calling-c-and-fortran-code/","page":"调用 C 和 Fortran 代码","title":"调用 C 和 Fortran 代码","text":"julia> cglobal((:errno, :libc), Int32)\nPtr{Int32} @0x00007f418d0816b8","category":"page"},{"location":"manual/calling-c-and-fortran-code/","page":"调用 C 和 Fortran 代码","title":"调用 C 和 Fortran 代码","text":"结果是一个给出值地址的指针。 可以使用 unsafe_load 和 unsafe_store! 通过这个指针来操作该值。","category":"page"},{"location":"manual/calling-c-and-fortran-code/","page":"调用 C 和 Fortran 代码","title":"调用 C 和 Fortran 代码","text":"note: Note\n在名为“libc”的库中可能找不到此 errno 符号,因为这是系统编译器的实现细节。 通常标准库符号应该只通过名称访问,允许编译器填写正确的符号。 然而,这个例子中显示的 errno 符号在大多数编译器中都是特殊的,所以这里看到的值可能不是你所期望或想要的。 在任何支持多线程的系统上用 C 编译等效代码通常实际上会调用不同的函数(通过宏预处理器重载),并且可能给出与此处打印的遗留值不同的结果。","category":"page"},{"location":"manual/calling-c-and-fortran-code/#通过指针来访问数据","page":"调用 C 和 Fortran 代码","title":"通过指针来访问数据","text":"","category":"section"},{"location":"manual/calling-c-and-fortran-code/","page":"调用 C 和 Fortran 代码","title":"调用 C 和 Fortran 代码","text":"以下方法被描述为“不安全”,因为错误的指针或类型声明会导致 Julia 突然终止。","category":"page"},{"location":"manual/calling-c-and-fortran-code/","page":"调用 C 和 Fortran 代码","title":"调用 C 和 Fortran 代码","text":"给定一个 Ptr{T},通常可以使用 unsafe_load(ptr, [index]) 将 T 类型的内容从引用的内存复制到 Julia 对象中。 index 参数是可选的(默认为 1),并遵循基于 1 的索引的 Julia 惯例。 此函数类似于 getindex 和 setindex! 的行为(例如[] 访问语法)。","category":"page"},{"location":"manual/calling-c-and-fortran-code/","page":"调用 C 和 Fortran 代码","title":"调用 C 和 Fortran 代码","text":"返回值将是一个初始化为包含引用内存内容副本的新对象。 引用的内存可以安全地释放或释放。","category":"page"},{"location":"manual/calling-c-and-fortran-code/","page":"调用 C 和 Fortran 代码","title":"调用 C 和 Fortran 代码","text":"如果 T 是 Any,则假定内存包含对 Julia 对象的引用(jl_value_t*),结果将是对该对象的引用,并且不会复制该对象。 在这种情况下,你必须小心确保对象始终对垃圾收集器可见(指针不计数,但新引用计数)以确保内存不会过早释放。 请注意,如果对象最初不是由 Julia 分配的,则新对象将永远不会被 Julia 的垃圾收集器终结。 如果 Ptr 本身实际上是一个 jl_value_t*,它可以通过 unsafe_pointer_to_objref(ptr) 转换回 Julia 对象引用。 (Julia 值 v 可以通过调用 pointer_from_objref(v) 转换为 jl_value_t* 指针,如 Ptr{Cvoid}。)","category":"page"},{"location":"manual/calling-c-and-fortran-code/","page":"调用 C 和 Fortran 代码","title":"调用 C 和 Fortran 代码","text":"可以使用 unsafe_store!(ptr, value, [index]) 执行反向操作(将数据写入 Ptr{T})。 目前,这仅支持原始类型或其他无指针(isbits)不可变结构类型。","category":"page"},{"location":"manual/calling-c-and-fortran-code/","page":"调用 C 和 Fortran 代码","title":"调用 C 和 Fortran 代码","text":"任何引发错误的操作目前可能尚未实现,应作为错误发布,以便解决。","category":"page"},{"location":"manual/calling-c-and-fortran-code/","page":"调用 C 和 Fortran 代码","title":"调用 C 和 Fortran 代码","text":"如果感兴趣的指针是纯数据数组(原始类型或不可变结构),则函数 unsafe_wrap(Array, ptr,dims, own = false) 可能更有用。 如果 Julia 应该“获得”底层缓冲区的所有权并在返回的 Array 对象最终确定时调用 free(ptr),则最后一个参数应该为 true。 如果省略了 own 参数或为 false,则调用者必须确保缓冲区一直存在,直到所有访问完成。","category":"page"},{"location":"manual/calling-c-and-fortran-code/","page":"调用 C 和 Fortran 代码","title":"调用 C 和 Fortran 代码","text":"Julia 中 Ptr 类型的算术(例如使用 +)与 C 的指针算术的行为不同。 将整数添加到 Julia 中的 Ptr 总是将指针移动一定数量的 bytes,而不是元素。 这样,通过指针运算获得的地址值不依赖于指针的元素类型。","category":"page"},{"location":"manual/calling-c-and-fortran-code/#线程安全","page":"调用 C 和 Fortran 代码","title":"线程安全","text":"","category":"section"},{"location":"manual/calling-c-and-fortran-code/","page":"调用 C 和 Fortran 代码","title":"调用 C 和 Fortran 代码","text":"一些 C 库从不同的线程执行它们的回调,并且由于 Julia 不是线程安全的,因此你需要采取一些额外的预防措施。 特别是,你需要设置一个两层系统:C 回调应该只 安排(通过 Julia 的事件循环)执行“真实”回调。 为此,创建一个 AsyncCondition 对象并在其上创建 wait:","category":"page"},{"location":"manual/calling-c-and-fortran-code/","page":"调用 C 和 Fortran 代码","title":"调用 C 和 Fortran 代码","text":"cond = Base.AsyncCondition()\nwait(cond)","category":"page"},{"location":"manual/calling-c-and-fortran-code/","page":"调用 C 和 Fortran 代码","title":"调用 C 和 Fortran 代码","text":"传递给 C 的回调应该只通过 ccall 将 cond.handle 作为参数传递给 :uv_async_send 并调用,注意避免任何内存分配操作或与 Julia 运行时的其他交互。","category":"page"},{"location":"manual/calling-c-and-fortran-code/","page":"调用 C 和 Fortran 代码","title":"调用 C 和 Fortran 代码","text":"注意,事件可能会合并,因此对 uv_async_send 的多个调用可能会导致对该条件的单个唤醒通知。","category":"page"},{"location":"manual/calling-c-and-fortran-code/#关于-Callbacks-的更多内容","page":"调用 C 和 Fortran 代码","title":"关于 Callbacks 的更多内容","text":"","category":"section"},{"location":"manual/calling-c-and-fortran-code/","page":"调用 C 和 Fortran 代码","title":"调用 C 和 Fortran 代码","text":"关于如何传递 callback 到 C 库的更多细节,请参考此博客。","category":"page"},{"location":"manual/calling-c-and-fortran-code/#C","page":"调用 C 和 Fortran 代码","title":"C++","text":"","category":"section"},{"location":"manual/calling-c-and-fortran-code/","page":"调用 C 和 Fortran 代码","title":"调用 C 和 Fortran 代码","text":"如需要直接易用的C++接口,即直接用Julia写封装代码,请参考 Cxx。如需封装C++库的工具,即用C++写封装/胶水代码,请参考CxxWrap。","category":"page"},{"location":"manual/calling-c-and-fortran-code/","page":"调用 C 和 Fortran 代码","title":"调用 C 和 Fortran 代码","text":"[1]: Non-library function calls in both C and Julia can be inlined and thus may have even less overhead than calls to shared library functions. The point above is that the cost of actually doing foreign function call is about the same as doing a call in either native language.","category":"page"},{"location":"manual/calling-c-and-fortran-code/","page":"调用 C 和 Fortran 代码","title":"调用 C 和 Fortran 代码","text":"[2]: The Clang package can be used to auto-generate Julia code from a C header file.","category":"page"},{"location":"base/libc/#C-标准库","page":"C 标准库","title":"C 标准库","text":"","category":"section"},{"location":"base/libc/","page":"C 标准库","title":"C 标准库","text":"Base.Libc.malloc\nBase.Libc.calloc\nBase.Libc.realloc\nBase.Libc.free\nBase.Libc.errno\nBase.Libc.strerror\nBase.Libc.GetLastError\nBase.Libc.FormatMessage\nBase.Libc.time(::Base.Libc.TmStruct)\nBase.Libc.strftime\nBase.Libc.strptime\nBase.Libc.TmStruct\nBase.Libc.flush_cstdio\nBase.Libc.systemsleep","category":"page"},{"location":"base/libc/#Base.Libc.malloc","page":"C 标准库","title":"Base.Libc.malloc","text":"malloc(size::Integer) -> Ptr{Cvoid}\n\nCall malloc from the C standard library.\n\n\n\n\n\n","category":"function"},{"location":"base/libc/#Base.Libc.calloc","page":"C 标准库","title":"Base.Libc.calloc","text":"calloc(num::Integer, size::Integer) -> Ptr{Cvoid}\n\nCall calloc from the C standard library.\n\n\n\n\n\n","category":"function"},{"location":"base/libc/#Base.Libc.realloc","page":"C 标准库","title":"Base.Libc.realloc","text":"realloc(addr::Ptr, size::Integer) -> Ptr{Cvoid}\n\nCall realloc from the C standard library.\n\nSee warning in the documentation for free regarding only using this on memory originally obtained from malloc.\n\n\n\n\n\n","category":"function"},{"location":"base/libc/#Base.Libc.free","page":"C 标准库","title":"Base.Libc.free","text":"free(addr::Ptr)\n\nCall free from the C standard library. Only use this on memory obtained from malloc, not on pointers retrieved from other C libraries. Ptr objects obtained from C libraries should be freed by the free functions defined in that library, to avoid assertion failures if multiple libc libraries exist on the system.\n\n\n\n\n\n","category":"function"},{"location":"base/libc/#Base.Libc.errno","page":"C 标准库","title":"Base.Libc.errno","text":"errno([code])\n\nGet the value of the C library's errno. If an argument is specified, it is used to set the value of errno.\n\nThe value of errno is only valid immediately after a ccall to a C library routine that sets it. Specifically, you cannot call errno at the next prompt in a REPL, because lots of code is executed between prompts.\n\n\n\n\n\n","category":"function"},{"location":"base/libc/#Base.Libc.strerror","page":"C 标准库","title":"Base.Libc.strerror","text":"strerror(n=errno())\n\nConvert a system call error code to a descriptive string\n\n\n\n\n\n","category":"function"},{"location":"base/libc/#Base.Libc.GetLastError","page":"C 标准库","title":"Base.Libc.GetLastError","text":"GetLastError()\n\nCall the Win32 GetLastError function [only available on Windows].\n\n\n\n\n\n","category":"function"},{"location":"base/libc/#Base.Libc.FormatMessage","page":"C 标准库","title":"Base.Libc.FormatMessage","text":"FormatMessage(n=GetLastError())\n\nConvert a Win32 system call error code to a descriptive string [only available on Windows].\n\n\n\n\n\n","category":"function"},{"location":"base/libc/#Base.Libc.time-Tuple{Base.Libc.TmStruct}","page":"C 标准库","title":"Base.Libc.time","text":"time(t::TmStruct)\n\nConverts a TmStruct struct to a number of seconds since the epoch.\n\n\n\n\n\n","category":"method"},{"location":"base/libc/#Base.Libc.strftime","page":"C 标准库","title":"Base.Libc.strftime","text":"strftime([format], time)\n\nConvert time, given as a number of seconds since the epoch or a TmStruct, to a formatted string using the given format. Supported formats are the same as those in the standard C library.\n\n\n\n\n\n","category":"function"},{"location":"base/libc/#Base.Libc.strptime","page":"C 标准库","title":"Base.Libc.strptime","text":"strptime([format], timestr)\n\nParse a formatted time string into a TmStruct giving the seconds, minute, hour, date, etc. Supported formats are the same as those in the standard C library. On some platforms, timezones will not be parsed correctly. If the result of this function will be passed to time to convert it to seconds since the epoch, the isdst field should be filled in manually. Setting it to -1 will tell the C library to use the current system settings to determine the timezone.\n\n\n\n\n\n","category":"function"},{"location":"base/libc/#Base.Libc.TmStruct","page":"C 标准库","title":"Base.Libc.TmStruct","text":"TmStruct([seconds])\n\nConvert a number of seconds since the epoch to broken-down format, with fields sec, min, hour, mday, month, year, wday, yday, and isdst.\n\n\n\n\n\n","category":"type"},{"location":"base/libc/#Base.Libc.flush_cstdio","page":"C 标准库","title":"Base.Libc.flush_cstdio","text":"flush_cstdio()\n\nFlushes the C stdout and stderr streams (which may have been written to by external C code).\n\n\n\n\n\n","category":"function"},{"location":"base/libc/#Base.Libc.systemsleep","page":"C 标准库","title":"Base.Libc.systemsleep","text":"systemsleep(s::Real)\n\nSuspends execution for s seconds. This function does not yield to Julia's scheduler and therefore blocks the Julia thread that it is running on for the duration of the sleep time.\n\nSee also sleep.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LinearAlgebra/#man-linalg","page":"Linear Algebra","title":"Linear Algebra","text":"","category":"section"},{"location":"stdlib/LinearAlgebra/","page":"Linear Algebra","title":"Linear Algebra","text":"DocTestSetup = :(using LinearAlgebra, SparseArrays, SuiteSparse)","category":"page"},{"location":"stdlib/LinearAlgebra/","page":"Linear Algebra","title":"Linear Algebra","text":"除了(且作为一部分)对多维数组的支持,Julia 还提供了许多常见和实用的线性代数运算的本地实现,可通过 using LinearAlgebra 加载。 基本的运算,比如 tr,det 和 inv 都是支持的:","category":"page"},{"location":"stdlib/LinearAlgebra/","page":"Linear Algebra","title":"Linear Algebra","text":"julia> A = [1 2 3; 4 1 6; 7 8 1]\n3×3 Matrix{Int64}:\n 1 2 3\n 4 1 6\n 7 8 1\n\njulia> tr(A)\n3\n\njulia> det(A)\n104.0\n\njulia> inv(A)\n3×3 Matrix{Float64}:\n -0.451923 0.211538 0.0865385\n 0.365385 -0.192308 0.0576923\n 0.240385 0.0576923 -0.0673077","category":"page"},{"location":"stdlib/LinearAlgebra/","page":"Linear Algebra","title":"Linear Algebra","text":"还有其它实用的运算,比如寻找特征值或特征向量:","category":"page"},{"location":"stdlib/LinearAlgebra/","page":"Linear Algebra","title":"Linear Algebra","text":"julia> A = [-4. -17.; 2. 2.]\n2×2 Matrix{Float64}:\n -4.0 -17.0\n 2.0 2.0\n\njulia> eigvals(A)\n2-element Vector{ComplexF64}:\n -1.0 - 5.0im\n -1.0 + 5.0im\n\njulia> eigvecs(A)\n2×2 Matrix{ComplexF64}:\n 0.945905-0.0im 0.945905+0.0im\n -0.166924+0.278207im -0.166924-0.278207im","category":"page"},{"location":"stdlib/LinearAlgebra/","page":"Linear Algebra","title":"Linear Algebra","text":"此外,Julia 提供了多种矩阵分解,通过将矩阵预先分解成更适合问题的形式(出于性能或内存上的原因),它们可用于加快问题的求解,如线性求解或矩阵求幂。更多有关信息请参阅文档 factorize。举个例子:","category":"page"},{"location":"stdlib/LinearAlgebra/","page":"Linear Algebra","title":"Linear Algebra","text":"julia> A = [1.5 2 -4; 3 -1 -6; -10 2.3 4]\n3×3 Matrix{Float64}:\n 1.5 2.0 -4.0\n 3.0 -1.0 -6.0\n -10.0 2.3 4.0\n\njulia> factorize(A)\nLU{Float64, Matrix{Float64}}\nL factor:\n3×3 Matrix{Float64}:\n 1.0 0.0 0.0\n -0.15 1.0 0.0\n -0.3 -0.132196 1.0\nU factor:\n3×3 Matrix{Float64}:\n -10.0 2.3 4.0\n 0.0 2.345 -3.4\n 0.0 0.0 -5.24947","category":"page"},{"location":"stdlib/LinearAlgebra/","page":"Linear Algebra","title":"Linear Algebra","text":"因为 A 不是埃尔米特、对称、三角、三对角或双对角矩阵,LU 分解也许是我们能做的最好分解。与之相比:","category":"page"},{"location":"stdlib/LinearAlgebra/","page":"Linear Algebra","title":"Linear Algebra","text":"julia> B = [1.5 2 -4; 2 -1 -3; -4 -3 5]\n3×3 Matrix{Float64}:\n 1.5 2.0 -4.0\n 2.0 -1.0 -3.0\n -4.0 -3.0 5.0\n\njulia> factorize(B)\nBunchKaufman{Float64, Matrix{Float64}}\nD factor:\n3×3 Tridiagonal{Float64, Vector{Float64}}:\n -1.64286 0.0 ⋅\n 0.0 -2.8 0.0\n ⋅ 0.0 5.0\nU factor:\n3×3 UnitUpperTriangular{Float64, Matrix{Float64}}:\n 1.0 0.142857 -0.8\n ⋅ 1.0 -0.6\n ⋅ ⋅ 1.0\npermutation:\n3-element Vector{Int64}:\n 1\n 2\n 3","category":"page"},{"location":"stdlib/LinearAlgebra/","page":"Linear Algebra","title":"Linear Algebra","text":"在这里,Julia 能够发现 B 确实是对称矩阵,并且使用一种更适当的分解。针对一个具有某些属性的矩阵,比如一个对称或三对角矩阵,往往有可能写出更高效的代码。Julia 提供了一些特殊的类型好让你可以根据矩阵所具有的属性「标记」它们。例如:","category":"page"},{"location":"stdlib/LinearAlgebra/","page":"Linear Algebra","title":"Linear Algebra","text":"julia> B = [1.5 2 -4; 2 -1 -3; -4 -3 5]\n3×3 Matrix{Float64}:\n 1.5 2.0 -4.0\n 2.0 -1.0 -3.0\n -4.0 -3.0 5.0\n\njulia> sB = Symmetric(B)\n3×3 Symmetric{Float64, Matrix{Float64}}:\n 1.5 2.0 -4.0\n 2.0 -1.0 -3.0\n -4.0 -3.0 5.0","category":"page"},{"location":"stdlib/LinearAlgebra/","page":"Linear Algebra","title":"Linear Algebra","text":"sB 已经被标记成(实)对称矩阵,所以对于之后可能在它上面执行的操作,例如特征因子化或矩阵-向量乘积,只引用矩阵的一半可以提高效率。举个例子:","category":"page"},{"location":"stdlib/LinearAlgebra/","page":"Linear Algebra","title":"Linear Algebra","text":"julia> B = [1.5 2 -4; 2 -1 -3; -4 -3 5]\n3×3 Matrix{Float64}:\n 1.5 2.0 -4.0\n 2.0 -1.0 -3.0\n -4.0 -3.0 5.0\n\njulia> sB = Symmetric(B)\n3×3 Symmetric{Float64, Matrix{Float64}}:\n 1.5 2.0 -4.0\n 2.0 -1.0 -3.0\n -4.0 -3.0 5.0\n\njulia> x = [1; 2; 3]\n3-element Vector{Int64}:\n 1\n 2\n 3\n\njulia> sB\\x\n3-element Vector{Float64}:\n -1.7391304347826084\n -1.1086956521739126\n -1.4565217391304346","category":"page"},{"location":"stdlib/LinearAlgebra/","page":"Linear Algebra","title":"Linear Algebra","text":"\\ 运算在这里执行线性求解。左除运算符相当强大,很容易写出紧凑、可读的代码,它足够灵活,可以求解各种线性方程组。","category":"page"},{"location":"stdlib/LinearAlgebra/#特殊矩阵","page":"Linear Algebra","title":"特殊矩阵","text":"","category":"section"},{"location":"stdlib/LinearAlgebra/","page":"Linear Algebra","title":"Linear Algebra","text":"具有特殊对称性和结构的矩阵经常在线性代数中出现并且与各种矩阵分解相关。 Julia 具有丰富的特殊矩阵类型,可以快速计算专门为特定矩阵类型开发的专用例程。","category":"page"},{"location":"stdlib/LinearAlgebra/","page":"Linear Algebra","title":"Linear Algebra","text":"下表总结了在 Julia 中已经实现的特殊矩阵类型,以及为它们提供各种优化方法的钩子在 LAPACK 中是否可用。","category":"page"},{"location":"stdlib/LinearAlgebra/","page":"Linear Algebra","title":"Linear Algebra","text":"类型 描述\nSymmetric Symmetric matrix\nHermitian Hermitian matrix\nUpperTriangular 上三角矩阵\nUnitUpperTriangular 单位上三角矩阵 with unit diagonal\nLowerTriangular 下三角矩阵\nUnitLowerTriangular 单位下三角矩阵\nUpperHessenberg Upper Hessenberg matrix\nTridiagonal Tridiagonal matrix\nSymTridiagonal 对称三对角矩阵\nBidiagonal 上/下双对角矩阵\nDiagonal Diagonal matrix\nUniformScaling Uniform scaling operator","category":"page"},{"location":"stdlib/LinearAlgebra/#基本运算","page":"Linear Algebra","title":"基本运算","text":"","category":"section"},{"location":"stdlib/LinearAlgebra/","page":"Linear Algebra","title":"Linear Algebra","text":"矩阵类型 + - * \\ 具有优化方法的其它函数\nSymmetric MV inv, sqrt, exp\nHermitian MV inv, sqrt, exp\nUpperTriangular MV MV inv, det\nUnitUpperTriangular MV MV inv, det\nLowerTriangular MV MV inv, det\nUnitLowerTriangular MV MV inv, det\nUpperHessenberg MM inv, det\nSymTridiagonal M M MS MV eigmax, eigmin\nTridiagonal M M MS MV \nBidiagonal M M MS MV \nDiagonal M M MV MV inv, det, logdet, /\nUniformScaling M M MVS MVS /","category":"page"},{"location":"stdlib/LinearAlgebra/","page":"Linear Algebra","title":"Linear Algebra","text":"Legend:","category":"page"},{"location":"stdlib/LinearAlgebra/","page":"Linear Algebra","title":"Linear Algebra","text":"Key 说明\nM(矩阵) 针对矩阵与矩阵运算的优化方法可用\nV(向量) 针对矩阵与向量运算的优化方法可用\nS(标量) 针对矩阵与标量运算的优化方法可用","category":"page"},{"location":"stdlib/LinearAlgebra/#矩阵分解","page":"Linear Algebra","title":"矩阵分解","text":"","category":"section"},{"location":"stdlib/LinearAlgebra/","page":"Linear Algebra","title":"Linear Algebra","text":"矩阵类型 LAPACK eigen eigvals eigvecs svd svdvals\nSymmetric SY ARI \nHermitian HE ARI \nUpperTriangular TR A A A \nUnitUpperTriangular TR A A A \nLowerTriangular TR A A A \nUnitLowerTriangular TR A A A \nSymTridiagonal ST A ARI AV \nTridiagonal GT \nBidiagonal BD A A\nDiagonal DI A ","category":"page"},{"location":"stdlib/LinearAlgebra/","page":"Linear Algebra","title":"Linear Algebra","text":"图例:","category":"page"},{"location":"stdlib/LinearAlgebra/","page":"Linear Algebra","title":"Linear Algebra","text":"键名 说明 例子\nA (all) 找到所有特征值和/或特征向量的优化方法可用 e.g. eigvals(M)\nR (range) 通过第 ih 个特征值寻找第 il 个特征值的优化方法可用 eigvals(M, il, ih)\nI (interval) 寻找在区间 [vl, vh] 内的特征值的优化方法可用 eigvals(M, vl, vh)\nV (vectors) 寻找对应于特征值 x=[x1, x2,...] 的特征向量的优化方法可用 eigvecs(M, x)","category":"page"},{"location":"stdlib/LinearAlgebra/#均匀缩放运算符","page":"Linear Algebra","title":"均匀缩放运算符","text":"","category":"section"},{"location":"stdlib/LinearAlgebra/","page":"Linear Algebra","title":"Linear Algebra","text":"UniformScaling 运算符代表一个标量乘以单位运算符,λ*I。 单位运算符 I 被定义为常量,是 UniformScaling 的实例。 这些运算符的大小是通用的,并且会在二元运算符 +,-,* 和 \\ 中与另一个矩阵相匹配。 对于 A+I 和 A-I ,这意味着 A 必须是个方阵。 与单位运算符 I 相乘是一个空操作(除了检查比例因子是一),因此几乎没有开销。","category":"page"},{"location":"stdlib/LinearAlgebra/","page":"Linear Algebra","title":"Linear Algebra","text":"来查看 UniformScaling 运算符的运行结果:","category":"page"},{"location":"stdlib/LinearAlgebra/","page":"Linear Algebra","title":"Linear Algebra","text":"julia> U = UniformScaling(2);\n\njulia> a = [1 2; 3 4]\n2×2 Matrix{Int64}:\n 1 2\n 3 4\n\njulia> a + U\n2×2 Matrix{Int64}:\n 3 2\n 3 6\n\njulia> a * U\n2×2 Matrix{Int64}:\n 2 4\n 6 8\n\njulia> [a U]\n2×4 Matrix{Int64}:\n 1 2 2 0\n 3 4 0 2\n\njulia> b = [1 2 3; 4 5 6]\n2×3 Matrix{Int64}:\n 1 2 3\n 4 5 6\n\njulia> b - U\nERROR: DimensionMismatch(\"matrix is not square: dimensions are (2, 3)\")\nStacktrace:\n[...]","category":"page"},{"location":"stdlib/LinearAlgebra/","page":"Linear Algebra","title":"Linear Algebra","text":"If you need to solve many systems of the form (A+μI)x = b for the same A and different μ, it might be beneficial to first compute the Hessenberg factorization F of A via the hessenberg function. Given F, Julia employs an efficient algorithm for (F+μ*I) \\ b (equivalent to (A+μ*I)x \\ b) and related operations like determinants.","category":"page"},{"location":"stdlib/LinearAlgebra/#man-linalg-factorizations","page":"Linear Algebra","title":"Matrix factorizations","text":"","category":"section"},{"location":"stdlib/LinearAlgebra/","page":"Linear Algebra","title":"Linear Algebra","text":"Matrix factorizations (a.k.a. matrix decompositions) compute the factorization of a matrix into a product of matrices, and are one of the central concepts in linear algebra.","category":"page"},{"location":"stdlib/LinearAlgebra/","page":"Linear Algebra","title":"Linear Algebra","text":"The following table summarizes the types of matrix factorizations that have been implemented in Julia. Details of their associated methods can be found in the Standard functions section of the Linear Algebra documentation.","category":"page"},{"location":"stdlib/LinearAlgebra/","page":"Linear Algebra","title":"Linear Algebra","text":"Type Description\nBunchKaufman Bunch-Kaufman factorization\nCholesky Cholesky factorization\nCholeskyPivoted Pivoted Cholesky factorization\nLDLt LDL(T) factorization\nLU LU factorization\nQR QR factorization\nQRCompactWY Compact WY form of the QR factorization\nQRPivoted Pivoted QR factorization\nLQ QR factorization of transpose(A)\nHessenberg Hessenberg decomposition\nEigen Spectral decomposition\nGeneralizedEigen Generalized spectral decomposition\nSVD Singular value decomposition\nGeneralizedSVD Generalized SVD\nSchur Schur decomposition\nGeneralizedSchur Generalized Schur decomposition","category":"page"},{"location":"stdlib/LinearAlgebra/#Standard-functions","page":"Linear Algebra","title":"Standard functions","text":"","category":"section"},{"location":"stdlib/LinearAlgebra/","page":"Linear Algebra","title":"Linear Algebra","text":"Linear algebra functions in Julia are largely implemented by calling functions from LAPACK. Sparse matrix factorizations call functions from SuiteSparse. Other sparse solvers are available as Julia packages.","category":"page"},{"location":"stdlib/LinearAlgebra/","page":"Linear Algebra","title":"Linear Algebra","text":"Base.:*(::AbstractMatrix, ::AbstractMatrix)\nBase.:\\(::AbstractMatrix, ::AbstractVecOrMat)\nLinearAlgebra.SingularException\nLinearAlgebra.PosDefException\nLinearAlgebra.ZeroPivotException\nLinearAlgebra.dot\nLinearAlgebra.dot(::Any, ::Any, ::Any)\nLinearAlgebra.cross\nLinearAlgebra.factorize\nLinearAlgebra.Diagonal\nLinearAlgebra.Bidiagonal\nLinearAlgebra.SymTridiagonal\nLinearAlgebra.Tridiagonal\nLinearAlgebra.Symmetric\nLinearAlgebra.Hermitian\nLinearAlgebra.LowerTriangular\nLinearAlgebra.UpperTriangular\nLinearAlgebra.UnitLowerTriangular\nLinearAlgebra.UnitUpperTriangular\nLinearAlgebra.UpperHessenberg\nLinearAlgebra.UniformScaling\nLinearAlgebra.I\nLinearAlgebra.UniformScaling(::Integer)\nLinearAlgebra.Factorization\nLinearAlgebra.LU\nLinearAlgebra.lu\nLinearAlgebra.lu!\nLinearAlgebra.Cholesky\nLinearAlgebra.CholeskyPivoted\nLinearAlgebra.cholesky\nLinearAlgebra.cholesky!\nLinearAlgebra.lowrankupdate\nLinearAlgebra.lowrankdowndate\nLinearAlgebra.lowrankupdate!\nLinearAlgebra.lowrankdowndate!\nLinearAlgebra.LDLt\nLinearAlgebra.ldlt\nLinearAlgebra.ldlt!\nLinearAlgebra.QR\nLinearAlgebra.QRCompactWY\nLinearAlgebra.QRPivoted\nLinearAlgebra.qr\nLinearAlgebra.qr!\nLinearAlgebra.LQ\nLinearAlgebra.lq\nLinearAlgebra.lq!\nLinearAlgebra.BunchKaufman\nLinearAlgebra.bunchkaufman\nLinearAlgebra.bunchkaufman!\nLinearAlgebra.Eigen\nLinearAlgebra.GeneralizedEigen\nLinearAlgebra.eigvals\nLinearAlgebra.eigvals!\nLinearAlgebra.eigmax\nLinearAlgebra.eigmin\nLinearAlgebra.eigvecs\nLinearAlgebra.eigen\nLinearAlgebra.eigen!\nLinearAlgebra.Hessenberg\nLinearAlgebra.hessenberg\nLinearAlgebra.hessenberg!\nLinearAlgebra.Schur\nLinearAlgebra.GeneralizedSchur\nLinearAlgebra.schur\nLinearAlgebra.schur!\nLinearAlgebra.ordschur\nLinearAlgebra.ordschur!\nLinearAlgebra.SVD\nLinearAlgebra.GeneralizedSVD\nLinearAlgebra.svd\nLinearAlgebra.svd!\nLinearAlgebra.svdvals\nLinearAlgebra.svdvals!\nLinearAlgebra.Givens\nLinearAlgebra.givens\nLinearAlgebra.triu\nLinearAlgebra.triu!\nLinearAlgebra.tril\nLinearAlgebra.tril!\nLinearAlgebra.diagind\nLinearAlgebra.diag\nLinearAlgebra.diagm\nLinearAlgebra.rank\nLinearAlgebra.norm\nLinearAlgebra.opnorm\nLinearAlgebra.normalize!\nLinearAlgebra.normalize\nLinearAlgebra.cond\nLinearAlgebra.condskeel\nLinearAlgebra.tr\nLinearAlgebra.det\nLinearAlgebra.logdet\nLinearAlgebra.logabsdet\nBase.inv(::AbstractMatrix)\nLinearAlgebra.pinv\nLinearAlgebra.nullspace\nBase.kron\nBase.kron!\nLinearAlgebra.exp(::StridedMatrix{<:LinearAlgebra.BlasFloat})\nBase.cis(::AbstractMatrix)\nBase.:^(::AbstractMatrix, ::Number)\nBase.:^(::Number, ::AbstractMatrix)\nLinearAlgebra.log(::StridedMatrix)\nLinearAlgebra.sqrt(::StridedMatrix{<:Real})\nLinearAlgebra.cos(::StridedMatrix{<:Real})\nLinearAlgebra.sin(::StridedMatrix{<:Real})\nLinearAlgebra.sincos(::StridedMatrix{<:Real})\nLinearAlgebra.tan(::StridedMatrix{<:Real})\nLinearAlgebra.sec(::StridedMatrix)\nLinearAlgebra.csc(::StridedMatrix)\nLinearAlgebra.cot(::StridedMatrix)\nLinearAlgebra.cosh(::StridedMatrix)\nLinearAlgebra.sinh(::StridedMatrix)\nLinearAlgebra.tanh(::StridedMatrix)\nLinearAlgebra.sech(::StridedMatrix)\nLinearAlgebra.csch(::StridedMatrix)\nLinearAlgebra.coth(::StridedMatrix)\nLinearAlgebra.acos(::StridedMatrix)\nLinearAlgebra.asin(::StridedMatrix)\nLinearAlgebra.atan(::StridedMatrix)\nLinearAlgebra.asec(::StridedMatrix)\nLinearAlgebra.acsc(::StridedMatrix)\nLinearAlgebra.acot(::StridedMatrix)\nLinearAlgebra.acosh(::StridedMatrix)\nLinearAlgebra.asinh(::StridedMatrix)\nLinearAlgebra.atanh(::StridedMatrix)\nLinearAlgebra.asech(::StridedMatrix)\nLinearAlgebra.acsch(::StridedMatrix)\nLinearAlgebra.acoth(::StridedMatrix)\nLinearAlgebra.lyap\nLinearAlgebra.sylvester\nLinearAlgebra.issuccess\nLinearAlgebra.issymmetric\nLinearAlgebra.isposdef\nLinearAlgebra.isposdef!\nLinearAlgebra.istril\nLinearAlgebra.istriu\nLinearAlgebra.isdiag\nLinearAlgebra.ishermitian\nBase.transpose\nLinearAlgebra.transpose!\nLinearAlgebra.Transpose\nBase.adjoint\nLinearAlgebra.adjoint!\nLinearAlgebra.Adjoint\nBase.copy(::Union{Transpose,Adjoint})\nLinearAlgebra.stride1\nLinearAlgebra.checksquare\nLinearAlgebra.peakflops","category":"page"},{"location":"stdlib/LinearAlgebra/#Base.:*-Tuple{AbstractMatrix, AbstractMatrix}","page":"Linear Algebra","title":"Base.:*","text":"*(A::AbstractMatrix, B::AbstractMatrix)\n\nMatrix multiplication.\n\nExamples\n\njulia> [1 1; 0 1] * [1 0; 1 1]\n2×2 Matrix{Int64}:\n 2 1\n 1 1\n\n\n\n\n\n","category":"method"},{"location":"stdlib/LinearAlgebra/#Base.:\\-Tuple{AbstractMatrix, AbstractVecOrMat}","page":"Linear Algebra","title":"Base.:\\","text":"\\(A, B)\n\nMatrix division using a polyalgorithm. For input matrices A and B, the result X is such that A*X == B when A is square. The solver that is used depends upon the structure of A. If A is upper or lower triangular (or diagonal), no factorization of A is required and the system is solved with either forward or backward substitution. For non-triangular square matrices, an LU factorization is used.\n\nFor rectangular A the result is the minimum-norm least squares solution computed by a pivoted QR factorization of A and a rank estimate of A based on the R factor.\n\nWhen A is sparse, a similar polyalgorithm is used. For indefinite matrices, the LDLt factorization does not use pivoting during the numerical factorization and therefore the procedure can fail even for invertible matrices.\n\nSee also: factorize, pinv.\n\nExamples\n\njulia> A = [1 0; 1 -2]; B = [32; -4];\n\njulia> X = A \\ B\n2-element Vector{Float64}:\n 32.0\n 18.0\n\njulia> A * X == B\ntrue\n\n\n\n\n\n","category":"method"},{"location":"stdlib/LinearAlgebra/#LinearAlgebra.SingularException","page":"Linear Algebra","title":"LinearAlgebra.SingularException","text":"SingularException\n\nException thrown when the input matrix has one or more zero-valued eigenvalues, and is not invertible. A linear solve involving such a matrix cannot be computed. The info field indicates the location of (one of) the singular value(s).\n\n\n\n\n\n","category":"type"},{"location":"stdlib/LinearAlgebra/#LinearAlgebra.PosDefException","page":"Linear Algebra","title":"LinearAlgebra.PosDefException","text":"PosDefException\n\nException thrown when the input matrix was not positive definite. Some linear algebra functions and factorizations are only applicable to positive definite matrices. The info field indicates the location of (one of) the eigenvalue(s) which is (are) less than/equal to 0.\n\n\n\n\n\n","category":"type"},{"location":"stdlib/LinearAlgebra/#LinearAlgebra.ZeroPivotException","page":"Linear Algebra","title":"LinearAlgebra.ZeroPivotException","text":"ZeroPivotException <: Exception\n\nException thrown when a matrix factorization/solve encounters a zero in a pivot (diagonal) position and cannot proceed. This may not mean that the matrix is singular: it may be fruitful to switch to a diffent factorization such as pivoted LU that can re-order variables to eliminate spurious zero pivots. The info field indicates the location of (one of) the zero pivot(s).\n\n\n\n\n\n","category":"type"},{"location":"stdlib/LinearAlgebra/#LinearAlgebra.dot","page":"Linear Algebra","title":"LinearAlgebra.dot","text":"dot(x, y)\nx ⋅ y\n\nCompute the dot product between two vectors. For complex vectors, the first vector is conjugated.\n\ndot also works on arbitrary iterable objects, including arrays of any dimension, as long as dot is defined on the elements.\n\ndot is semantically equivalent to sum(dot(vx,vy) for (vx,vy) in zip(x, y)), with the added restriction that the arguments must have equal lengths.\n\nx ⋅ y (where ⋅ can be typed by tab-completing \\cdot in the REPL) is a synonym for dot(x, y).\n\nExamples\n\njulia> dot([1; 1], [2; 3])\n5\n\njulia> dot([im; im], [1; 1])\n0 - 2im\n\njulia> dot(1:5, 2:6)\n70\n\njulia> x = fill(2., (5,5));\n\njulia> y = fill(3., (5,5));\n\njulia> dot(x, y)\n150.0\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LinearAlgebra/#LinearAlgebra.dot-Tuple{Any, Any, Any}","page":"Linear Algebra","title":"LinearAlgebra.dot","text":"dot(x, A, y)\n\nCompute the generalized dot product dot(x, A*y) between two vectors x and y, without storing the intermediate result of A*y. As for the two-argument dot(_,_), this acts recursively. Moreover, for complex vectors, the first vector is conjugated.\n\ncompat: Julia 1.4\nThree-argument dot requires at least Julia 1.4.\n\nExamples\n\njulia> dot([1; 1], [1 2; 3 4], [2; 3])\n26\n\njulia> dot(1:5, reshape(1:25, 5, 5), 2:6)\n4850\n\njulia> ⋅(1:5, reshape(1:25, 5, 5), 2:6) == dot(1:5, reshape(1:25, 5, 5), 2:6)\ntrue\n\n\n\n\n\n","category":"method"},{"location":"stdlib/LinearAlgebra/#LinearAlgebra.cross","page":"Linear Algebra","title":"LinearAlgebra.cross","text":"cross(x, y)\n×(x,y)\n\nCompute the cross product of two 3-vectors.\n\nExamples\n\njulia> a = [0;1;0]\n3-element Vector{Int64}:\n 0\n 1\n 0\n\njulia> b = [0;0;1]\n3-element Vector{Int64}:\n 0\n 0\n 1\n\njulia> cross(a,b)\n3-element Vector{Int64}:\n 1\n 0\n 0\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LinearAlgebra/#LinearAlgebra.factorize","page":"Linear Algebra","title":"LinearAlgebra.factorize","text":"factorize(A)\n\nCompute a convenient factorization of A, based upon the type of the input matrix. factorize checks A to see if it is symmetric/triangular/etc. if A is passed as a generic matrix. factorize checks every element of A to verify/rule out each property. It will short-circuit as soon as it can rule out symmetry/triangular structure. The return value can be reused for efficient solving of multiple systems. For example: A=factorize(A); x=A\\b; y=A\\C.\n\nProperties of A type of factorization\nPositive-definite Cholesky (see cholesky)\nDense Symmetric/Hermitian Bunch-Kaufman (see bunchkaufman)\nSparse Symmetric/Hermitian LDLt (see ldlt)\nTriangular Triangular\nDiagonal Diagonal\nBidiagonal Bidiagonal\nTridiagonal LU (see lu)\nSymmetric real tridiagonal LDLt (see ldlt)\nGeneral square LU (see lu)\nGeneral non-square QR (see qr)\n\nIf factorize is called on a Hermitian positive-definite matrix, for instance, then factorize will return a Cholesky factorization.\n\nExamples\n\njulia> A = Array(Bidiagonal(fill(1.0, (5, 5)), :U))\n5×5 Matrix{Float64}:\n 1.0 1.0 0.0 0.0 0.0\n 0.0 1.0 1.0 0.0 0.0\n 0.0 0.0 1.0 1.0 0.0\n 0.0 0.0 0.0 1.0 1.0\n 0.0 0.0 0.0 0.0 1.0\n\njulia> factorize(A) # factorize will check to see that A is already factorized\n5×5 Bidiagonal{Float64, Vector{Float64}}:\n 1.0 1.0 ⋅ ⋅ ⋅\n ⋅ 1.0 1.0 ⋅ ⋅\n ⋅ ⋅ 1.0 1.0 ⋅\n ⋅ ⋅ ⋅ 1.0 1.0\n ⋅ ⋅ ⋅ ⋅ 1.0\n\nThis returns a 5×5 Bidiagonal{Float64}, which can now be passed to other linear algebra functions (e.g. eigensolvers) which will use specialized methods for Bidiagonal types.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LinearAlgebra/#LinearAlgebra.Diagonal","page":"Linear Algebra","title":"LinearAlgebra.Diagonal","text":"Diagonal(V::AbstractVector)\n\nConstruct a matrix with V as its diagonal.\n\nSee also diag, diagm.\n\nExamples\n\njulia> Diagonal([1, 10, 100])\n3×3 Diagonal{Int64, Vector{Int64}}:\n 1 ⋅ ⋅\n ⋅ 10 ⋅\n ⋅ ⋅ 100\n\njulia> diagm([7, 13])\n2×2 Matrix{Int64}:\n 7 0\n 0 13\n\n\n\n\n\nDiagonal(A::AbstractMatrix)\n\nConstruct a matrix from the diagonal of A.\n\nExamples\n\njulia> A = permutedims(reshape(1:15, 5, 3))\n3×5 Matrix{Int64}:\n 1 2 3 4 5\n 6 7 8 9 10\n 11 12 13 14 15\n\njulia> Diagonal(A)\n3×3 Diagonal{Int64, Vector{Int64}}:\n 1 ⋅ ⋅\n ⋅ 7 ⋅\n ⋅ ⋅ 13\n\njulia> diag(A, 2)\n3-element Vector{Int64}:\n 3\n 9\n 15\n\n\n\n\n\nDiagonal{T}(undef, n)\n\nConstruct an uninitialized Diagonal{T} of length n. See undef.\n\n\n\n\n\n","category":"type"},{"location":"stdlib/LinearAlgebra/#LinearAlgebra.Bidiagonal","page":"Linear Algebra","title":"LinearAlgebra.Bidiagonal","text":"Bidiagonal(dv::V, ev::V, uplo::Symbol) where V <: AbstractVector\n\nConstructs an upper (uplo=:U) or lower (uplo=:L) bidiagonal matrix using the given diagonal (dv) and off-diagonal (ev) vectors. The result is of type Bidiagonal and provides efficient specialized linear solvers, but may be converted into a regular matrix with convert(Array, _) (or Array(_) for short). The length of ev must be one less than the length of dv.\n\nExamples\n\njulia> dv = [1, 2, 3, 4]\n4-element Vector{Int64}:\n 1\n 2\n 3\n 4\n\njulia> ev = [7, 8, 9]\n3-element Vector{Int64}:\n 7\n 8\n 9\n\njulia> Bu = Bidiagonal(dv, ev, :U) # ev is on the first superdiagonal\n4×4 Bidiagonal{Int64, Vector{Int64}}:\n 1 7 ⋅ ⋅\n ⋅ 2 8 ⋅\n ⋅ ⋅ 3 9\n ⋅ ⋅ ⋅ 4\n\njulia> Bl = Bidiagonal(dv, ev, :L) # ev is on the first subdiagonal\n4×4 Bidiagonal{Int64, Vector{Int64}}:\n 1 ⋅ ⋅ ⋅\n 7 2 ⋅ ⋅\n ⋅ 8 3 ⋅\n ⋅ ⋅ 9 4\n\n\n\n\n\nBidiagonal(A, uplo::Symbol)\n\nConstruct a Bidiagonal matrix from the main diagonal of A and its first super- (if uplo=:U) or sub-diagonal (if uplo=:L).\n\nExamples\n\njulia> A = [1 1 1 1; 2 2 2 2; 3 3 3 3; 4 4 4 4]\n4×4 Matrix{Int64}:\n 1 1 1 1\n 2 2 2 2\n 3 3 3 3\n 4 4 4 4\n\njulia> Bidiagonal(A, :U) # contains the main diagonal and first superdiagonal of A\n4×4 Bidiagonal{Int64, Vector{Int64}}:\n 1 1 ⋅ ⋅\n ⋅ 2 2 ⋅\n ⋅ ⋅ 3 3\n ⋅ ⋅ ⋅ 4\n\njulia> Bidiagonal(A, :L) # contains the main diagonal and first subdiagonal of A\n4×4 Bidiagonal{Int64, Vector{Int64}}:\n 1 ⋅ ⋅ ⋅\n 2 2 ⋅ ⋅\n ⋅ 3 3 ⋅\n ⋅ ⋅ 4 4\n\n\n\n\n\n","category":"type"},{"location":"stdlib/LinearAlgebra/#LinearAlgebra.SymTridiagonal","page":"Linear Algebra","title":"LinearAlgebra.SymTridiagonal","text":"SymTridiagonal(dv::V, ev::V) where V <: AbstractVector\n\nConstruct a symmetric tridiagonal matrix from the diagonal (dv) and first sub/super-diagonal (ev), respectively. The result is of type SymTridiagonal and provides efficient specialized eigensolvers, but may be converted into a regular matrix with convert(Array, _) (or Array(_) for short).\n\nFor SymTridiagonal block matrices, the elements of dv are symmetrized. The argument ev is interpreted as the superdiagonal. Blocks from the subdiagonal are (materialized) transpose of the corresponding superdiagonal blocks.\n\nExamples\n\njulia> dv = [1, 2, 3, 4]\n4-element Vector{Int64}:\n 1\n 2\n 3\n 4\n\njulia> ev = [7, 8, 9]\n3-element Vector{Int64}:\n 7\n 8\n 9\n\njulia> SymTridiagonal(dv, ev)\n4×4 SymTridiagonal{Int64, Vector{Int64}}:\n 1 7 ⋅ ⋅\n 7 2 8 ⋅\n ⋅ 8 3 9\n ⋅ ⋅ 9 4\n\njulia> A = SymTridiagonal(fill([1 2; 3 4], 3), fill([1 2; 3 4], 2));\n\njulia> A[1,1]\n2×2 Symmetric{Int64, Matrix{Int64}}:\n 1 2\n 2 4\n\njulia> A[1,2]\n2×2 Matrix{Int64}:\n 1 2\n 3 4\n\njulia> A[2,1]\n2×2 Matrix{Int64}:\n 1 3\n 2 4\n\n\n\n\n\nSymTridiagonal(A::AbstractMatrix)\n\nConstruct a symmetric tridiagonal matrix from the diagonal and first superdiagonal of the symmetric matrix A.\n\nExamples\n\njulia> A = [1 2 3; 2 4 5; 3 5 6]\n3×3 Matrix{Int64}:\n 1 2 3\n 2 4 5\n 3 5 6\n\njulia> SymTridiagonal(A)\n3×3 SymTridiagonal{Int64, Vector{Int64}}:\n 1 2 ⋅\n 2 4 5\n ⋅ 5 6\n\njulia> B = reshape([[1 2; 2 3], [1 2; 3 4], [1 3; 2 4], [1 2; 2 3]], 2, 2);\n\njulia> SymTridiagonal(B)\n2×2 SymTridiagonal{Matrix{Int64}, Vector{Matrix{Int64}}}:\n [1 2; 2 3] [1 3; 2 4]\n [1 2; 3 4] [1 2; 2 3]\n\n\n\n\n\n","category":"type"},{"location":"stdlib/LinearAlgebra/#LinearAlgebra.Tridiagonal","page":"Linear Algebra","title":"LinearAlgebra.Tridiagonal","text":"Tridiagonal(dl::V, d::V, du::V) where V <: AbstractVector\n\nConstruct a tridiagonal matrix from the first subdiagonal, diagonal, and first superdiagonal, respectively. The result is of type Tridiagonal and provides efficient specialized linear solvers, but may be converted into a regular matrix with convert(Array, _) (or Array(_) for short). The lengths of dl and du must be one less than the length of d.\n\nExamples\n\njulia> dl = [1, 2, 3];\n\njulia> du = [4, 5, 6];\n\njulia> d = [7, 8, 9, 0];\n\njulia> Tridiagonal(dl, d, du)\n4×4 Tridiagonal{Int64, Vector{Int64}}:\n 7 4 ⋅ ⋅\n 1 8 5 ⋅\n ⋅ 2 9 6\n ⋅ ⋅ 3 0\n\n\n\n\n\nTridiagonal(A)\n\nConstruct a tridiagonal matrix from the first sub-diagonal, diagonal and first super-diagonal of the matrix A.\n\nExamples\n\njulia> A = [1 2 3 4; 1 2 3 4; 1 2 3 4; 1 2 3 4]\n4×4 Matrix{Int64}:\n 1 2 3 4\n 1 2 3 4\n 1 2 3 4\n 1 2 3 4\n\njulia> Tridiagonal(A)\n4×4 Tridiagonal{Int64, Vector{Int64}}:\n 1 2 ⋅ ⋅\n 1 2 3 ⋅\n ⋅ 2 3 4\n ⋅ ⋅ 3 4\n\n\n\n\n\n","category":"type"},{"location":"stdlib/LinearAlgebra/#LinearAlgebra.Symmetric","page":"Linear Algebra","title":"LinearAlgebra.Symmetric","text":"Symmetric(A, uplo=:U)\n\nConstruct a Symmetric view of the upper (if uplo = :U) or lower (if uplo = :L) triangle of the matrix A.\n\nExamples\n\njulia> A = [1 0 2 0 3; 0 4 0 5 0; 6 0 7 0 8; 0 9 0 1 0; 2 0 3 0 4]\n5×5 Matrix{Int64}:\n 1 0 2 0 3\n 0 4 0 5 0\n 6 0 7 0 8\n 0 9 0 1 0\n 2 0 3 0 4\n\njulia> Supper = Symmetric(A)\n5×5 Symmetric{Int64, Matrix{Int64}}:\n 1 0 2 0 3\n 0 4 0 5 0\n 2 0 7 0 8\n 0 5 0 1 0\n 3 0 8 0 4\n\njulia> Slower = Symmetric(A, :L)\n5×5 Symmetric{Int64, Matrix{Int64}}:\n 1 0 6 0 2\n 0 4 0 9 0\n 6 0 7 0 3\n 0 9 0 1 0\n 2 0 3 0 4\n\nNote that Supper will not be equal to Slower unless A is itself symmetric (e.g. if A == transpose(A)).\n\n\n\n\n\n","category":"type"},{"location":"stdlib/LinearAlgebra/#LinearAlgebra.Hermitian","page":"Linear Algebra","title":"LinearAlgebra.Hermitian","text":"Hermitian(A, uplo=:U)\n\nConstruct a Hermitian view of the upper (if uplo = :U) or lower (if uplo = :L) triangle of the matrix A.\n\nExamples\n\njulia> A = [1 0 2+2im 0 3-3im; 0 4 0 5 0; 6-6im 0 7 0 8+8im; 0 9 0 1 0; 2+2im 0 3-3im 0 4];\n\njulia> Hupper = Hermitian(A)\n5×5 Hermitian{Complex{Int64}, Matrix{Complex{Int64}}}:\n 1+0im 0+0im 2+2im 0+0im 3-3im\n 0+0im 4+0im 0+0im 5+0im 0+0im\n 2-2im 0+0im 7+0im 0+0im 8+8im\n 0+0im 5+0im 0+0im 1+0im 0+0im\n 3+3im 0+0im 8-8im 0+0im 4+0im\n\njulia> Hlower = Hermitian(A, :L)\n5×5 Hermitian{Complex{Int64}, Matrix{Complex{Int64}}}:\n 1+0im 0+0im 6+6im 0+0im 2-2im\n 0+0im 4+0im 0+0im 9+0im 0+0im\n 6-6im 0+0im 7+0im 0+0im 3+3im\n 0+0im 9+0im 0+0im 1+0im 0+0im\n 2+2im 0+0im 3-3im 0+0im 4+0im\n\nNote that Hupper will not be equal to Hlower unless A is itself Hermitian (e.g. if A == adjoint(A)).\n\nAll non-real parts of the diagonal will be ignored.\n\nHermitian(fill(complex(1,1), 1, 1)) == fill(1, 1, 1)\n\n\n\n\n\n","category":"type"},{"location":"stdlib/LinearAlgebra/#LinearAlgebra.LowerTriangular","page":"Linear Algebra","title":"LinearAlgebra.LowerTriangular","text":"LowerTriangular(A::AbstractMatrix)\n\nConstruct a LowerTriangular view of the matrix A.\n\nExamples\n\njulia> A = [1.0 2.0 3.0; 4.0 5.0 6.0; 7.0 8.0 9.0]\n3×3 Matrix{Float64}:\n 1.0 2.0 3.0\n 4.0 5.0 6.0\n 7.0 8.0 9.0\n\njulia> LowerTriangular(A)\n3×3 LowerTriangular{Float64, Matrix{Float64}}:\n 1.0 ⋅ ⋅\n 4.0 5.0 ⋅\n 7.0 8.0 9.0\n\n\n\n\n\n","category":"type"},{"location":"stdlib/LinearAlgebra/#LinearAlgebra.UpperTriangular","page":"Linear Algebra","title":"LinearAlgebra.UpperTriangular","text":"UpperTriangular(A::AbstractMatrix)\n\nConstruct an UpperTriangular view of the matrix A.\n\nExamples\n\njulia> A = [1.0 2.0 3.0; 4.0 5.0 6.0; 7.0 8.0 9.0]\n3×3 Matrix{Float64}:\n 1.0 2.0 3.0\n 4.0 5.0 6.0\n 7.0 8.0 9.0\n\njulia> UpperTriangular(A)\n3×3 UpperTriangular{Float64, Matrix{Float64}}:\n 1.0 2.0 3.0\n ⋅ 5.0 6.0\n ⋅ ⋅ 9.0\n\n\n\n\n\n","category":"type"},{"location":"stdlib/LinearAlgebra/#LinearAlgebra.UnitLowerTriangular","page":"Linear Algebra","title":"LinearAlgebra.UnitLowerTriangular","text":"UnitLowerTriangular(A::AbstractMatrix)\n\nConstruct a UnitLowerTriangular view of the matrix A. Such a view has the oneunit of the eltype of A on its diagonal.\n\nExamples\n\njulia> A = [1.0 2.0 3.0; 4.0 5.0 6.0; 7.0 8.0 9.0]\n3×3 Matrix{Float64}:\n 1.0 2.0 3.0\n 4.0 5.0 6.0\n 7.0 8.0 9.0\n\njulia> UnitLowerTriangular(A)\n3×3 UnitLowerTriangular{Float64, Matrix{Float64}}:\n 1.0 ⋅ ⋅\n 4.0 1.0 ⋅\n 7.0 8.0 1.0\n\n\n\n\n\n","category":"type"},{"location":"stdlib/LinearAlgebra/#LinearAlgebra.UnitUpperTriangular","page":"Linear Algebra","title":"LinearAlgebra.UnitUpperTriangular","text":"UnitUpperTriangular(A::AbstractMatrix)\n\nConstruct an UnitUpperTriangular view of the matrix A. Such a view has the oneunit of the eltype of A on its diagonal.\n\nExamples\n\njulia> A = [1.0 2.0 3.0; 4.0 5.0 6.0; 7.0 8.0 9.0]\n3×3 Matrix{Float64}:\n 1.0 2.0 3.0\n 4.0 5.0 6.0\n 7.0 8.0 9.0\n\njulia> UnitUpperTriangular(A)\n3×3 UnitUpperTriangular{Float64, Matrix{Float64}}:\n 1.0 2.0 3.0\n ⋅ 1.0 6.0\n ⋅ ⋅ 1.0\n\n\n\n\n\n","category":"type"},{"location":"stdlib/LinearAlgebra/#LinearAlgebra.UpperHessenberg","page":"Linear Algebra","title":"LinearAlgebra.UpperHessenberg","text":"UpperHessenberg(A::AbstractMatrix)\n\nConstruct an UpperHessenberg view of the matrix A. Entries of A below the first subdiagonal are ignored.\n\nEfficient algorithms are implemented for H \\ b, det(H), and similar.\n\nSee also the hessenberg function to factor any matrix into a similar upper-Hessenberg matrix.\n\nIf F::Hessenberg is the factorization object, the unitary matrix can be accessed with F.Q and the Hessenberg matrix with F.H. When Q is extracted, the resulting type is the HessenbergQ object, and may be converted to a regular matrix with convert(Array, _) (or Array(_) for short).\n\nIterating the decomposition produces the factors F.Q and F.H.\n\nExamples\n\njulia> A = [1 2 3 4; 5 6 7 8; 9 10 11 12; 13 14 15 16]\n4×4 Matrix{Int64}:\n 1 2 3 4\n 5 6 7 8\n 9 10 11 12\n 13 14 15 16\n\njulia> UpperHessenberg(A)\n4×4 UpperHessenberg{Int64, Matrix{Int64}}:\n 1 2 3 4\n 5 6 7 8\n ⋅ 10 11 12\n ⋅ ⋅ 15 16\n\n\n\n\n\n","category":"type"},{"location":"stdlib/LinearAlgebra/#LinearAlgebra.UniformScaling","page":"Linear Algebra","title":"LinearAlgebra.UniformScaling","text":"UniformScaling{T<:Number}\n\nGenerically sized uniform scaling operator defined as a scalar times the identity operator, λ*I. Although without an explicit size, it acts similarly to a matrix in many cases and includes support for some indexing. See also I.\n\ncompat: Julia 1.6\nIndexing using ranges is available as of Julia 1.6.\n\nExamples\n\njulia> J = UniformScaling(2.)\nUniformScaling{Float64}\n2.0*I\n\njulia> A = [1. 2.; 3. 4.]\n2×2 Matrix{Float64}:\n 1.0 2.0\n 3.0 4.0\n\njulia> J*A\n2×2 Matrix{Float64}:\n 2.0 4.0\n 6.0 8.0\n\njulia> J[1:2, 1:2]\n2×2 Matrix{Float64}:\n 2.0 0.0\n 0.0 2.0\n\n\n\n\n\n","category":"type"},{"location":"stdlib/LinearAlgebra/#LinearAlgebra.I","page":"Linear Algebra","title":"LinearAlgebra.I","text":"I\n\nAn object of type UniformScaling, representing an identity matrix of any size.\n\nExamples\n\njulia> fill(1, (5,6)) * I == fill(1, (5,6))\ntrue\n\njulia> [1 2im 3; 1im 2 3] * I\n2×3 Matrix{Complex{Int64}}:\n 1+0im 0+2im 3+0im\n 0+1im 2+0im 3+0im\n\n\n\n\n\n","category":"constant"},{"location":"stdlib/LinearAlgebra/#LinearAlgebra.UniformScaling-Tuple{Integer}","page":"Linear Algebra","title":"LinearAlgebra.UniformScaling","text":"(I::UniformScaling)(n::Integer)\n\nConstruct a Diagonal matrix from a UniformScaling.\n\ncompat: Julia 1.2\nThis method is available as of Julia 1.2.\n\nExamples\n\njulia> I(3)\n3×3 Diagonal{Bool, Vector{Bool}}:\n 1 ⋅ ⋅\n ⋅ 1 ⋅\n ⋅ ⋅ 1\n\njulia> (0.7*I)(3)\n3×3 Diagonal{Float64, Vector{Float64}}:\n 0.7 ⋅ ⋅\n ⋅ 0.7 ⋅\n ⋅ ⋅ 0.7\n\n\n\n\n\n","category":"method"},{"location":"stdlib/LinearAlgebra/#LinearAlgebra.Factorization","page":"Linear Algebra","title":"LinearAlgebra.Factorization","text":"LinearAlgebra.Factorization\n\nAbstract type for matrix factorizations a.k.a. matrix decompositions. See online documentation for a list of available matrix factorizations.\n\n\n\n\n\n","category":"type"},{"location":"stdlib/LinearAlgebra/#LinearAlgebra.LU","page":"Linear Algebra","title":"LinearAlgebra.LU","text":"LU <: Factorization\n\nMatrix factorization type of the LU factorization of a square matrix A. This is the return type of lu, the corresponding matrix factorization function.\n\nThe individual components of the factorization F::LU can be accessed via getproperty:\n\nComponent Description\nF.L L (unit lower triangular) part of LU\nF.U U (upper triangular) part of LU\nF.p (right) permutation Vector\nF.P (right) permutation Matrix\n\nIterating the factorization produces the components F.L, F.U, and F.p.\n\nExamples\n\njulia> A = [4 3; 6 3]\n2×2 Matrix{Int64}:\n 4 3\n 6 3\n\njulia> F = lu(A)\nLU{Float64, Matrix{Float64}, Vector{Int64}}\nL factor:\n2×2 Matrix{Float64}:\n 1.0 0.0\n 0.666667 1.0\nU factor:\n2×2 Matrix{Float64}:\n 6.0 3.0\n 0.0 1.0\n\njulia> F.L * F.U == A[F.p, :]\ntrue\n\njulia> l, u, p = lu(A); # destructuring via iteration\n\njulia> l == F.L && u == F.U && p == F.p\ntrue\n\n\n\n\n\n","category":"type"},{"location":"stdlib/LinearAlgebra/#LinearAlgebra.lu","page":"Linear Algebra","title":"LinearAlgebra.lu","text":"lu(A, pivot = RowMaximum(); check = true) -> F::LU\n\nCompute the LU factorization of A.\n\nWhen check = true, an error is thrown if the decomposition fails. When check = false, responsibility for checking the decomposition's validity (via issuccess) lies with the user.\n\nIn most cases, if A is a subtype S of AbstractMatrix{T} with an element type T supporting +, -, * and /, the return type is LU{T,S{T}}. If pivoting is chosen (default) the element type should also support abs and <. Pivoting can be turned off by passing pivot = NoPivot().\n\nThe individual components of the factorization F can be accessed via getproperty:\n\nComponent Description\nF.L L (lower triangular) part of LU\nF.U U (upper triangular) part of LU\nF.p (right) permutation Vector\nF.P (right) permutation Matrix\n\nIterating the factorization produces the components F.L, F.U, and F.p.\n\nThe relationship between F and A is\n\nF.L*F.U == A[F.p, :]\n\nF further supports the following functions:\n\nSupported function LU LU{T,Tridiagonal{T}}\n/ ✓ \n\\ ✓ ✓\ninv ✓ ✓\ndet ✓ ✓\nlogdet ✓ ✓\nlogabsdet ✓ ✓\nsize ✓ ✓\n\nExamples\n\njulia> A = [4 3; 6 3]\n2×2 Matrix{Int64}:\n 4 3\n 6 3\n\njulia> F = lu(A)\nLU{Float64, Matrix{Float64}, Vector{Int64}}\nL factor:\n2×2 Matrix{Float64}:\n 1.0 0.0\n 0.666667 1.0\nU factor:\n2×2 Matrix{Float64}:\n 6.0 3.0\n 0.0 1.0\n\njulia> F.L * F.U == A[F.p, :]\ntrue\n\njulia> l, u, p = lu(A); # destructuring via iteration\n\njulia> l == F.L && u == F.U && p == F.p\ntrue\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LinearAlgebra/#LinearAlgebra.lu!","page":"Linear Algebra","title":"LinearAlgebra.lu!","text":"lu!(A, pivot = RowMaximum(); check = true) -> LU\n\nlu! is the same as lu, but saves space by overwriting the input A, instead of creating a copy. An InexactError exception is thrown if the factorization produces a number not representable by the element type of A, e.g. for integer types.\n\nExamples\n\njulia> A = [4. 3.; 6. 3.]\n2×2 Matrix{Float64}:\n 4.0 3.0\n 6.0 3.0\n\njulia> F = lu!(A)\nLU{Float64, Matrix{Float64}, Vector{Int64}}\nL factor:\n2×2 Matrix{Float64}:\n 1.0 0.0\n 0.666667 1.0\nU factor:\n2×2 Matrix{Float64}:\n 6.0 3.0\n 0.0 1.0\n\njulia> iA = [4 3; 6 3]\n2×2 Matrix{Int64}:\n 4 3\n 6 3\n\njulia> lu!(iA)\nERROR: InexactError: Int64(0.6666666666666666)\nStacktrace:\n[...]\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LinearAlgebra/#LinearAlgebra.Cholesky","page":"Linear Algebra","title":"LinearAlgebra.Cholesky","text":"Cholesky <: Factorization\n\nMatrix factorization type of the Cholesky factorization of a dense symmetric/Hermitian positive definite matrix A. This is the return type of cholesky, the corresponding matrix factorization function.\n\nThe triangular Cholesky factor can be obtained from the factorization F::Cholesky via F.L and F.U, where A ≈ F.U' * F.U ≈ F.L * F.L'.\n\nThe following functions are available for Cholesky objects: size, \\, inv, det, logdet and isposdef.\n\nIterating the decomposition produces the components L and U.\n\nExamples\n\njulia> A = [4. 12. -16.; 12. 37. -43.; -16. -43. 98.]\n3×3 Matrix{Float64}:\n 4.0 12.0 -16.0\n 12.0 37.0 -43.0\n -16.0 -43.0 98.0\n\njulia> C = cholesky(A)\nCholesky{Float64, Matrix{Float64}}\nU factor:\n3×3 UpperTriangular{Float64, Matrix{Float64}}:\n 2.0 6.0 -8.0\n ⋅ 1.0 5.0\n ⋅ ⋅ 3.0\n\njulia> C.U\n3×3 UpperTriangular{Float64, Matrix{Float64}}:\n 2.0 6.0 -8.0\n ⋅ 1.0 5.0\n ⋅ ⋅ 3.0\n\njulia> C.L\n3×3 LowerTriangular{Float64, Matrix{Float64}}:\n 2.0 ⋅ ⋅\n 6.0 1.0 ⋅\n -8.0 5.0 3.0\n\njulia> C.L * C.U == A\ntrue\n\njulia> l, u = C; # destructuring via iteration\n\njulia> l == C.L && u == C.U\ntrue\n\n\n\n\n\n","category":"type"},{"location":"stdlib/LinearAlgebra/#LinearAlgebra.CholeskyPivoted","page":"Linear Algebra","title":"LinearAlgebra.CholeskyPivoted","text":"CholeskyPivoted\n\nMatrix factorization type of the pivoted Cholesky factorization of a dense symmetric/Hermitian positive semi-definite matrix A. This is the return type of cholesky(_, ::RowMaximum), the corresponding matrix factorization function.\n\nThe triangular Cholesky factor can be obtained from the factorization F::CholeskyPivoted via F.L and F.U, and the permutation via F.p, where A[F.p, F.p] ≈ Ur' * Ur ≈ Lr * Lr' with Ur = F.U[1:F.rank, :] and Lr = F.L[:, 1:F.rank], or alternatively A ≈ Up' * Up ≈ Lp * Lp' with Up = F.U[1:F.rank, invperm(F.p)] and Lp = F.L[invperm(F.p), 1:F.rank].\n\nThe following functions are available for CholeskyPivoted objects: size, \\, inv, det, and rank.\n\nIterating the decomposition produces the components L and U.\n\nExamples\n\njulia> X = [1.0, 2.0, 3.0, 4.0];\n\njulia> A = X * X';\n\njulia> C = cholesky(A, RowMaximum(), check = false)\nCholeskyPivoted{Float64, Matrix{Float64}, Vector{Int64}}\nU factor with rank 1:\n4×4 UpperTriangular{Float64, Matrix{Float64}}:\n 4.0 2.0 3.0 1.0\n ⋅ 0.0 6.0 2.0\n ⋅ ⋅ 9.0 3.0\n ⋅ ⋅ ⋅ 1.0\npermutation:\n4-element Vector{Int64}:\n 4\n 2\n 3\n 1\n\njulia> C.U[1:C.rank, :]' * C.U[1:C.rank, :] ≈ A[C.p, C.p]\ntrue\n\njulia> l, u = C; # destructuring via iteration\n\njulia> l == C.L && u == C.U\ntrue\n\n\n\n\n\n","category":"type"},{"location":"stdlib/LinearAlgebra/#LinearAlgebra.cholesky","page":"Linear Algebra","title":"LinearAlgebra.cholesky","text":"cholesky(A, NoPivot(); check = true) -> Cholesky\n\nCompute the Cholesky factorization of a dense symmetric positive definite matrix A and return a Cholesky factorization. The matrix A can either be a Symmetric or Hermitian AbstractMatrix or a perfectly symmetric or Hermitian AbstractMatrix.\n\nThe triangular Cholesky factor can be obtained from the factorization F via F.L and F.U, where A ≈ F.U' * F.U ≈ F.L * F.L'.\n\nThe following functions are available for Cholesky objects: size, \\, inv, det, logdet and isposdef.\n\nIf you have a matrix A that is slightly non-Hermitian due to roundoff errors in its construction, wrap it in Hermitian(A) before passing it to cholesky in order to treat it as perfectly Hermitian.\n\nWhen check = true, an error is thrown if the decomposition fails. When check = false, responsibility for checking the decomposition's validity (via issuccess) lies with the user.\n\nExamples\n\njulia> A = [4. 12. -16.; 12. 37. -43.; -16. -43. 98.]\n3×3 Matrix{Float64}:\n 4.0 12.0 -16.0\n 12.0 37.0 -43.0\n -16.0 -43.0 98.0\n\njulia> C = cholesky(A)\nCholesky{Float64, Matrix{Float64}}\nU factor:\n3×3 UpperTriangular{Float64, Matrix{Float64}}:\n 2.0 6.0 -8.0\n ⋅ 1.0 5.0\n ⋅ ⋅ 3.0\n\njulia> C.U\n3×3 UpperTriangular{Float64, Matrix{Float64}}:\n 2.0 6.0 -8.0\n ⋅ 1.0 5.0\n ⋅ ⋅ 3.0\n\njulia> C.L\n3×3 LowerTriangular{Float64, Matrix{Float64}}:\n 2.0 ⋅ ⋅\n 6.0 1.0 ⋅\n -8.0 5.0 3.0\n\njulia> C.L * C.U == A\ntrue\n\n\n\n\n\ncholesky(A, RowMaximum(); tol = 0.0, check = true) -> CholeskyPivoted\n\nCompute the pivoted Cholesky factorization of a dense symmetric positive semi-definite matrix A and return a CholeskyPivoted factorization. The matrix A can either be a Symmetric or Hermitian AbstractMatrix or a perfectly symmetric or Hermitian AbstractMatrix.\n\nThe triangular Cholesky factor can be obtained from the factorization F via F.L and F.U, and the permutation via F.p, where A[F.p, F.p] ≈ Ur' * Ur ≈ Lr * Lr' with Ur = F.U[1:F.rank, :] and Lr = F.L[:, 1:F.rank], or alternatively A ≈ Up' * Up ≈ Lp * Lp' with Up = F.U[1:F.rank, invperm(F.p)] and Lp = F.L[invperm(F.p), 1:F.rank].\n\nThe following functions are available for CholeskyPivoted objects: size, \\, inv, det, and rank.\n\nThe argument tol determines the tolerance for determining the rank. For negative values, the tolerance is the machine precision.\n\nIf you have a matrix A that is slightly non-Hermitian due to roundoff errors in its construction, wrap it in Hermitian(A) before passing it to cholesky in order to treat it as perfectly Hermitian.\n\nWhen check = true, an error is thrown if the decomposition fails. When check = false, responsibility for checking the decomposition's validity (via issuccess) lies with the user.\n\nExamples\n\njulia> X = [1.0, 2.0, 3.0, 4.0];\n\njulia> A = X * X';\n\njulia> C = cholesky(A, RowMaximum(), check = false)\nCholeskyPivoted{Float64, Matrix{Float64}, Vector{Int64}}\nU factor with rank 1:\n4×4 UpperTriangular{Float64, Matrix{Float64}}:\n 4.0 2.0 3.0 1.0\n ⋅ 0.0 6.0 2.0\n ⋅ ⋅ 9.0 3.0\n ⋅ ⋅ ⋅ 1.0\npermutation:\n4-element Vector{Int64}:\n 4\n 2\n 3\n 1\n\njulia> C.U[1:C.rank, :]' * C.U[1:C.rank, :] ≈ A[C.p, C.p]\ntrue\n\njulia> l, u = C; # destructuring via iteration\n\njulia> l == C.L && u == C.U\ntrue\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LinearAlgebra/#LinearAlgebra.cholesky!","page":"Linear Algebra","title":"LinearAlgebra.cholesky!","text":"cholesky!(A::AbstractMatrix, NoPivot(); check = true) -> Cholesky\n\nThe same as cholesky, but saves space by overwriting the input A, instead of creating a copy. An InexactError exception is thrown if the factorization produces a number not representable by the element type of A, e.g. for integer types.\n\nExamples\n\njulia> A = [1 2; 2 50]\n2×2 Matrix{Int64}:\n 1 2\n 2 50\n\njulia> cholesky!(A)\nERROR: InexactError: Int64(6.782329983125268)\nStacktrace:\n[...]\n\n\n\n\n\ncholesky!(A::AbstractMatrix, RowMaximum(); tol = 0.0, check = true) -> CholeskyPivoted\n\nThe same as cholesky, but saves space by overwriting the input A, instead of creating a copy. An InexactError exception is thrown if the factorization produces a number not representable by the element type of A, e.g. for integer types.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LinearAlgebra/#LinearAlgebra.lowrankupdate","page":"Linear Algebra","title":"LinearAlgebra.lowrankupdate","text":"lowrankupdate(C::Cholesky, v::AbstractVector) -> CC::Cholesky\n\nUpdate a Cholesky factorization C with the vector v. If A = C.U'C.U then CC = cholesky(C.U'C.U + v*v') but the computation of CC only uses O(n^2) operations.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LinearAlgebra/#LinearAlgebra.lowrankdowndate","page":"Linear Algebra","title":"LinearAlgebra.lowrankdowndate","text":"lowrankdowndate(C::Cholesky, v::AbstractVector) -> CC::Cholesky\n\nDowndate a Cholesky factorization C with the vector v. If A = C.U'C.U then CC = cholesky(C.U'C.U - v*v') but the computation of CC only uses O(n^2) operations.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LinearAlgebra/#LinearAlgebra.lowrankupdate!","page":"Linear Algebra","title":"LinearAlgebra.lowrankupdate!","text":"lowrankupdate!(C::Cholesky, v::AbstractVector) -> CC::Cholesky\n\nUpdate a Cholesky factorization C with the vector v. If A = C.U'C.U then CC = cholesky(C.U'C.U + v*v') but the computation of CC only uses O(n^2) operations. The input factorization C is updated in place such that on exit C == CC. The vector v is destroyed during the computation.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LinearAlgebra/#LinearAlgebra.lowrankdowndate!","page":"Linear Algebra","title":"LinearAlgebra.lowrankdowndate!","text":"lowrankdowndate!(C::Cholesky, v::AbstractVector) -> CC::Cholesky\n\nDowndate a Cholesky factorization C with the vector v. If A = C.U'C.U then CC = cholesky(C.U'C.U - v*v') but the computation of CC only uses O(n^2) operations. The input factorization C is updated in place such that on exit C == CC. The vector v is destroyed during the computation.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LinearAlgebra/#LinearAlgebra.LDLt","page":"Linear Algebra","title":"LinearAlgebra.LDLt","text":"LDLt <: Factorization\n\nMatrix factorization type of the LDLt factorization of a real SymTridiagonal matrix S such that S = L*Diagonal(d)*L', where L is a UnitLowerTriangular matrix and d is a vector. The main use of an LDLt factorization F = ldlt(S) is to solve the linear system of equations Sx = b with F\\b. This is the return type of ldlt, the corresponding matrix factorization function.\n\nThe individual components of the factorization F::LDLt can be accessed via getproperty:\n\nComponent Description\nF.L L (unit lower triangular) part of LDLt\nF.D D (diagonal) part of LDLt\nF.Lt Lt (unit upper triangular) part of LDLt\nF.d diagonal values of D as a Vector\n\nExamples\n\njulia> S = SymTridiagonal([3., 4., 5.], [1., 2.])\n3×3 SymTridiagonal{Float64, Vector{Float64}}:\n 3.0 1.0 ⋅\n 1.0 4.0 2.0\n ⋅ 2.0 5.0\n\njulia> F = ldlt(S)\nLDLt{Float64, SymTridiagonal{Float64, Vector{Float64}}}\nL factor:\n3×3 UnitLowerTriangular{Float64, SymTridiagonal{Float64, Vector{Float64}}}:\n 1.0 ⋅ ⋅\n 0.333333 1.0 ⋅\n 0.0 0.545455 1.0\nD factor:\n3×3 Diagonal{Float64, Vector{Float64}}:\n 3.0 ⋅ ⋅\n ⋅ 3.66667 ⋅\n ⋅ ⋅ 3.90909\n\n\n\n\n\n","category":"type"},{"location":"stdlib/LinearAlgebra/#LinearAlgebra.ldlt","page":"Linear Algebra","title":"LinearAlgebra.ldlt","text":"ldlt(S::SymTridiagonal) -> LDLt\n\nCompute an LDLt (i.e., LDL^T) factorization of the real symmetric tridiagonal matrix S such that S = L*Diagonal(d)*L' where L is a unit lower triangular matrix and d is a vector. The main use of an LDLt factorization F = ldlt(S) is to solve the linear system of equations Sx = b with F\\b.\n\nSee also bunchkaufman for a similar, but pivoted, factorization of arbitrary symmetric or Hermitian matrices.\n\nExamples\n\njulia> S = SymTridiagonal([3., 4., 5.], [1., 2.])\n3×3 SymTridiagonal{Float64, Vector{Float64}}:\n 3.0 1.0 ⋅\n 1.0 4.0 2.0\n ⋅ 2.0 5.0\n\njulia> ldltS = ldlt(S);\n\njulia> b = [6., 7., 8.];\n\njulia> ldltS \\ b\n3-element Vector{Float64}:\n 1.7906976744186047\n 0.627906976744186\n 1.3488372093023255\n\njulia> S \\ b\n3-element Vector{Float64}:\n 1.7906976744186047\n 0.627906976744186\n 1.3488372093023255\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LinearAlgebra/#LinearAlgebra.ldlt!","page":"Linear Algebra","title":"LinearAlgebra.ldlt!","text":"ldlt!(S::SymTridiagonal) -> LDLt\n\nSame as ldlt, but saves space by overwriting the input S, instead of creating a copy.\n\nExamples\n\njulia> S = SymTridiagonal([3., 4., 5.], [1., 2.])\n3×3 SymTridiagonal{Float64, Vector{Float64}}:\n 3.0 1.0 ⋅\n 1.0 4.0 2.0\n ⋅ 2.0 5.0\n\njulia> ldltS = ldlt!(S);\n\njulia> ldltS === S\nfalse\n\njulia> S\n3×3 SymTridiagonal{Float64, Vector{Float64}}:\n 3.0 0.333333 ⋅\n 0.333333 3.66667 0.545455\n ⋅ 0.545455 3.90909\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LinearAlgebra/#LinearAlgebra.QR","page":"Linear Algebra","title":"LinearAlgebra.QR","text":"QR <: Factorization\n\nA QR matrix factorization stored in a packed format, typically obtained from qr. If A is an m×n matrix, then\n\nA = Q R\n\nwhere Q is an orthogonal/unitary matrix and R is upper triangular. The matrix Q is stored as a sequence of Householder reflectors v_i and coefficients tau_i where:\n\nQ = prod_i=1^min(mn) (I - tau_i v_i v_i^T)\n\nIterating the decomposition produces the components Q and R.\n\nThe object has two fields:\n\nfactors is an m×n matrix.\nThe upper triangular part contains the elements of R, that is R = triu(F.factors) for a QR object F.\nThe subdiagonal part contains the reflectors v_i stored in a packed format where v_i is the ith column of the matrix V = I + tril(F.factors, -1).\nτ is a vector of length min(m,n) containing the coefficients au_i.\n\n\n\n\n\n","category":"type"},{"location":"stdlib/LinearAlgebra/#LinearAlgebra.QRCompactWY","page":"Linear Algebra","title":"LinearAlgebra.QRCompactWY","text":"QRCompactWY <: Factorization\n\nA QR matrix factorization stored in a compact blocked format, typically obtained from qr. If A is an m×n matrix, then\n\nA = Q R\n\nwhere Q is an orthogonal/unitary matrix and R is upper triangular. It is similar to the QR format except that the orthogonal/unitary matrix Q is stored in Compact WY format [Schreiber1989]. For the block size n_b, it is stored as a m×n lower trapezoidal matrix V and a matrix T = (T_1 T_2 T_b-1 T_b) composed of b = lceil min(mn) n_b rceil upper triangular matrices T_j of size n_b×n_b (j = 1 b-1) and an upper trapezoidal n_b×min(mn) - (b-1) n_b matrix T_b (j=b) whose upper square part denoted with T_b satisfying\n\nQ = prod_i=1^min(mn) (I - tau_i v_i v_i^T)\n= prod_j=1^b (I - V_j T_j V_j^T)\n\nsuch that v_i is the ith column of V, tau_i is the ith element of [diag(T_1); diag(T_2); …; diag(T_b)], and (V_1 V_2 V_b) is the left m×min(m, n) block of V. When constructed using qr, the block size is given by n_b = min(m n 36).\n\nIterating the decomposition produces the components Q and R.\n\nThe object has two fields:\n\nfactors, as in the QR type, is an m×n matrix.\nThe upper triangular part contains the elements of R, that is R = triu(F.factors) for a QR object F.\nThe subdiagonal part contains the reflectors v_i stored in a packed format such that V = I + tril(F.factors, -1).\nT is a n_b-by-min(mn) matrix as described above. The subdiagonal elements for each triangular matrix T_j are ignored.\n\nnote: Note\nThis format should not to be confused with the older WY representation [Bischof1987].\n\n[Bischof1987]: C Bischof and C Van Loan, \"The WY representation for products of Householder matrices\", SIAM J Sci Stat Comput 8 (1987), s2-s13. doi:10.1137/0908009\n\n[Schreiber1989]: R Schreiber and C Van Loan, \"A storage-efficient WY representation for products of Householder transformations\", SIAM J Sci Stat Comput 10 (1989), 53-57. doi:10.1137/0910005\n\n\n\n\n\n","category":"type"},{"location":"stdlib/LinearAlgebra/#LinearAlgebra.QRPivoted","page":"Linear Algebra","title":"LinearAlgebra.QRPivoted","text":"QRPivoted <: Factorization\n\nA QR matrix factorization with column pivoting in a packed format, typically obtained from qr. If A is an m×n matrix, then\n\nA P = Q R\n\nwhere P is a permutation matrix, Q is an orthogonal/unitary matrix and R is upper triangular. The matrix Q is stored as a sequence of Householder reflectors:\n\nQ = prod_i=1^min(mn) (I - tau_i v_i v_i^T)\n\nIterating the decomposition produces the components Q, R, and p.\n\nThe object has three fields:\n\nfactors is an m×n matrix.\nThe upper triangular part contains the elements of R, that is R = triu(F.factors) for a QR object F.\nThe subdiagonal part contains the reflectors v_i stored in a packed format where v_i is the ith column of the matrix V = I + tril(F.factors, -1).\nτ is a vector of length min(m,n) containing the coefficients au_i.\njpvt is an integer vector of length n corresponding to the permutation P.\n\n\n\n\n\n","category":"type"},{"location":"stdlib/LinearAlgebra/#LinearAlgebra.qr","page":"Linear Algebra","title":"LinearAlgebra.qr","text":"qr(A, pivot = NoPivot(); blocksize) -> F\n\nCompute the QR factorization of the matrix A: an orthogonal (or unitary if A is complex-valued) matrix Q, and an upper triangular matrix R such that\n\nA = Q R\n\nThe returned object F stores the factorization in a packed format:\n\nif pivot == ColumnNorm() then F is a QRPivoted object,\notherwise if the element type of A is a BLAS type (Float32, Float64, ComplexF32 or ComplexF64), then F is a QRCompactWY object,\notherwise F is a QR object.\n\nThe individual components of the decomposition F can be retrieved via property accessors:\n\nF.Q: the orthogonal/unitary matrix Q\nF.R: the upper triangular matrix R\nF.p: the permutation vector of the pivot (QRPivoted only)\nF.P: the permutation matrix of the pivot (QRPivoted only)\n\nIterating the decomposition produces the components Q, R, and if extant p.\n\nThe following functions are available for the QR objects: inv, size, and \\. When A is rectangular, \\ will return a least squares solution and if the solution is not unique, the one with smallest norm is returned. When A is not full rank, factorization with (column) pivoting is required to obtain a minimum norm solution.\n\nMultiplication with respect to either full/square or non-full/square Q is allowed, i.e. both F.Q*F.R and F.Q*A are supported. A Q matrix can be converted into a regular matrix with Matrix. This operation returns the \"thin\" Q factor, i.e., if A is m×n with m>=n, then Matrix(F.Q) yields an m×n matrix with orthonormal columns. To retrieve the \"full\" Q factor, an m×m orthogonal matrix, use F.Q*I. If m<=n, then Matrix(F.Q) yields an m×m orthogonal matrix.\n\nThe block size for QR decomposition can be specified by keyword argument blocksize :: Integer when pivot == NoPivot() and A isa StridedMatrix{<:BlasFloat}. It is ignored when blocksize > minimum(size(A)). See QRCompactWY.\n\ncompat: Julia 1.4\nThe blocksize keyword argument requires Julia 1.4 or later.\n\nExamples\n\njulia> A = [3.0 -6.0; 4.0 -8.0; 0.0 1.0]\n3×2 Matrix{Float64}:\n 3.0 -6.0\n 4.0 -8.0\n 0.0 1.0\n\njulia> F = qr(A)\nLinearAlgebra.QRCompactWY{Float64, Matrix{Float64}, Matrix{Float64}}\nQ factor:\n3×3 LinearAlgebra.QRCompactWYQ{Float64, Matrix{Float64}, Matrix{Float64}}:\n -0.6 0.0 0.8\n -0.8 0.0 -0.6\n 0.0 -1.0 0.0\nR factor:\n2×2 Matrix{Float64}:\n -5.0 10.0\n 0.0 -1.0\n\njulia> F.Q * F.R == A\ntrue\n\nnote: Note\nqr returns multiple types because LAPACK uses several representations that minimize the memory storage requirements of products of Householder elementary reflectors, so that the Q and R matrices can be stored compactly rather as two separate dense matrices.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LinearAlgebra/#LinearAlgebra.qr!","page":"Linear Algebra","title":"LinearAlgebra.qr!","text":"qr!(A, pivot = NoPivot(); blocksize)\n\nqr! is the same as qr when A is a subtype of StridedMatrix, but saves space by overwriting the input A, instead of creating a copy. An InexactError exception is thrown if the factorization produces a number not representable by the element type of A, e.g. for integer types.\n\ncompat: Julia 1.4\nThe blocksize keyword argument requires Julia 1.4 or later.\n\nExamples\n\njulia> a = [1. 2.; 3. 4.]\n2×2 Matrix{Float64}:\n 1.0 2.0\n 3.0 4.0\n\njulia> qr!(a)\nLinearAlgebra.QRCompactWY{Float64, Matrix{Float64}, Matrix{Float64}}\nQ factor:\n2×2 LinearAlgebra.QRCompactWYQ{Float64, Matrix{Float64}, Matrix{Float64}}:\n -0.316228 -0.948683\n -0.948683 0.316228\nR factor:\n2×2 Matrix{Float64}:\n -3.16228 -4.42719\n 0.0 -0.632456\n\njulia> a = [1 2; 3 4]\n2×2 Matrix{Int64}:\n 1 2\n 3 4\n\njulia> qr!(a)\nERROR: InexactError: Int64(3.1622776601683795)\nStacktrace:\n[...]\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LinearAlgebra/#LinearAlgebra.LQ","page":"Linear Algebra","title":"LinearAlgebra.LQ","text":"LQ <: Factorization\n\nMatrix factorization type of the LQ factorization of a matrix A. The LQ decomposition is the QR decomposition of transpose(A). This is the return type of lq, the corresponding matrix factorization function.\n\nIf S::LQ is the factorization object, the lower triangular component can be obtained via S.L, and the orthogonal/unitary component via S.Q, such that A ≈ S.L*S.Q.\n\nIterating the decomposition produces the components S.L and S.Q.\n\nExamples\n\njulia> A = [5. 7.; -2. -4.]\n2×2 Matrix{Float64}:\n 5.0 7.0\n -2.0 -4.0\n\njulia> S = lq(A)\nLQ{Float64, Matrix{Float64}, Vector{Float64}}\nL factor:\n2×2 Matrix{Float64}:\n -8.60233 0.0\n 4.41741 -0.697486\nQ factor:\n2×2 LinearAlgebra.LQPackedQ{Float64, Matrix{Float64}, Vector{Float64}}:\n -0.581238 -0.813733\n -0.813733 0.581238\n\njulia> S.L * S.Q\n2×2 Matrix{Float64}:\n 5.0 7.0\n -2.0 -4.0\n\njulia> l, q = S; # destructuring via iteration\n\njulia> l == S.L && q == S.Q\ntrue\n\n\n\n\n\n","category":"type"},{"location":"stdlib/LinearAlgebra/#LinearAlgebra.lq","page":"Linear Algebra","title":"LinearAlgebra.lq","text":"lq(A) -> S::LQ\n\nCompute the LQ decomposition of A. The decomposition's lower triangular component can be obtained from the LQ object S via S.L, and the orthogonal/unitary component via S.Q, such that A ≈ S.L*S.Q.\n\nIterating the decomposition produces the components S.L and S.Q.\n\nThe LQ decomposition is the QR decomposition of transpose(A), and it is useful in order to compute the minimum-norm solution lq(A) \\ b to an underdetermined system of equations (A has more columns than rows, but has full row rank).\n\nExamples\n\njulia> A = [5. 7.; -2. -4.]\n2×2 Matrix{Float64}:\n 5.0 7.0\n -2.0 -4.0\n\njulia> S = lq(A)\nLQ{Float64, Matrix{Float64}, Vector{Float64}}\nL factor:\n2×2 Matrix{Float64}:\n -8.60233 0.0\n 4.41741 -0.697486\nQ factor:\n2×2 LinearAlgebra.LQPackedQ{Float64, Matrix{Float64}, Vector{Float64}}:\n -0.581238 -0.813733\n -0.813733 0.581238\n\njulia> S.L * S.Q\n2×2 Matrix{Float64}:\n 5.0 7.0\n -2.0 -4.0\n\njulia> l, q = S; # destructuring via iteration\n\njulia> l == S.L && q == S.Q\ntrue\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LinearAlgebra/#LinearAlgebra.lq!","page":"Linear Algebra","title":"LinearAlgebra.lq!","text":"lq!(A) -> LQ\n\nCompute the LQ factorization of A, using the input matrix as a workspace. See also lq.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LinearAlgebra/#LinearAlgebra.BunchKaufman","page":"Linear Algebra","title":"LinearAlgebra.BunchKaufman","text":"BunchKaufman <: Factorization\n\nMatrix factorization type of the Bunch-Kaufman factorization of a symmetric or Hermitian matrix A as P'UDU'P or P'LDL'P, depending on whether the upper (the default) or the lower triangle is stored in A. If A is complex symmetric then U' and L' denote the unconjugated transposes, i.e. transpose(U) and transpose(L), respectively. This is the return type of bunchkaufman, the corresponding matrix factorization function.\n\nIf S::BunchKaufman is the factorization object, the components can be obtained via S.D, S.U or S.L as appropriate given S.uplo, and S.p.\n\nIterating the decomposition produces the components S.D, S.U or S.L as appropriate given S.uplo, and S.p.\n\nExamples\n\njulia> A = [1 2; 2 3]\n2×2 Matrix{Int64}:\n 1 2\n 2 3\n\njulia> S = bunchkaufman(A) # A gets wrapped internally by Symmetric(A)\nBunchKaufman{Float64, Matrix{Float64}, Vector{Int64}}\nD factor:\n2×2 Tridiagonal{Float64, Vector{Float64}}:\n -0.333333 0.0\n 0.0 3.0\nU factor:\n2×2 UnitUpperTriangular{Float64, Matrix{Float64}}:\n 1.0 0.666667\n ⋅ 1.0\npermutation:\n2-element Vector{Int64}:\n 1\n 2\n\njulia> d, u, p = S; # destructuring via iteration\n\njulia> d == S.D && u == S.U && p == S.p\ntrue\n\njulia> S = bunchkaufman(Symmetric(A, :L))\nBunchKaufman{Float64, Matrix{Float64}, Vector{Int64}}\nD factor:\n2×2 Tridiagonal{Float64, Vector{Float64}}:\n 3.0 0.0\n 0.0 -0.333333\nL factor:\n2×2 UnitLowerTriangular{Float64, Matrix{Float64}}:\n 1.0 ⋅\n 0.666667 1.0\npermutation:\n2-element Vector{Int64}:\n 2\n 1\n\n\n\n\n\n","category":"type"},{"location":"stdlib/LinearAlgebra/#LinearAlgebra.bunchkaufman","page":"Linear Algebra","title":"LinearAlgebra.bunchkaufman","text":"bunchkaufman(A, rook::Bool=false; check = true) -> S::BunchKaufman\n\nCompute the Bunch-Kaufman [Bunch1977] factorization of a symmetric or Hermitian matrix A as P'*U*D*U'*P or P'*L*D*L'*P, depending on which triangle is stored in A, and return a BunchKaufman object. Note that if A is complex symmetric then U' and L' denote the unconjugated transposes, i.e. transpose(U) and transpose(L).\n\nIterating the decomposition produces the components S.D, S.U or S.L as appropriate given S.uplo, and S.p.\n\nIf rook is true, rook pivoting is used. If rook is false, rook pivoting is not used.\n\nWhen check = true, an error is thrown if the decomposition fails. When check = false, responsibility for checking the decomposition's validity (via issuccess) lies with the user.\n\nThe following functions are available for BunchKaufman objects: size, \\, inv, issymmetric, ishermitian, getindex.\n\n[Bunch1977]: J R Bunch and L Kaufman, Some stable methods for calculating inertia and solving symmetric linear systems, Mathematics of Computation 31:137 (1977), 163-179. url.\n\nExamples\n\njulia> A = [1 2; 2 3]\n2×2 Matrix{Int64}:\n 1 2\n 2 3\n\njulia> S = bunchkaufman(A) # A gets wrapped internally by Symmetric(A)\nBunchKaufman{Float64, Matrix{Float64}, Vector{Int64}}\nD factor:\n2×2 Tridiagonal{Float64, Vector{Float64}}:\n -0.333333 0.0\n 0.0 3.0\nU factor:\n2×2 UnitUpperTriangular{Float64, Matrix{Float64}}:\n 1.0 0.666667\n ⋅ 1.0\npermutation:\n2-element Vector{Int64}:\n 1\n 2\n\njulia> d, u, p = S; # destructuring via iteration\n\njulia> d == S.D && u == S.U && p == S.p\ntrue\n\njulia> S.U*S.D*S.U' - S.P*A*S.P'\n2×2 Matrix{Float64}:\n 0.0 0.0\n 0.0 0.0\n\njulia> S = bunchkaufman(Symmetric(A, :L))\nBunchKaufman{Float64, Matrix{Float64}, Vector{Int64}}\nD factor:\n2×2 Tridiagonal{Float64, Vector{Float64}}:\n 3.0 0.0\n 0.0 -0.333333\nL factor:\n2×2 UnitLowerTriangular{Float64, Matrix{Float64}}:\n 1.0 ⋅\n 0.666667 1.0\npermutation:\n2-element Vector{Int64}:\n 2\n 1\n\njulia> S.L*S.D*S.L' - A[S.p, S.p]\n2×2 Matrix{Float64}:\n 0.0 0.0\n 0.0 0.0\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LinearAlgebra/#LinearAlgebra.bunchkaufman!","page":"Linear Algebra","title":"LinearAlgebra.bunchkaufman!","text":"bunchkaufman!(A, rook::Bool=false; check = true) -> BunchKaufman\n\nbunchkaufman! is the same as bunchkaufman, but saves space by overwriting the input A, instead of creating a copy.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LinearAlgebra/#LinearAlgebra.Eigen","page":"Linear Algebra","title":"LinearAlgebra.Eigen","text":"Eigen <: Factorization\n\nMatrix factorization type of the eigenvalue/spectral decomposition of a square matrix A. This is the return type of eigen, the corresponding matrix factorization function.\n\nIf F::Eigen is the factorization object, the eigenvalues can be obtained via F.values and the eigenvectors as the columns of the matrix F.vectors. (The kth eigenvector can be obtained from the slice F.vectors[:, k].)\n\nIterating the decomposition produces the components F.values and F.vectors.\n\nExamples\n\njulia> F = eigen([1.0 0.0 0.0; 0.0 3.0 0.0; 0.0 0.0 18.0])\nEigen{Float64, Float64, Matrix{Float64}, Vector{Float64}}\nvalues:\n3-element Vector{Float64}:\n 1.0\n 3.0\n 18.0\nvectors:\n3×3 Matrix{Float64}:\n 1.0 0.0 0.0\n 0.0 1.0 0.0\n 0.0 0.0 1.0\n\njulia> F.values\n3-element Vector{Float64}:\n 1.0\n 3.0\n 18.0\n\njulia> F.vectors\n3×3 Matrix{Float64}:\n 1.0 0.0 0.0\n 0.0 1.0 0.0\n 0.0 0.0 1.0\n\njulia> vals, vecs = F; # destructuring via iteration\n\njulia> vals == F.values && vecs == F.vectors\ntrue\n\n\n\n\n\n","category":"type"},{"location":"stdlib/LinearAlgebra/#LinearAlgebra.GeneralizedEigen","page":"Linear Algebra","title":"LinearAlgebra.GeneralizedEigen","text":"GeneralizedEigen <: Factorization\n\nMatrix factorization type of the generalized eigenvalue/spectral decomposition of A and B. This is the return type of eigen, the corresponding matrix factorization function, when called with two matrix arguments.\n\nIf F::GeneralizedEigen is the factorization object, the eigenvalues can be obtained via F.values and the eigenvectors as the columns of the matrix F.vectors. (The kth eigenvector can be obtained from the slice F.vectors[:, k].)\n\nIterating the decomposition produces the components F.values and F.vectors.\n\nExamples\n\njulia> A = [1 0; 0 -1]\n2×2 Matrix{Int64}:\n 1 0\n 0 -1\n\njulia> B = [0 1; 1 0]\n2×2 Matrix{Int64}:\n 0 1\n 1 0\n\njulia> F = eigen(A, B)\nGeneralizedEigen{ComplexF64, ComplexF64, Matrix{ComplexF64}, Vector{ComplexF64}}\nvalues:\n2-element Vector{ComplexF64}:\n 0.0 - 1.0im\n 0.0 + 1.0im\nvectors:\n2×2 Matrix{ComplexF64}:\n 0.0+1.0im 0.0-1.0im\n -1.0+0.0im -1.0-0.0im\n\njulia> F.values\n2-element Vector{ComplexF64}:\n 0.0 - 1.0im\n 0.0 + 1.0im\n\njulia> F.vectors\n2×2 Matrix{ComplexF64}:\n 0.0+1.0im 0.0-1.0im\n -1.0+0.0im -1.0-0.0im\n\njulia> vals, vecs = F; # destructuring via iteration\n\njulia> vals == F.values && vecs == F.vectors\ntrue\n\n\n\n\n\n","category":"type"},{"location":"stdlib/LinearAlgebra/#LinearAlgebra.eigvals","page":"Linear Algebra","title":"LinearAlgebra.eigvals","text":"eigvals(A; permute::Bool=true, scale::Bool=true, sortby) -> values\n\nReturn the eigenvalues of A.\n\nFor general non-symmetric matrices it is possible to specify how the matrix is balanced before the eigenvalue calculation. The permute, scale, and sortby keywords are the same as for eigen.\n\nExamples\n\njulia> diag_matrix = [1 0; 0 4]\n2×2 Matrix{Int64}:\n 1 0\n 0 4\n\njulia> eigvals(diag_matrix)\n2-element Vector{Float64}:\n 1.0\n 4.0\n\n\n\n\n\nFor a scalar input, eigvals will return a scalar.\n\nExample\n\njulia> eigvals(-2)\n-2\n\n\n\n\n\neigvals(A, B) -> values\n\nCompute the generalized eigenvalues of A and B.\n\nExamples\n\njulia> A = [1 0; 0 -1]\n2×2 Matrix{Int64}:\n 1 0\n 0 -1\n\njulia> B = [0 1; 1 0]\n2×2 Matrix{Int64}:\n 0 1\n 1 0\n\njulia> eigvals(A,B)\n2-element Vector{ComplexF64}:\n 0.0 - 1.0im\n 0.0 + 1.0im\n\n\n\n\n\neigvals(A::Union{SymTridiagonal, Hermitian, Symmetric}, irange::UnitRange) -> values\n\nReturn the eigenvalues of A. It is possible to calculate only a subset of the eigenvalues by specifying a UnitRange irange covering indices of the sorted eigenvalues, e.g. the 2nd to 8th eigenvalues.\n\nExamples\n\njulia> A = SymTridiagonal([1.; 2.; 1.], [2.; 3.])\n3×3 SymTridiagonal{Float64, Vector{Float64}}:\n 1.0 2.0 ⋅\n 2.0 2.0 3.0\n ⋅ 3.0 1.0\n\njulia> eigvals(A, 2:2)\n1-element Vector{Float64}:\n 0.9999999999999996\n\njulia> eigvals(A)\n3-element Vector{Float64}:\n -2.1400549446402604\n 1.0000000000000002\n 5.140054944640259\n\n\n\n\n\neigvals(A::Union{SymTridiagonal, Hermitian, Symmetric}, vl::Real, vu::Real) -> values\n\nReturn the eigenvalues of A. It is possible to calculate only a subset of the eigenvalues by specifying a pair vl and vu for the lower and upper boundaries of the eigenvalues.\n\nExamples\n\njulia> A = SymTridiagonal([1.; 2.; 1.], [2.; 3.])\n3×3 SymTridiagonal{Float64, Vector{Float64}}:\n 1.0 2.0 ⋅\n 2.0 2.0 3.0\n ⋅ 3.0 1.0\n\njulia> eigvals(A, -1, 2)\n1-element Vector{Float64}:\n 1.0000000000000009\n\njulia> eigvals(A)\n3-element Vector{Float64}:\n -2.1400549446402604\n 1.0000000000000002\n 5.140054944640259\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LinearAlgebra/#LinearAlgebra.eigvals!","page":"Linear Algebra","title":"LinearAlgebra.eigvals!","text":"eigvals!(A; permute::Bool=true, scale::Bool=true, sortby) -> values\n\nSame as eigvals, but saves space by overwriting the input A, instead of creating a copy. The permute, scale, and sortby keywords are the same as for eigen.\n\nnote: Note\nThe input matrix A will not contain its eigenvalues after eigvals! is called on it - A is used as a workspace.\n\nExamples\n\njulia> A = [1. 2.; 3. 4.]\n2×2 Matrix{Float64}:\n 1.0 2.0\n 3.0 4.0\n\njulia> eigvals!(A)\n2-element Vector{Float64}:\n -0.3722813232690143\n 5.372281323269014\n\njulia> A\n2×2 Matrix{Float64}:\n -0.372281 -1.0\n 0.0 5.37228\n\n\n\n\n\neigvals!(A, B; sortby) -> values\n\nSame as eigvals, but saves space by overwriting the input A (and B), instead of creating copies.\n\nnote: Note\nThe input matrices A and B will not contain their eigenvalues after eigvals! is called. They are used as workspaces.\n\nExamples\n\njulia> A = [1. 0.; 0. -1.]\n2×2 Matrix{Float64}:\n 1.0 0.0\n 0.0 -1.0\n\njulia> B = [0. 1.; 1. 0.]\n2×2 Matrix{Float64}:\n 0.0 1.0\n 1.0 0.0\n\njulia> eigvals!(A, B)\n2-element Vector{ComplexF64}:\n 0.0 - 1.0im\n 0.0 + 1.0im\n\njulia> A\n2×2 Matrix{Float64}:\n -0.0 -1.0\n 1.0 -0.0\n\njulia> B\n2×2 Matrix{Float64}:\n 1.0 0.0\n 0.0 1.0\n\n\n\n\n\neigvals!(A::Union{SymTridiagonal, Hermitian, Symmetric}, irange::UnitRange) -> values\n\nSame as eigvals, but saves space by overwriting the input A, instead of creating a copy. irange is a range of eigenvalue indices to search for - for instance, the 2nd to 8th eigenvalues.\n\n\n\n\n\neigvals!(A::Union{SymTridiagonal, Hermitian, Symmetric}, vl::Real, vu::Real) -> values\n\nSame as eigvals, but saves space by overwriting the input A, instead of creating a copy. vl is the lower bound of the interval to search for eigenvalues, and vu is the upper bound.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LinearAlgebra/#LinearAlgebra.eigmax","page":"Linear Algebra","title":"LinearAlgebra.eigmax","text":"eigmax(A; permute::Bool=true, scale::Bool=true)\n\nReturn the largest eigenvalue of A. The option permute=true permutes the matrix to become closer to upper triangular, and scale=true scales the matrix by its diagonal elements to make rows and columns more equal in norm. Note that if the eigenvalues of A are complex, this method will fail, since complex numbers cannot be sorted.\n\nExamples\n\njulia> A = [0 im; -im 0]\n2×2 Matrix{Complex{Int64}}:\n 0+0im 0+1im\n 0-1im 0+0im\n\njulia> eigmax(A)\n1.0\n\njulia> A = [0 im; -1 0]\n2×2 Matrix{Complex{Int64}}:\n 0+0im 0+1im\n -1+0im 0+0im\n\njulia> eigmax(A)\nERROR: DomainError with Complex{Int64}[0+0im 0+1im; -1+0im 0+0im]:\n`A` cannot have complex eigenvalues.\nStacktrace:\n[...]\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LinearAlgebra/#LinearAlgebra.eigmin","page":"Linear Algebra","title":"LinearAlgebra.eigmin","text":"eigmin(A; permute::Bool=true, scale::Bool=true)\n\nReturn the smallest eigenvalue of A. The option permute=true permutes the matrix to become closer to upper triangular, and scale=true scales the matrix by its diagonal elements to make rows and columns more equal in norm. Note that if the eigenvalues of A are complex, this method will fail, since complex numbers cannot be sorted.\n\nExamples\n\njulia> A = [0 im; -im 0]\n2×2 Matrix{Complex{Int64}}:\n 0+0im 0+1im\n 0-1im 0+0im\n\njulia> eigmin(A)\n-1.0\n\njulia> A = [0 im; -1 0]\n2×2 Matrix{Complex{Int64}}:\n 0+0im 0+1im\n -1+0im 0+0im\n\njulia> eigmin(A)\nERROR: DomainError with Complex{Int64}[0+0im 0+1im; -1+0im 0+0im]:\n`A` cannot have complex eigenvalues.\nStacktrace:\n[...]\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LinearAlgebra/#LinearAlgebra.eigvecs","page":"Linear Algebra","title":"LinearAlgebra.eigvecs","text":"eigvecs(A::SymTridiagonal[, eigvals]) -> Matrix\n\nReturn a matrix M whose columns are the eigenvectors of A. (The kth eigenvector can be obtained from the slice M[:, k].)\n\nIf the optional vector of eigenvalues eigvals is specified, eigvecs returns the specific corresponding eigenvectors.\n\nExamples\n\njulia> A = SymTridiagonal([1.; 2.; 1.], [2.; 3.])\n3×3 SymTridiagonal{Float64, Vector{Float64}}:\n 1.0 2.0 ⋅\n 2.0 2.0 3.0\n ⋅ 3.0 1.0\n\njulia> eigvals(A)\n3-element Vector{Float64}:\n -2.1400549446402604\n 1.0000000000000002\n 5.140054944640259\n\njulia> eigvecs(A)\n3×3 Matrix{Float64}:\n 0.418304 -0.83205 0.364299\n -0.656749 -7.39009e-16 0.754109\n 0.627457 0.5547 0.546448\n\njulia> eigvecs(A, [1.])\n3×1 Matrix{Float64}:\n 0.8320502943378438\n 4.263514128092366e-17\n -0.5547001962252291\n\n\n\n\n\neigvecs(A; permute::Bool=true, scale::Bool=true, `sortby`) -> Matrix\n\nReturn a matrix M whose columns are the eigenvectors of A. (The kth eigenvector can be obtained from the slice M[:, k].) The permute, scale, and sortby keywords are the same as for eigen.\n\nExamples\n\njulia> eigvecs([1.0 0.0 0.0; 0.0 3.0 0.0; 0.0 0.0 18.0])\n3×3 Matrix{Float64}:\n 1.0 0.0 0.0\n 0.0 1.0 0.0\n 0.0 0.0 1.0\n\n\n\n\n\neigvecs(A, B) -> Matrix\n\nReturn a matrix M whose columns are the generalized eigenvectors of A and B. (The kth eigenvector can be obtained from the slice M[:, k].)\n\nExamples\n\njulia> A = [1 0; 0 -1]\n2×2 Matrix{Int64}:\n 1 0\n 0 -1\n\njulia> B = [0 1; 1 0]\n2×2 Matrix{Int64}:\n 0 1\n 1 0\n\njulia> eigvecs(A, B)\n2×2 Matrix{ComplexF64}:\n 0.0+1.0im 0.0-1.0im\n -1.0+0.0im -1.0-0.0im\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LinearAlgebra/#LinearAlgebra.eigen","page":"Linear Algebra","title":"LinearAlgebra.eigen","text":"eigen(A; permute::Bool=true, scale::Bool=true, sortby) -> Eigen\n\nCompute the eigenvalue decomposition of A, returning an Eigen factorization object F which contains the eigenvalues in F.values and the eigenvectors in the columns of the matrix F.vectors. (The kth eigenvector can be obtained from the slice F.vectors[:, k].)\n\nIterating the decomposition produces the components F.values and F.vectors.\n\nThe following functions are available for Eigen objects: inv, det, and isposdef.\n\nFor general nonsymmetric matrices it is possible to specify how the matrix is balanced before the eigenvector calculation. The option permute=true permutes the matrix to become closer to upper triangular, and scale=true scales the matrix by its diagonal elements to make rows and columns more equal in norm. The default is true for both options.\n\nBy default, the eigenvalues and vectors are sorted lexicographically by (real(λ),imag(λ)). A different comparison function by(λ) can be passed to sortby, or you can pass sortby=nothing to leave the eigenvalues in an arbitrary order. Some special matrix types (e.g. Diagonal or SymTridiagonal) may implement their own sorting convention and not accept a sortby keyword.\n\nExamples\n\njulia> F = eigen([1.0 0.0 0.0; 0.0 3.0 0.0; 0.0 0.0 18.0])\nEigen{Float64, Float64, Matrix{Float64}, Vector{Float64}}\nvalues:\n3-element Vector{Float64}:\n 1.0\n 3.0\n 18.0\nvectors:\n3×3 Matrix{Float64}:\n 1.0 0.0 0.0\n 0.0 1.0 0.0\n 0.0 0.0 1.0\n\njulia> F.values\n3-element Vector{Float64}:\n 1.0\n 3.0\n 18.0\n\njulia> F.vectors\n3×3 Matrix{Float64}:\n 1.0 0.0 0.0\n 0.0 1.0 0.0\n 0.0 0.0 1.0\n\njulia> vals, vecs = F; # destructuring via iteration\n\njulia> vals == F.values && vecs == F.vectors\ntrue\n\n\n\n\n\neigen(A, B; sortby) -> GeneralizedEigen\n\nCompute the generalized eigenvalue decomposition of A and B, returning a GeneralizedEigen factorization object F which contains the generalized eigenvalues in F.values and the generalized eigenvectors in the columns of the matrix F.vectors. (The kth generalized eigenvector can be obtained from the slice F.vectors[:, k].)\n\nIterating the decomposition produces the components F.values and F.vectors.\n\nBy default, the eigenvalues and vectors are sorted lexicographically by (real(λ),imag(λ)). A different comparison function by(λ) can be passed to sortby, or you can pass sortby=nothing to leave the eigenvalues in an arbitrary order.\n\nExamples\n\njulia> A = [1 0; 0 -1]\n2×2 Matrix{Int64}:\n 1 0\n 0 -1\n\njulia> B = [0 1; 1 0]\n2×2 Matrix{Int64}:\n 0 1\n 1 0\n\njulia> F = eigen(A, B);\n\njulia> F.values\n2-element Vector{ComplexF64}:\n 0.0 - 1.0im\n 0.0 + 1.0im\n\njulia> F.vectors\n2×2 Matrix{ComplexF64}:\n 0.0+1.0im 0.0-1.0im\n -1.0+0.0im -1.0-0.0im\n\njulia> vals, vecs = F; # destructuring via iteration\n\njulia> vals == F.values && vecs == F.vectors\ntrue\n\n\n\n\n\neigen(A::Union{SymTridiagonal, Hermitian, Symmetric}, irange::UnitRange) -> Eigen\n\nCompute the eigenvalue decomposition of A, returning an Eigen factorization object F which contains the eigenvalues in F.values and the eigenvectors in the columns of the matrix F.vectors. (The kth eigenvector can be obtained from the slice F.vectors[:, k].)\n\nIterating the decomposition produces the components F.values and F.vectors.\n\nThe following functions are available for Eigen objects: inv, det, and isposdef.\n\nThe UnitRange irange specifies indices of the sorted eigenvalues to search for.\n\nnote: Note\nIf irange is not 1:n, where n is the dimension of A, then the returned factorization will be a truncated factorization.\n\n\n\n\n\neigen(A::Union{SymTridiagonal, Hermitian, Symmetric}, vl::Real, vu::Real) -> Eigen\n\nCompute the eigenvalue decomposition of A, returning an Eigen factorization object F which contains the eigenvalues in F.values and the eigenvectors in the columns of the matrix F.vectors. (The kth eigenvector can be obtained from the slice F.vectors[:, k].)\n\nIterating the decomposition produces the components F.values and F.vectors.\n\nThe following functions are available for Eigen objects: inv, det, and isposdef.\n\nvl is the lower bound of the window of eigenvalues to search for, and vu is the upper bound.\n\nnote: Note\nIf [vl, vu] does not contain all eigenvalues of A, then the returned factorization will be a truncated factorization.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LinearAlgebra/#LinearAlgebra.eigen!","page":"Linear Algebra","title":"LinearAlgebra.eigen!","text":"eigen!(A; permute, scale, sortby)\neigen!(A, B; sortby)\n\nSame as eigen, but saves space by overwriting the input A (and B), instead of creating a copy.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LinearAlgebra/#LinearAlgebra.Hessenberg","page":"Linear Algebra","title":"LinearAlgebra.Hessenberg","text":"Hessenberg <: Factorization\n\nA Hessenberg object represents the Hessenberg factorization QHQ' of a square matrix, or a shift Q(H+μI)Q' thereof, which is produced by the hessenberg function.\n\n\n\n\n\n","category":"type"},{"location":"stdlib/LinearAlgebra/#LinearAlgebra.hessenberg","page":"Linear Algebra","title":"LinearAlgebra.hessenberg","text":"hessenberg(A) -> Hessenberg\n\nCompute the Hessenberg decomposition of A and return a Hessenberg object. If F is the factorization object, the unitary matrix can be accessed with F.Q (of type LinearAlgebra.HessenbergQ) and the Hessenberg matrix with F.H (of type UpperHessenberg), either of which may be converted to a regular matrix with Matrix(F.H) or Matrix(F.Q).\n\nIf A is Hermitian or real-Symmetric, then the Hessenberg decomposition produces a real-symmetric tridiagonal matrix and F.H is of type SymTridiagonal.\n\nNote that the shifted factorization A+μI = Q (H+μI) Q' can be constructed efficiently by F + μ*I using the UniformScaling object I, which creates a new Hessenberg object with shared storage and a modified shift. The shift of a given F is obtained by F.μ. This is useful because multiple shifted solves (F + μ*I) \\ b (for different μ and/or b) can be performed efficiently once F is created.\n\nIterating the decomposition produces the factors F.Q, F.H, F.μ.\n\nExamples\n\njulia> A = [4. 9. 7.; 4. 4. 1.; 4. 3. 2.]\n3×3 Matrix{Float64}:\n 4.0 9.0 7.0\n 4.0 4.0 1.0\n 4.0 3.0 2.0\n\njulia> F = hessenberg(A)\nHessenberg{Float64, UpperHessenberg{Float64, Matrix{Float64}}, Matrix{Float64}, Vector{Float64}, Bool}\nQ factor:\n3×3 LinearAlgebra.HessenbergQ{Float64, Matrix{Float64}, Vector{Float64}, false}:\n 1.0 0.0 0.0\n 0.0 -0.707107 -0.707107\n 0.0 -0.707107 0.707107\nH factor:\n3×3 UpperHessenberg{Float64, Matrix{Float64}}:\n 4.0 -11.3137 -1.41421\n -5.65685 5.0 2.0\n ⋅ -8.88178e-16 1.0\n\njulia> F.Q * F.H * F.Q'\n3×3 Matrix{Float64}:\n 4.0 9.0 7.0\n 4.0 4.0 1.0\n 4.0 3.0 2.0\n\njulia> q, h = F; # destructuring via iteration\n\njulia> q == F.Q && h == F.H\ntrue\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LinearAlgebra/#LinearAlgebra.hessenberg!","page":"Linear Algebra","title":"LinearAlgebra.hessenberg!","text":"hessenberg!(A) -> Hessenberg\n\nhessenberg! is the same as hessenberg, but saves space by overwriting the input A, instead of creating a copy.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LinearAlgebra/#LinearAlgebra.Schur","page":"Linear Algebra","title":"LinearAlgebra.Schur","text":"Schur <: Factorization\n\nMatrix factorization type of the Schur factorization of a matrix A. This is the return type of schur(_), the corresponding matrix factorization function.\n\nIf F::Schur is the factorization object, the (quasi) triangular Schur factor can be obtained via either F.Schur or F.T and the orthogonal/unitary Schur vectors via F.vectors or F.Z such that A = F.vectors * F.Schur * F.vectors'. The eigenvalues of A can be obtained with F.values.\n\nIterating the decomposition produces the components F.T, F.Z, and F.values.\n\nExamples\n\njulia> A = [5. 7.; -2. -4.]\n2×2 Matrix{Float64}:\n 5.0 7.0\n -2.0 -4.0\n\njulia> F = schur(A)\nSchur{Float64, Matrix{Float64}, Vector{Float64}}\nT factor:\n2×2 Matrix{Float64}:\n 3.0 9.0\n 0.0 -2.0\nZ factor:\n2×2 Matrix{Float64}:\n 0.961524 0.274721\n -0.274721 0.961524\neigenvalues:\n2-element Vector{Float64}:\n 3.0\n -2.0\n\njulia> F.vectors * F.Schur * F.vectors'\n2×2 Matrix{Float64}:\n 5.0 7.0\n -2.0 -4.0\n\njulia> t, z, vals = F; # destructuring via iteration\n\njulia> t == F.T && z == F.Z && vals == F.values\ntrue\n\n\n\n\n\n","category":"type"},{"location":"stdlib/LinearAlgebra/#LinearAlgebra.GeneralizedSchur","page":"Linear Algebra","title":"LinearAlgebra.GeneralizedSchur","text":"GeneralizedSchur <: Factorization\n\nMatrix factorization type of the generalized Schur factorization of two matrices A and B. This is the return type of schur(_, _), the corresponding matrix factorization function.\n\nIf F::GeneralizedSchur is the factorization object, the (quasi) triangular Schur factors can be obtained via F.S and F.T, the left unitary/orthogonal Schur vectors via F.left or F.Q, and the right unitary/orthogonal Schur vectors can be obtained with F.right or F.Z such that A=F.left*F.S*F.right' and B=F.left*F.T*F.right'. The generalized eigenvalues of A and B can be obtained with F.α./F.β.\n\nIterating the decomposition produces the components F.S, F.T, F.Q, F.Z, F.α, and F.β.\n\n\n\n\n\n","category":"type"},{"location":"stdlib/LinearAlgebra/#LinearAlgebra.schur","page":"Linear Algebra","title":"LinearAlgebra.schur","text":"schur(A) -> F::Schur\n\nComputes the Schur factorization of the matrix A. The (quasi) triangular Schur factor can be obtained from the Schur object F with either F.Schur or F.T and the orthogonal/unitary Schur vectors can be obtained with F.vectors or F.Z such that A = F.vectors * F.Schur * F.vectors'. The eigenvalues of A can be obtained with F.values.\n\nFor real A, the Schur factorization is \"quasitriangular\", which means that it is upper-triangular except with 2×2 diagonal blocks for any conjugate pair of complex eigenvalues; this allows the factorization to be purely real even when there are complex eigenvalues. To obtain the (complex) purely upper-triangular Schur factorization from a real quasitriangular factorization, you can use Schur{Complex}(schur(A)).\n\nIterating the decomposition produces the components F.T, F.Z, and F.values.\n\nExamples\n\njulia> A = [5. 7.; -2. -4.]\n2×2 Matrix{Float64}:\n 5.0 7.0\n -2.0 -4.0\n\njulia> F = schur(A)\nSchur{Float64, Matrix{Float64}, Vector{Float64}}\nT factor:\n2×2 Matrix{Float64}:\n 3.0 9.0\n 0.0 -2.0\nZ factor:\n2×2 Matrix{Float64}:\n 0.961524 0.274721\n -0.274721 0.961524\neigenvalues:\n2-element Vector{Float64}:\n 3.0\n -2.0\n\njulia> F.vectors * F.Schur * F.vectors'\n2×2 Matrix{Float64}:\n 5.0 7.0\n -2.0 -4.0\n\njulia> t, z, vals = F; # destructuring via iteration\n\njulia> t == F.T && z == F.Z && vals == F.values\ntrue\n\n\n\n\n\nschur(A, B) -> F::GeneralizedSchur\n\nComputes the Generalized Schur (or QZ) factorization of the matrices A and B. The (quasi) triangular Schur factors can be obtained from the Schur object F with F.S and F.T, the left unitary/orthogonal Schur vectors can be obtained with F.left or F.Q and the right unitary/orthogonal Schur vectors can be obtained with F.right or F.Z such that A=F.left*F.S*F.right' and B=F.left*F.T*F.right'. The generalized eigenvalues of A and B can be obtained with F.α./F.β.\n\nIterating the decomposition produces the components F.S, F.T, F.Q, F.Z, F.α, and F.β.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LinearAlgebra/#LinearAlgebra.schur!","page":"Linear Algebra","title":"LinearAlgebra.schur!","text":"schur!(A::StridedMatrix) -> F::Schur\n\nSame as schur but uses the input argument A as workspace.\n\nExamples\n\njulia> A = [5. 7.; -2. -4.]\n2×2 Matrix{Float64}:\n 5.0 7.0\n -2.0 -4.0\n\njulia> F = schur!(A)\nSchur{Float64, Matrix{Float64}, Vector{Float64}}\nT factor:\n2×2 Matrix{Float64}:\n 3.0 9.0\n 0.0 -2.0\nZ factor:\n2×2 Matrix{Float64}:\n 0.961524 0.274721\n -0.274721 0.961524\neigenvalues:\n2-element Vector{Float64}:\n 3.0\n -2.0\n\njulia> A\n2×2 Matrix{Float64}:\n 3.0 9.0\n 0.0 -2.0\n\n\n\n\n\nschur!(A::StridedMatrix, B::StridedMatrix) -> F::GeneralizedSchur\n\nSame as schur but uses the input matrices A and B as workspace.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LinearAlgebra/#LinearAlgebra.ordschur","page":"Linear Algebra","title":"LinearAlgebra.ordschur","text":"ordschur(F::Schur, select::Union{Vector{Bool},BitVector}) -> F::Schur\n\nReorders the Schur factorization F of a matrix A = Z*T*Z' according to the logical array select returning the reordered factorization F object. The selected eigenvalues appear in the leading diagonal of F.Schur and the corresponding leading columns of F.vectors form an orthogonal/unitary basis of the corresponding right invariant subspace. In the real case, a complex conjugate pair of eigenvalues must be either both included or both excluded via select.\n\n\n\n\n\nordschur(F::GeneralizedSchur, select::Union{Vector{Bool},BitVector}) -> F::GeneralizedSchur\n\nReorders the Generalized Schur factorization F of a matrix pair (A, B) = (Q*S*Z', Q*T*Z') according to the logical array select and returns a GeneralizedSchur object F. The selected eigenvalues appear in the leading diagonal of both F.S and F.T, and the left and right orthogonal/unitary Schur vectors are also reordered such that (A, B) = F.Q*(F.S, F.T)*F.Z' still holds and the generalized eigenvalues of A and B can still be obtained with F.α./F.β.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LinearAlgebra/#LinearAlgebra.ordschur!","page":"Linear Algebra","title":"LinearAlgebra.ordschur!","text":"ordschur!(F::Schur, select::Union{Vector{Bool},BitVector}) -> F::Schur\n\nSame as ordschur but overwrites the factorization F.\n\n\n\n\n\nordschur!(F::GeneralizedSchur, select::Union{Vector{Bool},BitVector}) -> F::GeneralizedSchur\n\nSame as ordschur but overwrites the factorization F.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LinearAlgebra/#LinearAlgebra.SVD","page":"Linear Algebra","title":"LinearAlgebra.SVD","text":"SVD <: Factorization\n\nMatrix factorization type of the singular value decomposition (SVD) of a matrix A. This is the return type of svd(_), the corresponding matrix factorization function.\n\nIf F::SVD is the factorization object, U, S, V and Vt can be obtained via F.U, F.S, F.V and F.Vt, such that A = U * Diagonal(S) * Vt. The singular values in S are sorted in descending order.\n\nIterating the decomposition produces the components U, S, and V.\n\nExamples\n\njulia> A = [1. 0. 0. 0. 2.; 0. 0. 3. 0. 0.; 0. 0. 0. 0. 0.; 0. 2. 0. 0. 0.]\n4×5 Matrix{Float64}:\n 1.0 0.0 0.0 0.0 2.0\n 0.0 0.0 3.0 0.0 0.0\n 0.0 0.0 0.0 0.0 0.0\n 0.0 2.0 0.0 0.0 0.0\n\njulia> F = svd(A)\nSVD{Float64, Float64, Matrix{Float64}, Vector{Float64}}\nU factor:\n4×4 Matrix{Float64}:\n 0.0 1.0 0.0 0.0\n 1.0 0.0 0.0 0.0\n 0.0 0.0 0.0 -1.0\n 0.0 0.0 1.0 0.0\nsingular values:\n4-element Vector{Float64}:\n 3.0\n 2.23606797749979\n 2.0\n 0.0\nVt factor:\n4×5 Matrix{Float64}:\n -0.0 0.0 1.0 -0.0 0.0\n 0.447214 0.0 0.0 0.0 0.894427\n -0.0 1.0 0.0 -0.0 0.0\n 0.0 0.0 0.0 1.0 0.0\n\njulia> F.U * Diagonal(F.S) * F.Vt\n4×5 Matrix{Float64}:\n 1.0 0.0 0.0 0.0 2.0\n 0.0 0.0 3.0 0.0 0.0\n 0.0 0.0 0.0 0.0 0.0\n 0.0 2.0 0.0 0.0 0.0\n\njulia> u, s, v = F; # destructuring via iteration\n\njulia> u == F.U && s == F.S && v == F.V\ntrue\n\n\n\n\n\n","category":"type"},{"location":"stdlib/LinearAlgebra/#LinearAlgebra.GeneralizedSVD","page":"Linear Algebra","title":"LinearAlgebra.GeneralizedSVD","text":"GeneralizedSVD <: Factorization\n\nMatrix factorization type of the generalized singular value decomposition (SVD) of two matrices A and B, such that A = F.U*F.D1*F.R0*F.Q' and B = F.V*F.D2*F.R0*F.Q'. This is the return type of svd(_, _), the corresponding matrix factorization function.\n\nFor an M-by-N matrix A and P-by-N matrix B,\n\nU is a M-by-M orthogonal matrix,\nV is a P-by-P orthogonal matrix,\nQ is a N-by-N orthogonal matrix,\nD1 is a M-by-(K+L) diagonal matrix with 1s in the first K entries,\nD2 is a P-by-(K+L) matrix whose top right L-by-L block is diagonal,\nR0 is a (K+L)-by-N matrix whose rightmost (K+L)-by-(K+L) block is nonsingular upper block triangular,\n\nK+L is the effective numerical rank of the matrix [A; B].\n\nIterating the decomposition produces the components U, V, Q, D1, D2, and R0.\n\nThe entries of F.D1 and F.D2 are related, as explained in the LAPACK documentation for the generalized SVD and the xGGSVD3 routine which is called underneath (in LAPACK 3.6.0 and newer).\n\nExamples\n\njulia> A = [1. 0.; 0. -1.]\n2×2 Matrix{Float64}:\n 1.0 0.0\n 0.0 -1.0\n\njulia> B = [0. 1.; 1. 0.]\n2×2 Matrix{Float64}:\n 0.0 1.0\n 1.0 0.0\n\njulia> F = svd(A, B)\nGeneralizedSVD{Float64, Matrix{Float64}, Float64, Vector{Float64}}\nU factor:\n2×2 Matrix{Float64}:\n 1.0 0.0\n 0.0 1.0\nV factor:\n2×2 Matrix{Float64}:\n -0.0 -1.0\n 1.0 0.0\nQ factor:\n2×2 Matrix{Float64}:\n 1.0 0.0\n 0.0 1.0\nD1 factor:\n2×2 Matrix{Float64}:\n 0.707107 0.0\n 0.0 0.707107\nD2 factor:\n2×2 Matrix{Float64}:\n 0.707107 0.0\n 0.0 0.707107\nR0 factor:\n2×2 Matrix{Float64}:\n 1.41421 0.0\n 0.0 -1.41421\n\njulia> F.U*F.D1*F.R0*F.Q'\n2×2 Matrix{Float64}:\n 1.0 0.0\n 0.0 -1.0\n\njulia> F.V*F.D2*F.R0*F.Q'\n2×2 Matrix{Float64}:\n -0.0 1.0\n 1.0 0.0\n\n\n\n\n\n","category":"type"},{"location":"stdlib/LinearAlgebra/#LinearAlgebra.svd","page":"Linear Algebra","title":"LinearAlgebra.svd","text":"svd(A; full::Bool = false, alg::Algorithm = default_svd_alg(A)) -> SVD\n\nCompute the singular value decomposition (SVD) of A and return an SVD object.\n\nU, S, V and Vt can be obtained from the factorization F with F.U, F.S, F.V and F.Vt, such that A = U * Diagonal(S) * Vt. The algorithm produces Vt and hence Vt is more efficient to extract than V. The singular values in S are sorted in descending order.\n\nIterating the decomposition produces the components U, S, and V.\n\nIf full = false (default), a \"thin\" SVD is returned. For an M times N matrix A, in the full factorization U is M times M and V is N times N, while in the thin factorization U is M times K and V is N times K, where K = min(MN) is the number of singular values.\n\nIf alg = DivideAndConquer() a divide-and-conquer algorithm is used to calculate the SVD. Another (typically slower but more accurate) option is alg = QRIteration().\n\ncompat: Julia 1.3\nThe alg keyword argument requires Julia 1.3 or later.\n\nExamples\n\njulia> A = rand(4,3);\n\njulia> F = svd(A); # Store the Factorization Object\n\njulia> A ≈ F.U * Diagonal(F.S) * F.Vt\ntrue\n\njulia> U, S, V = F; # destructuring via iteration\n\njulia> A ≈ U * Diagonal(S) * V'\ntrue\n\njulia> Uonly, = svd(A); # Store U only\n\njulia> Uonly == U\ntrue\n\n\n\n\n\nsvd(A, B) -> GeneralizedSVD\n\nCompute the generalized SVD of A and B, returning a GeneralizedSVD factorization object F such that [A;B] = [F.U * F.D1; F.V * F.D2] * F.R0 * F.Q'\n\nU is a M-by-M orthogonal matrix,\nV is a P-by-P orthogonal matrix,\nQ is a N-by-N orthogonal matrix,\nD1 is a M-by-(K+L) diagonal matrix with 1s in the first K entries,\nD2 is a P-by-(K+L) matrix whose top right L-by-L block is diagonal,\nR0 is a (K+L)-by-N matrix whose rightmost (K+L)-by-(K+L) block is nonsingular upper block triangular,\n\nK+L is the effective numerical rank of the matrix [A; B].\n\nIterating the decomposition produces the components U, V, Q, D1, D2, and R0.\n\nThe generalized SVD is used in applications such as when one wants to compare how much belongs to A vs. how much belongs to B, as in human vs yeast genome, or signal vs noise, or between clusters vs within clusters. (See Edelman and Wang for discussion: https://arxiv.org/abs/1901.00485)\n\nIt decomposes [A; B] into [UC; VS]H, where [UC; VS] is a natural orthogonal basis for the column space of [A; B], and H = RQ' is a natural non-orthogonal basis for the rowspace of [A;B], where the top rows are most closely attributed to the A matrix, and the bottom to the B matrix. The multi-cosine/sine matrices C and S provide a multi-measure of how much A vs how much B, and U and V provide directions in which these are measured.\n\nExamples\n\njulia> A = randn(3,2); B=randn(4,2);\n\njulia> F = svd(A, B);\n\njulia> U,V,Q,C,S,R = F;\n\njulia> H = R*Q';\n\njulia> [A; B] ≈ [U*C; V*S]*H\ntrue\n\njulia> [A; B] ≈ [F.U*F.D1; F.V*F.D2]*F.R0*F.Q'\ntrue\n\njulia> Uonly, = svd(A,B);\n\njulia> U == Uonly\ntrue\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LinearAlgebra/#LinearAlgebra.svd!","page":"Linear Algebra","title":"LinearAlgebra.svd!","text":"svd!(A; full::Bool = false, alg::Algorithm = default_svd_alg(A)) -> SVD\n\nsvd! is the same as svd, but saves space by overwriting the input A, instead of creating a copy. See documentation of svd for details.\n\n\n\n\n\nsvd!(A, B) -> GeneralizedSVD\n\nsvd! is the same as svd, but modifies the arguments A and B in-place, instead of making copies. See documentation of svd for details.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LinearAlgebra/#LinearAlgebra.svdvals","page":"Linear Algebra","title":"LinearAlgebra.svdvals","text":"svdvals(A)\n\nReturn the singular values of A in descending order.\n\nExamples\n\njulia> A = [1. 0. 0. 0. 2.; 0. 0. 3. 0. 0.; 0. 0. 0. 0. 0.; 0. 2. 0. 0. 0.]\n4×5 Matrix{Float64}:\n 1.0 0.0 0.0 0.0 2.0\n 0.0 0.0 3.0 0.0 0.0\n 0.0 0.0 0.0 0.0 0.0\n 0.0 2.0 0.0 0.0 0.0\n\njulia> svdvals(A)\n4-element Vector{Float64}:\n 3.0\n 2.23606797749979\n 2.0\n 0.0\n\n\n\n\n\nsvdvals(A, B)\n\nReturn the generalized singular values from the generalized singular value decomposition of A and B. See also svd.\n\nExamples\n\njulia> A = [1. 0.; 0. -1.]\n2×2 Matrix{Float64}:\n 1.0 0.0\n 0.0 -1.0\n\njulia> B = [0. 1.; 1. 0.]\n2×2 Matrix{Float64}:\n 0.0 1.0\n 1.0 0.0\n\njulia> svdvals(A, B)\n2-element Vector{Float64}:\n 1.0\n 1.0\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LinearAlgebra/#LinearAlgebra.svdvals!","page":"Linear Algebra","title":"LinearAlgebra.svdvals!","text":"svdvals!(A)\n\nReturn the singular values of A, saving space by overwriting the input. See also svdvals and svd. ```\n\n\n\n\n\nsvdvals!(A, B)\n\nReturn the generalized singular values from the generalized singular value decomposition of A and B, saving space by overwriting A and B. See also svd and svdvals.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LinearAlgebra/#LinearAlgebra.Givens","page":"Linear Algebra","title":"LinearAlgebra.Givens","text":"LinearAlgebra.Givens(i1,i2,c,s) -> G\n\nA Givens rotation linear operator. The fields c and s represent the cosine and sine of the rotation angle, respectively. The Givens type supports left multiplication G*A and conjugated transpose right multiplication A*G'. The type doesn't have a size and can therefore be multiplied with matrices of arbitrary size as long as i2<=size(A,2) for G*A or i2<=size(A,1) for A*G'.\n\nSee also givens.\n\n\n\n\n\n","category":"type"},{"location":"stdlib/LinearAlgebra/#LinearAlgebra.givens","page":"Linear Algebra","title":"LinearAlgebra.givens","text":"givens(f::T, g::T, i1::Integer, i2::Integer) where {T} -> (G::Givens, r::T)\n\nComputes the Givens rotation G and scalar r such that for any vector x where\n\nx[i1] = f\nx[i2] = g\n\nthe result of the multiplication\n\ny = G*x\n\nhas the property that\n\ny[i1] = r\ny[i2] = 0\n\nSee also LinearAlgebra.Givens.\n\n\n\n\n\ngivens(A::AbstractArray, i1::Integer, i2::Integer, j::Integer) -> (G::Givens, r)\n\nComputes the Givens rotation G and scalar r such that the result of the multiplication\n\nB = G*A\n\nhas the property that\n\nB[i1,j] = r\nB[i2,j] = 0\n\nSee also LinearAlgebra.Givens.\n\n\n\n\n\ngivens(x::AbstractVector, i1::Integer, i2::Integer) -> (G::Givens, r)\n\nComputes the Givens rotation G and scalar r such that the result of the multiplication\n\nB = G*x\n\nhas the property that\n\nB[i1] = r\nB[i2] = 0\n\nSee also LinearAlgebra.Givens.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LinearAlgebra/#LinearAlgebra.triu","page":"Linear Algebra","title":"LinearAlgebra.triu","text":"triu(M)\n\nUpper triangle of a matrix.\n\nExamples\n\njulia> a = fill(1.0, (4,4))\n4×4 Matrix{Float64}:\n 1.0 1.0 1.0 1.0\n 1.0 1.0 1.0 1.0\n 1.0 1.0 1.0 1.0\n 1.0 1.0 1.0 1.0\n\njulia> triu(a)\n4×4 Matrix{Float64}:\n 1.0 1.0 1.0 1.0\n 0.0 1.0 1.0 1.0\n 0.0 0.0 1.0 1.0\n 0.0 0.0 0.0 1.0\n\n\n\n\n\ntriu(M, k::Integer)\n\nReturns the upper triangle of M starting from the kth superdiagonal.\n\nExamples\n\njulia> a = fill(1.0, (4,4))\n4×4 Matrix{Float64}:\n 1.0 1.0 1.0 1.0\n 1.0 1.0 1.0 1.0\n 1.0 1.0 1.0 1.0\n 1.0 1.0 1.0 1.0\n\njulia> triu(a,3)\n4×4 Matrix{Float64}:\n 0.0 0.0 0.0 1.0\n 0.0 0.0 0.0 0.0\n 0.0 0.0 0.0 0.0\n 0.0 0.0 0.0 0.0\n\njulia> triu(a,-3)\n4×4 Matrix{Float64}:\n 1.0 1.0 1.0 1.0\n 1.0 1.0 1.0 1.0\n 1.0 1.0 1.0 1.0\n 1.0 1.0 1.0 1.0\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LinearAlgebra/#LinearAlgebra.triu!","page":"Linear Algebra","title":"LinearAlgebra.triu!","text":"triu!(M)\n\nUpper triangle of a matrix, overwriting M in the process. See also triu.\n\n\n\n\n\ntriu!(M, k::Integer)\n\nReturn the upper triangle of M starting from the kth superdiagonal, overwriting M in the process.\n\nExamples\n\njulia> M = [1 2 3 4 5; 1 2 3 4 5; 1 2 3 4 5; 1 2 3 4 5; 1 2 3 4 5]\n5×5 Matrix{Int64}:\n 1 2 3 4 5\n 1 2 3 4 5\n 1 2 3 4 5\n 1 2 3 4 5\n 1 2 3 4 5\n\njulia> triu!(M, 1)\n5×5 Matrix{Int64}:\n 0 2 3 4 5\n 0 0 3 4 5\n 0 0 0 4 5\n 0 0 0 0 5\n 0 0 0 0 0\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LinearAlgebra/#LinearAlgebra.tril","page":"Linear Algebra","title":"LinearAlgebra.tril","text":"tril(M)\n\nLower triangle of a matrix.\n\nExamples\n\njulia> a = fill(1.0, (4,4))\n4×4 Matrix{Float64}:\n 1.0 1.0 1.0 1.0\n 1.0 1.0 1.0 1.0\n 1.0 1.0 1.0 1.0\n 1.0 1.0 1.0 1.0\n\njulia> tril(a)\n4×4 Matrix{Float64}:\n 1.0 0.0 0.0 0.0\n 1.0 1.0 0.0 0.0\n 1.0 1.0 1.0 0.0\n 1.0 1.0 1.0 1.0\n\n\n\n\n\ntril(M, k::Integer)\n\nReturns the lower triangle of M starting from the kth superdiagonal.\n\nExamples\n\njulia> a = fill(1.0, (4,4))\n4×4 Matrix{Float64}:\n 1.0 1.0 1.0 1.0\n 1.0 1.0 1.0 1.0\n 1.0 1.0 1.0 1.0\n 1.0 1.0 1.0 1.0\n\njulia> tril(a,3)\n4×4 Matrix{Float64}:\n 1.0 1.0 1.0 1.0\n 1.0 1.0 1.0 1.0\n 1.0 1.0 1.0 1.0\n 1.0 1.0 1.0 1.0\n\njulia> tril(a,-3)\n4×4 Matrix{Float64}:\n 0.0 0.0 0.0 0.0\n 0.0 0.0 0.0 0.0\n 0.0 0.0 0.0 0.0\n 1.0 0.0 0.0 0.0\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LinearAlgebra/#LinearAlgebra.tril!","page":"Linear Algebra","title":"LinearAlgebra.tril!","text":"tril!(M)\n\nLower triangle of a matrix, overwriting M in the process. See also tril.\n\n\n\n\n\ntril!(M, k::Integer)\n\nReturn the lower triangle of M starting from the kth superdiagonal, overwriting M in the process.\n\nExamples\n\njulia> M = [1 2 3 4 5; 1 2 3 4 5; 1 2 3 4 5; 1 2 3 4 5; 1 2 3 4 5]\n5×5 Matrix{Int64}:\n 1 2 3 4 5\n 1 2 3 4 5\n 1 2 3 4 5\n 1 2 3 4 5\n 1 2 3 4 5\n\njulia> tril!(M, 2)\n5×5 Matrix{Int64}:\n 1 2 3 0 0\n 1 2 3 4 0\n 1 2 3 4 5\n 1 2 3 4 5\n 1 2 3 4 5\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LinearAlgebra/#LinearAlgebra.diagind","page":"Linear Algebra","title":"LinearAlgebra.diagind","text":"diagind(M, k::Integer=0)\n\nAn AbstractRange giving the indices of the kth diagonal of the matrix M.\n\nSee also: diag, diagm, Diagonal.\n\nExamples\n\njulia> A = [1 2 3; 4 5 6; 7 8 9]\n3×3 Matrix{Int64}:\n 1 2 3\n 4 5 6\n 7 8 9\n\njulia> diagind(A,-1)\n2:4:6\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LinearAlgebra/#LinearAlgebra.diag","page":"Linear Algebra","title":"LinearAlgebra.diag","text":"diag(M, k::Integer=0)\n\nThe kth diagonal of a matrix, as a vector.\n\nSee also diagm, diagind, Diagonal, isdiag.\n\nExamples\n\njulia> A = [1 2 3; 4 5 6; 7 8 9]\n3×3 Matrix{Int64}:\n 1 2 3\n 4 5 6\n 7 8 9\n\njulia> diag(A,1)\n2-element Vector{Int64}:\n 2\n 6\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LinearAlgebra/#LinearAlgebra.diagm","page":"Linear Algebra","title":"LinearAlgebra.diagm","text":"diagm(kv::Pair{<:Integer,<:AbstractVector}...)\ndiagm(m::Integer, n::Integer, kv::Pair{<:Integer,<:AbstractVector}...)\n\nConstruct a matrix from Pairs of diagonals and vectors. Vector kv.second will be placed on the kv.first diagonal. By default the matrix is square and its size is inferred from kv, but a non-square size m×n (padded with zeros as needed) can be specified by passing m,n as the first arguments. For repeated diagonal indices kv.first the values in the corresponding vectors kv.second will be added.\n\ndiagm constructs a full matrix; if you want storage-efficient versions with fast arithmetic, see Diagonal, Bidiagonal Tridiagonal and SymTridiagonal.\n\nExamples\n\njulia> diagm(1 => [1,2,3])\n4×4 Matrix{Int64}:\n 0 1 0 0\n 0 0 2 0\n 0 0 0 3\n 0 0 0 0\n\njulia> diagm(1 => [1,2,3], -1 => [4,5])\n4×4 Matrix{Int64}:\n 0 1 0 0\n 4 0 2 0\n 0 5 0 3\n 0 0 0 0\n\njulia> diagm(1 => [1,2,3], 1 => [1,2,3])\n4×4 Matrix{Int64}:\n 0 2 0 0\n 0 0 4 0\n 0 0 0 6\n 0 0 0 0\n\n\n\n\n\ndiagm(v::AbstractVector)\ndiagm(m::Integer, n::Integer, v::AbstractVector)\n\nConstruct a matrix with elements of the vector as diagonal elements. By default, the matrix is square and its size is given by length(v), but a non-square size m×n can be specified by passing m,n as the first arguments.\n\nExamples\n\njulia> diagm([1,2,3])\n3×3 Matrix{Int64}:\n 1 0 0\n 0 2 0\n 0 0 3\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LinearAlgebra/#LinearAlgebra.rank","page":"Linear Algebra","title":"LinearAlgebra.rank","text":"rank(A::AbstractMatrix; atol::Real=0, rtol::Real=atol>0 ? 0 : n*ϵ)\nrank(A::AbstractMatrix, rtol::Real)\n\nCompute the rank of a matrix by counting how many singular values of A have magnitude greater than max(atol, rtol*σ₁) where σ₁ is A's largest singular value. atol and rtol are the absolute and relative tolerances, respectively. The default relative tolerance is n*ϵ, where n is the size of the smallest dimension of A, and ϵ is the eps of the element type of A.\n\ncompat: Julia 1.1\nThe atol and rtol keyword arguments requires at least Julia 1.1. In Julia 1.0 rtol is available as a positional argument, but this will be deprecated in Julia 2.0.\n\nExamples\n\njulia> rank(Matrix(I, 3, 3))\n3\n\njulia> rank(diagm(0 => [1, 0, 2]))\n2\n\njulia> rank(diagm(0 => [1, 0.001, 2]), rtol=0.1)\n2\n\njulia> rank(diagm(0 => [1, 0.001, 2]), rtol=0.00001)\n3\n\njulia> rank(diagm(0 => [1, 0.001, 2]), atol=1.5)\n1\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LinearAlgebra/#LinearAlgebra.norm","page":"Linear Algebra","title":"LinearAlgebra.norm","text":"norm(A, p::Real=2)\n\nFor any iterable container A (including arrays of any dimension) of numbers (or any element type for which norm is defined), compute the p-norm (defaulting to p=2) as if A were a vector of the corresponding length.\n\nThe p-norm is defined as\n\nA_p = left( sum_i=1^n a_i ^p right)^1p\n\nwith a_i the entries of A, a_i the norm of a_i, and n the length of A. Since the p-norm is computed using the norms of the entries of A, the p-norm of a vector of vectors is not compatible with the interpretation of it as a block vector in general if p != 2.\n\np can assume any numeric value (even though not all values produce a mathematically valid vector norm). In particular, norm(A, Inf) returns the largest value in abs.(A), whereas norm(A, -Inf) returns the smallest. If A is a matrix and p=2, then this is equivalent to the Frobenius norm.\n\nThe second argument p is not necessarily a part of the interface for norm, i.e. a custom type may only implement norm(A) without second argument.\n\nUse opnorm to compute the operator norm of a matrix.\n\nExamples\n\njulia> v = [3, -2, 6]\n3-element Vector{Int64}:\n 3\n -2\n 6\n\njulia> norm(v)\n7.0\n\njulia> norm(v, 1)\n11.0\n\njulia> norm(v, Inf)\n6.0\n\njulia> norm([1 2 3; 4 5 6; 7 8 9])\n16.881943016134134\n\njulia> norm([1 2 3 4 5 6 7 8 9])\n16.881943016134134\n\njulia> norm(1:9)\n16.881943016134134\n\njulia> norm(hcat(v,v), 1) == norm(vcat(v,v), 1) != norm([v,v], 1)\ntrue\n\njulia> norm(hcat(v,v), 2) == norm(vcat(v,v), 2) == norm([v,v], 2)\ntrue\n\njulia> norm(hcat(v,v), Inf) == norm(vcat(v,v), Inf) != norm([v,v], Inf)\ntrue\n\n\n\n\n\nnorm(x::Number, p::Real=2)\n\nFor numbers, return left( x^p right)^1p.\n\nExamples\n\njulia> norm(2, 1)\n2.0\n\njulia> norm(-2, 1)\n2.0\n\njulia> norm(2, 2)\n2.0\n\njulia> norm(-2, 2)\n2.0\n\njulia> norm(2, Inf)\n2.0\n\njulia> norm(-2, Inf)\n2.0\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LinearAlgebra/#LinearAlgebra.opnorm","page":"Linear Algebra","title":"LinearAlgebra.opnorm","text":"opnorm(A::AbstractMatrix, p::Real=2)\n\nCompute the operator norm (or matrix norm) induced by the vector p-norm, where valid values of p are 1, 2, or Inf. (Note that for sparse matrices, p=2 is currently not implemented.) Use norm to compute the Frobenius norm.\n\nWhen p=1, the operator norm is the maximum absolute column sum of A:\n\nA_1 = max_1 j n sum_i=1^m a_ij \n\nwith a_ij the entries of A, and m and n its dimensions.\n\nWhen p=2, the operator norm is the spectral norm, equal to the largest singular value of A.\n\nWhen p=Inf, the operator norm is the maximum absolute row sum of A:\n\nA_infty = max_1 i m sum _j=1^n a_ij \n\nExamples\n\njulia> A = [1 -2 -3; 2 3 -1]\n2×3 Matrix{Int64}:\n 1 -2 -3\n 2 3 -1\n\njulia> opnorm(A, Inf)\n6.0\n\njulia> opnorm(A, 1)\n5.0\n\n\n\n\n\nopnorm(x::Number, p::Real=2)\n\nFor numbers, return left( x^p right)^1p. This is equivalent to norm.\n\n\n\n\n\nopnorm(A::Adjoint{<:Any,<:AbstracVector}, q::Real=2)\nopnorm(A::Transpose{<:Any,<:AbstracVector}, q::Real=2)\n\nFor Adjoint/Transpose-wrapped vectors, return the operator q-norm of A, which is equivalent to the p-norm with value p = q/(q-1). They coincide at p = q = 2. Use norm to compute the p norm of A as a vector.\n\nThe difference in norm between a vector space and its dual arises to preserve the relationship between duality and the dot product, and the result is consistent with the operator p-norm of a 1 × n matrix.\n\nExamples\n\njulia> v = [1; im];\n\njulia> vc = v';\n\njulia> opnorm(vc, 1)\n1.0\n\njulia> norm(vc, 1)\n2.0\n\njulia> norm(v, 1)\n2.0\n\njulia> opnorm(vc, 2)\n1.4142135623730951\n\njulia> norm(vc, 2)\n1.4142135623730951\n\njulia> norm(v, 2)\n1.4142135623730951\n\njulia> opnorm(vc, Inf)\n2.0\n\njulia> norm(vc, Inf)\n1.0\n\njulia> norm(v, Inf)\n1.0\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LinearAlgebra/#LinearAlgebra.normalize!","page":"Linear Algebra","title":"LinearAlgebra.normalize!","text":"normalize!(a::AbstractArray, p::Real=2)\n\nNormalize the array a in-place so that its p-norm equals unity, i.e. norm(a, p) == 1. See also normalize and norm.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LinearAlgebra/#LinearAlgebra.normalize","page":"Linear Algebra","title":"LinearAlgebra.normalize","text":"normalize(a::AbstractArray, p::Real=2)\n\nNormalize the array a so that its p-norm equals unity, i.e. norm(a, p) == 1. See also normalize! and norm.\n\nExamples\n\njulia> a = [1,2,4];\n\njulia> b = normalize(a)\n3-element Vector{Float64}:\n 0.2182178902359924\n 0.4364357804719848\n 0.8728715609439696\n\njulia> norm(b)\n1.0\n\njulia> c = normalize(a, 1)\n3-element Vector{Float64}:\n 0.14285714285714285\n 0.2857142857142857\n 0.5714285714285714\n\njulia> norm(c, 1)\n1.0\n\njulia> a = [1 2 4 ; 1 2 4]\n2×3 Matrix{Int64}:\n 1 2 4\n 1 2 4\n\njulia> norm(a)\n6.48074069840786\n\njulia> normalize(a)\n2×3 Matrix{Float64}:\n 0.154303 0.308607 0.617213\n 0.154303 0.308607 0.617213\n\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LinearAlgebra/#LinearAlgebra.cond","page":"Linear Algebra","title":"LinearAlgebra.cond","text":"cond(M, p::Real=2)\n\nCondition number of the matrix M, computed using the operator p-norm. Valid values for p are 1, 2 (default), or Inf.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LinearAlgebra/#LinearAlgebra.condskeel","page":"Linear Algebra","title":"LinearAlgebra.condskeel","text":"condskeel(M, [x, p::Real=Inf])\n\nkappa_S(M p) = leftVert leftvert M rightvert leftvert M^-1 rightvert rightVert_p \nkappa_S(M x p) = fracleftVert leftvert M rightvert leftvert M^-1 rightvert leftvert x rightvert rightVert_pleft Vert x right Vert_p\n\nSkeel condition number kappa_S of the matrix M, optionally with respect to the vector x, as computed using the operator p-norm. leftvert M rightvert denotes the matrix of (entry wise) absolute values of M; leftvert M rightvert_ij = leftvert M_ij rightvert. Valid values for p are 1, 2 and Inf (default).\n\nThis quantity is also known in the literature as the Bauer condition number, relative condition number, or componentwise relative condition number.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LinearAlgebra/#LinearAlgebra.tr","page":"Linear Algebra","title":"LinearAlgebra.tr","text":"tr(M)\n\nMatrix trace. Sums the diagonal elements of M.\n\nExamples\n\njulia> A = [1 2; 3 4]\n2×2 Matrix{Int64}:\n 1 2\n 3 4\n\njulia> tr(A)\n5\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LinearAlgebra/#LinearAlgebra.det","page":"Linear Algebra","title":"LinearAlgebra.det","text":"det(M)\n\nMatrix determinant.\n\nSee also: logdet and logabsdet.\n\nExamples\n\njulia> M = [1 0; 2 2]\n2×2 Matrix{Int64}:\n 1 0\n 2 2\n\njulia> det(M)\n2.0\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LinearAlgebra/#LinearAlgebra.logdet","page":"Linear Algebra","title":"LinearAlgebra.logdet","text":"logdet(M)\n\nLog of matrix determinant. Equivalent to log(det(M)), but may provide increased accuracy and/or speed.\n\nExamples\n\njulia> M = [1 0; 2 2]\n2×2 Matrix{Int64}:\n 1 0\n 2 2\n\njulia> logdet(M)\n0.6931471805599453\n\njulia> logdet(Matrix(I, 3, 3))\n0.0\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LinearAlgebra/#LinearAlgebra.logabsdet","page":"Linear Algebra","title":"LinearAlgebra.logabsdet","text":"logabsdet(M)\n\nLog of absolute value of matrix determinant. Equivalent to (log(abs(det(M))), sign(det(M))), but may provide increased accuracy and/or speed.\n\nExamples\n\njulia> A = [-1. 0.; 0. 1.]\n2×2 Matrix{Float64}:\n -1.0 0.0\n 0.0 1.0\n\njulia> det(A)\n-1.0\n\njulia> logabsdet(A)\n(0.0, -1.0)\n\njulia> B = [2. 0.; 0. 1.]\n2×2 Matrix{Float64}:\n 2.0 0.0\n 0.0 1.0\n\njulia> det(B)\n2.0\n\njulia> logabsdet(B)\n(0.6931471805599453, 1.0)\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LinearAlgebra/#Base.inv-Tuple{AbstractMatrix}","page":"Linear Algebra","title":"Base.inv","text":"inv(M)\n\nMatrix inverse. Computes matrix N such that M * N = I, where I is the identity matrix. Computed by solving the left-division N = M \\ I.\n\nExamples\n\njulia> M = [2 5; 1 3]\n2×2 Matrix{Int64}:\n 2 5\n 1 3\n\njulia> N = inv(M)\n2×2 Matrix{Float64}:\n 3.0 -5.0\n -1.0 2.0\n\njulia> M*N == N*M == Matrix(I, 2, 2)\ntrue\n\n\n\n\n\n","category":"method"},{"location":"stdlib/LinearAlgebra/#LinearAlgebra.pinv","page":"Linear Algebra","title":"LinearAlgebra.pinv","text":"pinv(M; atol::Real=0, rtol::Real=atol>0 ? 0 : n*ϵ)\npinv(M, rtol::Real) = pinv(M; rtol=rtol) # to be deprecated in Julia 2.0\n\nComputes the Moore-Penrose pseudoinverse.\n\nFor matrices M with floating point elements, it is convenient to compute the pseudoinverse by inverting only singular values greater than max(atol, rtol*σ₁) where σ₁ is the largest singular value of M.\n\nThe optimal choice of absolute (atol) and relative tolerance (rtol) varies both with the value of M and the intended application of the pseudoinverse. The default relative tolerance is n*ϵ, where n is the size of the smallest dimension of M, and ϵ is the eps of the element type of M.\n\nFor inverting dense ill-conditioned matrices in a least-squares sense, rtol = sqrt(eps(real(float(one(eltype(M)))))) is recommended.\n\nFor more information, see [issue8859], [B96], [S84], [KY88].\n\nExamples\n\njulia> M = [1.5 1.3; 1.2 1.9]\n2×2 Matrix{Float64}:\n 1.5 1.3\n 1.2 1.9\n\njulia> N = pinv(M)\n2×2 Matrix{Float64}:\n 1.47287 -1.00775\n -0.930233 1.16279\n\njulia> M * N\n2×2 Matrix{Float64}:\n 1.0 -2.22045e-16\n 4.44089e-16 1.0\n\n[issue8859]: Issue 8859, \"Fix least squares\", https://github.com/JuliaLang/julia/pull/8859\n\n[B96]: Åke Björck, \"Numerical Methods for Least Squares Problems\", SIAM Press, Philadelphia, 1996, \"Other Titles in Applied Mathematics\", Vol. 51. doi:10.1137/1.9781611971484\n\n[S84]: G. W. Stewart, \"Rank Degeneracy\", SIAM Journal on Scientific and Statistical Computing, 5(2), 1984, 403-413. doi:10.1137/0905030\n\n[KY88]: Konstantinos Konstantinides and Kung Yao, \"Statistical analysis of effective singular values in matrix rank determination\", IEEE Transactions on Acoustics, Speech and Signal Processing, 36(5), 1988, 757-763. doi:10.1109/29.1585\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LinearAlgebra/#LinearAlgebra.nullspace","page":"Linear Algebra","title":"LinearAlgebra.nullspace","text":"nullspace(M; atol::Real=0, rtol::Real=atol>0 ? 0 : n*ϵ)\nnullspace(M, rtol::Real) = nullspace(M; rtol=rtol) # to be deprecated in Julia 2.0\n\nComputes a basis for the nullspace of M by including the singular vectors of M whose singular values have magnitudes smaller than max(atol, rtol*σ₁), where σ₁ is M's largest singular value.\n\nBy default, the relative tolerance rtol is n*ϵ, where n is the size of the smallest dimension of M, and ϵ is the eps of the element type of M.\n\nExamples\n\njulia> M = [1 0 0; 0 1 0; 0 0 0]\n3×3 Matrix{Int64}:\n 1 0 0\n 0 1 0\n 0 0 0\n\njulia> nullspace(M)\n3×1 Matrix{Float64}:\n 0.0\n 0.0\n 1.0\n\njulia> nullspace(M, rtol=3)\n3×3 Matrix{Float64}:\n 0.0 1.0 0.0\n 1.0 0.0 0.0\n 0.0 0.0 1.0\n\njulia> nullspace(M, atol=0.95)\n3×1 Matrix{Float64}:\n 0.0\n 0.0\n 1.0\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LinearAlgebra/#Base.kron","page":"Linear Algebra","title":"Base.kron","text":"kron(A, B)\n\nKronecker tensor product of two vectors or two matrices.\n\nFor real vectors v and w, the Kronecker product is related to the outer product by kron(v,w) == vec(w * transpose(v)) or w * transpose(v) == reshape(kron(v,w), (length(w), length(v))). Note how the ordering of v and w differs on the left and right of these expressions (due to column-major storage). For complex vectors, the outer product w * v' also differs by conjugation of v.\n\nExamples\n\njulia> A = [1 2; 3 4]\n2×2 Matrix{Int64}:\n 1 2\n 3 4\n\njulia> B = [im 1; 1 -im]\n2×2 Matrix{Complex{Int64}}:\n 0+1im 1+0im\n 1+0im 0-1im\n\njulia> kron(A, B)\n4×4 Matrix{Complex{Int64}}:\n 0+1im 1+0im 0+2im 2+0im\n 1+0im 0-1im 2+0im 0-2im\n 0+3im 3+0im 0+4im 4+0im\n 3+0im 0-3im 4+0im 0-4im\n\njulia> v = [1, 2]; w = [3, 4, 5];\n\njulia> w*transpose(v)\n3×2 Matrix{Int64}:\n 3 6\n 4 8\n 5 10\n\njulia> reshape(kron(v,w), (length(w), length(v)))\n3×2 Matrix{Int64}:\n 3 6\n 4 8\n 5 10\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LinearAlgebra/#Base.kron!","page":"Linear Algebra","title":"Base.kron!","text":"kron!(C, A, B)\n\nkron! is the in-place version of kron. Computes kron(A, B) and stores the result in C overwriting the existing value of C.\n\ntip: Tip\nBounds checking can be disabled by @inbounds, but you need to take care of the shape of C, A, B yourself.\n\ncompat: Julia 1.6\nThis function requires Julia 1.6 or later.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LinearAlgebra/#Base.exp-Tuple{StridedMatrix{var\"#s387\"} where var\"#s387\"<:Union{Float32, Float64, ComplexF32, ComplexF64}}","page":"Linear Algebra","title":"Base.exp","text":"exp(A::AbstractMatrix)\n\nCompute the matrix exponential of A, defined by\n\ne^A = sum_n=0^infty fracA^nn\n\nFor symmetric or Hermitian A, an eigendecomposition (eigen) is used, otherwise the scaling and squaring algorithm (see [H05]) is chosen.\n\n[H05]: Nicholas J. Higham, \"The squaring and scaling method for the matrix exponential revisited\", SIAM Journal on Matrix Analysis and Applications, 26(4), 2005, 1179-1193. doi:10.1137/090768539\n\nExamples\n\njulia> A = Matrix(1.0I, 2, 2)\n2×2 Matrix{Float64}:\n 1.0 0.0\n 0.0 1.0\n\njulia> exp(A)\n2×2 Matrix{Float64}:\n 2.71828 0.0\n 0.0 2.71828\n\n\n\n\n\n","category":"method"},{"location":"stdlib/LinearAlgebra/#Base.cis-Tuple{AbstractMatrix}","page":"Linear Algebra","title":"Base.cis","text":"cis(A::AbstractMatrix)\n\nMore efficient method for exp(im*A) of square matrix A (especially if A is Hermitian or real-Symmetric).\n\nSee also cispi, sincos, exp.\n\ncompat: Julia 1.7\nSupport for using cis with matrices was added in Julia 1.7.\n\nExamples\n\njulia> cis([π 0; 0 π]) ≈ -I\ntrue\n\n\n\n\n\n","category":"method"},{"location":"stdlib/LinearAlgebra/#Base.:^-Tuple{AbstractMatrix, Number}","page":"Linear Algebra","title":"Base.:^","text":"^(A::AbstractMatrix, p::Number)\n\nMatrix power, equivalent to exp(plog(A))\n\nExamples\n\njulia> [1 2; 0 3]^3\n2×2 Matrix{Int64}:\n 1 26\n 0 27\n\n\n\n\n\n","category":"method"},{"location":"stdlib/LinearAlgebra/#Base.:^-Tuple{Number, AbstractMatrix}","page":"Linear Algebra","title":"Base.:^","text":"^(b::Number, A::AbstractMatrix)\n\nMatrix exponential, equivalent to exp(log(b)A).\n\ncompat: Julia 1.1\nSupport for raising Irrational numbers (like ℯ) to a matrix was added in Julia 1.1.\n\nExamples\n\njulia> 2^[1 2; 0 3]\n2×2 Matrix{Float64}:\n 2.0 6.0\n 0.0 8.0\n\njulia> ℯ^[1 2; 0 3]\n2×2 Matrix{Float64}:\n 2.71828 17.3673\n 0.0 20.0855\n\n\n\n\n\n","category":"method"},{"location":"stdlib/LinearAlgebra/#Base.log-Tuple{StridedMatrix{T} where T}","page":"Linear Algebra","title":"Base.log","text":"log(A::StridedMatrix)\n\nIf A has no negative real eigenvalue, compute the principal matrix logarithm of A, i.e. the unique matrix X such that e^X = A and -pi Im(lambda) pi for all the eigenvalues lambda of X. If A has nonpositive eigenvalues, a nonprincipal matrix function is returned whenever possible.\n\nIf A is symmetric or Hermitian, its eigendecomposition (eigen) is used, if A is triangular an improved version of the inverse scaling and squaring method is employed (see [AH12] and [AHR13]). If A is real with no negative eigenvalues, then the real Schur form is computed. Otherwise, the complex Schur form is computed. Then the upper (quasi-)triangular algorithm in [AHR13] is used on the upper (quasi-)triangular factor.\n\n[AH12]: Awad H. Al-Mohy and Nicholas J. Higham, \"Improved inverse scaling and squaring algorithms for the matrix logarithm\", SIAM Journal on Scientific Computing, 34(4), 2012, C153-C169. doi:10.1137/110852553\n\n[AHR13]: Awad H. Al-Mohy, Nicholas J. Higham and Samuel D. Relton, \"Computing the Fréchet derivative of the matrix logarithm and estimating the condition number\", SIAM Journal on Scientific Computing, 35(4), 2013, C394-C410. doi:10.1137/120885991\n\nExamples\n\njulia> A = Matrix(2.7182818*I, 2, 2)\n2×2 Matrix{Float64}:\n 2.71828 0.0\n 0.0 2.71828\n\njulia> log(A)\n2×2 Matrix{Float64}:\n 1.0 0.0\n 0.0 1.0\n\n\n\n\n\n","category":"method"},{"location":"stdlib/LinearAlgebra/#Base.sqrt-Tuple{StridedMatrix{var\"#s387\"} where var\"#s387\"<:Real}","page":"Linear Algebra","title":"Base.sqrt","text":"sqrt(x)\n\nReturn sqrtx. Throws DomainError for negative Real arguments. Use complex negative arguments instead. The prefix operator √ is equivalent to sqrt.\n\nSee also: hypot.\n\nExamples\n\njulia> sqrt(big(81))\n9.0\n\njulia> sqrt(big(-81))\nERROR: DomainError with -81.0:\nNaN result for non-NaN input.\nStacktrace:\n [1] sqrt(::BigFloat) at ./mpfr.jl:501\n[...]\n\njulia> sqrt(big(complex(-81)))\n0.0 + 9.0im\n\njulia> .√(1:4)\n4-element Vector{Float64}:\n 1.0\n 1.4142135623730951\n 1.7320508075688772\n 2.0\n\n\n\n\n\nsqrt(A::AbstractMatrix)\n\nIf A has no negative real eigenvalues, compute the principal matrix square root of A, that is the unique matrix X with eigenvalues having positive real part such that X^2 = A. Otherwise, a nonprincipal square root is returned.\n\nIf A is real-symmetric or Hermitian, its eigendecomposition (eigen) is used to compute the square root. For such matrices, eigenvalues λ that appear to be slightly negative due to roundoff errors are treated as if they were zero. More precisely, matrices with all eigenvalues ≥ -rtol*(max |λ|) are treated as semidefinite (yielding a Hermitian square root), with negative eigenvalues taken to be zero. rtol is a keyword argument to sqrt (in the Hermitian/real-symmetric case only) that defaults to machine precision scaled by size(A,1).\n\nOtherwise, the square root is determined by means of the Björck-Hammarling method [BH83], which computes the complex Schur form (schur) and then the complex square root of the triangular factor. If a real square root exists, then an extension of this method [H87] that computes the real Schur form and then the real square root of the quasi-triangular factor is instead used.\n\n[BH83]: Åke Björck and Sven Hammarling, \"A Schur method for the square root of a matrix\", Linear Algebra and its Applications, 52-53, 1983, 127-140. doi:10.1016/0024-3795(83)80010-X\n\n[H87]: Nicholas J. Higham, \"Computing real square roots of a real matrix\", Linear Algebra and its Applications, 88-89, 1987, 405-430. doi:10.1016/0024-3795(87)90118-2\n\nExamples\n\njulia> A = [4 0; 0 4]\n2×2 Matrix{Int64}:\n 4 0\n 0 4\n\njulia> sqrt(A)\n2×2 Matrix{Float64}:\n 2.0 0.0\n 0.0 2.0\n\n\n\n\n\n","category":"method"},{"location":"stdlib/LinearAlgebra/#Base.cos-Tuple{StridedMatrix{var\"#s387\"} where var\"#s387\"<:Real}","page":"Linear Algebra","title":"Base.cos","text":"cos(A::AbstractMatrix)\n\nCompute the matrix cosine of a square matrix A.\n\nIf A is symmetric or Hermitian, its eigendecomposition (eigen) is used to compute the cosine. Otherwise, the cosine is determined by calling exp.\n\nExamples\n\njulia> cos(fill(1.0, (2,2)))\n2×2 Matrix{Float64}:\n 0.291927 -0.708073\n -0.708073 0.291927\n\n\n\n\n\n","category":"method"},{"location":"stdlib/LinearAlgebra/#Base.sin-Tuple{StridedMatrix{var\"#s387\"} where var\"#s387\"<:Real}","page":"Linear Algebra","title":"Base.sin","text":"sin(A::AbstractMatrix)\n\nCompute the matrix sine of a square matrix A.\n\nIf A is symmetric or Hermitian, its eigendecomposition (eigen) is used to compute the sine. Otherwise, the sine is determined by calling exp.\n\nExamples\n\njulia> sin(fill(1.0, (2,2)))\n2×2 Matrix{Float64}:\n 0.454649 0.454649\n 0.454649 0.454649\n\n\n\n\n\n","category":"method"},{"location":"stdlib/LinearAlgebra/#Base.Math.sincos-Tuple{StridedMatrix{var\"#s387\"} where var\"#s387\"<:Real}","page":"Linear Algebra","title":"Base.Math.sincos","text":"sincos(A::AbstractMatrix)\n\nCompute the matrix sine and cosine of a square matrix A.\n\nExamples\n\njulia> S, C = sincos(fill(1.0, (2,2)));\n\njulia> S\n2×2 Matrix{Float64}:\n 0.454649 0.454649\n 0.454649 0.454649\n\njulia> C\n2×2 Matrix{Float64}:\n 0.291927 -0.708073\n -0.708073 0.291927\n\n\n\n\n\n","category":"method"},{"location":"stdlib/LinearAlgebra/#Base.tan-Tuple{StridedMatrix{var\"#s387\"} where var\"#s387\"<:Real}","page":"Linear Algebra","title":"Base.tan","text":"tan(A::AbstractMatrix)\n\nCompute the matrix tangent of a square matrix A.\n\nIf A is symmetric or Hermitian, its eigendecomposition (eigen) is used to compute the tangent. Otherwise, the tangent is determined by calling exp.\n\nExamples\n\njulia> tan(fill(1.0, (2,2)))\n2×2 Matrix{Float64}:\n -1.09252 -1.09252\n -1.09252 -1.09252\n\n\n\n\n\n","category":"method"},{"location":"stdlib/LinearAlgebra/#Base.Math.sec-Tuple{StridedMatrix{T} where T}","page":"Linear Algebra","title":"Base.Math.sec","text":"sec(A::AbstractMatrix)\n\nCompute the matrix secant of a square matrix A.\n\n\n\n\n\n","category":"method"},{"location":"stdlib/LinearAlgebra/#Base.Math.csc-Tuple{StridedMatrix{T} where T}","page":"Linear Algebra","title":"Base.Math.csc","text":"csc(A::AbstractMatrix)\n\nCompute the matrix cosecant of a square matrix A.\n\n\n\n\n\n","category":"method"},{"location":"stdlib/LinearAlgebra/#Base.Math.cot-Tuple{StridedMatrix{T} where T}","page":"Linear Algebra","title":"Base.Math.cot","text":"cot(A::AbstractMatrix)\n\nCompute the matrix cotangent of a square matrix A.\n\n\n\n\n\n","category":"method"},{"location":"stdlib/LinearAlgebra/#Base.cosh-Tuple{StridedMatrix{T} where T}","page":"Linear Algebra","title":"Base.cosh","text":"cosh(A::AbstractMatrix)\n\nCompute the matrix hyperbolic cosine of a square matrix A.\n\n\n\n\n\n","category":"method"},{"location":"stdlib/LinearAlgebra/#Base.sinh-Tuple{StridedMatrix{T} where T}","page":"Linear Algebra","title":"Base.sinh","text":"sinh(A::AbstractMatrix)\n\nCompute the matrix hyperbolic sine of a square matrix A.\n\n\n\n\n\n","category":"method"},{"location":"stdlib/LinearAlgebra/#Base.tanh-Tuple{StridedMatrix{T} where T}","page":"Linear Algebra","title":"Base.tanh","text":"tanh(A::AbstractMatrix)\n\nCompute the matrix hyperbolic tangent of a square matrix A.\n\n\n\n\n\n","category":"method"},{"location":"stdlib/LinearAlgebra/#Base.Math.sech-Tuple{StridedMatrix{T} where T}","page":"Linear Algebra","title":"Base.Math.sech","text":"sech(A::AbstractMatrix)\n\nCompute the matrix hyperbolic secant of square matrix A.\n\n\n\n\n\n","category":"method"},{"location":"stdlib/LinearAlgebra/#Base.Math.csch-Tuple{StridedMatrix{T} where T}","page":"Linear Algebra","title":"Base.Math.csch","text":"csch(A::AbstractMatrix)\n\nCompute the matrix hyperbolic cosecant of square matrix A.\n\n\n\n\n\n","category":"method"},{"location":"stdlib/LinearAlgebra/#Base.Math.coth-Tuple{StridedMatrix{T} where T}","page":"Linear Algebra","title":"Base.Math.coth","text":"coth(A::AbstractMatrix)\n\nCompute the matrix hyperbolic cotangent of square matrix A.\n\n\n\n\n\n","category":"method"},{"location":"stdlib/LinearAlgebra/#Base.acos-Tuple{StridedMatrix{T} where T}","page":"Linear Algebra","title":"Base.acos","text":"acos(A::AbstractMatrix)\n\nCompute the inverse matrix cosine of a square matrix A.\n\nIf A is symmetric or Hermitian, its eigendecomposition (eigen) is used to compute the inverse cosine. Otherwise, the inverse cosine is determined by using log and sqrt. For the theory and logarithmic formulas used to compute this function, see [AH16_1].\n\n[AH16_1]: Mary Aprahamian and Nicholas J. Higham, \"Matrix Inverse Trigonometric and Inverse Hyperbolic Functions: Theory and Algorithms\", MIMS EPrint: 2016.4. https://doi.org/10.1137/16M1057577\n\nExamples\n\njulia> acos(cos([0.5 0.1; -0.2 0.3]))\n2×2 Matrix{ComplexF64}:\n 0.5-8.32667e-17im 0.1+0.0im\n -0.2+2.63678e-16im 0.3-3.46945e-16im\n\n\n\n\n\n","category":"method"},{"location":"stdlib/LinearAlgebra/#Base.asin-Tuple{StridedMatrix{T} where T}","page":"Linear Algebra","title":"Base.asin","text":"asin(A::AbstractMatrix)\n\nCompute the inverse matrix sine of a square matrix A.\n\nIf A is symmetric or Hermitian, its eigendecomposition (eigen) is used to compute the inverse sine. Otherwise, the inverse sine is determined by using log and sqrt. For the theory and logarithmic formulas used to compute this function, see [AH16_2].\n\n[AH16_2]: Mary Aprahamian and Nicholas J. Higham, \"Matrix Inverse Trigonometric and Inverse Hyperbolic Functions: Theory and Algorithms\", MIMS EPrint: 2016.4. https://doi.org/10.1137/16M1057577\n\nExamples\n\njulia> asin(sin([0.5 0.1; -0.2 0.3]))\n2×2 Matrix{ComplexF64}:\n 0.5-4.16334e-17im 0.1-5.55112e-17im\n -0.2+9.71445e-17im 0.3-1.249e-16im\n\n\n\n\n\n","category":"method"},{"location":"stdlib/LinearAlgebra/#Base.atan-Tuple{StridedMatrix{T} where T}","page":"Linear Algebra","title":"Base.atan","text":"atan(A::AbstractMatrix)\n\nCompute the inverse matrix tangent of a square matrix A.\n\nIf A is symmetric or Hermitian, its eigendecomposition (eigen) is used to compute the inverse tangent. Otherwise, the inverse tangent is determined by using log. For the theory and logarithmic formulas used to compute this function, see [AH16_3].\n\n[AH16_3]: Mary Aprahamian and Nicholas J. Higham, \"Matrix Inverse Trigonometric and Inverse Hyperbolic Functions: Theory and Algorithms\", MIMS EPrint: 2016.4. https://doi.org/10.1137/16M1057577\n\nExamples\n\njulia> atan(tan([0.5 0.1; -0.2 0.3]))\n2×2 Matrix{ComplexF64}:\n 0.5+1.38778e-17im 0.1-2.77556e-17im\n -0.2+6.93889e-17im 0.3-4.16334e-17im\n\n\n\n\n\n","category":"method"},{"location":"stdlib/LinearAlgebra/#Base.Math.asec-Tuple{StridedMatrix{T} where T}","page":"Linear Algebra","title":"Base.Math.asec","text":"asec(A::AbstractMatrix)\n\nCompute the inverse matrix secant of A. \n\n\n\n\n\n","category":"method"},{"location":"stdlib/LinearAlgebra/#Base.Math.acsc-Tuple{StridedMatrix{T} where T}","page":"Linear Algebra","title":"Base.Math.acsc","text":"acsc(A::AbstractMatrix)\n\nCompute the inverse matrix cosecant of A. \n\n\n\n\n\n","category":"method"},{"location":"stdlib/LinearAlgebra/#Base.Math.acot-Tuple{StridedMatrix{T} where T}","page":"Linear Algebra","title":"Base.Math.acot","text":"acot(A::AbstractMatrix)\n\nCompute the inverse matrix cotangent of A. \n\n\n\n\n\n","category":"method"},{"location":"stdlib/LinearAlgebra/#Base.acosh-Tuple{StridedMatrix{T} where T}","page":"Linear Algebra","title":"Base.acosh","text":"acosh(A::AbstractMatrix)\n\nCompute the inverse hyperbolic matrix cosine of a square matrix A. For the theory and logarithmic formulas used to compute this function, see [AH16_4].\n\n[AH16_4]: Mary Aprahamian and Nicholas J. Higham, \"Matrix Inverse Trigonometric and Inverse Hyperbolic Functions: Theory and Algorithms\", MIMS EPrint: 2016.4. https://doi.org/10.1137/16M1057577\n\n\n\n\n\n","category":"method"},{"location":"stdlib/LinearAlgebra/#Base.asinh-Tuple{StridedMatrix{T} where T}","page":"Linear Algebra","title":"Base.asinh","text":"asinh(A::AbstractMatrix)\n\nCompute the inverse hyperbolic matrix sine of a square matrix A. For the theory and logarithmic formulas used to compute this function, see [AH16_5].\n\n[AH16_5]: Mary Aprahamian and Nicholas J. Higham, \"Matrix Inverse Trigonometric and Inverse Hyperbolic Functions: Theory and Algorithms\", MIMS EPrint: 2016.4. https://doi.org/10.1137/16M1057577\n\n\n\n\n\n","category":"method"},{"location":"stdlib/LinearAlgebra/#Base.atanh-Tuple{StridedMatrix{T} where T}","page":"Linear Algebra","title":"Base.atanh","text":"atanh(A::AbstractMatrix)\n\nCompute the inverse hyperbolic matrix tangent of a square matrix A. For the theory and logarithmic formulas used to compute this function, see [AH16_6].\n\n[AH16_6]: Mary Aprahamian and Nicholas J. Higham, \"Matrix Inverse Trigonometric and Inverse Hyperbolic Functions: Theory and Algorithms\", MIMS EPrint: 2016.4. https://doi.org/10.1137/16M1057577\n\n\n\n\n\n","category":"method"},{"location":"stdlib/LinearAlgebra/#Base.Math.asech-Tuple{StridedMatrix{T} where T}","page":"Linear Algebra","title":"Base.Math.asech","text":"asech(A::AbstractMatrix)\n\nCompute the inverse matrix hyperbolic secant of A. \n\n\n\n\n\n","category":"method"},{"location":"stdlib/LinearAlgebra/#Base.Math.acsch-Tuple{StridedMatrix{T} where T}","page":"Linear Algebra","title":"Base.Math.acsch","text":"acsch(A::AbstractMatrix)\n\nCompute the inverse matrix hyperbolic cosecant of A. \n\n\n\n\n\n","category":"method"},{"location":"stdlib/LinearAlgebra/#Base.Math.acoth-Tuple{StridedMatrix{T} where T}","page":"Linear Algebra","title":"Base.Math.acoth","text":"acoth(A::AbstractMatrix)\n\nCompute the inverse matrix hyperbolic cotangent of A. \n\n\n\n\n\n","category":"method"},{"location":"stdlib/LinearAlgebra/#LinearAlgebra.lyap","page":"Linear Algebra","title":"LinearAlgebra.lyap","text":"lyap(A, C)\n\nComputes the solution X to the continuous Lyapunov equation AX + XA' + C = 0, where no eigenvalue of A has a zero real part and no two eigenvalues are negative complex conjugates of each other.\n\nExamples\n\njulia> A = [3. 4.; 5. 6]\n2×2 Matrix{Float64}:\n 3.0 4.0\n 5.0 6.0\n\njulia> B = [1. 1.; 1. 2.]\n2×2 Matrix{Float64}:\n 1.0 1.0\n 1.0 2.0\n\njulia> X = lyap(A, B)\n2×2 Matrix{Float64}:\n 0.5 -0.5\n -0.5 0.25\n\njulia> A*X + X*A' + B\n2×2 Matrix{Float64}:\n 0.0 6.66134e-16\n 6.66134e-16 8.88178e-16\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LinearAlgebra/#LinearAlgebra.sylvester","page":"Linear Algebra","title":"LinearAlgebra.sylvester","text":"sylvester(A, B, C)\n\nComputes the solution X to the Sylvester equation AX + XB + C = 0, where A, B and C have compatible dimensions and A and -B have no eigenvalues with equal real part.\n\nExamples\n\njulia> A = [3. 4.; 5. 6]\n2×2 Matrix{Float64}:\n 3.0 4.0\n 5.0 6.0\n\njulia> B = [1. 1.; 1. 2.]\n2×2 Matrix{Float64}:\n 1.0 1.0\n 1.0 2.0\n\njulia> C = [1. 2.; -2. 1]\n2×2 Matrix{Float64}:\n 1.0 2.0\n -2.0 1.0\n\njulia> X = sylvester(A, B, C)\n2×2 Matrix{Float64}:\n -4.46667 1.93333\n 3.73333 -1.8\n\njulia> A*X + X*B + C\n2×2 Matrix{Float64}:\n 2.66454e-15 1.77636e-15\n -3.77476e-15 4.44089e-16\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LinearAlgebra/#LinearAlgebra.issuccess","page":"Linear Algebra","title":"LinearAlgebra.issuccess","text":"issuccess(F::Factorization)\n\nTest that a factorization of a matrix succeeded.\n\ncompat: Julia 1.6\nissuccess(::CholeskyPivoted) requires Julia 1.6 or later.\n\njulia> F = cholesky([1 0; 0 1]);\n\njulia> LinearAlgebra.issuccess(F)\ntrue\n\njulia> F = lu([1 0; 0 0]; check = false);\n\njulia> LinearAlgebra.issuccess(F)\nfalse\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LinearAlgebra/#LinearAlgebra.issymmetric","page":"Linear Algebra","title":"LinearAlgebra.issymmetric","text":"issymmetric(A) -> Bool\n\nTest whether a matrix is symmetric.\n\nExamples\n\njulia> a = [1 2; 2 -1]\n2×2 Matrix{Int64}:\n 1 2\n 2 -1\n\njulia> issymmetric(a)\ntrue\n\njulia> b = [1 im; -im 1]\n2×2 Matrix{Complex{Int64}}:\n 1+0im 0+1im\n 0-1im 1+0im\n\njulia> issymmetric(b)\nfalse\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LinearAlgebra/#LinearAlgebra.isposdef","page":"Linear Algebra","title":"LinearAlgebra.isposdef","text":"isposdef(A) -> Bool\n\nTest whether a matrix is positive definite (and Hermitian) by trying to perform a Cholesky factorization of A.\n\nSee also isposdef!, cholesky.\n\nExamples\n\njulia> A = [1 2; 2 50]\n2×2 Matrix{Int64}:\n 1 2\n 2 50\n\njulia> isposdef(A)\ntrue\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LinearAlgebra/#LinearAlgebra.isposdef!","page":"Linear Algebra","title":"LinearAlgebra.isposdef!","text":"isposdef!(A) -> Bool\n\nTest whether a matrix is positive definite (and Hermitian) by trying to perform a Cholesky factorization of A, overwriting A in the process. See also isposdef.\n\nExamples\n\njulia> A = [1. 2.; 2. 50.];\n\njulia> isposdef!(A)\ntrue\n\njulia> A\n2×2 Matrix{Float64}:\n 1.0 2.0\n 2.0 6.78233\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LinearAlgebra/#LinearAlgebra.istril","page":"Linear Algebra","title":"LinearAlgebra.istril","text":"istril(A::AbstractMatrix, k::Integer = 0) -> Bool\n\nTest whether A is lower triangular starting from the kth superdiagonal.\n\nExamples\n\njulia> a = [1 2; 2 -1]\n2×2 Matrix{Int64}:\n 1 2\n 2 -1\n\njulia> istril(a)\nfalse\n\njulia> istril(a, 1)\ntrue\n\njulia> b = [1 0; -im -1]\n2×2 Matrix{Complex{Int64}}:\n 1+0im 0+0im\n 0-1im -1+0im\n\njulia> istril(b)\ntrue\n\njulia> istril(b, -1)\nfalse\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LinearAlgebra/#LinearAlgebra.istriu","page":"Linear Algebra","title":"LinearAlgebra.istriu","text":"istriu(A::AbstractMatrix, k::Integer = 0) -> Bool\n\nTest whether A is upper triangular starting from the kth superdiagonal.\n\nExamples\n\njulia> a = [1 2; 2 -1]\n2×2 Matrix{Int64}:\n 1 2\n 2 -1\n\njulia> istriu(a)\nfalse\n\njulia> istriu(a, -1)\ntrue\n\njulia> b = [1 im; 0 -1]\n2×2 Matrix{Complex{Int64}}:\n 1+0im 0+1im\n 0+0im -1+0im\n\njulia> istriu(b)\ntrue\n\njulia> istriu(b, 1)\nfalse\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LinearAlgebra/#LinearAlgebra.isdiag","page":"Linear Algebra","title":"LinearAlgebra.isdiag","text":"isdiag(A) -> Bool\n\nTest whether a matrix is diagonal.\n\nExamples\n\njulia> a = [1 2; 2 -1]\n2×2 Matrix{Int64}:\n 1 2\n 2 -1\n\njulia> isdiag(a)\nfalse\n\njulia> b = [im 0; 0 -im]\n2×2 Matrix{Complex{Int64}}:\n 0+1im 0+0im\n 0+0im 0-1im\n\njulia> isdiag(b)\ntrue\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LinearAlgebra/#LinearAlgebra.ishermitian","page":"Linear Algebra","title":"LinearAlgebra.ishermitian","text":"ishermitian(A) -> Bool\n\nTest whether a matrix is Hermitian.\n\nExamples\n\njulia> a = [1 2; 2 -1]\n2×2 Matrix{Int64}:\n 1 2\n 2 -1\n\njulia> ishermitian(a)\ntrue\n\njulia> b = [1 im; -im 1]\n2×2 Matrix{Complex{Int64}}:\n 1+0im 0+1im\n 0-1im 1+0im\n\njulia> ishermitian(b)\ntrue\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LinearAlgebra/#Base.transpose","page":"Linear Algebra","title":"Base.transpose","text":"transpose(A)\n\nLazy transpose. Mutating the returned object should appropriately mutate A. Often, but not always, yields Transpose(A), where Transpose is a lazy transpose wrapper. Note that this operation is recursive.\n\nThis operation is intended for linear algebra usage - for general data manipulation see permutedims, which is non-recursive.\n\nExamples\n\njulia> A = [3+2im 9+2im; 8+7im 4+6im]\n2×2 Matrix{Complex{Int64}}:\n 3+2im 9+2im\n 8+7im 4+6im\n\njulia> transpose(A)\n2×2 transpose(::Matrix{Complex{Int64}}) with eltype Complex{Int64}:\n 3+2im 8+7im\n 9+2im 4+6im\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LinearAlgebra/#LinearAlgebra.transpose!","page":"Linear Algebra","title":"LinearAlgebra.transpose!","text":"transpose!(dest,src)\n\nTranspose array src and store the result in the preallocated array dest, which should have a size corresponding to (size(src,2),size(src,1)). No in-place transposition is supported and unexpected results will happen if src and dest have overlapping memory regions.\n\nExamples\n\njulia> A = [3+2im 9+2im; 8+7im 4+6im]\n2×2 Matrix{Complex{Int64}}:\n 3+2im 9+2im\n 8+7im 4+6im\n\njulia> B = zeros(Complex{Int64}, 2, 2)\n2×2 Matrix{Complex{Int64}}:\n 0+0im 0+0im\n 0+0im 0+0im\n\njulia> transpose!(B, A);\n\njulia> B\n2×2 Matrix{Complex{Int64}}:\n 3+2im 8+7im\n 9+2im 4+6im\n\njulia> A\n2×2 Matrix{Complex{Int64}}:\n 3+2im 9+2im\n 8+7im 4+6im\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LinearAlgebra/#LinearAlgebra.Transpose","page":"Linear Algebra","title":"LinearAlgebra.Transpose","text":"Transpose\n\nLazy wrapper type for a transpose view of the underlying linear algebra object, usually an AbstractVector/AbstractMatrix, but also some Factorization, for instance. Usually, the Transpose constructor should not be called directly, use transpose instead. To materialize the view use copy.\n\nThis type is intended for linear algebra usage - for general data manipulation see permutedims.\n\nExamples\n\njulia> A = [3+2im 9+2im; 8+7im 4+6im]\n2×2 Matrix{Complex{Int64}}:\n 3+2im 9+2im\n 8+7im 4+6im\n\njulia> transpose(A)\n2×2 transpose(::Matrix{Complex{Int64}}) with eltype Complex{Int64}:\n 3+2im 8+7im\n 9+2im 4+6im\n\n\n\n\n\n","category":"type"},{"location":"stdlib/LinearAlgebra/#Base.adjoint","page":"Linear Algebra","title":"Base.adjoint","text":"A'\nadjoint(A)\n\nLazy adjoint (conjugate transposition). Note that adjoint is applied recursively to elements.\n\nFor number types, adjoint returns the complex conjugate, and therefore it is equivalent to the identity function for real numbers.\n\nThis operation is intended for linear algebra usage - for general data manipulation see permutedims.\n\nExamples\n\njulia> A = [3+2im 9+2im; 8+7im 4+6im]\n2×2 Matrix{Complex{Int64}}:\n 3+2im 9+2im\n 8+7im 4+6im\n\njulia> adjoint(A)\n2×2 adjoint(::Matrix{Complex{Int64}}) with eltype Complex{Int64}:\n 3-2im 8-7im\n 9-2im 4-6im\n\njulia> x = [3, 4im]\n2-element Vector{Complex{Int64}}:\n 3 + 0im\n 0 + 4im\n\njulia> x'x\n25 + 0im\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LinearAlgebra/#LinearAlgebra.adjoint!","page":"Linear Algebra","title":"LinearAlgebra.adjoint!","text":"adjoint!(dest,src)\n\nConjugate transpose array src and store the result in the preallocated array dest, which should have a size corresponding to (size(src,2),size(src,1)). No in-place transposition is supported and unexpected results will happen if src and dest have overlapping memory regions.\n\nExamples\n\njulia> A = [3+2im 9+2im; 8+7im 4+6im]\n2×2 Matrix{Complex{Int64}}:\n 3+2im 9+2im\n 8+7im 4+6im\n\njulia> B = zeros(Complex{Int64}, 2, 2)\n2×2 Matrix{Complex{Int64}}:\n 0+0im 0+0im\n 0+0im 0+0im\n\njulia> adjoint!(B, A);\n\njulia> B\n2×2 Matrix{Complex{Int64}}:\n 3-2im 8-7im\n 9-2im 4-6im\n\njulia> A\n2×2 Matrix{Complex{Int64}}:\n 3+2im 9+2im\n 8+7im 4+6im\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LinearAlgebra/#LinearAlgebra.Adjoint","page":"Linear Algebra","title":"LinearAlgebra.Adjoint","text":"Adjoint\n\nLazy wrapper type for an adjoint view of the underlying linear algebra object, usually an AbstractVector/AbstractMatrix, but also some Factorization, for instance. Usually, the Adjoint constructor should not be called directly, use adjoint instead. To materialize the view use copy.\n\nThis type is intended for linear algebra usage - for general data manipulation see permutedims.\n\nExamples\n\njulia> A = [3+2im 9+2im; 8+7im 4+6im]\n2×2 Matrix{Complex{Int64}}:\n 3+2im 9+2im\n 8+7im 4+6im\n\njulia> adjoint(A)\n2×2 adjoint(::Matrix{Complex{Int64}}) with eltype Complex{Int64}:\n 3-2im 8-7im\n 9-2im 4-6im\n\n\n\n\n\n","category":"type"},{"location":"stdlib/LinearAlgebra/#Base.copy-Tuple{Union{Adjoint, Transpose}}","page":"Linear Algebra","title":"Base.copy","text":"copy(A::Transpose)\ncopy(A::Adjoint)\n\nEagerly evaluate the lazy matrix transpose/adjoint. Note that the transposition is applied recursively to elements.\n\nThis operation is intended for linear algebra usage - for general data manipulation see permutedims, which is non-recursive.\n\nExamples\n\njulia> A = [1 2im; -3im 4]\n2×2 Matrix{Complex{Int64}}:\n 1+0im 0+2im\n 0-3im 4+0im\n\njulia> T = transpose(A)\n2×2 transpose(::Matrix{Complex{Int64}}) with eltype Complex{Int64}:\n 1+0im 0-3im\n 0+2im 4+0im\n\njulia> copy(T)\n2×2 Matrix{Complex{Int64}}:\n 1+0im 0-3im\n 0+2im 4+0im\n\n\n\n\n\n","category":"method"},{"location":"stdlib/LinearAlgebra/#LinearAlgebra.stride1","page":"Linear Algebra","title":"LinearAlgebra.stride1","text":"stride1(A) -> Int\n\nReturn the distance between successive array elements in dimension 1 in units of element size.\n\nExamples\n\njulia> A = [1,2,3,4]\n4-element Vector{Int64}:\n 1\n 2\n 3\n 4\n\njulia> LinearAlgebra.stride1(A)\n1\n\njulia> B = view(A, 2:2:4)\n2-element view(::Vector{Int64}, 2:2:4) with eltype Int64:\n 2\n 4\n\njulia> LinearAlgebra.stride1(B)\n2\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LinearAlgebra/#LinearAlgebra.checksquare","page":"Linear Algebra","title":"LinearAlgebra.checksquare","text":"LinearAlgebra.checksquare(A)\n\nCheck that a matrix is square, then return its common dimension. For multiple arguments, return a vector.\n\nExamples\n\njulia> A = fill(1, (4,4)); B = fill(1, (5,5));\n\njulia> LinearAlgebra.checksquare(A, B)\n2-element Vector{Int64}:\n 4\n 5\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LinearAlgebra/#LinearAlgebra.peakflops","page":"Linear Algebra","title":"LinearAlgebra.peakflops","text":"LinearAlgebra.peakflops(n::Integer=2000; parallel::Bool=false)\n\npeakflops computes the peak flop rate of the computer by using double precision gemm!. By default, if no arguments are specified, it multiplies a matrix of size n x n, where n = 2000. If the underlying BLAS is using multiple threads, higher flop rates are realized. The number of BLAS threads can be set with BLAS.set_num_threads(n).\n\nIf the keyword argument parallel is set to true, peakflops is run in parallel on all the worker processors. The flop rate of the entire parallel computer is returned. When running in parallel, only 1 BLAS thread is used. The argument n still refers to the size of the problem that is solved on each processor.\n\ncompat: Julia 1.1\nThis function requires at least Julia 1.1. In Julia 1.0 it is available from the standard library InteractiveUtils.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LinearAlgebra/#Low-level-matrix-operations","page":"Linear Algebra","title":"Low-level matrix operations","text":"","category":"section"},{"location":"stdlib/LinearAlgebra/","page":"Linear Algebra","title":"Linear Algebra","text":"In many cases there are in-place versions of matrix operations that allow you to supply a pre-allocated output vector or matrix. This is useful when optimizing critical code in order to avoid the overhead of repeated allocations. These in-place operations are suffixed with ! below (e.g. mul!) according to the usual Julia convention.","category":"page"},{"location":"stdlib/LinearAlgebra/","page":"Linear Algebra","title":"Linear Algebra","text":"LinearAlgebra.mul!\nLinearAlgebra.lmul!\nLinearAlgebra.rmul!\nLinearAlgebra.ldiv!\nLinearAlgebra.rdiv!","category":"page"},{"location":"stdlib/LinearAlgebra/#LinearAlgebra.mul!","page":"Linear Algebra","title":"LinearAlgebra.mul!","text":"mul!(Y, A, B) -> Y\n\nCalculates the matrix-matrix or matrix-vector product AB and stores the result in Y, overwriting the existing value of Y. Note that Y must not be aliased with either A or B.\n\nExamples\n\njulia> A=[1.0 2.0; 3.0 4.0]; B=[1.0 1.0; 1.0 1.0]; Y = similar(B); mul!(Y, A, B);\n\njulia> Y\n2×2 Matrix{Float64}:\n 3.0 3.0\n 7.0 7.0\n\nImplementation\n\nFor custom matrix and vector types, it is recommended to implement 5-argument mul! rather than implementing 3-argument mul! directly if possible.\n\n\n\n\n\nmul!(C, A, B, α, β) -> C\n\nCombined inplace matrix-matrix or matrix-vector multiply-add A B α + C β. The result is stored in C by overwriting it. Note that C must not be aliased with either A or B.\n\ncompat: Julia 1.3\nFive-argument mul! requires at least Julia 1.3.\n\nExamples\n\njulia> A=[1.0 2.0; 3.0 4.0]; B=[1.0 1.0; 1.0 1.0]; C=[1.0 2.0; 3.0 4.0];\n\njulia> mul!(C, A, B, 100.0, 10.0) === C\ntrue\n\njulia> C\n2×2 Matrix{Float64}:\n 310.0 320.0\n 730.0 740.0\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LinearAlgebra/#LinearAlgebra.lmul!","page":"Linear Algebra","title":"LinearAlgebra.lmul!","text":"lmul!(a::Number, B::AbstractArray)\n\nScale an array B by a scalar a overwriting B in-place. Use rmul! to multiply scalar from right. The scaling operation respects the semantics of the multiplication * between a and an element of B. In particular, this also applies to multiplication involving non-finite numbers such as NaN and ±Inf.\n\ncompat: Julia 1.1\nPrior to Julia 1.1, NaN and ±Inf entries in B were treated inconsistently.\n\nExamples\n\njulia> B = [1 2; 3 4]\n2×2 Matrix{Int64}:\n 1 2\n 3 4\n\njulia> lmul!(2, B)\n2×2 Matrix{Int64}:\n 2 4\n 6 8\n\njulia> lmul!(0.0, [Inf])\n1-element Vector{Float64}:\n NaN\n\n\n\n\n\nlmul!(A, B)\n\nCalculate the matrix-matrix product AB, overwriting B, and return the result. Here, A must be of special matrix type, like, e.g., Diagonal, UpperTriangular or LowerTriangular, or of some orthogonal type, see QR.\n\nExamples\n\njulia> B = [0 1; 1 0];\n\njulia> A = LinearAlgebra.UpperTriangular([1 2; 0 3]);\n\njulia> LinearAlgebra.lmul!(A, B);\n\njulia> B\n2×2 Matrix{Int64}:\n 2 1\n 3 0\n\njulia> B = [1.0 2.0; 3.0 4.0];\n\njulia> F = qr([0 1; -1 0]);\n\njulia> lmul!(F.Q, B)\n2×2 Matrix{Float64}:\n 3.0 4.0\n 1.0 2.0\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LinearAlgebra/#LinearAlgebra.rmul!","page":"Linear Algebra","title":"LinearAlgebra.rmul!","text":"rmul!(A::AbstractArray, b::Number)\n\nScale an array A by a scalar b overwriting A in-place. Use lmul! to multiply scalar from left. The scaling operation respects the semantics of the multiplication * between an element of A and b. In particular, this also applies to multiplication involving non-finite numbers such as NaN and ±Inf.\n\ncompat: Julia 1.1\nPrior to Julia 1.1, NaN and ±Inf entries in A were treated inconsistently.\n\nExamples\n\njulia> A = [1 2; 3 4]\n2×2 Matrix{Int64}:\n 1 2\n 3 4\n\njulia> rmul!(A, 2)\n2×2 Matrix{Int64}:\n 2 4\n 6 8\n\njulia> rmul!([NaN], 0.0)\n1-element Vector{Float64}:\n NaN\n\n\n\n\n\nrmul!(A, B)\n\nCalculate the matrix-matrix product AB, overwriting A, and return the result. Here, B must be of special matrix type, like, e.g., Diagonal, UpperTriangular or LowerTriangular, or of some orthogonal type, see QR.\n\nExamples\n\njulia> A = [0 1; 1 0];\n\njulia> B = LinearAlgebra.UpperTriangular([1 2; 0 3]);\n\njulia> LinearAlgebra.rmul!(A, B);\n\njulia> A\n2×2 Matrix{Int64}:\n 0 3\n 1 2\n\njulia> A = [1.0 2.0; 3.0 4.0];\n\njulia> F = qr([0 1; -1 0]);\n\njulia> rmul!(A, F.Q)\n2×2 Matrix{Float64}:\n 2.0 1.0\n 4.0 3.0\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LinearAlgebra/#LinearAlgebra.ldiv!","page":"Linear Algebra","title":"LinearAlgebra.ldiv!","text":"ldiv!(Y, A, B) -> Y\n\nCompute A \\ B in-place and store the result in Y, returning the result.\n\nThe argument A should not be a matrix. Rather, instead of matrices it should be a factorization object (e.g. produced by factorize or cholesky). The reason for this is that factorization itself is both expensive and typically allocates memory (although it can also be done in-place via, e.g., lu!), and performance-critical situations requiring ldiv! usually also require fine-grained control over the factorization of A.\n\nExamples\n\njulia> A = [1 2.2 4; 3.1 0.2 3; 4 1 2];\n\njulia> X = [1; 2.5; 3];\n\njulia> Y = zero(X);\n\njulia> ldiv!(Y, qr(A), X);\n\njulia> Y\n3-element Vector{Float64}:\n 0.7128099173553719\n -0.051652892561983674\n 0.10020661157024757\n\njulia> A\\X\n3-element Vector{Float64}:\n 0.7128099173553719\n -0.05165289256198333\n 0.10020661157024785\n\n\n\n\n\nldiv!(A, B)\n\nCompute A \\ B in-place and overwriting B to store the result.\n\nThe argument A should not be a matrix. Rather, instead of matrices it should be a factorization object (e.g. produced by factorize or cholesky). The reason for this is that factorization itself is both expensive and typically allocates memory (although it can also be done in-place via, e.g., lu!), and performance-critical situations requiring ldiv! usually also require fine-grained control over the factorization of A.\n\nExamples\n\njulia> A = [1 2.2 4; 3.1 0.2 3; 4 1 2];\n\njulia> X = [1; 2.5; 3];\n\njulia> Y = copy(X);\n\njulia> ldiv!(qr(A), X);\n\njulia> X\n3-element Vector{Float64}:\n 0.7128099173553719\n -0.051652892561983674\n 0.10020661157024757\n\njulia> A\\Y\n3-element Vector{Float64}:\n 0.7128099173553719\n -0.05165289256198333\n 0.10020661157024785\n\n\n\n\n\nldiv!(a::Number, B::AbstractArray)\n\nDivide each entry in an array B by a scalar a overwriting B in-place. Use rdiv! to divide scalar from right.\n\nExamples\n\njulia> B = [1.0 2.0; 3.0 4.0]\n2×2 Matrix{Float64}:\n 1.0 2.0\n 3.0 4.0\n\njulia> ldiv!(2.0, B)\n2×2 Matrix{Float64}:\n 0.5 1.0\n 1.5 2.0\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LinearAlgebra/#LinearAlgebra.rdiv!","page":"Linear Algebra","title":"LinearAlgebra.rdiv!","text":"rdiv!(A, B)\n\nCompute A / B in-place and overwriting A to store the result.\n\nThe argument B should not be a matrix. Rather, instead of matrices it should be a factorization object (e.g. produced by factorize or cholesky). The reason for this is that factorization itself is both expensive and typically allocates memory (although it can also be done in-place via, e.g., lu!), and performance-critical situations requiring rdiv! usually also require fine-grained control over the factorization of B.\n\n\n\n\n\nrdiv!(A::AbstractArray, b::Number)\n\nDivide each entry in an array A by a scalar b overwriting A in-place. Use ldiv! to divide scalar from left.\n\nExamples\n\njulia> A = [1.0 2.0; 3.0 4.0]\n2×2 Matrix{Float64}:\n 1.0 2.0\n 3.0 4.0\n\njulia> rdiv!(A, 2.0)\n2×2 Matrix{Float64}:\n 0.5 1.0\n 1.5 2.0\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LinearAlgebra/#BLAS-functions","page":"Linear Algebra","title":"BLAS functions","text":"","category":"section"},{"location":"stdlib/LinearAlgebra/","page":"Linear Algebra","title":"Linear Algebra","text":"In Julia (as in much of scientific computation), dense linear-algebra operations are based on the LAPACK library, which in turn is built on top of basic linear-algebra building-blocks known as the BLAS. There are highly optimized implementations of BLAS available for every computer architecture, and sometimes in high-performance linear algebra routines it is useful to call the BLAS functions directly.","category":"page"},{"location":"stdlib/LinearAlgebra/","page":"Linear Algebra","title":"Linear Algebra","text":"LinearAlgebra.BLAS provides wrappers for some of the BLAS functions. Those BLAS functions that overwrite one of the input arrays have names ending in '!'. Usually, a BLAS function has four methods defined, for Float64, Float32, ComplexF64, and ComplexF32 arrays.","category":"page"},{"location":"stdlib/LinearAlgebra/#stdlib-blas-chars","page":"Linear Algebra","title":"BLAS character arguments","text":"","category":"section"},{"location":"stdlib/LinearAlgebra/","page":"Linear Algebra","title":"Linear Algebra","text":"Many BLAS functions accept arguments that determine whether to transpose an argument (trans), which triangle of a matrix to reference (uplo or ul), whether the diagonal of a triangular matrix can be assumed to be all ones (dA) or which side of a matrix multiplication the input argument belongs on (side). The possibilities are:","category":"page"},{"location":"stdlib/LinearAlgebra/#stdlib-blas-side","page":"Linear Algebra","title":"Multiplication order","text":"","category":"section"},{"location":"stdlib/LinearAlgebra/","page":"Linear Algebra","title":"Linear Algebra","text":"side Meaning\n'L' The argument goes on the left side of a matrix-matrix operation.\n'R' The argument goes on the right side of a matrix-matrix operation.","category":"page"},{"location":"stdlib/LinearAlgebra/#stdlib-blas-uplo","page":"Linear Algebra","title":"Triangle referencing","text":"","category":"section"},{"location":"stdlib/LinearAlgebra/","page":"Linear Algebra","title":"Linear Algebra","text":"uplo/ul Meaning\n'U' Only the upper triangle of the matrix will be used.\n'L' Only the lower triangle of the matrix will be used.","category":"page"},{"location":"stdlib/LinearAlgebra/#stdlib-blas-trans","page":"Linear Algebra","title":"Transposition operation","text":"","category":"section"},{"location":"stdlib/LinearAlgebra/","page":"Linear Algebra","title":"Linear Algebra","text":"trans/tX Meaning\n'N' The input matrix X is not transposed or conjugated.\n'T' The input matrix X will be transposed.\n'C' The input matrix X will be conjugated and transposed.","category":"page"},{"location":"stdlib/LinearAlgebra/#stdlib-blas-diag","page":"Linear Algebra","title":"Unit diagonal","text":"","category":"section"},{"location":"stdlib/LinearAlgebra/","page":"Linear Algebra","title":"Linear Algebra","text":"diag/dX Meaning\n'N' The diagonal values of the matrix X will be read.\n'U' The diagonal of the matrix X is assumed to be all ones.","category":"page"},{"location":"stdlib/LinearAlgebra/","page":"Linear Algebra","title":"Linear Algebra","text":"LinearAlgebra.BLAS\nLinearAlgebra.BLAS.dot\nLinearAlgebra.BLAS.dotu\nLinearAlgebra.BLAS.dotc\nLinearAlgebra.BLAS.blascopy!\nLinearAlgebra.BLAS.nrm2\nLinearAlgebra.BLAS.asum\nLinearAlgebra.axpy!\nLinearAlgebra.axpby!\nLinearAlgebra.BLAS.scal!\nLinearAlgebra.BLAS.scal\nLinearAlgebra.BLAS.iamax\nLinearAlgebra.BLAS.ger!\nLinearAlgebra.BLAS.syr!\nLinearAlgebra.BLAS.syrk!\nLinearAlgebra.BLAS.syrk\nLinearAlgebra.BLAS.syr2k!\nLinearAlgebra.BLAS.syr2k\nLinearAlgebra.BLAS.her!\nLinearAlgebra.BLAS.herk!\nLinearAlgebra.BLAS.herk\nLinearAlgebra.BLAS.her2k!\nLinearAlgebra.BLAS.her2k\nLinearAlgebra.BLAS.gbmv!\nLinearAlgebra.BLAS.gbmv\nLinearAlgebra.BLAS.sbmv!\nLinearAlgebra.BLAS.sbmv(::Any, ::Any, ::Any, ::Any, ::Any)\nLinearAlgebra.BLAS.sbmv(::Any, ::Any, ::Any, ::Any)\nLinearAlgebra.BLAS.gemm!\nLinearAlgebra.BLAS.gemm(::Any, ::Any, ::Any, ::Any, ::Any)\nLinearAlgebra.BLAS.gemm(::Any, ::Any, ::Any, ::Any)\nLinearAlgebra.BLAS.gemv!\nLinearAlgebra.BLAS.gemv(::Any, ::Any, ::Any, ::Any)\nLinearAlgebra.BLAS.gemv(::Any, ::Any, ::Any)\nLinearAlgebra.BLAS.symm!\nLinearAlgebra.BLAS.symm(::Any, ::Any, ::Any, ::Any, ::Any)\nLinearAlgebra.BLAS.symm(::Any, ::Any, ::Any, ::Any)\nLinearAlgebra.BLAS.symv!\nLinearAlgebra.BLAS.symv(::Any, ::Any, ::Any, ::Any)\nLinearAlgebra.BLAS.symv(::Any, ::Any, ::Any)\nLinearAlgebra.BLAS.hemm!\nLinearAlgebra.BLAS.hemm(::Any, ::Any, ::Any, ::Any, ::Any)\nLinearAlgebra.BLAS.hemm(::Any, ::Any, ::Any, ::Any)\nLinearAlgebra.BLAS.hemv!\nLinearAlgebra.BLAS.hemv(::Any, ::Any, ::Any, ::Any)\nLinearAlgebra.BLAS.hemv(::Any, ::Any, ::Any)\nLinearAlgebra.BLAS.trmm!\nLinearAlgebra.BLAS.trmm\nLinearAlgebra.BLAS.trsm!\nLinearAlgebra.BLAS.trsm\nLinearAlgebra.BLAS.trmv!\nLinearAlgebra.BLAS.trmv\nLinearAlgebra.BLAS.trsv!\nLinearAlgebra.BLAS.trsv\nLinearAlgebra.BLAS.set_num_threads\nLinearAlgebra.BLAS.get_num_threads","category":"page"},{"location":"stdlib/LinearAlgebra/#LinearAlgebra.BLAS","page":"Linear Algebra","title":"LinearAlgebra.BLAS","text":"Interface to BLAS subroutines.\n\n\n\n\n\n","category":"module"},{"location":"stdlib/LinearAlgebra/#LinearAlgebra.BLAS.dot","page":"Linear Algebra","title":"LinearAlgebra.BLAS.dot","text":"dot(n, X, incx, Y, incy)\n\nDot product of two vectors consisting of n elements of array X with stride incx and n elements of array Y with stride incy.\n\nExamples\n\njulia> BLAS.dot(10, fill(1.0, 10), 1, fill(1.0, 20), 2)\n10.0\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LinearAlgebra/#LinearAlgebra.BLAS.dotu","page":"Linear Algebra","title":"LinearAlgebra.BLAS.dotu","text":"dotu(n, X, incx, Y, incy)\n\nDot function for two complex vectors consisting of n elements of array X with stride incx and n elements of array Y with stride incy.\n\nExamples\n\njulia> BLAS.dotu(10, fill(1.0im, 10), 1, fill(1.0+im, 20), 2)\n-10.0 + 10.0im\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LinearAlgebra/#LinearAlgebra.BLAS.dotc","page":"Linear Algebra","title":"LinearAlgebra.BLAS.dotc","text":"dotc(n, X, incx, U, incy)\n\nDot function for two complex vectors, consisting of n elements of array X with stride incx and n elements of array U with stride incy, conjugating the first vector.\n\nExamples\n\njulia> BLAS.dotc(10, fill(1.0im, 10), 1, fill(1.0+im, 20), 2)\n10.0 - 10.0im\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LinearAlgebra/#LinearAlgebra.BLAS.blascopy!","page":"Linear Algebra","title":"LinearAlgebra.BLAS.blascopy!","text":"blascopy!(n, X, incx, Y, incy)\n\nCopy n elements of array X with stride incx to array Y with stride incy. Returns Y.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LinearAlgebra/#LinearAlgebra.BLAS.nrm2","page":"Linear Algebra","title":"LinearAlgebra.BLAS.nrm2","text":"nrm2(n, X, incx)\n\n2-norm of a vector consisting of n elements of array X with stride incx.\n\nExamples\n\njulia> BLAS.nrm2(4, fill(1.0, 8), 2)\n2.0\n\njulia> BLAS.nrm2(1, fill(1.0, 8), 2)\n1.0\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LinearAlgebra/#LinearAlgebra.BLAS.asum","page":"Linear Algebra","title":"LinearAlgebra.BLAS.asum","text":"asum(n, X, incx)\n\nSum of the magnitudes of the first n elements of array X with stride incx.\n\nFor a real array, the magnitude is the absolute value. For a complex array, the magnitude is the sum of the absolute value of the real part and the absolute value of the imaginary part.\n\nExamples\n\njulia> BLAS.asum(5, fill(1.0im, 10), 2)\n5.0\n\njulia> BLAS.asum(2, fill(1.0im, 10), 5)\n2.0\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LinearAlgebra/#LinearAlgebra.axpy!","page":"Linear Algebra","title":"LinearAlgebra.axpy!","text":"axpy!(a, X, Y)\n\nOverwrite Y with X*a + Y, where a is a scalar. Return Y.\n\nExamples\n\njulia> x = [1; 2; 3];\n\njulia> y = [4; 5; 6];\n\njulia> BLAS.axpy!(2, x, y)\n3-element Vector{Int64}:\n 6\n 9\n 12\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LinearAlgebra/#LinearAlgebra.axpby!","page":"Linear Algebra","title":"LinearAlgebra.axpby!","text":"axpby!(a, X, b, Y)\n\nOverwrite Y with X*a + Y*b, where a and b are scalars. Return Y.\n\nExamples\n\njulia> x = [1., 2, 3];\n\njulia> y = [4., 5, 6];\n\njulia> BLAS.axpby!(2., x, 3., y)\n3-element Vector{Float64}:\n 14.0\n 19.0\n 24.0\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LinearAlgebra/#LinearAlgebra.BLAS.scal!","page":"Linear Algebra","title":"LinearAlgebra.BLAS.scal!","text":"scal!(n, a, X, incx)\nscal!(a, X)\n\nOverwrite X with a*X for the first n elements of array X with stride incx. Returns X.\n\nIf n and incx are not provided, length(X) and stride(X,1) are used.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LinearAlgebra/#LinearAlgebra.BLAS.scal","page":"Linear Algebra","title":"LinearAlgebra.BLAS.scal","text":"scal(n, a, X, incx)\nscal(a, X)\n\nReturn X scaled by a for the first n elements of array X with stride incx.\n\nIf n and incx are not provided, length(X) and stride(X,1) are used.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LinearAlgebra/#LinearAlgebra.BLAS.iamax","page":"Linear Algebra","title":"LinearAlgebra.BLAS.iamax","text":"iamax(n, dx, incx)\niamax(dx)\n\nFind the index of the element of dx with the maximum absolute value. n is the length of dx, and incx is the stride. If n and incx are not provided, they assume default values of n=length(dx) and incx=stride1(dx).\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LinearAlgebra/#LinearAlgebra.BLAS.ger!","page":"Linear Algebra","title":"LinearAlgebra.BLAS.ger!","text":"ger!(alpha, x, y, A)\n\nRank-1 update of the matrix A with vectors x and y as alpha*x*y' + A.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LinearAlgebra/#LinearAlgebra.BLAS.syr!","page":"Linear Algebra","title":"LinearAlgebra.BLAS.syr!","text":"syr!(uplo, alpha, x, A)\n\nRank-1 update of the symmetric matrix A with vector x as alpha*x*transpose(x) + A. uplo controls which triangle of A is updated. Returns A.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LinearAlgebra/#LinearAlgebra.BLAS.syrk!","page":"Linear Algebra","title":"LinearAlgebra.BLAS.syrk!","text":"syrk!(uplo, trans, alpha, A, beta, C)\n\nRank-k update of the symmetric matrix C as alpha*A*transpose(A) + beta*C or alpha*transpose(A)*A + beta*C according to trans. Only the uplo triangle of C is used. Returns C.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LinearAlgebra/#LinearAlgebra.BLAS.syrk","page":"Linear Algebra","title":"LinearAlgebra.BLAS.syrk","text":"syrk(uplo, trans, alpha, A)\n\nReturns either the upper triangle or the lower triangle of A, according to uplo, of alpha*A*transpose(A) or alpha*transpose(A)*A, according to trans.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LinearAlgebra/#LinearAlgebra.BLAS.syr2k!","page":"Linear Algebra","title":"LinearAlgebra.BLAS.syr2k!","text":"syr2k!(uplo, trans, alpha, A, B, beta, C)\n\nRank-2k update of the symmetric matrix C as alpha*A*transpose(B) + alpha*B*transpose(A) + beta*C or alpha*transpose(A)*B + alpha*transpose(B)*A + beta*C according to trans. Only the uplo triangle of C is used. Returns C.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LinearAlgebra/#LinearAlgebra.BLAS.syr2k","page":"Linear Algebra","title":"LinearAlgebra.BLAS.syr2k","text":"syr2k(uplo, trans, alpha, A, B)\n\nReturns the uplo triangle of alpha*A*transpose(B) + alpha*B*transpose(A) or alpha*transpose(A)*B + alpha*transpose(B)*A, according to trans.\n\n\n\n\n\nsyr2k(uplo, trans, A, B)\n\nReturns the uplo triangle of A*transpose(B) + B*transpose(A) or transpose(A)*B + transpose(B)*A, according to trans.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LinearAlgebra/#LinearAlgebra.BLAS.her!","page":"Linear Algebra","title":"LinearAlgebra.BLAS.her!","text":"her!(uplo, alpha, x, A)\n\nMethods for complex arrays only. Rank-1 update of the Hermitian matrix A with vector x as alpha*x*x' + A. uplo controls which triangle of A is updated. Returns A.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LinearAlgebra/#LinearAlgebra.BLAS.herk!","page":"Linear Algebra","title":"LinearAlgebra.BLAS.herk!","text":"herk!(uplo, trans, alpha, A, beta, C)\n\nMethods for complex arrays only. Rank-k update of the Hermitian matrix C as alpha*A*A' + beta*C or alpha*A'*A + beta*C according to trans. Only the uplo triangle of C is updated. Returns C.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LinearAlgebra/#LinearAlgebra.BLAS.herk","page":"Linear Algebra","title":"LinearAlgebra.BLAS.herk","text":"herk(uplo, trans, alpha, A)\n\nMethods for complex arrays only. Returns the uplo triangle of alpha*A*A' or alpha*A'*A, according to trans.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LinearAlgebra/#LinearAlgebra.BLAS.her2k!","page":"Linear Algebra","title":"LinearAlgebra.BLAS.her2k!","text":"her2k!(uplo, trans, alpha, A, B, beta, C)\n\nRank-2k update of the Hermitian matrix C as alpha*A*B' + alpha*B*A' + beta*C or alpha*A'*B + alpha*B'*A + beta*C according to trans. The scalar beta has to be real. Only the uplo triangle of C is used. Returns C.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LinearAlgebra/#LinearAlgebra.BLAS.her2k","page":"Linear Algebra","title":"LinearAlgebra.BLAS.her2k","text":"her2k(uplo, trans, alpha, A, B)\n\nReturns the uplo triangle of alpha*A*B' + alpha*B*A' or alpha*A'*B + alpha*B'*A, according to trans.\n\n\n\n\n\nher2k(uplo, trans, A, B)\n\nReturns the uplo triangle of A*B' + B*A' or A'*B + B'*A, according to trans.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LinearAlgebra/#LinearAlgebra.BLAS.gbmv!","page":"Linear Algebra","title":"LinearAlgebra.BLAS.gbmv!","text":"gbmv!(trans, m, kl, ku, alpha, A, x, beta, y)\n\nUpdate vector y as alpha*A*x + beta*y or alpha*A'*x + beta*y according to trans. The matrix A is a general band matrix of dimension m by size(A,2) with kl sub-diagonals and ku super-diagonals. alpha and beta are scalars. Return the updated y.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LinearAlgebra/#LinearAlgebra.BLAS.gbmv","page":"Linear Algebra","title":"LinearAlgebra.BLAS.gbmv","text":"gbmv(trans, m, kl, ku, alpha, A, x)\n\nReturn alpha*A*x or alpha*A'*x according to trans. The matrix A is a general band matrix of dimension m by size(A,2) with kl sub-diagonals and ku super-diagonals, and alpha is a scalar.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LinearAlgebra/#LinearAlgebra.BLAS.sbmv!","page":"Linear Algebra","title":"LinearAlgebra.BLAS.sbmv!","text":"sbmv!(uplo, k, alpha, A, x, beta, y)\n\nUpdate vector y as alpha*A*x + beta*y where A is a symmetric band matrix of order size(A,2) with k super-diagonals stored in the argument A. The storage layout for A is described the reference BLAS module, level-2 BLAS at http://www.netlib.org/lapack/explore-html/. Only the uplo triangle of A is used.\n\nReturn the updated y.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LinearAlgebra/#LinearAlgebra.BLAS.sbmv-NTuple{5, Any}","page":"Linear Algebra","title":"LinearAlgebra.BLAS.sbmv","text":"sbmv(uplo, k, alpha, A, x)\n\nReturn alpha*A*x where A is a symmetric band matrix of order size(A,2) with k super-diagonals stored in the argument A. Only the uplo triangle of A is used.\n\n\n\n\n\n","category":"method"},{"location":"stdlib/LinearAlgebra/#LinearAlgebra.BLAS.sbmv-NTuple{4, Any}","page":"Linear Algebra","title":"LinearAlgebra.BLAS.sbmv","text":"sbmv(uplo, k, A, x)\n\nReturn A*x where A is a symmetric band matrix of order size(A,2) with k super-diagonals stored in the argument A. Only the uplo triangle of A is used.\n\n\n\n\n\n","category":"method"},{"location":"stdlib/LinearAlgebra/#LinearAlgebra.BLAS.gemm!","page":"Linear Algebra","title":"LinearAlgebra.BLAS.gemm!","text":"gemm!(tA, tB, alpha, A, B, beta, C)\n\nUpdate C as alpha*A*B + beta*C or the other three variants according to tA and tB. Return the updated C.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LinearAlgebra/#LinearAlgebra.BLAS.gemm-NTuple{5, Any}","page":"Linear Algebra","title":"LinearAlgebra.BLAS.gemm","text":"gemm(tA, tB, alpha, A, B)\n\nReturn alpha*A*B or the other three variants according to tA and tB.\n\n\n\n\n\n","category":"method"},{"location":"stdlib/LinearAlgebra/#LinearAlgebra.BLAS.gemm-NTuple{4, Any}","page":"Linear Algebra","title":"LinearAlgebra.BLAS.gemm","text":"gemm(tA, tB, A, B)\n\nReturn A*B or the other three variants according to tA and tB.\n\n\n\n\n\n","category":"method"},{"location":"stdlib/LinearAlgebra/#LinearAlgebra.BLAS.gemv!","page":"Linear Algebra","title":"LinearAlgebra.BLAS.gemv!","text":"gemv!(tA, alpha, A, x, beta, y)\n\nUpdate the vector y as alpha*A*x + beta*y or alpha*A'x + beta*y according to tA. alpha and beta are scalars. Return the updated y.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LinearAlgebra/#LinearAlgebra.BLAS.gemv-NTuple{4, Any}","page":"Linear Algebra","title":"LinearAlgebra.BLAS.gemv","text":"gemv(tA, alpha, A, x)\n\nReturn alpha*A*x or alpha*A'x according to tA. alpha is a scalar.\n\n\n\n\n\n","category":"method"},{"location":"stdlib/LinearAlgebra/#LinearAlgebra.BLAS.gemv-Tuple{Any, Any, Any}","page":"Linear Algebra","title":"LinearAlgebra.BLAS.gemv","text":"gemv(tA, A, x)\n\nReturn A*x or A'x according to tA.\n\n\n\n\n\n","category":"method"},{"location":"stdlib/LinearAlgebra/#LinearAlgebra.BLAS.symm!","page":"Linear Algebra","title":"LinearAlgebra.BLAS.symm!","text":"symm!(side, ul, alpha, A, B, beta, C)\n\nUpdate C as alpha*A*B + beta*C or alpha*B*A + beta*C according to side. A is assumed to be symmetric. Only the ul triangle of A is used. Return the updated C.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LinearAlgebra/#LinearAlgebra.BLAS.symm-NTuple{5, Any}","page":"Linear Algebra","title":"LinearAlgebra.BLAS.symm","text":"symm(side, ul, alpha, A, B)\n\nReturn alpha*A*B or alpha*B*A according to side. A is assumed to be symmetric. Only the ul triangle of A is used.\n\n\n\n\n\n","category":"method"},{"location":"stdlib/LinearAlgebra/#LinearAlgebra.BLAS.symm-NTuple{4, Any}","page":"Linear Algebra","title":"LinearAlgebra.BLAS.symm","text":"symm(side, ul, A, B)\n\nReturn A*B or B*A according to side. A is assumed to be symmetric. Only the ul triangle of A is used.\n\n\n\n\n\n","category":"method"},{"location":"stdlib/LinearAlgebra/#LinearAlgebra.BLAS.symv!","page":"Linear Algebra","title":"LinearAlgebra.BLAS.symv!","text":"symv!(ul, alpha, A, x, beta, y)\n\nUpdate the vector y as alpha*A*x + beta*y. A is assumed to be symmetric. Only the ul triangle of A is used. alpha and beta are scalars. Return the updated y.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LinearAlgebra/#LinearAlgebra.BLAS.symv-NTuple{4, Any}","page":"Linear Algebra","title":"LinearAlgebra.BLAS.symv","text":"symv(ul, alpha, A, x)\n\nReturn alpha*A*x. A is assumed to be symmetric. Only the ul triangle of A is used. alpha is a scalar.\n\n\n\n\n\n","category":"method"},{"location":"stdlib/LinearAlgebra/#LinearAlgebra.BLAS.symv-Tuple{Any, Any, Any}","page":"Linear Algebra","title":"LinearAlgebra.BLAS.symv","text":"symv(ul, A, x)\n\nReturn A*x. A is assumed to be symmetric. Only the ul triangle of A is used.\n\n\n\n\n\n","category":"method"},{"location":"stdlib/LinearAlgebra/#LinearAlgebra.BLAS.hemm!","page":"Linear Algebra","title":"LinearAlgebra.BLAS.hemm!","text":"hemm!(side, ul, alpha, A, B, beta, C)\n\nUpdate C as alpha*A*B + beta*C or alpha*B*A + beta*C according to side. A is assumed to be Hermitian. Only the ul triangle of A is used. Return the updated C.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LinearAlgebra/#LinearAlgebra.BLAS.hemm-NTuple{5, Any}","page":"Linear Algebra","title":"LinearAlgebra.BLAS.hemm","text":"hemm(side, ul, alpha, A, B)\n\nReturn alpha*A*B or alpha*B*A according to side. A is assumed to be Hermitian. Only the ul triangle of A is used.\n\n\n\n\n\n","category":"method"},{"location":"stdlib/LinearAlgebra/#LinearAlgebra.BLAS.hemm-NTuple{4, Any}","page":"Linear Algebra","title":"LinearAlgebra.BLAS.hemm","text":"hemm(side, ul, A, B)\n\nReturn A*B or B*A according to side. A is assumed to be Hermitian. Only the ul triangle of A is used.\n\n\n\n\n\n","category":"method"},{"location":"stdlib/LinearAlgebra/#LinearAlgebra.BLAS.hemv!","page":"Linear Algebra","title":"LinearAlgebra.BLAS.hemv!","text":"hemv!(ul, alpha, A, x, beta, y)\n\nUpdate the vector y as alpha*A*x + beta*y. A is assumed to be Hermitian. Only the ul triangle of A is used. alpha and beta are scalars. Return the updated y.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LinearAlgebra/#LinearAlgebra.BLAS.hemv-NTuple{4, Any}","page":"Linear Algebra","title":"LinearAlgebra.BLAS.hemv","text":"hemv(ul, alpha, A, x)\n\nReturn alpha*A*x. A is assumed to be Hermitian. Only the ul triangle of A is used. alpha is a scalar.\n\n\n\n\n\n","category":"method"},{"location":"stdlib/LinearAlgebra/#LinearAlgebra.BLAS.hemv-Tuple{Any, Any, Any}","page":"Linear Algebra","title":"LinearAlgebra.BLAS.hemv","text":"hemv(ul, A, x)\n\nReturn A*x. A is assumed to be Hermitian. Only the ul triangle of A is used.\n\n\n\n\n\n","category":"method"},{"location":"stdlib/LinearAlgebra/#LinearAlgebra.BLAS.trmm!","page":"Linear Algebra","title":"LinearAlgebra.BLAS.trmm!","text":"trmm!(side, ul, tA, dA, alpha, A, B)\n\nUpdate B as alpha*A*B or one of the other three variants determined by side and tA. Only the ul triangle of A is used. dA determines if the diagonal values are read or are assumed to be all ones. Returns the updated B.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LinearAlgebra/#LinearAlgebra.BLAS.trmm","page":"Linear Algebra","title":"LinearAlgebra.BLAS.trmm","text":"trmm(side, ul, tA, dA, alpha, A, B)\n\nReturns alpha*A*B or one of the other three variants determined by side and tA. Only the ul triangle of A is used. dA determines if the diagonal values are read or are assumed to be all ones.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LinearAlgebra/#LinearAlgebra.BLAS.trsm!","page":"Linear Algebra","title":"LinearAlgebra.BLAS.trsm!","text":"trsm!(side, ul, tA, dA, alpha, A, B)\n\nOverwrite B with the solution to A*X = alpha*B or one of the other three variants determined by side and tA. Only the ul triangle of A is used. dA determines if the diagonal values are read or are assumed to be all ones. Returns the updated B.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LinearAlgebra/#LinearAlgebra.BLAS.trsm","page":"Linear Algebra","title":"LinearAlgebra.BLAS.trsm","text":"trsm(side, ul, tA, dA, alpha, A, B)\n\nReturn the solution to A*X = alpha*B or one of the other three variants determined by determined by side and tA. Only the ul triangle of A is used. dA determines if the diagonal values are read or are assumed to be all ones.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LinearAlgebra/#LinearAlgebra.BLAS.trmv!","page":"Linear Algebra","title":"LinearAlgebra.BLAS.trmv!","text":"trmv!(ul, tA, dA, A, b)\n\nReturn op(A)*b, where op is determined by tA. Only the ul triangle of A is used. dA determines if the diagonal values are read or are assumed to be all ones. The multiplication occurs in-place on b.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LinearAlgebra/#LinearAlgebra.BLAS.trmv","page":"Linear Algebra","title":"LinearAlgebra.BLAS.trmv","text":"trmv(ul, tA, dA, A, b)\n\nReturn op(A)*b, where op is determined by tA. Only the ul triangle of A is used. dA determines if the diagonal values are read or are assumed to be all ones.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LinearAlgebra/#LinearAlgebra.BLAS.trsv!","page":"Linear Algebra","title":"LinearAlgebra.BLAS.trsv!","text":"trsv!(ul, tA, dA, A, b)\n\nOverwrite b with the solution to A*x = b or one of the other two variants determined by tA and ul. dA determines if the diagonal values are read or are assumed to be all ones. Return the updated b.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LinearAlgebra/#LinearAlgebra.BLAS.trsv","page":"Linear Algebra","title":"LinearAlgebra.BLAS.trsv","text":"trsv(ul, tA, dA, A, b)\n\nReturn the solution to A*x = b or one of the other two variants determined by tA and ul. dA determines if the diagonal values are read or are assumed to be all ones.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LinearAlgebra/#LinearAlgebra.BLAS.set_num_threads","page":"Linear Algebra","title":"LinearAlgebra.BLAS.set_num_threads","text":"set_num_threads(n::Integer)\nset_num_threads(::Nothing)\n\nSet the number of threads the BLAS library should use equal to n::Integer.\n\nAlso accepts nothing, in which case julia tries to guess the default number of threads. Passing nothing is discouraged and mainly exists for historical reasons.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LinearAlgebra/#LinearAlgebra.BLAS.get_num_threads","page":"Linear Algebra","title":"LinearAlgebra.BLAS.get_num_threads","text":"get_num_threads()\n\nGet the number of threads the BLAS library is using.\n\ncompat: Julia 1.6\nget_num_threads requires at least Julia 1.6.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LinearAlgebra/#LAPACK-functions","page":"Linear Algebra","title":"LAPACK functions","text":"","category":"section"},{"location":"stdlib/LinearAlgebra/","page":"Linear Algebra","title":"Linear Algebra","text":"LinearAlgebra.LAPACK provides wrappers for some of the LAPACK functions for linear algebra. Those functions that overwrite one of the input arrays have names ending in '!'.","category":"page"},{"location":"stdlib/LinearAlgebra/","page":"Linear Algebra","title":"Linear Algebra","text":"Usually a function has 4 methods defined, one each for Float64, Float32, ComplexF64 and ComplexF32 arrays.","category":"page"},{"location":"stdlib/LinearAlgebra/","page":"Linear Algebra","title":"Linear Algebra","text":"Note that the LAPACK API provided by Julia can and will change in the future. Since this API is not user-facing, there is no commitment to support/deprecate this specific set of functions in future releases.","category":"page"},{"location":"stdlib/LinearAlgebra/","page":"Linear Algebra","title":"Linear Algebra","text":"LinearAlgebra.LAPACK\nLinearAlgebra.LAPACK.gbtrf!\nLinearAlgebra.LAPACK.gbtrs!\nLinearAlgebra.LAPACK.gebal!\nLinearAlgebra.LAPACK.gebak!\nLinearAlgebra.LAPACK.gebrd!\nLinearAlgebra.LAPACK.gelqf!\nLinearAlgebra.LAPACK.geqlf!\nLinearAlgebra.LAPACK.geqrf!\nLinearAlgebra.LAPACK.geqp3!\nLinearAlgebra.LAPACK.gerqf!\nLinearAlgebra.LAPACK.geqrt!\nLinearAlgebra.LAPACK.geqrt3!\nLinearAlgebra.LAPACK.getrf!\nLinearAlgebra.LAPACK.tzrzf!\nLinearAlgebra.LAPACK.ormrz!\nLinearAlgebra.LAPACK.gels!\nLinearAlgebra.LAPACK.gesv!\nLinearAlgebra.LAPACK.getrs!\nLinearAlgebra.LAPACK.getri!\nLinearAlgebra.LAPACK.gesvx!\nLinearAlgebra.LAPACK.gelsd!\nLinearAlgebra.LAPACK.gelsy!\nLinearAlgebra.LAPACK.gglse!\nLinearAlgebra.LAPACK.geev!\nLinearAlgebra.LAPACK.gesdd!\nLinearAlgebra.LAPACK.gesvd!\nLinearAlgebra.LAPACK.ggsvd!\nLinearAlgebra.LAPACK.ggsvd3!\nLinearAlgebra.LAPACK.geevx!\nLinearAlgebra.LAPACK.ggev!\nLinearAlgebra.LAPACK.gtsv!\nLinearAlgebra.LAPACK.gttrf!\nLinearAlgebra.LAPACK.gttrs!\nLinearAlgebra.LAPACK.orglq!\nLinearAlgebra.LAPACK.orgqr!\nLinearAlgebra.LAPACK.orgql!\nLinearAlgebra.LAPACK.orgrq!\nLinearAlgebra.LAPACK.ormlq!\nLinearAlgebra.LAPACK.ormqr!\nLinearAlgebra.LAPACK.ormql!\nLinearAlgebra.LAPACK.ormrq!\nLinearAlgebra.LAPACK.gemqrt!\nLinearAlgebra.LAPACK.posv!\nLinearAlgebra.LAPACK.potrf!\nLinearAlgebra.LAPACK.potri!\nLinearAlgebra.LAPACK.potrs!\nLinearAlgebra.LAPACK.pstrf!\nLinearAlgebra.LAPACK.ptsv!\nLinearAlgebra.LAPACK.pttrf!\nLinearAlgebra.LAPACK.pttrs!\nLinearAlgebra.LAPACK.trtri!\nLinearAlgebra.LAPACK.trtrs!\nLinearAlgebra.LAPACK.trcon!\nLinearAlgebra.LAPACK.trevc!\nLinearAlgebra.LAPACK.trrfs!\nLinearAlgebra.LAPACK.stev!\nLinearAlgebra.LAPACK.stebz!\nLinearAlgebra.LAPACK.stegr!\nLinearAlgebra.LAPACK.stein!\nLinearAlgebra.LAPACK.syconv!\nLinearAlgebra.LAPACK.sysv!\nLinearAlgebra.LAPACK.sytrf!\nLinearAlgebra.LAPACK.sytri!\nLinearAlgebra.LAPACK.sytrs!\nLinearAlgebra.LAPACK.hesv!\nLinearAlgebra.LAPACK.hetrf!\nLinearAlgebra.LAPACK.hetri!\nLinearAlgebra.LAPACK.hetrs!\nLinearAlgebra.LAPACK.syev!\nLinearAlgebra.LAPACK.syevr!\nLinearAlgebra.LAPACK.sygvd!\nLinearAlgebra.LAPACK.bdsqr!\nLinearAlgebra.LAPACK.bdsdc!\nLinearAlgebra.LAPACK.gecon!\nLinearAlgebra.LAPACK.gehrd!\nLinearAlgebra.LAPACK.orghr!\nLinearAlgebra.LAPACK.gees!\nLinearAlgebra.LAPACK.gges!\nLinearAlgebra.LAPACK.trexc!\nLinearAlgebra.LAPACK.trsen!\nLinearAlgebra.LAPACK.tgsen!\nLinearAlgebra.LAPACK.trsyl!","category":"page"},{"location":"stdlib/LinearAlgebra/#LinearAlgebra.LAPACK","page":"Linear Algebra","title":"LinearAlgebra.LAPACK","text":"Interfaces to LAPACK subroutines.\n\n\n\n\n\n","category":"module"},{"location":"stdlib/LinearAlgebra/#LinearAlgebra.LAPACK.gbtrf!","page":"Linear Algebra","title":"LinearAlgebra.LAPACK.gbtrf!","text":"gbtrf!(kl, ku, m, AB) -> (AB, ipiv)\n\nCompute the LU factorization of a banded matrix AB. kl is the first subdiagonal containing a nonzero band, ku is the last superdiagonal containing one, and m is the first dimension of the matrix AB. Returns the LU factorization in-place and ipiv, the vector of pivots used.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LinearAlgebra/#LinearAlgebra.LAPACK.gbtrs!","page":"Linear Algebra","title":"LinearAlgebra.LAPACK.gbtrs!","text":"gbtrs!(trans, kl, ku, m, AB, ipiv, B)\n\nSolve the equation AB * X = B. trans determines the orientation of AB. It may be N (no transpose), T (transpose), or C (conjugate transpose). kl is the first subdiagonal containing a nonzero band, ku is the last superdiagonal containing one, and m is the first dimension of the matrix AB. ipiv is the vector of pivots returned from gbtrf!. Returns the vector or matrix X, overwriting B in-place.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LinearAlgebra/#LinearAlgebra.LAPACK.gebal!","page":"Linear Algebra","title":"LinearAlgebra.LAPACK.gebal!","text":"gebal!(job, A) -> (ilo, ihi, scale)\n\nBalance the matrix A before computing its eigensystem or Schur factorization. job can be one of N (A will not be permuted or scaled), P (A will only be permuted), S (A will only be scaled), or B (A will be both permuted and scaled). Modifies A in-place and returns ilo, ihi, and scale. If permuting was turned on, A[i,j] = 0 if j > i and 1 < j < ilo or j > ihi. scale contains information about the scaling/permutations performed.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LinearAlgebra/#LinearAlgebra.LAPACK.gebak!","page":"Linear Algebra","title":"LinearAlgebra.LAPACK.gebak!","text":"gebak!(job, side, ilo, ihi, scale, V)\n\nTransform the eigenvectors V of a matrix balanced using gebal! to the unscaled/unpermuted eigenvectors of the original matrix. Modifies V in-place. side can be L (left eigenvectors are transformed) or R (right eigenvectors are transformed).\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LinearAlgebra/#LinearAlgebra.LAPACK.gebrd!","page":"Linear Algebra","title":"LinearAlgebra.LAPACK.gebrd!","text":"gebrd!(A) -> (A, d, e, tauq, taup)\n\nReduce A in-place to bidiagonal form A = QBP'. Returns A, containing the bidiagonal matrix B; d, containing the diagonal elements of B; e, containing the off-diagonal elements of B; tauq, containing the elementary reflectors representing Q; and taup, containing the elementary reflectors representing P.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LinearAlgebra/#LinearAlgebra.LAPACK.gelqf!","page":"Linear Algebra","title":"LinearAlgebra.LAPACK.gelqf!","text":"gelqf!(A, tau)\n\nCompute the LQ factorization of A, A = LQ. tau contains scalars which parameterize the elementary reflectors of the factorization. tau must have length greater than or equal to the smallest dimension of A.\n\nReturns A and tau modified in-place.\n\n\n\n\n\ngelqf!(A) -> (A, tau)\n\nCompute the LQ factorization of A, A = LQ.\n\nReturns A, modified in-place, and tau, which contains scalars which parameterize the elementary reflectors of the factorization.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LinearAlgebra/#LinearAlgebra.LAPACK.geqlf!","page":"Linear Algebra","title":"LinearAlgebra.LAPACK.geqlf!","text":"geqlf!(A, tau)\n\nCompute the QL factorization of A, A = QL. tau contains scalars which parameterize the elementary reflectors of the factorization. tau must have length greater than or equal to the smallest dimension of A.\n\nReturns A and tau modified in-place.\n\n\n\n\n\ngeqlf!(A) -> (A, tau)\n\nCompute the QL factorization of A, A = QL.\n\nReturns A, modified in-place, and tau, which contains scalars which parameterize the elementary reflectors of the factorization.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LinearAlgebra/#LinearAlgebra.LAPACK.geqrf!","page":"Linear Algebra","title":"LinearAlgebra.LAPACK.geqrf!","text":"geqrf!(A, tau)\n\nCompute the QR factorization of A, A = QR. tau contains scalars which parameterize the elementary reflectors of the factorization. tau must have length greater than or equal to the smallest dimension of A.\n\nReturns A and tau modified in-place.\n\n\n\n\n\ngeqrf!(A) -> (A, tau)\n\nCompute the QR factorization of A, A = QR.\n\nReturns A, modified in-place, and tau, which contains scalars which parameterize the elementary reflectors of the factorization.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LinearAlgebra/#LinearAlgebra.LAPACK.geqp3!","page":"Linear Algebra","title":"LinearAlgebra.LAPACK.geqp3!","text":"geqp3!(A, [jpvt, tau]) -> (A, tau, jpvt)\n\nCompute the pivoted QR factorization of A, AP = QR using BLAS level 3. P is a pivoting matrix, represented by jpvt. tau stores the elementary reflectors. The arguments jpvt and tau are optional and allow for passing preallocated arrays. When passed, jpvt must have length greater than or equal to n if A is an (m x n) matrix and tau must have length greater than or equal to the smallest dimension of A.\n\nA, jpvt, and tau are modified in-place.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LinearAlgebra/#LinearAlgebra.LAPACK.gerqf!","page":"Linear Algebra","title":"LinearAlgebra.LAPACK.gerqf!","text":"gerqf!(A, tau)\n\nCompute the RQ factorization of A, A = RQ. tau contains scalars which parameterize the elementary reflectors of the factorization. tau must have length greater than or equal to the smallest dimension of A.\n\nReturns A and tau modified in-place.\n\n\n\n\n\ngerqf!(A) -> (A, tau)\n\nCompute the RQ factorization of A, A = RQ.\n\nReturns A, modified in-place, and tau, which contains scalars which parameterize the elementary reflectors of the factorization.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LinearAlgebra/#LinearAlgebra.LAPACK.geqrt!","page":"Linear Algebra","title":"LinearAlgebra.LAPACK.geqrt!","text":"geqrt!(A, T)\n\nCompute the blocked QR factorization of A, A = QR. T contains upper triangular block reflectors which parameterize the elementary reflectors of the factorization. The first dimension of T sets the block size and it must be between 1 and n. The second dimension of T must equal the smallest dimension of A.\n\nReturns A and T modified in-place.\n\n\n\n\n\ngeqrt!(A, nb) -> (A, T)\n\nCompute the blocked QR factorization of A, A = QR. nb sets the block size and it must be between 1 and n, the second dimension of A.\n\nReturns A, modified in-place, and T, which contains upper triangular block reflectors which parameterize the elementary reflectors of the factorization.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LinearAlgebra/#LinearAlgebra.LAPACK.geqrt3!","page":"Linear Algebra","title":"LinearAlgebra.LAPACK.geqrt3!","text":"geqrt3!(A, T)\n\nRecursively computes the blocked QR factorization of A, A = QR. T contains upper triangular block reflectors which parameterize the elementary reflectors of the factorization. The first dimension of T sets the block size and it must be between 1 and n. The second dimension of T must equal the smallest dimension of A.\n\nReturns A and T modified in-place.\n\n\n\n\n\ngeqrt3!(A) -> (A, T)\n\nRecursively computes the blocked QR factorization of A, A = QR.\n\nReturns A, modified in-place, and T, which contains upper triangular block reflectors which parameterize the elementary reflectors of the factorization.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LinearAlgebra/#LinearAlgebra.LAPACK.getrf!","page":"Linear Algebra","title":"LinearAlgebra.LAPACK.getrf!","text":"getrf!(A) -> (A, ipiv, info)\n\nCompute the pivoted LU factorization of A, A = LU.\n\nReturns A, modified in-place, ipiv, the pivoting information, and an info code which indicates success (info = 0), a singular value in U (info = i, in which case U[i,i] is singular), or an error code (info < 0).\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LinearAlgebra/#LinearAlgebra.LAPACK.tzrzf!","page":"Linear Algebra","title":"LinearAlgebra.LAPACK.tzrzf!","text":"tzrzf!(A) -> (A, tau)\n\nTransforms the upper trapezoidal matrix A to upper triangular form in-place. Returns A and tau, the scalar parameters for the elementary reflectors of the transformation.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LinearAlgebra/#LinearAlgebra.LAPACK.ormrz!","page":"Linear Algebra","title":"LinearAlgebra.LAPACK.ormrz!","text":"ormrz!(side, trans, A, tau, C)\n\nMultiplies the matrix C by Q from the transformation supplied by tzrzf!. Depending on side or trans the multiplication can be left-sided (side = L, Q*C) or right-sided (side = R, C*Q) and Q can be unmodified (trans = N), transposed (trans = T), or conjugate transposed (trans = C). Returns matrix C which is modified in-place with the result of the multiplication.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LinearAlgebra/#LinearAlgebra.LAPACK.gels!","page":"Linear Algebra","title":"LinearAlgebra.LAPACK.gels!","text":"gels!(trans, A, B) -> (F, B, ssr)\n\nSolves the linear equation A * X = B, transpose(A) * X = B, or adjoint(A) * X = B using a QR or LQ factorization. Modifies the matrix/vector B in place with the solution. A is overwritten with its QR or LQ factorization. trans may be one of N (no modification), T (transpose), or C (conjugate transpose). gels! searches for the minimum norm/least squares solution. A may be under or over determined. The solution is returned in B.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LinearAlgebra/#LinearAlgebra.LAPACK.gesv!","page":"Linear Algebra","title":"LinearAlgebra.LAPACK.gesv!","text":"gesv!(A, B) -> (B, A, ipiv)\n\nSolves the linear equation A * X = B where A is a square matrix using the LU factorization of A. A is overwritten with its LU factorization and B is overwritten with the solution X. ipiv contains the pivoting information for the LU factorization of A.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LinearAlgebra/#LinearAlgebra.LAPACK.getrs!","page":"Linear Algebra","title":"LinearAlgebra.LAPACK.getrs!","text":"getrs!(trans, A, ipiv, B)\n\nSolves the linear equation A * X = B, transpose(A) * X = B, or adjoint(A) * X = B for square A. Modifies the matrix/vector B in place with the solution. A is the LU factorization from getrf!, with ipiv the pivoting information. trans may be one of N (no modification), T (transpose), or C (conjugate transpose).\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LinearAlgebra/#LinearAlgebra.LAPACK.getri!","page":"Linear Algebra","title":"LinearAlgebra.LAPACK.getri!","text":"getri!(A, ipiv)\n\nComputes the inverse of A, using its LU factorization found by getrf!. ipiv is the pivot information output and A contains the LU factorization of getrf!. A is overwritten with its inverse.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LinearAlgebra/#LinearAlgebra.LAPACK.gesvx!","page":"Linear Algebra","title":"LinearAlgebra.LAPACK.gesvx!","text":"gesvx!(fact, trans, A, AF, ipiv, equed, R, C, B) -> (X, equed, R, C, B, rcond, ferr, berr, work)\n\nSolves the linear equation A * X = B (trans = N), transpose(A) * X = B (trans = T), or adjoint(A) * X = B (trans = C) using the LU factorization of A. fact may be E, in which case A will be equilibrated and copied to AF; F, in which case AF and ipiv from a previous LU factorization are inputs; or N, in which case A will be copied to AF and then factored. If fact = F, equed may be N, meaning A has not been equilibrated; R, meaning A was multiplied by Diagonal(R) from the left; C, meaning A was multiplied by Diagonal(C) from the right; or B, meaning A was multiplied by Diagonal(R) from the left and Diagonal(C) from the right. If fact = F and equed = R or B the elements of R must all be positive. If fact = F and equed = C or B the elements of C must all be positive.\n\nReturns the solution X; equed, which is an output if fact is not N, and describes the equilibration that was performed; R, the row equilibration diagonal; C, the column equilibration diagonal; B, which may be overwritten with its equilibrated form Diagonal(R)*B (if trans = N and equed = R,B) or Diagonal(C)*B (if trans = T,C and equed = C,B); rcond, the reciprocal condition number of A after equilbrating; ferr, the forward error bound for each solution vector in X; berr, the forward error bound for each solution vector in X; and work, the reciprocal pivot growth factor.\n\n\n\n\n\ngesvx!(A, B)\n\nThe no-equilibration, no-transpose simplification of gesvx!.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LinearAlgebra/#LinearAlgebra.LAPACK.gelsd!","page":"Linear Algebra","title":"LinearAlgebra.LAPACK.gelsd!","text":"gelsd!(A, B, rcond) -> (B, rnk)\n\nComputes the least norm solution of A * X = B by finding the SVD factorization of A, then dividing-and-conquering the problem. B is overwritten with the solution X. Singular values below rcond will be treated as zero. Returns the solution in B and the effective rank of A in rnk.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LinearAlgebra/#LinearAlgebra.LAPACK.gelsy!","page":"Linear Algebra","title":"LinearAlgebra.LAPACK.gelsy!","text":"gelsy!(A, B, rcond) -> (B, rnk)\n\nComputes the least norm solution of A * X = B by finding the full QR factorization of A, then dividing-and-conquering the problem. B is overwritten with the solution X. Singular values below rcond will be treated as zero. Returns the solution in B and the effective rank of A in rnk.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LinearAlgebra/#LinearAlgebra.LAPACK.gglse!","page":"Linear Algebra","title":"LinearAlgebra.LAPACK.gglse!","text":"gglse!(A, c, B, d) -> (X,res)\n\nSolves the equation A * x = c where x is subject to the equality constraint B * x = d. Uses the formula ||c - A*x||^2 = 0 to solve. Returns X and the residual sum-of-squares.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LinearAlgebra/#LinearAlgebra.LAPACK.geev!","page":"Linear Algebra","title":"LinearAlgebra.LAPACK.geev!","text":"geev!(jobvl, jobvr, A) -> (W, VL, VR)\n\nFinds the eigensystem of A. If jobvl = N, the left eigenvectors of A aren't computed. If jobvr = N, the right eigenvectors of A aren't computed. If jobvl = V or jobvr = V, the corresponding eigenvectors are computed. Returns the eigenvalues in W, the right eigenvectors in VR, and the left eigenvectors in VL.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LinearAlgebra/#LinearAlgebra.LAPACK.gesdd!","page":"Linear Algebra","title":"LinearAlgebra.LAPACK.gesdd!","text":"gesdd!(job, A) -> (U, S, VT)\n\nFinds the singular value decomposition of A, A = U * S * V', using a divide and conquer approach. If job = A, all the columns of U and the rows of V' are computed. If job = N, no columns of U or rows of V' are computed. If job = O, A is overwritten with the columns of (thin) U and the rows of (thin) V'. If job = S, the columns of (thin) U and the rows of (thin) V' are computed and returned separately.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LinearAlgebra/#LinearAlgebra.LAPACK.gesvd!","page":"Linear Algebra","title":"LinearAlgebra.LAPACK.gesvd!","text":"gesvd!(jobu, jobvt, A) -> (U, S, VT)\n\nFinds the singular value decomposition of A, A = U * S * V'. If jobu = A, all the columns of U are computed. If jobvt = A all the rows of V' are computed. If jobu = N, no columns of U are computed. If jobvt = N no rows of V' are computed. If jobu = O, A is overwritten with the columns of (thin) U. If jobvt = O, A is overwritten with the rows of (thin) V'. If jobu = S, the columns of (thin) U are computed and returned separately. If jobvt = S the rows of (thin) V' are computed and returned separately. jobu and jobvt can't both be O.\n\nReturns U, S, and Vt, where S are the singular values of A.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LinearAlgebra/#LinearAlgebra.LAPACK.ggsvd!","page":"Linear Algebra","title":"LinearAlgebra.LAPACK.ggsvd!","text":"ggsvd!(jobu, jobv, jobq, A, B) -> (U, V, Q, alpha, beta, k, l, R)\n\nFinds the generalized singular value decomposition of A and B, U'*A*Q = D1*R and V'*B*Q = D2*R. D1 has alpha on its diagonal and D2 has beta on its diagonal. If jobu = U, the orthogonal/unitary matrix U is computed. If jobv = V the orthogonal/unitary matrix V is computed. If jobq = Q, the orthogonal/unitary matrix Q is computed. If jobu, jobv or jobq is N, that matrix is not computed. This function is only available in LAPACK versions prior to 3.6.0.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LinearAlgebra/#LinearAlgebra.LAPACK.ggsvd3!","page":"Linear Algebra","title":"LinearAlgebra.LAPACK.ggsvd3!","text":"ggsvd3!(jobu, jobv, jobq, A, B) -> (U, V, Q, alpha, beta, k, l, R)\n\nFinds the generalized singular value decomposition of A and B, U'*A*Q = D1*R and V'*B*Q = D2*R. D1 has alpha on its diagonal and D2 has beta on its diagonal. If jobu = U, the orthogonal/unitary matrix U is computed. If jobv = V the orthogonal/unitary matrix V is computed. If jobq = Q, the orthogonal/unitary matrix Q is computed. If jobu, jobv, or jobq is N, that matrix is not computed. This function requires LAPACK 3.6.0.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LinearAlgebra/#LinearAlgebra.LAPACK.geevx!","page":"Linear Algebra","title":"LinearAlgebra.LAPACK.geevx!","text":"geevx!(balanc, jobvl, jobvr, sense, A) -> (A, w, VL, VR, ilo, ihi, scale, abnrm, rconde, rcondv)\n\nFinds the eigensystem of A with matrix balancing. If jobvl = N, the left eigenvectors of A aren't computed. If jobvr = N, the right eigenvectors of A aren't computed. If jobvl = V or jobvr = V, the corresponding eigenvectors are computed. If balanc = N, no balancing is performed. If balanc = P, A is permuted but not scaled. If balanc = S, A is scaled but not permuted. If balanc = B, A is permuted and scaled. If sense = N, no reciprocal condition numbers are computed. If sense = E, reciprocal condition numbers are computed for the eigenvalues only. If sense = V, reciprocal condition numbers are computed for the right eigenvectors only. If sense = B, reciprocal condition numbers are computed for the right eigenvectors and the eigenvectors. If sense = E,B, the right and left eigenvectors must be computed.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LinearAlgebra/#LinearAlgebra.LAPACK.ggev!","page":"Linear Algebra","title":"LinearAlgebra.LAPACK.ggev!","text":"ggev!(jobvl, jobvr, A, B) -> (alpha, beta, vl, vr)\n\nFinds the generalized eigendecomposition of A and B. If jobvl = N, the left eigenvectors aren't computed. If jobvr = N, the right eigenvectors aren't computed. If jobvl = V or jobvr = V, the corresponding eigenvectors are computed.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LinearAlgebra/#LinearAlgebra.LAPACK.gtsv!","page":"Linear Algebra","title":"LinearAlgebra.LAPACK.gtsv!","text":"gtsv!(dl, d, du, B)\n\nSolves the equation A * X = B where A is a tridiagonal matrix with dl on the subdiagonal, d on the diagonal, and du on the superdiagonal.\n\nOverwrites B with the solution X and returns it.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LinearAlgebra/#LinearAlgebra.LAPACK.gttrf!","page":"Linear Algebra","title":"LinearAlgebra.LAPACK.gttrf!","text":"gttrf!(dl, d, du) -> (dl, d, du, du2, ipiv)\n\nFinds the LU factorization of a tridiagonal matrix with dl on the subdiagonal, d on the diagonal, and du on the superdiagonal.\n\nModifies dl, d, and du in-place and returns them and the second superdiagonal du2 and the pivoting vector ipiv.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LinearAlgebra/#LinearAlgebra.LAPACK.gttrs!","page":"Linear Algebra","title":"LinearAlgebra.LAPACK.gttrs!","text":"gttrs!(trans, dl, d, du, du2, ipiv, B)\n\nSolves the equation A * X = B (trans = N), transpose(A) * X = B (trans = T), or adjoint(A) * X = B (trans = C) using the LU factorization computed by gttrf!. B is overwritten with the solution X.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LinearAlgebra/#LinearAlgebra.LAPACK.orglq!","page":"Linear Algebra","title":"LinearAlgebra.LAPACK.orglq!","text":"orglq!(A, tau, k = length(tau))\n\nExplicitly finds the matrix Q of a LQ factorization after calling gelqf! on A. Uses the output of gelqf!. A is overwritten by Q.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LinearAlgebra/#LinearAlgebra.LAPACK.orgqr!","page":"Linear Algebra","title":"LinearAlgebra.LAPACK.orgqr!","text":"orgqr!(A, tau, k = length(tau))\n\nExplicitly finds the matrix Q of a QR factorization after calling geqrf! on A. Uses the output of geqrf!. A is overwritten by Q.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LinearAlgebra/#LinearAlgebra.LAPACK.orgql!","page":"Linear Algebra","title":"LinearAlgebra.LAPACK.orgql!","text":"orgql!(A, tau, k = length(tau))\n\nExplicitly finds the matrix Q of a QL factorization after calling geqlf! on A. Uses the output of geqlf!. A is overwritten by Q.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LinearAlgebra/#LinearAlgebra.LAPACK.orgrq!","page":"Linear Algebra","title":"LinearAlgebra.LAPACK.orgrq!","text":"orgrq!(A, tau, k = length(tau))\n\nExplicitly finds the matrix Q of a RQ factorization after calling gerqf! on A. Uses the output of gerqf!. A is overwritten by Q.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LinearAlgebra/#LinearAlgebra.LAPACK.ormlq!","page":"Linear Algebra","title":"LinearAlgebra.LAPACK.ormlq!","text":"ormlq!(side, trans, A, tau, C)\n\nComputes Q * C (trans = N), transpose(Q) * C (trans = T), adjoint(Q) * C (trans = C) for side = L or the equivalent right-sided multiplication for side = R using Q from a LQ factorization of A computed using gelqf!. C is overwritten.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LinearAlgebra/#LinearAlgebra.LAPACK.ormqr!","page":"Linear Algebra","title":"LinearAlgebra.LAPACK.ormqr!","text":"ormqr!(side, trans, A, tau, C)\n\nComputes Q * C (trans = N), transpose(Q) * C (trans = T), adjoint(Q) * C (trans = C) for side = L or the equivalent right-sided multiplication for side = R using Q from a QR factorization of A computed using geqrf!. C is overwritten.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LinearAlgebra/#LinearAlgebra.LAPACK.ormql!","page":"Linear Algebra","title":"LinearAlgebra.LAPACK.ormql!","text":"ormql!(side, trans, A, tau, C)\n\nComputes Q * C (trans = N), transpose(Q) * C (trans = T), adjoint(Q) * C (trans = C) for side = L or the equivalent right-sided multiplication for side = R using Q from a QL factorization of A computed using geqlf!. C is overwritten.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LinearAlgebra/#LinearAlgebra.LAPACK.ormrq!","page":"Linear Algebra","title":"LinearAlgebra.LAPACK.ormrq!","text":"ormrq!(side, trans, A, tau, C)\n\nComputes Q * C (trans = N), transpose(Q) * C (trans = T), adjoint(Q) * C (trans = C) for side = L or the equivalent right-sided multiplication for side = R using Q from a RQ factorization of A computed using gerqf!. C is overwritten.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LinearAlgebra/#LinearAlgebra.LAPACK.gemqrt!","page":"Linear Algebra","title":"LinearAlgebra.LAPACK.gemqrt!","text":"gemqrt!(side, trans, V, T, C)\n\nComputes Q * C (trans = N), transpose(Q) * C (trans = T), adjoint(Q) * C (trans = C) for side = L or the equivalent right-sided multiplication for side = R using Q from a QR factorization of A computed using geqrt!. C is overwritten.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LinearAlgebra/#LinearAlgebra.LAPACK.posv!","page":"Linear Algebra","title":"LinearAlgebra.LAPACK.posv!","text":"posv!(uplo, A, B) -> (A, B)\n\nFinds the solution to A * X = B where A is a symmetric or Hermitian positive definite matrix. If uplo = U the upper Cholesky decomposition of A is computed. If uplo = L the lower Cholesky decomposition of A is computed. A is overwritten by its Cholesky decomposition. B is overwritten with the solution X.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LinearAlgebra/#LinearAlgebra.LAPACK.potrf!","page":"Linear Algebra","title":"LinearAlgebra.LAPACK.potrf!","text":"potrf!(uplo, A)\n\nComputes the Cholesky (upper if uplo = U, lower if uplo = L) decomposition of positive-definite matrix A. A is overwritten and returned with an info code.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LinearAlgebra/#LinearAlgebra.LAPACK.potri!","page":"Linear Algebra","title":"LinearAlgebra.LAPACK.potri!","text":"potri!(uplo, A)\n\nComputes the inverse of positive-definite matrix A after calling potrf! to find its (upper if uplo = U, lower if uplo = L) Cholesky decomposition.\n\nA is overwritten by its inverse and returned.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LinearAlgebra/#LinearAlgebra.LAPACK.potrs!","page":"Linear Algebra","title":"LinearAlgebra.LAPACK.potrs!","text":"potrs!(uplo, A, B)\n\nFinds the solution to A * X = B where A is a symmetric or Hermitian positive definite matrix whose Cholesky decomposition was computed by potrf!. If uplo = U the upper Cholesky decomposition of A was computed. If uplo = L the lower Cholesky decomposition of A was computed. B is overwritten with the solution X.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LinearAlgebra/#LinearAlgebra.LAPACK.pstrf!","page":"Linear Algebra","title":"LinearAlgebra.LAPACK.pstrf!","text":"pstrf!(uplo, A, tol) -> (A, piv, rank, info)\n\nComputes the (upper if uplo = U, lower if uplo = L) pivoted Cholesky decomposition of positive-definite matrix A with a user-set tolerance tol. A is overwritten by its Cholesky decomposition.\n\nReturns A, the pivots piv, the rank of A, and an info code. If info = 0, the factorization succeeded. If info = i > 0, then A is indefinite or rank-deficient.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LinearAlgebra/#LinearAlgebra.LAPACK.ptsv!","page":"Linear Algebra","title":"LinearAlgebra.LAPACK.ptsv!","text":"ptsv!(D, E, B)\n\nSolves A * X = B for positive-definite tridiagonal A. D is the diagonal of A and E is the off-diagonal. B is overwritten with the solution X and returned.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LinearAlgebra/#LinearAlgebra.LAPACK.pttrf!","page":"Linear Algebra","title":"LinearAlgebra.LAPACK.pttrf!","text":"pttrf!(D, E)\n\nComputes the LDLt factorization of a positive-definite tridiagonal matrix with D as diagonal and E as off-diagonal. D and E are overwritten and returned.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LinearAlgebra/#LinearAlgebra.LAPACK.pttrs!","page":"Linear Algebra","title":"LinearAlgebra.LAPACK.pttrs!","text":"pttrs!(D, E, B)\n\nSolves A * X = B for positive-definite tridiagonal A with diagonal D and off-diagonal E after computing A's LDLt factorization using pttrf!. B is overwritten with the solution X.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LinearAlgebra/#LinearAlgebra.LAPACK.trtri!","page":"Linear Algebra","title":"LinearAlgebra.LAPACK.trtri!","text":"trtri!(uplo, diag, A)\n\nFinds the inverse of (upper if uplo = U, lower if uplo = L) triangular matrix A. If diag = N, A has non-unit diagonal elements. If diag = U, all diagonal elements of A are one. A is overwritten with its inverse.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LinearAlgebra/#LinearAlgebra.LAPACK.trtrs!","page":"Linear Algebra","title":"LinearAlgebra.LAPACK.trtrs!","text":"trtrs!(uplo, trans, diag, A, B)\n\nSolves A * X = B (trans = N), transpose(A) * X = B (trans = T), or adjoint(A) * X = B (trans = C) for (upper if uplo = U, lower if uplo = L) triangular matrix A. If diag = N, A has non-unit diagonal elements. If diag = U, all diagonal elements of A are one. B is overwritten with the solution X.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LinearAlgebra/#LinearAlgebra.LAPACK.trcon!","page":"Linear Algebra","title":"LinearAlgebra.LAPACK.trcon!","text":"trcon!(norm, uplo, diag, A)\n\nFinds the reciprocal condition number of (upper if uplo = U, lower if uplo = L) triangular matrix A. If diag = N, A has non-unit diagonal elements. If diag = U, all diagonal elements of A are one. If norm = I, the condition number is found in the infinity norm. If norm = O or 1, the condition number is found in the one norm.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LinearAlgebra/#LinearAlgebra.LAPACK.trevc!","page":"Linear Algebra","title":"LinearAlgebra.LAPACK.trevc!","text":"trevc!(side, howmny, select, T, VL = similar(T), VR = similar(T))\n\nFinds the eigensystem of an upper triangular matrix T. If side = R, the right eigenvectors are computed. If side = L, the left eigenvectors are computed. If side = B, both sets are computed. If howmny = A, all eigenvectors are found. If howmny = B, all eigenvectors are found and backtransformed using VL and VR. If howmny = S, only the eigenvectors corresponding to the values in select are computed.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LinearAlgebra/#LinearAlgebra.LAPACK.trrfs!","page":"Linear Algebra","title":"LinearAlgebra.LAPACK.trrfs!","text":"trrfs!(uplo, trans, diag, A, B, X, Ferr, Berr) -> (Ferr, Berr)\n\nEstimates the error in the solution to A * X = B (trans = N), transpose(A) * X = B (trans = T), adjoint(A) * X = B (trans = C) for side = L, or the equivalent equations a right-handed side = R X * A after computing X using trtrs!. If uplo = U, A is upper triangular. If uplo = L, A is lower triangular. If diag = N, A has non-unit diagonal elements. If diag = U, all diagonal elements of A are one. Ferr and Berr are optional inputs. Ferr is the forward error and Berr is the backward error, each component-wise.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LinearAlgebra/#LinearAlgebra.LAPACK.stev!","page":"Linear Algebra","title":"LinearAlgebra.LAPACK.stev!","text":"stev!(job, dv, ev) -> (dv, Zmat)\n\nComputes the eigensystem for a symmetric tridiagonal matrix with dv as diagonal and ev as off-diagonal. If job = N only the eigenvalues are found and returned in dv. If job = V then the eigenvectors are also found and returned in Zmat.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LinearAlgebra/#LinearAlgebra.LAPACK.stebz!","page":"Linear Algebra","title":"LinearAlgebra.LAPACK.stebz!","text":"stebz!(range, order, vl, vu, il, iu, abstol, dv, ev) -> (dv, iblock, isplit)\n\nComputes the eigenvalues for a symmetric tridiagonal matrix with dv as diagonal and ev as off-diagonal. If range = A, all the eigenvalues are found. If range = V, the eigenvalues in the half-open interval (vl, vu] are found. If range = I, the eigenvalues with indices between il and iu are found. If order = B, eigvalues are ordered within a block. If order = E, they are ordered across all the blocks. abstol can be set as a tolerance for convergence.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LinearAlgebra/#LinearAlgebra.LAPACK.stegr!","page":"Linear Algebra","title":"LinearAlgebra.LAPACK.stegr!","text":"stegr!(jobz, range, dv, ev, vl, vu, il, iu) -> (w, Z)\n\nComputes the eigenvalues (jobz = N) or eigenvalues and eigenvectors (jobz = V) for a symmetric tridiagonal matrix with dv as diagonal and ev as off-diagonal. If range = A, all the eigenvalues are found. If range = V, the eigenvalues in the half-open interval (vl, vu] are found. If range = I, the eigenvalues with indices between il and iu are found. The eigenvalues are returned in w and the eigenvectors in Z.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LinearAlgebra/#LinearAlgebra.LAPACK.stein!","page":"Linear Algebra","title":"LinearAlgebra.LAPACK.stein!","text":"stein!(dv, ev_in, w_in, iblock_in, isplit_in)\n\nComputes the eigenvectors for a symmetric tridiagonal matrix with dv as diagonal and ev_in as off-diagonal. w_in specifies the input eigenvalues for which to find corresponding eigenvectors. iblock_in specifies the submatrices corresponding to the eigenvalues in w_in. isplit_in specifies the splitting points between the submatrix blocks.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LinearAlgebra/#LinearAlgebra.LAPACK.syconv!","page":"Linear Algebra","title":"LinearAlgebra.LAPACK.syconv!","text":"syconv!(uplo, A, ipiv) -> (A, work)\n\nConverts a symmetric matrix A (which has been factorized into a triangular matrix) into two matrices L and D. If uplo = U, A is upper triangular. If uplo = L, it is lower triangular. ipiv is the pivot vector from the triangular factorization. A is overwritten by L and D.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LinearAlgebra/#LinearAlgebra.LAPACK.sysv!","page":"Linear Algebra","title":"LinearAlgebra.LAPACK.sysv!","text":"sysv!(uplo, A, B) -> (B, A, ipiv)\n\nFinds the solution to A * X = B for symmetric matrix A. If uplo = U, the upper half of A is stored. If uplo = L, the lower half is stored. B is overwritten by the solution X. A is overwritten by its Bunch-Kaufman factorization. ipiv contains pivoting information about the factorization.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LinearAlgebra/#LinearAlgebra.LAPACK.sytrf!","page":"Linear Algebra","title":"LinearAlgebra.LAPACK.sytrf!","text":"sytrf!(uplo, A) -> (A, ipiv, info)\n\nComputes the Bunch-Kaufman factorization of a symmetric matrix A. If uplo = U, the upper half of A is stored. If uplo = L, the lower half is stored.\n\nReturns A, overwritten by the factorization, a pivot vector ipiv, and the error code info which is a non-negative integer. If info is positive the matrix is singular and the diagonal part of the factorization is exactly zero at position info.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LinearAlgebra/#LinearAlgebra.LAPACK.sytri!","page":"Linear Algebra","title":"LinearAlgebra.LAPACK.sytri!","text":"sytri!(uplo, A, ipiv)\n\nComputes the inverse of a symmetric matrix A using the results of sytrf!. If uplo = U, the upper half of A is stored. If uplo = L, the lower half is stored. A is overwritten by its inverse.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LinearAlgebra/#LinearAlgebra.LAPACK.sytrs!","page":"Linear Algebra","title":"LinearAlgebra.LAPACK.sytrs!","text":"sytrs!(uplo, A, ipiv, B)\n\nSolves the equation A * X = B for a symmetric matrix A using the results of sytrf!. If uplo = U, the upper half of A is stored. If uplo = L, the lower half is stored. B is overwritten by the solution X.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LinearAlgebra/#LinearAlgebra.LAPACK.hesv!","page":"Linear Algebra","title":"LinearAlgebra.LAPACK.hesv!","text":"hesv!(uplo, A, B) -> (B, A, ipiv)\n\nFinds the solution to A * X = B for Hermitian matrix A. If uplo = U, the upper half of A is stored. If uplo = L, the lower half is stored. B is overwritten by the solution X. A is overwritten by its Bunch-Kaufman factorization. ipiv contains pivoting information about the factorization.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LinearAlgebra/#LinearAlgebra.LAPACK.hetrf!","page":"Linear Algebra","title":"LinearAlgebra.LAPACK.hetrf!","text":"hetrf!(uplo, A) -> (A, ipiv, info)\n\nComputes the Bunch-Kaufman factorization of a Hermitian matrix A. If uplo = U, the upper half of A is stored. If uplo = L, the lower half is stored.\n\nReturns A, overwritten by the factorization, a pivot vector ipiv, and the error code info which is a non-negative integer. If info is positive the matrix is singular and the diagonal part of the factorization is exactly zero at position info.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LinearAlgebra/#LinearAlgebra.LAPACK.hetri!","page":"Linear Algebra","title":"LinearAlgebra.LAPACK.hetri!","text":"hetri!(uplo, A, ipiv)\n\nComputes the inverse of a Hermitian matrix A using the results of sytrf!. If uplo = U, the upper half of A is stored. If uplo = L, the lower half is stored. A is overwritten by its inverse.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LinearAlgebra/#LinearAlgebra.LAPACK.hetrs!","page":"Linear Algebra","title":"LinearAlgebra.LAPACK.hetrs!","text":"hetrs!(uplo, A, ipiv, B)\n\nSolves the equation A * X = B for a Hermitian matrix A using the results of sytrf!. If uplo = U, the upper half of A is stored. If uplo = L, the lower half is stored. B is overwritten by the solution X.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LinearAlgebra/#LinearAlgebra.LAPACK.syev!","page":"Linear Algebra","title":"LinearAlgebra.LAPACK.syev!","text":"syev!(jobz, uplo, A)\n\nFinds the eigenvalues (jobz = N) or eigenvalues and eigenvectors (jobz = V) of a symmetric matrix A. If uplo = U, the upper triangle of A is used. If uplo = L, the lower triangle of A is used.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LinearAlgebra/#LinearAlgebra.LAPACK.syevr!","page":"Linear Algebra","title":"LinearAlgebra.LAPACK.syevr!","text":"syevr!(jobz, range, uplo, A, vl, vu, il, iu, abstol) -> (W, Z)\n\nFinds the eigenvalues (jobz = N) or eigenvalues and eigenvectors (jobz = V) of a symmetric matrix A. If uplo = U, the upper triangle of A is used. If uplo = L, the lower triangle of A is used. If range = A, all the eigenvalues are found. If range = V, the eigenvalues in the half-open interval (vl, vu] are found. If range = I, the eigenvalues with indices between il and iu are found. abstol can be set as a tolerance for convergence.\n\nThe eigenvalues are returned in W and the eigenvectors in Z.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LinearAlgebra/#LinearAlgebra.LAPACK.sygvd!","page":"Linear Algebra","title":"LinearAlgebra.LAPACK.sygvd!","text":"sygvd!(itype, jobz, uplo, A, B) -> (w, A, B)\n\nFinds the generalized eigenvalues (jobz = N) or eigenvalues and eigenvectors (jobz = V) of a symmetric matrix A and symmetric positive-definite matrix B. If uplo = U, the upper triangles of A and B are used. If uplo = L, the lower triangles of A and B are used. If itype = 1, the problem to solve is A * x = lambda * B * x. If itype = 2, the problem to solve is A * B * x = lambda * x. If itype = 3, the problem to solve is B * A * x = lambda * x.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LinearAlgebra/#LinearAlgebra.LAPACK.bdsqr!","page":"Linear Algebra","title":"LinearAlgebra.LAPACK.bdsqr!","text":"bdsqr!(uplo, d, e_, Vt, U, C) -> (d, Vt, U, C)\n\nComputes the singular value decomposition of a bidiagonal matrix with d on the diagonal and e_ on the off-diagonal. If uplo = U, e_ is the superdiagonal. If uplo = L, e_ is the subdiagonal. Can optionally also compute the product Q' * C.\n\nReturns the singular values in d, and the matrix C overwritten with Q' * C.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LinearAlgebra/#LinearAlgebra.LAPACK.bdsdc!","page":"Linear Algebra","title":"LinearAlgebra.LAPACK.bdsdc!","text":"bdsdc!(uplo, compq, d, e_) -> (d, e, u, vt, q, iq)\n\nComputes the singular value decomposition of a bidiagonal matrix with d on the diagonal and e_ on the off-diagonal using a divide and conqueq method. If uplo = U, e_ is the superdiagonal. If uplo = L, e_ is the subdiagonal. If compq = N, only the singular values are found. If compq = I, the singular values and vectors are found. If compq = P, the singular values and vectors are found in compact form. Only works for real types.\n\nReturns the singular values in d, and if compq = P, the compact singular vectors in iq.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LinearAlgebra/#LinearAlgebra.LAPACK.gecon!","page":"Linear Algebra","title":"LinearAlgebra.LAPACK.gecon!","text":"gecon!(normtype, A, anorm)\n\nFinds the reciprocal condition number of matrix A. If normtype = I, the condition number is found in the infinity norm. If normtype = O or 1, the condition number is found in the one norm. A must be the result of getrf! and anorm is the norm of A in the relevant norm.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LinearAlgebra/#LinearAlgebra.LAPACK.gehrd!","page":"Linear Algebra","title":"LinearAlgebra.LAPACK.gehrd!","text":"gehrd!(ilo, ihi, A) -> (A, tau)\n\nConverts a matrix A to Hessenberg form. If A is balanced with gebal! then ilo and ihi are the outputs of gebal!. Otherwise they should be ilo = 1 and ihi = size(A,2). tau contains the elementary reflectors of the factorization.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LinearAlgebra/#LinearAlgebra.LAPACK.orghr!","page":"Linear Algebra","title":"LinearAlgebra.LAPACK.orghr!","text":"orghr!(ilo, ihi, A, tau)\n\nExplicitly finds Q, the orthogonal/unitary matrix from gehrd!. ilo, ihi, A, and tau must correspond to the input/output to gehrd!.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LinearAlgebra/#LinearAlgebra.LAPACK.gees!","page":"Linear Algebra","title":"LinearAlgebra.LAPACK.gees!","text":"gees!(jobvs, A) -> (A, vs, w)\n\nComputes the eigenvalues (jobvs = N) or the eigenvalues and Schur vectors (jobvs = V) of matrix A. A is overwritten by its Schur form.\n\nReturns A, vs containing the Schur vectors, and w, containing the eigenvalues.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LinearAlgebra/#LinearAlgebra.LAPACK.gges!","page":"Linear Algebra","title":"LinearAlgebra.LAPACK.gges!","text":"gges!(jobvsl, jobvsr, A, B) -> (A, B, alpha, beta, vsl, vsr)\n\nComputes the generalized eigenvalues, generalized Schur form, left Schur vectors (jobsvl = V), or right Schur vectors (jobvsr = V) of A and B.\n\nThe generalized eigenvalues are returned in alpha and beta. The left Schur vectors are returned in vsl and the right Schur vectors are returned in vsr.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LinearAlgebra/#LinearAlgebra.LAPACK.trexc!","page":"Linear Algebra","title":"LinearAlgebra.LAPACK.trexc!","text":"trexc!(compq, ifst, ilst, T, Q) -> (T, Q)\ntrexc!(ifst, ilst, T, Q) -> (T, Q)\n\nReorder the Schur factorization T of a matrix, such that the diagonal block of T with row index ifst is moved to row index ilst. If compq = V, the Schur vectors Q are reordered. If compq = N they are not modified. The 4-arg method calls the 5-arg method with compq = V.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LinearAlgebra/#LinearAlgebra.LAPACK.trsen!","page":"Linear Algebra","title":"LinearAlgebra.LAPACK.trsen!","text":"trsen!(job, compq, select, T, Q) -> (T, Q, w, s, sep)\ntrsen!(select, T, Q) -> (T, Q, w, s, sep)\n\nReorder the Schur factorization of a matrix and optionally finds reciprocal condition numbers. If job = N, no condition numbers are found. If job = E, only the condition number for this cluster of eigenvalues is found. If job = V, only the condition number for the invariant subspace is found. If job = B then the condition numbers for the cluster and subspace are found. If compq = V the Schur vectors Q are updated. If compq = N the Schur vectors are not modified. select determines which eigenvalues are in the cluster. The 3-arg method calls the 5-arg method with job = N and compq = V.\n\nReturns T, Q, reordered eigenvalues in w, the condition number of the cluster of eigenvalues s, and the condition number of the invariant subspace sep.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LinearAlgebra/#LinearAlgebra.LAPACK.tgsen!","page":"Linear Algebra","title":"LinearAlgebra.LAPACK.tgsen!","text":"tgsen!(select, S, T, Q, Z) -> (S, T, alpha, beta, Q, Z)\n\nReorders the vectors of a generalized Schur decomposition. select specifies the eigenvalues in each cluster.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LinearAlgebra/#LinearAlgebra.LAPACK.trsyl!","page":"Linear Algebra","title":"LinearAlgebra.LAPACK.trsyl!","text":"trsyl!(transa, transb, A, B, C, isgn=1) -> (C, scale)\n\nSolves the Sylvester matrix equation A * X +/- X * B = scale*C where A and B are both quasi-upper triangular. If transa = N, A is not modified. If transa = T, A is transposed. If transa = C, A is conjugate transposed. Similarly for transb and B. If isgn = 1, the equation A * X + X * B = scale * C is solved. If isgn = -1, the equation A * X - X * B = scale * C is solved.\n\nReturns X (overwriting C) and scale.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LinearAlgebra/","page":"Linear Algebra","title":"Linear Algebra","text":"DocTestSetup = nothing","category":"page"},{"location":"stdlib/Sockets/#套接字","page":"套接字","title":"套接字","text":"","category":"section"},{"location":"stdlib/Sockets/","page":"套接字","title":"套接字","text":"Sockets.Sockets\nSockets.connect(::TCPSocket, ::Integer)\nSockets.connect(::AbstractString)\nSockets.listen(::Any)\nSockets.listen(::AbstractString)\nSockets.getaddrinfo\nSockets.getipaddr\nSockets.getipaddrs\nSockets.islinklocaladdr\nSockets.getalladdrinfo\nSockets.DNSError\nSockets.getnameinfo\nSockets.getsockname\nSockets.getpeername\nSockets.IPAddr\nSockets.IPv4\nSockets.IPv6\nSockets.@ip_str\nSockets.TCPSocket\nSockets.UDPSocket\nSockets.accept\nSockets.listenany\nSockets.bind\nSockets.send\nSockets.recv\nSockets.recvfrom\nSockets.setopt\nSockets.nagle\nSockets.quickack","category":"page"},{"location":"stdlib/Sockets/#Sockets.Sockets","page":"套接字","title":"Sockets.Sockets","text":"Support for sockets. Provides IPAddr and subtypes, TCPSocket, and UDPSocket.\n\n\n\n\n\n","category":"module"},{"location":"stdlib/Sockets/#Sockets.connect-Tuple{TCPSocket, Integer}","page":"套接字","title":"Sockets.connect","text":"connect([host], port::Integer) -> TCPSocket\n\nConnect to the host host on port port.\n\n\n\n\n\n","category":"method"},{"location":"stdlib/Sockets/#Sockets.connect-Tuple{AbstractString}","page":"套接字","title":"Sockets.connect","text":"connect(path::AbstractString) -> PipeEndpoint\n\nConnect to the named pipe / UNIX domain socket at path.\n\nnote: Note\nPath length on Unix is limited to somewhere between 92 and 108 bytes (cf. man unix).\n\n\n\n\n\n","category":"method"},{"location":"stdlib/Sockets/#Sockets.listen-Tuple{Any}","page":"套接字","title":"Sockets.listen","text":"listen([addr, ]port::Integer; backlog::Integer=BACKLOG_DEFAULT) -> TCPServer\n\nListen on port on the address specified by addr. By default this listens on localhost only. To listen on all interfaces pass IPv4(0) or IPv6(0) as appropriate. backlog determines how many connections can be pending (not having called accept) before the server will begin to reject them. The default value of backlog is 511.\n\n\n\n\n\n","category":"method"},{"location":"stdlib/Sockets/#Sockets.listen-Tuple{AbstractString}","page":"套接字","title":"Sockets.listen","text":"listen(path::AbstractString) -> PipeServer\n\nCreate and listen on a named pipe / UNIX domain socket.\n\nnote: Note\nPath length on Unix is limited to somewhere between 92 and 108 bytes (cf. man unix).\n\n\n\n\n\n","category":"method"},{"location":"stdlib/Sockets/#Sockets.getaddrinfo","page":"套接字","title":"Sockets.getaddrinfo","text":"getaddrinfo(host::AbstractString, IPAddr=IPv4) -> IPAddr\n\nGets the first IP address of the host of the specified IPAddr type. Uses the operating system's underlying getaddrinfo implementation, which may do a DNS lookup.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/Sockets/#Sockets.getipaddr","page":"套接字","title":"Sockets.getipaddr","text":"getipaddr() -> IPAddr\n\nGet an IP address of the local machine, preferring IPv4 over IPv6. Throws if no addresses are available.\n\ngetipaddr(addr_type::Type{T}) where T<:IPAddr -> T\n\nGet an IP address of the local machine of the specified type. Throws if no addresses of the specified type are available.\n\nThis function is a backwards-compatibility wrapper around getipaddrs. New applications should use getipaddrs instead.\n\nExamples\n\njulia> getipaddr()\nip\"192.168.1.28\"\n\njulia> getipaddr(IPv6)\nip\"fe80::9731:35af:e1c5:6e49\"\n\nSee also getipaddrs.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/Sockets/#Sockets.getipaddrs","page":"套接字","title":"Sockets.getipaddrs","text":"getipaddrs(addr_type::Type{T}=IPAddr; loopback::Bool=false) where T<:IPAddr -> Vector{T}\n\nGet the IP addresses of the local machine.\n\nSetting the optional addr_type parameter to IPv4 or IPv6 causes only addresses of that type to be returned.\n\nThe loopback keyword argument dictates whether loopback addresses (e.g. ip\"127.0.0.1\", ip\"::1\") are included.\n\ncompat: Julia 1.2\nThis function is available as of Julia 1.2.\n\nExamples\n\njulia> getipaddrs()\n5-element Array{IPAddr,1}:\n ip\"198.51.100.17\"\n ip\"203.0.113.2\"\n ip\"2001:db8:8:4:445e:5fff:fe5d:5500\"\n ip\"2001:db8:8:4:c164:402e:7e3c:3668\"\n ip\"fe80::445e:5fff:fe5d:5500\"\n\njulia> getipaddrs(IPv6)\n3-element Array{IPv6,1}:\n ip\"2001:db8:8:4:445e:5fff:fe5d:5500\"\n ip\"2001:db8:8:4:c164:402e:7e3c:3668\"\n ip\"fe80::445e:5fff:fe5d:5500\"\n\nSee also islinklocaladdr.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/Sockets/#Sockets.islinklocaladdr","page":"套接字","title":"Sockets.islinklocaladdr","text":"islinklocaladdr(addr::IPAddr)\n\nTests if an IP address is a link-local address. Link-local addresses are not guaranteed to be unique beyond their network segment, therefore routers do not forward them. Link-local addresses are from the address blocks 169.254.0.0/16 or fe80::/10.\n\nExample\n\nfilter(!islinklocaladdr, getipaddrs())\n\n\n\n\n\n","category":"function"},{"location":"stdlib/Sockets/#Sockets.getalladdrinfo","page":"套接字","title":"Sockets.getalladdrinfo","text":"getalladdrinfo(host::AbstractString) -> Vector{IPAddr}\n\nGets all of the IP addresses of the host. Uses the operating system's underlying getaddrinfo implementation, which may do a DNS lookup.\n\nExample\n\njulia> getalladdrinfo(\"google.com\")\n2-element Array{IPAddr,1}:\n ip\"172.217.6.174\"\n ip\"2607:f8b0:4000:804::200e\"\n\n\n\n\n\n","category":"function"},{"location":"stdlib/Sockets/#Sockets.DNSError","page":"套接字","title":"Sockets.DNSError","text":"DNSError\n\nThe type of exception thrown when an error occurs in DNS lookup. The host field indicates the host URL string. The code field indicates the error code based on libuv.\n\n\n\n\n\n","category":"type"},{"location":"stdlib/Sockets/#Sockets.getnameinfo","page":"套接字","title":"Sockets.getnameinfo","text":"getnameinfo(host::IPAddr) -> String\n\nPerforms a reverse-lookup for IP address to return a hostname and service using the operating system's underlying getnameinfo implementation.\n\nExamples\n\njulia> getnameinfo(Sockets.IPv4(\"8.8.8.8\"))\n\"google-public-dns-a.google.com\"\n\n\n\n\n\n","category":"function"},{"location":"stdlib/Sockets/#Sockets.getsockname","page":"套接字","title":"Sockets.getsockname","text":"getsockname(sock::Union{TCPServer, TCPSocket}) -> (IPAddr, UInt16)\n\nGet the IP address and port that the given socket is bound to.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/Sockets/#Sockets.getpeername","page":"套接字","title":"Sockets.getpeername","text":"getpeername(sock::TCPSocket) -> (IPAddr, UInt16)\n\nGet the IP address and port of the remote endpoint that the given socket is connected to. Valid only for connected TCP sockets.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/Sockets/#Sockets.IPAddr","page":"套接字","title":"Sockets.IPAddr","text":"IPAddr\n\nAbstract supertype for IP addresses. IPv4 and IPv6 are subtypes of this.\n\n\n\n\n\n","category":"type"},{"location":"stdlib/Sockets/#Sockets.IPv4","page":"套接字","title":"Sockets.IPv4","text":"IPv4(host::Integer) -> IPv4\n\nReturns an IPv4 object from ip address host formatted as an Integer.\n\nExamples\n\njulia> IPv4(3223256218)\nip\"192.30.252.154\"\n\n\n\n\n\n","category":"type"},{"location":"stdlib/Sockets/#Sockets.IPv6","page":"套接字","title":"Sockets.IPv6","text":"IPv6(host::Integer) -> IPv6\n\nReturns an IPv6 object from ip address host formatted as an Integer.\n\nExamples\n\njulia> IPv6(3223256218)\nip\"::c01e:fc9a\"\n\n\n\n\n\n","category":"type"},{"location":"stdlib/Sockets/#Sockets.@ip_str","page":"套接字","title":"Sockets.@ip_str","text":"@ip_str str -> IPAddr\n\nParse str as an IP address.\n\nExamples\n\njulia> ip\"127.0.0.1\"\nip\"127.0.0.1\"\n\njulia> @ip_str \"2001:db8:0:0:0:0:2:1\"\nip\"2001:db8::2:1\"\n\n\n\n\n\n","category":"macro"},{"location":"stdlib/Sockets/#Sockets.TCPSocket","page":"套接字","title":"Sockets.TCPSocket","text":"TCPSocket(; delay=true)\n\nOpen a TCP socket using libuv. If delay is true, libuv delays creation of the socket's file descriptor till the first bind call. TCPSocket has various fields to denote the state of the socket as well as its send/receive buffers.\n\n\n\n\n\n","category":"type"},{"location":"stdlib/Sockets/#Sockets.UDPSocket","page":"套接字","title":"Sockets.UDPSocket","text":"UDPSocket()\n\nOpen a UDP socket using libuv. UDPSocket has various fields to denote the state of the socket.\n\n\n\n\n\n","category":"type"},{"location":"stdlib/Sockets/#Sockets.accept","page":"套接字","title":"Sockets.accept","text":"accept(server[, client])\n\nAccepts a connection on the given server and returns a connection to the client. An uninitialized client stream may be provided, in which case it will be used instead of creating a new stream.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/Sockets/#Sockets.listenany","page":"套接字","title":"Sockets.listenany","text":"listenany([host::IPAddr,] port_hint) -> (UInt16, TCPServer)\n\nCreate a TCPServer on any port, using hint as a starting point. Returns a tuple of the actual port that the server was created on and the server itself.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/Sockets/#Base.bind","page":"套接字","title":"Base.bind","text":"bind(chnl::Channel, task::Task)\n\nAssociate the lifetime of chnl with a task. Channel chnl is automatically closed when the task terminates. Any uncaught exception in the task is propagated to all waiters on chnl.\n\nThe chnl object can be explicitly closed independent of task termination. Terminating tasks have no effect on already closed Channel objects.\n\nWhen a channel is bound to multiple tasks, the first task to terminate will close the channel. When multiple channels are bound to the same task, termination of the task will close all of the bound channels.\n\nExamples\n\njulia> c = Channel(0);\n\njulia> task = @async foreach(i->put!(c, i), 1:4);\n\njulia> bind(c,task);\n\njulia> for i in c\n @show i\n end;\ni = 1\ni = 2\ni = 3\ni = 4\n\njulia> isopen(c)\nfalse\n\njulia> c = Channel(0);\n\njulia> task = @async (put!(c, 1); error(\"foo\"));\n\njulia> bind(c, task);\n\njulia> take!(c)\n1\n\njulia> put!(c, 1);\nERROR: TaskFailedException\nStacktrace:\n[...]\n nested task error: foo\n[...]\n\n\n\n\n\nbind(socket::Union{TCPServer, UDPSocket, TCPSocket}, host::IPAddr, port::Integer; ipv6only=false, reuseaddr=false, kws...)\n\nBind socket to the given host:port. Note that 0.0.0.0 will listen on all devices.\n\nThe ipv6only parameter disables dual stack mode. If ipv6only=true, only an IPv6 stack is created.\nIf reuseaddr=true, multiple threads or processes can bind to the same address without error if they all set reuseaddr=true, but only the last to bind will receive any traffic.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/Sockets/#Sockets.send","page":"套接字","title":"Sockets.send","text":"send(socket::UDPSocket, host::IPAddr, port::Integer, msg)\n\nSend msg over socket to host:port.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/Sockets/#Sockets.recv","page":"套接字","title":"Sockets.recv","text":"recv(socket::UDPSocket)\n\nRead a UDP packet from the specified socket, and return the bytes received. This call blocks.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/Sockets/#Sockets.recvfrom","page":"套接字","title":"Sockets.recvfrom","text":"recvfrom(socket::UDPSocket) -> (host_port, data)\n\nRead a UDP packet from the specified socket, returning a tuple of (host_port, data), where host_port will be an InetAddr{IPv4} or InetAddr{IPv6}, as appropriate.\n\ncompat: Julia 1.3\nPrior to Julia version 1.3, the first returned value was an address (IPAddr). In version 1.3 it was changed to an InetAddr.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/Sockets/#Sockets.setopt","page":"套接字","title":"Sockets.setopt","text":"setopt(sock::UDPSocket; multicast_loop=nothing, multicast_ttl=nothing, enable_broadcast=nothing, ttl=nothing)\n\nSet UDP socket options.\n\nmulticast_loop: loopback for multicast packets (default: true).\nmulticast_ttl: TTL for multicast packets (default: nothing).\nenable_broadcast: flag must be set to true if socket will be used for broadcast messages, or else the UDP system will return an access error (default: false).\nttl: Time-to-live of packets sent on the socket (default: nothing).\n\n\n\n\n\n","category":"function"},{"location":"stdlib/Sockets/#Sockets.nagle","page":"套接字","title":"Sockets.nagle","text":"nagle(socket::Union{TCPServer, TCPSocket}, enable::Bool)\n\nEnables or disables Nagle's algorithm on a given TCP server or socket.\n\ncompat: Julia 1.3\nThis function requires Julia 1.3 or later.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/Sockets/#Sockets.quickack","page":"套接字","title":"Sockets.quickack","text":"quickack(socket::Union{TCPServer, TCPSocket}, enable::Bool)\n\nOn Linux systems, the TCP_QUICKACK is disabled or enabled on socket.\n\n\n\n\n\n","category":"function"},{"location":"manual/distributed-computing/#多进程和分布式计算","page":"多进程和分布式计算","title":"多进程和分布式计算","text":"","category":"section"},{"location":"manual/distributed-computing/","page":"多进程和分布式计算","title":"多进程和分布式计算","text":"分布式内存并行计算的实现由模块 Distributed 作为 Julia 附带的标准库的一部分提供。","category":"page"},{"location":"manual/distributed-computing/","page":"多进程和分布式计算","title":"多进程和分布式计算","text":"大多数现代计算机都拥有不止一个 CPU,而且多台计算机可以组织在一起形成一个集群。借助多个 CPU 的计算能力,许多计算过程能够更快地完成,这其中影响性能的两个主要因素分别是:CPU 自身的速度以及它们访问内存的速度。显然,在一个集群中,一个 CPU 访问同一个节点的 RAM 速度是最快的,不过令人吃惊的是,在一台典型的多核笔记本电脑上,由于访问主存和缓存的速度存在差别,类似的现象也会存在。因此,一个良好的多进程环境应该能够管理好某一片内存区域“所属”的CPU。Julia提供的多进程环境是基于消息传递来实现的,可以做到同时让程序在多个进程的不同内存区域中运行。","category":"page"},{"location":"manual/distributed-computing/","page":"多进程和分布式计算","title":"多进程和分布式计算","text":"Julia 的消息传递实现不同于其他环境,例如 MPI[1]。 Julia 中的通信通常是“单方面的”,这意味着程序员只需在双进程操作中显式管理一个进程。 此外,这些操作通常看起来不像“消息发送”和“消息接收”,而是类似于更高级别的操作,例如调用用户函数。","category":"page"},{"location":"manual/distributed-computing/","page":"多进程和分布式计算","title":"多进程和分布式计算","text":"Julia 中的分布式编程基于两个基本概念:远程引用(remote references)和远程调用(remote calls)。远程引用是一个对象,任意一个进程可以通过它访问存储在某个特定进程上的对象。远程调用指是某个进程发起的执行函数的请求,该函数会在另一个(也可能是同一个)进程中执行。","category":"page"},{"location":"manual/distributed-computing/","page":"多进程和分布式计算","title":"多进程和分布式计算","text":"远程引用有两种形式:Future 和 RemoteChannel。","category":"page"},{"location":"manual/distributed-computing/","page":"多进程和分布式计算","title":"多进程和分布式计算","text":"远程调用返回 Future 作为其结果。 远程调用立即返回;当远程调用发生在其他地方后,发出调用的进程继续执行下一个操作。你可以通过在返回的 Future 上调用 wait 来等待远程调用完成,并且可以使用 fetch。","category":"page"},{"location":"manual/distributed-computing/","page":"多进程和分布式计算","title":"多进程和分布式计算","text":"对于 RemoteChannel 而言,它可以被反复写入。例如,多个进程可以通过引用同一个远程 Channel 来协调相互之间的操作。","category":"page"},{"location":"manual/distributed-computing/","page":"多进程和分布式计算","title":"多进程和分布式计算","text":"每个进程都有一个关联的标识符。 提供交互式 Julia 提示符的进程的 id 总是等于 1。默认情况下用于并行操作的进程被称为“workers”。 当只有一个进程时,进程 1 被认为是一个worker。 否则,workers 被认为是进程 1 之外的所有进程。因此,需要添加 2 个或更多进程才能从 pmap 等并行处理方法中获益。 如果你只想在主进程中做其他事情,同时在工作进程上运行长时间的计算,那么添加单个进程是有益的。","category":"page"},{"location":"manual/distributed-computing/","page":"多进程和分布式计算","title":"多进程和分布式计算","text":"让我们开始尝试。 以 julia -p n 开始,在本地机器上提供 n 个工作进程。 通常,n 等于机器上的 CPU 线程(逻辑核心)的数量是有意义的。 请注意,-p 参数隐式加载模块 Distributed。","category":"page"},{"location":"manual/distributed-computing/","page":"多进程和分布式计算","title":"多进程和分布式计算","text":"$ julia -p 2\n\njulia> r = remotecall(rand, 2, 2, 2)\nFuture(2, 1, 4, nothing)\n\njulia> s = @spawnat 2 1 .+ fetch(r)\nFuture(2, 1, 5, nothing)\n\njulia> fetch(s)\n2×2 Array{Float64,2}:\n 1.18526 1.50912\n 1.16296 1.60607","category":"page"},{"location":"manual/distributed-computing/","page":"多进程和分布式计算","title":"多进程和分布式计算","text":"remotecall 的第一个参数是想要调用的函数,第二个参数是执行函数的进程 id,其余的参数会喂给将要被调用的函数。在 Julia 中进行并行编程时,一般不需要显示地指明具体在哪个进程上执行,不过 remotecall 是一个相对底层的接口用来提供细粒度的管理。","category":"page"},{"location":"manual/distributed-computing/","page":"多进程和分布式计算","title":"多进程和分布式计算","text":"可以看到,第一行代码请求进程2构建一个随机矩阵,第二行代码对该矩阵执行加一操作。每次执行的结果存在对应的 Future 中,即 r 和 s。这里 @spawnat 宏会在第一个参数所指定的进程中执行后面第二个参数中的表达式。","category":"page"},{"location":"manual/distributed-computing/","page":"多进程和分布式计算","title":"多进程和分布式计算","text":"有时候,你可能会希望立即获取远程计算的结果,比如,在接下来的操作中就需要读取远程调用的结果,这时候你可以使用 remotecall_fetch 函数,其效果相当于 fetch(remotecall(...)),不过更高效些。","category":"page"},{"location":"manual/distributed-computing/","page":"多进程和分布式计算","title":"多进程和分布式计算","text":"julia> remotecall_fetch(r-> fetch(r)[1, 1], 2, r)\n0.18526337335308085","category":"page"},{"location":"manual/distributed-computing/","page":"多进程和分布式计算","title":"多进程和分布式计算","text":"这将获取 worker 2 上的数组并返回第一个值。 请注意,在这种情况下,fetch 不会移动任何数据,因为它是在拥有该数组的 worker 上执行的。 还可以这样写:","category":"page"},{"location":"manual/distributed-computing/","page":"多进程和分布式计算","title":"多进程和分布式计算","text":"julia> remotecall_fetch(getindex, 2, r, 1, 1)\n0.10824216411304866","category":"page"},{"location":"manual/distributed-computing/","page":"多进程和分布式计算","title":"多进程和分布式计算","text":"回忆下,这里 getindex(r,1,1) 相当于 r[1,1],因此,上面的调用相当于获取 r 的第一个元素。","category":"page"},{"location":"manual/distributed-computing/","page":"多进程和分布式计算","title":"多进程和分布式计算","text":"为方便起见,可以将符号 :any 传递给 @spawnat,它会为你选择执行操作的位置:","category":"page"},{"location":"manual/distributed-computing/","page":"多进程和分布式计算","title":"多进程和分布式计算","text":"julia> r = @spawnat :any rand(2,2)\nFuture(2, 1, 4, nothing)\n\njulia> s = @spawnat :any 1 .+ fetch(r)\nFuture(3, 1, 5, nothing)\n\njulia> fetch(s)\n2×2 Array{Float64,2}:\n 1.38854 1.9098\n 1.20939 1.57158","category":"page"},{"location":"manual/distributed-computing/","page":"多进程和分布式计算","title":"多进程和分布式计算","text":"请注意,我们使用了 1 .+ fetch(r) 而不是 1 .+ r。 这是因为我们不知道代码将在哪里运行,因此通常可能需要一个 fetch 将 r 移动到执行添加的进程。 在这种情况下,@spawnat 足够聪明,可以在拥有 r 的进程上执行计算,因此 fetch 将是一个空操作(没有工作被完成)。","category":"page"},{"location":"manual/distributed-computing/","page":"多进程和分布式计算","title":"多进程和分布式计算","text":"(值得注意的是, @spawnat 不是内置的,而是在 Julia 中定义的 [宏](@ref man-macros)。你也可以自己定义此类构造。)","category":"page"},{"location":"manual/distributed-computing/","page":"多进程和分布式计算","title":"多进程和分布式计算","text":"需要记住的重要一点是,一旦 fetch,Future 将在本地缓存其值。 进一步的 fetch 调用不需要网络跃点。 一旦所有引用 Future 都已获取,远程存储的值将被删除。","category":"page"},{"location":"manual/distributed-computing/","page":"多进程和分布式计算","title":"多进程和分布式计算","text":"@async 类似于 @spawnat,但只在本地进程上运行任务。我们使用它为每个进程创建一个“feeder”任务。每个任务选择需要计算的下一个索引,然后等待其进程完成,然后重复直到我们用完索引。请注意,feeder任务直到主任务到达 @sync 块的末尾才开始执行,此时它放弃控制并等待所有本地任务完成,然后从主任务返回功能。对于 v0.7 及更高版本,feeder 任务能够通过 nextidx 共享状态,因为它们都运行在同一个进程上。即使Tasks 是协作调度的,在某些上下文中可能仍然需要锁定,例如在 asynchronous I/O 中。这意味着上下文切换只发生在明确定义的点:在这种情况下,当 remotecall_fetch 被调用时。这是当前的实现状态,它可能会在未来的 Julia 版本中发生变化,因为它旨在使在 M个 Process 上运行最多 N 个 Tasks 成为可能,也就是 M:N Threading。然后,需要为 nextidx 提供锁获取/释放模型,因为让多个进程同时读写一个资源是不安全的。","category":"page"},{"location":"manual/distributed-computing/#code-availability","page":"多进程和分布式计算","title":"访问代码以及加载库","text":"","category":"section"},{"location":"manual/distributed-computing/","page":"多进程和分布式计算","title":"多进程和分布式计算","text":"对于想要并行执行的代码,需要所有对所有进程都可见。例如,在 Julia 命令行中输入以下命令:","category":"page"},{"location":"manual/distributed-computing/","page":"多进程和分布式计算","title":"多进程和分布式计算","text":"julia> function rand2(dims...)\n return 2*rand(dims...)\n end\n\njulia> rand2(2,2)\n2×2 Array{Float64,2}:\n 0.153756 0.368514\n 1.15119 0.918912\n\njulia> fetch(@spawnat :any rand2(2,2))\nERROR: RemoteException(2, CapturedException(UndefVarError(Symbol(\"#rand2\"))\nStacktrace:\n[...]","category":"page"},{"location":"manual/distributed-computing/","page":"多进程和分布式计算","title":"多进程和分布式计算","text":"进程1知道函数 rand2 的存在,但进程2并不知道。","category":"page"},{"location":"manual/distributed-computing/","page":"多进程和分布式计算","title":"多进程和分布式计算","text":"大多数情况下,你会从文件或者库中加载代码,在此过程中你可以灵活地控制哪个进程加载哪部分代码。假设有这样一个文件,DummyModule.jl,其代码如下:","category":"page"},{"location":"manual/distributed-computing/","page":"多进程和分布式计算","title":"多进程和分布式计算","text":"module DummyModule\n\nexport MyType, f\n\nmutable struct MyType\n a::Int\nend\n\nf(x) = x^2+1\n\nprintln(\"loaded\")\n\nend","category":"page"},{"location":"manual/distributed-computing/","page":"多进程和分布式计算","title":"多进程和分布式计算","text":"为了在所有进程中引用 MyType,DummyModule.jl 需要在每个进程中载入。单独执行 include(\"DummyModule.jl\") 只会在一个进程中将其载入。为了让每个进程都载入它,可以用 @everywhere 宏来实现(启动 Julia 的时候,执行 julia -p 2)。","category":"page"},{"location":"manual/distributed-computing/","page":"多进程和分布式计算","title":"多进程和分布式计算","text":"julia> @everywhere include(\"DummyModule.jl\")\nloaded\n From worker 3: loaded\n From worker 2: loaded","category":"page"},{"location":"manual/distributed-computing/","page":"多进程和分布式计算","title":"多进程和分布式计算","text":"像往常一样,这不会将 DummyModule 引入任何进程的作用域,这需要 using 或 import。 此外,当 DummyModule 被带入一个进程的作用域时,它不在任何其他进程中:","category":"page"},{"location":"manual/distributed-computing/","page":"多进程和分布式计算","title":"多进程和分布式计算","text":"julia> using .DummyModule\n\njulia> MyType(7)\nMyType(7)\n\njulia> fetch(@spawnat 2 MyType(7))\nERROR: On worker 2:\nUndefVarError: MyType not defined\n⋮\n\njulia> fetch(@spawnat 2 DummyModule.MyType(7))\nMyType(7)","category":"page"},{"location":"manual/distributed-computing/","page":"多进程和分布式计算","title":"多进程和分布式计算","text":"不过,我们仍然可以在已经包含(include)过 DummyModule 的进程中,发送 MyType 类型的实例,尽管此时该进程的命名空间中并没有 MyType 变量:","category":"page"},{"location":"manual/distributed-computing/","page":"多进程和分布式计算","title":"多进程和分布式计算","text":"julia> put!(RemoteChannel(2), MyType(7))\nRemoteChannel{Channel{Any}}(2, 1, 13)","category":"page"},{"location":"manual/distributed-computing/","page":"多进程和分布式计算","title":"多进程和分布式计算","text":"文件代码还可以在启动的时候,通过 -L 参数指定,从而提前在多个进程中载入,然后通过一个 driver.jl 文件控制执行逻辑:","category":"page"},{"location":"manual/distributed-computing/","page":"多进程和分布式计算","title":"多进程和分布式计算","text":"julia -p -L file1.jl -L file2.jl driver.jl","category":"page"},{"location":"manual/distributed-computing/","page":"多进程和分布式计算","title":"多进程和分布式计算","text":"上面执行 driver.jl 的进程 id 为1,就跟提供交互式命令行的 Julia 进程一样。","category":"page"},{"location":"manual/distributed-computing/","page":"多进程和分布式计算","title":"多进程和分布式计算","text":"最后,如果DummyModule.jl不是一个独立的文件,而是一个包,那么using DummyModule将在所有进程上加载 DummyModule.jl,但只在调用[using](@ref)的进程上将其纳入作用域。","category":"page"},{"location":"manual/distributed-computing/#启动和管理-worker-进程","page":"多进程和分布式计算","title":"启动和管理 worker 进程","text":"","category":"section"},{"location":"manual/distributed-computing/","page":"多进程和分布式计算","title":"多进程和分布式计算","text":"Julia 自带两种集群管理模式:","category":"page"},{"location":"manual/distributed-computing/","page":"多进程和分布式计算","title":"多进程和分布式计算","text":"本地集群,前面通过启动时指定 -p 参数就是这种模式\n跨机器的集群,通过 --machine-file 指定。这种模式采用没有密码的 ssh 登陆并对应的机器上(与 host 相同的路径下)启动 Julia 的 worker 进程。每个机器定义都采用 [count*][user@]host[:port] [bind_addr[:port]] 的形式。 user 默认为当前用户,port 为标准 ssh 端口。count 是在节点上生成的 worker 数量,默认为 1。可选的 bind-to bind_addr[:port] 指定其他 worker 应该用来连接到这个 worker 的 IP 地址和端口。","category":"page"},{"location":"manual/distributed-computing/","page":"多进程和分布式计算","title":"多进程和分布式计算","text":"addprocs, rmprocs, workers 这些函数可以分别用来对集群中的进程进行增加,删除和修改。","category":"page"},{"location":"manual/distributed-computing/","page":"多进程和分布式计算","title":"多进程和分布式计算","text":"julia> using Distributed\n\njulia> addprocs(2)\n2-element Array{Int64,1}:\n 2\n 3","category":"page"},{"location":"manual/distributed-computing/","page":"多进程和分布式计算","title":"多进程和分布式计算","text":"模块 Distributed 必须在调用 addprocs 之前显式加载到主进程上。 它在工作进程上自动可用。","category":"page"},{"location":"manual/distributed-computing/","page":"多进程和分布式计算","title":"多进程和分布式计算","text":"请注意,worker 不会运行 ~/.julia/config/startup.jl 启动脚本,也不会将其全局状态(例如全局变量、新方法定义和加载的模块)与任何其他正在运行的进程同步 。你可以使用 addprocs(exeflags=\"--project\") 来初始化具有特定环境的 worker,然后使用 @everywhere using 或 @everywhere include(\"file.jl\")。","category":"page"},{"location":"manual/distributed-computing/","page":"多进程和分布式计算","title":"多进程和分布式计算","text":"其它类型的集群可以通过自己写一个 ClusterManager 来实现,下面 集群管理器 部分会介绍。","category":"page"},{"location":"manual/distributed-computing/#数据转移","page":"多进程和分布式计算","title":"数据转移","text":"","category":"section"},{"location":"manual/distributed-computing/","page":"多进程和分布式计算","title":"多进程和分布式计算","text":"分布式程序的性能瓶颈主要是由发送消息和数据转移造成的,减少发送消息和转移数据的数量对于获取高性能和可扩展性至关重要,因此,深入了解 Julia 分布式程序是如何转移数据的非常有必要。","category":"page"},{"location":"manual/distributed-computing/","page":"多进程和分布式计算","title":"多进程和分布式计算","text":"fetch 可以被认为是一个显式的数据转移操作,因为它直接要求将一个对象移动到本地机器。 @spawnat(以及一些相关的结构体)也移动数据,但这并不明显,因此可以称为隐式数据转移操作。 考虑这两种构造和平方一个随机矩阵的方法:","category":"page"},{"location":"manual/distributed-computing/","page":"多进程和分布式计算","title":"多进程和分布式计算","text":"方法一:","category":"page"},{"location":"manual/distributed-computing/","page":"多进程和分布式计算","title":"多进程和分布式计算","text":"julia> A = rand(1000,1000);\n\njulia> Bref = @spawnat :any A^2;\n\n[...]\n\njulia> fetch(Bref);","category":"page"},{"location":"manual/distributed-computing/","page":"多进程和分布式计算","title":"多进程和分布式计算","text":"方法二:","category":"page"},{"location":"manual/distributed-computing/","page":"多进程和分布式计算","title":"多进程和分布式计算","text":"julia> Bref = @spawnat :any rand(1000,1000)^2;\n\n[...]\n\njulia> fetch(Bref);","category":"page"},{"location":"manual/distributed-computing/","page":"多进程和分布式计算","title":"多进程和分布式计算","text":"这种差异看起来微不足道,但实际上由于 @spawnat 的行为而非常显着。 在第一种方法中,在本地构造一个随机矩阵,然后将其发送到另一个进程进行平方。 在第二种方法中,随机矩阵在另一个进程中被构造和平方。 因此,第二种方法发送的数据比第一种方法少得多。","category":"page"},{"location":"manual/distributed-computing/","page":"多进程和分布式计算","title":"多进程和分布式计算","text":"在这个简单示例中,这两种方法很容易区分和选择。 然而,在一个真正的程序设计数据转移可能需要更多的思考和一些测量。 例如,如果第一个进程需要矩阵A,那么第一种方法可能更好。 或者,如果计算 A 很昂贵并且只有当前进程拥有它,那么将它移到另一个进程可能是不可避免的。 或者,如果当前进程在 @spawnat 和 fetch(Bref) 之间几乎没有什么关系,最好完全消除并行性。 或者想象一下 rand(1000,1000) 被更昂贵的操作取代。 那么为这一步添加另一个 @spawnat 语句可能是有意义的。","category":"page"},{"location":"manual/distributed-computing/#全局变量","page":"多进程和分布式计算","title":"全局变量","text":"","category":"section"},{"location":"manual/distributed-computing/","page":"多进程和分布式计算","title":"多进程和分布式计算","text":"通过 @spawnat 远程执行的表达式,或使用 remotecall 为远程执行指定的闭包可能会引用全局变量。 与其他模块中的全局绑定相比,模块 Main 下的全局绑定的处理方式略有不同。 考虑以下代码片段:","category":"page"},{"location":"manual/distributed-computing/","page":"多进程和分布式计算","title":"多进程和分布式计算","text":"A = rand(10,10)\nremotecall_fetch(()->sum(A), 2)","category":"page"},{"location":"manual/distributed-computing/","page":"多进程和分布式计算","title":"多进程和分布式计算","text":"在这种情况下,sum 必须在远程进程中定义。请注意,A 是在本地工作区中定义的全局变量。 worker 2 在 Main 下没有名为 A 的变量。 将闭包 ()->sum(A) 传送到 worker 2 的行为导致 Main.A 被定义在 2 上。即使在调用 remotecall_fetch 返回之后, Main.A 仍然存在于 worker 2 上。带有嵌入式全局引用的远程调用(仅在Main 模块下)以如下的方式管理全局变量:","category":"page"},{"location":"manual/distributed-computing/","page":"多进程和分布式计算","title":"多进程和分布式计算","text":"在全局调用中引用的全局绑定会在将要执行该调用的 worker 中被创建。\n全局常量仍然在远端结点定义为常量。\n全局绑定会在下一次远程调用中引用到的时候,当其值发生改变时,再次发送给目标 worker。此外,集群并不会所有结点的全局绑定。例如:\nA = rand(10,10)\nremotecall_fetch(()->sum(A), 2) # worker 2\nA = rand(10,10)\nremotecall_fetch(()->sum(A), 3) # worker 3\nA = nothing\n可以看到,A 作为全局变量在 worker 2中有定义,而 B 是一个局部变量,因而最后在 worker 2 中并没有 B 的绑定。 执行以上代码之后,worker 2 和 worker 3中的 Main.A 的值是不同的,同时,节点1上的值则为 nothing。","category":"page"},{"location":"manual/distributed-computing/","page":"多进程和分布式计算","title":"多进程和分布式计算","text":"也许你也注意到了,在 master 主节点上被赋值为 nothing 之后,全局变量的内存会被回收,但在 worker 节点上的全局变量并没有被回收掉。执行 clear 可以手动将远端结点上的特定全局变量置为 nothing,然后对应的内存会被周期性的垃圾回收机制回收。","category":"page"},{"location":"manual/distributed-computing/","page":"多进程和分布式计算","title":"多进程和分布式计算","text":"因此,在远程调用中,需要非常小心地引用全局变量。事实上,应当尽量避免引用全局变量,如果必须引用,那么可以考虑用let代码块将全局变量局部化:","category":"page"},{"location":"manual/distributed-computing/","page":"多进程和分布式计算","title":"多进程和分布式计算","text":"julia> A = rand(10,10);\n\njulia> remotecall_fetch(()->A, 2);\n\njulia> B = rand(10,10);\n\njulia> let B = B\n remotecall_fetch(()->B, 2)\n end;\n\njulia> @fetchfrom 2 InteractiveUtils.varinfo()\nname size summary\n––––––––– ––––––––– ––––––––––––––––––––––\nA 800 bytes 10×10 Array{Float64,2}\nBase Module\nCore Module\nMain Module","category":"page"},{"location":"manual/distributed-computing/","page":"多进程和分布式计算","title":"多进程和分布式计算","text":"可以看到,A 作为全局变量在 worker 2中有定义,而 B 是一个局部变量,因而最后在 worker 2 中并没有 B 的绑定。","category":"page"},{"location":"manual/distributed-computing/#并行的Map和Loop","page":"多进程和分布式计算","title":"并行的Map和Loop","text":"","category":"section"},{"location":"manual/distributed-computing/","page":"多进程和分布式计算","title":"多进程和分布式计算","text":"幸运的是,许多有用的并行计算不需要数据转移。 一个常见的例子是蒙特卡罗模拟,其中多个进程可以同时处理独立的模拟试验。 我们可以使用 @spawnat 在两个进程上抛硬币。 首先,在 count_heads.jl 中编写以下函数:","category":"page"},{"location":"manual/distributed-computing/","page":"多进程和分布式计算","title":"多进程和分布式计算","text":"function count_heads(n)\n c::Int = 0\n for i = 1:n\n c += rand(Bool)\n end\n c\nend","category":"page"},{"location":"manual/distributed-computing/","page":"多进程和分布式计算","title":"多进程和分布式计算","text":"函数 count_heads 只是简单地将 n 个随机 0-1 值累加,下面在两个机器上进行试验,并将结果叠加:","category":"page"},{"location":"manual/distributed-computing/","page":"多进程和分布式计算","title":"多进程和分布式计算","text":"julia> @everywhere include_string(Main, $(read(\"count_heads.jl\", String)), \"count_heads.jl\")\n\njulia> a = @spawnat :any count_heads(100000000)\nFuture(2, 1, 6, nothing)\n\njulia> b = @spawnat :any count_heads(100000000)\nFuture(3, 1, 7, nothing)\n\njulia> fetch(a)+fetch(b)\n100001564","category":"page"},{"location":"manual/distributed-computing/","page":"多进程和分布式计算","title":"多进程和分布式计算","text":"上面的例子展示了一种非常常见而且有用的并行编程模式,在一些进程中执行多次独立的迭代,然后将它们的结果通过某个函数合并到一起,这个合并操作通常称作聚合(reduction),也就是一般意义上的张量降维(tensor-rank-reducing),比如将一个向量降维成一个数,或者是将一个 tensor 降维到某一行或者某一列等。在代码中,通常具有 x = f(x, v[i]) 这种形式,其中 x 是一个叠加器,f 是一个聚合函数,而 v[i] 则是将要被聚合的值。一般来说,f 要求满足结合律,这样不管执行的顺序如何,都不会影响计算结果。","category":"page"},{"location":"manual/distributed-computing/","page":"多进程和分布式计算","title":"多进程和分布式计算","text":"请注意,我们可以将这种count_heads 模式推广。 我们使用了两个显式的 @spawnat 语句,将并行性限制为两个进程。 要在任意数量的进程上运行,我们可以使用 并行for循环,在分布式内存中运行,可以在 Julia 中使用 @distributed 编写,如下所示:","category":"page"},{"location":"manual/distributed-computing/","page":"多进程和分布式计算","title":"多进程和分布式计算","text":"nheads = @distributed (+) for i = 1:200000000\n Int(rand(Bool))\nend","category":"page"},{"location":"manual/distributed-computing/","page":"多进程和分布式计算","title":"多进程和分布式计算","text":"上面的写法将多次迭代分配到了不同的进程,然后通过一个聚合函数(这里是 (+))合并计算结果,其中,每次迭代的结果作为 for 循环中的表达式的结果,最后整个循环的结果聚合后得到最终的结果。","category":"page"},{"location":"manual/distributed-computing/","page":"多进程和分布式计算","title":"多进程和分布式计算","text":"注意,尽管这里 for 循环看起来跟串行的 for 循环差不多,实际表现完全不同。这里的迭代并没有特定的执行顺序,而且由于所有的迭代都在不同的进程中进行,其中变量的写入对全局来说不可见。所有并行的 for 循环中的变量都会复制并广播到每个进程。","category":"page"},{"location":"manual/distributed-computing/","page":"多进程和分布式计算","title":"多进程和分布式计算","text":"比如,下面这段代码并不会像你想要的那样执行:","category":"page"},{"location":"manual/distributed-computing/","page":"多进程和分布式计算","title":"多进程和分布式计算","text":"a = zeros(100000)\n@distributed for i = 1:100000\n a[i] = i\nend","category":"page"},{"location":"manual/distributed-computing/","page":"多进程和分布式计算","title":"多进程和分布式计算","text":"这段代码并不会把 a 的所有元素初始化,因为每个进程都会有一份 a 的拷贝,因此类似的 for 循环一定要避免。幸运的是,共享数组 可以用来突破这种限制:","category":"page"},{"location":"manual/distributed-computing/","page":"多进程和分布式计算","title":"多进程和分布式计算","text":"using SharedArrays\n\na = SharedArray{Float64}(10)\n@distributed for i = 1:10\n a[i] = i\nend","category":"page"},{"location":"manual/distributed-computing/","page":"多进程和分布式计算","title":"多进程和分布式计算","text":"当然,对于 for 循环外面的变量来说,如果是只读的话,使用起来完全没问题:","category":"page"},{"location":"manual/distributed-computing/","page":"多进程和分布式计算","title":"多进程和分布式计算","text":"a = randn(1000)\n@distributed (+) for i = 1:100000\n f(a[rand(1:end)])\nend","category":"page"},{"location":"manual/distributed-computing/","page":"多进程和分布式计算","title":"多进程和分布式计算","text":"这里每次迭代都会从共享给每个进程的向量 a 中随机选一个样本,然后用来计算 f。","category":"page"},{"location":"manual/distributed-computing/","page":"多进程和分布式计算","title":"多进程和分布式计算","text":"如你所见,如果不需要,可以省略归约运算符。 在这种情况下,循环异步执行,即它在所有可用的 worker 上产生独立的任务,并立即返回一个 Future 数组,而无需等待完成。 调用者可以稍后通过调用 fetch 来等待 Future 完成,或者通过添加前缀 @sync,比如 @sync @distributed for,来等待循环结束。","category":"page"},{"location":"manual/distributed-computing/","page":"多进程和分布式计算","title":"多进程和分布式计算","text":"在一些不需要聚合函数的情况下,我们可能只是像对某个范围内的整数应用一个函数(或者,更一般地,某个序列中的所有元素),这种操作称作并行的 map,在 Julia 中有一个对应的函数 pmap。例如,可以像下面这样计算一些随机大矩阵的奇异值:","category":"page"},{"location":"manual/distributed-computing/","page":"多进程和分布式计算","title":"多进程和分布式计算","text":"julia> M = Matrix{Float64}[rand(1000,1000) for i = 1:10];\n\njulia> pmap(svdvals, M);","category":"page"},{"location":"manual/distributed-computing/","page":"多进程和分布式计算","title":"多进程和分布式计算","text":"Julia 中的 pmap 是被设计用来处理一些计算量比较复杂的函数的并行化的。与之对比的是,@distributed for 是用来处理一些每次迭代计算都很轻量的计算,比如简单地对两个数求和。pmap 和 @distributed for 都只会用到 worker 的进程。对于 @distributed for 而言,最后的聚合计算由发起者的进程完成。","category":"page"},{"location":"manual/distributed-computing/#远程引用和-AbstractChannel","page":"多进程和分布式计算","title":"远程引用和 AbstractChannel","text":"","category":"section"},{"location":"manual/distributed-computing/","page":"多进程和分布式计算","title":"多进程和分布式计算","text":"远程引用通常指某种 AbstractChannel 的实现。","category":"page"},{"location":"manual/distributed-computing/","page":"多进程和分布式计算","title":"多进程和分布式计算","text":"AbstractChannel(如Channel)的具体实现,需要实现 put!, take!, fetch , isready 和 wait。 Future 所引用的远程对象存储在Channel{Any}(1) 中,即大小为 1 的、能够容纳 Any 类型对象的 Channel 。","category":"page"},{"location":"manual/distributed-computing/","page":"多进程和分布式计算","title":"多进程和分布式计算","text":"RemoteChannel 可以被反复写入,可以指向任意大小和类型的 channel(或者是任意 AbstractChannel 的实现)。","category":"page"},{"location":"manual/distributed-computing/","page":"多进程和分布式计算","title":"多进程和分布式计算","text":"RemoteChannel(f::Function, pid)() 构造器可以构造一些引用,而这些引用指向的 channel 可以容纳多个某种具体类型的数据。其中 f 是将要在 pid 上执行的函数,其返回值必须是 AbstractChannel 类型。","category":"page"},{"location":"manual/distributed-computing/","page":"多进程和分布式计算","title":"多进程和分布式计算","text":"例如,RemoteChannel(()->Channel{Int}(10), pid) 会创建一个 channel,其类型是 Int,容量是 10,这个 channel 存在于 pid 进程中。","category":"page"},{"location":"manual/distributed-computing/","page":"多进程和分布式计算","title":"多进程和分布式计算","text":"针对 RemoteChannel 的 put!, take!, fetch, isready 和 wait 方法会被重定向到其底层存储着 channel 的进程。","category":"page"},{"location":"manual/distributed-computing/","page":"多进程和分布式计算","title":"多进程和分布式计算","text":"因此,RemoteChannel 可以用来引用用户自定义的 AbstractChannel 对象。在 Examples repository 中的 dictchannel.jl 文件中有一个简单的例子,其中使用了一个字典用于远端存储。","category":"page"},{"location":"manual/distributed-computing/#Channel-和-RemoteChannel","page":"多进程和分布式计算","title":"Channel 和 RemoteChannel","text":"","category":"section"},{"location":"manual/distributed-computing/","page":"多进程和分布式计算","title":"多进程和分布式计算","text":"一个 Channel 仅对局部的进程可见,worker 2 无法直接访问 worker 3 上的 Channel,反之亦如此。不过 RemoteChannel 可以跨 worker 获取和写入数据。\nRemoteChannel 可以看作是对 Channel 的封装。\nRemoteChannel 的 pid 就是其封装的 channel 所在的进程 id。\n任意拥有 RemoteChannel 引用的进程都可以对其进行读写,数据会自动发送到 RemoteChannel 底层 channel 的进程(或从中获取数据)\n序列化 Channel 会将其中的所有数据也都序列化,因此反序列化的时候也就可以得到一个原始数据的拷贝。\n不过,对 RemoteChannel 的序列化则只会序列化其底层指向的 channel 的 id,因此反序列化之后得到的对象仍然会指向之前存储的对象。","category":"page"},{"location":"manual/distributed-computing/","page":"多进程和分布式计算","title":"多进程和分布式计算","text":"如上的通道示例可以修改为进程间通信,如下所示","category":"page"},{"location":"manual/distributed-computing/","page":"多进程和分布式计算","title":"多进程和分布式计算","text":"首先,起 4 个 worker 进程处理同一个 remote channel jobs,其中的每个 job 都有一个对应的 job_id,然后每个 task 读取一个 job_id,然后模拟随机等待一段时间,然后往存储结果的 RemoteChannel 中写入一个 Tuple 对象,其中包含 job_id 和等待的时间。最后将结果打印出来。","category":"page"},{"location":"manual/distributed-computing/","page":"多进程和分布式计算","title":"多进程和分布式计算","text":"julia> addprocs(4); # add worker processes\n\njulia> const jobs = RemoteChannel(()->Channel{Int}(32));\n\njulia> const results = RemoteChannel(()->Channel{Tuple}(32));\n\njulia> @everywhere function do_work(jobs, results) # define work function everywhere\n while true\n job_id = take!(jobs)\n exec_time = rand()\n sleep(exec_time) # simulates elapsed time doing actual work\n put!(results, (job_id, exec_time, myid()))\n end\n end\n\njulia> function make_jobs(n)\n for i in 1:n\n put!(jobs, i)\n end\n end;\n\njulia> n = 12;\n\njulia> errormonitor(@async make_jobs(n)); # feed the jobs channel with \"n\" jobs\n\njulia> for p in workers() # start tasks on the workers to process requests in parallel\n remote_do(do_work, p, jobs, results)\n end\n\njulia> @elapsed while n > 0 # print out results\n job_id, exec_time, where = take!(results)\n println(\"$job_id finished in $(round(exec_time; digits=2)) seconds on worker $where\")\n global n = n - 1\n end\n1 finished in 0.18 seconds on worker 4\n2 finished in 0.26 seconds on worker 5\n6 finished in 0.12 seconds on worker 4\n7 finished in 0.18 seconds on worker 4\n5 finished in 0.35 seconds on worker 5\n4 finished in 0.68 seconds on worker 2\n3 finished in 0.73 seconds on worker 3\n11 finished in 0.01 seconds on worker 3\n12 finished in 0.02 seconds on worker 3\n9 finished in 0.26 seconds on worker 5\n8 finished in 0.57 seconds on worker 4\n10 finished in 0.58 seconds on worker 2\n0.055971741","category":"page"},{"location":"manual/distributed-computing/#远程调用和分布式垃圾回收","page":"多进程和分布式计算","title":"远程调用和分布式垃圾回收","text":"","category":"section"},{"location":"manual/distributed-computing/","page":"多进程和分布式计算","title":"多进程和分布式计算","text":"远程引用所指向的对象可以在其所有引用都被集群删除之后被释放掉。","category":"page"},{"location":"manual/distributed-computing/","page":"多进程和分布式计算","title":"多进程和分布式计算","text":"存储值的节点会跟踪哪些 worker 引用了它。 每次将 RemoteChannel 或(未获取的)Future 序列化为 worker 时,都会通知引用指向的节点。 并且每次在本地对 RemoteChannel 或(未获取的)Future 进行垃圾回收时,都会再次通知拥有该值的节点。 这是在内部集群感知序列化程序中实现的。 远程引用仅在正在运行的集群的上下文中有效。 不支持对常规IO对象的引用进行序列化和反序列化。","category":"page"},{"location":"manual/distributed-computing/","page":"多进程和分布式计算","title":"多进程和分布式计算","text":"上面说到的通知都是通过发送\"跟踪\"信息来实现的,当一个引用被序列化的时候,就会发送\"添加引用\"的信息,而一个引用被本地的垃圾回收器回收的时候,就会发送一个\"删除引用\"的信息。","category":"page"},{"location":"manual/distributed-computing/","page":"多进程和分布式计算","title":"多进程和分布式计算","text":"由于 Future 是一次性写入并在本地缓存,因此 fetching 一个 Future 的行为也会更新拥有该值的节点上的引用跟踪信息。","category":"page"},{"location":"manual/distributed-computing/","page":"多进程和分布式计算","title":"多进程和分布式计算","text":"一旦指向某个值的引用都被删除了,对应的节点会将其释放。","category":"page"},{"location":"manual/distributed-computing/","page":"多进程和分布式计算","title":"多进程和分布式计算","text":"使用 [Future](@ref Distributed.Future),将已获取的[Future](@ref Distributed.Future)序列化到其他节点也会发送该值,因为此时原始远程存储可能已收集该值了。","category":"page"},{"location":"manual/distributed-computing/","page":"多进程和分布式计算","title":"多进程和分布式计算","text":"此外需要注意的是,本地的垃圾回收到底发生在什么时候取决于具体对象的大小以及当时系统的内存压力。","category":"page"},{"location":"manual/distributed-computing/","page":"多进程和分布式计算","title":"多进程和分布式计算","text":"在远程引用的情况下,本地引用对象的大小非常小,而存储在远程节点上的值可能非常大。 由于可能不会立即收集本地对象,因此在 RemoteChannel 的本地实例或未获取的 Future 上显式调用 finalize 是一个好习惯 。 由于在 Future 上调用 fetch 也会从远程存储中删除其引用,因此在获取的 Future 上不需要这样做。 显式调用 finalize 会导致立即向远程节点发送消息以继续并删除其对该值的引用。","category":"page"},{"location":"manual/distributed-computing/","page":"多进程和分布式计算","title":"多进程和分布式计算","text":"一旦执行了 finalize 之后,引用就不可用了。","category":"page"},{"location":"manual/distributed-computing/#本地调用","page":"多进程和分布式计算","title":"本地调用","text":"","category":"section"},{"location":"manual/distributed-computing/","page":"多进程和分布式计算","title":"多进程和分布式计算","text":"数据必须复制到远程节点以供执行。 远程调用和数据存储到不同节点上的 RemoteChannel / Future 时都是这种情况。 正如预期的那样,这会在远程节点上生成序列化对象的副本。 但是,当目的节点是本地节点时,即调用进程id与远程节点id相同,则作为本地调用执行。 它通常(并非总是)在不同的 Task 中执行 - 但没有数据的序列化/反序列化。 因此,该调用引用了与传递相同的对象实例 - 没有创建副本。 这种行为在下面突出显示:","category":"page"},{"location":"manual/distributed-computing/","page":"多进程和分布式计算","title":"多进程和分布式计算","text":"julia> using Distributed;\n\njulia> rc = RemoteChannel(()->Channel(3)); # RemoteChannel created on local node\n\njulia> v = [0];\n\njulia> for i in 1:3\n v[1] = i # Reusing `v`\n put!(rc, v)\n end;\n\njulia> result = [take!(rc) for _ in 1:3];\n\njulia> println(result);\nArray{Int64,1}[[3], [3], [3]]\n\njulia> println(\"Num Unique objects : \", length(unique(map(objectid, result))));\nNum Unique objects : 1\n\njulia> addprocs(1);\n\njulia> rc = RemoteChannel(()->Channel(3), workers()[1]); # RemoteChannel created on remote node\n\njulia> v = [0];\n\njulia> for i in 1:3\n v[1] = i\n put!(rc, v)\n end;\n\njulia> result = [take!(rc) for _ in 1:3];\n\njulia> println(result);\nArray{Int64,1}[[1], [2], [3]]\n\njulia> println(\"Num Unique objects : \", length(unique(map(objectid, result))));\nNum Unique objects : 3","category":"page"},{"location":"manual/distributed-computing/","page":"多进程和分布式计算","title":"多进程和分布式计算","text":"可以看出,本地拥有的 RemoteChannel 上的 put! 在调用之间修改了相同的对象 v 会导致存储相同的单个对象实例。 与当拥有 rc 的节点是不同节点时创建的 v 副本相反。","category":"page"},{"location":"manual/distributed-computing/","page":"多进程和分布式计算","title":"多进程和分布式计算","text":"需要注意的是,这通常不是问题。 只有当对象既存储在本地又在调用后被修改时,才需要考虑这一点。 在这种情况下,存储对象的 deepcopy 可能是合适的。","category":"page"},{"location":"manual/distributed-computing/","page":"多进程和分布式计算","title":"多进程和分布式计算","text":"对于本地节点上的远程调用也是如此,如下例所示:","category":"page"},{"location":"manual/distributed-computing/","page":"多进程和分布式计算","title":"多进程和分布式计算","text":"julia> using Distributed; addprocs(1);\n\njulia> v = [0];\n\njulia> v2 = remotecall_fetch(x->(x[1] = 1; x), myid(), v); # Executed on local node\n\njulia> println(\"v=$v, v2=$v2, \", v === v2);\nv=[1], v2=[1], true\n\njulia> v = [0];\n\njulia> v2 = remotecall_fetch(x->(x[1] = 1; x), workers()[1], v); # Executed on remote node\n\njulia> println(\"v=$v, v2=$v2, \", v === v2);\nv=[0], v2=[1], false","category":"page"},{"location":"manual/distributed-computing/","page":"多进程和分布式计算","title":"多进程和分布式计算","text":"再次可以看出,对本地节点的远程调用就像直接调用一样。调用修改作为参数传递的本地对象。 在远程调用中,它对参数的副本进行操作。","category":"page"},{"location":"manual/distributed-computing/","page":"多进程和分布式计算","title":"多进程和分布式计算","text":"重复一遍,一般来说这不是问题。 如果本地节点也被用作计算节点,并且在调用后使用的参数,则需要考虑此行为,并且如果需要,必须将参数的深拷贝传递给在本地节点上唤起的调用。 对远程节点的调用将始终对参数的副本进行操作。","category":"page"},{"location":"manual/distributed-computing/#man-shared-arrays","page":"多进程和分布式计算","title":"共享数组","text":"","category":"section"},{"location":"manual/distributed-computing/","page":"多进程和分布式计算","title":"多进程和分布式计算","text":"共享数组使用系统共享内存将数组映射到多个进程上,尽管和 DArray 有点像,但其实际表现有很大不同。在 DArray 中,每个进程可以访问数据中的一块,但任意两个进程都不能共享同一块数据,而对于 SharedArray,每个进程都可以访问整个数组。如果你想在一台机器上,让一大块数据能够被多个进程访问到,那么 SharedArray 是个不错的选择。","category":"page"},{"location":"manual/distributed-computing/","page":"多进程和分布式计算","title":"多进程和分布式计算","text":"共享数组由 SharedArray 提供,必须在所有相关的 worker 中都显式地加载。","category":"page"},{"location":"manual/distributed-computing/","page":"多进程和分布式计算","title":"多进程和分布式计算","text":"对 SharedArray 索引(访问和复制)操作就跟普通的数组一样,由于底层的内存对本地的进程是可见的,索引的效率很高,因此大多数单进程上的算法对 SharedArray 来说都是适用的,除非某些算法必须使用 Array 类型(此时可以通过调用 sdata 来获取 SharedArray 数组)。对于其它类型的 AbstractArray 类型数组来说,sdata 仅仅会返回数组本身,因此,可以放心地使用 sdata 对任意类型的 Array 进行操作。","category":"page"},{"location":"manual/distributed-computing/","page":"多进程和分布式计算","title":"多进程和分布式计算","text":"共享数组可以通过以下形式构造:","category":"page"},{"location":"manual/distributed-computing/","page":"多进程和分布式计算","title":"多进程和分布式计算","text":"SharedArray{T,N}(dims::NTuple; init=false, pids=Int[])","category":"page"},{"location":"manual/distributed-computing/","page":"多进程和分布式计算","title":"多进程和分布式计算","text":"它在由 pids 指定的进程中创建了一个位类型为 T 和形状为 dims 的 N 维共享数组。 与分布式数组不同,共享数组只能从由pids 命名参数指定的那些参与 worker 访问(如果创建过程在同一主机上,也是如此)。 请注意,SharedArray 中仅支持 isbits 元素。","category":"page"},{"location":"manual/distributed-computing/","page":"多进程和分布式计算","title":"多进程和分布式计算","text":"如果提供了一个类型为 initfn(S::SharedArray) 的 init 函数,那么所有相关的 worker 都会调用它。你可以让每个 worker 都在共享数组不同的地方执行 init 函数,从而实现并行初始化。","category":"page"},{"location":"manual/distributed-computing/","page":"多进程和分布式计算","title":"多进程和分布式计算","text":"下面是个例子:","category":"page"},{"location":"manual/distributed-computing/","page":"多进程和分布式计算","title":"多进程和分布式计算","text":"julia> using Distributed\n\njulia> addprocs(3)\n3-element Array{Int64,1}:\n 2\n 3\n 4\n\njulia> @everywhere using SharedArrays\n\njulia> S = SharedArray{Int,2}((3,4), init = S -> S[localindices(S)] = repeat([myid()], length(localindices(S))))\n3×4 SharedArray{Int64,2}:\n 2 2 3 4\n 2 3 3 4\n 2 3 4 4\n\njulia> S[3,2] = 7\n7\n\njulia> S\n3×4 SharedArray{Int64,2}:\n 2 2 3 4\n 2 3 3 4\n 2 7 4 4","category":"page"},{"location":"manual/distributed-computing/","page":"多进程和分布式计算","title":"多进程和分布式计算","text":"SharedArrays.localindices 提供了一个以为的切片,可以很方便地用来将 task 分配到各个进程上。当然你可以按你想要的方式做区分:","category":"page"},{"location":"manual/distributed-computing/","page":"多进程和分布式计算","title":"多进程和分布式计算","text":"julia> S = SharedArray{Int,2}((3,4), init = S -> S[indexpids(S):length(procs(S)):length(S)] = repeat([myid()], length( indexpids(S):length(procs(S)):length(S))))\n3×4 SharedArray{Int64,2}:\n 2 2 2 2\n 3 3 3 3\n 4 4 4 4","category":"page"},{"location":"manual/distributed-computing/","page":"多进程和分布式计算","title":"多进程和分布式计算","text":"由于所有的进程都能够访问底层的数据,因此一定要小心避免出现冲突:","category":"page"},{"location":"manual/distributed-computing/","page":"多进程和分布式计算","title":"多进程和分布式计算","text":"@sync begin\n for p in procs(S)\n @async begin\n remotecall_wait(fill!, p, S, p)\n end\n end\nend","category":"page"},{"location":"manual/distributed-computing/","page":"多进程和分布式计算","title":"多进程和分布式计算","text":"上面的代码会导致不确定的结果,因为每个进程都将整个数组赋值为其 pid,从而导致最后一个执行完成的进程会保留其 pid。","category":"page"},{"location":"manual/distributed-computing/","page":"多进程和分布式计算","title":"多进程和分布式计算","text":"考虑更复杂的一种情况:","category":"page"},{"location":"manual/distributed-computing/","page":"多进程和分布式计算","title":"多进程和分布式计算","text":"q[i,j,t+1] = q[i,j,t] + u[i,j,t]","category":"page"},{"location":"manual/distributed-computing/","page":"多进程和分布式计算","title":"多进程和分布式计算","text":"这个例子中,如果首先将任务用按照一维的索引作区分,那么就会出问题:如果 q[i,j,t] 位于分配给某个 worker 的最后一个位置,而 q[i,j,t+1] 位于下一个 worker 的开始位置,那么后面这个 worker 开始计算的时候,可能 q[i,j,t] 还没有准备好,这时候,更好的做法是,手动分区,比如可以定义一个函数,按照 (irange,jrange) 给每个 worker 分配任务。","category":"page"},{"location":"manual/distributed-computing/","page":"多进程和分布式计算","title":"多进程和分布式计算","text":"julia> @everywhere function myrange(q::SharedArray)\n idx = indexpids(q)\n if idx == 0 # This worker is not assigned a piece\n return 1:0, 1:0\n end\n nchunks = length(procs(q))\n splits = [round(Int, s) for s in range(0, stop=size(q,2), length=nchunks+1)]\n 1:size(q,1), splits[idx]+1:splits[idx+1]\n end","category":"page"},{"location":"manual/distributed-computing/","page":"多进程和分布式计算","title":"多进程和分布式计算","text":"然后定义计算内核:","category":"page"},{"location":"manual/distributed-computing/","page":"多进程和分布式计算","title":"多进程和分布式计算","text":"julia> @everywhere function advection_chunk!(q, u, irange, jrange, trange)\n @show (irange, jrange, trange) # display so we can see what's happening\n for t in trange, j in jrange, i in irange\n q[i,j,t+1] = q[i,j,t] + u[i,j,t]\n end\n q\n end","category":"page"},{"location":"manual/distributed-computing/","page":"多进程和分布式计算","title":"多进程和分布式计算","text":"然后定义一个 wrapper:","category":"page"},{"location":"manual/distributed-computing/","page":"多进程和分布式计算","title":"多进程和分布式计算","text":"julia> @everywhere advection_shared_chunk!(q, u) =\n advection_chunk!(q, u, myrange(q)..., 1:size(q,3)-1)","category":"page"},{"location":"manual/distributed-computing/","page":"多进程和分布式计算","title":"多进程和分布式计算","text":"接下来,比较三个不同的版本,第一个是单进程版本:","category":"page"},{"location":"manual/distributed-computing/","page":"多进程和分布式计算","title":"多进程和分布式计算","text":"julia> advection_serial!(q, u) = advection_chunk!(q, u, 1:size(q,1), 1:size(q,2), 1:size(q,3)-1);","category":"page"},{"location":"manual/distributed-computing/","page":"多进程和分布式计算","title":"多进程和分布式计算","text":"然后是使用 @distributed:","category":"page"},{"location":"manual/distributed-computing/","page":"多进程和分布式计算","title":"多进程和分布式计算","text":"julia> function advection_parallel!(q, u)\n for t = 1:size(q,3)-1\n @sync @distributed for j = 1:size(q,2)\n for i = 1:size(q,1)\n q[i,j,t+1]= q[i,j,t] + u[i,j,t]\n end\n end\n end\n q\n end;","category":"page"},{"location":"manual/distributed-computing/","page":"多进程和分布式计算","title":"多进程和分布式计算","text":"最后是使用分区:","category":"page"},{"location":"manual/distributed-computing/","page":"多进程和分布式计算","title":"多进程和分布式计算","text":"julia> function advection_shared!(q, u)\n @sync begin\n for p in procs(q)\n @async remotecall_wait(advection_shared_chunk!, p, q, u)\n end\n end\n q\n end;","category":"page"},{"location":"manual/distributed-computing/","page":"多进程和分布式计算","title":"多进程和分布式计算","text":"如果创建好了 SharedArray 之后,计算这些函数的执行时间,那么可以得到以下结果(用 julia -p 4 启动):","category":"page"},{"location":"manual/distributed-computing/","page":"多进程和分布式计算","title":"多进程和分布式计算","text":"julia> q = SharedArray{Float64,3}((500,500,500));\n\njulia> u = SharedArray{Float64,3}((500,500,500));","category":"page"},{"location":"manual/distributed-computing/","page":"多进程和分布式计算","title":"多进程和分布式计算","text":"先执行一次以便 JIT 编译,然后用 @time 宏测试其第二次执行的时间:","category":"page"},{"location":"manual/distributed-computing/","page":"多进程和分布式计算","title":"多进程和分布式计算","text":"julia> @time advection_serial!(q, u);\n(irange,jrange,trange) = (1:500,1:500,1:499)\n 830.220 milliseconds (216 allocations: 13820 bytes)\n\njulia> @time advection_parallel!(q, u);\n 2.495 seconds (3999 k allocations: 289 MB, 2.09% gc time)\n\njulia> @time advection_shared!(q,u);\n From worker 2: (irange,jrange,trange) = (1:500,1:125,1:499)\n From worker 4: (irange,jrange,trange) = (1:500,251:375,1:499)\n From worker 3: (irange,jrange,trange) = (1:500,126:250,1:499)\n From worker 5: (irange,jrange,trange) = (1:500,376:500,1:499)\n 238.119 milliseconds (2264 allocations: 169 KB)","category":"page"},{"location":"manual/distributed-computing/","page":"多进程和分布式计算","title":"多进程和分布式计算","text":"这里 advection_shared! 最大的优势在于,最小程度地降低了 woker 之间的通信,从而让每个 worker 能针对被分配的部分持续地计算一段时间。","category":"page"},{"location":"manual/distributed-computing/#共享数组与分布式垃圾回收","page":"多进程和分布式计算","title":"共享数组与分布式垃圾回收","text":"","category":"section"},{"location":"manual/distributed-computing/","page":"多进程和分布式计算","title":"多进程和分布式计算","text":"和远程引用一样,共享数组也依赖于创建节点上的垃圾回收来释放所有参与的 worker 上的引用。因此,创建大量生命周期比较短的数组,并尽可能快地显式 finilize 这些对象,代码会更高效,这样与之对用的内存和文件句柄都会更快地释放。","category":"page"},{"location":"manual/distributed-computing/#集群管理器","page":"多进程和分布式计算","title":"集群管理器","text":"","category":"section"},{"location":"manual/distributed-computing/","page":"多进程和分布式计算","title":"多进程和分布式计算","text":"Julia 通过集群管理器实现对多个进程(所构成的逻辑上的集群)的启动,管理以及网络通信。一个 ClusterManager 负责:","category":"page"},{"location":"manual/distributed-computing/","page":"多进程和分布式计算","title":"多进程和分布式计算","text":"在一个集群环境中启动 worker 进程 \n管理每个 worker 生命周期内的事件\n(可选),提供数据传输","category":"page"},{"location":"manual/distributed-computing/","page":"多进程和分布式计算","title":"多进程和分布式计算","text":"一个 Julia 集群由以下特点:","category":"page"},{"location":"manual/distributed-computing/","page":"多进程和分布式计算","title":"多进程和分布式计算","text":"初始进程,称为 master,其 id 为 1\n只有 master 进程可以增加或删除 worker 进程\n所有进程之间都可以直接通信","category":"page"},{"location":"manual/distributed-computing/","page":"多进程和分布式计算","title":"多进程和分布式计算","text":"worker 之间的连接(用的是内置的 TCP/IP 传输)按照以下方式进行:","category":"page"},{"location":"manual/distributed-computing/","page":"多进程和分布式计算","title":"多进程和分布式计算","text":"master 进程对一个 ClusterManager 对象调用 addprocs\naddprocs 调用对应的 launch 方法,然后在对应的机器上启动相应数量的 worker 进程\n每个 worker 监听一个端口,然后将其 host 和 port 信息传给 stdout\n集群管理器捕获 stdout 中每个 worker 的信息,并提供给 master 进程\nmaster 进程解析信息并与相应的 worker 建立 TCP/IP 连接\n每个 worker 都会被通知集群中的其它 worker\n每个 worker 与 id 小于自己的 worker 连接\n这样,一个网络就建立了,从而,每个 worker 都可以与其它 worker 建立连接","category":"page"},{"location":"manual/distributed-computing/","page":"多进程和分布式计算","title":"多进程和分布式计算","text":"尽管默认的传输层使用的是 TCPSocket,对于一个自定义的集群管理器来说,完全可以使用其它传输方式。","category":"page"},{"location":"manual/distributed-computing/","page":"多进程和分布式计算","title":"多进程和分布式计算","text":"Julia 提供了两种内置的集群管理器:","category":"page"},{"location":"manual/distributed-computing/","page":"多进程和分布式计算","title":"多进程和分布式计算","text":"LocalManager,调用 addprocs() 或 addprocs(np::Integer) 时会用到。\nSSHManager,调用 addprocs(hostnames::Array) 时,传递一个 hostnames 的列表。","category":"page"},{"location":"manual/distributed-computing/","page":"多进程和分布式计算","title":"多进程和分布式计算","text":"LocalManager 用来在同一个 host 上启动多个 worker,从而利用多核/多处理器硬件。","category":"page"},{"location":"manual/distributed-computing/","page":"多进程和分布式计算","title":"多进程和分布式计算","text":"因此,一个最小的集群管理器需要:","category":"page"},{"location":"manual/distributed-computing/","page":"多进程和分布式计算","title":"多进程和分布式计算","text":"是一个 ClusterManager 抽象类的一个子类\n实现 launch 接口,用来启动新的 worker\n实现 manage,在一个 worker 的生命周期中多次被调用(例如,发送中断信号)","category":"page"},{"location":"manual/distributed-computing/","page":"多进程和分布式计算","title":"多进程和分布式计算","text":"addprocs(manager::FooManager) 需要 FooManager 实现:","category":"page"},{"location":"manual/distributed-computing/","page":"多进程和分布式计算","title":"多进程和分布式计算","text":"function launch(manager::FooManager, params::Dict, launched::Array, c::Condition)\n [...]\nend\n\nfunction manage(manager::FooManager, id::Integer, config::WorkerConfig, op::Symbol)\n [...]\nend","category":"page"},{"location":"manual/distributed-computing/","page":"多进程和分布式计算","title":"多进程和分布式计算","text":"作为一个例子,我们来看下 LocalManager 是怎么实现的:","category":"page"},{"location":"manual/distributed-computing/","page":"多进程和分布式计算","title":"多进程和分布式计算","text":"struct LocalManager <: ClusterManager\n np::Integer\nend\n\nfunction launch(manager::LocalManager, params::Dict, launched::Array, c::Condition)\n [...]\nend\n\nfunction manage(manager::LocalManager, id::Integer, config::WorkerConfig, op::Symbol)\n [...]\nend","category":"page"},{"location":"manual/distributed-computing/","page":"多进程和分布式计算","title":"多进程和分布式计算","text":"launch 方法接收以下参数:","category":"page"},{"location":"manual/distributed-computing/","page":"多进程和分布式计算","title":"多进程和分布式计算","text":"manager::ClusterManager: 调用 addprocs 时所用到的集群管理器\nparams::Dict: 所有的关键字参数都会传递到 addprocs 中\nlaunched::Array: 用来存储一个或多个 WorkerConfig\nc::Condition: 在 workers 启动后被通知的条件变量","category":"page"},{"location":"manual/distributed-computing/","page":"多进程和分布式计算","title":"多进程和分布式计算","text":"launch 会在一个异步的task中调用,该 task 结束之后,意味着所有请求的 worker 都已经启动好了。因此,launch 函数必须在所有 worker 启动之后,尽快退出。","category":"page"},{"location":"manual/distributed-computing/","page":"多进程和分布式计算","title":"多进程和分布式计算","text":"新启动的 worker 之间采用的是多对多的连接方式。在命令行中指定参数 --worker[=] 会让所有启动的进程把自己当作 worker,然后通过 TCP/IP 构建连接。","category":"page"},{"location":"manual/distributed-computing/","page":"多进程和分布式计算","title":"多进程和分布式计算","text":"集群中所有的 worker 默认使用同一个 master 的 cookie。如果 cookie 没有指定,(比如没有通过 --worker 指定),那么 worker 会尝试从它的标准输入中读取。LocalManager 和 SSHManager 都是通过标准输入来将 cookie 传递给新启动的 worker。","category":"page"},{"location":"manual/distributed-computing/","page":"多进程和分布式计算","title":"多进程和分布式计算","text":"默认情况下,一个 worker 会监听从 getipaddr() 函数返回的地址上的一个开放端口。若要指定监听的地址,可以通过额外的参数 --bind-to bind_addr[:port] 指定,这对于多 host 的情况来说很方便。","category":"page"},{"location":"manual/distributed-computing/","page":"多进程和分布式计算","title":"多进程和分布式计算","text":"对于非 TCP/IP 传输,可以选择 MPI 作为一种实现,此时一定不要指定 --worker 参数,另外,新启动的 worker 必须调用 init_worker(cookie) 之后再使用并行的结构体。","category":"page"},{"location":"manual/distributed-computing/","page":"多进程和分布式计算","title":"多进程和分布式计算","text":"对于每个已经启动的 worker,launch 方法必须往 launched 中添加一个 WorkerConfig 对象(相应的值已经初始化)。","category":"page"},{"location":"manual/distributed-computing/","page":"多进程和分布式计算","title":"多进程和分布式计算","text":"mutable struct WorkerConfig\n # Common fields relevant to all cluster managers\n io::Union{IO, Nothing}\n host::Union{AbstractString, Nothing}\n port::Union{Integer, Nothing}\n\n # Used when launching additional workers at a host\n count::Union{Int, Symbol, Nothing}\n exename::Union{AbstractString, Cmd, Nothing}\n exeflags::Union{Cmd, Nothing}\n\n # External cluster managers can use this to store information at a per-worker level\n # Can be a dict if multiple fields need to be stored.\n userdata::Any\n\n # SSHManager / SSH tunnel connections to workers\n tunnel::Union{Bool, Nothing}\n bind_addr::Union{AbstractString, Nothing}\n sshflags::Union{Cmd, Nothing}\n max_parallel::Union{Integer, Nothing}\n\n # Used by Local/SSH managers\n connect_at::Any\n\n [...]\nend","category":"page"},{"location":"manual/distributed-computing/","page":"多进程和分布式计算","title":"多进程和分布式计算","text":"WorkerConfig 中的大多数字段都是内置的集群管理器会用到,对于自定义的管理器,通常只需要指定 io 或 host/port:","category":"page"},{"location":"manual/distributed-computing/","page":"多进程和分布式计算","title":"多进程和分布式计算","text":"如果指定了 io,那么就会用来读取 host/port 信息。每个 worker 会在启动时打印地址和端口,这样 worker 就可以自由监听可用的端口,而不必手动配置 worker 的端口。\n如果 io 没有指定,那么 host 和 port 就会用来连接。\ncount,exename 和 exeflags 用于从一个 worker 上启动额外的 worker。例如,一个集群管理器可能对每个节点都只启动一个 worker,然后再用它来启动额外的 worker。\ncount 可以是一个整数 n,用来指定启动 n 个 worker\ncount 还可以是 :auto,用来启动跟那台机器上 CPU 个数(逻辑上的核的个数)相同的 worker\nexename 是 julia 可执行文件的全路径\nexeflags 应该设置成传递给将要启动的 worker 命令行参数\ntunnel, bind_addr, sshflags 和 max_parallel 会在从 worker 与 master 进程建立 ssh 隧道时用到\nuserdata 用来提供给自定义集群管理器存储自己的 worker 相关的信息","category":"page"},{"location":"manual/distributed-computing/","page":"多进程和分布式计算","title":"多进程和分布式计算","text":"manage(manager::FooManager, id::Integer, config::WorkerConfig, op::Symbol) 会在一个 worker 生命周期中的不同时刻被调用,其中 op 的值可能是:","category":"page"},{"location":"manual/distributed-computing/","page":"多进程和分布式计算","title":"多进程和分布式计算","text":":register/:deregister,从 Julia 的 worker 池子中添加/删除一个 worker\n:interrupt,当 interrupt(workers) 被调用是,此时,ClusterManager 应该给相应的 worker 发送终端信号\n:finalize,用于清理操作。","category":"page"},{"location":"manual/distributed-computing/#自定义集群管理器的传输方式","page":"多进程和分布式计算","title":"自定义集群管理器的传输方式","text":"","category":"section"},{"location":"manual/distributed-computing/","page":"多进程和分布式计算","title":"多进程和分布式计算","text":"将默认的 TCP/IP 多对多 socket 连接替换成一个自定义的传输层需要做很多工作。每个 Julia 进程都有与其连接的 worker 数量相同的通信 task。例如,在一个有 32 个进程的多对多集群中:","category":"page"},{"location":"manual/distributed-computing/","page":"多进程和分布式计算","title":"多进程和分布式计算","text":"每个进程都有31个通信task\n每个 task 在一个消息处理循环中从一个远端 worker 读取所有的输入信息\n每个消息处理循环等待一个 IO 对象(比如,在默认实现中是一个 TCPSocket),然后读取整个信息,处理,等待下一个\n发送消息则可以直接在任意 Julia task 中完成,而不只是通信 task,同样,也是通过相应的 IO 对象","category":"page"},{"location":"manual/distributed-computing/","page":"多进程和分布式计算","title":"多进程和分布式计算","text":"要替换默认的传输方式,需要新的实现能够在远程 worker 之间建立连接,同时提供一个可以用来被消息处理循环等待的 IO 对象。集群管理器的回调函数需要实现如下函数:","category":"page"},{"location":"manual/distributed-computing/","page":"多进程和分布式计算","title":"多进程和分布式计算","text":"connect(manager::FooManager, pid::Integer, config::WorkerConfig)\nkill(manager::FooManager, pid::Int, config::WorkerConfig)","category":"page"},{"location":"manual/distributed-computing/","page":"多进程和分布式计算","title":"多进程和分布式计算","text":"默认的实现(使用的是 TCP/IP socket)是 connect(manager::ClusterManager, pid::Integer, config::WorkerConfig)。","category":"page"},{"location":"manual/distributed-computing/","page":"多进程和分布式计算","title":"多进程和分布式计算","text":"connect 需要返回一对 IO 对象,一个用于从 pid worker 读取数据,另一个用于往 pid 写数据。自定义的集群管理器可以用内存中的 BUfferStream 作为一个管道将自定义的(很可能是非 IO 的)传输与 Julia 内置的并行基础设施衔接起来。","category":"page"},{"location":"manual/distributed-computing/","page":"多进程和分布式计算","title":"多进程和分布式计算","text":"BufferStream 是一个内存中的 IOBuffer,其表现很像 IO,就是一个流(stream),可以异步地处理。","category":"page"},{"location":"manual/distributed-computing/","page":"多进程和分布式计算","title":"多进程和分布式计算","text":"在 Examples repository 的 clustermanager/0mq 目录中,包含一个使用 ZeroMQ 连接 Julia worker 的例子,用的是星型拓补结构。需要注意的是:Julia 的进程仍然是逻辑上相互连接的,任意 worker 都可以与其它 worker 直接相连而无需感知到 0MQ 作为传输层的存在。","category":"page"},{"location":"manual/distributed-computing/","page":"多进程和分布式计算","title":"多进程和分布式计算","text":"在使用自定义传输的时候:","category":"page"},{"location":"manual/distributed-computing/","page":"多进程和分布式计算","title":"多进程和分布式计算","text":"Julia 的 workers 必须不能通过 --worker 启动。如果启动的时候使用了 --worker,那么新启动的 worker 会默认使用基于 TCP/IP socket 的实现\n对于每个 worker 逻辑上的输入连接,必须调用 Base.process_messages(rd::IO, wr::IO)(),这会创建一个新的 task 来处理 worker 消息的读写\ninit_worker(cookie, manager::FooManager) 必须作为 worker 进程初始化的一部分呢被调用\nWorkerConfig中的 connect_at::Any 字段可以被集群管理器在调用 launch 的时候设置,该字段的值会发送到所有的 connect 回调中。通常,其中包含的是如何连接到一个 worker 的信息。例如,在 TCP/IP socket 传输中,用这个字段存储 (host, port) 来声明如何连接到一个 worker。","category":"page"},{"location":"manual/distributed-computing/","page":"多进程和分布式计算","title":"多进程和分布式计算","text":"kill(manager, pid, config) 用来从一个集群中删除一个 worker,在 master 进程中,对应的 IO 对象必须通过对应的实现来关闭,从而保证正确地释放资源。默认的实现简单地对指定的远端 worker 执行 exit() 即可。","category":"page"},{"location":"manual/distributed-computing/","page":"多进程和分布式计算","title":"多进程和分布式计算","text":"在例子目录中,clustermanager/simple 展示了一个简单地实现,使用的是 UNIX 下的 socket。","category":"page"},{"location":"manual/distributed-computing/#LocalManager-和-SSHManager-的网络要求","page":"多进程和分布式计算","title":"LocalManager 和 SSHManager 的网络要求","text":"","category":"section"},{"location":"manual/distributed-computing/","page":"多进程和分布式计算","title":"多进程和分布式计算","text":"Julia 集群设计的时候,默认是在一个安全的环境中执行,比如本地的笔记本,部门的集群,甚至是云端。这部分将介绍 LocalManager 和 SSHManager 的网络安全要点:","category":"page"},{"location":"manual/distributed-computing/","page":"多进程和分布式计算","title":"多进程和分布式计算","text":"master 进程不监听任何端口,它只负责向外连接 worker\n每个 worker 都只绑定一个本地的接口,同时监听一个操作系统分配的临时端口。\naddprocs(N) 使用的 LocalManager,默认只会绑定到回环接口(loopback interface),这就意味着,之后在远程主机上(恶意)启动的 worker 无法连接到集群中,在执行 addprocs(4) 之后,又跟一个 addprocs([\"remote_host\"]) 会失败。有些用户可能希望创建一个集群同时管理本地系统和几个远端系统,这可以通过在绑定 LocalManager 到外部网络接口的时候,指定一个 restrict 参数:addprocs(4; restrict=false)\naddprocs(list_of_remote_hosts) 使用的 SSHManager 会通过 SSH 启动远程机上的 worker。","category":"page"},{"location":"manual/distributed-computing/","page":"多进程和分布式计算","title":"多进程和分布式计算","text":"默认 SSH 只会用来启动 Julia 的 worker。随后的 master-worker 和 worker-worker 连接使用的是普通的、未加密的 TCP/IP 通信。 远程机必须开启免密登陆。 额外的 SSH 标记或认证信息会通过关键字参数 sshflags 指定。","category":"page"},{"location":"manual/distributed-computing/","page":"多进程和分布式计算","title":"多进程和分布式计算","text":"addprocs(list_of_remote_hosts; tunnel=true, sshflags=) 在我们希望给 master-worker 也使用 SSH 连接的时候很有用。 一个典型的场景是本地的笔记本 运行 Julia ERPL (做为 master)和云上的其他机器,比如 Amazon EC2,构成集群。 这时候远程机器只要开启 22 端口就可以,然后要有 SSH 客户端 通过公约基础设施(PKI)认证过。授权信息可以通过 sshflags 生效,比如 sshflags=`-i `。\n在一个所有节点联通的拓扑网中(默认情况下是这样的),所有的 worker 节点都通过普通 TCP socket 通信互相连接。 这样集群的安全策略就必须允许 worker 节点间 通过操作系统分配的临时端口范围自由连接。\n所有 worker-worker 间(都是 SSH)的安全和加密或者信息的加密 都可以通过自定义 ClusterManager 完成。\n如果将 multiplex=true 指定为 addprocs 的选项,则 SSH 多路复用用于在 master 和 worker 之间创建隧道。 如果你自己配置了 SSH 多路复用并且已经建立了连接,则无论 multiplex 选项如何,都会使用 SSH 多路复用。 如果启用了多路复用,则使用现有连接(ssh 中的 -O forward 选项)设置转发。 如果你的服务器需要密码验证,那么这就很有用了;\n你可以通过在 addprocs 之前登录服务器来避免在 Julia 中进行身份验证。 除非使用现有的多路复用连接,否则在会话期间控制套接字将位于 ~/.ssh/julia-%r@%h:%p。 请注意,如果你在一个节点上创建多个进程并启用多路复用,带宽可能会受到限制,因为在这种情况下,进程共享一个多路复用 TCP 连接。","category":"page"},{"location":"manual/distributed-computing/#man-cluster-cookie","page":"多进程和分布式计算","title":"集群 Cookie","text":"","category":"section"},{"location":"manual/distributed-computing/","page":"多进程和分布式计算","title":"多进程和分布式计算","text":"集群上所有的进程都共享同一个 cookie,默认是 master 进程随机生成的字符串。","category":"page"},{"location":"manual/distributed-computing/","page":"多进程和分布式计算","title":"多进程和分布式计算","text":"cluster_cookie() 返回 cookie,而 cluster_cookie(cookie)() 设置并返回新的 cookie。\n所有的连接都进行双向认证,从而保证只有 master 启动的 worker 才能相互连接。\ncookie 可以在 worker 启动的时候,通过参数 --worker= 指定,如果参数 --worker 没有指定 cookie,那么 worker 会从它的标准输入中 (stdin) 读取, stdin 会在 cookie 获取之后立即关闭。\nClusterManager 可以通过 cluster_cookie() 从 master 中过去 cookie,不适用默认 TCP/IP 传输的集群管理器(即没有指定 --worker)必须用于 master 相同的 cookie 调用 init_worker(cookie, manager)。","category":"page"},{"location":"manual/distributed-computing/","page":"多进程和分布式计算","title":"多进程和分布式计算","text":"注意,在对安全性要求很高的环境中,可以通过自定义 ClusterManager 实现。例如,cookie 可以提前共享,然后不必再启动参数中指定。","category":"page"},{"location":"manual/distributed-computing/#指定网络拓补结构(实验性功能)","page":"多进程和分布式计算","title":"指定网络拓补结构(实验性功能)","text":"","category":"section"},{"location":"manual/distributed-computing/","page":"多进程和分布式计算","title":"多进程和分布式计算","text":"传递给 addprocs 的关键字参数 topology 用于指定 workers 必须如何相互连接:","category":"page"},{"location":"manual/distributed-computing/","page":"多进程和分布式计算","title":"多进程和分布式计算","text":":all_to_all,默认的,所有 worker 之间相互都连接\n:master_worker,只有主进程,即 pid 为 1 的进程能够与 worker 建立连接\n:custom: 集群管理器的 launch 方法通过 WorkerConfig 中的 ident 和 connect_idents 指定连接的拓补结构。一个 worker 通过集群管理器提供的 ident 来连接到所有 connect_idents 指定的 worker。","category":"page"},{"location":"manual/distributed-computing/","page":"多进程和分布式计算","title":"多进程和分布式计算","text":"关键字参数 lazy=true|false 只会影响 topology 选项中的 :all_to_all。如果是 true,那么集群启动的时候 master 会连接所有的 worker,然后 worker 之间的特定连接会在初次唤醒的是建立连接,这有利于降低集群初始化的时候对资源的分配。lazy 的默认值是 true。","category":"page"},{"location":"manual/distributed-computing/","page":"多进程和分布式计算","title":"多进程和分布式计算","text":"目前,在没有建立连接的两个 worker 之间传递消息会出错,目前该行为是实验性的,未来的版本中可能会改变。","category":"page"},{"location":"manual/distributed-computing/#一些值得关注的外部库","page":"多进程和分布式计算","title":"一些值得关注的外部库","text":"","category":"section"},{"location":"manual/distributed-computing/","page":"多进程和分布式计算","title":"多进程和分布式计算","text":"除了 Julia 自带的并行机制之外,还有许多外部的库值得一提。例如 MPI.jl 提供了一个 MPI 协议的 Julia 的封装,或者是在 共享数组 提到的 DistributedArrays.jl,此外尤其值得一提的是 Julia 的 GPU 编程生态,其包括:","category":"page"},{"location":"manual/distributed-computing/","page":"多进程和分布式计算","title":"多进程和分布式计算","text":"底层(C内核)的 OpenCL.jl 和 CUDAdrv.jl,分别提供了 OpenCL 和 CUDA 的封装。\n底层(Julia 内核)的接口,如 CUDAnative.jl,提供了 Julia 原生的 CUDA 实现。\n高层的特定抽象,如 CuArrays.jl 和 CLArrays.jl。\n高层的库,如 ArrayFire.jl 和 GPUArrays.jl。","category":"page"},{"location":"manual/distributed-computing/","page":"多进程和分布式计算","title":"多进程和分布式计算","text":"下面的例子将介绍如何用 DistributedArrays.jl 和 CuArrays.jl 通过 distribute() 和 CuArray() 将数组分配到多个进程。","category":"page"},{"location":"manual/distributed-computing/","page":"多进程和分布式计算","title":"多进程和分布式计算","text":"记住在载入 DistributedArrays.jl 时,需要用 @everywhere 将其载入到多个进程中。","category":"page"},{"location":"manual/distributed-computing/","page":"多进程和分布式计算","title":"多进程和分布式计算","text":"$ ./julia -p 4\n\njulia> addprocs()\n\njulia> @everywhere using DistributedArrays\n\njulia> using CuArrays\n\njulia> B = ones(10_000) ./ 2;\n\njulia> A = ones(10_000) .* π;\n\njulia> C = 2 .* A ./ B;\n\njulia> all(C .≈ 4*π)\ntrue\n\njulia> typeof(C)\nArray{Float64,1}\n\njulia> dB = distribute(B);\n\njulia> dA = distribute(A);\n\njulia> dC = 2 .* dA ./ dB;\n\njulia> all(dC .≈ 4*π)\ntrue\n\njulia> typeof(dC)\nDistributedArrays.DArray{Float64,1,Array{Float64,1}}\n\njulia> cuB = CuArray(B);\n\njulia> cuA = CuArray(A);\n\njulia> cuC = 2 .* cuA ./ cuB;\n\njulia> all(cuC .≈ 4*π);\ntrue\n\njulia> typeof(cuC)\nCuArray{Float64,1}","category":"page"},{"location":"manual/distributed-computing/","page":"多进程和分布式计算","title":"多进程和分布式计算","text":"请记住,CUDAnative.jl[2] 目前不支持某些 Julia 功能,尤其是像 sin 这样的一些函数需要替换为 CUDAnative.sin(cc:@maleadt)。","category":"page"},{"location":"manual/distributed-computing/","page":"多进程和分布式计算","title":"多进程和分布式计算","text":"下面的例子中,通过 DistributedArrays.jl 和 CuArrays.jl 将一个数组分配到多个进程,然后调用一个函数。","category":"page"},{"location":"manual/distributed-computing/","page":"多进程和分布式计算","title":"多进程和分布式计算","text":"function power_method(M, v)\n for i in 1:100\n v = M*v\n v /= norm(v)\n end\n\n return v, norm(M*v) / norm(v) # or (M*v) ./ v\nend","category":"page"},{"location":"manual/distributed-computing/","page":"多进程和分布式计算","title":"多进程和分布式计算","text":"power_method 重复创建一个新的向量然后对其归一化,这里并没有在函数中指定类型信息,来看看是否对前面提到的类型适用:","category":"page"},{"location":"manual/distributed-computing/","page":"多进程和分布式计算","title":"多进程和分布式计算","text":"julia> M = [2. 1; 1 1];\n\njulia> v = rand(2)\n2-element Array{Float64,1}:\n0.40395\n0.445877\n\njulia> power_method(M,v)\n([0.850651, 0.525731], 2.618033988749895)\n\njulia> cuM = CuArray(M);\n\njulia> cuv = CuArray(v);\n\njulia> curesult = power_method(cuM, cuv);\n\njulia> typeof(curesult)\nCuArray{Float64,1}\n\njulia> dM = distribute(M);\n\njulia> dv = distribute(v);\n\njulia> dC = power_method(dM, dv);\n\njulia> typeof(dC)\nTuple{DistributedArrays.DArray{Float64,1,Array{Float64,1}},Float64}","category":"page"},{"location":"manual/distributed-computing/","page":"多进程和分布式计算","title":"多进程和分布式计算","text":"最后,我们来看看 MPI.jl,这个库时 Julia 对 MPI 协议的封装。一一介绍其中的每个函数太累赘了,这里领会其实现协议的方法就够了。","category":"page"},{"location":"manual/distributed-computing/","page":"多进程和分布式计算","title":"多进程和分布式计算","text":"考虑下面这个简单的脚本,它做的只是调用每个子进程,然后初始化其 rank,然后在 master 访问时,对 rank 求和。","category":"page"},{"location":"manual/distributed-computing/","page":"多进程和分布式计算","title":"多进程和分布式计算","text":"import MPI\n\nMPI.Init()\n\ncomm = MPI.COMM_WORLD\nMPI.Barrier(comm)\n\nroot = 0\nr = MPI.Comm_rank(comm)\n\nsr = MPI.Reduce(r, MPI.SUM, root, comm)\n\nif(MPI.Comm_rank(comm) == root)\n @printf(\"sum of ranks: %s\\n\", sr)\nend\n\nMPI.Finalize()","category":"page"},{"location":"manual/distributed-computing/","page":"多进程和分布式计算","title":"多进程和分布式计算","text":"mpirun -np 4 ./julia example.jl","category":"page"},{"location":"manual/distributed-computing/","page":"多进程和分布式计算","title":"多进程和分布式计算","text":"[1]: In this context, MPI refers to the MPI-1 standard. Beginning with MPI-2, the MPI standards committee introduced a new set of communication mechanisms, collectively referred to as Remote Memory Access (RMA). The motivation for adding rma to the MPI standard was to facilitate one-sided communication patterns. For additional information on the latest MPI standard, see https://mpi-forum.org/docs.","category":"page"},{"location":"manual/distributed-computing/","page":"多进程和分布式计算","title":"多进程和分布式计算","text":"[2]: Julia GPU man pages","category":"page"},{"location":"manual/running-external-programs/#运行外部程序","page":"运行外部程序","title":"运行外部程序","text":"","category":"section"},{"location":"manual/running-external-programs/","page":"运行外部程序","title":"运行外部程序","text":"Julia 中命令的反引号记法借鉴于 shell、Perl 和 Ruby。然而,在 Julia 中编写","category":"page"},{"location":"manual/running-external-programs/","page":"运行外部程序","title":"运行外部程序","text":"julia> `echo hello`\n`echo hello`","category":"page"},{"location":"manual/running-external-programs/","page":"运行外部程序","title":"运行外部程序","text":"在多个方面上与 shell、Perl 和 Ruby 中的行为有所不同:","category":"page"},{"location":"manual/running-external-programs/","page":"运行外部程序","title":"运行外部程序","text":"反引号创建一个 Cmd 对象来表示命令,而不是立即运行命令。 你可以使用此对象将命令通过管道连接到其它命令、run 它以及对它进行 read 或 write。\n在命令运行时,Julia 不会捕获命令的输出结果,除非你对它专门安排。相反,在默认情况下,命令的输出会被定向到 stdout,因为它将使用 libc 的 system 调用。\n命令从不会在 shell 中运行。相反地,Julia 会直接解析命令语法,适当地插入变量并像 shell 那样拆分单词,同时遵从 shell 的引用语法。命令会作为 julia 的直接子进程运行,使用 fork 和 exec 调用。","category":"page"},{"location":"manual/running-external-programs/","page":"运行外部程序","title":"运行外部程序","text":"note: Note\n下面假设在 Linux 或 MacOS 上使用 Posix 环境。 在 Windows 上,许多类似的命令,例如 echo 和 dir,不是外部程序,而是内置在 shell cmd.exe 本身中。 运行这些命令的一种选择是调用 cmd.exe,例如 cmd /C echo hello。 或者,Julia 可以在 Posix 环境中运行,例如 Cygwin。","category":"page"},{"location":"manual/running-external-programs/","page":"运行外部程序","title":"运行外部程序","text":"这是运行外部程序的简单示例:","category":"page"},{"location":"manual/running-external-programs/","page":"运行外部程序","title":"运行外部程序","text":"julia> mycommand = `echo hello`\n`echo hello`\n\njulia> typeof(mycommand)\nCmd\n\njulia> run(mycommand);\nhello","category":"page"},{"location":"manual/running-external-programs/","page":"运行外部程序","title":"运行外部程序","text":"hello 是 echo 命令的输出,发送到 stdout。 如果外部命令无法成功运行,则 run 方法会抛出 ErrorException。","category":"page"},{"location":"manual/running-external-programs/","page":"运行外部程序","title":"运行外部程序","text":"如果要读取外部命令的输出,可以使用 read 或 readchomp 代替:","category":"page"},{"location":"manual/running-external-programs/","page":"运行外部程序","title":"运行外部程序","text":"julia> read(`echo hello`, String)\n\"hello\\n\"\n\njulia> readchomp(`echo hello`)\n\"hello\"","category":"page"},{"location":"manual/running-external-programs/","page":"运行外部程序","title":"运行外部程序","text":"更一般地,你可以使用 open 来读取或写入外部命令。","category":"page"},{"location":"manual/running-external-programs/","page":"运行外部程序","title":"运行外部程序","text":"julia> open(`less`, \"w\", stdout) do io\n for i = 1:3\n println(io, i)\n end\n end\n1\n2\n3","category":"page"},{"location":"manual/running-external-programs/","page":"运行外部程序","title":"运行外部程序","text":"命令中的程序名称和各个参数可以访问和迭代,这就好像命令也是一个字符串数组:","category":"page"},{"location":"manual/running-external-programs/","page":"运行外部程序","title":"运行外部程序","text":"julia> collect(`echo \"foo bar\"`)\n2-element Vector{String}:\n \"echo\"\n \"foo bar\"\n\njulia> `echo \"foo bar\"`[2]\n\"foo bar\"","category":"page"},{"location":"manual/running-external-programs/#command-interpolation","page":"运行外部程序","title":"插值","text":"","category":"section"},{"location":"manual/running-external-programs/","page":"运行外部程序","title":"运行外部程序","text":"假设你想要做的事情更复杂,并使用以变量 file 表示的文件名作为命令的参数。那你可以像在字符串字面量中那样使用 $ 进行插值:","category":"page"},{"location":"manual/running-external-programs/","page":"运行外部程序","title":"运行外部程序","text":"julia> file = \"/etc/passwd\"\n\"/etc/passwd\"\n\njulia> `sort $file`\n`sort /etc/passwd`","category":"page"},{"location":"manual/running-external-programs/","page":"运行外部程序","title":"运行外部程序","text":"通过 shell 运行外部程序的一个常见陷阱是,如果文件名中包含 shell 中的特殊字符,那么可能会导致不希望出现的行为。例如,假设我们想要对其内容进行排序的文件是 /Volumes/External HD/data.csv,而不是 /etc/passwd。让我们来试试:","category":"page"},{"location":"manual/running-external-programs/","page":"运行外部程序","title":"运行外部程序","text":"julia> file = \"/Volumes/External HD/data.csv\"\n\"/Volumes/External HD/data.csv\"\n\njulia> `sort $file`\n`sort '/Volumes/External HD/data.csv'`","category":"page"},{"location":"manual/running-external-programs/","page":"运行外部程序","title":"运行外部程序","text":"文件名是如何被引用的?Julia 知道 file 是作为单个参数插入的,因此它替你引用了此单词。事实上,这不太准确:file 的值始终不会被 shell 解释,因此并不需要实际引用;插入引号只是为了展现给用户。就算你把值作为 shell 单词的一部分插入,这也可以工作:","category":"page"},{"location":"manual/running-external-programs/","page":"运行外部程序","title":"运行外部程序","text":"julia> path = \"/Volumes/External HD\"\n\"/Volumes/External HD\"\n\njulia> name = \"data\"\n\"data\"\n\njulia> ext = \"csv\"\n\"csv\"\n\njulia> `sort $path/$name.$ext`\n`sort '/Volumes/External HD/data.csv'`","category":"page"},{"location":"manual/running-external-programs/","page":"运行外部程序","title":"运行外部程序","text":"如你所见,path 变量中的空格被恰当地转义了。但是,如果你想插入多个单词怎么办?在此情况下,只需使用数组(或其它可迭代容器):","category":"page"},{"location":"manual/running-external-programs/","page":"运行外部程序","title":"运行外部程序","text":"julia> files = [\"/etc/passwd\",\"/Volumes/External HD/data.csv\"]\n2-element Vector{String}:\n \"/etc/passwd\"\n \"/Volumes/External HD/data.csv\"\n\njulia> `grep foo $files`\n`grep foo /etc/passwd '/Volumes/External HD/data.csv'`","category":"page"},{"location":"manual/running-external-programs/","page":"运行外部程序","title":"运行外部程序","text":"如果将数组作为 shell 单词的一部分插入,Julia 将模拟 shell 的 {a,b,c} 参数生成:","category":"page"},{"location":"manual/running-external-programs/","page":"运行外部程序","title":"运行外部程序","text":"julia> names = [\"foo\",\"bar\",\"baz\"]\n3-element Vector{String}:\n \"foo\"\n \"bar\"\n \"baz\"\n\njulia> `grep xylophone $names.txt`\n`grep xylophone foo.txt bar.txt baz.txt`","category":"page"},{"location":"manual/running-external-programs/","page":"运行外部程序","title":"运行外部程序","text":"此外,若在同一单词中插入多个数组,则将模拟 shell 的笛卡尔积生成行为:","category":"page"},{"location":"manual/running-external-programs/","page":"运行外部程序","title":"运行外部程序","text":"julia> names = [\"foo\",\"bar\",\"baz\"]\n3-element Vector{String}:\n \"foo\"\n \"bar\"\n \"baz\"\n\njulia> exts = [\"aux\",\"log\"]\n2-element Vector{String}:\n \"aux\"\n \"log\"\n\njulia> `rm -f $names.$exts`\n`rm -f foo.aux foo.log bar.aux bar.log baz.aux baz.log`","category":"page"},{"location":"manual/running-external-programs/","page":"运行外部程序","title":"运行外部程序","text":"因为可以插入字面量数组,所以你可以使用此生成功能,而无需先创建临时数组对象:","category":"page"},{"location":"manual/running-external-programs/","page":"运行外部程序","title":"运行外部程序","text":"julia> `rm -rf $[\"foo\",\"bar\",\"baz\",\"qux\"].$[\"aux\",\"log\",\"pdf\"]`\n`rm -rf foo.aux foo.log foo.pdf bar.aux bar.log bar.pdf baz.aux baz.log baz.pdf qux.aux qux.log qux.pdf`","category":"page"},{"location":"manual/running-external-programs/#引用","page":"运行外部程序","title":"引用","text":"","category":"section"},{"location":"manual/running-external-programs/","page":"运行外部程序","title":"运行外部程序","text":"不可避免地,我们会想要编写不那么简单的命令,且有必要使用引号。下面是 shell 提示符下单行 Perl 程序的简单示例:","category":"page"},{"location":"manual/running-external-programs/","page":"运行外部程序","title":"运行外部程序","text":"sh$ perl -le '$|=1; for (0..3) { print }'\n0\n1\n2\n3","category":"page"},{"location":"manual/running-external-programs/","page":"运行外部程序","title":"运行外部程序","text":"该 Perl 表达式需要使用单引号有两个原因:一是为了避免空格将表达式分解为多个 shell 单词,二是为了在使用像 $|(是的,这在 Perl 中是变量名)这样的 Perl 变量时避免发生插值。在其它情况下,你可能想要使用双引号来真的进行插值:","category":"page"},{"location":"manual/running-external-programs/","page":"运行外部程序","title":"运行外部程序","text":"sh$ first=\"A\"\nsh$ second=\"B\"\nsh$ perl -le '$|=1; print for @ARGV' \"1: $first\" \"2: $second\"\n1: A\n2: B","category":"page"},{"location":"manual/running-external-programs/","page":"运行外部程序","title":"运行外部程序","text":"总之,Julia 反引号语法是经过精心设计的,因此你可以只是将 shell 命令剪切并粘贴到反引号中,接着它们将会工作:转义、引用和插值行为与 shell 相同。唯一的不同是,插值是集成的并且知道在 Julia 的概念中什么是单个字符串值、什么是多个值的容器。让我们在 Julia 中尝试上面的两个例子:","category":"page"},{"location":"manual/running-external-programs/","page":"运行外部程序","title":"运行外部程序","text":"julia> A = `perl -le '$|=1; for (0..3) { print }'`\n`perl -le '$|=1; for (0..3) { print }'`\n\njulia> run(A);\n0\n1\n2\n3\n\njulia> first = \"A\"; second = \"B\";\n\njulia> B = `perl -le 'print for @ARGV' \"1: $first\" \"2: $second\"`\n`perl -le 'print for @ARGV' '1: A' '2: B'`\n\njulia> run(B);\n1: A\n2: B","category":"page"},{"location":"manual/running-external-programs/","page":"运行外部程序","title":"运行外部程序","text":"结果是相同的,且 Julia 的插值行为模仿了 shell 的并对其做了一些改进,因为 Julia 支持头等的可迭代对象,但大多数 shell 通过使用空格分隔字符串来实现这一点,而这又引入了歧义。在尝试将 shell 命令移植到 Julia 中时,请先试着剪切并粘贴它。因为 Julia 会在运行命令前向你显示命令,所以你可以在不造成任何破坏的前提下轻松并安全地检查命令的解释。","category":"page"},{"location":"manual/running-external-programs/#管道","page":"运行外部程序","title":"管道","text":"","category":"section"},{"location":"manual/running-external-programs/","page":"运行外部程序","title":"运行外部程序","text":"Shell 元字符,如 |、& 和 >,在 Julia 的反引号中需被引用(或转义):","category":"page"},{"location":"manual/running-external-programs/","page":"运行外部程序","title":"运行外部程序","text":"julia> run(`echo hello '|' sort`);\nhello | sort\n\njulia> run(`echo hello \\| sort`);\nhello | sort","category":"page"},{"location":"manual/running-external-programs/","page":"运行外部程序","title":"运行外部程序","text":"此表达式调用 echo 命令并以三个单词作为其参数:hello、| 和 sort。结果是只打印了一行:hello | sort。那么,如何构造管道呢?为此,请使用 pipeline,而不是在反引号内使用 '|':","category":"page"},{"location":"manual/running-external-programs/","page":"运行外部程序","title":"运行外部程序","text":"julia> run(pipeline(`echo hello`, `sort`));\nhello","category":"page"},{"location":"manual/running-external-programs/","page":"运行外部程序","title":"运行外部程序","text":"这将 echo 命令的输出传输到 sort 命令中。当然,这不是很有趣,因为只有一行要排序,但是我们的当然可以做更多、更有趣的事:","category":"page"},{"location":"manual/running-external-programs/","page":"运行外部程序","title":"运行外部程序","text":"julia> run(pipeline(`cut -d: -f3 /etc/passwd`, `sort -n`, `tail -n5`))\n210\n211\n212\n213\n214","category":"page"},{"location":"manual/running-external-programs/","page":"运行外部程序","title":"运行外部程序","text":"这将打印在 UNIX 系统上最高的五个用户 ID。cut、sort 和 tail 命令都是当前 julia 进程的直接子进程,这中间没有 shell 进程的干预。Julia 自己负责设置管道和连接文件描述符,而这通常由 shell 完成。因为 Julia 自己做了这些事,所以它能更好的控制并做 shell 做不到的一些事情。","category":"page"},{"location":"manual/running-external-programs/","page":"运行外部程序","title":"运行外部程序","text":"Julia 可以并行地运行多个命令:","category":"page"},{"location":"manual/running-external-programs/","page":"运行外部程序","title":"运行外部程序","text":"julia> run(`echo hello` & `echo world`);\nworld\nhello","category":"page"},{"location":"manual/running-external-programs/","page":"运行外部程序","title":"运行外部程序","text":"这里的输出顺序是不确定的,因为两个 echo 进程几乎同时启动,并且争着先写入 stdout 描述符和 julia 父进程。Julia 允许你将这两个进程的输出通过管道传输到另一个程序:","category":"page"},{"location":"manual/running-external-programs/","page":"运行外部程序","title":"运行外部程序","text":"julia> run(pipeline(`echo world` & `echo hello`, `sort`));\nhello\nworld","category":"page"},{"location":"manual/running-external-programs/","page":"运行外部程序","title":"运行外部程序","text":"在 UNIX 管道方面,这里发生的是,一个 UNIX 管道对象由两个 echo 进程创建和写入,管道的另一端由 sort 命令读取。","category":"page"},{"location":"manual/running-external-programs/","page":"运行外部程序","title":"运行外部程序","text":"IO 重定向可以通过向 pipeline 函数传递关键字参数 stdin、stdout 和 stderr 来实现:","category":"page"},{"location":"manual/running-external-programs/","page":"运行外部程序","title":"运行外部程序","text":"pipeline(`do_work`, stdout=pipeline(`sort`, \"out.txt\"), stderr=\"errs.txt\")","category":"page"},{"location":"manual/running-external-programs/#避免管道中的死锁","page":"运行外部程序","title":"避免管道中的死锁","text":"","category":"section"},{"location":"manual/running-external-programs/","page":"运行外部程序","title":"运行外部程序","text":"在单个进程中读取和写入管道的两端时,避免强制内核缓冲所有数据是很重要的。","category":"page"},{"location":"manual/running-external-programs/","page":"运行外部程序","title":"运行外部程序","text":"例如,在读取命令的所有输出时,请调用 read(out, String),而非 wait(process),因为前者会积极地消耗由该进程写入的所有数据,而后者在等待读取者连接时会尝试将数据存储内核的缓冲区中。","category":"page"},{"location":"manual/running-external-programs/","page":"运行外部程序","title":"运行外部程序","text":"另一个常见的解决方案是将读取者和写入者分离到单独的 Task 中:","category":"page"},{"location":"manual/running-external-programs/","page":"运行外部程序","title":"运行外部程序","text":"writer = @async write(process, \"data\")\nreader = @async do_compute(read(process, String))\nwait(writer)\nfetch(reader)","category":"page"},{"location":"manual/running-external-programs/","page":"运行外部程序","title":"运行外部程序","text":"(通常,reader 不是一个单独的任务,因为无论如何我们都会立即fetch它)。","category":"page"},{"location":"manual/running-external-programs/#复杂示例","page":"运行外部程序","title":"复杂示例","text":"","category":"section"},{"location":"manual/running-external-programs/","page":"运行外部程序","title":"运行外部程序","text":"高级编程语言、头等的命令抽象以及进程间管道的自动设置,三者组合起来非常强大。为了更好地理解可被轻松创建的复杂管道,这里有一些更复杂的例子,以避免对单行 Perl 程序的滥用。","category":"page"},{"location":"manual/running-external-programs/","page":"运行外部程序","title":"运行外部程序","text":"julia> prefixer(prefix, sleep) = `perl -nle '$|=1; print \"'$prefix' \", $_; sleep '$sleep';'`;\n\njulia> run(pipeline(`perl -le '$|=1; for(0..5){ print; sleep 1 }'`, prefixer(\"A\",2) & prefixer(\"B\",2)));\nB 0\nA 1\nB 2\nA 3\nB 4\nA 5","category":"page"},{"location":"manual/running-external-programs/","page":"运行外部程序","title":"运行外部程序","text":"这是一个经典的例子,一个生产者为两个并发的消费者提供内容:一个 perl 进程生成从数字 0 到 5 的行,而两个并行进程则使用该输出,一个行首加字母「A」,另一个行首加字母「B」。哪个进程使用第一行是不确定的,但是一旦赢得了竞争,这些行会先后被其中一个进程及另一个进程交替使用。(在 Perl 中设置 $|=1 会导致每个 print 语句刷新 stdout 句柄,这是本例工作所必需的。此外,所有输出将被缓存并一次性打印到管道中,以便只由一个消费者进程读取。)","category":"page"},{"location":"manual/running-external-programs/","page":"运行外部程序","title":"运行外部程序","text":"这是一个更加复杂的多阶段生产者——消费者示例:","category":"page"},{"location":"manual/running-external-programs/","page":"运行外部程序","title":"运行外部程序","text":"julia> run(pipeline(`perl -le '$|=1; for(0..5){ print; sleep 1 }'`,\n prefixer(\"X\",3) & prefixer(\"Y\",3) & prefixer(\"Z\",3),\n prefixer(\"A\",2) & prefixer(\"B\",2)));\nA X 0\nB Y 1\nA Z 2\nB X 3\nA Y 4\nB Z 5","category":"page"},{"location":"manual/running-external-programs/","page":"运行外部程序","title":"运行外部程序","text":"此示例与前一个类似,不同之处在于本例中的消费者有两个阶段,并且阶段间有不同的延迟,因此它们使用不同数量的并行 worker 来维持饱和的吞吐量。","category":"page"},{"location":"manual/running-external-programs/","page":"运行外部程序","title":"运行外部程序","text":"我们强烈建议你尝试所有这些例子,以便了解它们的工作原理。","category":"page"},{"location":"manual/running-external-programs/#Cmd对象","page":"运行外部程序","title":"Cmd对象","text":"","category":"section"},{"location":"manual/running-external-programs/","page":"运行外部程序","title":"运行外部程序","text":"反引号语法创建一个 Cmd 类型的对象。 此类对象也可以直接从现有的 Cmd 或参数列表构造:","category":"page"},{"location":"manual/running-external-programs/","page":"运行外部程序","title":"运行外部程序","text":"run(Cmd(`pwd`, dir=\"..\"))\nrun(Cmd([\"pwd\"], detach=true, ignorestatus=true))","category":"page"},{"location":"manual/running-external-programs/","page":"运行外部程序","title":"运行外部程序","text":"这允许你通过关键字参数指定 Cmd 的执行环境的几个方面。 例如,dir 关键字提供对 Cmd 工作目录的控制:","category":"page"},{"location":"manual/running-external-programs/","page":"运行外部程序","title":"运行外部程序","text":"julia> run(Cmd(`pwd`, dir=\"/\"));\n/","category":"page"},{"location":"manual/running-external-programs/","page":"运行外部程序","title":"运行外部程序","text":"并且 env 关键字允许您设置执行环境变量:","category":"page"},{"location":"manual/running-external-programs/","page":"运行外部程序","title":"运行外部程序","text":"julia> run(Cmd(`sh -c \"echo foo \\$HOWLONG\"`, env=(\"HOWLONG\" => \"ever!\",)));\nfoo ever!","category":"page"},{"location":"manual/running-external-programs/","page":"运行外部程序","title":"运行外部程序","text":"有关其它关键字参数,请参阅 Cmd。 setenv 和 addenv 命令分别提供了另一种替换或添加到 Cmd 执行环境变量的方法:","category":"page"},{"location":"manual/running-external-programs/","page":"运行外部程序","title":"运行外部程序","text":"julia> run(setenv(`sh -c \"echo foo \\$HOWLONG\"`, (\"HOWLONG\" => \"ever!\",)));\nfoo ever!\n\njulia> run(addenv(`sh -c \"echo foo \\$HOWLONG\"`, \"HOWLONG\" => \"ever!\"));\nfoo ever!","category":"page"},{"location":"manual/networking-and-streams/#网络和流","page":"网络和流","title":"网络和流","text":"","category":"section"},{"location":"manual/networking-and-streams/","page":"网络和流","title":"网络和流","text":"Julia 提供了一个功能丰富的接口来处理流式 I/O 对象,如终端、管道和 TCP 套接字。此接口虽然在系统级是异步的,但是其以同步的方式展现给程序员,通常也不需要考虑底层的异步操作。这是通过大量使用 Julia 协作线程(协程)功能实现的。","category":"page"},{"location":"manual/networking-and-streams/#基础流-I/O","page":"网络和流","title":"基础流 I/O","text":"","category":"section"},{"location":"manual/networking-and-streams/","page":"网络和流","title":"网络和流","text":"所有 Julia stream 都暴露了 read 和 write 方法,将 stream 作为它们的第一个参数,如:","category":"page"},{"location":"manual/networking-and-streams/","page":"网络和流","title":"网络和流","text":"julia> write(stdout, \"Hello World\"); # suppress return value 11 with ;\nHello World\njulia> read(stdin, Char)\n\n'\\n': ASCII/Unicode U+000a (category Cc: Other, control)","category":"page"},{"location":"manual/networking-and-streams/","page":"网络和流","title":"网络和流","text":"注意,write 返回 11,字节数(\"Hello World\")写入 stdout,但是返回值使用 ; 抑制。","category":"page"},{"location":"manual/networking-and-streams/","page":"网络和流","title":"网络和流","text":"这里按了两次回车,以便 Julia 能够读取到换行符。正如你在这个例子中所看到的,write 以待写入的数据作为其第二个参数,而 read 以待读取的数据的类型作为其第二个参数。","category":"page"},{"location":"manual/networking-and-streams/","page":"网络和流","title":"网络和流","text":"例如,为了读取一个简单的字节数组,我们可以这样做:","category":"page"},{"location":"manual/networking-and-streams/","page":"网络和流","title":"网络和流","text":"julia> x = zeros(UInt8, 4)\n4-element Array{UInt8,1}:\n 0x00\n 0x00\n 0x00\n 0x00\n\njulia> read!(stdin, x)\nabcd\n4-element Array{UInt8,1}:\n 0x61\n 0x62\n 0x63\n 0x64","category":"page"},{"location":"manual/networking-and-streams/","page":"网络和流","title":"网络和流","text":"但是,因为这有些繁琐,所以提供了几个方便的方法。例如,我们可以把上面的代码编写为:","category":"page"},{"location":"manual/networking-and-streams/","page":"网络和流","title":"网络和流","text":"julia> read(stdin, 4)\nabcd\n4-element Array{UInt8,1}:\n 0x61\n 0x62\n 0x63\n 0x64","category":"page"},{"location":"manual/networking-and-streams/","page":"网络和流","title":"网络和流","text":"或者如果我们想要读取一整行:","category":"page"},{"location":"manual/networking-and-streams/","page":"网络和流","title":"网络和流","text":"julia> readline(stdin)\nabcd\n\"abcd\"","category":"page"},{"location":"manual/networking-and-streams/","page":"网络和流","title":"网络和流","text":"请注意,根据你的终端设置,你的 TTY 可能是行缓冲的,因此在数据发送给 Julia 前可能需要额外的回车。","category":"page"},{"location":"manual/networking-and-streams/","page":"网络和流","title":"网络和流","text":"若要读取 stdin 的每一行,可以使用 eachline:","category":"page"},{"location":"manual/networking-and-streams/","page":"网络和流","title":"网络和流","text":"for line in eachline(stdin)\n print(\"Found $line\")\nend","category":"page"},{"location":"manual/networking-and-streams/","page":"网络和流","title":"网络和流","text":"或者如果你想要按字符读取的话,使用 read :","category":"page"},{"location":"manual/networking-and-streams/","page":"网络和流","title":"网络和流","text":"while !eof(stdin)\n x = read(stdin, Char)\n println(\"Found: $x\")\nend","category":"page"},{"location":"manual/networking-and-streams/#文本-I/O","page":"网络和流","title":"文本 I/O","text":"","category":"section"},{"location":"manual/networking-and-streams/","page":"网络和流","title":"网络和流","text":"请注意,上面提到的 write 方法对二进制流进行操作。具体来说,值不会转换为任何规范的文本表示形式,而是按原样输出:","category":"page"},{"location":"manual/networking-and-streams/","page":"网络和流","title":"网络和流","text":"julia> write(stdout, 0x61); # suppress return value 1 with ;\na","category":"page"},{"location":"manual/networking-and-streams/","page":"网络和流","title":"网络和流","text":"请注意,a 被 write 函数写入到 stdout 并且返回值为 1(因为 0x61 为一个字节)。","category":"page"},{"location":"manual/networking-and-streams/","page":"网络和流","title":"网络和流","text":"对于文本 I/O,请根据需要使用 print 或 show 方法(有关这两个方法之间的差异的详细讨论,请参阅它们的文档):","category":"page"},{"location":"manual/networking-and-streams/","page":"网络和流","title":"网络和流","text":"julia> print(stdout, 0x61)\n97","category":"page"},{"location":"manual/networking-and-streams/","page":"网络和流","title":"网络和流","text":"有关如何实现自定义类型的显示方法的更多信息,请参阅 自定义 pretty-printing。","category":"page"},{"location":"manual/networking-and-streams/#IO-输出的上下文信息","page":"网络和流","title":"IO 输出的上下文信息","text":"","category":"section"},{"location":"manual/networking-and-streams/","page":"网络和流","title":"网络和流","text":"有时,IO 输出可受益于将上下文信息传递到 show 方法的能力。IOContext 对象提供了将任意元数据与 IO 对象相关联的框架。例如,:compact => true 向 IO 对象添加一个参数来提示调用的 show 方法应该打印一个较短的输出(如果适用)。有关常用属性的列表,请参阅 IOContext 文档。","category":"page"},{"location":"manual/networking-and-streams/#使用文件","page":"网络和流","title":"使用文件","text":"","category":"section"},{"location":"manual/networking-and-streams/","page":"网络和流","title":"网络和流","text":"和其他环境一样,Julia 有 open 函数,它接收文件名并返回一个 IOStream 对象,你可以用该对象来对文件进行读取和写入。例如,如果我们有文件 hello.txt,其内容为 Hello, World!:","category":"page"},{"location":"manual/networking-and-streams/","page":"网络和流","title":"网络和流","text":"julia> f = open(\"hello.txt\")\nIOStream()\n\njulia> readlines(f)\n1-element Array{String,1}:\n \"Hello, World!\"","category":"page"},{"location":"manual/networking-and-streams/","page":"网络和流","title":"网络和流","text":"若要写入文件,则可以带着 write(\"w\")标志来打开它:","category":"page"},{"location":"manual/networking-and-streams/","page":"网络和流","title":"网络和流","text":"julia> f = open(\"hello.txt\",\"w\")\nIOStream()\n\njulia> write(f,\"Hello again.\")\n12","category":"page"},{"location":"manual/networking-and-streams/","page":"网络和流","title":"网络和流","text":"你如果在此刻检查 hello.txt 的内容,会注意到它是空的;改动实际上还没有写入到磁盘中。这是因为 IOStream 必须在写入实际刷新到磁盘前关闭:","category":"page"},{"location":"manual/networking-and-streams/","page":"网络和流","title":"网络和流","text":"julia> close(f)","category":"page"},{"location":"manual/networking-and-streams/","page":"网络和流","title":"网络和流","text":"再次检查 hello.txt 将显示其内容已被更改。","category":"page"},{"location":"manual/networking-and-streams/","page":"网络和流","title":"网络和流","text":"打开文件,对其内容执行一些操作,并再次关闭它是一种非常常见的模式。为了使这更容易,open 还有另一种调用方式,它以一个函数作为其第一个参数,以文件名作为其第二个参数,以该文件为参数调用该函数,然后再次关闭它。例如,给定函数:","category":"page"},{"location":"manual/networking-and-streams/","page":"网络和流","title":"网络和流","text":"function read_and_capitalize(f::IOStream)\n return uppercase(read(f, String))\nend","category":"page"},{"location":"manual/networking-and-streams/","page":"网络和流","title":"网络和流","text":"可以调用:","category":"page"},{"location":"manual/networking-and-streams/","page":"网络和流","title":"网络和流","text":"julia> open(read_and_capitalize, \"hello.txt\")\n\"HELLO AGAIN.\"","category":"page"},{"location":"manual/networking-and-streams/","page":"网络和流","title":"网络和流","text":"来打开 hello.txt,对它调用 read_and_capitalize,关闭 hello.txt 并返回大写的内容。","category":"page"},{"location":"manual/networking-and-streams/","page":"网络和流","title":"网络和流","text":"为了避免被迫定义一个命名函数,你可以使用 do 语法,它可以动态地创建匿名函数:","category":"page"},{"location":"manual/networking-and-streams/","page":"网络和流","title":"网络和流","text":"julia> open(\"hello.txt\") do f\n uppercase(read(f, String))\n end\n\"HELLO AGAIN.\"","category":"page"},{"location":"manual/networking-and-streams/#一个简单的-TCP-示例","page":"网络和流","title":"一个简单的 TCP 示例","text":"","category":"section"},{"location":"manual/networking-and-streams/","page":"网络和流","title":"网络和流","text":"让我们直接进入一个 TCP 套接字相关的简单示例。此功能位于名为 Sockets 的标准库中。让我们先创建一个简单的服务器:","category":"page"},{"location":"manual/networking-and-streams/","page":"网络和流","title":"网络和流","text":"julia> using Sockets\n\njulia> errormonitor(@async begin\n server = listen(2000)\n while true\n sock = accept(server)\n println(\"Hello World\\n\")\n end\n end)\nTask (runnable) @0x00007fd31dc11ae0","category":"page"},{"location":"manual/networking-and-streams/","page":"网络和流","title":"网络和流","text":"对于那些熟悉 Unix 套接字 API 的人,这些方法名称会让人感觉很熟悉,可是它们的用法比原始的 Unix 套接字 API 要简单些。在本例中,首次调用 listen 会创建一个服务器,等待传入指定端口(2000)的连接。","category":"page"},{"location":"manual/networking-and-streams/","page":"网络和流","title":"网络和流","text":"julia> listen(2000) # 监听(IPv4 下的)localhost:2000\nSockets.TCPServer(active)\n\njulia> listen(ip\"127.0.0.1\",2000) # 等价于第一个\nSockets.TCPServer(active)\n\njulia> listen(ip\"::1\",2000) # 监听(IPv6 下的)localhost:2000\nSockets.TCPServer(active)\n\njulia> listen(IPv4(0),2001) # 监听所有 IPv4 接口的端口 2001\nSockets.TCPServer(active)\n\njulia> listen(IPv6(0),2001) # 监听所有 IPv6 接口的端口 2001\nSockets.TCPServer(active)\n\njulia> listen(\"testsocket\") # 监听 UNIX 域套接字\nSockets.PipeServer(active)\n\njulia> listen(\"\\\\\\\\.\\\\pipe\\\\testsocket\") # 监听 Windows 命名管道\nSockets.PipeServer(active)","category":"page"},{"location":"manual/networking-and-streams/","page":"网络和流","title":"网络和流","text":"请注意,最后一次调用返回的类型是不同的。这是因为此服务器不监听 TCP,而是监听命名管道(Windows)或 UNIX 域套接字。还请注意 Windows 命名管道格式必须具有特定的模式,即名称前缀(\\\\.\\pipe\\),以便唯一标识文件类型。TCP 和命名管道或 UNIX 域套接字之间的区别是微妙的,这与 accept 和 connect 方法有关。accept 方法检索到连接到我们刚创建的服务器的客户端的连接,而 connect 函数使用指定的方法连接到服务器。connect 函数接收与 listen 相同的参数,因此,假设环境(即 host、cwd 等)相同,你应该能够将相同的参数传递给 connect,就像你在监听建立连接时所做的那样。那么让我们尝试一下(在创建上面的服务器之后):","category":"page"},{"location":"manual/networking-and-streams/","page":"网络和流","title":"网络和流","text":"julia> connect(2000)\nTCPSocket(open, 0 bytes waiting)\n\njulia> Hello World","category":"page"},{"location":"manual/networking-and-streams/","page":"网络和流","title":"网络和流","text":"不出所料,我们看到「Hello World」被打印出来。那么,让我们分析一下幕后发生的事情。在我们调用 connect 时,我们连接到刚刚创建的服务器。与此同时,accept 函数返回到新创建的套接字的服务器端连接,并打印「Hello World」来表明连接成功。","category":"page"},{"location":"manual/networking-and-streams/","page":"网络和流","title":"网络和流","text":"Julia 的强大优势在于,即使 I/O 实际上是异步发生的,API 也以同步方式暴露,我们不必担心回调,甚至不必确保服务器能够运行。在我们调用 connect 时,当前任务等待建立连接,并在这之后才继续执行。在此暂停中,服务器任务恢复执行(因为现在有一个连接请求是可用的),接受该连接,打印信息并等待下一个客户端。读取和写入以同样的方式运行。为了理解这一点,请考虑以下简单的 echo 服务器:","category":"page"},{"location":"manual/networking-and-streams/","page":"网络和流","title":"网络和流","text":"julia> errormonitor(@async begin\n server = listen(2001)\n while true\n sock = accept(server)\n @async while isopen(sock)\n write(sock, readline(sock, keep=true))\n end\n end\n end)\nTask (runnable) @0x00007fd31dc12e60\n\njulia> clientside = connect(2001)\nTCPSocket(RawFD(28) open, 0 bytes waiting)\n\njulia> errormonitor(@async while isopen(clientside)\n write(stdout, readline(clientside, keep=true))\n end)\nTask (runnable) @0x00007fd31dc11870\n\njulia> println(clientside,\"Hello World from the Echo Server\")\nHello World from the Echo Server","category":"page"},{"location":"manual/networking-and-streams/","page":"网络和流","title":"网络和流","text":"与其他流一样,使用 close 即可断开该套接字:","category":"page"},{"location":"manual/networking-and-streams/","page":"网络和流","title":"网络和流","text":"julia> close(clientside)","category":"page"},{"location":"manual/networking-and-streams/#解析-IP-地址","page":"网络和流","title":"解析 IP 地址","text":"","category":"section"},{"location":"manual/networking-and-streams/","page":"网络和流","title":"网络和流","text":"与 listen 方法不一致的 connect 方法之一是 connect(host::String,port),它将尝试连接到由 host 参数给定的主机上的由 port 参数给定的端口。它允许你执行以下操作:","category":"page"},{"location":"manual/networking-and-streams/","page":"网络和流","title":"网络和流","text":"julia> connect(\"google.com\", 80)\nTCPSocket(RawFD(30) open, 0 bytes waiting)","category":"page"},{"location":"manual/networking-and-streams/","page":"网络和流","title":"网络和流","text":"此功能的基础是 getaddrinfo,它将执行适当的地址解析:","category":"page"},{"location":"manual/networking-and-streams/","page":"网络和流","title":"网络和流","text":"julia> getaddrinfo(\"google.com\")\nip\"74.125.226.225\"","category":"page"},{"location":"manual/networking-and-streams/#异步-I/O","page":"网络和流","title":"异步 I/O","text":"","category":"section"},{"location":"manual/networking-and-streams/","page":"网络和流","title":"网络和流","text":"Base.read 和 Base.write 的所有 I/O 操作都可以通过使用 coroutines 异步执行。 你可以使用 @async 宏创建一个新的协程来读取或写入流:","category":"page"},{"location":"manual/networking-and-streams/","page":"网络和流","title":"网络和流","text":"julia> task = @async open(\"foo.txt\", \"w\") do io\n write(io, \"Hello, World!\")\n end;\n\njulia> wait(task)\n\njulia> readlines(\"foo.txt\")\n1-element Array{String,1}:\n \"Hello, World!\"","category":"page"},{"location":"manual/networking-and-streams/","page":"网络和流","title":"网络和流","text":"通常会遇到您想要同时执行多个异步操作并等待它们全部完成的情况。你可以使用@ sync宏,这会阻塞你的程序直到它所包裹的所有协程运行完毕。","category":"page"},{"location":"manual/networking-and-streams/","page":"网络和流","title":"网络和流","text":"julia> using Sockets\n\njulia> @sync for hostname in (\"google.com\", \"github.com\", \"julialang.org\")\n @async begin\n conn = connect(hostname, 80)\n write(conn, \"GET / HTTP/1.1\\r\\nHost:$(hostname)\\r\\n\\r\\n\")\n readline(conn, keep=true)\n println(\"Finished connection to $(hostname)\")\n end\n end\nFinished connection to google.com\nFinished connection to julialang.org\nFinished connection to github.com","category":"page"},{"location":"stdlib/REPL/#Julia-REPL","page":"Julia REPL","title":"Julia REPL","text":"","category":"section"},{"location":"stdlib/REPL/","page":"Julia REPL","title":"Julia REPL","text":"Julia 附带了一个全功能的交互式命令行 REPL(read-eval-print loop),其内置于 julia 可执行文件中。它除了允许快速简便地执行 Julia 语句外,还具有可搜索的历史记录,tab 补全,许多有用的按键绑定以及专用的 help 和 shell 模式。只需不附带任何参数地调用 julia 或双击可执行文件即可启动 REPL:","category":"page"},{"location":"stdlib/REPL/","page":"Julia REPL","title":"Julia REPL","text":"io = IOBuffer()\nBase.banner(io)\nbanner = String(take!(io))\nimport Markdown\nMarkdown.parse(\"```\\n\\$ julia\\n\\n$(banner)\\njulia>\\n```\")","category":"page"},{"location":"stdlib/REPL/","page":"Julia REPL","title":"Julia REPL","text":"要退出交互式会话,在空白行上键入 ^D——control 键和 d 键,或者先键入 quit(),然后键入 return 或 enter 键。REPL 用横幅和 julia> 提示符欢迎你。","category":"page"},{"location":"stdlib/REPL/#不同的提示符模式","page":"Julia REPL","title":"不同的提示符模式","text":"","category":"section"},{"location":"stdlib/REPL/#Julian-模式","page":"Julia REPL","title":"Julian 模式","text":"","category":"section"},{"location":"stdlib/REPL/","page":"Julia REPL","title":"Julia REPL","text":"The REPL has five main modes of operation. The first and most common is the Julian prompt. It is the default mode of operation; each new line initially starts with julia>. It is here that you can enter Julia expressions. Hitting return or enter after a complete expression has been entered will evaluate the entry and show the result of the last expression.","category":"page"},{"location":"stdlib/REPL/","page":"Julia REPL","title":"Julia REPL","text":"julia> string(1 + 2)\n\"3\"","category":"page"},{"location":"stdlib/REPL/","page":"Julia REPL","title":"Julia REPL","text":"交互式运行有许多独特的实用功能。除了显示结果外,REPL 还将结果绑定到变量 ans 上。一行的尾随分号可用作禁止显示结果的标志。","category":"page"},{"location":"stdlib/REPL/","page":"Julia REPL","title":"Julia REPL","text":"julia> string(3 * 4);\n\njulia> ans\n\"12\"","category":"page"},{"location":"stdlib/REPL/","page":"Julia REPL","title":"Julia REPL","text":"In Julia mode, the REPL supports something called prompt pasting. This activates when pasting text that starts with julia> into the REPL. In that case, only expressions starting with julia> are parsed, others are removed. This makes it possible to paste a chunk of code that has been copied from a REPL session without having to scrub away prompts and outputs. This feature is enabled by default but can be disabled or enabled at will with REPL.enable_promptpaste(::Bool). If it is enabled, you can try it out by pasting the code block above this paragraph straight into the REPL. This feature does not work on the standard Windows command prompt due to its limitation at detecting when a paste occurs.","category":"page"},{"location":"stdlib/REPL/","page":"Julia REPL","title":"Julia REPL","text":"Objects are printed at the REPL using the show function with a specific IOContext. In particular, the :limit attribute is set to true. Other attributes can receive in certain show methods a default value if it's not already set, like :compact. It's possible, as an experimental feature, to specify the attributes used by the REPL via the Base.active_repl.options.iocontext dictionary (associating values to attributes). For example:","category":"page"},{"location":"stdlib/REPL/","page":"Julia REPL","title":"Julia REPL","text":"julia> rand(2, 2)\n2×2 Array{Float64,2}:\n 0.8833 0.329197\n 0.719708 0.59114\n\njulia> show(IOContext(stdout, :compact => false), \"text/plain\", rand(2, 2))\n 0.43540323669187075 0.15759787870609387\n 0.2540832269192739 0.4597637838786053\njulia> Base.active_repl.options.iocontext[:compact] = false;\n\njulia> rand(2, 2)\n2×2 Array{Float64,2}:\n 0.2083967319174056 0.13330606013126012\n 0.6244375177790158 0.9777957560761545","category":"page"},{"location":"stdlib/REPL/","page":"Julia REPL","title":"Julia REPL","text":"In order to define automatically the values of this dictionary at startup time, one can use the atreplinit function in the ~/.julia/config/startup.jl file, for example:","category":"page"},{"location":"stdlib/REPL/","page":"Julia REPL","title":"Julia REPL","text":"atreplinit() do repl\n repl.options.iocontext[:compact] = false\nend","category":"page"},{"location":"stdlib/REPL/#帮助模式","page":"Julia REPL","title":"帮助模式","text":"","category":"section"},{"location":"stdlib/REPL/","page":"Julia REPL","title":"Julia REPL","text":"When the cursor is at the beginning of the line, the prompt can be changed to a help mode by typing ?. Julia will attempt to print help or documentation for anything entered in help mode:","category":"page"},{"location":"stdlib/REPL/","page":"Julia REPL","title":"Julia REPL","text":"julia> ? # upon typing ?, the prompt changes (in place) to: help?>\n\nhelp?> string\nsearch: string String Cstring Cwstring RevString randstring bytestring SubString\n\n string(xs...)\n\n Create a string from any values using the print function.","category":"page"},{"location":"stdlib/REPL/","page":"Julia REPL","title":"Julia REPL","text":"Macros, types and variables can also be queried:","category":"page"},{"location":"stdlib/REPL/","page":"Julia REPL","title":"Julia REPL","text":"help?> @time\n @time\n\n A macro to execute an expression, printing the time it took to execute, the number of allocations,\n and the total number of bytes its execution caused to be allocated, before returning the value of the\n expression.\n\n See also @timev, @timed, @elapsed, and @allocated.\n\nhelp?> Int32\nsearch: Int32 UInt32\n\n Int32 <: Signed\n\n 32-bit signed integer type.","category":"page"},{"location":"stdlib/REPL/","page":"Julia REPL","title":"Julia REPL","text":"A string or regex literal searches all docstrings using apropos:","category":"page"},{"location":"stdlib/REPL/","page":"Julia REPL","title":"Julia REPL","text":"help?> \"aprop\"\nREPL.stripmd\nBase.Docs.apropos\n\nhelp?> r\"ap..p\"\nBase.:∘\nBase.shell_escape_posixly\nDistributed.CachingPool\nREPL.stripmd\nBase.Docs.apropos","category":"page"},{"location":"stdlib/REPL/","page":"Julia REPL","title":"Julia REPL","text":"Help mode can be exited by pressing backspace at the beginning of the line.","category":"page"},{"location":"stdlib/REPL/#man-shell-mode","page":"Julia REPL","title":"Shell mode","text":"","category":"section"},{"location":"stdlib/REPL/","page":"Julia REPL","title":"Julia REPL","text":"Just as help mode is useful for quick access to documentation, another common task is to use the system shell to execute system commands. Just as ? entered help mode when at the beginning of the line, a semicolon (;) will enter the shell mode. And it can be exited by pressing backspace at the beginning of the line.","category":"page"},{"location":"stdlib/REPL/","page":"Julia REPL","title":"Julia REPL","text":"julia> ; # upon typing ;, the prompt changes (in place) to: shell>\n\nshell> echo hello\nhello","category":"page"},{"location":"stdlib/REPL/","page":"Julia REPL","title":"Julia REPL","text":"note: Note\nFor Windows users, Julia's shell mode does not expose windows shell commands. Hence, this will fail:","category":"page"},{"location":"stdlib/REPL/","page":"Julia REPL","title":"Julia REPL","text":"julia> ; # upon typing ;, the prompt changes (in place) to: shell>\n\nshell> dir\nERROR: IOError: could not spawn `dir`: no such file or directory (ENOENT)\nStacktrace!\n.......","category":"page"},{"location":"stdlib/REPL/","page":"Julia REPL","title":"Julia REPL","text":"However, you can get access to PowerShell like this:","category":"page"},{"location":"stdlib/REPL/","page":"Julia REPL","title":"Julia REPL","text":"julia> ; # upon typing ;, the prompt changes (in place) to: shell>\n\nshell> powershell\nWindows PowerShell\nCopyright (C) Microsoft Corporation. All rights reserved.\nPS C:\\Users\\elm>","category":"page"},{"location":"stdlib/REPL/","page":"Julia REPL","title":"Julia REPL","text":"... and to cmd.exe like that (see the dir command):","category":"page"},{"location":"stdlib/REPL/","page":"Julia REPL","title":"Julia REPL","text":"julia> ; # upon typing ;, the prompt changes (in place) to: shell>\n\nshell> cmd\nMicrosoft Windows [version 10.0.17763.973]\n(c) 2018 Microsoft Corporation. All rights reserved.\nC:\\Users\\elm>dir\n Volume in drive C has no label\n Volume Serial Number is 1643-0CD7\n Directory of C:\\Users\\elm\n\n29/01/2020 22:15 .\n29/01/2020 22:15 ..\n02/02/2020 08:06 .atom","category":"page"},{"location":"stdlib/REPL/#Pkg-mode","page":"Julia REPL","title":"Pkg mode","text":"","category":"section"},{"location":"stdlib/REPL/","page":"Julia REPL","title":"Julia REPL","text":"The Package manager mode accepts specialized commands for loading and updating packages. It is entered by pressing the ] key at the Julian REPL prompt and exited by pressing CTRL-C or pressing the backspace key at the beginning of the line. The prompt for this mode is pkg>. It supports its own help-mode, which is entered by pressing ? at the beginning of the line of the pkg> prompt. The Package manager mode is documented in the Pkg manual, available at https://julialang.github.io/Pkg.jl/v1/.","category":"page"},{"location":"stdlib/REPL/#Search-modes","page":"Julia REPL","title":"Search modes","text":"","category":"section"},{"location":"stdlib/REPL/","page":"Julia REPL","title":"Julia REPL","text":"In all of the above modes, the executed lines get saved to a history file, which can be searched. To initiate an incremental search through the previous history, type ^R – the control key together with the r key. The prompt will change to (reverse-i-search)`':, and as you type the search query will appear in the quotes. The most recent result that matches the query will dynamically update to the right of the colon as more is typed. To find an older result using the same query, simply type ^R again.","category":"page"},{"location":"stdlib/REPL/","page":"Julia REPL","title":"Julia REPL","text":"Just as ^R is a reverse search, ^S is a forward search, with the prompt (i-search)`':. The two may be used in conjunction with each other to move through the previous or next matching results, respectively.","category":"page"},{"location":"stdlib/REPL/#Key-bindings","page":"Julia REPL","title":"Key bindings","text":"","category":"section"},{"location":"stdlib/REPL/","page":"Julia REPL","title":"Julia REPL","text":"The Julia REPL makes great use of key bindings. Several control-key bindings were already introduced above (^D to exit, ^R and ^S for searching), but there are many more. In addition to the control-key, there are also meta-key bindings. These vary more by platform, but most terminals default to using alt- or option- held down with a key to send the meta-key (or can be configured to do so), or pressing Esc and then the key.","category":"page"},{"location":"stdlib/REPL/","page":"Julia REPL","title":"Julia REPL","text":"Keybinding Description\nProgram control \n^D Exit (when buffer is empty)\n^C Interrupt or cancel\n^L Clear console screen\nReturn/Enter, ^J New line, executing if it is complete\nmeta-Return/Enter Insert new line without executing it\n? or ; Enter help or shell mode (when at start of a line)\n^R, ^S Incremental history search, described above\nCursor movement \nRight arrow, ^F Move right one character\nLeft arrow, ^B Move left one character\nctrl-Right, meta-F Move right one word\nctrl-Left, meta-B Move left one word\nHome, ^A Move to beginning of line\nEnd, ^E Move to end of line\nUp arrow, ^P Move up one line (or change to the previous history entry that matches the text before the cursor)\nDown arrow, ^N Move down one line (or change to the next history entry that matches the text before the cursor)\nShift-Arrow Key Move cursor according to the direction of the Arrow key, while activating the region (\"shift selection\")\nPage-up, meta-P Change to the previous history entry\nPage-down, meta-N Change to the next history entry\nmeta-< Change to the first history entry (of the current session if it is before the current position in history)\nmeta-> Change to the last history entry\n^-Space Set the \"mark\" in the editing region (and de-activate the region if it's active)\n^-Space ^-Space Set the \"mark\" in the editing region and make the region \"active\", i.e. highlighted\n^G De-activate the region (i.e. make it not highlighted)\n^X^X Exchange the current position with the mark\nEditing \nBackspace, ^H Delete the previous character, or the whole region when it's active\nDelete, ^D Forward delete one character (when buffer has text)\nmeta-Backspace Delete the previous word\nmeta-d Forward delete the next word\n^W Delete previous text up to the nearest whitespace\nmeta-w Copy the current region in the kill ring\nmeta-W \"Kill\" the current region, placing the text in the kill ring\n^K \"Kill\" to end of line, placing the text in the kill ring\n^Y \"Yank\" insert the text from the kill ring\nmeta-y Replace a previously yanked text with an older entry from the kill ring\n^T Transpose the characters about the cursor\nmeta-Up arrow Transpose current line with line above\nmeta-Down arrow Transpose current line with line below\nmeta-u Change the next word to uppercase\nmeta-c Change the next word to titlecase\nmeta-l Change the next word to lowercase\n^/, ^_ Undo previous editing action\n^Q Write a number in REPL and press ^Q to open editor at corresponding stackframe or method\nmeta-Left Arrow indent the current line on the left\nmeta-Right Arrow indent the current line on the right\nmeta-. insert last word from previous history entry","category":"page"},{"location":"stdlib/REPL/#Customizing-keybindings","page":"Julia REPL","title":"Customizing keybindings","text":"","category":"section"},{"location":"stdlib/REPL/","page":"Julia REPL","title":"Julia REPL","text":"Julia's REPL keybindings may be fully customized to a user's preferences by passing a dictionary to REPL.setup_interface. The keys of this dictionary may be characters or strings. The key '*' refers to the default action. Control plus character x bindings are indicated with \"^x\". Meta plus x can be written \"\\\\M-x\" or \"\\ex\", and Control plus x can be written \"\\\\C-x\" or \"^x\". The values of the custom keymap must be nothing (indicating that the input should be ignored) or functions that accept the signature (PromptState, AbstractREPL, Char). The REPL.setup_interface function must be called before the REPL is initialized, by registering the operation with atreplinit . For example, to bind the up and down arrow keys to move through history without prefix search, one could put the following code in ~/.julia/config/startup.jl:","category":"page"},{"location":"stdlib/REPL/","page":"Julia REPL","title":"Julia REPL","text":"import REPL\nimport REPL.LineEdit\n\nconst mykeys = Dict{Any,Any}(\n # Up Arrow\n \"\\e[A\" => (s,o...)->(LineEdit.edit_move_up(s) || LineEdit.history_prev(s, LineEdit.mode(s).hist)),\n # Down Arrow\n \"\\e[B\" => (s,o...)->(LineEdit.edit_move_down(s) || LineEdit.history_next(s, LineEdit.mode(s).hist))\n)\n\nfunction customize_keys(repl)\n repl.interface = REPL.setup_interface(repl; extra_repl_keymap = mykeys)\nend\n\natreplinit(customize_keys)","category":"page"},{"location":"stdlib/REPL/","page":"Julia REPL","title":"Julia REPL","text":"Users should refer to LineEdit.jl to discover the available actions on key input.","category":"page"},{"location":"stdlib/REPL/#Tab-completion","page":"Julia REPL","title":"Tab completion","text":"","category":"section"},{"location":"stdlib/REPL/","page":"Julia REPL","title":"Julia REPL","text":"In both the Julian and help modes of the REPL, one can enter the first few characters of a function or type and then press the tab key to get a list all matches:","category":"page"},{"location":"stdlib/REPL/","page":"Julia REPL","title":"Julia REPL","text":"julia> stri[TAB]\nstride strides string strip\n\njulia> Stri[TAB]\nStridedArray StridedMatrix StridedVecOrMat StridedVector String","category":"page"},{"location":"stdlib/REPL/","page":"Julia REPL","title":"Julia REPL","text":"The tab key can also be used to substitute LaTeX math symbols with their Unicode equivalents, and get a list of LaTeX matches as well:","category":"page"},{"location":"stdlib/REPL/","page":"Julia REPL","title":"Julia REPL","text":"julia> \\pi[TAB]\njulia> π\nπ = 3.1415926535897...\n\njulia> e\\_1[TAB] = [1,0]\njulia> e₁ = [1,0]\n2-element Array{Int64,1}:\n 1\n 0\n\njulia> e\\^1[TAB] = [1 0]\njulia> e¹ = [1 0]\n1×2 Array{Int64,2}:\n 1 0\n\njulia> \\sqrt[TAB]2 # √ is equivalent to the sqrt function\njulia> √2\n1.4142135623730951\n\njulia> \\hbar[TAB](h) = h / 2\\pi[TAB]\njulia> ħ(h) = h / 2π\nħ (generic function with 1 method)\n\njulia> \\h[TAB]\n\\hat \\hermitconjmatrix \\hkswarow \\hrectangle\n\\hatapprox \\hexagon \\hookleftarrow \\hrectangleblack\n\\hbar \\hexagonblack \\hookrightarrow \\hslash\n\\heartsuit \\hksearow \\house \\hspace\n\njulia> α=\"\\alpha[TAB]\" # LaTeX completion also works in strings\njulia> α=\"α\"","category":"page"},{"location":"stdlib/REPL/","page":"Julia REPL","title":"Julia REPL","text":"A full list of tab-completions can be found in the Unicode Input section of the manual.","category":"page"},{"location":"stdlib/REPL/","page":"Julia REPL","title":"Julia REPL","text":"Completion of paths works for strings and julia's shell mode:","category":"page"},{"location":"stdlib/REPL/","page":"Julia REPL","title":"Julia REPL","text":"julia> path=\"/[TAB]\"\n.dockerenv .juliabox/ boot/ etc/ lib/ media/ opt/ root/ sbin/ sys/ usr/\n.dockerinit bin/ dev/ home/ lib64/ mnt/ proc/ run/ srv/ tmp/ var/\nshell> /[TAB]\n.dockerenv .juliabox/ boot/ etc/ lib/ media/ opt/ root/ sbin/ sys/ usr/\n.dockerinit bin/ dev/ home/ lib64/ mnt/ proc/ run/ srv/ tmp/ var/","category":"page"},{"location":"stdlib/REPL/","page":"Julia REPL","title":"Julia REPL","text":"Tab completion can help with investigation of the available methods matching the input arguments:","category":"page"},{"location":"stdlib/REPL/","page":"Julia REPL","title":"Julia REPL","text":"julia> max([TAB] # All methods are displayed, not shown here due to size of the list\n\njulia> max([1, 2], [TAB] # All methods where `Vector{Int}` matches as first argument\nmax(x, y) in Base at operators.jl:215\nmax(a, b, c, xs...) in Base at operators.jl:281\n\njulia> max([1, 2], max(1, 2), [TAB] # All methods matching the arguments.\nmax(x, y) in Base at operators.jl:215\nmax(a, b, c, xs...) in Base at operators.jl:281","category":"page"},{"location":"stdlib/REPL/","page":"Julia REPL","title":"Julia REPL","text":"Keywords are also displayed in the suggested methods after ;, see below line where limit and keepempty are keyword arguments:","category":"page"},{"location":"stdlib/REPL/","page":"Julia REPL","title":"Julia REPL","text":"julia> split(\"1 1 1\", [TAB]\nsplit(str::AbstractString; limit, keepempty) in Base at strings/util.jl:302\nsplit(str::T, splitter; limit, keepempty) where T<:AbstractString in Base at strings/util.jl:277","category":"page"},{"location":"stdlib/REPL/","page":"Julia REPL","title":"Julia REPL","text":"The completion of the methods uses type inference and can therefore see if the arguments match even if the arguments are output from functions. The function needs to be type stable for the completion to be able to remove non-matching methods.","category":"page"},{"location":"stdlib/REPL/","page":"Julia REPL","title":"Julia REPL","text":"Tab completion can also help completing fields:","category":"page"},{"location":"stdlib/REPL/","page":"Julia REPL","title":"Julia REPL","text":"julia> import UUIDs\n\njulia> UUIDs.uuid[TAB]\nuuid1 uuid4 uuid_version","category":"page"},{"location":"stdlib/REPL/","page":"Julia REPL","title":"Julia REPL","text":"Fields for output from functions can also be completed:","category":"page"},{"location":"stdlib/REPL/","page":"Julia REPL","title":"Julia REPL","text":"julia> split(\"\",\"\")[1].[TAB]\nlastindex offset string","category":"page"},{"location":"stdlib/REPL/","page":"Julia REPL","title":"Julia REPL","text":"The completion of fields for output from functions uses type inference, and it can only suggest fields if the function is type stable.","category":"page"},{"location":"stdlib/REPL/","page":"Julia REPL","title":"Julia REPL","text":"Dictionary keys can also be tab completed:","category":"page"},{"location":"stdlib/REPL/","page":"Julia REPL","title":"Julia REPL","text":"julia> foo = Dict(\"qwer1\"=>1, \"qwer2\"=>2, \"asdf\"=>3)\nDict{String,Int64} with 3 entries:\n \"qwer2\" => 2\n \"asdf\" => 3\n \"qwer1\" => 1\n\njulia> foo[\"q[TAB]\n\n\"qwer1\" \"qwer2\"\njulia> foo[\"qwer","category":"page"},{"location":"stdlib/REPL/#Customizing-Colors","page":"Julia REPL","title":"Customizing Colors","text":"","category":"section"},{"location":"stdlib/REPL/","page":"Julia REPL","title":"Julia REPL","text":"The colors used by Julia and the REPL can be customized, as well. To change the color of the Julia prompt you can add something like the following to your ~/.julia/config/startup.jl file, which is to be placed inside your home directory:","category":"page"},{"location":"stdlib/REPL/","page":"Julia REPL","title":"Julia REPL","text":"function customize_colors(repl)\n repl.prompt_color = Base.text_colors[:cyan]\nend\n\natreplinit(customize_colors)","category":"page"},{"location":"stdlib/REPL/","page":"Julia REPL","title":"Julia REPL","text":"The available color keys can be seen by typing Base.text_colors in the help mode of the REPL. In addition, the integers 0 to 255 can be used as color keys for terminals with 256 color support.","category":"page"},{"location":"stdlib/REPL/","page":"Julia REPL","title":"Julia REPL","text":"You can also change the colors for the help and shell prompts and input and answer text by setting the appropriate field of repl in the customize_colors function above (respectively, help_color, shell_color, input_color, and answer_color). For the latter two, be sure that the envcolors field is also set to false.","category":"page"},{"location":"stdlib/REPL/","page":"Julia REPL","title":"Julia REPL","text":"It is also possible to apply boldface formatting by using Base.text_colors[:bold] as a color. For instance, to print answers in boldface font, one can use the following as a ~/.julia/config/startup.jl:","category":"page"},{"location":"stdlib/REPL/","page":"Julia REPL","title":"Julia REPL","text":"function customize_colors(repl)\n repl.envcolors = false\n repl.answer_color = Base.text_colors[:bold]\nend\n\natreplinit(customize_colors)","category":"page"},{"location":"stdlib/REPL/","page":"Julia REPL","title":"Julia REPL","text":"You can also customize the color used to render warning and informational messages by setting the appropriate environment variables. For instance, to render error, warning, and informational messages respectively in magenta, yellow, and cyan you can add the following to your ~/.julia/config/startup.jl file:","category":"page"},{"location":"stdlib/REPL/","page":"Julia REPL","title":"Julia REPL","text":"ENV[\"JULIA_ERROR_COLOR\"] = :magenta\nENV[\"JULIA_WARN_COLOR\"] = :yellow\nENV[\"JULIA_INFO_COLOR\"] = :cyan","category":"page"},{"location":"stdlib/REPL/#TerminalMenus","page":"Julia REPL","title":"TerminalMenus","text":"","category":"section"},{"location":"stdlib/REPL/","page":"Julia REPL","title":"Julia REPL","text":"TerminalMenus is a submodule of the Julia REPL and enables small, low-profile interactive menus in the terminal.","category":"page"},{"location":"stdlib/REPL/#Examples","page":"Julia REPL","title":"Examples","text":"","category":"section"},{"location":"stdlib/REPL/","page":"Julia REPL","title":"Julia REPL","text":"import REPL\nusing REPL.TerminalMenus\n\noptions = [\"apple\", \"orange\", \"grape\", \"strawberry\",\n \"blueberry\", \"peach\", \"lemon\", \"lime\"]\n","category":"page"},{"location":"stdlib/REPL/#RadioMenu","page":"Julia REPL","title":"RadioMenu","text":"","category":"section"},{"location":"stdlib/REPL/","page":"Julia REPL","title":"Julia REPL","text":"The RadioMenu allows the user to select one option from the list. The request function displays the interactive menu and returns the index of the selected choice. If a user presses 'q' or ctrl-c, request will return a -1.","category":"page"},{"location":"stdlib/REPL/","page":"Julia REPL","title":"Julia REPL","text":"# `pagesize` is the number of items to be displayed at a time.\n# The UI will scroll if the number of options is greater\n# than the `pagesize`\nmenu = RadioMenu(options, pagesize=4)\n\n# `request` displays the menu and returns the index after the\n# user has selected a choice\nchoice = request(\"Choose your favorite fruit:\", menu)\n\nif choice != -1\n println(\"Your favorite fruit is \", options[choice], \"!\")\nelse\n println(\"Menu canceled.\")\nend\n","category":"page"},{"location":"stdlib/REPL/","page":"Julia REPL","title":"Julia REPL","text":"Output:","category":"page"},{"location":"stdlib/REPL/","page":"Julia REPL","title":"Julia REPL","text":"Choose your favorite fruit:\n^ grape\n strawberry\n > blueberry\nv peach\nYour favorite fruit is blueberry!","category":"page"},{"location":"stdlib/REPL/#MultiSelectMenu","page":"Julia REPL","title":"MultiSelectMenu","text":"","category":"section"},{"location":"stdlib/REPL/","page":"Julia REPL","title":"Julia REPL","text":"The MultiSelectMenu allows users to select many choices from a list.","category":"page"},{"location":"stdlib/REPL/","page":"Julia REPL","title":"Julia REPL","text":"# here we use the default `pagesize` 10\nmenu = MultiSelectMenu(options)\n\n# `request` returns a `Set` of selected indices\n# if the menu us canceled (ctrl-c or q), return an empty set\nchoices = request(\"Select the fruits you like:\", menu)\n\nif length(choices) > 0\n println(\"You like the following fruits:\")\n for i in choices\n println(\" - \", options[i])\n end\nelse\n println(\"Menu canceled.\")\nend","category":"page"},{"location":"stdlib/REPL/","page":"Julia REPL","title":"Julia REPL","text":"Output:","category":"page"},{"location":"stdlib/REPL/","page":"Julia REPL","title":"Julia REPL","text":"Select the fruits you like:\n[press: d=done, a=all, n=none]\n [ ] apple\n > [X] orange\n [X] grape\n [ ] strawberry\n [ ] blueberry\n [X] peach\n [ ] lemon\n [ ] lime\nYou like the following fruits:\n - orange\n - grape\n - peach","category":"page"},{"location":"stdlib/REPL/#Customization-/-Configuration","page":"Julia REPL","title":"Customization / Configuration","text":"","category":"section"},{"location":"stdlib/REPL/#ConfiguredMenu-subtypes","page":"Julia REPL","title":"ConfiguredMenu subtypes","text":"","category":"section"},{"location":"stdlib/REPL/","page":"Julia REPL","title":"Julia REPL","text":"Starting with Julia 1.6, the recommended way to configure menus is via the constructor. For instance, the default multiple-selection menu","category":"page"},{"location":"stdlib/REPL/","page":"Julia REPL","title":"Julia REPL","text":"julia> menu = MultiSelectMenu(options, pagesize=5);\n\njulia> request(menu) # ASCII is used by default\n[press: d=done, a=all, n=none]\n [ ] apple\n [X] orange\n [ ] grape\n > [X] strawberry\nv [ ] blueberry","category":"page"},{"location":"stdlib/REPL/","page":"Julia REPL","title":"Julia REPL","text":"can instead be rendered with Unicode selection and navigation characters with","category":"page"},{"location":"stdlib/REPL/","page":"Julia REPL","title":"Julia REPL","text":"julia> menu = MultiSelectMenu(options, pagesize=5, charset=:unicode);\n\njulia> request(menu)\n[press: d=done, a=all, n=none]\n ⬚ apple\n ✓ orange\n ⬚ grape\n → ✓ strawberry\n↓ ⬚ blueberry","category":"page"},{"location":"stdlib/REPL/","page":"Julia REPL","title":"Julia REPL","text":"More fine-grained configuration is also possible:","category":"page"},{"location":"stdlib/REPL/","page":"Julia REPL","title":"Julia REPL","text":"julia> menu = MultiSelectMenu(options, pagesize=5, charset=:unicode, checked=\"YEP!\", unchecked=\"NOPE\", cursor='⧐');\n\njulia> request(menu)\njulia> request(menu)\n[press: d=done, a=all, n=none]\n NOPE apple\n YEP! orange\n NOPE grape\n ⧐ YEP! strawberry\n↓ NOPE blueberry","category":"page"},{"location":"stdlib/REPL/","page":"Julia REPL","title":"Julia REPL","text":"Aside from the overall charset option, for RadioMenu the configurable options are:","category":"page"},{"location":"stdlib/REPL/","page":"Julia REPL","title":"Julia REPL","text":"cursor::Char='>'|'→': character to use for cursor\nup_arrow::Char='^'|'↑': character to use for up arrow\ndown_arrow::Char='v'|'↓': character to use for down arrow\nupdown_arrow::Char='I'|'↕': character to use for up/down arrow in one-line page\nscroll_wrap::Bool=false: optionally wrap-around at the beginning/end of a menu\nctrl_c_interrupt::Bool=true: If false, return empty on ^C, if true throw InterruptException() on ^C","category":"page"},{"location":"stdlib/REPL/","page":"Julia REPL","title":"Julia REPL","text":"MultiSelectMenu adds:","category":"page"},{"location":"stdlib/REPL/","page":"Julia REPL","title":"Julia REPL","text":"checked::String=\"[X]\"|\"✓\": string to use for checked\nunchecked::String=\"[ ]\"|\"⬚\"): string to use for unchecked","category":"page"},{"location":"stdlib/REPL/","page":"Julia REPL","title":"Julia REPL","text":"You can create new menu types of your own. Types that are derived from TerminalMenus.ConfiguredMenu configure the menu options at construction time.","category":"page"},{"location":"stdlib/REPL/#Legacy-interface","page":"Julia REPL","title":"Legacy interface","text":"","category":"section"},{"location":"stdlib/REPL/","page":"Julia REPL","title":"Julia REPL","text":"Prior to Julia 1.6, and still supported throughout Julia 1.x, one can also configure menus by calling TerminalMenus.config().","category":"page"},{"location":"stdlib/REPL/#References","page":"Julia REPL","title":"References","text":"","category":"section"},{"location":"stdlib/REPL/#REPL","page":"Julia REPL","title":"REPL","text":"","category":"section"},{"location":"stdlib/REPL/","page":"Julia REPL","title":"Julia REPL","text":"Base.atreplinit","category":"page"},{"location":"stdlib/REPL/#Base.atreplinit","page":"Julia REPL","title":"Base.atreplinit","text":"atreplinit(f)\n\nRegister a one-argument function to be called before the REPL interface is initialized in interactive sessions; this is useful to customize the interface. The argument of f is the REPL object. This function should be called from within the .julia/config/startup.jl initialization file.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/REPL/#TerminalMenus-2","page":"Julia REPL","title":"TerminalMenus","text":"","category":"section"},{"location":"stdlib/REPL/#Configuration","page":"Julia REPL","title":"Configuration","text":"","category":"section"},{"location":"stdlib/REPL/","page":"Julia REPL","title":"Julia REPL","text":"REPL.TerminalMenus.Config\nREPL.TerminalMenus.MultiSelectConfig\nREPL.TerminalMenus.config","category":"page"},{"location":"stdlib/REPL/#REPL.TerminalMenus.Config","page":"Julia REPL","title":"REPL.TerminalMenus.Config","text":"Config(; scroll_wrap=false, ctrl_c_interrupt=true, charset=:ascii, cursor::Char, up_arrow::Char, down_arrow::Char)\n\nConfigure behavior for selection menus via keyword arguments:\n\nscroll_wrap, if true, causes the menu to wrap around when scrolling above the first or below the last entry\nctrl_c_interrupt, if true, throws an InterruptException if the user hits Ctrl-C during menu selection. If false, TerminalMenus.request will return the default result from TerminalMenus.selected.\ncharset affects the default values for cursor, up_arrow, and down_arrow, and can be :ascii or :unicode\ncursor is the character printed to indicate the option that will be chosen by hitting \"Enter.\" Defaults are '>' or '→', depending on charset.\nup_arrow is the character printed when the display does not include the first entry. Defaults are '^' or '↑', depending on charset.\ndown_arrow is the character printed when the display does not include the last entry. Defaults are 'v' or '↓', depending on charset.\n\nSubtypes of ConfiguredMenu will print cursor, up_arrow, and down_arrow automatically as needed, your writeline method should not print them.\n\ncompat: Julia 1.6\nConfig is available as of Julia 1.6. On older releases use the global CONFIG.\n\n\n\n\n\n","category":"type"},{"location":"stdlib/REPL/#REPL.TerminalMenus.MultiSelectConfig","page":"Julia REPL","title":"REPL.TerminalMenus.MultiSelectConfig","text":"MultiSelectConfig(; charset=:ascii, checked::String, unchecked::String, kwargs...)\n\nConfigure behavior for a multiple-selection menu via keyword arguments:\n\nchecked is the string to print when an option has been selected. Defaults are \"[X]\" or \"✓\", depending on charset.\nunchecked is the string to print when an option has not been selected. Defaults are \"[ ]\" or \"⬚\", depending on charset.\n\nAll other keyword arguments are as described for TerminalMenus.Config. checked and unchecked are not printed automatically, and should be printed by your writeline method.\n\ncompat: Julia 1.6\nMultiSelectConfig is available as of Julia 1.6. On older releases use the global CONFIG.\n\n\n\n\n\n","category":"type"},{"location":"stdlib/REPL/#REPL.TerminalMenus.config","page":"Julia REPL","title":"REPL.TerminalMenus.config","text":"config( )\n\nKeyword-only function to configure global menu parameters\n\nArguments\n\ncharset::Symbol=:na: ui characters to use (:ascii or :unicode); overridden by other arguments\ncursor::Char='>'|'→': character to use for cursor\nup_arrow::Char='^'|'↑': character to use for up arrow\ndown_arrow::Char='v'|'↓': character to use for down arrow\nchecked::String=\"[X]\"|\"✓\": string to use for checked\nunchecked::String=\"[ ]\"|\"⬚\"): string to use for unchecked\nscroll::Symbol=:nowrap: If :wrap wrap cursor around top and bottom, if :nowrap do not wrap cursor\nsupress_output::Bool=false: Ignored legacy argument, pass suppress_output as a keyword argument to request instead.\nctrl_c_interrupt::Bool=true: If false, return empty on ^C, if true throw InterruptException() on ^C\n\ncompat: Julia 1.6\nAs of Julia 1.6, config is deprecated. Use Config or MultiSelectConfig instead.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/REPL/#User-interaction","page":"Julia REPL","title":"User interaction","text":"","category":"section"},{"location":"stdlib/REPL/","page":"Julia REPL","title":"Julia REPL","text":"REPL.TerminalMenus.request","category":"page"},{"location":"stdlib/REPL/#REPL.TerminalMenus.request","page":"Julia REPL","title":"REPL.TerminalMenus.request","text":"request(m::AbstractMenu; cursor=1)\n\nDisplay the menu and enter interactive mode. cursor indicates the item number used for the initial cursor position. cursor can be either an Int or a RefValue{Int}. The latter is useful for observation and control of the cursor position from the outside.\n\nReturns selected(m).\n\ncompat: Julia 1.6\nThe cursor argument requires Julia 1.6 or later.\n\n\n\n\n\nrequest([term,] msg::AbstractString, m::AbstractMenu)\n\nShorthand for println(msg); request(m).\n\n\n\n\n\n","category":"function"},{"location":"stdlib/REPL/#AbstractMenu-extension-interface","page":"Julia REPL","title":"AbstractMenu extension interface","text":"","category":"section"},{"location":"stdlib/REPL/","page":"Julia REPL","title":"Julia REPL","text":"Any subtype of AbstractMenu must be mutable, and must contain the fields pagesize::Int and pageoffset::Int. Any subtype must also implement the following functions:","category":"page"},{"location":"stdlib/REPL/","page":"Julia REPL","title":"Julia REPL","text":"REPL.TerminalMenus.pick\nREPL.TerminalMenus.cancel\nREPL.TerminalMenus.writeline","category":"page"},{"location":"stdlib/REPL/#REPL.TerminalMenus.pick","page":"Julia REPL","title":"REPL.TerminalMenus.pick","text":"pick(m::AbstractMenu, cursor::Int)\n\nDefines what happens when a user presses the Enter key while the menu is open. If true is returned, request() will exit. cursor indexes the position of the selection.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/REPL/#REPL.TerminalMenus.cancel","page":"Julia REPL","title":"REPL.TerminalMenus.cancel","text":"cancel(m::AbstractMenu)\n\nDefine what happens when a user cancels ('q' or ctrl-c) a menu. request() will always exit after calling this function.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/REPL/#REPL.TerminalMenus.writeline","page":"Julia REPL","title":"REPL.TerminalMenus.writeline","text":"writeline(buf::IO, m::AbstractMenu, idx::Int, iscursor::Bool)\n\nWrite the option at index idx to buf. iscursor, if true, indicates that this item is at the current cursor position (the one that will be selected by hitting \"Enter\").\n\nIf m is a ConfiguredMenu, TerminalMenus will print the cursor indicator. Otherwise the callee is expected to handle such printing.\n\ncompat: Julia 1.6\nwriteline requires Julia 1.6 or higher.On older versions of Julia, this was writeLine(buf::IO, m::AbstractMenu, idx, iscursor::Bool) and m is assumed to be unconfigured. The selection and cursor indicators can be obtained from TerminalMenus.CONFIG.This older function is supported on all Julia 1.x versions but will be dropped in Julia 2.0.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/REPL/","page":"Julia REPL","title":"Julia REPL","text":"It must also implement either options or numoptions:","category":"page"},{"location":"stdlib/REPL/","page":"Julia REPL","title":"Julia REPL","text":"REPL.TerminalMenus.options\nREPL.TerminalMenus.numoptions","category":"page"},{"location":"stdlib/REPL/#REPL.TerminalMenus.options","page":"Julia REPL","title":"REPL.TerminalMenus.options","text":"options(m::AbstractMenu)\n\nReturn a list of strings to be displayed as options in the current page.\n\nAlternatively, implement numoptions, in which case options is not needed.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/REPL/#REPL.TerminalMenus.numoptions","page":"Julia REPL","title":"REPL.TerminalMenus.numoptions","text":"numoptions(m::AbstractMenu) -> Int\n\nReturn the number of options in menu m. Defaults to length(options(m)).\n\ncompat: Julia 1.6\nThis function requires Julia 1.6 or later.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/REPL/","page":"Julia REPL","title":"Julia REPL","text":"If the subtype does not have a field named selected, it must also implement","category":"page"},{"location":"stdlib/REPL/","page":"Julia REPL","title":"Julia REPL","text":"REPL.TerminalMenus.selected","category":"page"},{"location":"stdlib/REPL/#REPL.TerminalMenus.selected","page":"Julia REPL","title":"REPL.TerminalMenus.selected","text":"selected(m::AbstractMenu)\n\nReturn information about the user-selected option. By default it returns m.selected.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/REPL/","page":"Julia REPL","title":"Julia REPL","text":"The following are optional but can allow additional customization:","category":"page"},{"location":"stdlib/REPL/","page":"Julia REPL","title":"Julia REPL","text":"REPL.TerminalMenus.header\nREPL.TerminalMenus.keypress","category":"page"},{"location":"stdlib/REPL/#REPL.TerminalMenus.header","page":"Julia REPL","title":"REPL.TerminalMenus.header","text":"header(m::AbstractMenu) -> String\n\nReturns a header string to be printed above the menu. Defaults to \"\".\n\n\n\n\n\n","category":"function"},{"location":"stdlib/REPL/#REPL.TerminalMenus.keypress","page":"Julia REPL","title":"REPL.TerminalMenus.keypress","text":"keypress(m::AbstractMenu, i::UInt32) -> Bool\n\nHandle any non-standard keypress event. If true is returned, TerminalMenus.request will exit. Defaults to false.\n\n\n\n\n\n","category":"function"},{"location":"base/stacktraces/#堆栈跟踪","page":"堆栈跟踪","title":"堆栈跟踪","text":"","category":"section"},{"location":"base/stacktraces/","page":"堆栈跟踪","title":"堆栈跟踪","text":"Base.StackTraces.StackFrame\nBase.StackTraces.StackTrace\nBase.StackTraces.stacktrace","category":"page"},{"location":"base/stacktraces/#Base.StackTraces.StackFrame","page":"堆栈跟踪","title":"Base.StackTraces.StackFrame","text":"StackFrame\n\nStack information representing execution context, with the following fields:\n\nfunc::Symbol\nThe name of the function containing the execution context.\nlinfo::Union{Core.MethodInstance, CodeInfo, Nothing}\nThe MethodInstance containing the execution context (if it could be found).\nfile::Symbol\nThe path to the file containing the execution context.\nline::Int\nThe line number in the file containing the execution context.\nfrom_c::Bool\nTrue if the code is from C.\ninlined::Bool\nTrue if the code is from an inlined frame.\npointer::UInt64\nRepresentation of the pointer to the execution context as returned by backtrace.\n\n\n\n\n\n","category":"type"},{"location":"base/stacktraces/#Base.StackTraces.StackTrace","page":"堆栈跟踪","title":"Base.StackTraces.StackTrace","text":"StackTrace\n\nAn alias for Vector{StackFrame} provided for convenience; returned by calls to stacktrace.\n\n\n\n\n\n","category":"type"},{"location":"base/stacktraces/#Base.StackTraces.stacktrace","page":"堆栈跟踪","title":"Base.StackTraces.stacktrace","text":"stacktrace([trace::Vector{Ptr{Cvoid}},] [c_funcs::Bool=false]) -> StackTrace\n\nReturns a stack trace in the form of a vector of StackFrames. (By default stacktrace doesn't return C functions, but this can be enabled.) When called without specifying a trace, stacktrace first calls backtrace.\n\n\n\n\n\n","category":"function"},{"location":"base/stacktraces/","page":"堆栈跟踪","title":"堆栈跟踪","text":"Base.StackTraces 中以下方法和类型不会被导出,需要显式调用,例如 StackTraces.lookup(ptr)。","category":"page"},{"location":"base/stacktraces/","page":"堆栈跟踪","title":"堆栈跟踪","text":"Base.StackTraces.lookup\nBase.StackTraces.remove_frames!","category":"page"},{"location":"base/stacktraces/#Base.StackTraces.lookup","page":"堆栈跟踪","title":"Base.StackTraces.lookup","text":"lookup(pointer::Ptr{Cvoid}) -> Vector{StackFrame}\n\nGiven a pointer to an execution context (usually generated by a call to backtrace), looks up stack frame context information. Returns an array of frame information for all functions inlined at that point, innermost function first.\n\n\n\n\n\n","category":"function"},{"location":"base/stacktraces/#Base.StackTraces.remove_frames!","page":"堆栈跟踪","title":"Base.StackTraces.remove_frames!","text":"remove_frames!(stack::StackTrace, name::Symbol)\n\nTakes a StackTrace (a vector of StackFrames) and a function name (a Symbol) and removes the StackFrame specified by the function name from the StackTrace (also removing all frames above the specified function). Primarily used to remove StackTraces functions from the StackTrace prior to returning it.\n\n\n\n\n\nremove_frames!(stack::StackTrace, m::Module)\n\nReturns the StackTrace with all StackFrames from the provided Module removed.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/SparseArrays/#稀疏数组","page":"稀疏数组","title":"稀疏数组","text":"","category":"section"},{"location":"stdlib/SparseArrays/","page":"稀疏数组","title":"稀疏数组","text":"DocTestSetup = :(using SparseArrays, LinearAlgebra)","category":"page"},{"location":"stdlib/SparseArrays/","page":"稀疏数组","title":"稀疏数组","text":"Julia 在 SparseArrays 标准库模块中提供了对稀疏向量和稀疏矩阵的支持。与稠密数组相比,包含足够多零值的稀疏数组在以特殊的数据结构存储时可以节省大量的空间和运算时间。","category":"page"},{"location":"stdlib/SparseArrays/#man-csc","page":"稀疏数组","title":"压缩稀疏列(CSC)稀疏矩阵存储","text":"","category":"section"},{"location":"stdlib/SparseArrays/","page":"稀疏数组","title":"稀疏数组","text":"在 Julia 中,稀疏矩阵是按照压缩稀疏列(CSC)格式存储的。Julia 稀疏矩阵具有 SparseMatrixCSC{Tv,Ti} 类型,其中 Tv 是存储值的类型,Ti 是存储列指针和行索引的整型类型。SparseMatrixCSC 的内部表示如下所示:","category":"page"},{"location":"stdlib/SparseArrays/","page":"稀疏数组","title":"稀疏数组","text":"struct SparseMatrixCSC{Tv,Ti<:Integer} <: AbstractSparseMatrixCSC{Tv,Ti}\n m::Int # Number of rows\n n::Int # Number of columns\n colptr::Vector{Ti} # Column j is in colptr[j]:(colptr[j+1]-1)\n rowval::Vector{Ti} # Row indices of stored values\n nzval::Vector{Tv} # Stored values, typically nonzeros\nend","category":"page"},{"location":"stdlib/SparseArrays/","page":"稀疏数组","title":"稀疏数组","text":"压缩稀疏列存储格式使得访问稀疏矩阵的列元素非常简单快速,而访问稀疏矩阵的行会非常缓慢。在 CSC 稀疏矩阵中执行类似插入新元素的操作也会非常慢。这是由于在稀疏矩阵中插入新元素时,在插入点之后的所有元素都要向后移动一位。","category":"page"},{"location":"stdlib/SparseArrays/","page":"稀疏数组","title":"稀疏数组","text":"All operations on sparse matrices are carefully implemented to exploit the CSC data structure for performance, and to avoid expensive operations.","category":"page"},{"location":"stdlib/SparseArrays/","page":"稀疏数组","title":"稀疏数组","text":"如果你有来自不同应用或库的 CSC 格式数据,并且想要将它导入 Julia,确保使用基于 1 的索引。每个列中的行索引都要是有序的。如果你的 SparseMatrixCSC 对象包含无序的行索引,一个快速将它们排序的方法是做一次二重转置。","category":"page"},{"location":"stdlib/SparseArrays/","page":"稀疏数组","title":"稀疏数组","text":"In some applications, it is convenient to store explicit zero values in a SparseMatrixCSC. These are accepted by functions in Base (but there is no guarantee that they will be preserved in mutating operations). Such explicitly stored zeros are treated as structural nonzeros by many routines. The nnz function returns the number of elements explicitly stored in the sparse data structure, including non-structural zeros. In order to count the exact number of numerical nonzeros, use count(!iszero, x), which inspects every stored element of a sparse matrix. dropzeros, and the in-place dropzeros!, can be used to remove stored zeros from the sparse matrix.","category":"page"},{"location":"stdlib/SparseArrays/","page":"稀疏数组","title":"稀疏数组","text":"julia> A = sparse([1, 1, 2, 3], [1, 3, 2, 3], [0, 1, 2, 0])\n3×3 SparseMatrixCSC{Int64, Int64} with 4 stored entries:\n 0 ⋅ 1\n ⋅ 2 ⋅\n ⋅ ⋅ 0\n\njulia> dropzeros(A)\n3×3 SparseMatrixCSC{Int64, Int64} with 2 stored entries:\n ⋅ ⋅ 1\n ⋅ 2 ⋅\n ⋅ ⋅ ⋅","category":"page"},{"location":"stdlib/SparseArrays/#稀疏向量储存","page":"稀疏数组","title":"稀疏向量储存","text":"","category":"section"},{"location":"stdlib/SparseArrays/","page":"稀疏数组","title":"稀疏数组","text":"Sparse vectors are stored in a close analog to compressed sparse column format for sparse matrices. In Julia, sparse vectors have the type SparseVector{Tv,Ti} where Tv is the type of the stored values and Ti the integer type for the indices. The internal representation is as follows:","category":"page"},{"location":"stdlib/SparseArrays/","page":"稀疏数组","title":"稀疏数组","text":"struct SparseVector{Tv,Ti<:Integer} <: AbstractSparseVector{Tv,Ti}\n n::Int # Length of the sparse vector\n nzind::Vector{Ti} # Indices of stored values\n nzval::Vector{Tv} # Stored values, typically nonzeros\nend","category":"page"},{"location":"stdlib/SparseArrays/","page":"稀疏数组","title":"稀疏数组","text":"对于 SparseMatrixCSC, SparseVector 类型也能包含显示存储的,零值。(见 稀疏矩阵存储。)","category":"page"},{"location":"stdlib/SparseArrays/#稀疏向量与矩阵构造函数","page":"稀疏数组","title":"稀疏向量与矩阵构造函数","text":"","category":"section"},{"location":"stdlib/SparseArrays/","page":"稀疏数组","title":"稀疏数组","text":"创建一个稀疏矩阵的最简单的方法是使用一个与 Julia 提供的用来处理稠密矩阵的zeros 等价的函数。要产生一个稀疏矩阵,你可以用同样的名字加上 sp 前缀:","category":"page"},{"location":"stdlib/SparseArrays/","page":"稀疏数组","title":"稀疏数组","text":"julia> spzeros(3)\n3-element SparseVector{Float64, Int64} with 0 stored entries","category":"page"},{"location":"stdlib/SparseArrays/","page":"稀疏数组","title":"稀疏数组","text":"sparse 函数通常是一个构建稀疏矩阵的便捷方法。例如,要构建一个稀疏矩阵,我们可以输入一个列索引向量 I,一个行索引向量 J,一个储存值的向量 V(这也叫作 COO(坐标) 格式)。 然后 sparse(I,J,V) 创建一个满足 S[I[k], J[k]] = V[k] 的稀疏矩阵。等价的稀疏向量构建函数是 sparsevec,它接受(行)索引向量 I 和储存值的向量 V 并创建一个满足 R[I[k]] = V[k] 的向量 R。","category":"page"},{"location":"stdlib/SparseArrays/","page":"稀疏数组","title":"稀疏数组","text":"julia> I = [1, 4, 3, 5]; J = [4, 7, 18, 9]; V = [1, 2, -5, 3];\n\njulia> S = sparse(I,J,V)\n5×18 SparseMatrixCSC{Int64, Int64} with 4 stored entries:\n⠀⠈⠀⡀⠀⠀⠀⠀⠠\n⠀⠀⠀⠀⠁⠀⠀⠀⠀\n\njulia> R = sparsevec(I,V)\n5-element SparseVector{Int64, Int64} with 4 stored entries:\n [1] = 1\n [3] = -5\n [4] = 2\n [5] = 3","category":"page"},{"location":"stdlib/SparseArrays/","page":"稀疏数组","title":"稀疏数组","text":"The inverse of the sparse and sparsevec functions is findnz, which retrieves the inputs used to create the sparse array. findall(!iszero, x) returns the cartesian indices of non-zero entries in x (including stored entries equal to zero).","category":"page"},{"location":"stdlib/SparseArrays/","page":"稀疏数组","title":"稀疏数组","text":"julia> findnz(S)\n([1, 4, 5, 3], [4, 7, 9, 18], [1, 2, 3, -5])\n\njulia> findall(!iszero, S)\n4-element Vector{CartesianIndex{2}}:\n CartesianIndex(1, 4)\n CartesianIndex(4, 7)\n CartesianIndex(5, 9)\n CartesianIndex(3, 18)\n\njulia> findnz(R)\n([1, 3, 4, 5], [1, -5, 2, 3])\n\njulia> findall(!iszero, R)\n4-element Vector{Int64}:\n 1\n 3\n 4\n 5","category":"page"},{"location":"stdlib/SparseArrays/","page":"稀疏数组","title":"稀疏数组","text":"另一个创建稀疏数组的方法是使用 sparse 函数将一个稠密数组转化为稀疏数组:","category":"page"},{"location":"stdlib/SparseArrays/","page":"稀疏数组","title":"稀疏数组","text":"julia> sparse(Matrix(1.0I, 5, 5))\n5×5 SparseMatrixCSC{Float64, Int64} with 5 stored entries:\n 1.0 ⋅ ⋅ ⋅ ⋅\n ⋅ 1.0 ⋅ ⋅ ⋅\n ⋅ ⋅ 1.0 ⋅ ⋅\n ⋅ ⋅ ⋅ 1.0 ⋅\n ⋅ ⋅ ⋅ ⋅ 1.0\n\njulia> sparse([1.0, 0.0, 1.0])\n3-element SparseVector{Float64, Int64} with 2 stored entries:\n [1] = 1.0\n [3] = 1.0","category":"page"},{"location":"stdlib/SparseArrays/","page":"稀疏数组","title":"稀疏数组","text":"You can go in the other direction using the Array constructor. The issparse function can be used to query if a matrix is sparse.","category":"page"},{"location":"stdlib/SparseArrays/","page":"稀疏数组","title":"稀疏数组","text":"julia> issparse(spzeros(5))\ntrue","category":"page"},{"location":"stdlib/SparseArrays/#稀疏矩阵的操作","page":"稀疏数组","title":"稀疏矩阵的操作","text":"","category":"section"},{"location":"stdlib/SparseArrays/","page":"稀疏数组","title":"稀疏数组","text":"Arithmetic operations on sparse matrices also work as they do on dense matrices. Indexing of, assignment into, and concatenation of sparse matrices work in the same way as dense matrices. Indexing operations, especially assignment, are expensive, when carried out one element at a time. In many cases it may be better to convert the sparse matrix into (I,J,V) format using findnz, manipulate the values or the structure in the dense vectors (I,J,V), and then reconstruct the sparse matrix.","category":"page"},{"location":"stdlib/SparseArrays/#Correspondence-of-dense-and-sparse-methods","page":"稀疏数组","title":"Correspondence of dense and sparse methods","text":"","category":"section"},{"location":"stdlib/SparseArrays/","page":"稀疏数组","title":"稀疏数组","text":"The following table gives a correspondence between built-in methods on sparse matrices and their corresponding methods on dense matrix types. In general, methods that generate sparse matrices differ from their dense counterparts in that the resulting matrix follows the same sparsity pattern as a given sparse matrix S, or that the resulting sparse matrix has density d, i.e. each matrix element has a probability d of being non-zero.","category":"page"},{"location":"stdlib/SparseArrays/","page":"稀疏数组","title":"稀疏数组","text":"Details can be found in the Sparse Vectors and Matrices section of the standard library reference.","category":"page"},{"location":"stdlib/SparseArrays/","page":"稀疏数组","title":"稀疏数组","text":"构造函数 密度 说明\nspzeros(m,n) zeros(m,n) Creates a m-by-n matrix of zeros. (spzeros(m,n) is empty.)\nsparse(I,n,n) Matrix(I,n,n) Creates a n-by-n identity matrix.\nsparse(A) Array(S) Interconverts between dense and sparse formats.\nsprand(m,n,d) rand(m,n) Creates a m-by-n random matrix (of density d) with iid non-zero elements distributed uniformly on the half-open interval 0 1).\nsprandn(m,n,d) randn(m,n) Creates a m-by-n random matrix (of density d) with iid non-zero elements distributed according to the standard normal (Gaussian) distribution.\nsprandn(rng,m,n,d) randn(rng,m,n) Creates a m-by-n random matrix (of density d) with iid non-zero elements generated with the rng random number generator","category":"page"},{"location":"stdlib/SparseArrays/#stdlib-sparse-arrays","page":"稀疏数组","title":"Sparse Arrays","text":"","category":"section"},{"location":"stdlib/SparseArrays/","page":"稀疏数组","title":"稀疏数组","text":"SparseArrays.AbstractSparseArray\nSparseArrays.AbstractSparseVector\nSparseArrays.AbstractSparseMatrix\nSparseArrays.SparseVector\nSparseArrays.SparseMatrixCSC\nSparseArrays.sparse\nSparseArrays.sparsevec\nSparseArrays.issparse\nSparseArrays.nnz\nSparseArrays.findnz\nSparseArrays.spzeros\nSparseArrays.spdiagm\nSparseArrays.blockdiag\nSparseArrays.sprand\nSparseArrays.sprandn\nSparseArrays.nonzeros\nSparseArrays.rowvals\nSparseArrays.nzrange\nSparseArrays.droptol!\nSparseArrays.dropzeros!\nSparseArrays.dropzeros\nSparseArrays.permute\npermute!{Tv, Ti, Tp <: Integer, Tq <: Integer}(::SparseMatrixCSC{Tv,Ti}, ::SparseMatrixCSC{Tv,Ti}, ::AbstractArray{Tp,1}, ::AbstractArray{Tq,1})","category":"page"},{"location":"stdlib/SparseArrays/#SparseArrays.AbstractSparseArray","page":"稀疏数组","title":"SparseArrays.AbstractSparseArray","text":"AbstractSparseArray{Tv,Ti,N}\n\nSupertype for N-dimensional sparse arrays (or array-like types) with elements of type Tv and index type Ti. SparseMatrixCSC, SparseVector and SuiteSparse.CHOLMOD.Sparse are subtypes of this.\n\n\n\n\n\n","category":"type"},{"location":"stdlib/SparseArrays/#SparseArrays.AbstractSparseVector","page":"稀疏数组","title":"SparseArrays.AbstractSparseVector","text":"AbstractSparseVector{Tv,Ti}\n\nSupertype for one-dimensional sparse arrays (or array-like types) with elements of type Tv and index type Ti. Alias for AbstractSparseArray{Tv,Ti,1}.\n\n\n\n\n\n","category":"type"},{"location":"stdlib/SparseArrays/#SparseArrays.AbstractSparseMatrix","page":"稀疏数组","title":"SparseArrays.AbstractSparseMatrix","text":"AbstractSparseMatrix{Tv,Ti}\n\nSupertype for two-dimensional sparse arrays (or array-like types) with elements of type Tv and index type Ti. Alias for AbstractSparseArray{Tv,Ti,2}.\n\n\n\n\n\n","category":"type"},{"location":"stdlib/SparseArrays/#SparseArrays.SparseVector","page":"稀疏数组","title":"SparseArrays.SparseVector","text":"SparseVector{Tv,Ti<:Integer} <: AbstractSparseVector{Tv,Ti}\n\nVector type for storing sparse vectors.\n\n\n\n\n\n","category":"type"},{"location":"stdlib/SparseArrays/#SparseArrays.SparseMatrixCSC","page":"稀疏数组","title":"SparseArrays.SparseMatrixCSC","text":"SparseMatrixCSC{Tv,Ti<:Integer} <: AbstractSparseMatrixCSC{Tv,Ti}\n\nMatrix type for storing sparse matrices in the Compressed Sparse Column format. The standard way of constructing SparseMatrixCSC is through the sparse function. See also spzeros, spdiagm and sprand.\n\n\n\n\n\n","category":"type"},{"location":"stdlib/SparseArrays/#SparseArrays.sparse","page":"稀疏数组","title":"SparseArrays.sparse","text":"sparse(A)\n\nConvert an AbstractMatrix A into a sparse matrix.\n\nExamples\n\njulia> A = Matrix(1.0I, 3, 3)\n3×3 Matrix{Float64}:\n 1.0 0.0 0.0\n 0.0 1.0 0.0\n 0.0 0.0 1.0\n\njulia> sparse(A)\n3×3 SparseMatrixCSC{Float64, Int64} with 3 stored entries:\n 1.0 ⋅ ⋅\n ⋅ 1.0 ⋅\n ⋅ ⋅ 1.0\n\n\n\n\n\nsparse(I, J, V,[ m, n, combine])\n\nCreate a sparse matrix S of dimensions m x n such that S[I[k], J[k]] = V[k]. The combine function is used to combine duplicates. If m and n are not specified, they are set to maximum(I) and maximum(J) respectively. If the combine function is not supplied, combine defaults to + unless the elements of V are Booleans in which case combine defaults to |. All elements of I must satisfy 1 <= I[k] <= m, and all elements of J must satisfy 1 <= J[k] <= n. Numerical zeros in (I, J, V) are retained as structural nonzeros; to drop numerical zeros, use dropzeros!.\n\nFor additional documentation and an expert driver, see SparseArrays.sparse!.\n\nExamples\n\njulia> Is = [1; 2; 3];\n\njulia> Js = [1; 2; 3];\n\njulia> Vs = [1; 2; 3];\n\njulia> sparse(Is, Js, Vs)\n3×3 SparseMatrixCSC{Int64, Int64} with 3 stored entries:\n 1 ⋅ ⋅\n ⋅ 2 ⋅\n ⋅ ⋅ 3\n\n\n\n\n\n","category":"function"},{"location":"stdlib/SparseArrays/#SparseArrays.sparsevec","page":"稀疏数组","title":"SparseArrays.sparsevec","text":"sparsevec(I, V, [m, combine])\n\nCreate a sparse vector S of length m such that S[I[k]] = V[k]. Duplicates are combined using the combine function, which defaults to + if no combine argument is provided, unless the elements of V are Booleans in which case combine defaults to |.\n\nExamples\n\njulia> II = [1, 3, 3, 5]; V = [0.1, 0.2, 0.3, 0.2];\n\njulia> sparsevec(II, V)\n5-element SparseVector{Float64, Int64} with 3 stored entries:\n [1] = 0.1\n [3] = 0.5\n [5] = 0.2\n\njulia> sparsevec(II, V, 8, -)\n8-element SparseVector{Float64, Int64} with 3 stored entries:\n [1] = 0.1\n [3] = -0.1\n [5] = 0.2\n\njulia> sparsevec([1, 3, 1, 2, 2], [true, true, false, false, false])\n3-element SparseVector{Bool, Int64} with 3 stored entries:\n [1] = 1\n [2] = 0\n [3] = 1\n\n\n\n\n\nsparsevec(d::Dict, [m])\n\nCreate a sparse vector of length m where the nonzero indices are keys from the dictionary, and the nonzero values are the values from the dictionary.\n\nExamples\n\njulia> sparsevec(Dict(1 => 3, 2 => 2))\n2-element SparseVector{Int64, Int64} with 2 stored entries:\n [1] = 3\n [2] = 2\n\n\n\n\n\nsparsevec(A)\n\nConvert a vector A into a sparse vector of length m.\n\nExamples\n\njulia> sparsevec([1.0, 2.0, 0.0, 0.0, 3.0, 0.0])\n6-element SparseVector{Float64, Int64} with 3 stored entries:\n [1] = 1.0\n [2] = 2.0\n [5] = 3.0\n\n\n\n\n\n","category":"function"},{"location":"stdlib/SparseArrays/#SparseArrays.issparse","page":"稀疏数组","title":"SparseArrays.issparse","text":"issparse(S)\n\nReturns true if S is sparse, and false otherwise.\n\nExamples\n\njulia> sv = sparsevec([1, 4], [2.3, 2.2], 10)\n10-element SparseVector{Float64, Int64} with 2 stored entries:\n [1 ] = 2.3\n [4 ] = 2.2\n\njulia> issparse(sv)\ntrue\n\njulia> issparse(Array(sv))\nfalse\n\n\n\n\n\n","category":"function"},{"location":"stdlib/SparseArrays/#SparseArrays.nnz","page":"稀疏数组","title":"SparseArrays.nnz","text":"nnz(A)\n\nReturns the number of stored (filled) elements in a sparse array.\n\nExamples\n\njulia> A = sparse(2I, 3, 3)\n3×3 SparseMatrixCSC{Int64, Int64} with 3 stored entries:\n 2 ⋅ ⋅\n ⋅ 2 ⋅\n ⋅ ⋅ 2\n\njulia> nnz(A)\n3\n\n\n\n\n\n","category":"function"},{"location":"stdlib/SparseArrays/#SparseArrays.findnz","page":"稀疏数组","title":"SparseArrays.findnz","text":"findnz(A::SparseMatrixCSC)\n\nReturn a tuple (I, J, V) where I and J are the row and column indices of the stored (\"structurally non-zero\") values in sparse matrix A, and V is a vector of the values.\n\nExamples\n\njulia> A = sparse([1 2 0; 0 0 3; 0 4 0])\n3×3 SparseMatrixCSC{Int64, Int64} with 4 stored entries:\n 1 2 ⋅\n ⋅ ⋅ 3\n ⋅ 4 ⋅\n\njulia> findnz(A)\n([1, 1, 3, 2], [1, 2, 2, 3], [1, 2, 4, 3])\n\n\n\n\n\n","category":"function"},{"location":"stdlib/SparseArrays/#SparseArrays.spzeros","page":"稀疏数组","title":"SparseArrays.spzeros","text":"spzeros([type,]m[,n])\n\nCreate a sparse vector of length m or sparse matrix of size m x n. This sparse array will not contain any nonzero values. No storage will be allocated for nonzero values during construction. The type defaults to Float64 if not specified.\n\nExamples\n\njulia> spzeros(3, 3)\n3×3 SparseMatrixCSC{Float64, Int64} with 0 stored entries:\n ⋅ ⋅ ⋅\n ⋅ ⋅ ⋅\n ⋅ ⋅ ⋅\n\njulia> spzeros(Float32, 4)\n4-element SparseVector{Float32, Int64} with 0 stored entries\n\n\n\n\n\n","category":"function"},{"location":"stdlib/SparseArrays/#SparseArrays.spdiagm","page":"稀疏数组","title":"SparseArrays.spdiagm","text":"spdiagm(kv::Pair{<:Integer,<:AbstractVector}...)\nspdiagm(m::Integer, n::Integer, kv::Pair{<:Integer,<:AbstractVector}...)\n\nConstruct a sparse diagonal matrix from Pairs of vectors and diagonals. Each vector kv.second will be placed on the kv.first diagonal. By default, the matrix is square and its size is inferred from kv, but a non-square size m×n (padded with zeros as needed) can be specified by passing m,n as the first arguments.\n\nExamples\n\njulia> spdiagm(-1 => [1,2,3,4], 1 => [4,3,2,1])\n5×5 SparseMatrixCSC{Int64, Int64} with 8 stored entries:\n ⋅ 4 ⋅ ⋅ ⋅\n 1 ⋅ 3 ⋅ ⋅\n ⋅ 2 ⋅ 2 ⋅\n ⋅ ⋅ 3 ⋅ 1\n ⋅ ⋅ ⋅ 4 ⋅\n\n\n\n\n\nspdiagm(v::AbstractVector)\nspdiagm(m::Integer, n::Integer, v::AbstractVector)\n\nConstruct a sparse matrix with elements of the vector as diagonal elements. By default (no given m and n), the matrix is square and its size is given by length(v), but a non-square size m×n can be specified by passing m and n as the first arguments.\n\ncompat: Julia 1.6\nThese functions require at least Julia 1.6.\n\nExamples\n\njulia> spdiagm([1,2,3])\n3×3 SparseMatrixCSC{Int64, Int64} with 3 stored entries:\n 1 ⋅ ⋅\n ⋅ 2 ⋅\n ⋅ ⋅ 3\n\njulia> spdiagm(sparse([1,0,3]))\n3×3 SparseMatrixCSC{Int64, Int64} with 2 stored entries:\n 1 ⋅ ⋅\n ⋅ ⋅ ⋅\n ⋅ ⋅ 3\n\n\n\n\n\n","category":"function"},{"location":"stdlib/SparseArrays/#SparseArrays.blockdiag","page":"稀疏数组","title":"SparseArrays.blockdiag","text":"blockdiag(A...)\n\nConcatenate matrices block-diagonally. Currently only implemented for sparse matrices.\n\nExamples\n\njulia> blockdiag(sparse(2I, 3, 3), sparse(4I, 2, 2))\n5×5 SparseMatrixCSC{Int64, Int64} with 5 stored entries:\n 2 ⋅ ⋅ ⋅ ⋅\n ⋅ 2 ⋅ ⋅ ⋅\n ⋅ ⋅ 2 ⋅ ⋅\n ⋅ ⋅ ⋅ 4 ⋅\n ⋅ ⋅ ⋅ ⋅ 4\n\n\n\n\n\n","category":"function"},{"location":"stdlib/SparseArrays/#SparseArrays.sprand","page":"稀疏数组","title":"SparseArrays.sprand","text":"sprand([rng],[type],m,[n],p::AbstractFloat,[rfn])\n\nCreate a random length m sparse vector or m by n sparse matrix, in which the probability of any element being nonzero is independently given by p (and hence the mean density of nonzeros is also exactly p). Nonzero values are sampled from the distribution specified by rfn and have the type type. The uniform distribution is used in case rfn is not specified. The optional rng argument specifies a random number generator, see Random Numbers.\n\nExamples\n\njulia> sprand(Bool, 2, 2, 0.5)\n2×2 SparseMatrixCSC{Bool, Int64} with 2 stored entries:\n 1 1\n ⋅ ⋅\n\njulia> sprand(Float64, 3, 0.75)\n3-element SparseVector{Float64, Int64} with 2 stored entries:\n [1] = 0.795547\n [2] = 0.49425\n\n\n\n\n\n","category":"function"},{"location":"stdlib/SparseArrays/#SparseArrays.sprandn","page":"稀疏数组","title":"SparseArrays.sprandn","text":"sprandn([rng][,Type],m[,n],p::AbstractFloat)\n\nCreate a random sparse vector of length m or sparse matrix of size m by n with the specified (independent) probability p of any entry being nonzero, where nonzero values are sampled from the normal distribution. The optional rng argument specifies a random number generator, see Random Numbers.\n\ncompat: Julia 1.1\nSpecifying the output element type Type requires at least Julia 1.1.\n\nExamples\n\njulia> sprandn(2, 2, 0.75)\n2×2 SparseMatrixCSC{Float64, Int64} with 3 stored entries:\n -1.20577 ⋅\n 0.311817 -0.234641\n\n\n\n\n\n","category":"function"},{"location":"stdlib/SparseArrays/#SparseArrays.nonzeros","page":"稀疏数组","title":"SparseArrays.nonzeros","text":"nonzeros(A)\n\nReturn a vector of the structural nonzero values in sparse array A. This includes zeros that are explicitly stored in the sparse array. The returned vector points directly to the internal nonzero storage of A, and any modifications to the returned vector will mutate A as well. See rowvals and nzrange.\n\nExamples\n\njulia> A = sparse(2I, 3, 3)\n3×3 SparseMatrixCSC{Int64, Int64} with 3 stored entries:\n 2 ⋅ ⋅\n ⋅ 2 ⋅\n ⋅ ⋅ 2\n\njulia> nonzeros(A)\n3-element Vector{Int64}:\n 2\n 2\n 2\n\n\n\n\n\n","category":"function"},{"location":"stdlib/SparseArrays/#SparseArrays.rowvals","page":"稀疏数组","title":"SparseArrays.rowvals","text":"rowvals(A::AbstractSparseMatrixCSC)\n\nReturn a vector of the row indices of A. Any modifications to the returned vector will mutate A as well. Providing access to how the row indices are stored internally can be useful in conjunction with iterating over structural nonzero values. See also nonzeros and nzrange.\n\nExamples\n\njulia> A = sparse(2I, 3, 3)\n3×3 SparseMatrixCSC{Int64, Int64} with 3 stored entries:\n 2 ⋅ ⋅\n ⋅ 2 ⋅\n ⋅ ⋅ 2\n\njulia> rowvals(A)\n3-element Vector{Int64}:\n 1\n 2\n 3\n\n\n\n\n\n","category":"function"},{"location":"stdlib/SparseArrays/#SparseArrays.nzrange","page":"稀疏数组","title":"SparseArrays.nzrange","text":"nzrange(A::AbstractSparseMatrixCSC, col::Integer)\n\nReturn the range of indices to the structural nonzero values of a sparse matrix column. In conjunction with nonzeros and rowvals, this allows for convenient iterating over a sparse matrix :\n\nA = sparse(I,J,V)\nrows = rowvals(A)\nvals = nonzeros(A)\nm, n = size(A)\nfor j = 1:n\n for i in nzrange(A, j)\n row = rows[i]\n val = vals[i]\n # perform sparse wizardry...\n end\nend\n\n\n\n\n\nnzrange(x::SparseVectorUnion, col)\n\nGive the range of indices to the structural nonzero values of a sparse vector. The column index col is ignored (assumed to be 1).\n\n\n\n\n\n","category":"function"},{"location":"stdlib/SparseArrays/#SparseArrays.droptol!","page":"稀疏数组","title":"SparseArrays.droptol!","text":"droptol!(A::AbstractSparseMatrixCSC, tol)\n\nRemoves stored values from A whose absolute value is less than or equal to tol.\n\n\n\n\n\ndroptol!(x::SparseVector, tol)\n\nRemoves stored values from x whose absolute value is less than or equal to tol.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/SparseArrays/#SparseArrays.dropzeros!","page":"稀疏数组","title":"SparseArrays.dropzeros!","text":"dropzeros!(A::AbstractSparseMatrixCSC;)\n\nRemoves stored numerical zeros from A.\n\nFor an out-of-place version, see dropzeros. For algorithmic information, see fkeep!.\n\n\n\n\n\ndropzeros!(x::SparseVector)\n\nRemoves stored numerical zeros from x.\n\nFor an out-of-place version, see dropzeros. For algorithmic information, see fkeep!.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/SparseArrays/#SparseArrays.dropzeros","page":"稀疏数组","title":"SparseArrays.dropzeros","text":"dropzeros(A::AbstractSparseMatrixCSC;)\n\nGenerates a copy of A and removes stored numerical zeros from that copy.\n\nFor an in-place version and algorithmic information, see dropzeros!.\n\nExamples\n\njulia> A = sparse([1, 2, 3], [1, 2, 3], [1.0, 0.0, 1.0])\n3×3 SparseMatrixCSC{Float64, Int64} with 3 stored entries:\n 1.0 ⋅ ⋅\n ⋅ 0.0 ⋅\n ⋅ ⋅ 1.0\n\njulia> dropzeros(A)\n3×3 SparseMatrixCSC{Float64, Int64} with 2 stored entries:\n 1.0 ⋅ ⋅\n ⋅ ⋅ ⋅\n ⋅ ⋅ 1.0\n\n\n\n\n\ndropzeros(x::SparseVector)\n\nGenerates a copy of x and removes numerical zeros from that copy.\n\nFor an in-place version and algorithmic information, see dropzeros!.\n\nExamples\n\njulia> A = sparsevec([1, 2, 3], [1.0, 0.0, 1.0])\n3-element SparseVector{Float64, Int64} with 3 stored entries:\n [1] = 1.0\n [2] = 0.0\n [3] = 1.0\n\njulia> dropzeros(A)\n3-element SparseVector{Float64, Int64} with 2 stored entries:\n [1] = 1.0\n [3] = 1.0\n\n\n\n\n\n","category":"function"},{"location":"stdlib/SparseArrays/#SparseArrays.permute","page":"稀疏数组","title":"SparseArrays.permute","text":"permute(A::AbstractSparseMatrixCSC{Tv,Ti}, p::AbstractVector{<:Integer},\n q::AbstractVector{<:Integer}) where {Tv,Ti}\n\nBilaterally permute A, returning PAQ (A[p,q]). Column-permutation q's length must match A's column count (length(q) == size(A, 2)). Row-permutation p's length must match A's row count (length(p) == size(A, 1)).\n\nFor expert drivers and additional information, see permute!.\n\nExamples\n\njulia> A = spdiagm(0 => [1, 2, 3, 4], 1 => [5, 6, 7])\n4×4 SparseMatrixCSC{Int64, Int64} with 7 stored entries:\n 1 5 ⋅ ⋅\n ⋅ 2 6 ⋅\n ⋅ ⋅ 3 7\n ⋅ ⋅ ⋅ 4\n\njulia> permute(A, [4, 3, 2, 1], [1, 2, 3, 4])\n4×4 SparseMatrixCSC{Int64, Int64} with 7 stored entries:\n ⋅ ⋅ ⋅ 4\n ⋅ ⋅ 3 7\n ⋅ 2 6 ⋅\n 1 5 ⋅ ⋅\n\njulia> permute(A, [1, 2, 3, 4], [4, 3, 2, 1])\n4×4 SparseMatrixCSC{Int64, Int64} with 7 stored entries:\n ⋅ ⋅ 5 1\n ⋅ 6 2 ⋅\n 7 3 ⋅ ⋅\n 4 ⋅ ⋅ ⋅\n\n\n\n\n\n","category":"function"},{"location":"stdlib/SparseArrays/#Base.permute!-Union{Tuple{Tq}, Tuple{Tp}, Tuple{Ti}, Tuple{Tv}, Tuple{SparseMatrixCSC{Tv, Ti}, SparseMatrixCSC{Tv, Ti}, AbstractVector{Tp}, AbstractVector{Tq}}} where {Tv, Ti, Tp<:Integer, Tq<:Integer}","page":"稀疏数组","title":"Base.permute!","text":"permute!(X::AbstractSparseMatrixCSC{Tv,Ti}, A::AbstractSparseMatrixCSC{Tv,Ti},\n p::AbstractVector{<:Integer}, q::AbstractVector{<:Integer},\n [C::AbstractSparseMatrixCSC{Tv,Ti}]) where {Tv,Ti}\n\nBilaterally permute A, storing result PAQ (A[p,q]) in X. Stores intermediate result (AQ)^T (transpose(A[:,q])) in optional argument C if present. Requires that none of X, A, and, if present, C alias each other; to store result PAQ back into A, use the following method lacking X:\n\npermute!(A::AbstractSparseMatrixCSC{Tv,Ti}, p::AbstractVector{<:Integer},\n q::AbstractVector{<:Integer}[, C::AbstractSparseMatrixCSC{Tv,Ti},\n [workcolptr::Vector{Ti}]]) where {Tv,Ti}\n\nX's dimensions must match those of A (size(X, 1) == size(A, 1) and size(X, 2) == size(A, 2)), and X must have enough storage to accommodate all allocated entries in A (length(rowvals(X)) >= nnz(A) and length(nonzeros(X)) >= nnz(A)). Column-permutation q's length must match A's column count (length(q) == size(A, 2)). Row-permutation p's length must match A's row count (length(p) == size(A, 1)).\n\nC's dimensions must match those of transpose(A) (size(C, 1) == size(A, 2) and size(C, 2) == size(A, 1)), and C must have enough storage to accommodate all allocated entries in A (length(rowvals(C)) >= nnz(A) and length(nonzeros(C)) >= nnz(A)).\n\nFor additional (algorithmic) information, and for versions of these methods that forgo argument checking, see (unexported) parent methods unchecked_noalias_permute! and unchecked_aliasing_permute!.\n\nSee also permute.\n\n\n\n\n\n","category":"method"},{"location":"stdlib/SparseArrays/","page":"稀疏数组","title":"稀疏数组","text":"DocTestSetup = nothing","category":"page"},{"location":"manual/constructors/#man-constructors","page":"构造函数","title":"构造函数","text":"","category":"section"},{"location":"manual/constructors/","page":"构造函数","title":"构造函数","text":"构造函数 [1] 是用来创建新对象的函数 – 确切地说,它创建的是复合类型的实例。在 Julia 中,类型对象也同时充当构造函数的角色:可以用类名加参数元组的方式像函数调用一样来创建新实例。这一点在介绍复合类型(Composite Types)时已经大致谈过了。例如:","category":"page"},{"location":"manual/constructors/","page":"构造函数","title":"构造函数","text":"julia> struct Foo\n bar\n baz\n end\n\njulia> foo = Foo(1, 2)\nFoo(1, 2)\n\njulia> foo.bar\n1\n\njulia> foo.baz\n2","category":"page"},{"location":"manual/constructors/","page":"构造函数","title":"构造函数","text":"对很多类型来说,通过给所有字段赋值来创建新对象的这种方式就足以用于产生新实例了。然而,在某些情形下,创建复合对象需要更多的功能。有时必须通过检查或转化参数来确保固有属性不变。递归数据结构,特别是那些可能引用自身的数据结构,它们通常不能被干净地构造,而是需要首先被不完整地构造,然后再通过编程的方式完成补全。为了方便,有时需要用较少的参数或者不同类型的参数来创建对象,Julia 的对象构造系统解决了所有这些问题。","category":"page"},{"location":"manual/constructors/","page":"构造函数","title":"构造函数","text":"[1]: 命名法:虽然术语「构造函数」通常是指用于构造类型对象的函数全体,但通常会略微滥用术语将特定的构造方法称为「构造函数」。在这种情况下,通常可以从上下文中清楚地辨别出术语表示的是「构造方法」而不是「构造函数」,尤其是在讨论某个特别的「构造方法」的时候。","category":"page"},{"location":"manual/constructors/#man-outer-constructor-methods","page":"构造函数","title":"外部构造方法","text":"","category":"section"},{"location":"manual/constructors/","page":"构造函数","title":"构造函数","text":"构造函数与 Julia 中的其他任何函数一样,其整体行为由其各个方法的组合行为定义。因此,只要定义新方法就可以向构造函数添加功能。例如,假设你想为 Foo 对象添加一个构造方法,该方法只接受一个参数并其作为 bar 和 baz 的值。这很简单:","category":"page"},{"location":"manual/constructors/","page":"构造函数","title":"构造函数","text":"julia> Foo(x) = Foo(x,x)\nFoo\n\njulia> Foo(1)\nFoo(1, 1)","category":"page"},{"location":"manual/constructors/","page":"构造函数","title":"构造函数","text":"你也可以为 Foo 添加新的零参数构造方法,它为 bar 和 baz 提供默认值:","category":"page"},{"location":"manual/constructors/","page":"构造函数","title":"构造函数","text":"julia> Foo() = Foo(0)\nFoo\n\njulia> Foo()\nFoo(0, 0)","category":"page"},{"location":"manual/constructors/","page":"构造函数","title":"构造函数","text":"这里零参数构造方法会调用单参数构造方法,单参数构造方法又调用了自动提供默认值的双参数构造方法。上面附加的这类构造方法,它们的声明方式与普通的方法一样,像这样的构造方法被称为外部构造方法,下文很快就会揭示这样称呼的原因。外部构造方法只能通过调用其他构造方法来创建新实例,比如自动提供默认值的构造方法。","category":"page"},{"location":"manual/constructors/#man-inner-constructor-methods","page":"构造函数","title":"内部构造方法","text":"","category":"section"},{"location":"manual/constructors/","page":"构造函数","title":"构造函数","text":"尽管外部构造方法可以成功地为构造对象提供了额外的便利,但它无法解决另外两个在本章导言里提到的问题:确保固有属性不变和允许创建自引用对象。因此,我们需要内部构造方法。内部构造方法和外部构造方法很相像,但有两点不同:","category":"page"},{"location":"manual/constructors/","page":"构造函数","title":"构造函数","text":"内部构造方法在类型声明代码块的内部,而不是和普通方法一样在外部。\n内部构造方法能够访问一个特殊的局部函数 new,此函数能够创建该类型的对象。","category":"page"},{"location":"manual/constructors/","page":"构造函数","title":"构造函数","text":"例如,假设你要声明一个保存一对实数的类型,但要约束第一个数不大于第二个数。你可以像这样声明它:","category":"page"},{"location":"manual/constructors/","page":"构造函数","title":"构造函数","text":"julia> struct OrderedPair\n x::Real\n y::Real\n OrderedPair(x,y) = x > y ? error(\"out of order\") : new(x,y)\n end","category":"page"},{"location":"manual/constructors/","page":"构造函数","title":"构造函数","text":"现在 OrderedPair 对象只能在 x <= y 时被成功构造:","category":"page"},{"location":"manual/constructors/","page":"构造函数","title":"构造函数","text":"julia> OrderedPair(1, 2)\nOrderedPair(1, 2)\n\njulia> OrderedPair(2,1)\nERROR: out of order\nStacktrace:\n [1] error at ./error.jl:33 [inlined]\n [2] OrderedPair(::Int64, ::Int64) at ./none:4\n [3] top-level scope","category":"page"},{"location":"manual/constructors/","page":"构造函数","title":"构造函数","text":"如果类型被声明为 mutable,你可以直接更改字段值来打破这个固有属性,然而,在未经允许的情况下,随意摆弄对象的内核一般都是不好的行为。你(或者其他人)可以在以后任何时候提供额外的外部构造方法,但一旦类型被声明了,就没有办法来添加更多的内部构造方法了。由于外部构造方法只能通过调用其它的构造方法来创建对象,所以最终构造对象的一定是某个内部构造函数。这保证了已声明类型的对象必须通过调用该类型的内部构造方法才得已存在,从而在某种程度上保证了类型的固有属性。","category":"page"},{"location":"manual/constructors/","page":"构造函数","title":"构造函数","text":"只要定义了任何一个内部构造方法,Julia 就不会再提供默认的构造方法:它会假定你已经为自己提供了所需的所有内部构造方法。默认构造方法等效于一个你自己编写的内部构造函数,该函数将所有成员作为参数(如果相应的字段具有类型,则约束为正确的类型),并将它们传递给 new,最后返回结果对象:","category":"page"},{"location":"manual/constructors/","page":"构造函数","title":"构造函数","text":"julia> struct Foo\n bar\n baz\n Foo(bar,baz) = new(bar,baz)\n end\n","category":"page"},{"location":"manual/constructors/","page":"构造函数","title":"构造函数","text":"这个声明与前面没有显式内部构造方法的 Foo 类型的定义效果相同。 以下两个类型是等价的 – 一个具有默认构造方法,另一个具有显式构造方法:","category":"page"},{"location":"manual/constructors/","page":"构造函数","title":"构造函数","text":"julia> struct T1\n x::Int64\n end\n\njulia> struct T2\n x::Int64\n T2(x) = new(x)\n end\n\njulia> T1(1)\nT1(1)\n\njulia> T2(1)\nT2(1)\n\njulia> T1(1.0)\nT1(1)\n\njulia> T2(1.0)\nT2(1)","category":"page"},{"location":"manual/constructors/","page":"构造函数","title":"构造函数","text":"提供尽可能少的内部构造方法是一种良好的形式:仅在需要显式地处理所有参数,以及强制执行必要的错误检查和转换时候才使用内部构造。其它用于提供便利的构造方法,比如提供默认值或辅助转换,应该定义为外部构造函数,然后再通过调用内部构造函数来执行繁重的工作。这种解耦是很自然的。","category":"page"},{"location":"manual/constructors/#不完整初始化","page":"构造函数","title":"不完整初始化","text":"","category":"section"},{"location":"manual/constructors/","page":"构造函数","title":"构造函数","text":"最后一个还没提到的问题是,如何构造具有自引用的对象,更广义地来说是构造递归数据结构。由于这其中的困难并不是那么显而易见,这里我们来简单解释一下,考虑如下的递归类型声明:","category":"page"},{"location":"manual/constructors/","page":"构造函数","title":"构造函数","text":"julia> mutable struct SelfReferential\n obj::SelfReferential\n end\n","category":"page"},{"location":"manual/constructors/","page":"构造函数","title":"构造函数","text":"这种类型可能看起来没什么大不了,直到我们考虑如何来构造它的实例。 如果 a 是 SelfReferential 的一个实例,则第二个实例可以用如下的调用来创建:","category":"page"},{"location":"manual/constructors/","page":"构造函数","title":"构造函数","text":"julia> b = SelfReferential(a)","category":"page"},{"location":"manual/constructors/","page":"构造函数","title":"构造函数","text":"但是,当没有实例存在的情况下,即没有可以传递给 obj 成员变量的有效值时,如何构造第一个实例?唯一的解决方案是允许使用未初始化的 obj 成员来创建一个未完全初始化的 SelfReferential 实例,并使用该不完整的实例作为另一个实例的 obj 成员的有效值,例如,它本身。","category":"page"},{"location":"manual/constructors/","page":"构造函数","title":"构造函数","text":"为了允许创建未完全初始化的对象,Julia 允许使用少于该类型成员数的参数来调用 new 函数,并返回一个具有某个未初始化成员的对象。然后,内部构造函数可以使用不完整的对象,在返回之前完成初始化。例如,我们在定义 SelfReferential 类型时采用了另一个方法,使用零参数内部构造函数来返回一个实例,此实例的 obj 成员指向其自身:","category":"page"},{"location":"manual/constructors/","page":"构造函数","title":"构造函数","text":"julia> mutable struct SelfReferential\n obj::SelfReferential\n SelfReferential() = (x = new(); x.obj = x)\n end\n","category":"page"},{"location":"manual/constructors/","page":"构造函数","title":"构造函数","text":"我们可以验证这一构造函数有效性,且由其构造的对象确实是自引用的:","category":"page"},{"location":"manual/constructors/","page":"构造函数","title":"构造函数","text":"julia> x = SelfReferential();\n\njulia> x === x\ntrue\n\njulia> x === x.obj\ntrue\n\njulia> x === x.obj.obj\ntrue","category":"page"},{"location":"manual/constructors/","page":"构造函数","title":"构造函数","text":"虽然从一个内部构造函数中返回一个完全初始化的对象是很好的,但是也可以返回未完全初始化的对象:","category":"page"},{"location":"manual/constructors/","page":"构造函数","title":"构造函数","text":"julia> mutable struct Incomplete\n data\n Incomplete() = new()\n end\n\njulia> z = Incomplete();","category":"page"},{"location":"manual/constructors/","page":"构造函数","title":"构造函数","text":"尽管允许创建含有未初始化成员的对象,然而任何对未初始化引用的访问都会立即报错:","category":"page"},{"location":"manual/constructors/","page":"构造函数","title":"构造函数","text":"julia> z.data\nERROR: UndefRefError: access to undefined reference","category":"page"},{"location":"manual/constructors/","page":"构造函数","title":"构造函数","text":"这避免了不断地检测 null 值的需要。然而,并不是所有的对象成员都是引用。Julia 会将一些类型当作纯数据(\"plain data\"),这意味着它们的数据是自包含的,并且没有引用其它对象。这些纯数据包括原始类型(比如 Int )和由其它纯数据类型构成的不可变结构体。纯数据类型的初始值是未定义的:","category":"page"},{"location":"manual/constructors/","page":"构造函数","title":"构造函数","text":"julia> struct HasPlain\n n::Int\n HasPlain() = new()\n end\n\njulia> HasPlain()\nHasPlain(438103441441)","category":"page"},{"location":"manual/constructors/","page":"构造函数","title":"构造函数","text":"由纯数据组成的数组也具有一样的行为。","category":"page"},{"location":"manual/constructors/","page":"构造函数","title":"构造函数","text":"在内部构造函数中,你可以将不完整的对象传递给其它函数来委托其补全构造:","category":"page"},{"location":"manual/constructors/","page":"构造函数","title":"构造函数","text":"julia> mutable struct Lazy\n data\n Lazy(v) = complete_me(new(), v)\n end","category":"page"},{"location":"manual/constructors/","page":"构造函数","title":"构造函数","text":"与构造函数返回的不完整对象一样,如果 complete_me 或其任何被调用者尝试在初始化之前访问 Lazy 对象的 data 字段,就会立刻报错。","category":"page"},{"location":"manual/constructors/#参数类型的构造函数","page":"构造函数","title":"参数类型的构造函数","text":"","category":"section"},{"location":"manual/constructors/","page":"构造函数","title":"构造函数","text":"参数类型的存在为构造函数增加了更多的复杂性。首先,让我们回顾一下参数类型。在默认情况下,我们可以用两种方法来实例化参数复合类型,一种是显式地提供类型参数,另一种是让 Julia 根据构造函数输入参数的类型来隐式地推导类型参数。这里有一些例子:","category":"page"},{"location":"manual/constructors/","page":"构造函数","title":"构造函数","text":"julia> struct Point{T<:Real}\n x::T\n y::T\n end\n\njulia> Point(1,2) ## 隐式的 T ##\nPoint{Int64}(1, 2)\n\njulia> Point(1.0,2.5) ## 隐式的 T ##\nPoint{Float64}(1.0, 2.5)\n\njulia> Point(1,2.5) ## 隐式的 T ##\nERROR: MethodError: no method matching Point(::Int64, ::Float64)\nClosest candidates are:\n Point(::T, ::T) where T<:Real at none:2\n\njulia> Point{Int64}(1, 2) ## 显式的 T ##\nPoint{Int64}(1, 2)\n\njulia> Point{Int64}(1.0,2.5) ## 显式的 T ##\nERROR: InexactError: Int64(2.5)\nStacktrace:\n[...]\n\njulia> Point{Float64}(1.0, 2.5) ## 显式的 T ##\nPoint{Float64}(1.0, 2.5)\n\njulia> Point{Float64}(1,2) ## 显式的 T ##\nPoint{Float64}(1.0, 2.0)","category":"page"},{"location":"manual/constructors/","page":"构造函数","title":"构造函数","text":"就像你看到的那样,用类型参数显式地调用构造函数,其参数会被转换为指定的类型:Point{Int64}(1,2) 可以正常工作,但是 Point{Int64}(1.0,2.5) 则会在将 2.5 转换为 Int64 的时候报一个 InexactError。当类型是从构造函数的参数隐式推导出来的时候,比如在例子 Point(1,2) 中,输入参数的类型必须一致,否则就无法确定 T 是什么,但 Point 的构造函数仍可以适配任意同类型的实数对。","category":"page"},{"location":"manual/constructors/","page":"构造函数","title":"构造函数","text":"实际上,这里的 Point,Point{Float64} 以及 Point{Int64} 是不同的构造函数。Point{T} 表示对于每个类型 T 都存在一个不同的构造函数。如果不显式提供内部构造函数,在声明复合类型 Point{T<:Real} 的时候,Julia 会对每个满足 T<:Real 条件的类型都提供一个默认的内部构造函数 Point{T},它们的行为与非参数类型的默认内部构造函数一致。Julia 同时也会提供了一个通用的外部构造函数 Point,用于适配任意同类型的实数对。Julia 默认提供的构造函数等价于下面这种显式的声明:","category":"page"},{"location":"manual/constructors/","page":"构造函数","title":"构造函数","text":"julia> struct Point{T<:Real}\n x::T\n y::T\n Point{T}(x,y) where {T<:Real} = new(x,y)\n end\n\njulia> Point(x::T, y::T) where {T<:Real} = Point{T}(x,y);","category":"page"},{"location":"manual/constructors/","page":"构造函数","title":"构造函数","text":"注意,每个构造函数定义的方式与调用它们的方式是一样的。调用 Point{Int64}(1,2) 会触发 struct 块内部的 Point{T}(x,y)。另一方面,外部构造函数声明的 Point 构造函数只会被同类型的实数对触发,它使得我们可以直接以 Point(1,2) 和 Point(1.0,2.5) 这种方式来创建实例,而不需要显示地使用类型参数。由于此方法的声明方式已经对输入参数的类型施加了约束,像 Point(1,2.5) 这种调用自然会导致 \"no method\" 错误。","category":"page"},{"location":"manual/constructors/","page":"构造函数","title":"构造函数","text":"假如我们想让 Point(1,2.5) 这种调用方式正常工作,比如,通过将整数 1 自动「提升」为浮点数 1.0,最简单的方法是像下面这样定义一个额外的外部构造函数:","category":"page"},{"location":"manual/constructors/","page":"构造函数","title":"构造函数","text":"julia> Point(x::Int64, y::Float64) = Point(convert(Float64,x),y);","category":"page"},{"location":"manual/constructors/","page":"构造函数","title":"构造函数","text":"此方法使用 convert 函数将 x 显式转换为 Float64,然后在两个参数都是 Float64 的情况下使用通用的构造函数。通过这个方法定义,以前的报MethodError的代码现在可以成功地创建一个类型为 Point{Float64} 的点:","category":"page"},{"location":"manual/constructors/","page":"构造函数","title":"构造函数","text":"julia> p = Point(1,2.5)\nPoint{Float64}(1.0, 2.5)\n\njulia> typeof(p)\nPoint{Float64}","category":"page"},{"location":"manual/constructors/","page":"构造函数","title":"构造函数","text":"然而,其它类似的调用依然有问题:","category":"page"},{"location":"manual/constructors/","page":"构造函数","title":"构造函数","text":"julia> Point(1.5,2)\nERROR: MethodError: no method matching Point(::Float64, ::Int64)\nClosest candidates are:\n Point(::T, !Matched::T) where T<:Real at none:1","category":"page"},{"location":"manual/constructors/","page":"构造函数","title":"构造函数","text":"如果你想要找到一种方法可以使类似的调用都可以正常工作,请参阅类型转换与类型提升。这里稍稍“剧透”一下,我们可以利用下面的这个外部构造函数来满足需求,无论输入参数的类型如何,它都可以触发通用的 Point 构造函数:","category":"page"},{"location":"manual/constructors/","page":"构造函数","title":"构造函数","text":"julia> Point(x::Real, y::Real) = Point(promote(x,y)...);","category":"page"},{"location":"manual/constructors/","page":"构造函数","title":"构造函数","text":"这里的 promote 函数会将它的输入转化为同一类型,在此例中是 Float64。定义了这个方法,Point 构造函数会自动提升输入参数的类型,且提升机制与算术运算符相同,比如 +,因此对所有的实数输入参数都适用:","category":"page"},{"location":"manual/constructors/","page":"构造函数","title":"构造函数","text":"julia> Point(1.5,2)\nPoint{Float64}(1.5, 2.0)\n\njulia> Point(1,1//2)\nPoint{Rational{Int64}}(1//1, 1//2)\n\njulia> Point(1.0,1//2)\nPoint{Float64}(1.0, 0.5)","category":"page"},{"location":"manual/constructors/","page":"构造函数","title":"构造函数","text":"因此,虽然 Julia 中默认提供的隐式类型参数构造函数相当严格,但可以很容易地使它们以更轻松且明智的方式运行。 此外,由于构造函数可以利用类型系统、方法和多重派发的所有功能,因此定义复杂的行为通常非常简单。","category":"page"},{"location":"manual/constructors/#示例学习:有理数","page":"构造函数","title":"示例学习:有理数","text":"","category":"section"},{"location":"manual/constructors/","page":"构造函数","title":"构造函数","text":"也许将所有这些部分联系在一起的最佳方法是展示参数复合类型及其构造方法的真实示例。 为此,我们实现了自己的有理数类型 OurRational,类似于 Julia 的内置 Rational 类型,定义在 [rational.jl](https://github.com/JuliaLang /julia/blob/master/base/rational.jl):","category":"page"},{"location":"manual/constructors/","page":"构造函数","title":"构造函数","text":"julia> struct OurRational{T<:Integer} <: Real\n num::T\n den::T\n function OurRational{T}(num::T, den::T) where T<:Integer\n if num == 0 && den == 0\n error(\"invalid rational: 0//0\")\n end\n num = flipsign(num, den)\n den = flipsign(den, den)\n g = gcd(num, den)\n num = div(num, g)\n den = div(den, g)\n new(num, den)\n end\n end\n\njulia> OurRational(n::T, d::T) where {T<:Integer} = OurRational{T}(n,d)\nOurRational\n\njulia> OurRational(n::Integer, d::Integer) = OurRational(promote(n,d)...)\nOurRational\n\njulia> OurRational(n::Integer) = OurRational(n,one(n))\nOurRational\n\njulia> ⊘(n::Integer, d::Integer) = OurRational(n,d)\n⊘ (generic function with 1 method)\n\njulia> ⊘(x::OurRational, y::Integer) = x.num ⊘ (x.den*y)\n⊘ (generic function with 2 methods)\n\njulia> ⊘(x::Integer, y::OurRational) = (x*y.den) ⊘ y.num\n⊘ (generic function with 3 methods)\n\njulia> ⊘(x::Complex, y::Real) = complex(real(x) ⊘ y, imag(x) ⊘ y)\n⊘ (generic function with 4 methods)\n\njulia> ⊘(x::Real, y::Complex) = (x*y') ⊘ real(y*y')\n⊘ (generic function with 5 methods)\n\njulia> function ⊘(x::Complex, y::Complex)\n xy = x*y'\n yy = real(y*y')\n complex(real(xy) ⊘ yy, imag(xy) ⊘ yy)\n end\n⊘ (generic function with 6 methods)","category":"page"},{"location":"manual/constructors/","page":"构造函数","title":"构造函数","text":"第一行 – struct OurRational{T<:Integer} <: Real – 声明了 OurRational 会接收一个整数类型的类型参数,且它自己属于实数类型。它声明了两个成员:num::T 和 den::T。这表明一个 OurRational{T} 的实例中会包含一对整数,且类型为 T,其中一个表示分子,另一个表示分母。","category":"page"},{"location":"manual/constructors/","page":"构造函数","title":"构造函数","text":"现在事情变得有趣了。 OurRational 有一个内部构造器方法,它检查 num 和 den 不都为零,并确保每个有理数都是以非负分母的“最低项”构造的。 这是通过首先翻转分子和分母的符号(如果分母为负)来实现的。 然后,两者都除以它们的最大公约数(gcd 总是返回一个非负数,无论其参数的符号如何)。 因为这是 OurRational 唯一的内部构造函数,我们可以确定 OurRational 对象总是以这种规范化形式构造的。","category":"page"},{"location":"manual/constructors/","page":"构造函数","title":"构造函数","text":"为了方便,OurRational 也提供了一些其它的外部构造函数。第一个外部构造函数是“标准的”通用构造函数,当分子和分母的类型一致时,它就可以推导出类型参数 T。第二个外部构造函数可以用于分子和分母的类型不一致的情景,它会将分子和分母的类型提升至一个共同的类型,然后再委托第一个外部构造函数进行构造。第三个构造函数会将一个整数转化为分数,方法是将 1 当作分母。","category":"page"},{"location":"manual/constructors/","page":"构造函数","title":"构造函数","text":"在定义了外部构造函数之后,我们为 ⊘ 算符定义了一系列的方法,之后就可以使用 ⊘ 算符来写分数,(比如 1 ⊘ 2)。Julia 的 Rational 类型采用的是 // 算符。在做上述定义之前,⊘ 是一个无意的且未被定义的算符。定义之后,它的行为与在 有理数 一节中描述的一致——注意它的所有行为都是那短短几行定义的。第一个也是最基础的定义只是将 a ⊘ b 中的 a 和 b 当作参数传递给 OurRational 的构造函数来实例化 OurRational,这要求 a 和 b 分别都是整数。在 ⊘ 的某个操作数已经是分数的情况下,我们采用了一个有点不一样的方法来构建新的分数,这实际上等价于用分数除以一个整数。最后,我们也可以让 ⊘ 作用于复数,用来创建一个类型为 Complex{<:OurRational} 的对象——即一个实部和虚部都是分数的复数:","category":"page"},{"location":"manual/constructors/","page":"构造函数","title":"构造函数","text":"julia> z = (1 + 2im) ⊘ (1 - 2im);\n\njulia> typeof(z)\nComplex{OurRational{Int64}}\n\njulia> typeof(z) <: Complex{<:OurRational}\ntrue","category":"page"},{"location":"manual/constructors/","page":"构造函数","title":"构造函数","text":"因此,尽管 ⊘ 算符通常会返回一个 OurRational 的实例,但倘若其中一个操作数是复整数,那么就会返回 Complex{<:OurRational}。感兴趣的话可以读一读 rational.jl:它实现了一个完整的 Julia 基本类型,但却非常的简短,而且是自恰的。","category":"page"},{"location":"manual/constructors/#仅外部的构造函数","page":"构造函数","title":"仅外部的构造函数","text":"","category":"section"},{"location":"manual/constructors/","page":"构造函数","title":"构造函数","text":"正如我们所看到的,典型的参数类型都有一个内部构造函数,它仅在全部的类型参数都已知的情况下才会被调用。例如,可以用 Point{Int}调用,但Point 就不行。我们可以选择性的添加外部构造函数来自动推导并添加类型参数,比如,调用 Point(1,2) 来构造 Point{Int}。外部构造函数调用内部构造函数来实际创建实例。然而,在某些情况下,我们可能并不想要内部构造函数,从而达到禁止手动指定类型参数的目的。","category":"page"},{"location":"manual/constructors/","page":"构造函数","title":"构造函数","text":"例如,假设我们要定义一个类型用于存储向量以及其累加和:","category":"page"},{"location":"manual/constructors/","page":"构造函数","title":"构造函数","text":"julia> struct SummedArray{T<:Number,S<:Number}\n data::Vector{T}\n sum::S\n end\n\njulia> SummedArray(Int32[1; 2; 3], Int32(6))\nSummedArray{Int32, Int32}(Int32[1, 2, 3], 6)","category":"page"},{"location":"manual/constructors/","page":"构造函数","title":"构造函数","text":"问题在于我们想让 S 的类型始终比 T 大,这样做是为了确保累加过程不会丢失信息。例如,当 T 是 Int32 时,我们想让 S 是 Int64。所以我们想要一种接口来禁止用户创建像 SummedArray{Int32,Int32} 这种类型的实例。一种实现方式是只提供一个 SummedArray 构造函数,当需要将其放入 struct-block 中,从而不让 Julia 提供默认的构造函数:","category":"page"},{"location":"manual/constructors/","page":"构造函数","title":"构造函数","text":"julia> struct SummedArray{T<:Number,S<:Number}\n data::Vector{T}\n sum::S\n function SummedArray(a::Vector{T}) where T\n S = widen(T)\n new{T,S}(a, sum(S, a))\n end\n end\n\njulia> SummedArray(Int32[1; 2; 3], Int32(6))\nERROR: MethodError: no method matching SummedArray(::Vector{Int32}, ::Int32)\nClosest candidates are:\n SummedArray(::Vector{T}) where T at none:4\nStacktrace:\n[...]","category":"page"},{"location":"manual/constructors/","page":"构造函数","title":"构造函数","text":"此构造函数将会被 SummedArray(a) 这种写法触发。new{T,S} 的这种写法允许指定待构建类型的参数,也就是说调用它会返回一个 SummedArray{T,S} 的实例。new{T,S} 也可以用于其它构造函数的定义中,但为了方便,Julia 会根据正在构造的类型自动推导出 new{} 花括号里的参数(如果可行的话)。","category":"page"},{"location":"stdlib/SHA/#SHA","page":"SHA","title":"SHA","text":"","category":"section"},{"location":"stdlib/SHA/","page":"SHA","title":"SHA","text":"用法非常直接:","category":"page"},{"location":"stdlib/SHA/","page":"SHA","title":"SHA","text":"julia> using SHA\n\njulia> bytes2hex(sha256(\"test\"))\n\"9f86d081884c7d659a2feaa0c55ad015a3bf4f1b2b0b822cd15d6c15b0f00a08\"","category":"page"},{"location":"stdlib/SHA/","page":"SHA","title":"SHA","text":"Each exported function (at the time of this writing, SHA-1, SHA-2 224, 256, 384 and 512, and SHA-3 224, 256, 384 and 512 functions are implemented) takes in either an AbstractVector{UInt8}, an AbstractString or an IO object. This makes it trivial to checksum a file:","category":"page"},{"location":"stdlib/SHA/","page":"SHA","title":"SHA","text":"shell> cat /tmp/test.txt\ntest\njulia> using SHA\n\njulia> open(\"/tmp/test.txt\") do f\n sha2_256(f)\n end\n32-element Array{UInt8,1}:\n 0x9f\n 0x86\n 0xd0\n 0x81\n 0x88\n 0x4c\n 0x7d\n 0x65\n ⋮\n 0x5d\n 0x6c\n 0x15\n 0xb0\n 0xf0\n 0x0a\n 0x08","category":"page"},{"location":"stdlib/SHA/","page":"SHA","title":"SHA","text":"Due to the colloquial usage of sha256 to refer to sha2_256, convenience functions are provided, mapping shaxxx() function calls to sha2_xxx(). For SHA-3, no such colloquialisms exist and the user must use the full sha3_xxx() names.","category":"page"},{"location":"stdlib/SHA/","page":"SHA","title":"SHA","text":"shaxxx() takes AbstractString and array-like objects (NTuple and Array) with elements of type UInt8.","category":"page"},{"location":"stdlib/SHA/","page":"SHA","title":"SHA","text":"To create a hash from multiple items the SHAX_XXX_CTX() types can be used to create a stateful hash object that is updated with update! and finalized with digest!","category":"page"},{"location":"stdlib/SHA/","page":"SHA","title":"SHA","text":"julia> ctx = SHA2_256_CTX()\nSHA2 256-bit hash state\n\njulia> update!(ctx, b\"some data\")\n0x0000000000000009\n\njulia> update!(ctx, b\"some more data\")\n0x0000000000000017\n\njulia> digest!(ctx)\n32-element Vector{UInt8}:\n 0xbe\n 0xcf\n 0x23\n 0xda\n 0xaf\n 0x02\n ⋮\n 0x25\n 0x52\n 0x19\n 0xa0\n 0x8b\n 0xc5","category":"page"},{"location":"stdlib/SHA/","page":"SHA","title":"SHA","text":"Note that, at the time of this writing, the SHA3 code is not optimized, and as such is roughly an order of magnitude slower than SHA2.","category":"page"},{"location":"devdocs/ssair/#Julia-SSA-form-IR","page":"Julia SSA-form IR","title":"Julia SSA-form IR","text":"","category":"section"},{"location":"devdocs/ssair/#Background","page":"Julia SSA-form IR","title":"Background","text":"","category":"section"},{"location":"devdocs/ssair/","page":"Julia SSA-form IR","title":"Julia SSA-form IR","text":"Beginning in Julia 0.7, parts of the compiler use a new SSA-form intermediate representation. Historically, the compiler used to directly generate LLVM IR, from a lowered form of the Julia AST. This form had most syntactic abstractions removed, but still looked a lot like an abstract syntax tree. Over time, in order to facilitate optimizations, SSA values were introduced to this IR and the IR was linearized (i.e. a form where function arguments may only be SSA values or constants). However, non-SSA values (slots) remained in the IR due to the lack of Phi nodes in the IR (necessary for back-edges and re-merging of conditional control flow), negating much of the usefulness of the SSA form representation to perform middle end optimizations. Some heroic effort was put into making these optimizations work without a complete SSA form representation, but the lack of such a representation ultimately proved prohibitive.","category":"page"},{"location":"devdocs/ssair/#New-IR-nodes","page":"Julia SSA-form IR","title":"New IR nodes","text":"","category":"section"},{"location":"devdocs/ssair/","page":"Julia SSA-form IR","title":"Julia SSA-form IR","text":"With the new IR representation, the compiler learned to handle four new IR nodes, Phi nodes, Pi nodes as well as PhiC nodes and Upsilon nodes (the latter two are only used for exception handling).","category":"page"},{"location":"devdocs/ssair/#Phi-nodes-and-Pi-nodes","page":"Julia SSA-form IR","title":"Phi nodes and Pi nodes","text":"","category":"section"},{"location":"devdocs/ssair/","page":"Julia SSA-form IR","title":"Julia SSA-form IR","text":"Phi nodes are part of generic SSA abstraction (see the link above if you're not familiar with the concept). In the Julia IR, these nodes are represented as:","category":"page"},{"location":"devdocs/ssair/","page":"Julia SSA-form IR","title":"Julia SSA-form IR","text":"struct PhiNode\n edges::Vector{Int}\n values::Vector{Any}\nend","category":"page"},{"location":"devdocs/ssair/","page":"Julia SSA-form IR","title":"Julia SSA-form IR","text":"where we ensure that both vectors always have the same length. In the canonical representation (the one handled by codegen and the interpreter), the edge values indicate come-from statement numbers (i.e. if edge has an entry of 15, there must be a goto, gotoifnot or implicit fall through from statement 15 that targets this phi node). Values are either SSA values or constants. It is also possible for a value to be unassigned if the variable was not defined on this path. However, undefinedness checks get explicitly inserted and represented as booleans after middle end optimizations, so code generators may assume that any use of a Phi node will have an assigned value in the corresponding slot. It is also legal for the mapping to be incomplete, i.e. for a Phi node to have missing incoming edges. In that case, it must be dynamically guaranteed that the corresponding value will not be used.","category":"page"},{"location":"devdocs/ssair/","page":"Julia SSA-form IR","title":"Julia SSA-form IR","text":"PiNodes encode statically proven information that may be implicitly assumed in basic blocks dominated by a given pi node. They are conceptually equivalent to the technique introduced in the paper ABCD: Eliminating Array Bounds Checks on Demand or the predicate info nodes in LLVM. To see how they work, consider, e.g.","category":"page"},{"location":"devdocs/ssair/","page":"Julia SSA-form IR","title":"Julia SSA-form IR","text":"%x::Union{Int, Float64} # %x is some Union{Int, Float64} typed ssa value\nif isa(x, Int)\n # use x\nelse\n # use x\nend","category":"page"},{"location":"devdocs/ssair/","page":"Julia SSA-form IR","title":"Julia SSA-form IR","text":"We can perform predicate insertion and turn this into:","category":"page"},{"location":"devdocs/ssair/","page":"Julia SSA-form IR","title":"Julia SSA-form IR","text":"%x::Union{Int, Float64} # %x is some Union{Int, Float64} typed ssa value\nif isa(x, Int)\n %x_int = PiNode(x, Int)\n # use %x_int\nelse\n %x_float = PiNode(x, Float64)\n # use %x_float\nend","category":"page"},{"location":"devdocs/ssair/","page":"Julia SSA-form IR","title":"Julia SSA-form IR","text":"Pi nodes are generally ignored in the interpreter, since they don't have any effect on the values, but they may sometimes lead to code generation in the compiler (e.g. to change from an implicitly union split representation to a plain unboxed representation). The main usefulness of PiNodes stems from the fact that path conditions of the values can be accumulated simply by def-use chain walking that is generally done for most optimizations that care about these conditions anyway.","category":"page"},{"location":"devdocs/ssair/#PhiC-nodes-and-Upsilon-nodes","page":"Julia SSA-form IR","title":"PhiC nodes and Upsilon nodes","text":"","category":"section"},{"location":"devdocs/ssair/","page":"Julia SSA-form IR","title":"Julia SSA-form IR","text":"Exception handling complicates the SSA story moderately, because exception handling introduces additional control flow edges into the IR across which values must be tracked. One approach to do so, which is followed by LLVM is to make calls which may throw exceptions into basic block terminators and add an explicit control flow edge to the catch handler:","category":"page"},{"location":"devdocs/ssair/","page":"Julia SSA-form IR","title":"Julia SSA-form IR","text":"invoke @function_that_may_throw() to label %regular unwind to %catch\n\nregular:\n# Control flow continues here\n\ncatch:\n# Exceptions go here","category":"page"},{"location":"devdocs/ssair/","page":"Julia SSA-form IR","title":"Julia SSA-form IR","text":"However, this is problematic in a language like julia where at the start of the optimization pipeline, we do not know which calls throw. We would have to conservatively assume that every call (which in julia is every statement) throws. This would have several negative effects. On the one hand, it would essentially reduce the scope of every basic block to a single call, defeating the purpose of having operations be performed at the basic block level. On the other hand, every catch basic block would have n*m phi node arguments (n, the number of statements in the critical region, m the number of live values through the catch block). To work around this, we use a combination of Upsilon and PhiC (the C standing for catch, written φᶜ in the IR pretty printer, because unicode subscript c is not available) nodes. There are several ways to think of these nodes, but perhaps the easiest is to think of each PhiC as a load from a unique store-many, read-once slot, with Upsilon being the corresponding store operation. The PhiC has an operand list of all the upsilon nodes that store to its implicit slot. The Upsilon nodes however, do not record which PhiC node they store to. This is done for more natural integration with the rest of the SSA IR. E.g. if there are no more uses of a PhiC node, it is safe to delete it, and the same is true of an Upsilon node. In most IR passes, PhiC nodes can be treated like Phi nodes. One can follow use-def chains through them, and they can be lifted to new PhiC nodes and new Upsilon nodes (in the same places as the original Upsilon nodes). The result of this scheme is that the number of Upsilon nodes (and PhiC arguments) is proportional to the number of assigned values to a particular variable (before SSA conversion), rather than the number of statements in the critical region.","category":"page"},{"location":"devdocs/ssair/","page":"Julia SSA-form IR","title":"Julia SSA-form IR","text":"To see this scheme in action, consider the function","category":"page"},{"location":"devdocs/ssair/","page":"Julia SSA-form IR","title":"Julia SSA-form IR","text":"@noinline opaque() = invokelatest(identity, nothing) # Something opaque\nfunction foo()\n local y\n x = 1\n try\n y = 2\n opaque()\n y = 3\n error()\n catch\n end\n (x, y)\nend","category":"page"},{"location":"devdocs/ssair/","page":"Julia SSA-form IR","title":"Julia SSA-form IR","text":"The corresponding IR (with irrelevant types stripped) is:","category":"page"},{"location":"devdocs/ssair/","page":"Julia SSA-form IR","title":"Julia SSA-form IR","text":"1 ─ nothing::Nothing\n2 ─ %2 = $(Expr(:enter, #4))\n3 ─ %3 = ϒ (false)\n│ %4 = ϒ (#undef)\n│ %5 = ϒ (1)\n│ %6 = ϒ (true)\n│ %7 = ϒ (2)\n│ invoke Main.opaque()::Any\n│ %9 = ϒ (true)\n│ %10 = ϒ (3)\n│ invoke Main.error()::Union{}\n└── $(Expr(:unreachable))::Union{}\n4 ┄ %13 = φᶜ (%3, %6, %9)::Bool\n│ %14 = φᶜ (%4, %7, %10)::Core.Compiler.MaybeUndef(Int64)\n│ %15 = φᶜ (%5)::Core.Const(1)\n└── $(Expr(:leave, 1))\n5 ─ $(Expr(:pop_exception, :(%2)))::Any\n│ $(Expr(:throw_undef_if_not, :y, :(%13)))::Any\n│ %19 = Core.tuple(%15, %14)\n└── return %19","category":"page"},{"location":"devdocs/ssair/","page":"Julia SSA-form IR","title":"Julia SSA-form IR","text":"Note in particular that every value live into the critical region gets an upsilon node at the top of the critical region. This is because catch blocks are considered to have an invisible control flow edge from outside the function. As a result, no SSA value dominates the catch blocks, and all incoming values have to come through a φᶜ node.","category":"page"},{"location":"devdocs/ssair/#Main-SSA-data-structure","page":"Julia SSA-form IR","title":"Main SSA data structure","text":"","category":"section"},{"location":"devdocs/ssair/","page":"Julia SSA-form IR","title":"Julia SSA-form IR","text":"The main SSAIR data structure is worthy of discussion. It draws inspiration from LLVM and Webkit's B3 IR. The core of the data structure is a flat vector of statements. Each statement is implicitly assigned an SSA value based on its position in the vector (i.e. the result of the statement at idx 1 can be accessed using SSAValue(1) etc). For each SSA value, we additionally maintain its type. Since, SSA values are definitionally assigned only once, this type is also the result type of the expression at the corresponding index. However, while this representation is rather efficient (since the assignments don't need to be explicitly encoded), it of course carries the drawback that order is semantically significant, so reorderings and insertions change statement numbers. Additionally, we do not keep use lists (i.e. it is impossible to walk from a def to all its uses without explicitly computing this map–def lists however are trivial since you can look up the corresponding statement from the index), so the LLVM-style RAUW (replace-all-uses-with) operation is unavailable.","category":"page"},{"location":"devdocs/ssair/","page":"Julia SSA-form IR","title":"Julia SSA-form IR","text":"Instead, we do the following:","category":"page"},{"location":"devdocs/ssair/","page":"Julia SSA-form IR","title":"Julia SSA-form IR","text":"We keep a separate buffer of nodes to insert (including the position to insert them at, the type of the corresponding value and the node itself). These nodes are numbered by their occurrence in the insertion buffer, allowing their values to be immediately used elsewhere in the IR (i.e. if there are 12 statements in the original statement list, the first new statement will be accessible as SSAValue(13)).\nRAUW style operations are performed by setting the corresponding statement index to the replacement value.\nStatements are erased by setting the corresponding statement to nothing (this is essentially just a special-case convention of the above.\nIf there are any uses of the statement being erased, they will be set to nothing.","category":"page"},{"location":"devdocs/ssair/","page":"Julia SSA-form IR","title":"Julia SSA-form IR","text":"There is a compact! function that compacts the above data structure by performing the insertion of nodes in the appropriate place, trivial copy propagation, and renaming of uses to any changed SSA values. However, the clever part of this scheme is that this compaction can be done lazily as part of the subsequent pass. Most optimization passes need to walk over the entire list of statements, performing analysis or modifications along the way. We provide an IncrementalCompact iterator that can be used to iterate over the statement list. It will perform any necessary compaction and return the new index of the node, as well as the node itself. It is legal at this point to walk def-use chains, as well as make any modifications or deletions to the IR (insertions are disallowed however).","category":"page"},{"location":"devdocs/ssair/","page":"Julia SSA-form IR","title":"Julia SSA-form IR","text":"The idea behind this arrangement is that, since the optimization passes need to touch the corresponding memory anyway and incur the corresponding memory access penalty, performing the extra housekeeping should have comparatively little overhead (and save the overhead of maintaining these data structures during IR modification).","category":"page"},{"location":"manual/","page":"-","title":"-","text":"io = IOBuffer()\nrelease = isempty(VERSION.prerelease)\nv = \"$(VERSION.major).$(VERSION.minor)\"\n!release && (v = v*\"-$(first(VERSION.prerelease))\")\nprint(io, \"\"\"\n # Julia $(v) Documentation\n\n Welcome to the documentation for Julia $(v).\n\n \"\"\")\nif !release\n print(io,\"\"\"\n !!! warning \"Work in progress!\"\n This documentation is for an unreleased, in-development, version of Julia.\n \"\"\")\nend\nimport Markdown\nMarkdown.parse(String(take!(io)))","category":"page"},{"location":"manual/","page":"-","title":"-","text":"请阅读 release notes 以了解自上次发行以来发生了什么变化。","category":"page"},{"location":"manual/","page":"-","title":"-","text":"release = isempty(VERSION.prerelease)\nfile = release ? \"julia-$(VERSION).pdf\" :\n \"julia-$(VERSION.major).$(VERSION.minor).$(VERSION.patch)-$(first(VERSION.prerelease)).pdf\"\nurl = \"https://raw.githubusercontent.com/JuliaLang/docs.julialang.org/assets/$(file)\"\nimport Markdown\nMarkdown.parse(\"\"\"\n!!! note\n The documentation is also available in PDF format: [$file]($url).\n\"\"\")","category":"page"},{"location":"manual/#man-introduction","page":"-","title":"简介","text":"","category":"section"},{"location":"manual/","page":"-","title":"-","text":"科学计算对性能一直有着最高的需求,但目前各领域的专家却大量使用较慢的动态语言来开展他们的日常工作。 偏爱动态语言有很多很好的理由,因此我们不会舍弃动态的特性。 幸运的是,现代编程语言设计与编译器技术可以大大消除性能折衷(trade-off),并提供有足够生产力的单一环境进行原型设计,而且能高效地部署性能密集型应用程序。 Julia 语言在这其中扮演了这样一个角色:它是一门灵活的动态语言,适合用于科学计算和数值计算,并且性能可与传统的静态类型语言媲美。","category":"page"},{"location":"manual/","page":"-","title":"-","text":"由于 Julia 的编译器和其它语言比如 Python 或 R 的解释器有所不同,一开始你可能发现 Julia 的性能并不是很突出。 如果你觉得速度有点慢,我们强烈建议在尝试其他功能前,先读一读文档中的提高性能的窍门部分。 一旦你理解了 Julia 的运作方式后,写出和 C 一样快的代码就是小菜一碟。","category":"page"},{"location":"manual/","page":"-","title":"-","text":"Julia features optional typing, multiple dispatch, and good performance, achieved using type inference and just-in-time (JIT) compilation, implemented using LLVM. It is multi-paradigm, combining features of imperative, functional, and object-oriented programming. Julia provides ease and expressiveness for high-level numerical computing, in the same way as languages such as R, MATLAB, and Python, but also supports general programming. To achieve this, Julia builds upon the lineage of mathematical programming languages, but also borrows much from popular dynamic languages, including Lisp, Perl, Python, Lua, and Ruby.","category":"page"},{"location":"manual/","page":"-","title":"-","text":"Julia 与传统动态语言最重要的区别是:","category":"page"},{"location":"manual/","page":"-","title":"-","text":"The core language imposes very little; Julia Base and the standard library are written in Julia itself, including primitive operations like integer arithmetic\nA rich language of types for constructing and describing objects, that can also optionally be used to make type declarations\nThe ability to define function behavior across many combinations of argument types via multiple dispatch\nAutomatic generation of efficient, specialized code for different argument types\nGood performance, approaching that of statically-compiled languages like C","category":"page"},{"location":"manual/","page":"-","title":"-","text":"Although one sometimes speaks of dynamic languages as being \"typeless\", they are definitely not: every object, whether primitive or user-defined, has a type. The lack of type declarations in most dynamic languages, however, means that one cannot instruct the compiler about the types of values, and often cannot explicitly talk about types at all. In static languages, on the other hand, while one can – and usually must – annotate types for the compiler, types exist only at compile time and cannot be manipulated or expressed at run time. In Julia, types are themselves run-time objects, and can also be used to convey information to the compiler.","category":"page"},{"location":"manual/","page":"-","title":"-","text":"While the casual programmer need not explicitly use types or multiple dispatch, they are the core unifying features of Julia: functions are defined on different combinations of argument types, and applied by dispatching to the most specific matching definition. This model is a good fit for mathematical programming, where it is unnatural for the first argument to \"own\" an operation as in traditional object-oriented dispatch. Operators are just functions with special notation – to extend addition to new user-defined data types, you define new methods for the + function. Existing code then seamlessly applies to the new data types.","category":"page"},{"location":"manual/","page":"-","title":"-","text":"Partly because of run-time type inference (augmented by optional type annotations), and partly because of a strong focus on performance from the inception of the project, Julia's computational efficiency exceeds that of other dynamic languages, and even rivals that of statically-compiled languages. For large scale numerical problems, speed always has been, continues to be, and probably always will be crucial: the amount of data being processed has easily kept pace with Moore's Law over the past decades.","category":"page"},{"location":"manual/","page":"-","title":"-","text":"Julia aims to create an unprecedented combination of ease-of-use, power, and efficiency in a single language. In addition to the above, some advantages of Julia over comparable systems include:","category":"page"},{"location":"manual/","page":"-","title":"-","text":"Free and open source (MIT licensed)\nUser-defined types are as fast and compact as built-ins\nNo need to vectorize code for performance; devectorized code is fast\nDesigned for parallelism and distributed computation\nLightweight \"green\" threading (coroutines)\nUnobtrusive yet powerful type system\nElegant and extensible conversions and promotions for numeric and other types\nEfficient support for Unicode, including but not limited to UTF-8\nCall C functions directly (no wrappers or special APIs needed)\nPowerful shell-like capabilities for managing other processes\nLisp-like macros and other metaprogramming facilities","category":"page"},{"location":"manual/control-flow/#流程控制","page":"流程控制","title":"流程控制","text":"","category":"section"},{"location":"manual/control-flow/","page":"流程控制","title":"流程控制","text":"Julia 提供了大量的流程控制构件:","category":"page"},{"location":"manual/control-flow/","page":"流程控制","title":"流程控制","text":"复合表达式:begin 和 ;。\n条件表达式:if-elseif-else 和 ?: (三元运算符)。\n短路求值:逻辑运算符 &&(与)和 ||(或),以及链式比较。\n重复执行:循环:while 和 for。\n异常处理:try-catch、error 和 throw。\nTask(协程):yieldto。","category":"page"},{"location":"manual/control-flow/","page":"流程控制","title":"流程控制","text":"前五个流程控制机制是高级编程语言的标准。Task 不是那么的标准:它提供了非局部的流程控制,这使得在暂时挂起的计算任务之间进行切换成为可能。这是一个功能强大的构件:Julia 中的异常处理和协同多任务都是通过 Task 实现的。虽然日常编程并不需要直接使用 Task,但某些问题用 Task 处理会更加简单。","category":"page"},{"location":"manual/control-flow/#man-compound-expressions","page":"流程控制","title":"复合表达式","text":"","category":"section"},{"location":"manual/control-flow/","page":"流程控制","title":"流程控制","text":"有时一个表达式能够有序地计算若干子表达式,并返回最后一个子表达式的值作为它的值是很方便的。Julia 有两个组件来完成这个: begin 代码块 和 ; 链。这两个复合表达式组件的值都是最后一个子表达式的值。下面是一个 begin 代码块的例子:","category":"page"},{"location":"manual/control-flow/","page":"流程控制","title":"流程控制","text":"julia> z = begin\n x = 1\n y = 2\n x + y\n end\n3","category":"page"},{"location":"manual/control-flow/","page":"流程控制","title":"流程控制","text":"因为这些是非常简短的表达式,它们可以简单地被放到一行里,这也是 ; 链的由来:","category":"page"},{"location":"manual/control-flow/","page":"流程控制","title":"流程控制","text":"julia> z = (x = 1; y = 2; x + y)\n3","category":"page"},{"location":"manual/control-flow/","page":"流程控制","title":"流程控制","text":"这个语法在定义简洁的单行函数的时候特别有用,参见函数。尽管很典型,但是并不要求 begin 代码块是多行的,或者 ; 链是单行的:","category":"page"},{"location":"manual/control-flow/","page":"流程控制","title":"流程控制","text":"julia> begin x = 1; y = 2; x + y end\n3\n\njulia> (x = 1;\n y = 2;\n x + y)\n3","category":"page"},{"location":"manual/control-flow/#man-conditional-evaluation","page":"流程控制","title":"条件表达式","text":"","category":"section"},{"location":"manual/control-flow/","page":"流程控制","title":"流程控制","text":"条件表达式(Conditional evaluation)可以根据布尔表达式的值,让部分代码被执行或者不被执行。下面是对 if-elseif-else 条件语法的分析:","category":"page"},{"location":"manual/control-flow/","page":"流程控制","title":"流程控制","text":"if x < y\n println(\"x is less than y\")\nelseif x > y\n println(\"x is greater than y\")\nelse\n println(\"x is equal to y\")\nend","category":"page"},{"location":"manual/control-flow/","page":"流程控制","title":"流程控制","text":"如果表达式 x < y 是 true,那么对应的代码块会被执行;否则判断条件表达式 x > y,如果它是 true,则执行对应的代码块;如果没有表达式是 true,则执行 else 代码块。下面是一个例子:","category":"page"},{"location":"manual/control-flow/","page":"流程控制","title":"流程控制","text":"julia> function test(x, y)\n if x < y\n println(\"x is less than y\")\n elseif x > y\n println(\"x is greater than y\")\n else\n println(\"x is equal to y\")\n end\n end\ntest (generic function with 1 method)\n\njulia> test(1, 2)\nx is less than y\n\njulia> test(2, 1)\nx is greater than y\n\njulia> test(1, 1)\nx is equal to y","category":"page"},{"location":"manual/control-flow/","page":"流程控制","title":"流程控制","text":"elseif 和 else 代码块是可选的,并且可以使用任意多个 elseif 代码块。 if-elseif-else 组件中的第一个条件表达式为 true 时,其他条件表达式才会被执行,当对应的代码块被执行后,其余的表达式或者代码块将不会被执行。","category":"page"},{"location":"manual/control-flow/","page":"流程控制","title":"流程控制","text":"if 代码块是\"有渗漏的\",也就是说它们不会引入局部作用域。这意味着在 if 语句中新定义的变量依然可以在 if 代码块之后使用,尽管这些变量没有在 if 语句之前定义过。所以,我们可以将上面的 test 函数定义为","category":"page"},{"location":"manual/control-flow/","page":"流程控制","title":"流程控制","text":"julia> function test(x,y)\n if x < y\n relation = \"less than\"\n elseif x == y\n relation = \"equal to\"\n else\n relation = \"greater than\"\n end\n println(\"x is \", relation, \" y.\")\n end\ntest (generic function with 1 method)\n\njulia> test(2, 1)\nx is greater than y.","category":"page"},{"location":"manual/control-flow/","page":"流程控制","title":"流程控制","text":"变量 relation 是在 if 代码块内部声明的,但可以在外部使用。然而,在利用这种行为的时候,要保证变量在所有的分支下都进行了定义。对上述函数做如下修改会导致运行时错误","category":"page"},{"location":"manual/control-flow/","page":"流程控制","title":"流程控制","text":"julia> function test(x,y)\n if x < y\n relation = \"less than\"\n elseif x == y\n relation = \"equal to\"\n end\n println(\"x is \", relation, \" y.\")\n end\ntest (generic function with 1 method)\n\njulia> test(1,2)\nx is less than y.\n\njulia> test(2,1)\nERROR: UndefVarError: relation not defined\nStacktrace:\n [1] test(::Int64, ::Int64) at ./none:7","category":"page"},{"location":"manual/control-flow/","page":"流程控制","title":"流程控制","text":"if 代码块也会返回一个值,这可能对于一些从其他语言转过来的用户来说不是很直观。 这个返回值就是被执行的分支中最后一个被执行的语句的返回值。 所以","category":"page"},{"location":"manual/control-flow/","page":"流程控制","title":"流程控制","text":"julia> x = 3\n3\n\njulia> if x > 0\n \"positive!\"\n else\n \"negative...\"\n end\n\"positive!\"","category":"page"},{"location":"manual/control-flow/","page":"流程控制","title":"流程控制","text":"需要注意的是,在 Julia 中,经常会用短路求值来表示非常短的条件表达式(单行),这会在下一节中介绍。","category":"page"},{"location":"manual/control-flow/","page":"流程控制","title":"流程控制","text":"与 C, MATLAB, Perl, Python,以及 Ruby 不同,但跟 Java,还有一些别的严谨的类型语言类似:一个条件表达式的值如果不是 true 或者 false 的话,会返回错误:","category":"page"},{"location":"manual/control-flow/","page":"流程控制","title":"流程控制","text":"julia> if 1\n println(\"true\")\n end\nERROR: TypeError: non-boolean (Int64) used in boolean context","category":"page"},{"location":"manual/control-flow/","page":"流程控制","title":"流程控制","text":"这个错误是说,条件判断结果的类型:Int64 是错的,而不是期望的 Bool。","category":"page"},{"location":"manual/control-flow/","page":"流程控制","title":"流程控制","text":"所谓的 \"三元运算符\", ?:,很类似 if-elseif-else 语法,它用于选择性获取单个表达式的值,而不是选择性执行大段的代码块。它因在很多语言中是唯一一个有三个操作数的运算符而得名:","category":"page"},{"location":"manual/control-flow/","page":"流程控制","title":"流程控制","text":"a ? b : c","category":"page"},{"location":"manual/control-flow/","page":"流程控制","title":"流程控制","text":"在 ? 之前的表达式 a, 是一个条件表达式,如果条件 a 是 true,三元运算符计算在 : 之前的表达式 b;如果条件 a 是 false,则执行 : 后面的表达式 c。注意,? 和 : 旁边的空格是强制的,像 a?b:c 这种表达式不是一个有效的三元表达式(但在? 和 : 之后的换行是允许的)。","category":"page"},{"location":"manual/control-flow/","page":"流程控制","title":"流程控制","text":"理解这种行为的最简单方式是看一个实际的例子。在前一个例子中,虽然在三个分支中都有调用 println,但实质上是选择打印哪一个字符串。在这种情况下,我们可以用三元运算符更紧凑地改写。为了简明,我们先尝试只有两个分支的版本:","category":"page"},{"location":"manual/control-flow/","page":"流程控制","title":"流程控制","text":"julia> x = 1; y = 2;\n\njulia> println(x < y ? \"less than\" : \"not less than\")\nless than\n\njulia> x = 1; y = 0;\n\njulia> println(x < y ? \"less than\" : \"not less than\")\nnot less than","category":"page"},{"location":"manual/control-flow/","page":"流程控制","title":"流程控制","text":"如果表达式 x < y 为真,整个三元运算符会执行字符串 \"less than\",否则执行字符串 \"not less than\"。原本的三个分支的例子需要链式嵌套使用三元运算符:","category":"page"},{"location":"manual/control-flow/","page":"流程控制","title":"流程控制","text":"julia> test(x, y) = println(x < y ? \"x is less than y\" :\n x > y ? \"x is greater than y\" : \"x is equal to y\")\ntest (generic function with 1 method)\n\njulia> test(1, 2)\nx is less than y\n\njulia> test(2, 1)\nx is greater than y\n\njulia> test(1, 1)\nx is equal to y","category":"page"},{"location":"manual/control-flow/","page":"流程控制","title":"流程控制","text":"为了方便链式传值,运算符从右到左连接到一起。","category":"page"},{"location":"manual/control-flow/","page":"流程控制","title":"流程控制","text":"重要地是,与 if-elseif-else 类似,: 之前和之后的表达式只有在条件表达式为 true 或者 false 时才会被相应地执行:","category":"page"},{"location":"manual/control-flow/","page":"流程控制","title":"流程控制","text":"julia> v(x) = (println(x); x)\nv (generic function with 1 method)\n\njulia> 1 < 2 ? v(\"yes\") : v(\"no\")\nyes\n\"yes\"\n\njulia> 1 > 2 ? v(\"yes\") : v(\"no\")\nno\n\"no\"","category":"page"},{"location":"manual/control-flow/#短路求值","page":"流程控制","title":"短路求值","text":"","category":"section"},{"location":"manual/control-flow/","page":"流程控制","title":"流程控制","text":"Julia 中的 && 和 || 运算符分别对应于逻辑“与”和“或”操作,并通常都这样使用。 但是,它们具有 逻辑短路 的特殊性质:不一定评估其第二个参数,下面会详细介绍。 (也有按位 & 和 | 运算符可用作逻辑“与”和“或”的无短路行为,但要注意 & 和 | 的评估时的优先级高于 && 和 || 。)","category":"page"},{"location":"manual/control-flow/","page":"流程控制","title":"流程控制","text":"短路求值与条件求值非常相似。 这种行为在大多数具有 && 和 || 布尔运算符的命令式编程语言中都可以找到:在一系列由这些运算符连接的布尔表达式中,为了得到整个链的最终布尔值,仅仅只有最小数量的表达式被计算。 一些语言(如 Python)将它们称为and(&&)和or(||)。 更准确地说,这意味着:","category":"page"},{"location":"manual/control-flow/","page":"流程控制","title":"流程控制","text":"在表达式 a && b 中,子表达式 b 仅当 a 为 true 的时候才会被执行。\n在表达式 a || b 中,子表达式 b 仅在 a 为 false 的时候才会被执行。","category":"page"},{"location":"manual/control-flow/","page":"流程控制","title":"流程控制","text":"这里的原因是:如果 a 是 false,那么无论 b 的值是多少,a && b 一定是 false。同理,如果 a 是 true,那么无论 b 的值是多少,a || b 的值一定是 true。&& 和 || 都依赖于右边,但是 && 比 || 有更高的优先级。我们可以简单地测试一下这个行为:","category":"page"},{"location":"manual/control-flow/","page":"流程控制","title":"流程控制","text":"julia> t(x) = (println(x); true)\nt (generic function with 1 method)\n\njulia> f(x) = (println(x); false)\nf (generic function with 1 method)\n\njulia> t(1) && t(2)\n1\n2\ntrue\n\njulia> t(1) && f(2)\n1\n2\nfalse\n\njulia> f(1) && t(2)\n1\nfalse\n\njulia> f(1) && f(2)\n1\nfalse\n\njulia> t(1) || t(2)\n1\ntrue\n\njulia> t(1) || f(2)\n1\ntrue\n\njulia> f(1) || t(2)\n1\n2\ntrue\n\njulia> f(1) || f(2)\n1\n2\nfalse","category":"page"},{"location":"manual/control-flow/","page":"流程控制","title":"流程控制","text":"你可以用同样的方式测试不同 && 和 || 运算符的组合条件下的关联和优先级。","category":"page"},{"location":"manual/control-flow/","page":"流程控制","title":"流程控制","text":"这种行为在 Julia 中经常被用来作为简短 if 语句的替代。 可以用 && (可读为: and then )来替换 if end。 类似的, 可以用 || (可读为: or else )来替换 if ! end.","category":"page"},{"location":"manual/control-flow/","page":"流程控制","title":"流程控制","text":"例如,可以像这样定义递归阶乘:","category":"page"},{"location":"manual/control-flow/","page":"流程控制","title":"流程控制","text":"julia> function fact(n::Int)\n n >= 0 || error(\"n must be non-negative\")\n n == 0 && return 1\n n * fact(n-1)\n end\nfact (generic function with 1 method)\n\njulia> fact(5)\n120\n\njulia> fact(0)\n1\n\njulia> fact(-1)\nERROR: n must be non-negative\nStacktrace:\n [1] error at ./error.jl:33 [inlined]\n [2] fact(::Int64) at ./none:2\n [3] top-level scope","category":"page"},{"location":"manual/control-flow/","page":"流程控制","title":"流程控制","text":"无短路求值的布尔运算可以用位布尔运算符来完成,见数学运算和初等函数:& 和 |。这些是普通的函数,同时也刚好支持中缀运算符语法,但总是会计算它们的所有参数:","category":"page"},{"location":"manual/control-flow/","page":"流程控制","title":"流程控制","text":"julia> f(1) & t(2)\n1\n2\nfalse\n\njulia> t(1) | t(2)\n1\n2\ntrue","category":"page"},{"location":"manual/control-flow/","page":"流程控制","title":"流程控制","text":"与 if, elseif 或者三元运算符中的条件表达式相同,&& 或者 || 的操作数必须是布尔值(true 或者 false)。在链式嵌套的条件表达式中, 除最后一项外,使用非布尔值会导致错误:","category":"page"},{"location":"manual/control-flow/","page":"流程控制","title":"流程控制","text":"julia> 1 && true\nERROR: TypeError: non-boolean (Int64) used in boolean context","category":"page"},{"location":"manual/control-flow/","page":"流程控制","title":"流程控制","text":"但在链的末尾允许使用任意类型的表达式,此表达式会根据前面的条件被执行并返回:","category":"page"},{"location":"manual/control-flow/","page":"流程控制","title":"流程控制","text":"julia> true && (x = (1, 2, 3))\n(1, 2, 3)\n\njulia> false && (x = (1, 2, 3))\nfalse","category":"page"},{"location":"manual/control-flow/#man-loops","page":"流程控制","title":"重复执行:循环","text":"","category":"section"},{"location":"manual/control-flow/","page":"流程控制","title":"流程控制","text":"有两个用于重复执行表达式的组件:while 循环和 for 循环。下面是一个 while 循环的例子:","category":"page"},{"location":"manual/control-flow/","page":"流程控制","title":"流程控制","text":"julia> i = 1;\n\njulia> while i <= 5\n println(i)\n global i += 1\n end\n1\n2\n3\n4\n5","category":"page"},{"location":"manual/control-flow/","page":"流程控制","title":"流程控制","text":"while 循环会执行条件表达式(例子中为 i <= 5),只要它为 true,就一直执行while 循环的主体部分。当 while 循环第一次执行时,如果条件表达式为 false,那么主体代码就一次也不会被执行。","category":"page"},{"location":"manual/control-flow/","page":"流程控制","title":"流程控制","text":"for 循环使得常见的重复执行代码写起来更容易。 像之前 while 循环中用到的向上和向下计数是可以用 for 循环更简明地表达:","category":"page"},{"location":"manual/control-flow/","page":"流程控制","title":"流程控制","text":"julia> for i = 1:5\n println(i)\n end\n1\n2\n3\n4\n5","category":"page"},{"location":"manual/control-flow/","page":"流程控制","title":"流程控制","text":"这里的 1:5 是一个范围对象,代表数字 1, 2, 3, 4, 5 的序列。for 循环在这些值之中迭代,对每一个变量 i 进行赋值。for 循环与之前 while 循环的一个非常重要区别是作用域,即变量的可见性。如果变量 i 没有在另一个作用域里引入,在 for 循环内,它就只在 for 循环内部可见,在外部和后面均不可见。你需要一个新的交互式会话实例或者一个新的变量名来测试这个特性:","category":"page"},{"location":"manual/control-flow/","page":"流程控制","title":"流程控制","text":"julia> for j = 1:5\n println(j)\n end\n1\n2\n3\n4\n5\n\njulia> j\nERROR: UndefVarError: j not defined","category":"page"},{"location":"manual/control-flow/","page":"流程控制","title":"流程控制","text":"参见变量作用域中对变量作用域的详细解释以及它在 Julia 中是如何工作的。","category":"page"},{"location":"manual/control-flow/","page":"流程控制","title":"流程控制","text":"一般来说,for 循环组件可以用于迭代任一个容器。在这种情况下,相比 =,另外的(但完全相同)关键字 in 或者 ∈ 则更常用,因为它使得代码更清晰:","category":"page"},{"location":"manual/control-flow/","page":"流程控制","title":"流程控制","text":"julia> for i in [1,4,0]\n println(i)\n end\n1\n4\n0\n\njulia> for s ∈ [\"foo\",\"bar\",\"baz\"]\n println(s)\n end\nfoo\nbar\nbaz","category":"page"},{"location":"manual/control-flow/","page":"流程控制","title":"流程控制","text":"在手册后面的章节中会介绍和讨论各种不同的迭代容器(比如,多维数组)。","category":"page"},{"location":"manual/control-flow/","page":"流程控制","title":"流程控制","text":"为了方便,我们可能会在测试条件不成立之前终止一个 while 循环,或者在访问到迭代对象的结尾之前停止一个 for 循环,这可以用关键字 break 来完成:","category":"page"},{"location":"manual/control-flow/","page":"流程控制","title":"流程控制","text":"julia> i = 1;\n\njulia> while true\n println(i)\n if i >= 5\n break\n end\n global i += 1\n end\n1\n2\n3\n4\n5\n\njulia> for j = 1:1000\n println(j)\n if j >= 5\n break\n end\n end\n1\n2\n3\n4\n5","category":"page"},{"location":"manual/control-flow/","page":"流程控制","title":"流程控制","text":"没有关键字 break 的话,上面的 while 循环永远不会自己结束,而 for 循环会迭代到 1000,这些循环都可以使用 break 来提前结束。","category":"page"},{"location":"manual/control-flow/","page":"流程控制","title":"流程控制","text":"在某些场景下,需要直接结束此次迭代,并立刻进入下次迭代,continue 关键字可以用来完成此功能:","category":"page"},{"location":"manual/control-flow/","page":"流程控制","title":"流程控制","text":"julia> for i = 1:10\n if i % 3 != 0\n continue\n end\n println(i)\n end\n3\n6\n9","category":"page"},{"location":"manual/control-flow/","page":"流程控制","title":"流程控制","text":"这是一个有点做作的例子,因为我们可以通过否定这个条件,把 println 调用放到 if 代码块里来更简洁的实现同样的功能。在实际应用中,在 continue 后面还会有更多的代码要运行,并且调用 continue 的地方可能会有多个。","category":"page"},{"location":"manual/control-flow/","page":"流程控制","title":"流程控制","text":"多个嵌套的 for 循环可以合并到一个外部循环,可以用来创建其迭代对象的笛卡尔积:","category":"page"},{"location":"manual/control-flow/","page":"流程控制","title":"流程控制","text":"julia> for i = 1:2, j = 3:4\n println((i, j))\n end\n(1, 3)\n(1, 4)\n(2, 3)\n(2, 4)","category":"page"},{"location":"manual/control-flow/","page":"流程控制","title":"流程控制","text":"有了这个语法,迭代变量依然可以正常使用循环变量来进行索引,例如 for i = 1:n, j = 1:i 是合法的,但是在一个循环里面使用 break 语句则会跳出整个嵌套循环,不仅仅是内层循环。每次内层循环运行的时候,变量(i 和 j)会被赋值为他们当前的迭代变量值。所以对 i 的赋值对于接下来的迭代是不可见的:","category":"page"},{"location":"manual/control-flow/","page":"流程控制","title":"流程控制","text":"julia> for i = 1:2, j = 3:4\n println((i, j))\n i = 0\n end\n(1, 3)\n(1, 4)\n(2, 3)\n(2, 4)","category":"page"},{"location":"manual/control-flow/","page":"流程控制","title":"流程控制","text":"如果这个例子给每个变量一个关键字 for 来重写,那么输出会不一样:第二个和第四个变量包含 0。","category":"page"},{"location":"manual/control-flow/","page":"流程控制","title":"流程控制","text":"可以使用 zip 在单个 for 循环中同时迭代多个容器:","category":"page"},{"location":"manual/control-flow/","page":"流程控制","title":"流程控制","text":"julia> for (j, k) in zip([1 2 3], [4 5 6 7])\n println((j,k))\n end\n(1, 4)\n(2, 5)\n(3, 6)","category":"page"},{"location":"manual/control-flow/","page":"流程控制","title":"流程控制","text":"使用 zip 将创建一个迭代器,它是一个包含传递给它的容器的子迭代器的元组。 zip 迭代器将按顺序迭代所有子迭代器,在 for 循环的第 i 次迭代中选择每个子迭代器的第 i 个元素。 一旦任何子迭代器用完,for 循环就会停止。","category":"page"},{"location":"manual/control-flow/#异常处理","page":"流程控制","title":"异常处理","text":"","category":"section"},{"location":"manual/control-flow/","page":"流程控制","title":"流程控制","text":"当一个意外条件发生时,一个函数可能无法向调用者返回一个合理的值。在这种情况下,最好让意外条件终止程序并打印出调试的错误信息,或者根据程序员预先提供的异常处理代码来采取恰当的措施。","category":"page"},{"location":"manual/control-flow/#内置的-Exception","page":"流程控制","title":"内置的 Exception","text":"","category":"section"},{"location":"manual/control-flow/","page":"流程控制","title":"流程控制","text":"当一个意外的情况发生时,会抛出 Exception。下面列出的内置 Exception 都会中断正常的控制流程。","category":"page"},{"location":"manual/control-flow/","page":"流程控制","title":"流程控制","text":"Exception\nArgumentError\nBoundsError\nCompositeException\nDimensionMismatch\nDivideError\nDomainError\nEOFError\nErrorException\nInexactError\nInitError\nInterruptException\nInvalidStateException\nKeyError\nLoadError\nOutOfMemoryError\nReadOnlyMemoryError\nRemoteException\nMethodError\nOverflowError\nMeta.ParseError\nSystemError\nTypeError\nUndefRefError\nUndefVarError\nStringIndexError","category":"page"},{"location":"manual/control-flow/","page":"流程控制","title":"流程控制","text":"例如,当输入参数为负实数时,sqrt 函数会抛出一个 DomainError :","category":"page"},{"location":"manual/control-flow/","page":"流程控制","title":"流程控制","text":"julia> sqrt(-1)\nERROR: DomainError with -1.0:\nsqrt will only return a complex result if called with a complex argument. Try sqrt(Complex(x)).\nStacktrace:\n[...]","category":"page"},{"location":"manual/control-flow/","page":"流程控制","title":"流程控制","text":"你可能需要根据下面的方式来定义你自己的异常:","category":"page"},{"location":"manual/control-flow/","page":"流程控制","title":"流程控制","text":"julia> struct MyCustomException <: Exception end","category":"page"},{"location":"manual/control-flow/#[throw](@ref)-函数","page":"流程控制","title":"throw 函数","text":"","category":"section"},{"location":"manual/control-flow/","page":"流程控制","title":"流程控制","text":"我们可以用 throw 显式地创建异常。例如,若一个函数只对非负数有定义,当输入参数是负数的时候,可以用 throw 抛出一个 DomainError。","category":"page"},{"location":"manual/control-flow/","page":"流程控制","title":"流程控制","text":"julia> f(x) = x>=0 ? exp(-x) : throw(DomainError(x, \"argument must be nonnegative\"))\nf (generic function with 1 method)\n\njulia> f(1)\n0.36787944117144233\n\njulia> f(-1)\nERROR: DomainError with -1:\nargument must be nonnegative\nStacktrace:\n [1] f(::Int64) at ./none:1","category":"page"},{"location":"manual/control-flow/","page":"流程控制","title":"流程控制","text":"注意 DomainError 后面不接括号的话不是一个异常,而是一个异常类型。我们需要调用它来获得一个 Exception 对象:","category":"page"},{"location":"manual/control-flow/","page":"流程控制","title":"流程控制","text":"julia> typeof(DomainError(nothing)) <: Exception\ntrue\n\njulia> typeof(DomainError) <: Exception\nfalse","category":"page"},{"location":"manual/control-flow/","page":"流程控制","title":"流程控制","text":"另外,一些异常类型会接受一个或多个参数来进行错误报告:","category":"page"},{"location":"manual/control-flow/","page":"流程控制","title":"流程控制","text":"julia> throw(UndefVarError(:x))\nERROR: UndefVarError: x not defined","category":"page"},{"location":"manual/control-flow/","page":"流程控制","title":"流程控制","text":"我们可以仿照 UndefVarError 的写法,用自定义异常类型来轻松实现这个机制:","category":"page"},{"location":"manual/control-flow/","page":"流程控制","title":"流程控制","text":"julia> struct MyUndefVarError <: Exception\n var::Symbol\n end\n\njulia> Base.showerror(io::IO, e::MyUndefVarError) = print(io, e.var, \" not defined\")","category":"page"},{"location":"manual/control-flow/","page":"流程控制","title":"流程控制","text":"note: Note\n错误信息的第一个单词最好用小写。例如:size(A) == size(B) || throw(DimensionMismatch(\"size of A not equal to size of B\"))就比size(A) == size(B) || throw(DimensionMismatch(\"Size of A not equal to size of B\")).更好。但是,有时保留大写首字母是有意义的,例如函数的参数就是大写字母时:size(A,1) == size(B,2) || throw(DimensionMismatch(\"A has first dimension...\")).","category":"page"},{"location":"manual/control-flow/#错误","page":"流程控制","title":"错误","text":"","category":"section"},{"location":"manual/control-flow/","page":"流程控制","title":"流程控制","text":"我们可以用 error 函数生成一个 ErrorException 来中断正常的控制流程。","category":"page"},{"location":"manual/control-flow/","page":"流程控制","title":"流程控制","text":"假设我们希望在计算负数的平方根时让程序立即停止执行。为了实现它,我们可以定义一个挑剔的 sqrt 函数,当它的参数是负数时,产生一个错误:","category":"page"},{"location":"manual/control-flow/","page":"流程控制","title":"流程控制","text":"julia> fussy_sqrt(x) = x >= 0 ? sqrt(x) : error(\"negative x not allowed\")\nfussy_sqrt (generic function with 1 method)\n\njulia> fussy_sqrt(2)\n1.4142135623730951\n\njulia> fussy_sqrt(-1)\nERROR: negative x not allowed\nStacktrace:\n [1] error at ./error.jl:33 [inlined]\n [2] fussy_sqrt(::Int64) at ./none:1\n [3] top-level scope","category":"page"},{"location":"manual/control-flow/","page":"流程控制","title":"流程控制","text":"如果另一个函数调用 fussy_sqrt 和一个负数, 它会立马返回, 在交互会话中显示错误信息,而不会继续执行调用的函数:","category":"page"},{"location":"manual/control-flow/","page":"流程控制","title":"流程控制","text":"julia> function verbose_fussy_sqrt(x)\n println(\"before fussy_sqrt\")\n r = fussy_sqrt(x)\n println(\"after fussy_sqrt\")\n return r\n end\nverbose_fussy_sqrt (generic function with 1 method)\n\njulia> verbose_fussy_sqrt(2)\nbefore fussy_sqrt\nafter fussy_sqrt\n1.4142135623730951\n\njulia> verbose_fussy_sqrt(-1)\nbefore fussy_sqrt\nERROR: negative x not allowed\nStacktrace:\n [1] error at ./error.jl:33 [inlined]\n [2] fussy_sqrt at ./none:1 [inlined]\n [3] verbose_fussy_sqrt(::Int64) at ./none:3\n [4] top-level scope","category":"page"},{"location":"manual/control-flow/#try/catch-语句","page":"流程控制","title":"try/catch 语句","text":"","category":"section"},{"location":"manual/control-flow/","page":"流程控制","title":"流程控制","text":"通过 try / catch 语句,可以测试 Exception 并 优雅处理可能会破坏应用程序的事情。 例如, 在下面的代码中,平方根函数会引发异常。 通过 在其周围放置 try / catch 块可以缓解。 您可以选择如何 处理此异常,无论是记录它,返回占位符值还是 就像下面仅打印一句话。 要注意的是 在决定如何处理异常时,使用try / catch 块 比使用条件分支处理要慢得多。 以下是使用try / catch 块处理异常的更多示例:","category":"page"},{"location":"manual/control-flow/","page":"流程控制","title":"流程控制","text":"julia> try\nsqrt(\"ten\")\ncatch e\nprintln(\"You should have entered a numeric value\")\nend\nYou should have entered a numeric value","category":"page"},{"location":"manual/control-flow/","page":"流程控制","title":"流程控制","text":"try/catch 语句允许保存 Exception 到一个变量中。在下面这个做作的例子中,如果 x 是可索引的,则计算 x 的第二项的平方根,否则就假设 x 是一个实数,并返回它的平方根:","category":"page"},{"location":"manual/control-flow/","page":"流程控制","title":"流程控制","text":"julia> sqrt_second(x) = try\n sqrt(x[2])\n catch y\n if isa(y, DomainError)\n sqrt(complex(x[2], 0))\n elseif isa(y, BoundsError)\n sqrt(x)\n end\n end\nsqrt_second (generic function with 1 method)\n\njulia> sqrt_second([1 4])\n2.0\n\njulia> sqrt_second([1 -4])\n0.0 + 2.0im\n\njulia> sqrt_second(9)\n3.0\n\njulia> sqrt_second(-9)\nERROR: DomainError with -9.0:\nsqrt will only return a complex result if called with a complex argument. Try sqrt(Complex(x)).\nStacktrace:\n[...]","category":"page"},{"location":"manual/control-flow/","page":"流程控制","title":"流程控制","text":"注意 catch 后面的字符会被一直认为是异常的名字,所以在写 try/catch 单行表达式时,需要特别小心。下面的代码不会在错误的情况下返回 x 的值:","category":"page"},{"location":"manual/control-flow/","page":"流程控制","title":"流程控制","text":"try bad() catch x end","category":"page"},{"location":"manual/control-flow/","page":"流程控制","title":"流程控制","text":"正确的做法是在 catch 后添加一个分号或者直接换行:","category":"page"},{"location":"manual/control-flow/","page":"流程控制","title":"流程控制","text":"try bad() catch; x end\n\ntry bad()\ncatch\n x\nend","category":"page"},{"location":"manual/control-flow/","page":"流程控制","title":"流程控制","text":"try/catch 结构的强大之处在于能够立即将深度嵌套的计算展开到调用函数堆栈中的更高级别。 在某些情况下,没有发生错误,但需要能够展开堆栈并将值传递到更高级别。 Julia 提供了 rethrow、backtrace、catch_backtrace 和 current_exceptions 函数来进行更高级的错误处理。","category":"page"},{"location":"manual/control-flow/#finally-子句","page":"流程控制","title":"finally 子句","text":"","category":"section"},{"location":"manual/control-flow/","page":"流程控制","title":"流程控制","text":"在进行状态改变或者使用类似文件的资源的编程时,经常需要在代码结束的时候进行必要的清理工作(比如关闭文件)。由于异常会使得部分代码块在正常结束之前退出,所以可能会让上述工作变得复杂。finally 关键字提供了一种方式,无论代码块是如何退出的,都能够让代码块在退出时运行某段代码。","category":"page"},{"location":"manual/control-flow/","page":"流程控制","title":"流程控制","text":"这里是一个确保一个打开的文件被关闭的例子:","category":"page"},{"location":"manual/control-flow/","page":"流程控制","title":"流程控制","text":"f = open(\"file\")\ntry\n # operate on file f\nfinally\n close(f)\nend","category":"page"},{"location":"manual/control-flow/","page":"流程控制","title":"流程控制","text":"当控制流离开 try 代码块(例如,遇到 return,或者正常结束),close(f) 就会被执行。如果 try 代码块由于异常退出,这个异常会继续传递。catch 代码块可以和 try 还有 finally 配合使用。这时 finally 代码块会在 catch 处理错误之后才运行。","category":"page"},{"location":"manual/control-flow/#man-tasks","page":"流程控制","title":" Tasks 任务(或协程)","text":"","category":"section"},{"location":"manual/control-flow/","page":"流程控制","title":"流程控制","text":"Task 是一种允许计算以更灵活的方式被中断或者恢复的流程控制特性。 我们提及它只是为了说明的完整性;详细的介绍参见:异步编程。","category":"page"},{"location":"devdocs/meta/#Talking-to-the-compiler-(the-:meta-mechanism)","page":"Talking to the compiler (the :meta mechanism)","title":"Talking to the compiler (the :meta mechanism)","text":"","category":"section"},{"location":"devdocs/meta/","page":"Talking to the compiler (the :meta mechanism)","title":"Talking to the compiler (the :meta mechanism)","text":"In some circumstances, one might wish to provide hints or instructions that a given block of code has special properties: you might always want to inline it, or you might want to turn on special compiler optimization passes. Starting with version 0.4, Julia has a convention that these instructions can be placed inside a :meta expression, which is typically (but not necessarily) the first expression in the body of a function.","category":"page"},{"location":"devdocs/meta/","page":"Talking to the compiler (the :meta mechanism)","title":"Talking to the compiler (the :meta mechanism)","text":":meta expressions are created with macros. As an example, consider the implementation of the @inline macro:","category":"page"},{"location":"devdocs/meta/","page":"Talking to the compiler (the :meta mechanism)","title":"Talking to the compiler (the :meta mechanism)","text":"macro inline(ex)\n esc(isa(ex, Expr) ? pushmeta!(ex, :inline) : ex)\nend","category":"page"},{"location":"devdocs/meta/","page":"Talking to the compiler (the :meta mechanism)","title":"Talking to the compiler (the :meta mechanism)","text":"Here, ex is expected to be an expression defining a function. A statement like this:","category":"page"},{"location":"devdocs/meta/","page":"Talking to the compiler (the :meta mechanism)","title":"Talking to the compiler (the :meta mechanism)","text":"@inline function myfunction(x)\n x*(x+3)\nend","category":"page"},{"location":"devdocs/meta/","page":"Talking to the compiler (the :meta mechanism)","title":"Talking to the compiler (the :meta mechanism)","text":"gets turned into an expression like this:","category":"page"},{"location":"devdocs/meta/","page":"Talking to the compiler (the :meta mechanism)","title":"Talking to the compiler (the :meta mechanism)","text":"quote\n function myfunction(x)\n Expr(:meta, :inline)\n x*(x+3)\n end\nend","category":"page"},{"location":"devdocs/meta/","page":"Talking to the compiler (the :meta mechanism)","title":"Talking to the compiler (the :meta mechanism)","text":"Base.pushmeta!(ex, :symbol, args...) appends :symbol to the end of the :meta expression, creating a new :meta expression if necessary. If args is specified, a nested expression containing :symbol and these arguments is appended instead, which can be used to specify additional information.","category":"page"},{"location":"devdocs/meta/","page":"Talking to the compiler (the :meta mechanism)","title":"Talking to the compiler (the :meta mechanism)","text":"To use the metadata, you have to parse these :meta expressions. If your implementation can be performed within Julia, Base.popmeta! is very handy: Base.popmeta!(body, :symbol) will scan a function body expression (one without the function signature) for the first :meta expression containing :symbol, extract any arguments, and return a tuple (found::Bool, args::Array{Any}). If the metadata did not have any arguments, or :symbol was not found, the args array will be empty.","category":"page"},{"location":"devdocs/meta/","page":"Talking to the compiler (the :meta mechanism)","title":"Talking to the compiler (the :meta mechanism)","text":"Not yet provided is a convenient infrastructure for parsing :meta expressions from C++.","category":"page"},{"location":"devdocs/stdio/#printf()-and-stdio-in-the-Julia-runtime","page":"printf() and stdio in the Julia runtime","title":"printf() and stdio in the Julia runtime","text":"","category":"section"},{"location":"devdocs/stdio/#Libuv-wrappers-for-stdio","page":"printf() and stdio in the Julia runtime","title":"Libuv wrappers for stdio","text":"","category":"section"},{"location":"devdocs/stdio/","page":"printf() and stdio in the Julia runtime","title":"printf() and stdio in the Julia runtime","text":"julia.h defines libuv wrappers for the stdio.h streams:","category":"page"},{"location":"devdocs/stdio/","page":"printf() and stdio in the Julia runtime","title":"printf() and stdio in the Julia runtime","text":"uv_stream_t *JL_STDIN;\nuv_stream_t *JL_STDOUT;\nuv_stream_t *JL_STDERR;","category":"page"},{"location":"devdocs/stdio/","page":"printf() and stdio in the Julia runtime","title":"printf() and stdio in the Julia runtime","text":"... and corresponding output functions:","category":"page"},{"location":"devdocs/stdio/","page":"printf() and stdio in the Julia runtime","title":"printf() and stdio in the Julia runtime","text":"int jl_printf(uv_stream_t *s, const char *format, ...);\nint jl_vprintf(uv_stream_t *s, const char *format, va_list args);","category":"page"},{"location":"devdocs/stdio/","page":"printf() and stdio in the Julia runtime","title":"printf() and stdio in the Julia runtime","text":"These printf functions are used by the .c files in the src/ and cli/ directories wherever stdio is needed to ensure that output buffering is handled in a unified way.","category":"page"},{"location":"devdocs/stdio/","page":"printf() and stdio in the Julia runtime","title":"printf() and stdio in the Julia runtime","text":"In special cases, like signal handlers, where the full libuv infrastructure is too heavy, jl_safe_printf() can be used to write(2) directly to STDERR_FILENO:","category":"page"},{"location":"devdocs/stdio/","page":"printf() and stdio in the Julia runtime","title":"printf() and stdio in the Julia runtime","text":"void jl_safe_printf(const char *str, ...);","category":"page"},{"location":"devdocs/stdio/#Interface-between-JL_STD*-and-Julia-code","page":"printf() and stdio in the Julia runtime","title":"Interface between JL_STD* and Julia code","text":"","category":"section"},{"location":"devdocs/stdio/","page":"printf() and stdio in the Julia runtime","title":"printf() and stdio in the Julia runtime","text":"Base.stdin, Base.stdout and Base.stderr are bound to the JL_STD* libuv streams defined in the runtime.","category":"page"},{"location":"devdocs/stdio/","page":"printf() and stdio in the Julia runtime","title":"printf() and stdio in the Julia runtime","text":"Julia's __init__() function (in base/sysimg.jl) calls reinit_stdio() (in base/stream.jl) to create Julia objects for Base.stdin, Base.stdout and Base.stderr.","category":"page"},{"location":"devdocs/stdio/","page":"printf() and stdio in the Julia runtime","title":"printf() and stdio in the Julia runtime","text":"reinit_stdio() uses ccall to retrieve pointers to JL_STD* and calls jl_uv_handle_type() to inspect the type of each stream. It then creates a Julia Base.IOStream, Base.TTY or Base.PipeEndpoint object to represent each stream, e.g.:","category":"page"},{"location":"devdocs/stdio/","page":"printf() and stdio in the Julia runtime","title":"printf() and stdio in the Julia runtime","text":"$ julia -e 'println(typeof((stdin, stdout, stderr)))'\nTuple{Base.TTY,Base.TTY,Base.TTY}\n\n$ julia -e 'println(typeof((stdin, stdout, stderr)))' < /dev/null 2>/dev/null\nTuple{IOStream,Base.TTY,IOStream}\n\n$ echo hello | julia -e 'println(typeof((stdin, stdout, stderr)))' | cat\nTuple{Base.PipeEndpoint,Base.PipeEndpoint,Base.TTY}","category":"page"},{"location":"devdocs/stdio/","page":"printf() and stdio in the Julia runtime","title":"printf() and stdio in the Julia runtime","text":"The Base.read and Base.write methods for these streams use ccall to call libuv wrappers in src/jl_uv.c, e.g.:","category":"page"},{"location":"devdocs/stdio/","page":"printf() and stdio in the Julia runtime","title":"printf() and stdio in the Julia runtime","text":"stream.jl: function write(s::IO, p::Ptr, nb::Integer)\n -> ccall(:jl_uv_write, ...)\n jl_uv.c: -> int jl_uv_write(uv_stream_t *stream, ...)\n -> uv_write(uvw, stream, buf, ...)","category":"page"},{"location":"devdocs/stdio/#printf()-during-initialization","page":"printf() and stdio in the Julia runtime","title":"printf() during initialization","text":"","category":"section"},{"location":"devdocs/stdio/","page":"printf() and stdio in the Julia runtime","title":"printf() and stdio in the Julia runtime","text":"The libuv streams relied upon by jl_printf() etc., are not available until midway through initialization of the runtime (see init.c, init_stdio()). Error messages or warnings that need to be printed before this are routed to the standard C library fwrite() function by the following mechanism:","category":"page"},{"location":"devdocs/stdio/","page":"printf() and stdio in the Julia runtime","title":"printf() and stdio in the Julia runtime","text":"In sys.c, the JL_STD* stream pointers are statically initialized to integer constants: STD*_FILENO (0, 1 and 2). In jl_uv.c the jl_uv_puts() function checks its uv_stream_t* stream argument and calls fwrite() if stream is set to STDOUT_FILENO or STDERR_FILENO.","category":"page"},{"location":"devdocs/stdio/","page":"printf() and stdio in the Julia runtime","title":"printf() and stdio in the Julia runtime","text":"This allows for uniform use of jl_printf() throughout the runtime regardless of whether or not any particular piece of code is reachable before initialization is complete.","category":"page"},{"location":"devdocs/stdio/#Legacy-ios.c-library","page":"printf() and stdio in the Julia runtime","title":"Legacy ios.c library","text":"","category":"section"},{"location":"devdocs/stdio/","page":"printf() and stdio in the Julia runtime","title":"printf() and stdio in the Julia runtime","text":"The src/support/ios.c library is inherited from femtolisp. It provides cross-platform buffered file IO and in-memory temporary buffers.","category":"page"},{"location":"devdocs/stdio/","page":"printf() and stdio in the Julia runtime","title":"printf() and stdio in the Julia runtime","text":"ios.c is still used by:","category":"page"},{"location":"devdocs/stdio/","page":"printf() and stdio in the Julia runtime","title":"printf() and stdio in the Julia runtime","text":"src/flisp/*.c\nsrc/dump.c – for serialization file IO and for memory buffers.\nsrc/staticdata.c – for serialization file IO and for memory buffers.\nbase/iostream.jl – for file IO (see base/fs.jl for libuv equivalent).","category":"page"},{"location":"devdocs/stdio/","page":"printf() and stdio in the Julia runtime","title":"printf() and stdio in the Julia runtime","text":"Use of ios.c in these modules is mostly self-contained and separated from the libuv I/O system. However, there is one place where femtolisp calls through to jl_printf() with a legacy ios_t stream.","category":"page"},{"location":"devdocs/stdio/","page":"printf() and stdio in the Julia runtime","title":"printf() and stdio in the Julia runtime","text":"There is a hack in ios.h that makes the ios_t.bm field line up with the uv_stream_t.type and ensures that the values used for ios_t.bm to not overlap with valid UV_HANDLE_TYPE values. This allows uv_stream_t pointers to point to ios_t streams.","category":"page"},{"location":"devdocs/stdio/","page":"printf() and stdio in the Julia runtime","title":"printf() and stdio in the Julia runtime","text":"This is needed because jl_printf() caller jl_static_show() is passed an ios_t stream by femtolisp's fl_print() function. Julia's jl_uv_puts() function has special handling for this:","category":"page"},{"location":"devdocs/stdio/","page":"printf() and stdio in the Julia runtime","title":"printf() and stdio in the Julia runtime","text":"if (stream->type > UV_HANDLE_TYPE_MAX) {\n return ios_write((ios_t*)stream, str, n);\n}","category":"page"},{"location":"manual/getting-started/#man-getting-started","page":"入门","title":"入门","text":"","category":"section"},{"location":"manual/getting-started/","page":"入门","title":"入门","text":"无论是使用预编译好的二进制程序,还是自己从源码编译,安装 Julia 都是一件很简单的事情。 请按照 https://julialang.org/downloads/ 的提示来下载并安装 Julia。","category":"page"},{"location":"manual/getting-started/","page":"入门","title":"入门","text":"如果你是从下面的某一种语言切换到 Julia 的话,那么你应该首先阅读与这些语言有显著差异的那一部分 MATLAB, R, Python, C/C++ or Common Lisp. 这将帮助你避免一些常见的编程陷阱,因为 Julia 在许多微妙的方面与这些语言不同。","category":"page"},{"location":"manual/getting-started/","page":"入门","title":"入门","text":"启动一个交互式会话(也叫 REPL)是学习和尝试 Julia 最简单的方法。双击 Julia 的可执行文件或是从命令行运行 julia 就可以启动:","category":"page"},{"location":"manual/getting-started/","page":"入门","title":"入门","text":"io = IOBuffer()\nBase.banner(io)\nbanner = String(take!(io))\nimport Markdown\nMarkdown.parse(\"```\\n\\$ julia\\n\\n$(banner)\\njulia> 1 + 2\\n3\\n\\njulia> ans\\n3\\n```\")","category":"page"},{"location":"manual/getting-started/","page":"入门","title":"入门","text":"输入 CTRL-D(同时按 Ctrl 键和 d 键)或 exit() 便可以退出交互式会话。在交互式模式中,julia 会显示一条横幅并提示用户输入。一旦用户输入了一段完整的代码(表达式),例如 1 + 2,然后按回车,交互式会话就会执行这段代码,并将结果显示出来。如果输入的代码以分号结尾,那么结果将不会显示出来。然而不管结果显示与否,变量 ans 总会存储上一次执行代码的结果,需要注意的是,变量 ans 只在交互式会话中才有。","category":"page"},{"location":"manual/getting-started/","page":"入门","title":"入门","text":"在交互式会话中,要运行写在源文件 file.jl 中的代码,只需输入 include(\"file.jl\")。","category":"page"},{"location":"manual/getting-started/","page":"入门","title":"入门","text":"如果想以非交互的方式执行文件中的代码,可以把文件名作为 julia 命令的第一个参数:","category":"page"},{"location":"manual/getting-started/","page":"入门","title":"入门","text":"$ julia script.jl arg1 arg2...","category":"page"},{"location":"manual/getting-started/","page":"入门","title":"入门","text":"如这个例子所示,julia 后跟着的命令行参数会被作为程序 script.jl 的命令行参数。这些参数使用全局常量 ARGS 来传递,脚本自身的名字会以全局变量 PROGRAM_FILE 传入。注意当脚本以命令行里的 -e 选项输入时,ARGS 也会被设定(详见此页末尾列表)但是 PROGRAM_FILE 会是空的。例如,要把一个脚本的输入参数显示出来,你可以:","category":"page"},{"location":"manual/getting-started/","page":"入门","title":"入门","text":"$ julia -e 'println(PROGRAM_FILE); for x in ARGS; println(x); end' foo bar\n\nfoo\nbar","category":"page"},{"location":"manual/getting-started/","page":"入门","title":"入门","text":"或者你可以把代码写到一个脚本文件中再执行它:","category":"page"},{"location":"manual/getting-started/","page":"入门","title":"入门","text":"$ echo 'println(PROGRAM_FILE); for x in ARGS; println(x); end' > script.jl\n$ julia script.jl foo bar\nscript.jl\nfoo\nbar","category":"page"},{"location":"manual/getting-started/","page":"入门","title":"入门","text":"可以使用 -- 分隔符来将传给脚本文件的参数和 Julia 本身的命令行参数区分开:","category":"page"},{"location":"manual/getting-started/","page":"入门","title":"入门","text":"$ julia --color=yes -O -- script.jl arg1 arg2..","category":"page"},{"location":"manual/getting-started/","page":"入门","title":"入门","text":"有关编写 Julia 脚本的更多信息,请参阅 脚本。","category":"page"},{"location":"manual/getting-started/","page":"入门","title":"入门","text":"使用选项 -p 或者 --machine-file 可以在并行模式下启动 Julia。 -p n 会启动额外的 n 个 worker,使用 --machine-file file 会为 file 文件中的每一行启动一个 worker。 定义在 file 中的机器必须能够通过一个不需要密码的 ssh 登陆访问到,且 Julia 的安装位置需要和当前主机相同。 定义机器的格式为 [count*][user@]host[:port] [bind_addr[:port]]。 user 默认值是当前用户; port 默认值是标准 ssh 端口; count 是在这个节点上的 worker 的数量,默认是 1; 可选的 bind-to bind_addr[:port] 指定了其它 worker 访问当前 worker 应当使用的 IP 地址与端口。","category":"page"},{"location":"manual/getting-started/","page":"入门","title":"入门","text":"要让 Julia 每次启动都自动执行一些代码,你可以把它们放在 ~/.julia/config/startup.jl 中:","category":"page"},{"location":"manual/getting-started/","page":"入门","title":"入门","text":"$ echo 'println(\"Greetings! 你好! 안녕하세요?\")' > ~/.julia/config/startup.jl\n$ julia\nGreetings! 你好! 안녕하세요?\n\n...","category":"page"},{"location":"manual/getting-started/","page":"入门","title":"入门","text":"在你第一次运行 Julia 后,你应该多了一个 ~/.julia 文件夹。 你还可以新建 ~/.julia/config 文件夹和 ~/.julia/config/startup.jl 文件来配置 Julia。","category":"page"},{"location":"manual/getting-started/","page":"入门","title":"入门","text":"和 perl 和 ruby 程序类似,还有很多种运行 Julia 代码的方式,运行代码时也有很多选项:","category":"page"},{"location":"manual/getting-started/","page":"入门","title":"入门","text":"julia [switches] -- [programfile] [args...]","category":"page"},{"location":"manual/getting-started/","page":"入门","title":"入门","text":"详细的命令选项可以在这里找到 Command-line Options.","category":"page"},{"location":"manual/getting-started/#资源","page":"入门","title":"资源","text":"","category":"section"},{"location":"manual/getting-started/","page":"入门","title":"入门","text":"除了本手册以外,官方网站还提供了一个有用的学习资源列表来帮助新用户学习 Julia。","category":"page"},{"location":"manual/getting-started/","page":"入门","title":"入门","text":"如果已经对 Julia 有所了解,你可以先看 Performance Tips 和 Workflow Tips。","category":"page"},{"location":"manual/types/#man-types","page":"类型","title":"类型","text":"","category":"section"},{"location":"manual/types/","page":"类型","title":"类型","text":"通常,我们把程序语言中的类型系统划分成两类:静态类型和动态类型。对于静态类型系统,在程序运行之前,我们就可计算每一个表达式的类型。而对于动态类型系统,我们只有通过运行那个程序,得到表达式具体的值,才能确定其具体的类型。通过让编写的代码无需在编译时知道值的确切类型,面向对象允许静态类型语言具有一定的灵活性。可以编写在不同类型上都能运行的代码的能力被称为多态。在经典的动态类型语言中,所有的代码都是多态的,这意味着这些代码对于其中值的类型没有约束,除非在代码中去具体的判断一个值的类型,或者对对象做一些它不支持的操作。","category":"page"},{"location":"manual/types/","page":"类型","title":"类型","text":"Julia 类型系统是动态的,但由于允许指出某些变量具有特定类型,因此占有静态类型系统的一些优势。这对于生成高效的代码非常有帮助,但更重要的是,它允许针对函数参数类型的方法派发与语言深度集成。方法派发将在方法中详细探讨,但它根植于此处提供的类型系统。","category":"page"},{"location":"manual/types/","page":"类型","title":"类型","text":"在类型被省略时,Julia 的默认行为是允许值为任何类型。因此,可以编写许多有用的 Julia 函数,而无需显式使用类型。然而,当需要额外的表达力时,很容易逐渐将显式的类型注释引入先前的「无类型」代码中。添加类型注释主要有三个目的:利用 Julia 强大的多重派发机制、提高代码可读性以及捕获程序错误。","category":"page"},{"location":"manual/types/","page":"类型","title":"类型","text":"用类型系统的术语描述,Julia是动态(dynamic)、主格(nominative)和参数(parametric)的。泛型可以被参数化,并且类型之间的层次关系可以被显式地声明,而不是隐含地通过兼容的结构。Julia 类型系统的一个特别显著的特征是具体类型相互之间不能是子类型:所有具体类型都是最终的,并且超类只能是抽象类型。虽然这乍一看可能过于严格,但它有许多益处,且缺点却少得出奇。事实证明,能够继承行为比继承结构更重要,同时继承两者在传统的面向对象语言中导致了重大困难。Julia 类型系统的其它高级方面应当在先言明:","category":"page"},{"location":"manual/types/","page":"类型","title":"类型","text":"对象值和非对象值之间没有分别:Julia 中的所有值都是具有类型的真实对象且其类型属于一个单独的、完全连通的类型图,该类型图的所有节点作为类型一样都是头等的。\n「编译期类型」是没有任何意义的概念:变量所具有的唯一类型是程序运行时的实际类型。这在面向对象被称为「运行时类型」,其中静态编译和多态的组合使得这种区别变得显著。\n只有值,而不是变量,有类型——变量只是绑定到值的名称,尽管为了简单起见,我们可以说“变量的类型”作为“变量所引用的值的类型”的简写。\n抽象类型和具体类型都可以通过其它类型进行参数化。它们的参数化还可通过符号、使得 isbits 返回 true 的任意类型的值(实质上,也就是像数字或布尔变量这样的东西,存储方式像 C 类型或不包含指向其它对象的指针的 struct)和其元组。类型参数在不需要被引用或限制时可以省略。","category":"page"},{"location":"manual/types/","page":"类型","title":"类型","text":"Julia 的类型系统设计得强大而富有表现力,却清晰、直观且不引人注目。许多 Julia 程序员可能从未感觉需要编写明确使用类型的代码。但是,某些场景的编程可通过声明类型变得更加清晰、简单、快速和稳健。","category":"page"},{"location":"manual/types/#类型声明","page":"类型","title":"类型声明","text":"","category":"section"},{"location":"manual/types/","page":"类型","title":"类型","text":":: 运算符可以用来在程序中给表达式和变量附加类型注释。这有两个主要原因:","category":"page"},{"location":"manual/types/","page":"类型","title":"类型","text":"作为断言,帮助程序确认能是否正常运行,\n给编译器提供额外的类型信息,在一些情况下这可以提升程序性能。","category":"page"},{"location":"manual/types/","page":"类型","title":"类型","text":"置于到计算值的表达式后面时,:: 操作符读作「是······的实例(is an instance of)」。在任何地方都可以用它来断言左侧表达式的值是右侧类型的实例。当右侧类型是具体类型时,左侧的值必须能够以该类型作为其实现——回想一下,所有具体类型都是最终的,因此没有任何实现是任何其它具体类型的子类型。当右侧类型是抽象类型时,值是由该抽象类型子类型中的某个具体类型实现的才能满足该断言。如果类型断言非真,抛出一个异常,否则返回左侧的值:","category":"page"},{"location":"manual/types/","page":"类型","title":"类型","text":"julia> (1+2)::AbstractFloat\nERROR: TypeError: in typeassert, expected AbstractFloat, got a value of type Int64\n\njulia> (1+2)::Int\n3","category":"page"},{"location":"manual/types/","page":"类型","title":"类型","text":"这将允许类型断言作用在任意表达式上。","category":"page"},{"location":"manual/types/","page":"类型","title":"类型","text":"置于赋值语句左侧的变量之后,或作为 local 声明的一部分时,:: 操作符的意义有所不同:它声明变量始终具有指定的类型,就像静态类型语言(如 C)中的类型声明。每个被赋给该变量的值都将使用 convert 转换为被声明的类型:","category":"page"},{"location":"manual/types/","page":"类型","title":"类型","text":"julia> function foo()\n x::Int8 = 100\n x\n end\nfoo (generic function with 1 method)\n\njulia> x = foo()\n100\n\njulia> typeof(x)\nInt8","category":"page"},{"location":"manual/types/","page":"类型","title":"类型","text":"这个特性对避免特定的性能「陷阱」很有帮助,比如给一个变量赋值时意外地更改了其类型。","category":"page"},{"location":"manual/types/","page":"类型","title":"类型","text":"此「声明」行为仅发生在特定上下文中:","category":"page"},{"location":"manual/types/","page":"类型","title":"类型","text":"local x::Int8 # in a local declaration\nx::Int8 = 10 # as the left-hand side of an assignment","category":"page"},{"location":"manual/types/","page":"类型","title":"类型","text":"并应用于整个当前作用域,甚至在该声明之前。目前,类型声明不能在全局作用域中使用,例如在 REPL 中就不可以,因为 Julia 还没有常量类型的全局变量。","category":"page"},{"location":"manual/types/","page":"类型","title":"类型","text":"声明也可以附加到函数定义:","category":"page"},{"location":"manual/types/","page":"类型","title":"类型","text":"function sinc(x)::Float64\n if x == 0\n return 1\n end\n return sin(pi*x)/(pi*x)\nend","category":"page"},{"location":"manual/types/","page":"类型","title":"类型","text":"从函数返回时就如同给一个已被声明类型的变量赋值:返回值始终会被转换为Float64。","category":"page"},{"location":"manual/types/#man-abstract-types","page":"类型","title":"抽象类型","text":"","category":"section"},{"location":"manual/types/","page":"类型","title":"类型","text":"抽象类型不能实例化,只能作为类型图中的节点使用,从而描述相关具体类型的集,即那些作为其后代的具体类型。即便抽象类型没有实例, 由于它们是类型系统的主干,故我们首先从抽象类型谈起:抽象类型形成了概念的层次结构,这使得 Julia 的类型系统不只是对象实现的集合。","category":"page"},{"location":"manual/types/","page":"类型","title":"类型","text":"回想一下,在整数和浮点数中,我们介绍了各种数值的具体类型:Int8、UInt8、Int16、UInt16、Int32、UInt32、Int64、UInt64、Int128、UInt128、Float16、Float32 和 Float64。尽管 Int8、Int16、Int32、Int64 和 Int128 具有不同的表示大小,但都具有共同的特征,即它们都是带符号的整数类型。类似地,UInt8、UInt16、UInt32、UInt64 和 UInt128 都是无符号整数类型,而 Float16、Float32 和 Float64 是不同的浮点数类型而非整数类型。一段代码只对某些类型有意义是很常见的,比如,只在其参数是某种类型的整数,而不真正取决于特定类型的整数时有意义。例如,最大公分母算法适用于所有类型的整数,但不适用于浮点数。抽象类型允许构造类型的层次结构,这给具体类型提供了可以适应的环境。例如,你可以轻松地为任何类型的整数编程,而不用将算法限制为某种特殊类型的整数。","category":"page"},{"location":"manual/types/","page":"类型","title":"类型","text":"抽象类型可以由 abstract type 关键字来声明。声明抽象类型的一般语法是:","category":"page"},{"location":"manual/types/","page":"类型","title":"类型","text":"abstract type «name» end\nabstract type «name» <: «supertype» end","category":"page"},{"location":"manual/types/","page":"类型","title":"类型","text":"该 abstract type 关键字引入了一个新的抽象类型,«name» 为其名称。此名称后面可以跟 <: 和一个已存在的类型,表示新声明的抽象类型是此「父」类型的子类型。","category":"page"},{"location":"manual/types/","page":"类型","title":"类型","text":"如果没有给出超类型,则默认超类型为 Any——一个已经定义好的抽象类型,所有对象都是 Any 的实例并且所有类型都是 Any 的子类型。在类型理论中,Any 通常称为「top」,因为它位于类型图的顶点。Julia 还有一个预定义了的抽象「bottom」类型,在类型图的最低点,写成 Union{}。这与 Any 完全相反:任何对象都不是 Union{} 的实例,所有的类型都是 Union{} 的超类型。","category":"page"},{"location":"manual/types/","page":"类型","title":"类型","text":"让我们考虑一些构成 Julia 数值类型层次结构的抽象类型:","category":"page"},{"location":"manual/types/","page":"类型","title":"类型","text":"abstract type Number end\nabstract type Real <: Number end\nabstract type AbstractFloat <: Real end\nabstract type Integer <: Real end\nabstract type Signed <: Integer end\nabstract type Unsigned <: Integer end","category":"page"},{"location":"manual/types/","page":"类型","title":"类型","text":"Number 类型为 Any 类型的直接子类型,并且 Real 为它的子类型。接下来,Real 有两个子类型(它还有更多的子类型,但这里只展示了两个,稍后将会看到其它的子类型): Integer 和 AbstractFloat,将世界分为整数的表示和实数的表示。实数的表示当然包括浮点类型,但也包括其他类型,例如有理数。因此,AbstractFloat 是一个 Real 的子类型,仅包括实数的浮点表示。整数被进一步细分为 Signed 和 Unsigned 两类。","category":"page"},{"location":"manual/types/","page":"类型","title":"类型","text":"<: 运算符的通常意义为「是······的子类型(is a subtype of)」,可以用在声明中,声明右侧类型是新声明类型的直接超类型;也可以在表达式中用作子类型运算符,在其左操作数为其右操作数的子类型时返回 true:","category":"page"},{"location":"manual/types/","page":"类型","title":"类型","text":"julia> Integer <: Number\ntrue\n\njulia> Integer <: AbstractFloat\nfalse","category":"page"},{"location":"manual/types/","page":"类型","title":"类型","text":"抽象类型的一个重要用途是为具体类型提供默认实现。举个简单的例子,考虑:","category":"page"},{"location":"manual/types/","page":"类型","title":"类型","text":"function myplus(x,y)\n x+y\nend","category":"page"},{"location":"manual/types/","page":"类型","title":"类型","text":"首先需要注意的是上述的参数声明等价于 x::Any 和 y::Any。当函数被调用时,例如 myplus(2,5),派发器会选择与给定参数相匹配的名称为 myplus 的最具体方法。(有关多重派发的更多信息,请参阅方法。)","category":"page"},{"location":"manual/types/","page":"类型","title":"类型","text":"假设没有找到比上述方法更具体的方法,Julia 则会基于上面给出的泛型函数,在内部定义并编译一个名为 myplus 的方法,专门用于处理两个 Int 参数,即它隐式地定义并编译:","category":"page"},{"location":"manual/types/","page":"类型","title":"类型","text":"function myplus(x::Int,y::Int)\n x+y\nend","category":"page"},{"location":"manual/types/","page":"类型","title":"类型","text":"最后,调用这个具体的方法。","category":"page"},{"location":"manual/types/","page":"类型","title":"类型","text":"因此,抽象类型允许程序员编写泛型函数,泛型函数可以通过许多具体类型的组合用作默认方法。多重派发使得程序员可以完全控制是使用默认方法还是更具体的方法。","category":"page"},{"location":"manual/types/","page":"类型","title":"类型","text":"需要注意的重点是,即使程序员依赖参数为抽象类型的函数,性能也不会有任何损失,因为它会针对每个调用它的参数元组的具体类型重新编译。(但在函数参数是抽象类型的容器的情况下,可能存在性能问题;请参阅性能建议。)","category":"page"},{"location":"manual/types/#原始类型","page":"类型","title":"原始类型","text":"","category":"section"},{"location":"manual/types/","page":"类型","title":"类型","text":"warning: Warning\n通常情况下更建议在新的复合类型中封装现有的原始类型,而不是重新定义自己的原始类型。这个功能的存在是为了允许 Julia 能引导受 LLVM 支持的标准基本类型。一旦一些标准类型被定义,就不需要再定义更多了。","category":"page"},{"location":"manual/types/","page":"类型","title":"类型","text":"原始类型是具体类型,其数据是由简单的位组成。原始类型的经典示例是整数和浮点数。与大多数语言不同,Julia 允许你声明自己的原始类型,而不是只提供一组固定的内置原始类型。实际上,标准原始类型都是在语言本身中定义的:","category":"page"},{"location":"manual/types/","page":"类型","title":"类型","text":"primitive type Float16 <: AbstractFloat 16 end\nprimitive type Float32 <: AbstractFloat 32 end\nprimitive type Float64 <: AbstractFloat 64 end\n\nprimitive type Bool <: Integer 8 end\nprimitive type Char <: AbstractChar 32 end\n\nprimitive type Int8 <: Signed 8 end\nprimitive type UInt8 <: Unsigned 8 end\nprimitive type Int16 <: Signed 16 end\nprimitive type UInt16 <: Unsigned 16 end\nprimitive type Int32 <: Signed 32 end\nprimitive type UInt32 <: Unsigned 32 end\nprimitive type Int64 <: Signed 64 end\nprimitive type UInt64 <: Unsigned 64 end\nprimitive type Int128 <: Signed 128 end\nprimitive type UInt128 <: Unsigned 128 end","category":"page"},{"location":"manual/types/","page":"类型","title":"类型","text":"声明原始类型的一般语法是:","category":"page"},{"location":"manual/types/","page":"类型","title":"类型","text":"primitive type «name» «bits» end\nprimitive type «name» <: «supertype» «bits» end","category":"page"},{"location":"manual/types/","page":"类型","title":"类型","text":"bits 的数值表示该类型需要多少存储空间,name 为新类型指定名称。可以选择将一个原始类型声明为某个超类型的子类型。如果省略超类型,则默认 Any 为其直接超类型。上述声明中意味着 Bool 类型需要 8 位来储存,并且直接超类型为 Integer。目前支持的大小只能是 8 位的倍数,不然你就会遇到 LLVM 的 bug。因此,布尔值虽然确实只需要一位,但不能声明为小于 8 位的值。","category":"page"},{"location":"manual/types/","page":"类型","title":"类型","text":"Bool,Int8 和 UInt8 类型都具有相同的表现形式:它们都是 8 位内存块。然而,由于 Julia 的类型系统是主格的,它们尽管具有相同的结构,但不是通用的。它们之间的一个根本区别是它们具有不同的超类型:Bool 的直接超类型是 Integer、Int8 的是 Signed 而 UInt8 的是 Unsigned。Bool,Int8 和 UInt8 的所有其它差异是行为上的——定义函数的方式在这些类型的对象作为参数给定时起作用。这也是为什么主格的类型系统是必须的:如果结构确定类型,类型决定行为,就不可能使 Bool 的行为与 Int8 或 UInt8 有任何不同。","category":"page"},{"location":"manual/types/#复合类型","page":"类型","title":"复合类型","text":"","category":"section"},{"location":"manual/types/","page":"类型","title":"类型","text":"复合类型在各种语言中被称为 record、struct 和 object。复合类型是命名字段的集合,其实例可以视为单个值。复合类型在许多语言中是唯一一种用户可定义的类型,也是 Julia 中最常用的用户定义类型。","category":"page"},{"location":"manual/types/","page":"类型","title":"类型","text":"在主流的面向对象语言中,比如 C++、Java、Python 和 Ruby,复合类型也具有与它们相关的命名函数,并且该组合称为「对象」。在纯粹的面向对象语言中,例如 Ruby 或 Smalltalk,所有值都是对象,无论它们是否为复合类型。在不太纯粹的面向对象语言中,包括 C++ 和 Java,一些值,比如整数和浮点值,不是对象,而用户定义的复合类型是具有相关方法的真实对象。在 Julia 中,所有值都是对象,但函数不与它们操作的对象捆绑在一起。这是必要的,因为 Julia 通过多重派发选择函数使用的方法,这意味着在选择方法时考虑所有函数参数的类型,而不仅仅是第一个(有关方法和派发的更多信息,请参阅方法)。因此,函数仅仅「属于」它们的第一个参数是不合适的。将方法组织到函数对象中而不是在每个对象「内部」命名方法最终成为语言设计中一个非常有益的方面。","category":"page"},{"location":"manual/types/","page":"类型","title":"类型","text":"struct 关键字与复合类型一起引入,后跟一个字段名称的块,可选择使用 :: 运算符注释类型:","category":"page"},{"location":"manual/types/","page":"类型","title":"类型","text":"julia> struct Foo\n bar\n baz::Int\n qux::Float64\n end","category":"page"},{"location":"manual/types/","page":"类型","title":"类型","text":"没有类型注释的字段默认为 Any 类型,所以可以包含任何类型的值。","category":"page"},{"location":"manual/types/","page":"类型","title":"类型","text":"类型为 Foo 的新对象通过将 Foo 类型对象像函数一样应用于其字段的值来创建:","category":"page"},{"location":"manual/types/","page":"类型","title":"类型","text":"julia> foo = Foo(\"Hello, world.\", 23, 1.5)\nFoo(\"Hello, world.\", 23, 1.5)\n\njulia> typeof(foo)\nFoo","category":"page"},{"location":"manual/types/","page":"类型","title":"类型","text":"像函数一样使用的类型称为构造函数。有两个构造函数已被自动生成(这些构造函数称为默认构造函数)。其中一个接受任何参数并调用 convert 函数将它其转换为字段的类型,另一个接受与字段类型完全匹配的参数。两者都生成的原因是,这使得更容易添加新定义而不会在无意中替换默认构造函数。","category":"page"},{"location":"manual/types/","page":"类型","title":"类型","text":"由于 bar 字段在类型上不受限制,因此任何值都可以。但是 baz 的值必须可转换为 Int 类型:","category":"page"},{"location":"manual/types/","page":"类型","title":"类型","text":"julia> Foo((), 23.5, 1)\nERROR: InexactError: Int64(23.5)\nStacktrace:\n[...]","category":"page"},{"location":"manual/types/","page":"类型","title":"类型","text":"可以使用 fieldnames 函数找到字段名称列表。","category":"page"},{"location":"manual/types/","page":"类型","title":"类型","text":"julia> fieldnames(Foo)\n(:bar, :baz, :qux)","category":"page"},{"location":"manual/types/","page":"类型","title":"类型","text":"可以使用传统的 foo.bar 表示法访问复合对象的字段值:","category":"page"},{"location":"manual/types/","page":"类型","title":"类型","text":"julia> foo.bar\n\"Hello, world.\"\n\njulia> foo.baz\n23\n\njulia> foo.qux\n1.5","category":"page"},{"location":"manual/types/","page":"类型","title":"类型","text":"用 struct 声明的复合对象是不可变的;创建后不能修改。乍一看这似乎很奇怪,但它有几个优点:","category":"page"},{"location":"manual/types/","page":"类型","title":"类型","text":"它可以更高效。某些 struct 可以被高效地打包到数组中,并且在某些情况下,编译器可以避免完全分配不可变对象。\n不可能违反类型构造函数提供的不变性。\n使用不可变对象的代码更容易推理。","category":"page"},{"location":"manual/types/","page":"类型","title":"类型","text":"不可变对象可以包含可变对象(比如数组)作为字段。那些被包含的对象将保持可变;只是不可变对象本身的字段不能更改为指向不同的对象。","category":"page"},{"location":"manual/types/","page":"类型","title":"类型","text":"如果需要,可以使用关键字 mutable struct 声明可变复合对象,这将在下一节中讨论。","category":"page"},{"location":"manual/types/","page":"类型","title":"类型","text":"如果一个不可变结构的所有字段都是不可区分的(===),那么包含这些字段的两个不可变值也是不可区分的:","category":"page"},{"location":"manual/types/","page":"类型","title":"类型","text":"julia> struct X\n a::Int\n b::Float64\n end\n\njulia> X(1, 2) === X(1, 2)\ntrue","category":"page"},{"location":"manual/types/","page":"类型","title":"类型","text":"关于如何构造复合类型的实例还有很多要说的,但这种讨论依赖于参数类型和方法,并且这是非常重要的,应该在专门的章节中讨论:构造函数。","category":"page"},{"location":"manual/types/#可变复合类型","page":"类型","title":"可变复合类型","text":"","category":"section"},{"location":"manual/types/","page":"类型","title":"类型","text":"如果使用 mutable struct 而不是 struct 声明复合类型,则它的实例可以被修改:","category":"page"},{"location":"manual/types/","page":"类型","title":"类型","text":"julia> mutable struct Bar\n baz\n qux::Float64\n end\n\njulia> bar = Bar(\"Hello\", 1.5);\n\njulia> bar.qux = 2.0\n2.0\n\njulia> bar.baz = 1//2\n1//2","category":"page"},{"location":"manual/types/","page":"类型","title":"类型","text":"为了支持修改,这种对象通常分配在堆上,并且具有稳定的内存地址。可变对象就像一个小容器,随着时间的推移,可能保持不同的值,因此只能通过其地址可靠地识别。相反地,不可变类型的实例与特定字段值相关——仅字段值就告诉你该对象的所有内容。在决定是否使类型为可变类型时,请询问具有相同字段值的两个实例是否被视为相同,或者它们是否可能需要随时间独立更改。如果它们被认为是相同的,该类型就应该是不可变的。","category":"page"},{"location":"manual/types/","page":"类型","title":"类型","text":"总结一下,Julia 的两个基本属性定义了不变性:","category":"page"},{"location":"manual/types/","page":"类型","title":"类型","text":"不允许修改不可变类型的值。\n对于位类型,这意味着值的位模式一旦设置将不再改变,并且该值是位类型的标识。\n对于复合类型,这意味着其字段值的标识将不再改变。当字段是位类型时,这意味着它们的位将不再改变,对于其值是可变类型(如数组)的字段,这意味着字段将始终引用相同的可变值,尽管该可变值的内容本身可能被修改。\n具有不可变类型的对象可以被编译器自由复制,因为其不可变性使得不可能以编程方式区分原始对象和副本。\n特别地,这意味着足够小的不可变值(如整数和浮点数)通常在寄存器(或栈分配)中传递给函数。\n另一方面,可变值是堆分配的,并作为指向堆分配值的指针传递给函数,除非编译器确定没有办法知道这不是正在发生的事情。","category":"page"},{"location":"manual/types/#man-declared-types","page":"类型","title":"已声明的类型","text":"","category":"section"},{"location":"manual/types/","page":"类型","title":"类型","text":"前面章节中讨论的三种类型(抽象、原始、复合)实际上都是密切相关的。它们共有相同的关键属性:","category":"page"},{"location":"manual/types/","page":"类型","title":"类型","text":"它们都是显式声明的。\n它们都具有名称。\n它们都已经显式声明超类型。\n它们可以有参数。","category":"page"},{"location":"manual/types/","page":"类型","title":"类型","text":"由于这些共有属性,它们在内部表现为相同概念 DataType 的实例,其是任何这些类型的类型:","category":"page"},{"location":"manual/types/","page":"类型","title":"类型","text":"julia> typeof(Real)\nDataType\n\njulia> typeof(Int)\nDataType","category":"page"},{"location":"manual/types/","page":"类型","title":"类型","text":"DataType 可以是抽象的或具体的。它如果是具体的,就具有指定的大小、存储布局和字段名称(可选)。因此,原始类型是具有非零大小的 DataType,但没有字段名称。复合类型是具有字段名称或者为空(大小为零)的 DataType。","category":"page"},{"location":"manual/types/","page":"类型","title":"类型","text":"每一个具体的值在系统里都是某个 DataType 的实例。","category":"page"},{"location":"manual/types/#类型共用体","page":"类型","title":"类型共用体","text":"","category":"section"},{"location":"manual/types/","page":"类型","title":"类型","text":"类型共用体是一种特殊的抽象类型,它包含作为对象的任何参数类型的所有实例,使用特殊Union关键字构造:","category":"page"},{"location":"manual/types/","page":"类型","title":"类型","text":"julia> IntOrString = Union{Int,AbstractString}\nUnion{Int64, AbstractString}\n\njulia> 1 :: IntOrString\n1\n\njulia> \"Hello!\" :: IntOrString\n\"Hello!\"\n\njulia> 1.0 :: IntOrString\nERROR: TypeError: in typeassert, expected Union{Int64, AbstractString}, got a value of type Float64","category":"page"},{"location":"manual/types/","page":"类型","title":"类型","text":"许多语言都有内建的共用体结构来推导类型;Julia 简单地将它暴露给程序员。Julia 编译器能在 Union 类型只具有少量类型[1]的情况下生成高效的代码,方法是为每个可能类型的不同分支都生成专用代码。","category":"page"},{"location":"manual/types/","page":"类型","title":"类型","text":"Union 类型的一种特别有用的情况是 Union{T, Nothing},其中 T 可以是任何类型,Nothing 是单态类型,其唯一实例是对象 nothing。此模式是其它语言中 Nullable、Option 或 Maybe 类型在 Julia 的等价。通过将函数参数或字段声明为 Union{T, Nothing},可以将其设置为类型为 T 的值,或者 nothing 来表示没有值。有关详细信息,请参阅常见问题的此条目。","category":"page"},{"location":"manual/types/#Parametric-Types","page":"类型","title":"参数类型","text":"","category":"section"},{"location":"manual/types/","page":"类型","title":"类型","text":"Julia 类型系统的一个重要和强大的特征是它是参数的:类型可以接受参数,因此类型声明实际上引入了一整套新类型——每一个参数值的可能组合引入一个新类型。许多语言支持某种版本的泛型编程,其中,可以指定操作泛型的数据结构和算法,而无需指定所涉及的确切类型。例如,某些形式的泛型编程存在于 ML、Haskell、Ada、Eiffel、C++、Java、C#、F#、和 Scala 中,这只是其中的一些例子。这些语言中的一些支持真正的参数多态(例如 ML、Haskell、Scala),而其它语言基于模板的泛型编程风格(例如 C++、Java)。由于在不同语言中有多种不同种类的泛型编程和参数类型,我们甚至不会尝试将 Julia 的参数类型与其它语言的进行比较,而是专注于解释 Julia 系统本身。然而,我们将注意到,因为 Julia 是动态类型语言并且不需要在编译时做出所有类型决定,所以许多在静态参数类型系统中遇到的传统困难可以被相对容易地处理。","category":"page"},{"location":"manual/types/","page":"类型","title":"类型","text":"所有已声明的类型(DataType 类型)都可被参数化,在每种情况下都使用一样的语法。我们将按一下顺序讨论它们:首先是参数复合类型,接着是参数抽象类型,最后是参数原始类型。","category":"page"},{"location":"manual/types/#man-parametric-composite-types","page":"类型","title":"参数复合类型","text":"","category":"section"},{"location":"manual/types/","page":"类型","title":"类型","text":"类型参数在类型名称后引入,用大括号扩起来:","category":"page"},{"location":"manual/types/","page":"类型","title":"类型","text":"julia> struct Point{T}\n x::T\n y::T\n end","category":"page"},{"location":"manual/types/","page":"类型","title":"类型","text":"此声明定义了一个新的参数类型,Point{T},拥有类型为 T 的两个「坐标」。有人可能会问 T 是什么?嗯,这恰恰是参数类型的重点:它可以是任何类型(或者任何位类型值,虽然它实际上在这里显然用作类型)。Point{Float64} 是一个具体类型,该类型等价于通过用 Float64 替换 Point 的定义中的 T 所定义的类型。因此,单独这一个声明实际上声明了无限个类型:Point{Float64},Point{AbstractString},Point{Int64},等等。这些类型中的每一个类型现在都是可用的具体类型:","category":"page"},{"location":"manual/types/","page":"类型","title":"类型","text":"julia> Point{Float64}\nPoint{Float64}\n\njulia> Point{AbstractString}\nPoint{AbstractString}","category":"page"},{"location":"manual/types/","page":"类型","title":"类型","text":"Point{Float64} 类型是坐标为 64 位浮点值的点,而 Point{AbstractString} 类型是「坐标」为字符串对象(请参阅 Strings)的「点」。","category":"page"},{"location":"manual/types/","page":"类型","title":"类型","text":"Point 本身也是一个有效的类型对象,包括所有实例 Point{Float64}、Point{AbstractString} 等作为子类型:","category":"page"},{"location":"manual/types/","page":"类型","title":"类型","text":"julia> Point{Float64} <: Point\ntrue\n\njulia> Point{AbstractString} <: Point\ntrue","category":"page"},{"location":"manual/types/","page":"类型","title":"类型","text":"当然,其他类型不是它的子类型:","category":"page"},{"location":"manual/types/","page":"类型","title":"类型","text":"julia> Float64 <: Point\nfalse\n\njulia> AbstractString <: Point\nfalse","category":"page"},{"location":"manual/types/","page":"类型","title":"类型","text":"Point 不同 T 值所声明的具体类型之间,不能互相作为子类型:","category":"page"},{"location":"manual/types/","page":"类型","title":"类型","text":"julia> Point{Float64} <: Point{Int64}\nfalse\n\njulia> Point{Float64} <: Point{Real}\nfalse","category":"page"},{"location":"manual/types/","page":"类型","title":"类型","text":"warning: Warning\n最后一点非常重要:即使 Float64 <: Real 也没有 Point{Float64} <: Point{Real}。","category":"page"},{"location":"manual/types/","page":"类型","title":"类型","text":"换成类型理论说法,Julia 的类型参数是不变的,而不是协变的(或甚至是逆变的)。这是出于实际原因:虽然任何 Point{Float64} 的实例在概念上也可能像是 Point{Real} 的实例,但这两种类型在内存中有不同的表示:","category":"page"},{"location":"manual/types/","page":"类型","title":"类型","text":"Point{Float64} 的实例可以紧凑而高效地表示为一对 64 位立即数;\nPoint{Real} 的实例必须能够保存任何一对 Real 的实例。由于 Real 实例的对象可以具有任意的大小和结构,Point{Real} 的实例实际上必须表示为一对指向单独分配的 Real 对象的指针。","category":"page"},{"location":"manual/types/","page":"类型","title":"类型","text":"在数组的情况下,能够以立即数存储 Point{Float64} 对象会极大地提高效率:Array{Float64} 可以存储为一段 64 位浮点值组成的连续内存块,而 Array{Real} 必须是一个由指向单独分配的 Real 的指针组成的数组——这可能是 boxed 64 位浮点值,但也可能是任意庞大和复杂的对象,且其被声明为 Real 抽象类型的表示。","category":"page"},{"location":"manual/types/","page":"类型","title":"类型","text":"由于 Point{Float64} 不是 Point{Real} 的子类型,下面的方法不适用于类型为 Point{Float64} 的参数:","category":"page"},{"location":"manual/types/","page":"类型","title":"类型","text":"function norm(p::Point{Real})\n sqrt(p.x^2 + p.y^2)\nend","category":"page"},{"location":"manual/types/","page":"类型","title":"类型","text":"一种正确的方法来定义一个接受类型的所有参数的方法,Point{T}其中T是一个子类型Real:","category":"page"},{"location":"manual/types/","page":"类型","title":"类型","text":"function norm(p::Point{<:Real})\n sqrt(p.x^2 + p.y^2)\nend","category":"page"},{"location":"manual/types/","page":"类型","title":"类型","text":"(等效地,另一种定义方法 function norm(p::Point{T} where T<:Real) 或 function norm(p::Point{T}) where T<:Real;查看 UnionAll 类型。)","category":"page"},{"location":"manual/types/","page":"类型","title":"类型","text":"稍后将在方法中讨论更多示例。","category":"page"},{"location":"manual/types/","page":"类型","title":"类型","text":"如何构造一个 Point 对象?可以为复合类型定义自定义的构造函数,这将在构造函数中详细讨论,但在没有任何特别的构造函数声明的情况下,有两种默认方式可以创建新的复合对象,一种是显式地给出类型参数,另一种是通过传给对象构造函数的参数隐式地推断出。","category":"page"},{"location":"manual/types/","page":"类型","title":"类型","text":"由于 Point{Float64} 类型等价于在 Point 声明时用 Float64 替换 T 得到的具体类型,它可以相应地作为构造函数使用:","category":"page"},{"location":"manual/types/","page":"类型","title":"类型","text":"julia> p = Point{Float64}(1.0, 2.0)\nPoint{Float64}(1.0, 2.0)\n\njulia> typeof(p)\nPoint{Float64}","category":"page"},{"location":"manual/types/","page":"类型","title":"类型","text":"对于默认的构造函数,必须为每个字段提供一个参数:","category":"page"},{"location":"manual/types/","page":"类型","title":"类型","text":"julia> Point{Float64}(1.0)\nERROR: MethodError: no method matching Point{Float64}(::Float64)\n[...]\n\njulia> Point{Float64}(1.0,2.0,3.0)\nERROR: MethodError: no method matching Point{Float64}(::Float64, ::Float64, ::Float64)\n[...]","category":"page"},{"location":"manual/types/","page":"类型","title":"类型","text":"参数类型只生成一个默认的构造函数,因为它无法覆盖。这个构造函数接受任何参数并将它们转换为字段的类型。","category":"page"},{"location":"manual/types/","page":"类型","title":"类型","text":"许多情况下,没有必要提供想要构造的 Point 对象的类型,因为构造函数调用参数的类型已经隐式地提供了类型信息。因此,你也可以将 Point 本身用作构造函数,前提是参数类型 T 的隐含值是明确的:","category":"page"},{"location":"manual/types/","page":"类型","title":"类型","text":"julia> p1 = Point(1.0,2.0)\nPoint{Float64}(1.0, 2.0)\n\njulia> typeof(p1)\nPoint{Float64}\n\njulia> p2 = Point(1,2)\nPoint{Int64}(1, 2)\n\njulia> typeof(p2)\nPoint{Int64}","category":"page"},{"location":"manual/types/","page":"类型","title":"类型","text":"在 Point 的例子中,当且仅当 Point 的两个参数类型相同时,T 的类型才确实是隐含的。如果不是这种情况,构造函数将失败并出现 MethodError:","category":"page"},{"location":"manual/types/","page":"类型","title":"类型","text":"julia> Point(1,2.5)\nERROR: MethodError: no method matching Point(::Int64, ::Float64)\nClosest candidates are:\n Point(::T, !Matched::T) where T at none:2","category":"page"},{"location":"manual/types/","page":"类型","title":"类型","text":"可以定义适当处理此类混合情况的函数构造方法,将在后面的构造函数中讨论。","category":"page"},{"location":"manual/types/#参数抽象类型","page":"类型","title":"参数抽象类型","text":"","category":"section"},{"location":"manual/types/","page":"类型","title":"类型","text":"参数抽象类型声明以非常相似的方式声明了一族抽象类型:","category":"page"},{"location":"manual/types/","page":"类型","title":"类型","text":"julia> abstract type Pointy{T} end","category":"page"},{"location":"manual/types/","page":"类型","title":"类型","text":"在此声明中,对于每个类型或整数值 T,Pointy{T} 都是不同的抽象类型。与参数复合类型一样,每个此类型的实例都是 Pointy 的子类型:","category":"page"},{"location":"manual/types/","page":"类型","title":"类型","text":"julia> Pointy{Int64} <: Pointy\ntrue\n\njulia> Pointy{1} <: Pointy\ntrue","category":"page"},{"location":"manual/types/","page":"类型","title":"类型","text":"参数抽象类型是不变的,就像参数复合类型:","category":"page"},{"location":"manual/types/","page":"类型","title":"类型","text":"julia> Pointy{Float64} <: Pointy{Real}\nfalse\n\njulia> Pointy{Real} <: Pointy{Float64}\nfalse","category":"page"},{"location":"manual/types/","page":"类型","title":"类型","text":"符号 Pointy{<:Real} 可用于表示协变类型的 Julia 类似物,而 Pointy{>:Int} 类似于逆变类型,但从技术上讲,它们都代表了类型的集合(参见 UnionAll 类型)。","category":"page"},{"location":"manual/types/","page":"类型","title":"类型","text":"julia> Pointy{Float64} <: Pointy{<:Real}\ntrue\n\njulia> Pointy{Real} <: Pointy{>:Int}\ntrue","category":"page"},{"location":"manual/types/","page":"类型","title":"类型","text":"正如之前的普通抽象类型用于在具体类型上创建实用的类型层次结构一样,参数抽象类型在参数复合类型上具有相同的用途。例如,我们可以将 Point{T} 声明为 Pointy{T} 的子类型,如下所示:","category":"page"},{"location":"manual/types/","page":"类型","title":"类型","text":"julia> struct Point{T} <: Pointy{T}\n x::T\n y::T\n end","category":"page"},{"location":"manual/types/","page":"类型","title":"类型","text":"鉴于此类声明,对每个 T,都有 Point{T} 是 Pointy{T} 的子类型:","category":"page"},{"location":"manual/types/","page":"类型","title":"类型","text":"julia> Point{Float64} <: Pointy{Float64}\ntrue\n\njulia> Point{Real} <: Pointy{Real}\ntrue\n\njulia> Point{AbstractString} <: Pointy{AbstractString}\ntrue","category":"page"},{"location":"manual/types/","page":"类型","title":"类型","text":"下面的关系依然不变:","category":"page"},{"location":"manual/types/","page":"类型","title":"类型","text":"julia> Point{Float64} <: Pointy{Real}\nfalse\n\njulia> Point{Float64} <: Pointy{<:Real}\ntrue","category":"page"},{"location":"manual/types/","page":"类型","title":"类型","text":"参数抽象类型(比如 Pointy)的用途是什么?考虑一下如果点都在对角线 x = y 上,那我们创建的点的实现可以只有一个坐标:","category":"page"},{"location":"manual/types/","page":"类型","title":"类型","text":"julia> struct DiagPoint{T} <: Pointy{T}\n x::T\n end","category":"page"},{"location":"manual/types/","page":"类型","title":"类型","text":"现在,Point{Float64} 和 DiagPoint{Float64} 都是抽象 Pointy{Float64} 的实现,每个类型 T 的其它可能选择与之类似。这允许对被所有 Pointy 对象共享的公共接口进行编程,接口都由 Point 和 DiagPoint 实现。但是,直到我们在下一节方法中引入方法和分派前,这无法完全证明。","category":"page"},{"location":"manual/types/","page":"类型","title":"类型","text":"有时,类型参数取遍所有可能类型也许是无意义的。在这种情况下,可以像这样约束 T 的范围:","category":"page"},{"location":"manual/types/","page":"类型","title":"类型","text":"julia> abstract type Pointy{T<:Real} end","category":"page"},{"location":"manual/types/","page":"类型","title":"类型","text":"在这样的声明中,可以使用任何 Real 的子类型替换 T,但不能使用不是 Real 子类型的类型:","category":"page"},{"location":"manual/types/","page":"类型","title":"类型","text":"julia> Pointy{Float64}\nPointy{Float64}\n\njulia> Pointy{Real}\nPointy{Real}\n\njulia> Pointy{AbstractString}\nERROR: TypeError: in Pointy, in T, expected T<:Real, got Type{AbstractString}\n\njulia> Pointy{1}\nERROR: TypeError: in Pointy, in T, expected T<:Real, got a value of type Int64","category":"page"},{"location":"manual/types/","page":"类型","title":"类型","text":"参数化复合类型的类型参数可用相同的方式限制:","category":"page"},{"location":"manual/types/","page":"类型","title":"类型","text":"struct Point{T<:Real} <: Pointy{T}\n x::T\n y::T\nend","category":"page"},{"location":"manual/types/","page":"类型","title":"类型","text":"这里给出了一个真实示例,展示了所有这些参数类型机制如何发挥作用,下面是 Julia 的不可变类型 Rational 的实际定义(除了我们为了简单起见省略了的构造函数),用来表示准确的整数比例:","category":"page"},{"location":"manual/types/","page":"类型","title":"类型","text":"struct Rational{T<:Integer} <: Real\n num::T\n den::T\nend","category":"page"},{"location":"manual/types/","page":"类型","title":"类型","text":"只有接受整数值的比例才是有意义的,因此参数类型 T 被限制为 Integer 的子类型,又整数的比例代表实数轴上的值,因此任何 Rational 都是抽象 Real 的实现。","category":"page"},{"location":"manual/types/#元组类型","page":"类型","title":"元组类型","text":"","category":"section"},{"location":"manual/types/","page":"类型","title":"类型","text":"元组类型是函数参数的抽象化——不带函数本身。函数参数的突出特征是它们的顺序和类型。因此,元组类型类似于参数化的不可变类型,其中每个参数都是一个字段的类型。例如,二元元组类型类似于以下不可变类型:","category":"page"},{"location":"manual/types/","page":"类型","title":"类型","text":"struct Tuple2{A,B}\n a::A\n b::B\nend","category":"page"},{"location":"manual/types/","page":"类型","title":"类型","text":"然而,有三个主要差异:","category":"page"},{"location":"manual/types/","page":"类型","title":"类型","text":"元组类型可以具有任意数量的参数。\n元组类型的参数是协变的(covariant):Tuple{Int} 是 Tuple{Any} 的子类型。因此,Tuple{Any} 被认为是一种抽象类型,且元组类型只有在它们的参数都是具体类型时才是具体类型。 \n元组没有字段名称; 字段只能通过索引访问。","category":"page"},{"location":"manual/types/","page":"类型","title":"类型","text":"元组值用括号和逗号书写。构造元组时,会根据需要生成适当的元组类型:","category":"page"},{"location":"manual/types/","page":"类型","title":"类型","text":"julia> typeof((1,\"foo\",2.5))\nTuple{Int64, String, Float64}","category":"page"},{"location":"manual/types/","page":"类型","title":"类型","text":"请注意协变性的含义:","category":"page"},{"location":"manual/types/","page":"类型","title":"类型","text":"julia> Tuple{Int,AbstractString} <: Tuple{Real,Any}\ntrue\n\njulia> Tuple{Int,AbstractString} <: Tuple{Real,Real}\nfalse\n\njulia> Tuple{Int,AbstractString} <: Tuple{Real,}\nfalse","category":"page"},{"location":"manual/types/","page":"类型","title":"类型","text":"直观地,这对应于函数参数的类型是函数签名(当函数签名匹配时)的子类型。","category":"page"},{"location":"manual/types/#变参元组类型","page":"类型","title":"变参元组类型","text":"","category":"section"},{"location":"manual/types/","page":"类型","title":"类型","text":"元组类型的最后一个参数可以是特殊值Vararg,它表示任意数量的尾随参数:  ","category":"page"},{"location":"manual/types/","page":"类型","title":"类型","text":"julia> mytupletype = Tuple{AbstractString,Vararg{Int}}\nTuple{AbstractString, Vararg{Int64}}\n\njulia> isa((\"1\",), mytupletype)\ntrue\n\njulia> isa((\"1\",1), mytupletype)\ntrue\n\njulia> isa((\"1\",1,2), mytupletype)\ntrue\n\njulia> isa((\"1\",1,2,3.0), mytupletype)\nfalse","category":"page"},{"location":"manual/types/","page":"类型","title":"类型","text":"此外,Vararg{T} 对应于零个或更多的类型为 T 的元素。变参元组类型被用来表示变参方法接受的参数(请参阅变参函数)。  ","category":"page"},{"location":"manual/types/","page":"类型","title":"类型","text":"特殊值 Vararg{T,N}(当用作元组类型的最后一个参数时)正好对应于类型为 T 的 N 个元素。 NTuple{N,T} 是 Tuple{Vararg{T,N}} 的一个方便的别名,即一个包含正好包含 T 类型的 N 个元素的元组类型。","category":"page"},{"location":"manual/types/#具名元组类型","page":"类型","title":"具名元组类型","text":"","category":"section"},{"location":"manual/types/","page":"类型","title":"类型","text":"具名元组是 NamedTuple 类型的实例,该类型有两个参数:一个给出字段名称的符号元组,和一个给出字段类型的元组类型。","category":"page"},{"location":"manual/types/","page":"类型","title":"类型","text":"julia> typeof((a=1,b=\"hello\"))\nNamedTuple{(:a, :b), Tuple{Int64, String}}","category":"page"},{"location":"manual/types/","page":"类型","title":"类型","text":"@NamedTuple 宏提供了类结构体(struct)的具名元组(NamedTuple)声明,使用 key::Type 的语法,如果省略 ::Type 则默认为 ::Any。","category":"page"},{"location":"manual/types/","page":"类型","title":"类型","text":"julia> @NamedTuple{a::Int, b::String}\nNamedTuple{(:a, :b), Tuple{Int64, String}}\n\njulia> @NamedTuple begin\n a::Int\n b::String\n end\nNamedTuple{(:a, :b), Tuple{Int64, String}}","category":"page"},{"location":"manual/types/","page":"类型","title":"类型","text":"NamedTuple 类型可以用作构造函数,接受一个单独的元组作为参数。构造出来的 NamedTuple 类型可以是具体类型,如果参数都被指定,也可以是只由字段名称所指定的类型:","category":"page"},{"location":"manual/types/","page":"类型","title":"类型","text":"julia> @NamedTuple{a::Float32,b::String}((1,\"\"))\n(a = 1.0f0, b = \"\")\n\njulia> NamedTuple{(:a, :b)}((1,\"\"))\n(a = 1, b = \"\")","category":"page"},{"location":"manual/types/","page":"类型","title":"类型","text":"如果指定了字段类型,参数会被转换。否则,就直接使用参数的类型。","category":"page"},{"location":"manual/types/#参数原始类型","page":"类型","title":"参数原始类型","text":"","category":"section"},{"location":"manual/types/","page":"类型","title":"类型","text":"原始类型也可以参数化声明,例如,指针都能表示为原始类型,其在 Julia 中以如下方式声明:","category":"page"},{"location":"manual/types/","page":"类型","title":"类型","text":"# 32-bit system:\nprimitive type Ptr{T} 32 end\n\n# 64-bit system:\nprimitive type Ptr{T} 64 end","category":"page"},{"location":"manual/types/","page":"类型","title":"类型","text":"与典型的参数复合类型相比,此声明中略显奇怪的特点是类型参数 T 并未在类型本身的定义里使用——它实际上只是一个抽象的标记,定义了一整族具有相同结构的类型,类型间仅由它们的类型参数来区分。因此,Ptr{Float64} 和 Ptr{Int64} 是不同的类型,就算它们具有相同的表示。当然,所有特定的指针类型都是总类型 Ptr 的子类型:","category":"page"},{"location":"manual/types/","page":"类型","title":"类型","text":"julia> Ptr{Float64} <: Ptr\ntrue\n\njulia> Ptr{Int64} <: Ptr\ntrue","category":"page"},{"location":"manual/types/#UnionAll-类型","page":"类型","title":"UnionAll 类型","text":"","category":"section"},{"location":"manual/types/","page":"类型","title":"类型","text":"我们已经说过,像 Ptr 这样的参数类型可充当它所有实例(Ptr{Int64} 等)的超类型。这是如何办到的?Ptr 本身不能是普通的数据类型,因为在不知道引用数据的类型时,该类型显然不能用于存储器操作。答案是 Ptr(或其它参数类型像 Array)是一种不同种类的类型,称为 UnionAll 类型。这种类型表示某些参数的所有值的类型的迭代并集。","category":"page"},{"location":"manual/types/","page":"类型","title":"类型","text":"UnionAll 类型通常使用关键字 where 编写。例如,Ptr 可以更精确地写为 Ptr{T} where T,也就是对于 T 的某些值,所有类型为 Ptr{T} 的值。在这种情况下,参数 T 也常被称为「类型变量」,因为它就像一个取值范围为类型的变量。每个 where 只引入一个类型变量,因此在具有多个参数的类型中这些表达式会被嵌套,例如 Array{T,N} where N where T。","category":"page"},{"location":"manual/types/","page":"类型","title":"类型","text":"类型应用语法 A{B,C} 要求 A 是个 UnionAll 类型,并先代入 B 作为 A 中最外层的类型变量。结果应该是另一个 UnionAll 类型,然后再将 C 代入。所以 A{B,C} 等价于 A{B}{C}。这解释了为什么可以部分实例化一个类型,比如 Array{Float64}:第一个参数已经被固定,但第二个参数仍取遍所有可能值。通过使用 where 语法,任何参数子集都能被固定。例如,所有一维数组的类型可以写为 Array{T,1} where T。","category":"page"},{"location":"manual/types/","page":"类型","title":"类型","text":"类型变量可以用子类型关系来加以限制。Array{T} where T<:Integer 指的是元素类型是某种 Integer 的所有数组。语法 Array{<:Integer} 是 Array{T} where T<:Integer 的便捷的缩写。类型变量可同时具有上下界。Array{T} where Int<:T<:Number 指的是元素类型为能够包含 Int 的 Number 的所有数组(因为 T 至少和 Int 一样大)。语法 where T>:Int 也能用来只指定类型变量的下界,且 Array{>:Int} 等价于 Array{T} where T>:Int。","category":"page"},{"location":"manual/types/","page":"类型","title":"类型","text":"由于 where 表达式可以嵌套,类型变量界可以引用更外层的类型变量。比如 Tuple{T,Array{S}} where S<:AbstractArray{T} where T<:Real 指的是二元元组,其第一个元素是某个 Real,而第二个元素是数组的数组 Array,其包含的内部数组的元素类型由元组的第一个元素类型决定。","category":"page"},{"location":"manual/types/","page":"类型","title":"类型","text":"where 关键字本身可以嵌套在更复杂的声明里。例如,考虑由以下声明创建的两个类型:","category":"page"},{"location":"manual/types/","page":"类型","title":"类型","text":"julia> const T1 = Array{Array{T, 1} where T, 1}\nVector{Vector} (alias for Array{Array{T, 1} where T, 1})\n\njulia> const T2 = Array{Array{T, 1}, 1} where T\nArray{Vector{T}, 1} where T","category":"page"},{"location":"manual/types/","page":"类型","title":"类型","text":"类型 T1 定义了由一维数组组成的一维数组;每个内部数组由相同类型的对象组成,但此类型对于不同内部数组可以不同。另一方面,类型 T2 定义了由一维数组组成的一维数组,其中的每个内部数组必须具有相同的类型。请注意,T2 是个抽象类型,比如 Array{Array{Int,1},1} <: T2,而 T1 是个具体类型。因此,T1 可由零参数构造函数 a=T1() 构造,但 T2 不行。","category":"page"},{"location":"manual/types/","page":"类型","title":"类型","text":"命名此类型有一种方便的语法,类似于函数定义语法的简短形式:","category":"page"},{"location":"manual/types/","page":"类型","title":"类型","text":"Vector{T} = Array{T, 1}","category":"page"},{"location":"manual/types/","page":"类型","title":"类型","text":"这等价于 const Vector = Array{T,1} where T。编写 Vector{Float64} 等价于编写 Array{Float64,1},总类型 Vector 具有所有 Array 对象的实例,其中 Array 对象的第二个参数——数组维数——是 1,而不考虑元素类型是什么。在参数类型必须总被完整指定的语言中,这不是特别有用,但在 Julia 中,这允许只编写 Vector 来表示包含任何元素类型的所有一维密集数组的抽象类型。","category":"page"},{"location":"manual/types/#man-singleton-types","page":"类型","title":"单例类型","text":"","category":"section"},{"location":"manual/types/","page":"类型","title":"类型","text":"没有字段的不可变复合类型称为 单例类型。正式地,如果","category":"page"},{"location":"manual/types/","page":"类型","title":"类型","text":"T 是一个不可变的复合类型(即用 struct 定义),\na isa T && b isa T 暗含 a === b,","category":"page"},{"location":"manual/types/","page":"类型","title":"类型","text":"那么T是单例类型。[2] Base.issingletontype 可以用来检查一个类型是否是单例类型。 抽象类型 不能通过构造成为单例类型。","category":"page"},{"location":"manual/types/","page":"类型","title":"类型","text":"根据定义,此类类型只能有一个实例:","category":"page"},{"location":"manual/types/","page":"类型","title":"类型","text":"julia> struct NoFields\n end\n\njulia> NoFields() === NoFields()\ntrue\n\njulia> Base.issingletontype(NoFields)\ntrue","category":"page"},{"location":"manual/types/","page":"类型","title":"类型","text":"=== 函数确认NoFields 的构造实例实际上是一个且相同的。","category":"page"},{"location":"manual/types/","page":"类型","title":"类型","text":"当上述条件成立时,参数类型可以是单例类型。例如,","category":"page"},{"location":"manual/types/","page":"类型","title":"类型","text":"julia> struct NoFieldsParam{T}\n end\n\njulia> Base.issingletontype(NoFieldsParam) # can't be a singleton type ...\nfalse\n\njulia> NoFieldsParam{Int}() isa NoFieldsParam # ... because it has ...\ntrue\n\njulia> NoFieldsParam{Bool}() isa NoFieldsParam # ... multiple instances\ntrue\n\njulia> Base.issingletontype(NoFieldsParam{Int}) # parametrized, it is a singleton\ntrue\n\njulia> NoFieldsParam{Int}() === NoFieldsParam{Int}()\ntrue","category":"page"},{"location":"manual/types/#man-typet-type","page":"类型","title":"Type{T} 类型选择器","text":"","category":"section"},{"location":"manual/types/","page":"类型","title":"类型","text":"对于每个类型T,Type{T} 是一个抽象的参数类型,它的唯一实例是对象T。 在我们讨论 参数方法 和 类型转换 之前,很难解释这个构造的效用,但简而言之,它允许人们专门针对特定类型的函数行为 作为值。 这对于编写其行为取决于作为显式参数给出的类型而不是由其参数之一的类型隐含的类型的方法(尤其是参数方法)很有用。","category":"page"},{"location":"manual/types/","page":"类型","title":"类型","text":"由于定义有点难理解,我们来看一些例子:","category":"page"},{"location":"manual/types/","page":"类型","title":"类型","text":"julia> isa(Float64, Type{Float64})\ntrue\n\njulia> isa(Real, Type{Float64})\nfalse\n\njulia> isa(Real, Type{Real})\ntrue\n\njulia> isa(Float64, Type{Real})\nfalse","category":"page"},{"location":"manual/types/","page":"类型","title":"类型","text":"换句话说,is(A, Type{B}) 当且仅当 A 和 B 是同一个对象并且该对象是一个类型时才为真。","category":"page"},{"location":"manual/types/","page":"类型","title":"类型","text":"特别的,由于参数类型是 不变量,我们有","category":"page"},{"location":"manual/types/","page":"类型","title":"类型","text":"julia> struct TypeParamExample{T}\n x::T\n end\n\njulia> TypeParamExample isa Type{TypeParamExample}\ntrue\n\njulia> TypeParamExample{Int} isa Type{TypeParamExample}\nfalse\n\njulia> TypeParamExample{Int} isa Type{TypeParamExample{Int}}\ntrue","category":"page"},{"location":"manual/types/","page":"类型","title":"类型","text":"如果没有参数,Type 只是一个抽象类型,所有类型对象都是其实例:","category":"page"},{"location":"manual/types/","page":"类型","title":"类型","text":"julia> isa(Type{Float64}, Type)\ntrue\n\njulia> isa(Float64, Type)\ntrue\n\njulia> isa(Real, Type)\ntrue","category":"page"},{"location":"manual/types/","page":"类型","title":"类型","text":"不是类型的对象不是 Type 的实例:","category":"page"},{"location":"manual/types/","page":"类型","title":"类型","text":"julia> isa(1, Type)\nfalse\n\njulia> isa(\"foo\", Type)\nfalse","category":"page"},{"location":"manual/types/","page":"类型","title":"类型","text":"虽然 Type 与任何其他抽象参数类型一样是 Julia 类型层次结构的一部分,但它并不常用在方法签名之外,除非在某些特殊情况下。 Type 的另一个重要用法是使不太精确的字段类型更加清晰,例如DataType 在下面的示例中,默认构造函数可能会导致依赖精确包装类型的代码出现性能问题(类似于 [抽象类型参数](@ref man-performance-abstract-container))。","category":"page"},{"location":"manual/types/","page":"类型","title":"类型","text":"julia> struct WrapType{T}\n value::T\n end\n\njulia> WrapType(Float64) # default constructor, note DataType\nWrapType{DataType}(Float64)\n\njulia> WrapType(::Type{T}) where T = WrapType{Type{T}}(T)\nWrapType\n\njulia> WrapType(Float64) # sharpened constructor, note more precise Type{Float64}\nWrapType{Type{Float64}}(Float64)","category":"page"},{"location":"manual/types/#类型别名","page":"类型","title":"类型别名","text":"","category":"section"},{"location":"manual/types/","page":"类型","title":"类型","text":"有时为一个已经可表达的类型引入新名称是很方便的。这可通过一个简单的赋值语句完成。例如,UInt 是 UInt32 或 UInt64 的别名,因为它的大小与系统上的指针大小是相适应的。","category":"page"},{"location":"manual/types/","page":"类型","title":"类型","text":"# 32-bit system:\njulia> UInt\nUInt32\n\n# 64-bit system:\njulia> UInt\nUInt64","category":"page"},{"location":"manual/types/","page":"类型","title":"类型","text":"这是由 base/boot.jl 中以下代码实现的:","category":"page"},{"location":"manual/types/","page":"类型","title":"类型","text":"if Int === Int64\n const UInt = UInt64\nelse\n const UInt = UInt32\nend","category":"page"},{"location":"manual/types/","page":"类型","title":"类型","text":"当然,这依赖于 Int 的别名,但它被预定义成正确的类型—— Int32 或 Int64。","category":"page"},{"location":"manual/types/","page":"类型","title":"类型","text":"(注意,与 Int 不同,Float 不作为特定大小的 AbstractFloat 类型的别名而存在。与整数寄存器不同,浮点数寄存器大小由 IEEE-754 标准指定,而 Int 的大小反映了该机器上本地指针的大小。)","category":"page"},{"location":"manual/types/#类型操作","page":"类型","title":"类型操作","text":"","category":"section"},{"location":"manual/types/","page":"类型","title":"类型","text":"因为 Julia 中的类型本身就是对象,所以一般的函数可以对它们进行操作。已经引入了一些对于使用或探索类型特别有用的函数,例如 <: 运算符,它表示其左操作数是否为其右操作数的子类型。","category":"page"},{"location":"manual/types/","page":"类型","title":"类型","text":"isa 函数测试对象是否具有给定类型并返回 true 或 false:","category":"page"},{"location":"manual/types/","page":"类型","title":"类型","text":"julia> isa(1, Int)\ntrue\n\njulia> isa(1, AbstractFloat)\nfalse","category":"page"},{"location":"manual/types/","page":"类型","title":"类型","text":"在文档示例中随处可见的 typeof 函数返回其参数的类型。如上所述,因为类型都是对象,所以它们也有类型,我们可以询问它们的类型:","category":"page"},{"location":"manual/types/","page":"类型","title":"类型","text":"julia> typeof(Rational{Int})\nDataType\n\njulia> typeof(Union{Real,String})\nUnion","category":"page"},{"location":"manual/types/","page":"类型","title":"类型","text":"如果我们重复这个过程会怎样?一个类型的类型是什么?碰巧,每个类型都是复合值,因此都具有 DataType 类型:","category":"page"},{"location":"manual/types/","page":"类型","title":"类型","text":"julia> typeof(DataType)\nDataType\n\njulia> typeof(Union)\nDataType","category":"page"},{"location":"manual/types/","page":"类型","title":"类型","text":"DataType 是它自己的类型。","category":"page"},{"location":"manual/types/","page":"类型","title":"类型","text":"另一个适用于某些类型的操作是 supertype,它显示了类型的超类型。只有已声明的类型(DataType)才有明确的超类型:","category":"page"},{"location":"manual/types/","page":"类型","title":"类型","text":"julia> supertype(Float64)\nAbstractFloat\n\njulia> supertype(Number)\nAny\n\njulia> supertype(AbstractString)\nAny\n\njulia> supertype(Any)\nAny","category":"page"},{"location":"manual/types/","page":"类型","title":"类型","text":"如果将 supertype 应用于其它类型对象(或非类型对象),则会引发 MethodError:","category":"page"},{"location":"manual/types/","page":"类型","title":"类型","text":"julia> supertype(Union{Float64,Int64})\nERROR: MethodError: no method matching supertype(::Type{Union{Float64, Int64}})\nClosest candidates are:\n[...]","category":"page"},{"location":"manual/types/#man-custom-pretty-printing","page":"类型","title":"自定义 pretty-printing","text":"","category":"section"},{"location":"manual/types/","page":"类型","title":"类型","text":"通常,人们会想要自定义显示类型实例的方式。这可通过重载 show 函数来完成。举个例子,假设我们定义一个类型来表示极坐标形式的复数:","category":"page"},{"location":"manual/types/","page":"类型","title":"类型","text":"julia> struct Polar{T<:Real} <: Number\n r::T\n Θ::T\n end\n\njulia> Polar(r::Real,Θ::Real) = Polar(promote(r,Θ)...)\nPolar","category":"page"},{"location":"manual/types/","page":"类型","title":"类型","text":"在这里,我们添加了一个自定义的构造函数,这样就可以接受不同 Real 类型的参数并将它们类型提升为共同类型(请参阅构造函数和类型转换和类型提升)。(当然,为了让它表现地像个 Number,我们需要定义许多其它方法,例如 +、*、one、zero 及类型提升规则等。)默认情况下,此类型的实例只是相当简单地显示有关类型名称和字段值的信息,比如,Polar{Float64}(3.0,4.0)。","category":"page"},{"location":"manual/types/","page":"类型","title":"类型","text":"如果我们希望它显示为 3.0 * exp(4.0im),我们可定义以下方法来将对象打印到给定的输出对象 io(其代表文件、终端、及缓冲区等;请参阅网络和流):","category":"page"},{"location":"manual/types/","page":"类型","title":"类型","text":"julia> Base.show(io::IO, z::Polar) = print(io, z.r, \" * exp(\", z.Θ, \"im)\")","category":"page"},{"location":"manual/types/","page":"类型","title":"类型","text":"Polar 对象的输出可以被更精细地控制。特别是,人们有时想要啰嗦的多行打印格式,用于在 REPL 和其它交互式环境中显示单个对象,以及一个更紧凑的单行格式,用于 print 函数或在作为其它对象(比如一个数组)的部分是显示该对象。虽然在两种情况下默认都会调用 show(io, z) 函数,你仍可以定义一个不同的多行格式来显示单个对象,这通过重载三参数形式的 show 函数,该函数接收 text/plain MIME 类型(请参阅 多媒体 I/O)作为它的第二个参数,举个例子:","category":"page"},{"location":"manual/types/","page":"类型","title":"类型","text":"julia> Base.show(io::IO, ::MIME\"text/plain\", z::Polar{T}) where{T} =\n print(io, \"Polar{$T} complex number:\\n \", z)","category":"page"},{"location":"manual/types/","page":"类型","title":"类型","text":"(请注意 print(..., z) 在这里调用的是双参数的 show(io, z) 方法。)这导致:","category":"page"},{"location":"manual/types/","page":"类型","title":"类型","text":"julia> Polar(3, 4.0)\nPolar{Float64} complex number:\n 3.0 * exp(4.0im)\n\njulia> [Polar(3, 4.0), Polar(4.0,5.3)]\n2-element Vector{Polar{Float64}}:\n 3.0 * exp(4.0im)\n 4.0 * exp(5.3im)","category":"page"},{"location":"manual/types/","page":"类型","title":"类型","text":"其中单行格式的 show(io, z) 仍用于由 Polar 值组成的数组。从技术上讲,REPL 调用 display(z) 来显示单行的执行结果,其默认为 show(stdout, MIME(\"text/plain\"), z),而后者又默认为 show(stdout, z),但是你不应该定义新的 display 方法,除非你正在定义新的多媒体显示管理器(请参阅多媒体 I/O)。","category":"page"},{"location":"manual/types/","page":"类型","title":"类型","text":"此外,你还可以为其它 MIME 类型定义 show 方法,以便在支持的环境(比如 IJulia)中实现更丰富的对象显示(HTML、图像等)。例如,我们可以定义 Polar 对象的 HTML 显示格式,使其带有上标和斜体:","category":"page"},{"location":"manual/types/","page":"类型","title":"类型","text":"julia> Base.show(io::IO, ::MIME\"text/html\", z::Polar{T}) where {T} =\n println(io, \"Polar{$T} complex number: \",\n z.r, \" e\", z.Θ, \" i\")","category":"page"},{"location":"manual/types/","page":"类型","title":"类型","text":"之后会在支持 HTML 显示的环境中自动使用 HTML 显示 Polar 对象,但你也可以手动调用 show 来获取 HTML 输出:","category":"page"},{"location":"manual/types/","page":"类型","title":"类型","text":"julia> show(stdout, \"text/html\", Polar(3.0,4.0))\nPolar{Float64} complex number: 3.0 e4.0 i","category":"page"},{"location":"manual/types/","page":"类型","title":"类型","text":"

        An HTML renderer would display this as: Polar{Float64} complex number: 3.0 e4.0 i

        ","category":"page"},{"location":"manual/types/","page":"类型","title":"类型","text":"根据经验,单行 show 方法应为创建的显示对象打印有效的 Julia 表达式。当这个 show 方法包含中缀运算符时,比如上面的 Polar 的单行 show 方法里的乘法运算符(*),在作为另一个对象的部分打印时,它可能无法被正确解析。要查看此问题,请考虑下面的表达式对象(请参阅程序表示),它代表 Polar 类型的特定实例的平方:","category":"page"},{"location":"manual/types/","page":"类型","title":"类型","text":"julia> a = Polar(3, 4.0)\nPolar{Float64} complex number:\n 3.0 * exp(4.0im)\n\njulia> print(:($a^2))\n3.0 * exp(4.0im) ^ 2","category":"page"},{"location":"manual/types/","page":"类型","title":"类型","text":"因为运算符 ^ 的优先级高于 *(请参阅运算符的优先级与结合性),所以此输出错误地表示了表达式 a ^ 2,而该表达式等价于 (3.0 * exp(4.0im)) ^ 2。为了解决这个问题,我们必须为 Base.show_unquoted(io::IO, z::Polar, indent::Int, precedence::Int) 创建一个自定义方法,在打印时,表达式对象会在内部调用它:","category":"page"},{"location":"manual/types/","page":"类型","title":"类型","text":"julia> function Base.show_unquoted(io::IO, z::Polar, ::Int, precedence::Int)\n if Base.operator_precedence(:*) <= precedence\n print(io, \"(\")\n show(io, z)\n print(io, \")\")\n else\n show(io, z)\n end\n end\n\njulia> :($a^2)\n:((3.0 * exp(4.0im)) ^ 2)","category":"page"},{"location":"manual/types/","page":"类型","title":"类型","text":"当正在调用的运算符的优先级大于等于乘法的优先级时,上面定义的方法会在 show 调用的两侧加上括号。这个检查允许,在没有括号时也可被正确解析的表达式(例如 :($a + 2) 和 :($a == 2)),在打印时省略括号:","category":"page"},{"location":"manual/types/","page":"类型","title":"类型","text":"julia> :($a + 2)\n:(3.0 * exp(4.0im) + 2)\n\njulia> :($a == 2)\n:(3.0 * exp(4.0im) == 2)","category":"page"},{"location":"manual/types/","page":"类型","title":"类型","text":"在某些情况下,根据上下文调整 show 方法的行为是很有用的。这可通过 IOContext 类型实现,它允许同时传递上下文属性和封装后的 IO 流。例如,我们可以在 :compact 属性设置为 true 时创建一个更短的表示,而在该属性为 false 或不存在时返回长的表示:","category":"page"},{"location":"manual/types/","page":"类型","title":"类型","text":"julia> function Base.show(io::IO, z::Polar)\n if get(io, :compact, false)\n print(io, z.r, \"ℯ\", z.Θ, \"im\")\n else\n print(io, z.r, \" * exp(\", z.Θ, \"im)\")\n end\n end","category":"page"},{"location":"manual/types/","page":"类型","title":"类型","text":"当传入的 IO 流是设置了 :compact(译注:该属性还应当设置为 true)属性的 IOContext 对象时,新的紧凑表示将被使用。特别地,当打印具有多列的数组(由于水平空间有限)时就是这种情况:","category":"page"},{"location":"manual/types/","page":"类型","title":"类型","text":"julia> show(IOContext(stdout, :compact=>true), Polar(3, 4.0))\n3.0ℯ4.0im\n\njulia> [Polar(3, 4.0) Polar(4.0,5.3)]\n1×2 Matrix{Polar{Float64}}:\n 3.0ℯ4.0im 4.0ℯ5.3im","category":"page"},{"location":"manual/types/","page":"类型","title":"类型","text":"有关调整打印效果的常用属性列表,请参阅文档 IOContext。","category":"page"},{"location":"manual/types/#值类型","page":"类型","title":"值类型","text":"","category":"section"},{"location":"manual/types/","page":"类型","title":"类型","text":"在 Julia 中,你无法根据诸如 true 或 false 之类的值进行分派。然而,你可以根据参数类型进行分派,Julia 允许你包含「plain bits」值(类型、符号、整数、浮点数和元组等)作为类型参数。Array{T,N} 里的维度参数就是一个常见的例子,在这里 T 是类型(比如 Float64),而 N 只是个 Int。","category":"page"},{"location":"manual/types/","page":"类型","title":"类型","text":"你可以创建把值作为参数的自定义类型,并使用它们控制自定义类型的分派。为了说明这个想法,让我们引入参数类型 Val{x} 和构造函数 Val(x) = Val{x}(),在不需要更精细的层次结构时,这是利用此技巧的一种习惯的方式。","category":"page"},{"location":"manual/types/","page":"类型","title":"类型","text":"Val 的定义为:","category":"page"},{"location":"manual/types/","page":"类型","title":"类型","text":"julia> struct Val{x}\n end\n\njulia> Val(x) = Val{x}()\nVal","category":"page"},{"location":"manual/types/","page":"类型","title":"类型","text":"Val 的实现就只需要这些。一些 Julia 标准库里的函数接收 Val 的实例作为参数,你也可以使用它来编写你自己的函数,例如:","category":"page"},{"location":"manual/types/","page":"类型","title":"类型","text":"julia> firstlast(::Val{true}) = \"First\"\nfirstlast (generic function with 1 method)\n\njulia> firstlast(::Val{false}) = \"Last\"\nfirstlast (generic function with 2 methods)\n\njulia> firstlast(Val(true))\n\"First\"\n\njulia> firstlast(Val(false))\n\"Last\"","category":"page"},{"location":"manual/types/","page":"类型","title":"类型","text":"为了保证 Julia 的一致性,调用处应当始终传递 Val 实例 而不是 类型,也就是使用 foo(Val(:bar)) 而不是 foo(Val{:bar})。","category":"page"},{"location":"manual/types/","page":"类型","title":"类型","text":"值得注意的是,参数「值」类型非常容易被误用,包括 Val;在不适用的情形下,你很容易使代码性能变得更糟糕。特别是,你可能永远都不会想要写出如上所示的代码。有关 Val 的正确(和不正确)使用的更多信息,请阅读性能建议中更广泛的讨论。","category":"page"},{"location":"manual/types/","page":"类型","title":"类型","text":"[1]: 「少数」由常数 MAX_UNION_SPLITTING 定义,目前设置为 4。","category":"page"},{"location":"manual/types/","page":"类型","title":"类型","text":"[2]: 一些流行的编程语言具有单例类型,包括 Haskell、Scala 和 Ruby。","category":"page"},{"location":"stdlib/Unicode/#Unicode","page":"Unicode","title":"Unicode","text":"","category":"section"},{"location":"stdlib/Unicode/","page":"Unicode","title":"Unicode","text":"Unicode.isassigned\nUnicode.normalize\nUnicode.graphemes","category":"page"},{"location":"stdlib/Unicode/#Unicode.isassigned","page":"Unicode","title":"Unicode.isassigned","text":"Unicode.isassigned(c) -> Bool\n\nReturns true if the given char or integer is an assigned Unicode code point.\n\nExamples\n\njulia> Unicode.isassigned(101)\ntrue\n\njulia> Unicode.isassigned('\\x01')\ntrue\n\n\n\n\n\n","category":"function"},{"location":"stdlib/Unicode/#Unicode.normalize","page":"Unicode","title":"Unicode.normalize","text":"Unicode.normalize(s::AbstractString; keywords...)\nUnicode.normalize(s::AbstractString, normalform::Symbol)\n\nNormalize the string s. By default, canonical composition (compose=true) is performed without ensuring Unicode versioning stability (compat=false), which produces the shortest possible equivalent string but may introduce composition characters not present in earlier Unicode versions.\n\nAlternatively, one of the four \"normal forms\" of the Unicode standard can be specified: normalform can be :NFC, :NFD, :NFKC, or :NFKD. Normal forms C (canonical composition) and D (canonical decomposition) convert different visually identical representations of the same abstract string into a single canonical form, with form C being more compact. Normal forms KC and KD additionally canonicalize \"compatibility equivalents\": they convert characters that are abstractly similar but visually distinct into a single canonical choice (e.g. they expand ligatures into the individual characters), with form KC being more compact.\n\nAlternatively, finer control and additional transformations may be obtained by calling Unicode.normalize(s; keywords...), where any number of the following boolean keywords options (which all default to false except for compose) are specified:\n\ncompose=false: do not perform canonical composition\ndecompose=true: do canonical decomposition instead of canonical composition (compose=true is ignored if present)\ncompat=true: compatibility equivalents are canonicalized\ncasefold=true: perform Unicode case folding, e.g. for case-insensitive string comparison\nnewline2lf=true, newline2ls=true, or newline2ps=true: convert various newline sequences (LF, CRLF, CR, NEL) into a linefeed (LF), line-separation (LS), or paragraph-separation (PS) character, respectively\nstripmark=true: strip diacritical marks (e.g. accents)\nstripignore=true: strip Unicode's \"default ignorable\" characters (e.g. the soft hyphen or the left-to-right marker)\nstripcc=true: strip control characters; horizontal tabs and form feeds are converted to spaces; newlines are also converted to spaces unless a newline-conversion flag was specified\nrejectna=true: throw an error if unassigned code points are found\nstable=true: enforce Unicode versioning stability (never introduce characters missing from earlier Unicode versions)\n\nYou can also use the chartransform keyword (which defaults to identity) to pass an arbitrary function mapping Integer codepoints to codepoints, which is is called on each character in s as it is processed, in order to perform arbitrary additional normalizations. For example, by passing chartransform=Unicode.julia_chartransform, you can apply a few Julia-specific character normalizations that are performed by Julia when parsing identifiers (in addition to NFC normalization: compose=true, stable=true).\n\nFor example, NFKC corresponds to the options compose=true, compat=true, stable=true.\n\nExamples\n\njulia> \"é\" == Unicode.normalize(\"é\") #LHS: Unicode U+00e9, RHS: U+0065 & U+0301\ntrue\n\njulia> \"μ\" == Unicode.normalize(\"µ\", compat=true) #LHS: Unicode U+03bc, RHS: Unicode U+00b5\ntrue\n\njulia> Unicode.normalize(\"JuLiA\", casefold=true)\n\"julia\"\n\njulia> Unicode.normalize(\"JúLiA\", stripmark=true)\n\"JuLiA\"\n\ncompat: Julia 1.8\nThe chartransform keyword argument requires Julia 1.8.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/Unicode/#Unicode.graphemes","page":"Unicode","title":"Unicode.graphemes","text":"graphemes(s::AbstractString) -> GraphemeIterator\n\nReturns an iterator over substrings of s that correspond to the extended graphemes in the string, as defined by Unicode UAX #29. (Roughly, these are what users would perceive as single characters, even though they may contain more than one codepoint; for example a letter combined with an accent mark is a single grapheme.)\n\n\n\n\n\n","category":"function"},{"location":"base/constants/#lib-constants","page":"常量","title":"常量","text":"","category":"section"},{"location":"base/constants/","page":"常量","title":"常量","text":"Core.nothing\nBase.PROGRAM_FILE\nBase.ARGS\nBase.C_NULL\nBase.VERSION\nBase.DEPOT_PATH\nBase.LOAD_PATH\nBase.Sys.BINDIR\nBase.Sys.CPU_THREADS\nBase.Sys.WORD_SIZE\nBase.Sys.KERNEL\nBase.Sys.ARCH\nBase.Sys.MACHINE","category":"page"},{"location":"base/constants/#Core.nothing","page":"常量","title":"Core.nothing","text":"nothing\n\nThe singleton instance of type Nothing, used by convention when there is no value to return (as in a C void function) or when a variable or field holds no value.\n\nSee also: isnothing, something, missing.\n\n\n\n\n\n","category":"constant"},{"location":"base/constants/#Base.PROGRAM_FILE","page":"常量","title":"Base.PROGRAM_FILE","text":"PROGRAM_FILE\n\nA string containing the script name passed to Julia from the command line. Note that the script name remains unchanged from within included files. Alternatively see @__FILE__.\n\n\n\n\n\n","category":"constant"},{"location":"base/constants/#Base.ARGS","page":"常量","title":"Base.ARGS","text":"ARGS\n\nAn array of the command line arguments passed to Julia, as strings.\n\n\n\n\n\n","category":"constant"},{"location":"base/constants/#Base.C_NULL","page":"常量","title":"Base.C_NULL","text":"C_NULL\n\nThe C null pointer constant, sometimes used when calling external code.\n\n\n\n\n\n","category":"constant"},{"location":"base/constants/#Base.VERSION","page":"常量","title":"Base.VERSION","text":"VERSION\n\nA VersionNumber object describing which version of Julia is in use. See also Version Number Literals.\n\n\n\n\n\n","category":"constant"},{"location":"base/constants/#Base.DEPOT_PATH","page":"常量","title":"Base.DEPOT_PATH","text":"DEPOT_PATH\n\nA stack of \"depot\" locations where the package manager, as well as Julia's code loading mechanisms, look for package registries, installed packages, named environments, repo clones, cached compiled package images, and configuration files. By default it includes:\n\n~/.julia where ~ is the user home as appropriate on the system;\nan architecture-specific shared system directory, e.g. /usr/local/share/julia;\nan architecture-independent shared system directory, e.g. /usr/share/julia.\n\nSo DEPOT_PATH might be:\n\n[joinpath(homedir(), \".julia\"), \"/usr/local/share/julia\", \"/usr/share/julia\"]\n\nThe first entry is the \"user depot\" and should be writable by and owned by the current user. The user depot is where: registries are cloned, new package versions are installed, named environments are created and updated, package repos are cloned, newly compiled package image files are saved, log files are written, development packages are checked out by default, and global configuration data is saved. Later entries in the depot path are treated as read-only and are appropriate for registries, packages, etc. installed and managed by system administrators.\n\nDEPOT_PATH is populated based on the JULIA_DEPOT_PATH environment variable if set.\n\nDEPOT_PATH contents\n\nEach entry in DEPOT_PATH is a path to a directory which contains subdirectories used by Julia for various purposes. Here is an overview of some of the subdirectories that may exist in a depot:\n\nclones: Contains full clones of package repos. Maintained by Pkg.jl and used as a cache.\ncompiled: Contains precompiled *.ji files for packages. Maintained by Julia.\ndev: Default directory for Pkg.develop. Maintained by Pkg.jl and the user.\nenvironments: Default package environments. For instance the global environment for a specific julia version. Maintained by Pkg.jl.\nlogs: Contains logs of Pkg and REPL operations. Maintained by Pkg.jl and Julia.\npackages: Contains packages, some of which were explicitly installed and some which are implicit dependencies. Maintained by Pkg.jl.\nregistries: Contains package registries. By default only General. Maintained by Pkg.jl.\n\nSee also JULIA_DEPOT_PATH, and Code Loading.\n\n\n\n\n\n","category":"constant"},{"location":"base/constants/#Base.LOAD_PATH","page":"常量","title":"Base.LOAD_PATH","text":"LOAD_PATH\n\nAn array of paths for using and import statements to consider as project environments or package directories when loading code. It is populated based on the JULIA_LOAD_PATH environment variable if set; otherwise it defaults to [\"@\", \"@v#.#\", \"@stdlib\"]. Entries starting with @ have special meanings:\n\n@ refers to the \"current active environment\", the initial value of which is initially determined by the JULIA_PROJECT environment variable or the --project command-line option.\n@stdlib expands to the absolute path of the current Julia installation's standard library directory.\n@name refers to a named environment, which are stored in depots (see JULIA_DEPOT_PATH) under the environments subdirectory. The user's named environments are stored in ~/.julia/environments so @name would refer to the environment in ~/.julia/environments/name if it exists and contains a Project.toml file. If name contains # characters, then they are replaced with the major, minor and patch components of the Julia version number. For example, if you are running Julia 1.2 then @v#.# expands to @v1.2 and will look for an environment by that name, typically at ~/.julia/environments/v1.2.\n\nThe fully expanded value of LOAD_PATH that is searched for projects and packages can be seen by calling the Base.load_path() function.\n\nSee also JULIA_LOAD_PATH, JULIA_PROJECT, JULIA_DEPOT_PATH, and Code Loading.\n\n\n\n\n\n","category":"constant"},{"location":"base/constants/#Base.Sys.BINDIR","page":"常量","title":"Base.Sys.BINDIR","text":"Sys.BINDIR::String\n\nA string containing the full path to the directory containing the julia executable.\n\n\n\n\n\n","category":"constant"},{"location":"base/constants/#Base.Sys.CPU_THREADS","page":"常量","title":"Base.Sys.CPU_THREADS","text":"Sys.CPU_THREADS::Int\n\nThe number of logical CPU cores available in the system, i.e. the number of threads that the CPU can run concurrently. Note that this is not necessarily the number of CPU cores, for example, in the presence of hyper-threading.\n\nSee Hwloc.jl or CpuId.jl for extended information, including number of physical cores.\n\n\n\n\n\n","category":"constant"},{"location":"base/constants/#Base.Sys.WORD_SIZE","page":"常量","title":"Base.Sys.WORD_SIZE","text":"Sys.WORD_SIZE::Int\n\nStandard word size on the current machine, in bits.\n\n\n\n\n\n","category":"constant"},{"location":"base/constants/#Base.Sys.KERNEL","page":"常量","title":"Base.Sys.KERNEL","text":"Sys.KERNEL::Symbol\n\nA symbol representing the name of the operating system, as returned by uname of the build configuration.\n\n\n\n\n\n","category":"constant"},{"location":"base/constants/#Base.Sys.ARCH","page":"常量","title":"Base.Sys.ARCH","text":"Sys.ARCH::Symbol\n\nA symbol representing the architecture of the build configuration.\n\n\n\n\n\n","category":"constant"},{"location":"base/constants/#Base.Sys.MACHINE","page":"常量","title":"Base.Sys.MACHINE","text":"Sys.MACHINE::String\n\nA string containing the build triple.\n\n\n\n\n\n","category":"constant"},{"location":"base/constants/","page":"常量","title":"常量","text":"参见:","category":"page"},{"location":"base/constants/","page":"常量","title":"常量","text":"stdin\nstdout\nstderr\nENV\nENDIAN_BOM\nLibc.MS_ASYNC\nLibc.MS_INVALIDATE\nLibc.MS_SYNC","category":"page"},{"location":"devdocs/cartesian/#笛卡尔","page":"笛卡尔","title":"笛卡尔","text":"","category":"section"},{"location":"devdocs/cartesian/","page":"笛卡尔","title":"笛卡尔","text":"The (non-exported) Cartesian module provides macros that facilitate writing multidimensional algorithms. Most often you can write such algorithms with straightforward techniques; however, there are a few cases where Base.Cartesian is still useful or necessary.","category":"page"},{"location":"devdocs/cartesian/#Principles-of-usage","page":"笛卡尔","title":"Principles of usage","text":"","category":"section"},{"location":"devdocs/cartesian/","page":"笛卡尔","title":"笛卡尔","text":"A simple example of usage is:","category":"page"},{"location":"devdocs/cartesian/","page":"笛卡尔","title":"笛卡尔","text":"@nloops 3 i A begin\n s += @nref 3 A i\nend","category":"page"},{"location":"devdocs/cartesian/","page":"笛卡尔","title":"笛卡尔","text":"which generates the following code:","category":"page"},{"location":"devdocs/cartesian/","page":"笛卡尔","title":"笛卡尔","text":"for i_3 = axes(A, 3)\n for i_2 = axes(A, 2)\n for i_1 = axes(A, 1)\n s += A[i_1, i_2, i_3]\n end\n end\nend","category":"page"},{"location":"devdocs/cartesian/","page":"笛卡尔","title":"笛卡尔","text":"In general, Cartesian allows you to write generic code that contains repetitive elements, like the nested loops in this example. Other applications include repeated expressions (e.g., loop unwinding) or creating function calls with variable numbers of arguments without using the \"splat\" construct (i...).","category":"page"},{"location":"devdocs/cartesian/#基本语法","page":"笛卡尔","title":"基本语法","text":"","category":"section"},{"location":"devdocs/cartesian/","page":"笛卡尔","title":"笛卡尔","text":"The (basic) syntax of @nloops is as follows:","category":"page"},{"location":"devdocs/cartesian/","page":"笛卡尔","title":"笛卡尔","text":"The first argument must be an integer (not a variable) specifying the number of loops.\nThe second argument is the symbol-prefix used for the iterator variable. Here we used i, and variables i_1, i_2, i_3 were generated.\nThe third argument specifies the range for each iterator variable. If you use a variable (symbol) here, it's taken as axes(A, dim). More flexibly, you can use the anonymous-function expression syntax described below.\nThe last argument is the body of the loop. Here, that's what appears between the begin...end.","category":"page"},{"location":"devdocs/cartesian/","page":"笛卡尔","title":"笛卡尔","text":"There are some additional features of @nloops described in the reference section.","category":"page"},{"location":"devdocs/cartesian/","page":"笛卡尔","title":"笛卡尔","text":"@nref follows a similar pattern, generating A[i_1,i_2,i_3] from @nref 3 A i. The general practice is to read from left to right, which is why @nloops is @nloops 3 i A expr (as in for i_2 = axes(A, 2), where i_2 is to the left and the range is to the right) whereas @nref is @nref 3 A i (as in A[i_1,i_2,i_3], where the array comes first).","category":"page"},{"location":"devdocs/cartesian/","page":"笛卡尔","title":"笛卡尔","text":"If you're developing code with Cartesian, you may find that debugging is easier when you examine the generated code, using @macroexpand:","category":"page"},{"location":"devdocs/cartesian/","page":"笛卡尔","title":"笛卡尔","text":"DocTestSetup = quote\n import Base.Cartesian: @nref\nend","category":"page"},{"location":"devdocs/cartesian/","page":"笛卡尔","title":"笛卡尔","text":"julia> @macroexpand @nref 2 A i\n:(A[i_1, i_2])","category":"page"},{"location":"devdocs/cartesian/","page":"笛卡尔","title":"笛卡尔","text":"DocTestSetup = nothing","category":"page"},{"location":"devdocs/cartesian/#Supplying-the-number-of-expressions","page":"笛卡尔","title":"Supplying the number of expressions","text":"","category":"section"},{"location":"devdocs/cartesian/","page":"笛卡尔","title":"笛卡尔","text":"The first argument to both of these macros is the number of expressions, which must be an integer. When you're writing a function that you intend to work in multiple dimensions, this may not be something you want to hard-code. The recommended approach is to use a @generated function. Here's an example:","category":"page"},{"location":"devdocs/cartesian/","page":"笛卡尔","title":"笛卡尔","text":"@generated function mysum(A::Array{T,N}) where {T,N}\n quote\n s = zero(T)\n @nloops $N i A begin\n s += @nref $N A i\n end\n s\n end\nend","category":"page"},{"location":"devdocs/cartesian/","page":"笛卡尔","title":"笛卡尔","text":"Naturally, you can also prepare expressions or perform calculations before the quote block.","category":"page"},{"location":"devdocs/cartesian/#Anonymous-function-expressions-as-macro-arguments","page":"笛卡尔","title":"Anonymous-function expressions as macro arguments","text":"","category":"section"},{"location":"devdocs/cartesian/","page":"笛卡尔","title":"笛卡尔","text":"Perhaps the single most powerful feature in Cartesian is the ability to supply anonymous-function expressions that get evaluated at parsing time. Let's consider a simple example:","category":"page"},{"location":"devdocs/cartesian/","page":"笛卡尔","title":"笛卡尔","text":"@nexprs 2 j->(i_j = 1)","category":"page"},{"location":"devdocs/cartesian/","page":"笛卡尔","title":"笛卡尔","text":"@nexprs generates n expressions that follow a pattern. This code would generate the following statements:","category":"page"},{"location":"devdocs/cartesian/","page":"笛卡尔","title":"笛卡尔","text":"i_1 = 1\ni_2 = 1","category":"page"},{"location":"devdocs/cartesian/","page":"笛卡尔","title":"笛卡尔","text":"In each generated statement, an \"isolated\" j (the variable of the anonymous function) gets replaced by values in the range 1:2. Generally speaking, Cartesian employs a LaTeX-like syntax. This allows you to do math on the index j. Here's an example computing the strides of an array:","category":"page"},{"location":"devdocs/cartesian/","page":"笛卡尔","title":"笛卡尔","text":"s_1 = 1\n@nexprs 3 j->(s_{j+1} = s_j * size(A, j))","category":"page"},{"location":"devdocs/cartesian/","page":"笛卡尔","title":"笛卡尔","text":"would generate expressions","category":"page"},{"location":"devdocs/cartesian/","page":"笛卡尔","title":"笛卡尔","text":"s_1 = 1\ns_2 = s_1 * size(A, 1)\ns_3 = s_2 * size(A, 2)\ns_4 = s_3 * size(A, 3)","category":"page"},{"location":"devdocs/cartesian/","page":"笛卡尔","title":"笛卡尔","text":"Anonymous-function expressions have many uses in practice.","category":"page"},{"location":"devdocs/cartesian/#dev-cartesian-reference","page":"笛卡尔","title":"Macro reference","text":"","category":"section"},{"location":"devdocs/cartesian/","page":"笛卡尔","title":"笛卡尔","text":"Base.Cartesian.@nloops\nBase.Cartesian.@nref\nBase.Cartesian.@nextract\nBase.Cartesian.@nexprs\nBase.Cartesian.@ncall\nBase.Cartesian.@ntuple\nBase.Cartesian.@nall\nBase.Cartesian.@nany\nBase.Cartesian.@nif","category":"page"},{"location":"devdocs/cartesian/#Base.Cartesian.@nloops","page":"笛卡尔","title":"Base.Cartesian.@nloops","text":"@nloops N itersym rangeexpr bodyexpr\n@nloops N itersym rangeexpr preexpr bodyexpr\n@nloops N itersym rangeexpr preexpr postexpr bodyexpr\n\nGenerate N nested loops, using itersym as the prefix for the iteration variables. rangeexpr may be an anonymous-function expression, or a simple symbol var in which case the range is axes(var, d) for dimension d.\n\nOptionally, you can provide \"pre\" and \"post\" expressions. These get executed first and last, respectively, in the body of each loop. For example:\n\n@nloops 2 i A d -> j_d = min(i_d, 5) begin\n s += @nref 2 A j\nend\n\nwould generate:\n\nfor i_2 = axes(A, 2)\n j_2 = min(i_2, 5)\n for i_1 = axes(A, 1)\n j_1 = min(i_1, 5)\n s += A[j_1, j_2]\n end\nend\n\nIf you want just a post-expression, supply nothing for the pre-expression. Using parentheses and semicolons, you can supply multi-statement expressions.\n\n\n\n\n\n","category":"macro"},{"location":"devdocs/cartesian/#Base.Cartesian.@nref","page":"笛卡尔","title":"Base.Cartesian.@nref","text":"@nref N A indexexpr\n\nGenerate expressions like A[i_1, i_2, ...]. indexexpr can either be an iteration-symbol prefix, or an anonymous-function expression.\n\nExamples\n\njulia> @macroexpand Base.Cartesian.@nref 3 A i\n:(A[i_1, i_2, i_3])\n\n\n\n\n\n","category":"macro"},{"location":"devdocs/cartesian/#Base.Cartesian.@nextract","page":"笛卡尔","title":"Base.Cartesian.@nextract","text":"@nextract N esym isym\n\nGenerate N variables esym_1, esym_2, ..., esym_N to extract values from isym. isym can be either a Symbol or anonymous-function expression.\n\n@nextract 2 x y would generate\n\nx_1 = y[1]\nx_2 = y[2]\n\nwhile @nextract 3 x d->y[2d-1] yields\n\nx_1 = y[1]\nx_2 = y[3]\nx_3 = y[5]\n\n\n\n\n\n","category":"macro"},{"location":"devdocs/cartesian/#Base.Cartesian.@nexprs","page":"笛卡尔","title":"Base.Cartesian.@nexprs","text":"@nexprs N expr\n\nGenerate N expressions. expr should be an anonymous-function expression.\n\nExamples\n\njulia> @macroexpand Base.Cartesian.@nexprs 4 i -> y[i] = A[i+j]\nquote\n y[1] = A[1 + j]\n y[2] = A[2 + j]\n y[3] = A[3 + j]\n y[4] = A[4 + j]\nend\n\n\n\n\n\n","category":"macro"},{"location":"devdocs/cartesian/#Base.Cartesian.@ncall","page":"笛卡尔","title":"Base.Cartesian.@ncall","text":"@ncall N f sym...\n\nGenerate a function call expression. sym represents any number of function arguments, the last of which may be an anonymous-function expression and is expanded into N arguments.\n\nFor example, @ncall 3 func a generates\n\nfunc(a_1, a_2, a_3)\n\nwhile @ncall 2 func a b i->c[i] yields\n\nfunc(a, b, c[1], c[2])\n\n\n\n\n\n","category":"macro"},{"location":"devdocs/cartesian/#Base.Cartesian.@ntuple","page":"笛卡尔","title":"Base.Cartesian.@ntuple","text":"@ntuple N expr\n\nGenerates an N-tuple. @ntuple 2 i would generate (i_1, i_2), and @ntuple 2 k->k+1 would generate (2,3).\n\n\n\n\n\n","category":"macro"},{"location":"devdocs/cartesian/#Base.Cartesian.@nall","page":"笛卡尔","title":"Base.Cartesian.@nall","text":"@nall N expr\n\nCheck whether all of the expressions generated by the anonymous-function expression expr evaluate to true.\n\n@nall 3 d->(i_d > 1) would generate the expression (i_1 > 1 && i_2 > 1 && i_3 > 1). This can be convenient for bounds-checking.\n\n\n\n\n\n","category":"macro"},{"location":"devdocs/cartesian/#Base.Cartesian.@nany","page":"笛卡尔","title":"Base.Cartesian.@nany","text":"@nany N expr\n\nCheck whether any of the expressions generated by the anonymous-function expression expr evaluate to true.\n\n@nany 3 d->(i_d > 1) would generate the expression (i_1 > 1 || i_2 > 1 || i_3 > 1).\n\n\n\n\n\n","category":"macro"},{"location":"devdocs/cartesian/#Base.Cartesian.@nif","page":"笛卡尔","title":"Base.Cartesian.@nif","text":"@nif N conditionexpr expr\n@nif N conditionexpr expr elseexpr\n\nGenerates a sequence of if ... elseif ... else ... end statements. For example:\n\n@nif 3 d->(i_d >= size(A,d)) d->(error(\"Dimension \", d, \" too big\")) d->println(\"All OK\")\n\nwould generate:\n\nif i_1 > size(A, 1)\n error(\"Dimension \", 1, \" too big\")\nelseif i_2 > size(A, 2)\n error(\"Dimension \", 2, \" too big\")\nelse\n println(\"All OK\")\nend\n\n\n\n\n\n","category":"macro"},{"location":"stdlib/SharedArrays/#共享数组","page":"共享数组","title":"共享数组","text":"","category":"section"},{"location":"stdlib/SharedArrays/","page":"共享数组","title":"共享数组","text":"SharedArrays.SharedArray\nSharedArrays.SharedVector\nSharedArrays.SharedMatrix\nSharedArrays.procs(::SharedArray)\nSharedArrays.sdata\nSharedArrays.indexpids\nSharedArrays.localindices","category":"page"},{"location":"stdlib/SharedArrays/#SharedArrays.SharedArray","page":"共享数组","title":"SharedArrays.SharedArray","text":"SharedArray{T}(dims::NTuple; init=false, pids=Int[])\nSharedArray{T,N}(...)\n\nConstruct a SharedArray of a bits type T and size dims across the processes specified by pids - all of which have to be on the same host. If N is specified by calling SharedArray{T,N}(dims), then N must match the length of dims.\n\nIf pids is left unspecified, the shared array will be mapped across all processes on the current host, including the master. But, localindices and indexpids will only refer to worker processes. This facilitates work distribution code to use workers for actual computation with the master process acting as a driver.\n\nIf an init function of the type initfn(S::SharedArray) is specified, it is called on all the participating workers.\n\nThe shared array is valid as long as a reference to the SharedArray object exists on the node which created the mapping.\n\nSharedArray{T}(filename::AbstractString, dims::NTuple, [offset=0]; mode=nothing, init=false, pids=Int[])\nSharedArray{T,N}(...)\n\nConstruct a SharedArray backed by the file filename, with element type T (must be a bits type) and size dims, across the processes specified by pids - all of which have to be on the same host. This file is mmapped into the host memory, with the following consequences:\n\nThe array data must be represented in binary format (e.g., an ASCII format like CSV cannot be supported)\nAny changes you make to the array values (e.g., A[3] = 0) will also change the values on disk\n\nIf pids is left unspecified, the shared array will be mapped across all processes on the current host, including the master. But, localindices and indexpids will only refer to worker processes. This facilitates work distribution code to use workers for actual computation with the master process acting as a driver.\n\nmode must be one of \"r\", \"r+\", \"w+\", or \"a+\", and defaults to \"r+\" if the file specified by filename already exists, or \"w+\" if not. If an init function of the type initfn(S::SharedArray) is specified, it is called on all the participating workers. You cannot specify an init function if the file is not writable.\n\noffset allows you to skip the specified number of bytes at the beginning of the file.\n\n\n\n\n\n","category":"type"},{"location":"stdlib/SharedArrays/#SharedArrays.SharedVector","page":"共享数组","title":"SharedArrays.SharedVector","text":"SharedVector\n\nA one-dimensional SharedArray.\n\n\n\n\n\n","category":"type"},{"location":"stdlib/SharedArrays/#SharedArrays.SharedMatrix","page":"共享数组","title":"SharedArrays.SharedMatrix","text":"SharedMatrix\n\nA two-dimensional SharedArray.\n\n\n\n\n\n","category":"type"},{"location":"stdlib/SharedArrays/#Distributed.procs-Tuple{SharedArray}","page":"共享数组","title":"Distributed.procs","text":"procs(S::SharedArray)\n\nGet the vector of processes mapping the shared array.\n\n\n\n\n\n","category":"method"},{"location":"stdlib/SharedArrays/#SharedArrays.sdata","page":"共享数组","title":"SharedArrays.sdata","text":"sdata(S::SharedArray)\n\nReturns the actual Array object backing S.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/SharedArrays/#SharedArrays.indexpids","page":"共享数组","title":"SharedArrays.indexpids","text":"indexpids(S::SharedArray)\n\nReturns the current worker's index in the list of workers mapping the SharedArray (i.e. in the same list returned by procs(S)), or 0 if the SharedArray is not mapped locally.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/SharedArrays/#SharedArrays.localindices","page":"共享数组","title":"SharedArrays.localindices","text":"localindices(S::SharedArray)\n\nReturns a range describing the \"default\" indices to be handled by the current process. This range should be interpreted in the sense of linear indexing, i.e., as a sub-range of 1:length(S). In multi-process contexts, returns an empty range in the parent process (or any process for which indexpids returns 0).\n\nIt's worth emphasizing that localindices exists purely as a convenience, and you can partition work on the array among workers any way you wish. For a SharedArray, all indices should be equally fast for each worker process.\n\n\n\n\n\n","category":"function"},{"location":"manual/modules/#modules","page":"模块","title":"模块","text":"","category":"section"},{"location":"manual/modules/","page":"模块","title":"模块","text":"Julia 中的模块有助于将代码组织成连贯的部分。 它们在语法上以 module Name ... end 界定,并具有以下特点:","category":"page"},{"location":"manual/modules/","page":"模块","title":"模块","text":"模块是独立的命名空间,每个都引入了一个新的全局作用域。 这很有用,因为它允许对不同的函数或全局变量使用相同的名称而不会发生冲突,只要它们在不同的模块中即可。\n模块具有用于命名空间管理的工具:每个模块定义一组它export的名称,并且可以使用 using 和 import 从其他模块导入名称(我们将在下面解释这些)。\n模块可以预编译以加快加载速度,并包含用于运行时初始化的代码。","category":"page"},{"location":"manual/modules/","page":"模块","title":"模块","text":"通常,在较大的 Julia 包中,你会看到模块的代码组织成文件,例如","category":"page"},{"location":"manual/modules/","page":"模块","title":"模块","text":"module SomeModule\n\n# export, using, import statements are usually here; we discuss these below\n\ninclude(\"file1.jl\")\ninclude(\"file2.jl\")\n\nend","category":"page"},{"location":"manual/modules/","page":"模块","title":"模块","text":"文件和文件名大多与模块无关; 模块仅与模块表达式相关联。 每个模块可以有多个文件,每个文件可以有多个模块。 include 的行为就像在包含模块的全局作用域内执行源文件的内容一样。 在本章中,我们使用简短和简化的示例,因此我们不会使用include。","category":"page"},{"location":"manual/modules/","page":"模块","title":"模块","text":"我们推荐不要缩进模块的主体,因为这通常会导致整个文件被缩进。 此外,通常使用 UpperCamelCase 作为模块名称(就像类型一样),并在适用时使用复数形式,特别是如果模块包含类似命名的标识符,以避免名称冲突。 例如,","category":"page"},{"location":"manual/modules/","page":"模块","title":"模块","text":"module FastThings\n\nstruct FastThing\n ...\nend\n\nend","category":"page"},{"location":"manual/modules/#namespace-management","page":"模块","title":"命名空间管理","text":"","category":"section"},{"location":"manual/modules/","page":"模块","title":"模块","text":"命名空间管理是指语言提供的设施,用于使模块中的名称在其他模块中可用。 我们在下面详细讨论相关的概念和功能。","category":"page"},{"location":"manual/modules/#合格的名称","page":"模块","title":"合格的名称","text":"","category":"section"},{"location":"manual/modules/","page":"模块","title":"模块","text":"全局作用域内的函数、变量和类型的名称,如sin、ARGS和UnitRange始终属于一个模块,称为母模块,例如,可以与parentmodule交互来找到该模块","category":"page"},{"location":"manual/modules/","page":"模块","title":"模块","text":"julia> parentmodule(UnitRange)\nBase","category":"page"},{"location":"manual/modules/","page":"模块","title":"模块","text":"也可以通过在它们的模块前面加上前缀来引用它们的父模块之外的这些名称,例如Base.UnitRange。 这称为限定名称。 父模块可以使用像Base.Math.sin这样的子模块链来访问,其中Base.Math被称为模块路径。 由于句法歧义,限定只包含符号的名称,例如运算符,需要插入冒号,例如 Base.:+。 少数运算符还需要括号,例如 Base.:(==)。","category":"page"},{"location":"manual/modules/","page":"模块","title":"模块","text":"如果一个名称是限定的,那么它总是可访问的,在函数的情况下,它也可以通过使用限定的名称作为函数名称来添加方法。","category":"page"},{"location":"manual/modules/","page":"模块","title":"模块","text":"在一个模块中,一个变量名可以通过将其声明 global x 不赋值而“保留”。 这可以防止在加载时间后初始化的全局变量的名称冲突。 语法M.x = y 不适用于在另一个模块中分配一个全局变量; 全局分配需要在模块本地进行操作。","category":"page"},{"location":"manual/modules/#导出列表","page":"模块","title":"导出列表","text":"","category":"section"},{"location":"manual/modules/","page":"模块","title":"模块","text":"名称(指函数、类型、全局变量和常量)可以通过 export 添加到模块的 *导出列表 *。 通常,它们位于或靠近模块定义的顶部,以便源代码的读者可以轻松找到它们,如","category":"page"},{"location":"manual/modules/","page":"模块","title":"模块","text":"module NiceStuff\n\nexport nice, DOG\n\nstruct Dog end # singleton type, not exported\n\nconst DOG = Dog() # named instance, exported\n\nnice(x) = \"nice $x\" # function, exported\n\nend","category":"page"},{"location":"manual/modules/","page":"模块","title":"模块","text":"但这只是一个风格建议——一个模块可以在任意位置有多个 export 语句。","category":"page"},{"location":"manual/modules/","page":"模块","title":"模块","text":"导出构成 API(应用程序接口)一部分的名称是很常见的。 在上面的代码中,导出列表建议用户应该使用nice和DOG。 然而,由于限定名称总是使标识符可访问,这只是组织 API 的一个选项:与其他语言不同,Julia 没有真正隐藏模块内部的功能。","category":"page"},{"location":"manual/modules/","page":"模块","title":"模块","text":"此外,某些模块根本不导出名称。 这通常是因为他们的 API 中使用常用词(例如derivative),这很容易与其他模块的导出列表发生冲突。 我们将在下面看到如何管理名称冲突。","category":"page"},{"location":"manual/modules/#单独使用using和import","page":"模块","title":"单独使用using和import","text":"","category":"section"},{"location":"manual/modules/","page":"模块","title":"模块","text":"加载模块最常见的方式可能是using ModuleName。 这 加载 与 ModuleName 关联的代码,并引入","category":"page"},{"location":"manual/modules/","page":"模块","title":"模块","text":"模块名称\n和导出列表的元素到周围的全局命名空间中。","category":"page"},{"location":"manual/modules/","page":"模块","title":"模块","text":"严格来说,声明 using ModuleName 意味着一个名为 ModuleName 的模块可用于根据需要解析名称。 当遇到当前模块中没有定义的全局变量时,系统会在ModuleName导出的变量中查找,找到就使用。 这意味着当前模块中该全局变量的所有使用都将解析为ModuleName中该变量的定义。","category":"page"},{"location":"manual/modules/","page":"模块","title":"模块","text":"继续我们的例子,","category":"page"},{"location":"manual/modules/","page":"模块","title":"模块","text":"using NiceStuff","category":"page"},{"location":"manual/modules/","page":"模块","title":"模块","text":"将加载上面的代码,使 NiceStuff(模块名称)、DOG 和 nice 可用。 Dog 不在导出列表中,但如果名称被模块路径(这里只是模块名称)限定为 NiceStuff.Dog,则可以访问它。","category":"page"},{"location":"manual/modules/","page":"模块","title":"模块","text":"重要的是,导出列表只在using ModuleName 的形式下起作用。","category":"page"},{"location":"manual/modules/","page":"模块","title":"模块","text":"相反,","category":"page"},{"location":"manual/modules/","page":"模块","title":"模块","text":"import NiceStuff","category":"page"},{"location":"manual/modules/","page":"模块","title":"模块","text":"仅将模块名称带入作用域。 用户需要使用 NiceStuff.DOG、NiceStuff.Dog 和 NiceStuff.nice 来访问其内容。 通常,当用户想要保持命名空间干净时,在上下文中使用 import ModuleName。 正如我们将在下一节中看到的,import NiceStuff 等同于 using NiceStuff: NiceStuff。","category":"page"},{"location":"manual/modules/","page":"模块","title":"模块","text":"你可以用逗号分隔符来组合相同类型的多个using和import语句,例如:","category":"page"},{"location":"manual/modules/","page":"模块","title":"模块","text":"using LinearAlgebra, Statistics","category":"page"},{"location":"manual/modules/#具有特定标识符的using-和-import-,并添加方法","page":"模块","title":"具有特定标识符的using 和 import ,并添加方法","text":"","category":"section"},{"location":"manual/modules/","page":"模块","title":"模块","text":"当 using ModuleName: 或 import ModuleName: 后跟以逗号分隔的名称列表时,模块会被加载,但 只有那些特定的名称才会被语句带入命名空间。 例如,","category":"page"},{"location":"manual/modules/","page":"模块","title":"模块","text":"using NiceStuff: nice, DOG","category":"page"},{"location":"manual/modules/","page":"模块","title":"模块","text":"将导入名称nice和DOG。","category":"page"},{"location":"manual/modules/","page":"模块","title":"模块","text":"重要的是,模块名称NiceStuff 不会出现在命名空间中。 如果要使其可访问,则必须明确列出它,如","category":"page"},{"location":"manual/modules/","page":"模块","title":"模块","text":"using NiceStuff: nice, DOG, NiceStuff","category":"page"},{"location":"manual/modules/","page":"模块","title":"模块","text":"Julia有两种形式来表示似乎相同的内容,因为只有 import ModuleName:f 允许在 没有模块路径的情况下向 f 添加方法。也就是说,以下示例将给出一个错误:","category":"page"},{"location":"manual/modules/","page":"模块","title":"模块","text":"using NiceStuff: nice\nstruct Cat end\nnice(::Cat) = \"nice 😸\"","category":"page"},{"location":"manual/modules/","page":"模块","title":"模块","text":"此错误可防止意外将方法添加到你仅打算使用的其他模块中的函数。","category":"page"},{"location":"manual/modules/","page":"模块","title":"模块","text":"有两种方法可以解决这个问题。 你始终可以使用模块路径限定函数名称:","category":"page"},{"location":"manual/modules/","page":"模块","title":"模块","text":"using NiceStuff\nstruct Cat end\nNiceStuff.nice(::Cat) = \"nice 😸\"","category":"page"},{"location":"manual/modules/","page":"模块","title":"模块","text":"或者,你可以import特定的函数名称:","category":"page"},{"location":"manual/modules/","page":"模块","title":"模块","text":"import NiceStuff: nice\nstruct Cat end\nnice(::Cat) = \"nice 😸\"","category":"page"},{"location":"manual/modules/","page":"模块","title":"模块","text":"你选择哪一个取决于你的代码风格。第一种形式表明你正在向另一个模块中的函数添加一个方法(请记住,导入和方法定义可能在单独的文件中),而第二种形式较短,如果你定义了多个方法,这一点尤其方便。","category":"page"},{"location":"manual/modules/","page":"模块","title":"模块","text":"一旦一个变量通过 using 或 import 引入,当前模块就不能创建同名的变量了。而且导入的变量是只读的,给全局变量赋值只能影响到由当前模块拥有的变量,否则会报错。","category":"page"},{"location":"manual/modules/#用as来重命名","page":"模块","title":"用as来重命名","text":"","category":"section"},{"location":"manual/modules/","page":"模块","title":"模块","text":"由import 或using 引入作用域的标识符可以用关键字as 重命名。 这对于解决名称冲突以及缩短名称很有用。 例如,Base 导出函数名read,但CSV.jl 包也提供了CSV.read。 如果我们要多次调用 CSV 读取,删除 CSV. 限定符会很方便。 但是,我们指的是Base.read还是CSV.read是模棱两可的:","category":"page"},{"location":"manual/modules/","page":"模块","title":"模块","text":"julia> read;\n\njulia> import CSV: read\nWARNING: ignoring conflicting import of CSV.read into Main","category":"page"},{"location":"manual/modules/","page":"模块","title":"模块","text":"重命名提供了一个解决方案:","category":"page"},{"location":"manual/modules/","page":"模块","title":"模块","text":"julia> import CSV: read as rd","category":"page"},{"location":"manual/modules/","page":"模块","title":"模块","text":"导入的包本身也可以重命名:","category":"page"},{"location":"manual/modules/","page":"模块","title":"模块","text":"import BenchmarkTools as BT","category":"page"},{"location":"manual/modules/","page":"模块","title":"模块","text":"as 仅在将单个标识符引入作用域时才与 using 一起使用。 例如,using CSV: read as rd 有效,但using CSV as C 无效,因为它对 CSV 中的所有导出名称进行操作。","category":"page"},{"location":"manual/modules/#混合使用多个-using-和-import-语句","page":"模块","title":"混合使用多个 using 和 import 语句","text":"","category":"section"},{"location":"manual/modules/","page":"模块","title":"模块","text":"当使用上述任何形式的多个 using 或 import 语句时,它们的效果将按照它们出现的顺序组合。 例如,","category":"page"},{"location":"manual/modules/","page":"模块","title":"模块","text":"using NiceStuff # exported names and the module name\nimport NiceStuff: nice # allows adding methods to unqualified functions","category":"page"},{"location":"manual/modules/","page":"模块","title":"模块","text":"会将 NiceStuff 的所有导出名称和模块名称本身带入作用域,并且还允许向 nice 添加方法而不用模块名称作为前缀。","category":"page"},{"location":"manual/modules/#处理名称冲突","page":"模块","title":"处理名称冲突","text":"","category":"section"},{"location":"manual/modules/","page":"模块","title":"模块","text":"考虑两个(或更多)包导出相同名称的情况,如","category":"page"},{"location":"manual/modules/","page":"模块","title":"模块","text":"module A\nexport f\nf() = 1\nend\n\nmodule B\nexport f\nf() = 2\nend","category":"page"},{"location":"manual/modules/","page":"模块","title":"模块","text":"using A, B 语句有效,但是当你尝试调用 f 时,你会收到警告","category":"page"},{"location":"manual/modules/","page":"模块","title":"模块","text":"WARNING: both B and A export \"f\"; uses of it in module Main must be qualified\nERROR: LoadError: UndefVarError: f not defined","category":"page"},{"location":"manual/modules/","page":"模块","title":"模块","text":"在这里,Julia 无法确定您指的是哪个 f,因此你必须做出选择。 常用的解决方法有以下几种:","category":"page"},{"location":"manual/modules/","page":"模块","title":"模块","text":"只需继续使用限定名称,如A.f 和B.f。 这使代码的读者可以清楚地了解上下文,特别是如果 f 恰好重合但在不同的包中具有不同的含义。 例如,degree在数学、自然科学和日常生活中有多种用途,这些含义应该分开。\n使用上面的 as 关键字重命名一个或两个标识符,例如\nusing A: f as f\nusing B: f as g\n会使B.f 可用作g。 在这里,我们假设您之前没有使用 using A, 这会把f代入命名空间。\n当问题中的多个名称确实有相同的含义时,通常一个模块会从另一个模块导入它,或者有一个轻量级的“基础”包,它的唯一功能是定义这样的接口,可以被其他包使用。按照惯例,这些包名以 ...Base 结尾(这与 Julia 的 Base 模块无关)","category":"page"},{"location":"manual/modules/#默认顶层定义以及裸模块","page":"模块","title":"默认顶层定义以及裸模块","text":"","category":"section"},{"location":"manual/modules/","page":"模块","title":"模块","text":"模块自动包含 using Core、using Base 以及 eval 和 include 函数的定义,这些函数在该模块的全局作用域内计算表达式/文件 .","category":"page"},{"location":"manual/modules/","page":"模块","title":"模块","text":"如果不需要这些默认定义,可以使用关键字 baremodule 来定义模块(注意:Core 仍然是导入的)。 就 baremodule 而言,一个标准的 module 看起来像这样:","category":"page"},{"location":"manual/modules/","page":"模块","title":"模块","text":"baremodule Mod\n\nusing Base\n\neval(x) = Core.eval(Mod, x)\ninclude(p) = Base.include(Mod, p)\n\n...\n\nend","category":"page"},{"location":"manual/modules/#标准模块","page":"模块","title":"标准模块","text":"","category":"section"},{"location":"manual/modules/","page":"模块","title":"模块","text":"有三个重要的标准模块:","category":"page"},{"location":"manual/modules/","page":"模块","title":"模块","text":"Core 包含了语言“内置”的所有功能。\nBase 包含了绝大多数情况下都会用到的基本功能。\nMain 是顶层模块,当 julia 启动时,也是当前模块。","category":"page"},{"location":"manual/modules/","page":"模块","title":"模块","text":"note: Standard library modules\n默认情况下,Julia 附带了一些标准库模块。 除了你不需要显式安装它们之外,它们的行为与常规 Julia 包类似。 例如,如果您想执行一些单元测试,你可以按如下方式加载 Test 标准库:using Test","category":"page"},{"location":"manual/modules/#子模块和相对路径","page":"模块","title":"子模块和相对路径","text":"","category":"section"},{"location":"manual/modules/","page":"模块","title":"模块","text":"模块可以包含 子模块,嵌套相同的语法module ... end。 它们可用于引入单独的命名空间,这有助于组织复杂的代码库。 请注意,每个 module 都引入了自己的 作用域,因此子模块不会自动从其父模块“继承”名称。","category":"page"},{"location":"manual/modules/","page":"模块","title":"模块","text":"建议子模块在 using 和 import 语句中使用 相对模块限定符 来引用封闭父模块中的其他模块(包括后者)。 相对模块限定符以句点 (.) 开头,它对应于当前模块,每个连续的 . 都指向当前模块的父级。 如有必要,这应该跟在模块之后,最后是要访问的实际名称,所有名称都以.分隔。","category":"page"},{"location":"manual/modules/","page":"模块","title":"模块","text":"考虑以下示例,其中子模块SubA定义了一个函数,然后在其“兄弟”模块中进行扩展:","category":"page"},{"location":"manual/modules/","page":"模块","title":"模块","text":"module ParentModule\n\nmodule SubA\nexport add_D # exported interface\nconst D = 3\nadd_D(x) = x + D\nend\n\nusing .SubA # brings `add_D` into the namespace\n\nexport add_D # export it from ParentModule too\n\nmodule SubB\nimport ..SubA: add_D # relative path for a “sibling” module\nstruct Infinity end\nadd_D(x::Infinity) = x\nend\n\nend","category":"page"},{"location":"manual/modules/","page":"模块","title":"模块","text":"你可能会在包中看到代码,在类似的情况下,它使用","category":"page"},{"location":"manual/modules/","page":"模块","title":"模块","text":"import ParentModule.SubA: add_D","category":"page"},{"location":"manual/modules/","page":"模块","title":"模块","text":"然而,这是通过 代码加载 操作的,因此仅当 ParentModule 在包中时才有效。 最好使用相对路径。","category":"page"},{"location":"manual/modules/","page":"模块","title":"模块","text":"请注意,如果你正在评估值,定义的顺序也很重要。 考虑","category":"page"},{"location":"manual/modules/","page":"模块","title":"模块","text":"module TestPackage\n\nexport x, y\n\nx = 0\n\nmodule Sub\nusing ..TestPackage\nz = y # ERROR: UndefVarError: y not defined\nend\n\ny = 1\n\nend","category":"page"},{"location":"manual/modules/","page":"模块","title":"模块","text":"其中 Sub 在定义之前尝试使用 TestPackage.y,因此它没有值。","category":"page"},{"location":"manual/modules/","page":"模块","title":"模块","text":"出于类似的原因,你不能使用循环顺序:","category":"page"},{"location":"manual/modules/","page":"模块","title":"模块","text":"module A\n\nmodule B\nusing ..C # ERROR: UndefVarError: C not defined\nend\n\nmodule C\nusing ..B\nend\n\nend","category":"page"},{"location":"manual/modules/#模块初始化和预编译","page":"模块","title":"模块初始化和预编译","text":"","category":"section"},{"location":"manual/modules/","page":"模块","title":"模块","text":"因为执行模块中的所有语句通常需要编译大量代码,大型模块可能需要几秒钟才能加载。Julia 会创建模块的预编译缓存以减少这个时间。","category":"page"},{"location":"manual/modules/","page":"模块","title":"模块","text":"当用 import 或 using 加载一个模块时,模块增量预编译文件会自动创建并使用。这会让模块在第一次加载时自动编译。 另外,你也可以手工调用 Base.compilecache(modulename),产生的缓存文件会放在 DEPOT_PATH[1]/compiled/ 目录下。 之后,当该模块的任何一个依赖发生变更时,该模块会在 using 或 import 时自动重新编译; 模块的依赖指的是:任何它导入的模块、Julia 自身、include 的文件或由 include_dependency(path) 显式声明的依赖。","category":"page"},{"location":"manual/modules/","page":"模块","title":"模块","text":"对于文件依赖项,通过检查由 include 加载或由 include_dependency 显式添加的每个文件的修改时间(mtime)是否保持不变,或是否等于截断到最接近秒的修改时间(以适应无法以亚秒精度复制 mtime的系统),来确定更改。它还考虑由 require 中的搜索逻辑选择的文件路径是否与创建预编译文件的路径匹配。它还考虑了已加载到当前进程中的依赖项集,并且不会重新编译这些模块,即使它们的文件更改或消失,以避免在正在运行的系统和预编译缓存之间创建不兼容。","category":"page"},{"location":"manual/modules/","page":"模块","title":"模块","text":"如果你知道一个模块预编译不安全(例如,由于下面描述的原因之一),你应该把__precompile__(false)放在模块文件中(通常放在顶部)。 这会导致Base.compilecache 抛出错误,并且会导致using / import 将其直接加载到当前进程中并跳过预编译和缓存。 这也因此防止了模块被任何其他预编译模块导入。","category":"page"},{"location":"manual/modules/","page":"模块","title":"模块","text":"在开发模块的时候,你可能需要了解一些与增量编译相关的固有行为。例如,外部状态不会被保留。为了解决这个问题,需要显式分离运行时与编译期的部分。Julia 允许你定义一个 __init__() 函数来执行任何需要在运行时发生的初始化。在编译期(--output-*),此函数将不会被调用。你可以假设在代码的生存周期中,此函数只会被运行一次。当然,如果有必要,你也可以手动调用它,但在默认的情况下,请假定此函数是为了处理与本机状态相关的信息,注意这些信息不需要,更不应该存入预编译镜像。此函数会在模块被导入到当前进程之后被调用,这包括在一个增量编译中导入该模块的时候(--output-incremental=yes),但在完整编译时该函数不会被调用。","category":"page"},{"location":"manual/modules/","page":"模块","title":"模块","text":"特别的,如果你在模块里定义了一个名为 __init__() 的函数,那么 Julia 在加载这个模块之后会在第一次运行时(runtime)立刻调用这个函数(例如,通过 import,using,或者 require 加载时),也就是说 __init__ 只会在模块中所有其它命令都执行完以后被调用一次。因为这个函数将在模块完全载入后被调用,任何子模块或者已经载入的模块都将在当前模块调用 __init__ 之前 调用自己的 __init__ 函数。","category":"page"},{"location":"manual/modules/","page":"模块","title":"模块","text":"__init__的典型用法有二,一是用于调用外部 C 库的运行时初始化函数,二是用于初始化涉及到外部库所返回的指针的全局常量。例如,假设我们正在调用一个 C 库 libfoo,它要求我们在运行时调用foo_init() 这个初始化函数。假设我们还想定义一个全局常量 foo_data_ptr,它保存 libfoo 所定义的 void *foo_data() 函数的返回值——必须在运行时(而非编译时)初始化这个常量,因为指针地址不是固定的。可以通过在模块中定义 __init__ 函数来完成这个操作。","category":"page"},{"location":"manual/modules/","page":"模块","title":"模块","text":"const foo_data_ptr = Ref{Ptr{Cvoid}}(0)\nfunction __init__()\n ccall((:foo_init, :libfoo), Cvoid, ())\n foo_data_ptr[] = ccall((:foo_data, :libfoo), Ptr{Cvoid}, ())\n nothing\nend","category":"page"},{"location":"manual/modules/","page":"模块","title":"模块","text":"注意,在像 __init__ 这样的函数里定义一个全局变量是完全可以的,这是动态语言的优点之一。但是把全局作用域的值定义成常量,可以让编译器能确定该值的类型,并且能让编译器生成更好的优化过的代码。显然,你的模块(Module)中,任何其他依赖于 foo_data_ptr 的全局量也必须在 __init__ 中被初始化。","category":"page"},{"location":"manual/modules/","page":"模块","title":"模块","text":"涉及大多数不是由 ccall 生成的 Julia 对象的常量不需要放在 __init__ 中:它们的定义可以从缓存的模块映像中预编译和加载。 这包括复杂的堆分配对象,如数组。 但是,任何返回原始指针值的例程都必须在运行时调用才能使预编译工作(Ptr 对象将变成空指针,除非它们隐藏在 isbits 目的)。 这包括 Julia 函数 @cfunction 和 pointer 的返回值。","category":"page"},{"location":"manual/modules/","page":"模块","title":"模块","text":"字典和集合类型,或者通常任何依赖于 hash(key) 方法的类型,都是比较棘手的情况。 通常当键是数字、字符串、符号、范围、Expr 或这些类型的组合(通过数组、元组、集合、映射对等)时,可以安全地预编译它们。但是,对于一些其它的键类型,例如 Function 或 DataType、以及还没有定义散列方法的通用用户定义类型,回退(fallback)的散列(hash)方法依赖于对象的内存地址(通过 objectid),因此可能会在每次运行时发生变化。 如果您有这些关键类型中的一种,或者您不确定,为了安全起见,您可以在您的 __init__ 函数中初始化这个字典。或者,您可以使用 IdDict 字典类型,它是由预编译专门处理的,因此在编译时初始化是安全的。","category":"page"},{"location":"manual/modules/","page":"模块","title":"模块","text":"当使用预编译时,我们必须要清楚地区分代码的编译阶段和运行阶段。在此模式下,我们会更清楚发现 Julia 的编译器可以执行任何 Julia 代码,而不是一个用于生成编译后代码的独立的解释器。","category":"page"},{"location":"manual/modules/","page":"模块","title":"模块","text":"其它已知的潜在失败场景包括:","category":"page"},{"location":"manual/modules/","page":"模块","title":"模块","text":"全局计数器,例如:为了试图唯一的标识对象。考虑以下代码片段:\nmutable struct UniquedById\n myid::Int\n let counter = 0\n UniquedById() = new(counter += 1)\n end\nend\n尽管这段代码的目标是给每个实例赋一个唯一的 ID,但计数器的值会在代码编译结束时被记录。任何对此增量编译模块的后续使用,计数器都将从同一个值开始计数。\n注意 objectid (工作原理是取内存指针的 hash)也有类似的问题,请查阅下面关于 Dict 的用法。\n一种解决方案是用宏捕捉 @__MODULE__,并将它与目前的 counter 值一起保存。然而,更好的方案是对代码进行重新设计,不要依赖这种全局状态变量。\n像 Dict 和 Set 这种关联集合需要在 __init__ 中 re-hash。Julia 在未来很可能会提供一个机制来注册初始化函数。\n依赖编译期的副作用会在加载时蔓延。例子包括:更改其它 Julia 模块里的数组或变量,操作文件或设备的句柄,保存指向其它系统资源(包括内存)的指针。\n无意中从其它模块中“拷贝”了全局状态:通过直接引用的方式而不是通过查找的方式。例如,在全局作用域下:\n#mystdout = Base.stdout #= will not work correctly, since this will copy Base.stdout into this module =#\n# instead use accessor functions:\ngetstdout() = Base.stdout #= best option =#\n# or move the assignment into the runtime:\n__init__() = global mystdout = Base.stdout #= also works =#","category":"page"},{"location":"manual/modules/","page":"模块","title":"模块","text":"此处为预编译中的操作附加了若干限制,以帮助用户避免其他误操作:","category":"page"},{"location":"manual/modules/","page":"模块","title":"模块","text":"调用 eval 来在另一个模块中引发副作用。当增量预编译被标记时,该操作同时会导致抛出一个警告。\n当 __init__() 已经开始执行后,在局部作用域中声明 global const(见 issue #12010,计划为此情况添加一个错误提示)\n在增量预编译时替换模块是一个运行时错误。","category":"page"},{"location":"manual/modules/","page":"模块","title":"模块","text":"一些其他需要注意的点:","category":"page"},{"location":"manual/modules/","page":"模块","title":"模块","text":"在源代码文件本身被修改之后,不会执行代码重载或缓存失效化处理(包括由 Pkg.update 执行的修改,此外在 Pkg.rm 执行后也没有清理操作)\n变形数组的内存共享特性会被预编译忽略(每个数组样貌都会获得一个拷贝)\n文件系统在编译期间和运行期间被假设为不变的,比如使用 @__FILE__/source_path() 在运行期间寻找资源、或使用 BinDeps 宏 @checked_lib。有时这是不可避免的。但是可能的话,在编译期将资源复制到模块里面是个好做法,这样在运行期间,就不需要去寻找它们了。\nWeakRef 对象和完成器目前在序列化器中无法被恰当地处理(在接下来的发行版中将修复)。\n通常,最好避免去捕捉内部元数据对象的引用,如 Method、MethodInstance、TypeMapLevel、TypeMapEntry 及这些对象的字段,因为这会迷惑序列化器,且可能会引发你不想要的结果。此操作不足以成为一个错误,但你需做好准备:系统会尝试拷贝一部分,然后创建其余部分的单个独立实例。","category":"page"},{"location":"manual/modules/","page":"模块","title":"模块","text":"在开发模块时,关闭增量预编译可能会有所帮助。命令行标记 --compiled-modules={yes|no} 可以让你切换预编译的开启和关闭。当 Julia 附加 --compiled-modules=no 启动,在载入模块和模块依赖时,编译缓存中的序列化模块会被忽略。Base.compilecache 仍可以被手动调用。此命令行标记的状态会被传递给 Pkg.build,禁止其在安装、更新、显式构建包时触发自动预编译。","category":"page"},{"location":"devdocs/debuggingtips/#gdb-调试提示","page":"gdb 调试提示","title":"gdb 调试提示","text":"","category":"section"},{"location":"devdocs/debuggingtips/#显示-Julia-变量","page":"gdb 调试提示","title":"显示 Julia 变量","text":"","category":"section"},{"location":"devdocs/debuggingtips/","page":"gdb 调试提示","title":"gdb 调试提示","text":"在 gdb 中, 任何 jl_value_t* 类型的变量 obj 的展示可以通过使用:","category":"page"},{"location":"devdocs/debuggingtips/","page":"gdb 调试提示","title":"gdb 调试提示","text":"(gdb) call jl_(obj)","category":"page"},{"location":"devdocs/debuggingtips/","page":"gdb 调试提示","title":"gdb 调试提示","text":"这个对象会在 julia 会话中展示,而不是在 gdb 会话中。这是一种行之有效的方式来发现由 Julia 的 C 代码操控的对象的类型和值。","category":"page"},{"location":"devdocs/debuggingtips/","page":"gdb 调试提示","title":"gdb 调试提示","text":"同样,如果你在调试一些 Julia 内部的东西 (比如 compiler.jl ),你可以通过使用这些来打印 obj :","category":"page"},{"location":"devdocs/debuggingtips/","page":"gdb 调试提示","title":"gdb 调试提示","text":"ccall(:jl_, Cvoid, (Any,), obj)","category":"page"},{"location":"devdocs/debuggingtips/","page":"gdb 调试提示","title":"gdb 调试提示","text":"这是一种很好的方法,可以避免 Julia 的输出流初始化顺序引起的问题。","category":"page"},{"location":"devdocs/debuggingtips/","page":"gdb 调试提示","title":"gdb 调试提示","text":"Julia的 flisp 解释器使用 value_t 对象;能够通过 call fl_print(fl_ctx, ios_stdout, obj) 来展示。","category":"page"},{"location":"devdocs/debuggingtips/#有用的用于检查的-Julia-变量","page":"gdb 调试提示","title":"有用的用于检查的 Julia 变量","text":"","category":"section"},{"location":"devdocs/debuggingtips/","page":"gdb 调试提示","title":"gdb 调试提示","text":"While the addresses of many variables, like singletons, can be useful to print for many failures, there are a number of additional variables (see julia.h for a complete list) that are even more useful.","category":"page"},{"location":"devdocs/debuggingtips/","page":"gdb 调试提示","title":"gdb 调试提示","text":"(when in jl_apply_generic) mfunc and jl_uncompress_ast(mfunc->def, mfunc->code) :: for figuring out a bit about the call-stack\njl_lineno and jl_filename :: for figuring out what line in a test to go start debugging from (or figure out how far into a file has been parsed)\n$1 :: not really a variable, but still a useful shorthand for referring to the result of the last gdb command (such as print)\njl_options :: sometimes useful, since it lists all of the command line options that were successfully parsed\njl_uv_stderr :: because who doesn't like to be able to interact with stdio","category":"page"},{"location":"devdocs/debuggingtips/#Useful-Julia-functions-for-Inspecting-those-variables","page":"gdb 调试提示","title":"Useful Julia functions for Inspecting those variables","text":"","category":"section"},{"location":"devdocs/debuggingtips/","page":"gdb 调试提示","title":"gdb 调试提示","text":"jl_gdblookup($rip) :: For looking up the current function and line. (use $eip on i686 platforms)\njlbacktrace() :: For dumping the current Julia backtrace stack to stderr. Only usable after record_backtrace() has been called.\njl_dump_llvm_value(Value*) :: For invoking Value->dump() in gdb, where it doesn't work natively. For example, f->linfo->functionObject, f->linfo->specFunctionObject, and to_function(f->linfo).\nType->dump() :: only works in lldb. Note: add something like ;1 to prevent lldb from printing its prompt over the output\njl_eval_string(\"expr\") :: for invoking side-effects to modify the current state or to lookup symbols\njl_typeof(jl_value_t*) :: for extracting the type tag of a Julia value (in gdb, call macro define jl_typeof jl_typeof first, or pick something short like ty for the first arg to define a shorthand)","category":"page"},{"location":"devdocs/debuggingtips/#Inserting-breakpoints-for-inspection-from-gdb","page":"gdb 调试提示","title":"Inserting breakpoints for inspection from gdb","text":"","category":"section"},{"location":"devdocs/debuggingtips/","page":"gdb 调试提示","title":"gdb 调试提示","text":"In your gdb session, set a breakpoint in jl_breakpoint like so:","category":"page"},{"location":"devdocs/debuggingtips/","page":"gdb 调试提示","title":"gdb 调试提示","text":"(gdb) break jl_breakpoint","category":"page"},{"location":"devdocs/debuggingtips/","page":"gdb 调试提示","title":"gdb 调试提示","text":"Then within your Julia code, insert a call to jl_breakpoint by adding","category":"page"},{"location":"devdocs/debuggingtips/","page":"gdb 调试提示","title":"gdb 调试提示","text":"ccall(:jl_breakpoint, Cvoid, (Any,), obj)","category":"page"},{"location":"devdocs/debuggingtips/","page":"gdb 调试提示","title":"gdb 调试提示","text":"where obj can be any variable or tuple you want to be accessible in the breakpoint.","category":"page"},{"location":"devdocs/debuggingtips/","page":"gdb 调试提示","title":"gdb 调试提示","text":"It's particularly helpful to back up to the jl_apply frame, from which you can display the arguments to a function using, e.g.,","category":"page"},{"location":"devdocs/debuggingtips/","page":"gdb 调试提示","title":"gdb 调试提示","text":"(gdb) call jl_(args[0])","category":"page"},{"location":"devdocs/debuggingtips/","page":"gdb 调试提示","title":"gdb 调试提示","text":"Another useful frame is to_function(jl_method_instance_t *li, bool cstyle). The jl_method_instance_t* argument is a struct with a reference to the final AST sent into the compiler. However, the AST at this point will usually be compressed; to view the AST, call jl_uncompress_ast and then pass the result to jl_:","category":"page"},{"location":"devdocs/debuggingtips/","page":"gdb 调试提示","title":"gdb 调试提示","text":"#2 0x00007ffff7928bf7 in to_function (li=0x2812060, cstyle=false) at codegen.cpp:584\n584 abort();\n(gdb) p jl_(jl_uncompress_ast(li, li->ast))","category":"page"},{"location":"devdocs/debuggingtips/#Inserting-breakpoints-upon-certain-conditions","page":"gdb 调试提示","title":"Inserting breakpoints upon certain conditions","text":"","category":"section"},{"location":"devdocs/debuggingtips/#Loading-a-particular-file","page":"gdb 调试提示","title":"Loading a particular file","text":"","category":"section"},{"location":"devdocs/debuggingtips/","page":"gdb 调试提示","title":"gdb 调试提示","text":"Let's say the file is sysimg.jl:","category":"page"},{"location":"devdocs/debuggingtips/","page":"gdb 调试提示","title":"gdb 调试提示","text":"(gdb) break jl_load if strcmp(fname, \"sysimg.jl\")==0","category":"page"},{"location":"devdocs/debuggingtips/#Calling-a-particular-method","page":"gdb 调试提示","title":"Calling a particular method","text":"","category":"section"},{"location":"devdocs/debuggingtips/","page":"gdb 调试提示","title":"gdb 调试提示","text":"(gdb) break jl_apply_generic if strcmp((char*)(jl_symbol_name)(jl_gf_mtable(F)->name), \"method_to_break\")==0","category":"page"},{"location":"devdocs/debuggingtips/","page":"gdb 调试提示","title":"gdb 调试提示","text":"Since this function is used for every call, you will make everything 1000x slower if you do this.","category":"page"},{"location":"devdocs/debuggingtips/#Dealing-with-signals","page":"gdb 调试提示","title":"Dealing with signals","text":"","category":"section"},{"location":"devdocs/debuggingtips/","page":"gdb 调试提示","title":"gdb 调试提示","text":"Julia requires a few signal to function property. The profiler uses SIGUSR2 for sampling and the garbage collector uses SIGSEGV for threads synchronization. If you are debugging some code that uses the profiler or multiple threads, you may want to let the debugger ignore these signals since they can be triggered very often during normal operations. The command to do this in GDB is (replace SIGSEGV with SIGUSRS or other signals you want to ignore):","category":"page"},{"location":"devdocs/debuggingtips/","page":"gdb 调试提示","title":"gdb 调试提示","text":"(gdb) handle SIGSEGV noprint nostop pass","category":"page"},{"location":"devdocs/debuggingtips/","page":"gdb 调试提示","title":"gdb 调试提示","text":"The corresponding LLDB command is (after the process is started):","category":"page"},{"location":"devdocs/debuggingtips/","page":"gdb 调试提示","title":"gdb 调试提示","text":"(lldb) pro hand -p true -s false -n false SIGSEGV","category":"page"},{"location":"devdocs/debuggingtips/","page":"gdb 调试提示","title":"gdb 调试提示","text":"If you are debugging a segfault with threaded code, you can set a breakpoint on jl_critical_error (sigdie_handler should also work on Linux and BSD) in order to only catch the actual segfault rather than the GC synchronization points.","category":"page"},{"location":"devdocs/debuggingtips/#Debugging-during-Julia's-build-process-(bootstrap)","page":"gdb 调试提示","title":"Debugging during Julia's build process (bootstrap)","text":"","category":"section"},{"location":"devdocs/debuggingtips/","page":"gdb 调试提示","title":"gdb 调试提示","text":"Errors that occur during make need special handling. Julia is built in two stages, constructing sys0 and sys.ji. To see what commands are running at the time of failure, use make VERBOSE=1.","category":"page"},{"location":"devdocs/debuggingtips/","page":"gdb 调试提示","title":"gdb 调试提示","text":"At the time of this writing, you can debug build errors during the sys0 phase from the base directory using:","category":"page"},{"location":"devdocs/debuggingtips/","page":"gdb 调试提示","title":"gdb 调试提示","text":"julia/base$ gdb --args ../usr/bin/julia-debug -C native --build ../usr/lib/julia/sys0 sysimg.jl","category":"page"},{"location":"devdocs/debuggingtips/","page":"gdb 调试提示","title":"gdb 调试提示","text":"You might need to delete all the files in usr/lib/julia/ to get this to work.","category":"page"},{"location":"devdocs/debuggingtips/","page":"gdb 调试提示","title":"gdb 调试提示","text":"You can debug the sys.ji phase using:","category":"page"},{"location":"devdocs/debuggingtips/","page":"gdb 调试提示","title":"gdb 调试提示","text":"julia/base$ gdb --args ../usr/bin/julia-debug -C native --build ../usr/lib/julia/sys -J ../usr/lib/julia/sys0.ji sysimg.jl","category":"page"},{"location":"devdocs/debuggingtips/","page":"gdb 调试提示","title":"gdb 调试提示","text":"By default, any errors will cause Julia to exit, even under gdb. To catch an error \"in the act\", set a breakpoint in jl_error (there are several other useful spots, for specific kinds of failures, including: jl_too_few_args, jl_too_many_args, and jl_throw).","category":"page"},{"location":"devdocs/debuggingtips/","page":"gdb 调试提示","title":"gdb 调试提示","text":"Once an error is caught, a useful technique is to walk up the stack and examine the function by inspecting the related call to jl_apply. To take a real-world example:","category":"page"},{"location":"devdocs/debuggingtips/","page":"gdb 调试提示","title":"gdb 调试提示","text":"Breakpoint 1, jl_throw (e=0x7ffdf42de400) at task.c:802\n802 {\n(gdb) p jl_(e)\nErrorException(\"auto_unbox: unable to determine argument type\")\n$2 = void\n(gdb) bt 10\n#0 jl_throw (e=0x7ffdf42de400) at task.c:802\n#1 0x00007ffff65412fe in jl_error (str=0x7ffde56be000 <_j_str267> \"auto_unbox:\n unable to determine argument type\")\n at builtins.c:39\n#2 0x00007ffde56bd01a in julia_convert_16886 ()\n#3 0x00007ffff6541154 in jl_apply (f=0x7ffdf367f630, args=0x7fffffffc2b0, nargs=2) at julia.h:1281\n...","category":"page"},{"location":"devdocs/debuggingtips/","page":"gdb 调试提示","title":"gdb 调试提示","text":"The most recent jl_apply is at frame #3, so we can go back there and look at the AST for the function julia_convert_16886. This is the uniqued name for some method of convert. f in this frame is a jl_function_t*, so we can look at the type signature, if any, from the specTypes field:","category":"page"},{"location":"devdocs/debuggingtips/","page":"gdb 调试提示","title":"gdb 调试提示","text":"(gdb) f 3\n#3 0x00007ffff6541154 in jl_apply (f=0x7ffdf367f630, args=0x7fffffffc2b0, nargs=2) at julia.h:1281\n1281 return f->fptr((jl_value_t*)f, args, nargs);\n(gdb) p f->linfo->specTypes\n$4 = (jl_tupletype_t *) 0x7ffdf39b1030\n(gdb) p jl_( f->linfo->specTypes )\nTuple{Type{Float32}, Float64} # <-- type signature for julia_convert_16886","category":"page"},{"location":"devdocs/debuggingtips/","page":"gdb 调试提示","title":"gdb 调试提示","text":"Then, we can look at the AST for this function:","category":"page"},{"location":"devdocs/debuggingtips/","page":"gdb 调试提示","title":"gdb 调试提示","text":"(gdb) p jl_( jl_uncompress_ast(f->linfo, f->linfo->ast) )\nExpr(:lambda, Array{Any, 1}[:#s29, :x], Array{Any, 1}[Array{Any, 1}[], Array{Any, 1}[Array{Any, 1}[:#s29, :Any, 0], Array{Any, 1}[:x, :Any, 0]], Array{Any, 1}[], 0], Expr(:body,\nExpr(:line, 90, :float.jl)::Any,\nExpr(:return, Expr(:call, :box, :Float32, Expr(:call, :fptrunc, :Float32, :x)::Any)::Any)::Any)::Any)::Any","category":"page"},{"location":"devdocs/debuggingtips/","page":"gdb 调试提示","title":"gdb 调试提示","text":"Finally, and perhaps most usefully, we can force the function to be recompiled in order to step through the codegen process. To do this, clear the cached functionObject from the jl_lamdbda_info_t*:","category":"page"},{"location":"devdocs/debuggingtips/","page":"gdb 调试提示","title":"gdb 调试提示","text":"(gdb) p f->linfo->functionObject\n$8 = (void *) 0x1289d070\n(gdb) set f->linfo->functionObject = NULL","category":"page"},{"location":"devdocs/debuggingtips/","page":"gdb 调试提示","title":"gdb 调试提示","text":"Then, set a breakpoint somewhere useful (e.g. emit_function, emit_expr, emit_call, etc.), and run codegen:","category":"page"},{"location":"devdocs/debuggingtips/","page":"gdb 调试提示","title":"gdb 调试提示","text":"(gdb) p jl_compile(f)\n... # your breakpoint here","category":"page"},{"location":"devdocs/debuggingtips/#Debugging-precompilation-errors","page":"gdb 调试提示","title":"Debugging precompilation errors","text":"","category":"section"},{"location":"devdocs/debuggingtips/","page":"gdb 调试提示","title":"gdb 调试提示","text":"Module precompilation spawns a separate Julia process to precompile each module. Setting a breakpoint or catching failures in a precompile worker requires attaching a debugger to the worker. The easiest approach is to set the debugger watch for new process launches matching a given name. For example:","category":"page"},{"location":"devdocs/debuggingtips/","page":"gdb 调试提示","title":"gdb 调试提示","text":"(gdb) attach -w -n julia-debug","category":"page"},{"location":"devdocs/debuggingtips/","page":"gdb 调试提示","title":"gdb 调试提示","text":"or:","category":"page"},{"location":"devdocs/debuggingtips/","page":"gdb 调试提示","title":"gdb 调试提示","text":"(lldb) process attach -w -n julia-debug","category":"page"},{"location":"devdocs/debuggingtips/","page":"gdb 调试提示","title":"gdb 调试提示","text":"Then run a script/command to start precompilation. As described earlier, use conditional breakpoints in the parent process to catch specific file-loading events and narrow the debugging window. (some operating systems may require alternative approaches, such as following each fork from the parent process)","category":"page"},{"location":"devdocs/debuggingtips/#Mozilla's-Record-and-Replay-Framework-(rr)","page":"gdb 调试提示","title":"Mozilla's Record and Replay Framework (rr)","text":"","category":"section"},{"location":"devdocs/debuggingtips/","page":"gdb 调试提示","title":"gdb 调试提示","text":"Julia now works out of the box with rr, the lightweight recording and deterministic debugging framework from Mozilla. This allows you to replay the trace of an execution deterministically. The replayed execution's address spaces, register contents, syscall data etc are exactly the same in every run.","category":"page"},{"location":"devdocs/debuggingtips/","page":"gdb 调试提示","title":"gdb 调试提示","text":"A recent version of rr (3.1.0 or higher) is required.","category":"page"},{"location":"devdocs/debuggingtips/#Reproducing-concurrency-bugs-with-rr","page":"gdb 调试提示","title":"Reproducing concurrency bugs with rr","text":"","category":"section"},{"location":"devdocs/debuggingtips/","page":"gdb 调试提示","title":"gdb 调试提示","text":"rr simulates a single-threaded machine by default. In order to debug concurrent code you can use rr record --chaos which will cause rr to simulate between one to eight cores, chosen randomly. You might therefore want to set JULIA_NUM_THREADS=8 and rerun your code under rr until you have caught your bug.","category":"page"},{"location":"manual/stacktraces/#栈跟踪","page":"栈跟踪","title":"栈跟踪","text":"","category":"section"},{"location":"manual/stacktraces/","page":"栈跟踪","title":"栈跟踪","text":"StackTraces 模块提供了简单的栈跟踪功能,这些栈跟踪信息既可读又易于编程使用。","category":"page"},{"location":"manual/stacktraces/#查看栈跟踪","page":"栈跟踪","title":"查看栈跟踪","text":"","category":"section"},{"location":"manual/stacktraces/","page":"栈跟踪","title":"栈跟踪","text":"获取栈跟踪信息的主要函数是 stacktrace:","category":"page"},{"location":"manual/stacktraces/","page":"栈跟踪","title":"栈跟踪","text":"6-element Array{Base.StackTraces.StackFrame,1}:\n top-level scope\n eval at boot.jl:317 [inlined]\n eval(::Module, ::Expr) at REPL.jl:5\n eval_user_input(::Any, ::REPL.REPLBackend) at REPL.jl:85\n macro expansion at REPL.jl:116 [inlined]\n (::getfield(REPL, Symbol(\"##28#29\")){REPL.REPLBackend})() at event.jl:92","category":"page"},{"location":"manual/stacktraces/","page":"栈跟踪","title":"栈跟踪","text":"调用 stacktrace() 会返回一个 StackTraces.StackFrame 数组。为了使用方便,可以用 StackTraces.StackTrace 来代替 Vector{StackFrame}。下面例子中 [...] 的意思是这部分输出的内容可能会根据代码的实际执行情况而定。","category":"page"},{"location":"manual/stacktraces/","page":"栈跟踪","title":"栈跟踪","text":"julia> example() = stacktrace()\nexample (generic function with 1 method)\n\njulia> example()\n7-element Array{Base.StackTraces.StackFrame,1}:\n example() at REPL[1]:1\n top-level scope\n eval at boot.jl:317 [inlined]\n[...]\n\njulia> @noinline child() = stacktrace()\nchild (generic function with 1 method)\n\njulia> @noinline parent() = child()\nparent (generic function with 1 method)\n\njulia> grandparent() = parent()\ngrandparent (generic function with 1 method)\n\njulia> grandparent()\n9-element Array{Base.StackTraces.StackFrame,1}:\n child() at REPL[3]:1\n parent() at REPL[4]:1\n grandparent() at REPL[5]:1\n[...]","category":"page"},{"location":"manual/stacktraces/","page":"栈跟踪","title":"栈跟踪","text":"注意,在调用 stacktrace() 的时,通常会出现 eval at boot.jl 这帧。 当从 REPL 里调用 stacktrace() 的时候,还会显示 REPL.jl 里的一些额外帧,就像下面一样:","category":"page"},{"location":"manual/stacktraces/","page":"栈跟踪","title":"栈跟踪","text":"julia> example() = stacktrace()\nexample (generic function with 1 method)\n\njulia> example()\n7-element Array{Base.StackTraces.StackFrame,1}:\n example() at REPL[1]:1\n top-level scope\n eval at boot.jl:317 [inlined]\n eval(::Module, ::Expr) at REPL.jl:5\n eval_user_input(::Any, ::REPL.REPLBackend) at REPL.jl:85\n macro expansion at REPL.jl:116 [inlined]\n (::getfield(REPL, Symbol(\"##28#29\")){REPL.REPLBackend})() at event.jl:92","category":"page"},{"location":"manual/stacktraces/#抽取有用信息","page":"栈跟踪","title":"抽取有用信息","text":"","category":"section"},{"location":"manual/stacktraces/","page":"栈跟踪","title":"栈跟踪","text":"每个 StackTraces.StackFrame 都会包含函数名,文件名,代码行数,lambda 信息,一个用于确认此帧是否被内联的标帜,一个用于确认函数是否为 C 函数的标帜(在默认的情况下 C 函数不会出现在栈跟踪信息中)以及一个用整数表示的指针,它是由 backtrace 返回的:","category":"page"},{"location":"manual/stacktraces/","page":"栈跟踪","title":"栈跟踪","text":"julia> frame = stacktrace()[3]\neval(::Module, ::Expr) at REPL.jl:5\n\njulia> frame.func\n:eval\n\njulia> frame.file\nSymbol(\"~/julia/usr/share/julia/stdlib/v0.7/REPL/src/REPL.jl\")\n\njulia> frame.line\n5\n\njulia> frame.linfo\nMethodInstance for eval(::Module, ::Expr)\n\njulia> frame.inlined\nfalse\n\njulia> frame.from_c\nfalse\n\njulia> frame.pointer\n0x00007f92d6293171","category":"page"},{"location":"manual/stacktraces/","page":"栈跟踪","title":"栈跟踪","text":"这使得我们可以通过编程的方式将栈跟踪信息用于打印日志,处理错误以及其它更多用途。","category":"page"},{"location":"manual/stacktraces/#错误处理","page":"栈跟踪","title":"错误处理","text":"","category":"section"},{"location":"manual/stacktraces/","page":"栈跟踪","title":"栈跟踪","text":"能够轻松地获取当前调用栈的状态信息在许多场景下都很有用,但最直接的应用是错误处理和调试。","category":"page"},{"location":"manual/stacktraces/","page":"栈跟踪","title":"栈跟踪","text":"julia> @noinline bad_function() = undeclared_variable\nbad_function (generic function with 1 method)\n\njulia> @noinline example() = try\n bad_function()\n catch\n stacktrace()\n end\nexample (generic function with 1 method)\n\njulia> example()\n7-element Array{Base.StackTraces.StackFrame,1}:\n example() at REPL[2]:4\n top-level scope\n eval at boot.jl:317 [inlined]\n[...]","category":"page"},{"location":"manual/stacktraces/","page":"栈跟踪","title":"栈跟踪","text":"你可能已经注意到了,上述例子中第一个栈帧指向了stacktrace被调用的第 4 行,而不是 bad_function 被调用的第 2 行,且完全没有出现 bad_function 的栈帧。这是也是可以理解的,因为 stacktrace 是在 catch 的上下文中被调用的。虽然在这个例子中很容易查找到错误的真正源头,但在复杂的情况下查找错误源并不是一件容易的事。","category":"page"},{"location":"manual/stacktraces/","page":"栈跟踪","title":"栈跟踪","text":"为了补救,我们可以将 catch_backtrace 的输出传递给 stacktrace。catch_backtrace 会返回最近发生异常的上下文中的栈信息,而不是返回当前上下文中的调用栈信息。","category":"page"},{"location":"manual/stacktraces/","page":"栈跟踪","title":"栈跟踪","text":"julia> @noinline bad_function() = undeclared_variable\nbad_function (generic function with 1 method)\n\njulia> @noinline example() = try\n bad_function()\n catch\n stacktrace(catch_backtrace())\n end\nexample (generic function with 1 method)\n\njulia> example()\n8-element Array{Base.StackTraces.StackFrame,1}:\n bad_function() at REPL[1]:1\n example() at REPL[2]:2\n[...]","category":"page"},{"location":"manual/stacktraces/","page":"栈跟踪","title":"栈跟踪","text":"可以看到,现在栈跟踪会显示正确的行号以及之前缺失的栈帧。","category":"page"},{"location":"manual/stacktraces/","page":"栈跟踪","title":"栈跟踪","text":"julia> @noinline child() = error(\"Whoops!\")\nchild (generic function with 1 method)\n\njulia> @noinline parent() = child()\nparent (generic function with 1 method)\n\njulia> @noinline function grandparent()\n try\n parent()\n catch err\n println(\"ERROR: \", err.msg)\n stacktrace(catch_backtrace())\n end\n end\ngrandparent (generic function with 1 method)\n\njulia> grandparent()\nERROR: Whoops!\n10-element Array{Base.StackTraces.StackFrame,1}:\n error at error.jl:33 [inlined]\n child() at REPL[1]:1\n parent() at REPL[2]:1\n grandparent() at REPL[3]:3\n[...]","category":"page"},{"location":"manual/stacktraces/#异常栈与[current_exceptions](@ref)","page":"栈跟踪","title":"异常栈与current_exceptions","text":"","category":"section"},{"location":"manual/stacktraces/","page":"栈跟踪","title":"栈跟踪","text":"compat: Julia 1.1\n异常栈需要 Julia 1.1 及以上版本。","category":"page"},{"location":"manual/stacktraces/","page":"栈跟踪","title":"栈跟踪","text":"在处理一个异常时,后续的异常同样可能被抛出。观察这些异常对定位问题的源头极有帮助。Julia runtime 支持将每个异常发生后推入一个内部的异常栈。当代码正常退出一个catch语句,可认为所有被推入栈中的异常在相应的try语句中被成功处理并已从栈中移除。","category":"page"},{"location":"manual/stacktraces/","page":"栈跟踪","title":"栈跟踪","text":"存放当前异常的栈可通过测试函数 current_exceptions 获取,例如","category":"page"},{"location":"manual/stacktraces/","page":"栈跟踪","title":"栈跟踪","text":"julia> try\n error(\"(A) The root cause\")\n catch\n try\n error(\"(B) An exception while handling the exception\")\n catch\n for (exc, bt) in current_exceptions()\n showerror(stdout, exc, bt)\n println(stdout)\n end\n end\n end\n(A) The root cause\nStacktrace:\n [1] error(::String) at error.jl:33\n [2] top-level scope at REPL[7]:2\n [3] eval(::Module, ::Any) at boot.jl:319\n [4] eval_user_input(::Any, ::REPL.REPLBackend) at REPL.jl:85\n [5] macro expansion at REPL.jl:117 [inlined]\n [6] (::getfield(REPL, Symbol(\"##26#27\")){REPL.REPLBackend})() at task.jl:259\n(B) An exception while handling the exception\nStacktrace:\n [1] error(::String) at error.jl:33\n [2] top-level scope at REPL[7]:5\n [3] eval(::Module, ::Any) at boot.jl:319\n [4] eval_user_input(::Any, ::REPL.REPLBackend) at REPL.jl:85\n [5] macro expansion at REPL.jl:117 [inlined]\n [6] (::getfield(REPL, Symbol(\"##26#27\")){REPL.REPLBackend})() at task.jl:259","category":"page"},{"location":"manual/stacktraces/","page":"栈跟踪","title":"栈跟踪","text":"在本例中,根源异常(A)排在栈头,其后放置着延伸异常(B)。 在正常退出(例如,不抛出新异常)两个 catch 块后,所有异常都被移除出栈,无法访问。","category":"page"},{"location":"manual/stacktraces/","page":"栈跟踪","title":"栈跟踪","text":"异常栈被存放于发生异常的 Task 处。当某个任务失败,出现意料外的异常时,current_exceptions(task) 可被用于观察该任务的异常栈。","category":"page"},{"location":"manual/stacktraces/#[stacktrace](@ref)-与-[backtrace](@ref)-的比较","page":"栈跟踪","title":"stacktrace 与 backtrace 的比较","text":"","category":"section"},{"location":"manual/stacktraces/","page":"栈跟踪","title":"栈跟踪","text":"调用 backtrace 会返回一个 Union{Ptr{Nothing}, Base.InterpreterIP} 的数组,可以将其传给 stacktrace 函数进行转化:","category":"page"},{"location":"manual/stacktraces/","page":"栈跟踪","title":"栈跟踪","text":"julia> trace = backtrace()\n18-element Array{Union{Ptr{Nothing}, Base.InterpreterIP},1}:\n Ptr{Nothing} @0x00007fd8734c6209\n Ptr{Nothing} @0x00007fd87362b342\n Ptr{Nothing} @0x00007fd87362c136\n Ptr{Nothing} @0x00007fd87362c986\n Ptr{Nothing} @0x00007fd87362d089\n Base.InterpreterIP(CodeInfo(:(begin\n Core.SSAValue(0) = backtrace()\n trace = Core.SSAValue(0)\n return Core.SSAValue(0)\n end)), 0x0000000000000000)\n Ptr{Nothing} @0x00007fd87362e4cf\n[...]\n\njulia> stacktrace(trace)\n6-element Array{Base.StackTraces.StackFrame,1}:\n top-level scope\n eval at boot.jl:317 [inlined]\n eval(::Module, ::Expr) at REPL.jl:5\n eval_user_input(::Any, ::REPL.REPLBackend) at REPL.jl:85\n macro expansion at REPL.jl:116 [inlined]\n (::getfield(REPL, Symbol(\"##28#29\")){REPL.REPLBackend})() at event.jl:92","category":"page"},{"location":"manual/stacktraces/","page":"栈跟踪","title":"栈跟踪","text":"需要注意的是,backtrace 返回的向量有 18 个元素,而 stacktrace 返回的向量只包含6 个元素。这是因为 stacktrace 在默认情况下会移除所有底层 C 函数的栈信息。如果你想显示 C 函数调用的栈帧,可以这样做:","category":"page"},{"location":"manual/stacktraces/","page":"栈跟踪","title":"栈跟踪","text":"julia> stacktrace(trace, true)\n21-element Array{Base.StackTraces.StackFrame,1}:\n jl_apply_generic at gf.c:2167\n do_call at interpreter.c:324\n eval_value at interpreter.c:416\n eval_body at interpreter.c:559\n jl_interpret_toplevel_thunk_callback at interpreter.c:798\n top-level scope\n jl_interpret_toplevel_thunk at interpreter.c:807\n jl_toplevel_eval_flex at toplevel.c:856\n jl_toplevel_eval_in at builtins.c:624\n eval at boot.jl:317 [inlined]\n eval(::Module, ::Expr) at REPL.jl:5\n jl_apply_generic at gf.c:2167\n eval_user_input(::Any, ::REPL.REPLBackend) at REPL.jl:85\n jl_apply_generic at gf.c:2167\n macro expansion at REPL.jl:116 [inlined]\n (::getfield(REPL, Symbol(\"##28#29\")){REPL.REPLBackend})() at event.jl:92\n jl_fptr_trampoline at gf.c:1838\n jl_apply_generic at gf.c:2167\n jl_apply at julia.h:1540 [inlined]\n start_task at task.c:268\n ip:0xffffffffffffffff","category":"page"},{"location":"manual/stacktraces/","page":"栈跟踪","title":"栈跟踪","text":"backtrace 返回的单个指针可以通过 StackTraces.lookup 来转化成一组 StackTraces.StackFrame:","category":"page"},{"location":"manual/stacktraces/","page":"栈跟踪","title":"栈跟踪","text":"julia> pointer = backtrace()[1];\n\njulia> frame = StackTraces.lookup(pointer)\n1-element Array{Base.StackTraces.StackFrame,1}:\n jl_apply_generic at gf.c:2167\n\njulia> println(\"The top frame is from $(frame[1].func)!\")\nThe top frame is from jl_apply_generic!","category":"page"},{"location":"base/collections/#集合和数据结构","page":"集合和数据结构","title":"集合和数据结构","text":"","category":"section"},{"location":"base/collections/#lib-collections-iteration","page":"集合和数据结构","title":"迭代","text":"","category":"section"},{"location":"base/collections/","page":"集合和数据结构","title":"集合和数据结构","text":"序列迭代由 iterate 实现 广义的 for 循环","category":"page"},{"location":"base/collections/","page":"集合和数据结构","title":"集合和数据结构","text":"for i in iter # or \"for i = iter\"\n # body\nend","category":"page"},{"location":"base/collections/","page":"集合和数据结构","title":"集合和数据结构","text":"被转换成","category":"page"},{"location":"base/collections/","page":"集合和数据结构","title":"集合和数据结构","text":"next = iterate(iter)\nwhile next !== nothing\n (i, state) = next\n # body\n next = iterate(iter, state)\nend","category":"page"},{"location":"base/collections/","page":"集合和数据结构","title":"集合和数据结构","text":"state 对象可以是任何对象,并且对于每个可迭代类型应该选择合适的 state 对象。 请参照 帮助文档接口的迭代小节 来获取关于定义一个常见迭代类型的更多细节。","category":"page"},{"location":"base/collections/","page":"集合和数据结构","title":"集合和数据结构","text":"Base.iterate\nBase.IteratorSize\nBase.IteratorEltype","category":"page"},{"location":"base/collections/#Base.iterate","page":"集合和数据结构","title":"Base.iterate","text":"iterate(iter [, state]) -> Union{Nothing, Tuple{Any, Any}}\n\nAdvance the iterator to obtain the next element. If no elements remain, nothing should be returned. Otherwise, a 2-tuple of the next element and the new iteration state should be returned.\n\n\n\n\n\n","category":"function"},{"location":"base/collections/#Base.IteratorSize","page":"集合和数据结构","title":"Base.IteratorSize","text":"IteratorSize(itertype::Type) -> IteratorSize\n\nGiven the type of an iterator, return one of the following values:\n\nSizeUnknown() if the length (number of elements) cannot be determined in advance.\nHasLength() if there is a fixed, finite length.\nHasShape{N}() if there is a known length plus a notion of multidimensional shape (as for an array). In this case N should give the number of dimensions, and the axes function is valid for the iterator.\nIsInfinite() if the iterator yields values forever.\n\nThe default value (for iterators that do not define this function) is HasLength(). This means that most iterators are assumed to implement length.\n\nThis trait is generally used to select between algorithms that pre-allocate space for their result, and algorithms that resize their result incrementally.\n\njulia> Base.IteratorSize(1:5)\nBase.HasShape{1}()\n\njulia> Base.IteratorSize((2,3))\nBase.HasLength()\n\n\n\n\n\n","category":"type"},{"location":"base/collections/#Base.IteratorEltype","page":"集合和数据结构","title":"Base.IteratorEltype","text":"IteratorEltype(itertype::Type) -> IteratorEltype\n\nGiven the type of an iterator, return one of the following values:\n\nEltypeUnknown() if the type of elements yielded by the iterator is not known in advance.\nHasEltype() if the element type is known, and eltype would return a meaningful value.\n\nHasEltype() is the default, since iterators are assumed to implement eltype.\n\nThis trait is generally used to select between algorithms that pre-allocate a specific type of result, and algorithms that pick a result type based on the types of yielded values.\n\njulia> Base.IteratorEltype(1:5)\nBase.HasEltype()\n\n\n\n\n\n","category":"type"},{"location":"base/collections/","page":"集合和数据结构","title":"集合和数据结构","text":"以下类型均完全实现了上述函数:","category":"page"},{"location":"base/collections/","page":"集合和数据结构","title":"集合和数据结构","text":"AbstractRange\nUnitRange\nTuple\nNumber\nAbstractArray\nBitSet\nIdDict\nDict\nWeakKeyDict\nEachLine\nAbstractString\nSet\nPair\nNamedTuple","category":"page"},{"location":"base/collections/#构造函数和类型","page":"集合和数据结构","title":"构造函数和类型","text":"","category":"section"},{"location":"base/collections/","page":"集合和数据结构","title":"集合和数据结构","text":"Base.AbstractRange\nBase.OrdinalRange\nBase.AbstractUnitRange\nBase.StepRange\nBase.UnitRange\nBase.LinRange","category":"page"},{"location":"base/collections/#Base.AbstractRange","page":"集合和数据结构","title":"Base.AbstractRange","text":"AbstractRange{T}\n\nSupertype for ranges with elements of type T. UnitRange and other types are subtypes of this.\n\n\n\n\n\n","category":"type"},{"location":"base/collections/#Base.OrdinalRange","page":"集合和数据结构","title":"Base.OrdinalRange","text":"OrdinalRange{T, S} <: AbstractRange{T}\n\nSupertype for ordinal ranges with elements of type T with spacing(s) of type S. The steps should be always-exact multiples of oneunit, and T should be a \"discrete\" type, which cannot have values smaller than oneunit. For example, Integer or Date types would qualify, whereas Float64 would not (since this type can represent values smaller than oneunit(Float64). UnitRange, StepRange, and other types are subtypes of this.\n\n\n\n\n\n","category":"type"},{"location":"base/collections/#Base.AbstractUnitRange","page":"集合和数据结构","title":"Base.AbstractUnitRange","text":"AbstractUnitRange{T} <: OrdinalRange{T, T}\n\nSupertype for ranges with a step size of oneunit(T) with elements of type T. UnitRange and other types are subtypes of this.\n\n\n\n\n\n","category":"type"},{"location":"base/collections/#Base.StepRange","page":"集合和数据结构","title":"Base.StepRange","text":"StepRange{T, S} <: OrdinalRange{T, S}\n\nRanges with elements of type T with spacing of type S. The step between each element is constant, and the range is defined in terms of a start and stop of type T and a step of type S. Neither T nor S should be floating point types. The syntax a:b:c with b > 1 and a, b, and c all integers creates a StepRange.\n\nExamples\n\njulia> collect(StepRange(1, Int8(2), 10))\n5-element Vector{Int64}:\n 1\n 3\n 5\n 7\n 9\n\njulia> typeof(StepRange(1, Int8(2), 10))\nStepRange{Int64, Int8}\n\njulia> typeof(1:3:6)\nStepRange{Int64, Int64}\n\n\n\n\n\n","category":"type"},{"location":"base/collections/#Base.UnitRange","page":"集合和数据结构","title":"Base.UnitRange","text":"UnitRange{T<:Real}\n\nA range parameterized by a start and stop of type T, filled with elements spaced by 1 from start until stop is exceeded. The syntax a:b with a and b both Integers creates a UnitRange.\n\nExamples\n\njulia> collect(UnitRange(2.3, 5.2))\n3-element Vector{Float64}:\n 2.3\n 3.3\n 4.3\n\njulia> typeof(1:10)\nUnitRange{Int64}\n\n\n\n\n\n","category":"type"},{"location":"base/collections/#Base.LinRange","page":"集合和数据结构","title":"Base.LinRange","text":"LinRange{T,L}\n\nA range with len linearly spaced elements between its start and stop. The size of the spacing is controlled by len, which must be an Integer.\n\nExamples\n\njulia> LinRange(1.5, 5.5, 9)\n9-element LinRange{Float64, Int64}:\n 1.5,2.0,2.5,3.0,3.5,4.0,4.5,5.0,5.5\n\nCompared to using range, directly constructing a LinRange should have less overhead but won't try to correct for floating point errors:\n\njulia> collect(range(-0.1, 0.3, length=5))\n5-element Vector{Float64}:\n -0.1\n 0.0\n 0.1\n 0.2\n 0.3\n\njulia> collect(LinRange(-0.1, 0.3, 5))\n5-element Vector{Float64}:\n -0.1\n -1.3877787807814457e-17\n 0.09999999999999999\n 0.19999999999999998\n 0.3\n\n\n\n\n\n","category":"type"},{"location":"base/collections/#通用集合","page":"集合和数据结构","title":"通用集合","text":"","category":"section"},{"location":"base/collections/","page":"集合和数据结构","title":"集合和数据结构","text":"Base.isempty\nBase.empty!\nBase.length\nBase.checked_length","category":"page"},{"location":"base/collections/#Base.isempty","page":"集合和数据结构","title":"Base.isempty","text":"isempty(collection) -> Bool\n\nDetermine whether a collection is empty (has no elements).\n\nExamples\n\njulia> isempty([])\ntrue\n\njulia> isempty([1 2 3])\nfalse\n\n\n\n\n\nisempty(condition)\n\nReturn true if no tasks are waiting on the condition, false otherwise.\n\n\n\n\n\n","category":"function"},{"location":"base/collections/#Base.empty!","page":"集合和数据结构","title":"Base.empty!","text":"empty!(collection) -> collection\n\nRemove all elements from a collection.\n\nExamples\n\njulia> A = Dict(\"a\" => 1, \"b\" => 2)\nDict{String, Int64} with 2 entries:\n \"b\" => 2\n \"a\" => 1\n\njulia> empty!(A);\n\njulia> A\nDict{String, Int64}()\n\n\n\n\n\n","category":"function"},{"location":"base/collections/#Base.length","page":"集合和数据结构","title":"Base.length","text":"length(collection) -> Integer\n\nReturn the number of elements in the collection.\n\nUse lastindex to get the last valid index of an indexable collection.\n\nSee also: size, ndims, eachindex.\n\nExamples\n\njulia> length(1:5)\n5\n\njulia> length([1, 2, 3, 4])\n4\n\njulia> length([1 2; 3 4])\n4\n\n\n\n\n\n","category":"function"},{"location":"base/collections/#Base.checked_length","page":"集合和数据结构","title":"Base.checked_length","text":"Base.checked_length(r)\n\nCalculates length(r), but may check for overflow errors where applicable when the result doesn't fit into Union{Integer(eltype(r)),Int}.\n\n\n\n\n\n","category":"function"},{"location":"base/collections/","page":"集合和数据结构","title":"集合和数据结构","text":"以下类型均完全实现了上述函数:","category":"page"},{"location":"base/collections/","page":"集合和数据结构","title":"集合和数据结构","text":"AbstractRange\nUnitRange\nTuple\nNumber\nAbstractArray\nBitSet\nIdDict\nDict\nWeakKeyDict\nAbstractString\nSet\nNamedTuple","category":"page"},{"location":"base/collections/#可迭代集合","page":"集合和数据结构","title":"可迭代集合","text":"","category":"section"},{"location":"base/collections/","page":"集合和数据结构","title":"集合和数据结构","text":"Base.in\nBase.:∉\nBase.eltype\nBase.indexin\nBase.unique\nBase.unique!\nBase.allunique\nBase.reduce(::Any, ::Any)\nBase.foldl(::Any, ::Any)\nBase.foldr(::Any, ::Any)\nBase.maximum\nBase.maximum!\nBase.minimum\nBase.minimum!\nBase.extrema\nBase.argmax\nBase.argmin\nBase.findmax\nBase.findmin\nBase.findmax!\nBase.findmin!\nBase.sum\nBase.sum!\nBase.prod\nBase.prod!\nBase.any(::Any)\nBase.any(::AbstractArray, ::Any)\nBase.any!\nBase.all(::Any)\nBase.all(::AbstractArray, ::Any)\nBase.all!\nBase.count\nBase.any(::Any, ::Any)\nBase.all(::Any, ::Any)\nBase.foreach\nBase.map\nBase.map!\nBase.mapreduce(::Any, ::Any, ::Any)\nBase.mapfoldl(::Any, ::Any, ::Any)\nBase.mapfoldr(::Any, ::Any, ::Any)\nBase.first\nBase.last\nBase.front\nBase.tail\nBase.step\nBase.collect(::Any)\nBase.collect(::Type, ::Any)\nBase.filter\nBase.filter!\nBase.replace(::Any, ::Pair...)\nBase.replace(::Base.Callable, ::Any)\nBase.replace!\nBase.rest","category":"page"},{"location":"base/collections/#Base.in","page":"集合和数据结构","title":"Base.in","text":"in(item, collection) -> Bool\n∈(item, collection) -> Bool\n\nDetermine whether an item is in the given collection, in the sense that it is == to one of the values generated by iterating over the collection. Returns a Bool value, except if item is missing or collection contains missing but not item, in which case missing is returned (three-valued logic, matching the behavior of any and ==).\n\nSome collections follow a slightly different definition. For example, Sets check whether the item isequal to one of the elements. Dicts look for key=>value pairs, and the key is compared using isequal. To test for the presence of a key in a dictionary, use haskey or k in keys(dict). For these collections, the result is always a Bool and never missing.\n\nTo determine whether an item is not in a given collection, see :∉. You may also negate the in by doing !(a in b) which is logically similar to \"not in\".\n\nWhen broadcasting with in.(items, collection) or items .∈ collection, both item and collection are broadcasted over, which is often not what is intended. For example, if both arguments are vectors (and the dimensions match), the result is a vector indicating whether each value in collection items is in the value at the corresponding position in collection. To get a vector indicating whether each value in items is in collection, wrap collection in a tuple or a Ref like this: in.(items, Ref(collection)) or items .∈ Ref(collection).\n\nExamples\n\njulia> a = 1:3:20\n1:3:19\n\njulia> 4 in a\ntrue\n\njulia> 5 in a\nfalse\n\njulia> missing in [1, 2]\nmissing\n\njulia> 1 in [2, missing]\nmissing\n\njulia> 1 in [1, missing]\ntrue\n\njulia> missing in Set([1, 2])\nfalse\n\njulia> !(21 in a)\ntrue\n\njulia> !(19 in a)\nfalse\n\njulia> [1, 2] .∈ [2, 3]\n2-element BitVector:\n 0\n 0\n\njulia> [1, 2] .∈ ([2, 3],)\n2-element BitVector:\n 0\n 1\n\nSee also: insorted, contains, occursin, issubset.\n\n\n\n\n\n","category":"function"},{"location":"base/collections/#Base.:∉","page":"集合和数据结构","title":"Base.:∉","text":"∉(item, collection) -> Bool\n∌(collection, item) -> Bool\n\nNegation of ∈ and ∋, i.e. checks that item is not in collection.\n\nWhen broadcasting with items .∉ collection, both item and collection are broadcasted over, which is often not what is intended. For example, if both arguments are vectors (and the dimensions match), the result is a vector indicating whether each value in collection items is not in the value at the corresponding position in collection. To get a vector indicating whether each value in items is not in collection, wrap collection in a tuple or a Ref like this: items .∉ Ref(collection).\n\nExamples\n\njulia> 1 ∉ 2:4\ntrue\n\njulia> 1 ∉ 1:3\nfalse\n\njulia> [1, 2] .∉ [2, 3]\n2-element BitVector:\n 1\n 1\n\njulia> [1, 2] .∉ ([2, 3],)\n2-element BitVector:\n 1\n 0\n\n\n\n\n\n","category":"function"},{"location":"base/collections/#Base.eltype","page":"集合和数据结构","title":"Base.eltype","text":"eltype(type)\n\nDetermine the type of the elements generated by iterating a collection of the given type. For dictionary types, this will be a Pair{KeyType,ValType}. The definition eltype(x) = eltype(typeof(x)) is provided for convenience so that instances can be passed instead of types. However the form that accepts a type argument should be defined for new types.\n\nSee also: keytype, typeof.\n\nExamples\n\njulia> eltype(fill(1f0, (2,2)))\nFloat32\n\njulia> eltype(fill(0x1, (2,2)))\nUInt8\n\n\n\n\n\n","category":"function"},{"location":"base/collections/#Base.indexin","page":"集合和数据结构","title":"Base.indexin","text":"indexin(a, b)\n\nReturn an array containing the first index in b for each value in a that is a member of b. The output array contains nothing wherever a is not a member of b.\n\nSee also: sortperm, findfirst.\n\nExamples\n\njulia> a = ['a', 'b', 'c', 'b', 'd', 'a'];\n\njulia> b = ['a', 'b', 'c'];\n\njulia> indexin(a, b)\n6-element Vector{Union{Nothing, Int64}}:\n 1\n 2\n 3\n 2\n nothing\n 1\n\njulia> indexin(b, a)\n3-element Vector{Union{Nothing, Int64}}:\n 1\n 2\n 3\n\n\n\n\n\n","category":"function"},{"location":"base/collections/#Base.unique","page":"集合和数据结构","title":"Base.unique","text":"unique(itr)\n\nReturn an array containing only the unique elements of collection itr, as determined by isequal, in the order that the first of each set of equivalent elements originally appears. The element type of the input is preserved.\n\nSee also: unique!, allunique, allequal.\n\nExamples\n\njulia> unique([1, 2, 6, 2])\n3-element Vector{Int64}:\n 1\n 2\n 6\n\njulia> unique(Real[1, 1.0, 2])\n2-element Vector{Real}:\n 1\n 2\n\n\n\n\n\nunique(f, itr)\n\nReturns an array containing one value from itr for each unique value produced by f applied to elements of itr.\n\nExamples\n\njulia> unique(x -> x^2, [1, -1, 3, -3, 4])\n3-element Vector{Int64}:\n 1\n 3\n 4\n\n\n\n\n\nunique(A::AbstractArray; dims::Int)\n\nReturn unique regions of A along dimension dims.\n\nExamples\n\njulia> A = map(isodd, reshape(Vector(1:8), (2,2,2)))\n2×2×2 Array{Bool, 3}:\n[:, :, 1] =\n 1 1\n 0 0\n\n[:, :, 2] =\n 1 1\n 0 0\n\njulia> unique(A)\n2-element Vector{Bool}:\n 1\n 0\n\njulia> unique(A, dims=2)\n2×1×2 Array{Bool, 3}:\n[:, :, 1] =\n 1\n 0\n\n[:, :, 2] =\n 1\n 0\n\njulia> unique(A, dims=3)\n2×2×1 Array{Bool, 3}:\n[:, :, 1] =\n 1 1\n 0 0\n\n\n\n\n\n","category":"function"},{"location":"base/collections/#Base.unique!","page":"集合和数据结构","title":"Base.unique!","text":"unique!(f, A::AbstractVector)\n\nSelects one value from A for each unique value produced by f applied to elements of A, then return the modified A.\n\ncompat: Julia 1.1\nThis method is available as of Julia 1.1.\n\nExamples\n\njulia> unique!(x -> x^2, [1, -1, 3, -3, 4])\n3-element Vector{Int64}:\n 1\n 3\n 4\n\njulia> unique!(n -> n%3, [5, 1, 8, 9, 3, 4, 10, 7, 2, 6])\n3-element Vector{Int64}:\n 5\n 1\n 9\n\njulia> unique!(iseven, [2, 3, 5, 7, 9])\n2-element Vector{Int64}:\n 2\n 3\n\n\n\n\n\nunique!(A::AbstractVector)\n\nRemove duplicate items as determined by isequal, then return the modified A. unique! will return the elements of A in the order that they occur. If you do not care about the order of the returned data, then calling (sort!(A); unique!(A)) will be much more efficient as long as the elements of A can be sorted.\n\nExamples\n\njulia> unique!([1, 1, 1])\n1-element Vector{Int64}:\n 1\n\njulia> A = [7, 3, 2, 3, 7, 5];\n\njulia> unique!(A)\n4-element Vector{Int64}:\n 7\n 3\n 2\n 5\n\njulia> B = [7, 6, 42, 6, 7, 42];\n\njulia> sort!(B); # unique! is able to process sorted data much more efficiently.\n\njulia> unique!(B)\n3-element Vector{Int64}:\n 6\n 7\n 42\n\n\n\n\n\n","category":"function"},{"location":"base/collections/#Base.allunique","page":"集合和数据结构","title":"Base.allunique","text":"allunique(itr) -> Bool\n\nReturn true if all values from itr are distinct when compared with isequal.\n\nSee also: unique, issorted, allequal.\n\nExamples\n\njulia> a = [1; 2; 3]\n3-element Vector{Int64}:\n 1\n 2\n 3\n\njulia> allunique(a)\ntrue\n\njulia> allunique([a, a])\nfalse\n\n\n\n\n\n","category":"function"},{"location":"base/collections/#Base.reduce-Tuple{Any, Any}","page":"集合和数据结构","title":"Base.reduce","text":"reduce(op, itr; [init])\n\nReduce the given collection itr with the given binary operator op. If provided, the initial value init must be a neutral element for op that will be returned for empty collections. It is unspecified whether init is used for non-empty collections.\n\nFor empty collections, providing init will be necessary, except for some special cases (e.g. when op is one of +, *, max, min, &, |) when Julia can determine the neutral element of op.\n\nReductions for certain commonly-used operators may have special implementations, and should be used instead: maximum(itr), minimum(itr), sum(itr), prod(itr), any(itr), all(itr).\n\nThe associativity of the reduction is implementation dependent. This means that you can't use non-associative operations like - because it is undefined whether reduce(-,[1,2,3]) should be evaluated as (1-2)-3 or 1-(2-3). Use foldl or foldr instead for guaranteed left or right associativity.\n\nSome operations accumulate error. Parallelism will be easier if the reduction can be executed in groups. Future versions of Julia might change the algorithm. Note that the elements are not reordered if you use an ordered collection.\n\nExamples\n\njulia> reduce(*, [2; 3; 4])\n24\n\njulia> reduce(*, [2; 3; 4]; init=-1)\n-24\n\n\n\n\n\n","category":"method"},{"location":"base/collections/#Base.foldl-Tuple{Any, Any}","page":"集合和数据结构","title":"Base.foldl","text":"foldl(op, itr; [init])\n\nLike reduce, but with guaranteed left associativity. If provided, the keyword argument init will be used exactly once. In general, it will be necessary to provide init to work with empty collections.\n\nSee also mapfoldl, foldr, accumulate.\n\nExamples\n\njulia> foldl(=>, 1:4)\n((1 => 2) => 3) => 4\n\njulia> foldl(=>, 1:4; init=0)\n(((0 => 1) => 2) => 3) => 4\n\njulia> accumulate(=>, (1,2,3,4))\n(1, 1 => 2, (1 => 2) => 3, ((1 => 2) => 3) => 4)\n\n\n\n\n\n","category":"method"},{"location":"base/collections/#Base.foldr-Tuple{Any, Any}","page":"集合和数据结构","title":"Base.foldr","text":"foldr(op, itr; [init])\n\nLike reduce, but with guaranteed right associativity. If provided, the keyword argument init will be used exactly once. In general, it will be necessary to provide init to work with empty collections.\n\nExamples\n\njulia> foldr(=>, 1:4)\n1 => (2 => (3 => 4))\n\njulia> foldr(=>, 1:4; init=0)\n1 => (2 => (3 => (4 => 0)))\n\n\n\n\n\n","category":"method"},{"location":"base/collections/#Base.maximum","page":"集合和数据结构","title":"Base.maximum","text":"maximum(f, itr; [init])\n\nReturns the largest result of calling function f on each element of itr.\n\nThe value returned for empty itr can be specified by init. It must be a neutral element for max (i.e. which is less than or equal to any other element) as it is unspecified whether init is used for non-empty collections.\n\ncompat: Julia 1.6\nKeyword argument init requires Julia 1.6 or later.\n\nExamples\n\njulia> maximum(length, [\"Julion\", \"Julia\", \"Jule\"])\n6\n\njulia> maximum(length, []; init=-1)\n-1\n\njulia> maximum(sin, Real[]; init=-1.0) # good, since output of sin is >= -1\n-1.0\n\n\n\n\n\nmaximum(itr; [init])\n\nReturns the largest element in a collection.\n\nThe value returned for empty itr can be specified by init. It must be a neutral element for max (i.e. which is less than or equal to any other element) as it is unspecified whether init is used for non-empty collections.\n\ncompat: Julia 1.6\nKeyword argument init requires Julia 1.6 or later.\n\nExamples\n\njulia> maximum(-20.5:10)\n9.5\n\njulia> maximum([1,2,3])\n3\n\njulia> maximum(())\nERROR: MethodError: reducing over an empty collection is not allowed; consider supplying `init` to the reducer\nStacktrace:\n[...]\n\njulia> maximum((); init=-Inf)\n-Inf\n\n\n\n\n\nmaximum(A::AbstractArray; dims)\n\nCompute the maximum value of an array over the given dimensions. See also the max(a,b) function to take the maximum of two or more arguments, which can be applied elementwise to arrays via max.(a,b).\n\nSee also: maximum!, extrema, findmax, argmax.\n\nExamples\n\njulia> A = [1 2; 3 4]\n2×2 Matrix{Int64}:\n 1 2\n 3 4\n\njulia> maximum(A, dims=1)\n1×2 Matrix{Int64}:\n 3 4\n\njulia> maximum(A, dims=2)\n2×1 Matrix{Int64}:\n 2\n 4\n\n\n\n\n\nmaximum(f, A::AbstractArray; dims)\n\nCompute the maximum value by calling the function f on each element of an array over the given dimensions.\n\nExamples\n\njulia> A = [1 2; 3 4]\n2×2 Matrix{Int64}:\n 1 2\n 3 4\n\njulia> maximum(abs2, A, dims=1)\n1×2 Matrix{Int64}:\n 9 16\n\njulia> maximum(abs2, A, dims=2)\n2×1 Matrix{Int64}:\n 4\n 16\n\n\n\n\n\n","category":"function"},{"location":"base/collections/#Base.maximum!","page":"集合和数据结构","title":"Base.maximum!","text":"maximum!(r, A)\n\nCompute the maximum value of A over the singleton dimensions of r, and write results to r.\n\nExamples\n\njulia> A = [1 2; 3 4]\n2×2 Matrix{Int64}:\n 1 2\n 3 4\n\njulia> maximum!([1; 1], A)\n2-element Vector{Int64}:\n 2\n 4\n\njulia> maximum!([1 1], A)\n1×2 Matrix{Int64}:\n 3 4\n\n\n\n\n\n","category":"function"},{"location":"base/collections/#Base.minimum","page":"集合和数据结构","title":"Base.minimum","text":"minimum(f, itr; [init])\n\nReturns the smallest result of calling function f on each element of itr.\n\nThe value returned for empty itr can be specified by init. It must be a neutral element for min (i.e. which is greater than or equal to any other element) as it is unspecified whether init is used for non-empty collections.\n\ncompat: Julia 1.6\nKeyword argument init requires Julia 1.6 or later.\n\nExamples\n\njulia> minimum(length, [\"Julion\", \"Julia\", \"Jule\"])\n4\n\njulia> minimum(length, []; init=typemax(Int64))\n9223372036854775807\n\njulia> minimum(sin, Real[]; init=1.0) # good, since output of sin is <= 1\n1.0\n\n\n\n\n\nminimum(itr; [init])\n\nReturns the smallest element in a collection.\n\nThe value returned for empty itr can be specified by init. It must be a neutral element for min (i.e. which is greater than or equal to any other element) as it is unspecified whether init is used for non-empty collections.\n\ncompat: Julia 1.6\nKeyword argument init requires Julia 1.6 or later.\n\nExamples\n\njulia> minimum(-20.5:10)\n-20.5\n\njulia> minimum([1,2,3])\n1\n\njulia> minimum([])\nERROR: MethodError: reducing over an empty collection is not allowed; consider supplying `init` to the reducer\nStacktrace:\n[...]\n\njulia> minimum([]; init=Inf)\nInf\n\n\n\n\n\nminimum(A::AbstractArray; dims)\n\nCompute the minimum value of an array over the given dimensions. See also the min(a,b) function to take the minimum of two or more arguments, which can be applied elementwise to arrays via min.(a,b).\n\nSee also: minimum!, extrema, findmin, argmin.\n\nExamples\n\njulia> A = [1 2; 3 4]\n2×2 Matrix{Int64}:\n 1 2\n 3 4\n\njulia> minimum(A, dims=1)\n1×2 Matrix{Int64}:\n 1 2\n\njulia> minimum(A, dims=2)\n2×1 Matrix{Int64}:\n 1\n 3\n\n\n\n\n\nminimum(f, A::AbstractArray; dims)\n\nCompute the minimum value by calling the function f on each element of an array over the given dimensions.\n\nExamples\n\njulia> A = [1 2; 3 4]\n2×2 Matrix{Int64}:\n 1 2\n 3 4\n\njulia> minimum(abs2, A, dims=1)\n1×2 Matrix{Int64}:\n 1 4\n\njulia> minimum(abs2, A, dims=2)\n2×1 Matrix{Int64}:\n 1\n 9\n\n\n\n\n\n","category":"function"},{"location":"base/collections/#Base.minimum!","page":"集合和数据结构","title":"Base.minimum!","text":"minimum!(r, A)\n\nCompute the minimum value of A over the singleton dimensions of r, and write results to r.\n\nExamples\n\njulia> A = [1 2; 3 4]\n2×2 Matrix{Int64}:\n 1 2\n 3 4\n\njulia> minimum!([1; 1], A)\n2-element Vector{Int64}:\n 1\n 3\n\njulia> minimum!([1 1], A)\n1×2 Matrix{Int64}:\n 1 2\n\n\n\n\n\n","category":"function"},{"location":"base/collections/#Base.extrema","page":"集合和数据结构","title":"Base.extrema","text":"extrema(itr; [init]) -> (mn, mx)\n\nCompute both the minimum mn and maximum mx element in a single pass, and return them as a 2-tuple.\n\nThe value returned for empty itr can be specified by init. It must be a 2-tuple whose first and second elements are neutral elements for min and max respectively (i.e. which are greater/less than or equal to any other element). As a consequence, when itr is empty the returned (mn, mx) tuple will satisfy mn ≥ mx. When init is specified it may be used even for non-empty itr.\n\ncompat: Julia 1.8\nKeyword argument init requires Julia 1.8 or later.\n\nExamples\n\njulia> extrema(2:10)\n(2, 10)\n\njulia> extrema([9,pi,4.5])\n(3.141592653589793, 9.0)\n\njulia> extrema([]; init = (Inf, -Inf))\n(Inf, -Inf)\n\n\n\n\n\nextrema(f, itr; [init]) -> (mn, mx)\n\nCompute both the minimum mn and maximum mx of f applied to each element in itr and return them as a 2-tuple. Only one pass is made over itr.\n\nThe value returned for empty itr can be specified by init. It must be a 2-tuple whose first and second elements are neutral elements for min and max respectively (i.e. which are greater/less than or equal to any other element). It is used for non-empty collections. Note: it implies that, for empty itr, the returned value (mn, mx) satisfies mn ≥ mx even though for non-empty itr it satisfies mn ≤ mx. This is a \"paradoxical\" but yet expected result.\n\ncompat: Julia 1.2\nThis method requires Julia 1.2 or later.\n\ncompat: Julia 1.8\nKeyword argument init requires Julia 1.8 or later.\n\nExamples\n\njulia> extrema(sin, 0:π)\n(0.0, 0.9092974268256817)\n\njulia> extrema(sin, Real[]; init = (1.0, -1.0)) # good, since -1 ≤ sin(::Real) ≤ 1\n(1.0, -1.0)\n\n\n\n\n\nextrema(A::AbstractArray; dims) -> Array{Tuple}\n\nCompute the minimum and maximum elements of an array over the given dimensions.\n\nSee also: minimum, maximum, extrema!.\n\nExamples\n\njulia> A = reshape(Vector(1:2:16), (2,2,2))\n2×2×2 Array{Int64, 3}:\n[:, :, 1] =\n 1 5\n 3 7\n\n[:, :, 2] =\n 9 13\n 11 15\n\njulia> extrema(A, dims = (1,2))\n1×1×2 Array{Tuple{Int64, Int64}, 3}:\n[:, :, 1] =\n (1, 7)\n\n[:, :, 2] =\n (9, 15)\n\n\n\n\n\nextrema(f, A::AbstractArray; dims) -> Array{Tuple}\n\nCompute the minimum and maximum of f applied to each element in the given dimensions of A.\n\ncompat: Julia 1.2\nThis method requires Julia 1.2 or later.\n\n\n\n\n\n","category":"function"},{"location":"base/collections/#Base.argmax","page":"集合和数据结构","title":"Base.argmax","text":"argmax(r::AbstractRange)\n\nRanges can have multiple maximal elements. In that case argmax will return a maximal index, but not necessarily the first one.\n\n\n\n\n\nargmax(f, domain)\n\nReturn a value x in the domain of f for which f(x) is maximised. If there are multiple maximal values for f(x) then the first one will be found.\n\ndomain must be a non-empty iterable.\n\nValues are compared with isless.\n\ncompat: Julia 1.7\nThis method requires Julia 1.7 or later.\n\nSee also argmin, findmax.\n\nExamples\n\njulia> argmax(abs, -10:5)\n-10\n\njulia> argmax(cos, 0:π/2:2π)\n0.0\n\n\n\n\n\nargmax(itr)\n\nReturn the index or key of the maximal element in a collection. If there are multiple maximal elements, then the first one will be returned.\n\nThe collection must not be empty.\n\nValues are compared with isless.\n\nSee also: argmin, findmax.\n\nExamples\n\njulia> argmax([8, 0.1, -9, pi])\n1\n\njulia> argmax([1, 7, 7, 6])\n2\n\njulia> argmax([1, 7, 7, NaN])\n4\n\n\n\n\n\nargmax(A; dims) -> indices\n\nFor an array input, return the indices of the maximum elements over the given dimensions. NaN is treated as greater than all other values except missing.\n\nExamples\n\njulia> A = [1.0 2; 3 4]\n2×2 Matrix{Float64}:\n 1.0 2.0\n 3.0 4.0\n\njulia> argmax(A, dims=1)\n1×2 Matrix{CartesianIndex{2}}:\n CartesianIndex(2, 1) CartesianIndex(2, 2)\n\njulia> argmax(A, dims=2)\n2×1 Matrix{CartesianIndex{2}}:\n CartesianIndex(1, 2)\n CartesianIndex(2, 2)\n\n\n\n\n\n","category":"function"},{"location":"base/collections/#Base.argmin","page":"集合和数据结构","title":"Base.argmin","text":"argmin(r::AbstractRange)\n\nRanges can have multiple minimal elements. In that case argmin will return a minimal index, but not necessarily the first one.\n\n\n\n\n\nargmin(f, domain)\n\nReturn a value x in the domain of f for which f(x) is minimised. If there are multiple minimal values for f(x) then the first one will be found.\n\ndomain must be a non-empty iterable.\n\nNaN is treated as less than all other values except missing.\n\ncompat: Julia 1.7\nThis method requires Julia 1.7 or later.\n\nSee also argmax, findmin.\n\nExamples\n\njulia> argmin(sign, -10:5)\n-10\n\njulia> argmin(x -> -x^3 + x^2 - 10, -5:5)\n5\n\njulia> argmin(acos, 0:0.1:1)\n1.0\n\n\n\n\n\nargmin(itr)\n\nReturn the index or key of the minimal element in a collection. If there are multiple minimal elements, then the first one will be returned.\n\nThe collection must not be empty.\n\nNaN is treated as less than all other values except missing.\n\nSee also: argmax, findmin.\n\nExamples\n\njulia> argmin([8, 0.1, -9, pi])\n3\n\njulia> argmin([7, 1, 1, 6])\n2\n\njulia> argmin([7, 1, 1, NaN])\n4\n\n\n\n\n\nargmin(A; dims) -> indices\n\nFor an array input, return the indices of the minimum elements over the given dimensions. NaN is treated as less than all other values except missing.\n\nExamples\n\njulia> A = [1.0 2; 3 4]\n2×2 Matrix{Float64}:\n 1.0 2.0\n 3.0 4.0\n\njulia> argmin(A, dims=1)\n1×2 Matrix{CartesianIndex{2}}:\n CartesianIndex(1, 1) CartesianIndex(1, 2)\n\njulia> argmin(A, dims=2)\n2×1 Matrix{CartesianIndex{2}}:\n CartesianIndex(1, 1)\n CartesianIndex(2, 1)\n\n\n\n\n\n","category":"function"},{"location":"base/collections/#Base.findmax","page":"集合和数据结构","title":"Base.findmax","text":"findmax(f, domain) -> (f(x), index)\n\nReturns a pair of a value in the codomain (outputs of f) and the index of the corresponding value in the domain (inputs to f) such that f(x) is maximised. If there are multiple maximal points, then the first one will be returned.\n\ndomain must be a non-empty iterable.\n\nValues are compared with isless.\n\ncompat: Julia 1.7\nThis method requires Julia 1.7 or later.\n\nExamples\n\njulia> findmax(identity, 5:9)\n(9, 5)\n\njulia> findmax(-, 1:10)\n(-1, 1)\n\njulia> findmax(first, [(1, :a), (3, :b), (3, :c)])\n(3, 2)\n\njulia> findmax(cos, 0:π/2:2π)\n(1.0, 1)\n\n\n\n\n\nfindmax(itr) -> (x, index)\n\nReturn the maximal element of the collection itr and its index or key. If there are multiple maximal elements, then the first one will be returned. Values are compared with isless.\n\nSee also: findmin, argmax, maximum.\n\nExamples\n\njulia> findmax([8, 0.1, -9, pi])\n(8.0, 1)\n\njulia> findmax([1, 7, 7, 6])\n(7, 2)\n\njulia> findmax([1, 7, 7, NaN])\n(NaN, 4)\n\n\n\n\n\nfindmax(A; dims) -> (maxval, index)\n\nFor an array input, returns the value and index of the maximum over the given dimensions. NaN is treated as greater than all other values except missing.\n\nExamples\n\njulia> A = [1.0 2; 3 4]\n2×2 Matrix{Float64}:\n 1.0 2.0\n 3.0 4.0\n\njulia> findmax(A, dims=1)\n([3.0 4.0], CartesianIndex{2}[CartesianIndex(2, 1) CartesianIndex(2, 2)])\n\njulia> findmax(A, dims=2)\n([2.0; 4.0;;], CartesianIndex{2}[CartesianIndex(1, 2); CartesianIndex(2, 2);;])\n\n\n\n\n\n","category":"function"},{"location":"base/collections/#Base.findmin","page":"集合和数据结构","title":"Base.findmin","text":"findmin(f, domain) -> (f(x), index)\n\nReturns a pair of a value in the codomain (outputs of f) and the index of the corresponding value in the domain (inputs to f) such that f(x) is minimised. If there are multiple minimal points, then the first one will be returned.\n\ndomain must be a non-empty iterable.\n\nNaN is treated as less than all other values except missing.\n\ncompat: Julia 1.7\nThis method requires Julia 1.7 or later.\n\nExamples\n\njulia> findmin(identity, 5:9)\n(5, 1)\n\njulia> findmin(-, 1:10)\n(-10, 10)\n\njulia> findmin(first, [(2, :a), (2, :b), (3, :c)])\n(2, 1)\n\njulia> findmin(cos, 0:π/2:2π)\n(-1.0, 3)\n\n\n\n\n\nfindmin(itr) -> (x, index)\n\nReturn the minimal element of the collection itr and its index or key. If there are multiple minimal elements, then the first one will be returned. NaN is treated as less than all other values except missing.\n\nSee also: findmax, argmin, minimum.\n\nExamples\n\njulia> findmin([8, 0.1, -9, pi])\n(-9.0, 3)\n\njulia> findmin([1, 7, 7, 6])\n(1, 1)\n\njulia> findmin([1, 7, 7, NaN])\n(NaN, 4)\n\n\n\n\n\nfindmin(A; dims) -> (minval, index)\n\nFor an array input, returns the value and index of the minimum over the given dimensions. NaN is treated as less than all other values except missing.\n\nExamples\n\njulia> A = [1.0 2; 3 4]\n2×2 Matrix{Float64}:\n 1.0 2.0\n 3.0 4.0\n\njulia> findmin(A, dims=1)\n([1.0 2.0], CartesianIndex{2}[CartesianIndex(1, 1) CartesianIndex(1, 2)])\n\njulia> findmin(A, dims=2)\n([1.0; 3.0;;], CartesianIndex{2}[CartesianIndex(1, 1); CartesianIndex(2, 1);;])\n\n\n\n\n\n","category":"function"},{"location":"base/collections/#Base.findmax!","page":"集合和数据结构","title":"Base.findmax!","text":"findmax!(rval, rind, A) -> (maxval, index)\n\nFind the maximum of A and the corresponding linear index along singleton dimensions of rval and rind, and store the results in rval and rind. NaN is treated as greater than all other values except missing.\n\n\n\n\n\n","category":"function"},{"location":"base/collections/#Base.findmin!","page":"集合和数据结构","title":"Base.findmin!","text":"findmin!(rval, rind, A) -> (minval, index)\n\nFind the minimum of A and the corresponding linear index along singleton dimensions of rval and rind, and store the results in rval and rind. NaN is treated as less than all other values except missing.\n\n\n\n\n\n","category":"function"},{"location":"base/collections/#Base.sum","page":"集合和数据结构","title":"Base.sum","text":"sum(f, itr; [init])\n\nSum the results of calling function f on each element of itr.\n\nThe return type is Int for signed integers of less than system word size, and UInt for unsigned integers of less than system word size. For all other arguments, a common return type is found to which all arguments are promoted.\n\nThe value returned for empty itr can be specified by init. It must be the additive identity (i.e. zero) as it is unspecified whether init is used for non-empty collections.\n\ncompat: Julia 1.6\nKeyword argument init requires Julia 1.6 or later.\n\nExamples\n\njulia> sum(abs2, [2; 3; 4])\n29\n\nNote the important difference between sum(A) and reduce(+, A) for arrays with small integer eltype:\n\njulia> sum(Int8[100, 28])\n128\n\njulia> reduce(+, Int8[100, 28])\n-128\n\nIn the former case, the integers are widened to system word size and therefore the result is 128. In the latter case, no such widening happens and integer overflow results in -128.\n\n\n\n\n\nsum(itr; [init])\n\nReturns the sum of all elements in a collection.\n\nThe return type is Int for signed integers of less than system word size, and UInt for unsigned integers of less than system word size. For all other arguments, a common return type is found to which all arguments are promoted.\n\nThe value returned for empty itr can be specified by init. It must be the additive identity (i.e. zero) as it is unspecified whether init is used for non-empty collections.\n\ncompat: Julia 1.6\nKeyword argument init requires Julia 1.6 or later.\n\nSee also: reduce, mapreduce, count, union.\n\nExamples\n\njulia> sum(1:20)\n210\n\njulia> sum(1:20; init = 0.0)\n210.0\n\n\n\n\n\nsum(A::AbstractArray; dims)\n\nSum elements of an array over the given dimensions.\n\nExamples\n\njulia> A = [1 2; 3 4]\n2×2 Matrix{Int64}:\n 1 2\n 3 4\n\njulia> sum(A, dims=1)\n1×2 Matrix{Int64}:\n 4 6\n\njulia> sum(A, dims=2)\n2×1 Matrix{Int64}:\n 3\n 7\n\n\n\n\n\nsum(f, A::AbstractArray; dims)\n\nSum the results of calling function f on each element of an array over the given dimensions.\n\nExamples\n\njulia> A = [1 2; 3 4]\n2×2 Matrix{Int64}:\n 1 2\n 3 4\n\njulia> sum(abs2, A, dims=1)\n1×2 Matrix{Int64}:\n 10 20\n\njulia> sum(abs2, A, dims=2)\n2×1 Matrix{Int64}:\n 5\n 25\n\n\n\n\n\n","category":"function"},{"location":"base/collections/#Base.sum!","page":"集合和数据结构","title":"Base.sum!","text":"sum!(r, A)\n\nSum elements of A over the singleton dimensions of r, and write results to r.\n\nExamples\n\njulia> A = [1 2; 3 4]\n2×2 Matrix{Int64}:\n 1 2\n 3 4\n\njulia> sum!([1; 1], A)\n2-element Vector{Int64}:\n 3\n 7\n\njulia> sum!([1 1], A)\n1×2 Matrix{Int64}:\n 4 6\n\n\n\n\n\n","category":"function"},{"location":"base/collections/#Base.prod","page":"集合和数据结构","title":"Base.prod","text":"prod(f, itr; [init])\n\nReturns the product of f applied to each element of itr.\n\nThe return type is Int for signed integers of less than system word size, and UInt for unsigned integers of less than system word size. For all other arguments, a common return type is found to which all arguments are promoted.\n\nThe value returned for empty itr can be specified by init. It must be the multiplicative identity (i.e. one) as it is unspecified whether init is used for non-empty collections.\n\ncompat: Julia 1.6\nKeyword argument init requires Julia 1.6 or later.\n\nExamples\n\njulia> prod(abs2, [2; 3; 4])\n576\n\n\n\n\n\nprod(itr; [init])\n\nReturns the product of all elements of a collection.\n\nThe return type is Int for signed integers of less than system word size, and UInt for unsigned integers of less than system word size. For all other arguments, a common return type is found to which all arguments are promoted.\n\nThe value returned for empty itr can be specified by init. It must be the multiplicative identity (i.e. one) as it is unspecified whether init is used for non-empty collections.\n\ncompat: Julia 1.6\nKeyword argument init requires Julia 1.6 or later.\n\nSee also: reduce, cumprod, any.\n\nExamples\n\njulia> prod(1:5)\n120\n\njulia> prod(1:5; init = 1.0)\n120.0\n\n\n\n\n\nprod(A::AbstractArray; dims)\n\nMultiply elements of an array over the given dimensions.\n\nExamples\n\njulia> A = [1 2; 3 4]\n2×2 Matrix{Int64}:\n 1 2\n 3 4\n\njulia> prod(A, dims=1)\n1×2 Matrix{Int64}:\n 3 8\n\njulia> prod(A, dims=2)\n2×1 Matrix{Int64}:\n 2\n 12\n\n\n\n\n\nprod(f, A::AbstractArray; dims)\n\nMultiply the results of calling the function f on each element of an array over the given dimensions.\n\nExamples\n\njulia> A = [1 2; 3 4]\n2×2 Matrix{Int64}:\n 1 2\n 3 4\n\njulia> prod(abs2, A, dims=1)\n1×2 Matrix{Int64}:\n 9 64\n\njulia> prod(abs2, A, dims=2)\n2×1 Matrix{Int64}:\n 4\n 144\n\n\n\n\n\n","category":"function"},{"location":"base/collections/#Base.prod!","page":"集合和数据结构","title":"Base.prod!","text":"prod!(r, A)\n\nMultiply elements of A over the singleton dimensions of r, and write results to r.\n\nExamples\n\njulia> A = [1 2; 3 4]\n2×2 Matrix{Int64}:\n 1 2\n 3 4\n\njulia> prod!([1; 1], A)\n2-element Vector{Int64}:\n 2\n 12\n\njulia> prod!([1 1], A)\n1×2 Matrix{Int64}:\n 3 8\n\n\n\n\n\n","category":"function"},{"location":"base/collections/#Base.any-Tuple{Any}","page":"集合和数据结构","title":"Base.any","text":"any(itr) -> Bool\n\nTest whether any elements of a boolean collection are true, returning true as soon as the first true value in itr is encountered (short-circuiting). To short-circuit on false, use all.\n\nIf the input contains missing values, return missing if all non-missing values are false (or equivalently, if the input contains no true value), following three-valued logic.\n\nSee also: all, count, sum, |, , ||.\n\nExamples\n\njulia> a = [true,false,false,true]\n4-element Vector{Bool}:\n 1\n 0\n 0\n 1\n\njulia> any(a)\ntrue\n\njulia> any((println(i); v) for (i, v) in enumerate(a))\n1\ntrue\n\njulia> any([missing, true])\ntrue\n\njulia> any([false, missing])\nmissing\n\n\n\n\n\n","category":"method"},{"location":"base/collections/#Base.any-Tuple{AbstractArray, Any}","page":"集合和数据结构","title":"Base.any","text":"any(p, itr) -> Bool\n\nDetermine whether predicate p returns true for any elements of itr, returning true as soon as the first item in itr for which p returns true is encountered (short-circuiting). To short-circuit on false, use all.\n\nIf the input contains missing values, return missing if all non-missing values are false (or equivalently, if the input contains no true value), following three-valued logic.\n\nExamples\n\njulia> any(i->(4<=i<=6), [3,5,7])\ntrue\n\njulia> any(i -> (println(i); i > 3), 1:10)\n1\n2\n3\n4\ntrue\n\njulia> any(i -> i > 0, [1, missing])\ntrue\n\njulia> any(i -> i > 0, [-1, missing])\nmissing\n\njulia> any(i -> i > 0, [-1, 0])\nfalse\n\n\n\n\n\n","category":"method"},{"location":"base/collections/#Base.any!","page":"集合和数据结构","title":"Base.any!","text":"any!(r, A)\n\nTest whether any values in A along the singleton dimensions of r are true, and write results to r.\n\nExamples\n\njulia> A = [true false; true false]\n2×2 Matrix{Bool}:\n 1 0\n 1 0\n\njulia> any!([1; 1], A)\n2-element Vector{Int64}:\n 1\n 1\n\njulia> any!([1 1], A)\n1×2 Matrix{Int64}:\n 1 0\n\n\n\n\n\n","category":"function"},{"location":"base/collections/#Base.all-Tuple{Any}","page":"集合和数据结构","title":"Base.all","text":"all(itr) -> Bool\n\nTest whether all elements of a boolean collection are true, returning false as soon as the first false value in itr is encountered (short-circuiting). To short-circuit on true, use any.\n\nIf the input contains missing values, return missing if all non-missing values are true (or equivalently, if the input contains no false value), following three-valued logic.\n\nSee also: all!, any, count, &, , &&, allunique.\n\nExamples\n\njulia> a = [true,false,false,true]\n4-element Vector{Bool}:\n 1\n 0\n 0\n 1\n\njulia> all(a)\nfalse\n\njulia> all((println(i); v) for (i, v) in enumerate(a))\n1\n2\nfalse\n\njulia> all([missing, false])\nfalse\n\njulia> all([true, missing])\nmissing\n\n\n\n\n\n","category":"method"},{"location":"base/collections/#Base.all-Tuple{AbstractArray, Any}","page":"集合和数据结构","title":"Base.all","text":"all(p, itr) -> Bool\n\nDetermine whether predicate p returns true for all elements of itr, returning false as soon as the first item in itr for which p returns false is encountered (short-circuiting). To short-circuit on true, use any.\n\nIf the input contains missing values, return missing if all non-missing values are true (or equivalently, if the input contains no false value), following three-valued logic.\n\nExamples\n\njulia> all(i->(4<=i<=6), [4,5,6])\ntrue\n\njulia> all(i -> (println(i); i < 3), 1:10)\n1\n2\n3\nfalse\n\njulia> all(i -> i > 0, [1, missing])\nmissing\n\njulia> all(i -> i > 0, [-1, missing])\nfalse\n\njulia> all(i -> i > 0, [1, 2])\ntrue\n\n\n\n\n\n","category":"method"},{"location":"base/collections/#Base.all!","page":"集合和数据结构","title":"Base.all!","text":"all!(r, A)\n\nTest whether all values in A along the singleton dimensions of r are true, and write results to r.\n\nExamples\n\njulia> A = [true false; true false]\n2×2 Matrix{Bool}:\n 1 0\n 1 0\n\njulia> all!([1; 1], A)\n2-element Vector{Int64}:\n 0\n 0\n\njulia> all!([1 1], A)\n1×2 Matrix{Int64}:\n 1 0\n\n\n\n\n\n","category":"function"},{"location":"base/collections/#Base.count","page":"集合和数据结构","title":"Base.count","text":"count([f=identity,] itr; init=0) -> Integer\n\nCount the number of elements in itr for which the function f returns true. If f is omitted, count the number of true elements in itr (which should be a collection of boolean values). init optionally specifies the value to start counting from and therefore also determines the output type.\n\ncompat: Julia 1.6\ninit keyword was added in Julia 1.6.\n\nSee also: any, sum.\n\nExamples\n\njulia> count(i->(4<=i<=6), [2,3,4,5,6])\n3\n\njulia> count([true, false, true, true])\n3\n\njulia> count(>(3), 1:7, init=0x03)\n0x07\n\n\n\n\n\ncount(\n pattern::Union{AbstractChar,AbstractString,AbstractPattern},\n string::AbstractString;\n overlap::Bool = false,\n)\n\nReturn the number of matches for pattern in string. This is equivalent to calling length(findall(pattern, string)) but more efficient.\n\nIf overlap=true, the matching sequences are allowed to overlap indices in the original string, otherwise they must be from disjoint character ranges.\n\ncompat: Julia 1.3\nThis method requires at least Julia 1.3.\n\ncompat: Julia 1.7\nUsing a character as the pattern requires at least Julia 1.7.\n\n\n\n\n\ncount([f=identity,] A::AbstractArray; dims=:)\n\nCount the number of elements in A for which f returns true over the given dimensions.\n\ncompat: Julia 1.5\ndims keyword was added in Julia 1.5.\n\ncompat: Julia 1.6\ninit keyword was added in Julia 1.6.\n\nExamples\n\njulia> A = [1 2; 3 4]\n2×2 Matrix{Int64}:\n 1 2\n 3 4\n\njulia> count(<=(2), A, dims=1)\n1×2 Matrix{Int64}:\n 1 1\n\njulia> count(<=(2), A, dims=2)\n2×1 Matrix{Int64}:\n 2\n 0\n\n\n\n\n\n","category":"function"},{"location":"base/collections/#Base.any-Tuple{Any, Any}","page":"集合和数据结构","title":"Base.any","text":"any(p, itr) -> Bool\n\nDetermine whether predicate p returns true for any elements of itr, returning true as soon as the first item in itr for which p returns true is encountered (short-circuiting). To short-circuit on false, use all.\n\nIf the input contains missing values, return missing if all non-missing values are false (or equivalently, if the input contains no true value), following three-valued logic.\n\nExamples\n\njulia> any(i->(4<=i<=6), [3,5,7])\ntrue\n\njulia> any(i -> (println(i); i > 3), 1:10)\n1\n2\n3\n4\ntrue\n\njulia> any(i -> i > 0, [1, missing])\ntrue\n\njulia> any(i -> i > 0, [-1, missing])\nmissing\n\njulia> any(i -> i > 0, [-1, 0])\nfalse\n\n\n\n\n\n","category":"method"},{"location":"base/collections/#Base.all-Tuple{Any, Any}","page":"集合和数据结构","title":"Base.all","text":"all(p, itr) -> Bool\n\nDetermine whether predicate p returns true for all elements of itr, returning false as soon as the first item in itr for which p returns false is encountered (short-circuiting). To short-circuit on true, use any.\n\nIf the input contains missing values, return missing if all non-missing values are true (or equivalently, if the input contains no false value), following three-valued logic.\n\nExamples\n\njulia> all(i->(4<=i<=6), [4,5,6])\ntrue\n\njulia> all(i -> (println(i); i < 3), 1:10)\n1\n2\n3\nfalse\n\njulia> all(i -> i > 0, [1, missing])\nmissing\n\njulia> all(i -> i > 0, [-1, missing])\nfalse\n\njulia> all(i -> i > 0, [1, 2])\ntrue\n\n\n\n\n\n","category":"method"},{"location":"base/collections/#Base.foreach","page":"集合和数据结构","title":"Base.foreach","text":"foreach(f, c...) -> Nothing\n\nCall function f on each element of iterable c. For multiple iterable arguments, f is called elementwise, and iteration stops when any iterator is finished.\n\nforeach should be used instead of map when the results of f are not needed, for example in foreach(println, array).\n\nExamples\n\njulia> tri = 1:3:7; res = Int[];\n\njulia> foreach(x -> push!(res, x^2), tri)\n\njulia> res\n3-element Vector{Int64}:\n 1\n 16\n 49\n\njulia> foreach((x, y) -> println(x, \" with \", y), tri, 'a':'z')\n1 with a\n4 with b\n7 with c\n\n\n\n\n\n","category":"function"},{"location":"base/collections/#Base.map","page":"集合和数据结构","title":"Base.map","text":"map(f, c...) -> collection\n\nTransform collection c by applying f to each element. For multiple collection arguments, apply f elementwise, and stop when when any of them is exhausted.\n\nSee also map!, foreach, mapreduce, mapslices, zip, Iterators.map.\n\nExamples\n\njulia> map(x -> x * 2, [1, 2, 3])\n3-element Vector{Int64}:\n 2\n 4\n 6\n\njulia> map(+, [1, 2, 3], [10, 20, 30, 400, 5000])\n3-element Vector{Int64}:\n 11\n 22\n 33\n\n\n\n\n\nmap(f, A::AbstractArray...) -> N-array\n\nWhen acting on multi-dimensional arrays of the same ndims, they must all have the same axes, and the answer will too.\n\nSee also broadcast, which allows mismatched sizes.\n\nExamples\n\njulia> map(//, [1 2; 3 4], [4 3; 2 1])\n2×2 Matrix{Rational{Int64}}:\n 1//4 2//3\n 3//2 4//1\n\njulia> map(+, [1 2; 3 4], zeros(2,1))\nERROR: DimensionMismatch\n\njulia> map(+, [1 2; 3 4], [1,10,100,1000], zeros(3,1)) # iterates until 3rd is exhausted\n3-element Vector{Float64}:\n 2.0\n 13.0\n 102.0\n\n\n\n\n\n","category":"function"},{"location":"base/collections/#Base.map!","page":"集合和数据结构","title":"Base.map!","text":"map!(function, destination, collection...)\n\nLike map, but stores the result in destination rather than a new collection. destination must be at least as large as the smallest collection.\n\nSee also: map, foreach, zip, copyto!.\n\nExamples\n\njulia> a = zeros(3);\n\njulia> map!(x -> x * 2, a, [1, 2, 3]);\n\njulia> a\n3-element Vector{Float64}:\n 2.0\n 4.0\n 6.0\n\njulia> map!(+, zeros(Int, 5), 100:999, 1:3)\n5-element Vector{Int64}:\n 101\n 103\n 105\n 0\n 0\n\n\n\n\n\nmap!(f, values(dict::AbstractDict))\n\nModifies dict by transforming each value from val to f(val). Note that the type of dict cannot be changed: if f(val) is not an instance of the value type of dict then it will be converted to the value type if possible and otherwise raise an error.\n\ncompat: Julia 1.2\nmap!(f, values(dict::AbstractDict)) requires Julia 1.2 or later.\n\nExamples\n\njulia> d = Dict(:a => 1, :b => 2)\nDict{Symbol, Int64} with 2 entries:\n :a => 1\n :b => 2\n\njulia> map!(v -> v-1, values(d))\nValueIterator for a Dict{Symbol, Int64} with 2 entries. Values:\n 0\n 1\n\n\n\n\n\n","category":"function"},{"location":"base/collections/#Base.mapreduce-Tuple{Any, Any, Any}","page":"集合和数据结构","title":"Base.mapreduce","text":"mapreduce(f, op, itrs...; [init])\n\nApply function f to each element(s) in itrs, and then reduce the result using the binary function op. If provided, init must be a neutral element for op that will be returned for empty collections. It is unspecified whether init is used for non-empty collections. In general, it will be necessary to provide init to work with empty collections.\n\nmapreduce is functionally equivalent to calling reduce(op, map(f, itr); init=init), but will in general execute faster since no intermediate collection needs to be created. See documentation for reduce and map.\n\ncompat: Julia 1.2\nmapreduce with multiple iterators requires Julia 1.2 or later.\n\nExamples\n\njulia> mapreduce(x->x^2, +, [1:3;]) # == 1 + 4 + 9\n14\n\nThe associativity of the reduction is implementation-dependent. Additionally, some implementations may reuse the return value of f for elements that appear multiple times in itr. Use mapfoldl or mapfoldr instead for guaranteed left or right associativity and invocation of f for every value.\n\n\n\n\n\n","category":"method"},{"location":"base/collections/#Base.mapfoldl-Tuple{Any, Any, Any}","page":"集合和数据结构","title":"Base.mapfoldl","text":"mapfoldl(f, op, itr; [init])\n\nLike mapreduce, but with guaranteed left associativity, as in foldl. If provided, the keyword argument init will be used exactly once. In general, it will be necessary to provide init to work with empty collections.\n\n\n\n\n\n","category":"method"},{"location":"base/collections/#Base.mapfoldr-Tuple{Any, Any, Any}","page":"集合和数据结构","title":"Base.mapfoldr","text":"mapfoldr(f, op, itr; [init])\n\nLike mapreduce, but with guaranteed right associativity, as in foldr. If provided, the keyword argument init will be used exactly once. In general, it will be necessary to provide init to work with empty collections.\n\n\n\n\n\n","category":"method"},{"location":"base/collections/#Base.first","page":"集合和数据结构","title":"Base.first","text":"first(coll)\n\nGet the first element of an iterable collection. Return the start point of an AbstractRange even if it is empty.\n\nSee also: only, firstindex, last.\n\nExamples\n\njulia> first(2:2:10)\n2\n\njulia> first([1; 2; 3; 4])\n1\n\n\n\n\n\nfirst(itr, n::Integer)\n\nGet the first n elements of the iterable collection itr, or fewer elements if itr is not long enough.\n\nSee also: startswith, Iterators.take.\n\ncompat: Julia 1.6\nThis method requires at least Julia 1.6.\n\nExamples\n\njulia> first([\"foo\", \"bar\", \"qux\"], 2)\n2-element Vector{String}:\n \"foo\"\n \"bar\"\n\njulia> first(1:6, 10)\n1:6\n\njulia> first(Bool[], 1)\nBool[]\n\n\n\n\n\nfirst(s::AbstractString, n::Integer)\n\nGet a string consisting of the first n characters of s.\n\nExamples\n\njulia> first(\"∀ϵ≠0: ϵ²>0\", 0)\n\"\"\n\njulia> first(\"∀ϵ≠0: ϵ²>0\", 1)\n\"∀\"\n\njulia> first(\"∀ϵ≠0: ϵ²>0\", 3)\n\"∀ϵ≠\"\n\n\n\n\n\n","category":"function"},{"location":"base/collections/#Base.last","page":"集合和数据结构","title":"Base.last","text":"last(coll)\n\nGet the last element of an ordered collection, if it can be computed in O(1) time. This is accomplished by calling lastindex to get the last index. Return the end point of an AbstractRange even if it is empty.\n\nSee also first, endswith.\n\nExamples\n\njulia> last(1:2:10)\n9\n\njulia> last([1; 2; 3; 4])\n4\n\n\n\n\n\nlast(itr, n::Integer)\n\nGet the last n elements of the iterable collection itr, or fewer elements if itr is not long enough.\n\ncompat: Julia 1.6\nThis method requires at least Julia 1.6.\n\nExamples\n\njulia> last([\"foo\", \"bar\", \"qux\"], 2)\n2-element Vector{String}:\n \"bar\"\n \"qux\"\n\njulia> last(1:6, 10)\n1:6\n\njulia> last(Float64[], 1)\nFloat64[]\n\n\n\n\n\nlast(s::AbstractString, n::Integer)\n\nGet a string consisting of the last n characters of s.\n\nExamples\n\njulia> last(\"∀ϵ≠0: ϵ²>0\", 0)\n\"\"\n\njulia> last(\"∀ϵ≠0: ϵ²>0\", 1)\n\"0\"\n\njulia> last(\"∀ϵ≠0: ϵ²>0\", 3)\n\"²>0\"\n\n\n\n\n\n","category":"function"},{"location":"base/collections/#Base.front","page":"集合和数据结构","title":"Base.front","text":"front(x::Tuple)::Tuple\n\nReturn a Tuple consisting of all but the last component of x.\n\nSee also: first, tail.\n\nExamples\n\njulia> Base.front((1,2,3))\n(1, 2)\n\njulia> Base.front(())\nERROR: ArgumentError: Cannot call front on an empty tuple.\n\n\n\n\n\n","category":"function"},{"location":"base/collections/#Base.tail","page":"集合和数据结构","title":"Base.tail","text":"tail(x::Tuple)::Tuple\n\nReturn a Tuple consisting of all but the first component of x.\n\nSee also: front, rest, first, Iterators.peel.\n\nExamples\n\njulia> Base.tail((1,2,3))\n(2, 3)\n\njulia> Base.tail(())\nERROR: ArgumentError: Cannot call tail on an empty tuple.\n\n\n\n\n\n","category":"function"},{"location":"base/collections/#Base.step","page":"集合和数据结构","title":"Base.step","text":"step(r)\n\nGet the step size of an AbstractRange object.\n\nExamples\n\njulia> step(1:10)\n1\n\njulia> step(1:2:10)\n2\n\njulia> step(2.5:0.3:10.9)\n0.3\n\njulia> step(range(2.5, stop=10.9, length=85))\n0.1\n\n\n\n\n\n","category":"function"},{"location":"base/collections/#Base.collect-Tuple{Any}","page":"集合和数据结构","title":"Base.collect","text":"collect(collection)\n\nReturn an Array of all items in a collection or iterator. For dictionaries, returns Pair{KeyType, ValType}. If the argument is array-like or is an iterator with the HasShape trait, the result will have the same shape and number of dimensions as the argument.\n\nUsed by comprehensions to turn a generator into an Array.\n\nExamples\n\njulia> collect(1:2:13)\n7-element Vector{Int64}:\n 1\n 3\n 5\n 7\n 9\n 11\n 13\n\njulia> [x^2 for x in 1:8 if isodd(x)]\n4-element Vector{Int64}:\n 1\n 9\n 25\n 49\n\n\n\n\n\n","category":"method"},{"location":"base/collections/#Base.collect-Tuple{Type, Any}","page":"集合和数据结构","title":"Base.collect","text":"collect(element_type, collection)\n\nReturn an Array with the given element type of all items in a collection or iterable. The result has the same shape and number of dimensions as collection.\n\nExamples\n\njulia> collect(Float64, 1:2:5)\n3-element Vector{Float64}:\n 1.0\n 3.0\n 5.0\n\n\n\n\n\n","category":"method"},{"location":"base/collections/#Base.filter","page":"集合和数据结构","title":"Base.filter","text":"filter(f, a)\n\nReturn a copy of collection a, removing elements for which f is false. The function f is passed one argument.\n\ncompat: Julia 1.4\nSupport for a as a tuple requires at least Julia 1.4.\n\nSee also: filter!, Iterators.filter.\n\nExamples\n\njulia> a = 1:10\n1:10\n\njulia> filter(isodd, a)\n5-element Vector{Int64}:\n 1\n 3\n 5\n 7\n 9\n\n\n\n\n\nfilter(f, d::AbstractDict)\n\nReturn a copy of d, removing elements for which f is false. The function f is passed key=>value pairs.\n\nExamples\n\njulia> d = Dict(1=>\"a\", 2=>\"b\")\nDict{Int64, String} with 2 entries:\n 2 => \"b\"\n 1 => \"a\"\n\njulia> filter(p->isodd(p.first), d)\nDict{Int64, String} with 1 entry:\n 1 => \"a\"\n\n\n\n\n\nfilter(f, itr::SkipMissing{<:AbstractArray})\n\nReturn a vector similar to the array wrapped by the given SkipMissing iterator but with all missing elements and those for which f returns false removed.\n\ncompat: Julia 1.2\nThis method requires Julia 1.2 or later.\n\nExamples\n\njulia> x = [1 2; missing 4]\n2×2 Matrix{Union{Missing, Int64}}:\n 1 2\n missing 4\n\njulia> filter(isodd, skipmissing(x))\n1-element Vector{Int64}:\n 1\n\n\n\n\n\n","category":"function"},{"location":"base/collections/#Base.filter!","page":"集合和数据结构","title":"Base.filter!","text":"filter!(f, a)\n\nUpdate collection a, removing elements for which f is false. The function f is passed one argument.\n\nExamples\n\njulia> filter!(isodd, Vector(1:10))\n5-element Vector{Int64}:\n 1\n 3\n 5\n 7\n 9\n\n\n\n\n\nfilter!(f, d::AbstractDict)\n\nUpdate d, removing elements for which f is false. The function f is passed key=>value pairs.\n\nExample\n\njulia> d = Dict(1=>\"a\", 2=>\"b\", 3=>\"c\")\nDict{Int64, String} with 3 entries:\n 2 => \"b\"\n 3 => \"c\"\n 1 => \"a\"\n\njulia> filter!(p->isodd(p.first), d)\nDict{Int64, String} with 2 entries:\n 3 => \"c\"\n 1 => \"a\"\n\n\n\n\n\n","category":"function"},{"location":"base/collections/#Base.replace-Tuple{Any, Vararg{Pair}}","page":"集合和数据结构","title":"Base.replace","text":"replace(A, old_new::Pair...; [count::Integer])\n\nReturn a copy of collection A where, for each pair old=>new in old_new, all occurrences of old are replaced by new. Equality is determined using isequal. If count is specified, then replace at most count occurrences in total.\n\nThe element type of the result is chosen using promotion (see promote_type) based on the element type of A and on the types of the new values in pairs. If count is omitted and the element type of A is a Union, the element type of the result will not include singleton types which are replaced with values of a different type: for example, Union{T,Missing} will become T if missing is replaced.\n\nSee also replace!, splice!, delete!, insert!.\n\ncompat: Julia 1.7\nVersion 1.7 is required to replace elements of a Tuple.\n\nExamples\n\njulia> replace([1, 2, 1, 3], 1=>0, 2=>4, count=2)\n4-element Vector{Int64}:\n 0\n 4\n 1\n 3\n\njulia> replace([1, missing], missing=>0)\n2-element Vector{Int64}:\n 1\n 0\n\n\n\n\n\n","category":"method"},{"location":"base/collections/#Base.replace-Tuple{Union{Function, Type}, Any}","page":"集合和数据结构","title":"Base.replace","text":"replace(new::Function, A; [count::Integer])\n\nReturn a copy of A where each value x in A is replaced by new(x). If count is specified, then replace at most count values in total (replacements being defined as new(x) !== x).\n\ncompat: Julia 1.7\nVersion 1.7 is required to replace elements of a Tuple.\n\nExamples\n\njulia> replace(x -> isodd(x) ? 2x : x, [1, 2, 3, 4])\n4-element Vector{Int64}:\n 2\n 2\n 6\n 4\n\njulia> replace(Dict(1=>2, 3=>4)) do kv\n first(kv) < 3 ? first(kv)=>3 : kv\n end\nDict{Int64, Int64} with 2 entries:\n 3 => 4\n 1 => 3\n\n\n\n\n\n","category":"method"},{"location":"base/collections/#Base.replace!","page":"集合和数据结构","title":"Base.replace!","text":"replace!(A, old_new::Pair...; [count::Integer])\n\nFor each pair old=>new in old_new, replace all occurrences of old in collection A by new. Equality is determined using isequal. If count is specified, then replace at most count occurrences in total. See also replace.\n\nExamples\n\njulia> replace!([1, 2, 1, 3], 1=>0, 2=>4, count=2)\n4-element Vector{Int64}:\n 0\n 4\n 1\n 3\n\njulia> replace!(Set([1, 2, 3]), 1=>0)\nSet{Int64} with 3 elements:\n 0\n 2\n 3\n\n\n\n\n\nreplace!(new::Function, A; [count::Integer])\n\nReplace each element x in collection A by new(x). If count is specified, then replace at most count values in total (replacements being defined as new(x) !== x).\n\nExamples\n\njulia> replace!(x -> isodd(x) ? 2x : x, [1, 2, 3, 4])\n4-element Vector{Int64}:\n 2\n 2\n 6\n 4\n\njulia> replace!(Dict(1=>2, 3=>4)) do kv\n first(kv) < 3 ? first(kv)=>3 : kv\n end\nDict{Int64, Int64} with 2 entries:\n 3 => 4\n 1 => 3\n\njulia> replace!(x->2x, Set([3, 6]))\nSet{Int64} with 2 elements:\n 6\n 12\n\n\n\n\n\n","category":"function"},{"location":"base/collections/#Base.rest","page":"集合和数据结构","title":"Base.rest","text":"Base.rest(collection[, itr_state])\n\nGeneric function for taking the tail of collection, starting from a specific iteration state itr_state. Return a Tuple, if collection itself is a Tuple, a subtype of AbstractVector, if collection is an AbstractArray, a subtype of AbstractString if collection is an AbstractString, and an arbitrary iterator, falling back to Iterators.rest(collection[, itr_state]), otherwise.\n\nCan be overloaded for user-defined collection types to customize the behavior of slurping in assignments, like a, b... = collection.\n\ncompat: Julia 1.6\nBase.rest requires at least Julia 1.6.\n\nSee also: first, Iterators.rest.\n\nExamples\n\njulia> a = [1 2; 3 4]\n2×2 Matrix{Int64}:\n 1 2\n 3 4\n\njulia> first, state = iterate(a)\n(1, 2)\n\njulia> first, Base.rest(a, state)\n(1, [3, 2, 4])\n\n\n\n\n\n","category":"function"},{"location":"base/collections/#可索引集合","page":"集合和数据结构","title":"可索引集合","text":"","category":"section"},{"location":"base/collections/","page":"集合和数据结构","title":"集合和数据结构","text":"Base.getindex\nBase.setindex!\nBase.firstindex\nBase.lastindex","category":"page"},{"location":"base/collections/#Base.getindex","page":"集合和数据结构","title":"Base.getindex","text":"getindex(collection, key...)\n\nRetrieve the value(s) stored at the given key or index within a collection. The syntax a[i,j,...] is converted by the compiler to getindex(a, i, j, ...).\n\nSee also get, keys, eachindex.\n\nExamples\n\njulia> A = Dict(\"a\" => 1, \"b\" => 2)\nDict{String, Int64} with 2 entries:\n \"b\" => 2\n \"a\" => 1\n\njulia> getindex(A, \"a\")\n1\n\n\n\n\n\n","category":"function"},{"location":"base/collections/#Base.setindex!","page":"集合和数据结构","title":"Base.setindex!","text":"setindex!(collection, value, key...)\n\nStore the given value at the given key or index within a collection. The syntax a[i,j,...] = x is converted by the compiler to (setindex!(a, x, i, j, ...); x).\n\n\n\n\n\n","category":"function"},{"location":"base/collections/#Base.firstindex","page":"集合和数据结构","title":"Base.firstindex","text":"firstindex(collection) -> Integer\nfirstindex(collection, d) -> Integer\n\nReturn the first index of collection. If d is given, return the first index of collection along dimension d.\n\nThe syntaxes A[begin] and A[1, begin] lower to A[firstindex(A)] and A[1, firstindex(A, 2)], respectively.\n\nSee also: first, axes, lastindex, nextind.\n\nExamples\n\njulia> firstindex([1,2,4])\n1\n\njulia> firstindex(rand(3,4,5), 2)\n1\n\n\n\n\n\n","category":"function"},{"location":"base/collections/#Base.lastindex","page":"集合和数据结构","title":"Base.lastindex","text":"lastindex(collection) -> Integer\nlastindex(collection, d) -> Integer\n\nReturn the last index of collection. If d is given, return the last index of collection along dimension d.\n\nThe syntaxes A[end] and A[end, end] lower to A[lastindex(A)] and A[lastindex(A, 1), lastindex(A, 2)], respectively.\n\nSee also: axes, firstindex, eachindex, prevind.\n\nExamples\n\njulia> lastindex([1,2,4])\n3\n\njulia> lastindex(rand(3,4,5), 2)\n4\n\n\n\n\n\n","category":"function"},{"location":"base/collections/","page":"集合和数据结构","title":"集合和数据结构","text":"以下类型均完全实现了上述函数:","category":"page"},{"location":"base/collections/","page":"集合和数据结构","title":"集合和数据结构","text":"Array\nBitArray\nAbstractArray\nSubArray","category":"page"},{"location":"base/collections/","page":"集合和数据结构","title":"集合和数据结构","text":"以下类型仅实现了部分上述函数:","category":"page"},{"location":"base/collections/","page":"集合和数据结构","title":"集合和数据结构","text":"AbstractRange\nUnitRange\nTuple\nAbstractString\nDict\nIdDict\nWeakKeyDict\nNamedTuple","category":"page"},{"location":"base/collections/#字典","page":"集合和数据结构","title":"字典","text":"","category":"section"},{"location":"base/collections/","page":"集合和数据结构","title":"集合和数据结构","text":"Dict 是一个标准字典。其实现利用了 hash 作为键的哈希函数和 isequal 来决定是否相等。对于自定义类型,可以定义这两个函数来重载它们在哈希表内的存储方式。","category":"page"},{"location":"base/collections/","page":"集合和数据结构","title":"集合和数据结构","text":"IdDict 是一种特殊的哈希表,在里面键始终是对象标识符。","category":"page"},{"location":"base/collections/","page":"集合和数据结构","title":"集合和数据结构","text":"WeakKeyDict 是一个哈希表的实现,里面键是对象的弱引用, 所以即使键在哈希表中被引用也有可能被垃圾回收。 它像 Dict 一样使用 hash 来做哈希和 isequal 来做相等判断, 但是它不会在插入时转换键,这点不像 Dict。","category":"page"},{"location":"base/collections/","page":"集合和数据结构","title":"集合和数据结构","text":"Dicts 可以由传递含有 => 的成对对象给 Dict 的构造函数来被创建:Dict(\"A\"=>1, \"B\"=>2)。 这个调用会尝试从键值对中推到类型信息(比如这个例子创造了一个 Dict{String, Int64})。 为了显式指定类型,请使用语法 Dict{KeyType,ValueType}(...)。例如:Dict{String,Int32}(\"A\"=>1, \"B\"=>2)。","category":"page"},{"location":"base/collections/","page":"集合和数据结构","title":"集合和数据结构","text":"字典也可以用生成器创建。例如:Dict(i => f(i) for i = 1:10)。","category":"page"},{"location":"base/collections/","page":"集合和数据结构","title":"集合和数据结构","text":"对于字典 D,若键 x 的值存在,则语法 D[x] 返回 x 的值;否则抛出一个错误。 D[x] = y 存储键值对 x => y 到 D 中,会覆盖键 x 的已有的值。 多个参数传入D[...] 会被转化成元组; 例如:语法 D[x,y] 等于 D[(x,y)],也就是说,它指向键为元组 (x,y) 的值。","category":"page"},{"location":"base/collections/","page":"集合和数据结构","title":"集合和数据结构","text":"Base.AbstractDict\nBase.Dict\nBase.IdDict\nBase.WeakKeyDict\nBase.ImmutableDict\nBase.haskey\nBase.get\nBase.get!\nBase.getkey\nBase.delete!\nBase.pop!(::Any, ::Any, ::Any)\nBase.keys\nBase.values\nBase.pairs\nBase.merge\nBase.mergewith\nBase.merge!\nBase.mergewith!\nBase.sizehint!\nBase.keytype\nBase.valtype","category":"page"},{"location":"base/collections/#Base.AbstractDict","page":"集合和数据结构","title":"Base.AbstractDict","text":"AbstractDict{K, V}\n\nSupertype for dictionary-like types with keys of type K and values of type V. Dict, IdDict and other types are subtypes of this. An AbstractDict{K, V} should be an iterator of Pair{K, V}.\n\n\n\n\n\n","category":"type"},{"location":"base/collections/#Base.Dict","page":"集合和数据结构","title":"Base.Dict","text":"Dict([itr])\n\nDict{K,V}() constructs a hash table with keys of type K and values of type V. Keys are compared with isequal and hashed with hash.\n\nGiven a single iterable argument, constructs a Dict whose key-value pairs are taken from 2-tuples (key,value) generated by the argument.\n\nExamples\n\njulia> Dict([(\"A\", 1), (\"B\", 2)])\nDict{String, Int64} with 2 entries:\n \"B\" => 2\n \"A\" => 1\n\nAlternatively, a sequence of pair arguments may be passed.\n\njulia> Dict(\"A\"=>1, \"B\"=>2)\nDict{String, Int64} with 2 entries:\n \"B\" => 2\n \"A\" => 1\n\n\n\n\n\n","category":"type"},{"location":"base/collections/#Base.IdDict","page":"集合和数据结构","title":"Base.IdDict","text":"IdDict([itr])\n\nIdDict{K,V}() constructs a hash table using objectid as hash and === as equality with keys of type K and values of type V.\n\nSee Dict for further help. In the example below, The Dict keys are all isequal and therefore get hashed the same, so they get overwritten. The IdDict hashes by object-id, and thus preserves the 3 different keys.\n\nExamples\n\njulia> Dict(true => \"yes\", 1 => \"no\", 1.0 => \"maybe\")\nDict{Real, String} with 1 entry:\n 1.0 => \"maybe\"\n\njulia> IdDict(true => \"yes\", 1 => \"no\", 1.0 => \"maybe\")\nIdDict{Any, String} with 3 entries:\n true => \"yes\"\n 1.0 => \"maybe\"\n 1 => \"no\"\n\n\n\n\n\n","category":"type"},{"location":"base/collections/#Base.WeakKeyDict","page":"集合和数据结构","title":"Base.WeakKeyDict","text":"WeakKeyDict([itr])\n\nWeakKeyDict() constructs a hash table where the keys are weak references to objects which may be garbage collected even when referenced in a hash table.\n\nSee Dict for further help. Note, unlike Dict, WeakKeyDict does not convert keys on insertion, as this would imply the key object was unreferenced anywhere before insertion.\n\n\n\n\n\n","category":"type"},{"location":"base/collections/#Base.ImmutableDict","page":"集合和数据结构","title":"Base.ImmutableDict","text":"ImmutableDict\n\nImmutableDict is a dictionary implemented as an immutable linked list, which is optimal for small dictionaries that are constructed over many individual insertions. Note that it is not possible to remove a value, although it can be partially overridden and hidden by inserting a new value with the same key.\n\nImmutableDict(KV::Pair)\n\nCreate a new entry in the ImmutableDict for a key => value pair\n\nuse (key => value) in dict to see if this particular combination is in the properties set\nuse get(dict, key, default) to retrieve the most recent value for a particular key\n\n\n\n\n\n","category":"type"},{"location":"base/collections/#Base.haskey","page":"集合和数据结构","title":"Base.haskey","text":"haskey(collection, key) -> Bool\n\nDetermine whether a collection has a mapping for a given key.\n\nExamples\n\njulia> D = Dict('a'=>2, 'b'=>3)\nDict{Char, Int64} with 2 entries:\n 'a' => 2\n 'b' => 3\n\njulia> haskey(D, 'a')\ntrue\n\njulia> haskey(D, 'c')\nfalse\n\n\n\n\n\n","category":"function"},{"location":"base/collections/#Base.get","page":"集合和数据结构","title":"Base.get","text":"get(collection, key, default)\n\nReturn the value stored for the given key, or the given default value if no mapping for the key is present.\n\ncompat: Julia 1.7\nFor tuples and numbers, this function requires at least Julia 1.7.\n\nExamples\n\njulia> d = Dict(\"a\"=>1, \"b\"=>2);\n\njulia> get(d, \"a\", 3)\n1\n\njulia> get(d, \"c\", 3)\n3\n\n\n\n\n\nget(f::Function, collection, key)\n\nReturn the value stored for the given key, or if no mapping for the key is present, return f(). Use get! to also store the default value in the dictionary.\n\nThis is intended to be called using do block syntax\n\nget(dict, key) do\n # default value calculated here\n time()\nend\n\n\n\n\n\n","category":"function"},{"location":"base/collections/#Base.get!","page":"集合和数据结构","title":"Base.get!","text":"get!(collection, key, default)\n\nReturn the value stored for the given key, or if no mapping for the key is present, store key => default, and return default.\n\nExamples\n\njulia> d = Dict(\"a\"=>1, \"b\"=>2, \"c\"=>3);\n\njulia> get!(d, \"a\", 5)\n1\n\njulia> get!(d, \"d\", 4)\n4\n\njulia> d\nDict{String, Int64} with 4 entries:\n \"c\" => 3\n \"b\" => 2\n \"a\" => 1\n \"d\" => 4\n\n\n\n\n\nget!(f::Function, collection, key)\n\nReturn the value stored for the given key, or if no mapping for the key is present, store key => f(), and return f().\n\nThis is intended to be called using do block syntax.\n\nExamples\n\njulia> squares = Dict{Int, Int}();\n\njulia> function get_square!(d, i)\n get!(d, i) do\n i^2\n end\n end\nget_square! (generic function with 1 method)\n\njulia> get_square!(squares, 2)\n4\n\njulia> squares\nDict{Int64, Int64} with 1 entry:\n 2 => 4\n\n\n\n\n\n","category":"function"},{"location":"base/collections/#Base.getkey","page":"集合和数据结构","title":"Base.getkey","text":"getkey(collection, key, default)\n\nReturn the key matching argument key if one exists in collection, otherwise return default.\n\nExamples\n\njulia> D = Dict('a'=>2, 'b'=>3)\nDict{Char, Int64} with 2 entries:\n 'a' => 2\n 'b' => 3\n\njulia> getkey(D, 'a', 1)\n'a': ASCII/Unicode U+0061 (category Ll: Letter, lowercase)\n\njulia> getkey(D, 'd', 'a')\n'a': ASCII/Unicode U+0061 (category Ll: Letter, lowercase)\n\n\n\n\n\n","category":"function"},{"location":"base/collections/#Base.delete!","page":"集合和数据结构","title":"Base.delete!","text":"delete!(collection, key)\n\nDelete the mapping for the given key in a collection, if any, and return the collection.\n\nExamples\n\njulia> d = Dict(\"a\"=>1, \"b\"=>2)\nDict{String, Int64} with 2 entries:\n \"b\" => 2\n \"a\" => 1\n\njulia> delete!(d, \"b\")\nDict{String, Int64} with 1 entry:\n \"a\" => 1\n\njulia> delete!(d, \"b\") # d is left unchanged\nDict{String, Int64} with 1 entry:\n \"a\" => 1\n\n\n\n\n\n","category":"function"},{"location":"base/collections/#Base.pop!-Tuple{Any, Any, Any}","page":"集合和数据结构","title":"Base.pop!","text":"pop!(collection, key[, default])\n\nDelete and return the mapping for key if it exists in collection, otherwise return default, or throw an error if default is not specified.\n\nExamples\n\njulia> d = Dict(\"a\"=>1, \"b\"=>2, \"c\"=>3);\n\njulia> pop!(d, \"a\")\n1\n\njulia> pop!(d, \"d\")\nERROR: KeyError: key \"d\" not found\nStacktrace:\n[...]\n\njulia> pop!(d, \"e\", 4)\n4\n\n\n\n\n\n","category":"method"},{"location":"base/collections/#Base.keys","page":"集合和数据结构","title":"Base.keys","text":"keys(iterator)\n\nFor an iterator or collection that has keys and values (e.g. arrays and dictionaries), return an iterator over the keys.\n\n\n\n\n\n","category":"function"},{"location":"base/collections/#Base.values","page":"集合和数据结构","title":"Base.values","text":"values(iterator)\n\nFor an iterator or collection that has keys and values, return an iterator over the values. This function simply returns its argument by default, since the elements of a general iterator are normally considered its \"values\".\n\nExamples\n\njulia> d = Dict(\"a\"=>1, \"b\"=>2);\n\njulia> values(d)\nValueIterator for a Dict{String, Int64} with 2 entries. Values:\n 2\n 1\n\njulia> values([2])\n1-element Vector{Int64}:\n 2\n\n\n\n\n\nvalues(a::AbstractDict)\n\nReturn an iterator over all values in a collection. collect(values(a)) returns an array of values. When the values are stored internally in a hash table, as is the case for Dict, the order in which they are returned may vary. But keys(a) and values(a) both iterate a and return the elements in the same order.\n\nExamples\n\njulia> D = Dict('a'=>2, 'b'=>3)\nDict{Char, Int64} with 2 entries:\n 'a' => 2\n 'b' => 3\n\njulia> collect(values(D))\n2-element Vector{Int64}:\n 2\n 3\n\n\n\n\n\n","category":"function"},{"location":"base/collections/#Base.pairs","page":"集合和数据结构","title":"Base.pairs","text":"pairs(collection)\n\nReturn an iterator over key => value pairs for any collection that maps a set of keys to a set of values. This includes arrays, where the keys are the array indices.\n\nExamples\n\njulia> a = Dict(zip([\"a\", \"b\", \"c\"], [1, 2, 3]))\nDict{String, Int64} with 3 entries:\n \"c\" => 3\n \"b\" => 2\n \"a\" => 1\n\njulia> pairs(a)\nDict{String, Int64} with 3 entries:\n \"c\" => 3\n \"b\" => 2\n \"a\" => 1\n\njulia> foreach(println, pairs([\"a\", \"b\", \"c\"]))\n1 => \"a\"\n2 => \"b\"\n3 => \"c\"\n\njulia> (;a=1, b=2, c=3) |> pairs |> collect\n3-element Vector{Pair{Symbol, Int64}}:\n :a => 1\n :b => 2\n :c => 3\n\njulia> (;a=1, b=2, c=3) |> collect\n3-element Vector{Int64}:\n 1\n 2\n 3\n\n\n\n\n\npairs(IndexLinear(), A)\npairs(IndexCartesian(), A)\npairs(IndexStyle(A), A)\n\nAn iterator that accesses each element of the array A, returning i => x, where i is the index for the element and x = A[i]. Identical to pairs(A), except that the style of index can be selected. Also similar to enumerate(A), except i will be a valid index for A, while enumerate always counts from 1 regardless of the indices of A.\n\nSpecifying IndexLinear() ensures that i will be an integer; specifying IndexCartesian() ensures that i will be a CartesianIndex; specifying IndexStyle(A) chooses whichever has been defined as the native indexing style for array A.\n\nMutation of the bounds of the underlying array will invalidate this iterator.\n\nExamples\n\njulia> A = [\"a\" \"d\"; \"b\" \"e\"; \"c\" \"f\"];\n\njulia> for (index, value) in pairs(IndexStyle(A), A)\n println(\"$index $value\")\n end\n1 a\n2 b\n3 c\n4 d\n5 e\n6 f\n\njulia> S = view(A, 1:2, :);\n\njulia> for (index, value) in pairs(IndexStyle(S), S)\n println(\"$index $value\")\n end\nCartesianIndex(1, 1) a\nCartesianIndex(2, 1) b\nCartesianIndex(1, 2) d\nCartesianIndex(2, 2) e\n\nSee also IndexStyle, axes.\n\n\n\n\n\n","category":"function"},{"location":"base/collections/#Base.merge","page":"集合和数据结构","title":"Base.merge","text":"merge(d::AbstractDict, others::AbstractDict...)\n\nConstruct a merged collection from the given collections. If necessary, the types of the resulting collection will be promoted to accommodate the types of the merged collections. If the same key is present in another collection, the value for that key will be the value it has in the last collection listed. See also mergewith for custom handling of values with the same key.\n\nExamples\n\njulia> a = Dict(\"foo\" => 0.0, \"bar\" => 42.0)\nDict{String, Float64} with 2 entries:\n \"bar\" => 42.0\n \"foo\" => 0.0\n\njulia> b = Dict(\"baz\" => 17, \"bar\" => 4711)\nDict{String, Int64} with 2 entries:\n \"bar\" => 4711\n \"baz\" => 17\n\njulia> merge(a, b)\nDict{String, Float64} with 3 entries:\n \"bar\" => 4711.0\n \"baz\" => 17.0\n \"foo\" => 0.0\n\njulia> merge(b, a)\nDict{String, Float64} with 3 entries:\n \"bar\" => 42.0\n \"baz\" => 17.0\n \"foo\" => 0.0\n\n\n\n\n\nmerge(a::NamedTuple, bs::NamedTuple...)\n\nConstruct a new named tuple by merging two or more existing ones, in a left-associative manner. Merging proceeds left-to-right, between pairs of named tuples, and so the order of fields present in both the leftmost and rightmost named tuples take the same position as they are found in the leftmost named tuple. However, values are taken from matching fields in the rightmost named tuple that contains that field. Fields present in only the rightmost named tuple of a pair are appended at the end. A fallback is implemented for when only a single named tuple is supplied, with signature merge(a::NamedTuple).\n\ncompat: Julia 1.1\nMerging 3 or more NamedTuple requires at least Julia 1.1.\n\nExamples\n\njulia> merge((a=1, b=2, c=3), (b=4, d=5))\n(a = 1, b = 4, c = 3, d = 5)\n\njulia> merge((a=1, b=2), (b=3, c=(d=1,)), (c=(d=2,),))\n(a = 1, b = 3, c = (d = 2,))\n\n\n\n\n\nmerge(a::NamedTuple, iterable)\n\nInterpret an iterable of key-value pairs as a named tuple, and perform a merge.\n\njulia> merge((a=1, b=2, c=3), [:b=>4, :d=>5])\n(a = 1, b = 4, c = 3, d = 5)\n\n\n\n\n\n","category":"function"},{"location":"base/collections/#Base.mergewith","page":"集合和数据结构","title":"Base.mergewith","text":"mergewith(combine, d::AbstractDict, others::AbstractDict...)\nmergewith(combine)\nmerge(combine, d::AbstractDict, others::AbstractDict...)\n\nConstruct a merged collection from the given collections. If necessary, the types of the resulting collection will be promoted to accommodate the types of the merged collections. Values with the same key will be combined using the combiner function. The curried form mergewith(combine) returns the function (args...) -> mergewith(combine, args...).\n\nMethod merge(combine::Union{Function,Type}, args...) as an alias of mergewith(combine, args...) is still available for backward compatibility.\n\ncompat: Julia 1.5\nmergewith requires Julia 1.5 or later.\n\nExamples\n\njulia> a = Dict(\"foo\" => 0.0, \"bar\" => 42.0)\nDict{String, Float64} with 2 entries:\n \"bar\" => 42.0\n \"foo\" => 0.0\n\njulia> b = Dict(\"baz\" => 17, \"bar\" => 4711)\nDict{String, Int64} with 2 entries:\n \"bar\" => 4711\n \"baz\" => 17\n\njulia> mergewith(+, a, b)\nDict{String, Float64} with 3 entries:\n \"bar\" => 4753.0\n \"baz\" => 17.0\n \"foo\" => 0.0\n\njulia> ans == mergewith(+)(a, b)\ntrue\n\n\n\n\n\n","category":"function"},{"location":"base/collections/#Base.merge!","page":"集合和数据结构","title":"Base.merge!","text":"merge!(d::AbstractDict, others::AbstractDict...)\n\nUpdate collection with pairs from the other collections. See also merge.\n\nExamples\n\njulia> d1 = Dict(1 => 2, 3 => 4);\n\njulia> d2 = Dict(1 => 4, 4 => 5);\n\njulia> merge!(d1, d2);\n\njulia> d1\nDict{Int64, Int64} with 3 entries:\n 4 => 5\n 3 => 4\n 1 => 4\n\n\n\n\n\n","category":"function"},{"location":"base/collections/#Base.mergewith!","page":"集合和数据结构","title":"Base.mergewith!","text":"mergewith!(combine, d::AbstractDict, others::AbstractDict...) -> d\nmergewith!(combine)\nmerge!(combine, d::AbstractDict, others::AbstractDict...) -> d\n\nUpdate collection with pairs from the other collections. Values with the same key will be combined using the combiner function. The curried form mergewith!(combine) returns the function (args...) -> mergewith!(combine, args...).\n\nMethod merge!(combine::Union{Function,Type}, args...) as an alias of mergewith!(combine, args...) is still available for backward compatibility.\n\ncompat: Julia 1.5\nmergewith! requires Julia 1.5 or later.\n\nExamples\n\njulia> d1 = Dict(1 => 2, 3 => 4);\n\njulia> d2 = Dict(1 => 4, 4 => 5);\n\njulia> mergewith!(+, d1, d2);\n\njulia> d1\nDict{Int64, Int64} with 3 entries:\n 4 => 5\n 3 => 4\n 1 => 6\n\njulia> mergewith!(-, d1, d1);\n\njulia> d1\nDict{Int64, Int64} with 3 entries:\n 4 => 0\n 3 => 0\n 1 => 0\n\njulia> foldl(mergewith!(+), [d1, d2]; init=Dict{Int64, Int64}())\nDict{Int64, Int64} with 3 entries:\n 4 => 5\n 3 => 0\n 1 => 4\n\n\n\n\n\n","category":"function"},{"location":"base/collections/#Base.sizehint!","page":"集合和数据结构","title":"Base.sizehint!","text":"sizehint!(s, n)\n\nSuggest that collection s reserve capacity for at least n elements. This can improve performance.\n\nNotes on the performance model\n\nFor types that support sizehint!,\n\npush! and append! methods generally may (but are not required to) preallocate extra storage. For types implemented in Base, they typically do, using a heuristic optimized for a general use case.\nsizehint! may control this preallocation. Again, it typically does this for types in Base.\nempty! is nearly costless (and O(1)) for types that support this kind of preallocation.\n\n\n\n\n\n","category":"function"},{"location":"base/collections/#Base.keytype","page":"集合和数据结构","title":"Base.keytype","text":"keytype(T::Type{<:AbstractArray})\nkeytype(A::AbstractArray)\n\nReturn the key type of an array. This is equal to the eltype of the result of keys(...), and is provided mainly for compatibility with the dictionary interface.\n\nExamples\n\njulia> keytype([1, 2, 3]) == Int\ntrue\n\njulia> keytype([1 2; 3 4])\nCartesianIndex{2}\n\ncompat: Julia 1.2\nFor arrays, this function requires at least Julia 1.2.\n\n\n\n\n\nkeytype(type)\n\nGet the key type of a dictionary type. Behaves similarly to eltype.\n\nExamples\n\njulia> keytype(Dict(Int32(1) => \"foo\"))\nInt32\n\n\n\n\n\n","category":"function"},{"location":"base/collections/#Base.valtype","page":"集合和数据结构","title":"Base.valtype","text":"valtype(T::Type{<:AbstractArray})\nvaltype(A::AbstractArray)\n\nReturn the value type of an array. This is identical to eltype and is provided mainly for compatibility with the dictionary interface.\n\nExamples\n\njulia> valtype([\"one\", \"two\", \"three\"])\nString\n\ncompat: Julia 1.2\nFor arrays, this function requires at least Julia 1.2.\n\n\n\n\n\nvaltype(type)\n\nGet the value type of a dictionary type. Behaves similarly to eltype.\n\nExamples\n\njulia> valtype(Dict(Int32(1) => \"foo\"))\nString\n\n\n\n\n\n","category":"function"},{"location":"base/collections/","page":"集合和数据结构","title":"集合和数据结构","text":"以下类型均完全实现了上述函数:","category":"page"},{"location":"base/collections/","page":"集合和数据结构","title":"集合和数据结构","text":"IdDict\nDict\nWeakKeyDict","category":"page"},{"location":"base/collections/","page":"集合和数据结构","title":"集合和数据结构","text":"以下类型仅实现了部分上述函数:","category":"page"},{"location":"base/collections/","page":"集合和数据结构","title":"集合和数据结构","text":"BitSet\nSet\nEnvDict\nArray\nBitArray\nImmutableDict\nIterators.Pairs","category":"page"},{"location":"base/collections/#类似-Set-的集合","page":"集合和数据结构","title":"类似 Set 的集合","text":"","category":"section"},{"location":"base/collections/","page":"集合和数据结构","title":"集合和数据结构","text":"Base.AbstractSet\nBase.Set\nBase.BitSet\nBase.union\nBase.union!\nBase.intersect\nBase.setdiff\nBase.setdiff!\nBase.symdiff\nBase.symdiff!\nBase.intersect!\nBase.issubset\nBase.:⊈\nBase.:⊊\nBase.issetequal\nBase.isdisjoint","category":"page"},{"location":"base/collections/#Base.AbstractSet","page":"集合和数据结构","title":"Base.AbstractSet","text":"AbstractSet{T}\n\nSupertype for set-like types whose elements are of type T. Set, BitSet and other types are subtypes of this.\n\n\n\n\n\n","category":"type"},{"location":"base/collections/#Base.Set","page":"集合和数据结构","title":"Base.Set","text":"Set([itr])\n\nConstruct a Set of the values generated by the given iterable object, or an empty set. Should be used instead of BitSet for sparse integer sets, or for sets of arbitrary objects.\n\nSee also: push!, empty!, union!, in.\n\n\n\n\n\n","category":"type"},{"location":"base/collections/#Base.BitSet","page":"集合和数据结构","title":"Base.BitSet","text":"BitSet([itr])\n\nConstruct a sorted set of Ints generated by the given iterable object, or an empty set. Implemented as a bit string, and therefore designed for dense integer sets. If the set will be sparse (for example, holding a few very large integers), use Set instead.\n\n\n\n\n\n","category":"type"},{"location":"base/collections/#Base.union","page":"集合和数据结构","title":"Base.union","text":"union(s, itrs...)\n∪(s, itrs...)\n\nConstruct an object containing all distinct elements from all of the arguments.\n\nThe first argument controls what kind of container is returned. If this is an array, it maintains the order in which elements first appear.\n\nUnicode ∪ can be typed by writing \\cup then pressing tab in the Julia REPL, and in many editors. This is an infix operator, allowing s ∪ itr.\n\nSee also unique, intersect, isdisjoint, vcat, Iterators.flatten.\n\nExamples\n\njulia> union([1, 2], [3])\n3-element Vector{Int64}:\n 1\n 2\n 3\n\njulia> union([4 2 3 4 4], 1:3, 3.0)\n4-element Vector{Float64}:\n 4.0\n 2.0\n 3.0\n 1.0\n\njulia> (0, 0.0) ∪ (-0.0, NaN)\n3-element Vector{Real}:\n 0\n -0.0\n NaN\n\njulia> union(Set([1, 2]), 2:3)\nSet{Int64} with 3 elements:\n 2\n 3\n 1\n\n\n\n\n\n","category":"function"},{"location":"base/collections/#Base.union!","page":"集合和数据结构","title":"Base.union!","text":"union!(s::Union{AbstractSet,AbstractVector}, itrs...)\n\nConstruct the union of passed in sets and overwrite s with the result. Maintain order with arrays.\n\nExamples\n\njulia> a = Set([3, 4, 5]);\n\njulia> union!(a, 1:2:7);\n\njulia> a\nSet{Int64} with 5 elements:\n 5\n 4\n 7\n 3\n 1\n\n\n\n\n\n","category":"function"},{"location":"base/collections/#Base.intersect","page":"集合和数据结构","title":"Base.intersect","text":"intersect(s, itrs...)\n∩(s, itrs...)\n\nConstruct the set containing those elements which appear in all of the arguments.\n\nThe first argument controls what kind of container is returned. If this is an array, it maintains the order in which elements first appear.\n\nUnicode ∩ can be typed by writing \\cap then pressing tab in the Julia REPL, and in many editors. This is an infix operator, allowing s ∩ itr.\n\nSee also setdiff, isdisjoint, issubset, issetequal.\n\ncompat: Julia 1.8\nAs of Julia 1.8 intersect returns a result with the eltype of the type-promoted eltypes of the two inputs\n\nExamples\n\njulia> intersect([1, 2, 3], [3, 4, 5])\n1-element Vector{Int64}:\n 3\n\njulia> intersect([1, 4, 4, 5, 6], [6, 4, 6, 7, 8])\n2-element Vector{Int64}:\n 4\n 6\n\njulia> intersect(1:16, 7:99)\n7:16\n\njulia> (0, 0.0) ∩ (-0.0, 0)\n1-element Vector{Real}:\n 0\n\njulia> intersect(Set([1, 2]), BitSet([2, 3]), 1.0:10.0)\nSet{Float64} with 1 element:\n 2.0\n\n\n\n\n\n","category":"function"},{"location":"base/collections/#Base.setdiff","page":"集合和数据结构","title":"Base.setdiff","text":"setdiff(s, itrs...)\n\nConstruct the set of elements in s but not in any of the iterables in itrs. Maintain order with arrays.\n\nSee also setdiff!, union and intersect.\n\nExamples\n\njulia> setdiff([1,2,3], [3,4,5])\n2-element Vector{Int64}:\n 1\n 2\n\n\n\n\n\n","category":"function"},{"location":"base/collections/#Base.setdiff!","page":"集合和数据结构","title":"Base.setdiff!","text":"setdiff!(s, itrs...)\n\nRemove from set s (in-place) each element of each iterable from itrs. Maintain order with arrays.\n\nExamples\n\njulia> a = Set([1, 3, 4, 5]);\n\njulia> setdiff!(a, 1:2:6);\n\njulia> a\nSet{Int64} with 1 element:\n 4\n\n\n\n\n\n","category":"function"},{"location":"base/collections/#Base.symdiff","page":"集合和数据结构","title":"Base.symdiff","text":"symdiff(s, itrs...)\n\nConstruct the symmetric difference of elements in the passed in sets. When s is not an AbstractSet, the order is maintained. Note that in this case the multiplicity of elements matters.\n\nSee also symdiff!, setdiff, union and intersect.\n\nExamples\n\njulia> symdiff([1,2,3], [3,4,5], [4,5,6])\n3-element Vector{Int64}:\n 1\n 2\n 6\n\njulia> symdiff([1,2,1], [2, 1, 2])\n2-element Vector{Int64}:\n 1\n 2\n\njulia> symdiff(unique([1,2,1]), unique([2, 1, 2]))\nInt64[]\n\n\n\n\n\n","category":"function"},{"location":"base/collections/#Base.symdiff!","page":"集合和数据结构","title":"Base.symdiff!","text":"symdiff!(s::Union{AbstractSet,AbstractVector}, itrs...)\n\nConstruct the symmetric difference of the passed in sets, and overwrite s with the result. When s is an array, the order is maintained. Note that in this case the multiplicity of elements matters.\n\n\n\n\n\n","category":"function"},{"location":"base/collections/#Base.intersect!","page":"集合和数据结构","title":"Base.intersect!","text":"intersect!(s::Union{AbstractSet,AbstractVector}, itrs...)\n\nIntersect all passed in sets and overwrite s with the result. Maintain order with arrays.\n\n\n\n\n\n","category":"function"},{"location":"base/collections/#Base.issubset","page":"集合和数据结构","title":"Base.issubset","text":"issubset(a, b) -> Bool\n⊆(a, b) -> Bool\n⊇(b, a) -> Bool\n\nDetermine whether every element of a is also in b, using in.\n\nSee also ⊊, ⊈, ∩, ∪, contains.\n\nExamples\n\njulia> issubset([1, 2], [1, 2, 3])\ntrue\n\njulia> [1, 2, 3] ⊆ [1, 2]\nfalse\n\njulia> [1, 2, 3] ⊇ [1, 2]\ntrue\n\n\n\n\n\n","category":"function"},{"location":"base/collections/#Base.:⊈","page":"集合和数据结构","title":"Base.:⊈","text":"⊈(a, b) -> Bool\n⊉(b, a) -> Bool\n\nNegation of ⊆ and ⊇, i.e. checks that a is not a subset of b.\n\nSee also issubset (⊆), ⊊.\n\nExamples\n\njulia> (1, 2) ⊈ (2, 3)\ntrue\n\njulia> (1, 2) ⊈ (1, 2, 3)\nfalse\n\n\n\n\n\n","category":"function"},{"location":"base/collections/#Base.:⊊","page":"集合和数据结构","title":"Base.:⊊","text":"⊊(a, b) -> Bool\n⊋(b, a) -> Bool\n\nDetermines if a is a subset of, but not equal to, b.\n\nSee also issubset (⊆), ⊈.\n\nExamples\n\njulia> (1, 2) ⊊ (1, 2, 3)\ntrue\n\njulia> (1, 2) ⊊ (1, 2)\nfalse\n\n\n\n\n\n","category":"function"},{"location":"base/collections/#Base.issetequal","page":"集合和数据结构","title":"Base.issetequal","text":"issetequal(a, b) -> Bool\n\nDetermine whether a and b have the same elements. Equivalent to a ⊆ b && b ⊆ a but more efficient when possible.\n\nSee also: isdisjoint, union.\n\nExamples\n\njulia> issetequal([1, 2], [1, 2, 3])\nfalse\n\njulia> issetequal([1, 2], [2, 1])\ntrue\n\n\n\n\n\n","category":"function"},{"location":"base/collections/#Base.isdisjoint","page":"集合和数据结构","title":"Base.isdisjoint","text":"isdisjoint(a, b) -> Bool\n\nDetermine whether the collections a and b are disjoint. Equivalent to isempty(a ∩ b) but more efficient when possible.\n\nSee also: intersect, isempty, issetequal.\n\ncompat: Julia 1.5\nThis function requires at least Julia 1.5.\n\nExamples\n\njulia> isdisjoint([1, 2], [2, 3, 4])\nfalse\n\njulia> isdisjoint([3, 1], [2, 4])\ntrue\n\n\n\n\n\n","category":"function"},{"location":"base/collections/","page":"集合和数据结构","title":"集合和数据结构","text":"以下类型均完全实现了上述函数:","category":"page"},{"location":"base/collections/","page":"集合和数据结构","title":"集合和数据结构","text":"BitSet\nSet","category":"page"},{"location":"base/collections/","page":"集合和数据结构","title":"集合和数据结构","text":"以下类型仅实现了部分上述函数:","category":"page"},{"location":"base/collections/","page":"集合和数据结构","title":"集合和数据结构","text":"Array","category":"page"},{"location":"base/collections/#双端队列","page":"集合和数据结构","title":"双端队列","text":"","category":"section"},{"location":"base/collections/","page":"集合和数据结构","title":"集合和数据结构","text":"Base.push!\nBase.pop!\nBase.popat!\nBase.pushfirst!\nBase.popfirst!\nBase.insert!\nBase.deleteat!\nBase.keepat!\nBase.splice!\nBase.resize!\nBase.append!\nBase.prepend!","category":"page"},{"location":"base/collections/#Base.push!","page":"集合和数据结构","title":"Base.push!","text":"push!(collection, items...) -> collection\n\nInsert one or more items in collection. If collection is an ordered container, the items are inserted at the end (in the given order).\n\nExamples\n\njulia> push!([1, 2, 3], 4, 5, 6)\n6-element Vector{Int64}:\n 1\n 2\n 3\n 4\n 5\n 6\n\nIf collection is ordered, use append! to add all the elements of another collection to it. The result of the preceding example is equivalent to append!([1, 2, 3], [4, 5, 6]). For AbstractSet objects, union! can be used instead.\n\nSee sizehint! for notes about the performance model.\n\nSee also pushfirst!.\n\n\n\n\n\n","category":"function"},{"location":"base/collections/#Base.pop!","page":"集合和数据结构","title":"Base.pop!","text":"pop!(collection) -> item\n\nRemove an item in collection and return it. If collection is an ordered container, the last item is returned; for unordered containers, an arbitrary element is returned.\n\nSee also: popfirst!, popat!, delete!, deleteat!, splice!, and push!.\n\nExamples\n\njulia> A=[1, 2, 3]\n3-element Vector{Int64}:\n 1\n 2\n 3\n\njulia> pop!(A)\n3\n\njulia> A\n2-element Vector{Int64}:\n 1\n 2\n\njulia> S = Set([1, 2])\nSet{Int64} with 2 elements:\n 2\n 1\n\njulia> pop!(S)\n2\n\njulia> S\nSet{Int64} with 1 element:\n 1\n\njulia> pop!(Dict(1=>2))\n1 => 2\n\n\n\n\n\npop!(collection, key[, default])\n\nDelete and return the mapping for key if it exists in collection, otherwise return default, or throw an error if default is not specified.\n\nExamples\n\njulia> d = Dict(\"a\"=>1, \"b\"=>2, \"c\"=>3);\n\njulia> pop!(d, \"a\")\n1\n\njulia> pop!(d, \"d\")\nERROR: KeyError: key \"d\" not found\nStacktrace:\n[...]\n\njulia> pop!(d, \"e\", 4)\n4\n\n\n\n\n\n","category":"function"},{"location":"base/collections/#Base.popat!","page":"集合和数据结构","title":"Base.popat!","text":"popat!(a::Vector, i::Integer, [default])\n\nRemove the item at the given i and return it. Subsequent items are shifted to fill the resulting gap. When i is not a valid index for a, return default, or throw an error if default is not specified.\n\nSee also: pop!, popfirst!, deleteat!, splice!.\n\ncompat: Julia 1.5\nThis function is available as of Julia 1.5.\n\nExamples\n\njulia> a = [4, 3, 2, 1]; popat!(a, 2)\n3\n\njulia> a\n3-element Vector{Int64}:\n 4\n 2\n 1\n\njulia> popat!(a, 4, missing)\nmissing\n\njulia> popat!(a, 4)\nERROR: BoundsError: attempt to access 3-element Vector{Int64} at index [4]\n[...]\n\n\n\n\n\n","category":"function"},{"location":"base/collections/#Base.pushfirst!","page":"集合和数据结构","title":"Base.pushfirst!","text":"pushfirst!(collection, items...) -> collection\n\nInsert one or more items at the beginning of collection.\n\nThis function is called unshift in many other programming languages.\n\nExamples\n\njulia> pushfirst!([1, 2, 3, 4], 5, 6)\n6-element Vector{Int64}:\n 5\n 6\n 1\n 2\n 3\n 4\n\n\n\n\n\n","category":"function"},{"location":"base/collections/#Base.popfirst!","page":"集合和数据结构","title":"Base.popfirst!","text":"popfirst!(collection) -> item\n\nRemove the first item from collection.\n\nThis function is called shift in many other programming languages.\n\nSee also: pop!, popat!, delete!.\n\nExamples\n\njulia> A = [1, 2, 3, 4, 5, 6]\n6-element Vector{Int64}:\n 1\n 2\n 3\n 4\n 5\n 6\n\njulia> popfirst!(A)\n1\n\njulia> A\n5-element Vector{Int64}:\n 2\n 3\n 4\n 5\n 6\n\n\n\n\n\n","category":"function"},{"location":"base/collections/#Base.insert!","page":"集合和数据结构","title":"Base.insert!","text":"insert!(a::Vector, index::Integer, item)\n\nInsert an item into a at the given index. index is the index of item in the resulting a.\n\nSee also: push!, replace, popat!, splice!.\n\nExamples\n\njulia> insert!(Any[1:6;], 3, \"here\")\n7-element Vector{Any}:\n 1\n 2\n \"here\"\n 3\n 4\n 5\n 6\n\n\n\n\n\n","category":"function"},{"location":"base/collections/#Base.deleteat!","page":"集合和数据结构","title":"Base.deleteat!","text":"deleteat!(a::Vector, i::Integer)\n\nRemove the item at the given i and return the modified a. Subsequent items are shifted to fill the resulting gap.\n\nSee also: delete!, popat!, splice!.\n\nExamples\n\njulia> deleteat!([6, 5, 4, 3, 2, 1], 2)\n5-element Vector{Int64}:\n 6\n 4\n 3\n 2\n 1\n\n\n\n\n\ndeleteat!(a::Vector, inds)\n\nRemove the items at the indices given by inds, and return the modified a. Subsequent items are shifted to fill the resulting gap.\n\ninds can be either an iterator or a collection of sorted and unique integer indices, or a boolean vector of the same length as a with true indicating entries to delete.\n\nExamples\n\njulia> deleteat!([6, 5, 4, 3, 2, 1], 1:2:5)\n3-element Vector{Int64}:\n 5\n 3\n 1\n\njulia> deleteat!([6, 5, 4, 3, 2, 1], [true, false, true, false, true, false])\n3-element Vector{Int64}:\n 5\n 3\n 1\n\njulia> deleteat!([6, 5, 4, 3, 2, 1], (2, 2))\nERROR: ArgumentError: indices must be unique and sorted\nStacktrace:\n[...]\n\n\n\n\n\n","category":"function"},{"location":"base/collections/#Base.keepat!","page":"集合和数据结构","title":"Base.keepat!","text":"keepat!(a::Vector, inds)\nkeepat!(a::BitVector, inds)\n\nRemove the items at all the indices which are not given by inds, and return the modified a. Items which are kept are shifted to fill the resulting gaps.\n\ninds must be an iterator of sorted and unique integer indices. See also deleteat!.\n\ncompat: Julia 1.7\nThis function is available as of Julia 1.7.\n\nExamples\n\njulia> keepat!([6, 5, 4, 3, 2, 1], 1:2:5)\n3-element Vector{Int64}:\n 6\n 4\n 2\n\n\n\n\n\nkeepat!(a::Vector, m::AbstractVector{Bool})\nkeepat!(a::BitVector, m::AbstractVector{Bool})\n\nThe in-place version of logical indexing a = a[m]. That is, keepat!(a, m) on vectors of equal length a and m will remove all elements from a for which m at the corresponding index is false.\n\nExamples\n\njulia> a = [:a, :b, :c];\n\njulia> keepat!(a, [true, false, true])\n2-element Vector{Symbol}:\n :a\n :c\n\njulia> a\n2-element Vector{Symbol}:\n :a\n :c\n\n\n\n\n\n","category":"function"},{"location":"base/collections/#Base.splice!","page":"集合和数据结构","title":"Base.splice!","text":"splice!(a::Vector, index::Integer, [replacement]) -> item\n\nRemove the item at the given index, and return the removed item. Subsequent items are shifted left to fill the resulting gap. If specified, replacement values from an ordered collection will be spliced in place of the removed item.\n\nSee also: replace, delete!, deleteat!, pop!, popat!.\n\nExamples\n\njulia> A = [6, 5, 4, 3, 2, 1]; splice!(A, 5)\n2\n\njulia> A\n5-element Vector{Int64}:\n 6\n 5\n 4\n 3\n 1\n\njulia> splice!(A, 5, -1)\n1\n\njulia> A\n5-element Vector{Int64}:\n 6\n 5\n 4\n 3\n -1\n\njulia> splice!(A, 1, [-1, -2, -3])\n6\n\njulia> A\n7-element Vector{Int64}:\n -1\n -2\n -3\n 5\n 4\n 3\n -1\n\nTo insert replacement before an index n without removing any items, use splice!(collection, n:n-1, replacement).\n\n\n\n\n\nsplice!(a::Vector, indices, [replacement]) -> items\n\nRemove items at specified indices, and return a collection containing the removed items. Subsequent items are shifted left to fill the resulting gaps. If specified, replacement values from an ordered collection will be spliced in place of the removed items; in this case, indices must be a AbstractUnitRange.\n\nTo insert replacement before an index n without removing any items, use splice!(collection, n:n-1, replacement).\n\ncompat: Julia 1.5\nPrior to Julia 1.5, indices must always be a UnitRange.\n\ncompat: Julia 1.8\nPrior to Julia 1.8, indices must be a UnitRange if splicing in replacement values.\n\nExamples\n\njulia> A = [-1, -2, -3, 5, 4, 3, -1]; splice!(A, 4:3, 2)\nInt64[]\n\njulia> A\n8-element Vector{Int64}:\n -1\n -2\n -3\n 2\n 5\n 4\n 3\n -1\n\n\n\n\n\n","category":"function"},{"location":"base/collections/#Base.resize!","page":"集合和数据结构","title":"Base.resize!","text":"resize!(a::Vector, n::Integer) -> Vector\n\nResize a to contain n elements. If n is smaller than the current collection length, the first n elements will be retained. If n is larger, the new elements are not guaranteed to be initialized.\n\nExamples\n\njulia> resize!([6, 5, 4, 3, 2, 1], 3)\n3-element Vector{Int64}:\n 6\n 5\n 4\n\njulia> a = resize!([6, 5, 4, 3, 2, 1], 8);\n\njulia> length(a)\n8\n\njulia> a[1:6]\n6-element Vector{Int64}:\n 6\n 5\n 4\n 3\n 2\n 1\n\n\n\n\n\n","category":"function"},{"location":"base/collections/#Base.append!","page":"集合和数据结构","title":"Base.append!","text":"append!(collection, collections...) -> collection.\n\nFor an ordered container collection, add the elements of each collections to the end of it.\n\ncompat: Julia 1.6\nSpecifying multiple collections to be appended requires at least Julia 1.6.\n\nExamples\n\njulia> append!([1], [2, 3])\n3-element Vector{Int64}:\n 1\n 2\n 3\n\njulia> append!([1, 2, 3], [4, 5], [6])\n6-element Vector{Int64}:\n 1\n 2\n 3\n 4\n 5\n 6\n\nUse push! to add individual items to collection which are not already themselves in another collection. The result of the preceding example is equivalent to push!([1, 2, 3], 4, 5, 6).\n\nSee sizehint! for notes about the performance model.\n\nSee also vcat for vectors, union! for sets, and prepend! and pushfirst! for the opposite order.\n\n\n\n\n\n","category":"function"},{"location":"base/collections/#Base.prepend!","page":"集合和数据结构","title":"Base.prepend!","text":"prepend!(a::Vector, collections...) -> collection\n\nInsert the elements of each collections to the beginning of a.\n\nWhen collections specifies multiple collections, order is maintained: elements of collections[1] will appear leftmost in a, and so on.\n\ncompat: Julia 1.6\nSpecifying multiple collections to be prepended requires at least Julia 1.6.\n\nExamples\n\njulia> prepend!([3], [1, 2])\n3-element Vector{Int64}:\n 1\n 2\n 3\n\njulia> prepend!([6], [1, 2], [3, 4, 5])\n6-element Vector{Int64}:\n 1\n 2\n 3\n 4\n 5\n 6\n\n\n\n\n\n","category":"function"},{"location":"base/collections/","page":"集合和数据结构","title":"集合和数据结构","text":"以下类型均完全实现了上述函数:","category":"page"},{"location":"base/collections/","page":"集合和数据结构","title":"集合和数据结构","text":"Vector (a.k.a. 1-dimensional Array)\nBitVector (a.k.a. 1-dimensional BitArray)","category":"page"},{"location":"base/collections/#集合相关的实用工具","page":"集合和数据结构","title":"集合相关的实用工具","text":"","category":"section"},{"location":"base/collections/","page":"集合和数据结构","title":"集合和数据结构","text":"Base.Pair\nIterators.Pairs","category":"page"},{"location":"base/collections/#Core.Pair","page":"集合和数据结构","title":"Core.Pair","text":"Pair(x, y)\nx => y\n\nConstruct a Pair object with type Pair{typeof(x), typeof(y)}. The elements are stored in the fields first and second. They can also be accessed via iteration (but a Pair is treated as a single \"scalar\" for broadcasting operations).\n\nSee also Dict.\n\nExamples\n\njulia> p = \"foo\" => 7\n\"foo\" => 7\n\njulia> typeof(p)\nPair{String, Int64}\n\njulia> p.first\n\"foo\"\n\njulia> for x in p\n println(x)\n end\nfoo\n7\n\n\n\n\n\n","category":"type"},{"location":"base/collections/#Base.Pairs","page":"集合和数据结构","title":"Base.Pairs","text":"Iterators.Pairs(values, keys) <: AbstractDict{eltype(keys), eltype(values)}\n\nTransforms an indexable container into a Dictionary-view of the same data. Modifying the key-space of the underlying data may invalidate this object.\n\n\n\n\n\n","category":"type"},{"location":"stdlib/Distributed/#man-distributed","page":"Distributed Computing","title":"Distributed Computing","text":"","category":"section"},{"location":"stdlib/Distributed/","page":"Distributed Computing","title":"Distributed Computing","text":"Distributed.addprocs\nDistributed.nprocs\nDistributed.nworkers\nDistributed.procs()\nDistributed.procs(::Integer)\nDistributed.workers\nDistributed.rmprocs\nDistributed.interrupt\nDistributed.myid\nDistributed.pmap\nDistributed.RemoteException\nDistributed.Future\nDistributed.RemoteChannel\nDistributed.fetch(::Distributed.Future)\nDistributed.fetch(::RemoteChannel)\nDistributed.remotecall(::Any, ::Integer, ::Any...)\nDistributed.remotecall_wait(::Any, ::Integer, ::Any...)\nDistributed.remotecall_fetch(::Any, ::Integer, ::Any...)\nDistributed.remote_do(::Any, ::Integer, ::Any...)\nDistributed.put!(::RemoteChannel, ::Any...)\nDistributed.put!(::Distributed.Future, ::Any)\nDistributed.take!(::RemoteChannel, ::Any...)\nDistributed.isready(::RemoteChannel, ::Any...)\nDistributed.isready(::Distributed.Future)\nDistributed.AbstractWorkerPool\nDistributed.WorkerPool\nDistributed.CachingPool\nDistributed.default_worker_pool\nDistributed.clear!(::CachingPool)\nDistributed.remote\nDistributed.remotecall(::Any, ::AbstractWorkerPool, ::Any...)\nDistributed.remotecall_wait(::Any, ::AbstractWorkerPool, ::Any...)\nDistributed.remotecall_fetch(::Any, ::AbstractWorkerPool, ::Any...)\nDistributed.remote_do(::Any, ::AbstractWorkerPool, ::Any...)\nDistributed.@spawnat\nDistributed.@fetch\nDistributed.@fetchfrom\nDistributed.@distributed\nDistributed.@everywhere\nDistributed.clear!(::Any, ::Any; ::Any)\nDistributed.remoteref_id\nDistributed.channel_from_id\nDistributed.worker_id_from_socket\nDistributed.cluster_cookie()\nDistributed.cluster_cookie(::Any)","category":"page"},{"location":"stdlib/Distributed/#Distributed.addprocs","page":"Distributed Computing","title":"Distributed.addprocs","text":"addprocs(manager::ClusterManager; kwargs...) -> List of process identifiers\n\nLaunches worker processes via the specified cluster manager.\n\nFor example, Beowulf clusters are supported via a custom cluster manager implemented in the package ClusterManagers.jl.\n\nThe number of seconds a newly launched worker waits for connection establishment from the master can be specified via variable JULIA_WORKER_TIMEOUT in the worker process's environment. Relevant only when using TCP/IP as transport.\n\nTo launch workers without blocking the REPL, or the containing function if launching workers programmatically, execute addprocs in its own task.\n\nExamples\n\n# On busy clusters, call `addprocs` asynchronously\nt = @async addprocs(...)\n\n# Utilize workers as and when they come online\nif nprocs() > 1 # Ensure at least one new worker is available\n .... # perform distributed execution\nend\n\n# Retrieve newly launched worker IDs, or any error messages\nif istaskdone(t) # Check if `addprocs` has completed to ensure `fetch` doesn't block\n if nworkers() == N\n new_pids = fetch(t)\n else\n fetch(t)\n end\nend\n\n\n\n\n\naddprocs(machines; tunnel=false, sshflags=``, max_parallel=10, kwargs...) -> List of process identifiers\n\nAdd processes on remote machines via SSH. See exename to set the path to the julia installation on remote machines.\n\nmachines is a vector of machine specifications. Workers are started for each specification.\n\nA machine specification is either a string machine_spec or a tuple - (machine_spec, count).\n\nmachine_spec is a string of the form [user@]host[:port] [bind_addr[:port]]. user defaults to current user, port to the standard ssh port. If [bind_addr[:port]] is specified, other workers will connect to this worker at the specified bind_addr and port.\n\ncount is the number of workers to be launched on the specified host. If specified as :auto it will launch as many workers as the number of CPU threads on the specific host.\n\nKeyword arguments:\n\ntunnel: if true then SSH tunneling will be used to connect to the worker from the master process. Default is false.\nmultiplex: if true then SSH multiplexing is used for SSH tunneling. Default is false.\nssh: the name or path of the SSH client executable used to start the workers. Default is \"ssh\".\nsshflags: specifies additional ssh options, e.g. sshflags=`-i /home/foo/bar.pem`\nmax_parallel: specifies the maximum number of workers connected to in parallel at a host. Defaults to 10.\nshell: specifies the type of shell to which ssh connects on the workers.\nshell=:posix: a POSIX-compatible Unix/Linux shell (sh, ksh, bash, dash, zsh, etc.). The default.\nshell=:csh: a Unix C shell (csh, tcsh).\nshell=:wincmd: Microsoft Windows cmd.exe.\ndir: specifies the working directory on the workers. Defaults to the host's current directory (as found by pwd())\nenable_threaded_blas: if true then BLAS will run on multiple threads in added processes. Default is false.\nexename: name of the julia executable. Defaults to \"$(Sys.BINDIR)/julia\" or \"$(Sys.BINDIR)/julia-debug\" as the case may be.\nexeflags: additional flags passed to the worker processes.\ntopology: Specifies how the workers connect to each other. Sending a message between unconnected workers results in an error.\ntopology=:all_to_all: All processes are connected to each other. The default.\ntopology=:master_worker: Only the driver process, i.e. pid 1 connects to the workers. The workers do not connect to each other.\ntopology=:custom: The launch method of the cluster manager specifies the connection topology via fields ident and connect_idents in WorkerConfig. A worker with a cluster manager identity ident will connect to all workers specified in connect_idents.\nlazy: Applicable only with topology=:all_to_all. If true, worker-worker connections are setup lazily, i.e. they are setup at the first instance of a remote call between workers. Default is true.\nenv: provide an array of string pairs such as env=[\"JULIA_DEPOT_PATH\"=>\"/depot\"] to request that environment variables are set on the remote machine. By default only the environment variable JULIA_WORKER_TIMEOUT is passed automatically from the local to the remote environment.\ncmdline_cookie: pass the authentication cookie via the --worker commandline option. The (more secure) default behaviour of passing the cookie via ssh stdio may hang with Windows workers that use older (pre-ConPTY) Julia or Windows versions, in which case cmdline_cookie=true offers a work-around.\n\ncompat: Julia 1.6\nThe keyword arguments ssh, shell, env and cmdline_cookie were added in Julia 1.6.\n\nEnvironment variables:\n\nIf the master process fails to establish a connection with a newly launched worker within 60.0 seconds, the worker treats it as a fatal situation and terminates. This timeout can be controlled via environment variable JULIA_WORKER_TIMEOUT. The value of JULIA_WORKER_TIMEOUT on the master process specifies the number of seconds a newly launched worker waits for connection establishment.\n\n\n\n\n\naddprocs(; kwargs...) -> List of process identifiers\n\nEquivalent to addprocs(Sys.CPU_THREADS; kwargs...)\n\nNote that workers do not run a .julia/config/startup.jl startup script, nor do they synchronize their global state (such as global variables, new method definitions, and loaded modules) with any of the other running processes.\n\n\n\n\n\naddprocs(np::Integer; restrict=true, kwargs...) -> List of process identifiers\n\nLaunches workers using the in-built LocalManager which only launches workers on the local host. This can be used to take advantage of multiple cores. addprocs(4) will add 4 processes on the local machine. If restrict is true, binding is restricted to 127.0.0.1. Keyword args dir, exename, exeflags, topology, lazy and enable_threaded_blas have the same effect as documented for addprocs(machines).\n\n\n\n\n\n","category":"function"},{"location":"stdlib/Distributed/#Distributed.nprocs","page":"Distributed Computing","title":"Distributed.nprocs","text":"nprocs()\n\nGet the number of available processes.\n\nExamples\n\njulia> nprocs()\n3\n\njulia> workers()\n2-element Array{Int64,1}:\n 2\n 3\n\n\n\n\n\n","category":"function"},{"location":"stdlib/Distributed/#Distributed.nworkers","page":"Distributed Computing","title":"Distributed.nworkers","text":"nworkers()\n\nGet the number of available worker processes. This is one less than nprocs(). Equal to nprocs() if nprocs() == 1.\n\nExamples\n\n$ julia -p 2\n\njulia> nprocs()\n3\n\njulia> nworkers()\n2\n\n\n\n\n\n","category":"function"},{"location":"stdlib/Distributed/#Distributed.procs-Tuple{}","page":"Distributed Computing","title":"Distributed.procs","text":"procs()\n\nReturn a list of all process identifiers, including pid 1 (which is not included by workers()).\n\nExamples\n\n$ julia -p 2\n\njulia> procs()\n3-element Array{Int64,1}:\n 1\n 2\n 3\n\n\n\n\n\n","category":"method"},{"location":"stdlib/Distributed/#Distributed.procs-Tuple{Integer}","page":"Distributed Computing","title":"Distributed.procs","text":"procs(pid::Integer)\n\nReturn a list of all process identifiers on the same physical node. Specifically all workers bound to the same ip-address as pid are returned.\n\n\n\n\n\n","category":"method"},{"location":"stdlib/Distributed/#Distributed.workers","page":"Distributed Computing","title":"Distributed.workers","text":"workers()\n\nReturn a list of all worker process identifiers.\n\nExamples\n\n$ julia -p 2\n\njulia> workers()\n2-element Array{Int64,1}:\n 2\n 3\n\n\n\n\n\n","category":"function"},{"location":"stdlib/Distributed/#Distributed.rmprocs","page":"Distributed Computing","title":"Distributed.rmprocs","text":"rmprocs(pids...; waitfor=typemax(Int))\n\nRemove the specified workers. Note that only process 1 can add or remove workers.\n\nArgument waitfor specifies how long to wait for the workers to shut down:\n\nIf unspecified, rmprocs will wait until all requested pids are removed.\nAn ErrorException is raised if all workers cannot be terminated before the requested waitfor seconds.\nWith a waitfor value of 0, the call returns immediately with the workers scheduled for removal in a different task. The scheduled Task object is returned. The user should call wait on the task before invoking any other parallel calls.\n\nExamples\n\n$ julia -p 5\n\njulia> t = rmprocs(2, 3, waitfor=0)\nTask (runnable) @0x0000000107c718d0\n\njulia> wait(t)\n\njulia> workers()\n3-element Array{Int64,1}:\n 4\n 5\n 6\n\n\n\n\n\n","category":"function"},{"location":"stdlib/Distributed/#Distributed.interrupt","page":"Distributed Computing","title":"Distributed.interrupt","text":"interrupt(pids::Integer...)\n\nInterrupt the current executing task on the specified workers. This is equivalent to pressing Ctrl-C on the local machine. If no arguments are given, all workers are interrupted.\n\n\n\n\n\ninterrupt(pids::AbstractVector=workers())\n\nInterrupt the current executing task on the specified workers. This is equivalent to pressing Ctrl-C on the local machine. If no arguments are given, all workers are interrupted.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/Distributed/#Distributed.myid","page":"Distributed Computing","title":"Distributed.myid","text":"myid()\n\nGet the id of the current process.\n\nExamples\n\njulia> myid()\n1\n\njulia> remotecall_fetch(() -> myid(), 4)\n4\n\n\n\n\n\n","category":"function"},{"location":"stdlib/Distributed/#Distributed.pmap","page":"Distributed Computing","title":"Distributed.pmap","text":"pmap(f, [::AbstractWorkerPool], c...; distributed=true, batch_size=1, on_error=nothing, retry_delays=[], retry_check=nothing) -> collection\n\nTransform collection c by applying f to each element using available workers and tasks.\n\nFor multiple collection arguments, apply f elementwise.\n\nNote that f must be made available to all worker processes; see Code Availability and Loading Packages for details.\n\nIf a worker pool is not specified, all available workers, i.e., the default worker pool is used.\n\nBy default, pmap distributes the computation over all specified workers. To use only the local process and distribute over tasks, specify distributed=false. This is equivalent to using asyncmap. For example, pmap(f, c; distributed=false) is equivalent to asyncmap(f,c; ntasks=()->nworkers())\n\npmap can also use a mix of processes and tasks via the batch_size argument. For batch sizes greater than 1, the collection is processed in multiple batches, each of length batch_size or less. A batch is sent as a single request to a free worker, where a local asyncmap processes elements from the batch using multiple concurrent tasks.\n\nAny error stops pmap from processing the remainder of the collection. To override this behavior you can specify an error handling function via argument on_error which takes in a single argument, i.e., the exception. The function can stop the processing by rethrowing the error, or, to continue, return any value which is then returned inline with the results to the caller.\n\nConsider the following two examples. The first one returns the exception object inline, the second a 0 in place of any exception:\n\njulia> pmap(x->iseven(x) ? error(\"foo\") : x, 1:4; on_error=identity)\n4-element Array{Any,1}:\n 1\n ErrorException(\"foo\")\n 3\n ErrorException(\"foo\")\n\njulia> pmap(x->iseven(x) ? error(\"foo\") : x, 1:4; on_error=ex->0)\n4-element Array{Int64,1}:\n 1\n 0\n 3\n 0\n\nErrors can also be handled by retrying failed computations. Keyword arguments retry_delays and retry_check are passed through to retry as keyword arguments delays and check respectively. If batching is specified, and an entire batch fails, all items in the batch are retried.\n\nNote that if both on_error and retry_delays are specified, the on_error hook is called before retrying. If on_error does not throw (or rethrow) an exception, the element will not be retried.\n\nExample: On errors, retry f on an element a maximum of 3 times without any delay between retries.\n\npmap(f, c; retry_delays = zeros(3))\n\nExample: Retry f only if the exception is not of type InexactError, with exponentially increasing delays up to 3 times. Return a NaN in place for all InexactError occurrences.\n\npmap(f, c; on_error = e->(isa(e, InexactError) ? NaN : rethrow()), retry_delays = ExponentialBackOff(n = 3))\n\n\n\n\n\n","category":"function"},{"location":"stdlib/Distributed/#Distributed.RemoteException","page":"Distributed Computing","title":"Distributed.RemoteException","text":"RemoteException(captured)\n\nExceptions on remote computations are captured and rethrown locally. A RemoteException wraps the pid of the worker and a captured exception. A CapturedException captures the remote exception and a serializable form of the call stack when the exception was raised.\n\n\n\n\n\n","category":"type"},{"location":"stdlib/Distributed/#Distributed.Future","page":"Distributed Computing","title":"Distributed.Future","text":"Future(w::Int, rrid::RRID, v::Union{Some, Nothing}=nothing)\n\nA Future is a placeholder for a single computation of unknown termination status and time. For multiple potential computations, see RemoteChannel. See remoteref_id for identifying an AbstractRemoteRef.\n\n\n\n\n\n","category":"type"},{"location":"stdlib/Distributed/#Distributed.RemoteChannel","page":"Distributed Computing","title":"Distributed.RemoteChannel","text":"RemoteChannel(pid::Integer=myid())\n\nMake a reference to a Channel{Any}(1) on process pid. The default pid is the current process.\n\nRemoteChannel(f::Function, pid::Integer=myid())\n\nCreate references to remote channels of a specific size and type. f is a function that when executed on pid must return an implementation of an AbstractChannel.\n\nFor example, RemoteChannel(()->Channel{Int}(10), pid), will return a reference to a channel of type Int and size 10 on pid.\n\nThe default pid is the current process.\n\n\n\n\n\n","category":"type"},{"location":"stdlib/Distributed/#Base.fetch-Tuple{Distributed.Future}","page":"Distributed Computing","title":"Base.fetch","text":"fetch(x::Future)\n\nWait for and get the value of a Future. The fetched value is cached locally. Further calls to fetch on the same reference return the cached value. If the remote value is an exception, throws a RemoteException which captures the remote exception and backtrace.\n\n\n\n\n\n","category":"method"},{"location":"stdlib/Distributed/#Base.fetch-Tuple{RemoteChannel}","page":"Distributed Computing","title":"Base.fetch","text":"fetch(c::RemoteChannel)\n\nWait for and get a value from a RemoteChannel. Exceptions raised are the same as for a Future. Does not remove the item fetched.\n\n\n\n\n\n","category":"method"},{"location":"stdlib/Distributed/#Distributed.remotecall-Tuple{Any, Integer, Vararg{Any}}","page":"Distributed Computing","title":"Distributed.remotecall","text":"remotecall(f, id::Integer, args...; kwargs...) -> Future\n\nCall a function f asynchronously on the given arguments on the specified process. Return a Future. Keyword arguments, if any, are passed through to f.\n\n\n\n\n\n","category":"method"},{"location":"stdlib/Distributed/#Distributed.remotecall_wait-Tuple{Any, Integer, Vararg{Any}}","page":"Distributed Computing","title":"Distributed.remotecall_wait","text":"remotecall_wait(f, id::Integer, args...; kwargs...)\n\nPerform a faster wait(remotecall(...)) in one message on the Worker specified by worker id id. Keyword arguments, if any, are passed through to f.\n\nSee also wait and remotecall.\n\n\n\n\n\n","category":"method"},{"location":"stdlib/Distributed/#Distributed.remotecall_fetch-Tuple{Any, Integer, Vararg{Any}}","page":"Distributed Computing","title":"Distributed.remotecall_fetch","text":"remotecall_fetch(f, id::Integer, args...; kwargs...)\n\nPerform fetch(remotecall(...)) in one message. Keyword arguments, if any, are passed through to f. Any remote exceptions are captured in a RemoteException and thrown.\n\nSee also fetch and remotecall.\n\nExamples\n\n$ julia -p 2\n\njulia> remotecall_fetch(sqrt, 2, 4)\n2.0\n\njulia> remotecall_fetch(sqrt, 2, -4)\nERROR: On worker 2:\nDomainError with -4.0:\nsqrt will only return a complex result if called with a complex argument. Try sqrt(Complex(x)).\n...\n\n\n\n\n\n","category":"method"},{"location":"stdlib/Distributed/#Distributed.remote_do-Tuple{Any, Integer, Vararg{Any}}","page":"Distributed Computing","title":"Distributed.remote_do","text":"remote_do(f, id::Integer, args...; kwargs...) -> nothing\n\nExecutes f on worker id asynchronously. Unlike remotecall, it does not store the result of computation, nor is there a way to wait for its completion.\n\nA successful invocation indicates that the request has been accepted for execution on the remote node.\n\nWhile consecutive remotecalls to the same worker are serialized in the order they are invoked, the order of executions on the remote worker is undetermined. For example, remote_do(f1, 2); remotecall(f2, 2); remote_do(f3, 2) will serialize the call to f1, followed by f2 and f3 in that order. However, it is not guaranteed that f1 is executed before f3 on worker 2.\n\nAny exceptions thrown by f are printed to stderr on the remote worker.\n\nKeyword arguments, if any, are passed through to f.\n\n\n\n\n\n","category":"method"},{"location":"stdlib/Distributed/#Base.put!-Tuple{RemoteChannel, Vararg{Any}}","page":"Distributed Computing","title":"Base.put!","text":"put!(rr::RemoteChannel, args...)\n\nStore a set of values to the RemoteChannel. If the channel is full, blocks until space is available. Return the first argument.\n\n\n\n\n\n","category":"method"},{"location":"stdlib/Distributed/#Base.put!-Tuple{Distributed.Future, Any}","page":"Distributed Computing","title":"Base.put!","text":"put!(rr::Future, v)\n\nStore a value to a Future rr. Futures are write-once remote references. A put! on an already set Future throws an Exception. All asynchronous remote calls return Futures and set the value to the return value of the call upon completion.\n\n\n\n\n\n","category":"method"},{"location":"stdlib/Distributed/#Base.take!-Tuple{RemoteChannel, Vararg{Any}}","page":"Distributed Computing","title":"Base.take!","text":"take!(rr::RemoteChannel, args...)\n\nFetch value(s) from a RemoteChannel rr, removing the value(s) in the process.\n\n\n\n\n\n","category":"method"},{"location":"stdlib/Distributed/#Base.isready-Tuple{RemoteChannel, Vararg{Any}}","page":"Distributed Computing","title":"Base.isready","text":"isready(rr::RemoteChannel, args...)\n\nDetermine whether a RemoteChannel has a value stored to it. Note that this function can cause race conditions, since by the time you receive its result it may no longer be true. However, it can be safely used on a Future since they are assigned only once.\n\n\n\n\n\n","category":"method"},{"location":"stdlib/Distributed/#Base.isready-Tuple{Distributed.Future}","page":"Distributed Computing","title":"Base.isready","text":"isready(rr::Future)\n\nDetermine whether a Future has a value stored to it.\n\nIf the argument Future is owned by a different node, this call will block to wait for the answer. It is recommended to wait for rr in a separate task instead or to use a local Channel as a proxy:\n\np = 1\nf = Future(p)\nerrormonitor(@async put!(f, remotecall_fetch(long_computation, p)))\nisready(f) # will not block\n\n\n\n\n\n","category":"method"},{"location":"stdlib/Distributed/#Distributed.AbstractWorkerPool","page":"Distributed Computing","title":"Distributed.AbstractWorkerPool","text":"AbstractWorkerPool\n\nSupertype for worker pools such as WorkerPool and CachingPool. An AbstractWorkerPool should implement:\n\npush! - add a new worker to the overall pool (available + busy)\nput! - put back a worker to the available pool\ntake! - take a worker from the available pool (to be used for remote function execution)\nlength - number of workers available in the overall pool\nisready - return false if a take! on the pool would block, else true\n\nThe default implementations of the above (on a AbstractWorkerPool) require fields\n\nchannel::Channel{Int}\nworkers::Set{Int}\n\nwhere channel contains free worker pids and workers is the set of all workers associated with this pool.\n\n\n\n\n\n","category":"type"},{"location":"stdlib/Distributed/#Distributed.WorkerPool","page":"Distributed Computing","title":"Distributed.WorkerPool","text":"WorkerPool(workers::Vector{Int})\n\nCreate a WorkerPool from a vector of worker ids.\n\nExamples\n\n$ julia -p 3\n\njulia> WorkerPool([2, 3])\nWorkerPool(Channel{Int64}(sz_max:9223372036854775807,sz_curr:2), Set([2, 3]), RemoteChannel{Channel{Any}}(1, 1, 6))\n\n\n\n\n\n","category":"type"},{"location":"stdlib/Distributed/#Distributed.CachingPool","page":"Distributed Computing","title":"Distributed.CachingPool","text":"CachingPool(workers::Vector{Int})\n\nAn implementation of an AbstractWorkerPool. remote, remotecall_fetch, pmap (and other remote calls which execute functions remotely) benefit from caching the serialized/deserialized functions on the worker nodes, especially closures (which may capture large amounts of data).\n\nThe remote cache is maintained for the lifetime of the returned CachingPool object. To clear the cache earlier, use clear!(pool).\n\nFor global variables, only the bindings are captured in a closure, not the data. let blocks can be used to capture global data.\n\nExamples\n\nconst foo = rand(10^8);\nwp = CachingPool(workers())\nlet foo = foo\n pmap(i -> sum(foo) + i, wp, 1:100);\nend\n\nThe above would transfer foo only once to each worker.\n\n\n\n\n\n","category":"type"},{"location":"stdlib/Distributed/#Distributed.default_worker_pool","page":"Distributed Computing","title":"Distributed.default_worker_pool","text":"default_worker_pool()\n\nWorkerPool containing idle workers - used by remote(f) and pmap (by default).\n\nExamples\n\n$ julia -p 3\n\njulia> default_worker_pool()\nWorkerPool(Channel{Int64}(sz_max:9223372036854775807,sz_curr:3), Set([4, 2, 3]), RemoteChannel{Channel{Any}}(1, 1, 4))\n\n\n\n\n\n","category":"function"},{"location":"stdlib/Distributed/#Distributed.clear!-Tuple{CachingPool}","page":"Distributed Computing","title":"Distributed.clear!","text":"clear!(pool::CachingPool) -> pool\n\nRemoves all cached functions from all participating workers.\n\n\n\n\n\n","category":"method"},{"location":"stdlib/Distributed/#Distributed.remote","page":"Distributed Computing","title":"Distributed.remote","text":"remote([p::AbstractWorkerPool], f) -> Function\n\nReturn an anonymous function that executes function f on an available worker (drawn from WorkerPool p if provided) using remotecall_fetch.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/Distributed/#Distributed.remotecall-Tuple{Any, AbstractWorkerPool, Vararg{Any}}","page":"Distributed Computing","title":"Distributed.remotecall","text":"remotecall(f, pool::AbstractWorkerPool, args...; kwargs...) -> Future\n\nWorkerPool variant of remotecall(f, pid, ....). Wait for and take a free worker from pool and perform a remotecall on it.\n\nExamples\n\n$ julia -p 3\n\njulia> wp = WorkerPool([2, 3]);\n\njulia> A = rand(3000);\n\njulia> f = remotecall(maximum, wp, A)\nFuture(2, 1, 6, nothing)\n\nIn this example, the task ran on pid 2, called from pid 1.\n\n\n\n\n\n","category":"method"},{"location":"stdlib/Distributed/#Distributed.remotecall_wait-Tuple{Any, AbstractWorkerPool, Vararg{Any}}","page":"Distributed Computing","title":"Distributed.remotecall_wait","text":"remotecall_wait(f, pool::AbstractWorkerPool, args...; kwargs...) -> Future\n\nWorkerPool variant of remotecall_wait(f, pid, ....). Wait for and take a free worker from pool and perform a remotecall_wait on it.\n\nExamples\n\n$ julia -p 3\n\njulia> wp = WorkerPool([2, 3]);\n\njulia> A = rand(3000);\n\njulia> f = remotecall_wait(maximum, wp, A)\nFuture(3, 1, 9, nothing)\n\njulia> fetch(f)\n0.9995177101692958\n\n\n\n\n\n","category":"method"},{"location":"stdlib/Distributed/#Distributed.remotecall_fetch-Tuple{Any, AbstractWorkerPool, Vararg{Any}}","page":"Distributed Computing","title":"Distributed.remotecall_fetch","text":"remotecall_fetch(f, pool::AbstractWorkerPool, args...; kwargs...) -> result\n\nWorkerPool variant of remotecall_fetch(f, pid, ....). Waits for and takes a free worker from pool and performs a remotecall_fetch on it.\n\nExamples\n\n$ julia -p 3\n\njulia> wp = WorkerPool([2, 3]);\n\njulia> A = rand(3000);\n\njulia> remotecall_fetch(maximum, wp, A)\n0.9995177101692958\n\n\n\n\n\n","category":"method"},{"location":"stdlib/Distributed/#Distributed.remote_do-Tuple{Any, AbstractWorkerPool, Vararg{Any}}","page":"Distributed Computing","title":"Distributed.remote_do","text":"remote_do(f, pool::AbstractWorkerPool, args...; kwargs...) -> nothing\n\nWorkerPool variant of remote_do(f, pid, ....). Wait for and take a free worker from pool and perform a remote_do on it.\n\n\n\n\n\n","category":"method"},{"location":"stdlib/Distributed/#Distributed.@spawnat","page":"Distributed Computing","title":"Distributed.@spawnat","text":"@spawnat p expr\n\nCreate a closure around an expression and run the closure asynchronously on process p. Return a Future to the result. If p is the quoted literal symbol :any, then the system will pick a processor to use automatically.\n\nExamples\n\njulia> addprocs(3);\n\njulia> f = @spawnat 2 myid()\nFuture(2, 1, 3, nothing)\n\njulia> fetch(f)\n2\n\njulia> f = @spawnat :any myid()\nFuture(3, 1, 7, nothing)\n\njulia> fetch(f)\n3\n\ncompat: Julia 1.3\nThe :any argument is available as of Julia 1.3.\n\n\n\n\n\n","category":"macro"},{"location":"stdlib/Distributed/#Distributed.@fetch","page":"Distributed Computing","title":"Distributed.@fetch","text":"@fetch expr\n\nEquivalent to fetch(@spawnat :any expr). See fetch and @spawnat.\n\nExamples\n\njulia> addprocs(3);\n\njulia> @fetch myid()\n2\n\njulia> @fetch myid()\n3\n\njulia> @fetch myid()\n4\n\njulia> @fetch myid()\n2\n\n\n\n\n\n","category":"macro"},{"location":"stdlib/Distributed/#Distributed.@fetchfrom","page":"Distributed Computing","title":"Distributed.@fetchfrom","text":"@fetchfrom\n\nEquivalent to fetch(@spawnat p expr). See fetch and @spawnat.\n\nExamples\n\njulia> addprocs(3);\n\njulia> @fetchfrom 2 myid()\n2\n\njulia> @fetchfrom 4 myid()\n4\n\n\n\n\n\n","category":"macro"},{"location":"stdlib/Distributed/#Distributed.@distributed","page":"Distributed Computing","title":"Distributed.@distributed","text":"@distributed\n\nA distributed memory, parallel for loop of the form :\n\n@distributed [reducer] for var = range\n body\nend\n\nThe specified range is partitioned and locally executed across all workers. In case an optional reducer function is specified, @distributed performs local reductions on each worker with a final reduction on the calling process.\n\nNote that without a reducer function, @distributed executes asynchronously, i.e. it spawns independent tasks on all available workers and returns immediately without waiting for completion. To wait for completion, prefix the call with @sync, like :\n\n@sync @distributed for var = range\n body\nend\n\n\n\n\n\n","category":"macro"},{"location":"stdlib/Distributed/#Distributed.@everywhere","page":"Distributed Computing","title":"Distributed.@everywhere","text":"@everywhere [procs()] expr\n\nExecute an expression under Main on all procs. Errors on any of the processes are collected into a CompositeException and thrown. For example:\n\n@everywhere bar = 1\n\nwill define Main.bar on all current processes. Any processes added later (say with addprocs()) will not have the expression defined.\n\nUnlike @spawnat, @everywhere does not capture any local variables. Instead, local variables can be broadcast using interpolation:\n\nfoo = 1\n@everywhere bar = $foo\n\nThe optional argument procs allows specifying a subset of all processes to have execute the expression.\n\nSimilar to calling remotecall_eval(Main, procs, expr), but with two extra features:\n\n- `using` and `import` statements run on the calling process first, to ensure\n packages are precompiled.\n- The current source file path used by `include` is propagated to other processes.\n\n\n\n\n\n","category":"macro"},{"location":"stdlib/Distributed/#Distributed.clear!-Tuple{Any, Any}","page":"Distributed Computing","title":"Distributed.clear!","text":"clear!(syms, pids=workers(); mod=Main)\n\nClears global bindings in modules by initializing them to nothing. syms should be of type Symbol or a collection of Symbols . pids and mod identify the processes and the module in which global variables are to be reinitialized. Only those names found to be defined under mod are cleared.\n\nAn exception is raised if a global constant is requested to be cleared.\n\n\n\n\n\n","category":"method"},{"location":"stdlib/Distributed/#Distributed.remoteref_id","page":"Distributed Computing","title":"Distributed.remoteref_id","text":"remoteref_id(r::AbstractRemoteRef) -> RRID\n\nFutures and RemoteChannels are identified by fields:\n\nwhere - refers to the node where the underlying object/storage referred to by the reference actually exists.\nwhence - refers to the node the remote reference was created from. Note that this is different from the node where the underlying object referred to actually exists. For example calling RemoteChannel(2) from the master process would result in a where value of 2 and a whence value of 1.\nid is unique across all references created from the worker specified by whence.\n\nTaken together, whence and id uniquely identify a reference across all workers.\n\nremoteref_id is a low-level API which returns a RRID object that wraps whence and id values of a remote reference.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/Distributed/#Distributed.channel_from_id","page":"Distributed Computing","title":"Distributed.channel_from_id","text":"channel_from_id(id) -> c\n\nA low-level API which returns the backing AbstractChannel for an id returned by remoteref_id. The call is valid only on the node where the backing channel exists.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/Distributed/#Distributed.worker_id_from_socket","page":"Distributed Computing","title":"Distributed.worker_id_from_socket","text":"worker_id_from_socket(s) -> pid\n\nA low-level API which, given a IO connection or a Worker, returns the pid of the worker it is connected to. This is useful when writing custom serialize methods for a type, which optimizes the data written out depending on the receiving process id.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/Distributed/#Distributed.cluster_cookie-Tuple{}","page":"Distributed Computing","title":"Distributed.cluster_cookie","text":"cluster_cookie() -> cookie\n\nReturn the cluster cookie.\n\n\n\n\n\n","category":"method"},{"location":"stdlib/Distributed/#Distributed.cluster_cookie-Tuple{Any}","page":"Distributed Computing","title":"Distributed.cluster_cookie","text":"cluster_cookie(cookie) -> cookie\n\nSet the passed cookie as the cluster cookie, then returns it.\n\n\n\n\n\n","category":"method"},{"location":"stdlib/Distributed/#Cluster-Manager-Interface","page":"Distributed Computing","title":"Cluster Manager Interface","text":"","category":"section"},{"location":"stdlib/Distributed/","page":"Distributed Computing","title":"Distributed Computing","text":"This interface provides a mechanism to launch and manage Julia workers on different cluster environments. There are two types of managers present in Base: LocalManager, for launching additional workers on the same host, and SSHManager, for launching on remote hosts via ssh. TCP/IP sockets are used to connect and transport messages between processes. It is possible for Cluster Managers to provide a different transport.","category":"page"},{"location":"stdlib/Distributed/","page":"Distributed Computing","title":"Distributed Computing","text":"Distributed.ClusterManager\nDistributed.WorkerConfig\nDistributed.launch\nDistributed.manage\nDistributed.kill(::ClusterManager, ::Int, ::WorkerConfig)\nDistributed.connect(::ClusterManager, ::Int, ::WorkerConfig)\nDistributed.init_worker\nDistributed.start_worker\nDistributed.process_messages\nDistributed.default_addprocs_params","category":"page"},{"location":"stdlib/Distributed/#Distributed.ClusterManager","page":"Distributed Computing","title":"Distributed.ClusterManager","text":"ClusterManager\n\nSupertype for cluster managers, which control workers processes as a cluster. Cluster managers implement how workers can be added, removed and communicated with. SSHManager and LocalManager are subtypes of this.\n\n\n\n\n\n","category":"type"},{"location":"stdlib/Distributed/#Distributed.WorkerConfig","page":"Distributed Computing","title":"Distributed.WorkerConfig","text":"WorkerConfig\n\nType used by ClusterManagers to control workers added to their clusters. Some fields are used by all cluster managers to access a host:\n\nio – the connection used to access the worker (a subtype of IO or Nothing)\nhost – the host address (either a String or Nothing)\nport – the port on the host used to connect to the worker (either an Int or Nothing)\n\nSome are used by the cluster manager to add workers to an already-initialized host:\n\ncount – the number of workers to be launched on the host\nexename – the path to the Julia executable on the host, defaults to \"$(Sys.BINDIR)/julia\" or \"$(Sys.BINDIR)/julia-debug\"\nexeflags – flags to use when lauching Julia remotely\n\nThe userdata field is used to store information for each worker by external managers.\n\nSome fields are used by SSHManager and similar managers:\n\ntunnel – true (use tunneling), false (do not use tunneling), or nothing (use default for the manager)\nmultiplex – true (use SSH multiplexing for tunneling) or false\nforward – the forwarding option used for -L option of ssh\nbind_addr – the address on the remote host to bind to\nsshflags – flags to use in establishing the SSH connection\nmax_parallel – the maximum number of workers to connect to in parallel on the host\n\nSome fields are used by both LocalManagers and SSHManagers:\n\nconnect_at – determines whether this is a worker-to-worker or driver-to-worker setup call\nprocess – the process which will be connected (usually the manager will assign this during addprocs)\nospid – the process ID according to the host OS, used to interrupt worker processes\nenviron – private dictionary used to store temporary information by Local/SSH managers\nident – worker as identified by the ClusterManager\nconnect_idents – list of worker ids the worker must connect to if using a custom topology\nenable_threaded_blas – true, false, or nothing, whether to use threaded BLAS or not on the workers\n\n\n\n\n\n","category":"type"},{"location":"stdlib/Distributed/#Distributed.launch","page":"Distributed Computing","title":"Distributed.launch","text":"launch(manager::ClusterManager, params::Dict, launched::Array, launch_ntfy::Condition)\n\nImplemented by cluster managers. For every Julia worker launched by this function, it should append a WorkerConfig entry to launched and notify launch_ntfy. The function MUST exit once all workers, requested by manager have been launched. params is a dictionary of all keyword arguments addprocs was called with.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/Distributed/#Distributed.manage","page":"Distributed Computing","title":"Distributed.manage","text":"manage(manager::ClusterManager, id::Integer, config::WorkerConfig. op::Symbol)\n\nImplemented by cluster managers. It is called on the master process, during a worker's lifetime, with appropriate op values:\n\nwith :register/:deregister when a worker is added / removed from the Julia worker pool.\nwith :interrupt when interrupt(workers) is called. The ClusterManager should signal the appropriate worker with an interrupt signal.\nwith :finalize for cleanup purposes.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/Distributed/#Base.kill-Tuple{ClusterManager, Int64, WorkerConfig}","page":"Distributed Computing","title":"Base.kill","text":"kill(manager::ClusterManager, pid::Int, config::WorkerConfig)\n\nImplemented by cluster managers. It is called on the master process, by rmprocs. It should cause the remote worker specified by pid to exit. kill(manager::ClusterManager.....) executes a remote exit() on pid.\n\n\n\n\n\n","category":"method"},{"location":"stdlib/Distributed/#Sockets.connect-Tuple{ClusterManager, Int64, WorkerConfig}","page":"Distributed Computing","title":"Sockets.connect","text":"connect(manager::ClusterManager, pid::Int, config::WorkerConfig) -> (instrm::IO, outstrm::IO)\n\nImplemented by cluster managers using custom transports. It should establish a logical connection to worker with id pid, specified by config and return a pair of IO objects. Messages from pid to current process will be read off instrm, while messages to be sent to pid will be written to outstrm. The custom transport implementation must ensure that messages are delivered and received completely and in order. connect(manager::ClusterManager.....) sets up TCP/IP socket connections in-between workers.\n\n\n\n\n\n","category":"method"},{"location":"stdlib/Distributed/#Distributed.init_worker","page":"Distributed Computing","title":"Distributed.init_worker","text":"init_worker(cookie::AbstractString, manager::ClusterManager=DefaultClusterManager())\n\nCalled by cluster managers implementing custom transports. It initializes a newly launched process as a worker. Command line argument --worker[=] has the effect of initializing a process as a worker using TCP/IP sockets for transport. cookie is a cluster_cookie.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/Distributed/#Distributed.start_worker","page":"Distributed Computing","title":"Distributed.start_worker","text":"start_worker([out::IO=stdout], cookie::AbstractString=readline(stdin); close_stdin::Bool=true, stderr_to_stdout::Bool=true)\n\nstart_worker is an internal function which is the default entry point for worker processes connecting via TCP/IP. It sets up the process as a Julia cluster worker.\n\nhost:port information is written to stream out (defaults to stdout).\n\nThe function reads the cookie from stdin if required, and listens on a free port (or if specified, the port in the --bind-to command line option) and schedules tasks to process incoming TCP connections and requests. It also (optionally) closes stdin and redirects stderr to stdout.\n\nIt does not return.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/Distributed/#Distributed.process_messages","page":"Distributed Computing","title":"Distributed.process_messages","text":"process_messages(r_stream::IO, w_stream::IO, incoming::Bool=true)\n\nCalled by cluster managers using custom transports. It should be called when the custom transport implementation receives the first message from a remote worker. The custom transport must manage a logical connection to the remote worker and provide two IO objects, one for incoming messages and the other for messages addressed to the remote worker. If incoming is true, the remote peer initiated the connection. Whichever of the pair initiates the connection sends the cluster cookie and its Julia version number to perform the authentication handshake.\n\nSee also cluster_cookie.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/Distributed/#Distributed.default_addprocs_params","page":"Distributed Computing","title":"Distributed.default_addprocs_params","text":"default_addprocs_params(mgr::ClusterManager) -> Dict{Symbol, Any}\n\nImplemented by cluster managers. The default keyword parameters passed when calling addprocs(mgr). The minimal set of options is available by calling default_addprocs_params()\n\n\n\n\n\n","category":"function"},{"location":"manual/conversion-and-promotion/#conversion-and-promotion","page":"类型转换和类型提升","title":"类型转换和类型提升","text":"","category":"section"},{"location":"manual/conversion-and-promotion/","page":"类型转换和类型提升","title":"类型转换和类型提升","text":"Julia 有一个提升系统,可以将数学运算符的参数提升为通用类型,如在前面章节中提到的整数和浮点数、数学运算和初等函数、类型和方法。在本节中,我们将解释类型提升系统如何工作,以及如何将其扩展到新的类型,并将其应用于除内置数学运算符之外的其他函数。传统上,编程语言在参数的类型提升上分为两大阵营:","category":"page"},{"location":"manual/conversion-and-promotion/","page":"类型转换和类型提升","title":"类型转换和类型提升","text":"内置数学类型和运算符的自动类型提升。大多数语言中,内置数值类型,当作为带有中缀语法的算术运算符的操作数时,例如 +、-、* 和 / 将自动提升为通用类型,以产生预期的结果。举例来说,C、Java、Perl 和 Python,都将 1 + 1.5 的和作为浮点值 2.5,即使 + 的一个操作数是整数。这些系统非常方便且设计得足够精细,以至于它对于程序员来讲通常是不可见的:在编写这样的表达式时,几乎没有人有意识地想到这种类型提升,但编译器和解释器必须在相加前执行转换,因为整数和浮点值无法按原样相加。因此,这种自动类型转换的复杂规则不可避免地是这些语言的规范和实现的一部分。\n没有自动类型提升。这个阵营包括 Ada 和 ML——非常「严格的」 静态类型语言。在这些语言中,每个类型转换都必须由程序员明确指定。因此,示例表达式 1 + 1.5 在 Ada 和 ML 中都会导致编译错误。相反地,必须编写 real(1) + 1.5,来在执行加法前将整数 1 显式转换为浮点值。然而,处处都显式转换是如此地不方便,以至于连 Ada 也有一定程度的自动类型转换:整数字面量被类型提升为预期的整数类型,浮点字面量同样被类型提升为适当的浮点类型。","category":"page"},{"location":"manual/conversion-and-promotion/","page":"类型转换和类型提升","title":"类型转换和类型提升","text":"在某种意义上,Julia 属于「无自动类型提升」类别:数学操作符只是具有特殊语法的函数,函数的参数永远不会自动转换。然而,人们可能会发现数学运算能应用于各种混合的参数类型,但这只是多态的多重分派的极端情况——这是 Julia 的分派和类型系统特别适合处理的情况。数学操作数的「自动」类型提升只是作为一个特殊的应用出现:Julia 带有预定义的数学运算符的 catch-all 分派规则,其在某些操作数类型的组合没有特定实现时调用。这些 catch-all 分派规则首先使用用户可定义的类型提升规则将所有操作数提升到一个通用的类型,然后针对结果值(现在已属于相同类型)调用相关运算符的特定实现。用户定义的类型可简单地加入这个类型提升系统,这需要先定义与其它类型进行相互类型转换的方法,接着提供一些类型提升规则来定义与其它类型混合时应该提升到什么类型。","category":"page"},{"location":"manual/conversion-and-promotion/#类型转换","page":"类型转换和类型提升","title":"类型转换","text":"","category":"section"},{"location":"manual/conversion-and-promotion/","page":"类型转换和类型提升","title":"类型转换和类型提升","text":"获取某种类型 T 的值的标准方法是调用该类型的构造函数 T(x)。但是,有些情况下,在程序员没有明确要求时,仍将值从一种类型转换为另一种类型是很方便的。其中一个例子是将值赋给一个数组:假设 A 是个 Vector{Float64},表达式 A[1] = 2 执行时应该自动将 2 从 Int 转换为 Float,并将结果存储在该数组中。这通过 convert 函数完成。","category":"page"},{"location":"manual/conversion-and-promotion/","page":"类型转换和类型提升","title":"类型转换和类型提升","text":"convert 函数通常接受两个参数:第一个是类型对象,第二个是需要转换为该类型的值。返回的是已转换后的值。理解这个函数最简单的办法就是尝试:","category":"page"},{"location":"manual/conversion-and-promotion/","page":"类型转换和类型提升","title":"类型转换和类型提升","text":"julia> x = 12\n12\n\njulia> typeof(x)\nInt64\n\njulia> xu = convert(UInt8, x)\n0x0c\n\njulia> typeof(xu)\nUInt8\n\njulia> xf = convert(AbstractFloat, x)\n12.0\n\njulia> typeof(xf)\nFloat64\n\njulia> a = Any[1 2 3; 4 5 6]\n2×3 Matrix{Any}:\n 1 2 3\n 4 5 6\n\njulia> convert(Array{Float64}, a)\n2×3 Matrix{Float64}:\n 1.0 2.0 3.0\n 4.0 5.0 6.0","category":"page"},{"location":"manual/conversion-and-promotion/","page":"类型转换和类型提升","title":"类型转换和类型提升","text":"类型转换并不总是可行的,有时 convert 函数并不知道该如何执行所请求的类型转换就会抛出 MethodError 错误。例如下例:","category":"page"},{"location":"manual/conversion-and-promotion/","page":"类型转换和类型提升","title":"类型转换和类型提升","text":"julia> convert(AbstractFloat, \"foo\")\nERROR: MethodError: Cannot `convert` an object of type String to an object of type AbstractFloat\n[...]","category":"page"},{"location":"manual/conversion-and-promotion/","page":"类型转换和类型提升","title":"类型转换和类型提升","text":"一些语言考虑将解析字符串为数字或格式化数字为字符串来进行转换(许多动态语言甚至会自动执行转换),但 Julia 不会:尽管某些字符串可以解析为数字,但大多数字符串都不是有效的数字表示形式,只有非常有限的子集才是。因此,在 Julia 中,必须使用专用的 parse 函数来执行此操作,这使其更加明确。","category":"page"},{"location":"manual/conversion-and-promotion/#什么时候使用-convert-函数?","page":"类型转换和类型提升","title":"什么时候使用 convert 函数?","text":"","category":"section"},{"location":"manual/conversion-and-promotion/","page":"类型转换和类型提升","title":"类型转换和类型提升","text":"构造以下语言结构时需要调用 convert 函数:","category":"page"},{"location":"manual/conversion-and-promotion/","page":"类型转换和类型提升","title":"类型转换和类型提升","text":"对一个数组赋值会转换为数组元素的类型。\n对一个对象的字段赋值会转换为已声明的字段类型。\n使用 new 构造对象会转换为该对象已声明的字段类型。\n对已声明类型的变量赋值(例如 local x::T)会转换为该类型。\n已声明返回类型的函数会转换其返回值为该类型。\n把值传递给 ccall 会将其转换为相应参数的类型。","category":"page"},{"location":"manual/conversion-and-promotion/#类型转换与构造","page":"类型转换和类型提升","title":"类型转换与构造","text":"","category":"section"},{"location":"manual/conversion-and-promotion/","page":"类型转换和类型提升","title":"类型转换和类型提升","text":"注意到 convert(T, x) 的行为似乎与 T(x) 几乎相同,它的确通常是这样。但是,有一个关键的语义差别:因为 convert 能被隐式调用,所以它的方法仅限于被认为是「安全」或「意料之内」的情况。convert 只会在表示事物的相同基本种类的类型之间进行转换(例如,不同的数字表示和不同的字符串编码)。它通常也是无损的;将值转换为其它类型并再次转换回去应该产生完全相同的值。","category":"page"},{"location":"manual/conversion-and-promotion/","page":"类型转换和类型提升","title":"类型转换和类型提升","text":"这是四种一般的构造函数与 convert 不同的情况:","category":"page"},{"location":"manual/conversion-and-promotion/#与其参数类型无关的类型的构造函数","page":"类型转换和类型提升","title":"与其参数类型无关的类型的构造函数","text":"","category":"section"},{"location":"manual/conversion-and-promotion/","page":"类型转换和类型提升","title":"类型转换和类型提升","text":"一些构造函数没有体现「转换」的概念。例如,Timer(2) 创建一个时长 2 秒的定时器,它实际上并不是从整数到定时器的「转换」。","category":"page"},{"location":"manual/conversion-and-promotion/#可变的集合","page":"类型转换和类型提升","title":"可变的集合","text":"","category":"section"},{"location":"manual/conversion-and-promotion/","page":"类型转换和类型提升","title":"类型转换和类型提升","text":"如果 x 类型已经为 T,convert(T, x) 应该返回原本的 x。相反地,如果 T 是一个可变的集合类型,那么 T(x) 应该总是创建一个新的集合(从 x 复制元素)。","category":"page"},{"location":"manual/conversion-and-promotion/#封装器类型","page":"类型转换和类型提升","title":"封装器类型","text":"","category":"section"},{"location":"manual/conversion-and-promotion/","page":"类型转换和类型提升","title":"类型转换和类型提升","text":"对于某些「封装」其它值的类型,构造函数可能会将其参数封装在一个新对象中,即使它已经是所请求的类型。例如,用 Some(x) 表示封装了一个 x 值(在上下文中,其结果可能是一个 Some 或 nothing)。但是,x 本身可能是对象 Some(y),在这种情况下,结果为 Some(Some(y)),封装了两层。然而,convert(Some, x) 只会返回 x,因为它已经是 Some 的实例了。","category":"page"},{"location":"manual/conversion-and-promotion/#不返回自身类型的实例的构造函数","page":"类型转换和类型提升","title":"不返回自身类型的实例的构造函数","text":"","category":"section"},{"location":"manual/conversion-and-promotion/","page":"类型转换和类型提升","title":"类型转换和类型提升","text":"在极少见的情况下,构造函数 T(x) 返回一个类型不为 T 的对象是有意义的。如果封装器类型是它自身的反转(例如 Flip(Flip(x)) === x),或者在重构库时为了支持某个旧的调用语法以实现向后兼容,则可能发生这种情况。但是,convert(T, x) 应该总是返回一个类型为 T 的值。","category":"page"},{"location":"manual/conversion-and-promotion/#定义新的类型转换","page":"类型转换和类型提升","title":"定义新的类型转换","text":"","category":"section"},{"location":"manual/conversion-and-promotion/","page":"类型转换和类型提升","title":"类型转换和类型提升","text":"在定义新类型时,最初创建它的所有方法都应定义为构造函数。如果隐式类型转换很明显是有用的,并且某些构造函数满足上面的「安全」标准,那么可以考虑添加 convert 方法。这些方法通常非常简单,因为它们只需要调用适当的构造函数。此类定义可能会像这样:","category":"page"},{"location":"manual/conversion-and-promotion/","page":"类型转换和类型提升","title":"类型转换和类型提升","text":"convert(::Type{MyType}, x) = MyType(x)","category":"page"},{"location":"manual/conversion-and-promotion/","page":"类型转换和类型提升","title":"类型转换和类型提升","text":"这个方法的第一个参数的类型是Type{MyType},它的唯一实例是MyType。 因此,仅当第一个参数是类型值MyType时才会调用此方法。注意第一个参数使用的语法:在::符号之前省略参数名称,只给出类型。 这是 Julia 中指定类型但不需要通过名称引用其值的函数参数的语法。","category":"page"},{"location":"manual/conversion-and-promotion/","page":"类型转换和类型提升","title":"类型转换和类型提升","text":"某些抽象类型的所有实例默认都被认为是「足够相似的」,在 Julia Base 中也提供了通用的 convert 定义。例如,这个定义声明通过调用单参数构造函数将任何 Number 类型 convert 为其它任何 Number 类型是有效的:","category":"page"},{"location":"manual/conversion-and-promotion/","page":"类型转换和类型提升","title":"类型转换和类型提升","text":"convert(::Type{T}, x::Number) where {T<:Number} = T(x)","category":"page"},{"location":"manual/conversion-and-promotion/","page":"类型转换和类型提升","title":"类型转换和类型提升","text":"这意味着新的 Number 类型只需要定义构造函数,因为此定义将为它们处理 convert。在参数已经是所请求的类型的情况下,用恒同变换来处理 convert。","category":"page"},{"location":"manual/conversion-and-promotion/","page":"类型转换和类型提升","title":"类型转换和类型提升","text":"convert(::Type{T}, x::T) where {T<:Number} = x","category":"page"},{"location":"manual/conversion-and-promotion/","page":"类型转换和类型提升","title":"类型转换和类型提升","text":"AbstractString、AbstractArray 和 AbstractDict 也存在类似的定义。","category":"page"},{"location":"manual/conversion-and-promotion/#类型提升","page":"类型转换和类型提升","title":"类型提升","text":"","category":"section"},{"location":"manual/conversion-and-promotion/","page":"类型转换和类型提升","title":"类型转换和类型提升","text":"类型提升是指将一组混合类型的值转换为单个通用类型。尽管不是绝对必要的,但一般暗示被转换的值的通用类型可以忠实地表示所有原始值。此意义下,术语「类型提升」是合适的,因为值被转换为「更大」的类型——即能用一个通用类型表示所有输入值的类型。但重要的是,不要将它与面向对象(结构)超类或 Julia 的抽象超类型混淆:类型提升与类型层次结构无关,而与备选的表示之间的转换有关。例如,尽管每个 Int32 值可以表示为 Float64 值,但 Int32 不是 Float64 的子类型。","category":"page"},{"location":"manual/conversion-and-promotion/","page":"类型转换和类型提升","title":"类型转换和类型提升","text":"在 Julia 中,类型提升到一个通用的「更大」类型的操作是通过 promote 函数执行的,该函数接受任意数量的参数,并返回由相同数量的值组成的元组,值会被转换为一个通用类型,或在无法类型提升时抛出异常。类型提升的最常见用途是将数字参数转换为通用类型:","category":"page"},{"location":"manual/conversion-and-promotion/","page":"类型转换和类型提升","title":"类型转换和类型提升","text":"julia> promote(1, 2.5)\n(1.0, 2.5)\n\njulia> promote(1, 2.5, 3)\n(1.0, 2.5, 3.0)\n\njulia> promote(2, 3//4)\n(2//1, 3//4)\n\njulia> promote(1, 2.5, 3, 3//4)\n(1.0, 2.5, 3.0, 0.75)\n\njulia> promote(1.5, im)\n(1.5 + 0.0im, 0.0 + 1.0im)\n\njulia> promote(1 + 2im, 3//4)\n(1//1 + 2//1*im, 3//4 + 0//1*im)","category":"page"},{"location":"manual/conversion-and-promotion/","page":"类型转换和类型提升","title":"类型转换和类型提升","text":"浮点值被提升为最大的浮点参数类型。整数值会被提升为本机机器字大小或最大的整数参数类型中较大的一个。整数和浮点值的混合会被提升为一个足以包含所有值的浮点类型。与有理数混合的整数会被提升有理数。与浮点数混合的有理数会被提升为浮点数。与实数值混合的复数值会被提升为合适类型的复数值。","category":"page"},{"location":"manual/conversion-and-promotion/","page":"类型转换和类型提升","title":"类型转换和类型提升","text":"这就是使用类型提升的全部内容。剩下的只是聪明的应用,最典型的「聪明」应用是数值操作(如 +、-、* 和 /)的 catch-all 方法的定义。以下是在 promotion.jl 中给出的几个 catch-all 方法的定义:","category":"page"},{"location":"manual/conversion-and-promotion/","page":"类型转换和类型提升","title":"类型转换和类型提升","text":"+(x::Number, y::Number) = +(promote(x,y)...)\n-(x::Number, y::Number) = -(promote(x,y)...)\n*(x::Number, y::Number) = *(promote(x,y)...)\n/(x::Number, y::Number) = /(promote(x,y)...)","category":"page"},{"location":"manual/conversion-and-promotion/","page":"类型转换和类型提升","title":"类型转换和类型提升","text":"这些方法的定义表明,如果没有更特殊的规则来加、减、乘及除一对数值,则将这些值提升为通用类型并再试一次。这就是它的全部内容:在其它任何地方都不需要为数值操作担心到通用数值类型的类型提升——它会自动进行。许多算术和数学函数的 catch-all 类型提升方法的定义在 promotion.jl 中,但除此之外,Julia Base 中几乎不再需要调用 promote。promote 最常用于外部构造方法中,为了更方便,可允许使用混合类型的构造函数调用委托给一个内部构造函数,并将字段提升为适当的通用类型。例如,回想一下,rational.jl 提供了以下外部构造方法:","category":"page"},{"location":"manual/conversion-and-promotion/","page":"类型转换和类型提升","title":"类型转换和类型提升","text":"Rational(n::Integer, d::Integer) = Rational(promote(n,d)...)","category":"page"},{"location":"manual/conversion-and-promotion/","page":"类型转换和类型提升","title":"类型转换和类型提升","text":"这允许像下面这样的调用正常工作:","category":"page"},{"location":"manual/conversion-and-promotion/","page":"类型转换和类型提升","title":"类型转换和类型提升","text":"julia> x = Rational(Int8(15),Int32(-5))\n-3//1\n\njulia> typeof(x)\nRational{Int32}","category":"page"},{"location":"manual/conversion-and-promotion/","page":"类型转换和类型提升","title":"类型转换和类型提升","text":"对于大多数用户定义的类型,最好要求程序员明确地向构造函数提供期待的类型,但有时,尤其是对于数值问题,自动进行类型提升会很方便。","category":"page"},{"location":"manual/conversion-and-promotion/#定义类型提升规则","page":"类型转换和类型提升","title":"定义类型提升规则","text":"","category":"section"},{"location":"manual/conversion-and-promotion/","page":"类型转换和类型提升","title":"类型转换和类型提升","text":"虽然原则上可以直接为 promote 函数定义方法,但这需要为参数类型的所有可能排列下许多冗余的定义。相反地,promote 的行为是根据名为 promote_rule 的辅助函数定义的,该辅助函数可以为其提供方法。promote_rule 函数接受一对类型对象并返回另一个类型对象,这样参数类型的实例会被提升为被返回的类型。 因此,通过定义规则:","category":"page"},{"location":"manual/conversion-and-promotion/","page":"类型转换和类型提升","title":"类型转换和类型提升","text":"promote_rule(::Type{Float64}, ::Type{Float32}) = Float64","category":"page"},{"location":"manual/conversion-and-promotion/","page":"类型转换和类型提升","title":"类型转换和类型提升","text":"声明当同时类型提升 64 位和 32 位浮点值时,它们应该被类型提升为 64 位浮点数。但是,提升类型不需要是参数类型之一;例如,在 Julia Base 中有以下类型提升规则:","category":"page"},{"location":"manual/conversion-and-promotion/","page":"类型转换和类型提升","title":"类型转换和类型提升","text":"promote_rule(::Type{BigInt}, ::Type{Float64}) = BigFloat\npromote_rule(::Type{BigInt}, ::Type{Int8}) = BigInt","category":"page"},{"location":"manual/conversion-and-promotion/","page":"类型转换和类型提升","title":"类型转换和类型提升","text":"在后一种情况下,输出类型是 BigInt,因为 BigInt 是唯一一个足以容纳任意精度整数运算结果的类型。还要注意,不需要同时定义 promote_rule(::Type{A}, ::Type{B}) 和 promote_rule(::Type{B}, ::Type{A})——对称性隐含在类型提升过程中使用 promote_rule 的方式。","category":"page"},{"location":"manual/conversion-and-promotion/","page":"类型转换和类型提升","title":"类型转换和类型提升","text":"以 promote_rule 函数为基础定义了 promote_type 函数,在给定任意数量的类型对象时,它返回这些值作为 promote 的参数应被提升的通用类型。因此,如果想知道在没有实际值情况下,具有确定类型的一些值会被类型提升为什么类型,可以使用 promote_type:","category":"page"},{"location":"manual/conversion-and-promotion/","page":"类型转换和类型提升","title":"类型转换和类型提升","text":"julia> promote_type(Int8, Int64)\nInt64","category":"page"},{"location":"manual/conversion-and-promotion/","page":"类型转换和类型提升","title":"类型转换和类型提升","text":"在内部,promote_type 在 promote 中用于确定参数值应被转换为什么类型以便进行类型提升。但是,它本身可能是有用的。好奇的读者可以阅读 promotion.jl,该文件用大概 35 行定义了完整的类型提升规则。","category":"page"},{"location":"manual/conversion-and-promotion/#案例研究:有理数的类型提升","page":"类型转换和类型提升","title":"案例研究:有理数的类型提升","text":"","category":"section"},{"location":"manual/conversion-and-promotion/","page":"类型转换和类型提升","title":"类型转换和类型提升","text":"最后,我们来完成关于 Julia 的有理数类型的案例研究,该案例通过以下类型提升规则相对复杂地使用了类型提升机制:","category":"page"},{"location":"manual/conversion-and-promotion/","page":"类型转换和类型提升","title":"类型转换和类型提升","text":"promote_rule(::Type{Rational{T}}, ::Type{S}) where {T<:Integer,S<:Integer} = Rational{promote_type(T,S)}\npromote_rule(::Type{Rational{T}}, ::Type{Rational{S}}) where {T<:Integer,S<:Integer} = Rational{promote_type(T,S)}\npromote_rule(::Type{Rational{T}}, ::Type{S}) where {T<:Integer,S<:AbstractFloat} = promote_type(T,S)","category":"page"},{"location":"manual/conversion-and-promotion/","page":"类型转换和类型提升","title":"类型转换和类型提升","text":"第一条规则说,使用其它整数类型类型提升有理数类型会得到个有理数类型,其分子/分母类型是使用其它整数类型提升该有理数分子/分母类型的结果。第二条规则将相同的逻辑应用于两种不同的有理数类型,它们进行类型提升会得到有理数类型,其分子/分母类型是它们各自的分子/分母类型进行提升的结果。第三个也是最后一个规则规定,使用浮点数类型提升有理数类型与使用该浮点数类型提升其分子/分母类型会产生相同的类型。","category":"page"},{"location":"manual/conversion-and-promotion/","page":"类型转换和类型提升","title":"类型转换和类型提升","text":"这一小部分的类型提升规则,连同该类型的构造函数和数字的默认 convert 方法,便足以使有理数与 Julia 的其它数值类型——整数、浮点数和复数——完全自然地互操作。通过以相同的方式提供类型转换方法和类型提升规则,任何用户定义的数值类型都可像 Julia 的预定义数值类型一样自然地进行互操作。","category":"page"},{"location":"devdocs/ast/#Julia-的-AST","page":"Julia 的 AST","title":"Julia 的 AST","text":"","category":"section"},{"location":"devdocs/ast/","page":"Julia 的 AST","title":"Julia 的 AST","text":"Julia 有两种代码的表现形式。 第一种是解析器返回的表面语法 AST (例如 Meta.parse 函数),由宏来操控。是代码编写时的结构化表示,由 julia-parser.scm 用字符流构造而成。 另一种则是底层形式,或者 IR(中间表示),这种形式在进行类型推导和代码生成的时候被使用。在这种底层形式中结点的类型相对更少,所有的宏都会被展开,所有的控制流会被转化成显式的分支和语句的序列。底层的形式由 julia-syntax.scm 构建。","category":"page"},{"location":"devdocs/ast/","page":"Julia 的 AST","title":"Julia 的 AST","text":"首先,我们将关注AST,因为需要它来编写宏。","category":"page"},{"location":"devdocs/ast/#表面语法AST","page":"Julia 的 AST","title":"表面语法AST","text":"","category":"section"},{"location":"devdocs/ast/","page":"Julia 的 AST","title":"Julia 的 AST","text":"前端AST几乎由 Expr 和原子(例如 符号、数字)。 对于视觉上不同的语法形式,通常有不同的表达式头。 示例将在s-expression 语法中给出。 每个圆括号括着的列表都对应着一个 Expr,其中第一个元素是它的头部。 例如(call f x)对应于Julia中的 Expr(:call,:f,:x) 。","category":"page"},{"location":"devdocs/ast/#调用","page":"Julia 的 AST","title":"调用","text":"","category":"section"},{"location":"devdocs/ast/","page":"Julia 的 AST","title":"Julia 的 AST","text":"输入 AST\nf(x) (call f x)\nf(x, y=1, z=2) (call f x (kw y 1) (kw z 2))\nf(x; y=1) (call f (parameters (kw y 1)) x)\nf(x...) (call f (... x))","category":"page"},{"location":"devdocs/ast/","page":"Julia 的 AST","title":"Julia 的 AST","text":"do syntax:","category":"page"},{"location":"devdocs/ast/","page":"Julia 的 AST","title":"Julia 的 AST","text":"f(x) do a,b\n body\nend","category":"page"},{"location":"devdocs/ast/","page":"Julia 的 AST","title":"Julia 的 AST","text":"parses as (do (call f x) (-> (tuple a b) (block body))).","category":"page"},{"location":"devdocs/ast/#运算符","page":"Julia 的 AST","title":"运算符","text":"","category":"section"},{"location":"devdocs/ast/","page":"Julia 的 AST","title":"Julia 的 AST","text":"Most uses of operators are just function calls, so they are parsed with the head call. However some operators are special forms (not necessarily function calls), and in those cases the operator itself is the expression head. In julia-parser.scm these are referred to as \"syntactic operators\". Some operators (+ and *) use N-ary parsing; chained calls are parsed as a single N-argument call. Finally, chains of comparisons have their own special expression structure.","category":"page"},{"location":"devdocs/ast/","page":"Julia 的 AST","title":"Julia 的 AST","text":"Input AST\nx+y (call + x y)\na+b+c+d (call + a b c d)\n2x (call * 2 x)\na&&b (&& a b)\nx += 1 (+= x 1)\na ? 1 : 2 (if a 1 2)\na:b (: a b)\na:b:c (: a b c)\na,b (tuple a b)\na==b (call == a b)\n1 inlinehint,always-inline,noinline\n3 = strict-ieee (strictfp)\n4-6 = \n7 = has out-of-band info\nlinetable\nAn array of source location objects\ncodelocs\nAn array of integer indices into the linetable, giving the location associated with each statement.","category":"page"},{"location":"devdocs/ast/","page":"Julia 的 AST","title":"Julia 的 AST","text":"Optional Fields:","category":"page"},{"location":"devdocs/ast/","page":"Julia 的 AST","title":"Julia 的 AST","text":"slottypes\nAn array of types for the slots.\nrettype\nThe inferred return type of the lowered form (IR). Default value is Any.\nmethod_for_inference_limit_heuristics\nThe method_for_inference_heuristics will expand the given method's generator if necessary during inference.\nparent\nThe MethodInstance that \"owns\" this object (if applicable).\nmin_world/max_world\nThe range of world ages for which this code was valid at the time when it had been inferred.","category":"page"},{"location":"devdocs/ast/","page":"Julia 的 AST","title":"Julia 的 AST","text":"Boolean properties:","category":"page"},{"location":"devdocs/ast/","page":"Julia 的 AST","title":"Julia 的 AST","text":"inferred\nWhether this has been produced by type inference.\ninlineable\nWhether this should be eligible for inlining.\npropagate_inbounds\nWhether this should propagate @inbounds when inlined for the purpose of eliding @boundscheck blocks.\npure\nWhether this is known to be a pure function of its arguments, without respect to the state of the method caches or other mutable global state.","category":"page"},{"location":"stdlib/Printf/#man-printf","page":"Printf","title":"Printf","text":"","category":"section"},{"location":"stdlib/Printf/","page":"Printf","title":"Printf","text":"Printf.@printf\nPrintf.@sprintf","category":"page"},{"location":"stdlib/Printf/#Printf.@printf","page":"Printf","title":"Printf.@printf","text":"@printf([io::IO], \"%Fmt\", args...)\n\nPrint args using C printf style format specification string. Optionally, an IO may be passed as the first argument to redirect output.\n\nExamples\n\njulia> @printf \"Hello %s\" \"world\"\nHello world\n\njulia> @printf \"Scientific notation %e\" 1.234\nScientific notation 1.234000e+00\n\njulia> @printf \"Scientific notation three digits %.3e\" 1.23456\nScientific notation three digits 1.235e+00\n\njulia> @printf \"Decimal two digits %.2f\" 1.23456\nDecimal two digits 1.23\n\njulia> @printf \"Padded to length 5 %5i\" 123\nPadded to length 5 123\n\njulia> @printf \"Padded with zeros to length 6 %06i\" 123\nPadded with zeros to length 6 000123\n\njulia> @printf \"Use shorter of decimal or scientific %g %g\" 1.23 12300000.0\nUse shorter of decimal or scientific 1.23 1.23e+07\n\nFor a systematic specification of the format, see here. See also @sprintf.\n\nCaveats\n\nInf and NaN are printed consistently as Inf and NaN for flags %a, %A, %e, %E, %f, %F, %g, and %G. Furthermore, if a floating point number is equally close to the numeric values of two possible output strings, the output string further away from zero is chosen.\n\nExamples\n\njulia> @printf(\"%f %F %f %F\", Inf, Inf, NaN, NaN)\nInf Inf NaN NaN\n\njulia> @printf \"%.0f %.1f %f\" 0.5 0.025 -0.0078125\n0 0.0 -0.007812\n\ncompat: Julia 1.8\nStarting in Julia 1.8, %s (string) and %c (character) widths are computed using textwidth, which e.g. ignores zero-width characters (such as combining characters for diacritical marks) and treats certain \"wide\" characters (e.g. emoji) as width 2.\n\n\n\n\n\n","category":"macro"},{"location":"stdlib/Printf/#Printf.@sprintf","page":"Printf","title":"Printf.@sprintf","text":"@sprintf(\"%Fmt\", args...)\n\nReturn @printf formatted output as string.\n\nExamples\n\njulia> @sprintf \"this is a %s %15.1f\" \"test\" 34.567\n\"this is a test 34.6\"\n\n\n\n\n\n","category":"macro"},{"location":"stdlib/Test/#单元测试","page":"单元测试","title":"单元测试","text":"","category":"section"},{"location":"stdlib/Test/","page":"单元测试","title":"单元测试","text":"DocTestSetup = :(using Test)","category":"page"},{"location":"stdlib/Test/#测试-Julia-Base-库","page":"单元测试","title":"测试 Julia Base 库","text":"","category":"section"},{"location":"stdlib/Test/","page":"单元测试","title":"单元测试","text":"Julia 处于快速开发中,有着可以扩展的测试套件,用来跨平台测试功能。 如果你是通过源代码构建的 Julia ,你可以通过 make test 来运行这个测试套件。 如果是通过二进制包安装的,你可以通过 Base.runtests() 来运行这个测试套件。","category":"page"},{"location":"stdlib/Test/","page":"单元测试","title":"单元测试","text":"Base.runtests","category":"page"},{"location":"stdlib/Test/#Base.runtests","page":"单元测试","title":"Base.runtests","text":"Base.runtests(tests=[\"all\"]; ncores=ceil(Int, Sys.CPU_THREADS / 2),\n exit_on_error=false, revise=false, [seed])\n\nRun the Julia unit tests listed in tests, which can be either a string or an array of strings, using ncores processors. If exit_on_error is false, when one test fails, all remaining tests in other files will still be run; they are otherwise discarded, when exit_on_error == true. If revise is true, the Revise package is used to load any modifications to Base or to the standard libraries before running the tests. If a seed is provided via the keyword argument, it is used to seed the global RNG in the context where the tests are run; otherwise the seed is chosen randomly.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/Test/#基本的单元测试","page":"单元测试","title":"基本的单元测试","text":"","category":"section"},{"location":"stdlib/Test/","page":"单元测试","title":"单元测试","text":"The Test module provides simple unit testing functionality. Unit testing is a way to see if your code is correct by checking that the results are what you expect. It can be helpful to ensure your code still works after you make changes, and can be used when developing as a way of specifying the behaviors your code should have when complete.","category":"page"},{"location":"stdlib/Test/","page":"单元测试","title":"单元测试","text":"简单的单元测试可以通过 @test 和 @test_throws 宏来完成:","category":"page"},{"location":"stdlib/Test/","page":"单元测试","title":"单元测试","text":"Test.@test\nTest.@test_throws","category":"page"},{"location":"stdlib/Test/#Test.@test","page":"单元测试","title":"Test.@test","text":"@test ex\n@test f(args...) key=val ...\n@test ex broken=true\n@test ex skip=true\n\nTest that the expression ex evaluates to true. If executed inside a @testset, return a Pass Result if it does, a Fail Result if it is false, and an Error Result if it could not be evaluated. If executed outside a @testset, throw an exception instead of returning Fail or Error.\n\nExamples\n\njulia> @test true\nTest Passed\n\njulia> @test [1, 2] + [2, 1] == [3, 3]\nTest Passed\n\nThe @test f(args...) key=val... form is equivalent to writing @test f(args..., key=val...) which can be useful when the expression is a call using infix syntax such as approximate comparisons:\n\njulia> @test π ≈ 3.14 atol=0.01\nTest Passed\n\nThis is equivalent to the uglier test @test ≈(π, 3.14, atol=0.01). It is an error to supply more than one expression unless the first is a call expression and the rest are assignments (k=v).\n\nYou can use any key for the key=val arguments, except for broken and skip, which have special meanings in the context of @test:\n\nbroken=cond indicates a test that should pass but currently consistently fails when cond==true. Tests that the expression ex evaluates to false or causes an exception. Returns a Broken Result if it does, or an Error Result if the expression evaluates to true. Regular @test ex is evaluated when cond==false.\nskip=cond marks a test that should not be executed but should be included in test summary reporting as Broken, when cond==true. This can be useful for tests that intermittently fail, or tests of not-yet-implemented functionality. Regular @test ex is evaluated when cond==false.\n\nExamples\n\njulia> @test 2 + 2 ≈ 6 atol=1 broken=true\nTest Broken\n Expression: ≈(2 + 2, 6, atol = 1)\n\njulia> @test 2 + 2 ≈ 5 atol=1 broken=false\nTest Passed\n\njulia> @test 2 + 2 == 5 skip=true\nTest Broken\n Skipped: 2 + 2 == 5\n\njulia> @test 2 + 2 == 4 skip=false\nTest Passed\n\ncompat: Julia 1.7\nThe broken and skip keyword arguments require at least Julia 1.7.\n\n\n\n\n\n","category":"macro"},{"location":"stdlib/Test/#Test.@test_throws","page":"单元测试","title":"Test.@test_throws","text":"@test_throws exception expr\n\nTests that the expression expr throws exception. The exception may specify either a type, a string, regular expression, or list of strings occurring in the displayed error message, a matching function, or a value (which will be tested for equality by comparing fields). Note that @test_throws does not support a trailing keyword form.\n\ncompat: Julia 1.8\nThe ability to specify anything other than a type or a value as exception requires Julia v1.8 or later.\n\nExamples\n\njulia> @test_throws BoundsError [1, 2, 3][4]\nTest Passed\n Thrown: BoundsError\n\njulia> @test_throws DimensionMismatch [1, 2, 3] + [1, 2]\nTest Passed\n Thrown: DimensionMismatch\n\njulia> @test_throws \"Try sqrt(Complex\" sqrt(-1)\nTest Passed\n Message: \"DomainError with -1.0:\\nsqrt will only return a complex result if called with a complex argument. Try sqrt(Complex(x)).\"\n\nIn the final example, instead of matching a single string it could alternatively have been performed with:\n\n[\"Try\", \"Complex\"] (a list of strings)\nr\"Try sqrt\\([Cc]omplex\" (a regular expression)\nstr -> occursin(\"complex\", str) (a matching function)\n\n\n\n\n\n","category":"macro"},{"location":"stdlib/Test/","page":"单元测试","title":"单元测试","text":"例如,假设我们想要测试新的函数 foo(x) 是否按照期望的方式工作:","category":"page"},{"location":"stdlib/Test/","page":"单元测试","title":"单元测试","text":"julia> using Test\n\njulia> foo(x) = length(x)^2\nfoo (generic function with 1 method)","category":"page"},{"location":"stdlib/Test/","page":"单元测试","title":"单元测试","text":"If the condition is true, a Pass is returned:","category":"page"},{"location":"stdlib/Test/","page":"单元测试","title":"单元测试","text":"julia> @test foo(\"bar\") == 9\nTest Passed\n Expression: foo(\"bar\") == 9\n Evaluated: 9 == 9\n\njulia> @test foo(\"fizz\") >= 10\nTest Passed\n Expression: foo(\"fizz\") >= 10\n Evaluated: 16 >= 10","category":"page"},{"location":"stdlib/Test/","page":"单元测试","title":"单元测试","text":"如果条件为假,则返回 Fail 并抛出异常。","category":"page"},{"location":"stdlib/Test/","page":"单元测试","title":"单元测试","text":"julia> @test foo(\"f\") == 20\nTest Failed at none:1\n Expression: foo(\"f\") == 20\n Evaluated: 1 == 20\nERROR: There was an error during testing","category":"page"},{"location":"stdlib/Test/","page":"单元测试","title":"单元测试","text":"If the condition could not be evaluated because an exception was thrown, which occurs in this case because length is not defined for symbols, an Error object is returned and an exception is thrown:","category":"page"},{"location":"stdlib/Test/","page":"单元测试","title":"单元测试","text":"julia> @test foo(:cat) == 1\nError During Test\n Test threw an exception of type MethodError\n Expression: foo(:cat) == 1\n MethodError: no method matching length(::Symbol)\n Closest candidates are:\n length(::SimpleVector) at essentials.jl:256\n length(::Base.MethodList) at reflection.jl:521\n length(::MethodTable) at reflection.jl:597\n ...\n Stacktrace:\n [...]\nERROR: There was an error during testing","category":"page"},{"location":"stdlib/Test/","page":"单元测试","title":"单元测试","text":"If we expect that evaluating an expression should throw an exception, then we can use @test_throws to check that this occurs:","category":"page"},{"location":"stdlib/Test/","page":"单元测试","title":"单元测试","text":"julia> @test_throws MethodError foo(:cat)\nTest Passed\n Expression: foo(:cat)\n Thrown: MethodError","category":"page"},{"location":"stdlib/Test/#Working-with-Test-Sets","page":"单元测试","title":"Working with Test Sets","text":"","category":"section"},{"location":"stdlib/Test/","page":"单元测试","title":"单元测试","text":"Typically a large number of tests are used to make sure functions work correctly over a range of inputs. In the event a test fails, the default behavior is to throw an exception immediately. However, it is normally preferable to run the rest of the tests first to get a better picture of how many errors there are in the code being tested.","category":"page"},{"location":"stdlib/Test/","page":"单元测试","title":"单元测试","text":"note: Note\nThe @testset will create a local scope of its own when running the tests in it.","category":"page"},{"location":"stdlib/Test/","page":"单元测试","title":"单元测试","text":"The @testset macro can be used to group tests into sets. All the tests in a test set will be run, and at the end of the test set a summary will be printed. If any of the tests failed, or could not be evaluated due to an error, the test set will then throw a TestSetException.","category":"page"},{"location":"stdlib/Test/","page":"单元测试","title":"单元测试","text":"Test.@testset\nTest.TestSetException","category":"page"},{"location":"stdlib/Test/#Test.@testset","page":"单元测试","title":"Test.@testset","text":"@testset [CustomTestSet] [option=val ...] [\"description\"] begin ... end\n@testset [CustomTestSet] [option=val ...] [\"description $v\"] for v in (...) ... end\n@testset [CustomTestSet] [option=val ...] [\"description $v, $w\"] for v in (...), w in (...) ... end\n@testset [CustomTestSet] [option=val ...] [\"description $v, $w\"] foo()\n\nStarts a new test set, or multiple test sets if a for loop is provided.\n\nIf no custom testset type is given it defaults to creating a DefaultTestSet. DefaultTestSet records all the results and, if there are any Fails or Errors, throws an exception at the end of the top-level (non-nested) test set, along with a summary of the test results.\n\nAny custom testset type (subtype of AbstractTestSet) can be given and it will also be used for any nested @testset invocations. The given options are only applied to the test set where they are given. The default test set type accepts two boolean options:\n\nverbose: if true, the result summary of the nested testsets is shown even\n\nwhen they all pass (the default is false).\n\nshowtiming: if true, the duration of each displayed testset is shown\n\n(the default is true).\n\ncompat: Julia 1.8\n@testset foo() requires at least Julia 1.8.\n\nThe description string accepts interpolation from the loop indices. If no description is provided, one is constructed based on the variables. If a function call is provided, its name will be used. Explicit description strings override this behavior.\n\nBy default the @testset macro will return the testset object itself, though this behavior can be customized in other testset types. If a for loop is used then the macro collects and returns a list of the return values of the finish method, which by default will return a list of the testset objects used in each iteration.\n\nBefore the execution of the body of a @testset, there is an implicit call to Random.seed!(seed) where seed is the current seed of the global RNG. Moreover, after the execution of the body, the state of the global RNG is restored to what it was before the @testset. This is meant to ease reproducibility in case of failure, and to allow seamless re-arrangements of @testsets regardless of their side-effect on the global RNG state.\n\nExamples\n\njulia> @testset \"trigonometric identities\" begin\n θ = 2/3*π\n @test sin(-θ) ≈ -sin(θ)\n @test cos(-θ) ≈ cos(θ)\n @test sin(2θ) ≈ 2*sin(θ)*cos(θ)\n @test cos(2θ) ≈ cos(θ)^2 - sin(θ)^2\n end;\nTest Summary: | Pass Total Time\ntrigonometric identities | 4 4 0.2s\n\n\n\n\n\n","category":"macro"},{"location":"stdlib/Test/#Test.TestSetException","page":"单元测试","title":"Test.TestSetException","text":"TestSetException\n\nThrown when a test set finishes and not all tests passed.\n\n\n\n\n\n","category":"type"},{"location":"stdlib/Test/","page":"单元测试","title":"单元测试","text":"We can put our tests for the foo(x) function in a test set:","category":"page"},{"location":"stdlib/Test/","page":"单元测试","title":"单元测试","text":"julia> @testset \"Foo Tests\" begin\n @test foo(\"a\") == 1\n @test foo(\"ab\") == 4\n @test foo(\"abc\") == 9\n end;\nTest Summary: | Pass Total\nFoo Tests | 3 3","category":"page"},{"location":"stdlib/Test/","page":"单元测试","title":"单元测试","text":"测试集可以嵌套:","category":"page"},{"location":"stdlib/Test/","page":"单元测试","title":"单元测试","text":"julia> @testset \"Foo Tests\" begin\n @testset \"Animals\" begin\n @test foo(\"cat\") == 9\n @test foo(\"dog\") == foo(\"cat\")\n end\n @testset \"Arrays $i\" for i in 1:3\n @test foo(zeros(i)) == i^2\n @test foo(fill(1.0, i)) == i^2\n end\n end;\nTest Summary: | Pass Total\nFoo Tests | 8 8","category":"page"},{"location":"stdlib/Test/","page":"单元测试","title":"单元测试","text":"In the event that a nested test set has no failures, as happened here, it will be hidden in the summary, unless the verbose=true option is passed:","category":"page"},{"location":"stdlib/Test/","page":"单元测试","title":"单元测试","text":"julia> @testset verbose = true \"Foo Tests\" begin\n @testset \"Animals\" begin\n @test foo(\"cat\") == 9\n @test foo(\"dog\") == foo(\"cat\")\n end\n @testset \"Arrays $i\" for i in 1:3\n @test foo(zeros(i)) == i^2\n @test foo(fill(1.0, i)) == i^2\n end\n end;\nTest Summary: | Pass Total\nFoo Tests | 8 8\n Animals | 2 2\n Arrays 1 | 2 2\n Arrays 2 | 2 2\n Arrays 3 | 2 2","category":"page"},{"location":"stdlib/Test/","page":"单元测试","title":"单元测试","text":"If we do have a test failure, only the details for the failed test sets will be shown:","category":"page"},{"location":"stdlib/Test/","page":"单元测试","title":"单元测试","text":"julia> @testset \"Foo Tests\" begin\n @testset \"Animals\" begin\n @testset \"Felines\" begin\n @test foo(\"cat\") == 9\n end\n @testset \"Canines\" begin\n @test foo(\"dog\") == 9\n end\n end\n @testset \"Arrays\" begin\n @test foo(zeros(2)) == 4\n @test foo(fill(1.0, 4)) == 15\n end\n end\n\nArrays: Test Failed\n Expression: foo(fill(1.0, 4)) == 15\n Evaluated: 16 == 15\n[...]\nTest Summary: | Pass Fail Total\nFoo Tests | 3 1 4\n Animals | 2 2\n Arrays | 1 1 2\nERROR: Some tests did not pass: 3 passed, 1 failed, 0 errored, 0 broken.","category":"page"},{"location":"stdlib/Test/#Other-Test-Macros","page":"单元测试","title":"Other Test Macros","text":"","category":"section"},{"location":"stdlib/Test/","page":"单元测试","title":"单元测试","text":"As calculations on floating-point values can be imprecise, you can perform approximate equality checks using either @test a ≈ b (where ≈, typed via tab completion of \\approx, is the isapprox function) or use isapprox directly.","category":"page"},{"location":"stdlib/Test/","page":"单元测试","title":"单元测试","text":"julia> @test 1 ≈ 0.999999999\nTest Passed\n Expression: 1 ≈ 0.999999999\n Evaluated: 1 ≈ 0.999999999\n\njulia> @test 1 ≈ 0.999999\nTest Failed at none:1\n Expression: 1 ≈ 0.999999\n Evaluated: 1 ≈ 0.999999\nERROR: There was an error during testing","category":"page"},{"location":"stdlib/Test/","page":"单元测试","title":"单元测试","text":"You can specify relative and absolute tolerances by setting the rtol and atol keyword arguments of isapprox, respectively, after the ≈ comparison:","category":"page"},{"location":"stdlib/Test/","page":"单元测试","title":"单元测试","text":"julia> @test 1 ≈ 0.999999 rtol=1e-5\nTest Passed\n Expression: ≈(1, 0.999999, rtol = 1.0e-5)\n Evaluated: ≈(1, 0.999999; rtol = 1.0e-5)","category":"page"},{"location":"stdlib/Test/","page":"单元测试","title":"单元测试","text":"Note that this is not a specific feature of the ≈ but rather a general feature of the @test macro: @test a b key=val is transformed by the macro into @test op(a, b, key=val). It is, however, particularly useful for ≈ tests.","category":"page"},{"location":"stdlib/Test/","page":"单元测试","title":"单元测试","text":"Test.@inferred\nTest.@test_logs\nTest.@test_deprecated\nTest.@test_warn\nTest.@test_nowarn","category":"page"},{"location":"stdlib/Test/#Test.@inferred","page":"单元测试","title":"Test.@inferred","text":"@inferred [AllowedType] f(x)\n\nTests that the call expression f(x) returns a value of the same type inferred by the compiler. It is useful to check for type stability.\n\nf(x) can be any call expression. Returns the result of f(x) if the types match, and an Error Result if it finds different types.\n\nOptionally, AllowedType relaxes the test, by making it pass when either the type of f(x) matches the inferred type modulo AllowedType, or when the return type is a subtype of AllowedType. This is useful when testing type stability of functions returning a small union such as Union{Nothing, T} or Union{Missing, T}.\n\njulia> f(a) = a > 1 ? 1 : 1.0\nf (generic function with 1 method)\n\njulia> typeof(f(2))\nInt64\n\njulia> @code_warntype f(2)\nMethodInstance for f(::Int64)\n from f(a) in Main at none:1\nArguments\n #self#::Core.Const(f)\n a::Int64\nBody::UNION{FLOAT64, INT64}\n1 ─ %1 = (a > 1)::Bool\n└── goto #3 if not %1\n2 ─ return 1\n3 ─ return 1.0\n\njulia> @inferred f(2)\nERROR: return type Int64 does not match inferred return type Union{Float64, Int64}\n[...]\n\njulia> @inferred max(1, 2)\n2\n\njulia> g(a) = a < 10 ? missing : 1.0\ng (generic function with 1 method)\n\njulia> @inferred g(20)\nERROR: return type Float64 does not match inferred return type Union{Missing, Float64}\n[...]\n\njulia> @inferred Missing g(20)\n1.0\n\njulia> h(a) = a < 10 ? missing : f(a)\nh (generic function with 1 method)\n\njulia> @inferred Missing h(20)\nERROR: return type Int64 does not match inferred return type Union{Missing, Float64, Int64}\n[...]\n\n\n\n\n\n","category":"macro"},{"location":"stdlib/Test/#Test.@test_logs","page":"单元测试","title":"Test.@test_logs","text":"@test_logs [log_patterns...] [keywords] expression\n\nCollect a list of log records generated by expression using collect_test_logs, check that they match the sequence log_patterns, and return the value of expression. The keywords provide some simple filtering of log records: the min_level keyword controls the minimum log level which will be collected for the test, the match_mode keyword defines how matching will be performed (the default :all checks that all logs and patterns match pairwise; use :any to check that the pattern matches at least once somewhere in the sequence.)\n\nThe most useful log pattern is a simple tuple of the form (level,message). A different number of tuple elements may be used to match other log metadata, corresponding to the arguments to passed to AbstractLogger via the handle_message function: (level,message,module,group,id,file,line). Elements which are present will be matched pairwise with the log record fields using == by default, with the special cases that Symbols may be used for the standard log levels, and Regexs in the pattern will match string or Symbol fields using occursin.\n\nExamples\n\nConsider a function which logs a warning, and several debug messages:\n\nfunction foo(n)\n @info \"Doing foo with n=$n\"\n for i=1:n\n @debug \"Iteration $i\"\n end\n 42\nend\n\nWe can test the info message using\n\n@test_logs (:info,\"Doing foo with n=2\") foo(2)\n\nIf we also wanted to test the debug messages, these need to be enabled with the min_level keyword:\n\nusing Logging\n@test_logs (:info,\"Doing foo with n=2\") (:debug,\"Iteration 1\") (:debug,\"Iteration 2\") min_level=Logging.Debug foo(2)\n\nIf you want to test that some particular messages are generated while ignoring the rest, you can set the keyword match_mode=:any:\n\nusing Logging\n@test_logs (:info,) (:debug,\"Iteration 42\") min_level=Logging.Debug match_mode=:any foo(100)\n\nThe macro may be chained with @test to also test the returned value:\n\n@test (@test_logs (:info,\"Doing foo with n=2\") foo(2)) == 42\n\nIf you want to test for the absence of warnings, you can omit specifying log patterns and set the min_level accordingly:\n\n# test that the expression logs no messages when the logger level is warn:\n@test_logs min_level=Logging.Warn @info(\"Some information\") # passes\n@test_logs min_level=Logging.Warn @warn(\"Some information\") # fails\n\nIf you want to test the absence of warnings (or error messages) in stderr which are not generated by @warn, see @test_nowarn.\n\n\n\n\n\n","category":"macro"},{"location":"stdlib/Test/#Test.@test_deprecated","page":"单元测试","title":"Test.@test_deprecated","text":"@test_deprecated [pattern] expression\n\nWhen --depwarn=yes, test that expression emits a deprecation warning and return the value of expression. The log message string will be matched against pattern which defaults to r\"deprecated\"i.\n\nWhen --depwarn=no, simply return the result of executing expression. When --depwarn=error, check that an ErrorException is thrown.\n\nExamples\n\n# Deprecated in julia 0.7\n@test_deprecated num2hex(1)\n\n# The returned value can be tested by chaining with @test:\n@test (@test_deprecated num2hex(1)) == \"0000000000000001\"\n\n\n\n\n\n","category":"macro"},{"location":"stdlib/Test/#Test.@test_warn","page":"单元测试","title":"Test.@test_warn","text":"@test_warn msg expr\n\nTest whether evaluating expr results in stderr output that contains the msg string or matches the msg regular expression. If msg is a boolean function, tests whether msg(output) returns true. If msg is a tuple or array, checks that the error output contains/matches each item in msg. Returns the result of evaluating expr.\n\nSee also @test_nowarn to check for the absence of error output.\n\nNote: Warnings generated by @warn cannot be tested with this macro. Use @test_logs instead.\n\n\n\n\n\n","category":"macro"},{"location":"stdlib/Test/#Test.@test_nowarn","page":"单元测试","title":"Test.@test_nowarn","text":"@test_nowarn expr\n\nTest whether evaluating expr results in empty stderr output (no warnings or other messages). Returns the result of evaluating expr.\n\nNote: The absence of warnings generated by @warn cannot be tested with this macro. Use @test_logs instead.\n\n\n\n\n\n","category":"macro"},{"location":"stdlib/Test/#Broken-Tests","page":"单元测试","title":"Broken Tests","text":"","category":"section"},{"location":"stdlib/Test/","page":"单元测试","title":"单元测试","text":"If a test fails consistently it can be changed to use the @test_broken macro. This will denote the test as Broken if the test continues to fail and alerts the user via an Error if the test succeeds.","category":"page"},{"location":"stdlib/Test/","page":"单元测试","title":"单元测试","text":"Test.@test_broken","category":"page"},{"location":"stdlib/Test/#Test.@test_broken","page":"单元测试","title":"Test.@test_broken","text":"@test_broken ex\n@test_broken f(args...) key=val ...\n\nIndicates a test that should pass but currently consistently fails. Tests that the expression ex evaluates to false or causes an exception. Returns a Broken Result if it does, or an Error Result if the expression evaluates to true. This is equivalent to @test ex broken=true.\n\nThe @test_broken f(args...) key=val... form works as for the @test macro.\n\nExamples\n\njulia> @test_broken 1 == 2\nTest Broken\n Expression: 1 == 2\n\njulia> @test_broken 1 == 2 atol=0.1\nTest Broken\n Expression: ==(1, 2, atol = 0.1)\n\n\n\n\n\n","category":"macro"},{"location":"stdlib/Test/","page":"单元测试","title":"单元测试","text":"@test_skip is also available to skip a test without evaluation, but counting the skipped test in the test set reporting. The test will not run but gives a Broken Result.","category":"page"},{"location":"stdlib/Test/","page":"单元测试","title":"单元测试","text":"Test.@test_skip","category":"page"},{"location":"stdlib/Test/#Test.@test_skip","page":"单元测试","title":"Test.@test_skip","text":"@test_skip ex\n@test_skip f(args...) key=val ...\n\nMarks a test that should not be executed but should be included in test summary reporting as Broken. This can be useful for tests that intermittently fail, or tests of not-yet-implemented functionality. This is equivalent to @test ex skip=true.\n\nThe @test_skip f(args...) key=val... form works as for the @test macro.\n\nExamples\n\njulia> @test_skip 1 == 2\nTest Broken\n Skipped: 1 == 2\n\njulia> @test_skip 1 == 2 atol=0.1\nTest Broken\n Skipped: ==(1, 2, atol = 0.1)\n\n\n\n\n\n","category":"macro"},{"location":"stdlib/Test/#Creating-Custom-AbstractTestSet-Types","page":"单元测试","title":"Creating Custom AbstractTestSet Types","text":"","category":"section"},{"location":"stdlib/Test/","page":"单元测试","title":"单元测试","text":"Packages can create their own AbstractTestSet subtypes by implementing the record and finish methods. The subtype should have a one-argument constructor taking a description string, with any options passed in as keyword arguments.","category":"page"},{"location":"stdlib/Test/","page":"单元测试","title":"单元测试","text":"Test.record\nTest.finish","category":"page"},{"location":"stdlib/Test/#Test.record","page":"单元测试","title":"Test.record","text":"record(ts::AbstractTestSet, res::Result)\n\nRecord a result to a testset. This function is called by the @testset infrastructure each time a contained @test macro completes, and is given the test result (which could be an Error). This will also be called with an Error if an exception is thrown inside the test block but outside of a @test context.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/Test/#Test.finish","page":"单元测试","title":"Test.finish","text":"finish(ts::AbstractTestSet)\n\nDo any final processing necessary for the given testset. This is called by the @testset infrastructure after a test block executes.\n\nCustom AbstractTestSet subtypes should call record on their parent (if there is one) to add themselves to the tree of test results. This might be implemented as:\n\nif get_testset_depth() != 0\n # Attach this test set to the parent test set\n parent_ts = get_testset()\n record(parent_ts, self)\n return self\nend\n\n\n\n\n\n","category":"function"},{"location":"stdlib/Test/","page":"单元测试","title":"单元测试","text":"Test takes responsibility for maintaining a stack of nested testsets as they are executed, but any result accumulation is the responsibility of the AbstractTestSet subtype. You can access this stack with the get_testset and get_testset_depth methods. Note that these functions are not exported.","category":"page"},{"location":"stdlib/Test/","page":"单元测试","title":"单元测试","text":"Test.get_testset\nTest.get_testset_depth","category":"page"},{"location":"stdlib/Test/#Test.get_testset","page":"单元测试","title":"Test.get_testset","text":"get_testset()\n\nRetrieve the active test set from the task's local storage. If no test set is active, use the fallback default test set.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/Test/#Test.get_testset_depth","page":"单元测试","title":"Test.get_testset_depth","text":"get_testset_depth()\n\nReturns the number of active test sets, not including the default test set\n\n\n\n\n\n","category":"function"},{"location":"stdlib/Test/","page":"单元测试","title":"单元测试","text":"Test also makes sure that nested @testset invocations use the same AbstractTestSet subtype as their parent unless it is set explicitly. It does not propagate any properties of the testset. Option inheritance behavior can be implemented by packages using the stack infrastructure that Test provides.","category":"page"},{"location":"stdlib/Test/","page":"单元测试","title":"单元测试","text":"Defining a basic AbstractTestSet subtype might look like:","category":"page"},{"location":"stdlib/Test/","page":"单元测试","title":"单元测试","text":"import Test: Test, record, finish\nusing Test: AbstractTestSet, Result, Pass, Fail, Error\nusing Test: get_testset_depth, get_testset\nstruct CustomTestSet <: Test.AbstractTestSet\n description::AbstractString\n foo::Int\n results::Vector\n # constructor takes a description string and options keyword arguments\n CustomTestSet(desc; foo=1) = new(desc, foo, [])\nend\n\nrecord(ts::CustomTestSet, child::AbstractTestSet) = push!(ts.results, child)\nrecord(ts::CustomTestSet, res::Result) = push!(ts.results, res)\nfunction finish(ts::CustomTestSet)\n # just record if we're not the top-level parent\n if get_testset_depth() > 0\n record(get_testset(), ts)\n end\n ts\nend","category":"page"},{"location":"stdlib/Test/","page":"单元测试","title":"单元测试","text":"And using that testset looks like:","category":"page"},{"location":"stdlib/Test/","page":"单元测试","title":"单元测试","text":"@testset CustomTestSet foo=4 \"custom testset inner 2\" begin\n # this testset should inherit the type, but not the argument.\n @testset \"custom testset inner\" begin\n @test true\n end\nend","category":"page"},{"location":"stdlib/Test/#Test-utilities","page":"单元测试","title":"Test utilities","text":"","category":"section"},{"location":"stdlib/Test/","page":"单元测试","title":"单元测试","text":"Test.GenericArray\nTest.GenericDict\nTest.GenericOrder\nTest.GenericSet\nTest.GenericString\nTest.detect_ambiguities\nTest.detect_unbound_args","category":"page"},{"location":"stdlib/Test/#Test.GenericArray","page":"单元测试","title":"Test.GenericArray","text":"The GenericArray can be used to test generic array APIs that program to the AbstractArray interface, in order to ensure that functions can work with array types besides the standard Array type.\n\n\n\n\n\n","category":"type"},{"location":"stdlib/Test/#Test.GenericDict","page":"单元测试","title":"Test.GenericDict","text":"The GenericDict can be used to test generic dict APIs that program to the AbstractDict interface, in order to ensure that functions can work with associative types besides the standard Dict type.\n\n\n\n\n\n","category":"type"},{"location":"stdlib/Test/#Test.GenericOrder","page":"单元测试","title":"Test.GenericOrder","text":"The GenericOrder can be used to test APIs for their support of generic ordered types.\n\n\n\n\n\n","category":"type"},{"location":"stdlib/Test/#Test.GenericSet","page":"单元测试","title":"Test.GenericSet","text":"The GenericSet can be used to test generic set APIs that program to the AbstractSet interface, in order to ensure that functions can work with set types besides the standard Set and BitSet types.\n\n\n\n\n\n","category":"type"},{"location":"stdlib/Test/#Test.GenericString","page":"单元测试","title":"Test.GenericString","text":"The GenericString can be used to test generic string APIs that program to the AbstractString interface, in order to ensure that functions can work with string types besides the standard String type.\n\n\n\n\n\n","category":"type"},{"location":"stdlib/Test/#Test.detect_ambiguities","page":"单元测试","title":"Test.detect_ambiguities","text":"detect_ambiguities(mod1, mod2...; recursive=false,\n ambiguous_bottom=false,\n allowed_undefineds=nothing)\n\nReturns a vector of (Method,Method) pairs of ambiguous methods defined in the specified modules. Use recursive=true to test in all submodules.\n\nambiguous_bottom controls whether ambiguities triggered only by Union{} type parameters are included; in most cases you probably want to set this to false. See Base.isambiguous.\n\nSee Test.detect_unbound_args for an explanation of allowed_undefineds.\n\ncompat: Julia 1.8\nallowed_undefineds requires at least Julia 1.8.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/Test/#Test.detect_unbound_args","page":"单元测试","title":"Test.detect_unbound_args","text":"detect_unbound_args(mod1, mod2...; recursive=false, allowed_undefineds=nothing)\n\nReturns a vector of Methods which may have unbound type parameters. Use recursive=true to test in all submodules.\n\nBy default, any undefined symbols trigger a warning. This warning can be suppressed by supplying a collection of GlobalRefs for which the warning can be skipped. For example, setting\n\nallow_undefineds = Set([GlobalRef(Base, :active_repl),\n GlobalRef(Base, :active_repl_backend)])\n\nwould suppress warnings about Base.active_repl and Base.active_repl_backend.\n\ncompat: Julia 1.8\nallowed_undefineds requires at least Julia 1.8.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/Test/","page":"单元测试","title":"单元测试","text":"DocTestSetup = nothing","category":"page"},{"location":"manual/interfaces/#接口","page":"接口","title":"接口","text":"","category":"section"},{"location":"manual/interfaces/","page":"接口","title":"接口","text":"Julia 的很多能力和扩展性都来自于一些非正式的接口。通过为自定义的类型扩展一些特定的方法,自定义类型的对象不但获得那些方法的功能,而且也能够用于其它的基于那些行为而定义的通用方法中。","category":"page"},{"location":"manual/interfaces/#man-interface-iteration","page":"接口","title":"迭代","text":"","category":"section"},{"location":"manual/interfaces/","page":"接口","title":"接口","text":"必需方法 简短描述\niterate(iter) 通常返回由第一项及其初始状态组成的元组,但如果为空,则返回 nothing\niterate(iter, state) 通常返回由下一项及其状态组成的元组,或者在没有下一项存在时返回 nothing。\n重要可选方法 默认定义 简短描述\nIteratorSize(IterType) HasLength() HasLength(),HasShape{N}(),IsInfinite() 或者 SizeUnknown() 中合适的一个\nIteratorEltype(IterType) HasEltype() EltypeUnknown() 或 HasEltype() 中合适的一个\neltype(IterType) Any 由 iterate() 返回元组中第一项的类型。\nlength(iter) (未定义) 项数,如果已知\nsize(iter, [dim]) (未定义) 在各个维度上项数,如果已知","category":"page"},{"location":"manual/interfaces/","page":"接口","title":"接口","text":"由 IteratorSize(IterType) 返回的值 必需方法\nHasLength() length(iter)\nHasShape{N}() length(iter) 和 size(iter, [dim])\nIsInfinite() (无)\nSizeUnknown() (无)","category":"page"},{"location":"manual/interfaces/","page":"接口","title":"接口","text":"由 IteratorEltype(IterType) 返回的值 必需方法\nHasEltype() eltype(IterType)\nEltypeUnknown() (none)","category":"page"},{"location":"manual/interfaces/","page":"接口","title":"接口","text":"顺序迭代由 iterate 函数实现。 Julia 的迭代器可以从对象外部跟踪迭代状态,而不是在迭代过程中改变对象本身。 迭代过程中的返回一个包含了当前迭代值及其状态的元组,或者在没有元素存在的情况下返回 nothing。 状态对象将在下一次迭代时传递回 iterate 函数,并且通常被认为是可迭代对象的私有实现细节。","category":"page"},{"location":"manual/interfaces/","page":"接口","title":"接口","text":"任何定义了这个函数的对象都是可迭代的,并且可以被应用到许多依赖迭代的函数上 。 也可以直接被应用到 for 循环中,因为根据语法:","category":"page"},{"location":"manual/interfaces/","page":"接口","title":"接口","text":"for item in iter # or \"for item = iter\"\n # body\nend","category":"page"},{"location":"manual/interfaces/","page":"接口","title":"接口","text":"以上代码被解释为:","category":"page"},{"location":"manual/interfaces/","page":"接口","title":"接口","text":"next = iterate(iter)\nwhile next !== nothing\n (item, state) = next\n # body\n next = iterate(iter, state)\nend","category":"page"},{"location":"manual/interfaces/","page":"接口","title":"接口","text":"举一个简单的例子:一组定长数据的平方数迭代序列:","category":"page"},{"location":"manual/interfaces/","page":"接口","title":"接口","text":"julia> struct Squares\n count::Int\n end\n\njulia> Base.iterate(S::Squares, state=1) = state > S.count ? nothing : (state*state, state+1)","category":"page"},{"location":"manual/interfaces/","page":"接口","title":"接口","text":"仅仅定义了 iterate 函数的 Squares 类型就已经很强大了。 我们现在可以迭代所有的元素了:","category":"page"},{"location":"manual/interfaces/","page":"接口","title":"接口","text":"julia> for item in Squares(7)\n println(item)\n end\n1\n4\n9\n16\n25\n36\n49","category":"page"},{"location":"manual/interfaces/","page":"接口","title":"接口","text":"我们可以利用许多内置方法来处理迭代,比如标准库 Statistics 中的 in,mean 和 std 。","category":"page"},{"location":"manual/interfaces/","page":"接口","title":"接口","text":"julia> 25 in Squares(10)\ntrue\n\njulia> using Statistics\n\njulia> mean(Squares(100))\n3383.5\n\njulia> std(Squares(100))\n3024.355854282583","category":"page"},{"location":"manual/interfaces/","page":"接口","title":"接口","text":"我们可以扩展一些其它的方法,为 Julia 提供有关此可迭代集合的更多信息。我们知道 Squares 序列中的元素总是 Int 型的。通过扩展 eltype 方法,我们可以给 Julia 更多信息来帮助其在更复杂的方法中生成更具体的代码。我们同时也知道该序列中的元素数目,故同样地也可以扩展 length:","category":"page"},{"location":"manual/interfaces/","page":"接口","title":"接口","text":"julia> Base.eltype(::Type{Squares}) = Int # Note that this is defined for the type\n\njulia> Base.length(S::Squares) = S.count","category":"page"},{"location":"manual/interfaces/","page":"接口","title":"接口","text":"现在,当我们让 Julia 去 collect 所有元素到一个数组中时,Julia 可以预分配一个适当大小的 Vector{Int},而不是朴素地 push! 每一个元素到 Vector{Any}:","category":"page"},{"location":"manual/interfaces/","page":"接口","title":"接口","text":"julia> collect(Squares(4))\n4-element Vector{Int64}:\n 1\n 4\n 9\n 16","category":"page"},{"location":"manual/interfaces/","page":"接口","title":"接口","text":"尽管大多时候我们都可以依赖一些通用的实现,但某些时候,如果我们知道一个更简单的算法,可以用其扩展具体方法。例如,计算平方和有公式,因此可以扩展出一个更高效的解法来替代通用方法:","category":"page"},{"location":"manual/interfaces/","page":"接口","title":"接口","text":"julia> Base.sum(S::Squares) = (n = S.count; return n*(n+1)*(2n+1)÷6)\n\njulia> sum(Squares(1803))\n1955361914","category":"page"},{"location":"manual/interfaces/","page":"接口","title":"接口","text":"这种模式在 Julia Base 中很常见,一些必须实现的方法构成了一个小的集合,从而定义出一个非正式的接口,用于实现一些更加炫酷的操作。某些应用场景中,一些类型有更高效的算法,故可以扩展出额外的专用方法。","category":"page"},{"location":"manual/interfaces/","page":"接口","title":"接口","text":"能以逆序迭代集合也很有用,这可由 Iterators.reverse(iterator) 迭代实现。但是,为了实际支持逆序迭代,迭代器类型 T 需要为 Iterators.Reverse{T} 实现 iterate。(给定 r::Iterators.Reverse{T},类型 T 的底层迭代器是 r.itr。)在我们的 Squares 示例中,我们可以实现 Iterators.Reverse{Squares} 方法:","category":"page"},{"location":"manual/interfaces/","page":"接口","title":"接口","text":"julia> Base.iterate(rS::Iterators.Reverse{Squares}, state=rS.itr.count) = state < 1 ? nothing : (state*state, state-1)\n\njulia> collect(Iterators.reverse(Squares(4)))\n4-element Vector{Int64}:\n 16\n 9\n 4\n 1","category":"page"},{"location":"manual/interfaces/#Indexing","page":"接口","title":"Indexing","text":"","category":"section"},{"location":"manual/interfaces/","page":"接口","title":"接口","text":"Methods to implement Brief description\ngetindex(X, i) X[i], indexed element access\nsetindex!(X, v, i) X[i] = v, indexed assignment\nfirstindex(X) The first index, used in X[begin]\nlastindex(X) The last index, used in X[end]","category":"page"},{"location":"manual/interfaces/","page":"接口","title":"接口","text":"For the Squares iterable above, we can easily compute the ith element of the sequence by squaring it. We can expose this as an indexing expression S[i]. To opt into this behavior, Squares simply needs to define getindex:","category":"page"},{"location":"manual/interfaces/","page":"接口","title":"接口","text":"julia> function Base.getindex(S::Squares, i::Int)\n 1 <= i <= S.count || throw(BoundsError(S, i))\n return i*i\n end\n\njulia> Squares(100)[23]\n529","category":"page"},{"location":"manual/interfaces/","page":"接口","title":"接口","text":"另外,为了支持语法 S[begin] 和 S[end],我们必须定义 lastindex 来指定最后一个有效索引。建议也定义 firstindex 来指定第一个有效索引:","category":"page"},{"location":"manual/interfaces/","page":"接口","title":"接口","text":"julia> Base.firstindex(S::Squares) = 1\n\njulia> Base.lastindex(S::Squares) = length(S)\n\njulia> Squares(23)[end]\n529","category":"page"},{"location":"manual/interfaces/","page":"接口","title":"接口","text":"对多维的 begin/end索引,例如,像是 a[3, begin, 7],你应该定义 firstindex(a, dim) 和 lastindex(a, dim)(它们默认各自在 axes(a, dim) 上调用 first和last)","category":"page"},{"location":"manual/interfaces/","page":"接口","title":"接口","text":"注意,上面只定义了一个整数索引的 getindex 方法,用除一个整数之外的其它东西索引会抛出MethodError,因为现在还没有匹配的方法。为了支持 Int 的范围或向量索引,必须另外写一个方法:","category":"page"},{"location":"manual/interfaces/","page":"接口","title":"接口","text":"julia> Base.getindex(S::Squares, i::Number) = S[convert(Int, i)]\n\njulia> Base.getindex(S::Squares, I) = [S[i] for i in I]\n\njulia> Squares(10)[[3,4.,5]]\n3-element Vector{Int64}:\n 9\n 16\n 25","category":"page"},{"location":"manual/interfaces/","page":"接口","title":"接口","text":"虽然这开始支持更多某些内置类型支持的索引操作,但仍然有很多行为不支持。因为我们为 Squares 序列所添加的行为,它开始看起来越来越像向量。我们可以正式定义其为 AbstractArray 的子类型,而不是自己定义所有这些行为。","category":"page"},{"location":"manual/interfaces/#man-interface-array","page":"接口","title":"抽象数组","text":"","category":"section"},{"location":"manual/interfaces/","page":"接口","title":"接口","text":"需要实现的方法 简短描述\nsize(A) 返回包含 A 各维度大小的元组\ngetindex(A, i::Int) (若为 IndexLinear)线性标量索引\ngetindex(A, I::Vararg{Int, N}) (若为 IndexCartesian,其中 N = ndims(A))N 维标量索引\nsetindex!(A, v, i::Int) (若为 IndexLinear)线性索引元素赋值\nsetindex!(A, v, I::Vararg{Int, N}) (若为 IndexCartesian,其中 N = ndims(A))N 维标量索引元素赋值\n可选方法 默认定义 简短描述\nIndexStyle(::Type) IndexCartesian() 返回 IndexLinear() 或 IndexCartesian()。请参阅下文描述。\ngetindex(A, I...) 基于标量 getindex 定义 多维非标量索引\nsetindex!(A, X, I...) 基于标量 setindex! 定义 多维非标量索引元素赋值\niterate 基于标量 getindex 定义 Iteration\nlength(A) prod(size(A)) 元素数\nsimilar(A) similar(A, eltype(A), size(A)) 返回具有相同形状和元素类型的可变数组\nsimilar(A, ::Type{S}) similar(A, S, size(A)) 返回具有相同形状和指定元素类型的可变数组\nsimilar(A, dims::Dims) similar(A, eltype(A), dims) 返回具有相同元素类型和大小为 dims 的可变数组\nsimilar(A, ::Type{S}, dims::Dims) Array{S}(undef, dims) 返回具有指定元素类型及大小的可变数组\n不遵循惯例的索引 默认定义 简短描述\naxes(A) map(OneTo, size(A)) 返回有效索引的 AbstractUnitRange{<:Integer}\nsimilar(A, ::Type{S}, inds) similar(A, S, Base.to_shape(inds)) 返回使用特殊索引 inds 的可变数组(详见下文)\nsimilar(T::Union{Type,Function}, inds) T(Base.to_shape(inds)) 返回类似于 T 的使用特殊索引 inds 的数组(详见下文)","category":"page"},{"location":"manual/interfaces/","page":"接口","title":"接口","text":"如果一个类型被定义为 AbstractArray 的子类型,那它就继承了一大堆丰富的行为,包括构建在单元素访问之上的迭代和多维索引。有关更多支持的方法,请参阅文档 多维数组 及 Julia Base。","category":"page"},{"location":"manual/interfaces/","page":"接口","title":"接口","text":"定义 AbstractArray 子类型的关键部分是 IndexStyle。由于索引是数组的重要部分且经常出现在 hot loops 中,使索引和索引赋值尽可能高效非常重要。数组数据结构通常以两种方式定义:要么仅使用一个索引(即线性索引)来最高效地访问其元素,要么实际上使用由各个维度确定的索引访问其元素。这两种方式被 Julia 标记为 IndexLinear() 和 IndexCartesian()。把线性索引转换为多重索引下标通常代价高昂,因此这提供了基于 traits 机制,以便能为所有矩阵类型提供高效的通用代码。","category":"page"},{"location":"manual/interfaces/","page":"接口","title":"接口","text":"此区别决定了该类型必须定义的标量索引方法。IndexLinear() 很简单:只需定义 getindex(A::ArrayType, i::Int)。当数组后用多维索引集进行索引时,回退 getindex(A::AbstractArray, I...)() 高效地将该索引转换为线性索引,然后调用上述方法。另一方面,IndexCartesian() 数组需要为每个支持的、使用 ndims(A) 个 Int 索引的维度定义方法。例如,SparseArrays 标准库里的 SparseMatrixCSC 只支持二维,所以它只定义了 getindex(A::SparseMatrixCSC, i::Int, j::Int)。setindex! 也是如此。","category":"page"},{"location":"manual/interfaces/","page":"接口","title":"接口","text":"回到上面的平方数序列,我们可以将它定义为 AbstractArray{Int, 1} 的子类型:","category":"page"},{"location":"manual/interfaces/","page":"接口","title":"接口","text":"julia> struct SquaresVector <: AbstractArray{Int, 1}\n count::Int\n end\n\njulia> Base.size(S::SquaresVector) = (S.count,)\n\njulia> Base.IndexStyle(::Type{<:SquaresVector}) = IndexLinear()\n\njulia> Base.getindex(S::SquaresVector, i::Int) = i*i","category":"page"},{"location":"manual/interfaces/","page":"接口","title":"接口","text":"请注意,指定 AbstractArray 的两个参数非常重要;第一个参数定义了 eltype,第二个则定义了 ndims。该超类型和这三个方法就足以使 SquaresVector 变成一个可迭代、可索引且功能齐全的数组:","category":"page"},{"location":"manual/interfaces/","page":"接口","title":"接口","text":"julia> s = SquaresVector(4)\n4-element SquaresVector:\n 1\n 4\n 9\n 16\n\njulia> s[s .> 8]\n2-element Vector{Int64}:\n 9\n 16\n\njulia> s + s\n4-element Vector{Int64}:\n 2\n 8\n 18\n 32\n\njulia> sin.(s)\n4-element Vector{Float64}:\n 0.8414709848078965\n -0.7568024953079282\n 0.4121184852417566\n -0.2879033166650653","category":"page"},{"location":"manual/interfaces/","page":"接口","title":"接口","text":"作为一个更复杂的例子,让我们在 Dict 之上定义自己的玩具性质的 N 维稀疏数组类型。","category":"page"},{"location":"manual/interfaces/","page":"接口","title":"接口","text":"julia> struct SparseArray{T,N} <: AbstractArray{T,N}\n data::Dict{NTuple{N,Int}, T}\n dims::NTuple{N,Int}\n end\n\njulia> SparseArray(::Type{T}, dims::Int...) where {T} = SparseArray(T, dims);\n\njulia> SparseArray(::Type{T}, dims::NTuple{N,Int}) where {T,N} = SparseArray{T,N}(Dict{NTuple{N,Int}, T}(), dims);\n\njulia> Base.size(A::SparseArray) = A.dims\n\njulia> Base.similar(A::SparseArray, ::Type{T}, dims::Dims) where {T} = SparseArray(T, dims)\n\njulia> Base.getindex(A::SparseArray{T,N}, I::Vararg{Int,N}) where {T,N} = get(A.data, I, zero(T))\n\njulia> Base.setindex!(A::SparseArray{T,N}, v, I::Vararg{Int,N}) where {T,N} = (A.data[I] = v)","category":"page"},{"location":"manual/interfaces/","page":"接口","title":"接口","text":"请注意,这是个 IndexCartesian 数组,因此我们必须在数组的维度上手动定义 getindex 和 setindex!。与 SquaresVector 不同,我们可以定义 setindex!,这样便能更改数组:","category":"page"},{"location":"manual/interfaces/","page":"接口","title":"接口","text":"julia> A = SparseArray(Float64, 3, 3)\n3×3 SparseArray{Float64, 2}:\n 0.0 0.0 0.0\n 0.0 0.0 0.0\n 0.0 0.0 0.0\n\njulia> fill!(A, 2)\n3×3 SparseArray{Float64, 2}:\n 2.0 2.0 2.0\n 2.0 2.0 2.0\n 2.0 2.0 2.0\n\njulia> A[:] = 1:length(A); A\n3×3 SparseArray{Float64, 2}:\n 1.0 4.0 7.0\n 2.0 5.0 8.0\n 3.0 6.0 9.0","category":"page"},{"location":"manual/interfaces/","page":"接口","title":"接口","text":"索引 AbstractArray 的结果本身可以是数组(例如,在使用 AbstractRange 时)。AbstractArray 回退方法使用 similar 来分配具有适当大小和元素类型的 Array,该数组使用上述的基本索引方法填充。但是,在实现数组封装器时,你通常希望也封装结果:","category":"page"},{"location":"manual/interfaces/","page":"接口","title":"接口","text":"julia> A[1:2,:]\n2×3 SparseArray{Float64, 2}:\n 1.0 4.0 7.0\n 2.0 5.0 8.0","category":"page"},{"location":"manual/interfaces/","page":"接口","title":"接口","text":"在此例中,创建合适的封装数组通过定义 Base.similar(A::SparseArray, ::Type{T}, dims::Dims) where T 来实现。(请注意,虽然 similar 支持 1 参数和 2 参数形式,但在大多数情况下,你只需要专门定义 3 参数形式。)为此,SparseArray 是可变的(支持 setindex!)便很重要。为 SparseArray 定义 similar、getindex 和 setindex! 也使得该数组能够 copy 。","category":"page"},{"location":"manual/interfaces/","page":"接口","title":"接口","text":"julia> copy(A)\n3×3 SparseArray{Float64,2}:\n 1.0 4.0 7.0\n 2.0 5.0 8.0\n 3.0 6.0 9.0","category":"page"},{"location":"manual/interfaces/","page":"接口","title":"接口","text":"除了上面的所有可迭代和可索引方法之外,这些类型还能相互交互,并使用在 Julia Base 中为 AbstractArray 定义的大多数方法:","category":"page"},{"location":"manual/interfaces/","page":"接口","title":"接口","text":"julia> A[SquaresVector(3)]\n3-element SparseArray{Float64, 1}:\n 1.0\n 4.0\n 9.0\n\njulia> sum(A)\n45.0","category":"page"},{"location":"manual/interfaces/","page":"接口","title":"接口","text":"如果要定义允许非传统索引(索引以 1 之外的数字开始)的数组类型,你应该专门指定 axes。你也应该专门指定 similar,以便 dims 参数(通常是大小为 Dims 的元组)可以接收 AbstractUnitRange 对象,它也许是你自己设计的 range 类型 Ind。有关更多信息,请参阅使用自定义索引的数组。","category":"page"},{"location":"manual/interfaces/#man-interface-strided-arrays","page":"接口","title":"等步长数组","text":"","category":"section"},{"location":"manual/interfaces/","page":"接口","title":"接口","text":"实习方法 简要描述\nstrides(A) 返回每个维度中相邻元素之间的内存距离(以内存元素数量的形式)组成的元组。如果 A 是 AbstractArray{T,0},这应该返回空元组。\nBase.unsafe_convert(::Type{Ptr{T}}, A) 返回数组的本地内存地址\nBase.elsize(::Type{<:A}) 返回数组中连续元素的步长\n可选方法 默认定义 简要描述\nstride(A, i::Int) strides(A)[i] 返回维度 i(译注:原文为 k)上相邻元素之间的内存距离(以内存元素数量的形式)。","category":"page"},{"location":"manual/interfaces/","page":"接口","title":"接口","text":"等步长数组是 AbstractArray 的子类型,其条目以固定步长储存在内存中。如果数组的元素类型与 BLAS 兼容,则 strided 数组可以利用 BLAS 和 LAPACK 例程来实现更高效的线性代数例程。用户定义的 strided 数组的典型示例是把标准 Array 用附加结构进行封装的数组。","category":"page"},{"location":"manual/interfaces/","page":"接口","title":"接口","text":"警告:如果底层存储实际上不是 strided,则不要实现这些方法,因为这可能导致错误的结果或段错误。","category":"page"},{"location":"manual/interfaces/","page":"接口","title":"接口","text":"下面是一些示例,用来演示哪些数组类型是 strided 数组,哪些不是:","category":"page"},{"location":"manual/interfaces/","page":"接口","title":"接口","text":"1:5 # not strided (there is no storage associated with this array.)\nVector(1:5) # is strided with strides (1,)\nA = [1 5; 2 6; 3 7; 4 8] # is strided with strides (1,4)\nV = view(A, 1:2, :) # is strided with strides (1,4)\nV = view(A, 1:2:3, 1:2) # is strided with strides (2,4)\nV = view(A, [1,2,4], :) # is not strided, as the spacing between rows is not fixed.","category":"page"},{"location":"manual/interfaces/#man-interfaces-broadcasting","page":"接口","title":"自定义广播","text":"","category":"section"},{"location":"manual/interfaces/","page":"接口","title":"接口","text":"需要实现的方法 简短描述\nBase.BroadcastStyle(::Type{SrcType}) = SrcStyle() SrcType 的广播行为\nBase.similar(bc::Broadcasted{DestStyle}, ::Type{ElType}) 输出容器的分配\n可选方法 \nBase.BroadcastStyle(::Style1, ::Style2) = Style12() 混合广播风格的优先级规则\nBase.axes(x) 用于广播的 x 的索引的声明(默认为 axes(x))\nBase.broadcastable(x) 将 x 转换为一个具有 axes 且支持索引的对象\n绕过默认机制 \nBase.copy(bc::Broadcasted{DestStyle}) broadcast 的自定义实现\nBase.copyto!(dest, bc::Broadcasted{DestStyle}) 专门针对 DestStyle 的自定义 broadcast! 实现\nBase.copyto!(dest::DestType, bc::Broadcasted{Nothing}) 专门针对 DestStyle 的自定义 broadcast! 实现\nBase.Broadcast.broadcasted(f, args...) 覆盖融合表达式中的默认惰性行为\nBase.Broadcast.instantiate(bc::Broadcasted{DestStyle}) 覆盖惰性广播的 axes 的计算","category":"page"},{"location":"manual/interfaces/","page":"接口","title":"接口","text":"广播可由 broadcast 或 broadcast! 的显式调用、或者像 A .+ b 或 f.(x, y) 这样的「点」操作隐式触发。任何具有 axes 且支持索引的对象都可作为参数参与广播,默认情况下,广播结果储存在 Array 中。这个基本框架可通过三个主要方式扩展:","category":"page"},{"location":"manual/interfaces/","page":"接口","title":"接口","text":"确保所有参数都支持广播\n为给定参数集选择合适的输出数组\n为给定参数集选择高效的实现","category":"page"},{"location":"manual/interfaces/","page":"接口","title":"接口","text":"不是所有类型都支持 axes 和索引,但许多类型便于支持广播。Base.broadcastable 函数会在每个广播参数上调用,它能返回与广播参数不同的支持 axes 和索引的对象。默认情况下,对于所有 AbstractArray 和 Number 来说这是 identity 函数——因为它们已经支持 axes 和索引了。少数其它类型(包括但不限于类型本身、函数、像 missing 和 nothing 这样的特殊单态类型以及日期)为了能被广播,Base.broadcastable 会返回封装在 Ref 的参数来充当 0 维「标量」。自定义类型可以类似地指定 Base.broadcastable 来定义其形状,但是它们应当遵循 collect(Base.broadcastable(x)) == collect(x) 的约定。一个值得注意的例外是 AbstractString;字符串是个特例,为了能被广播其表现为标量,尽管它们是其字符的可迭代集合(详见 字符串)。","category":"page"},{"location":"manual/interfaces/","page":"接口","title":"接口","text":"接下来的两个步骤(选择输出数组和实现)依赖于如何确定给定参数集的唯一解。广播必须接受其参数的所有不同类型,并把它们折叠到一个输出数组和实现。广播称此唯一解为“风格”。每个可广播对象都有自己的首选风格,并使用类似于类型提升的系统将这些风格组合成一个唯一解——“目标风格”。","category":"page"},{"location":"manual/interfaces/#广播风格","page":"接口","title":"广播风格","text":"","category":"section"},{"location":"manual/interfaces/","page":"接口","title":"接口","text":"抽象类型 Base.BroadcastStyle 派生了所有的广播风格。其在用作函数时有两种可能的形式,分别为一元形式(单参数)和二元形式。使用一元形式表明你打算实现特定的广播行为和/或输出类型,并且不希望依赖于默认的回退 Broadcast.DefaultArrayStyle。","category":"page"},{"location":"manual/interfaces/","page":"接口","title":"接口","text":"为了覆盖这些默认值,你可以为对象自定义 BroadcastStyle:","category":"page"},{"location":"manual/interfaces/","page":"接口","title":"接口","text":"struct MyStyle <: Broadcast.BroadcastStyle end\nBase.BroadcastStyle(::Type{<:MyType}) = MyStyle()","category":"page"},{"location":"manual/interfaces/","page":"接口","title":"接口","text":"在某些情况下,无需定义 MyStyle 也许很方便,在这些情况下,你可以利用一个通用的广播封装器:","category":"page"},{"location":"manual/interfaces/","page":"接口","title":"接口","text":"Base.BroadcastStyle(::Type{<:MyType}) = Broadcast.Style{MyType}() 可用于任意类型。\n如果 MyType 是一个 AbstractArray,首选是 Base.BroadcastStyle(::Type{<:MyType}) = Broadcast.ArrayStyle{MyType}()。\n对于只支持某个具体维度的 AbstractArrays,请创建 Broadcast.AbstractArrayStyle{N} 的子类型(请参阅下文)。","category":"page"},{"location":"manual/interfaces/","page":"接口","title":"接口","text":"当你的广播操作涉及多个参数,各个广播风格将合并,来确定唯一一个 DestStyle 以控制输出容器的类型。有关更多详细信息,请参阅下文。","category":"page"},{"location":"manual/interfaces/#选择合适的输出数组","page":"接口","title":"选择合适的输出数组","text":"","category":"section"},{"location":"manual/interfaces/","page":"接口","title":"接口","text":"每个广播操作都会计算广播风格以便支持派发和专门化。结果数组的实际分配由 similar 处理,其使用 Broadcasted 对象作为其第一个参数。","category":"page"},{"location":"manual/interfaces/","page":"接口","title":"接口","text":"Base.similar(bc::Broadcasted{DestStyle}, ::Type{ElType})","category":"page"},{"location":"manual/interfaces/","page":"接口","title":"接口","text":"回退定义是","category":"page"},{"location":"manual/interfaces/","page":"接口","title":"接口","text":"similar(bc::Broadcasted{DefaultArrayStyle{N}}, ::Type{ElType}) where {N,ElType} =\n similar(Array{ElType}, axes(bc))","category":"page"},{"location":"manual/interfaces/","page":"接口","title":"接口","text":"但是,如果需要,你可以专门化任何或所有这些参数。最后的参数 bc 是(还可能是融合的)广播操作的惰性表示,即 Broadcasted 对象。出于这些目的,该封装器中最重要的字段是 f 和 args,分别描述函数和参数列表。请注意,参数列表可以——并且经常——包含其它嵌套的 Broadcasted 封装器。","category":"page"},{"location":"manual/interfaces/","page":"接口","title":"接口","text":"举个完整的例子,假设你创建了类型 ArrayAndChar,该类型存储一个数组和单个字符:","category":"page"},{"location":"manual/interfaces/","page":"接口","title":"接口","text":"struct ArrayAndChar{T,N} <: AbstractArray{T,N}\n data::Array{T,N}\n char::Char\nend\nBase.size(A::ArrayAndChar) = size(A.data)\nBase.getindex(A::ArrayAndChar{T,N}, inds::Vararg{Int,N}) where {T,N} = A.data[inds...]\nBase.setindex!(A::ArrayAndChar{T,N}, val, inds::Vararg{Int,N}) where {T,N} = A.data[inds...] = val\nBase.showarg(io::IO, A::ArrayAndChar, toplevel) = print(io, typeof(A), \" with char '\", A.char, \"'\")","category":"page"},{"location":"manual/interfaces/","page":"接口","title":"接口","text":"你可能想要广播保留“元数据”char。为此,我们首先定义","category":"page"},{"location":"manual/interfaces/","page":"接口","title":"接口","text":"Base.BroadcastStyle(::Type{<:ArrayAndChar}) = Broadcast.ArrayStyle{ArrayAndChar}()","category":"page"},{"location":"manual/interfaces/","page":"接口","title":"接口","text":"这意味着我们还必须定义相应的 similar 方法:","category":"page"},{"location":"manual/interfaces/","page":"接口","title":"接口","text":"function Base.similar(bc::Broadcast.Broadcasted{Broadcast.ArrayStyle{ArrayAndChar}}, ::Type{ElType}) where ElType\n # Scan the inputs for the ArrayAndChar:\n A = find_aac(bc)\n # Use the char field of A to create the output\n ArrayAndChar(similar(Array{ElType}, axes(bc)), A.char)\nend\n\n\"`A = find_aac(As)` returns the first ArrayAndChar among the arguments.\"\nfind_aac(bc::Base.Broadcast.Broadcasted) = find_aac(bc.args)\nfind_aac(args::Tuple) = find_aac(find_aac(args[1]), Base.tail(args))\nfind_aac(x) = x\nfind_aac(::Tuple{}) = nothing\nfind_aac(a::ArrayAndChar, rest) = a\nfind_aac(::Any, rest) = find_aac(rest)","category":"page"},{"location":"manual/interfaces/","page":"接口","title":"接口","text":"在这些定义中,可以得到以下行为:","category":"page"},{"location":"manual/interfaces/","page":"接口","title":"接口","text":"julia> a = ArrayAndChar([1 2; 3 4], 'x')\n2×2 ArrayAndChar{Int64, 2} with char 'x':\n 1 2\n 3 4\n\njulia> a .+ 1\n2×2 ArrayAndChar{Int64, 2} with char 'x':\n 2 3\n 4 5\n\njulia> a .+ [5,10]\n2×2 ArrayAndChar{Int64, 2} with char 'x':\n 6 7\n 13 14","category":"page"},{"location":"manual/interfaces/#extending-in-place-broadcast","page":"接口","title":"使用自定义实现扩展广播","text":"","category":"section"},{"location":"manual/interfaces/","page":"接口","title":"接口","text":"一般来说,广播操作由一个惰性 Broadcasted 容器表示,该容器保存要应用的函数及其参数。这些参数可能本身是嵌套得更深的 Broadcasted 容器,并一起形成了一个待求值的大型表达式树。嵌套的 Broadcasted 容器树可由隐式的点语法直接构造;例如,5 .+ 2.*x 由 Broadcasted(+, 5, Broadcasted(*, 2, x)) 暂时表示。这对于用户是不可见的,因为它是通过调用 copy 立即实现的,但是此容器为自定义类型的作者提供了广播可扩展性的基础。然后,内置的广播机制将根据参数确定结果的类型和大小,为它分配内存,并最终通过默认的 copyto!(::AbstractArray, ::Broadcasted) 方法将 Broadcasted 对象复制到其中。内置的回退 broadcast 和 broadcast! 方法类似地构造操作的暂时 Broadcasted 表示,因此它们共享相同的代码路径。这便允许自定义的数组实现通过提供它们自己的专门化 copyto! 来定义和优化广播。这再次由计算后的广播风格确定。此广播风格在广播操作中非常重要,以至于它被存储为 Broadcasted 类型的第一个类型参数,且允许派发和专门化。","category":"page"},{"location":"manual/interfaces/","page":"接口","title":"接口","text":"对于某些类型,跨越层层嵌套的广播的「融合」操作无法实现,或者无法更高效地逐步完成。在这种情况下,你可能需要或者想要求值 x .* (x .+ 1),就好像该式已被编写成 broadcast(*, x, broadcast(+, x, 1)),其中内部广播操作会在处理外部广播操作前进行求值。这种直接的操作以有点间接的方式得到直接支持;Julia 不会直接构造 Broadcasted 对象,而会将 待融合的表达式 x .* (x .+ 1) 降低为 Broadcast.broadcasted(*, x, Broadcast.broadcasted(+, x, 1))。现在,默认情况下,broadcasted 只会调用 Broadcasted 构造函数来创建待融合表达式树的惰性表示,但是你可以选择为函数和参数的特定组合覆盖它。","category":"page"},{"location":"manual/interfaces/","page":"接口","title":"接口","text":"举个例子,内置的 AbstractRange 对象使用此机制优化广播表达式的片段,这些表达式片段可以只根据 start、step 和 length(或 stop)直接进行求值,而无需计算每个元素。与所有其它机制一样,broadcasted 也会计算并暴露其参数的组合广播风格,所以你可以为广播风格、函数和参数的任意组合专门化 broadcasted(::DestStyle, f, args...),而不是专门化 broadcasted(f, args...)。","category":"page"},{"location":"manual/interfaces/","page":"接口","title":"接口","text":"例如,以下定义支持 range 的负运算:","category":"page"},{"location":"manual/interfaces/","page":"接口","title":"接口","text":"broadcasted(::DefaultArrayStyle{1}, ::typeof(-), r::OrdinalRange) = range(-first(r), step=-step(r), length=length(r))","category":"page"},{"location":"manual/interfaces/#extending-in-place-broadcast-2","page":"接口","title":"扩展 in-place 广播","text":"","category":"section"},{"location":"manual/interfaces/","page":"接口","title":"接口","text":"In-place 广播可通过定义合适的 copyto!(dest, bc::Broadcasted) 方法来支持。由于你可能想要专门化 dest 或 bc 的特定子类型,为了避免包之间的歧义,我们建议采用以下约定。","category":"page"},{"location":"manual/interfaces/","page":"接口","title":"接口","text":"如果你想要专门化特定的广播风格 DestStyle,请为其定义一个方法","category":"page"},{"location":"manual/interfaces/","page":"接口","title":"接口","text":"copyto!(dest, bc::Broadcasted{DestStyle})","category":"page"},{"location":"manual/interfaces/","page":"接口","title":"接口","text":"你可选择使用此形式,如果使用,你还可以专门化 dest 的类型。","category":"page"},{"location":"manual/interfaces/","page":"接口","title":"接口","text":"如果你想专门化目标类型 DestType 而不专门化 DestStyle,那么你应该定义一个带有以下签名的方法:","category":"page"},{"location":"manual/interfaces/","page":"接口","title":"接口","text":"copyto!(dest::DestType, bc::Broadcasted{Nothing})","category":"page"},{"location":"manual/interfaces/","page":"接口","title":"接口","text":"这利用了 copyto! 的回退实现,它将该封装器转换为一个 Broadcasted{Nothing} 对象。因此,专门化 DestType 的方法优先级低于专门化 DestStyle 的方法。","category":"page"},{"location":"manual/interfaces/","page":"接口","title":"接口","text":"同样,你可以使用 copy(::Broadcasted) 方法完全覆盖 out-of-place 广播。","category":"page"},{"location":"manual/interfaces/#使用-Broadcasted-对象","page":"接口","title":"使用 Broadcasted 对象","text":"","category":"section"},{"location":"manual/interfaces/","page":"接口","title":"接口","text":"当然,为了实现这样的 copy 或 copyto! 方法,你必须使用 Broadcasted 封装器来计算每个元素。这主要有两种方式:","category":"page"},{"location":"manual/interfaces/","page":"接口","title":"接口","text":"Broadcast.flatten 将可能的嵌套操作重新计算为单个函数并平铺参数列表。你自己负责实现广播形状规则,但这在有限的情况下可能会有所帮助。\n迭代 axes(::Broadcasted) 的 CartesianIndices 并使用所生成的 CartesianIndex 对象的索引来计算结果。","category":"page"},{"location":"manual/interfaces/#writing-binary-broadcasting-rules","page":"接口","title":"编写二元广播规则","text":"","category":"section"},{"location":"manual/interfaces/","page":"接口","title":"接口","text":"广播风格的优先级规则由二元 BroadcastStyle 调用定义:","category":"page"},{"location":"manual/interfaces/","page":"接口","title":"接口","text":"Base.BroadcastStyle(::Style1, ::Style2) = Style12()","category":"page"},{"location":"manual/interfaces/","page":"接口","title":"接口","text":"其中,Style12 是你要为输出所选择的 BroadcastStyle,所涉及的参数具有 Style1 及 Style2。例如,","category":"page"},{"location":"manual/interfaces/","page":"接口","title":"接口","text":"Base.BroadcastStyle(::Broadcast.Style{Tuple}, ::Broadcast.AbstractArrayStyle{0}) = Broadcast.Style{Tuple}()","category":"page"},{"location":"manual/interfaces/","page":"接口","title":"接口","text":"表示 Tuple「胜过」零维数组(输出容器将是元组)。值得注意的是,你不需要(也不应该)为此调用的两个参数顺序下定义;无论用户提供的以何种顺序提供参数,定义一个就够了。","category":"page"},{"location":"manual/interfaces/","page":"接口","title":"接口","text":"对于 AbstractArray 类型,定义 BroadcastStyle 将取代回退选择 Broadcast.DefaultArrayStyle。DefaultArrayStyle 及其抽象超类型 AbstractArrayStyle 将维度存储为类型参数,以支持具有固定维度需求的特定数组类型。","category":"page"},{"location":"manual/interfaces/","page":"接口","title":"接口","text":"由于以下方法,DefaultArrayStyle「输给」任何其它已定义的 AbstractArrayStyle:","category":"page"},{"location":"manual/interfaces/","page":"接口","title":"接口","text":"BroadcastStyle(a::AbstractArrayStyle{Any}, ::DefaultArrayStyle) = a\nBroadcastStyle(a::AbstractArrayStyle{N}, ::DefaultArrayStyle{N}) where N = a\nBroadcastStyle(a::AbstractArrayStyle{M}, ::DefaultArrayStyle{N}) where {M,N} =\n typeof(a)(Val(max(M, N)))","category":"page"},{"location":"manual/interfaces/","page":"接口","title":"接口","text":"除非你想要为两个或多个非 DefaultArrayStyle 的类型建立优先级,否则不需要编写二元 BroadcastStyle 规则。","category":"page"},{"location":"manual/interfaces/","page":"接口","title":"接口","text":"如果你的数组类型确实有固定的维度需求,那么你应该定义一个 AbstractArrayStyle 的子类型。例如,稀疏数组的代码中有以下定义:","category":"page"},{"location":"manual/interfaces/","page":"接口","title":"接口","text":"struct SparseVecStyle <: Broadcast.AbstractArrayStyle{1} end\nstruct SparseMatStyle <: Broadcast.AbstractArrayStyle{2} end\nBase.BroadcastStyle(::Type{<:SparseVector}) = SparseVecStyle()\nBase.BroadcastStyle(::Type{<:SparseMatrixCSC}) = SparseMatStyle()","category":"page"},{"location":"manual/interfaces/","page":"接口","title":"接口","text":"每当你定义一个 AbstractArrayStyle 的子类型,你还需要定义用于组合维度的规则,这通过为你的广播风格创建带有一个 Val(N) 参数的构造函数。例如:","category":"page"},{"location":"manual/interfaces/","page":"接口","title":"接口","text":"SparseVecStyle(::Val{0}) = SparseVecStyle()\nSparseVecStyle(::Val{1}) = SparseVecStyle()\nSparseVecStyle(::Val{2}) = SparseMatStyle()\nSparseVecStyle(::Val{N}) where N = Broadcast.DefaultArrayStyle{N}()","category":"page"},{"location":"manual/interfaces/","page":"接口","title":"接口","text":"这些规则表明 SparseVecStyle 与 0 维或 1 维数组的组合会产生另一个 SparseVecStyle,与 2 维数组的组合会产生 SparseMatStyle,而与维度更高的数组则回退到任意维密集矩阵的框架中。这些规则允许广播为产生一维或二维输出的操作保持其稀疏表示,但为任何其它维度生成 Array。","category":"page"}] +[{"location":"stdlib/CRC32c/#CRC32c","page":"CRC32c","title":"CRC32c","text":"","category":"section"},{"location":"stdlib/CRC32c/","page":"CRC32c","title":"CRC32c","text":"CRC32c.crc32c\nCRC32c.crc32c(::IO, ::Integer, ::UInt32)","category":"page"},{"location":"stdlib/CRC32c/#CRC32c.crc32c","page":"CRC32c","title":"CRC32c.crc32c","text":"crc32c(data, crc::UInt32=0x00000000)\n\nCompute the CRC-32c checksum of the given data, which can be an Array{UInt8}, a contiguous subarray thereof, or a String. Optionally, you can pass a starting crc integer to be mixed in with the checksum. The crc parameter can be used to compute a checksum on data divided into chunks: performing crc32c(data2, crc32c(data1)) is equivalent to the checksum of [data1; data2]. (Technically, a little-endian checksum is computed.)\n\nThere is also a method crc32c(io, nb, crc) to checksum nb bytes from a stream io, or crc32c(io, crc) to checksum all the remaining bytes. Hence you can do open(crc32c, filename) to checksum an entire file, or crc32c(seekstart(buf)) to checksum an IOBuffer without calling take!.\n\nFor a String, note that the result is specific to the UTF-8 encoding (a different checksum would be obtained from a different Unicode encoding). To checksum an a::Array of some other bitstype, you can do crc32c(reinterpret(UInt8,a)), but note that the result may be endian-dependent.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/CRC32c/#CRC32c.crc32c-Tuple{IO, Integer, UInt32}","page":"CRC32c","title":"CRC32c.crc32c","text":"crc32c(io::IO, [nb::Integer,] crc::UInt32=0x00000000)\n\nRead up to nb bytes from io and return the CRC-32c checksum, optionally mixed with a starting crc integer. If nb is not supplied, then io will be read until the end of the stream.\n\n\n\n\n\n","category":"method"},{"location":"base/sort/#排序及相关函数","page":"排序及相关函数","title":"排序及相关函数","text":"","category":"section"},{"location":"base/sort/","page":"排序及相关函数","title":"排序及相关函数","text":"Julia 拥有为数众多的灵活的 API,用于对已经排序的值数组进行排序和交互。默认情况下,Julia 会选择合理的算法并按标准升序进行排序:","category":"page"},{"location":"base/sort/","page":"排序及相关函数","title":"排序及相关函数","text":"julia> sort([2,3,1])\n3-element Vector{Int64}:\n 1\n 2\n 3","category":"page"},{"location":"base/sort/","page":"排序及相关函数","title":"排序及相关函数","text":"你同样可以轻松实现逆序排序:","category":"page"},{"location":"base/sort/","page":"排序及相关函数","title":"排序及相关函数","text":"julia> sort([2,3,1], rev=true)\n3-element Vector{Int64}:\n 3\n 2\n 1","category":"page"},{"location":"base/sort/","page":"排序及相关函数","title":"排序及相关函数","text":"对数组进行 in-place 排序时,要使用 ! 版的排序函数:","category":"page"},{"location":"base/sort/","page":"排序及相关函数","title":"排序及相关函数","text":"julia> a = [2,3,1];\n\njulia> sort!(a);\n\njulia> a\n3-element Vector{Int64}:\n 1\n 2\n 3","category":"page"},{"location":"base/sort/","page":"排序及相关函数","title":"排序及相关函数","text":"你可以计算用于排列的索引,而不是直接对数组进行排序:","category":"page"},{"location":"base/sort/","page":"排序及相关函数","title":"排序及相关函数","text":"julia> v = randn(5)\n5-element Array{Float64,1}:\n 0.297288\n 0.382396\n -0.597634\n -0.0104452\n -0.839027\n\njulia> p = sortperm(v)\n5-element Array{Int64,1}:\n 5\n 3\n 4\n 1\n 2\n\njulia> v[p]\n5-element Array{Float64,1}:\n -0.839027\n -0.597634\n -0.0104452\n 0.297288\n 0.382396","category":"page"},{"location":"base/sort/","page":"排序及相关函数","title":"排序及相关函数","text":"数组可以根据对其值任意的转换结果来进行排序;","category":"page"},{"location":"base/sort/","page":"排序及相关函数","title":"排序及相关函数","text":"julia> sort(v, by=abs)\n5-element Array{Float64,1}:\n -0.0104452\n 0.297288\n 0.382396\n -0.597634\n -0.839027","category":"page"},{"location":"base/sort/","page":"排序及相关函数","title":"排序及相关函数","text":"或者通过转换来进行逆序排序","category":"page"},{"location":"base/sort/","page":"排序及相关函数","title":"排序及相关函数","text":"julia> sort(v, by=abs, rev=true)\n5-element Array{Float64,1}:\n -0.839027\n -0.597634\n 0.382396\n 0.297288\n -0.0104452","category":"page"},{"location":"base/sort/","page":"排序及相关函数","title":"排序及相关函数","text":"如有必要,可以选择排序算法:","category":"page"},{"location":"base/sort/","page":"排序及相关函数","title":"排序及相关函数","text":"julia> sort(v, alg=InsertionSort)\n5-element Array{Float64,1}:\n -0.839027\n -0.597634\n -0.0104452\n 0.297288\n 0.382396","category":"page"},{"location":"base/sort/","page":"排序及相关函数","title":"排序及相关函数","text":"所有与排序和顺序相关的函数依赖于“小于”关系,该关系定义了要操纵的值的总顺序。默认情况下会调用 isless 函数,但可以通过 lt 关键字指定关系。","category":"page"},{"location":"base/sort/#排序函数","page":"排序及相关函数","title":"排序函数","text":"","category":"section"},{"location":"base/sort/","page":"排序及相关函数","title":"排序及相关函数","text":"Base.sort!\nBase.sort\nBase.sortperm\nBase.InsertionSort\nBase.MergeSort\nBase.QuickSort\nBase.PartialQuickSort\nBase.Sort.sortperm!\nBase.Sort.sortslices","category":"page"},{"location":"base/sort/#Base.sort!","page":"排序及相关函数","title":"Base.sort!","text":"sort!(v; alg::Algorithm=defalg(v), lt=isless, by=identity, rev::Bool=false, order::Ordering=Forward)\n\nSort the vector v in place. QuickSort is used by default for numeric arrays while MergeSort is used for other arrays. You can specify an algorithm to use via the alg keyword (see Sorting Algorithms for available algorithms). The by keyword lets you provide a function that will be applied to each element before comparison; the lt keyword allows providing a custom \"less than\" function (note that for every x and y, only one of lt(x,y) and lt(y,x) can return true); use rev=true to reverse the sorting order. These options are independent and can be used together in all possible combinations: if both by and lt are specified, the lt function is applied to the result of the by function; rev=true reverses whatever ordering specified via the by and lt keywords.\n\nExamples\n\njulia> v = [3, 1, 2]; sort!(v); v\n3-element Vector{Int64}:\n 1\n 2\n 3\n\njulia> v = [3, 1, 2]; sort!(v, rev = true); v\n3-element Vector{Int64}:\n 3\n 2\n 1\n\njulia> v = [(1, \"c\"), (3, \"a\"), (2, \"b\")]; sort!(v, by = x -> x[1]); v\n3-element Vector{Tuple{Int64, String}}:\n (1, \"c\")\n (2, \"b\")\n (3, \"a\")\n\njulia> v = [(1, \"c\"), (3, \"a\"), (2, \"b\")]; sort!(v, by = x -> x[2]); v\n3-element Vector{Tuple{Int64, String}}:\n (3, \"a\")\n (2, \"b\")\n (1, \"c\")\n\n\n\n\n\nsort!(A; dims::Integer, alg::Algorithm=defalg(A), lt=isless, by=identity, rev::Bool=false, order::Ordering=Forward)\n\nSort the multidimensional array A along dimension dims. See sort! for a description of possible keyword arguments.\n\nTo sort slices of an array, refer to sortslices.\n\ncompat: Julia 1.1\nThis function requires at least Julia 1.1.\n\nExamples\n\njulia> A = [4 3; 1 2]\n2×2 Matrix{Int64}:\n 4 3\n 1 2\n\njulia> sort!(A, dims = 1); A\n2×2 Matrix{Int64}:\n 1 2\n 4 3\n\njulia> sort!(A, dims = 2); A\n2×2 Matrix{Int64}:\n 1 2\n 3 4\n\n\n\n\n\n","category":"function"},{"location":"base/sort/#Base.sort","page":"排序及相关函数","title":"Base.sort","text":"sort(v; alg::Algorithm=defalg(v), lt=isless, by=identity, rev::Bool=false, order::Ordering=Forward)\n\nVariant of sort! that returns a sorted copy of v leaving v itself unmodified.\n\nExamples\n\njulia> v = [3, 1, 2];\n\njulia> sort(v)\n3-element Vector{Int64}:\n 1\n 2\n 3\n\njulia> v\n3-element Vector{Int64}:\n 3\n 1\n 2\n\n\n\n\n\nsort(A; dims::Integer, alg::Algorithm=DEFAULT_UNSTABLE, lt=isless, by=identity, rev::Bool=false, order::Ordering=Forward)\n\nSort a multidimensional array A along the given dimension. See sort! for a description of possible keyword arguments.\n\nTo sort slices of an array, refer to sortslices.\n\nExamples\n\njulia> A = [4 3; 1 2]\n2×2 Matrix{Int64}:\n 4 3\n 1 2\n\njulia> sort(A, dims = 1)\n2×2 Matrix{Int64}:\n 1 2\n 4 3\n\njulia> sort(A, dims = 2)\n2×2 Matrix{Int64}:\n 3 4\n 1 2\n\n\n\n\n\n","category":"function"},{"location":"base/sort/#Base.sortperm","page":"排序及相关函数","title":"Base.sortperm","text":"sortperm(v; alg::Algorithm=DEFAULT_UNSTABLE, lt=isless, by=identity, rev::Bool=false, order::Ordering=Forward)\n\nReturn a permutation vector I that puts v[I] in sorted order. The order is specified using the same keywords as sort!. The permutation is guaranteed to be stable even if the sorting algorithm is unstable, meaning that indices of equal elements appear in ascending order.\n\nSee also sortperm!, partialsortperm, invperm, indexin.\n\nExamples\n\njulia> v = [3, 1, 2];\n\njulia> p = sortperm(v)\n3-element Vector{Int64}:\n 2\n 3\n 1\n\njulia> v[p]\n3-element Vector{Int64}:\n 1\n 2\n 3\n\n\n\n\n\n","category":"function"},{"location":"base/sort/#Base.Sort.InsertionSort","page":"排序及相关函数","title":"Base.Sort.InsertionSort","text":"InsertionSort\n\nIndicate that a sorting function should use the insertion sort algorithm. Insertion sort traverses the collection one element at a time, inserting each element into its correct, sorted position in the output list.\n\nCharacteristics:\n\nstable: preserves the ordering of elements which compare equal (e.g. \"a\" and \"A\" in a sort of letters which ignores case).\nin-place in memory.\nquadratic performance in the number of elements to be sorted: it is well-suited to small collections but should not be used for large ones.\n\n\n\n\n\n","category":"constant"},{"location":"base/sort/#Base.Sort.MergeSort","page":"排序及相关函数","title":"Base.Sort.MergeSort","text":"MergeSort\n\nIndicate that a sorting function should use the merge sort algorithm. Merge sort divides the collection into subcollections and repeatedly merges them, sorting each subcollection at each step, until the entire collection has been recombined in sorted form.\n\nCharacteristics:\n\nstable: preserves the ordering of elements which compare equal (e.g. \"a\" and \"A\" in a sort of letters which ignores case).\nnot in-place in memory.\ndivide-and-conquer sort strategy.\n\n\n\n\n\n","category":"constant"},{"location":"base/sort/#Base.Sort.QuickSort","page":"排序及相关函数","title":"Base.Sort.QuickSort","text":"QuickSort\n\nIndicate that a sorting function should use the quick sort algorithm, which is not stable.\n\nCharacteristics:\n\nnot stable: does not preserve the ordering of elements which compare equal (e.g. \"a\" and \"A\" in a sort of letters which ignores case).\nin-place in memory.\ndivide-and-conquer: sort strategy similar to MergeSort.\ngood performance for large collections.\n\n\n\n\n\n","category":"constant"},{"location":"base/sort/#Base.Sort.PartialQuickSort","page":"排序及相关函数","title":"Base.Sort.PartialQuickSort","text":"PartialQuickSort{T <: Union{Integer,OrdinalRange}}\n\nIndicate that a sorting function should use the partial quick sort algorithm. Partial quick sort returns the smallest k elements sorted from smallest to largest, finding them and sorting them using QuickSort.\n\nCharacteristics:\n\nnot stable: does not preserve the ordering of elements which compare equal (e.g. \"a\" and \"A\" in a sort of letters which ignores case).\nin-place in memory.\ndivide-and-conquer: sort strategy similar to MergeSort.\n\n\n\n\n\n","category":"type"},{"location":"base/sort/#Base.Sort.sortperm!","page":"排序及相关函数","title":"Base.Sort.sortperm!","text":"sortperm!(ix, v; alg::Algorithm=DEFAULT_UNSTABLE, lt=isless, by=identity, rev::Bool=false, order::Ordering=Forward, initialized::Bool=false)\n\nLike sortperm, but accepts a preallocated index vector ix. If initialized is false (the default), ix is initialized to contain the values 1:length(v).\n\nExamples\n\njulia> v = [3, 1, 2]; p = zeros(Int, 3);\n\njulia> sortperm!(p, v); p\n3-element Vector{Int64}:\n 2\n 3\n 1\n\njulia> v[p]\n3-element Vector{Int64}:\n 1\n 2\n 3\n\n\n\n\n\n","category":"function"},{"location":"base/sort/#Base.sortslices","page":"排序及相关函数","title":"Base.sortslices","text":"sortslices(A; dims, alg::Algorithm=DEFAULT_UNSTABLE, lt=isless, by=identity, rev::Bool=false, order::Ordering=Forward)\n\nSort slices of an array A. The required keyword argument dims must be either an integer or a tuple of integers. It specifies the dimension(s) over which the slices are sorted.\n\nE.g., if A is a matrix, dims=1 will sort rows, dims=2 will sort columns. Note that the default comparison function on one dimensional slices sorts lexicographically.\n\nFor the remaining keyword arguments, see the documentation of sort!.\n\nExamples\n\njulia> sortslices([7 3 5; -1 6 4; 9 -2 8], dims=1) # Sort rows\n3×3 Matrix{Int64}:\n -1 6 4\n 7 3 5\n 9 -2 8\n\njulia> sortslices([7 3 5; -1 6 4; 9 -2 8], dims=1, lt=(x,y)->isless(x[2],y[2]))\n3×3 Matrix{Int64}:\n 9 -2 8\n 7 3 5\n -1 6 4\n\njulia> sortslices([7 3 5; -1 6 4; 9 -2 8], dims=1, rev=true)\n3×3 Matrix{Int64}:\n 9 -2 8\n 7 3 5\n -1 6 4\n\njulia> sortslices([7 3 5; 6 -1 -4; 9 -2 8], dims=2) # Sort columns\n3×3 Matrix{Int64}:\n 3 5 7\n -1 -4 6\n -2 8 9\n\njulia> sortslices([7 3 5; 6 -1 -4; 9 -2 8], dims=2, alg=InsertionSort, lt=(x,y)->isless(x[2],y[2]))\n3×3 Matrix{Int64}:\n 5 3 7\n -4 -1 6\n 8 -2 9\n\njulia> sortslices([7 3 5; 6 -1 -4; 9 -2 8], dims=2, rev=true)\n3×3 Matrix{Int64}:\n 7 5 3\n 6 -4 -1\n 9 8 -2\n\nHigher dimensions\n\nsortslices extends naturally to higher dimensions. E.g., if A is a a 2x2x2 array, sortslices(A, dims=3) will sort slices within the 3rd dimension, passing the 2x2 slices A[:, :, 1] and A[:, :, 2] to the comparison function. Note that while there is no default order on higher-dimensional slices, you may use the by or lt keyword argument to specify such an order.\n\nIf dims is a tuple, the order of the dimensions in dims is relevant and specifies the linear order of the slices. E.g., if A is three dimensional and dims is (1, 2), the orderings of the first two dimensions are re-arranged such that the slices (of the remaining third dimension) are sorted. If dims is (2, 1) instead, the same slices will be taken, but the result order will be row-major instead.\n\nHigher dimensional examples\n\njulia> A = permutedims(reshape([4 3; 2 1; 'A' 'B'; 'C' 'D'], (2, 2, 2)), (1, 3, 2))\n2×2×2 Array{Any, 3}:\n[:, :, 1] =\n 4 3\n 2 1\n\n[:, :, 2] =\n 'A' 'B'\n 'C' 'D'\n\njulia> sortslices(A, dims=(1,2))\n2×2×2 Array{Any, 3}:\n[:, :, 1] =\n 1 3\n 2 4\n\n[:, :, 2] =\n 'D' 'B'\n 'C' 'A'\n\njulia> sortslices(A, dims=(2,1))\n2×2×2 Array{Any, 3}:\n[:, :, 1] =\n 1 2\n 3 4\n\n[:, :, 2] =\n 'D' 'C'\n 'B' 'A'\n\njulia> sortslices(reshape([5; 4; 3; 2; 1], (1,1,5)), dims=3, by=x->x[1,1])\n1×1×5 Array{Int64, 3}:\n[:, :, 1] =\n 1\n\n[:, :, 2] =\n 2\n\n[:, :, 3] =\n 3\n\n[:, :, 4] =\n 4\n\n[:, :, 5] =\n 5\n\n\n\n\n\n","category":"function"},{"location":"base/sort/#排列顺序相关的函数","page":"排序及相关函数","title":"排列顺序相关的函数","text":"","category":"section"},{"location":"base/sort/","page":"排序及相关函数","title":"排序及相关函数","text":"Base.issorted\nBase.Sort.searchsorted\nBase.Sort.searchsortedfirst\nBase.Sort.searchsortedlast\nBase.Sort.insorted\nBase.Sort.partialsort!\nBase.Sort.partialsort\nBase.Sort.partialsortperm\nBase.Sort.partialsortperm!","category":"page"},{"location":"base/sort/#Base.issorted","page":"排序及相关函数","title":"Base.issorted","text":"issorted(v, lt=isless, by=identity, rev::Bool=false, order::Ordering=Forward)\n\nTest whether a vector is in sorted order. The lt, by and rev keywords modify what order is considered to be sorted just as they do for sort.\n\nExamples\n\njulia> issorted([1, 2, 3])\ntrue\n\njulia> issorted([(1, \"b\"), (2, \"a\")], by = x -> x[1])\ntrue\n\njulia> issorted([(1, \"b\"), (2, \"a\")], by = x -> x[2])\nfalse\n\njulia> issorted([(1, \"b\"), (2, \"a\")], by = x -> x[2], rev=true)\ntrue\n\n\n\n\n\n","category":"function"},{"location":"base/sort/#Base.Sort.searchsorted","page":"排序及相关函数","title":"Base.Sort.searchsorted","text":"searchsorted(a, x; by=, lt=, rev=false)\n\nReturn the range of indices of a which compare as equal to x (using binary search) according to the order specified by the by, lt and rev keywords, assuming that a is already sorted in that order. Return an empty range located at the insertion point if a does not contain values equal to x.\n\nSee also: insorted, searchsortedfirst, sort, findall.\n\nExamples\n\njulia> searchsorted([1, 2, 4, 5, 5, 7], 4) # single match\n3:3\n\njulia> searchsorted([1, 2, 4, 5, 5, 7], 5) # multiple matches\n4:5\n\njulia> searchsorted([1, 2, 4, 5, 5, 7], 3) # no match, insert in the middle\n3:2\n\njulia> searchsorted([1, 2, 4, 5, 5, 7], 9) # no match, insert at end\n7:6\n\njulia> searchsorted([1, 2, 4, 5, 5, 7], 0) # no match, insert at start\n1:0\n\n\n\n\n\n","category":"function"},{"location":"base/sort/#Base.Sort.searchsortedfirst","page":"排序及相关函数","title":"Base.Sort.searchsortedfirst","text":"searchsortedfirst(a, x; by=, lt=, rev=false)\n\nReturn the index of the first value in a greater than or equal to x, according to the specified order. Return lastindex(a) + 1 if x is greater than all values in a. a is assumed to be sorted.\n\nSee also: searchsortedlast, searchsorted, findfirst.\n\nExamples\n\njulia> searchsortedfirst([1, 2, 4, 5, 5, 7], 4) # single match\n3\n\njulia> searchsortedfirst([1, 2, 4, 5, 5, 7], 5) # multiple matches\n4\n\njulia> searchsortedfirst([1, 2, 4, 5, 5, 7], 3) # no match, insert in the middle\n3\n\njulia> searchsortedfirst([1, 2, 4, 5, 5, 7], 9) # no match, insert at end\n7\n\njulia> searchsortedfirst([1, 2, 4, 5, 5, 7], 0) # no match, insert at start\n1\n\n\n\n\n\n","category":"function"},{"location":"base/sort/#Base.Sort.searchsortedlast","page":"排序及相关函数","title":"Base.Sort.searchsortedlast","text":"searchsortedlast(a, x; by=, lt=, rev=false)\n\nReturn the index of the last value in a less than or equal to x, according to the specified order. Return firstindex(a) - 1 if x is less than all values in a. a is assumed to be sorted.\n\nExamples\n\njulia> searchsortedlast([1, 2, 4, 5, 5, 7], 4) # single match\n3\n\njulia> searchsortedlast([1, 2, 4, 5, 5, 7], 5) # multiple matches\n5\n\njulia> searchsortedlast([1, 2, 4, 5, 5, 7], 3) # no match, insert in the middle\n2\n\njulia> searchsortedlast([1, 2, 4, 5, 5, 7], 9) # no match, insert at end\n6\n\njulia> searchsortedlast([1, 2, 4, 5, 5, 7], 0) # no match, insert at start\n0\n\n\n\n\n\n","category":"function"},{"location":"base/sort/#Base.Sort.insorted","page":"排序及相关函数","title":"Base.Sort.insorted","text":"insorted(a, x; by=, lt=, rev=false) -> Bool\n\nDetermine whether an item is in the given sorted collection, in the sense that it is == to one of the values of the collection according to the order specified by the by, lt and rev keywords, assuming that a is already sorted in that order, see sort for the keywords.\n\nSee also in.\n\nExamples\n\njulia> insorted(4, [1, 2, 4, 5, 5, 7]) # single match\ntrue\n\njulia> insorted(5, [1, 2, 4, 5, 5, 7]) # multiple matches\ntrue\n\njulia> insorted(3, [1, 2, 4, 5, 5, 7]) # no match\nfalse\n\njulia> insorted(9, [1, 2, 4, 5, 5, 7]) # no match\nfalse\n\njulia> insorted(0, [1, 2, 4, 5, 5, 7]) # no match\nfalse\n\ncompat: Julia 1.6\ninsorted was added in Julia 1.6.\n\n\n\n\n\n","category":"function"},{"location":"base/sort/#Base.Sort.partialsort!","page":"排序及相关函数","title":"Base.Sort.partialsort!","text":"partialsort!(v, k; by=, lt=, rev=false)\n\nPartially sort the vector v in place, according to the order specified by by, lt and rev so that the value at index k (or range of adjacent values if k is a range) occurs at the position where it would appear if the array were fully sorted via a non-stable algorithm. If k is a single index, that value is returned; if k is a range, an array of values at those indices is returned. Note that partialsort! does not fully sort the input array.\n\nExamples\n\njulia> a = [1, 2, 4, 3, 4]\n5-element Vector{Int64}:\n 1\n 2\n 4\n 3\n 4\n\njulia> partialsort!(a, 4)\n4\n\njulia> a\n5-element Vector{Int64}:\n 1\n 2\n 3\n 4\n 4\n\njulia> a = [1, 2, 4, 3, 4]\n5-element Vector{Int64}:\n 1\n 2\n 4\n 3\n 4\n\njulia> partialsort!(a, 4, rev=true)\n2\n\njulia> a\n5-element Vector{Int64}:\n 4\n 4\n 3\n 2\n 1\n\n\n\n\n\n","category":"function"},{"location":"base/sort/#Base.Sort.partialsort","page":"排序及相关函数","title":"Base.Sort.partialsort","text":"partialsort(v, k, by=, lt=, rev=false)\n\nVariant of partialsort! which copies v before partially sorting it, thereby returning the same thing as partialsort! but leaving v unmodified.\n\n\n\n\n\n","category":"function"},{"location":"base/sort/#Base.Sort.partialsortperm","page":"排序及相关函数","title":"Base.Sort.partialsortperm","text":"partialsortperm(v, k; by=, lt=, rev=false)\n\nReturn a partial permutation I of the vector v, so that v[I] returns values of a fully sorted version of v at index k. If k is a range, a vector of indices is returned; if k is an integer, a single index is returned. The order is specified using the same keywords as sort!. The permutation is stable, meaning that indices of equal elements appear in ascending order.\n\nNote that this function is equivalent to, but more efficient than, calling sortperm(...)[k].\n\nExamples\n\njulia> v = [3, 1, 2, 1];\n\njulia> v[partialsortperm(v, 1)]\n1\n\njulia> p = partialsortperm(v, 1:3)\n3-element view(::Vector{Int64}, 1:3) with eltype Int64:\n 2\n 4\n 3\n\njulia> v[p]\n3-element Vector{Int64}:\n 1\n 1\n 2\n\n\n\n\n\n","category":"function"},{"location":"base/sort/#Base.Sort.partialsortperm!","page":"排序及相关函数","title":"Base.Sort.partialsortperm!","text":"partialsortperm!(ix, v, k; by=, lt=, rev=false, initialized=false)\n\nLike partialsortperm, but accepts a preallocated index vector ix the same size as v, which is used to store (a permutation of) the indices of v.\n\nIf the index vector ix is initialized with the indices of v (or a permutation thereof), initialized should be set to true.\n\nIf initialized is false (the default), then ix is initialized to contain the indices of v.\n\nIf initialized is true, but ix does not contain (a permutation of) the indices of v, the behavior of partialsortperm! is undefined.\n\n(Typically, the indices of v will be 1:length(v), although if v has an alternative array type with non-one-based indices, such as an OffsetArray, ix must also be an OffsetArray with the same indices, and must contain as values (a permutation of) these same indices.)\n\nUpon return, ix is guaranteed to have the indices k in their sorted positions, such that\n\npartialsortperm!(ix, v, k);\nv[ix[k]] == partialsort(v, k)\n\nThe return value is the kth element of ix if k is an integer, or view into ix if k is a range.\n\nExamples\n\njulia> v = [3, 1, 2, 1];\n\njulia> ix = Vector{Int}(undef, 4);\n\njulia> partialsortperm!(ix, v, 1)\n2\n\njulia> ix = [1:4;];\n\njulia> partialsortperm!(ix, v, 2:3, initialized=true)\n2-element view(::Vector{Int64}, 2:3) with eltype Int64:\n 4\n 3\n\n\n\n\n\n\n\n","category":"function"},{"location":"base/sort/#排序算法","page":"排序及相关函数","title":"排序算法","text":"","category":"section"},{"location":"base/sort/","page":"排序及相关函数","title":"排序及相关函数","text":"目前,Julia Base 中有四种可用的排序算法:","category":"page"},{"location":"base/sort/","page":"排序及相关函数","title":"排序及相关函数","text":"InsertionSort\nQuickSort\nPartialQuickSort(k)\nMergeSort","category":"page"},{"location":"base/sort/","page":"排序及相关函数","title":"排序及相关函数","text":"InsertionSort 是一个在 QuickSort 中使用的时间复杂度为 O(n^2) 的稳定的排序算法,它通常在 n 比较小的时候才具有较高的效率。","category":"page"},{"location":"base/sort/","page":"排序及相关函数","title":"排序及相关函数","text":"QuickSort 是一个内置并且非常快,但是不稳定的时间复杂度为 O(n log n)的排序算法,例如即使数组两个元素相等的,它们排序之后的顺序也可能和在原数组中顺序不一致。QuickSort 是内置的包括整数和浮点数在内的数字值的默认排序算法。","category":"page"},{"location":"base/sort/","page":"排序及相关函数","title":"排序及相关函数","text":"PartialQuickSort(k) 类似于 QuickSort,但是如果 k 是一个整数,输出数组只排序到索引 k,如果 k 是 OrdinalRange,则输出数组排在 k 范围内。 例如:","category":"page"},{"location":"base/sort/","page":"排序及相关函数","title":"排序及相关函数","text":"x = rand(1:500, 100)\nk = 50\nk2 = 50:100\ns = sort(x; alg=QuickSort)\nps = sort(x; alg=PartialQuickSort(k))\nqs = sort(x; alg=PartialQuickSort(k2))\nmap(issorted, (s, ps, qs)) # => (true, false, false)\nmap(x->issorted(x[1:k]), (s, ps, qs)) # => (true, true, false)\nmap(x->issorted(x[k2]), (s, ps, qs)) # => (true, false, true)\ns[1:k] == ps[1:k] # => true\ns[k2] == qs[k2] # => true","category":"page"},{"location":"base/sort/","page":"排序及相关函数","title":"排序及相关函数","text":"MergeSort 是一个时间复杂度为 O(n log n) 的稳定但是非 in-place 的算法,它需要一个大小为输入数组一般的临时数组——同时也不像 QuickSort 一样快。MergeSort 是非数值型数据的默认排序算法。","category":"page"},{"location":"base/sort/","page":"排序及相关函数","title":"排序及相关函数","text":"默认排序算法的选择是基于它们的快速稳定,或者 appear 之类的。对于数值类型,实际上选择了 QuickSort,因为在这种情况下,它更快,与稳定排序没有区别(除非数组以某种方式记录了突变)","category":"page"},{"location":"base/sort/","page":"排序及相关函数","title":"排序及相关函数","text":"Julia选择默认排序算法的机制是通过 Base.Sort.defalg 来实现的,其允许将特定算法注册为特定数组的所有排序函数中的默认值。例如,这有两个默认算法 sort.jl:","category":"page"},{"location":"base/sort/","page":"排序及相关函数","title":"排序及相关函数","text":"defalg(v::AbstractArray) = MergeSort\ndefalg(v::AbstractArray{<:Number}) = QuickSort","category":"page"},{"location":"base/sort/","page":"排序及相关函数","title":"排序及相关函数","text":"对于数值型数组,选择非稳定的默认排序算法的原则是稳定的排序算法没有必要的(例如:但两个值相比较时相等且不可区分时)。","category":"page"},{"location":"base/sort/#Alternate-orderings","page":"排序及相关函数","title":"Alternate orderings","text":"","category":"section"},{"location":"base/sort/","page":"排序及相关函数","title":"排序及相关函数","text":"By default, sort and related functions use isless to compare two elements in order to determine which should come first. The Base.Order.Ordering abstract type provides a mechanism for defining alternate orderings on the same set of elements. Instances of Ordering define a total order on a set of elements, so that for any elements a, b, c the following hold:","category":"page"},{"location":"base/sort/","page":"排序及相关函数","title":"排序及相关函数","text":"Exactly one of the following is true: a is less than b, b is less than a, or a and b are equal (according to isequal).\nThe relation is transitive - if a is less than b and b is less than c then a is less than c.","category":"page"},{"location":"base/sort/","page":"排序及相关函数","title":"排序及相关函数","text":"The Base.Order.lt function works as a generalization of isless to test whether a is less than b according to a given order.","category":"page"},{"location":"base/sort/","page":"排序及相关函数","title":"排序及相关函数","text":"Base.Order.Ordering\nBase.Order.lt\nBase.Order.ord\nBase.Order.Forward\nBase.Order.ReverseOrdering\nBase.Order.Reverse\nBase.Order.By\nBase.Order.Lt\nBase.Order.Perm","category":"page"},{"location":"base/sort/#Base.Order.Ordering","page":"排序及相关函数","title":"Base.Order.Ordering","text":"Base.Order.Ordering\n\nAbstract type which represents a total order on some set of elements.\n\nUse Base.Order.lt to compare two elements according to the ordering.\n\n\n\n\n\n","category":"type"},{"location":"base/sort/#Base.Order.lt","page":"排序及相关函数","title":"Base.Order.lt","text":"lt(o::Ordering, a, b)\n\nTest whether a is less than b according to the ordering o.\n\n\n\n\n\n","category":"function"},{"location":"base/sort/#Base.Order.ord","page":"排序及相关函数","title":"Base.Order.ord","text":"ord(lt, by, rev::Union{Bool, Nothing}, order::Ordering=Forward)\n\nConstruct an Ordering object from the same arguments used by sort!. Elements are first transformed by the function by (which may be identity) and are then compared according to either the function lt or an existing ordering order. lt should be isless or a function which obeys similar rules. Finally, the resulting order is reversed if rev=true.\n\nPassing an lt other than isless along with an order other than Base.Order.Forward or Base.Order.Reverse is not permitted, otherwise all options are independent and can be used together in all possible combinations.\n\n\n\n\n\n","category":"function"},{"location":"base/sort/#Base.Order.Forward","page":"排序及相关函数","title":"Base.Order.Forward","text":"Base.Order.Forward\n\nDefault ordering according to isless.\n\n\n\n\n\n","category":"constant"},{"location":"base/sort/#Base.Order.ReverseOrdering","page":"排序及相关函数","title":"Base.Order.ReverseOrdering","text":"ReverseOrdering(fwd::Ordering=Forward)\n\nA wrapper which reverses an ordering.\n\nFor a given Ordering o, the following holds for all a, b:\n\nlt(ReverseOrdering(o), a, b) == lt(o, b, a)\n\n\n\n\n\n","category":"type"},{"location":"base/sort/#Base.Order.Reverse","page":"排序及相关函数","title":"Base.Order.Reverse","text":"Base.Order.Reverse\n\nReverse ordering according to isless.\n\n\n\n\n\n","category":"constant"},{"location":"base/sort/#Base.Order.By","page":"排序及相关函数","title":"Base.Order.By","text":"By(by, order::Ordering=Forward)\n\nOrdering which applies order to elements after they have been transformed by the function by.\n\n\n\n\n\n","category":"type"},{"location":"base/sort/#Base.Order.Lt","page":"排序及相关函数","title":"Base.Order.Lt","text":"Lt(lt)\n\nOrdering which calls lt(a, b) to compare elements. lt should obey the same rules as implementations of isless.\n\n\n\n\n\n","category":"type"},{"location":"base/sort/#Base.Order.Perm","page":"排序及相关函数","title":"Base.Order.Perm","text":"Perm(order::Ordering, data::AbstractVector)\n\nOrdering on the indices of data where i is less than j if data[i] is less than data[j] according to order. In the case that data[i] and data[j] are equal, i and j are compared by numeric value.\n\n\n\n\n\n","category":"type"},{"location":"stdlib/Base64/#Base64","page":"Base64","title":"Base64","text":"","category":"section"},{"location":"stdlib/Base64/","page":"Base64","title":"Base64","text":"Base64.Base64\nBase64.Base64EncodePipe\nBase64.base64encode\nBase64.Base64DecodePipe\nBase64.base64decode\nBase64.stringmime","category":"page"},{"location":"stdlib/Base64/#Base64.Base64","page":"Base64","title":"Base64.Base64","text":"Base64\n\nFunctionality for base-64 encoded strings and IO.\n\n\n\n\n\n","category":"module"},{"location":"stdlib/Base64/#Base64.Base64EncodePipe","page":"Base64","title":"Base64.Base64EncodePipe","text":"Base64EncodePipe(ostream)\n\nReturn a new write-only I/O stream, which converts any bytes written to it into base64-encoded ASCII bytes written to ostream. Calling close on the Base64EncodePipe stream is necessary to complete the encoding (but does not close ostream).\n\nExamples\n\njulia> io = IOBuffer();\n\njulia> iob64_encode = Base64EncodePipe(io);\n\njulia> write(iob64_encode, \"Hello!\")\n6\n\njulia> close(iob64_encode);\n\njulia> str = String(take!(io))\n\"SGVsbG8h\"\n\njulia> String(base64decode(str))\n\"Hello!\"\n\n\n\n\n\n","category":"type"},{"location":"stdlib/Base64/#Base64.base64encode","page":"Base64","title":"Base64.base64encode","text":"base64encode(writefunc, args...; context=nothing)\nbase64encode(args...; context=nothing)\n\nGiven a write-like function writefunc, which takes an I/O stream as its first argument, base64encode(writefunc, args...) calls writefunc to write args... to a base64-encoded string, and returns the string. base64encode(args...) is equivalent to base64encode(write, args...): it converts its arguments into bytes using the standard write functions and returns the base64-encoded string.\n\nThe optional keyword argument context can be set to :key=>value pair or an IO or IOContext object whose attributes are used for the I/O stream passed to writefunc or write.\n\nSee also base64decode.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/Base64/#Base64.Base64DecodePipe","page":"Base64","title":"Base64.Base64DecodePipe","text":"Base64DecodePipe(istream)\n\nReturn a new read-only I/O stream, which decodes base64-encoded data read from istream.\n\nExamples\n\njulia> io = IOBuffer();\n\njulia> iob64_decode = Base64DecodePipe(io);\n\njulia> write(io, \"SGVsbG8h\")\n8\n\njulia> seekstart(io);\n\njulia> String(read(iob64_decode))\n\"Hello!\"\n\n\n\n\n\n","category":"type"},{"location":"stdlib/Base64/#Base64.base64decode","page":"Base64","title":"Base64.base64decode","text":"base64decode(string)\n\nDecode the base64-encoded string and returns a Vector{UInt8} of the decoded bytes.\n\nSee also base64encode.\n\nExamples\n\njulia> b = base64decode(\"SGVsbG8h\")\n6-element Vector{UInt8}:\n 0x48\n 0x65\n 0x6c\n 0x6c\n 0x6f\n 0x21\n\njulia> String(b)\n\"Hello!\"\n\n\n\n\n\n","category":"function"},{"location":"stdlib/Base64/#Base64.stringmime","page":"Base64","title":"Base64.stringmime","text":"stringmime(mime, x; context=nothing)\n\nReturns an AbstractString containing the representation of x in the requested mime type. This is similar to repr(mime, x) except that binary data is base64-encoded as an ASCII string.\n\nThe optional keyword argument context can be set to :key=>value pair or an IO or IOContext object whose attributes are used for the I/O stream passed to show.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/FileWatching/#文件相关事件","page":"文件相关事件","title":"文件相关事件","text":"","category":"section"},{"location":"stdlib/FileWatching/","page":"文件相关事件","title":"文件相关事件","text":"FileWatching.poll_fd\nFileWatching.poll_file\nFileWatching.watch_file\nFileWatching.watch_folder\nFileWatching.unwatch_folder","category":"page"},{"location":"stdlib/FileWatching/#FileWatching.poll_fd","page":"文件相关事件","title":"FileWatching.poll_fd","text":"poll_fd(fd, timeout_s::Real=-1; readable=false, writable=false)\n\nMonitor a file descriptor fd for changes in the read or write availability, and with a timeout given by timeout_s seconds.\n\nThe keyword arguments determine which of read and/or write status should be monitored; at least one of them must be set to true.\n\nThe returned value is an object with boolean fields readable, writable, and timedout, giving the result of the polling.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/FileWatching/#FileWatching.poll_file","page":"文件相关事件","title":"FileWatching.poll_file","text":"poll_file(path::AbstractString, interval_s::Real=5.007, timeout_s::Real=-1) -> (previous::StatStruct, current)\n\nMonitor a file for changes by polling every interval_s seconds until a change occurs or timeout_s seconds have elapsed. The interval_s should be a long period; the default is 5.007 seconds.\n\nReturns a pair of status objects (previous, current) when a change is detected. The previous status is always a StatStruct, but it may have all of the fields zeroed (indicating the file didn't previously exist, or wasn't previously accessible).\n\nThe current status object may be a StatStruct, an EOFError (indicating the timeout elapsed), or some other Exception subtype (if the stat operation failed - for example, if the path does not exist).\n\nTo determine when a file was modified, compare current isa StatStruct && mtime(prev) != mtime(current) to detect notification of changes. However, using watch_file for this operation is preferred, since it is more reliable and efficient, although in some situations it may not be available.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/FileWatching/#FileWatching.watch_file","page":"文件相关事件","title":"FileWatching.watch_file","text":"watch_file(path::AbstractString, timeout_s::Real=-1)\n\nWatch file or directory path for changes until a change occurs or timeout_s seconds have elapsed.\n\nThe returned value is an object with boolean fields changed, renamed, and timedout, giving the result of watching the file.\n\nThis behavior of this function varies slightly across platforms. See https://nodejs.org/api/fs.html#fs_caveats for more detailed information.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/FileWatching/#FileWatching.watch_folder","page":"文件相关事件","title":"FileWatching.watch_folder","text":"watch_folder(path::AbstractString, timeout_s::Real=-1)\n\nWatches a file or directory path for changes until a change has occurred or timeout_s seconds have elapsed.\n\nThis will continuing tracking changes for path in the background until unwatch_folder is called on the same path.\n\nThe returned value is an pair where the first field is the name of the changed file (if available) and the second field is an object with boolean fields changed, renamed, and timedout, giving the event.\n\nThis behavior of this function varies slightly across platforms. See https://nodejs.org/api/fs.html#fs_caveats for more detailed information.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/FileWatching/#FileWatching.unwatch_folder","page":"文件相关事件","title":"FileWatching.unwatch_folder","text":"unwatch_folder(path::AbstractString)\n\nStop background tracking of changes for path. It is not recommended to do this while another task is waiting for watch_folder to return on the same path, as the result may be unpredictable.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/Logging/#日志记录","page":"日志记录","title":"日志记录","text":"","category":"section"},{"location":"stdlib/Logging/","page":"日志记录","title":"日志记录","text":"Logging 模块提供了一个将历史和计算进度记录为事件的日志。事件通过在源代码里插入日志语句产生,例如:","category":"page"},{"location":"stdlib/Logging/","page":"日志记录","title":"日志记录","text":"@warn \"Abandon printf debugging, all ye who enter here!\"\n┌ Warning: Abandon printf debugging, all ye who enter here!\n└ @ Main REPL[1]:1","category":"page"},{"location":"stdlib/Logging/","page":"日志记录","title":"日志记录","text":"The system provides several advantages over peppering your source code with calls to println(). First, it allows you to control the visibility and presentation of messages without editing the source code. For example, in contrast to the @warn above","category":"page"},{"location":"stdlib/Logging/","page":"日志记录","title":"日志记录","text":"@debug \"The sum of some values $(sum(rand(100)))\"","category":"page"},{"location":"stdlib/Logging/","page":"日志记录","title":"日志记录","text":"will produce no output by default. Furthermore, it's very cheap to leave debug statements like this in the source code because the system avoids evaluating the message if it would later be ignored. In this case sum(rand(100)) and the associated string processing will never be executed unless debug logging is enabled.","category":"page"},{"location":"stdlib/Logging/","page":"日志记录","title":"日志记录","text":"Second, the logging tools allow you to attach arbitrary data to each event as a set of key–value pairs. This allows you to capture local variables and other program state for later analysis. For example, to attach the local array variable A and the sum of a vector v as the key s you can use","category":"page"},{"location":"stdlib/Logging/","page":"日志记录","title":"日志记录","text":"A = ones(Int, 4, 4)\nv = ones(100)\n@info \"Some variables\" A s=sum(v)\n\n# output\n┌ Info: Some variables\n│ A =\n│ 4×4 Matrix{Int64}:\n│ 1 1 1 1\n│ 1 1 1 1\n│ 1 1 1 1\n│ 1 1 1 1\n└ s = 100.0","category":"page"},{"location":"stdlib/Logging/","page":"日志记录","title":"日志记录","text":"所有的日志宏如 @debug, @info, @warn 和 @error 有着共同的特征, 这些共同特征在更通用的宏 @logmsg 的文档里有细致说明。","category":"page"},{"location":"stdlib/Logging/#日志事件结构","page":"日志记录","title":"日志事件结构","text":"","category":"section"},{"location":"stdlib/Logging/","page":"日志记录","title":"日志记录","text":"Each event generates several pieces of data, some provided by the user and some automatically extracted. Let's examine the user-defined data first:","category":"page"},{"location":"stdlib/Logging/","page":"日志记录","title":"日志记录","text":"The log level is a broad category for the message that is used for early filtering. There are several standard levels of type LogLevel; user-defined levels are also possible. Each is distinct in purpose:\nLogging.Debug (log level -1000) is information intended for the developer of the program. These events are disabled by default.\nLogging.Info (log level 0) is for general information to the user. Think of it as an alternative to using println directly.\nLogging.Warn (log level 1000) means something is wrong and action is likely required but that for now the program is still working.\nLogging.Error (log level 2000) means something is wrong and it is unlikely to be recovered, at least by this part of the code. Often this log-level is unneeded as throwing an exception can convey all the required information.\nThe message is an object describing the event. By convention AbstractStrings passed as messages are assumed to be in markdown format. Other types will be displayed using print(io, obj) or string(obj) for text-based output and possibly show(io,mime,obj) for other multimedia displays used in the installed logger.\nOptional key–value pairs allow arbitrary data to be attached to each event. Some keys have conventional meaning that can affect the way an event is interpreted (see @logmsg).","category":"page"},{"location":"stdlib/Logging/","page":"日志记录","title":"日志记录","text":"The system also generates some standard information for each event:","category":"page"},{"location":"stdlib/Logging/","page":"日志记录","title":"日志记录","text":"The module in which the logging macro was expanded.\nThe file and line where the logging macro occurs in the source code.\nA message id that is a unique, fixed identifier for the source code statement where the logging macro appears. This identifier is designed to be fairly stable even if the source code of the file changes, as long as the logging statement itself remains the same.\nA group for the event, which is set to the base name of the file by default, without extension. This can be used to group messages into categories more finely than the log level (for example, all deprecation warnings have group :depwarn), or into logical groupings across or within modules.","category":"page"},{"location":"stdlib/Logging/","page":"日志记录","title":"日志记录","text":"Notice that some useful information such as the event time is not included by default. This is because such information can be expensive to extract and is also dynamically available to the current logger. It's simple to define a custom logger to augment event data with the time, backtrace, values of global variables and other useful information as required.","category":"page"},{"location":"stdlib/Logging/#Processing-log-events","page":"日志记录","title":"Processing log events","text":"","category":"section"},{"location":"stdlib/Logging/","page":"日志记录","title":"日志记录","text":"As you can see in the examples, logging statements make no mention of where log events go or how they are processed. This is a key design feature that makes the system composable and natural for concurrent use. It does this by separating two different concerns:","category":"page"},{"location":"stdlib/Logging/","page":"日志记录","title":"日志记录","text":"Creating log events is the concern of the module author who needs to decide where events are triggered and which information to include.\nProcessing of log events — that is, display, filtering, aggregation and recording — is the concern of the application author who needs to bring multiple modules together into a cooperating application.","category":"page"},{"location":"stdlib/Logging/#Loggers","page":"日志记录","title":"Loggers","text":"","category":"section"},{"location":"stdlib/Logging/","page":"日志记录","title":"日志记录","text":"Processing of events is performed by a logger, which is the first piece of user configurable code to see the event. All loggers must be subtypes of AbstractLogger.","category":"page"},{"location":"stdlib/Logging/","page":"日志记录","title":"日志记录","text":"When an event is triggered, the appropriate logger is found by looking for a task-local logger with the global logger as fallback. The idea here is that the application code knows how log events should be processed and exists somewhere at the top of the call stack. So we should look up through the call stack to discover the logger — that is, the logger should be dynamically scoped. (This is a point of contrast with logging frameworks where the logger is lexically scoped; provided explicitly by the module author or as a simple global variable. In such a system it's awkward to control logging while composing functionality from multiple modules.)","category":"page"},{"location":"stdlib/Logging/","page":"日志记录","title":"日志记录","text":"The global logger may be set with global_logger, and task-local loggers controlled using with_logger. Newly spawned tasks inherit the logger of the parent task.","category":"page"},{"location":"stdlib/Logging/","page":"日志记录","title":"日志记录","text":"There are three logger types provided by the library. ConsoleLogger is the default logger you see when starting the REPL. It displays events in a readable text format and tries to give simple but user friendly control over formatting and filtering. NullLogger is a convenient way to drop all messages where necessary; it is the logging equivalent of the devnull stream. SimpleLogger is a very simplistic text formatting logger, mainly useful for debugging the logging system itself.","category":"page"},{"location":"stdlib/Logging/","page":"日志记录","title":"日志记录","text":"Custom loggers should come with overloads for the functions described in the reference section.","category":"page"},{"location":"stdlib/Logging/#Early-filtering-and-message-handling","page":"日志记录","title":"Early filtering and message handling","text":"","category":"section"},{"location":"stdlib/Logging/","page":"日志记录","title":"日志记录","text":"When an event occurs, a few steps of early filtering occur to avoid generating messages that will be discarded:","category":"page"},{"location":"stdlib/Logging/","page":"日志记录","title":"日志记录","text":"The message log level is checked against a global minimum level (set via disable_logging). This is a crude but extremely cheap global setting.\nThe current logger state is looked up and the message level checked against the logger's cached minimum level, as found by calling Logging.min_enabled_level. This behavior can be overridden via environment variables (more on this later).\nThe Logging.shouldlog function is called with the current logger, taking some minimal information (level, module, group, id) which can be computed statically. Most usefully, shouldlog is passed an event id which can be used to discard events early based on a cached predicate.","category":"page"},{"location":"stdlib/Logging/","page":"日志记录","title":"日志记录","text":"If all these checks pass, the message and key–value pairs are evaluated in full and passed to the current logger via the Logging.handle_message function. handle_message() may perform additional filtering as required and display the event to the screen, save it to a file, etc.","category":"page"},{"location":"stdlib/Logging/","page":"日志记录","title":"日志记录","text":"Exceptions that occur while generating the log event are captured and logged by default. This prevents individual broken events from crashing the application, which is helpful when enabling little-used debug events in a production system. This behavior can be customized per logger type by extending Logging.catch_exceptions.","category":"page"},{"location":"stdlib/Logging/#Testing-log-events","page":"日志记录","title":"Testing log events","text":"","category":"section"},{"location":"stdlib/Logging/","page":"日志记录","title":"日志记录","text":"Log events are a side effect of running normal code, but you might find yourself wanting to test particular informational messages and warnings. The Test module provides a @test_logs macro that can be used to pattern match against the log event stream.","category":"page"},{"location":"stdlib/Logging/#Environment-variables","page":"日志记录","title":"Environment variables","text":"","category":"section"},{"location":"stdlib/Logging/","page":"日志记录","title":"日志记录","text":"Message filtering can be influenced through the JULIA_DEBUG environment variable, and serves as an easy way to enable debug logging for a file or module. For example, loading julia with JULIA_DEBUG=loading will activate @debug log messages in loading.jl:","category":"page"},{"location":"stdlib/Logging/","page":"日志记录","title":"日志记录","text":"$ JULIA_DEBUG=loading julia -e 'using OhMyREPL'\n┌ Debug: Rejecting cache file /home/user/.julia/compiled/v0.7/OhMyREPL.ji due to it containing an invalid cache header\n└ @ Base loading.jl:1328\n[ Info: Recompiling stale cache file /home/user/.julia/compiled/v0.7/OhMyREPL.ji for module OhMyREPL\n┌ Debug: Rejecting cache file /home/user/.julia/compiled/v0.7/Tokenize.ji due to it containing an invalid cache header\n└ @ Base loading.jl:1328\n...","category":"page"},{"location":"stdlib/Logging/","page":"日志记录","title":"日志记录","text":"Similarly, the environment variable can be used to enable debug logging of modules, such as Pkg, or module roots (see Base.moduleroot). To enable all debug logging, use the special value all.","category":"page"},{"location":"stdlib/Logging/","page":"日志记录","title":"日志记录","text":"To turn debug logging on from the REPL, set ENV[\"JULIA_DEBUG\"] to the name of the module of interest. Functions defined in the REPL belong to module Main; logging for them can be enabled like this:","category":"page"},{"location":"stdlib/Logging/","page":"日志记录","title":"日志记录","text":"julia> foo() = @debug \"foo\"\nfoo (generic function with 1 method)\n\njulia> foo()\n\njulia> ENV[\"JULIA_DEBUG\"] = Main\nMain\n\njulia> foo()\n┌ Debug: foo\n└ @ Main REPL[1]:1\n","category":"page"},{"location":"stdlib/Logging/#Examples","page":"日志记录","title":"Examples","text":"","category":"section"},{"location":"stdlib/Logging/#Example:-Writing-log-events-to-a-file","page":"日志记录","title":"Example: Writing log events to a file","text":"","category":"section"},{"location":"stdlib/Logging/","page":"日志记录","title":"日志记录","text":"Sometimes it can be useful to write log events to a file. Here is an example of how to use a task-local and global logger to write information to a text file:","category":"page"},{"location":"stdlib/Logging/","page":"日志记录","title":"日志记录","text":"# Load the logging module\njulia> using Logging\n\n# Open a textfile for writing\njulia> io = open(\"log.txt\", \"w+\")\nIOStream()\n\n# Create a simple logger\njulia> logger = SimpleLogger(io)\nSimpleLogger(IOStream(), Info, Dict{Any,Int64}())\n\n# Log a task-specific message\njulia> with_logger(logger) do\n @info(\"a context specific log message\")\n end\n\n# Write all buffered messages to the file\njulia> flush(io)\n\n# Set the global logger to logger\njulia> global_logger(logger)\nSimpleLogger(IOStream(), Info, Dict{Any,Int64}())\n\n# This message will now also be written to the file\njulia> @info(\"a global log message\")\n\n# Close the file\njulia> close(io)","category":"page"},{"location":"stdlib/Logging/#Example:-Enable-debug-level-messages","page":"日志记录","title":"Example: Enable debug-level messages","text":"","category":"section"},{"location":"stdlib/Logging/","page":"日志记录","title":"日志记录","text":"Here is an example of creating a ConsoleLogger that lets through any messages with log level higher than, or equal, to Logging.Debug.","category":"page"},{"location":"stdlib/Logging/","page":"日志记录","title":"日志记录","text":"julia> using Logging\n\n# Create a ConsoleLogger that prints any log messages with level >= Debug to stderr\njulia> debuglogger = ConsoleLogger(stderr, Logging.Debug)\n\n# Enable debuglogger for a task\njulia> with_logger(debuglogger) do\n @debug \"a context specific log message\"\n end\n\n# Set the global logger\njulia> global_logger(debuglogger)","category":"page"},{"location":"stdlib/Logging/#Reference","page":"日志记录","title":"Reference","text":"","category":"section"},{"location":"stdlib/Logging/#Logging-module","page":"日志记录","title":"Logging module","text":"","category":"section"},{"location":"stdlib/Logging/","page":"日志记录","title":"日志记录","text":"Logging.Logging","category":"page"},{"location":"stdlib/Logging/#Logging.Logging","page":"日志记录","title":"Logging.Logging","text":"Utilities for capturing, filtering and presenting streams of log events. Normally you don't need to import Logging to create log events; for this the standard logging macros such as @info are already exported by Base and available by default.\n\n\n\n\n\n","category":"module"},{"location":"stdlib/Logging/#Creating-events","page":"日志记录","title":"Creating events","text":"","category":"section"},{"location":"stdlib/Logging/","page":"日志记录","title":"日志记录","text":"Logging.@logmsg\nLogging.LogLevel\nLogging.Debug\nLogging.Info\nLogging.Warn\nLogging.Error","category":"page"},{"location":"stdlib/Logging/#Logging.@logmsg","page":"日志记录","title":"Logging.@logmsg","text":"@debug message [key=value | value ...]\n@info message [key=value | value ...]\n@warn message [key=value | value ...]\n@error message [key=value | value ...]\n\n@logmsg level message [key=value | value ...]\n\nCreate a log record with an informational message. For convenience, four logging macros @debug, @info, @warn and @error are defined which log at the standard severity levels Debug, Info, Warn and Error. @logmsg allows level to be set programmatically to any LogLevel or custom log level types.\n\nmessage should be an expression which evaluates to a string which is a human readable description of the log event. By convention, this string will be formatted as markdown when presented.\n\nThe optional list of key=value pairs supports arbitrary user defined metadata which will be passed through to the logging backend as part of the log record. If only a value expression is supplied, a key representing the expression will be generated using Symbol. For example, x becomes x=x, and foo(10) becomes Symbol(\"foo(10)\")=foo(10). For splatting a list of key value pairs, use the normal splatting syntax, @info \"blah\" kws....\n\nThere are some keys which allow automatically generated log data to be overridden:\n\n_module=mod can be used to specify a different originating module from the source location of the message.\n_group=symbol can be used to override the message group (this is normally derived from the base name of the source file).\n_id=symbol can be used to override the automatically generated unique message identifier. This is useful if you need to very closely associate messages generated on different source lines.\n_file=string and _line=integer can be used to override the apparent source location of a log message.\n\nThere's also some key value pairs which have conventional meaning:\n\nmaxlog=integer should be used as a hint to the backend that the message should be displayed no more than maxlog times.\nexception=ex should be used to transport an exception with a log message, often used with @error. An associated backtrace bt may be attached using the tuple exception=(ex,bt).\n\nExamples\n\n@debug \"Verbose debugging information. Invisible by default\"\n@info \"An informational message\"\n@warn \"Something was odd. You should pay attention\"\n@error \"A non fatal error occurred\"\n\nx = 10\n@info \"Some variables attached to the message\" x a=42.0\n\n@debug begin\n sA = sum(A)\n \"sum(A) = $sA is an expensive operation, evaluated only when `shouldlog` returns true\"\nend\n\nfor i=1:10000\n @info \"With the default backend, you will only see (i = $i) ten times\" maxlog=10\n @debug \"Algorithm1\" i progress=i/10000\nend\n\n\n\n\n\n","category":"macro"},{"location":"stdlib/Logging/#Logging.LogLevel","page":"日志记录","title":"Logging.LogLevel","text":"LogLevel(level)\n\nSeverity/verbosity of a log record.\n\nThe log level provides a key against which potential log records may be filtered, before any other work is done to construct the log record data structure itself.\n\nExamples\n\njulia> Logging.LogLevel(0) == Logging.Info\ntrue\n\n\n\n\n\n","category":"type"},{"location":"stdlib/Logging/#Logging.Debug","page":"日志记录","title":"Logging.Debug","text":"Debug\n\nAlias for LogLevel(-1000).\n\n\n\n\n\n","category":"constant"},{"location":"stdlib/Logging/#Logging.Info","page":"日志记录","title":"Logging.Info","text":"Info\n\nAlias for LogLevel(0).\n\n\n\n\n\n","category":"constant"},{"location":"stdlib/Logging/#Logging.Warn","page":"日志记录","title":"Logging.Warn","text":"Warn\n\nAlias for LogLevel(1000).\n\n\n\n\n\n","category":"constant"},{"location":"stdlib/Logging/#Logging.Error","page":"日志记录","title":"Logging.Error","text":"Error\n\nAlias for LogLevel(2000).\n\n\n\n\n\n","category":"constant"},{"location":"stdlib/Logging/#AbstractLogger-interface","page":"日志记录","title":"Processing events with AbstractLogger","text":"","category":"section"},{"location":"stdlib/Logging/","page":"日志记录","title":"日志记录","text":"Event processing is controlled by overriding functions associated with AbstractLogger:","category":"page"},{"location":"stdlib/Logging/","page":"日志记录","title":"日志记录","text":"Methods to implement Brief description\nLogging.handle_message Handle a log event\nLogging.shouldlog Early filtering of events\nLogging.min_enabled_level Lower bound for log level of accepted events\nOptional methods Default definition Brief description\nLogging.catch_exceptions true Catch exceptions during event evaluation","category":"page"},{"location":"stdlib/Logging/","page":"日志记录","title":"日志记录","text":"Logging.AbstractLogger\nLogging.handle_message\nLogging.shouldlog\nLogging.min_enabled_level\nLogging.catch_exceptions\nLogging.disable_logging","category":"page"},{"location":"stdlib/Logging/#Logging.AbstractLogger","page":"日志记录","title":"Logging.AbstractLogger","text":"A logger controls how log records are filtered and dispatched. When a log record is generated, the logger is the first piece of user configurable code which gets to inspect the record and decide what to do with it.\n\n\n\n\n\n","category":"type"},{"location":"stdlib/Logging/#Logging.handle_message","page":"日志记录","title":"Logging.handle_message","text":"handle_message(logger, level, message, _module, group, id, file, line; key1=val1, ...)\n\nLog a message to logger at level. The logical location at which the message was generated is given by module _module and group; the source location by file and line. id is an arbitrary unique value (typically a Symbol) to be used as a key to identify the log statement when filtering.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/Logging/#Logging.shouldlog","page":"日志记录","title":"Logging.shouldlog","text":"shouldlog(logger, level, _module, group, id)\n\nReturn true when logger accepts a message at level, generated for _module, group and with unique log identifier id.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/Logging/#Logging.min_enabled_level","page":"日志记录","title":"Logging.min_enabled_level","text":"min_enabled_level(logger)\n\nReturn the minimum enabled level for logger for early filtering. That is, the log level below or equal to which all messages are filtered.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/Logging/#Logging.catch_exceptions","page":"日志记录","title":"Logging.catch_exceptions","text":"catch_exceptions(logger)\n\nReturn true if the logger should catch exceptions which happen during log record construction. By default, messages are caught\n\nBy default all exceptions are caught to prevent log message generation from crashing the program. This lets users confidently toggle little-used functionality - such as debug logging - in a production system.\n\nIf you want to use logging as an audit trail you should disable this for your logger type.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/Logging/#Logging.disable_logging","page":"日志记录","title":"Logging.disable_logging","text":"disable_logging(level)\n\nDisable all log messages at log levels equal to or less than level. This is a global setting, intended to make debug logging extremely cheap when disabled.\n\nExamples\n\nLogging.disable_logging(Logging.Info) # Disable debug and info\n\n\n\n\n\n","category":"function"},{"location":"stdlib/Logging/#Using-Loggers","page":"日志记录","title":"Using Loggers","text":"","category":"section"},{"location":"stdlib/Logging/","page":"日志记录","title":"日志记录","text":"Logger installation and inspection:","category":"page"},{"location":"stdlib/Logging/","page":"日志记录","title":"日志记录","text":"Logging.global_logger\nLogging.with_logger\nLogging.current_logger","category":"page"},{"location":"stdlib/Logging/#Logging.global_logger","page":"日志记录","title":"Logging.global_logger","text":"global_logger()\n\nReturn the global logger, used to receive messages when no specific logger exists for the current task.\n\nglobal_logger(logger)\n\nSet the global logger to logger, and return the previous global logger.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/Logging/#Logging.with_logger","page":"日志记录","title":"Logging.with_logger","text":"with_logger(function, logger)\n\nExecute function, directing all log messages to logger.\n\nExample\n\nfunction test(x)\n @info \"x = $x\"\nend\n\nwith_logger(logger) do\n test(1)\n test([1,2])\nend\n\n\n\n\n\n","category":"function"},{"location":"stdlib/Logging/#Logging.current_logger","page":"日志记录","title":"Logging.current_logger","text":"current_logger()\n\nReturn the logger for the current task, or the global logger if none is attached to the task.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/Logging/","page":"日志记录","title":"日志记录","text":"Loggers that are supplied with the system:","category":"page"},{"location":"stdlib/Logging/","page":"日志记录","title":"日志记录","text":"Logging.NullLogger\nLogging.ConsoleLogger\nLogging.SimpleLogger","category":"page"},{"location":"stdlib/Logging/#Logging.NullLogger","page":"日志记录","title":"Logging.NullLogger","text":"NullLogger()\n\nLogger which disables all messages and produces no output - the logger equivalent of /dev/null.\n\n\n\n\n\n","category":"type"},{"location":"stdlib/Logging/#Logging.ConsoleLogger","page":"日志记录","title":"Logging.ConsoleLogger","text":"ConsoleLogger([stream,] min_level=Info; meta_formatter=default_metafmt,\n show_limited=true, right_justify=0)\n\nLogger with formatting optimized for readability in a text console, for example interactive work with the Julia REPL.\n\nLog levels less than min_level are filtered out.\n\nMessage formatting can be controlled by setting keyword arguments:\n\nmeta_formatter is a function which takes the log event metadata (level, _module, group, id, file, line) and returns a color (as would be passed to printstyled), prefix and suffix for the log message. The default is to prefix with the log level and a suffix containing the module, file and line location.\nshow_limited limits the printing of large data structures to something which can fit on the screen by setting the :limit IOContext key during formatting.\nright_justify is the integer column which log metadata is right justified at. The default is zero (metadata goes on its own line).\n\n\n\n\n\n","category":"type"},{"location":"stdlib/Logging/#Logging.SimpleLogger","page":"日志记录","title":"Logging.SimpleLogger","text":"SimpleLogger([stream,] min_level=Info)\n\nSimplistic logger for logging all messages with level greater than or equal to min_level to stream. If stream is closed then messages with log level greater or equal to Warn will be logged to stderr and below to stdout.\n\n\n\n\n\n","category":"type"},{"location":"devdocs/valgrind/#在Julia中使用Valgrind","page":"在Julia中使用Valgrind","title":"在Julia中使用Valgrind","text":"","category":"section"},{"location":"devdocs/valgrind/","page":"在Julia中使用Valgrind","title":"在Julia中使用Valgrind","text":"Valgrind is a tool for memory debugging, memory leak detection, and profiling. This section describes things to keep in mind when using Valgrind to debug memory issues with Julia.","category":"page"},{"location":"devdocs/valgrind/#General-considerations","page":"在Julia中使用Valgrind","title":"General considerations","text":"","category":"section"},{"location":"devdocs/valgrind/","page":"在Julia中使用Valgrind","title":"在Julia中使用Valgrind","text":"By default, Valgrind assumes that there is no self modifying code in the programs it runs. This assumption works fine in most instances but fails miserably for a just-in-time compiler like julia. For this reason it is crucial to pass --smc-check=all-non-file to valgrind, else code may crash or behave unexpectedly (often in subtle ways).","category":"page"},{"location":"devdocs/valgrind/","page":"在Julia中使用Valgrind","title":"在Julia中使用Valgrind","text":"In some cases, to better detect memory errors using Valgrind it can help to compile julia with memory pools disabled. The compile-time flag MEMDEBUG disables memory pools in Julia, and MEMDEBUG2 disables memory pools in FemtoLisp. To build julia with both flags, add the following line to Make.user:","category":"page"},{"location":"devdocs/valgrind/","page":"在Julia中使用Valgrind","title":"在Julia中使用Valgrind","text":"CFLAGS = -DMEMDEBUG -DMEMDEBUG2","category":"page"},{"location":"devdocs/valgrind/","page":"在Julia中使用Valgrind","title":"在Julia中使用Valgrind","text":"Another thing to note: if your program uses multiple workers processes, it is likely that you want all such worker processes to run under Valgrind, not just the parent process. To do this, pass --trace-children=yes to valgrind.","category":"page"},{"location":"devdocs/valgrind/#Suppressions","page":"在Julia中使用Valgrind","title":"Suppressions","text":"","category":"section"},{"location":"devdocs/valgrind/","page":"在Julia中使用Valgrind","title":"在Julia中使用Valgrind","text":"Valgrind will typically display spurious warnings as it runs. To reduce the number of such warnings, it helps to provide a suppressions file to Valgrind. A sample suppressions file is included in the Julia source distribution at contrib/valgrind-julia.supp.","category":"page"},{"location":"devdocs/valgrind/","page":"在Julia中使用Valgrind","title":"在Julia中使用Valgrind","text":"The suppressions file can be used from the julia/ source directory as follows:","category":"page"},{"location":"devdocs/valgrind/","page":"在Julia中使用Valgrind","title":"在Julia中使用Valgrind","text":"$ valgrind --smc-check=all-non-file --suppressions=contrib/valgrind-julia.supp ./julia progname.jl","category":"page"},{"location":"devdocs/valgrind/","page":"在Julia中使用Valgrind","title":"在Julia中使用Valgrind","text":"Any memory errors that are displayed should either be reported as bugs or contributed as additional suppressions. Note that some versions of Valgrind are shipped with insufficient default suppressions, so that may be one thing to consider before submitting any bugs.","category":"page"},{"location":"devdocs/valgrind/#Running-the-Julia-test-suite-under-Valgrind","page":"在Julia中使用Valgrind","title":"Running the Julia test suite under Valgrind","text":"","category":"section"},{"location":"devdocs/valgrind/","page":"在Julia中使用Valgrind","title":"在Julia中使用Valgrind","text":"It is possible to run the entire Julia test suite under Valgrind, but it does take quite some time (typically several hours). To do so, run the following command from the julia/test/ directory:","category":"page"},{"location":"devdocs/valgrind/","page":"在Julia中使用Valgrind","title":"在Julia中使用Valgrind","text":"valgrind --smc-check=all-non-file --trace-children=yes --suppressions=$PWD/../contrib/valgrind-julia.supp ../julia runtests.jl all","category":"page"},{"location":"devdocs/valgrind/","page":"在Julia中使用Valgrind","title":"在Julia中使用Valgrind","text":"If you would like to see a report of \"definite\" memory leaks, pass the flags --leak-check=full --show-leak-kinds=definite to valgrind as well.","category":"page"},{"location":"devdocs/valgrind/#Caveats","page":"在Julia中使用Valgrind","title":"Caveats","text":"","category":"section"},{"location":"devdocs/valgrind/","page":"在Julia中使用Valgrind","title":"在Julia中使用Valgrind","text":"Valgrind currently does not support multiple rounding modes, so code that adjusts the rounding mode will behave differently when run under Valgrind.","category":"page"},{"location":"devdocs/valgrind/","page":"在Julia中使用Valgrind","title":"在Julia中使用Valgrind","text":"In general, if after setting --smc-check=all-non-file you find that your program behaves differently when run under Valgrind, it may help to pass --tool=none to valgrind as you investigate further. This will enable the minimal Valgrind machinery but will also run much faster than when the full memory checker is enabled.","category":"page"},{"location":"manual/metaprogramming/#Metaprogramming","page":"元编程","title":"元编程","text":"","category":"section"},{"location":"manual/metaprogramming/","page":"元编程","title":"元编程","text":"Lisp 留给 Julia 最大的遗产就是它的元编程支持。和 Lisp 一样,Julia 把自己的代码表示为语言中的数据结构。既然代码被表示为了可以在语言中创建和操作的对象,程序就可以变换和生成自己的代码。这允许在没有额外构建步骤的情况下生成复杂的代码,并且还允许在 abstract syntax trees 级别上运行的真正的 Lisp 风格的宏。与之相对的是预处理器“宏”系统,比如 C 和 C++ 中的,它们在解析和解释代码之前进行文本操作和变换。由于 Julia 中的所有数据类型和代码都被表示为 Julia 的 数据结构,强大的 reflection 功能可用于探索程序的内部及其类型,就像任何其他数据一样。","category":"page"},{"location":"manual/metaprogramming/#程序表示","page":"元编程","title":"程序表示","text":"","category":"section"},{"location":"manual/metaprogramming/","page":"元编程","title":"元编程","text":"每个 Julia 程序均以字符串开始:","category":"page"},{"location":"manual/metaprogramming/","page":"元编程","title":"元编程","text":"julia> prog = \"1 + 1\"\n\"1 + 1\"","category":"page"},{"location":"manual/metaprogramming/","page":"元编程","title":"元编程","text":"接下来会发生什么?","category":"page"},{"location":"manual/metaprogramming/","page":"元编程","title":"元编程","text":"下一步是 parse 每个字符串到一个称为表达式的对象,由 Julia 的类型 Expr 表示:","category":"page"},{"location":"manual/metaprogramming/","page":"元编程","title":"元编程","text":"julia> ex1 = Meta.parse(prog)\n:(1 + 1)\n\njulia> typeof(ex1)\nExpr","category":"page"},{"location":"manual/metaprogramming/","page":"元编程","title":"元编程","text":"Expr 对象包含两个部分:","category":"page"},{"location":"manual/metaprogramming/","page":"元编程","title":"元编程","text":"一个标识表达式类型的 Symbol。","category":"page"},{"location":"manual/metaprogramming/","page":"元编程","title":"元编程","text":"Symbol 就是一个 interned string 标识符(下面会有更多讨论)","category":"page"},{"location":"manual/metaprogramming/","page":"元编程","title":"元编程","text":"julia> ex1.head\n:call","category":"page"},{"location":"manual/metaprogramming/","page":"元编程","title":"元编程","text":"表达式的参数,可能是符号、其他表达式或字面量:","category":"page"},{"location":"manual/metaprogramming/","page":"元编程","title":"元编程","text":"julia> ex1.args\n3-element Vector{Any}:\n :+\n 1\n 1","category":"page"},{"location":"manual/metaprogramming/","page":"元编程","title":"元编程","text":"表达式也可能直接用 prefix notation 构造:","category":"page"},{"location":"manual/metaprogramming/","page":"元编程","title":"元编程","text":"julia> ex2 = Expr(:call, :+, 1, 1)\n:(1 + 1)","category":"page"},{"location":"manual/metaprogramming/","page":"元编程","title":"元编程","text":"上面构造的两个表达式 – 一个通过解析构造一个通过直接构造 – 是等价的:","category":"page"},{"location":"manual/metaprogramming/","page":"元编程","title":"元编程","text":"julia> ex1 == ex2\ntrue","category":"page"},{"location":"manual/metaprogramming/","page":"元编程","title":"元编程","text":"这里的关键点是 Julia 的代码在内部表示为可以从语言本身访问的数据结构","category":"page"},{"location":"manual/metaprogramming/","page":"元编程","title":"元编程","text":"函数 dump 可以带有缩进和注释地显示 Expr 对象:","category":"page"},{"location":"manual/metaprogramming/","page":"元编程","title":"元编程","text":"julia> dump(ex2)\nExpr\n head: Symbol call\n args: Array{Any}((3,))\n 1: Symbol +\n 2: Int64 1\n 3: Int64 1","category":"page"},{"location":"manual/metaprogramming/","page":"元编程","title":"元编程","text":"Expr 对象也可以嵌套:","category":"page"},{"location":"manual/metaprogramming/","page":"元编程","title":"元编程","text":"julia> ex3 = Meta.parse(\"(4 + 4) / 2\")\n:((4 + 4) / 2)","category":"page"},{"location":"manual/metaprogramming/","page":"元编程","title":"元编程","text":"另外一个查看表达式的方法是使用 Meta.show_sexpr,它能显示给定 Expr 的 S-expression,对 Lisp 用户来说,这看着很熟悉。下面是一个示例,阐释了如何显示嵌套的 Expr:","category":"page"},{"location":"manual/metaprogramming/","page":"元编程","title":"元编程","text":"julia> Meta.show_sexpr(ex3)\n(:call, :/, (:call, :+, 4, 4), 2)","category":"page"},{"location":"manual/metaprogramming/#符号","page":"元编程","title":"符号","text":"","category":"section"},{"location":"manual/metaprogramming/","page":"元编程","title":"元编程","text":"字符 : 在 Julia 中有两个作用。第一种形式构造一个 Symbol,这是作为表达式组成部分的一个 interned string:","category":"page"},{"location":"manual/metaprogramming/","page":"元编程","title":"元编程","text":"julia> s = :foo\n:foo\n\njulia> typeof(s)\nSymbol","category":"page"},{"location":"manual/metaprogramming/","page":"元编程","title":"元编程","text":"构造函数 Symbol 接受任意数量的参数并通过把它们的字符串表示连在一起创建一个新的符号:","category":"page"},{"location":"manual/metaprogramming/","page":"元编程","title":"元编程","text":"julia> :foo == Symbol(\"foo\")\ntrue\n\njulia> Symbol(\"func\",10)\n:func10\n\njulia> Symbol(:var,'_',\"sym\")\n:var_sym","category":"page"},{"location":"manual/metaprogramming/","page":"元编程","title":"元编程","text":"注意,要使用 : 语法,符号的名称必须是有效的标识符。否则,必须使用 Symbol(str) 构造函数。","category":"page"},{"location":"manual/metaprogramming/","page":"元编程","title":"元编程","text":"在表达式的上下文中,符号用来表示对变量的访问;当一个表达式被求值时,符号会被替换为这个符号在合适的 scope 中所绑定的值。","category":"page"},{"location":"manual/metaprogramming/","page":"元编程","title":"元编程","text":"有时需要在 : 的参数两边加上额外的括号,以避免在解析时出现歧义:","category":"page"},{"location":"manual/metaprogramming/","page":"元编程","title":"元编程","text":"julia> :(:)\n:(:)\n\njulia> :(::)\n:(::)","category":"page"},{"location":"manual/metaprogramming/#表达式与求值","page":"元编程","title":"表达式与求值","text":"","category":"section"},{"location":"manual/metaprogramming/#引用","page":"元编程","title":"引用","text":"","category":"section"},{"location":"manual/metaprogramming/","page":"元编程","title":"元编程","text":": 的第二个语义是不显式调用 Expr 构造器来创建表达式对象。这被称为引用。: 后面跟着包围着单个 Julia 语句括号,可以基于被包围的代码生成一个 Expr 对象。下面是一个引用算数表达式的例子:","category":"page"},{"location":"manual/metaprogramming/","page":"元编程","title":"元编程","text":"julia> ex = :(a+b*c+1)\n:(a + b * c + 1)\n\njulia> typeof(ex)\nExpr","category":"page"},{"location":"manual/metaprogramming/","page":"元编程","title":"元编程","text":"(为了查看这个表达式的结构,可以试一试 ex.head 和 ex.args,或者使用 dump 同时查看 ex.head 和 ex.args 或者 Meta.@dump)","category":"page"},{"location":"manual/metaprogramming/","page":"元编程","title":"元编程","text":"注意等价的表达式也可以使用 Meta.parse 或者直接用 Expr 构造:","category":"page"},{"location":"manual/metaprogramming/","page":"元编程","title":"元编程","text":"julia> :(a + b*c + 1) ==\n Meta.parse(\"a + b*c + 1\") ==\n Expr(:call, :+, :a, Expr(:call, :*, :b, :c), 1)\ntrue","category":"page"},{"location":"manual/metaprogramming/","page":"元编程","title":"元编程","text":"解析器提供的表达式通常只有符号、其它表达式和字面量值作为其参数,而由 Julia 代码构造的表达式能以非字面量形式的任意运行期值作为其参数。在此特例中,+ 和 a 都是符号,*(b,c) 是子表达式,而 1 是 64 位带符号整数字面量。","category":"page"},{"location":"manual/metaprogramming/","page":"元编程","title":"元编程","text":"引用多个表达式有第二种语法形式:在 quote ... end 中包含代码块。","category":"page"},{"location":"manual/metaprogramming/","page":"元编程","title":"元编程","text":"julia> ex = quote\n x = 1\n y = 2\n x + y\n end\nquote\n #= none:2 =#\n x = 1\n #= none:3 =#\n y = 2\n #= none:4 =#\n x + y\nend\n\njulia> typeof(ex)\nExpr","category":"page"},{"location":"manual/metaprogramming/#man-expression-interpolation","page":"元编程","title":"插值","text":"","category":"section"},{"location":"manual/metaprogramming/","page":"元编程","title":"元编程","text":"使用值参数直接构造 Expr 对象虽然很强大,但与「通常的」 Julia 语法相比,Expr 构造函数可能让人觉得乏味。作为替代方法,Julia 允许将字面量或表达式插入到被引用的表达式中。表达式插值由前缀 $ 表示。","category":"page"},{"location":"manual/metaprogramming/","page":"元编程","title":"元编程","text":"在此示例中,插入了变量 a 的值:","category":"page"},{"location":"manual/metaprogramming/","page":"元编程","title":"元编程","text":"julia> a = 1;\n\njulia> ex = :($a + b)\n:(1 + b)","category":"page"},{"location":"manual/metaprogramming/","page":"元编程","title":"元编程","text":"对未被引用的表达式进行插值是不支持的,这会导致编译期错误:","category":"page"},{"location":"manual/metaprogramming/","page":"元编程","title":"元编程","text":"julia> $a + b\nERROR: syntax: \"$\" expression outside quote","category":"page"},{"location":"manual/metaprogramming/","page":"元编程","title":"元编程","text":"在此示例中,元组 (1,2,3) 作为表达式插入到条件测试中:","category":"page"},{"location":"manual/metaprogramming/","page":"元编程","title":"元编程","text":"julia> ex = :(a in $:((1,2,3)) )\n:(a in (1, 2, 3))","category":"page"},{"location":"manual/metaprogramming/","page":"元编程","title":"元编程","text":"在表达式插值中使用 $ 是有意让人联想到字符串插值和命令插值。表达式插值使得复杂 Julia 表达式的程序化构造变得方便和易读。","category":"page"},{"location":"manual/metaprogramming/#Splatting-插值","page":"元编程","title":"Splatting 插值","text":"","category":"section"},{"location":"manual/metaprogramming/","page":"元编程","title":"元编程","text":"请注意,$ 插值语法只允许插入单个表达式到包含它的表达式中。有时,你手头有个由表达式组成的数组,需要它们都变成其所处表达式的参数,而这可通过 $(xs...) 语法做到。例如,下面的代码生成了一个函数调用,其参数数量通过编程确定:","category":"page"},{"location":"manual/metaprogramming/","page":"元编程","title":"元编程","text":"julia> args = [:x, :y, :z];\n\njulia> :(f(1, $(args...)))\n:(f(1, x, y, z))","category":"page"},{"location":"manual/metaprogramming/#嵌套引用","page":"元编程","title":"嵌套引用","text":"","category":"section"},{"location":"manual/metaprogramming/","page":"元编程","title":"元编程","text":"自然地,引用表达式可以包含在其它引用表达式中。插值在这些情形中的工作方式可能会有点难以理解。考虑这个例子:","category":"page"},{"location":"manual/metaprogramming/","page":"元编程","title":"元编程","text":"julia> x = :(1 + 2);\n\njulia> e = quote quote $x end end\nquote\n #= none:1 =#\n $(Expr(:quote, quote\n #= none:1 =#\n $(Expr(:$, :x))\nend))\nend","category":"page"},{"location":"manual/metaprogramming/","page":"元编程","title":"元编程","text":"Notice that the result contains $x, which means that x has not been evaluated yet. In other words, the $ expression \"belongs to\" the inner quote expression, and so its argument is only evaluated when the inner quote expression is:","category":"page"},{"location":"manual/metaprogramming/","page":"元编程","title":"元编程","text":"julia> eval(e)\nquote\n #= none:1 =#\n 1 + 2\nend","category":"page"},{"location":"manual/metaprogramming/","page":"元编程","title":"元编程","text":"但是,外部 quote 表达式可以把值插入到内部引用表达式的 $ 中去。这通过多个 $ 实现:","category":"page"},{"location":"manual/metaprogramming/","page":"元编程","title":"元编程","text":"julia> e = quote quote $$x end end\nquote\n #= none:1 =#\n $(Expr(:quote, quote\n #= none:1 =#\n $(Expr(:$, :(1 + 2)))\nend))\nend","category":"page"},{"location":"manual/metaprogramming/","page":"元编程","title":"元编程","text":"Notice that (1 + 2) now appears in the result instead of the symbol x. Evaluating this expression yields an interpolated 3:","category":"page"},{"location":"manual/metaprogramming/","page":"元编程","title":"元编程","text":"julia> eval(e)\nquote\n #= none:1 =#\n 3\nend","category":"page"},{"location":"manual/metaprogramming/","page":"元编程","title":"元编程","text":"这种行为背后的直觉是每个 $ 都将 x 求值一遍:一个 $ 工作方式类似于 eval(:x),其返回 x 的值,而两个 $ 行为相当于 eval(eval(:x))。","category":"page"},{"location":"manual/metaprogramming/#man-quote-node","page":"元编程","title":"QuoteNode","text":"","category":"section"},{"location":"manual/metaprogramming/","page":"元编程","title":"元编程","text":"quote 形式在 AST 中通常表示为一个 head 为 :quote 的 Expr :","category":"page"},{"location":"manual/metaprogramming/","page":"元编程","title":"元编程","text":"julia> dump(Meta.parse(\":(1+2)\"))\nExpr\n head: Symbol quote\n args: Array{Any}((1,))\n 1: Expr\n head: Symbol call\n args: Array{Any}((3,))\n 1: Symbol +\n 2: Int64 1\n 3: Int64 2","category":"page"},{"location":"manual/metaprogramming/","page":"元编程","title":"元编程","text":"正如我们所看到的,这些表达式支持插值符号 $。但是,在某些情况下,需要在不执行插值的情况下引用代码。 这种引用还没有语法,但在内部表示为 QuoteNode 类型的对象:","category":"page"},{"location":"manual/metaprogramming/","page":"元编程","title":"元编程","text":"julia> eval(Meta.quot(Expr(:$, :(1+2))))\n3\n\njulia> eval(QuoteNode(Expr(:$, :(1+2))))\n:($(Expr(:$, :(1 + 2))))","category":"page"},{"location":"manual/metaprogramming/","page":"元编程","title":"元编程","text":"解析器为简单的引用项(如符号)生成 QuoteNode:","category":"page"},{"location":"manual/metaprogramming/","page":"元编程","title":"元编程","text":"julia> dump(Meta.parse(\":x\"))\nQuoteNode\n value: Symbol x","category":"page"},{"location":"manual/metaprogramming/","page":"元编程","title":"元编程","text":"QuoteNode 也可用于某些高级的元编程任务。","category":"page"},{"location":"manual/metaprogramming/#表达式求值","page":"元编程","title":"表达式求值","text":"","category":"section"},{"location":"manual/metaprogramming/","page":"元编程","title":"元编程","text":"给定一个表达式对象,可以使用 eval 使 Julia 在全局作用域内评估(执行)它:","category":"page"},{"location":"manual/metaprogramming/","page":"元编程","title":"元编程","text":"julia> ex1 = :(1 + 2)\n:(1 + 2)\n\njulia> eval(ex1)\n3\n\njulia> ex = :(a + b)\n:(a + b)\n\njulia> eval(ex)\nERROR: UndefVarError: b not defined\n[...]\n\njulia> a = 1; b = 2;\n\njulia> eval(ex)\n3","category":"page"},{"location":"manual/metaprogramming/","page":"元编程","title":"元编程","text":"每个模块有自己的 eval 函数,该函数在其全局作用域内对表达式求值。传给 eval 的表达式不止可以返回值——它们还能具有改变封闭模块的环境状态的副作用:","category":"page"},{"location":"manual/metaprogramming/","page":"元编程","title":"元编程","text":"julia> ex = :(x = 1)\n:(x = 1)\n\njulia> x\nERROR: UndefVarError: x not defined\n\njulia> eval(ex)\n1\n\njulia> x\n1","category":"page"},{"location":"manual/metaprogramming/","page":"元编程","title":"元编程","text":"这里,表达式对象的求值导致一个值被赋值给全局变量 x。","category":"page"},{"location":"manual/metaprogramming/","page":"元编程","title":"元编程","text":"由于表达式只是 Expr 对象,而其可以通过编程方式构造然后对它求值,因此可以动态地生成任意代码,然后使用 eval 运行所生成的代码。这是个简单的例子:","category":"page"},{"location":"manual/metaprogramming/","page":"元编程","title":"元编程","text":"julia> a = 1;\n\njulia> ex = Expr(:call, :+, a, :b)\n:(1 + b)\n\njulia> a = 0; b = 2;\n\njulia> eval(ex)\n3","category":"page"},{"location":"manual/metaprogramming/","page":"元编程","title":"元编程","text":"a 的值被用于构造表达式 ex,该表达式将函数 + 作用于值 1 和变量 b。请注意 a 和 b 使用方式间的重要区别:","category":"page"},{"location":"manual/metaprogramming/","page":"元编程","title":"元编程","text":"变量 a 在表达式构造时的值在表达式中用作立即值。因此,在对表达式求值时,a 的值就无关紧要了:表达式中的值已经是 1,与 a 的值无关。\n另一方面,因为在表达式构造时用的是符号 :b,所以变量 b 的值无关紧要——:b 只是一个符号,变量 b 甚至无需被定义。然而,在表达式求值时,符号 :b 的值通过寻找变量 b 的值来解析。","category":"page"},{"location":"manual/metaprogramming/#关于表达式的函数","page":"元编程","title":"关于表达式的函数","text":"","category":"section"},{"location":"manual/metaprogramming/","page":"元编程","title":"元编程","text":"如上所述,Julia 能在其内部生成和操作 Julia 代码,这是个非常有用的功能。我们已经见过返回 Expr 对象的函数例子:parse 函数,它接受字符串形式的 Julia 代码并返回相应的 Expr。函数也可以接受一个或多个 Expr 对象作为参数,并返回另一个 Expr。这是个简单、提神的例子:","category":"page"},{"location":"manual/metaprogramming/","page":"元编程","title":"元编程","text":"julia> function math_expr(op, op1, op2)\n expr = Expr(:call, op, op1, op2)\n return expr\n end\nmath_expr (generic function with 1 method)\n\njulia> ex = math_expr(:+, 1, Expr(:call, :*, 4, 5))\n:(1 + 4 * 5)\n\njulia> eval(ex)\n21","category":"page"},{"location":"manual/metaprogramming/","page":"元编程","title":"元编程","text":"作为另一个例子,这个函数将数值参数加倍,但不处理表达式:","category":"page"},{"location":"manual/metaprogramming/","page":"元编程","title":"元编程","text":"julia> function make_expr2(op, opr1, opr2)\n opr1f, opr2f = map(x -> isa(x, Number) ? 2*x : x, (opr1, opr2))\n retexpr = Expr(:call, op, opr1f, opr2f)\n return retexpr\n end\nmake_expr2 (generic function with 1 method)\n\njulia> make_expr2(:+, 1, 2)\n:(2 + 4)\n\njulia> ex = make_expr2(:+, 1, Expr(:call, :*, 5, 8))\n:(2 + 5 * 8)\n\njulia> eval(ex)\n42","category":"page"},{"location":"manual/metaprogramming/#man-macros","page":"元编程","title":"宏","text":"","category":"section"},{"location":"manual/metaprogramming/","page":"元编程","title":"元编程","text":"宏提供了一种机制,可以将生成的代码包含在程序的最终主体中。 宏将一组参数映射到返回的 表达式,并且生成的表达式被直接编译,而不需要运行时 eval 调用。 宏参数可能包括表达式、字面量和符号。","category":"page"},{"location":"manual/metaprogramming/#基础","page":"元编程","title":"基础","text":"","category":"section"},{"location":"manual/metaprogramming/","page":"元编程","title":"元编程","text":"这是一个非常简单的宏:","category":"page"},{"location":"manual/metaprogramming/","page":"元编程","title":"元编程","text":"julia> macro sayhello()\n return :( println(\"Hello, world!\") )\n end\n@sayhello (macro with 1 method)","category":"page"},{"location":"manual/metaprogramming/","page":"元编程","title":"元编程","text":"宏在Julia的语法中有一个专门的字符 @ (at-sign),紧接着是其使用macro NAME ... end 形式来声明的唯一的宏名。在这个例子中,编译器会把所有的@sayhello 替换成:","category":"page"},{"location":"manual/metaprogramming/","page":"元编程","title":"元编程","text":":( println(\"Hello, world!\") )","category":"page"},{"location":"manual/metaprogramming/","page":"元编程","title":"元编程","text":"当 @sayhello 在REPL中被输入时,解释器立即执行,因此我们只会看到计算后的结果:","category":"page"},{"location":"manual/metaprogramming/","page":"元编程","title":"元编程","text":"julia> @sayhello()\nHello, world!","category":"page"},{"location":"manual/metaprogramming/","page":"元编程","title":"元编程","text":"现在,考虑一个稍微复杂一点的宏:","category":"page"},{"location":"manual/metaprogramming/","page":"元编程","title":"元编程","text":"julia> macro sayhello(name)\n return :( println(\"Hello, \", $name) )\n end\n@sayhello (macro with 1 method)","category":"page"},{"location":"manual/metaprogramming/","page":"元编程","title":"元编程","text":"这个宏接受一个参数name。当遇到@sayhello时,quoted 表达式会被展开并将参数中的值插入到最终的表达式中:","category":"page"},{"location":"manual/metaprogramming/","page":"元编程","title":"元编程","text":"julia> @sayhello(\"human\")\nHello, human","category":"page"},{"location":"manual/metaprogramming/","page":"元编程","title":"元编程","text":"我们可以使用函数 macroexpand 查看引用的返回表达式(重要提示: 这是一个非常有用的调试宏的工具):","category":"page"},{"location":"manual/metaprogramming/","page":"元编程","title":"元编程","text":"julia> ex = macroexpand(Main, :(@sayhello(\"human\")) )\n:(Main.println(\"Hello, \", \"human\"))\n\njulia> typeof(ex)\nExpr","category":"page"},{"location":"manual/metaprogramming/","page":"元编程","title":"元编程","text":"我们可以看到 \"human\" 字面量已被插入到表达式中了。","category":"page"},{"location":"manual/metaprogramming/","page":"元编程","title":"元编程","text":"还有一个宏 @ macroexpand,它可能比 macroexpand 函数更方便:","category":"page"},{"location":"manual/metaprogramming/","page":"元编程","title":"元编程","text":"julia> @macroexpand @sayhello \"human\"\n:(println(\"Hello, \", \"human\"))","category":"page"},{"location":"manual/metaprogramming/#停:为什么需要宏?","page":"元编程","title":"停:为什么需要宏?","text":"","category":"section"},{"location":"manual/metaprogramming/","page":"元编程","title":"元编程","text":"我们已经在上一节中看到了一个函数 f(::Expr...) -> Expr。 其实macroexpand也是这样一个函数。 那么,为什么会要设计宏呢?","category":"page"},{"location":"manual/metaprogramming/","page":"元编程","title":"元编程","text":"宏是必需的,因为它们在解析代码时执行,因此,宏允许程序员在运行完整程序之前生成定制代码的片段。 为了说明差异,请考虑以下示例:","category":"page"},{"location":"manual/metaprogramming/","page":"元编程","title":"元编程","text":"julia> macro twostep(arg)\n println(\"I execute at parse time. The argument is: \", arg)\n return :(println(\"I execute at runtime. The argument is: \", $arg))\n end\n@twostep (macro with 1 method)\n\njulia> ex = macroexpand(Main, :(@twostep :(1, 2, 3)) );\nI execute at parse time. The argument is: :((1, 2, 3))","category":"page"},{"location":"manual/metaprogramming/","page":"元编程","title":"元编程","text":"第一个 println 调用在调用 macroexpand 时执行。生成的表达式只包含第二个 println:","category":"page"},{"location":"manual/metaprogramming/","page":"元编程","title":"元编程","text":"julia> typeof(ex)\nExpr\n\njulia> ex\n:(println(\"I execute at runtime. The argument is: \", $(Expr(:copyast, :($(QuoteNode(:((1, 2, 3)))))))))\n\njulia> eval(ex)\nI execute at runtime. The argument is: (1, 2, 3)","category":"page"},{"location":"manual/metaprogramming/#宏的调用","page":"元编程","title":"宏的调用","text":"","category":"section"},{"location":"manual/metaprogramming/","page":"元编程","title":"元编程","text":"宏的通常调用语法如下:","category":"page"},{"location":"manual/metaprogramming/","page":"元编程","title":"元编程","text":"@name expr1 expr2 ...\n@name(expr1, expr2, ...)","category":"page"},{"location":"manual/metaprogramming/","page":"元编程","title":"元编程","text":"请注意,在宏名称前的标志 @,且在第一种形式中参数表达式间没有逗号,而在第二种形式中 @name 后没有空格。这两种风格不应混淆。例如,下列语法不同于上述例子;它把元组 (expr1, expr2, ...) 作为参数传给宏:","category":"page"},{"location":"manual/metaprogramming/","page":"元编程","title":"元编程","text":"@name (expr1, expr2, ...)","category":"page"},{"location":"manual/metaprogramming/","page":"元编程","title":"元编程","text":"在数组字面量(或推导式)上调用宏的另一种方法是不使用括号直接并列两者。在这种情况下,数组将是唯一的传给宏的表达式。以下语法等价(且与 @name [a b] * v 不同):","category":"page"},{"location":"manual/metaprogramming/","page":"元编程","title":"元编程","text":"@name[a b] * v\n@name([a b]) * v","category":"page"},{"location":"manual/metaprogramming/","page":"元编程","title":"元编程","text":"在这着重强调,宏把它们的参数作为表达式、字面量或符号接收。浏览宏参数的一种方法是在宏的内部调用 show 函数:","category":"page"},{"location":"manual/metaprogramming/","page":"元编程","title":"元编程","text":"julia> macro showarg(x)\n show(x)\n # ... remainder of macro, returning an expression\n end\n@showarg (macro with 1 method)\n\njulia> @showarg(a)\n:a\n\njulia> @showarg(1+1)\n:(1 + 1)\n\njulia> @showarg(println(\"Yo!\"))\n:(println(\"Yo!\"))","category":"page"},{"location":"manual/metaprogramming/","page":"元编程","title":"元编程","text":"除了给定的参数列表,每个宏都会传递名为 __source__ 和 __module__ 的额外参数。","category":"page"},{"location":"manual/metaprogramming/","page":"元编程","title":"元编程","text":"参数 __source__ 提供 @ 符号在宏调用处的解析器位置的相关信息(以 LineNumberNode 对象的形式)。这使得宏能包含更好的错误诊断信息,其通常用于日志记录、字符串解析器宏和文档,比如,用于实现 @__LINE__、@__FILE__ 和 @__DIR__ 宏。","category":"page"},{"location":"manual/metaprogramming/","page":"元编程","title":"元编程","text":"引用 __source__.line 和 __source__.file 即可访问位置信息:","category":"page"},{"location":"manual/metaprogramming/","page":"元编程","title":"元编程","text":"julia> macro __LOCATION__(); return QuoteNode(__source__); end\n@__LOCATION__ (macro with 1 method)\n\njulia> dump(\n @__LOCATION__(\n ))\nLineNumberNode\n line: Int64 2\n file: Symbol none","category":"page"},{"location":"manual/metaprogramming/","page":"元编程","title":"元编程","text":"参数 __module__ 提供宏调用展开处的上下文相关信息(以 Module 对象的形式)。这允许宏查找上下文相关的信息,比如现有的绑定,或者将值作为附加参数插入到一个在当前模块中进行自我反射的运行时函数调用中。","category":"page"},{"location":"manual/metaprogramming/#构建高级的宏","page":"元编程","title":"构建高级的宏","text":"","category":"section"},{"location":"manual/metaprogramming/","page":"元编程","title":"元编程","text":"这是 Julia 的 @assert 宏的简化定义:","category":"page"},{"location":"manual/metaprogramming/","page":"元编程","title":"元编程","text":"julia> macro assert(ex)\n return :( $ex ? nothing : throw(AssertionError($(string(ex)))) )\n end\n@assert (macro with 1 method)","category":"page"},{"location":"manual/metaprogramming/","page":"元编程","title":"元编程","text":"这个宏可以像这样使用:","category":"page"},{"location":"manual/metaprogramming/","page":"元编程","title":"元编程","text":"julia> @assert 1 == 1.0\n\njulia> @assert 1 == 0\nERROR: AssertionError: 1 == 0","category":"page"},{"location":"manual/metaprogramming/","page":"元编程","title":"元编程","text":"宏调用在解析时扩展为其返回结果,并替代已编写的语法。这相当于编写:","category":"page"},{"location":"manual/metaprogramming/","page":"元编程","title":"元编程","text":"1 == 1.0 ? nothing : throw(AssertionError(\"1 == 1.0\"))\n1 == 0 ? nothing : throw(AssertionError(\"1 == 0\"))","category":"page"},{"location":"manual/metaprogramming/","page":"元编程","title":"元编程","text":"也就是说,在第一个调用中,表达式 :(1 == 1.0) 拼接到测试条件槽中,而 string(:(1 == 1.0)) 拼接到断言信息槽中。如此构造的表达式会被放置在发生 @assert 宏调用处的语法树。然后在执行时,如果测试表达式的计算结果为真,则返回 nothing,但如果测试结果为假,则会引发错误,表明声明的表达式为假。请注意,将其编写为函数是不可能的,因为能获取的只有条件的值而无法在错误信息中显示计算出它的表达式。","category":"page"},{"location":"manual/metaprogramming/","page":"元编程","title":"元编程","text":"在 Julia Base 中,@assert 的实际定义更复杂。它允许用户可选地制定自己的错误信息,而不仅仅是打印断言失败的表达式。与函数一样,具有可变数量的参数( 变参函数)可在最后一个参数后面用省略号指定:","category":"page"},{"location":"manual/metaprogramming/","page":"元编程","title":"元编程","text":"julia> macro assert(ex, msgs...)\n msg_body = isempty(msgs) ? ex : msgs[1]\n msg = string(msg_body)\n return :($ex ? nothing : throw(AssertionError($msg)))\n end\n@assert (macro with 1 method)","category":"page"},{"location":"manual/metaprogramming/","page":"元编程","title":"元编程","text":"现在@assert 有两种操作模式,这取决于它接收到的参数数量!如果只有一个参数,msgs 捕获的表达式元组将为空,并且其行为与上面更简单的定义相同。 但是现在如果用户指定了第二个参数,它会打印在消息正文中而不是不相等的表达式中。你可以使用恰当命名的 @macroexpand 宏检查宏展开的结果:","category":"page"},{"location":"manual/metaprogramming/","page":"元编程","title":"元编程","text":"julia> @macroexpand @assert a == b\n:(if Main.a == Main.b\n Main.nothing\n else\n Main.throw(Main.AssertionError(\"a == b\"))\n end)\n\njulia> @macroexpand @assert a==b \"a should equal b!\"\n:(if Main.a == Main.b\n Main.nothing\n else\n Main.throw(Main.AssertionError(\"a should equal b!\"))\n end)","category":"page"},{"location":"manual/metaprogramming/","page":"元编程","title":"元编程","text":"实际的 @assert 宏还处理了另一种情形:我们如果除了打印「a should equal b」外还想打印它们的值?有人也许会天真地尝试在自定义消息中使用字符串插值,例如,@assert a==b \"a ($a) should equal b ($b)!\",但这不会像上面的宏一样按预期工作。你能想到为什么吗?回想一下字符串插值,内插字符串会被重写为 string 的调用。比较:","category":"page"},{"location":"manual/metaprogramming/","page":"元编程","title":"元编程","text":"julia> typeof(:(\"a should equal b\"))\nString\n\njulia> typeof(:(\"a ($a) should equal b ($b)!\"))\nExpr\n\njulia> dump(:(\"a ($a) should equal b ($b)!\"))\nExpr\n head: Symbol string\n args: Array{Any}((5,))\n 1: String \"a (\"\n 2: Symbol a\n 3: String \") should equal b (\"\n 4: Symbol b\n 5: String \")!\"","category":"page"},{"location":"manual/metaprogramming/","page":"元编程","title":"元编程","text":"所以,现在宏在 msg_body 中获得的不是单纯的字符串,其接收了一个完整的表达式,该表达式需进行求值才能按预期显示。这可作为 string 调用的参数直接拼接到返回的表达式中;有关完整实现,请参阅 error.jl。","category":"page"},{"location":"manual/metaprogramming/","page":"元编程","title":"元编程","text":"@assert 宏充分利用拼接被引用的表达式,以便简化对宏内部表达式的操作。","category":"page"},{"location":"manual/metaprogramming/#卫生宏","page":"元编程","title":"卫生宏","text":"","category":"section"},{"location":"manual/metaprogramming/","page":"元编程","title":"元编程","text":"在更复杂的宏中会出现关于卫生宏 的问题。简而言之,宏必须确保在其返回表达式中引入的变量不会意外地与其展开处周围代码中的现有变量相冲突。相反,作为参数传递给宏的表达式通常被认为在其周围代码的上下文中进行求值,与现有变量交互并修改之。另一个问题源于这样的事实:宏可以在不同于其定义所处模块的模块中调用。在这种情况下,我们需要确保所有全局变量都被解析到正确的模块中。Julia 比使用文本宏展开的语言(比如 C)具有更大的优势,因为它只需要考虑返回的表达式。所有其它变量(例如上面@assert 中的 msg)遵循通常的作用域块规则。","category":"page"},{"location":"manual/metaprogramming/","page":"元编程","title":"元编程","text":"为了演示这些问题,让我们来编写宏 @time,其以表达式为参数,记录当前时间,对表达式求值,再次记录当前时间,打印前后的时间差,然后以表达式的值作为其最终值。该宏可能看起来就像这样:","category":"page"},{"location":"manual/metaprogramming/","page":"元编程","title":"元编程","text":"macro time(ex)\n return quote\n local t0 = time_ns()\n local val = $ex\n local t1 = time_ns()\n println(\"elapsed time: \", (t1-t0)/1e9, \" seconds\")\n val\n end\nend","category":"page"},{"location":"manual/metaprogramming/","page":"元编程","title":"元编程","text":"在这里,我们希望 t0、t1 和 val 成为私有临时变量,并且我们希望 time_ns 引用 Julia Base 中的 time_ns 函数,而不是任何用户可能拥有的 time_ns 变量(同样适用于 println)。 想象一下,如果用户表达式 ex 还包含对名为 t0 的变量的赋值,或者定义了自己的 time_ns 变量,可能会出现什么问题。 程序可能会报错,或者进行未知的行为。","category":"page"},{"location":"manual/metaprogramming/","page":"元编程","title":"元编程","text":"Julia 的宏展开器通过以下方式解决了这些问题。 首先,宏结果中的变量分为局部变量或全局变量。 如果变量被赋值(并且不是声明为全局的)、声明为局部、或用作函数参数名称,则该变量被视为局部变量。 否则,它被认为是全局的。 然后将局部变量重命名为唯一的(使用 gensym 函数,该函数生成新符号),并在宏定义环境中解析全局变量。 因此,上述两个问题都得到了处理; 宏的局部变量不会与任何用户变量冲突,并且 time_ns 和 println 将引用 Julia Base 定义。","category":"page"},{"location":"manual/metaprogramming/","page":"元编程","title":"元编程","text":"然而,仍有另外的问题。考虑此宏的以下用法:","category":"page"},{"location":"manual/metaprogramming/","page":"元编程","title":"元编程","text":"module MyModule\nimport Base.@time\n\ntime_ns() = ... # compute something\n\n@time time_ns()\nend","category":"page"},{"location":"manual/metaprogramming/","page":"元编程","title":"元编程","text":"这里的用户表达式ex 是对time_ns 的调用,但与宏使用的time_ns 函数不同。 它清楚地指向MyModule.time_ns。 因此我们必须安排在宏调用环境中解析ex中的代码。 这是通过使用 esc“转义”表达式来完成的:","category":"page"},{"location":"manual/metaprogramming/","page":"元编程","title":"元编程","text":"macro time(ex)\n ...\n local val = $(esc(ex))\n ...\nend","category":"page"},{"location":"manual/metaprogramming/","page":"元编程","title":"元编程","text":"以这种方式封装的表达式会被宏展开器单独保留,并将其简单地逐字粘贴到输出中。因此,它将在宏调用所处环境中解析。","category":"page"},{"location":"manual/metaprogramming/","page":"元编程","title":"元编程","text":"这种转义机制可以在必要时用于「违反」卫生,以便于引入或操作用户变量。例如,以下宏在其调用所处环境中将 x 设置为零:","category":"page"},{"location":"manual/metaprogramming/","page":"元编程","title":"元编程","text":"julia> macro zerox()\n return esc(:(x = 0))\n end\n@zerox (macro with 1 method)\n\njulia> function foo()\n x = 1\n @zerox\n return x # is zero\n end\nfoo (generic function with 1 method)\n\njulia> foo()\n0","category":"page"},{"location":"manual/metaprogramming/","page":"元编程","title":"元编程","text":"应当明智地使用这种变量操作,但它偶尔会很方便。","category":"page"},{"location":"manual/metaprogramming/","page":"元编程","title":"元编程","text":"获得正确的规则也许是个艰巨的挑战。在使用宏之前,你可以去考虑是否函数闭包便已足够。另一个有用的策略是将尽可能多的工作推迟到运行时。例如,许多宏只是将其参数封装为 QuoteNode 或类似的 Expr。这方面的例子有 @task body,它只返回 schedule(Task(() -> $body)), 和 @eval expr,它只返回 eval(QuoteNode(expr))。","category":"page"},{"location":"manual/metaprogramming/","page":"元编程","title":"元编程","text":"为了演示,我们可以将上面的 @time 示例重新编写成:","category":"page"},{"location":"manual/metaprogramming/","page":"元编程","title":"元编程","text":"macro time(expr)\n return :(timeit(() -> $(esc(expr))))\nend\nfunction timeit(f)\n t0 = time_ns()\n val = f()\n t1 = time_ns()\n println(\"elapsed time: \", (t1-t0)/1e9, \" seconds\")\n return val\nend","category":"page"},{"location":"manual/metaprogramming/","page":"元编程","title":"元编程","text":"但是,我们不这样做也是有充分理由的:将 expr 封装在新的作用域块(该匿名函数)中也会稍微改变该表达式的含义(其中任何变量的作用域),而我们想要 @time 使用时对其封装的代码影响最小。","category":"page"},{"location":"manual/metaprogramming/#宏与派发","page":"元编程","title":"宏与派发","text":"","category":"section"},{"location":"manual/metaprogramming/","page":"元编程","title":"元编程","text":"与 Julia 函数一样,宏也是泛型的。由于多重派发,这意味着宏也能有多个方法定义:","category":"page"},{"location":"manual/metaprogramming/","page":"元编程","title":"元编程","text":"julia> macro m end\n@m (macro with 0 methods)\n\njulia> macro m(args...)\n println(\"$(length(args)) arguments\")\n end\n@m (macro with 1 method)\n\njulia> macro m(x,y)\n println(\"Two arguments\")\n end\n@m (macro with 2 methods)\n\njulia> @m \"asd\"\n1 arguments\n\njulia> @m 1 2\nTwo arguments","category":"page"},{"location":"manual/metaprogramming/","page":"元编程","title":"元编程","text":"但是应该记住,宏派发基于传递给宏的 AST 的类型,而不是 AST 在运行时进行求值的类型:","category":"page"},{"location":"manual/metaprogramming/","page":"元编程","title":"元编程","text":"julia> macro m(::Int)\n println(\"An Integer\")\n end\n@m (macro with 3 methods)\n\njulia> @m 2\nAn Integer\n\njulia> x = 2\n2\n\njulia> @m x\n1 arguments","category":"page"},{"location":"manual/metaprogramming/#代码生成","page":"元编程","title":"代码生成","text":"","category":"section"},{"location":"manual/metaprogramming/","page":"元编程","title":"元编程","text":"当需要大量重复的样板代码时,为了避免冗余,通常以编程方式生成它。在大多数语言中,这需要一个额外的构建步骤以及生成重复代码的独立程序。在 Julia 中,表达式插值和 eval 允许在通常的程序执行过程中生成这些代码。例如,考虑下列自定义类型","category":"page"},{"location":"manual/metaprogramming/","page":"元编程","title":"元编程","text":"struct MyNumber\n x::Float64\nend\n# output\n","category":"page"},{"location":"manual/metaprogramming/","page":"元编程","title":"元编程","text":"我们想为该类型添加一些方法。在下面的循环中,我们以编程的方式完成此工作:","category":"page"},{"location":"manual/metaprogramming/","page":"元编程","title":"元编程","text":"for op = (:sin, :cos, :tan, :log, :exp)\n eval(quote\n Base.$op(a::MyNumber) = MyNumber($op(a.x))\n end)\nend\n# output\n","category":"page"},{"location":"manual/metaprogramming/","page":"元编程","title":"元编程","text":"现在,我们对自定义类型调用这些函数:","category":"page"},{"location":"manual/metaprogramming/","page":"元编程","title":"元编程","text":"julia> x = MyNumber(π)\nMyNumber(3.141592653589793)\n\njulia> sin(x)\nMyNumber(1.2246467991473532e-16)\n\njulia> cos(x)\nMyNumber(-1.0)","category":"page"},{"location":"manual/metaprogramming/","page":"元编程","title":"元编程","text":"在这种方法中,Julia 充当了自己的预处理器,并且允许从语言内部生成代码。使用 : 前缀的引用形式编写上述代码会使其更简洁:","category":"page"},{"location":"manual/metaprogramming/","page":"元编程","title":"元编程","text":"for op = (:sin, :cos, :tan, :log, :exp)\n eval(:(Base.$op(a::MyNumber) = MyNumber($op(a.x))))\nend","category":"page"},{"location":"manual/metaprogramming/","page":"元编程","title":"元编程","text":"不管怎样,这种使用 eval(quote(...)) 模式生成语言内部的代码很常见,为此,Julia 自带了一个宏来缩写该模式:","category":"page"},{"location":"manual/metaprogramming/","page":"元编程","title":"元编程","text":"for op = (:sin, :cos, :tan, :log, :exp)\n @eval Base.$op(a::MyNumber) = MyNumber($op(a.x))\nend","category":"page"},{"location":"manual/metaprogramming/","page":"元编程","title":"元编程","text":"@eval 重写此调用,使其与上面的较长版本完全等价。为了生成较长的代码块,可以把一个代码块作为表达式参数传给 @eval:","category":"page"},{"location":"manual/metaprogramming/","page":"元编程","title":"元编程","text":"@eval begin\n # multiple lines\nend","category":"page"},{"location":"manual/metaprogramming/#meta-non-standard-string-literals","page":"元编程","title":"非标准字符串字面量","text":"","category":"section"},{"location":"manual/metaprogramming/","page":"元编程","title":"元编程","text":"回想一下在字符串的文档中,以标识符为前缀的字符串字面量被称为非标准字符串字面量,它们可以具有与未加前缀的字符串字面量不同的语义。例如:","category":"page"},{"location":"manual/metaprogramming/","page":"元编程","title":"元编程","text":"r\"^\\s*(?:#|$)\" 产生一个正则表达式对象而不是一个字符串\nb\"DATA\\xff\\u2200\" 是一个字节数组字面量 ,表示[68,65,84,65,255,226,136,128]。","category":"page"},{"location":"manual/metaprogramming/","page":"元编程","title":"元编程","text":"可能令人惊讶的是,这些行为并没有被硬编码到 Julia 的解释器或编译器中。相反,它们是由一个通用机制实现的自定义行为,且任何人都可以使用该机制:带前缀的字符串字面量被解析为特定名称的宏的调用。例如,正则表达式宏如下:","category":"page"},{"location":"manual/metaprogramming/","page":"元编程","title":"元编程","text":"macro r_str(p)\n Regex(p)\nend","category":"page"},{"location":"manual/metaprogramming/","page":"元编程","title":"元编程","text":"这便是全部代码。这个宏说的是字符串字面量 r\"^\\s*(?:#|$)\" 的字面内容应该传给宏 @r_str,并且展开后的结果应当放在该字符串字面量出现处的语法树中。换句话说,表达式 r\"^\\s*(?:#|$)\" 等价于直接把下列对象放进语法树中:","category":"page"},{"location":"manual/metaprogramming/","page":"元编程","title":"元编程","text":"Regex(\"^\\\\s*(?:#|\\$)\")","category":"page"},{"location":"manual/metaprogramming/","page":"元编程","title":"元编程","text":"字符串字面量形式不仅更短、更方便,也更高效:因为正则表达式需要编译,Regex 对象实际上是在编译代码时创建的,所以编译只发生一次,而不是每次执行代码时都再编译一次。请考虑如果正则表达式出现在循环中:","category":"page"},{"location":"manual/metaprogramming/","page":"元编程","title":"元编程","text":"for line = lines\n m = match(r\"^\\s*(?:#|$)\", line)\n if m === nothing\n # non-comment\n else\n # comment\n end\nend","category":"page"},{"location":"manual/metaprogramming/","page":"元编程","title":"元编程","text":"因为正则表达式 r\"^\\s*(?:#|$)\" 在这段代码解析时便已编译并被插入到语法树中,所以它只编译一次,而不是每次执行循环时都再编译一次。要在不使用宏的情况下实现此效果,必须像这样编写此循环:","category":"page"},{"location":"manual/metaprogramming/","page":"元编程","title":"元编程","text":"re = Regex(\"^\\\\s*(?:#|\\$)\")\nfor line = lines\n m = match(re, line)\n if m === nothing\n # non-comment\n else\n # comment\n end\nend","category":"page"},{"location":"manual/metaprogramming/","page":"元编程","title":"元编程","text":"此外,如果编译器无法确定在所有循环中正则表达式对象都是常量,可能无法进行某些优化,使得此版本的效率依旧低于上面的更方便的字面量形式。当然,在某些情况下,非字面量形式更方便:如果需要向正则表达式中插入变量,就必须采用这种更冗长的方法;如果正则表达式模式本身是动态的,可能在每次循环迭代时发生变化,就必须在每次迭代中构造新的正则表达式对象。然而,在绝大多数用例中,正则表达式不是基于运行时的数据构造的。在大多数情况下,将正则表达式编写为编译期值的能力是无法估量的。","category":"page"},{"location":"manual/metaprogramming/","page":"元编程","title":"元编程","text":"用户定义字符串文字的机制非常强大。不仅使用它实现了 Julia 的非标准字面量,而且还使用以下看起来无害的宏实现了命令行字面量语法(`echo \"Hello, $person\"`):","category":"page"},{"location":"manual/metaprogramming/","page":"元编程","title":"元编程","text":"macro cmd(str)\n :(cmd_gen($(shell_parse(str)[1])))\nend","category":"page"},{"location":"manual/metaprogramming/","page":"元编程","title":"元编程","text":"当然,这个宏的定义中使用的函数隐藏了许多复杂性,但它们只是函数且完全用 Julia 编写。你可以阅读它们的源代码并精确地看到它们的行为——它们所做的一切就是构造要插入到你的程序的语法树的表达式对象。","category":"page"},{"location":"manual/metaprogramming/","page":"元编程","title":"元编程","text":"与字符串字面量一样,命令行字面量也可以以标识符为前缀,以形成所谓的非标准命令行字面量。 这些命令行字面量被解析为对特殊命名的宏的调用。 例如,语法 custom`literal` 被解析为 @custom_cmd \"literal\"。 Julia 本身不包含任何非标准的命令行字面量,但包可以使用这种语法。 除了不同的语法和 _cmd 后缀而不是 _str 后缀,非标准命令行字面量的行为与非标准字符串字面量完全一样。","category":"page"},{"location":"manual/metaprogramming/","page":"元编程","title":"元编程","text":"如果两个模块提供了同名的非标准字符串或命令字面量,能使用模块名限定该字符串或命令字面量。例如,如果 Foo 和 Bar 提供了相同的字符串字面量 @x_str,那么可以编写 Foo.x\"literal\" 或 Bar.x\"literal\" 来消除两者的歧义。","category":"page"},{"location":"manual/metaprogramming/","page":"元编程","title":"元编程","text":"以下是另一种定义宏的方式:","category":"page"},{"location":"manual/metaprogramming/","page":"元编程","title":"元编程","text":"macro foo_str(str, flag)\n # do stuff\nend","category":"page"},{"location":"manual/metaprogramming/","page":"元编程","title":"元编程","text":"可以使用如下语法来调用这个宏","category":"page"},{"location":"manual/metaprogramming/","page":"元编程","title":"元编程","text":"foo\"str\"flag","category":"page"},{"location":"manual/metaprogramming/","page":"元编程","title":"元编程","text":"上述语法中 flag 的类型可以是一个String,在字符串字面量之后包含的内容。","category":"page"},{"location":"manual/metaprogramming/#生成函数","page":"元编程","title":"生成函数","text":"","category":"section"},{"location":"manual/metaprogramming/","page":"元编程","title":"元编程","text":"有个非常特殊的宏叫 @generated,它允许你定义所谓的生成函数。它们能根据其参数类型生成专用代码,与用多重派发所能实现的代码相比,其代码更灵活和/或少。虽然宏在解析时使用表达式且无法访问其输入值的类型,但是生成函数在参数类型已知时会被展开,但该函数尚未编译。","category":"page"},{"location":"manual/metaprogramming/","page":"元编程","title":"元编程","text":"生成函数的声明不会执行某些计算或操作,而会返回一个被引用的表达式,接着该表达式构成参数类型所对应方法的主体。在调用生成函数时,其返回的表达式会被编译然后执行。为了提高效率,通常会缓存结果。为了能推断是否缓存结果,只能使用语言的受限子集。因此,生成函数提供了一个灵活的方式来将工作重运行时移到编译时,代价则是其构造能力受到更大的限制。","category":"page"},{"location":"manual/metaprogramming/","page":"元编程","title":"元编程","text":"定义生成函数与普通函数有五个主要区别:","category":"page"},{"location":"manual/metaprogramming/","page":"元编程","title":"元编程","text":"使用 @generated 标注函数声明。这会向 AST 附加一些信息,让编译器知道这个函数是生成函数。\n在生成函数的主体中,你只能访问参数的类型,而不能访问其值,以及在生成函数的定义之前便已定义的任何函数。\n不应计算某些东西或执行某些操作,应返回一个被引用的表达式,它会在被求值时执行你想要的操作。\n生成函数只允许调用在生成函数定义之前定义的函数。(如果不遵循这一点,引用来自未来世界的函数可能会导致 MethodErrors )\n生成函数不能更改或观察任何非常量的全局状态。(例如,其包括 IO、锁、非局部的字典或者使用 hasmethod)即它们只能读取全局常量,且没有任何副作用。换句话说,它们必须是纯函数。由于实现限制,这也意味着它们目前无法定义闭包或生成器。","category":"page"},{"location":"manual/metaprogramming/","page":"元编程","title":"元编程","text":"举例子来说明这个是最简单的。我们可以将生成函数 foo 声明为","category":"page"},{"location":"manual/metaprogramming/","page":"元编程","title":"元编程","text":"julia> @generated function foo(x)\n Core.println(x)\n return :(x * x)\n end\nfoo (generic function with 1 method)","category":"page"},{"location":"manual/metaprogramming/","page":"元编程","title":"元编程","text":"请注意,代码主体返回一个被引用的表达式,即 :(x * x),而不仅仅是 x * x 的值。","category":"page"},{"location":"manual/metaprogramming/","page":"元编程","title":"元编程","text":"从调用者的角度看,这与通常的函数等价;实际上,你无需知道你所调用的是通常的函数还是生成函数。让我们看看 foo 的行为:","category":"page"},{"location":"manual/metaprogramming/","page":"元编程","title":"元编程","text":"julia> x = foo(2); # note: output is from println() statement in the body\nInt64\n\njulia> x # now we print x\n4\n\njulia> y = foo(\"bar\");\nString\n\njulia> y\n\"barbar\"","category":"page"},{"location":"manual/metaprogramming/","page":"元编程","title":"元编程","text":"因此,我们知道在生成函数的主体中,x 是所传递参数的类型,并且,生成函数的返回值是其定义所返回的被引用的表达式的求值结果,在该表达式求值时 x 表示其值。","category":"page"},{"location":"manual/metaprogramming/","page":"元编程","title":"元编程","text":"如果我们使用我们已经使用过的类型再次对 foo 求值会发生什么?","category":"page"},{"location":"manual/metaprogramming/","page":"元编程","title":"元编程","text":"julia> foo(4)\n16","category":"page"},{"location":"manual/metaprogramming/","page":"元编程","title":"元编程","text":"请注意,这里并没有打印 Int64。我们可以看到对于特定的参数类型集来说,生成函数的主体只执行一次,且结果会被缓存。此后,对于此示例,生成函数首次调用返回的表达式被重新用作方法主体。但是,实际的缓存行为是由实现定义的性能优化,过于依赖此行为并不实际。","category":"page"},{"location":"manual/metaprogramming/","page":"元编程","title":"元编程","text":"生成函数可能只生成一次函数,但也可能多次生成,或者看起来根本就没有生成过函数。因此,你应该从不编写有副作用的生成函数——因为副作用发生的时间和频率是不确定的。(对于宏来说也是如此——跟宏一样,在生成函数中使用 eval 也许意味着你正以错误的方式做某事。)但是,与宏不同,运行时系统无法正确处理对 eval 的调用,所以不允许这样做。","category":"page"},{"location":"manual/metaprogramming/","page":"元编程","title":"元编程","text":"理解 @generated 函数与方法的重定义间如何相互作用也很重要。遵循正确的 @generated 函数不能观察任何可变状态或导致全局状态的任何更改的原则,我们看到以下行为。观察到,生成函数不能调用在生成函数本身的定义之前未定义的任何方法。","category":"page"},{"location":"manual/metaprogramming/","page":"元编程","title":"元编程","text":"一开始 f(x) 有一个定义","category":"page"},{"location":"manual/metaprogramming/","page":"元编程","title":"元编程","text":"julia> f(x) = \"original definition\";","category":"page"},{"location":"manual/metaprogramming/","page":"元编程","title":"元编程","text":"定义使用 f(x) 的其它操作:","category":"page"},{"location":"manual/metaprogramming/","page":"元编程","title":"元编程","text":"julia> g(x) = f(x);\n\njulia> @generated gen1(x) = f(x);\n\njulia> @generated gen2(x) = :(f(x));","category":"page"},{"location":"manual/metaprogramming/","page":"元编程","title":"元编程","text":"我们现在为 f(x) 添加几个新定义:","category":"page"},{"location":"manual/metaprogramming/","page":"元编程","title":"元编程","text":"julia> f(x::Int) = \"definition for Int\";\n\njulia> f(x::Type{Int}) = \"definition for Type{Int}\";","category":"page"},{"location":"manual/metaprogramming/","page":"元编程","title":"元编程","text":"并比较这些结果的差异:","category":"page"},{"location":"manual/metaprogramming/","page":"元编程","title":"元编程","text":"julia> f(1)\n\"definition for Int\"\n\njulia> g(1)\n\"definition for Int\"\n\njulia> gen1(1)\n\"original definition\"\n\njulia> gen2(1)\n\"definition for Int\"","category":"page"},{"location":"manual/metaprogramming/","page":"元编程","title":"元编程","text":"生成函数的每个方法都有自己的已定义函数视图:","category":"page"},{"location":"manual/metaprogramming/","page":"元编程","title":"元编程","text":"julia> @generated gen1(x::Real) = f(x);\n\njulia> gen1(1)\n\"definition for Type{Int}\"","category":"page"},{"location":"manual/metaprogramming/","page":"元编程","title":"元编程","text":"上例中的生成函数 foo 能做的,通常的函数 foo(x) = x * x 也能做(除了在第一次调用时打印类型,并产生了更高的开销)。但是,生成函数的强大之处在于其能够根据传递给它的类型计算不同的被引用的表达式:","category":"page"},{"location":"manual/metaprogramming/","page":"元编程","title":"元编程","text":"julia> @generated function bar(x)\n if x <: Integer\n return :(x ^ 2)\n else\n return :(x)\n end\n end\nbar (generic function with 1 method)\n\njulia> bar(4)\n16\n\njulia> bar(\"baz\")\n\"baz\"","category":"page"},{"location":"manual/metaprogramming/","page":"元编程","title":"元编程","text":"(当然,这个刻意的例子可以更简单地通过多重派发实现······)","category":"page"},{"location":"manual/metaprogramming/","page":"元编程","title":"元编程","text":"滥用它会破坏运行时系统并导致未定义行为:","category":"page"},{"location":"manual/metaprogramming/","page":"元编程","title":"元编程","text":"julia> @generated function baz(x)\n if rand() < .9\n return :(x^2)\n else\n return :(\"boo!\")\n end\n end\nbaz (generic function with 1 method)","category":"page"},{"location":"manual/metaprogramming/","page":"元编程","title":"元编程","text":"由于生成函数的主体具有不确定性,其行为和所有后续代码的行为并未定义。","category":"page"},{"location":"manual/metaprogramming/","page":"元编程","title":"元编程","text":"不要复制这些例子!","category":"page"},{"location":"manual/metaprogramming/","page":"元编程","title":"元编程","text":"这些例子有助于说明生成函数定义和调用的工作方式;但是,不要复制它们,原因如下:","category":"page"},{"location":"manual/metaprogramming/","page":"元编程","title":"元编程","text":"foo 函数有副作用(对 Core.println 的调用),并且未确切定义这些副作用发生的时间、频率和次数。\nbar 函数解决的问题可通过多重派发被更好地解决——定义 bar(x) = x 和 bar(x::Integer) = x ^ 2 会做同样的事,但它更简单和快捷。\nbaz 函数是病态的","category":"page"},{"location":"manual/metaprogramming/","page":"元编程","title":"元编程","text":"请注意,不应在生成函数中尝试的操作并无严格限制,且运行时系统现在只能检测一部分无效操作。还有许多操作只会破坏运行时系统而没有通知,通常以微妙的方式而非显然地与错误的定义相关联。因为函数生成器是在类型推导期间运行的,所以它必须遵守该代码的所有限制。","category":"page"},{"location":"manual/metaprogramming/","page":"元编程","title":"元编程","text":"一些不应该尝试的操作包括:","category":"page"},{"location":"manual/metaprogramming/","page":"元编程","title":"元编程","text":"缓存本地指针。\n以任何方式与 Core.Compiler 的内容或方法交互。\n观察任何可变状态。\n生成函数的类型推导可以在任何时候运行,包括你的代码正在尝试观察或更改此状态时。\n采用任何锁:你调用的 C 代码可以在内部使用锁(例如,调用 malloc 不会有问题,即使大多数实现在内部需要锁),但是不要试图在执行 Julia 代码时保持或请求任何锁。\n调用在生成函数的主体后定义的任何函数。对于增量加载的预编译模块,则放宽此条件,以允许调用模块中的任何函数。","category":"page"},{"location":"manual/metaprogramming/","page":"元编程","title":"元编程","text":"那好,我们现在已经更好地理解了生成函数的工作方式,让我们使用它来构建一些更高级(和有效)的功能……","category":"page"},{"location":"manual/metaprogramming/#一个高级的例子","page":"元编程","title":"一个高级的例子","text":"","category":"section"},{"location":"manual/metaprogramming/","page":"元编程","title":"元编程","text":"Julia 的 base 库有个内部函数 sub2ind,用于根据一组 n 重线性索引计算 n 维数组的线性索引——换句话说,用于计算索引 i,其可用于使用 A[i] 来索引数组 A,而不是用 A[x,y,z,...]。一种可能的实现如下:","category":"page"},{"location":"manual/metaprogramming/","page":"元编程","title":"元编程","text":"julia> function sub2ind_loop(dims::NTuple{N}, I::Integer...) where N\n ind = I[N] - 1\n for i = N-1:-1:1\n ind = I[i]-1 + dims[i]*ind\n end\n return ind + 1\n end\nsub2ind_loop (generic function with 1 method)\n\njulia> sub2ind_loop((3, 5), 1, 2)\n4","category":"page"},{"location":"manual/metaprogramming/","page":"元编程","title":"元编程","text":"用递归可以完成同样的事情:","category":"page"},{"location":"manual/metaprogramming/","page":"元编程","title":"元编程","text":"julia> sub2ind_rec(dims::Tuple{}) = 1;\n\njulia> sub2ind_rec(dims::Tuple{}, i1::Integer, I::Integer...) =\n i1 == 1 ? sub2ind_rec(dims, I...) : throw(BoundsError());\n\njulia> sub2ind_rec(dims::Tuple{Integer, Vararg{Integer}}, i1::Integer) = i1;\n\njulia> sub2ind_rec(dims::Tuple{Integer, Vararg{Integer}}, i1::Integer, I::Integer...) =\n i1 + dims[1] * (sub2ind_rec(Base.tail(dims), I...) - 1);\n\njulia> sub2ind_rec((3, 5), 1, 2)\n4","category":"page"},{"location":"manual/metaprogramming/","page":"元编程","title":"元编程","text":"这两种实现虽然不同,但本质上做同样的事情:在数组维度上的运行时循环,将每个维度上的偏移量收集到最后的索引中。","category":"page"},{"location":"manual/metaprogramming/","page":"元编程","title":"元编程","text":"然而,循环所需的信息都已嵌入到参数的类型信息中。因此,我们可以利用生成函数将迭代移动到编译期;用编译器的说法,我们用生成函数手动展开循环。代码主体变得几乎相同,但我们不是计算线性索引,而是建立计算索引的表达式:","category":"page"},{"location":"manual/metaprogramming/","page":"元编程","title":"元编程","text":"julia> @generated function sub2ind_gen(dims::NTuple{N}, I::Integer...) where N\n ex = :(I[$N] - 1)\n for i = (N - 1):-1:1\n ex = :(I[$i] - 1 + dims[$i] * $ex)\n end\n return :($ex + 1)\n end\nsub2ind_gen (generic function with 1 method)\n\njulia> sub2ind_gen((3, 5), 1, 2)\n4","category":"page"},{"location":"manual/metaprogramming/","page":"元编程","title":"元编程","text":"这会生成什么代码?","category":"page"},{"location":"manual/metaprogramming/","page":"元编程","title":"元编程","text":"找出所生成代码的一个简单方法是将生成函数的主体提取到另一个(通常的)函数中:","category":"page"},{"location":"manual/metaprogramming/","page":"元编程","title":"元编程","text":"julia> @generated function sub2ind_gen(dims::NTuple{N}, I::Integer...) where N\n return sub2ind_gen_impl(dims, I...)\n end\nsub2ind_gen (generic function with 1 method)\n\njulia> function sub2ind_gen_impl(dims::Type{T}, I...) where T <: NTuple{N,Any} where N\n length(I) == N || return :(error(\"partial indexing is unsupported\"))\n ex = :(I[$N] - 1)\n for i = (N - 1):-1:1\n ex = :(I[$i] - 1 + dims[$i] * $ex)\n end\n return :($ex + 1)\n end\nsub2ind_gen_impl (generic function with 1 method)","category":"page"},{"location":"manual/metaprogramming/","page":"元编程","title":"元编程","text":"我们现在可以执行 sub2ind_gen_impl 并检查它所返回的表达式:","category":"page"},{"location":"manual/metaprogramming/","page":"元编程","title":"元编程","text":"julia> sub2ind_gen_impl(Tuple{Int,Int}, Int, Int)\n:(((I[1] - 1) + dims[1] * (I[2] - 1)) + 1)","category":"page"},{"location":"manual/metaprogramming/","page":"元编程","title":"元编程","text":"因此,这里使用的方法主体根本不包含循环——只有两个元组的索引、乘法和加法/减法。所有循环都是在编译期执行的,我们完全避免了在执行期间的循环。因此,我们只需对每个类型循环一次,在本例中每个 N 循环一次(除了在该函数被多次生成的边缘情况——请参阅上面的免责声明)。","category":"page"},{"location":"manual/metaprogramming/#可选地生成函数","page":"元编程","title":"可选地生成函数","text":"","category":"section"},{"location":"manual/metaprogramming/","page":"元编程","title":"元编程","text":"生成函数可以在运行时实现高效率,但需要编译时间成本:必须为具体的参数类型的每个组合生成新的函数体。通常,Julia 能够编译函数的「泛型」版本,其适用于任何参数,但对于生成函数,这是不可能的。这意味着大量使用生成函数的程序可能无法静态编译。","category":"page"},{"location":"manual/metaprogramming/","page":"元编程","title":"元编程","text":"为了解决这个问题,语言提供用于编写生成函数的通常、非生成的替代实现的语法。应用于上面的 sub2ind 示例,它看起来像这样:","category":"page"},{"location":"manual/metaprogramming/","page":"元编程","title":"元编程","text":"function sub2ind_gen(dims::NTuple{N}, I::Integer...) where N\n if N != length(I)\n throw(ArgumentError(\"Number of dimensions must match number of indices.\"))\n end\n if @generated\n ex = :(I[$N] - 1)\n for i = (N - 1):-1:1\n ex = :(I[$i] - 1 + dims[$i] * $ex)\n end\n return :($ex + 1)\n else\n ind = I[N] - 1\n for i = (N - 1):-1:1\n ind = I[i] - 1 + dims[i]*ind\n end\n return ind + 1\n end\nend","category":"page"},{"location":"manual/metaprogramming/","page":"元编程","title":"元编程","text":"在内部,这段代码创建了函数的两个实现:一个生成函数的实现,其使用 if @generated 中的第一个块,一个通常的函数的实现,其使用 else 块。在 if @generated 块的 then 部分中,代码与其它生成函数具有相同的语义:参数名称引用类型,且代码应返回表达式。可能会出现多个 if @generated 块,在这种情况下,生成函数的实现使用所有的 then 块,而替代实现使用所有的 else 块。","category":"page"},{"location":"manual/metaprogramming/","page":"元编程","title":"元编程","text":"请注意,我们在函数顶部添加了错误检查。此代码对两个版本都是通用的,且是两个版本中的运行时代码(它将被引用并返回为生成函数版本中的表达式)。这意味着局部变量的值和类型在代码生成时不可用——用于代码生成的代码只能看到参数类型。","category":"page"},{"location":"manual/metaprogramming/","page":"元编程","title":"元编程","text":"在这种定义方式中,代码生成功能本质上只是一种可选的优化。如果方便,编译器将使用它,否则可能选择使用通常的实现。这种方式是首选的,因为它允许编译器做出更多决策和以更多方式编译程序,还因为通常代码比由代码生成的代码更易读。但是,使用哪种实现取决于编译器实现细节,因此,两个实现的行为必须相同。","category":"page"},{"location":"devdocs/offset-arrays/#man-custom-indices","page":"Arrays with custom indices","title":"Arrays with custom indices","text":"","category":"section"},{"location":"devdocs/offset-arrays/","page":"Arrays with custom indices","title":"Arrays with custom indices","text":"Conventionally, Julia's arrays are indexed starting at 1, whereas some other languages start numbering at 0, and yet others (e.g., Fortran) allow you to specify arbitrary starting indices. While there is much merit in picking a standard (i.e., 1 for Julia), there are some algorithms which simplify considerably if you can index outside the range 1:size(A,d) (and not just 0:size(A,d)-1, either). To facilitate such computations, Julia supports arrays with arbitrary indices.","category":"page"},{"location":"devdocs/offset-arrays/","page":"Arrays with custom indices","title":"Arrays with custom indices","text":"The purpose of this page is to address the question, \"what do I have to do to support such arrays in my own code?\" First, let's address the simplest case: if you know that your code will never need to handle arrays with unconventional indexing, hopefully the answer is \"nothing.\" Old code, on conventional arrays, should function essentially without alteration as long as it was using the exported interfaces of Julia. If you find it more convenient to just force your users to supply traditional arrays where indexing starts at one, you can add","category":"page"},{"location":"devdocs/offset-arrays/","page":"Arrays with custom indices","title":"Arrays with custom indices","text":"Base.require_one_based_indexing(arrays...)","category":"page"},{"location":"devdocs/offset-arrays/","page":"Arrays with custom indices","title":"Arrays with custom indices","text":"where arrays... is a list of the array objects that you wish to check for anything that violates 1-based indexing.","category":"page"},{"location":"devdocs/offset-arrays/#Generalizing-existing-code","page":"Arrays with custom indices","title":"Generalizing existing code","text":"","category":"section"},{"location":"devdocs/offset-arrays/","page":"Arrays with custom indices","title":"Arrays with custom indices","text":"As an overview, the steps are:","category":"page"},{"location":"devdocs/offset-arrays/","page":"Arrays with custom indices","title":"Arrays with custom indices","text":"replace many uses of size with axes\nreplace 1:length(A) with eachindex(A), or in some cases LinearIndices(A)\nreplace explicit allocations like Array{Int}(undef, size(B)) with similar(Array{Int}, axes(B))","category":"page"},{"location":"devdocs/offset-arrays/","page":"Arrays with custom indices","title":"Arrays with custom indices","text":"These are described in more detail below.","category":"page"},{"location":"devdocs/offset-arrays/#Things-to-watch-out-for","page":"Arrays with custom indices","title":"Things to watch out for","text":"","category":"section"},{"location":"devdocs/offset-arrays/","page":"Arrays with custom indices","title":"Arrays with custom indices","text":"Because unconventional indexing breaks many people's assumptions that all arrays start indexing with 1, there is always the chance that using such arrays will trigger errors. The most frustrating bugs would be incorrect results or segfaults (total crashes of Julia). For example, consider the following function:","category":"page"},{"location":"devdocs/offset-arrays/","page":"Arrays with custom indices","title":"Arrays with custom indices","text":"function mycopy!(dest::AbstractVector, src::AbstractVector)\n length(dest) == length(src) || throw(DimensionMismatch(\"vectors must match\"))\n # OK, now we're safe to use @inbounds, right? (not anymore!)\n for i = 1:length(src)\n @inbounds dest[i] = src[i]\n end\n dest\nend","category":"page"},{"location":"devdocs/offset-arrays/","page":"Arrays with custom indices","title":"Arrays with custom indices","text":"This code implicitly assumes that vectors are indexed from 1; if dest starts at a different index than src, there is a chance that this code would trigger a segfault. (If you do get segfaults, to help locate the cause try running julia with the option --check-bounds=yes.)","category":"page"},{"location":"devdocs/offset-arrays/#Using-axes-for-bounds-checks-and-loop-iteration","page":"Arrays with custom indices","title":"Using axes for bounds checks and loop iteration","text":"","category":"section"},{"location":"devdocs/offset-arrays/","page":"Arrays with custom indices","title":"Arrays with custom indices","text":"axes(A) (reminiscent of size(A)) returns a tuple of AbstractUnitRange{<:Integer} objects, specifying the range of valid indices along each dimension of A. When A has unconventional indexing, the ranges may not start at 1. If you just want the range for a particular dimension d, there is axes(A, d).","category":"page"},{"location":"devdocs/offset-arrays/","page":"Arrays with custom indices","title":"Arrays with custom indices","text":"Base implements a custom range type, OneTo, where OneTo(n) means the same thing as 1:n but in a form that guarantees (via the type system) that the lower index is 1. For any new AbstractArray type, this is the default returned by axes, and it indicates that this array type uses \"conventional\" 1-based indexing.","category":"page"},{"location":"devdocs/offset-arrays/","page":"Arrays with custom indices","title":"Arrays with custom indices","text":"For bounds checking, note that there are dedicated functions checkbounds and checkindex which can sometimes simplify such tests.","category":"page"},{"location":"devdocs/offset-arrays/#Linear-indexing-(LinearIndices)","page":"Arrays with custom indices","title":"Linear indexing (LinearIndices)","text":"","category":"section"},{"location":"devdocs/offset-arrays/","page":"Arrays with custom indices","title":"Arrays with custom indices","text":"Some algorithms are most conveniently (or efficiently) written in terms of a single linear index, A[i] even if A is multi-dimensional. Regardless of the array's native indices, linear indices always range from 1:length(A). However, this raises an ambiguity for one-dimensional arrays (a.k.a., AbstractVector): does v[i] mean linear indexing , or Cartesian indexing with the array's native indices?","category":"page"},{"location":"devdocs/offset-arrays/","page":"Arrays with custom indices","title":"Arrays with custom indices","text":"For this reason, your best option may be to iterate over the array with eachindex(A), or, if you require the indices to be sequential integers, to get the index range by calling LinearIndices(A). This will return axes(A, 1) if A is an AbstractVector, and the equivalent of 1:length(A) otherwise.","category":"page"},{"location":"devdocs/offset-arrays/","page":"Arrays with custom indices","title":"Arrays with custom indices","text":"By this definition, 1-dimensional arrays always use Cartesian indexing with the array's native indices. To help enforce this, it's worth noting that the index conversion functions will throw an error if shape indicates a 1-dimensional array with unconventional indexing (i.e., is a Tuple{UnitRange} rather than a tuple of OneTo). For arrays with conventional indexing, these functions continue to work the same as always.","category":"page"},{"location":"devdocs/offset-arrays/","page":"Arrays with custom indices","title":"Arrays with custom indices","text":"Using axes and LinearIndices, here is one way you could rewrite mycopy!:","category":"page"},{"location":"devdocs/offset-arrays/","page":"Arrays with custom indices","title":"Arrays with custom indices","text":"function mycopy!(dest::AbstractVector, src::AbstractVector)\n axes(dest) == axes(src) || throw(DimensionMismatch(\"vectors must match\"))\n for i in LinearIndices(src)\n @inbounds dest[i] = src[i]\n end\n dest\nend","category":"page"},{"location":"devdocs/offset-arrays/#Allocating-storage-using-generalizations-of-similar","page":"Arrays with custom indices","title":"Allocating storage using generalizations of similar","text":"","category":"section"},{"location":"devdocs/offset-arrays/","page":"Arrays with custom indices","title":"Arrays with custom indices","text":"Storage is often allocated with Array{Int}(undef, dims) or similar(A, args...). When the result needs to match the indices of some other array, this may not always suffice. The generic replacement for such patterns is to use similar(storagetype, shape). storagetype indicates the kind of underlying \"conventional\" behavior you'd like, e.g., Array{Int} or BitArray or even dims->zeros(Float32, dims) (which would allocate an all-zeros array). shape is a tuple of Integer or AbstractUnitRange values, specifying the indices that you want the result to use. Note that a convenient way of producing an all-zeros array that matches the indices of A is simply zeros(A).","category":"page"},{"location":"devdocs/offset-arrays/","page":"Arrays with custom indices","title":"Arrays with custom indices","text":"Let's walk through a couple of explicit examples. First, if A has conventional indices, then similar(Array{Int}, axes(A)) would end up calling Array{Int}(undef, size(A)), and thus return an array. If A is an AbstractArray type with unconventional indexing, then similar(Array{Int}, axes(A)) should return something that \"behaves like\" an Array{Int} but with a shape (including indices) that matches A. (The most obvious implementation is to allocate an Array{Int}(undef, size(A)) and then \"wrap\" it in a type that shifts the indices.)","category":"page"},{"location":"devdocs/offset-arrays/","page":"Arrays with custom indices","title":"Arrays with custom indices","text":"Note also that similar(Array{Int}, (axes(A, 2),)) would allocate an AbstractVector{Int} (i.e., 1-dimensional array) that matches the indices of the columns of A.","category":"page"},{"location":"devdocs/offset-arrays/#Writing-custom-array-types-with-non-1-indexing","page":"Arrays with custom indices","title":"Writing custom array types with non-1 indexing","text":"","category":"section"},{"location":"devdocs/offset-arrays/","page":"Arrays with custom indices","title":"Arrays with custom indices","text":"Most of the methods you'll need to define are standard for any AbstractArray type, see Abstract Arrays. This page focuses on the steps needed to define unconventional indexing.","category":"page"},{"location":"devdocs/offset-arrays/#Custom-AbstractUnitRange-types","page":"Arrays with custom indices","title":"Custom AbstractUnitRange types","text":"","category":"section"},{"location":"devdocs/offset-arrays/","page":"Arrays with custom indices","title":"Arrays with custom indices","text":"If you're writing a non-1 indexed array type, you will want to specialize axes so it returns a UnitRange, or (perhaps better) a custom AbstractUnitRange. The advantage of a custom type is that it \"signals\" the allocation type for functions like similar. If we're writing an array type for which indexing will start at 0, we likely want to begin by creating a new AbstractUnitRange, ZeroRange, where ZeroRange(n) is equivalent to 0:n-1.","category":"page"},{"location":"devdocs/offset-arrays/","page":"Arrays with custom indices","title":"Arrays with custom indices","text":"In general, you should probably not export ZeroRange from your package: there may be other packages that implement their own ZeroRange, and having multiple distinct ZeroRange types is (perhaps counterintuitively) an advantage: ModuleA.ZeroRange indicates that similar should create a ModuleA.ZeroArray, whereas ModuleB.ZeroRange indicates a ModuleB.ZeroArray type. This design allows peaceful coexistence among many different custom array types.","category":"page"},{"location":"devdocs/offset-arrays/","page":"Arrays with custom indices","title":"Arrays with custom indices","text":"Note that the Julia package CustomUnitRanges.jl can sometimes be used to avoid the need to write your own ZeroRange type.","category":"page"},{"location":"devdocs/offset-arrays/#Specializing-axes","page":"Arrays with custom indices","title":"Specializing axes","text":"","category":"section"},{"location":"devdocs/offset-arrays/","page":"Arrays with custom indices","title":"Arrays with custom indices","text":"Once you have your AbstractUnitRange type, then specialize axes:","category":"page"},{"location":"devdocs/offset-arrays/","page":"Arrays with custom indices","title":"Arrays with custom indices","text":"Base.axes(A::ZeroArray) = map(n->ZeroRange(n), A.size)","category":"page"},{"location":"devdocs/offset-arrays/","page":"Arrays with custom indices","title":"Arrays with custom indices","text":"where here we imagine that ZeroArray has a field called size (there would be other ways to implement this).","category":"page"},{"location":"devdocs/offset-arrays/","page":"Arrays with custom indices","title":"Arrays with custom indices","text":"In some cases, the fallback definition for axes(A, d):","category":"page"},{"location":"devdocs/offset-arrays/","page":"Arrays with custom indices","title":"Arrays with custom indices","text":"axes(A::AbstractArray{T,N}, d) where {T,N} = d <= N ? axes(A)[d] : OneTo(1)","category":"page"},{"location":"devdocs/offset-arrays/","page":"Arrays with custom indices","title":"Arrays with custom indices","text":"may not be what you want: you may need to specialize it to return something other than OneTo(1) when d > ndims(A). Likewise, in Base there is a dedicated function axes1 which is equivalent to axes(A, 1) but which avoids checking (at runtime) whether ndims(A) > 0. (This is purely a performance optimization.) It is defined as:","category":"page"},{"location":"devdocs/offset-arrays/","page":"Arrays with custom indices","title":"Arrays with custom indices","text":"axes1(A::AbstractArray{T,0}) where {T} = OneTo(1)\naxes1(A::AbstractArray) = axes(A)[1]","category":"page"},{"location":"devdocs/offset-arrays/","page":"Arrays with custom indices","title":"Arrays with custom indices","text":"If the first of these (the zero-dimensional case) is problematic for your custom array type, be sure to specialize it appropriately.","category":"page"},{"location":"devdocs/offset-arrays/#Specializing-similar","page":"Arrays with custom indices","title":"Specializing similar","text":"","category":"section"},{"location":"devdocs/offset-arrays/","page":"Arrays with custom indices","title":"Arrays with custom indices","text":"Given your custom ZeroRange type, then you should also add the following two specializations for similar:","category":"page"},{"location":"devdocs/offset-arrays/","page":"Arrays with custom indices","title":"Arrays with custom indices","text":"function Base.similar(A::AbstractArray, T::Type, shape::Tuple{ZeroRange,Vararg{ZeroRange}})\n # body\nend\n\nfunction Base.similar(f::Union{Function,DataType}, shape::Tuple{ZeroRange,Vararg{ZeroRange}})\n # body\nend","category":"page"},{"location":"devdocs/offset-arrays/","page":"Arrays with custom indices","title":"Arrays with custom indices","text":"Both of these should allocate your custom array type.","category":"page"},{"location":"devdocs/offset-arrays/#Specializing-reshape","page":"Arrays with custom indices","title":"Specializing reshape","text":"","category":"section"},{"location":"devdocs/offset-arrays/","page":"Arrays with custom indices","title":"Arrays with custom indices","text":"Optionally, define a method","category":"page"},{"location":"devdocs/offset-arrays/","page":"Arrays with custom indices","title":"Arrays with custom indices","text":"Base.reshape(A::AbstractArray, shape::Tuple{ZeroRange,Vararg{ZeroRange}}) = ...","category":"page"},{"location":"devdocs/offset-arrays/","page":"Arrays with custom indices","title":"Arrays with custom indices","text":"and you can reshape an array so that the result has custom indices.","category":"page"},{"location":"devdocs/offset-arrays/#For-objects-that-mimic-AbstractArray-but-are-not-subtypes","page":"Arrays with custom indices","title":"For objects that mimic AbstractArray but are not subtypes","text":"","category":"section"},{"location":"devdocs/offset-arrays/","page":"Arrays with custom indices","title":"Arrays with custom indices","text":"has_offset_axes depends on having axes defined for the objects you call it on. If there is some reason you don't have an axes method defined for your object, consider defining a method","category":"page"},{"location":"devdocs/offset-arrays/","page":"Arrays with custom indices","title":"Arrays with custom indices","text":"Base.has_offset_axes(obj::MyNon1IndexedArraylikeObject) = true","category":"page"},{"location":"devdocs/offset-arrays/","page":"Arrays with custom indices","title":"Arrays with custom indices","text":"This will allow code that assumes 1-based indexing to detect a problem and throw a helpful error, rather than returning incorrect results or segfaulting julia.","category":"page"},{"location":"devdocs/offset-arrays/#Catching-errors","page":"Arrays with custom indices","title":"Catching errors","text":"","category":"section"},{"location":"devdocs/offset-arrays/","page":"Arrays with custom indices","title":"Arrays with custom indices","text":"If your new array type triggers errors in other code, one helpful debugging step can be to comment out @boundscheck in your getindex and setindex! implementation. This will ensure that every element access checks bounds. Or, restart julia with --check-bounds=yes.","category":"page"},{"location":"devdocs/offset-arrays/","page":"Arrays with custom indices","title":"Arrays with custom indices","text":"In some cases it may also be helpful to temporarily disable size and length for your new array type, since code that makes incorrect assumptions frequently uses these functions.","category":"page"},{"location":"devdocs/boundscheck/#边界检查","page":"边界检查","title":"边界检查","text":"","category":"section"},{"location":"devdocs/boundscheck/","page":"边界检查","title":"边界检查","text":"和许多其他现代编程语言一样,Julia 在访问数组元素的时候也要通过边界检查来确保程序安全。当循环次数很多,或者在其他性能敏感的场景下,你可能希望不进行边界检查以提高运行时性能。比如要使用矢量 (SIMD) 指令,循环体就不能有分支语句,因此无法进行边界检查。Julia 提供了一个宏 @inbounds(...) 来告诉编译器在指定语句块不进行边界检查。用户自定义的数组类型可以通过宏 @boundscheck(...) 来达到上下文敏感的代码选择目的。","category":"page"},{"location":"devdocs/boundscheck/#移除边界检查","page":"边界检查","title":"移除边界检查","text":"","category":"section"},{"location":"devdocs/boundscheck/","page":"边界检查","title":"边界检查","text":"宏 @boundscheck(...) 把代码块标记为要执行边界检查。但当这些代码块被被宏 @inbounds(...) 标记的代码包裹时,它们可能会被编译器移除。仅当@boundscheck(...) 代码块被调用函数包裹时,编译器会移除它们。比如你可能这样写的 sum 方法: ","category":"page"},{"location":"devdocs/boundscheck/","page":"边界检查","title":"边界检查","text":"function sum(A::AbstractArray)\n r = zero(eltype(A))\n for i in eachindex(A)\n @inbounds r += A[i]\n end\n return r\nend","category":"page"},{"location":"devdocs/boundscheck/","page":"边界检查","title":"边界检查","text":"使用自定义的类数组类型 MyArray,我们有:","category":"page"},{"location":"devdocs/boundscheck/","page":"边界检查","title":"边界检查","text":"@inline getindex(A::MyArray, i::Real) = (@boundscheck checkbounds(A,i); A.data[to_index(i)])","category":"page"},{"location":"devdocs/boundscheck/","page":"边界检查","title":"边界检查","text":"当 getindex 被 sum 包裹时,对 checkbounds(A,i) 的调用会被忽略。如果存在多层包裹,最多只有一个 @boundscheck 被忽略。这个规则用来防止将来代码被改变时潜在的多余忽略。","category":"page"},{"location":"devdocs/boundscheck/#Propagating-inbounds","page":"边界检查","title":"Propagating inbounds","text":"","category":"section"},{"location":"devdocs/boundscheck/","page":"边界检查","title":"边界检查","text":"There may be certain scenarios where for code-organization reasons you want more than one layer between the @inbounds and @boundscheck declarations. For instance, the default getindex methods have the chain getindex(A::AbstractArray, i::Real) calls getindex(IndexStyle(A), A, i) calls _getindex(::IndexLinear, A, i).","category":"page"},{"location":"devdocs/boundscheck/","page":"边界检查","title":"边界检查","text":"To override the \"one layer of inlining\" rule, a function may be marked with Base.@propagate_inbounds to propagate an inbounds context (or out of bounds context) through one additional layer of inlining.","category":"page"},{"location":"devdocs/boundscheck/#The-bounds-checking-call-hierarchy","page":"边界检查","title":"The bounds checking call hierarchy","text":"","category":"section"},{"location":"devdocs/boundscheck/","page":"边界检查","title":"边界检查","text":"The overall hierarchy is:","category":"page"},{"location":"devdocs/boundscheck/","page":"边界检查","title":"边界检查","text":"checkbounds(A, I...) which calls\ncheckbounds(Bool, A, I...) which calls\ncheckbounds_indices(Bool, axes(A), I) which recursively calls\ncheckindex for each dimension","category":"page"},{"location":"devdocs/boundscheck/","page":"边界检查","title":"边界检查","text":"Here A is the array, and I contains the \"requested\" indices. axes(A) returns a tuple of \"permitted\" indices of A.","category":"page"},{"location":"devdocs/boundscheck/","page":"边界检查","title":"边界检查","text":"checkbounds(A, I...) throws an error if the indices are invalid, whereas checkbounds(Bool, A, I...) returns false in that circumstance. checkbounds_indices discards any information about the array other than its axes tuple, and performs a pure indices-vs-indices comparison: this allows relatively few compiled methods to serve a huge variety of array types. Indices are specified as tuples, and are usually compared in a 1-1 fashion with individual dimensions handled by calling another important function, checkindex: typically,","category":"page"},{"location":"devdocs/boundscheck/","page":"边界检查","title":"边界检查","text":"checkbounds_indices(Bool, (IA1, IA...), (I1, I...)) = checkindex(Bool, IA1, I1) &\n checkbounds_indices(Bool, IA, I)","category":"page"},{"location":"devdocs/boundscheck/","page":"边界检查","title":"边界检查","text":"so checkindex checks a single dimension. All of these functions, including the unexported checkbounds_indices have docstrings accessible with ? .","category":"page"},{"location":"devdocs/boundscheck/","page":"边界检查","title":"边界检查","text":"If you have to customize bounds checking for a specific array type, you should specialize checkbounds(Bool, A, I...). However, in most cases you should be able to rely on checkbounds_indices as long as you supply useful axes for your array type.","category":"page"},{"location":"devdocs/boundscheck/","page":"边界检查","title":"边界检查","text":"If you have novel index types, first consider specializing checkindex, which handles a single index for a particular dimension of an array. If you have a custom multidimensional index type (similar to CartesianIndex), then you may have to consider specializing checkbounds_indices.","category":"page"},{"location":"devdocs/boundscheck/","page":"边界检查","title":"边界检查","text":"Note this hierarchy has been designed to reduce the likelihood of method ambiguities. We try to make checkbounds the place to specialize on array type, and try to avoid specializations on index types; conversely, checkindex is intended to be specialized only on index type (especially, the last argument).","category":"page"},{"location":"devdocs/boundscheck/#Emit-bounds-checks","page":"边界检查","title":"Emit bounds checks","text":"","category":"section"},{"location":"devdocs/boundscheck/","page":"边界检查","title":"边界检查","text":"Julia can be launched with --check-bounds={yes|no|auto} to emit bounds checks always, never, or respect @inbounds declarations.","category":"page"},{"location":"stdlib/Random/#随机数","page":"随机数","title":"随机数","text":"","category":"section"},{"location":"stdlib/Random/","page":"随机数","title":"随机数","text":"DocTestSetup = :(using Random)","category":"page"},{"location":"stdlib/Random/","page":"随机数","title":"随机数","text":"Random number generation in Julia uses the Xoshiro256++ algorithm by default, with per-Task state. Other RNG types can be plugged in by inheriting the AbstractRNG type; they can then be used to obtain multiple streams of random numbers. Besides the default TaskLocalRNG type, the Random package also provides MersenneTwister, RandomDevice (which exposes OS-provided entropy), and Xoshiro (for explicitly-managed Xoshiro256++ streams).","category":"page"},{"location":"stdlib/Random/","page":"随机数","title":"随机数","text":"Most functions related to random generation accept an optional AbstractRNG object as first argument. Some also accept dimension specifications dims... (which can also be given as a tuple) to generate arrays of random values. In a multi-threaded program, you should generally use different RNG objects from different threads or tasks in order to be thread-safe. However, the default RNG is thread-safe as of Julia 1.3 (using a per-thread RNG up to version 1.6, and per-task thereafter).","category":"page"},{"location":"stdlib/Random/","page":"随机数","title":"随机数","text":"The provided RNGs can generate uniform random numbers of the following types: Float16, Float32, Float64, BigFloat, Bool, Int8, UInt8, Int16, UInt16, Int32, UInt32, Int64, UInt64, Int128, UInt128, BigInt (or complex numbers of those types). Random floating point numbers are generated uniformly in 0 1). As BigInt represents unbounded integers, the interval must be specified (e.g. rand(big.(1:6))).","category":"page"},{"location":"stdlib/Random/","page":"随机数","title":"随机数","text":"另外,正态和指数分布是针对某些 AbstractFloat 和 Complex 类型,详细内容见 randn 和 randexp。","category":"page"},{"location":"stdlib/Random/","page":"随机数","title":"随机数","text":"warning: Warning\nBecause the precise way in which random numbers are generated is considered an implementation detail, bug fixes and speed improvements may change the stream of numbers that are generated after a version change. Relying on a specific seed or generated stream of numbers during unit testing is thus discouraged - consider testing properties of the methods in question instead.","category":"page"},{"location":"stdlib/Random/#Random-numbers-module","page":"随机数","title":"Random numbers module","text":"","category":"section"},{"location":"stdlib/Random/","page":"随机数","title":"随机数","text":"Random.Random","category":"page"},{"location":"stdlib/Random/#Random.Random","page":"随机数","title":"Random.Random","text":"Random\n\nSupport for generating random numbers. Provides rand, randn, AbstractRNG, MersenneTwister, and RandomDevice.\n\n\n\n\n\n","category":"module"},{"location":"stdlib/Random/#Random-generation-functions","page":"随机数","title":"Random generation functions","text":"","category":"section"},{"location":"stdlib/Random/","page":"随机数","title":"随机数","text":"Random.rand\nRandom.rand!\nRandom.bitrand\nRandom.randn\nRandom.randn!\nRandom.randexp\nRandom.randexp!\nRandom.randstring","category":"page"},{"location":"stdlib/Random/#Base.rand","page":"随机数","title":"Base.rand","text":"rand([rng=GLOBAL_RNG], [S], [dims...])\n\nPick a random element or array of random elements from the set of values specified by S; S can be\n\nan indexable collection (for example 1:9 or ('x', \"y\", :z)),\nan AbstractDict or AbstractSet object,\na string (considered as a collection of characters), or\na type: the set of values to pick from is then equivalent to typemin(S):typemax(S) for integers (this is not applicable to BigInt), to 0 1) for floating point numbers and to 0 1)+i0 1) for complex floating point numbers;\n\nS defaults to Float64. When only one argument is passed besides the optional rng and is a Tuple, it is interpreted as a collection of values (S) and not as dims.\n\ncompat: Julia 1.1\nSupport for S as a tuple requires at least Julia 1.1.\n\nExamples\n\njulia> rand(Int, 2)\n2-element Array{Int64,1}:\n 1339893410598768192\n 1575814717733606317\n\njulia> using Random\n\njulia> rand(MersenneTwister(0), Dict(1=>2, 3=>4))\n1=>2\n\njulia> rand((2, 3))\n3\n\njulia> rand(Float64, (2, 3))\n2×3 Array{Float64,2}:\n 0.999717 0.0143835 0.540787\n 0.696556 0.783855 0.938235\n\nnote: Note\nThe complexity of rand(rng, s::Union{AbstractDict,AbstractSet}) is linear in the length of s, unless an optimized method with constant complexity is available, which is the case for Dict, Set and dense BitSets. For more than a few calls, use rand(rng, collect(s)) instead, or either rand(rng, Dict(s)) or rand(rng, Set(s)) as appropriate.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/Random/#Random.rand!","page":"随机数","title":"Random.rand!","text":"rand!([rng=GLOBAL_RNG], A, [S=eltype(A)])\n\nPopulate the array A with random values. If S is specified (S can be a type or a collection, cf. rand for details), the values are picked randomly from S. This is equivalent to copyto!(A, rand(rng, S, size(A))) but without allocating a new array.\n\nExamples\n\njulia> rng = MersenneTwister(1234);\n\njulia> rand!(rng, zeros(5))\n5-element Vector{Float64}:\n 0.5908446386657102\n 0.7667970365022592\n 0.5662374165061859\n 0.4600853424625171\n 0.7940257103317943\n\n\n\n\n\n","category":"function"},{"location":"stdlib/Random/#Random.bitrand","page":"随机数","title":"Random.bitrand","text":"bitrand([rng=GLOBAL_RNG], [dims...])\n\nGenerate a BitArray of random boolean values.\n\nExamples\n\njulia> rng = MersenneTwister(1234);\n\njulia> bitrand(rng, 10)\n10-element BitVector:\n 0\n 0\n 0\n 0\n 1\n 0\n 0\n 0\n 1\n 1\n\n\n\n\n\n","category":"function"},{"location":"stdlib/Random/#Base.randn","page":"随机数","title":"Base.randn","text":"randn([rng=GLOBAL_RNG], [T=Float64], [dims...])\n\nGenerate a normally-distributed random number of type T with mean 0 and standard deviation 1. Optionally generate an array of normally-distributed random numbers. The Base module currently provides an implementation for the types Float16, Float32, and Float64 (the default), and their Complex counterparts. When the type argument is complex, the values are drawn from the circularly symmetric complex normal distribution of variance 1 (corresponding to real and imaginary part having independent normal distribution with mean zero and variance 1/2).\n\nExamples\n\njulia> using Random\n\njulia> rng = MersenneTwister(1234);\n\njulia> randn(rng, ComplexF64)\n0.6133070881429037 - 0.6376291670853887im\n\njulia> randn(rng, ComplexF32, (2, 3))\n2×3 Matrix{ComplexF32}:\n -0.349649-0.638457im 0.376756-0.192146im -0.396334-0.0136413im\n 0.611224+1.56403im 0.355204-0.365563im 0.0905552+1.31012im\n\n\n\n\n\n","category":"function"},{"location":"stdlib/Random/#Random.randn!","page":"随机数","title":"Random.randn!","text":"randn!([rng=GLOBAL_RNG], A::AbstractArray) -> A\n\nFill the array A with normally-distributed (mean 0, standard deviation 1) random numbers. Also see the rand function.\n\nExamples\n\njulia> rng = MersenneTwister(1234);\n\njulia> randn!(rng, zeros(5))\n5-element Vector{Float64}:\n 0.8673472019512456\n -0.9017438158568171\n -0.4944787535042339\n -0.9029142938652416\n 0.8644013132535154\n\n\n\n\n\n","category":"function"},{"location":"stdlib/Random/#Random.randexp","page":"随机数","title":"Random.randexp","text":"randexp([rng=GLOBAL_RNG], [T=Float64], [dims...])\n\nGenerate a random number of type T according to the exponential distribution with scale 1. Optionally generate an array of such random numbers. The Base module currently provides an implementation for the types Float16, Float32, and Float64 (the default).\n\nExamples\n\njulia> rng = MersenneTwister(1234);\n\njulia> randexp(rng, Float32)\n2.4835055f0\n\njulia> randexp(rng, 3, 3)\n3×3 Matrix{Float64}:\n 1.5167 1.30652 0.344435\n 0.604436 2.78029 0.418516\n 0.695867 0.693292 0.643644\n\n\n\n\n\n","category":"function"},{"location":"stdlib/Random/#Random.randexp!","page":"随机数","title":"Random.randexp!","text":"randexp!([rng=GLOBAL_RNG], A::AbstractArray) -> A\n\nFill the array A with random numbers following the exponential distribution (with scale 1).\n\nExamples\n\njulia> rng = MersenneTwister(1234);\n\njulia> randexp!(rng, zeros(5))\n5-element Vector{Float64}:\n 2.4835053723904896\n 1.516703605376473\n 0.6044364871025417\n 0.6958665886385867\n 1.3065196315496677\n\n\n\n\n\n","category":"function"},{"location":"stdlib/Random/#Random.randstring","page":"随机数","title":"Random.randstring","text":"randstring([rng=GLOBAL_RNG], [chars], [len=8])\n\nCreate a random string of length len, consisting of characters from chars, which defaults to the set of upper- and lower-case letters and the digits 0-9. The optional rng argument specifies a random number generator, see Random Numbers.\n\nExamples\n\njulia> Random.seed!(3); randstring()\n\"Lxz5hUwn\"\n\njulia> randstring(MersenneTwister(3), 'a':'z', 6)\n\"ocucay\"\n\njulia> randstring(\"ACGT\")\n\"TGCTCCTC\"\n\nnote: Note\nchars can be any collection of characters, of type Char or UInt8 (more efficient), provided rand can randomly pick characters from it.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/Random/#Subsequences,-permutations-and-shuffling","page":"随机数","title":"Subsequences, permutations and shuffling","text":"","category":"section"},{"location":"stdlib/Random/","page":"随机数","title":"随机数","text":"Random.randsubseq\nRandom.randsubseq!\nRandom.randperm\nRandom.randperm!\nRandom.randcycle\nRandom.randcycle!\nRandom.shuffle\nRandom.shuffle!","category":"page"},{"location":"stdlib/Random/#Random.randsubseq","page":"随机数","title":"Random.randsubseq","text":"randsubseq([rng=GLOBAL_RNG,] A, p) -> Vector\n\nReturn a vector consisting of a random subsequence of the given array A, where each element of A is included (in order) with independent probability p. (Complexity is linear in p*length(A), so this function is efficient even if p is small and A is large.) Technically, this process is known as \"Bernoulli sampling\" of A.\n\nExamples\n\njulia> rng = MersenneTwister(1234);\n\njulia> randsubseq(rng, 1:8, 0.3)\n2-element Vector{Int64}:\n 7\n 8\n\n\n\n\n\n","category":"function"},{"location":"stdlib/Random/#Random.randsubseq!","page":"随机数","title":"Random.randsubseq!","text":"randsubseq!([rng=GLOBAL_RNG,] S, A, p)\n\nLike randsubseq, but the results are stored in S (which is resized as needed).\n\nExamples\n\njulia> rng = MersenneTwister(1234);\n\njulia> S = Int64[];\n\njulia> randsubseq!(rng, S, 1:8, 0.3)\n2-element Vector{Int64}:\n 7\n 8\n\njulia> S\n2-element Vector{Int64}:\n 7\n 8\n\n\n\n\n\n","category":"function"},{"location":"stdlib/Random/#Random.randperm","page":"随机数","title":"Random.randperm","text":"randperm([rng=GLOBAL_RNG,] n::Integer)\n\nConstruct a random permutation of length n. The optional rng argument specifies a random number generator (see Random Numbers). The element type of the result is the same as the type of n.\n\nTo randomly permute an arbitrary vector, see shuffle or shuffle!.\n\ncompat: Julia 1.1\nIn Julia 1.1 randperm returns a vector v with eltype(v) == typeof(n) while in Julia 1.0 eltype(v) == Int.\n\nExamples\n\njulia> randperm(MersenneTwister(1234), 4)\n4-element Vector{Int64}:\n 2\n 1\n 4\n 3\n\n\n\n\n\n","category":"function"},{"location":"stdlib/Random/#Random.randperm!","page":"随机数","title":"Random.randperm!","text":"randperm!([rng=GLOBAL_RNG,] A::Array{<:Integer})\n\nConstruct in A a random permutation of length length(A). The optional rng argument specifies a random number generator (see Random Numbers). To randomly permute an arbitrary vector, see shuffle or shuffle!.\n\nExamples\n\njulia> randperm!(MersenneTwister(1234), Vector{Int}(undef, 4))\n4-element Vector{Int64}:\n 2\n 1\n 4\n 3\n\n\n\n\n\n","category":"function"},{"location":"stdlib/Random/#Random.randcycle","page":"随机数","title":"Random.randcycle","text":"randcycle([rng=GLOBAL_RNG,] n::Integer)\n\nConstruct a random cyclic permutation of length n. The optional rng argument specifies a random number generator, see Random Numbers. The element type of the result is the same as the type of n.\n\ncompat: Julia 1.1\nIn Julia 1.1 randcycle returns a vector v with eltype(v) == typeof(n) while in Julia 1.0 eltype(v) == Int.\n\nExamples\n\njulia> randcycle(MersenneTwister(1234), 6)\n6-element Vector{Int64}:\n 3\n 5\n 4\n 6\n 1\n 2\n\n\n\n\n\n","category":"function"},{"location":"stdlib/Random/#Random.randcycle!","page":"随机数","title":"Random.randcycle!","text":"randcycle!([rng=GLOBAL_RNG,] A::Array{<:Integer})\n\nConstruct in A a random cyclic permutation of length length(A). The optional rng argument specifies a random number generator, see Random Numbers.\n\nExamples\n\njulia> randcycle!(MersenneTwister(1234), Vector{Int}(undef, 6))\n6-element Vector{Int64}:\n 3\n 5\n 4\n 6\n 1\n 2\n\n\n\n\n\n","category":"function"},{"location":"stdlib/Random/#Random.shuffle","page":"随机数","title":"Random.shuffle","text":"shuffle([rng=GLOBAL_RNG,] v::AbstractArray)\n\nReturn a randomly permuted copy of v. The optional rng argument specifies a random number generator (see Random Numbers). To permute v in-place, see shuffle!. To obtain randomly permuted indices, see randperm.\n\nExamples\n\njulia> rng = MersenneTwister(1234);\n\njulia> shuffle(rng, Vector(1:10))\n10-element Vector{Int64}:\n 6\n 1\n 10\n 2\n 3\n 9\n 5\n 7\n 4\n 8\n\n\n\n\n\n","category":"function"},{"location":"stdlib/Random/#Random.shuffle!","page":"随机数","title":"Random.shuffle!","text":"shuffle!([rng=GLOBAL_RNG,] v::AbstractArray)\n\nIn-place version of shuffle: randomly permute v in-place, optionally supplying the random-number generator rng.\n\nExamples\n\njulia> rng = MersenneTwister(1234);\n\njulia> shuffle!(rng, Vector(1:16))\n16-element Vector{Int64}:\n 2\n 15\n 5\n 14\n 1\n 9\n 10\n 6\n 11\n 3\n 16\n 7\n 4\n 12\n 8\n 13\n\n\n\n\n\n","category":"function"},{"location":"stdlib/Random/#Generators-(creation-and-seeding)","page":"随机数","title":"Generators (creation and seeding)","text":"","category":"section"},{"location":"stdlib/Random/","page":"随机数","title":"随机数","text":"Random.seed!\nRandom.AbstractRNG\nRandom.TaskLocalRNG\nRandom.Xoshiro\nRandom.MersenneTwister\nRandom.RandomDevice","category":"page"},{"location":"stdlib/Random/#Random.seed!","page":"随机数","title":"Random.seed!","text":"seed!([rng=GLOBAL_RNG], seed) -> rng\nseed!([rng=GLOBAL_RNG]) -> rng\n\nReseed the random number generator: rng will give a reproducible sequence of numbers if and only if a seed is provided. Some RNGs don't accept a seed, like RandomDevice. After the call to seed!, rng is equivalent to a newly created object initialized with the same seed.\n\nIf rng is not specified, it defaults to seeding the state of the shared task-local generator.\n\nExamples\n\njulia> Random.seed!(1234);\n\njulia> x1 = rand(2)\n2-element Array{Float64,1}:\n 0.590845\n 0.766797\n\njulia> Random.seed!(1234);\n\njulia> x2 = rand(2)\n2-element Array{Float64,1}:\n 0.590845\n 0.766797\n\njulia> x1 == x2\ntrue\n\njulia> rng = MersenneTwister(1234); rand(rng, 2) == x1\ntrue\n\njulia> MersenneTwister(1) == Random.seed!(rng, 1)\ntrue\n\njulia> rand(Random.seed!(rng), Bool) # not reproducible\ntrue\n\njulia> rand(Random.seed!(rng), Bool)\nfalse\n\njulia> rand(MersenneTwister(), Bool) # not reproducible either\ntrue\n\n\n\n\n\n","category":"function"},{"location":"stdlib/Random/#Random.AbstractRNG","page":"随机数","title":"Random.AbstractRNG","text":"AbstractRNG\n\nSupertype for random number generators such as MersenneTwister and RandomDevice.\n\n\n\n\n\n","category":"type"},{"location":"stdlib/Random/#Random.TaskLocalRNG","page":"随机数","title":"Random.TaskLocalRNG","text":"TaskLocalRNG\n\nThe TaskLocalRNG has state that is local to its task, not its thread. It is seeded upon task creation, from the state of its parent task. Therefore, task creation is an event that changes the parent's RNG state.\n\nAs an upside, the TaskLocalRNG is pretty fast, and permits reproducible multithreaded simulations (barring race conditions), independent of scheduler decisions. As long as the number of threads is not used to make decisions on task creation, simulation results are also independent of the number of available threads / CPUs. The random stream should not depend on hardware specifics, up to endianness and possibly word size.\n\nUsing or seeding the RNG of any other task than the one returned by current_task() is undefined behavior: it will work most of the time, and may sometimes fail silently.\n\n\n\n\n\n","category":"type"},{"location":"stdlib/Random/#Random.Xoshiro","page":"随机数","title":"Random.Xoshiro","text":"Xoshiro(seed)\nXoshiro()\n\nXoshiro256++ is a fast pseudorandom number generator described by David Blackman and Sebastiano Vigna in \"Scrambled Linear Pseudorandom Number Generators\", ACM Trans. Math. Softw., 2021. Reference implementation is available at http://prng.di.unimi.it\n\nApart from the high speed, Xoshiro has a small memory footprint, making it suitable for applications where many different random states need to be held for long time.\n\nJulia's Xoshiro implementation has a bulk-generation mode; this seeds new virtual PRNGs from the parent, and uses SIMD to generate in parallel (i.e. the bulk stream consists of multiple interleaved xoshiro instances). The virtual PRNGs are discarded once the bulk request has been serviced (and should cause no heap allocations).\n\nExamples\n\njulia> using Random\n\njulia> rng = Xoshiro(1234);\n\njulia> x1 = rand(rng, 2)\n2-element Vector{Float64}:\n 0.32597672886359486\n 0.5490511363155669\n\njulia> rng = Xoshiro(1234);\n\njulia> x2 = rand(rng, 2)\n2-element Vector{Float64}:\n 0.32597672886359486\n 0.5490511363155669\n\njulia> x1 == x2\ntrue\n\n\n\n\n\n","category":"type"},{"location":"stdlib/Random/#Random.MersenneTwister","page":"随机数","title":"Random.MersenneTwister","text":"MersenneTwister(seed)\nMersenneTwister()\n\nCreate a MersenneTwister RNG object. Different RNG objects can have their own seeds, which may be useful for generating different streams of random numbers. The seed may be a non-negative integer or a vector of UInt32 integers. If no seed is provided, a randomly generated one is created (using entropy from the system). See the seed! function for reseeding an already existing MersenneTwister object.\n\nExamples\n\njulia> rng = MersenneTwister(1234);\n\njulia> x1 = rand(rng, 2)\n2-element Vector{Float64}:\n 0.5908446386657102\n 0.7667970365022592\n\njulia> rng = MersenneTwister(1234);\n\njulia> x2 = rand(rng, 2)\n2-element Vector{Float64}:\n 0.5908446386657102\n 0.7667970365022592\n\njulia> x1 == x2\ntrue\n\n\n\n\n\n","category":"type"},{"location":"stdlib/Random/#Random.RandomDevice","page":"随机数","title":"Random.RandomDevice","text":"RandomDevice()\n\nCreate a RandomDevice RNG object. Two such objects will always generate different streams of random numbers. The entropy is obtained from the operating system.\n\n\n\n\n\n","category":"type"},{"location":"stdlib/Random/#Hooking-into-the-Random-API","page":"随机数","title":"Hooking into the Random API","text":"","category":"section"},{"location":"stdlib/Random/","page":"随机数","title":"随机数","text":"There are two mostly orthogonal ways to extend Random functionalities:","category":"page"},{"location":"stdlib/Random/","page":"随机数","title":"随机数","text":"generating random values of custom types\ncreating new generators","category":"page"},{"location":"stdlib/Random/","page":"随机数","title":"随机数","text":"The API for 1) is quite functional, but is relatively recent so it may still have to evolve in subsequent releases of the Random module. For example, it's typically sufficient to implement one rand method in order to have all other usual methods work automatically.","category":"page"},{"location":"stdlib/Random/","page":"随机数","title":"随机数","text":"The API for 2) is still rudimentary, and may require more work than strictly necessary from the implementor, in order to support usual types of generated values.","category":"page"},{"location":"stdlib/Random/#Generating-random-values-of-custom-types","page":"随机数","title":"Generating random values of custom types","text":"","category":"section"},{"location":"stdlib/Random/","page":"随机数","title":"随机数","text":"Generating random values for some distributions may involve various trade-offs. Pre-computed values, such as an alias table for discrete distributions, or “squeezing” functions for univariate distributions, can speed up sampling considerably. How much information should be pre-computed can depend on the number of values we plan to draw from a distribution. Also, some random number generators can have certain properties that various algorithms may want to exploit.","category":"page"},{"location":"stdlib/Random/","page":"随机数","title":"随机数","text":"The Random module defines a customizable framework for obtaining random values that can address these issues. Each invocation of rand generates a sampler which can be customized with the above trade-offs in mind, by adding methods to Sampler, which in turn can dispatch on the random number generator, the object that characterizes the distribution, and a suggestion for the number of repetitions. Currently, for the latter, Val{1} (for a single sample) and Val{Inf} (for an arbitrary number) are used, with Random.Repetition an alias for both.","category":"page"},{"location":"stdlib/Random/","page":"随机数","title":"随机数","text":"The object returned by Sampler is then used to generate the random values. When implementing the random generation interface for a value X that can be sampled from, the implementor should define the method","category":"page"},{"location":"stdlib/Random/","page":"随机数","title":"随机数","text":"rand(rng, sampler)","category":"page"},{"location":"stdlib/Random/","page":"随机数","title":"随机数","text":"for the particular sampler returned by Sampler(rng, X, repetition).","category":"page"},{"location":"stdlib/Random/","page":"随机数","title":"随机数","text":"Samplers can be arbitrary values that implement rand(rng, sampler), but for most applications the following predefined samplers may be sufficient:","category":"page"},{"location":"stdlib/Random/","page":"随机数","title":"随机数","text":"SamplerType{T}() can be used for implementing samplers that draw from type T (e.g. rand(Int)). This is the default returned by Sampler for types.\nSamplerTrivial(self) is a simple wrapper for self, which can be accessed with []. This is the recommended sampler when no pre-computed information is needed (e.g. rand(1:3)), and is the default returned by Sampler for values.\nSamplerSimple(self, data) also contains the additional data field, which can be used to store arbitrary pre-computed values, which should be computed in a custom method of Sampler.","category":"page"},{"location":"stdlib/Random/","page":"随机数","title":"随机数","text":"We provide examples for each of these. We assume here that the choice of algorithm is independent of the RNG, so we use AbstractRNG in our signatures.","category":"page"},{"location":"stdlib/Random/","page":"随机数","title":"随机数","text":"Random.Sampler\nRandom.SamplerType\nRandom.SamplerTrivial\nRandom.SamplerSimple","category":"page"},{"location":"stdlib/Random/#Random.Sampler","page":"随机数","title":"Random.Sampler","text":"Sampler(rng, x, repetition = Val(Inf))\n\nReturn a sampler object that can be used to generate random values from rng for x.\n\nWhen sp = Sampler(rng, x, repetition), rand(rng, sp) will be used to draw random values, and should be defined accordingly.\n\nrepetition can be Val(1) or Val(Inf), and should be used as a suggestion for deciding the amount of precomputation, if applicable.\n\nRandom.SamplerType and Random.SamplerTrivial are default fallbacks for types and values, respectively. Random.SamplerSimple can be used to store pre-computed values without defining extra types for only this purpose.\n\n\n\n\n\n","category":"type"},{"location":"stdlib/Random/#Random.SamplerType","page":"随机数","title":"Random.SamplerType","text":"SamplerType{T}()\n\nA sampler for types, containing no other information. The default fallback for Sampler when called with types.\n\n\n\n\n\n","category":"type"},{"location":"stdlib/Random/#Random.SamplerTrivial","page":"随机数","title":"Random.SamplerTrivial","text":"SamplerTrivial(x)\n\nCreate a sampler that just wraps the given value x. This is the default fall-back for values. The eltype of this sampler is equal to eltype(x).\n\nThe recommended use case is sampling from values without precomputed data.\n\n\n\n\n\n","category":"type"},{"location":"stdlib/Random/#Random.SamplerSimple","page":"随机数","title":"Random.SamplerSimple","text":"SamplerSimple(x, data)\n\nCreate a sampler that wraps the given value x and the data. The eltype of this sampler is equal to eltype(x).\n\nThe recommended use case is sampling from values with precomputed data.\n\n\n\n\n\n","category":"type"},{"location":"stdlib/Random/","page":"随机数","title":"随机数","text":"Decoupling pre-computation from actually generating the values is part of the API, and is also available to the user. As an example, assume that rand(rng, 1:20) has to be called repeatedly in a loop: the way to take advantage of this decoupling is as follows:","category":"page"},{"location":"stdlib/Random/","page":"随机数","title":"随机数","text":"rng = MersenneTwister()\nsp = Random.Sampler(rng, 1:20) # or Random.Sampler(MersenneTwister, 1:20)\nfor x in X\n n = rand(rng, sp) # similar to n = rand(rng, 1:20)\n # use n\nend","category":"page"},{"location":"stdlib/Random/","page":"随机数","title":"随机数","text":"This is the mechanism that is also used in the standard library, e.g. by the default implementation of random array generation (like in rand(1:20, 10)).","category":"page"},{"location":"stdlib/Random/#Generating-values-from-a-type","page":"随机数","title":"Generating values from a type","text":"","category":"section"},{"location":"stdlib/Random/","page":"随机数","title":"随机数","text":"Given a type T, it's currently assumed that if rand(T) is defined, an object of type T will be produced. SamplerType is the default sampler for types. In order to define random generation of values of type T, the rand(rng::AbstractRNG, ::Random.SamplerType{T}) method should be defined, and should return values what rand(rng, T) is expected to return.","category":"page"},{"location":"stdlib/Random/","page":"随机数","title":"随机数","text":"Let's take the following example: we implement a Die type, with a variable number n of sides, numbered from 1 to n. We want rand(Die) to produce a Die with a random number of up to 20 sides (and at least 4):","category":"page"},{"location":"stdlib/Random/","page":"随机数","title":"随机数","text":"struct Die\n nsides::Int # number of sides\nend\n\nRandom.rand(rng::AbstractRNG, ::Random.SamplerType{Die}) = Die(rand(rng, 4:20))\n\n# output\n","category":"page"},{"location":"stdlib/Random/","page":"随机数","title":"随机数","text":"Scalar and array methods for Die now work as expected:","category":"page"},{"location":"stdlib/Random/","page":"随机数","title":"随机数","text":"julia> rand(Die)\nDie(7)\n\njulia> rand(MersenneTwister(0), Die)\nDie(11)\n\njulia> rand(Die, 3)\n3-element Vector{Die}:\n Die(13)\n Die(8)\n Die(20)\n\njulia> a = Vector{Die}(undef, 3); rand!(a)\n3-element Vector{Die}:\n Die(4)\n Die(14)\n Die(10)","category":"page"},{"location":"stdlib/Random/#A-simple-sampler-without-pre-computed-data","page":"随机数","title":"A simple sampler without pre-computed data","text":"","category":"section"},{"location":"stdlib/Random/","page":"随机数","title":"随机数","text":"Here we define a sampler for a collection. If no pre-computed data is required, it can be implemented with a SamplerTrivial sampler, which is in fact the default fallback for values.","category":"page"},{"location":"stdlib/Random/","page":"随机数","title":"随机数","text":"In order to define random generation out of objects of type S, the following method should be defined: rand(rng::AbstractRNG, sp::Random.SamplerTrivial{S}). Here, sp simply wraps an object of type S, which can be accessed via sp[]. Continuing the Die example, we want now to define rand(d::Die) to produce an Int corresponding to one of d's sides:","category":"page"},{"location":"stdlib/Random/","page":"随机数","title":"随机数","text":"julia> Random.rand(rng::AbstractRNG, d::Random.SamplerTrivial{Die}) = rand(rng, 1:d[].nsides);\n\njulia> rand(Die(4))\n1\n\njulia> rand(Die(4), 3)\n3-element Vector{Any}:\n 3\n 2\n 4","category":"page"},{"location":"stdlib/Random/","page":"随机数","title":"随机数","text":"Given a collection type S, it's currently assumed that if rand(::S) is defined, an object of type eltype(S) will be produced. In the last example, a Vector{Any} is produced; the reason is that eltype(Die) == Any. The remedy is to define Base.eltype(::Type{Die}) = Int.","category":"page"},{"location":"stdlib/Random/#Generating-values-for-an-AbstractFloat-type","page":"随机数","title":"Generating values for an AbstractFloat type","text":"","category":"section"},{"location":"stdlib/Random/","page":"随机数","title":"随机数","text":"AbstractFloat types are special-cased, because by default random values are not produced in the whole type domain, but rather in [0,1). The following method should be implemented for T <: AbstractFloat: Random.rand(::AbstractRNG, ::Random.SamplerTrivial{Random.CloseOpen01{T}})","category":"page"},{"location":"stdlib/Random/#An-optimized-sampler-with-pre-computed-data","page":"随机数","title":"An optimized sampler with pre-computed data","text":"","category":"section"},{"location":"stdlib/Random/","page":"随机数","title":"随机数","text":"Consider a discrete distribution, where numbers 1:n are drawn with given probabilities that sum to one. When many values are needed from this distribution, the fastest method is using an alias table. We don't provide the algorithm for building such a table here, but suppose it is available in make_alias_table(probabilities) instead, and draw_number(rng, alias_table) can be used to draw a random number from it.","category":"page"},{"location":"stdlib/Random/","page":"随机数","title":"随机数","text":"Suppose that the distribution is described by","category":"page"},{"location":"stdlib/Random/","page":"随机数","title":"随机数","text":"struct DiscreteDistribution{V <: AbstractVector}\n probabilities::V\nend","category":"page"},{"location":"stdlib/Random/","page":"随机数","title":"随机数","text":"and that we always want to build an alias table, regardless of the number of values needed (we learn how to customize this below). The methods","category":"page"},{"location":"stdlib/Random/","page":"随机数","title":"随机数","text":"Random.eltype(::Type{<:DiscreteDistribution}) = Int\n\nfunction Random.Sampler(::Type{<:AbstractRNG}, distribution::DiscreteDistribution, ::Repetition)\n SamplerSimple(disribution, make_alias_table(distribution.probabilities))\nend","category":"page"},{"location":"stdlib/Random/","page":"随机数","title":"随机数","text":"should be defined to return a sampler with pre-computed data, then","category":"page"},{"location":"stdlib/Random/","page":"随机数","title":"随机数","text":"function rand(rng::AbstractRNG, sp::SamplerSimple{<:DiscreteDistribution})\n draw_number(rng, sp.data)\nend","category":"page"},{"location":"stdlib/Random/","page":"随机数","title":"随机数","text":"will be used to draw the values.","category":"page"},{"location":"stdlib/Random/#Custom-sampler-types","page":"随机数","title":"Custom sampler types","text":"","category":"section"},{"location":"stdlib/Random/","page":"随机数","title":"随机数","text":"The SamplerSimple type is sufficient for most use cases with precomputed data. However, in order to demonstrate how to use custom sampler types, here we implement something similar to SamplerSimple.","category":"page"},{"location":"stdlib/Random/","page":"随机数","title":"随机数","text":"Going back to our Die example: rand(::Die) uses random generation from a range, so there is an opportunity for this optimization. We call our custom sampler SamplerDie.","category":"page"},{"location":"stdlib/Random/","page":"随机数","title":"随机数","text":"import Random: Sampler, rand\n\nstruct SamplerDie <: Sampler{Int} # generates values of type Int\n die::Die\n sp::Sampler{Int} # this is an abstract type, so this could be improved\nend\n\nSampler(RNG::Type{<:AbstractRNG}, die::Die, r::Random.Repetition) =\n SamplerDie(die, Sampler(RNG, 1:die.nsides, r))\n# the `r` parameter will be explained later on\n\nrand(rng::AbstractRNG, sp::SamplerDie) = rand(rng, sp.sp)","category":"page"},{"location":"stdlib/Random/","page":"随机数","title":"随机数","text":"It's now possible to get a sampler with sp = Sampler(rng, die), and use sp instead of die in any rand call involving rng. In the simplistic example above, die doesn't need to be stored in SamplerDie but this is often the case in practice.","category":"page"},{"location":"stdlib/Random/","page":"随机数","title":"随机数","text":"Of course, this pattern is so frequent that the helper type used above, namely Random.SamplerSimple, is available, saving us the definition of SamplerDie: we could have implemented our decoupling with:","category":"page"},{"location":"stdlib/Random/","page":"随机数","title":"随机数","text":"Sampler(RNG::Type{<:AbstractRNG}, die::Die, r::Random.Repetition) =\n SamplerSimple(die, Sampler(RNG, 1:die.nsides, r))\n\nrand(rng::AbstractRNG, sp::SamplerSimple{Die}) = rand(rng, sp.data)","category":"page"},{"location":"stdlib/Random/","page":"随机数","title":"随机数","text":"Here, sp.data refers to the second parameter in the call to the SamplerSimple constructor (in this case equal to Sampler(rng, 1:die.nsides, r)), while the Die object can be accessed via sp[].","category":"page"},{"location":"stdlib/Random/","page":"随机数","title":"随机数","text":"Like SamplerDie, any custom sampler must be a subtype of Sampler{T} where T is the type of the generated values. Note that SamplerSimple(x, data) isa Sampler{eltype(x)}, so this constrains what the first argument to SamplerSimple can be (it's recommended to use SamplerSimple like in the Die example, where x is simply forwarded while defining a Sampler method). Similarly, SamplerTrivial(x) isa Sampler{eltype(x)}.","category":"page"},{"location":"stdlib/Random/","page":"随机数","title":"随机数","text":"Another helper type is currently available for other cases, Random.SamplerTag, but is considered as internal API, and can break at any time without proper deprecations.","category":"page"},{"location":"stdlib/Random/#Using-distinct-algorithms-for-scalar-or-array-generation","page":"随机数","title":"Using distinct algorithms for scalar or array generation","text":"","category":"section"},{"location":"stdlib/Random/","page":"随机数","title":"随机数","text":"In some cases, whether one wants to generate only a handful of values or a large number of values will have an impact on the choice of algorithm. This is handled with the third parameter of the Sampler constructor. Let's assume we defined two helper types for Die, say SamplerDie1 which should be used to generate only few random values, and SamplerDieMany for many values. We can use those types as follows:","category":"page"},{"location":"stdlib/Random/","page":"随机数","title":"随机数","text":"Sampler(RNG::Type{<:AbstractRNG}, die::Die, ::Val{1}) = SamplerDie1(...)\nSampler(RNG::Type{<:AbstractRNG}, die::Die, ::Val{Inf}) = SamplerDieMany(...)","category":"page"},{"location":"stdlib/Random/","page":"随机数","title":"随机数","text":"Of course, rand must also be defined on those types (i.e. rand(::AbstractRNG, ::SamplerDie1) and rand(::AbstractRNG, ::SamplerDieMany)). Note that, as usual, SamplerTrivial and SamplerSimple can be used if custom types are not necessary.","category":"page"},{"location":"stdlib/Random/","page":"随机数","title":"随机数","text":"Note: Sampler(rng, x) is simply a shorthand for Sampler(rng, x, Val(Inf)), and Random.Repetition is an alias for Union{Val{1}, Val{Inf}}.","category":"page"},{"location":"stdlib/Random/#Creating-new-generators","page":"随机数","title":"Creating new generators","text":"","category":"section"},{"location":"stdlib/Random/","page":"随机数","title":"随机数","text":"The API is not clearly defined yet, but as a rule of thumb:","category":"page"},{"location":"stdlib/Random/","page":"随机数","title":"随机数","text":"any rand method producing \"basic\" types (isbitstype integer and floating types in Base) should be defined for this specific RNG, if they are needed;\nother documented rand methods accepting an AbstractRNG should work out of the box, (provided the methods from 1) what are relied on are implemented), but can of course be specialized for this RNG if there is room for optimization;\ncopy for pseudo-RNGs should return an independent copy that generates the exact same random sequence as the original from that point when called in the same way. When this is not feasible (e.g. hardware-based RNGs), copy must not be implemented.","category":"page"},{"location":"stdlib/Random/","page":"随机数","title":"随机数","text":"Concerning 1), a rand method may happen to work automatically, but it's not officially supported and may break without warnings in a subsequent release.","category":"page"},{"location":"stdlib/Random/","page":"随机数","title":"随机数","text":"To define a new rand method for an hypothetical MyRNG generator, and a value specification s (e.g. s == Int, or s == 1:10) of type S==typeof(s) or S==Type{s} if s is a type, the same two methods as we saw before must be defined:","category":"page"},{"location":"stdlib/Random/","page":"随机数","title":"随机数","text":"Sampler(::Type{MyRNG}, ::S, ::Repetition), which returns an object of type say SamplerS\nrand(rng::MyRNG, sp::SamplerS)","category":"page"},{"location":"stdlib/Random/","page":"随机数","title":"随机数","text":"It can happen that Sampler(rng::AbstractRNG, ::S, ::Repetition) is already defined in the Random module. It would then be possible to skip step 1) in practice (if one wants to specialize generation for this particular RNG type), but the corresponding SamplerS type is considered as internal detail, and may be changed without warning.","category":"page"},{"location":"stdlib/Random/#Specializing-array-generation","page":"随机数","title":"Specializing array generation","text":"","category":"section"},{"location":"stdlib/Random/","page":"随机数","title":"随机数","text":"In some cases, for a given RNG type, generating an array of random values can be more efficient with a specialized method than by merely using the decoupling technique explained before. This is for example the case for MersenneTwister, which natively writes random values in an array.","category":"page"},{"location":"stdlib/Random/","page":"随机数","title":"随机数","text":"To implement this specialization for MyRNG and for a specification s, producing elements of type S, the following method can be defined: rand!(rng::MyRNG, a::AbstractArray{S}, ::SamplerS), where SamplerS is the type of the sampler returned by Sampler(MyRNG, s, Val(Inf)). Instead of AbstractArray, it's possible to implement the functionality only for a subtype, e.g. Array{S}. The non-mutating array method of rand will automatically call this specialization internally.","category":"page"},{"location":"stdlib/Random/","page":"随机数","title":"随机数","text":"DocTestSetup = nothing","category":"page"},{"location":"stdlib/Random/#Reproducibility","page":"随机数","title":"Reproducibility","text":"","category":"section"},{"location":"stdlib/Random/","page":"随机数","title":"随机数","text":"By using an RNG parameter initialized with a given seed, you can reproduce the same pseudorandom number sequence when running your program multiple times. However, a minor release of Julia (e.g. 1.3 to 1.4) may change the sequence of pseudorandom numbers generated from a specific seed, in particular if MersenneTwister is used. (Even if the sequence produced by a low-level function like rand does not change, the output of higher-level functions like randsubseq may change due to algorithm updates.) Rationale: guaranteeing that pseudorandom streams never change prohibits many algorithmic improvements.","category":"page"},{"location":"stdlib/Random/","page":"随机数","title":"随机数","text":"If you need to guarantee exact reproducibility of random data, it is advisable to simply save the data (e.g. as a supplementary attachment in a scientific publication). (You can also, of course, specify a particular Julia version and package manifest, especially if you require bit reproducibility.)","category":"page"},{"location":"stdlib/Random/","page":"随机数","title":"随机数","text":"Software tests that rely on specific \"random\" data should also generally either save the data, embed it into the test code, or use third-party packages like StableRNGs.jl. On the other hand, tests that should pass for most random data (e.g. testing A \\ (A*x) ≈ x for a random matrix A = randn(n,n)) can use an RNG with a fixed seed to ensure that simply running the test many times does not encounter a failure due to very improbable data (e.g. an extremely ill-conditioned matrix).","category":"page"},{"location":"stdlib/Random/","page":"随机数","title":"随机数","text":"The statistical distribution from which random samples are drawn is guaranteed to be the same across any minor Julia releases.","category":"page"},{"location":"manual/profile/#profiling","page":"性能分析","title":"性能分析","text":"","category":"section"},{"location":"manual/profile/","page":"性能分析","title":"性能分析","text":"Profile 模块提供了一些工具来帮助开发者提高其代码的性能。在使用时,它运行代码并进行测量,并生成输出,该输出帮助你了解在每行(或几行)上花费了多少时间。最常见的用法是识别性能「瓶颈」并将其作为优化目标。","category":"page"},{"location":"manual/profile/","page":"性能分析","title":"性能分析","text":"Profile 实现了所谓的「抽样」或统计分析器。它通过在执行任何任务期间定期进行回溯来工作。每次回溯捕获当前运行的函数和行号,以及导致该行执行的完整函数调用链,因此是当前执行状态的「快照」。","category":"page"},{"location":"manual/profile/","page":"性能分析","title":"性能分析","text":"如果大部分运行时间都花在执行特定代码行上,则此行会在所有回溯的集合中频繁出现。换句话说,执行给定行的「成本」——或实际上,调用及包含此行的函数序列的成本——与它在所有回溯的集合中的出现频率成正比。","category":"page"},{"location":"manual/profile/","page":"性能分析","title":"性能分析","text":"抽样分析器不提供完整的逐行覆盖功能,因为回溯是间隔发生的(默认情况下,该时间间隔在 Unix 上是 1 ms,而在 Windows 上是 10 ms,但实际调度受操作系统负载的影响)。此外,正如下文中进一步讨论的,因为样本是在所有执行点的稀疏子集处收集的,所以抽样分析器收集的数据会受到统计噪声的影响。","category":"page"},{"location":"manual/profile/","page":"性能分析","title":"性能分析","text":"尽管有这些限制,但抽样分析器仍然有很大的优势:","category":"page"},{"location":"manual/profile/","page":"性能分析","title":"性能分析","text":"你无需对代码进行任何修改即可进行时间测量。\n它可以分析 Julia 的核心代码,甚至(可选)可以分析 C 和 Fortran 库。\n通过「偶尔」运行,它只有很少的性能开销;代码在性能分析时能以接近本机的速度运行。","category":"page"},{"location":"manual/profile/","page":"性能分析","title":"性能分析","text":"出于这些原因,建议你在考虑任何替代方案前尝试使用内置的抽样分析器。","category":"page"},{"location":"manual/profile/#基本用法","page":"性能分析","title":"基本用法","text":"","category":"section"},{"location":"manual/profile/","page":"性能分析","title":"性能分析","text":"让我们使用一个简单的测试用例:","category":"page"},{"location":"manual/profile/","page":"性能分析","title":"性能分析","text":"julia> function myfunc()\n A = rand(200, 200, 400)\n maximum(A)\n end","category":"page"},{"location":"manual/profile/","page":"性能分析","title":"性能分析","text":"最好先至少运行一次你想要分析的代码(除非你想要分析 Julia 的 JIT 编译器):","category":"page"},{"location":"manual/profile/","page":"性能分析","title":"性能分析","text":"julia> myfunc() # run once to force compilation","category":"page"},{"location":"manual/profile/","page":"性能分析","title":"性能分析","text":"现在我们准备分析这个函数:","category":"page"},{"location":"manual/profile/","page":"性能分析","title":"性能分析","text":"julia> using Profile\n\njulia> @profile myfunc()","category":"page"},{"location":"manual/profile/","page":"性能分析","title":"性能分析","text":"有一些图形界面可以查看性能分析的结果。这其中有一类是基于 FlameGraphs.jl打造的,只不过提供了不同的用户接口:","category":"page"},{"location":"manual/profile/","page":"性能分析","title":"性能分析","text":"Juno 是一个完整的 IDE,内置对性能分析可视化的支持\nProfileView.jl 是一个基于 GTK 的独立可视化工具\nProfileVega.jl 使用 VegaLight 并与 Jupyter notebooks 很好地集成\nStatProfilerHTML 生成 HTML 并提供一些额外的摘要,并且还与 Jupyter 笔记本很好地集成\nProfileSVG 渲染 SVG","category":"page"},{"location":"manual/profile/","page":"性能分析","title":"性能分析","text":"一种完全独立的性能分析可视化方法是 PProf.jl,它使用外部 pprof 工具。","category":"page"},{"location":"manual/profile/","page":"性能分析","title":"性能分析","text":"不过,在这里,我们将使用标准库附带的基于文本的显示:","category":"page"},{"location":"manual/profile/","page":"性能分析","title":"性能分析","text":"julia> Profile.print()\n80 ./event.jl:73; (::Base.REPL.##1#2{Base.REPL.REPLBackend})()\n 80 ./REPL.jl:97; macro expansion\n 80 ./REPL.jl:66; eval_user_input(::Any, ::Base.REPL.REPLBackend)\n 80 ./boot.jl:235; eval(::Module, ::Any)\n 80 ./:?; anonymous\n 80 ./profile.jl:23; macro expansion\n 52 ./REPL[1]:2; myfunc()\n 38 ./random.jl:431; rand!(::MersenneTwister, ::Array{Float64,3}, ::Int64, ::Type{B...\n 38 ./dSFMT.jl:84; dsfmt_fill_array_close_open!(::Base.dSFMT.DSFMT_state, ::Ptr{F...\n 14 ./random.jl:278; rand\n 14 ./random.jl:277; rand\n 14 ./random.jl:366; rand\n 14 ./random.jl:369; rand\n 28 ./REPL[1]:3; myfunc()\n 28 ./reduce.jl:270; _mapreduce(::Base.#identity, ::Base.#scalarmax, ::IndexLinear,...\n 3 ./reduce.jl:426; mapreduce_impl(::Base.#identity, ::Base.#scalarmax, ::Array{F...\n 25 ./reduce.jl:428; mapreduce_impl(::Base.#identity, ::Base.#scalarmax, ::Array{F...","category":"page"},{"location":"manual/profile/","page":"性能分析","title":"性能分析","text":"显示结果中的每行表示代码中的特定点(行数)。缩进用来标明嵌套的函数调用序列,其中缩进更多的行在调用序列中更深。在每一行中,第一个「字段」是在这一行或由这一行执行的任何函数中获取的回溯(样本)数量。第二个字段是文件名和行数,第三个字段是函数名。请注意,具体的行号可能会随着 Julia 代码的改变而改变;如果你想跟上,最好自己运行这个示例。","category":"page"},{"location":"manual/profile/","page":"性能分析","title":"性能分析","text":"在此例中,我们可以看到顶层的调用函数位于文件 event.jl 中。这是启动 Julia 时运行 REPL 的函数。如果你查看 REPL.jl 的第 97 行,你会看到这是调用函数 eval_user_input() 的地方。这是对你在 REPL 上的输入进行求值的函数,因为我们正以交互方式运行,所以当我们输入 @profile myfunc() 时会调用这些函数。下一行反映了 @profile 所采取的操作。","category":"page"},{"location":"manual/profile/","page":"性能分析","title":"性能分析","text":"第一行显示在 event.jl 的第 73 行获取了 80 次回溯,但这并不是说此行本身「昂贵」:第三行表明所有这些 80 次回溯实际上它调用的 eval_user_input 中触发的,以此类推。为了找出实际占用时间的操作,我们需要深入了解调用链。","category":"page"},{"location":"manual/profile/","page":"性能分析","title":"性能分析","text":"此输出中第一个「重要」的行是这行:","category":"page"},{"location":"manual/profile/","page":"性能分析","title":"性能分析","text":"52 ./REPL[1]:2; myfunc()","category":"page"},{"location":"manual/profile/","page":"性能分析","title":"性能分析","text":"REPL 指的是我们在 REPL 中定义了 myfunc,而不是把它放在文件中;如果我们使用文件,这将显示文件名。[1] 表示函数 myfunc 是在当前 REPL 会话中第一个进行求值的表达式。myfunc() 的第 2 行包含对 rand 的调用,(80 次中)有 52 次回溯发生在该行。在此之下,你可以看到在 dSFMT.jl 中对 dsfmt_fill_array_close_open! 的调用。","category":"page"},{"location":"manual/profile/","page":"性能分析","title":"性能分析","text":"更进一步,你会看到:","category":"page"},{"location":"manual/profile/","page":"性能分析","title":"性能分析","text":"28 ./REPL[1]:3; myfunc()","category":"page"},{"location":"manual/profile/","page":"性能分析","title":"性能分析","text":"myfunc 的第 3 行包含对 maximum 的调用,(80 次中)有 28 次回溯发生在这里。在此之下,你可以看到对于这种类型的输入数据,maximum 函数中执行的耗时操作在 base/reduce.jl 中的具体位置。","category":"page"},{"location":"manual/profile/","page":"性能分析","title":"性能分析","text":"总的来说,我们可以暂时得出结论,生成随机数的成本大概是找到最大元素的两倍。通过收集更多样本,我们可以增加对此结果的信心:","category":"page"},{"location":"manual/profile/","page":"性能分析","title":"性能分析","text":"julia> @profile (for i = 1:100; myfunc(); end)\n\njulia> Profile.print()\n[....]\n 3821 ./REPL[1]:2; myfunc()\n 3511 ./random.jl:431; rand!(::MersenneTwister, ::Array{Float64,3}, ::Int64, ::Type...\n 3511 ./dSFMT.jl:84; dsfmt_fill_array_close_open!(::Base.dSFMT.DSFMT_state, ::Ptr...\n 310 ./random.jl:278; rand\n [....]\n 2893 ./REPL[1]:3; myfunc()\n 2893 ./reduce.jl:270; _mapreduce(::Base.#identity, ::Base.#scalarmax, ::IndexLinea...\n [....]","category":"page"},{"location":"manual/profile/","page":"性能分析","title":"性能分析","text":"一般来说,如果你在某行上收集到 N 个样本,那你可以预期其有 sqrt(N) 的不确定性(忽略其它噪音源,比如计算机在其它任务上的繁忙程度)。这个规则的主要例外是垃圾收集,它很少运行但往往成本高昂。(因为 Julia 的垃圾收集器是用 C 语言编写的,此类事件可使用下文描述的 C=true 输出模式来检测,或者使用 ProfileView.jl 来检测。)","category":"page"},{"location":"manual/profile/","page":"性能分析","title":"性能分析","text":"这展示了默认的「树」形转储;另一种选择是「扁平」形转储,它会累积与其嵌套无关的计数:","category":"page"},{"location":"manual/profile/","page":"性能分析","title":"性能分析","text":"julia> Profile.print(format=:flat)\n Count File Line Function\n 6714 ./ -1 anonymous\n 6714 ./REPL.jl 66 eval_user_input(::Any, ::Base.REPL.REPLBackend)\n 6714 ./REPL.jl 97 macro expansion\n 3821 ./REPL[1] 2 myfunc()\n 2893 ./REPL[1] 3 myfunc()\n 6714 ./REPL[7] 1 macro expansion\n 6714 ./boot.jl 235 eval(::Module, ::Any)\n 3511 ./dSFMT.jl 84 dsfmt_fill_array_close_open!(::Base.dSFMT.DSFMT_s...\n 6714 ./event.jl 73 (::Base.REPL.##1#2{Base.REPL.REPLBackend})()\n 6714 ./profile.jl 23 macro expansion\n 3511 ./random.jl 431 rand!(::MersenneTwister, ::Array{Float64,3}, ::In...\n 310 ./random.jl 277 rand\n 310 ./random.jl 278 rand\n 310 ./random.jl 366 rand\n 310 ./random.jl 369 rand\n 2893 ./reduce.jl 270 _mapreduce(::Base.#identity, ::Base.#scalarmax, :...\n 5 ./reduce.jl 420 mapreduce_impl(::Base.#identity, ::Base.#scalarma...\n 253 ./reduce.jl 426 mapreduce_impl(::Base.#identity, ::Base.#scalarma...\n 2592 ./reduce.jl 428 mapreduce_impl(::Base.#identity, ::Base.#scalarma...\n 43 ./reduce.jl 429 mapreduce_impl(::Base.#identity, ::Base.#scalarma...","category":"page"},{"location":"manual/profile/","page":"性能分析","title":"性能分析","text":"如果你的代码有递归,那么可能令人困惑的就是「子」函数中的行的累积计数可以多于总回溯次数。考虑以下函数定义:","category":"page"},{"location":"manual/profile/","page":"性能分析","title":"性能分析","text":"dumbsum(n::Integer) = n == 1 ? 1 : 1 + dumbsum(n-1)\ndumbsum3() = dumbsum(3)","category":"page"},{"location":"manual/profile/","page":"性能分析","title":"性能分析","text":"如果你要分析 dumbsum3,并在执行 dumbsum(1) 时执行了回溯,那么该回溯将如下所示:","category":"page"},{"location":"manual/profile/","page":"性能分析","title":"性能分析","text":"dumbsum3\n dumbsum(3)\n dumbsum(2)\n dumbsum(1)","category":"page"},{"location":"manual/profile/","page":"性能分析","title":"性能分析","text":"因此,即使父函数只获得 1 个计数,这个子函数也会获得 3 个计数。「树」形表示使这更清晰,因此(以及其它原因)可能是查看结果的最实用方法。","category":"page"},{"location":"manual/profile/#结果累积和清空","page":"性能分析","title":"结果累积和清空","text":"","category":"section"},{"location":"manual/profile/","page":"性能分析","title":"性能分析","text":"@profile 的结果会累积在一个缓冲区中;如果你在 @profile 下运行多端代码,那么 Profile.print() 会显示合并的结果。这可能非常有用,但有时你会想重新开始,这可通过 Profile.clear()。","category":"page"},{"location":"manual/profile/#用于控制性能分析结果显示的选项","page":"性能分析","title":"用于控制性能分析结果显示的选项","text":"","category":"section"},{"location":"manual/profile/","page":"性能分析","title":"性能分析","text":"Profile.print 还有一些未曾描述的选项。让我们看看完整的声明:","category":"page"},{"location":"manual/profile/","page":"性能分析","title":"性能分析","text":"function print(io::IO = stdout, data = fetch(); kwargs...)","category":"page"},{"location":"manual/profile/","page":"性能分析","title":"性能分析","text":"我们先讨论两个位置参数,然后讨论关键字参数:","category":"page"},{"location":"manual/profile/","page":"性能分析","title":"性能分析","text":"io——允许你将结果保存到缓冲区,例如一个文件,但默认是打印到 stdout(控制台)。\ndata——包含你要分析的数据;默认情况下,它是从 Profile.fetch() 中获取的,该函数从预先分配的缓冲区中拉出回溯。例如,如果你要分析性能分析器,可以说:\ndata = copy(Profile.fetch())\nProfile.clear()\n@profile Profile.print(stdout, data) # Prints the previous results\nProfile.print() # Prints results from Profile.print()","category":"page"},{"location":"manual/profile/","page":"性能分析","title":"性能分析","text":"关键字参数可以是以下参数的任意组合:","category":"page"},{"location":"manual/profile/","page":"性能分析","title":"性能分析","text":"format——上文已经介绍,确定是使用(默认值,:tree)还是不使用(:flat)缩进来表示其树形结构。\nC——如果为 true,则显示 C 和 Fortran 代码中的回溯(通常它们被排除在外)。请尝试用 Profile.print(C = true) 运行介绍性示例。这对于判断是 Julia 代码还是 C 代码导致了性能瓶颈非常有帮助;设置 C = true 也可提高嵌套的可解释性,代价是更长的性能分析转储。\ncombine——某些代码行包含多个操作;例如,s += A[i] 包含一个数组引用(A[i])和一个求和操作。这些操作在所生成的机器代码中对应不同的行,因此回溯期间可能会在此行中捕获两个或以上地址。combine = true 把它们混合在一起,可能你通常想要这样,但使用 combine = false,你可为每个唯一的指令指针单独生成输出。\nmaxdepth——限制 :tree 格式中深度大于 maxdepth 的帧。\n  * sortedby——控制 :flat 格式中的次序。为 :filefuncline(默认值)时按源代码行排序,而为 :count 时按收集的样本数排序。\nnoisefloor——限制低于样本的启发式噪音下限的帧(只适用于格式 :tree)。尝试此选项的建议值是 2.0(默认值是 0)。此参数会隐藏 n <= noisefloor * √N 的样本,其中 n 是该行上的样本数,N 是被调用者的样本数。\nmincount——限制出现次数少于 mincount 的帧。","category":"page"},{"location":"manual/profile/","page":"性能分析","title":"性能分析","text":"文件/函数名有时会被(用 ...)截断,缩进也有可能在开头用 +n 截断,其中 n 是在空间充足的情况下应该插入的额外空格数。如果你想要深层嵌套代码的完整性能分析,保存到文件并在 IOContext 中使用宽的 displaysize 通常是个好主意:","category":"page"},{"location":"manual/profile/","page":"性能分析","title":"性能分析","text":"open(\"/tmp/prof.txt\", \"w\") do s\n Profile.print(IOContext(s, :displaysize => (24, 500)))\nend","category":"page"},{"location":"manual/profile/#配置","page":"性能分析","title":"配置","text":"","category":"section"},{"location":"manual/profile/","page":"性能分析","title":"性能分析","text":"@profile 只是累积回溯,在你调用 Profile.print() 时才会进行性能分析。对于长时间运行的计算,完全有可能把用于存储回溯的预分配缓冲区填满。如果发生这种情况,回溯会停止,但你的计算会继续。因此,你也许会丢失一些重要的性能分析数据(当发生这种情况时,你会受到警告)。","category":"page"},{"location":"manual/profile/","page":"性能分析","title":"性能分析","text":"你可通过以下方式获取和配置相关参数:","category":"page"},{"location":"manual/profile/","page":"性能分析","title":"性能分析","text":"Profile.init() # returns the current settings\nProfile.init(n = 10^7, delay = 0.01)","category":"page"},{"location":"manual/profile/","page":"性能分析","title":"性能分析","text":"n 是能够存储的指令指针总数,默认值为 10^6。如果通常的回溯是 20 个指令指针,那么可以收集 50000 次回溯,这意味着统计不确定性少于 1%。这对于大多数应用来说可能已经足够了。","category":"page"},{"location":"manual/profile/","page":"性能分析","title":"性能分析","text":"因此,你更可能需要修改 delay,它以秒为单位,设置在快照之间 Julia 用于执行所请求计算的时长。长时间运行的工作可能不需要经常回溯。默认设置为 delay = 0.001。当然,你可以减少和增加 delay;但是,一旦 delay 接近执行一次回溯所需的时间(在作者的笔记本上约为 30 微妙),性能分析的开销就会增加。","category":"page"},{"location":"manual/profile/#memory-allocation-analysis","page":"性能分析","title":"内存分配分析","text":"","category":"section"},{"location":"manual/profile/","page":"性能分析","title":"性能分析","text":"减少内存分配是提高性能的最常用技术之一。内存分配总量可以用 @time 和 @allocated,触发内存分配的特定行通常可以通过这些行产生的垃圾分配成本从性能分析中推断出来。但是,直接测量每行代码的内存分配总量有时会更高效。","category":"page"},{"location":"manual/profile/","page":"性能分析","title":"性能分析","text":"为了逐行测量内存分配,启动 Julia 时请使用命令行选项 --track-allocation=,该选项的可选值有 none(默认值,不测量内存分配)、user(测量除 Julia core 代码之外的所有代码的内存分配)或 all(测量 Julia 代码中每一行的内存分配)。这会为每行已编译的代码测量内存。在退出 Julia 时,累积的结果将写入到文本文件中,此文本文件名称为该文件名称后加 .mem,并与源文件位于同一目录下。该文件的每行列出内存分配的总字节数。Coverage 包包括了一些基本分析工具,例如,按照内存分配的字节数对行进行排序的工具。","category":"page"},{"location":"manual/profile/","page":"性能分析","title":"性能分析","text":"在解释结果时,有一些需要注意的细节。在 user 设定下,直接从 REPL 调用的任何函数的第一行都将会显示内存分配,这是由发生在 REPL 代码本身的事件造成的。更重要的是,JIT 编译也会添加内存分配计数,因为 Julia 的编译器大部分是用 Julia 编写的(并且编译通常需要内存分配)。建议的分析过程是先通过执行待分析的所有命令来强制编译,然后调用 Profile.clear_malloc_data() 来重置所有内存计数器。最后,执行所需的命令并退出 Julia 以触发 .mem 文件的生成。","category":"page"},{"location":"manual/profile/#外部性能分析","page":"性能分析","title":"外部性能分析","text":"","category":"section"},{"location":"manual/profile/","page":"性能分析","title":"性能分析","text":"Julia 目前支持的外部性能分析工具有 Intel VTune、OProfile 和 perf。","category":"page"},{"location":"manual/profile/","page":"性能分析","title":"性能分析","text":"根据你所选择的工具,编译时请在 Make.user 中将 USE_INTEL_JITEVENTS、USE_OPROFILE_JITEVENTS 和 USE_PERF_JITEVENTS 设置为 1。多个上述编译标志是支持的。","category":"page"},{"location":"manual/profile/","page":"性能分析","title":"性能分析","text":"在运行 Julia 前,请将环境变量 ENABLE_JITPROFILING 设置为 1。","category":"page"},{"location":"manual/profile/","page":"性能分析","title":"性能分析","text":"现在,你可以通过多种方式使用这些工具!例如,可以使用 OProfile 来尝试做个简单的记录:","category":"page"},{"location":"manual/profile/","page":"性能分析","title":"性能分析","text":">ENABLE_JITPROFILING=1 sudo operf -Vdebug ./julia test/fastmath.jl\n>opreport -l `which ./julia`","category":"page"},{"location":"manual/profile/","page":"性能分析","title":"性能分析","text":"或与 perf 类似:","category":"page"},{"location":"manual/profile/","page":"性能分析","title":"性能分析","text":"$ ENABLE_JITPROFILING=1 perf record -o /tmp/perf.data --call-graph dwarf -k 1 ./julia /test/fastmath.jl\n$ perf inject --jit --input /tmp/perf.data --output /tmp/perf-jit.data\n$ perf report --call-graph -G -i /tmp/perf-jit.data","category":"page"},{"location":"manual/profile/","page":"性能分析","title":"性能分析","text":"你可以测量关于程序的更多有趣数据,若要获得详尽的列表,请阅读 Linux perf 示例页面。","category":"page"},{"location":"manual/profile/","page":"性能分析","title":"性能分析","text":"请记住,perf 会为每次执行保存一个 perf.data 文件,即使对于小程序,它也可能变得非常大。此外,perf LLVM 模块会将调试对象保存在 ~/.debug/jit 中,记得经常清理该文件夹。","category":"page"},{"location":"manual/variables/#man-variables","page":"变量","title":"变量","text":"","category":"section"},{"location":"manual/variables/","page":"变量","title":"变量","text":"Julia 语言中,变量是与某个值相关联(或绑定)的名字。你可以用它来保存一个值(例如某些计算得到的结果),供之后的代码使用。例如:","category":"page"},{"location":"manual/variables/","page":"变量","title":"变量","text":"# 将 10 赋值给变量 x\njulia> x = 10\n10\n\n# 使用 x 的值做计算\njulia> x + 1\n11\n\n# 重新给 x 赋值\njulia> x = 1 + 1\n2\n\n# 也可以给 x 赋其它类型的值, 比如字符串文本\njulia> x = \"Hello World!\"\n\"Hello World!\"","category":"page"},{"location":"manual/variables/","page":"变量","title":"变量","text":"Julia 提供了非常灵活的变量命名策略。变量名是大小写敏感的,且不包含语义,意思是说,Julia 不会根据变量的名字来区别对待它们。 (译者注:Julia 不会自动将全大写的变量识别为常量,也不会将有特定前后缀的变量自动识别为某种特定类型的变量,即不会根据变量名字,自动判断变量的任何属性。)","category":"page"},{"location":"manual/variables/","page":"变量","title":"变量","text":"julia> x = 1.0\n1.0\n\njulia> y = -3\n-3\n\njulia> Z = \"My string\"\n\"My string\"\n\njulia> customary_phrase = \"Hello world!\"\n\"Hello world!\"\n\njulia> UniversalDeclarationOfHumanRightsStart = \"人人生而自由,在尊严和权利上一律平等。\"\n\"人人生而自由,在尊严和权利上一律平等。\"","category":"page"},{"location":"manual/variables/","page":"变量","title":"变量","text":"你还可以使用 UTF-8 编码的 Unicode 字符作为变量名:","category":"page"},{"location":"manual/variables/","page":"变量","title":"变量","text":"julia> δ = 0.00001\n1.0e-5\n\njulia> 안녕하세요 = \"Hello\"\n\"Hello\"","category":"page"},{"location":"manual/variables/","page":"变量","title":"变量","text":"在 Julia REPL 和一些其它 Julia 的编辑器中,很多 Unicode 数学符号可以使用反斜杠加 LaTeX 符号接 tab 健打出。例如: 变量名 δ 可以通过 \\delta-tab 来输入,甚至可以用 \\alpha-tab-\\hat-tab-\\^(2)-tab来输入 α̂⁽²⁾ 这种复杂的变量名。(如果你在某个地方发现了一个不知道怎么输入的符号,比如在别人的代码里,输入? 接着复制那个符号,REPL的帮助功能会告诉你输入方法。)","category":"page"},{"location":"manual/variables/","page":"变量","title":"变量","text":"如果有需要的话,Julia 甚至允许你重定义内置常量和函数。(这样做可能引发潜在的混淆,所以并不推荐)","category":"page"},{"location":"manual/variables/","page":"变量","title":"变量","text":"julia> pi = 3\n3\n\njulia> pi\n3\n\njulia> sqrt = 4\n4","category":"page"},{"location":"manual/variables/","page":"变量","title":"变量","text":"然而,如果你试图重定义一个已经在使用中的内置常量或函数,Julia 会报错:","category":"page"},{"location":"manual/variables/","page":"变量","title":"变量","text":"julia> pi\nπ = 3.1415926535897...\n\njulia> pi = 3\nERROR: cannot assign a value to variable MathConstants.pi from module Main\n\njulia> sqrt(100)\n10.0\n\njulia> sqrt = 4\nERROR: cannot assign a value to variable Base.sqrt from module Main","category":"page"},{"location":"manual/variables/#man-allowed-variable-names","page":"变量","title":"合法的变量名","text":"","category":"section"},{"location":"manual/variables/","page":"变量","title":"变量","text":"变量名字必须以英文字母(A-Z 或 a-z)、下划线或编码大于 00A0 的 Unicode 字符的一个子集开头。 具体来说指的是,Unicode字符分类中的 Lu/Ll/Lt/Lm/Lo/Nl(字母)、Sc/So(货币和其他符号)以及一些其它像字母的符号(例如 Sm 类别数学符号中的一部分)。 变量名的非首字符还允许使用惊叹号 !、数字(包括 0-9 和其他 Nd/No 类别中的 Unicode 字符)以及其它 Unicode 字符:变音符号和其他修改标记(Mn/Mc/Me/Sk 类别)、标点和连接符(Pc 类别)、引号和少许其他字符。","category":"page"},{"location":"manual/variables/","page":"变量","title":"变量","text":"像 + 这样的运算符也是合法的标识符,但是它们会被特别地解析。 在一些上下文中,运算符可以像变量一样使用,比如 (+) 表示加函数,语句 (+) = f会把它重新赋值。大部分 Unicode 中缀运算符(Sm 类别),像 ⊕,会被解析成真正的中缀运算符,并且支持用户自定义方法(举个例子,你可以使用语句 const ⊗ = kron将 ⊗ 定义为中缀的 Kronecker 积)。 运算符也可以使用修改标记、引号和上标/下标进行加缀,例如 +̂ₐ″ 被解析成一个与 + 具有相同优先级的中缀运算符。以下标/上标字母结尾的运算符与后续变量名之间需要一个空格。举个例子,如果 +ᵃ 是一个运算符,那么 +ᵃx 应该被写为+ᵃ x,以区分表达式 + ᵃx ,其中 ᵃx 是变量名。","category":"page"},{"location":"manual/variables/","page":"变量","title":"变量","text":"一类特定的变量名是只包含下划线的变量名。这些标识符只能赋值,不能用于给其他变量赋值。严格来说,它们只能用作左值 而不能作右值:","category":"page"},{"location":"manual/variables/","page":"变量","title":"变量","text":"julia> x, ___ = size([2 2; 1 1])\n(2, 2)\n\njulia> y = ___\nERROR: syntax: all-underscore identifier used as rvalue","category":"page"},{"location":"manual/variables/","page":"变量","title":"变量","text":"唯一明确禁止的变量名称是内置关键字的名称:","category":"page"},{"location":"manual/variables/","page":"变量","title":"变量","text":"julia> else = false\nERROR: syntax: unexpected \"else\"\n\njulia> try = \"No\"\nERROR: syntax: unexpected \"=\"","category":"page"},{"location":"manual/variables/","page":"变量","title":"变量","text":"某些 Unicode 字符被认为是等效的标识符。不同的输入 Unicode 组合字符的方法(例如:重音)被视为等价的(Julia 标识符采用 NFC 标准)。Julia 还加入了一些非标准的等价字符,用于在视觉上相似且易于通过某些输入法输入的字符。Unicode 字符 ɛ (U+025B: Latin small letter open e) 和 µ (U+00B5: micro sign) 被视为等同于相应的希腊字母。点 · (U+00B7) 和希腊字符间断 · (U+0387) 都被当作数学上的点积运算符 ⋅ (U+22C5)。减号 − (U+2212) 与连接号 - (U+002D) 也被视作相同的符号。","category":"page"},{"location":"manual/variables/#命名规范","page":"变量","title":"命名规范","text":"","category":"section"},{"location":"manual/variables/","page":"变量","title":"变量","text":"虽然 Julia 语言对合法名字的限制非常少,但是遵循以下这些命名规范是非常有用的:","category":"page"},{"location":"manual/variables/","page":"变量","title":"变量","text":"变量的名字采用小写。\n使用下划线('_')来分隔名字中的单词,但是不鼓励使用下划线 除非在不使用下划线时名字会非常难读。\n类型 (Type) 和模块(Module)的名字使用大写字母开头,并且用大写字母 而不是用下划线分隔单词。\n函数(function)和宏(macro)的名字使用小写,不使用下划线。\n会对输入参数进行更改的函数要使用 ! 结尾。这些函数有时叫做 “mutating” 或 “in-place” 函数,因为它们在被调用后会修改他们的输入参数的内容 而不仅仅只是返回一个值。","category":"page"},{"location":"manual/variables/","page":"变量","title":"变量","text":"关于命名规范的更多信息,可查看代码风格指南。","category":"page"},{"location":"stdlib/InteractiveUtils/#man-interactive-utils","page":"Interactive Utilities","title":"Interactive Utilities","text":"","category":"section"},{"location":"stdlib/InteractiveUtils/","page":"Interactive Utilities","title":"Interactive Utilities","text":"This module is intended for interactive work. It is loaded automaticaly in interactive mode.","category":"page"},{"location":"stdlib/InteractiveUtils/","page":"Interactive Utilities","title":"Interactive Utilities","text":"InteractiveUtils.apropos\nInteractiveUtils.varinfo\nInteractiveUtils.versioninfo\nInteractiveUtils.methodswith\nInteractiveUtils.subtypes\nInteractiveUtils.supertypes\nInteractiveUtils.edit(::AbstractString, ::Integer)\nInteractiveUtils.edit(::Any)\nInteractiveUtils.@edit\nInteractiveUtils.define_editor\nInteractiveUtils.less(::AbstractString)\nInteractiveUtils.less(::Any)\nInteractiveUtils.@less\nInteractiveUtils.@which\nInteractiveUtils.@functionloc\nInteractiveUtils.@code_lowered\nInteractiveUtils.@code_typed\nInteractiveUtils.code_warntype\nInteractiveUtils.@code_warntype\nInteractiveUtils.code_llvm\nInteractiveUtils.@code_llvm\nInteractiveUtils.code_native\nInteractiveUtils.@code_native\nInteractiveUtils.clipboard","category":"page"},{"location":"stdlib/InteractiveUtils/#Base.Docs.apropos","page":"Interactive Utilities","title":"Base.Docs.apropos","text":"apropos([io::IO=stdout], pattern::Union{AbstractString,Regex})\n\nSearch available docstrings for entries containing pattern.\n\nWhen pattern is a string, case is ignored. Results are printed to io.\n\napropos can be called from the help mode in the REPL by wrapping the query in double quotes:\n\nhelp?> \"pattern\"\n\n\n\n\n\n","category":"function"},{"location":"stdlib/InteractiveUtils/#InteractiveUtils.varinfo","page":"Interactive Utilities","title":"InteractiveUtils.varinfo","text":"varinfo(m::Module=Main, pattern::Regex=r\"\"; all::Bool = false, imported::Bool = false, sortby::Symbol = :name, minsize::Int = 0)\n\nReturn a markdown table giving information about exported global variables in a module, optionally restricted to those matching pattern.\n\nThe memory consumption estimate is an approximate lower bound on the size of the internal structure of the object.\n\nall : also list non-exported objects defined in the module, deprecated objects, and compiler-generated objects.\nimported : also list objects explicitly imported from other modules.\nrecursive : recursively include objects in sub-modules, observing the same settings in each.\nsortby : the column to sort results by. Options are :name (default), :size, and :summary.\nminsize : only includes objects with size at least minsize bytes. Defaults to 0.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/InteractiveUtils/#InteractiveUtils.versioninfo","page":"Interactive Utilities","title":"InteractiveUtils.versioninfo","text":"versioninfo(io::IO=stdout; verbose::Bool=false)\n\nPrint information about the version of Julia in use. The output is controlled with boolean keyword arguments:\n\nverbose: print all additional information\n\nwarning: Warning\nThe output of this function may contain sensitive information. Before sharing the output, please review the output and remove any data that should not be shared publicly.\n\nSee also: VERSION.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/InteractiveUtils/#InteractiveUtils.methodswith","page":"Interactive Utilities","title":"InteractiveUtils.methodswith","text":"methodswith(typ[, module or function]; supertypes::Bool=false])\n\nReturn an array of methods with an argument of type typ.\n\nThe optional second argument restricts the search to a particular module or function (the default is all top-level modules).\n\nIf keyword supertypes is true, also return arguments with a parent type of typ, excluding type Any.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/InteractiveUtils/#InteractiveUtils.subtypes","page":"Interactive Utilities","title":"InteractiveUtils.subtypes","text":"subtypes(T::DataType)\n\nReturn a list of immediate subtypes of DataType T. Note that all currently loaded subtypes are included, including those not visible in the current module.\n\nSee also supertype, supertypes, methodswith.\n\nExamples\n\njulia> subtypes(Integer)\n3-element Vector{Any}:\n Bool\n Signed\n Unsigned\n\n\n\n\n\n","category":"function"},{"location":"stdlib/InteractiveUtils/#InteractiveUtils.supertypes","page":"Interactive Utilities","title":"InteractiveUtils.supertypes","text":"supertypes(T::Type)\n\nReturn a tuple (T, ..., Any) of T and all its supertypes, as determined by successive calls to the supertype function, listed in order of <: and terminated by Any.\n\nSee also subtypes.\n\nExamples\n\njulia> supertypes(Int)\n(Int64, Signed, Integer, Real, Number, Any)\n\n\n\n\n\n","category":"function"},{"location":"stdlib/InteractiveUtils/#InteractiveUtils.edit-Tuple{AbstractString, Integer}","page":"Interactive Utilities","title":"InteractiveUtils.edit","text":"edit(path::AbstractString, line::Integer=0)\n\nEdit a file or directory optionally providing a line number to edit the file at. Return to the julia prompt when you quit the editor. The editor can be changed by setting JULIA_EDITOR, VISUAL or EDITOR as an environment variable.\n\nSee also define_editor.\n\n\n\n\n\n","category":"method"},{"location":"stdlib/InteractiveUtils/#InteractiveUtils.edit-Tuple{Any}","page":"Interactive Utilities","title":"InteractiveUtils.edit","text":"edit(function, [types])\nedit(module)\n\nEdit the definition of a function, optionally specifying a tuple of types to indicate which method to edit. For modules, open the main source file. The module needs to be loaded with using or import first.\n\ncompat: Julia 1.1\nedit on modules requires at least Julia 1.1.\n\nTo ensure that the file can be opened at the given line, you may need to call define_editor first.\n\n\n\n\n\n","category":"method"},{"location":"stdlib/InteractiveUtils/#InteractiveUtils.@edit","page":"Interactive Utilities","title":"InteractiveUtils.@edit","text":"@edit\n\nEvaluates the arguments to the function or macro call, determines their types, and calls the edit function on the resulting expression.\n\nSee also: @less, @which.\n\n\n\n\n\n","category":"macro"},{"location":"stdlib/InteractiveUtils/#InteractiveUtils.define_editor","page":"Interactive Utilities","title":"InteractiveUtils.define_editor","text":"define_editor(fn, pattern; wait=false)\n\nDefine a new editor matching pattern that can be used to open a file (possibly at a given line number) using fn.\n\nThe fn argument is a function that determines how to open a file with the given editor. It should take three arguments, as follows:\n\ncmd - a base command object for the editor\npath - the path to the source file to open\nline - the line number to open the editor at\n\nEditors which cannot open to a specific line with a command may ignore the line argument. The fn callback must return either an appropriate Cmd object to open a file or nothing to indicate that they cannot edit this file. Use nothing to indicate that this editor is not appropriate for the current environment and another editor should be attempted. It is possible to add more general editing hooks that need not spawn external commands by pushing a callback directly to the vector EDITOR_CALLBACKS.\n\nThe pattern argument is a string, regular expression, or an array of strings and regular expressions. For the fn to be called, one of the patterns must match the value of EDITOR, VISUAL or JULIA_EDITOR. For strings, the string must equal the basename of the first word of the editor command, with its extension, if any, removed. E.g. \"vi\" doesn't match \"vim -g\" but matches \"/usr/bin/vi -m\"; it also matches vi.exe. If pattern is a regex it is matched against all of the editor command as a shell-escaped string. An array pattern matches if any of its items match. If multiple editors match, the one added most recently is used.\n\nBy default julia does not wait for the editor to close, running it in the background. However, if the editor is terminal based, you will probably want to set wait=true and julia will wait for the editor to close before resuming.\n\nIf one of the editor environment variables is set, but no editor entry matches it, the default editor entry is invoked:\n\n(cmd, path, line) -> `$cmd $path`\n\nNote that many editors are already defined. All of the following commands should already work:\n\nemacs\nemacsclient\nvim\nnvim\nnano\nmicro\nkak\ntextmate\nmate\nkate\nsubl\natom\nnotepad++\nVisual Studio Code\nopen\npycharm\nbbedit\n\nExample:\n\nThe following defines the usage of terminal-based emacs:\n\ndefine_editor(\n r\"\\bemacs\\b.*\\s(-nw|--no-window-system)\\b\", wait=true) do cmd, path, line\n `$cmd +$line $path`\nend\n\ncompat: Julia 1.4\ndefine_editor was introduced in Julia 1.4.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/InteractiveUtils/#InteractiveUtils.less-Tuple{AbstractString}","page":"Interactive Utilities","title":"InteractiveUtils.less","text":"less(file::AbstractString, [line::Integer])\n\nShow a file using the default pager, optionally providing a starting line number. Returns to the julia prompt when you quit the pager.\n\n\n\n\n\n","category":"method"},{"location":"stdlib/InteractiveUtils/#InteractiveUtils.less-Tuple{Any}","page":"Interactive Utilities","title":"InteractiveUtils.less","text":"less(function, [types])\n\nShow the definition of a function using the default pager, optionally specifying a tuple of types to indicate which method to see.\n\n\n\n\n\n","category":"method"},{"location":"stdlib/InteractiveUtils/#InteractiveUtils.@less","page":"Interactive Utilities","title":"InteractiveUtils.@less","text":"@less\n\nEvaluates the arguments to the function or macro call, determines their types, and calls the less function on the resulting expression.\n\nSee also: @edit, @which, @code_lowered.\n\n\n\n\n\n","category":"macro"},{"location":"stdlib/InteractiveUtils/#InteractiveUtils.@which","page":"Interactive Utilities","title":"InteractiveUtils.@which","text":"@which\n\nApplied to a function or macro call, it evaluates the arguments to the specified call, and returns the Method object for the method that would be called for those arguments. Applied to a variable, it returns the module in which the variable was bound. It calls out to the which function.\n\nSee also: @less, @edit.\n\n\n\n\n\n","category":"macro"},{"location":"stdlib/InteractiveUtils/#InteractiveUtils.@functionloc","page":"Interactive Utilities","title":"InteractiveUtils.@functionloc","text":"@functionloc\n\nApplied to a function or macro call, it evaluates the arguments to the specified call, and returns a tuple (filename,line) giving the location for the method that would be called for those arguments. It calls out to the functionloc function.\n\n\n\n\n\n","category":"macro"},{"location":"stdlib/InteractiveUtils/#InteractiveUtils.@code_lowered","page":"Interactive Utilities","title":"InteractiveUtils.@code_lowered","text":"@code_lowered\n\nEvaluates the arguments to the function or macro call, determines their types, and calls code_lowered on the resulting expression.\n\n\n\n\n\n","category":"macro"},{"location":"stdlib/InteractiveUtils/#InteractiveUtils.@code_typed","page":"Interactive Utilities","title":"InteractiveUtils.@code_typed","text":"@code_typed\n\nEvaluates the arguments to the function or macro call, determines their types, and calls code_typed on the resulting expression. Use the optional argument optimize with\n\n@code_typed optimize=true foo(x)\n\nto control whether additional optimizations, such as inlining, are also applied.\n\n\n\n\n\n","category":"macro"},{"location":"stdlib/InteractiveUtils/#InteractiveUtils.code_warntype","page":"Interactive Utilities","title":"InteractiveUtils.code_warntype","text":"code_warntype([io::IO], f, types; debuginfo=:default)\n\nPrints lowered and type-inferred ASTs for the methods matching the given generic function and type signature to io which defaults to stdout. The ASTs are annotated in such a way as to cause \"non-leaf\" types to be emphasized (if color is available, displayed in red). This serves as a warning of potential type instability. Not all non-leaf types are particularly problematic for performance, so the results need to be used judiciously. In particular, unions containing either missing or nothing are displayed in yellow, since these are often intentional.\n\nKeyword argument debuginfo may be one of :source or :none (default), to specify the verbosity of code comments.\n\nSee @code_warntype for more information.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/InteractiveUtils/#InteractiveUtils.@code_warntype","page":"Interactive Utilities","title":"InteractiveUtils.@code_warntype","text":"@code_warntype\n\nEvaluates the arguments to the function or macro call, determines their types, and calls code_warntype on the resulting expression.\n\n\n\n\n\n","category":"macro"},{"location":"stdlib/InteractiveUtils/#InteractiveUtils.code_llvm","page":"Interactive Utilities","title":"InteractiveUtils.code_llvm","text":"code_llvm([io=stdout,], f, types; raw=false, dump_module=false, optimize=true, debuginfo=:default)\n\nPrints the LLVM bitcodes generated for running the method matching the given generic function and type signature to io.\n\nIf the optimize keyword is unset, the code will be shown before LLVM optimizations. All metadata and dbg.* calls are removed from the printed bitcode. For the full IR, set the raw keyword to true. To dump the entire module that encapsulates the function (with declarations), set the dump_module keyword to true. Keyword argument debuginfo may be one of source (default) or none, to specify the verbosity of code comments.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/InteractiveUtils/#InteractiveUtils.@code_llvm","page":"Interactive Utilities","title":"InteractiveUtils.@code_llvm","text":"@code_llvm\n\nEvaluates the arguments to the function or macro call, determines their types, and calls code_llvm on the resulting expression. Set the optional keyword arguments raw, dump_module, debuginfo, optimize by putting them and their value before the function call, like this:\n\n@code_llvm raw=true dump_module=true debuginfo=:default f(x)\n@code_llvm optimize=false f(x)\n\noptimize controls whether additional optimizations, such as inlining, are also applied. raw makes all metadata and dbg.* calls visible. debuginfo may be one of :source (default) or :none, to specify the verbosity of code comments. dump_module prints the entire module that encapsulates the function.\n\n\n\n\n\n","category":"macro"},{"location":"stdlib/InteractiveUtils/#InteractiveUtils.code_native","page":"Interactive Utilities","title":"InteractiveUtils.code_native","text":"code_native([io=stdout,], f, types; syntax=:att, debuginfo=:default, binary=false, dump_module=true)\n\nPrints the native assembly instructions generated for running the method matching the given generic function and type signature to io.\n\nSet assembly syntax by setting syntax to :att (default) for AT&T syntax or :intel for Intel syntax.\nSpecify verbosity of code comments by setting debuginfo to :source (default) or :none.\nIf binary is true, also print the binary machine code for each instruction precedented by an abbreviated address.\nIf dump_module is false, do not print metadata such as rodata or directives.\n\nSee also: @code_native, code_llvm, code_typed and code_lowered\n\n\n\n\n\n","category":"function"},{"location":"stdlib/InteractiveUtils/#InteractiveUtils.@code_native","page":"Interactive Utilities","title":"InteractiveUtils.@code_native","text":"@code_native\n\nEvaluates the arguments to the function or macro call, determines their types, and calls code_native on the resulting expression.\n\nSet any of the optional keyword arguments syntax, debuginfo, binary or dump_module by putting it before the function call, like this:\n\n@code_native syntax=:intel debuginfo=:default binary=true dump_module=false f(x)\n\nSet assembly syntax by setting syntax to :att (default) for AT&T syntax or :intel for Intel syntax.\nSpecify verbosity of code comments by setting debuginfo to :source (default) or :none.\nIf binary is true, also print the binary machine code for each instruction precedented by an abbreviated address.\nIf dump_module is false, do not print metadata such as rodata or directives.\n\nSee also: code_native, @code_llvm, @code_typed and @code_lowered\n\n\n\n\n\n","category":"macro"},{"location":"stdlib/InteractiveUtils/#InteractiveUtils.clipboard","page":"Interactive Utilities","title":"InteractiveUtils.clipboard","text":"clipboard(x)\n\nSend a printed form of x to the operating system clipboard (\"copy\").\n\n\n\n\n\nclipboard() -> AbstractString\n\nReturn a string with the contents of the operating system clipboard (\"paste\").\n\n\n\n\n\n","category":"function"},{"location":"stdlib/Serialization/#序列化","page":"序列化","title":"序列化","text":"","category":"section"},{"location":"stdlib/Serialization/","page":"序列化","title":"序列化","text":"Serialization.serialize\nSerialization.deserialize\nSerialization.writeheader","category":"page"},{"location":"stdlib/Serialization/#Serialization.serialize","page":"序列化","title":"Serialization.serialize","text":"serialize(stream::IO, value)\n\nWrite an arbitrary value to a stream in an opaque format, such that it can be read back by deserialize. The read-back value will be as identical as possible to the original, but note that Ptr values are serialized as all-zero bit patterns (NULL).\n\nAn 8-byte identifying header is written to the stream first. To avoid writing the header, construct a Serializer and use it as the first argument to serialize instead. See also Serialization.writeheader.\n\nThe data format can change in minor (1.x) Julia releases, but files written by prior 1.x versions will remain readable. The main exception to this is when the definition of a type in an external package changes. If that occurs, it may be necessary to specify an explicit compatible version of the affected package in your environment. Renaming functions, even private functions, inside packages can also put existing files out of sync. Anonymous functions require special care: because their names are automatically generated, minor code changes can cause them to be renamed. Serializing anonymous functions should be avoided in files intended for long-term storage.\n\nIn some cases, the word size (32- or 64-bit) of the reading and writing machines must match. In rarer cases the OS or architecture must also match, for example when using packages that contain platform-dependent code.\n\n\n\n\n\nserialize(filename::AbstractString, value)\n\nOpen a file and serialize the given value to it.\n\ncompat: Julia 1.1\nThis method is available as of Julia 1.1.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/Serialization/#Serialization.deserialize","page":"序列化","title":"Serialization.deserialize","text":"deserialize(stream)\n\nRead a value written by serialize. deserialize assumes the binary data read from stream is correct and has been serialized by a compatible implementation of serialize. deserialize is designed for simplicity and performance, and so does not validate the data read. Malformed data can result in process termination. The caller must ensure the integrity and correctness of data read from stream.\n\n\n\n\n\ndeserialize(filename::AbstractString)\n\nOpen a file and deserialize its contents.\n\ncompat: Julia 1.1\nThis method is available as of Julia 1.1.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/Serialization/#Serialization.writeheader","page":"序列化","title":"Serialization.writeheader","text":"Serialization.writeheader(s::AbstractSerializer)\n\nWrite an identifying header to the specified serializer. The header consists of 8 bytes as follows:\n\nOffset Description\n0 tag byte (0x37)\n1-2 signature bytes \"JL\"\n3 protocol version\n4 bits 0-1: endianness: 0 = little, 1 = big\n4 bits 2-3: platform: 0 = 32-bit, 1 = 64-bit\n5-7 reserved\n\n\n\n\n\n","category":"function"},{"location":"stdlib/Future/#Future","page":"Future","title":"Future","text":"","category":"section"},{"location":"stdlib/Future/","page":"Future","title":"Future","text":"The Future module implements future behavior of already existing functions, which will replace the current version in a future release of Julia.","category":"page"},{"location":"stdlib/Future/","page":"Future","title":"Future","text":"Future.copy!\nFuture.randjump","category":"page"},{"location":"stdlib/Future/#Future.copy!","page":"Future","title":"Future.copy!","text":"Future.copy!(dst, src) -> dst\n\nCopy src into dst.\n\ncompat: Julia 1.1\nThis function has moved to Base with Julia 1.1, consider using copy!(dst, src) instead. Future.copy! will be deprecated in the future.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/Future/#Future.randjump","page":"Future","title":"Future.randjump","text":"randjump(r::MersenneTwister, steps::Integer) -> MersenneTwister\n\nCreate an initialized MersenneTwister object, whose state is moved forward (without generating numbers) from r by steps steps. One such step corresponds to the generation of two Float64 numbers. For each different value of steps, a large polynomial has to be generated internally. One is already pre-computed for steps=big(10)^20.\n\n\n\n\n\n","category":"function"},{"location":"manual/documentation/#man-documentation","page":"文档","title":"文档","text":"","category":"section"},{"location":"manual/documentation/","page":"文档","title":"文档","text":"Julia允许开发者和用户,使用其内置的文档系统更加便捷地为函数、类型以及其他对象编写文档。  ","category":"page"},{"location":"manual/documentation/","page":"文档","title":"文档","text":"基础语法很简单:紧接在对象(函数,宏,类型和实例)之前的字符串都会被认为是对应对象的文档(称作 docstrings)。 注意不要在 docstring 和文档对象之间有空行或者注释。 这里有个基础的例子:","category":"page"},{"location":"manual/documentation/","page":"文档","title":"文档","text":"\"Tell whether there are too foo items in the array.\"\nfoo(xs::Array) = ...","category":"page"},{"location":"manual/documentation/","page":"文档","title":"文档","text":"文档会被翻译成 Markdown,所以你可以 使用缩进和代码块来分隔代码示例和文本。从技术上来说,任何对象 都可以作为 metadata 与任何其他对象关联;Markdown 是默认的,但是可以创建 其它字符串宏并传递给 @doc 宏来使用其他格式。","category":"page"},{"location":"manual/documentation/","page":"文档","title":"文档","text":"note: Note\nMarkdown 支持由 Markdown 标准库实现,有关支持语法的完整列表,请参阅其文档。","category":"page"},{"location":"manual/documentation/","page":"文档","title":"文档","text":"这里是一个更加复杂的例子,但仍然使用 Markdown:","category":"page"},{"location":"manual/documentation/","page":"文档","title":"文档","text":"\"\"\"\n bar(x[, y])\n\nCompute the Bar index between `x` and `y`.\n\nIf `y` is unspecified, compute the Bar index between all pairs of columns of `x`.\n\n# Examples\n```julia-repl\njulia> bar([1, 2], [1, 2])\n1\n```\n\"\"\"\nfunction bar(x, y) ...","category":"page"},{"location":"manual/documentation/","page":"文档","title":"文档","text":"如上例所示,我们推荐在写文档时遵守一些简单约定:","category":"page"},{"location":"manual/documentation/","page":"文档","title":"文档","text":"始终在文档顶部显示函数的签名并带有四空格缩进,以便能够显示成 Julia 代码。\n这和在 Julia 代码中的签名是一样的(比如 mean(x::AbstractArray)),或是简化版。可选参数应该尽可能与默认值一同显示(例如 f(x, y=1)),这与实际的 Julia 语法一致。没有默认值的可选参数应该放在括号中(例如 f(x[, y]) 和 f(x[, y[, z]]))。可选的解决方法是使用多行:一个没有可选参数,其他的拥有可选参数(或者多个可选参数)。这个解决方案也可以用作给某个函数的多个方法来写文档。当一个函数接收到多个关键字参数,只在签名中包含占位符 (例如 f(x; )),并在 # Arguments 章节给出完整列表(参照下列第 4 点)。\n在简化的签名块后请包含一个描述函数能做什么或者对象代表什么的单行句。如果需要的话,在一个空行之后,在第二段提供更详细的信息。\n撰写函数的文档时,单行语句应使用祈使结构(比如「Do this」、「Return that」)而非第三人称(不要写「Returns the length...」)。并且应以句号结尾。如果函数的意义不能简单地总结,更好的方法是分成分开的组合句(虽然这不应被看做是对于每种情况下的绝对要求)。\n不要自我重复。\n因为签名给出了函数名,所以没有必要用「The function bar...」开始文档:直接说要点。类似地,如果签名指定了参数的类型,在描述中提到这些是多余的。\n只在确实必要时提供参数列表。\n对于简单函数,直接在函数目的的描述中提到参数的作用常常更加清楚。参数列表只会重复再其他地方提供过的信息。但是,对于拥有多个参数的(特别是含有关键字参数的)复杂函数来说,提供一个参数列表是个好主意。在这种情况下,请在函数的一般描述之后、标题 # Arguments 之下插入参数列表,并在每个参数前加个着重号 -。参数列表应该提到参数的类型和默认值(如果有):\n\"\"\"\n...\n# Arguments\n- `n::Integer`: the number of elements to compute.\n- `dim::Integer=1`: the dimensions along which to perform the computation.\n...\n\"\"\"\n给相关函数提供提示。\n有时会存在具有功能相联系的函数。为了更易于发现相关函数,请在段落 See also: 中为其提供一个小列表。\nSee also [`bar!`](@ref), [`baz`](@ref), [`baaz`](@ref).\n请在 # Examples 中包含一些代码例子。\n例子应尽可能按照 doctest 来写。doctest 是一个栅栏分隔开的代码块(请参阅代码块),其以 ```jldoctest 开头并包含任意数量的提示符 julia> 以及用来模拟 Julia REPL 的输入和预期输出。\nnote: Note\nDoctest 由 Documenter.jl 支持。有关更详细的文档,请参阅 Documenter 的手册。\n例如在下面的 docstring 中定义了变量 a,预期的输出,跟在 Julia REPL 中打印的一样,出现在后面。\n\"\"\"\nSome nice documentation here.\n\n# Examples\n```jldoctest\njulia> a = [1 2; 3 4]\n2×2 Array{Int64,2}:\n 1 2\n 3 4\n```\n\"\"\"\nwarning: Warning\nCalling rand and other RNG-related functions should be avoided in doctests since they will not produce consistent outputs during different Julia sessions. If you would like to show some random number generation related functionality, one option is to explicitly construct and seed your own RNG object (see Random) and pass it to the functions you are doctesting.Operating system word size (Int32 or Int64) as well as path separator differences (/ or \\) will also affect the reproducibility of some doctests.Note that whitespace in your doctest is significant! The doctest will fail if you misalign the output of pretty-printing an array, for example.\n你可以运行 make -C doc doctest=true 来运行在 Julia 手册和 API 文档中的 doctests,这样可以确保你的例子都能正常运行。\n为了表示输出结果被截断了,你应该在校验应该停止的一行写上 [...]。这个在当 doctest 显示有个异常被抛出时隐藏堆栈跟踪时很有用(堆栈跟踪包含对 julia 代码的行的非永久引用),例如:\n```jldoctest\njulia> div(1, 0)\nERROR: DivideError: integer division error\n[...]\n```\n那些不能进行测试的例子应该写在以 ```julia 开头的栅栏分隔的代码块中,以便在生成的文档中正确地高亮显示。\ntip: Tip\n例子应尽可能独立和可运行以便读者可以在不需要引入任何依赖的情况下对它们进行实验。\n使用倒引号来标识代码和方程。\nJulia 标识符和代码摘录应该出现在倒引号 ` 之间来使其能高亮显示。LaTeX 语法下的方程应该插入到双倒引号 `` 之间。请使用 Unicode 字符而非 LaTeX 转义序列,比如 ``α = 1`` 而非 ``\\\\alpha = 1``。\n请将起始和结束的\"\"\"符号单独成行。\n也就是说,请写:\n\"\"\"\n...\n\n...\n\"\"\"\nf(x, y) = ...\n而非:\n\"\"\"...\n\n...\"\"\"\nf(x, y) = ...\n这将让 docstring 的起始和结束位置更加清楚。\n请在代码中遵守单行长度限制。\nDocstring 是使用与代码相同的工具编辑的。所以应运用同样的约定。 建议一行 92 个字符后换行。\n请在 # Implementation 章节中提供自定义类型如何实现该函数的信息。这些实现细节是针对开发者而非用户的,解释了例如哪些函数应该被重写、哪些函数自动使用恰当的回退函数等信息,最好与描述函数的主体描述分开。\n对于长文档字符串,可以考虑使用 # Extended help 头拆分文档。典型的帮助模式将只显示标题上方的内容;你可以通过添加一个 ? 在表达的开头来查看完整的文档(即 ??foo 而不是 ?foo)。","category":"page"},{"location":"manual/documentation/#访问文档","page":"文档","title":"访问文档","text":"","category":"section"},{"location":"manual/documentation/","page":"文档","title":"文档","text":"文档可以在REPL中访问,也可以在 IJulia 中通过键入?紧接函数或者宏的名字并按下Enter访问。例如,","category":"page"},{"location":"manual/documentation/","page":"文档","title":"文档","text":"?cos\n?@time\n?r\"\"","category":"page"},{"location":"manual/documentation/","page":"文档","title":"文档","text":"会分别为相应的函数,宏或者字符显示文档。在 Juno 中,使用 Ctrl-J, Ctrl-D 会为光标处的对象显示文档。","category":"page"},{"location":"manual/documentation/#函数与方法","page":"文档","title":"函数与方法","text":"","category":"section"},{"location":"manual/documentation/","page":"文档","title":"文档","text":"在Julia中函数可能有多种实现,被称为方法。虽然通用函数 一般只有一个目的,Julia允许在必要时可以对方法独立写文档。 通常,应该只有最通用的方法才有文档,或者甚至只是函数本身 (也就是在function bar end之前没有任何方法的对象)。特定方法应该 只因为其行为与其他通用方法有所区别才写文档。在任何情况下都不应 重复其他地方有的信息。例如","category":"page"},{"location":"manual/documentation/","page":"文档","title":"文档","text":"\"\"\"\n *(x, y, z...)\n\nMultiplication operator. `x * y * z *...` calls this function with multiple\narguments, i.e. `*(x, y, z...)`.\n\"\"\"\nfunction *(x, y, z...)\n # ... [implementation sold separately] ...\nend\n\n\"\"\"\n *(x::AbstractString, y::AbstractString, z::AbstractString...)\n\nWhen applied to strings, concatenates them.\n\"\"\"\nfunction *(x::AbstractString, y::AbstractString, z::AbstractString...)\n # ... [insert secret sauce here] ...\nend\n\nhelp?> *\nsearch: * .*\n\n *(x, y, z...)\n\n Multiplication operator. x * y * z *... calls this function with multiple\n arguments, i.e. *(x,y,z...).\n\n *(x::AbstractString, y::AbstractString, z::AbstractString...)\n\n When applied to strings, concatenates them.","category":"page"},{"location":"manual/documentation/","page":"文档","title":"文档","text":"当从通用函数里抽取文档时,每个方法的元数据会用函数catdoc拼接,其当然可以被自定义类型重写。","category":"page"},{"location":"manual/documentation/#进阶用法","page":"文档","title":"进阶用法","text":"","category":"section"},{"location":"manual/documentation/","page":"文档","title":"文档","text":"@doc 宏将它的第一个参数与它的第二个参数关联在各个模块的名为 META 的字典中。","category":"page"},{"location":"manual/documentation/","page":"文档","title":"文档","text":"为了让写文档更加简单,语法分析器对宏名@doc特殊对待:如果@doc的调用只有一个参数,但是在下一行出现了另外一个表达式,那么这个表达式就会追加为宏的参数。所以接下来的语法会被分析成@doc的2个参数的调用:","category":"page"},{"location":"manual/documentation/","page":"文档","title":"文档","text":"@doc raw\"\"\"\n...\n\"\"\"\nf(x) = x","category":"page"},{"location":"manual/documentation/","page":"文档","title":"文档","text":"这就让使用任意对象(这里指的是原始字符串 raw\"\")作为 docstring 变得简单。","category":"page"},{"location":"manual/documentation/","page":"文档","title":"文档","text":"当@doc宏(或者doc函数)用作抽取文档时,他会在所有的META字典寻找与对象相关的元数据并且返回。返回的对象(例如一些Markdown内容)会默认智能地显示。这个设计也让以编程方法使用文档系统变得容易;例如,在一个函数的不同版本中重用文档:","category":"page"},{"location":"manual/documentation/","page":"文档","title":"文档","text":"@doc \"...\" foo!\n@doc (@doc foo!) foo","category":"page"},{"location":"manual/documentation/","page":"文档","title":"文档","text":"或者与Julia的元编程功能一起使用:","category":"page"},{"location":"manual/documentation/","page":"文档","title":"文档","text":"for (f, op) in ((:add, :+), (:subtract, :-), (:multiply, :*), (:divide, :/))\n @eval begin\n $f(a,b) = $op(a,b)\n end\nend\n@doc \"`add(a,b)` adds `a` and `b` together\" add\n@doc \"`subtract(a,b)` subtracts `b` from `a`\" subtract","category":"page"},{"location":"manual/documentation/","page":"文档","title":"文档","text":"写在非顶级块,比如begin, if, for, 和 let,中的文档会根据块的评估情况加入文档系统中,例如:","category":"page"},{"location":"manual/documentation/","page":"文档","title":"文档","text":"if condition()\n \"...\"\n f(x) = x\nend","category":"page"},{"location":"manual/documentation/","page":"文档","title":"文档","text":"会被加到f(x)的文档中,当condition()是true的时候。注意即使f(x)在块的末尾离开了作用域,他的文档还会保留。","category":"page"},{"location":"manual/documentation/","page":"文档","title":"文档","text":"可以利用元编程来帮助创建文档。当在文档字符串中使用字符串插值时,需要使用额外的 $ 例如:$($name)","category":"page"},{"location":"manual/documentation/","page":"文档","title":"文档","text":"for func in (:day, :dayofmonth)\n name = string(func)\n @eval begin\n @doc \"\"\"\n $($name)(dt::TimeType) -> Int64\n\n The day of month of a `Date` or `DateTime` as an `Int64`.\n \"\"\" $func(dt::Dates.TimeType)\n end\nend","category":"page"},{"location":"manual/documentation/#动态写文档","page":"文档","title":"动态写文档","text":"","category":"section"},{"location":"manual/documentation/","page":"文档","title":"文档","text":"有些时候类型的实例的合适的文档并非只取决于类型本身,也取决于实例的值。在这些情况下,你可以添加一个方法给自定义类型的Docs.getdoc函数,返回基于每个实例的文档。例如,","category":"page"},{"location":"manual/documentation/","page":"文档","title":"文档","text":"struct MyType\n value::Int\nend\n\nDocs.getdoc(t::MyType) = \"Documentation for MyType with value $(t.value)\"\n\nx = MyType(1)\ny = MyType(2)","category":"page"},{"location":"manual/documentation/","page":"文档","title":"文档","text":"?x 将显示“Documentation for MyType with value 1”,而?y 将显示“Documentation for MyType with value 2”。","category":"page"},{"location":"manual/documentation/#语法指南","page":"文档","title":"语法指南","text":"","category":"section"},{"location":"manual/documentation/","page":"文档","title":"文档","text":"本指南提供了如何将文档附加到所有可能的 Julia 语法构造的全面概述。","category":"page"},{"location":"manual/documentation/","page":"文档","title":"文档","text":"在下述例子中\"...\"用来表示任意的docstring。","category":"page"},{"location":"manual/documentation/#与-\\-字符","page":"文档","title":"$ 与 \\ 字符","text":"","category":"section"},{"location":"manual/documentation/","page":"文档","title":"文档","text":"$ 和 \\ 字符仍然被解析为字符串插值或转义序列的开始字符。 raw\"\" 字符串宏和 @doc 宏可以用来避免对它们进行转义。 当文档字符串包含 LaTeX 或 Julia 源代码,且示例中包含插值时,这是很方便的:","category":"page"},{"location":"manual/documentation/","page":"文档","title":"文档","text":"@doc raw\"\"\"\n```math\n\\LaTeX\n```\n\"\"\"\nfunction f end","category":"page"},{"location":"manual/documentation/#函数与方法-2","page":"文档","title":"函数与方法","text":"","category":"section"},{"location":"manual/documentation/","page":"文档","title":"文档","text":"\"...\"\nfunction f end\n\n\"...\"\nf","category":"page"},{"location":"manual/documentation/","page":"文档","title":"文档","text":"把 docstring \"...\" 添加给了函数 f。首选的语法是第一种,虽然两者是等价的。","category":"page"},{"location":"manual/documentation/","page":"文档","title":"文档","text":"\"...\"\nf(x) = x\n\n\"...\"\nfunction f(x)\n x\nend\n\n\"...\"\nf(x)","category":"page"},{"location":"manual/documentation/","page":"文档","title":"文档","text":"把 docstring \"...\" 添加给了方法 f(::Any)。","category":"page"},{"location":"manual/documentation/","page":"文档","title":"文档","text":"\"...\"\nf(x, y = 1) = x + y","category":"page"},{"location":"manual/documentation/","page":"文档","title":"文档","text":"把 docstring \"...\" 添加给了两个方法,分别为 f(::Any) 和 f(::Any, ::Any)。","category":"page"},{"location":"manual/documentation/#宏","page":"文档","title":"宏","text":"","category":"section"},{"location":"manual/documentation/","page":"文档","title":"文档","text":"\"...\"\nmacro m(x) end","category":"page"},{"location":"manual/documentation/","page":"文档","title":"文档","text":"把 docstring \"...\" 添加给了宏 @m(::Any) 的定义。","category":"page"},{"location":"manual/documentation/","page":"文档","title":"文档","text":"\"...\"\n:(@m)","category":"page"},{"location":"manual/documentation/","page":"文档","title":"文档","text":"把 docstring \"...\" 添加给了名为 @m 的宏。","category":"page"},{"location":"manual/documentation/#类型","page":"文档","title":"类型","text":"","category":"section"},{"location":"manual/documentation/","page":"文档","title":"文档","text":"\"...\"\nabstract type T1 end\n\n\"...\"\nmutable struct T2\n ...\nend\n\n\"...\"\nstruct T3\n ...\nend","category":"page"},{"location":"manual/documentation/","page":"文档","title":"文档","text":"把 docstring \"...\" 添加给了类型 T1、T2 和 T3。","category":"page"},{"location":"manual/documentation/","page":"文档","title":"文档","text":"\"...\"\nstruct T\n \"x\"\n x\n \"y\"\n y\nend","category":"page"},{"location":"manual/documentation/","page":"文档","title":"文档","text":"把 docstring \"...\" 添加给了类型 T,\"x\" 添加给字段 T.x,\"y\" 添加给字段 T.y。也可以运用于mutable struct 类型。","category":"page"},{"location":"manual/documentation/#模块","page":"文档","title":"模块","text":"","category":"section"},{"location":"manual/documentation/","page":"文档","title":"文档","text":"\"...\"\nmodule M end\n\nmodule M\n\n\"...\"\nM\n\nend","category":"page"},{"location":"manual/documentation/","page":"文档","title":"文档","text":"把 docstring \"...\" 添加给了模块 M。首选的语法是在模块之前添加 docstring,虽然两者是等价的。","category":"page"},{"location":"manual/documentation/","page":"文档","title":"文档","text":"\"...\"\nbaremodule M\n# ...\nend\n\nbaremodule M\n\nimport Base: @doc\n\n\"...\"\nf(x) = x\n\nend","category":"page"},{"location":"manual/documentation/","page":"文档","title":"文档","text":"通过在表达式上方放置一个 docstring 来记录 baremodule 会自动将 @doc 导入到模块中。 当没有记录模块表达式时,必须手动完成这些导入。","category":"page"},{"location":"manual/documentation/#全局变量","page":"文档","title":"全局变量","text":"","category":"section"},{"location":"manual/documentation/","page":"文档","title":"文档","text":"\"...\"\nconst a = 1\n\n\"...\"\nb = 2\n\n\"...\"\nglobal c = 3","category":"page"},{"location":"manual/documentation/","page":"文档","title":"文档","text":"把docstring\"...\"添加给了绑定 a,b和c。","category":"page"},{"location":"manual/documentation/","page":"文档","title":"文档","text":"绑定是用来在模块中存储对于特定符号的引用而非存储被引用的值本身。","category":"page"},{"location":"manual/documentation/","page":"文档","title":"文档","text":"note: Note\n当一个 const 定义只是用作定义另外一个定义的别名时,比如函数 div 和其在 Base 中的别名 ÷,并不要为别名写文档,转而去为实际的函数写文档。如果别名写了文档而实际定义没有,那么文档系统(? 模式)在寻找实际定义的文档时将不会返回别名的对应文档。比如你应该写\"...\"\nf(x) = x + 1\nconst alias = f而非f(x) = x + 1\n\"...\"\nconst alias = f","category":"page"},{"location":"manual/documentation/","page":"文档","title":"文档","text":"\"...\"\nsym","category":"page"},{"location":"manual/documentation/","page":"文档","title":"文档","text":"把 docstring \"...\" 添加给值 sym。但是应首选在 sym 的定义处写文档。","category":"page"},{"location":"manual/documentation/#多重对象","page":"文档","title":"多重对象","text":"","category":"section"},{"location":"manual/documentation/","page":"文档","title":"文档","text":"\"...\"\na, b","category":"page"},{"location":"manual/documentation/","page":"文档","title":"文档","text":"把docstring \"...\" 添加给a和b,两个都应该是可以写文档的表达式。这个语法等价于","category":"page"},{"location":"manual/documentation/","page":"文档","title":"文档","text":"\"...\"\na\n\n\"...\"\nb","category":"page"},{"location":"manual/documentation/","page":"文档","title":"文档","text":"这种方法可以给任意数量的表达式写文档。当两个函数相关,比如非变版本f和可变版本f!,这个语法是有用的。","category":"page"},{"location":"manual/documentation/#宏生成代码","page":"文档","title":"宏生成代码","text":"","category":"section"},{"location":"manual/documentation/","page":"文档","title":"文档","text":"\"...\"\n@m expression","category":"page"},{"location":"manual/documentation/","page":"文档","title":"文档","text":"把docstring \"...\" 添加给通过展开 @m expression 生成的表达式。 这就允许由 @inline、@noinline、@generated 或者任意其他宏装饰的表达式,能和没有装饰的表达式以同样的方式写文档。","category":"page"},{"location":"manual/documentation/","page":"文档","title":"文档","text":"宏作者应该注意到只有只生成单个表达式的宏才会自动支持docstring。如果宏返回的是含有多个子表达式的块,需要写文档的子表达式应该使用宏 @__doc__ 标记。","category":"page"},{"location":"manual/documentation/","page":"文档","title":"文档","text":"@enum 宏使用了 @__doc__ 来允许给 Enum 写文档。它的做法可以作为如何正确使用 @__doc__ 的范例。","category":"page"},{"location":"manual/documentation/","page":"文档","title":"文档","text":"Core.@__doc__","category":"page"},{"location":"manual/documentation/#Core.@__doc__","page":"文档","title":"Core.@__doc__","text":"@__doc__(ex)\n\nLow-level macro used to mark expressions returned by a macro that should be documented. If more than one expression is marked then the same docstring is applied to each expression.\n\nmacro example(f)\n quote\n $(f)() = 0\n @__doc__ $(f)(x) = 1\n $(f)(x, y) = 2\n end |> esc\nend\n\n@__doc__ has no effect when a macro that uses it is not documented.\n\n\n\n\n\n","category":"macro"},{"location":"manual/noteworthy-differences/#与其他语言的显著差异","page":"与其他语言的显著差异","title":"与其他语言的显著差异","text":"","category":"section"},{"location":"manual/noteworthy-differences/#Noteworthy-differences-from-MATLAB","page":"与其他语言的显著差异","title":"与 MATLAB 的显著差异","text":"","category":"section"},{"location":"manual/noteworthy-differences/","page":"与其他语言的显著差异","title":"与其他语言的显著差异","text":"虽然 MATLAB 用户可能会发现 Julia 的语法很熟悉,但 Julia 不是 MATLAB 的克隆。 它们之间存在重大的语法和功能差异。 以下是一些可能会使习惯于 MATLAB 的 Julia 用户感到困扰的显著差异:","category":"page"},{"location":"manual/noteworthy-differences/","page":"与其他语言的显著差异","title":"与其他语言的显著差异","text":"Julia 数组使用方括号 A[i,j] 进行索引。\nJulia 数组在分配给另一个变量时不会被复制。 在A = B之后,改变B的元素也会改变A的元素。\nJulia 的值在向函数传递时不发生复制。如果某个函数修改了数组,这一修改对调用者是可见的。\nJulia 不会在赋值语句中自动增长数组。 而在 MATLAB 中 a(4) = 3.2 可以创建数组 a = [0 0 0 3.2],而 a(5) = 7 可以将它增长为 a = [0 0 0 3.2 7]。如果 a 的长度小于 5 或者这个语句是第一次使用标识符 a,则相应的 Julia 语句 a[5] = 7 会抛出错误。Julia 使用 push! 和 append! 来增长 Vector,它们比 MATLAB 的 a(end+1) = val 更高效。\n虚数单位 sqrt(-1) 在 Julia 中表示为 im,而不是在 MATLAB 中的 i 或 j。\n在 Julia 中,没有小数点的数字字面量(例如 42)会创建整数而不是浮点数。也支持任意大整数字面量。因此,某些操作(如 2^-1)将抛出 domain error,因为结果不是整数(有关的详细信息,请参阅常见问题中有关 domain errors 的条目)。 在 Julia 中,没有小数点的数字字面量(例如 42)会创建整数而不是浮点数。因此,某些操作会因为需要浮点数而抛出 domain error;例如 julia > a = -1; 2^a ,因为结果不是整数了。请参阅常见问题中有关 domain errors 的条目)。\n在 Julia 中,能返回多个值并将其赋值为元组,例如 (a, b) = (1, 2) 或 a, b = 1, 2。 在 Julia 中不存在 MATLAB 的 nargout,它通常在 MATLAB 中用于根据返回值的数量执行可选工作。取而代之的是,用户可以使用可选参数和关键字参数来实现类似的功能。\nJulia 拥有真正的一维数组。列向量的大小为 N,而不是 Nx1。例如,rand(N) 创建一个一维数组。\n在 Julia 中,[x,y,z] 将始终构造一个包含x、y 和 z 的 3 元数组。\n要在第一个维度(「垂直列」)中连接元素,请使用 vcat(x,y,z) 或用分号分隔([x; y; z])。\n要在第二个维度(「水平行」)中连接元素,请使用 hcat(x,y,z) 或用空格分隔([x y z])。\n要构造分块矩阵(在前两个维度中连接元素),请使用 hvcat 或组合空格和分号([a b; c d])。\n在 Julia 中,a:b 和 a:b:c 构造 AbstractRange 对象。使用 collect(a:b) 构造一个类似 MATLAB 中完整的向量。通常,不需要调用 collect。在大多数情况下,AbstractRange 对象将像普通数组一样运行,但效率更高,因为它是懒惰求值。这种创建专用对象而不是完整数组的模式经常被使用,并且也可以在诸如 range 之类的函数中看到,或者在诸如 enumerate 和 zip 之类的迭代器中看到。特殊对象大多可以像正常数组一样使用。\nJulia 中的函数返回其最后一个表达式或 return 关键字的值而无需在函数定义中列出要返回的变量的名称(有关详细信息,请参阅 return 关键字)。\nJulia 脚本可以包含任意数量的函数,并且在加载文件时,所有定义都将在外部可见。可以从当前工作目录之外的文件加载函数定义。\n在 Julia 中,例如 sum、prod 和 max 的归约操作会作用到数组的每一个元素上,当调用时只有一个函数,例如 sum(A),即使 A 并不只有一个维度。\n在 Julia 中,调用无参数的函数时必须使用小括号,例如 rand()。\nJulia 不鼓励使用分号来结束语句。语句的结果不会自动打印(除了在 REPL 中),并且代码的一行不必使用分号结尾。println 或者 @printf 能用来打印特定输出。\n在 Julia 中,如果 A 和 B 是数组,像 A == B 这样的逻辑比较运算符不会返回布尔值数组。相反地,请使用 A .== B。对于其他的像是 <、> 的布尔运算符同理。\n在 Julia 中,运算符&、| 和 ⊻(xor)进行按位操作,分别与MATLAB中的and、or 和 xor 等价,并且优先级与 Python 的按位运算符相似(不像 C)。他们可以对标量运算或者数组中逐元素运算,可以用来合并逻辑数组,但是注意运算顺序的区别:括号可能是必要的(例如,选择 A 中等于 1 或 2 的元素可使用 (A .== 1) .| (A .== 2))。\n在 Julia 中,集合的元素可以使用 splat 运算符 ... 来作为参数传递给函数,如 xs=[1,2]; f(xs...)。\nJulia 的 svd 将奇异值作为向量而非密集对角矩阵返回。\n在 Julia 中,... 不用于延续代码行。不同的是,Julia 中不完整的表达式会自动延续到下一行。\n在 Julia 和 MATLAB 中,变量 ans 被设置为交互式会话中提交的最后一个表达式的值。在 Julia 中与 MATLAB 不同的是,当 Julia 代码以非交互式模式运行时并不会设置 ans。\nJulia 的 struct 不支持在运行时动态地添加字段,这与 MATLAB 的 class 不同。 如需支持,请使用 Dict。Julia 中的字典不是有序的。\n在 Julia 中,每个模块有自身的全局作用域/命名空间,而在 MATLAB 中只有一个全局作用域。\n在 MATLAB 中,删除不需要的值的惯用方法是使用逻辑索引,如表达式 x(x>3) 或语句 x(x>3) = [] 来 in-place 修改 x。相比之下,Julia 提供了更高阶的函数 filter 和 filter!,允许用户编写 filter(z->z>3, x) 和 filter!(z->z>3, x) 来代替相应直译 x[x.>3] 和 x = x[x.>3]。使用 filter! 可以减少临时数组的使用。\n类似于提取(或「解引用」)元胞数组的所有元素的操作,例如 MATLAB 中的 vertcat(A{:}),在 Julia 中是使用 splat 运算符编写的,例如 vcat(A...)。\n在 Julia 中,adjoint 函数执行共轭转置;在 MATLAB 中,adjoint 提供了经典伴随,它是余子式的转置。\n在 Julia 中,a^b^c 被认为是 a^(b^c) 而在 MATLAB 中它是 (a^b)^c。","category":"page"},{"location":"manual/noteworthy-differences/#Noteworthy-differences-from-R","page":"与其他语言的显著差异","title":"与 R 的显著差异","text":"","category":"section"},{"location":"manual/noteworthy-differences/","page":"与其他语言的显著差异","title":"与其他语言的显著差异","text":"Julia 的目标之一是为数据分析和统计编程提供高效的语言。对于从 R 转到 Julia 的用户来说,这是一些显著差异:","category":"page"},{"location":"manual/noteworthy-differences/","page":"与其他语言的显著差异","title":"与其他语言的显著差异","text":"Julia 的单引号封闭字符,而不是字符串。\nJulia 可以通过索引字符串来创建子字符串。在 R 中,在创建子字符串之前必须将字符串转换为字符向量。\n在 Julia 中,与 Python 相同但与 R 不同的是,字符串可由三重引号 \"\"\" ... \"\"\" 创建。此语法对于构造包含换行符的字符串很方便。\n在 Julia 中,可变参数使用 splat 运算符 ... 指定,该运算符总是跟在具体变量的名称后面,与 R 的不同,R 的 ... 可以单独出现。\n在 Julia 中,模数是 mod(a, b),而不是 a %% b。Julia 中的 % 是余数运算符。\n在 Julia 中,并非所有数据结构都支持逻辑索引。此外,Julia 中的逻辑索引只支持长度等于被索引对象的向量。例如:\n在 R 中,c(1, 2, 3, 4)[c(TRUE, FALSE)] 等价于 c(1, 3)。\n在 R 中,c(1, 2, 3, 4)[c(TRUE, FALSE, TRUE, FALSE)] 等价于 c(1, 3)。\n在 Julia 中,[1, 2, 3, 4][[true, false]] 抛出 BoundsError。\n在 Julia 中,[1, 2, 3, 4][[true, false, true, false]] 产生 [1, 3]。\n与许多语言一样,Julia 并不总是允许对不同长度的向量进行操作,与 R 不同,R 中的向量只需要共享一个公共的索引范围。例如,c(1, 2, 3, 4) + c(1, 2) 是有效的 R,但等价的 [1, 2, 3, 4] + [1, 2] 在 Julia 中会抛出一个错误。\n在逗号不改变代码含义时,Julia 允许使用可选的尾随括号。在索引数组时,这可能在 R 用户间造成混淆。例如,R 中的 x[1,] 将返回矩阵的第一行;但是,在 Julia 中,引号被忽略,于是 x[1,] == x[1],并且将返回第一个元素。要提取一行,请务必使用 :,如 x[1,:]。\nJulia 的 map 首先接受函数,然后是该函数的参数,这与 R 中的 lapply(, function, ...) 不同。类似地,R 中的 apply(X, MARGIN, FUN, ...) 等价于 Julia 的 mapslices,其中函数是第一个参数。\nR 中的多变量 apply,如 mapply(choose, 11:13, 1:3),在 Julia 中可以编写成 broadcast(binomial, 11:13, 1:3)。等价地,Julia 提供了更短的点语法来向量化函数 binomial.(11:13, 1:3)。\nJulia 使用 end 来表示条件块(如 if)、循环块(如 while/for)和函数的结束。为了代替单行 if ( cond ) statement,Julia 允许形式为 if cond; statement; end、cond && statement 和 !cond || statement 的语句。后两种语法中的赋值语句必须显式地包含在括号中,例如 cond && (x = value),这是因为运算符的优先级。\n在 Julia 中,<-, <<- 和 -> 不是赋值运算符。\nJulia 的 -> 创建一个匿名函数。\nJulia 使用括号构造向量。Julia 的 [1, 2, 3] 等价于 R 的 c(1, 2, 3)。\nJulia 的 * 运算符可以执行矩阵乘法,这与 R 不同。如果 A 和 B 都是矩阵,那么 A * B 在 Julia 中表示矩阵乘法,等价于 R 的 A %*% B。在 R 中,相同的符号将执行逐元素(Hadamard)乘积。要在 Julia 中使用逐元素乘法运算,你需要编写 A .* B。\nJulia 使用 transpose 函数来执行矩阵转置,使用 ' 运算符或 adjoint 函数来执行共轭转置。因此,Julia 的 transpose(A) 等价于 R 的 t(A)。另外,Julia 中的非递归转置由 permutedims 函数提供。\nJulia 在编写 if 语句或 for/while 循环时不需要括号:请使用 for i in [1, 2, 3] 代替 for (int i=1; i <= 3; i++),以及 if i == 1 代替 if (i == 1)\nJulia 不把数字 0 和 1 视为布尔值。在 Julia 中不能编写 if (1),因为 if 语句只接受布尔值。相反,可以编写 if true、if Bool(1) 或 if 1==1。\nJulia 不提供 nrow 和 ncol。相反,请使用 size(M, 1) 代替 nrow(M) 以及 size(M, 2) 代替 ncol(M)\nJulia 仔细区分了标量、向量和矩阵。在 R 中,1 和 c(1) 是相同的。在 Julia 中,它们不能互换地使用。\nJulia 的 diag 和 diagm 与 R 的不同。\nJulia 赋值操作的左侧不能为函数调用的结果:你不能编写 diag(M) = fill(1, n)。\nJulia 不鼓励使用函数填充主命名空间。Julia 的大多数统计功能都可在 JuliaStats 组织的包中找到。例如:\n与概率分布相关的函数由 Distributions 包提供。\nDataFrames 包提供数据帧。\n广义线性模型由 GLM 包提供。\nJulia 提供了元组和真正的哈希表,但不提供 R 风格的列表。在返回多个项时,通常应使用元组或具名元组:请使用 (1, 2) 或 (a=1, b=2) 代替 list(a = 1, b = 2)。\nJulia 鼓励用户编写自己的类型,它比 R 中的 S3 或 S4 对象更容易使用。Julia 的多重派发系统意味着 table(x::TypeA) 和 table(x::TypeB) 类似于 R 的 table.TypeA(x) 和 table.TypeB(x)。\nJulia 的值在向函数传递时不发生复制。如果某个函数修改了数组,这一修改对调用者是可见的。这与 R 非常不同,允许新函数更高效地操作大型数据结构。\n在 Julia 中,向量和矩阵使用 hcat、vcat 和 hvcat 拼接,而不是像在 R 中那样使用 c、rbind 和 cbind。\n在 Julia 中,像 a:b 这样的 range 不是 R 中的向量简写,而是一个专门的 AbstractRange 对象,该对象用于没有高内存开销地进行迭代。要将 range 转换为 vector,请使用 collect(a:b)。\nJulia 的 max 和 min 分别等价于 R 中的 pmax 和 pmin,但两者的参数都需要具有相同的维度。虽然 maximum 和 minimum 代替了 R 中的 max 和 min,但它们之间有重大区别。\nJulia 的 sum、prod、maximum 和 minimum 与它们在 R 中的对应物不同。它们都接受一个可选的关键字参数 dims,它表示执行操作的维度。例如,在 Julia 中令 A = [1 2; 3 4],在 R 中令 B <- rbind(c(1,2),c(3,4)) 是与之相同的矩阵。然后 sum(A) 得到与 sum(B) 相同的结果,但 sum(A, dims=1) 是一个包含每一列总和的行向量,sum(A, dims=2) 是一个包含每一行总和的列向量。这与 R 的行为形成了对比,在 R 中,单独的 colSums(B) 和 rowSums(B) 提供了这些功能。如果 dims 关键字参数是向量,则它指定执行求和的所有维度,并同时保持待求和数组的维数,例如 sum(A, dims=(1,2)) == hcat(10)。应该注意的是,没有针对第二个参数的错误检查。\nJulia 具有一些可以改变其参数的函数。例如,它具有 sort 和 sort!。\n在 R 中,高性能需要向量化。在 Julia 中,这几乎恰恰相反:性能最高的代码通常通过去向量化的循环来实现。\nJulia 是立即求值的,不支持 R 风格的惰性求值。对于大多数用户来说,这意味着很少有未引用的表达式或列名。\nJulia 不支持 NULL 类型。最接近的等价物是 nothing,但它的行为类似于标量值而不是列表。请使用 x === nothing 代替 is.null(x)。\n在 Julia 中,缺失值由 missing 表示,而不是由 NA 表示。请使用 ismissing(x)(或者在向量上使用逐元素操作 ismissing.(x))代替 isna(x)。通常使用 skipmissing 代替 na.rm=TRUE(尽管在某些特定情况下函数接受 skipmissing 参数)。\nJulia 缺少 R 中的 assign 或 get 的等价物。\n在 Julia 中,return 不需要括号。\n在 R 中,删除不需要的值的惯用方法是使用逻辑索引,如表达式 x[x>3] 或语句 x = x[x>3] 来 in-place 修改 x。相比之下,Julia 提供了更高阶的函数 filter 和 filter!,允许用户编写 filter(z->z>3, x) 和 filter!(z->z>3, x) 来代替相应直译 x[x.>3] 和 x = x[x.>3]。使用 filter! 可以减少临时数组的使用。","category":"page"},{"location":"manual/noteworthy-differences/#Noteworthy-differences-from-Python","page":"与其他语言的显著差异","title":"与 Python 的显著差异","text":"","category":"section"},{"location":"manual/noteworthy-differences/","page":"与其他语言的显著差异","title":"与其他语言的显著差异","text":"Julia 的 for, if, while 等语句块都以 end 关键字结束。代码的缩进不像在 Python 中那样重要。Julia 也没有 pass 关键字。 \nJulia 中的字符串使用双引号构造,如 \"text\",也可以使用三引号构造多行字符串。而在 Python 中可以使用单引号('text')或者双引号(\"text\")。单引号在 Julia 中用来表示单个字符,例如 'c'。\n在 Julia 中字符串的拼接使用 *,而不是像 Python 一样使用 +。类似的,字符串重复多次 Julia 使用 ^ 而不是 *。Julia 也不支持隐式的字符串拼接,例如 Python 中的 'ab' 'cd' == 'abcd'。\nPython 列表——灵活但缓慢——对应于 Julia 的 Vector{Any} 类型或更一般的 Vector{T},其中 T 是一些非具体元素类型。 “快”的数组,如 NumPy 数组,它们就地存储元素(即,dtype 是 np.float64、[('f1', np.uint64), ('f2', np.int32)], 等)可以用 Array{T} 表示,其中 T 是一个具体的、不可变的元素类型。 这包括内置类型,如 Float64、Int32、Int64,也包括更复杂的类型,如 Tuple{UInt64,Float64} 和许多用户定义的类型。\n在 Julia 中,数组、字符串等的索引从 1 开始,而不是从 0 开始。\nJulia 里的切片包含最后一个元素。Julia 里的 a[2:3] 等同于 Python 中的 a[1:3]。\nJulia 不支持负数索引。特别地,列表或数组的最后一个元素在 Julia 中使用 end 索引,而不像在 Python 中使用 -1。\nJulia 的索引必须写全。Python 中的 x[1:] 等价于 Julia 中的 x[2:end]。\nJulia 的范围语法为 x[start:step:stop],而 Python 的格式为 x[start:(stop+1):step]。","category":"page"},{"location":"manual/noteworthy-differences/","page":"与其他语言的显著差异","title":"与其他语言的显著差异","text":"因此 Python 中的 x[0:10:2] 等价于 Julia 里的 x[1:2:10]。类似的 Python 中的反转数组 x[::-1] 等价于 Julia 中的 x[end:-1:1]。","category":"page"},{"location":"manual/noteworthy-differences/","page":"与其他语言的显著差异","title":"与其他语言的显著差异","text":"在 Julia 中队一个矩阵取索引 X[[1,2], [1,3]] 返回一个子矩阵,它包含了第一和第二行与第一和第三列的交集。","category":"page"},{"location":"manual/noteworthy-differences/","page":"与其他语言的显著差异","title":"与其他语言的显著差异","text":"在 Python 中 X[[1,2], [1,3]] 返回一个向量,它包含索引 [1,1] 和 [2,3] 的值。Julia 中的 X[[1,2], [1,3]] 等价于 Python 中的 X[np.ix_([0,1],[0,2])]。Python 中的 X[[1,2], [1,3]] 等价于 Julia 中的 X[[CartesianIndex(1,1), CartesianIndex(2,3)]]。","category":"page"},{"location":"manual/noteworthy-differences/","page":"与其他语言的显著差异","title":"与其他语言的显著差异","text":"Julia 没有用来续行的语法:如果在行的末尾,到目前为止的输入是一个完整的表达式,则认为其已经结束;否则,认为输入继续。强制表达式继续的一种方式是将其包含在括号中。\n默认情况下,Julia 数组是列优先(Fortran 排序),而 NumPy 数组是行优先(C 排序)。为了在循环数组时获得最佳性能,Julia 中的循环顺序应相对于 NumPy 颠倒(请参阅性能提示的相关部分)。\nJulia 的更新运算符(例如 +=,-=,···)是非原位操作(not in-place),而 Numpy 的是。这意味着 A = [1, 1]; B = A; B += [3, 3] 不会改变 A 中的值,而将名称 B 重新绑定到右侧表达式 B = B + 3 的结果,这是一个新的数组。对于 in-place 操作,使用 B .+= 3(另请参阅 dot operators)、显式的循环或者 InplaceOps.jl。\nJulia 的函数在调用时,每次都对默认参数重新求值,不像 Python 只在函数定义时对默认参数求一次值。","category":"page"},{"location":"manual/noteworthy-differences/","page":"与其他语言的显著差异","title":"与其他语言的显著差异","text":"举例来说:Julia 的函数 f(x=rand()) = x 在无参数调用时(f()),每次都会返回不同的随机数。 另一方面,函数 g(x=[1,2]) = push!(x,3) 无参数调用时 g(),永远返回 [1,2,3]。","category":"page"},{"location":"manual/noteworthy-differences/","page":"与其他语言的显著差异","title":"与其他语言的显著差异","text":"在 Julia 中,必须使用关键字来传递关键字参数,这与 Python 中通常可以按位置传递它们不同。尝试按位置传递关键字参数会改变方法签名,从而导致 MethodError 或调用错误的方法。\n在 Julia 中,% 是余数运算符,而在 Python 中是模运算符。","category":"page"},{"location":"manual/noteworthy-differences/","page":"与其他语言的显著差异","title":"与其他语言的显著差异","text":"(译注:二者在参数有负数时有区别)","category":"page"},{"location":"manual/noteworthy-differences/","page":"与其他语言的显著差异","title":"与其他语言的显著差异","text":"在 Julia 中,常用的整数类型 Int 对应机器的整数类型,Int32 或 Int64。不像 Python 中的整数 int 是任意精度的。这意味着 Julia 中默认的整数类型会溢出,因此 2^64 == 0。如果你要表示一个大数,请选择一个合适的类型。如:Int128、任意精度的 BigInt 或者浮点类型 Flost64。\nJulia 中虚数单位 sqrt(-1) 是 im,而不是 Python 中的 j。\nJulia 中指数是 ^,而不是 Python 中的 **。\nJulia 使用 Nothing 类型的实例 nothing 代表空值(null),而不是 Python 中 NoneType 类的 None。\n在 Julia 中,标准的运算符作用在矩阵上就得到矩阵操作,不像 Python 标准运算符默认是逐元素操作。当 A 和 B 都是矩阵时,A * B 在 Julia 中代表着矩阵乘法,而不是 Python 中的逐元素相乘。即:Julia 中的 A * B 等同于 Python 的 A @ B;Python 中的 A * B 等同于 Julia 中的 A .* B。\nJulia 中的伴随操作符 ' 返回向量的转置(一种行向量的懒惰表示法)。Python 中对向量执行 .T 返回它本身(没有效果)。\n在Julia中,一个函数可能包含多个具体实现(称为方法),与Python中的函数相比,这些实现是根据调用的所有参数的类型通过多重派发选择的,它只有一个实现,没有多态性(与Python方法调用相反,Python方法调用使用不同的语法,并允许在方法的接收者上进行派发)。\nJulia 没有类(class),取而代替的是结构体(structures),可以是可变的或不可变的,它们只包含数据而不包含方法。","category":"page"},{"location":"manual/noteworthy-differences/","page":"与其他语言的显著差异","title":"与其他语言的显著差异","text":"在 Python 中调用类实例的方法 (x = MyClass(*args); x.f(y)) 对应于 Julia 中的函数调用,例如 x = MyType(args...); f(x, y)。 总的来说,多重派发比 Python 类系统更灵活和强大。\nJulia 的结构体有且只能有一个抽象超类型(abstract supertype),而 Python 的类可以纪成一个或多个、抽象或具体的超类(superclasses)。\n逻辑 Julia 程序结构(包和模块)独立于文件结构(include 用于附加文件),而 Python 代码结构由目录(包)和文件(模块)定义。\nJulia 中的三元运算符 x > 0 ? 1 : -1 对应于 Python 中的条件表达式 1 if x > 0 else -1。\nJulia 中以 @ 开头的符号是宏(macro),而 Python 中是装饰器(decorator)。\nJulia 的异常处理使用 try — catch — finally,而不是 Python 的 try — except — finally。与 Python 不同的是,因为性能的原因,Julia 不推荐在正常流程中使用异常处理。\nJulia 的循环很快,所以没必要手动向量化(vectorized)。\n小心 Julia 中的非常量全局变量,尤其它出现在循环中时。因为你在 Julia 中可以写出贴近硬件的代码,这时使用全局变量的影响非常大(参见性能建议)\nPython 中大多数的值都能用在逻辑运算中。例如:if \"a\" 永真,if \"\" 恒假。在 Julia 中你只能使用布尔类型的值,或者显示的将其他值转为布尔类型,否则就会抛出异常。例如当你想测试字符串是否为空是,请使用 if !isempty(\"\")。\n在 Julia 中大多数代码块都会引入新的本地作用域(local scope)。例如:循环和异常处理的 try — catch — finally。注意:列表推断(comprehensions)与生成器在 Julia 和 Python 中都会引入新的作用域;而 if 分支则都不会引入。","category":"page"},{"location":"manual/noteworthy-differences/#Noteworthy-differences-from-C/C","page":"与其他语言的显著差异","title":"与 C/C++ 的显著差异","text":"","category":"section"},{"location":"manual/noteworthy-differences/","page":"与其他语言的显著差异","title":"与其他语言的显著差异","text":"Julia 的数组由方括号索引,方括号中可以包含不止一个维度 A[i,j]。这样的语法不仅仅是像 C/C++ 中那样对指针或者地址引用的语法糖,参见关于数组构造的语法的 Julia 文档。\n在 Julia 中,数组、字符串等的索引从 1 开始,而不是从 0 开始。\nJulia 的数组在赋值给另一个变量时不发生复制。执行 A = B 后,改变 B 中元素也会修改 A。像 += 这样的更新运算符不会以 in-place 的方式执行,而是相当于 A = A + B,将左侧绑定到右侧表达式的计算结果上。\nJulia 的数组是列优先的(Fortran 顺序),而 C/C++ 的数组默认是行优先的。要使数组上的循环性能最优,在 Julia 中循环的顺序应该与 C/C++ 相反(参见 性能建议)。\nJulia 的值在赋值或向函数传递时不发生复制。如果某个函数修改了数组,这一修改对调用者是可见的。\n在 Julia 中,空格是有意义的,这与 C/C++ 不同,所以向 Julia 程序中添加或删除空格时必须谨慎。\n在 Julia 中,没有小数点的数值字面量(如 42)生成有符号整数,类型为 Int,但如果字面量太长,超过了机器字长,则会被自动提升为容量更大的类型,例如 Int64(如果 Int 是 Int32)、Int128,或者任意精度的 BigInt 类型。不存在诸如 L, LL, U, UL, ULL 这样的数值字面量后缀指示无符号和/或有符号与无符号。十进制字面量始终是有符号的,十六进制字面量(像 C/C++ 一样由 0x 开头)是无符号的。另外,十六进制字面量与 C/C++/Java 不同,也与 Julia 中的十进制字面量不同,它们的类型取决于字面量的长度,包括开头的 0。例如,0x0 和 0x00 的类型是 UInt8,0x000 和 0x0000 的类型是 UInt16。同理,字面量的长度在 5-8 之间,类型为 UInt32;在 9-16 之间,类型为 UInt64;在 17-32 之间,类型为 UInt128。当定义十六进制掩码时,就需要将这一问题考虑在内,比如 ~0xf == 0xf0 与 ~0x000f == 0xfff0 完全不同。64 位 Float64 和 32 位 Float32 的字面量分别表示为 1.0 和 1.0f0。浮点字面量在无法被精确表示时舍入(且不会提升为 BigFloat 类型)。浮点字面量在行为上与 C/C++ 更接近。八进制(前缀为 0o)和二进制(前缀为 0b)也被视为无符号的。\n在 Julia 中,当两个操作数都是整数类型时,除法运算符 / 返回一个浮点数。 要执行整数除法,请使用 div 或 ÷。\n使用浮点类型索引数组在 Julia 中通常是错误的。 C 表达式 a[i / 2] 的 Julia 等价写法是 a[i ÷ 2 + 1],其中 i 是整数类型。\n字符串字面量可用 \" 或 \"\"\" 分隔,用 \"\"\" 分隔的字面量可以包含 \" 字符而无需像 \"\\\"\" 这样来引用它。字符串字面量可以包含插入其中的其他变量或表达式,由 $variablename 或 $(expression) 表示,它在该函数所处的上下文中计算变量名或表达式。\n// 表示 Rational 数,而非单行注释(其在 Julia 中是 #)\n#= 表示多行注释的开头,=# 结束之。\nJulia 中的函数返回其最后一个表达式或 return 关键字的值。可以从函数中返回多个值并将其作为元组赋值,如 (a, b) = myfunction() 或 a, b = myfunction(),而不必像在 C/C++ 中那样必须传递指向值的指针(即 a = myfunction(&b))。\nJulia 不要求使用分号来结束语句。表达式的结果不会自动打印(除了在交互式提示符中,即 REPL),且代码行不需要以分号结尾。println 或 @printf 可用于打印特定输出。在 REPL 中,; 可用于抑制输出。; 在 [ ] 中也有不同的含义,需要注意。; 可用于在单行中分隔表达式,但在许多情况下不是绝对必要的,更经常是为了可读性。\n在 Julia 中,运算符 ⊻(xor)执行按位 XOR 操作,即 C/C++ 中的 ^。此外,按位运算符不具有与 C/C++ 相同的优先级,所以可能需要括号。\nJulia 的 ^ 是取幂(pow),而非 C/C++ 中的按位 XOR(在 Julia 中请使用 ⊻ 或 xor)\nJulia 有两个右移运算符,>> 和 >>>。 >> 执行算术移位,>>> 始终执行逻辑移位,这与 C/C++ 不同,其中 >> 的含义取决于被移位的值的类型。\nJulia 的 -> 创建一个匿名函数,它并不通过指针访问成员。\nJulia 在编写 if 语句或 for/while 循环时不需要括号:请使用 for i in [1, 2, 3] 代替 for (int i=1; i <= 3; i++),以及 if i == 1 代替 if (i == 1)\nJulia 不把数字 0 和 1 视为布尔值。在 Julia 中不能编写 if (1),因为 if 语句只接受布尔值。相反,可以编写 if true、if Bool(1) 或 if 1==1。\nJulia 使用 end 来表示条件块(如 if)、循环块(如 while/for)和函数的结束。为了代替单行 if ( cond ) statement,Julia 允许形式为 if cond; statement; end、cond && statement 和 !cond || statement 的语句。后两种语法中的赋值语句必须显式地包含在括号中,例如 cond && (x = value),这是因为运算符的优先级。\nJulia 没有用来续行的语法:如果在行的末尾,到目前为止的输入是一个完整的表达式,则认为其已经结束;否则,认为输入继续。强制表达式继续的一种方式是将其包含在括号中。\nJulia 宏对已解析的表达式进行操作,而非程序的文本,这允许它们执行复杂的 Julia 代码转换。宏名称以 @ 字符开头,具有类似函数的语法 @mymacro(arg1, arg2, arg3) 和类似语句的语法 @mymacro arg1 arg2 arg3。两种形式的语法可以相互转换;如果宏出现在另一个表达式中,则类似函数的形式尤其有用,并且它通常是最清晰的。类似语句的形式通常用于标注块,如在分布式 for 结构中:@distributed for i in 1:n; #= body =#; end。如果宏结构的结尾不那么清晰,请使用类似函数的形式。\nJulia 有一个枚举类型,使用宏 @enum(name, value1, value2, ...) 来表示,例如:@enum(Fruit, banana=1, apple, pear)。\n按照惯例,修改其参数的函数在名称的末尾有个 !,例如 push!。\n在 C++ 中,默认情况下,你具有静态分派,即为了支持动态派发,你需要将函数标注为 virtual 函数。另一方面,Julia 中的每个方法都是「virtual」(尽管它更通用,因为方法是在每个参数类型上派发的,而不仅仅是 this,并且使用的是最具体的声明规则)。","category":"page"},{"location":"manual/noteworthy-differences/#Noteworthy-differences-from-Common-Lisp","page":"与其他语言的显著差异","title":"与 Common Lisp 的显著差异","text":"","category":"section"},{"location":"manual/noteworthy-differences/","page":"与其他语言的显著差异","title":"与其他语言的显著差异","text":"Julia 默认使用 1 开始的数组索引,它也能处理任意的索引顺序。\n函数和变量共用一个命名空间(\"Lisp-1\")。\nJulia 中有 Pair 类型,但这并不意味着它能用作 COMMON-LISP:CONS。在 Julia 中绝大多数可迭代的集合都能互换使用,例如:集合解包(splatting)、元组等。Tuple 最接近 Common Lisp 中用于异构元素的短列表。使用 NamedTuple 来代替关联表(alists)。对于更大的、同类型元素的集合,应该使用 Array 和 Dict。\n典型的使用 Julia 进行原型开发时,也会对镜像进行连续的修改,Revise.jl 包提供了这个功能。\n对于性能,Julia 更喜欢操作具有 类型稳定性。 Common Lisp 从底层机器操作中抽象出来,而 Julia 则更接近它们。 例如:\n使用 / 的整数除法总是返回浮点结果,即使计算是精确的。\n// 总是返回一个有理数结果\n÷ 总是返回一个(被截断的)整数结果\nJulia 支持大整数,但不会自动转换。默认的整数类型会溢出。\n支持复数,但要获得复数结果,你需要复数输入。\n有多种 Complex 和 Rational 类型,具有不同的组成类型。\n模块(名称空间)可以是分层的。import 和 using 有着双重角色:他们加载代码并让代码在命名空间中可用。import 用于仅有模块名是可用的情况,大致等价于 ASDF:LOAD-OP。槽名(Slot name)不需要单独导出。全局变量不能从模块的外部赋值,除了 eval(mod, :(var = val)) 这个例外情况。\n宏以 @ 开头,并没有像 Common Lisp 那样无缝地集成到语言中;因此在 Julia 中,宏的使用不像在 Common Lisp 中那样广泛。Julia 支持宏的一种卫生(hygiene)形式。因为不同的表层语法,Julia 中没有 COMMON-LISP:&BODY 的等价形式。\n所有的函数都是通用的并且使用多重分派。函数的参数列表也无需遵循一样的模板,这让我们有了一个强大的范式:do。可选参数与关键字参数的处理方式不同。方法的歧义没有像在 Common Lisp 对象系统中那样得到解决,因此需要为交集定义更具体的方法。\n符号不属于任何包,它本身也不包含任何值。M.var 会对 M 模块里的  var 符号求值。\nJulia 完全支持函数式编程风格,包括闭包等特性。但这并不是 Julia 的惯用风格。修改捕获变量时需要一些额外的变通以便提高性能。","category":"page"},{"location":"stdlib/LibGit2/#LibGit2","page":"LibGit2","title":"LibGit2","text":"","category":"section"},{"location":"stdlib/LibGit2/","page":"LibGit2","title":"LibGit2","text":"The LibGit2 module provides bindings to libgit2, a portable C library that implements core functionality for the Git version control system. These bindings are currently used to power Julia's package manager. It is expected that this module will eventually be moved into a separate package.","category":"page"},{"location":"stdlib/LibGit2/#Functionality","page":"LibGit2","title":"Functionality","text":"","category":"section"},{"location":"stdlib/LibGit2/","page":"LibGit2","title":"LibGit2","text":"Some of this documentation assumes some prior knowledge of the libgit2 API. For more information on some of the objects and methods referenced here, consult the upstream libgit2 API reference.","category":"page"},{"location":"stdlib/LibGit2/","page":"LibGit2","title":"LibGit2","text":"LibGit2.Buffer\nLibGit2.CheckoutOptions\nLibGit2.CloneOptions\nLibGit2.DescribeOptions\nLibGit2.DescribeFormatOptions\nLibGit2.DiffDelta\nLibGit2.DiffFile\nLibGit2.DiffOptionsStruct\nLibGit2.FetchHead\nLibGit2.FetchOptions\nLibGit2.GitAnnotated\nLibGit2.GitBlame\nLibGit2.GitBlob\nLibGit2.GitCommit\nLibGit2.GitHash\nLibGit2.GitObject\nLibGit2.GitRemote\nLibGit2.GitRemoteAnon\nLibGit2.GitRepo\nLibGit2.GitRepoExt\nLibGit2.GitRevWalker\nLibGit2.GitShortHash\nLibGit2.GitSignature\nLibGit2.GitStatus\nLibGit2.GitTag\nLibGit2.GitTree\nLibGit2.IndexEntry\nLibGit2.IndexTime\nLibGit2.BlameOptions\nLibGit2.MergeOptions\nLibGit2.ProxyOptions\nLibGit2.PushOptions\nLibGit2.RebaseOperation\nLibGit2.RebaseOptions\nLibGit2.RemoteCallbacks\nLibGit2.SignatureStruct\nLibGit2.StatusEntry\nLibGit2.StatusOptions\nLibGit2.StrArrayStruct\nLibGit2.TimeStruct\nLibGit2.add!\nLibGit2.add_fetch!\nLibGit2.add_push!\nLibGit2.addblob!\nLibGit2.author\nLibGit2.authors\nLibGit2.branch\nLibGit2.branch!\nLibGit2.checkout!\nLibGit2.clone\nLibGit2.commit\nLibGit2.committer\nLibGit2.count\nLibGit2.counthunks\nLibGit2.create_branch\nLibGit2.credentials_callback\nLibGit2.credentials_cb\nLibGit2.default_signature\nLibGit2.delete_branch\nLibGit2.diff_files\nLibGit2.entryid\nLibGit2.entrytype\nLibGit2.fetch\nLibGit2.fetchheads\nLibGit2.fetch_refspecs\nLibGit2.fetchhead_foreach_cb\nLibGit2.merge_base\nLibGit2.merge!(::LibGit2.GitRepo; ::Any...)\nLibGit2.merge!(::LibGit2.GitRepo, ::Vector{LibGit2.GitAnnotated}; ::LibGit2.MergeOptions, ::LibGit2.CheckoutOptions)\nLibGit2.merge!(::LibGit2.GitRepo, ::Vector{LibGit2.GitAnnotated}, ::Bool; ::LibGit2.MergeOptions, ::LibGit2.CheckoutOptions)\nLibGit2.ffmerge!\nLibGit2.fullname\nLibGit2.features\nLibGit2.filename\nLibGit2.filemode\nLibGit2.gitdir\nLibGit2.git_url\nLibGit2.@githash_str\nLibGit2.head\nLibGit2.head!\nLibGit2.head_oid\nLibGit2.headname\nLibGit2.init\nLibGit2.is_ancestor_of\nLibGit2.isbinary\nLibGit2.iscommit\nLibGit2.isdiff\nLibGit2.isdirty\nLibGit2.isorphan\nLibGit2.isset\nLibGit2.iszero\nLibGit2.lookup_branch\nLibGit2.map\nLibGit2.mirror_callback\nLibGit2.mirror_cb\nLibGit2.message\nLibGit2.merge_analysis\nLibGit2.name\nLibGit2.need_update\nLibGit2.objtype\nLibGit2.path\nLibGit2.peel\nLibGit2.posixpath\nLibGit2.push\nLibGit2.push!(::LibGit2.GitRevWalker, ::LibGit2.GitHash)\nLibGit2.push_head!\nLibGit2.push_refspecs\nLibGit2.raw\nLibGit2.read_tree!\nLibGit2.rebase!\nLibGit2.ref_list\nLibGit2.reftype\nLibGit2.remotes\nLibGit2.remove!\nLibGit2.reset\nLibGit2.reset!\nLibGit2.restore\nLibGit2.revcount\nLibGit2.set_remote_url\nLibGit2.shortname\nLibGit2.snapshot\nLibGit2.split_cfg_entry\nLibGit2.status\nLibGit2.stage\nLibGit2.tag_create\nLibGit2.tag_delete\nLibGit2.tag_list\nLibGit2.target\nLibGit2.toggle\nLibGit2.transact\nLibGit2.treewalk\nLibGit2.upstream\nLibGit2.update!\nLibGit2.url\nLibGit2.version\nLibGit2.with\nLibGit2.with_warn\nLibGit2.workdir\nLibGit2.GitObject(::LibGit2.GitTreeEntry)\nLibGit2.UserPasswordCredential\nLibGit2.SSHCredential\nLibGit2.isfilled\nLibGit2.CachedCredentials\nLibGit2.CredentialPayload\nLibGit2.approve\nLibGit2.reject","category":"page"},{"location":"stdlib/LibGit2/#LibGit2.Buffer","page":"LibGit2","title":"LibGit2.Buffer","text":"LibGit2.Buffer\n\nA data buffer for exporting data from libgit2. Matches the git_buf struct.\n\nWhen fetching data from LibGit2, a typical usage would look like:\n\nbuf_ref = Ref(Buffer())\n@check ccall(..., (Ptr{Buffer},), buf_ref)\n# operation on buf_ref\nfree(buf_ref)\n\nIn particular, note that LibGit2.free should be called afterward on the Ref object.\n\n\n\n\n\n","category":"type"},{"location":"stdlib/LibGit2/#LibGit2.CheckoutOptions","page":"LibGit2","title":"LibGit2.CheckoutOptions","text":"LibGit2.CheckoutOptions\n\nMatches the git_checkout_options struct.\n\nThe fields represent:\n\nversion: version of the struct in use, in case this changes later. For now, always 1.\ncheckout_strategy: determine how to handle conflicts and whether to force the checkout/recreate missing files.\ndisable_filters: if nonzero, do not apply filters like CLRF (to convert file newlines between UNIX and DOS).\ndir_mode: read/write/access mode for any directories involved in the checkout. Default is 0755.\nfile_mode: read/write/access mode for any files involved in the checkout. Default is 0755 or 0644, depending on the blob.\nfile_open_flags: bitflags used to open any files during the checkout.\nnotify_flags: Flags for what sort of conflicts the user should be notified about.\nnotify_cb: An optional callback function to notify the user if a checkout conflict occurs. If this function returns a non-zero value, the checkout will be cancelled.\nnotify_payload: Payload for the notify callback function.\nprogress_cb: An optional callback function to display checkout progress.\nprogress_payload: Payload for the progress callback.\npaths: If not empty, describes which paths to search during the checkout. If empty, the checkout will occur over all files in the repository.\nbaseline: Expected content of the workdir, captured in a (pointer to a) GitTree. Defaults to the state of the tree at HEAD.\nbaseline_index: Expected content of the workdir, captured in a (pointer to a) GitIndex. Defaults to the state of the index at HEAD.\ntarget_directory: If not empty, checkout to this directory instead of the workdir.\nancestor_label: In case of conflicts, the name of the common ancestor side.\nour_label: In case of conflicts, the name of \"our\" side.\ntheir_label: In case of conflicts, the name of \"their\" side.\nperfdata_cb: An optional callback function to display performance data.\nperfdata_payload: Payload for the performance callback.\n\n\n\n\n\n","category":"type"},{"location":"stdlib/LibGit2/#LibGit2.CloneOptions","page":"LibGit2","title":"LibGit2.CloneOptions","text":"LibGit2.CloneOptions\n\nMatches the git_clone_options struct.\n\nThe fields represent:\n\nversion: version of the struct in use, in case this changes later. For now, always 1.\ncheckout_opts: The options for performing the checkout of the remote as part of the clone.\nfetch_opts: The options for performing the pre-checkout fetch of the remote as part of the clone.\nbare: If 0, clone the full remote repository. If non-zero, perform a bare clone, in which there is no local copy of the source files in the repository and the gitdir and workdir are the same.\nlocalclone: Flag whether to clone a local object database or do a fetch. The default is to let git decide. It will not use the git-aware transport for a local clone, but will use it for URLs which begin with file://.\ncheckout_branch: The name of the branch to checkout. If an empty string, the default branch of the remote will be checked out.\nrepository_cb: An optional callback which will be used to create the new repository into which the clone is made.\nrepository_cb_payload: The payload for the repository callback.\nremote_cb: An optional callback used to create the GitRemote before making the clone from it.\nremote_cb_payload: The payload for the remote callback.\n\n\n\n\n\n","category":"type"},{"location":"stdlib/LibGit2/#LibGit2.DescribeOptions","page":"LibGit2","title":"LibGit2.DescribeOptions","text":"LibGit2.DescribeOptions\n\nMatches the git_describe_options struct.\n\nThe fields represent:\n\nversion: version of the struct in use, in case this changes later. For now, always 1.\nmax_candidates_tags: consider this many most recent tags in refs/tags to describe a commit. Defaults to 10 (so that the 10 most recent tags would be examined to see if they describe a commit).\ndescribe_strategy: whether to consider all entries in refs/tags (equivalent to git-describe --tags) or all entries in refs/ (equivalent to git-describe --all). The default is to only show annotated tags. If Consts.DESCRIBE_TAGS is passed, all tags, annotated or not, will be considered. If Consts.DESCRIBE_ALL is passed, any ref in refs/ will be considered.\npattern: only consider tags which match pattern. Supports glob expansion.\nonly_follow_first_parent: when finding the distance from a matching reference to the described object, only consider the distance from the first parent.\nshow_commit_oid_as_fallback: if no matching reference can be found which describes a commit, show the commit's GitHash instead of throwing an error (the default behavior).\n\n\n\n\n\n","category":"type"},{"location":"stdlib/LibGit2/#LibGit2.DescribeFormatOptions","page":"LibGit2","title":"LibGit2.DescribeFormatOptions","text":"LibGit2.DescribeFormatOptions\n\nMatches the git_describe_format_options struct.\n\nThe fields represent:\n\nversion: version of the struct in use, in case this changes later. For now, always 1.\nabbreviated_size: lower bound on the size of the abbreviated GitHash to use, defaulting to 7.\nalways_use_long_format: set to 1 to use the long format for strings even if a short format can be used.\ndirty_suffix: if set, this will be appended to the end of the description string if the workdir is dirty.\n\n\n\n\n\n","category":"type"},{"location":"stdlib/LibGit2/#LibGit2.DiffDelta","page":"LibGit2","title":"LibGit2.DiffDelta","text":"LibGit2.DiffDelta\n\nDescription of changes to one entry. Matches the git_diff_delta struct.\n\nThe fields represent:\n\nstatus: One of Consts.DELTA_STATUS, indicating whether the file has been added/modified/deleted.\nflags: Flags for the delta and the objects on each side. Determines whether to treat the file(s) as binary/text, whether they exist on each side of the diff, and whether the object ids are known to be correct.\nsimilarity: Used to indicate if a file has been renamed or copied.\nnfiles: The number of files in the delta (for instance, if the delta was run on a submodule commit id, it may contain more than one file).\nold_file: A DiffFile containing information about the file(s) before the changes.\nnew_file: A DiffFile containing information about the file(s) after the changes.\n\n\n\n\n\n","category":"type"},{"location":"stdlib/LibGit2/#LibGit2.DiffFile","page":"LibGit2","title":"LibGit2.DiffFile","text":"LibGit2.DiffFile\n\nDescription of one side of a delta. Matches the git_diff_file struct.\n\nThe fields represent:\n\nid: the GitHash of the item in the diff. If the item is empty on this side of the diff (for instance, if the diff is of the removal of a file), this will be GitHash(0).\npath: a NULL terminated path to the item relative to the working directory of the repository.\nsize: the size of the item in bytes.\nflags: a combination of the git_diff_flag_t flags. The ith bit of this integer sets the ith flag.\nmode: the stat mode for the item.\nid_abbrev: only present in LibGit2 versions newer than or equal to 0.25.0. The length of the id field when converted using string. Usually equal to OID_HEXSZ (40).\n\n\n\n\n\n","category":"type"},{"location":"stdlib/LibGit2/#LibGit2.DiffOptionsStruct","page":"LibGit2","title":"LibGit2.DiffOptionsStruct","text":"LibGit2.DiffOptionsStruct\n\nMatches the git_diff_options struct.\n\nThe fields represent:\n\nversion: version of the struct in use, in case this changes later. For now, always 1.\nflags: flags controlling which files will appear in the diff. Defaults to DIFF_NORMAL.\nignore_submodules: whether to look at files in submodules or not. Defaults to SUBMODULE_IGNORE_UNSPECIFIED, which means the submodule's configuration will control whether it appears in the diff or not.\npathspec: path to files to include in the diff. Default is to use all files in the repository.\nnotify_cb: optional callback which will notify the user of changes to the diff as file deltas are added to it.\nprogress_cb: optional callback which will display diff progress. Only relevant on libgit2 versions at least as new as 0.24.0.\npayload: the payload to pass to notify_cb and progress_cb.\ncontext_lines: the number of unchanged lines used to define the edges of a hunk. This is also the number of lines which will be shown before/after a hunk to provide context. Default is 3.\ninterhunk_lines: the maximum number of unchanged lines between two separate hunks allowed before the hunks will be combined. Default is 0.\nid_abbrev: sets the length of the abbreviated GitHash to print. Default is 7.\nmax_size: the maximum file size of a blob. Above this size, it will be treated as a binary blob. The default is 512 MB.\nold_prefix: the virtual file directory in which to place old files on one side of the diff. Default is \"a\".\nnew_prefix: the virtual file directory in which to place new files on one side of the diff. Default is \"b\".\n\n\n\n\n\n","category":"type"},{"location":"stdlib/LibGit2/#LibGit2.FetchHead","page":"LibGit2","title":"LibGit2.FetchHead","text":"LibGit2.FetchHead\n\nContains the information about HEAD during a fetch, including the name and URL of the branch fetched from, the oid of the HEAD, and whether the fetched HEAD has been merged locally.\n\nThe fields represent:\n\nname: The name in the local reference database of the fetch head, for example, \"refs/heads/master\".\nurl: The URL of the fetch head.\noid: The GitHash of the tip of the fetch head.\nismerge: Boolean flag indicating whether the changes at the remote have been merged into the local copy yet or not. If true, the local copy is up to date with the remote fetch head.\n\n\n\n\n\n","category":"type"},{"location":"stdlib/LibGit2/#LibGit2.FetchOptions","page":"LibGit2","title":"LibGit2.FetchOptions","text":"LibGit2.FetchOptions\n\nMatches the git_fetch_options struct.\n\nThe fields represent:\n\nversion: version of the struct in use, in case this changes later. For now, always 1.\ncallbacks: remote callbacks to use during the fetch.\nprune: whether to perform a prune after the fetch or not. The default is to use the setting from the GitConfig.\nupdate_fetchhead: whether to update the FetchHead after the fetch. The default is to perform the update, which is the normal git behavior.\ndownload_tags: whether to download tags present at the remote or not. The default is to request the tags for objects which are being downloaded anyway from the server.\nproxy_opts: options for connecting to the remote through a proxy. See ProxyOptions. Only present on libgit2 versions newer than or equal to 0.25.0.\ncustom_headers: any extra headers needed for the fetch. Only present on libgit2 versions newer than or equal to 0.24.0.\n\n\n\n\n\n","category":"type"},{"location":"stdlib/LibGit2/#LibGit2.GitAnnotated","page":"LibGit2","title":"LibGit2.GitAnnotated","text":"GitAnnotated(repo::GitRepo, commit_id::GitHash)\nGitAnnotated(repo::GitRepo, ref::GitReference)\nGitAnnotated(repo::GitRepo, fh::FetchHead)\nGitAnnotated(repo::GitRepo, committish::AbstractString)\n\nAn annotated git commit carries with it information about how it was looked up and why, so that rebase or merge operations have more information about the context of the commit. Conflict files contain information about the source/target branches in the merge which are conflicting, for instance. An annotated commit can refer to the tip of a remote branch, for instance when a FetchHead is passed, or to a branch head described using GitReference.\n\n\n\n\n\n","category":"type"},{"location":"stdlib/LibGit2/#LibGit2.GitBlame","page":"LibGit2","title":"LibGit2.GitBlame","text":"GitBlame(repo::GitRepo, path::AbstractString; options::BlameOptions=BlameOptions())\n\nConstruct a GitBlame object for the file at path, using change information gleaned from the history of repo. The GitBlame object records who changed which chunks of the file when, and how. options controls how to separate the contents of the file and which commits to probe - see BlameOptions for more information.\n\n\n\n\n\n","category":"type"},{"location":"stdlib/LibGit2/#LibGit2.GitBlob","page":"LibGit2","title":"LibGit2.GitBlob","text":"GitBlob(repo::GitRepo, hash::AbstractGitHash)\nGitBlob(repo::GitRepo, spec::AbstractString)\n\nReturn a GitBlob object from repo specified by hash/spec.\n\nhash is a full (GitHash) or partial (GitShortHash) hash.\nspec is a textual specification: see the git docs for a full list.\n\n\n\n\n\n","category":"type"},{"location":"stdlib/LibGit2/#LibGit2.GitCommit","page":"LibGit2","title":"LibGit2.GitCommit","text":"GitCommit(repo::GitRepo, hash::AbstractGitHash)\nGitCommit(repo::GitRepo, spec::AbstractString)\n\nReturn a GitCommit object from repo specified by hash/spec.\n\nhash is a full (GitHash) or partial (GitShortHash) hash.\nspec is a textual specification: see the git docs for a full list.\n\n\n\n\n\n","category":"type"},{"location":"stdlib/LibGit2/#LibGit2.GitHash","page":"LibGit2","title":"LibGit2.GitHash","text":"GitHash\n\nA git object identifier, based on the sha-1 hash. It is a 20 byte string (40 hex digits) used to identify a GitObject in a repository.\n\n\n\n\n\n","category":"type"},{"location":"stdlib/LibGit2/#LibGit2.GitObject","page":"LibGit2","title":"LibGit2.GitObject","text":"GitObject(repo::GitRepo, hash::AbstractGitHash)\nGitObject(repo::GitRepo, spec::AbstractString)\n\nReturn the specified object (GitCommit, GitBlob, GitTree or GitTag) from repo specified by hash/spec.\n\nhash is a full (GitHash) or partial (GitShortHash) hash.\nspec is a textual specification: see the git docs for a full list.\n\n\n\n\n\n","category":"type"},{"location":"stdlib/LibGit2/#LibGit2.GitRemote","page":"LibGit2","title":"LibGit2.GitRemote","text":"GitRemote(repo::GitRepo, rmt_name::AbstractString, rmt_url::AbstractString) -> GitRemote\n\nLook up a remote git repository using its name and URL. Uses the default fetch refspec.\n\nExamples\n\nrepo = LibGit2.init(repo_path)\nremote = LibGit2.GitRemote(repo, \"upstream\", repo_url)\n\n\n\n\n\nGitRemote(repo::GitRepo, rmt_name::AbstractString, rmt_url::AbstractString, fetch_spec::AbstractString) -> GitRemote\n\nLook up a remote git repository using the repository's name and URL, as well as specifications for how to fetch from the remote (e.g. which remote branch to fetch from).\n\nExamples\n\nrepo = LibGit2.init(repo_path)\nrefspec = \"+refs/heads/mybranch:refs/remotes/origin/mybranch\"\nremote = LibGit2.GitRemote(repo, \"upstream\", repo_url, refspec)\n\n\n\n\n\n","category":"type"},{"location":"stdlib/LibGit2/#LibGit2.GitRemoteAnon","page":"LibGit2","title":"LibGit2.GitRemoteAnon","text":"GitRemoteAnon(repo::GitRepo, url::AbstractString) -> GitRemote\n\nLook up a remote git repository using only its URL, not its name.\n\nExamples\n\nrepo = LibGit2.init(repo_path)\nremote = LibGit2.GitRemoteAnon(repo, repo_url)\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LibGit2/#LibGit2.GitRepo","page":"LibGit2","title":"LibGit2.GitRepo","text":"LibGit2.GitRepo(path::AbstractString)\n\nOpen a git repository at path.\n\n\n\n\n\n","category":"type"},{"location":"stdlib/LibGit2/#LibGit2.GitRepoExt","page":"LibGit2","title":"LibGit2.GitRepoExt","text":"LibGit2.GitRepoExt(path::AbstractString, flags::Cuint = Cuint(Consts.REPOSITORY_OPEN_DEFAULT))\n\nOpen a git repository at path with extended controls (for instance, if the current user must be a member of a special access group to read path).\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LibGit2/#LibGit2.GitRevWalker","page":"LibGit2","title":"LibGit2.GitRevWalker","text":"GitRevWalker(repo::GitRepo)\n\nA GitRevWalker walks through the revisions (i.e. commits) of a git repository repo. It is a collection of the commits in the repository, and supports iteration and calls to LibGit2.map and LibGit2.count (for instance, LibGit2.count could be used to determine what percentage of commits in a repository were made by a certain author).\n\ncnt = LibGit2.with(LibGit2.GitRevWalker(repo)) do walker\n LibGit2.count((oid,repo)->(oid == commit_oid1), walker, oid=commit_oid1, by=LibGit2.Consts.SORT_TIME)\nend\n\nHere, LibGit2.count finds the number of commits along the walk with a certain GitHash. Since the GitHash is unique to a commit, cnt will be 1.\n\n\n\n\n\n","category":"type"},{"location":"stdlib/LibGit2/#LibGit2.GitShortHash","page":"LibGit2","title":"LibGit2.GitShortHash","text":"GitShortHash(hash::GitHash, len::Integer)\n\nA shortened git object identifier, which can be used to identify a git object when it is unique, consisting of the initial len hexadecimal digits of hash (the remaining digits are ignored).\n\n\n\n\n\n","category":"type"},{"location":"stdlib/LibGit2/#LibGit2.GitSignature","page":"LibGit2","title":"LibGit2.GitSignature","text":"LibGit2.GitSignature\n\nThis is a Julia wrapper around a pointer to a git_signature object.\n\n\n\n\n\n","category":"type"},{"location":"stdlib/LibGit2/#LibGit2.GitStatus","page":"LibGit2","title":"LibGit2.GitStatus","text":"LibGit2.GitStatus(repo::GitRepo; status_opts=StatusOptions())\n\nCollect information about the status of each file in the git repository repo (e.g. is the file modified, staged, etc.). status_opts can be used to set various options, for instance whether or not to look at untracked files or whether to include submodules or not. See StatusOptions for more information.\n\n\n\n\n\n","category":"type"},{"location":"stdlib/LibGit2/#LibGit2.GitTag","page":"LibGit2","title":"LibGit2.GitTag","text":"GitTag(repo::GitRepo, hash::AbstractGitHash)\nGitTag(repo::GitRepo, spec::AbstractString)\n\nReturn a GitTag object from repo specified by hash/spec.\n\nhash is a full (GitHash) or partial (GitShortHash) hash.\nspec is a textual specification: see the git docs for a full list.\n\n\n\n\n\n","category":"type"},{"location":"stdlib/LibGit2/#LibGit2.GitTree","page":"LibGit2","title":"LibGit2.GitTree","text":"GitTree(repo::GitRepo, hash::AbstractGitHash)\nGitTree(repo::GitRepo, spec::AbstractString)\n\nReturn a GitTree object from repo specified by hash/spec.\n\nhash is a full (GitHash) or partial (GitShortHash) hash.\nspec is a textual specification: see the git docs for a full list.\n\n\n\n\n\n","category":"type"},{"location":"stdlib/LibGit2/#LibGit2.IndexEntry","page":"LibGit2","title":"LibGit2.IndexEntry","text":"LibGit2.IndexEntry\n\nIn-memory representation of a file entry in the index. Matches the git_index_entry struct.\n\n\n\n\n\n","category":"type"},{"location":"stdlib/LibGit2/#LibGit2.IndexTime","page":"LibGit2","title":"LibGit2.IndexTime","text":"LibGit2.IndexTime\n\nMatches the git_index_time struct.\n\n\n\n\n\n","category":"type"},{"location":"stdlib/LibGit2/#LibGit2.BlameOptions","page":"LibGit2","title":"LibGit2.BlameOptions","text":"LibGit2.BlameOptions\n\nMatches the git_blame_options struct.\n\nThe fields represent:\n\nversion: version of the struct in use, in case this changes later. For now, always 1.\nflags: one of Consts.BLAME_NORMAL or Consts.BLAME_FIRST_PARENT (the other blame flags are not yet implemented by libgit2).\nmin_match_characters: the minimum number of alphanumeric characters which much change in a commit in order for the change to be associated with that commit. The default is 20. Only takes effect if one of the Consts.BLAME_*_COPIES flags are used, which libgit2 does not implement yet.\nnewest_commit: the GitHash of the newest commit from which to look at changes.\noldest_commit: the GitHash of the oldest commit from which to look at changes.\nmin_line: the first line of the file from which to starting blaming. The default is 1.\nmax_line: the last line of the file to which to blame. The default is 0, meaning the last line of the file.\n\n\n\n\n\n","category":"type"},{"location":"stdlib/LibGit2/#LibGit2.MergeOptions","page":"LibGit2","title":"LibGit2.MergeOptions","text":"LibGit2.MergeOptions\n\nMatches the git_merge_options struct.\n\nThe fields represent:\n\nversion: version of the struct in use, in case this changes later. For now, always 1.\nflags: an enum for flags describing merge behavior. Defined in git_merge_flag_t. The corresponding Julia enum is GIT_MERGE and has values:\nMERGE_FIND_RENAMES: detect if a file has been renamed between the common ancestor and the \"ours\" or \"theirs\" side of the merge. Allows merges where a file has been renamed.\nMERGE_FAIL_ON_CONFLICT: exit immediately if a conflict is found rather than trying to resolve it.\nMERGE_SKIP_REUC: do not write the REUC extension on the index resulting from the merge.\nMERGE_NO_RECURSIVE: if the commits being merged have multiple merge bases, use the first one, rather than trying to recursively merge the bases.\nrename_threshold: how similar two files must to consider one a rename of the other. This is an integer that sets the percentage similarity. The default is 50.\ntarget_limit: the maximum number of files to compare with to look for renames. The default is 200.\nmetric: optional custom function to use to determine the similarity between two files for rename detection.\nrecursion_limit: the upper limit on the number of merges of common ancestors to perform to try to build a new virtual merge base for the merge. The default is no limit. This field is only present on libgit2 versions newer than 0.24.0.\ndefault_driver: the merge driver to use if both sides have changed. This field is only present on libgit2 versions newer than 0.25.0.\nfile_favor: how to handle conflicting file contents for the text driver.\nMERGE_FILE_FAVOR_NORMAL: if both sides of the merge have changes to a section, make a note of the conflict in the index which git checkout will use to create a merge file, which the user can then reference to resolve the conflicts. This is the default.\nMERGE_FILE_FAVOR_OURS: if both sides of the merge have changes to a section, use the version in the \"ours\" side of the merge in the index.\nMERGE_FILE_FAVOR_THEIRS: if both sides of the merge have changes to a section, use the version in the \"theirs\" side of the merge in the index.\nMERGE_FILE_FAVOR_UNION: if both sides of the merge have changes to a section, include each unique line from both sides in the file which is put into the index.\nfile_flags: guidelines for merging files.\n\n\n\n\n\n","category":"type"},{"location":"stdlib/LibGit2/#LibGit2.ProxyOptions","page":"LibGit2","title":"LibGit2.ProxyOptions","text":"LibGit2.ProxyOptions\n\nOptions for connecting through a proxy.\n\nMatches the git_proxy_options struct.\n\nThe fields represent:\n\nversion: version of the struct in use, in case this changes later. For now, always 1.\nproxytype: an enum for the type of proxy to use. Defined in git_proxy_t. The corresponding Julia enum is GIT_PROXY and has values:\nPROXY_NONE: do not attempt the connection through a proxy.\nPROXY_AUTO: attempt to figure out the proxy configuration from the git configuration.\nPROXY_SPECIFIED: connect using the URL given in the url field of this struct.\nDefault is to auto-detect the proxy type.\nurl: the URL of the proxy.\ncredential_cb: a pointer to a callback function which will be called if the remote requires authentication to connect.\ncertificate_cb: a pointer to a callback function which will be called if certificate verification fails. This lets the user decide whether or not to keep connecting. If the function returns 1, connecting will be allowed. If it returns 0, the connection will not be allowed. A negative value can be used to return errors.\npayload: the payload to be provided to the two callback functions.\n\nExamples\n\njulia> fo = LibGit2.FetchOptions(\n proxy_opts = LibGit2.ProxyOptions(url = Cstring(\"https://my_proxy_url.com\")))\n\njulia> fetch(remote, \"master\", options=fo)\n\n\n\n\n\n","category":"type"},{"location":"stdlib/LibGit2/#LibGit2.PushOptions","page":"LibGit2","title":"LibGit2.PushOptions","text":"LibGit2.PushOptions\n\nMatches the git_push_options struct.\n\nThe fields represent:\n\nversion: version of the struct in use, in case this changes later. For now, always 1.\nparallelism: if a pack file must be created, this variable sets the number of worker threads which will be spawned by the packbuilder. If 0, the packbuilder will auto-set the number of threads to use. The default is 1.\ncallbacks: the callbacks (e.g. for authentication with the remote) to use for the push.\nproxy_opts: only relevant if the LibGit2 version is greater than or equal to 0.25.0. Sets options for using a proxy to communicate with a remote. See ProxyOptions for more information.\ncustom_headers: only relevant if the LibGit2 version is greater than or equal to 0.24.0. Extra headers needed for the push operation.\n\n\n\n\n\n","category":"type"},{"location":"stdlib/LibGit2/#LibGit2.RebaseOperation","page":"LibGit2","title":"LibGit2.RebaseOperation","text":"LibGit2.RebaseOperation\n\nDescribes a single instruction/operation to be performed during the rebase. Matches the git_rebase_operation struct.\n\nThe fields represent:\n\noptype: the type of rebase operation currently being performed. The options are:\nREBASE_OPERATION_PICK: cherry-pick the commit in question.\nREBASE_OPERATION_REWORD: cherry-pick the commit in question, but rewrite its message using the prompt.\nREBASE_OPERATION_EDIT: cherry-pick the commit in question, but allow the user to edit the commit's contents and its message.\nREBASE_OPERATION_SQUASH: squash the commit in question into the previous commit. The commit messages of the two commits will be merged.\nREBASE_OPERATION_FIXUP: squash the commit in question into the previous commit. Only the commit message of the previous commit will be used.\nREBASE_OPERATION_EXEC: do not cherry-pick a commit. Run a command and continue if the command exits successfully.\nid: the GitHash of the commit being worked on during this rebase step.\nexec: in case REBASE_OPERATION_EXEC is used, the command to run during this step (for instance, running the test suite after each commit).\n\n\n\n\n\n","category":"type"},{"location":"stdlib/LibGit2/#LibGit2.RebaseOptions","page":"LibGit2","title":"LibGit2.RebaseOptions","text":"LibGit2.RebaseOptions\n\nMatches the git_rebase_options struct.\n\nThe fields represent:\n\nversion: version of the struct in use, in case this changes later. For now, always 1.\nquiet: inform other git clients helping with/working on the rebase that the rebase should be done \"quietly\". Used for interoperability. The default is 1.\ninmemory: start an in-memory rebase. Callers working on the rebase can go through its steps and commit any changes, but cannot rewind HEAD or update the repository. The workdir will not be modified. Only present on libgit2 versions newer than or equal to 0.24.0.\nrewrite_notes_ref: name of the reference to notes to use to rewrite the commit notes as the rebase is finished.\nmerge_opts: merge options controlling how the trees will be merged at each rebase step. Only present on libgit2 versions newer than or equal to 0.24.0.\ncheckout_opts: checkout options for writing files when initializing the rebase, stepping through it, and aborting it. See CheckoutOptions for more information.\n\n\n\n\n\n","category":"type"},{"location":"stdlib/LibGit2/#LibGit2.RemoteCallbacks","page":"LibGit2","title":"LibGit2.RemoteCallbacks","text":"LibGit2.RemoteCallbacks\n\nCallback settings. Matches the git_remote_callbacks struct.\n\n\n\n\n\n","category":"type"},{"location":"stdlib/LibGit2/#LibGit2.SignatureStruct","page":"LibGit2","title":"LibGit2.SignatureStruct","text":"LibGit2.SignatureStruct\n\nAn action signature (e.g. for committers, taggers, etc). Matches the git_signature struct.\n\nThe fields represent:\n\nname: The full name of the committer or author of the commit.\nemail: The email at which the committer/author can be contacted.\nwhen: a TimeStruct indicating when the commit was authored/committed into the repository.\n\n\n\n\n\n","category":"type"},{"location":"stdlib/LibGit2/#LibGit2.StatusEntry","page":"LibGit2","title":"LibGit2.StatusEntry","text":"LibGit2.StatusEntry\n\nProviding the differences between the file as it exists in HEAD and the index, and providing the differences between the index and the working directory. Matches the git_status_entry struct.\n\nThe fields represent:\n\nstatus: contains the status flags for the file, indicating if it is current, or has been changed in some way in the index or work tree.\nhead_to_index: a pointer to a DiffDelta which encapsulates the difference(s) between the file as it exists in HEAD and in the index.\nindex_to_workdir: a pointer to a DiffDelta which encapsulates the difference(s) between the file as it exists in the index and in the workdir.\n\n\n\n\n\n","category":"type"},{"location":"stdlib/LibGit2/#LibGit2.StatusOptions","page":"LibGit2","title":"LibGit2.StatusOptions","text":"LibGit2.StatusOptions\n\nOptions to control how git_status_foreach_ext() will issue callbacks. Matches the git_status_opt_t struct.\n\nThe fields represent:\n\nversion: version of the struct in use, in case this changes later. For now, always 1.\nshow: a flag for which files to examine and in which order. The default is Consts.STATUS_SHOW_INDEX_AND_WORKDIR.\nflags: flags for controlling any callbacks used in a status call.\npathspec: an array of paths to use for path-matching. The behavior of the path-matching will vary depending on the values of show and flags.\nThe baseline is the tree to be used for comparison to the working directory and index; defaults to HEAD.\n\n\n\n\n\n","category":"type"},{"location":"stdlib/LibGit2/#LibGit2.StrArrayStruct","page":"LibGit2","title":"LibGit2.StrArrayStruct","text":"LibGit2.StrArrayStruct\n\nA LibGit2 representation of an array of strings. Matches the git_strarray struct.\n\nWhen fetching data from LibGit2, a typical usage would look like:\n\nsa_ref = Ref(StrArrayStruct())\n@check ccall(..., (Ptr{StrArrayStruct},), sa_ref)\nres = convert(Vector{String}, sa_ref[])\nfree(sa_ref)\n\nIn particular, note that LibGit2.free should be called afterward on the Ref object.\n\nConversely, when passing a vector of strings to LibGit2, it is generally simplest to rely on implicit conversion:\n\nstrs = String[...]\n@check ccall(..., (Ptr{StrArrayStruct},), strs)\n\nNote that no call to free is required as the data is allocated by Julia.\n\n\n\n\n\n","category":"type"},{"location":"stdlib/LibGit2/#LibGit2.TimeStruct","page":"LibGit2","title":"LibGit2.TimeStruct","text":"LibGit2.TimeStruct\n\nTime in a signature. Matches the git_time struct.\n\n\n\n\n\n","category":"type"},{"location":"stdlib/LibGit2/#LibGit2.add!","page":"LibGit2","title":"LibGit2.add!","text":"add!(repo::GitRepo, files::AbstractString...; flags::Cuint = Consts.INDEX_ADD_DEFAULT)\nadd!(idx::GitIndex, files::AbstractString...; flags::Cuint = Consts.INDEX_ADD_DEFAULT)\n\nAdd all the files with paths specified by files to the index idx (or the index of the repo). If the file already exists, the index entry will be updated. If the file does not exist already, it will be newly added into the index. files may contain glob patterns which will be expanded and any matching files will be added (unless INDEX_ADD_DISABLE_PATHSPEC_MATCH is set, see below). If a file has been ignored (in .gitignore or in the config), it will not be added, unless it is already being tracked in the index, in which case it will be updated. The keyword argument flags is a set of bit-flags which control the behavior with respect to ignored files:\n\nConsts.INDEX_ADD_DEFAULT - default, described above.\nConsts.INDEX_ADD_FORCE - disregard the existing ignore rules and force addition of the file to the index even if it is already ignored.\nConsts.INDEX_ADD_CHECK_PATHSPEC - cannot be used at the same time as INDEX_ADD_FORCE. Check that each file in files which exists on disk is not in the ignore list. If one of the files is ignored, the function will return EINVALIDSPEC.\nConsts.INDEX_ADD_DISABLE_PATHSPEC_MATCH - turn off glob matching, and only add files to the index which exactly match the paths specified in files.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LibGit2/#LibGit2.add_fetch!","page":"LibGit2","title":"LibGit2.add_fetch!","text":"add_fetch!(repo::GitRepo, rmt::GitRemote, fetch_spec::String)\n\nAdd a fetch refspec for the specified rmt. This refspec will contain information about which branch(es) to fetch from.\n\nExamples\n\njulia> LibGit2.add_fetch!(repo, remote, \"upstream\");\n\njulia> LibGit2.fetch_refspecs(remote)\nString[\"+refs/heads/*:refs/remotes/upstream/*\"]\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LibGit2/#LibGit2.add_push!","page":"LibGit2","title":"LibGit2.add_push!","text":"add_push!(repo::GitRepo, rmt::GitRemote, push_spec::String)\n\nAdd a push refspec for the specified rmt. This refspec will contain information about which branch(es) to push to.\n\nExamples\n\njulia> LibGit2.add_push!(repo, remote, \"refs/heads/master\");\n\njulia> remote = LibGit2.get(LibGit2.GitRemote, repo, branch);\n\njulia> LibGit2.push_refspecs(remote)\nString[\"refs/heads/master\"]\n\nnote: Note\nYou may need to close and reopen the GitRemote in question after updating its push refspecs in order for the change to take effect and for calls to push to work.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LibGit2/#LibGit2.addblob!","page":"LibGit2","title":"LibGit2.addblob!","text":"LibGit2.addblob!(repo::GitRepo, path::AbstractString)\n\nRead the file at path and adds it to the object database of repo as a loose blob. Return the GitHash of the resulting blob.\n\nExamples\n\nhash_str = string(commit_oid)\nblob_file = joinpath(repo_path, \".git\", \"objects\", hash_str[1:2], hash_str[3:end])\nid = LibGit2.addblob!(repo, blob_file)\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LibGit2/#LibGit2.author","page":"LibGit2","title":"LibGit2.author","text":"author(c::GitCommit)\n\nReturn the Signature of the author of the commit c. The author is the person who made changes to the relevant file(s). See also committer.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LibGit2/#LibGit2.authors","page":"LibGit2","title":"LibGit2.authors","text":"authors(repo::GitRepo) -> Vector{Signature}\n\nReturn all authors of commits to the repo repository.\n\nExamples\n\nrepo = LibGit2.GitRepo(repo_path)\nrepo_file = open(joinpath(repo_path, test_file), \"a\")\n\nprintln(repo_file, commit_msg)\nflush(repo_file)\nLibGit2.add!(repo, test_file)\nsig = LibGit2.Signature(\"TEST\", \"TEST@TEST.COM\", round(time(), 0), 0)\ncommit_oid1 = LibGit2.commit(repo, \"commit1\"; author=sig, committer=sig)\nprintln(repo_file, randstring(10))\nflush(repo_file)\nLibGit2.add!(repo, test_file)\ncommit_oid2 = LibGit2.commit(repo, \"commit2\"; author=sig, committer=sig)\n\n# will be a Vector of [sig, sig]\nauths = LibGit2.authors(repo)\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LibGit2/#LibGit2.branch","page":"LibGit2","title":"LibGit2.branch","text":"branch(repo::GitRepo)\n\nEquivalent to git branch. Create a new branch from the current HEAD.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LibGit2/#LibGit2.branch!","page":"LibGit2","title":"LibGit2.branch!","text":"branch!(repo::GitRepo, branch_name::AbstractString, commit::AbstractString=\"\"; kwargs...)\n\nCheckout a new git branch in the repo repository. commit is the GitHash, in string form, which will be the start of the new branch. If commit is an empty string, the current HEAD will be used.\n\nThe keyword arguments are:\n\ntrack::AbstractString=\"\": the name of the remote branch this new branch should track, if any. If empty (the default), no remote branch will be tracked.\nforce::Bool=false: if true, branch creation will be forced.\nset_head::Bool=true: if true, after the branch creation finishes the branch head will be set as the HEAD of repo.\n\nEquivalent to git checkout [-b|-B] [] [--track ].\n\nExamples\n\nrepo = LibGit2.GitRepo(repo_path)\nLibGit2.branch!(repo, \"new_branch\", set_head=false)\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LibGit2/#LibGit2.checkout!","page":"LibGit2","title":"LibGit2.checkout!","text":"checkout!(repo::GitRepo, commit::AbstractString=\"\"; force::Bool=true)\n\nEquivalent to git checkout [-f] --detach . Checkout the git commit commit (a GitHash in string form) in repo. If force is true, force the checkout and discard any current changes. Note that this detaches the current HEAD.\n\nExamples\n\nrepo = LibGit2.init(repo_path)\nopen(joinpath(LibGit2.path(repo), \"file1\"), \"w\") do f\n write(f, \"111\n\")\nend\nLibGit2.add!(repo, \"file1\")\ncommit_oid = LibGit2.commit(repo, \"add file1\")\nopen(joinpath(LibGit2.path(repo), \"file1\"), \"w\") do f\n write(f, \"112\n\")\nend\n# would fail without the force=true\n# since there are modifications to the file\nLibGit2.checkout!(repo, string(commit_oid), force=true)\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LibGit2/#LibGit2.clone","page":"LibGit2","title":"LibGit2.clone","text":"clone(repo_url::AbstractString, repo_path::AbstractString, clone_opts::CloneOptions)\n\nClone the remote repository at repo_url (which can be a remote URL or a path on the local filesystem) to repo_path (which must be a path on the local filesystem). Options for the clone, such as whether to perform a bare clone or not, are set by CloneOptions.\n\nExamples\n\nrepo_url = \"https://github.com/JuliaLang/Example.jl\"\nrepo = LibGit2.clone(repo_url, \"/home/me/projects/Example\")\n\n\n\n\n\nclone(repo_url::AbstractString, repo_path::AbstractString; kwargs...)\n\nClone a remote repository located at repo_url to the local filesystem location repo_path.\n\nThe keyword arguments are:\n\nbranch::AbstractString=\"\": which branch of the remote to clone, if not the default repository branch (usually master).\nisbare::Bool=false: if true, clone the remote as a bare repository, which will make repo_path itself the git directory instead of repo_path/.git. This means that a working tree cannot be checked out. Plays the role of the git CLI argument --bare.\nremote_cb::Ptr{Cvoid}=C_NULL: a callback which will be used to create the remote before it is cloned. If C_NULL (the default), no attempt will be made to create the remote - it will be assumed to already exist.\ncredentials::Creds=nothing: provides credentials and/or settings when authenticating against a private repository.\ncallbacks::Callbacks=Callbacks(): user provided callbacks and payloads.\n\nEquivalent to git clone [-b ] [--bare] .\n\nExamples\n\nrepo_url = \"https://github.com/JuliaLang/Example.jl\"\nrepo1 = LibGit2.clone(repo_url, \"test_path\")\nrepo2 = LibGit2.clone(repo_url, \"test_path\", isbare=true)\njulia_url = \"https://github.com/JuliaLang/julia\"\njulia_repo = LibGit2.clone(julia_url, \"julia_path\", branch=\"release-0.6\")\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LibGit2/#LibGit2.commit","page":"LibGit2","title":"LibGit2.commit","text":"commit(repo::GitRepo, msg::AbstractString; kwargs...) -> GitHash\n\nWrapper around git_commit_create. Create a commit in the repository repo. msg is the commit message. Return the OID of the new commit.\n\nThe keyword arguments are:\n\nrefname::AbstractString=Consts.HEAD_FILE: if not NULL, the name of the reference to update to point to the new commit. For example, \"HEAD\" will update the HEAD of the current branch. If the reference does not yet exist, it will be created.\nauthor::Signature = Signature(repo) is a Signature containing information about the person who authored the commit.\ncommitter::Signature = Signature(repo) is a Signature containing information about the person who committed the commit to the repository. Not necessarily the same as author, for instance if author emailed a patch to committer who committed it.\ntree_id::GitHash = GitHash() is a git tree to use to create the commit, showing its ancestry and relationship with any other history. tree must belong to repo.\nparent_ids::Vector{GitHash}=GitHash[] is a list of commits by GitHash to use as parent commits for the new one, and may be empty. A commit might have multiple parents if it is a merge commit, for example.\n\n\n\n\n\nLibGit2.commit(rb::GitRebase, sig::GitSignature)\n\nCommit the current patch to the rebase rb, using sig as the committer. Is silent if the commit has already been applied.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LibGit2/#LibGit2.committer","page":"LibGit2","title":"LibGit2.committer","text":"committer(c::GitCommit)\n\nReturn the Signature of the committer of the commit c. The committer is the person who committed the changes originally authored by the author, but need not be the same as the author, for example, if the author emailed a patch to a committer who committed it.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LibGit2/#LibGit2.count","page":"LibGit2","title":"LibGit2.count","text":"LibGit2.count(f::Function, walker::GitRevWalker; oid::GitHash=GitHash(), by::Cint=Consts.SORT_NONE, rev::Bool=false)\n\nUsing the GitRevWalker walker to \"walk\" over every commit in the repository's history, find the number of commits which return true when f is applied to them. The keyword arguments are: * oid: The GitHash of the commit to begin the walk from. The default is to use push_head! and therefore the HEAD commit and all its ancestors. * by: The sorting method. The default is not to sort. Other options are to sort by topology (LibGit2.Consts.SORT_TOPOLOGICAL), to sort forwards in time (LibGit2.Consts.SORT_TIME, most ancient first) or to sort backwards in time (LibGit2.Consts.SORT_REVERSE, most recent first). * rev: Whether to reverse the sorted order (for instance, if topological sorting is used).\n\nExamples\n\ncnt = LibGit2.with(LibGit2.GitRevWalker(repo)) do walker\n LibGit2.count((oid, repo)->(oid == commit_oid1), walker, oid=commit_oid1, by=LibGit2.Consts.SORT_TIME)\nend\n\nLibGit2.count finds the number of commits along the walk with a certain GitHash commit_oid1, starting the walk from that commit and moving forwards in time from it. Since the GitHash is unique to a commit, cnt will be 1.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LibGit2/#LibGit2.counthunks","page":"LibGit2","title":"LibGit2.counthunks","text":"counthunks(blame::GitBlame)\n\nReturn the number of distinct \"hunks\" with a file. A hunk may contain multiple lines. A hunk is usually a piece of a file that was added/changed/removed together, for example, a function added to a source file or an inner loop that was optimized out of that function later.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LibGit2/#LibGit2.create_branch","page":"LibGit2","title":"LibGit2.create_branch","text":"LibGit2.create_branch(repo::GitRepo, bname::AbstractString, commit_obj::GitCommit; force::Bool=false)\n\nCreate a new branch in the repository repo with name bname, which points to commit commit_obj (which has to be part of repo). If force is true, overwrite an existing branch named bname if it exists. If force is false and a branch already exists named bname, this function will throw an error.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LibGit2/#LibGit2.credentials_callback","page":"LibGit2","title":"LibGit2.credentials_callback","text":"credential_callback(...) -> Cint\n\nA LibGit2 credential callback function which provides different credential acquisition functionality w.r.t. a connection protocol. The payload_ptr is required to contain a LibGit2.CredentialPayload object which will keep track of state and settings.\n\nThe allowed_types contains a bitmask of LibGit2.Consts.GIT_CREDTYPE values specifying which authentication methods should be attempted.\n\nCredential authentication is done in the following order (if supported):\n\nSSH agent\nSSH private/public key pair\nUsername/password plain text\n\nIf a user is presented with a credential prompt they can abort the prompt by typing ^D (pressing the control key together with the d key).\n\nNote: Due to the specifics of the libgit2 authentication procedure, when authentication fails, this function is called again without any indication whether authentication was successful or not. To avoid an infinite loop from repeatedly using the same faulty credentials, we will keep track of state using the payload.\n\nFor addition details see the LibGit2 guide on authenticating against a server.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LibGit2/#LibGit2.credentials_cb","page":"LibGit2","title":"LibGit2.credentials_cb","text":"C function pointer for credentials_callback\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LibGit2/#LibGit2.default_signature","page":"LibGit2","title":"LibGit2.default_signature","text":"Return signature object. Free it after use.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LibGit2/#LibGit2.delete_branch","page":"LibGit2","title":"LibGit2.delete_branch","text":"LibGit2.delete_branch(branch::GitReference)\n\nDelete the branch pointed to by branch.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LibGit2/#LibGit2.diff_files","page":"LibGit2","title":"LibGit2.diff_files","text":"diff_files(repo::GitRepo, branch1::AbstractString, branch2::AbstractString; kwarg...) -> Vector{AbstractString}\n\nShow which files have changed in the git repository repo between branches branch1 and branch2.\n\nThe keyword argument is:\n\nfilter::Set{Consts.DELTA_STATUS}=Set([Consts.DELTA_ADDED, Consts.DELTA_MODIFIED, Consts.DELTA_DELETED])), and it sets options for the diff. The default is to show files added, modified, or deleted.\n\nReturn only the names of the files which have changed, not their contents.\n\nExamples\n\nLibGit2.branch!(repo, \"branch/a\")\nLibGit2.branch!(repo, \"branch/b\")\n# add a file to repo\nopen(joinpath(LibGit2.path(repo),\"file\"),\"w\") do f\n write(f, \"hello repo\n\")\nend\nLibGit2.add!(repo, \"file\")\nLibGit2.commit(repo, \"add file\")\n# returns [\"file\"]\nfilt = Set([LibGit2.Consts.DELTA_ADDED])\nfiles = LibGit2.diff_files(repo, \"branch/a\", \"branch/b\", filter=filt)\n# returns [] because existing files weren't modified\nfilt = Set([LibGit2.Consts.DELTA_MODIFIED])\nfiles = LibGit2.diff_files(repo, \"branch/a\", \"branch/b\", filter=filt)\n\nEquivalent to git diff --name-only --diff-filter= .\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LibGit2/#LibGit2.entryid","page":"LibGit2","title":"LibGit2.entryid","text":"entryid(te::GitTreeEntry)\n\nReturn the GitHash of the object to which te refers.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LibGit2/#LibGit2.entrytype","page":"LibGit2","title":"LibGit2.entrytype","text":"entrytype(te::GitTreeEntry)\n\nReturn the type of the object to which te refers. The result will be one of the types which objtype returns, e.g. a GitTree or GitBlob.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LibGit2/#LibGit2.fetch","page":"LibGit2","title":"LibGit2.fetch","text":"fetch(rmt::GitRemote, refspecs; options::FetchOptions=FetchOptions(), msg=\"\")\n\nFetch from the specified rmt remote git repository, using refspecs to determine which remote branch(es) to fetch. The keyword arguments are:\n\noptions: determines the options for the fetch, e.g. whether to prune afterwards. See FetchOptions for more information.\nmsg: a message to insert into the reflogs.\n\n\n\n\n\nfetch(repo::GitRepo; kwargs...)\n\nFetches updates from an upstream of the repository repo.\n\nThe keyword arguments are:\n\nremote::AbstractString=\"origin\": which remote, specified by name, of repo to fetch from. If this is empty, the URL will be used to construct an anonymous remote.\nremoteurl::AbstractString=\"\": the URL of remote. If not specified, will be assumed based on the given name of remote.\nrefspecs=AbstractString[]: determines properties of the fetch.\ncredentials=nothing: provides credentials and/or settings when authenticating against a private remote.\ncallbacks=Callbacks(): user provided callbacks and payloads.\n\nEquivalent to git fetch [|] [].\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LibGit2/#LibGit2.fetchheads","page":"LibGit2","title":"LibGit2.fetchheads","text":"fetchheads(repo::GitRepo) -> Vector{FetchHead}\n\nReturn the list of all the fetch heads for repo, each represented as a FetchHead, including their names, URLs, and merge statuses.\n\nExamples\n\njulia> fetch_heads = LibGit2.fetchheads(repo);\n\njulia> fetch_heads[1].name\n\"refs/heads/master\"\n\njulia> fetch_heads[1].ismerge\ntrue\n\njulia> fetch_heads[2].name\n\"refs/heads/test_branch\"\n\njulia> fetch_heads[2].ismerge\nfalse\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LibGit2/#LibGit2.fetch_refspecs","page":"LibGit2","title":"LibGit2.fetch_refspecs","text":"fetch_refspecs(rmt::GitRemote) -> Vector{String}\n\nGet the fetch refspecs for the specified rmt. These refspecs contain information about which branch(es) to fetch from.\n\nExamples\n\njulia> remote = LibGit2.get(LibGit2.GitRemote, repo, \"upstream\");\n\njulia> LibGit2.add_fetch!(repo, remote, \"upstream\");\n\njulia> LibGit2.fetch_refspecs(remote)\nString[\"+refs/heads/*:refs/remotes/upstream/*\"]\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LibGit2/#LibGit2.fetchhead_foreach_cb","page":"LibGit2","title":"LibGit2.fetchhead_foreach_cb","text":"C function pointer for fetchhead_foreach_callback\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LibGit2/#LibGit2.merge_base","page":"LibGit2","title":"LibGit2.merge_base","text":"merge_base(repo::GitRepo, one::AbstractString, two::AbstractString) -> GitHash\n\nFind a merge base (a common ancestor) between the commits one and two. one and two may both be in string form. Return the GitHash of the merge base.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LibGit2/#LibGit2.merge!-Tuple{GitRepo}","page":"LibGit2","title":"LibGit2.merge!","text":"merge!(repo::GitRepo; kwargs...) -> Bool\n\nPerform a git merge on the repository repo, merging commits with diverging history into the current branch. Return true if the merge succeeded, false if not.\n\nThe keyword arguments are:\n\ncommittish::AbstractString=\"\": Merge the named commit(s) in committish.\nbranch::AbstractString=\"\": Merge the branch branch and all its commits since it diverged from the current branch.\nfastforward::Bool=false: If fastforward is true, only merge if the merge is a fast-forward (the current branch head is an ancestor of the commits to be merged), otherwise refuse to merge and return false. This is equivalent to the git CLI option --ff-only.\nmerge_opts::MergeOptions=MergeOptions(): merge_opts specifies options for the merge, such as merge strategy in case of conflicts.\ncheckout_opts::CheckoutOptions=CheckoutOptions(): checkout_opts specifies options for the checkout step.\n\nEquivalent to git merge [--ff-only] [ | ].\n\nnote: Note\nIf you specify a branch, this must be done in reference format, since the string will be turned into a GitReference. For example, if you wanted to merge branch branch_a, you would call merge!(repo, branch=\"refs/heads/branch_a\").\n\n\n\n\n\n","category":"method"},{"location":"stdlib/LibGit2/#LibGit2.merge!-Tuple{GitRepo, Vector{LibGit2.GitAnnotated}}","page":"LibGit2","title":"LibGit2.merge!","text":"merge!(repo::GitRepo, anns::Vector{GitAnnotated}; kwargs...) -> Bool\n\nMerge changes from the annotated commits (captured as GitAnnotated objects) anns into the HEAD of the repository repo. The keyword arguments are:\n\nmerge_opts::MergeOptions = MergeOptions(): options for how to perform the merge, including whether fastforwarding is allowed. See MergeOptions for more information.\ncheckout_opts::CheckoutOptions = CheckoutOptions(): options for how to perform the checkout. See CheckoutOptions for more information.\n\nanns may refer to remote or local branch heads. Return true if the merge is successful, otherwise return false (for instance, if no merge is possible because the branches have no common ancestor).\n\nExamples\n\nupst_ann = LibGit2.GitAnnotated(repo, \"branch/a\")\n\n# merge the branch in\nLibGit2.merge!(repo, [upst_ann])\n\n\n\n\n\n","category":"method"},{"location":"stdlib/LibGit2/#LibGit2.merge!-Tuple{GitRepo, Vector{LibGit2.GitAnnotated}, Bool}","page":"LibGit2","title":"LibGit2.merge!","text":"merge!(repo::GitRepo, anns::Vector{GitAnnotated}, fastforward::Bool; kwargs...) -> Bool\n\nMerge changes from the annotated commits (captured as GitAnnotated objects) anns into the HEAD of the repository repo. If fastforward is true, only a fastforward merge is allowed. In this case, if conflicts occur, the merge will fail. Otherwise, if fastforward is false, the merge may produce a conflict file which the user will need to resolve.\n\nThe keyword arguments are:\n\nmerge_opts::MergeOptions = MergeOptions(): options for how to perform the merge, including whether fastforwarding is allowed. See MergeOptions for more information.\ncheckout_opts::CheckoutOptions = CheckoutOptions(): options for how to perform the checkout. See CheckoutOptions for more information.\n\nanns may refer to remote or local branch heads. Return true if the merge is successful, otherwise return false (for instance, if no merge is possible because the branches have no common ancestor).\n\nExamples\n\nupst_ann_1 = LibGit2.GitAnnotated(repo, \"branch/a\")\n\n# merge the branch in, fastforward\nLibGit2.merge!(repo, [upst_ann_1], true)\n\n# merge conflicts!\nupst_ann_2 = LibGit2.GitAnnotated(repo, \"branch/b\")\n# merge the branch in, try to fastforward\nLibGit2.merge!(repo, [upst_ann_2], true) # will return false\nLibGit2.merge!(repo, [upst_ann_2], false) # will return true\n\n\n\n\n\n","category":"method"},{"location":"stdlib/LibGit2/#LibGit2.ffmerge!","page":"LibGit2","title":"LibGit2.ffmerge!","text":"ffmerge!(repo::GitRepo, ann::GitAnnotated)\n\nFastforward merge changes into current HEAD. This is only possible if the commit referred to by ann is descended from the current HEAD (e.g. if pulling changes from a remote branch which is simply ahead of the local branch tip).\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LibGit2/#LibGit2.fullname","page":"LibGit2","title":"LibGit2.fullname","text":"LibGit2.fullname(ref::GitReference)\n\nReturn the name of the reference pointed to by the symbolic reference ref. If ref is not a symbolic reference, return an empty string.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LibGit2/#LibGit2.features","page":"LibGit2","title":"LibGit2.features","text":"features()\n\nReturn a list of git features the current version of libgit2 supports, such as threading or using HTTPS or SSH.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LibGit2/#LibGit2.filename","page":"LibGit2","title":"LibGit2.filename","text":"filename(te::GitTreeEntry)\n\nReturn the filename of the object on disk to which te refers.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LibGit2/#LibGit2.filemode","page":"LibGit2","title":"LibGit2.filemode","text":"filemode(te::GitTreeEntry) -> Cint\n\nReturn the UNIX filemode of the object on disk to which te refers as an integer.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LibGit2/#LibGit2.gitdir","page":"LibGit2","title":"LibGit2.gitdir","text":"LibGit2.gitdir(repo::GitRepo)\n\nReturn the location of the \"git\" files of repo:\n\nfor normal repositories, this is the location of the .git folder.\nfor bare repositories, this is the location of the repository itself.\n\nSee also workdir, path.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LibGit2/#LibGit2.git_url","page":"LibGit2","title":"LibGit2.git_url","text":"LibGit2.git_url(; kwargs...) -> String\n\nCreate a string based upon the URL components provided. When the scheme keyword is not provided the URL produced will use the alternative scp-like syntax.\n\nKeywords\n\nscheme::AbstractString=\"\": the URL scheme which identifies the protocol to be used. For HTTP use \"http\", SSH use \"ssh\", etc. When scheme is not provided the output format will be \"ssh\" but using the scp-like syntax.\nusername::AbstractString=\"\": the username to use in the output if provided.\npassword::AbstractString=\"\": the password to use in the output if provided.\nhost::AbstractString=\"\": the hostname to use in the output. A hostname is required to be specified.\nport::Union{AbstractString,Integer}=\"\": the port number to use in the output if provided. Cannot be specified when using the scp-like syntax.\npath::AbstractString=\"\": the path to use in the output if provided.\n\nwarning: Warning\nAvoid using passwords in URLs. Unlike the credential objects, Julia is not able to securely zero or destroy the sensitive data after use and the password may remain in memory; possibly to be exposed by an uninitialized memory.\n\nExamples\n\njulia> LibGit2.git_url(username=\"git\", host=\"github.com\", path=\"JuliaLang/julia.git\")\n\"git@github.com:JuliaLang/julia.git\"\n\njulia> LibGit2.git_url(scheme=\"https\", host=\"github.com\", path=\"/JuliaLang/julia.git\")\n\"https://github.com/JuliaLang/julia.git\"\n\njulia> LibGit2.git_url(scheme=\"ssh\", username=\"git\", host=\"github.com\", port=2222, path=\"JuliaLang/julia.git\")\n\"ssh://git@github.com:2222/JuliaLang/julia.git\"\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LibGit2/#LibGit2.@githash_str","page":"LibGit2","title":"LibGit2.@githash_str","text":"@githash_str -> AbstractGitHash\n\nConstruct a git hash object from the given string, returning a GitShortHash if the string is shorter than 40 hexadecimal digits, otherwise a GitHash.\n\nExamples\n\njulia> LibGit2.githash\"d114feb74ce633\"\nGitShortHash(\"d114feb74ce633\")\n\njulia> LibGit2.githash\"d114feb74ce63307afe878a5228ad014e0289a85\"\nGitHash(\"d114feb74ce63307afe878a5228ad014e0289a85\")\n\n\n\n\n\n","category":"macro"},{"location":"stdlib/LibGit2/#LibGit2.head","page":"LibGit2","title":"LibGit2.head","text":"LibGit2.head(repo::GitRepo) -> GitReference\n\nReturn a GitReference to the current HEAD of repo.\n\n\n\n\n\nhead(pkg::AbstractString) -> String\n\nReturn current HEAD GitHash of the pkg repo as a string.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LibGit2/#LibGit2.head!","page":"LibGit2","title":"LibGit2.head!","text":"LibGit2.head!(repo::GitRepo, ref::GitReference) -> GitReference\n\nSet the HEAD of repo to the object pointed to by ref.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LibGit2/#LibGit2.head_oid","page":"LibGit2","title":"LibGit2.head_oid","text":"LibGit2.head_oid(repo::GitRepo) -> GitHash\n\nLookup the object id of the current HEAD of git repository repo.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LibGit2/#LibGit2.headname","page":"LibGit2","title":"LibGit2.headname","text":"LibGit2.headname(repo::GitRepo)\n\nLookup the name of the current HEAD of git repository repo. If repo is currently detached, return the name of the HEAD it's detached from.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LibGit2/#LibGit2.init","page":"LibGit2","title":"LibGit2.init","text":"LibGit2.init(path::AbstractString, bare::Bool=false) -> GitRepo\n\nOpen a new git repository at path. If bare is false, the working tree will be created in path/.git. If bare is true, no working directory will be created.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LibGit2/#LibGit2.is_ancestor_of","page":"LibGit2","title":"LibGit2.is_ancestor_of","text":"is_ancestor_of(a::AbstractString, b::AbstractString, repo::GitRepo) -> Bool\n\nReturn true if a, a GitHash in string form, is an ancestor of b, a GitHash in string form.\n\nExamples\n\njulia> repo = LibGit2.GitRepo(repo_path);\n\njulia> LibGit2.add!(repo, test_file1);\n\njulia> commit_oid1 = LibGit2.commit(repo, \"commit1\");\n\njulia> LibGit2.add!(repo, test_file2);\n\njulia> commit_oid2 = LibGit2.commit(repo, \"commit2\");\n\njulia> LibGit2.is_ancestor_of(string(commit_oid1), string(commit_oid2), repo)\ntrue\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LibGit2/#LibGit2.isbinary","page":"LibGit2","title":"LibGit2.isbinary","text":"isbinary(blob::GitBlob) -> Bool\n\nUse a heuristic to guess if a file is binary: searching for NULL bytes and looking for a reasonable ratio of printable to non-printable characters among the first 8000 bytes.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LibGit2/#LibGit2.iscommit","page":"LibGit2","title":"LibGit2.iscommit","text":"iscommit(id::AbstractString, repo::GitRepo) -> Bool\n\nCheck if commit id (which is a GitHash in string form) is in the repository.\n\nExamples\n\njulia> repo = LibGit2.GitRepo(repo_path);\n\njulia> LibGit2.add!(repo, test_file);\n\njulia> commit_oid = LibGit2.commit(repo, \"add test_file\");\n\njulia> LibGit2.iscommit(string(commit_oid), repo)\ntrue\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LibGit2/#LibGit2.isdiff","page":"LibGit2","title":"LibGit2.isdiff","text":"LibGit2.isdiff(repo::GitRepo, treeish::AbstractString, pathspecs::AbstractString=\"\"; cached::Bool=false)\n\nChecks if there are any differences between the tree specified by treeish and the tracked files in the working tree (if cached=false) or the index (if cached=true). pathspecs are the specifications for options for the diff.\n\nExamples\n\nrepo = LibGit2.GitRepo(repo_path)\nLibGit2.isdiff(repo, \"HEAD\") # should be false\nopen(joinpath(repo_path, new_file), \"a\") do f\n println(f, \"here's my cool new file\")\nend\nLibGit2.isdiff(repo, \"HEAD\") # now true\n\nEquivalent to git diff-index [-- ].\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LibGit2/#LibGit2.isdirty","page":"LibGit2","title":"LibGit2.isdirty","text":"LibGit2.isdirty(repo::GitRepo, pathspecs::AbstractString=\"\"; cached::Bool=false) -> Bool\n\nCheck if there have been any changes to tracked files in the working tree (if cached=false) or the index (if cached=true). pathspecs are the specifications for options for the diff.\n\nExamples\n\nrepo = LibGit2.GitRepo(repo_path)\nLibGit2.isdirty(repo) # should be false\nopen(joinpath(repo_path, new_file), \"a\") do f\n println(f, \"here's my cool new file\")\nend\nLibGit2.isdirty(repo) # now true\nLibGit2.isdirty(repo, new_file) # now true\n\nEquivalent to git diff-index HEAD [-- ].\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LibGit2/#LibGit2.isorphan","page":"LibGit2","title":"LibGit2.isorphan","text":"LibGit2.isorphan(repo::GitRepo)\n\nCheck if the current branch is an \"orphan\" branch, i.e. has no commits. The first commit to this branch will have no parents.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LibGit2/#LibGit2.isset","page":"LibGit2","title":"LibGit2.isset","text":"isset(val::Integer, flag::Integer)\n\nTest whether the bits of val indexed by flag are set (1) or unset (0).\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LibGit2/#LibGit2.iszero","page":"LibGit2","title":"LibGit2.iszero","text":"iszero(id::GitHash) -> Bool\n\nDetermine whether all hexadecimal digits of the given GitHash are zero.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LibGit2/#LibGit2.lookup_branch","page":"LibGit2","title":"LibGit2.lookup_branch","text":"lookup_branch(repo::GitRepo, branch_name::AbstractString, remote::Bool=false) -> Union{GitReference, Nothing}\n\nDetermine if the branch specified by branch_name exists in the repository repo. If remote is true, repo is assumed to be a remote git repository. Otherwise, it is part of the local filesystem.\n\nReturn either a GitReference to the requested branch if it exists, or nothing if not.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LibGit2/#LibGit2.map","page":"LibGit2","title":"LibGit2.map","text":"LibGit2.map(f::Function, walker::GitRevWalker; oid::GitHash=GitHash(), range::AbstractString=\"\", by::Cint=Consts.SORT_NONE, rev::Bool=false)\n\nUsing the GitRevWalker walker to \"walk\" over every commit in the repository's history, apply f to each commit in the walk. The keyword arguments are: * oid: The GitHash of the commit to begin the walk from. The default is to use push_head! and therefore the HEAD commit and all its ancestors. * range: A range of GitHashs in the format oid1..oid2. f will be applied to all commits between the two. * by: The sorting method. The default is not to sort. Other options are to sort by topology (LibGit2.Consts.SORT_TOPOLOGICAL), to sort forwards in time (LibGit2.Consts.SORT_TIME, most ancient first) or to sort backwards in time (LibGit2.Consts.SORT_REVERSE, most recent first). * rev: Whether to reverse the sorted order (for instance, if topological sorting is used).\n\nExamples\n\noids = LibGit2.with(LibGit2.GitRevWalker(repo)) do walker\n LibGit2.map((oid, repo)->string(oid), walker, by=LibGit2.Consts.SORT_TIME)\nend\n\nHere, LibGit2.map visits each commit using the GitRevWalker and finds its GitHash.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LibGit2/#LibGit2.mirror_callback","page":"LibGit2","title":"LibGit2.mirror_callback","text":"Mirror callback function\n\nFunction sets +refs/*:refs/* refspecs and mirror flag for remote reference.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LibGit2/#LibGit2.mirror_cb","page":"LibGit2","title":"LibGit2.mirror_cb","text":"C function pointer for mirror_callback\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LibGit2/#LibGit2.message","page":"LibGit2","title":"LibGit2.message","text":"message(c::GitCommit, raw::Bool=false)\n\nReturn the commit message describing the changes made in commit c. If raw is false, return a slightly \"cleaned up\" message (which has any leading newlines removed). If raw is true, the message is not stripped of any such newlines.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LibGit2/#LibGit2.merge_analysis","page":"LibGit2","title":"LibGit2.merge_analysis","text":"merge_analysis(repo::GitRepo, anns::Vector{GitAnnotated}) -> analysis, preference\n\nRun analysis on the branches pointed to by the annotated branch tips anns and determine under what circumstances they can be merged. For instance, if anns[1] is simply an ancestor of ann[2], then merge_analysis will report that a fast-forward merge is possible.\n\nReturn two outputs, analysis and preference. analysis has several possible values: * MERGE_ANALYSIS_NONE: it is not possible to merge the elements of anns. * MERGE_ANALYSIS_NORMAL: a regular merge, when HEAD and the commits that the user wishes to merge have all diverged from a common ancestor. In this case the changes have to be resolved and conflicts may occur. * MERGE_ANALYSIS_UP_TO_DATE: all the input commits the user wishes to merge can be reached from HEAD, so no merge needs to be performed. * MERGE_ANALYSIS_FASTFORWARD: the input commit is a descendant of HEAD and so no merge needs to be performed - instead, the user can simply checkout the input commit(s). * MERGE_ANALYSIS_UNBORN: the HEAD of the repository refers to a commit which does not exist. It is not possible to merge, but it may be possible to checkout the input commits. preference also has several possible values: * MERGE_PREFERENCE_NONE: the user has no preference. * MERGE_PREFERENCE_NO_FASTFORWARD: do not allow any fast-forward merges. * MERGE_PREFERENCE_FASTFORWARD_ONLY: allow only fast-forward merges and no other type (which may introduce conflicts). preference can be controlled through the repository or global git configuration.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LibGit2/#LibGit2.name","page":"LibGit2","title":"LibGit2.name","text":"LibGit2.name(ref::GitReference)\n\nReturn the full name of ref.\n\n\n\n\n\nname(rmt::GitRemote)\n\nGet the name of a remote repository, for instance \"origin\". If the remote is anonymous (see GitRemoteAnon) the name will be an empty string \"\".\n\nExamples\n\njulia> repo_url = \"https://github.com/JuliaLang/Example.jl\";\n\njulia> repo = LibGit2.clone(cache_repo, \"test_directory\");\n\njulia> remote = LibGit2.GitRemote(repo, \"origin\", repo_url);\n\njulia> name(remote)\n\"origin\"\n\n\n\n\n\nLibGit2.name(tag::GitTag)\n\nThe name of tag (e.g. \"v0.5\").\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LibGit2/#LibGit2.need_update","page":"LibGit2","title":"LibGit2.need_update","text":"need_update(repo::GitRepo)\n\nEquivalent to git update-index. Return true if repo needs updating.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LibGit2/#LibGit2.objtype","page":"LibGit2","title":"LibGit2.objtype","text":"objtype(obj_type::Consts.OBJECT)\n\nReturn the type corresponding to the enum value.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LibGit2/#LibGit2.path","page":"LibGit2","title":"LibGit2.path","text":"LibGit2.path(repo::GitRepo)\n\nReturn the base file path of the repository repo.\n\nfor normal repositories, this will typically be the parent directory of the \".git\" directory (note: this may be different than the working directory, see workdir for more details).\nfor bare repositories, this is the location of the \"git\" files.\n\nSee also gitdir, workdir.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LibGit2/#LibGit2.peel","page":"LibGit2","title":"LibGit2.peel","text":"peel([T,] ref::GitReference)\n\nRecursively peel ref until an object of type T is obtained. If no T is provided, then ref will be peeled until an object other than a GitTag is obtained.\n\nA GitTag will be peeled to the object it references.\nA GitCommit will be peeled to a GitTree.\n\nnote: Note\nOnly annotated tags can be peeled to GitTag objects. Lightweight tags (the default) are references under refs/tags/ which point directly to GitCommit objects.\n\n\n\n\n\npeel([T,] obj::GitObject)\n\nRecursively peel obj until an object of type T is obtained. If no T is provided, then obj will be peeled until the type changes.\n\nA GitTag will be peeled to the object it references.\nA GitCommit will be peeled to a GitTree.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LibGit2/#LibGit2.posixpath","page":"LibGit2","title":"LibGit2.posixpath","text":"LibGit2.posixpath(path)\n\nStandardise the path string path to use POSIX separators.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LibGit2/#LibGit2.push","page":"LibGit2","title":"LibGit2.push","text":"push(rmt::GitRemote, refspecs; force::Bool=false, options::PushOptions=PushOptions())\n\nPush to the specified rmt remote git repository, using refspecs to determine which remote branch(es) to push to. The keyword arguments are:\n\nforce: if true, a force-push will occur, disregarding conflicts.\noptions: determines the options for the push, e.g. which proxy headers to use. See PushOptions for more information.\n\nnote: Note\nYou can add information about the push refspecs in two other ways: by setting an option in the repository's GitConfig (with push.default as the key) or by calling add_push!. Otherwise you will need to explicitly specify a push refspec in the call to push for it to have any effect, like so: LibGit2.push(repo, refspecs=[\"refs/heads/master\"]).\n\n\n\n\n\npush(repo::GitRepo; kwargs...)\n\nPushes updates to an upstream of repo.\n\nThe keyword arguments are:\n\nremote::AbstractString=\"origin\": the name of the upstream remote to push to.\nremoteurl::AbstractString=\"\": the URL of remote.\nrefspecs=AbstractString[]: determines properties of the push.\nforce::Bool=false: determines if the push will be a force push, overwriting the remote branch.\ncredentials=nothing: provides credentials and/or settings when authenticating against a private remote.\ncallbacks=Callbacks(): user provided callbacks and payloads.\n\nEquivalent to git push [|] [].\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LibGit2/#LibGit2.push!-Tuple{LibGit2.GitRevWalker, LibGit2.GitHash}","page":"LibGit2","title":"LibGit2.push!","text":"LibGit2.push!(w::GitRevWalker, cid::GitHash)\n\nStart the GitRevWalker walker at commit cid. This function can be used to apply a function to all commits since a certain year, by passing the first commit of that year as cid and then passing the resulting w to LibGit2.map.\n\n\n\n\n\n","category":"method"},{"location":"stdlib/LibGit2/#LibGit2.push_head!","page":"LibGit2","title":"LibGit2.push_head!","text":"LibGit2.push_head!(w::GitRevWalker)\n\nPush the HEAD commit and its ancestors onto the GitRevWalker w. This ensures that HEAD and all its ancestor commits will be encountered during the walk.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LibGit2/#LibGit2.push_refspecs","page":"LibGit2","title":"LibGit2.push_refspecs","text":"push_refspecs(rmt::GitRemote) -> Vector{String}\n\nGet the push refspecs for the specified rmt. These refspecs contain information about which branch(es) to push to.\n\nExamples\n\njulia> remote = LibGit2.get(LibGit2.GitRemote, repo, \"upstream\");\n\njulia> LibGit2.add_push!(repo, remote, \"refs/heads/master\");\n\njulia> close(remote);\n\njulia> remote = LibGit2.get(LibGit2.GitRemote, repo, \"upstream\");\n\njulia> LibGit2.push_refspecs(remote)\nString[\"refs/heads/master\"]\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LibGit2/#LibGit2.raw","page":"LibGit2","title":"LibGit2.raw","text":"raw(id::GitHash) -> Vector{UInt8}\n\nObtain the raw bytes of the GitHash as a vector of length 20.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LibGit2/#LibGit2.read_tree!","page":"LibGit2","title":"LibGit2.read_tree!","text":"LibGit2.read_tree!(idx::GitIndex, tree::GitTree)\nLibGit2.read_tree!(idx::GitIndex, treehash::AbstractGitHash)\n\nRead the tree tree (or the tree pointed to by treehash in the repository owned by idx) into the index idx. The current index contents will be replaced.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LibGit2/#LibGit2.rebase!","page":"LibGit2","title":"LibGit2.rebase!","text":"LibGit2.rebase!(repo::GitRepo, upstream::AbstractString=\"\", newbase::AbstractString=\"\")\n\nAttempt an automatic merge rebase of the current branch, from upstream if provided, or otherwise from the upstream tracking branch. newbase is the branch to rebase onto. By default this is upstream.\n\nIf any conflicts arise which cannot be automatically resolved, the rebase will abort, leaving the repository and working tree in its original state, and the function will throw a GitError. This is roughly equivalent to the following command line statement:\n\ngit rebase --merge []\nif [ -d \".git/rebase-merge\" ]; then\n git rebase --abort\nfi\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LibGit2/#LibGit2.ref_list","page":"LibGit2","title":"LibGit2.ref_list","text":"LibGit2.ref_list(repo::GitRepo) -> Vector{String}\n\nGet a list of all reference names in the repo repository.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LibGit2/#LibGit2.reftype","page":"LibGit2","title":"LibGit2.reftype","text":"LibGit2.reftype(ref::GitReference) -> Cint\n\nReturn a Cint corresponding to the type of ref:\n\n0 if the reference is invalid\n1 if the reference is an object id\n2 if the reference is symbolic\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LibGit2/#LibGit2.remotes","page":"LibGit2","title":"LibGit2.remotes","text":"LibGit2.remotes(repo::GitRepo)\n\nReturn a vector of the names of the remotes of repo.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LibGit2/#LibGit2.remove!","page":"LibGit2","title":"LibGit2.remove!","text":"remove!(repo::GitRepo, files::AbstractString...)\nremove!(idx::GitIndex, files::AbstractString...)\n\nRemove all the files with paths specified by files in the index idx (or the index of the repo).\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LibGit2/#LibGit2.reset","page":"LibGit2","title":"LibGit2.reset","text":"reset(val::Integer, flag::Integer)\n\nUnset the bits of val indexed by flag, returning them to 0.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LibGit2/#LibGit2.reset!","page":"LibGit2","title":"LibGit2.reset!","text":"reset!(payload, [config]) -> CredentialPayload\n\nReset the payload state back to the initial values so that it can be used again within the credential callback. If a config is provided the configuration will also be updated.\n\n\n\n\n\nUpdates some entries, determined by the pathspecs, in the index from the target commit tree.\n\n\n\n\n\nSets the current head to the specified commit oid and optionally resets the index and working tree to match.\n\n\n\n\n\ngit reset [] [–] ... \n\n\n\n\n\nreset!(repo::GitRepo, id::GitHash, mode::Cint=Consts.RESET_MIXED)\n\nReset the repository repo to its state at id, using one of three modes set by mode:\n\nConsts.RESET_SOFT - move HEAD to id.\nConsts.RESET_MIXED - default, move HEAD to id and reset the index to id.\nConsts.RESET_HARD - move HEAD to id, reset the index to id, and discard all working changes.\n\nExamples\n\n# fetch changes\nLibGit2.fetch(repo)\nisfile(joinpath(repo_path, our_file)) # will be false\n\n# fastforward merge the changes\nLibGit2.merge!(repo, fastforward=true)\n\n# because there was not any file locally, but there is\n# a file remotely, we need to reset the branch\nhead_oid = LibGit2.head_oid(repo)\nnew_head = LibGit2.reset!(repo, head_oid, LibGit2.Consts.RESET_HARD)\n\nIn this example, the remote which is being fetched from does have a file called our_file in its index, which is why we must reset.\n\nEquivalent to git reset [--soft | --mixed | --hard] .\n\nExamples\n\nrepo = LibGit2.GitRepo(repo_path)\nhead_oid = LibGit2.head_oid(repo)\nopen(joinpath(repo_path, \"file1\"), \"w\") do f\n write(f, \"111\n\")\nend\nLibGit2.add!(repo, \"file1\")\nmode = LibGit2.Consts.RESET_HARD\n# will discard the changes to file1\n# and unstage it\nnew_head = LibGit2.reset!(repo, head_oid, mode)\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LibGit2/#LibGit2.restore","page":"LibGit2","title":"LibGit2.restore","text":"restore(s::State, repo::GitRepo)\n\nReturn a repository repo to a previous State s, for example the HEAD of a branch before a merge attempt. s can be generated using the snapshot function.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LibGit2/#LibGit2.revcount","page":"LibGit2","title":"LibGit2.revcount","text":"LibGit2.revcount(repo::GitRepo, commit1::AbstractString, commit2::AbstractString)\n\nList the number of revisions between commit1 and commit2 (committish OIDs in string form). Since commit1 and commit2 may be on different branches, revcount performs a \"left-right\" revision list (and count), returning a tuple of Ints - the number of left and right commits, respectively. A left (or right) commit refers to which side of a symmetric difference in a tree the commit is reachable from.\n\nEquivalent to git rev-list --left-right --count .\n\nExamples\n\nrepo = LibGit2.GitRepo(repo_path)\nrepo_file = open(joinpath(repo_path, test_file), \"a\")\nprintln(repo_file, \"hello world\")\nflush(repo_file)\nLibGit2.add!(repo, test_file)\ncommit_oid1 = LibGit2.commit(repo, \"commit 1\")\nprintln(repo_file, \"hello world again\")\nflush(repo_file)\nLibGit2.add!(repo, test_file)\ncommit_oid2 = LibGit2.commit(repo, \"commit 2\")\nLibGit2.revcount(repo, string(commit_oid1), string(commit_oid2))\n\nThis will return (-1, 0).\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LibGit2/#LibGit2.set_remote_url","page":"LibGit2","title":"LibGit2.set_remote_url","text":"set_remote_url(repo::GitRepo, remote_name, url)\nset_remote_url(repo::String, remote_name, url)\n\nSet both the fetch and push url for remote_name for the GitRepo or the git repository located at path. Typically git repos use \"origin\" as the remote name.\n\nExamples\n\nrepo_path = joinpath(tempdir(), \"Example\")\nrepo = LibGit2.init(repo_path)\nLibGit2.set_remote_url(repo, \"upstream\", \"https://github.com/JuliaLang/Example.jl\")\nLibGit2.set_remote_url(repo_path, \"upstream2\", \"https://github.com/JuliaLang/Example2.jl\")\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LibGit2/#LibGit2.shortname","page":"LibGit2","title":"LibGit2.shortname","text":"LibGit2.shortname(ref::GitReference)\n\nReturn a shortened version of the name of ref that's \"human-readable\".\n\njulia> repo = LibGit2.GitRepo(path_to_repo);\n\njulia> branch_ref = LibGit2.head(repo);\n\njulia> LibGit2.name(branch_ref)\n\"refs/heads/master\"\n\njulia> LibGit2.shortname(branch_ref)\n\"master\"\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LibGit2/#LibGit2.snapshot","page":"LibGit2","title":"LibGit2.snapshot","text":"snapshot(repo::GitRepo) -> State\n\nTake a snapshot of the current state of the repository repo, storing the current HEAD, index, and any uncommitted work. The output State can be used later during a call to restore to return the repository to the snapshotted state.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LibGit2/#LibGit2.split_cfg_entry","page":"LibGit2","title":"LibGit2.split_cfg_entry","text":"LibGit2.split_cfg_entry(ce::LibGit2.ConfigEntry) -> Tuple{String,String,String,String}\n\nBreak the ConfigEntry up to the following pieces: section, subsection, name, and value.\n\nExamples\n\nGiven the git configuration file containing:\n\n[credential \"https://example.com\"]\n username = me\n\nThe ConfigEntry would look like the following:\n\njulia> entry\nConfigEntry(\"credential.https://example.com.username\", \"me\")\n\njulia> LibGit2.split_cfg_entry(entry)\n(\"credential\", \"https://example.com\", \"username\", \"me\")\n\nRefer to the git config syntax documentation for more details.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LibGit2/#LibGit2.status","page":"LibGit2","title":"LibGit2.status","text":"LibGit2.status(repo::GitRepo, path::String) -> Union{Cuint, Cvoid}\n\nLookup the status of the file at path in the git repository repo. For instance, this can be used to check if the file at path has been modified and needs to be staged and committed.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LibGit2/#LibGit2.stage","page":"LibGit2","title":"LibGit2.stage","text":"stage(ie::IndexEntry) -> Cint\n\nGet the stage number of ie. The stage number 0 represents the current state of the working tree, but other numbers can be used in the case of a merge conflict. In such a case, the various stage numbers on an IndexEntry describe which side(s) of the conflict the current state of the file belongs to. Stage 0 is the state before the attempted merge, stage 1 is the changes which have been made locally, stages 2 and larger are for changes from other branches (for instance, in the case of a multi-branch \"octopus\" merge, stages 2, 3, and 4 might be used).\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LibGit2/#LibGit2.tag_create","page":"LibGit2","title":"LibGit2.tag_create","text":"LibGit2.tag_create(repo::GitRepo, tag::AbstractString, commit; kwargs...)\n\nCreate a new git tag tag (e.g. \"v0.5\") in the repository repo, at the commit commit.\n\nThe keyword arguments are:\n\nmsg::AbstractString=\"\": the message for the tag.\nforce::Bool=false: if true, existing references will be overwritten.\nsig::Signature=Signature(repo): the tagger's signature.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LibGit2/#LibGit2.tag_delete","page":"LibGit2","title":"LibGit2.tag_delete","text":"LibGit2.tag_delete(repo::GitRepo, tag::AbstractString)\n\nRemove the git tag tag from the repository repo.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LibGit2/#LibGit2.tag_list","page":"LibGit2","title":"LibGit2.tag_list","text":"LibGit2.tag_list(repo::GitRepo) -> Vector{String}\n\nGet a list of all tags in the git repository repo.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LibGit2/#LibGit2.target","page":"LibGit2","title":"LibGit2.target","text":"LibGit2.target(tag::GitTag)\n\nThe GitHash of the target object of tag.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LibGit2/#LibGit2.toggle","page":"LibGit2","title":"LibGit2.toggle","text":"toggle(val::Integer, flag::Integer)\n\nFlip the bits of val indexed by flag, so that if a bit is 0 it will be 1 after the toggle, and vice-versa.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LibGit2/#LibGit2.transact","page":"LibGit2","title":"LibGit2.transact","text":"transact(f::Function, repo::GitRepo)\n\nApply function f to the git repository repo, taking a snapshot before applying f. If an error occurs within f, repo will be returned to its snapshot state using restore. The error which occurred will be rethrown, but the state of repo will not be corrupted.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LibGit2/#LibGit2.treewalk","page":"LibGit2","title":"LibGit2.treewalk","text":"treewalk(f, tree::GitTree, post::Bool=false)\n\nTraverse the entries in tree and its subtrees in post or pre order. Preorder means beginning at the root and then traversing the leftmost subtree (and recursively on down through that subtree's leftmost subtrees) and moving right through the subtrees. Postorder means beginning at the bottom of the leftmost subtree, traversing upwards through it, then traversing the next right subtree (again beginning at the bottom) and finally visiting the tree root last of all.\n\nThe function parameter f should have following signature:\n\n(String, GitTreeEntry) -> Cint\n\nA negative value returned from f stops the tree walk. A positive value means that the entry will be skipped if post is false.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LibGit2/#LibGit2.upstream","page":"LibGit2","title":"LibGit2.upstream","text":"upstream(ref::GitReference) -> Union{GitReference, Nothing}\n\nDetermine if the branch containing ref has a specified upstream branch.\n\nReturn either a GitReference to the upstream branch if it exists, or nothing if the requested branch does not have an upstream counterpart.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LibGit2/#LibGit2.update!","page":"LibGit2","title":"LibGit2.update!","text":"update!(repo::GitRepo, files::AbstractString...)\nupdate!(idx::GitIndex, files::AbstractString...)\n\nUpdate all the files with paths specified by files in the index idx (or the index of the repo). Match the state of each file in the index with the current state on disk, removing it if it has been removed on disk, or updating its entry in the object database.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LibGit2/#LibGit2.url","page":"LibGit2","title":"LibGit2.url","text":"url(rmt::GitRemote)\n\nGet the fetch URL of a remote git repository.\n\nExamples\n\njulia> repo_url = \"https://github.com/JuliaLang/Example.jl\";\n\njulia> repo = LibGit2.init(mktempdir());\n\njulia> remote = LibGit2.GitRemote(repo, \"origin\", repo_url);\n\njulia> LibGit2.url(remote)\n\"https://github.com/JuliaLang/Example.jl\"\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LibGit2/#LibGit2.version","page":"LibGit2","title":"LibGit2.version","text":"version() -> VersionNumber\n\nReturn the version of libgit2 in use, as a VersionNumber.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LibGit2/#LibGit2.with","page":"LibGit2","title":"LibGit2.with","text":"with(f::Function, obj)\n\nResource management helper function. Applies f to obj, making sure to call close on obj after f successfully returns or throws an error. Ensures that allocated git resources are finalized as soon as they are no longer needed.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LibGit2/#LibGit2.with_warn","page":"LibGit2","title":"LibGit2.with_warn","text":"with_warn(f::Function, ::Type{T}, args...)\n\nResource management helper function. Apply f to args, first constructing an instance of type T from args. Makes sure to call close on the resulting object after f successfully returns or throws an error. Ensures that allocated git resources are finalized as soon as they are no longer needed. If an error is thrown by f, a warning is shown containing the error.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LibGit2/#LibGit2.workdir","page":"LibGit2","title":"LibGit2.workdir","text":"LibGit2.workdir(repo::GitRepo)\n\nReturn the location of the working directory of repo. This will throw an error for bare repositories.\n\nnote: Note\nThis will typically be the parent directory of gitdir(repo), but can be different in some cases: e.g. if either the core.worktree configuration variable or the GIT_WORK_TREE environment variable is set.\n\nSee also gitdir, path.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LibGit2/#LibGit2.GitObject-Tuple{LibGit2.GitTreeEntry}","page":"LibGit2","title":"LibGit2.GitObject","text":"(::Type{T})(te::GitTreeEntry) where T<:GitObject\n\nGet the git object to which te refers and return it as its actual type (the type entrytype would show), for instance a GitBlob or GitTag.\n\nExamples\n\ntree = LibGit2.GitTree(repo, \"HEAD^{tree}\")\ntree_entry = tree[1]\nblob = LibGit2.GitBlob(tree_entry)\n\n\n\n\n\n","category":"method"},{"location":"stdlib/LibGit2/#LibGit2.UserPasswordCredential","page":"LibGit2","title":"LibGit2.UserPasswordCredential","text":"Credential that support only user and password parameters\n\n\n\n\n\n","category":"type"},{"location":"stdlib/LibGit2/#LibGit2.SSHCredential","page":"LibGit2","title":"LibGit2.SSHCredential","text":"SSH credential type\n\n\n\n\n\n","category":"type"},{"location":"stdlib/LibGit2/#LibGit2.isfilled","page":"LibGit2","title":"LibGit2.isfilled","text":"isfilled(cred::AbstractCredential) -> Bool\n\nVerifies that a credential is ready for use in authentication.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LibGit2/#LibGit2.CachedCredentials","page":"LibGit2","title":"LibGit2.CachedCredentials","text":"Caches credential information for re-use\n\n\n\n\n\n","category":"type"},{"location":"stdlib/LibGit2/#LibGit2.CredentialPayload","page":"LibGit2","title":"LibGit2.CredentialPayload","text":"LibGit2.CredentialPayload\n\nRetains the state between multiple calls to the credential callback for the same URL. A CredentialPayload instance is expected to be reset! whenever it will be used with a different URL.\n\n\n\n\n\n","category":"type"},{"location":"stdlib/LibGit2/#LibGit2.approve","page":"LibGit2","title":"LibGit2.approve","text":"approve(payload::CredentialPayload; shred::Bool=true) -> Nothing\n\nStore the payload credential for re-use in a future authentication. Should only be called when authentication was successful.\n\nThe shred keyword controls whether sensitive information in the payload credential field should be destroyed. Should only be set to false during testing.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LibGit2/#LibGit2.reject","page":"LibGit2","title":"LibGit2.reject","text":"reject(payload::CredentialPayload; shred::Bool=true) -> Nothing\n\nDiscard the payload credential from begin re-used in future authentication. Should only be called when authentication was unsuccessful.\n\nThe shred keyword controls whether sensitive information in the payload credential field should be destroyed. Should only be set to false during testing.\n\n\n\n\n\n","category":"function"},{"location":"base/punctuation/#运算符与记号","page":"运算符与记号","title":"运算符与记号","text":"","category":"section"},{"location":"base/punctuation/","page":"运算符与记号","title":"运算符与记号","text":"数学符号与函数的扩展文档在 这里.","category":"page"},{"location":"base/punctuation/","page":"运算符与记号","title":"运算符与记号","text":"符号 含义\n@ the at-sign marks a macro invocation; optionally followed by an argument list\n! 感叹号是一个表示逻辑否定的前缀算符\na! 在函数名的末尾,! 用作表示函数会修改参数(或多个参数)\n# the number sign (or hash or pound) character begins single line comments\n#= when followed by an equals sign, it begins a multi-line comment (these are nestable)\n=# end a multi-line comment by immediately preceding the number sign with an equals sign\n$ the dollar sign is used for string and expression interpolation\n% the percent symbol is the remainder operator\n^ the caret is the exponentiation operator\n& single ampersand is bitwise and\n&& double ampersands is short-circuiting boolean and\n| single pipe character is bitwise or\n|| double pipe characters is short-circuiting boolean or\n⊻ the unicode xor character is bitwise exclusive or\n~ the tilde is an operator for bitwise not\n' a trailing apostrophe is the adjoint (that is, the complex transpose) operator Aᴴ\n* the asterisk is used for multiplication, including matrix multiplication and string concatenation\n/ forward slash divides the argument on its left by the one on its right\n\\ backslash operator divides the argument on its right by the one on its left, commonly used to solve matrix equations\n() parentheses with no arguments constructs an empty Tuple\n(a,...) parentheses with comma-separated arguments constructs a tuple containing its arguments\n(a=1,...) parentheses with comma-separated assignments constructs a NamedTuple\n(x;y) parentheses can also be used to group one or more semicolon separated expressions\na[] array indexing (calling getindex or setindex!)\n[,] vector literal constructor (calling vect)\n[;] vertical concatenation (calling vcat or hvcat)\n[   ] with space-separated expressions, horizontal concatenation (calling hcat or hvcat)\nT{ } curly braces following a type list that type's parameters\n{} curly braces can also be used to group multiple where expressions in function declarations\n; semicolons separate statements, begin a list of keyword arguments in function declarations or calls, or are used to separate array literals for vertical concatenation\n, commas separate function arguments or tuple or array components\n? the question mark delimits the ternary conditional operator (used like: conditional ? if_true : if_false)\n\" \" the single double-quote character delimits String literals\n\"\"\" \"\"\" three double-quote characters delimits string literals that may contain \" and ignore leading indentation\n' ' the single-quote character delimits Char (that is, character) literals\n` ` the backtick character delimits external process (Cmd) literals\nA... triple periods are a postfix operator that \"splat\" their arguments' contents into many arguments of a function call or declare a varargs function that \"slurps\" up many arguments into a single tuple\na.b single periods access named fields in objects/modules (calling getproperty or setproperty!)\nf.() periods may also prefix parentheses (like f.(...)) or infix operators (like .+) to perform the function element-wise (calling broadcast)\na:b colons (:) used as a binary infix operator construct a range from a to b (inclusive) with fixed step size 1\na:s:b colons (:) used as a ternary infix operator construct a range from a to b (inclusive) with step size s\n: when used by themselves, Colons represent all indices within a dimension, frequently combined with indexing\n:: double-colons represent a type annotation or typeassert, depending on context, frequently used when declaring function arguments\n:( ) quoted expression\n:a Symbol a\n<: 子类型运算符\n>: supertype operator (reverse of subtype operator)\n= single equals sign is assignment\n== double equals sign is value equality comparison\n=== triple equals sign is programmatically identical equality comparison\n=> right arrow using an equals sign defines a Pair typically used to populate dictionaries\n-> right arrow using a hyphen defines an anonymous function on a single line\n` >`\n∘ function composition operator (typed with \\circ{tab}) combines two functions as though they are a single larger function","category":"page"},{"location":"manual/multi-threading/#man-multithreading","page":"多线程","title":"多线程","text":"","category":"section"},{"location":"manual/multi-threading/","page":"多线程","title":"多线程","text":"访问此 博客文章 以了解 Julia 多线程特性。","category":"page"},{"location":"manual/multi-threading/#启用Julia多线程","page":"多线程","title":"启用Julia多线程","text":"","category":"section"},{"location":"manual/multi-threading/","page":"多线程","title":"多线程","text":"Julia 默认启动一个线程执行代码,这点可以通过 Threads.nthreads() 来确认:","category":"page"},{"location":"manual/multi-threading/","page":"多线程","title":"多线程","text":"julia> Threads.nthreads()\n1","category":"page"},{"location":"manual/multi-threading/","page":"多线程","title":"多线程","text":"执行线程的数量通过使用-t/--threads 命令行参数或使用JULIA_NUM_THREADS 环境变量。 当两者都被指定时,-t/--threads 优先级更高。","category":"page"},{"location":"manual/multi-threading/","page":"多线程","title":"多线程","text":"compat: Julia 1.5\n-t/--threads 命令行参数至少需要 Julia 1.5。在旧版本中,你必须改用环境变量。","category":"page"},{"location":"manual/multi-threading/","page":"多线程","title":"多线程","text":"让我们以4个线程启动Julia","category":"page"},{"location":"manual/multi-threading/","page":"多线程","title":"多线程","text":"$ julia --threads 4","category":"page"},{"location":"manual/multi-threading/","page":"多线程","title":"多线程","text":"现在确认下确实有4个线程:","category":"page"},{"location":"manual/multi-threading/","page":"多线程","title":"多线程","text":"julia> Threads.nthreads()\n4","category":"page"},{"location":"manual/multi-threading/","page":"多线程","title":"多线程","text":"不过我们现在是在 master 线程,用 Threads.threadid 确认下:","category":"page"},{"location":"manual/multi-threading/","page":"多线程","title":"多线程","text":"julia> Threads.threadid()\n1","category":"page"},{"location":"manual/multi-threading/","page":"多线程","title":"多线程","text":"note: Note\n如果你更喜欢使用环境变量,可以按如下方式设置它 Bash (Linux/macOS):export JULIA_NUM_THREADS=4C shell on Linux/macOS, CMD on Windows:set JULIA_NUM_THREADS=4Powershell on Windows:$env:JULIA_NUM_THREADS=4Note that this must be done before starting Julia.","category":"page"},{"location":"manual/multi-threading/","page":"多线程","title":"多线程","text":"note: Note\n使用 -t/--threads 指定的线程数传播到使用 -p/--procs 或 --machine-file 命令行选项产生的工作进程。 例如,julia -p2 -t2 产生 1 个主进程和 2 个工作进程,并且所有三个进程都启用了 2 个线程。 要对工作线程进行更细粒度的控制,请使用 addprocs 并将 -t/--threads 作为 exeflags 传递。","category":"page"},{"location":"manual/multi-threading/#数据竞争自由","page":"多线程","title":"数据竞争自由","text":"","category":"section"},{"location":"manual/multi-threading/","page":"多线程","title":"多线程","text":"你有责任确保程序没有数据竞争,如果你不遵守该要求,则不能假设这里承诺的任何内容。 观察到的结果可能是反直觉的。","category":"page"},{"location":"manual/multi-threading/","page":"多线程","title":"多线程","text":"为了确保这一点,最好的办法是获取多线程同时访问的数据的锁。 例如,在大多数情况下,你应该使用以下代码模板:","category":"page"},{"location":"manual/multi-threading/","page":"多线程","title":"多线程","text":"julia> lock(lk) do\n use(a)\n end\n\njulia> begin\n lock(lk)\n try\n use(a)\n finally\n unlock(lk)\n end\n end","category":"page"},{"location":"manual/multi-threading/","page":"多线程","title":"多线程","text":"其中 lk 是一个锁(例如 ReentrantLock()), a 是数据。","category":"page"},{"location":"manual/multi-threading/","page":"多线程","title":"多线程","text":"此外,Julia 在出现数据竞争时不是内存安全的。如果另一个线程可能会写入数据,则在读取任何数据时都要非常小心! 相反,在更改其他线程访问的数据(例如分配给全局或闭包变量)时,请始终使用上述锁模式。","category":"page"},{"location":"manual/multi-threading/","page":"多线程","title":"多线程","text":"Thread 1:\nglobal b = false\nglobal a = rand()\nglobal b = true\n\nThread 2:\nwhile !b; end\nbad_read1(a) # it is NOT safe to access `a` here!\n\nThread 3:\nwhile !@isdefined(a); end\nbad_read2(a) # it is NOT safe to access `a` here","category":"page"},{"location":"manual/multi-threading/#@threads宏","page":"多线程","title":"@threads宏","text":"","category":"section"},{"location":"manual/multi-threading/","page":"多线程","title":"多线程","text":"下面用一个简单的例子测试我们原生的线程,首先创建一个全零的数组:","category":"page"},{"location":"manual/multi-threading/","page":"多线程","title":"多线程","text":"julia> a = zeros(10)\n10-element Vector{Float64}:\n 0.0\n 0.0\n 0.0\n 0.0\n 0.0\n 0.0\n 0.0\n 0.0\n 0.0\n 0.0","category":"page"},{"location":"manual/multi-threading/","page":"多线程","title":"多线程","text":"现在用4个线程模拟操作这个数组,每个线程往对应的位置写入线程ID。","category":"page"},{"location":"manual/multi-threading/","page":"多线程","title":"多线程","text":"Julia 用 Threads.@threads 宏实现并行循环,该宏加在 for 循环前面,提示 Julia 循环部分是一个多线程的区域:","category":"page"},{"location":"manual/multi-threading/","page":"多线程","title":"多线程","text":"julia> Threads.@threads for i = 1:10\n a[i] = Threads.threadid()\n end","category":"page"},{"location":"manual/multi-threading/","page":"多线程","title":"多线程","text":"根据线程调度,迭代在各线程中进行拆分,之后各线程将自己的线程ID写入对应区域。","category":"page"},{"location":"manual/multi-threading/","page":"多线程","title":"多线程","text":"julia> a\n10-element Vector{Float64}:\n 1.0\n 1.0\n 1.0\n 2.0\n 2.0\n 2.0\n 3.0\n 3.0\n 4.0\n 4.0","category":"page"},{"location":"manual/multi-threading/","page":"多线程","title":"多线程","text":"注意 Threads.@threads 并没有一个像 @distributed 一样的可选的 reduction 参数。","category":"page"},{"location":"manual/multi-threading/#原子操作","page":"多线程","title":"原子操作","text":"","category":"section"},{"location":"manual/multi-threading/","page":"多线程","title":"多线程","text":"Julia 支持访问和修改值的原子操作,即以一种线程安全的方式来避免竞态条件。一个值(必须是基本类型的,primitive type)可以通过 Threads.Atomic 来包装起来从而支持原子操作。下面看个例子:","category":"page"},{"location":"manual/multi-threading/","page":"多线程","title":"多线程","text":"julia> i = Threads.Atomic{Int}(0);\n\njulia> ids = zeros(4);\n\njulia> old_is = zeros(4);\n\njulia> Threads.@threads for id in 1:4\n old_is[id] = Threads.atomic_add!(i, id)\n ids[id] = id\n end\n\njulia> old_is\n4-element Vector{Float64}:\n 0.0\n 1.0\n 7.0\n 3.0\n\njulia> i[]\n 10\n\njulia> ids\n4-element Vector{Float64}:\n 1.0\n 2.0\n 3.0\n 4.0","category":"page"},{"location":"manual/multi-threading/","page":"多线程","title":"多线程","text":"如果不加 Atomic 的话,那么会因为竞态条件而得到错误的结果,下面是一个没有避免竞态条件的例子:","category":"page"},{"location":"manual/multi-threading/","page":"多线程","title":"多线程","text":"julia> using Base.Threads\n\njulia> nthreads()\n4\n\njulia> acc = Ref(0)\nBase.RefValue{Int64}(0)\n\njulia> @threads for i in 1:1000\n acc[] += 1\n end\n\njulia> acc[]\n926\n\njulia> acc = Atomic{Int64}(0)\nAtomic{Int64}(0)\n\njulia> @threads for i in 1:1000\n atomic_add!(acc, 1)\n end\n\njulia> acc[]\n1000","category":"page"},{"location":"manual/multi-threading/#man-atomics","page":"多线程","title":"field粒度的原子操作","text":"","category":"section"},{"location":"manual/multi-threading/","page":"多线程","title":"多线程","text":"我们还可以使用@atomic、@atomicswap和@atomicreplace 宏在更细粒度的级别上使用原子。","category":"page"},{"location":"manual/multi-threading/","page":"多线程","title":"多线程","text":"内存模型的具体细节和设计的其他细节写在Julia Atomics Manifesto中,稍后将正式发布。","category":"page"},{"location":"manual/multi-threading/","page":"多线程","title":"多线程","text":"struct 声明中的任何字段都可以用 @atomic 修饰,然后任何写入也必须用 @atomic 标记,并且必须使用定义的原子顺序之一(:monotonic、:acquire、:release、:acquire _release 或 :sequentially_consistent)。 对原子字段的任何读取也可以使用原子排序约束进行注释,或者如果未指定,将使用单调(宽松)排序完成。","category":"page"},{"location":"manual/multi-threading/","page":"多线程","title":"多线程","text":"compat: Julia 1.7\nfield粒度的原子操作至少需要 Julia 1.7.","category":"page"},{"location":"manual/multi-threading/#副作用和可变的函数参数","page":"多线程","title":"副作用和可变的函数参数","text":"","category":"section"},{"location":"manual/multi-threading/","page":"多线程","title":"多线程","text":"使用多线程时,我们必须小心使用非 纯 的函数,因为我们可能会得到错误的答案。 例如,按照惯例具有 名称以! 结尾 的函数会修改它们的参数,因此不是纯函数。","category":"page"},{"location":"manual/multi-threading/#@threadcall","page":"多线程","title":"@threadcall","text":"","category":"section"},{"location":"manual/multi-threading/","page":"多线程","title":"多线程","text":"外部库,例如通过 ccall 调用的库,给 Julia 基于任务的 I/O 机制带来了问题。 如果 C 库执行阻塞操作,这会阻止 Julia 调度程序执行任何其他任务,直到调用返回。(例外情况是调用回调到 Julia 的自定义 C 代码,然后它可能会 yield,或者调用 jl_yield() 的 C 代码,jl_yield 是 yield 的 C 等价物。)","category":"page"},{"location":"manual/multi-threading/","page":"多线程","title":"多线程","text":"@threadcall 宏提供了一种避免在这种情况下停止执行的方法。它调度一个 C 函数以在单独的线程中执行。为此使用默认大小为 4 的线程池。线程池的大小由环境变量UV_THREADPOOL_SIZE控制。 在等待空闲线程时,以及一旦线程可用后的函数执行期间,请求任务(在主 Julia 事件循环上)让步给其他任务。 注意,@threadcall 在执行完成之前不会返回。 因此,从用户的角度来看,它与其他 Julia API 一样是一个阻塞调用。","category":"page"},{"location":"manual/multi-threading/","page":"多线程","title":"多线程","text":"非常关键的一点是,被调用的函数不会再调用回 Julia。","category":"page"},{"location":"manual/multi-threading/","page":"多线程","title":"多线程","text":"@threadcall 在 Julia 未来的版本中可能会被移除或改变。","category":"page"},{"location":"manual/multi-threading/#注意!","page":"多线程","title":"注意!","text":"","category":"section"},{"location":"manual/multi-threading/","page":"多线程","title":"多线程","text":"此时,如果用户代码没有数据竞争,Julia 运行时和标准库中的大多数操作都可以以线程安全的方式使用。 然而,在某些领域,稳定线程支持的工作正在进行中。多线程编程有许多内在的困难,如果使用线程的程序表现出异常或与预期不符的行为(例如崩溃或神秘的结果),通常应该首先怀疑线程交互。","category":"page"},{"location":"manual/multi-threading/","page":"多线程","title":"多线程","text":"在 Julia 中使用线程时需要注意以下这些特定的限制和警告:","category":"page"},{"location":"manual/multi-threading/","page":"多线程","title":"多线程","text":"如果多个线程同时使用基本容器类型,且至少有一个线程修改容器时,需要手动加锁(常见示例包括 push! 数组,或将项插入 Dict)。\n任务开始在某个线程上运行后(例如通过@spawn),它会在阻塞后始终在同一线程上重新启动。 将来这个限制将被移除,任务会在线程之间迁移。\n@threads 当前使用静态调度,使用所有线程并为每个线程分配相等的迭代计数。将来,默认时间表可能会更改为动态的。\n@spawn 使用的时间表是不确定的,不应依赖。\n计算绑定、非内存分配任务可以防止垃圾回收在其他正在分配内存的线程中运行。 在这些情况下,可能需要手动调用 GC.safepoint() 以允许 GC 运行。\n该限制在未来会被移除。\n避免并行运行顶层操作,例如,include 或 eval 评估类型、方法和模块定义。\n请注意,如果启用线程,则库注册的终结器可能会中断。 这可能需要在整个生态系统中进行一些过渡工作,然后才能放心地广泛采用线程。 有关更多详细信息,请参阅下一节。","category":"page"},{"location":"manual/multi-threading/#终结器的安全使用","page":"多线程","title":"终结器的安全使用","text":"","category":"section"},{"location":"manual/multi-threading/","page":"多线程","title":"多线程","text":"因为终结器可以中断任何代码,所以它们在如何与任何全局状态交互时必须非常小心。 不幸的是,使用终结器的主要原因是更新全局状态(纯函数作为终结器通常毫无意义)。 这让我们陷入了一个难题。 有几种方法可以处理这个问题:","category":"page"},{"location":"manual/multi-threading/","page":"多线程","title":"多线程","text":"当单线程时,代码可以调用内部 jl_gc_enable_finalizers C 函数以防止在关键区域内调度终结器。 在内部,这在某些函数(例如我们的 C locks)中使用,以防止在执行某些操作(增量包加载、代码生成等)时发生递归。 锁和此标志的组合可用于使终结器安全。\nBase 在几个地方采用的第二种策略是显式延迟终结器,直到它可以非递归地获取其锁。 以下示例演示了如何将此策略应用于 Distributed.finalize_ref:\nfunction finalize_ref(r::AbstractRemoteRef)\n if r.where > 0 # Check if the finalizer is already run\n if islocked(client_refs) || !trylock(client_refs)\n # delay finalizer for later if we aren't free to acquire the lock\n finalizer(finalize_ref, r)\n return nothing\n end\n try # `lock` should always be followed by `try`\n if r.where > 0 # Must check again here\n # Do actual cleanup here\n r.where = 0\n end\n finally\n unlock(client_refs)\n end\n end\n nothing\nend\n相关的第三种策略是使用不需要 yield 的队列。 我们目前没有在 Base 中实现无锁队列,但 Base.InvasiveLinkedListSynchronized{T} 是合适的。 这通常是用于带有事件循环的代码的好策略。 例如,这个策略被 Gtk.jl 用来管理生命周期引用计数。 在这种方法中,我们不会在终结器内部做任何显式工作,而是将其添加到队列中以在更安全的时间运行。 事实上,Julia 的任务调度器已经使用了这种方法,因此将终结器定义为 x -> @spawn do_cleanup(x) 就是这种方法的一个示例。 但是请注意,这并不控制 do_cleanup 在哪个线程上运行,因此 do_cleanup 仍需要获取锁。 如果你实现自己的队列,则不必如此,因为你只能明确地从线程中排出该队列。","category":"page"},{"location":"manual/methods/#方法","page":"方法","title":"方法","text":"","category":"section"},{"location":"manual/methods/","page":"方法","title":"方法","text":"我们回想一下,在函数中我们知道函数是这么一个对象,它把一组参数映射成一个返回值,或者当没有办法返回恰当的值时扔出一个异常。具有相同概念的函数或者运算,经常会根据参数类型的不同而进行有很大差异的实现:两个整数的加法与两个浮点数的加法是相当不一样的,整数与浮点数之间的加法也不一样。除了它们实现上的不同,这些运算都归在\"加法\"这么一个广义的概念之下,因此在 Julia 中这些行为都属于同一个对象:+ 函数。","category":"page"},{"location":"manual/methods/","page":"方法","title":"方法","text":"为了让对同样的概念使用许多不同的实现这件事更顺畅,函数没有必要马上全部都被定义,反而应该是一块一块地定义,为特定的参数类型和数量的组合提供指定的行为。对于一个函数的一个可能行为的定义叫做方法。直到这里,我们只展示了那些只定了一个方法的,对参数的所有类型都适用的函数。但是方法定义的特征是不仅能表明参数的数量,也能表明参数的类型,并且能提供多个方法定义。当一个函数被应用于特殊的一组参数时,能用于这一组参数的最特定的方法会被使用。所以,函数的全体行为是他的不同的方法定义的行为的组合。如果这个组合被设计得好,即使方法们的实现之间会很不一样,函数的外部行为也会显得无缝而自洽。","category":"page"},{"location":"manual/methods/","page":"方法","title":"方法","text":"当一个函数被应用时执行方法的选择被称为 分派。Julia 允许分派过程基于给定的参数个数和所有参数的类型来选择调用函数的哪个方法。这与传统的面对对象的语言不一样,面对对象语言的分派只基于第一参数,经常有特殊的参数语法,并且有时是暗含而非显式写成一个参数。 [1] 使用函数的所有参数,而非只用第一个,来决定调用哪个方法被称为多重分派。多重分派对于数学代码来说特别有用,人工地将运算视为对于其中一个参数的属于程度比其他所有的参数都强的这个概念对于数学代码是几乎没有意义的:x + y 中的加法运算对 x 的属于程度比对 y 更强?一个数学运算符的实现普遍基于它所有的参数的类型。即使跳出数学运算,多重分派是对于结构和组织程序来说也是一个强大而方便的范式。","category":"page"},{"location":"manual/methods/","page":"方法","title":"方法","text":"[1]: In C++ or Java, for example, in a method call like obj.meth(arg1,arg2), the object obj \"receives\" the method call and is implicitly passed to the method via the this keyword, rather than as an explicit method argument. When the current this object is the receiver of a method call, it can be omitted altogether, writing just meth(arg1,arg2), with this implied as the receiving object.","category":"page"},{"location":"manual/methods/","page":"方法","title":"方法","text":"note: Note\n本章中的所有示例都假定是为相同模块中的函数定义模块。 如果你想给另一个模块中的函数添加方法,你必须import它或使用模块名称限定的名称。 请参阅有关 命名空间管理 的部分。","category":"page"},{"location":"manual/methods/#定义方法","page":"方法","title":"定义方法","text":"","category":"section"},{"location":"manual/methods/","page":"方法","title":"方法","text":"直到这里,在我们的例子中,我们定义的函数只有一个不限制参数类型的方法。这种函数的行为就与传统动态类型语言中的函数一样。不过,我们已经在没有意识到的情况下已经使用了多重分派和方法:所有 Julia 标准函数和运算符,就像之前提到的 + 函数,都根据参数的类型和数量的不同组合而定义了大量方法。","category":"page"},{"location":"manual/methods/","page":"方法","title":"方法","text":"当定义一个函数时,可以根据需要使用在复合类型中介绍的 :: 类型断言运算符来限制参数类型,","category":"page"},{"location":"manual/methods/","page":"方法","title":"方法","text":"julia> f(x::Float64, y::Float64) = 2x + y\nf (generic function with 1 method)","category":"page"},{"location":"manual/methods/","page":"方法","title":"方法","text":"这个函数只在 x 和 y 的类型都是 Float64 的情况下才会被调用:","category":"page"},{"location":"manual/methods/","page":"方法","title":"方法","text":"julia> f(2.0, 3.0)\n7.0","category":"page"},{"location":"manual/methods/","page":"方法","title":"方法","text":"用其它任意的参数类型则会导致 MethodError:","category":"page"},{"location":"manual/methods/","page":"方法","title":"方法","text":"julia> f(2.0, 3)\nERROR: MethodError: no method matching f(::Float64, ::Int64)\nClosest candidates are:\n f(::Float64, !Matched::Float64) at none:1\n\njulia> f(Float32(2.0), 3.0)\nERROR: MethodError: no method matching f(::Float32, ::Float64)\nClosest candidates are:\n f(!Matched::Float64, ::Float64) at none:1\n\njulia> f(2.0, \"3.0\")\nERROR: MethodError: no method matching f(::Float64, ::String)\nClosest candidates are:\n f(::Float64, !Matched::Float64) at none:1\n\njulia> f(\"2.0\", \"3.0\")\nERROR: MethodError: no method matching f(::String, ::String)","category":"page"},{"location":"manual/methods/","page":"方法","title":"方法","text":"如同你所看到的,参数必须精确地是 Float64 类型。其它数字类型,比如整数或者 32 位浮点数值,都不会自动转化成 64 位浮点数,字符串也不会解析成数字。由于 Float64 是一个具体类型,且在 Julia 中具体类型无法拥有子类,所以这种定义方式只能适用于函数的输入类型精确地是 Float64 的情况,但一个常见的做法是用抽象类型来定义通用的方法:","category":"page"},{"location":"manual/methods/","page":"方法","title":"方法","text":"julia> f(x::Number, y::Number) = 2x - y\nf (generic function with 2 methods)\n\njulia> f(2.0, 3)\n1.0","category":"page"},{"location":"manual/methods/","page":"方法","title":"方法","text":"用上面这种方式定义的方法可以接收任意一对 Number 的实例参数,且它们不需要是同一类型的,只要求都是数值。如何根据不同的类型来做相应的处理就可以委托给表达式 2x - y 中的代数运算。","category":"page"},{"location":"manual/methods/","page":"方法","title":"方法","text":"为了定义一个有多个方法的函数,只需简单定义这个函数多次,使用不同的参数数量和类型。函数的第一个方法定义会建立这个函数对象,后续的方法定义会添加新的方法到存在的函数对象中去。当函数被应用时,最符合参数的数量和类型的特定方法会被执行。所以,上面的两个方法定义在一起定义了函数f对于所有的一对虚拟类型Number实例的行为 – 但是针对一对Float64值有不同的行为。如果一个参数是64位浮点数而另一个不是,f(Float64,Float64)方法不会被调用,而一定使用更加通用的f(Number,Number)方法:","category":"page"},{"location":"manual/methods/","page":"方法","title":"方法","text":"julia> f(2.0, 3.0)\n7.0\n\njulia> f(2, 3.0)\n1.0\n\njulia> f(2.0, 3)\n1.0\n\njulia> f(2, 3)\n1","category":"page"},{"location":"manual/methods/","page":"方法","title":"方法","text":"2x + y 定义只用于第一个情况,2x - y 定义用于其他的情况。没有使用任何自动的函数参数的指派或者类型转换:Julia中的所有转换都不是 magic 的,都是完全显式的。然而类型转换和类型提升显示了足够先进的技术的智能应用能够与 magic 不可分辨到什么程度。[Clarke61] 对于非数字值,和比两个参数更多或者更少的情况,函数 f 并没有定义,应用会导致 MethodError:","category":"page"},{"location":"manual/methods/","page":"方法","title":"方法","text":"julia> f(\"foo\", 3)\nERROR: MethodError: no method matching f(::String, ::Int64)\nClosest candidates are:\n f(!Matched::Number, ::Number) at none:1\n\njulia> f()\nERROR: MethodError: no method matching f()\nClosest candidates are:\n f(!Matched::Float64, !Matched::Float64) at none:1\n f(!Matched::Number, !Matched::Number) at none:1","category":"page"},{"location":"manual/methods/","page":"方法","title":"方法","text":"可以简单地看到对于函数存在哪些方法,通过在交互式会话中键入函数对象本身:","category":"page"},{"location":"manual/methods/","page":"方法","title":"方法","text":"julia> f\nf (generic function with 2 methods)","category":"page"},{"location":"manual/methods/","page":"方法","title":"方法","text":"这个输出展示了f有两个方法。为了找到这些方法的前面,使用methods函数:","category":"page"},{"location":"manual/methods/","page":"方法","title":"方法","text":"julia> methods(f)\n# 2 methods for generic function \"f\":\n[1] f(x::Float64, y::Float64) in Main at none:1\n[2] f(x::Number, y::Number) in Main at none:1","category":"page"},{"location":"manual/methods/","page":"方法","title":"方法","text":"这表示f有两个方法,一个接受两个Float64参数一个接受两个Number类型的参数。它也显示了这些方法定义所在的文件和行数:因为这些方法是在REPL中定义的,我们得到了表面上的行数none:1.","category":"page"},{"location":"manual/methods/","page":"方法","title":"方法","text":"没有::的类型声明,方法参数的类型默认为Any,这就意味着没有约束,因为Julia中的所有的值都是抽象类型Any的实例。所以,我们可以为f定义一个接受所有的方法,像这样:","category":"page"},{"location":"manual/methods/","page":"方法","title":"方法","text":"julia> f(x,y) = println(\"Whoa there, Nelly.\")\nf (generic function with 3 methods)\n\njulia> methods(f)\n# 3 methods for generic function \"f\":\n[1] f(x::Float64, y::Float64) in Main at none:1\n[2] f(x::Number, y::Number) in Main at none:1\n[3] f(x, y) in Main at none:1\n\njulia> f(\"foo\", 1)\nWhoa there, Nelly.","category":"page"},{"location":"manual/methods/","page":"方法","title":"方法","text":"这个接受所有参数类型的方法比其他的对一对参数值的其他任意可能的方法定义更不专用。所以他只会被没有其他方法定义应用的一对参数调用。","category":"page"},{"location":"manual/methods/","page":"方法","title":"方法","text":"注意到第三个方法的签名中并没有指定参数x和y的类型。它是f(x::Any, y::Any)的简写。","category":"page"},{"location":"manual/methods/","page":"方法","title":"方法","text":"尽管这看起来很简单,但对值类型的多重派发可能是 Julia 语言最强大和最核心的特性。 核心运算通常有几十种方法:","category":"page"},{"location":"manual/methods/","page":"方法","title":"方法","text":"julia> methods(+)\n# 180 methods for generic function \"+\":\n[1] +(x::Bool, z::Complex{Bool}) in Base at complex.jl:227\n[2] +(x::Bool, y::Bool) in Base at bool.jl:89\n[3] +(x::Bool) in Base at bool.jl:86\n[4] +(x::Bool, y::T) where T<:AbstractFloat in Base at bool.jl:96\n[5] +(x::Bool, z::Complex) in Base at complex.jl:234\n[6] +(a::Float16, b::Float16) in Base at float.jl:373\n[7] +(x::Float32, y::Float32) in Base at float.jl:375\n[8] +(x::Float64, y::Float64) in Base at float.jl:376\n[9] +(z::Complex{Bool}, x::Bool) in Base at complex.jl:228\n[10] +(z::Complex{Bool}, x::Real) in Base at complex.jl:242\n[11] +(x::Char, y::Integer) in Base at char.jl:40\n[12] +(c::BigInt, x::BigFloat) in Base.MPFR at mpfr.jl:307\n[13] +(a::BigInt, b::BigInt, c::BigInt, d::BigInt, e::BigInt) in Base.GMP at gmp.jl:392\n[14] +(a::BigInt, b::BigInt, c::BigInt, d::BigInt) in Base.GMP at gmp.jl:391\n[15] +(a::BigInt, b::BigInt, c::BigInt) in Base.GMP at gmp.jl:390\n[16] +(x::BigInt, y::BigInt) in Base.GMP at gmp.jl:361\n[17] +(x::BigInt, c::Union{UInt16, UInt32, UInt64, UInt8}) in Base.GMP at gmp.jl:398\n...\n[180] +(a, b, c, xs...) in Base at operators.jl:424","category":"page"},{"location":"manual/methods/","page":"方法","title":"方法","text":"多重分派和灵活的参数类型系统让Julia有能力抽象地表达高层级算法,而与实现细节解耦,也能生成高效而专用的代码来在运行中处理每个情况。","category":"page"},{"location":"manual/methods/#man-ambiguities","page":"方法","title":"方法歧义","text":"","category":"section"},{"location":"manual/methods/","page":"方法","title":"方法","text":"在一系列的函数方法定义时有可能没有单独的最专用的方法能适用于参数的某些组合:","category":"page"},{"location":"manual/methods/","page":"方法","title":"方法","text":"julia> g(x::Float64, y) = 2x + y\ng (generic function with 1 method)\n\njulia> g(x, y::Float64) = x + 2y\ng (generic function with 2 methods)\n\njulia> g(2.0, 3)\n7.0\n\njulia> g(2, 3.0)\n8.0\n\njulia> g(2.0, 3.0)\nERROR: MethodError: g(::Float64, ::Float64) is ambiguous. Candidates:\n g(x::Float64, y) in Main at none:1\n g(x, y::Float64) in Main at none:1\nPossible fix, define\n g(::Float64, ::Float64)","category":"page"},{"location":"manual/methods/","page":"方法","title":"方法","text":"这里g(2.0,3.0)的调用使用g(Float64, Any)和g(Any, Float64)都能处理,并且两个都不更加专用。在这样的情况下,Julia会扔出MethodError而非任意选择一个方法。你可以通过对交叉情况指定一个合适的方法来避免方法歧义:","category":"page"},{"location":"manual/methods/","page":"方法","title":"方法","text":"julia> g(x::Float64, y::Float64) = 2x + 2y\ng (generic function with 3 methods)\n\njulia> g(2.0, 3)\n7.0\n\njulia> g(2, 3.0)\n8.0\n\njulia> g(2.0, 3.0)\n10.0","category":"page"},{"location":"manual/methods/","page":"方法","title":"方法","text":"建议先定义没有歧义的方法,因为不这样的话,歧义就会存在,即使是暂时性的,直到更加专用的方法被定义。","category":"page"},{"location":"manual/methods/","page":"方法","title":"方法","text":"在更加复杂的情况下,解决方法歧义会会涉及到设计的某一个元素;这个主题将会在下面进行进一步的探索。","category":"page"},{"location":"manual/methods/#参数方法","page":"方法","title":"参数方法","text":"","category":"section"},{"location":"manual/methods/","page":"方法","title":"方法","text":"方法定义可以视需要存在限定特征的类型参数:","category":"page"},{"location":"manual/methods/","page":"方法","title":"方法","text":"julia> same_type(x::T, y::T) where {T} = true\nsame_type (generic function with 1 method)\n\njulia> same_type(x,y) = false\nsame_type (generic function with 2 methods)","category":"page"},{"location":"manual/methods/","page":"方法","title":"方法","text":"第一个方法应用于两个参数都是同一个具体类型时,不管类型是什么,而第二个方法接受一切,涉及其他所有情况。所以,总得来说,这个定义了一个布尔函数来检查两个参数是否是同样的类型:","category":"page"},{"location":"manual/methods/","page":"方法","title":"方法","text":"julia> same_type(1, 2)\ntrue\n\njulia> same_type(1, 2.0)\nfalse\n\njulia> same_type(1.0, 2.0)\ntrue\n\njulia> same_type(\"foo\", 2.0)\nfalse\n\njulia> same_type(\"foo\", \"bar\")\ntrue\n\njulia> same_type(Int32(1), Int64(2))\nfalse","category":"page"},{"location":"manual/methods/","page":"方法","title":"方法","text":"这样的定义对应着那些类型签名是 UnionAll 类型的方法(参见 UnionAll 类型)。","category":"page"},{"location":"manual/methods/","page":"方法","title":"方法","text":"在Julia中这种通过分派进行函数行为的定义是十分常见的,甚至是惯用的。方法类型参数并不局限于用作参数的类型:他们可以用在任意地方,只要值会在函数或者函数体的特征中。这里有个例子,例子中方法类型参数T用作方法特征中的参数类型Vector{T}的类型参数:","category":"page"},{"location":"manual/methods/","page":"方法","title":"方法","text":"julia> myappend(v::Vector{T}, x::T) where {T} = [v..., x]\nmyappend (generic function with 1 method)\n\njulia> myappend([1,2,3],4)\n4-element Vector{Int64}:\n 1\n 2\n 3\n 4\n\njulia> myappend([1,2,3],2.5)\nERROR: MethodError: no method matching myappend(::Vector{Int64}, ::Float64)\nClosest candidates are:\n myappend(::Vector{T}, !Matched::T) where T at none:1\nStacktrace:\n[...]\n\njulia> myappend([1.0,2.0,3.0],4.0)\n4-element Vector{Float64}:\n 1.0\n 2.0\n 3.0\n 4.0\n\njulia> myappend([1.0,2.0,3.0],4)\nERROR: MethodError: no method matching myappend(::Vector{Float64}, ::Int64)\nClosest candidates are:\n myappend(::Vector{T}, !Matched::T) where T at none:1\nStacktrace:\n[...]","category":"page"},{"location":"manual/methods/","page":"方法","title":"方法","text":"如你所看到的,追加的元素的类型必须匹配它追加到的向量的元素类型,否则会引起MethodError。在下面的例子中,方法类型参量T用作返回值:","category":"page"},{"location":"manual/methods/","page":"方法","title":"方法","text":"julia> mytypeof(x::T) where {T} = T\nmytypeof (generic function with 1 method)\n\njulia> mytypeof(1)\nInt64\n\njulia> mytypeof(1.0)\nFloat64","category":"page"},{"location":"manual/methods/","page":"方法","title":"方法","text":"就像你能在类型声明时通过类型参数对子类型进行约束一样(参见参数类型),你也可以约束方法的类型参数:","category":"page"},{"location":"manual/methods/","page":"方法","title":"方法","text":"julia> same_type_numeric(x::T, y::T) where {T<:Number} = true\nsame_type_numeric (generic function with 1 method)\n\njulia> same_type_numeric(x::Number, y::Number) = false\nsame_type_numeric (generic function with 2 methods)\n\njulia> same_type_numeric(1, 2)\ntrue\n\njulia> same_type_numeric(1, 2.0)\nfalse\n\njulia> same_type_numeric(1.0, 2.0)\ntrue\n\njulia> same_type_numeric(\"foo\", 2.0)\nERROR: MethodError: no method matching same_type_numeric(::String, ::Float64)\nClosest candidates are:\n same_type_numeric(!Matched::T, ::T) where T<:Number at none:1\n same_type_numeric(!Matched::Number, ::Number) at none:1\n\njulia> same_type_numeric(\"foo\", \"bar\")\nERROR: MethodError: no method matching same_type_numeric(::String, ::String)\n\njulia> same_type_numeric(Int32(1), Int64(2))\nfalse","category":"page"},{"location":"manual/methods/","page":"方法","title":"方法","text":"same_type_numeric函数的行为与上面定义的same_type函数基本相似,但是它只对一对数定义。","category":"page"},{"location":"manual/methods/","page":"方法","title":"方法","text":"参数方法允许与 where 表达式同样的语法用来写类型(参见 UnionAll 类型)。如果只有一个参数,封闭的大括号(在 where {T} 中)可以省略,但是为了清楚起见推荐写上。多个参数可以使用逗号隔开,例如 where {T, S <: Real},或者使用嵌套的 where 来写,例如 where S<:Real where T。","category":"page"},{"location":"manual/methods/#重定义方法","page":"方法","title":"重定义方法","text":"","category":"section"},{"location":"manual/methods/","page":"方法","title":"方法","text":"当重定义一个方法或者增加一个方法时,知道这个变化不会立即生效很重要。这是Julia能够静态推断和编译代码使其运行很快而没有惯常的JIT技巧和额外开销的关键。实际上,任意新的方法定义不会对当前运行环境可见,包括Tasks和线程(和所有的之前定义的@generated函数)。让我们通过一个例子说明这意味着什么:","category":"page"},{"location":"manual/methods/","page":"方法","title":"方法","text":"julia> function tryeval()\n @eval newfun() = 1\n newfun()\n end\ntryeval (generic function with 1 method)\n\njulia> tryeval()\nERROR: MethodError: no method matching newfun()\nThe applicable method may be too new: running in world age xxxx1, while current world is xxxx2.\nClosest candidates are:\n newfun() at none:1 (method too new to be called from this world context.)\n in tryeval() at none:1\n ...\n\njulia> newfun()\n1","category":"page"},{"location":"manual/methods/","page":"方法","title":"方法","text":"在这个例子中看到newfun的新定义已经被创建,但是并不能立即调用。新的全局变量立即对tryeval函数可见,所以你可以写return newfun(没有小括号)。但是你,你的调用器,和他们调用的函数等等都不能调用这个新的方法定义!","category":"page"},{"location":"manual/methods/","page":"方法","title":"方法","text":"但是这里有个例外:之后的在 REPL 中的 newfun 的调用会按照预期工作,能够见到并调用newfun 的新定义。","category":"page"},{"location":"manual/methods/","page":"方法","title":"方法","text":"但是,之后的 tryeval 的调用将会继续看到 newfun 的定义,因为该定义位于 REPL 的前一个语句中并因此在之后的 tryeval 的调用之前。","category":"page"},{"location":"manual/methods/","page":"方法","title":"方法","text":"你可以试试这个来让自己了解这是如何工作的。","category":"page"},{"location":"manual/methods/","page":"方法","title":"方法","text":"这个行为的实现通过一个「world age 计数器」。这个单调递增的值会跟踪每个方法定义操作。此计数器允许用单个数字描述「对于给定运行时环境可见的方法定义集」,或者说「world age」。它还允许仅仅通过其序数值来比较在两个 world 中可用的方法。在上例中,我们看到(方法 newfun 所存在的)「current world」比局部于任务的「runtime world」大一,后者在 tryeval 开始执行时是固定的。","category":"page"},{"location":"manual/methods/","page":"方法","title":"方法","text":"有时规避这个是必要的(例如,如果你在实现上面的REPL)。幸运的是这里有个简单地解决方法:使用Base.invokelatest调用函数:","category":"page"},{"location":"manual/methods/","page":"方法","title":"方法","text":"julia> function tryeval2()\n @eval newfun2() = 2\n Base.invokelatest(newfun2)\n end\ntryeval2 (generic function with 1 method)\n\njulia> tryeval2()\n2","category":"page"},{"location":"manual/methods/","page":"方法","title":"方法","text":"最后,让我们看一些这个规则生效的更复杂的例子。 定义一个函数f(x),最开始有一个方法:","category":"page"},{"location":"manual/methods/","page":"方法","title":"方法","text":"julia> f(x) = \"original definition\"\nf (generic function with 1 method)","category":"page"},{"location":"manual/methods/","page":"方法","title":"方法","text":"开始一些使用f(x)的运算:","category":"page"},{"location":"manual/methods/","page":"方法","title":"方法","text":"julia> g(x) = f(x)\ng (generic function with 1 method)\n\njulia> t = @async f(wait()); yield();","category":"page"},{"location":"manual/methods/","page":"方法","title":"方法","text":"现在我们给f(x)加上一些新的方法:","category":"page"},{"location":"manual/methods/","page":"方法","title":"方法","text":"julia> f(x::Int) = \"definition for Int\"\nf (generic function with 2 methods)\n\njulia> f(x::Type{Int}) = \"definition for Type{Int}\"\nf (generic function with 3 methods)","category":"page"},{"location":"manual/methods/","page":"方法","title":"方法","text":"比较一下这些结果如何不同:","category":"page"},{"location":"manual/methods/","page":"方法","title":"方法","text":"julia> f(1)\n\"definition for Int\"\n\njulia> g(1)\n\"definition for Int\"\n\njulia> fetch(schedule(t, 1))\n\"original definition\"\n\njulia> t = @async f(wait()); yield();\n\njulia> fetch(schedule(t, 1))\n\"definition for Int\"","category":"page"},{"location":"manual/methods/#使用参数方法设计样式","page":"方法","title":"使用参数方法设计样式","text":"","category":"section"},{"location":"manual/methods/","page":"方法","title":"方法","text":"虽然复杂的分派逻辑对于性能或者可用性并不是必须的,但是有时这是表达某些算法的最好的方法。 这里有一些常见的设计样式,在以这个方法使用分派时有时会出现。","category":"page"},{"location":"manual/methods/#从超类型中提取出类型参数","page":"方法","title":"从超类型中提取出类型参数","text":"","category":"section"},{"location":"manual/methods/","page":"方法","title":"方法","text":"以下是一个正确的代码模板,用于返回具有明确定义的元素类型的 AbstractArray 的任意子类型的元素类型 T:","category":"page"},{"location":"manual/methods/","page":"方法","title":"方法","text":"abstract type AbstractArray{T, N} end\neltype(::Type{<:AbstractArray{T}}) where {T} = T","category":"page"},{"location":"manual/methods/","page":"方法","title":"方法","text":"使用所谓的三角派发。 请注意,UnionAll 类型,对于示例eltype(AbstractArray{T} where T <: Integer),与上述方法不符。 在这种情况下,Base 中 eltype 的实现为 Any 增加了一个回退方法。","category":"page"},{"location":"manual/methods/","page":"方法","title":"方法","text":"一个常见的错误是试着使用内省来得到元素类型:","category":"page"},{"location":"manual/methods/","page":"方法","title":"方法","text":"eltype_wrong(::Type{A}) where {A<:AbstractArray} = A.parameters[1]","category":"page"},{"location":"manual/methods/","page":"方法","title":"方法","text":"但是创建一个这个方法会失败的情况不难:","category":"page"},{"location":"manual/methods/","page":"方法","title":"方法","text":"struct BitVector <: AbstractArray{Bool, 1}; end","category":"page"},{"location":"manual/methods/","page":"方法","title":"方法","text":"这里我们已经创建了一个没有参数的类型BitVector,但是元素类型已经完全指定了,T等于Bool!","category":"page"},{"location":"manual/methods/","page":"方法","title":"方法","text":"另一个错误是尝试使用 supertype 沿着类型层次结构向上走:","category":"page"},{"location":"manual/methods/","page":"方法","title":"方法","text":"eltype_wrong(::Type{AbstractArray{T}}) where {T} = T\neltype_wrong(::Type{AbstractArray{T, N}}) where {T, N} = T\neltype_wrong(::Type{A}) where {A<:AbstractArray} = eltype_wrong(supertype(A))","category":"page"},{"location":"manual/methods/","page":"方法","title":"方法","text":"虽然这适用于声明的类型,但对于不适用于没有超类型的类型:","category":"page"},{"location":"manual/methods/","page":"方法","title":"方法","text":"julia> eltype_wrong(Union{AbstractArray{Int}, AbstractArray{Float64}})\nERROR: MethodError: no method matching supertype(::Type{Union{AbstractArray{Float64,N} where N, AbstractArray{Int64,N} where N}})\nClosest candidates are:\n supertype(::DataType) at operators.jl:43\n supertype(::UnionAll) at operators.jl:48","category":"page"},{"location":"manual/methods/#用不同的类型参数构建相似的类型","page":"方法","title":"用不同的类型参数构建相似的类型","text":"","category":"section"},{"location":"manual/methods/","page":"方法","title":"方法","text":"当构建通用代码时,通常需要创建一些类似对象,在类型的布局上有一些变化,这就也让类型参数的变化变得必要。 例如,你会有一些任意元素类型的抽象数组,想使用特定的元素类型来编写你基于它的计算。你必须实现为每个AbstractArray{T}的子类型实现方法,这些方法描述了如何计算类型转换。从一个子类型转化成拥有一个不同参数的另一个子类型的通用方法在这里不存在。(快速复习:你明白为什么吗?)","category":"page"},{"location":"manual/methods/","page":"方法","title":"方法","text":"AbstractArray的子类型典型情况下会实现两个方法来完成这个: 一个方法把输入输入转换成特定的AbstractArray{T,N}抽象类型的子类型;一个方法用特定的元素类型构建一个新的未初始化的数组。这些的样例实现可以在Julia Base里面找到。这里是一个基础的样例使用,保证输入与输出是同一种类型:","category":"page"},{"location":"manual/methods/","page":"方法","title":"方法","text":"input = convert(AbstractArray{Eltype}, input)\noutput = similar(input, Eltype)","category":"page"},{"location":"manual/methods/","page":"方法","title":"方法","text":"作为这个的扩展,在算法需要输入数组的拷贝的情况下,convert使无法胜任的,因为返回值可能只是原始输入的别名。把similar(构建输出数组)和copyto!(用输入数据填满)结合起来是需要给出输入参数的可变拷贝的一个范用方法:","category":"page"},{"location":"manual/methods/","page":"方法","title":"方法","text":"copy_with_eltype(input, Eltype) = copyto!(similar(input, Eltype), input)","category":"page"},{"location":"manual/methods/#迭代分派","page":"方法","title":"迭代分派","text":"","category":"section"},{"location":"manual/methods/","page":"方法","title":"方法","text":"为了分派一个多层的参数参量列表,将每一层分派分开到不同的函数中常常是最好的。这可能听起来跟单分派的方法相似,但是你会在下面见到,这个更加灵活。","category":"page"},{"location":"manual/methods/","page":"方法","title":"方法","text":"例如,尝试按照数组的元素类型进行分派常常会引起歧义。相反地,常见的代码会首先按照容易类型分派,然后基于eltype递归到更加更加专用的方法。在大部分情况下,算法会很方便地就屈从与这个分层方法,在其他情况下,这种严苛的工作必须手动解决。这个分派分支能被观察到,例如在两个矩阵的加法的逻辑中:","category":"page"},{"location":"manual/methods/","page":"方法","title":"方法","text":"# 首先分派选择了逐元素相加的map算法。\n+(a::Matrix, b::Matrix) = map(+, a, b)\n# 然后分派处理了每个元素然后选择了计算的\n# 恰当的常见元素类型。\n+(a, b) = +(promote(a, b)...)\n# 一旦元素有了相同类型,它们就可以相加。\n# 例如,通过处理器暴露出的原始运算。\n+(a::Float64, b::Float64) = Core.add(a, b)","category":"page"},{"location":"manual/methods/#基于-Trait-的分派","page":"方法","title":"基于 Trait 的分派","text":"","category":"section"},{"location":"manual/methods/","page":"方法","title":"方法","text":"对于上面的可迭代分派的一个自然扩展是给方法选择加一个内涵层,这个层允许按照那些与类型层级定义的集合相独立的类型的集合来分派。我们可以通过写出问题中的类型的一个Union来创建这个一个集合,但是这不能够扩展,因为Union类型在创建之后无法改变。但是这么一个可扩展的集合可以通过一个叫做\"Holy-trait\"的一个设计样式来实现。","category":"page"},{"location":"manual/methods/","page":"方法","title":"方法","text":"这个样式是通过定义一个范用函数来实现,这个函数为函数参数可能属于的每个trait集合都计算出不同的单例值(或者类型)。如果这个函数是单纯的,这与通常的分派对于性能没有任何影响。","category":"page"},{"location":"manual/methods/","page":"方法","title":"方法","text":"上一部分中的示例掩盖了 map 和 promote 的实现细节,这两个都是依据trait来进行运算的。 在迭代矩阵时,例如在 map 的实现中,一个重要的问题是使用什么顺序遍历数据。 当 AbstractArray 子类型实现 Base.IndexStyle trait 时,map 等其他函数可以根据此信息进行派发以选择最佳算法(请参阅 [抽象数组接口](@ref man-interface-array))。这意味着每个子类型不需要实现map的自定义版本,因为通用定义+trait类将使系统能够选择最快的版本。 下面是 map 的一个简单实现,说明了基于 trait 的调度:","category":"page"},{"location":"manual/methods/","page":"方法","title":"方法","text":"map(f, a::AbstractArray, b::AbstractArray) = map(Base.IndexStyle(a, b), f, a, b)\n# generic implementation:\nmap(::Base.IndexCartesian, f, a::AbstractArray, b::AbstractArray) = ...\n# linear-indexing implementation (faster)\nmap(::Base.IndexLinear, f, a::AbstractArray, b::AbstractArray) = ...","category":"page"},{"location":"manual/methods/","page":"方法","title":"方法","text":"这个基于trait的方法也出现在promote机制中,被标量+使用。 它使用了promote_type,这在知道两个计算对象的类型的情况下返回计算这个运算的最佳的常用类型。这就使得我们不用为每一对可能的类型参数实现每一个函数,而把问题简化为对于每个类型实现一个类型转换运算这样一个小很多的问题,还有一个优选的逐对的类型提升规则的表格。","category":"page"},{"location":"manual/methods/#输出类型计算","page":"方法","title":"输出类型计算","text":"","category":"section"},{"location":"manual/methods/","page":"方法","title":"方法","text":"基于trait的类型提升的讨论可以过渡到我们的下一个设计样式:为矩阵运算计算输出元素类型。","category":"page"},{"location":"manual/methods/","page":"方法","title":"方法","text":"为了实现像加法这样的原始运算,我们使用promote_type函数来计算想要的输出类型。(像之前一样,我们在+调用中的promote调用中见到了这个工作)。","category":"page"},{"location":"manual/methods/","page":"方法","title":"方法","text":"对于矩阵的更加复杂的函数,对于更加复杂的运算符序列来计算预期的返回类型是必要的。这经常按下列步骤进行:","category":"page"},{"location":"manual/methods/","page":"方法","title":"方法","text":"编写一个小函数op来表示算法核心中使用的运算的集合。\n使用promote_op(op, argument_types...)计算结果矩阵的元素类型R, 这里argument_types是通过应用到每个输入数组的eltype计算的。\n创建类似于similar(R, dims)的输出矩阵,这里dims是输出矩阵的预期维度数。","category":"page"},{"location":"manual/methods/","page":"方法","title":"方法","text":"作为一个更加具体的例子,一个范用的方阵乘法的伪代码是:","category":"page"},{"location":"manual/methods/","page":"方法","title":"方法","text":"function matmul(a::AbstractMatrix, b::AbstractMatrix)\n op = (ai, bi) -> ai * bi + ai * bi\n\n ## this is insufficient because it assumes `one(eltype(a))` is constructable:\n # R = typeof(op(one(eltype(a)), one(eltype(b))))\n\n ## this fails because it assumes `a[1]` exists and is representative of all elements of the array\n # R = typeof(op(a[1], b[1]))\n\n ## this is incorrect because it assumes that `+` calls `promote_type`\n ## but this is not true for some types, such as Bool:\n # R = promote_type(ai, bi)\n\n # this is wrong, since depending on the return value\n # of type-inference is very brittle (as well as not being optimizable):\n # R = Base.return_types(op, (eltype(a), eltype(b)))\n\n ## but, finally, this works:\n R = promote_op(op, eltype(a), eltype(b))\n ## although sometimes it may give a larger type than desired\n ## it will always give a correct type\n\n output = similar(b, R, (size(a, 1), size(b, 2)))\n if size(a, 2) > 0\n for j in 1:size(b, 2)\n for i in 1:size(a, 1)\n ## here we don't use `ab = zero(R)`,\n ## since `R` might be `Any` and `zero(Any)` is not defined\n ## we also must declare `ab::R` to make the type of `ab` constant in the loop,\n ## since it is possible that typeof(a * b) != typeof(a * b + a * b) == R\n ab::R = a[i, 1] * b[1, j]\n for k in 2:size(a, 2)\n ab += a[i, k] * b[k, j]\n end\n output[i, j] = ab\n end\n end\n end\n return output\nend","category":"page"},{"location":"manual/methods/#分离转换和内核逻辑","page":"方法","title":"分离转换和内核逻辑","text":"","category":"section"},{"location":"manual/methods/","page":"方法","title":"方法","text":"能有效减少编译时间和测试复杂度的一个方法是将预期的类型和计算转换的逻辑隔离。这会让编译器将与大型内核的其他部分相独立的类型转换逻辑特别化并内联。","category":"page"},{"location":"manual/methods/","page":"方法","title":"方法","text":"将更大的类型类转换成被算法实际支持的特定参数类是一个常见的设计样式:","category":"page"},{"location":"manual/methods/","page":"方法","title":"方法","text":"complexfunction(arg::Int) = ...\ncomplexfunction(arg::Any) = complexfunction(convert(Int, arg))\n\nmatmul(a::T, b::T) = ...\nmatmul(a, b) = matmul(promote(a, b)...)","category":"page"},{"location":"manual/methods/#参数化约束的可变参数方法","page":"方法","title":"参数化约束的可变参数方法","text":"","category":"section"},{"location":"manual/methods/","page":"方法","title":"方法","text":"函数参数也可以用于约束应用于\"可变参数\"函数(变参函数)的参数的数量。Vararg{T,N} 可用于表明这么一个约束。举个例子:","category":"page"},{"location":"manual/methods/","page":"方法","title":"方法","text":"julia> bar(a,b,x::Vararg{Any,2}) = (a,b,x)\nbar (generic function with 1 method)\n\njulia> bar(1,2,3)\nERROR: MethodError: no method matching bar(::Int64, ::Int64, ::Int64)\nClosest candidates are:\n bar(::Any, ::Any, ::Any, !Matched::Any) at none:1\n\njulia> bar(1,2,3,4)\n(1, 2, (3, 4))\n\njulia> bar(1,2,3,4,5)\nERROR: MethodError: no method matching bar(::Int64, ::Int64, ::Int64, ::Int64, ::Int64)\nClosest candidates are:\n bar(::Any, ::Any, ::Any, ::Any) at none:1","category":"page"},{"location":"manual/methods/","page":"方法","title":"方法","text":"更加有用的是,用一个参数就约束可变参数的方法是可能的。例如:","category":"page"},{"location":"manual/methods/","page":"方法","title":"方法","text":"function getindex(A::AbstractArray{T,N}, indices::Vararg{Number,N}) where {T,N}","category":"page"},{"location":"manual/methods/","page":"方法","title":"方法","text":"只会在indices的个数与数组的维数相同时才会调用。","category":"page"},{"location":"manual/methods/","page":"方法","title":"方法","text":"当只有提供的参数的类型需要被约束时,Vararg{T}可以写成T...。例如f(x::Int...) = x是f(x::Vararg{Int}) = x的简便写法。","category":"page"},{"location":"manual/methods/#可选参数和关键字的参数的注意事项","page":"方法","title":"可选参数和关键字的参数的注意事项","text":"","category":"section"},{"location":"manual/methods/","page":"方法","title":"方法","text":"与在函数中简要提到的一样,可选参数是使用多方法定义语法来实现的。例如,这个定义:","category":"page"},{"location":"manual/methods/","page":"方法","title":"方法","text":"f(a=1,b=2) = a+2b","category":"page"},{"location":"manual/methods/","page":"方法","title":"方法","text":"翻译成下列三个方法:","category":"page"},{"location":"manual/methods/","page":"方法","title":"方法","text":"f(a,b) = a+2b\nf(a) = f(a,2)\nf() = f(1,2)","category":"page"},{"location":"manual/methods/","page":"方法","title":"方法","text":"这就意味着调用f()等于调用f(1,2)。在这个情况下结果是5,因为f(1,2)使用的是上面f的第一个方法。但是,不总是需要是这种情况。如果你定义了第四个对于整数更加专用的方法:","category":"page"},{"location":"manual/methods/","page":"方法","title":"方法","text":"f(a::Int,b::Int) = a-2b","category":"page"},{"location":"manual/methods/","page":"方法","title":"方法","text":"此时f()和f(1,2)的结果都是-3。换句话说,可选参数只与函数捆绑,而不是函数的任意一个特定的方法。这个决定于使用的方法的可选参数的类型。当可选参数是用全局变量的形式定义时,可选参数的类型甚至会在运行时改变。","category":"page"},{"location":"manual/methods/","page":"方法","title":"方法","text":"关键字参数与普通的位置参数的行为很不一样。特别地,他们不参与到方法分派中。方法只基于位置参数分派,在匹配得方法确定之后关键字参数才会被处理。","category":"page"},{"location":"manual/methods/#类函数对象","page":"方法","title":"类函数对象","text":"","category":"section"},{"location":"manual/methods/","page":"方法","title":"方法","text":"方法与类型相关,所以可以通过给类型加方法使得任意一个Julia类型变得\"可被调用\"。(这个\"可调用\"的对象有时称为\"函子\"。)","category":"page"},{"location":"manual/methods/","page":"方法","title":"方法","text":"例如,你可以定义一个类型,存储着多项式的系数,但是行为像是一个函数,可以为多项式求值:","category":"page"},{"location":"manual/methods/","page":"方法","title":"方法","text":"julia> struct Polynomial{R}\n coeffs::Vector{R}\n end\n\njulia> function (p::Polynomial)(x)\n v = p.coeffs[end]\n for i = (length(p.coeffs)-1):-1:1\n v = v*x + p.coeffs[i]\n end\n return v\n end\n\njulia> (p::Polynomial)() = p(5)","category":"page"},{"location":"manual/methods/","page":"方法","title":"方法","text":"注意函数是通过类型而非名字来指定的。如同普通函数一样这里有一个简洁的语法形式。在函数体内,p会指向被调用的对象。Polynomial会按如下方式使用:","category":"page"},{"location":"manual/methods/","page":"方法","title":"方法","text":"julia> p = Polynomial([1,10,100])\nPolynomial{Int64}([1, 10, 100])\n\njulia> p(3)\n931\n\njulia> p()\n2551","category":"page"},{"location":"manual/methods/","page":"方法","title":"方法","text":"这个机制也是Julia中类型构造函数和闭包(指向其环境的内部函数)的工作原理。","category":"page"},{"location":"manual/methods/#空泛型函数","page":"方法","title":"空泛型函数","text":"","category":"section"},{"location":"manual/methods/","page":"方法","title":"方法","text":"有时引入一个没有添加方法的范用函数是有用的。这会用于分离实现与接口定义。这也可为了文档或者代码可读性。为了这个的语法是没有参数组的一个空函数块:","category":"page"},{"location":"manual/methods/","page":"方法","title":"方法","text":"function emptyfunc end","category":"page"},{"location":"manual/methods/#man-method-design-ambiguities","page":"方法","title":"方法设计与避免歧义","text":"","category":"section"},{"location":"manual/methods/","page":"方法","title":"方法","text":"Julia的方法多态性是其最有力的特性之一,利用这个功能会带来设计上的挑战。特别地,在更加复杂的方法层级中出现歧义不能说不常见。","category":"page"},{"location":"manual/methods/","page":"方法","title":"方法","text":"在上面我们曾经指出我们可以像这样解决歧义","category":"page"},{"location":"manual/methods/","page":"方法","title":"方法","text":"f(x, y::Int) = 1\nf(x::Int, y) = 2","category":"page"},{"location":"manual/methods/","page":"方法","title":"方法","text":"靠定义一个方法","category":"page"},{"location":"manual/methods/","page":"方法","title":"方法","text":"f(x::Int, y::Int) = 3","category":"page"},{"location":"manual/methods/","page":"方法","title":"方法","text":"这通常是正确的方案; 然而,在某些情况下,盲目地遵循这一建议可能会适得其反。 特别是,泛型函数的方法越多,产生歧义的可能性就越大。 当方法层次结构变得比这个简单的示例更复杂时,仔细考虑替代策略可能是值得的。","category":"page"},{"location":"manual/methods/","page":"方法","title":"方法","text":"下面我们会讨论特别的一些挑战和解决这些挑战的一些可选方法。","category":"page"},{"location":"manual/methods/#元组和N元组参数","page":"方法","title":"元组和N元组参数","text":"","category":"section"},{"location":"manual/methods/","page":"方法","title":"方法","text":"Tuple(和NTuple)参数会带来特别的挑战。例如,","category":"page"},{"location":"manual/methods/","page":"方法","title":"方法","text":"f(x::NTuple{N,Int}) where {N} = 1\nf(x::NTuple{N,Float64}) where {N} = 2","category":"page"},{"location":"manual/methods/","page":"方法","title":"方法","text":"是有歧义的,因为存在N == 0的可能性:没有元素去确定Int还是Float64变体应该被调用。为了解决歧义,一个方法是为空元组定义方法:","category":"page"},{"location":"manual/methods/","page":"方法","title":"方法","text":"f(x::Tuple{}) = 3","category":"page"},{"location":"manual/methods/","page":"方法","title":"方法","text":"作为一种选择,对于其中一个方法之外的所有的方法可以坚持元组中至少有一个元素:","category":"page"},{"location":"manual/methods/","page":"方法","title":"方法","text":"f(x::NTuple{N,Int}) where {N} = 1 # this is the fallback\nf(x::Tuple{Float64, Vararg{Float64}}) = 2 # this requires at least one Float64","category":"page"},{"location":"manual/methods/#man-methods-orthogonalize","page":"方法","title":"正交化你的设计","text":"","category":"section"},{"location":"manual/methods/","page":"方法","title":"方法","text":"当你打算根据两个或更多的参数进行分派时,考虑一下,一个「包裹」函数是否会让设计简单一些。举个例子,与其编写多变量:","category":"page"},{"location":"manual/methods/","page":"方法","title":"方法","text":"f(x::A, y::A) = ...\nf(x::A, y::B) = ...\nf(x::B, y::A) = ...\nf(x::B, y::B) = ...","category":"page"},{"location":"manual/methods/","page":"方法","title":"方法","text":"不如考虑定义","category":"page"},{"location":"manual/methods/","page":"方法","title":"方法","text":"f(x::A, y::A) = ...\nf(x, y) = f(g(x), g(y))","category":"page"},{"location":"manual/methods/","page":"方法","title":"方法","text":"这里g把参数转变为类型A。这是更加普遍的正交设计原理的一个特别特殊的例子,在正交设计中不同的概念被分配到不同的方法中去。这里g最可能需要一个fallback定义","category":"page"},{"location":"manual/methods/","page":"方法","title":"方法","text":"g(x::A) = x","category":"page"},{"location":"manual/methods/","page":"方法","title":"方法","text":"一个相关的方案使用promote来把x和y变成常见的类型:","category":"page"},{"location":"manual/methods/","page":"方法","title":"方法","text":"f(x::T, y::T) where {T} = ...\nf(x, y) = f(promote(x, y)...)","category":"page"},{"location":"manual/methods/","page":"方法","title":"方法","text":"这个设计的一个隐患是:如果没有合适的把 x 和 y 转换到同样类型的类型提升方法,第二个方法就可能无限自递归然后引发堆溢出。","category":"page"},{"location":"manual/methods/#一次只根据一个参数分派","page":"方法","title":"一次只根据一个参数分派","text":"","category":"section"},{"location":"manual/methods/","page":"方法","title":"方法","text":"如果你你需要根据多个参数进行分派,并且有太多的为了能定义所有可能的变量而存在的组合,而存在很多回退函数,你可以考虑引入\"名字级联\",这里(例如)你根据第一个参数分配然后调用一个内部的方法:","category":"page"},{"location":"manual/methods/","page":"方法","title":"方法","text":"f(x::A, y) = _fA(x, y)\nf(x::B, y) = _fB(x, y)","category":"page"},{"location":"manual/methods/","page":"方法","title":"方法","text":"接着内部方法_fA和_fB可以根据y进行分派,而不考虑有关x的歧义存在。","category":"page"},{"location":"manual/methods/","page":"方法","title":"方法","text":"需要意识到这个方案至少有一个主要的缺点:在很多情况下,用户没有办法通过进一步定义你的输出函数f的具体行为来进一步定制f的行为。相反,他们需要去定义你的内部方法_fA和_fB的具体行为,这会模糊输出方法和内部方法之间的界线。","category":"page"},{"location":"manual/methods/#抽象容器与元素类型","page":"方法","title":"抽象容器与元素类型","text":"","category":"section"},{"location":"manual/methods/","page":"方法","title":"方法","text":"在可能的情况下要试图避免定义根据抽象容器的具体元素类型来分派的方法。举个例子,","category":"page"},{"location":"manual/methods/","page":"方法","title":"方法","text":"-(A::AbstractArray{T}, b::Date) where {T<:Date}","category":"page"},{"location":"manual/methods/","page":"方法","title":"方法","text":"会引起歧义,当定义了这个方法:","category":"page"},{"location":"manual/methods/","page":"方法","title":"方法","text":"-(A::MyArrayType{T}, b::T) where {T}","category":"page"},{"location":"manual/methods/","page":"方法","title":"方法","text":"最好的方法是不要定义这些方法中的任何一个。相反,使用范用方法-(A::AbstractArray, b)并确认这个方法是使用分别对于每个容器类型和元素类型都是适用的通用调用(像similar和-)实现的。这只是建议正交化你的方法的一个更加复杂的变种而已。","category":"page"},{"location":"manual/methods/","page":"方法","title":"方法","text":"当这个方法不可行时,这就值得与其他开发者开始讨论如果解决歧义;只是因为一个函数先定义并不总是意味着他不能改变或者被移除。作为最后一个手段,开发者可以定义\"创可贴\"方法","category":"page"},{"location":"manual/methods/","page":"方法","title":"方法","text":"-(A::MyArrayType{T}, b::Date) where {T<:Date} = ...","category":"page"},{"location":"manual/methods/","page":"方法","title":"方法","text":"可以暴力解决歧义。","category":"page"},{"location":"manual/methods/#与默认参数的复杂方法\"级联\"","page":"方法","title":"与默认参数的复杂方法\"级联\"","text":"","category":"section"},{"location":"manual/methods/","page":"方法","title":"方法","text":"如果你定义了提供默认的方法\"级联\",要小心去掉对应着潜在默认的任何参数。例如,假设你在写一个数字过滤算法,你有一个通过应用padding来出来信号的边的方法:","category":"page"},{"location":"manual/methods/","page":"方法","title":"方法","text":"function myfilter(A, kernel, ::Replicate)\n Apadded = replicate_edges(A, size(kernel))\n myfilter(Apadded, kernel) # now perform the \"real\" computation\nend","category":"page"},{"location":"manual/methods/","page":"方法","title":"方法","text":"这会与提供默认padding的方法产生冲突:","category":"page"},{"location":"manual/methods/","page":"方法","title":"方法","text":"myfilter(A, kernel) = myfilter(A, kernel, Replicate()) # replicate the edge by default","category":"page"},{"location":"manual/methods/","page":"方法","title":"方法","text":"这两个方法一起会生成无限的递归,A会不断变大。","category":"page"},{"location":"manual/methods/","page":"方法","title":"方法","text":"更好的设计是像这样定义你的调用层级:","category":"page"},{"location":"manual/methods/","page":"方法","title":"方法","text":"struct NoPad end # indicate that no padding is desired, or that it's already applied\n\nmyfilter(A, kernel) = myfilter(A, kernel, Replicate()) # default boundary conditions\n\nfunction myfilter(A, kernel, ::Replicate)\n Apadded = replicate_edges(A, size(kernel))\n myfilter(Apadded, kernel, NoPad()) # indicate the new boundary conditions\nend\n\n# other padding methods go here\n\nfunction myfilter(A, kernel, ::NoPad)\n # Here's the \"real\" implementation of the core computation\nend","category":"page"},{"location":"manual/methods/","page":"方法","title":"方法","text":"NoPad 被置于与其他 padding 类型一致的参数位置上,这保持了分派层级的良好组织,同时降低了歧义的可能性。而且,它扩展了「公开」的 myfilter 接口:想要显式控制 padding 的用户可以直接调用 NoPad 变量。","category":"page"},{"location":"manual/methods/","page":"方法","title":"方法","text":"[Clarke61]: Arthur C. Clarke, Profiles of the Future (1961): Clarke's Third Law.","category":"page"},{"location":"devdocs/sanitizers/#Sanitizer-support","page":"Sanitizer support","title":"Sanitizer support","text":"","category":"section"},{"location":"devdocs/sanitizers/#General-considerations","page":"Sanitizer support","title":"General considerations","text":"","category":"section"},{"location":"devdocs/sanitizers/","page":"Sanitizer support","title":"Sanitizer support","text":"Using Clang's sanitizers obviously require you to use Clang (USECLANG=1), but there's another catch: most sanitizers require a run-time library, provided by the host compiler, while the instrumented code generated by Julia's JIT relies on functionality from that library. This implies that the LLVM version of your host compiler matches that of the LLVM library used within Julia.","category":"page"},{"location":"devdocs/sanitizers/","page":"Sanitizer support","title":"Sanitizer support","text":"An easy solution is to have an dedicated build folder for providing a matching toolchain, by building with BUILD_LLVM_CLANG=1. You can then refer to this toolchain from another build folder by specifying USECLANG=1 while overriding the CC and CXX variables.","category":"page"},{"location":"devdocs/sanitizers/","page":"Sanitizer support","title":"Sanitizer support","text":"To use one of of the sanitizers set SANITIZE=1 and then the appropriate flag for the sanitizer you want to use.","category":"page"},{"location":"devdocs/sanitizers/","page":"Sanitizer support","title":"Sanitizer support","text":"On macOS, this might need some extra flags also to work. Altogether, it might look like this, plus one or more of the SANITIZE_* flags listed below:","category":"page"},{"location":"devdocs/sanitizers/","page":"Sanitizer support","title":"Sanitizer support","text":"make -C deps USE_BINARYBUILDER_LLVM=0 LLVM_VER=svn stage-llvm\n\nmake -C src SANITIZE=1 USECLANG=1 \\\n CC=~+/deps/scratch/llvm-svn/build_Release/bin/clang \\\n CXX=~+/deps/scratch/llvm-svn/build_Release/bin/clang++ \\\n CPPFLAGS=\"-isysroot $(xcode-select -p)/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk\" \\\n CXXFLAGS=\"-isystem $(xcode-select -p)/Toolchains/XcodeDefault.xctoolchain/usr/include/c++/v1\"","category":"page"},{"location":"devdocs/sanitizers/","page":"Sanitizer support","title":"Sanitizer support","text":"(or put these into your Make.user, so you don't need to remember them every time).","category":"page"},{"location":"devdocs/sanitizers/#Address-Sanitizer-(ASAN)","page":"Sanitizer support","title":"Address Sanitizer (ASAN)","text":"","category":"section"},{"location":"devdocs/sanitizers/","page":"Sanitizer support","title":"Sanitizer support","text":"For detecting or debugging memory bugs, you can use Clang's address sanitizer (ASAN). By compiling with SANITIZE_ADDRESS=1 you enable ASAN for the Julia compiler and its generated code. In addition, you can specify LLVM_SANITIZE=1 to sanitize the LLVM library as well. Note that these options incur a high performance and memory cost. For example, using ASAN for Julia and LLVM makes testall1 takes 8-10 times as long while using 20 times as much memory (this can be reduced to respectively a factor of 3 and 4 by using the options described below).","category":"page"},{"location":"devdocs/sanitizers/","page":"Sanitizer support","title":"Sanitizer support","text":"By default, Julia sets the allow_user_segv_handler=1 ASAN flag, which is required for signal delivery to work properly. You can define other options using the ASAN_OPTIONS environment flag, in which case you'll need to repeat the default option mentioned before. For example, memory usage can be reduced by specifying fast_unwind_on_malloc=0 and malloc_context_size=2, at the cost of backtrace accuracy. For now, Julia also sets detect_leaks=0, but this should be removed in the future.","category":"page"},{"location":"devdocs/sanitizers/#Memory-Sanitizer-(MSAN)","page":"Sanitizer support","title":"Memory Sanitizer (MSAN)","text":"","category":"section"},{"location":"devdocs/sanitizers/","page":"Sanitizer support","title":"Sanitizer support","text":"For detecting use of uninitialized memory, you can use Clang's memory sanitizer (MSAN) by compiling with SANITIZE_MEMORY=1.","category":"page"},{"location":"devdocs/sanitizers/#Thread-Sanitizer-(TSAN)","page":"Sanitizer support","title":"Thread Sanitizer (TSAN)","text":"","category":"section"},{"location":"devdocs/sanitizers/","page":"Sanitizer support","title":"Sanitizer support","text":"For debugging data-races and other threading related issues you can use Clang's thread sanitizer (TSAN) by compiling with SANITIZE_THREAD=1.","category":"page"},{"location":"stdlib/Dates/#日期","page":"日期","title":"日期","text":"","category":"section"},{"location":"stdlib/Dates/","page":"日期","title":"日期","text":"DocTestSetup = :(using Dates)","category":"page"},{"location":"stdlib/Dates/","page":"日期","title":"日期","text":"Dates 模块提供了两种类型来处理日期:Date 和 DateTime,分别精确到日和毫秒;两者都是抽象类型 TimeType 的子类型。区分类型的动机很简单:不必处理更高精度所带来的复杂性时,一些操作在代码和思维推理上都更加简单。例如,由于 Date 类型仅精确到日(即没有时、分或秒),因此避免了时区、夏令时和闰秒等不必要的通常考虑。","category":"page"},{"location":"stdlib/Dates/","page":"日期","title":"日期","text":"Date 和 DateTime 类型都是基本不可变类型 Int64 的包装类。这两种类型的单个 instant 字段实际上属于 UTInstant{P} 类型。这种类型表示的是一种基于世界时间(UT)持续增长的机器时间 [1]。DateTime 类型并不考虑时区(用 Python 的话讲,它是 naive 的),与 Java 8 中的 LocalDateTime 类似。如果需要附加时区功能,可以通过 TimeZones.jl 包 实现,其汇编了来自 IANA 时区数据库 的数据。Date 和 DateTime 都基于 ISO 8601 标准,遵循公历(格里高利历)。 值得注意的是,ISO 8601 标准对公元前的日期需要特别处理。通常来说,公元前的最后一天是公元前 1 年的 12 月 31 日,接下来的一天是公元 1 年的 1 月 1 日,公元 0 年是不存在的。但是,在 ISO 8601 标准中,公元前 1 年被表示为 0 年,即 0001-01-01 的前一天是 0000-12-31,而 -0001(没错,年数为-1)的那一年则实际上是公元前 2 年,-0002 则表示公元前 3 年,以此类推。","category":"page"},{"location":"stdlib/Dates/","page":"日期","title":"日期","text":"[1]: The notion of the UT second is actually quite fundamental. There are basically two different notions of time generally accepted, one based on the physical rotation of the earth (one full rotation = 1 day), the other based on the SI second (a fixed, constant value). These are radically different! Think about it, a \"UT second\", as defined relative to the rotation of the earth, may have a different absolute length depending on the day! Anyway, the fact that Date and DateTime are based on UT seconds is a simplifying, yet honest assumption so that things like leap seconds and all their complexity can be avoided. This basis of time is formally called UT or UT1. Basing types on the UT second basically means that every minute has 60 seconds and every day has 24 hours and leads to more natural calculations when working with calendar dates.","category":"page"},{"location":"stdlib/Dates/#构造函数","page":"日期","title":"构造函数","text":"","category":"section"},{"location":"stdlib/Dates/","page":"日期","title":"日期","text":"Date 和 DateTime 类型可以通过整数或 Period 类型,解析,或调整器来构造(稍后会详细介绍):","category":"page"},{"location":"stdlib/Dates/","page":"日期","title":"日期","text":"julia> DateTime(2013)\n2013-01-01T00:00:00\n\njulia> DateTime(2013,7)\n2013-07-01T00:00:00\n\njulia> DateTime(2013,7,1)\n2013-07-01T00:00:00\n\njulia> DateTime(2013,7,1,12)\n2013-07-01T12:00:00\n\njulia> DateTime(2013,7,1,12,30)\n2013-07-01T12:30:00\n\njulia> DateTime(2013,7,1,12,30,59)\n2013-07-01T12:30:59\n\njulia> DateTime(2013,7,1,12,30,59,1)\n2013-07-01T12:30:59.001\n\njulia> Date(2013)\n2013-01-01\n\njulia> Date(2013,7)\n2013-07-01\n\njulia> Date(2013,7,1)\n2013-07-01\n\njulia> Date(Dates.Year(2013),Dates.Month(7),Dates.Day(1))\n2013-07-01\n\njulia> Date(Dates.Month(7),Dates.Year(2013))\n2013-07-01","category":"page"},{"location":"stdlib/Dates/","page":"日期","title":"日期","text":"Date or DateTime parsing is accomplished by the use of format strings. Format strings work by the notion of defining delimited or fixed-width \"slots\" that contain a period to parse and passing the text to parse and format string to a Date or DateTime constructor, of the form Date(\"2015-01-01\",dateformat\"y-m-d\") or DateTime(\"20150101\",dateformat\"yyyymmdd\").","category":"page"},{"location":"stdlib/Dates/","page":"日期","title":"日期","text":"有分隔的插入点是通过指定解析器在两个时段之间的分隔符来进行标记的。例如,\"y-m-d\" 会告诉解析器,一个诸如 \"2014-07-16\" 的时间字符串,应该在第一个和第二个插入点之间查找 - 字符。y,m 和 d 字符则告诉解析器每一个插入点对应的时段名称。","category":"page"},{"location":"stdlib/Dates/","page":"日期","title":"日期","text":"As in the case of constructors above such as Date(2013), delimited DateFormats allow for missing parts of dates and times so long as the preceding parts are given. The other parts are given the usual default values. For example, Date(\"1981-03\", dateformat\"y-m-d\") returns 1981-03-01, whilst Date(\"31/12\", dateformat\"d/m/y\") gives 0001-12-31. (Note that the default year is 1 AD/CE.) Consequently, an empty string will always return 0001-01-01 for Dates, and 0001-01-01T00:00:00.000 for DateTimes.","category":"page"},{"location":"stdlib/Dates/","page":"日期","title":"日期","text":"Fixed-width slots are specified by repeating the period character the number of times corresponding to the width with no delimiter between characters. So dateformat\"yyyymmdd\" would correspond to a date string like \"20140716\". The parser distinguishes a fixed-width slot by the absence of a delimiter, noting the transition \"yyyymm\" from one period character to the next.","category":"page"},{"location":"stdlib/Dates/","page":"日期","title":"日期","text":"Support for text-form month parsing is also supported through the u and U characters, for abbreviated and full-length month names, respectively. By default, only English month names are supported, so u corresponds to \"Jan\", \"Feb\", \"Mar\", etc. And U corresponds to \"January\", \"February\", \"March\", etc. Similar to other name=>value mapping functions dayname and monthname, custom locales can be loaded by passing in the locale=>Dict{String,Int} mapping to the MONTHTOVALUEABBR and MONTHTOVALUE dicts for abbreviated and full-name month names, respectively.","category":"page"},{"location":"stdlib/Dates/","page":"日期","title":"日期","text":"The above examples used the dateformat\"\" string macro. This macro creates a DateFormat object once when the macro is expanded and uses the same DateFormat object even if a code snippet is run multiple times.","category":"page"},{"location":"stdlib/Dates/","page":"日期","title":"日期","text":"julia> for i = 1:10^5\n Date(\"2015-01-01\", dateformat\"y-m-d\")\n end","category":"page"},{"location":"stdlib/Dates/","page":"日期","title":"日期","text":"Or you can create the DateFormat object explicitly:","category":"page"},{"location":"stdlib/Dates/","page":"日期","title":"日期","text":"julia> df = DateFormat(\"y-m-d\");\n\njulia> dt = Date(\"2015-01-01\",df)\n2015-01-01\n\njulia> dt2 = Date(\"2015-01-02\",df)\n2015-01-02","category":"page"},{"location":"stdlib/Dates/","page":"日期","title":"日期","text":"Alternatively, use broadcasting:","category":"page"},{"location":"stdlib/Dates/","page":"日期","title":"日期","text":"julia> years = [\"2015\", \"2016\"];\n\njulia> Date.(years, DateFormat(\"yyyy\"))\n2-element Vector{Date}:\n 2015-01-01\n 2016-01-01","category":"page"},{"location":"stdlib/Dates/","page":"日期","title":"日期","text":"For convenience, you may pass the format string directly (e.g., Date(\"2015-01-01\",\"y-m-d\")), although this form incurs performance costs if you are parsing the same format repeatedly, as it internally creates a new DateFormat object each time.","category":"page"},{"location":"stdlib/Dates/","page":"日期","title":"日期","text":"As well as via the constructors, a Date or DateTime can be constructed from strings using the parse and tryparse functions, but with an optional third argument of type DateFormat specifying the format; for example, parse(Date, \"06.23.2013\", dateformat\"m.d.y\"), or tryparse(DateTime, \"1999-12-31T23:59:59\") which uses the default format. The notable difference between the functions is that with tryparse, an error is not thrown if the string is in an invalid format; instead nothing is returned. Note however that as with the constructors above, empty date and time parts assume default values and consequently an empty string (\"\") is valid for any DateFormat, giving for example a Date of 0001-01-01. Code relying on parse or tryparse for Date and DateTime parsing should therefore also check whether parsed strings are empty before using the result.","category":"page"},{"location":"stdlib/Dates/","page":"日期","title":"日期","text":"A full suite of parsing and formatting tests and examples is available in stdlib/Dates/test/io.jl.","category":"page"},{"location":"stdlib/Dates/#Durations/Comparisons","page":"日期","title":"Durations/Comparisons","text":"","category":"section"},{"location":"stdlib/Dates/","page":"日期","title":"日期","text":"Finding the length of time between two Date or DateTime is straightforward given their underlying representation as UTInstant{Day} and UTInstant{Millisecond}, respectively. The difference between Date is returned in the number of Day, and DateTime in the number of Millisecond. Similarly, comparing TimeType is a simple matter of comparing the underlying machine instants (which in turn compares the internal Int64 values).","category":"page"},{"location":"stdlib/Dates/","page":"日期","title":"日期","text":"julia> dt = Date(2012,2,29)\n2012-02-29\n\njulia> dt2 = Date(2000,2,1)\n2000-02-01\n\njulia> dump(dt)\nDate\n instant: Dates.UTInstant{Day}\n periods: Day\n value: Int64 734562\n\njulia> dump(dt2)\nDate\n instant: Dates.UTInstant{Day}\n periods: Day\n value: Int64 730151\n\njulia> dt > dt2\ntrue\n\njulia> dt != dt2\ntrue\n\njulia> dt + dt2\nERROR: MethodError: no method matching +(::Date, ::Date)\n[...]\n\njulia> dt * dt2\nERROR: MethodError: no method matching *(::Date, ::Date)\n[...]\n\njulia> dt / dt2\nERROR: MethodError: no method matching /(::Date, ::Date)\n\njulia> dt - dt2\n4411 days\n\njulia> dt2 - dt\n-4411 days\n\njulia> dt = DateTime(2012,2,29)\n2012-02-29T00:00:00\n\njulia> dt2 = DateTime(2000,2,1)\n2000-02-01T00:00:00\n\njulia> dt - dt2\n381110400000 milliseconds","category":"page"},{"location":"stdlib/Dates/#Accessor-Functions","page":"日期","title":"Accessor Functions","text":"","category":"section"},{"location":"stdlib/Dates/","page":"日期","title":"日期","text":"Because the Date and DateTime types are stored as single Int64 values, date parts or fields can be retrieved through accessor functions. The lowercase accessors return the field as an integer:","category":"page"},{"location":"stdlib/Dates/","page":"日期","title":"日期","text":"julia> t = Date(2014, 1, 31)\n2014-01-31\n\njulia> Dates.year(t)\n2014\n\njulia> Dates.month(t)\n1\n\njulia> Dates.week(t)\n5\n\njulia> Dates.day(t)\n31","category":"page"},{"location":"stdlib/Dates/","page":"日期","title":"日期","text":"While propercase return the same value in the corresponding Period type:","category":"page"},{"location":"stdlib/Dates/","page":"日期","title":"日期","text":"julia> Dates.Year(t)\n2014 years\n\njulia> Dates.Day(t)\n31 days","category":"page"},{"location":"stdlib/Dates/","page":"日期","title":"日期","text":"Compound methods are provided because it is more efficient to access multiple fields at the same time than individually:","category":"page"},{"location":"stdlib/Dates/","page":"日期","title":"日期","text":"julia> Dates.yearmonth(t)\n(2014, 1)\n\njulia> Dates.monthday(t)\n(1, 31)\n\njulia> Dates.yearmonthday(t)\n(2014, 1, 31)","category":"page"},{"location":"stdlib/Dates/","page":"日期","title":"日期","text":"One may also access the underlying UTInstant or integer value:","category":"page"},{"location":"stdlib/Dates/","page":"日期","title":"日期","text":"julia> dump(t)\nDate\n instant: Dates.UTInstant{Day}\n periods: Day\n value: Int64 735264\n\njulia> t.instant\nDates.UTInstant{Day}(Day(735264))\n\njulia> Dates.value(t)\n735264","category":"page"},{"location":"stdlib/Dates/#Query-Functions","page":"日期","title":"Query Functions","text":"","category":"section"},{"location":"stdlib/Dates/","page":"日期","title":"日期","text":"Query functions provide calendrical information about a TimeType. They include information about the day of the week:","category":"page"},{"location":"stdlib/Dates/","page":"日期","title":"日期","text":"julia> t = Date(2014, 1, 31)\n2014-01-31\n\njulia> Dates.dayofweek(t)\n5\n\njulia> Dates.dayname(t)\n\"Friday\"\n\njulia> Dates.dayofweekofmonth(t) # 5th Friday of January\n5","category":"page"},{"location":"stdlib/Dates/","page":"日期","title":"日期","text":"Month of the year:","category":"page"},{"location":"stdlib/Dates/","page":"日期","title":"日期","text":"julia> Dates.monthname(t)\n\"January\"\n\njulia> Dates.daysinmonth(t)\n31","category":"page"},{"location":"stdlib/Dates/","page":"日期","title":"日期","text":"As well as information about the TimeType's year and quarter:","category":"page"},{"location":"stdlib/Dates/","page":"日期","title":"日期","text":"julia> Dates.isleapyear(t)\nfalse\n\njulia> Dates.dayofyear(t)\n31\n\njulia> Dates.quarterofyear(t)\n1\n\njulia> Dates.dayofquarter(t)\n31","category":"page"},{"location":"stdlib/Dates/","page":"日期","title":"日期","text":"The dayname and monthname methods can also take an optional locale keyword that can be used to return the name of the day or month of the year for other languages/locales. There are also versions of these functions returning the abbreviated names, namely dayabbr and monthabbr. First the mapping is loaded into the LOCALES variable:","category":"page"},{"location":"stdlib/Dates/","page":"日期","title":"日期","text":"julia> french_months = [\"janvier\", \"février\", \"mars\", \"avril\", \"mai\", \"juin\",\n \"juillet\", \"août\", \"septembre\", \"octobre\", \"novembre\", \"décembre\"];\n\njulia> french_monts_abbrev = [\"janv\",\"févr\",\"mars\",\"avril\",\"mai\",\"juin\",\n \"juil\",\"août\",\"sept\",\"oct\",\"nov\",\"déc\"];\n\njulia> french_days = [\"lundi\",\"mardi\",\"mercredi\",\"jeudi\",\"vendredi\",\"samedi\",\"dimanche\"];\n\njulia> Dates.LOCALES[\"french\"] = Dates.DateLocale(french_months, french_monts_abbrev, french_days, [\"\"]);","category":"page"},{"location":"stdlib/Dates/","page":"日期","title":"日期","text":"The above mentioned functions can then be used to perform the queries:","category":"page"},{"location":"stdlib/Dates/","page":"日期","title":"日期","text":"julia> Dates.dayname(t;locale=\"french\")\n\"vendredi\"\n\njulia> Dates.monthname(t;locale=\"french\")\n\"janvier\"\n\njulia> Dates.monthabbr(t;locale=\"french\")\n\"janv\"","category":"page"},{"location":"stdlib/Dates/","page":"日期","title":"日期","text":"Since the abbreviated versions of the days are not loaded, trying to use the function dayabbr will error.","category":"page"},{"location":"stdlib/Dates/","page":"日期","title":"日期","text":"julia> Dates.dayabbr(t;locale=\"french\")\nERROR: BoundsError: attempt to access 1-element Vector{String} at index [5]\nStacktrace:\n[...]","category":"page"},{"location":"stdlib/Dates/#TimeType-Period-Arithmetic","page":"日期","title":"TimeType-Period Arithmetic","text":"","category":"section"},{"location":"stdlib/Dates/","page":"日期","title":"日期","text":"It's good practice when using any language/date framework to be familiar with how date-period arithmetic is handled as there are some tricky issues to deal with (though much less so for day-precision types).","category":"page"},{"location":"stdlib/Dates/","page":"日期","title":"日期","text":"The Dates module approach tries to follow the simple principle of trying to change as little as possible when doing Period arithmetic. This approach is also often known as calendrical arithmetic or what you would probably guess if someone were to ask you the same calculation in a conversation. Why all the fuss about this? Let's take a classic example: add 1 month to January 31st, 2014. What's the answer? Javascript will say March 3 (assumes 31 days). PHP says March 2 (assumes 30 days). The fact is, there is no right answer. In the Dates module, it gives the result of February 28th. How does it figure that out? Consider the classic 7-7-7 gambling game in casinos.","category":"page"},{"location":"stdlib/Dates/","page":"日期","title":"日期","text":"Now just imagine that instead of 7-7-7, the slots are Year-Month-Day, or in our example, 2014-01-31. When you ask to add 1 month to this date, the month slot is incremented, so now we have 2014-02-31. Then the day number is checked if it is greater than the last valid day of the new month; if it is (as in the case above), the day number is adjusted down to the last valid day (28). What are the ramifications with this approach? Go ahead and add another month to our date, 2014-02-28 + Month(1) == 2014-03-28. What? Were you expecting the last day of March? Nope, sorry, remember the 7-7-7 slots. As few slots as possible are going to change, so we first increment the month slot by 1, 2014-03-28, and boom, we're done because that's a valid date. On the other hand, if we were to add 2 months to our original date, 2014-01-31, then we end up with 2014-03-31, as expected. The other ramification of this approach is a loss in associativity when a specific ordering is forced (i.e. adding things in different orders results in different outcomes). For example:","category":"page"},{"location":"stdlib/Dates/","page":"日期","title":"日期","text":"julia> (Date(2014,1,29)+Dates.Day(1)) + Dates.Month(1)\n2014-02-28\n\njulia> (Date(2014,1,29)+Dates.Month(1)) + Dates.Day(1)\n2014-03-01","category":"page"},{"location":"stdlib/Dates/","page":"日期","title":"日期","text":"What's going on there? In the first line, we're adding 1 day to January 29th, which results in 2014-01-30; then we add 1 month, so we get 2014-02-30, which then adjusts down to 2014-02-28. In the second example, we add 1 month first, where we get 2014-02-29, which adjusts down to 2014-02-28, and then add 1 day, which results in 2014-03-01. One design principle that helps in this case is that, in the presence of multiple Periods, the operations will be ordered by the Periods' types, not their value or positional order; this means Year will always be added first, then Month, then Week, etc. Hence the following does result in associativity and Just Works:","category":"page"},{"location":"stdlib/Dates/","page":"日期","title":"日期","text":"julia> Date(2014,1,29) + Dates.Day(1) + Dates.Month(1)\n2014-03-01\n\njulia> Date(2014,1,29) + Dates.Month(1) + Dates.Day(1)\n2014-03-01","category":"page"},{"location":"stdlib/Dates/","page":"日期","title":"日期","text":"Tricky? Perhaps. What is an innocent Dates user to do? The bottom line is to be aware that explicitly forcing a certain associativity, when dealing with months, may lead to some unexpected results, but otherwise, everything should work as expected. Thankfully, that's pretty much the extent of the odd cases in date-period arithmetic when dealing with time in UT (avoiding the \"joys\" of dealing with daylight savings, leap seconds, etc.).","category":"page"},{"location":"stdlib/Dates/","page":"日期","title":"日期","text":"As a bonus, all period arithmetic objects work directly with ranges:","category":"page"},{"location":"stdlib/Dates/","page":"日期","title":"日期","text":"julia> dr = Date(2014,1,29):Day(1):Date(2014,2,3)\nDate(\"2014-01-29\"):Day(1):Date(\"2014-02-03\")\n\njulia> collect(dr)\n6-element Vector{Date}:\n 2014-01-29\n 2014-01-30\n 2014-01-31\n 2014-02-01\n 2014-02-02\n 2014-02-03\n\njulia> dr = Date(2014,1,29):Dates.Month(1):Date(2014,07,29)\nDate(\"2014-01-29\"):Month(1):Date(\"2014-07-29\")\n\njulia> collect(dr)\n7-element Vector{Date}:\n 2014-01-29\n 2014-02-28\n 2014-03-29\n 2014-04-29\n 2014-05-29\n 2014-06-29\n 2014-07-29","category":"page"},{"location":"stdlib/Dates/#Adjuster-Functions","page":"日期","title":"Adjuster Functions","text":"","category":"section"},{"location":"stdlib/Dates/","page":"日期","title":"日期","text":"As convenient as date-period arithmetic is, often the kinds of calculations needed on dates take on a calendrical or temporal nature rather than a fixed number of periods. Holidays are a perfect example; most follow rules such as \"Memorial Day = Last Monday of May\", or \"Thanksgiving = 4th Thursday of November\". These kinds of temporal expressions deal with rules relative to the calendar, like first or last of the month, next Tuesday, or the first and third Wednesdays, etc.","category":"page"},{"location":"stdlib/Dates/","page":"日期","title":"日期","text":"The Dates module provides the adjuster API through several convenient methods that aid in simply and succinctly expressing temporal rules. The first group of adjuster methods deal with the first and last of weeks, months, quarters, and years. They each take a single TimeType as input and return or adjust to the first or last of the desired period relative to the input.","category":"page"},{"location":"stdlib/Dates/","page":"日期","title":"日期","text":"julia> Dates.firstdayofweek(Date(2014,7,16)) # Adjusts the input to the Monday of the input's week\n2014-07-14\n\njulia> Dates.lastdayofmonth(Date(2014,7,16)) # Adjusts to the last day of the input's month\n2014-07-31\n\njulia> Dates.lastdayofquarter(Date(2014,7,16)) # Adjusts to the last day of the input's quarter\n2014-09-30","category":"page"},{"location":"stdlib/Dates/","page":"日期","title":"日期","text":"The next two higher-order methods, tonext, and toprev, generalize working with temporal expressions by taking a DateFunction as first argument, along with a starting TimeType. A DateFunction is just a function, usually anonymous, that takes a single TimeType as input and returns a Bool, true indicating a satisfied adjustment criterion. For example:","category":"page"},{"location":"stdlib/Dates/","page":"日期","title":"日期","text":"julia> istuesday = x->Dates.dayofweek(x) == Dates.Tuesday; # Returns true if the day of the week of x is Tuesday\n\njulia> Dates.tonext(istuesday, Date(2014,7,13)) # 2014-07-13 is a Sunday\n2014-07-15\n\njulia> Dates.tonext(Date(2014,7,13), Dates.Tuesday) # Convenience method provided for day of the week adjustments\n2014-07-15","category":"page"},{"location":"stdlib/Dates/","page":"日期","title":"日期","text":"This is useful with the do-block syntax for more complex temporal expressions:","category":"page"},{"location":"stdlib/Dates/","page":"日期","title":"日期","text":"julia> Dates.tonext(Date(2014,7,13)) do x\n # Return true on the 4th Thursday of November (Thanksgiving)\n Dates.dayofweek(x) == Dates.Thursday &&\n Dates.dayofweekofmonth(x) == 4 &&\n Dates.month(x) == Dates.November\n end\n2014-11-27","category":"page"},{"location":"stdlib/Dates/","page":"日期","title":"日期","text":"The Base.filter method can be used to obtain all valid dates/moments in a specified range:","category":"page"},{"location":"stdlib/Dates/","page":"日期","title":"日期","text":"# Pittsburgh street cleaning; Every 2nd Tuesday from April to November\n# Date range from January 1st, 2014 to January 1st, 2015\njulia> dr = Dates.Date(2014):Day(1):Dates.Date(2015);\n\njulia> filter(dr) do x\n Dates.dayofweek(x) == Dates.Tue &&\n Dates.April <= Dates.month(x) <= Dates.Nov &&\n Dates.dayofweekofmonth(x) == 2\n end\n8-element Vector{Date}:\n 2014-04-08\n 2014-05-13\n 2014-06-10\n 2014-07-08\n 2014-08-12\n 2014-09-09\n 2014-10-14\n 2014-11-11","category":"page"},{"location":"stdlib/Dates/","page":"日期","title":"日期","text":"Additional examples and tests are available in stdlib/Dates/test/adjusters.jl.","category":"page"},{"location":"stdlib/Dates/#Period-Types","page":"日期","title":"Period Types","text":"","category":"section"},{"location":"stdlib/Dates/","page":"日期","title":"日期","text":"Periods are a human view of discrete, sometimes irregular durations of time. Consider 1 month; it could represent, in days, a value of 28, 29, 30, or 31 depending on the year and month context. Or a year could represent 365 or 366 days in the case of a leap year. Period types are simple Int64 wrappers and are constructed by wrapping any Int64 convertible type, i.e. Year(1) or Month(3.0). Arithmetic between Period of the same type behave like integers, and limited Period-Real arithmetic is available. You can extract the underlying integer with Dates.value.","category":"page"},{"location":"stdlib/Dates/","page":"日期","title":"日期","text":"julia> y1 = Dates.Year(1)\n1 year\n\njulia> y2 = Dates.Year(2)\n2 years\n\njulia> y3 = Dates.Year(10)\n10 years\n\njulia> y1 + y2\n3 years\n\njulia> div(y3,y2)\n5\n\njulia> y3 - y2\n8 years\n\njulia> y3 % y2\n0 years\n\njulia> div(y3,3) # mirrors integer division\n3 years\n\njulia> Dates.value(Dates.Millisecond(10))\n10","category":"page"},{"location":"stdlib/Dates/#Rounding","page":"日期","title":"Rounding","text":"","category":"section"},{"location":"stdlib/Dates/","page":"日期","title":"日期","text":"Date and DateTime values can be rounded to a specified resolution (e.g., 1 month or 15 minutes) with floor, ceil, or round:","category":"page"},{"location":"stdlib/Dates/","page":"日期","title":"日期","text":"julia> floor(Date(1985, 8, 16), Dates.Month)\n1985-08-01\n\njulia> ceil(DateTime(2013, 2, 13, 0, 31, 20), Dates.Minute(15))\n2013-02-13T00:45:00\n\njulia> round(DateTime(2016, 8, 6, 20, 15), Dates.Day)\n2016-08-07T00:00:00","category":"page"},{"location":"stdlib/Dates/","page":"日期","title":"日期","text":"Unlike the numeric round method, which breaks ties toward the even number by default, the TimeTyperound method uses the RoundNearestTiesUp rounding mode. (It's difficult to guess what breaking ties to nearest \"even\" TimeType would entail.) Further details on the available RoundingMode s can be found in the API reference.","category":"page"},{"location":"stdlib/Dates/","page":"日期","title":"日期","text":"Rounding should generally behave as expected, but there are a few cases in which the expected behaviour is not obvious.","category":"page"},{"location":"stdlib/Dates/#Rounding-Epoch","page":"日期","title":"Rounding Epoch","text":"","category":"section"},{"location":"stdlib/Dates/","page":"日期","title":"日期","text":"In many cases, the resolution specified for rounding (e.g., Dates.Second(30)) divides evenly into the next largest period (in this case, Dates.Minute(1)). But rounding behaviour in cases in which this is not true may lead to confusion. What is the expected result of rounding a DateTime to the nearest 10 hours?","category":"page"},{"location":"stdlib/Dates/","page":"日期","title":"日期","text":"julia> round(DateTime(2016, 7, 17, 11, 55), Dates.Hour(10))\n2016-07-17T12:00:00","category":"page"},{"location":"stdlib/Dates/","page":"日期","title":"日期","text":"That may seem confusing, given that the hour (12) is not divisible by 10. The reason that 2016-07-17T12:00:00 was chosen is that it is 17,676,660 hours after 0000-01-01T00:00:00, and 17,676,660 is divisible by 10.","category":"page"},{"location":"stdlib/Dates/","page":"日期","title":"日期","text":"As Julia Date and DateTime values are represented according to the ISO 8601 standard, 0000-01-01T00:00:00 was chosen as base (or \"rounding epoch\") from which to begin the count of days (and milliseconds) used in rounding calculations. (Note that this differs slightly from Julia's internal representation of Date s using Rata Die notation; but since the ISO 8601 standard is most visible to the end user, 0000-01-01T00:00:00 was chosen as the rounding epoch instead of the 0000-12-31T00:00:00 used internally to minimize confusion.)","category":"page"},{"location":"stdlib/Dates/","page":"日期","title":"日期","text":"The only exception to the use of 0000-01-01T00:00:00 as the rounding epoch is when rounding to weeks. Rounding to the nearest week will always return a Monday (the first day of the week as specified by ISO 8601). For this reason, we use 0000-01-03T00:00:00 (the first day of the first week of year 0000, as defined by ISO 8601) as the base when rounding to a number of weeks.","category":"page"},{"location":"stdlib/Dates/","page":"日期","title":"日期","text":"Here is a related case in which the expected behaviour is not necessarily obvious: What happens when we round to the nearest P(2), where P is a Period type? In some cases (specifically, when P <: Dates.TimePeriod) the answer is clear:","category":"page"},{"location":"stdlib/Dates/","page":"日期","title":"日期","text":"julia> round(DateTime(2016, 7, 17, 8, 55, 30), Dates.Hour(2))\n2016-07-17T08:00:00\n\njulia> round(DateTime(2016, 7, 17, 8, 55, 30), Dates.Minute(2))\n2016-07-17T08:56:00","category":"page"},{"location":"stdlib/Dates/","page":"日期","title":"日期","text":"This seems obvious, because two of each of these periods still divides evenly into the next larger order period. But in the case of two months (which still divides evenly into one year), the answer may be surprising:","category":"page"},{"location":"stdlib/Dates/","page":"日期","title":"日期","text":"julia> round(DateTime(2016, 7, 17, 8, 55, 30), Dates.Month(2))\n2016-07-01T00:00:00","category":"page"},{"location":"stdlib/Dates/","page":"日期","title":"日期","text":"Why round to the first day in July, even though it is month 7 (an odd number)? The key is that months are 1-indexed (the first month is assigned 1), unlike hours, minutes, seconds, and milliseconds (the first of which are assigned 0).","category":"page"},{"location":"stdlib/Dates/","page":"日期","title":"日期","text":"This means that rounding a DateTime to an even multiple of seconds, minutes, hours, or years (because the ISO 8601 specification includes a year zero) will result in a DateTime with an even value in that field, while rounding a DateTime to an even multiple of months will result in the months field having an odd value. Because both months and years may contain an irregular number of days, whether rounding to an even number of days will result in an even value in the days field is uncertain.","category":"page"},{"location":"stdlib/Dates/","page":"日期","title":"日期","text":"See the API reference for additional information on methods exported from the Dates module.","category":"page"},{"location":"stdlib/Dates/#stdlib-dates-api","page":"日期","title":"API reference","text":"","category":"section"},{"location":"stdlib/Dates/#Dates-and-Time-Types","page":"日期","title":"Dates and Time Types","text":"","category":"section"},{"location":"stdlib/Dates/","page":"日期","title":"日期","text":"Dates.Period\nDates.CompoundPeriod\nDates.Instant\nDates.UTInstant\nDates.TimeType\nDates.DateTime\nDates.Date\nDates.Time\nDates.TimeZone\nDates.UTC","category":"page"},{"location":"stdlib/Dates/#Dates.Period","page":"日期","title":"Dates.Period","text":"Period\nYear\nQuarter\nMonth\nWeek\nDay\nHour\nMinute\nSecond\nMillisecond\nMicrosecond\nNanosecond\n\nPeriod types represent discrete, human representations of time.\n\n\n\n\n\n","category":"type"},{"location":"stdlib/Dates/#Dates.CompoundPeriod","page":"日期","title":"Dates.CompoundPeriod","text":"CompoundPeriod\n\nA CompoundPeriod is useful for expressing time periods that are not a fixed multiple of smaller periods. For example, \"a year and a day\" is not a fixed number of days, but can be expressed using a CompoundPeriod. In fact, a CompoundPeriod is automatically generated by addition of different period types, e.g. Year(1) + Day(1) produces a CompoundPeriod result.\n\n\n\n\n\n","category":"type"},{"location":"stdlib/Dates/#Dates.Instant","page":"日期","title":"Dates.Instant","text":"Instant\n\nInstant types represent integer-based, machine representations of time as continuous timelines starting from an epoch.\n\n\n\n\n\n","category":"type"},{"location":"stdlib/Dates/#Dates.UTInstant","page":"日期","title":"Dates.UTInstant","text":"UTInstant{T}\n\nThe UTInstant represents a machine timeline based on UT time (1 day = one revolution of the earth). The T is a Period parameter that indicates the resolution or precision of the instant.\n\n\n\n\n\n","category":"type"},{"location":"stdlib/Dates/#Dates.TimeType","page":"日期","title":"Dates.TimeType","text":"TimeType\n\nTimeType types wrap Instant machine instances to provide human representations of the machine instant. Time, DateTime and Date are subtypes of TimeType.\n\n\n\n\n\n","category":"type"},{"location":"stdlib/Dates/#Dates.DateTime","page":"日期","title":"Dates.DateTime","text":"DateTime\n\nDateTime wraps a UTInstant{Millisecond} and interprets it according to the proleptic Gregorian calendar.\n\n\n\n\n\n","category":"type"},{"location":"stdlib/Dates/#Dates.Date","page":"日期","title":"Dates.Date","text":"Date\n\nDate wraps a UTInstant{Day} and interprets it according to the proleptic Gregorian calendar.\n\n\n\n\n\n","category":"type"},{"location":"stdlib/Dates/#Dates.Time","page":"日期","title":"Dates.Time","text":"Time\n\nTime wraps a Nanosecond and represents a specific moment in a 24-hour day.\n\n\n\n\n\n","category":"type"},{"location":"stdlib/Dates/#Dates.TimeZone","page":"日期","title":"Dates.TimeZone","text":"TimeZone\n\nGeographic zone generally based on longitude determining what the time is at a certain location. Some time zones observe daylight savings (eg EST -> EDT). For implementations and more support, see the TimeZones.jl package\n\n\n\n\n\n","category":"type"},{"location":"stdlib/Dates/#Dates.UTC","page":"日期","title":"Dates.UTC","text":"UTC\n\nUTC, or Coordinated Universal Time, is the TimeZone from which all others are measured. It is associated with the time at 0° longitude. It is not adjusted for daylight savings.\n\n\n\n\n\n","category":"type"},{"location":"stdlib/Dates/#Dates-Functions","page":"日期","title":"Dates Functions","text":"","category":"section"},{"location":"stdlib/Dates/","page":"日期","title":"日期","text":"Dates.DateTime(::Int64, ::Int64, ::Int64, ::Int64, ::Int64, ::Int64, ::Int64)\nDates.DateTime(::Dates.Period)\nDates.DateTime(::Function, ::Any...)\nDates.DateTime(::Dates.TimeType)\nDates.DateTime(::AbstractString, ::AbstractString)\nDates.format(::Dates.TimeType, ::AbstractString)\nDates.DateFormat\nDates.@dateformat_str\nDates.DateTime(::AbstractString, ::Dates.DateFormat)\nDates.Date(::Int64, ::Int64, ::Int64)\nDates.Date(::Dates.Period)\nDates.Date(::Function, ::Any, ::Any, ::Any)\nDates.Date(::Dates.TimeType)\nDates.Date(::AbstractString, ::AbstractString)\nDates.Date(::AbstractString, ::Dates.DateFormat)\nDates.Time(::Int64::Int64, ::Int64, ::Int64, ::Int64, ::Int64)\nDates.Time(::Dates.TimePeriod)\nDates.Time(::Function, ::Any...)\nDates.Time(::Dates.DateTime)\nDates.Time(::AbstractString, ::AbstractString)\nDates.Time(::AbstractString, ::Dates.DateFormat)\nDates.now()\nDates.now(::Type{Dates.UTC})\nBase.eps(::Union{Type{DateTime}, Type{Date}, Type{Time}, TimeType})","category":"page"},{"location":"stdlib/Dates/#Dates.DateTime-NTuple{7, Int64}","page":"日期","title":"Dates.DateTime","text":"DateTime(y, [m, d, h, mi, s, ms]) -> DateTime\n\nConstruct a DateTime type by parts. Arguments must be convertible to Int64.\n\n\n\n\n\n","category":"method"},{"location":"stdlib/Dates/#Dates.DateTime-Tuple{Period}","page":"日期","title":"Dates.DateTime","text":"DateTime(periods::Period...) -> DateTime\n\nConstruct a DateTime type by Period type parts. Arguments may be in any order. DateTime parts not provided will default to the value of Dates.default(period).\n\n\n\n\n\n","category":"method"},{"location":"stdlib/Dates/#Dates.DateTime-Tuple{Function, Vararg{Any}}","page":"日期","title":"Dates.DateTime","text":"DateTime(f::Function, y[, m, d, h, mi, s]; step=Day(1), limit=10000) -> DateTime\n\nCreate a DateTime through the adjuster API. The starting point will be constructed from the provided y, m, d... arguments, and will be adjusted until f::Function returns true. The step size in adjusting can be provided manually through the step keyword. limit provides a limit to the max number of iterations the adjustment API will pursue before throwing an error (in the case that f::Function is never satisfied).\n\nExamples\n\njulia> DateTime(dt -> Dates.second(dt) == 40, 2010, 10, 20, 10; step = Dates.Second(1))\n2010-10-20T10:00:40\n\njulia> DateTime(dt -> Dates.hour(dt) == 20, 2010, 10, 20, 10; step = Dates.Hour(1), limit = 5)\nERROR: ArgumentError: Adjustment limit reached: 5 iterations\nStacktrace:\n[...]\n\n\n\n\n\n","category":"method"},{"location":"stdlib/Dates/#Dates.DateTime-Tuple{TimeType}","page":"日期","title":"Dates.DateTime","text":"DateTime(dt::Date) -> DateTime\n\nConvert a Date to a DateTime. The hour, minute, second, and millisecond parts of the new DateTime are assumed to be zero.\n\n\n\n\n\n","category":"method"},{"location":"stdlib/Dates/#Dates.DateTime-Tuple{AbstractString, AbstractString}","page":"日期","title":"Dates.DateTime","text":"DateTime(dt::AbstractString, format::AbstractString; locale=\"english\") -> DateTime\n\nConstruct a DateTime by parsing the dt date time string following the pattern given in the format string (see DateFormat for syntax).\n\nnote: Note\nThis method creates a DateFormat object each time it is called. It is recommended that you create a DateFormat object instead and use that as the second argument to avoid performance loss when using the same format repeatedly.\n\nExample\n\njulia> DateTime(\"2020-01-01\", \"yyyy-mm-dd\")\n2020-01-01T00:00:00\n\njulia> a = (\"2020-01-01\", \"2020-01-02\");\n\njulia> [DateTime(d, dateformat\"yyyy-mm-dd\") for d ∈ a] # preferred\n2-element Vector{DateTime}:\n 2020-01-01T00:00:00\n 2020-01-02T00:00:00\n\n\n\n\n\n","category":"method"},{"location":"stdlib/Dates/#Dates.format-Tuple{TimeType, AbstractString}","page":"日期","title":"Dates.format","text":"format(dt::TimeType, format::AbstractString; locale=\"english\") -> AbstractString\n\nConstruct a string by using a TimeType object and applying the provided format. The following character codes can be used to construct the format string:\n\nCode Examples Comment\ny 6 Numeric year with a fixed width\nY 1996 Numeric year with a minimum width\nm 1, 12 Numeric month with a minimum width\nu Jan Month name shortened to 3-chars according to the locale\nU January Full month name according to the locale keyword\nd 1, 31 Day of the month with a minimum width\nH 0, 23 Hour (24-hour clock) with a minimum width\nM 0, 59 Minute with a minimum width\nS 0, 59 Second with a minimum width\ns 000, 500 Millisecond with a minimum width of 3\ne Mon, Tue Abbreviated days of the week\nE Monday Full day of week name\n\nThe number of sequential code characters indicate the width of the code. A format of yyyy-mm specifies that the code y should have a width of four while m a width of two. Codes that yield numeric digits have an associated mode: fixed-width or minimum-width. The fixed-width mode left-pads the value with zeros when it is shorter than the specified width and truncates the value when longer. Minimum-width mode works the same as fixed-width except that it does not truncate values longer than the width.\n\nWhen creating a format you can use any non-code characters as a separator. For example to generate the string \"1996-01-15T00:00:00\" you could use format: \"yyyy-mm-ddTHH:MM:SS\". Note that if you need to use a code character as a literal you can use the escape character backslash. The string \"1996y01m\" can be produced with the format \"yyyy\\ymm\\m\".\n\n\n\n\n\n","category":"method"},{"location":"stdlib/Dates/#Dates.DateFormat","page":"日期","title":"Dates.DateFormat","text":"DateFormat(format::AbstractString, locale=\"english\") -> DateFormat\n\nConstruct a date formatting object that can be used for parsing date strings or formatting a date object as a string. The following character codes can be used to construct the format string:\n\nCode Matches Comment\ny 1996, 96 Returns year of 1996, 0096\nY 1996, 96 Returns year of 1996, 0096. Equivalent to y\nm 1, 01 Matches 1 or 2-digit months\nu Jan Matches abbreviated months according to the locale keyword\nU January Matches full month names according to the locale keyword\nd 1, 01 Matches 1 or 2-digit days\nH 00 Matches hours (24-hour clock)\nI 00 For outputting hours with 12-hour clock\nM 00 Matches minutes\nS 00 Matches seconds\ns .500 Matches milliseconds\ne Mon, Tues Matches abbreviated days of the week\nE Monday Matches full name days of the week\np AM Matches AM/PM (case-insensitive)\nyyyymmdd 19960101 Matches fixed-width year, month, and day\n\nCharacters not listed above are normally treated as delimiters between date and time slots. For example a dt string of \"1996-01-15T00:00:00.0\" would have a format string like \"y-m-dTH:M:S.s\". If you need to use a code character as a delimiter you can escape it using backslash. The date \"1995y01m\" would have the format \"y\\ym\\m\".\n\nNote that 12:00AM corresponds 00:00 (midnight), and 12:00PM corresponds to 12:00 (noon). When parsing a time with a p specifier, any hour (either H or I) is interpreted as as a 12-hour clock, so the I code is mainly useful for output.\n\nCreating a DateFormat object is expensive. Whenever possible, create it once and use it many times or try the dateformat\"\" string macro. Using this macro creates the DateFormat object once at macro expansion time and reuses it later. There are also several pre-defined formatters, listed later.\n\nSee DateTime and format for how to use a DateFormat object to parse and write Date strings respectively.\n\n\n\n\n\n","category":"type"},{"location":"stdlib/Dates/#Dates.@dateformat_str","page":"日期","title":"Dates.@dateformat_str","text":"dateformat\"Y-m-d H:M:S\"\n\nCreate a DateFormat object. Similar to DateFormat(\"Y-m-d H:M:S\") but creates the DateFormat object once during macro expansion.\n\nSee DateFormat for details about format specifiers.\n\n\n\n\n\n","category":"macro"},{"location":"stdlib/Dates/#Dates.DateTime-Tuple{AbstractString, DateFormat}","page":"日期","title":"Dates.DateTime","text":"DateTime(dt::AbstractString, df::DateFormat=ISODateTimeFormat) -> DateTime\n\nConstruct a DateTime by parsing the dt date time string following the pattern given in the DateFormat object, or dateformat\"yyyy-mm-ddTHH:MM:SS.s\" if omitted.\n\nSimilar to DateTime(::AbstractString, ::AbstractString) but more efficient when repeatedly parsing similarly formatted date time strings with a pre-created DateFormat object.\n\n\n\n\n\n","category":"method"},{"location":"stdlib/Dates/#Dates.Date-Tuple{Int64, Int64, Int64}","page":"日期","title":"Dates.Date","text":"Date(y, [m, d]) -> Date\n\nConstruct a Date type by parts. Arguments must be convertible to Int64.\n\n\n\n\n\n","category":"method"},{"location":"stdlib/Dates/#Dates.Date-Tuple{Period}","page":"日期","title":"Dates.Date","text":"Date(period::Period...) -> Date\n\nConstruct a Date type by Period type parts. Arguments may be in any order. Date parts not provided will default to the value of Dates.default(period).\n\n\n\n\n\n","category":"method"},{"location":"stdlib/Dates/#Dates.Date-Tuple{Function, Any, Any, Any}","page":"日期","title":"Dates.Date","text":"Date(f::Function, y[, m, d]; step=Day(1), limit=10000) -> Date\n\nCreate a Date through the adjuster API. The starting point will be constructed from the provided y, m, d arguments, and will be adjusted until f::Function returns true. The step size in adjusting can be provided manually through the step keyword. limit provides a limit to the max number of iterations the adjustment API will pursue before throwing an error (given that f::Function is never satisfied).\n\nExamples\n\njulia> Date(date -> Dates.week(date) == 20, 2010, 01, 01)\n2010-05-17\n\njulia> Date(date -> Dates.year(date) == 2010, 2000, 01, 01)\n2010-01-01\n\njulia> Date(date -> Dates.month(date) == 10, 2000, 01, 01; limit = 5)\nERROR: ArgumentError: Adjustment limit reached: 5 iterations\nStacktrace:\n[...]\n\n\n\n\n\n","category":"method"},{"location":"stdlib/Dates/#Dates.Date-Tuple{TimeType}","page":"日期","title":"Dates.Date","text":"Date(dt::DateTime) -> Date\n\nConvert a DateTime to a Date. The hour, minute, second, and millisecond parts of the DateTime are truncated, so only the year, month and day parts are used in construction.\n\n\n\n\n\n","category":"method"},{"location":"stdlib/Dates/#Dates.Date-Tuple{AbstractString, AbstractString}","page":"日期","title":"Dates.Date","text":"Date(d::AbstractString, format::AbstractString; locale=\"english\") -> Date\n\nConstruct a Date by parsing the d date string following the pattern given in the format string (see DateFormat for syntax).\n\nnote: Note\nThis method creates a DateFormat object each time it is called. It is recommended that you create a DateFormat object instead and use that as the second argument to avoid performance loss when using the same format repeatedly.\n\nExample\n\njulia> Date(\"2020-01-01\", \"yyyy-mm-dd\")\n2020-01-01\n\njulia> a = (\"2020-01-01\", \"2020-01-02\");\n\njulia> [Date(d, dateformat\"yyyy-mm-dd\") for d ∈ a] # preferred\n2-element Vector{Date}:\n 2020-01-01\n 2020-01-02\n\n\n\n\n\n","category":"method"},{"location":"stdlib/Dates/#Dates.Date-Tuple{AbstractString, DateFormat}","page":"日期","title":"Dates.Date","text":"Date(d::AbstractString, df::DateFormat=ISODateFormat) -> Date\n\nConstruct a Date by parsing the d date string following the pattern given in the DateFormat object, or dateformat\"yyyy-mm-dd\" if omitted.\n\nSimilar to Date(::AbstractString, ::AbstractString) but more efficient when repeatedly parsing similarly formatted date strings with a pre-created DateFormat object.\n\n\n\n\n\n","category":"method"},{"location":"stdlib/Dates/#Dates.Time-NTuple{5, Int64}","page":"日期","title":"Dates.Time","text":"Time(h, [mi, s, ms, us, ns]) -> Time\n\nConstruct a Time type by parts. Arguments must be convertible to Int64.\n\n\n\n\n\n","category":"method"},{"location":"stdlib/Dates/#Dates.Time-Tuple{TimePeriod}","page":"日期","title":"Dates.Time","text":"Time(period::TimePeriod...) -> Time\n\nConstruct a Time type by Period type parts. Arguments may be in any order. Time parts not provided will default to the value of Dates.default(period).\n\n\n\n\n\n","category":"method"},{"location":"stdlib/Dates/#Dates.Time-Tuple{Function, Vararg{Any}}","page":"日期","title":"Dates.Time","text":"Time(f::Function, h, mi=0; step::Period=Second(1), limit::Int=10000)\nTime(f::Function, h, mi, s; step::Period=Millisecond(1), limit::Int=10000)\nTime(f::Function, h, mi, s, ms; step::Period=Microsecond(1), limit::Int=10000)\nTime(f::Function, h, mi, s, ms, us; step::Period=Nanosecond(1), limit::Int=10000)\n\nCreate a Time through the adjuster API. The starting point will be constructed from the provided h, mi, s, ms, us arguments, and will be adjusted until f::Function returns true. The step size in adjusting can be provided manually through the step keyword. limit provides a limit to the max number of iterations the adjustment API will pursue before throwing an error (in the case that f::Function is never satisfied). Note that the default step will adjust to allow for greater precision for the given arguments; i.e. if hour, minute, and second arguments are provided, the default step will be Millisecond(1) instead of Second(1).\n\nExamples\n\njulia> Dates.Time(t -> Dates.minute(t) == 30, 20)\n20:30:00\n\njulia> Dates.Time(t -> Dates.minute(t) == 0, 20)\n20:00:00\n\njulia> Dates.Time(t -> Dates.hour(t) == 10, 3; limit = 5)\nERROR: ArgumentError: Adjustment limit reached: 5 iterations\nStacktrace:\n[...]\n\n\n\n\n\n","category":"method"},{"location":"stdlib/Dates/#Dates.Time-Tuple{DateTime}","page":"日期","title":"Dates.Time","text":"Time(dt::DateTime) -> Time\n\nConvert a DateTime to a Time. The hour, minute, second, and millisecond parts of the DateTime are used to create the new Time. Microsecond and nanoseconds are zero by default.\n\n\n\n\n\n","category":"method"},{"location":"stdlib/Dates/#Dates.Time-Tuple{AbstractString, AbstractString}","page":"日期","title":"Dates.Time","text":"Time(t::AbstractString, format::AbstractString; locale=\"english\") -> Time\n\nConstruct a Time by parsing the t time string following the pattern given in the format string (see DateFormat for syntax).\n\nnote: Note\nThis method creates a DateFormat object each time it is called. It is recommended that you create a DateFormat object instead and use that as the second argument to avoid performance loss when using the same format repeatedly.\n\nExample\n\njulia> Time(\"12:34pm\", \"HH:MMp\")\n12:34:00\n\njulia> a = (\"12:34pm\", \"2:34am\");\n\njulia> [Time(d, dateformat\"HH:MMp\") for d ∈ a] # preferred\n2-element Vector{Time}:\n 12:34:00\n 02:34:00\n\n\n\n\n\n","category":"method"},{"location":"stdlib/Dates/#Dates.Time-Tuple{AbstractString, DateFormat}","page":"日期","title":"Dates.Time","text":"Time(t::AbstractString, df::DateFormat=ISOTimeFormat) -> Time\n\nConstruct a Time by parsing the t date time string following the pattern given in the DateFormat object, or dateformat\"HH:MM:SS.s\" if omitted.\n\nSimilar to Time(::AbstractString, ::AbstractString) but more efficient when repeatedly parsing similarly formatted time strings with a pre-created DateFormat object.\n\n\n\n\n\n","category":"method"},{"location":"stdlib/Dates/#Dates.now-Tuple{}","page":"日期","title":"Dates.now","text":"now() -> DateTime\n\nReturn a DateTime corresponding to the user's system time including the system timezone locale.\n\n\n\n\n\n","category":"method"},{"location":"stdlib/Dates/#Dates.now-Tuple{Type{UTC}}","page":"日期","title":"Dates.now","text":"now(::Type{UTC}) -> DateTime\n\nReturn a DateTime corresponding to the user's system time as UTC/GMT.\n\n\n\n\n\n","category":"method"},{"location":"stdlib/Dates/#Base.eps-Tuple{Union{Type{Date}, Type{DateTime}, Type{Time}, TimeType}}","page":"日期","title":"Base.eps","text":"eps(::Type{DateTime}) -> Millisecond\neps(::Type{Date}) -> Day\neps(::Type{Time}) -> Nanosecond\neps(::TimeType) -> Period\n\nReturn the smallest unit value supported by the TimeType.\n\nExamples\n\njulia> eps(DateTime)\n1 millisecond\n\njulia> eps(Date)\n1 day\n\njulia> eps(Time)\n1 nanosecond\n\n\n\n\n\n","category":"method"},{"location":"stdlib/Dates/#Accessor-Functions-2","page":"日期","title":"Accessor Functions","text":"","category":"section"},{"location":"stdlib/Dates/","page":"日期","title":"日期","text":"Dates.year\nDates.month\nDates.week\nDates.day\nDates.hour\nDates.minute\nDates.second\nDates.millisecond\nDates.microsecond\nDates.nanosecond\nDates.Year(::Dates.TimeType)\nDates.Month(::Dates.TimeType)\nDates.Week(::Dates.TimeType)\nDates.Day(::Dates.TimeType)\nDates.Hour(::DateTime)\nDates.Minute(::DateTime)\nDates.Second(::DateTime)\nDates.Millisecond(::DateTime)\nDates.Microsecond(::Dates.Time)\nDates.Nanosecond(::Dates.Time)\nDates.yearmonth\nDates.monthday\nDates.yearmonthday","category":"page"},{"location":"stdlib/Dates/#Dates.year","page":"日期","title":"Dates.year","text":"year(dt::TimeType) -> Int64\n\nThe year of a Date or DateTime as an Int64.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/Dates/#Dates.month","page":"日期","title":"Dates.month","text":"month(dt::TimeType) -> Int64\n\nThe month of a Date or DateTime as an Int64.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/Dates/#Dates.week","page":"日期","title":"Dates.week","text":"week(dt::TimeType) -> Int64\n\nReturn the ISO week date of a Date or DateTime as an Int64. Note that the first week of a year is the week that contains the first Thursday of the year, which can result in dates prior to January 4th being in the last week of the previous year. For example, week(Date(2005, 1, 1)) is the 53rd week of 2004.\n\nExamples\n\njulia> Dates.week(Date(1989, 6, 22))\n25\n\njulia> Dates.week(Date(2005, 1, 1))\n53\n\njulia> Dates.week(Date(2004, 12, 31))\n53\n\n\n\n\n\n","category":"function"},{"location":"stdlib/Dates/#Dates.day","page":"日期","title":"Dates.day","text":"day(dt::TimeType) -> Int64\n\nThe day of month of a Date or DateTime as an Int64.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/Dates/#Dates.hour","page":"日期","title":"Dates.hour","text":"hour(dt::DateTime) -> Int64\n\nThe hour of day of a DateTime as an Int64.\n\n\n\n\n\nhour(t::Time) -> Int64\n\nThe hour of a Time as an Int64.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/Dates/#Dates.minute","page":"日期","title":"Dates.minute","text":"minute(dt::DateTime) -> Int64\n\nThe minute of a DateTime as an Int64.\n\n\n\n\n\nminute(t::Time) -> Int64\n\nThe minute of a Time as an Int64.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/Dates/#Dates.second","page":"日期","title":"Dates.second","text":"second(dt::DateTime) -> Int64\n\nThe second of a DateTime as an Int64.\n\n\n\n\n\nsecond(t::Time) -> Int64\n\nThe second of a Time as an Int64.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/Dates/#Dates.millisecond","page":"日期","title":"Dates.millisecond","text":"millisecond(dt::DateTime) -> Int64\n\nThe millisecond of a DateTime as an Int64.\n\n\n\n\n\nmillisecond(t::Time) -> Int64\n\nThe millisecond of a Time as an Int64.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/Dates/#Dates.microsecond","page":"日期","title":"Dates.microsecond","text":"microsecond(t::Time) -> Int64\n\nThe microsecond of a Time as an Int64.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/Dates/#Dates.nanosecond","page":"日期","title":"Dates.nanosecond","text":"nanosecond(t::Time) -> Int64\n\nThe nanosecond of a Time as an Int64.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/Dates/#Dates.Year-Tuple{TimeType}","page":"日期","title":"Dates.Year","text":"Year(v)\n\nConstruct a Year object with the given v value. Input must be losslessly convertible to an Int64.\n\n\n\n\n\n","category":"method"},{"location":"stdlib/Dates/#Dates.Month-Tuple{TimeType}","page":"日期","title":"Dates.Month","text":"Month(v)\n\nConstruct a Month object with the given v value. Input must be losslessly convertible to an Int64.\n\n\n\n\n\n","category":"method"},{"location":"stdlib/Dates/#Dates.Week-Tuple{TimeType}","page":"日期","title":"Dates.Week","text":"Week(v)\n\nConstruct a Week object with the given v value. Input must be losslessly convertible to an Int64.\n\n\n\n\n\n","category":"method"},{"location":"stdlib/Dates/#Dates.Day-Tuple{TimeType}","page":"日期","title":"Dates.Day","text":"Day(v)\n\nConstruct a Day object with the given v value. Input must be losslessly convertible to an Int64.\n\n\n\n\n\n","category":"method"},{"location":"stdlib/Dates/#Dates.Hour-Tuple{DateTime}","page":"日期","title":"Dates.Hour","text":"Hour(dt::DateTime) -> Hour\n\nThe hour part of a DateTime as a Hour.\n\n\n\n\n\n","category":"method"},{"location":"stdlib/Dates/#Dates.Minute-Tuple{DateTime}","page":"日期","title":"Dates.Minute","text":"Minute(dt::DateTime) -> Minute\n\nThe minute part of a DateTime as a Minute.\n\n\n\n\n\n","category":"method"},{"location":"stdlib/Dates/#Dates.Second-Tuple{DateTime}","page":"日期","title":"Dates.Second","text":"Second(dt::DateTime) -> Second\n\nThe second part of a DateTime as a Second.\n\n\n\n\n\n","category":"method"},{"location":"stdlib/Dates/#Dates.Millisecond-Tuple{DateTime}","page":"日期","title":"Dates.Millisecond","text":"Millisecond(dt::DateTime) -> Millisecond\n\nThe millisecond part of a DateTime as a Millisecond.\n\n\n\n\n\n","category":"method"},{"location":"stdlib/Dates/#Dates.Microsecond-Tuple{Time}","page":"日期","title":"Dates.Microsecond","text":"Microsecond(dt::Time) -> Microsecond\n\nThe microsecond part of a Time as a Microsecond.\n\n\n\n\n\n","category":"method"},{"location":"stdlib/Dates/#Dates.Nanosecond-Tuple{Time}","page":"日期","title":"Dates.Nanosecond","text":"Nanosecond(dt::Time) -> Nanosecond\n\nThe nanosecond part of a Time as a Nanosecond.\n\n\n\n\n\n","category":"method"},{"location":"stdlib/Dates/#Dates.yearmonth","page":"日期","title":"Dates.yearmonth","text":"yearmonth(dt::TimeType) -> (Int64, Int64)\n\nSimultaneously return the year and month parts of a Date or DateTime.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/Dates/#Dates.monthday","page":"日期","title":"Dates.monthday","text":"monthday(dt::TimeType) -> (Int64, Int64)\n\nSimultaneously return the month and day parts of a Date or DateTime.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/Dates/#Dates.yearmonthday","page":"日期","title":"Dates.yearmonthday","text":"yearmonthday(dt::TimeType) -> (Int64, Int64, Int64)\n\nSimultaneously return the year, month and day parts of a Date or DateTime.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/Dates/#Query-Functions-2","page":"日期","title":"Query Functions","text":"","category":"section"},{"location":"stdlib/Dates/","page":"日期","title":"日期","text":"Dates.dayname\nDates.dayabbr\nDates.dayofweek\nDates.dayofmonth\nDates.dayofweekofmonth\nDates.daysofweekinmonth\nDates.monthname\nDates.monthabbr\nDates.daysinmonth\nDates.isleapyear\nDates.dayofyear\nDates.daysinyear\nDates.quarterofyear\nDates.dayofquarter","category":"page"},{"location":"stdlib/Dates/#Dates.dayname","page":"日期","title":"Dates.dayname","text":"dayname(dt::TimeType; locale=\"english\") -> String\ndayname(day::Integer; locale=\"english\") -> String\n\nReturn the full day name corresponding to the day of the week of the Date or DateTime in the given locale. Also accepts Integer.\n\nExamples\n\njulia> Dates.dayname(Date(\"2000-01-01\"))\n\"Saturday\"\n\njulia> Dates.dayname(4)\n\"Thursday\"\n\n\n\n\n\n","category":"function"},{"location":"stdlib/Dates/#Dates.dayabbr","page":"日期","title":"Dates.dayabbr","text":"dayabbr(dt::TimeType; locale=\"english\") -> String\ndayabbr(day::Integer; locale=\"english\") -> String\n\nReturn the abbreviated name corresponding to the day of the week of the Date or DateTime in the given locale. Also accepts Integer.\n\nExamples\n\njulia> Dates.dayabbr(Date(\"2000-01-01\"))\n\"Sat\"\n\njulia> Dates.dayabbr(3)\n\"Wed\"\n\n\n\n\n\n","category":"function"},{"location":"stdlib/Dates/#Dates.dayofweek","page":"日期","title":"Dates.dayofweek","text":"dayofweek(dt::TimeType) -> Int64\n\nReturn the day of the week as an Int64 with 1 = Monday, 2 = Tuesday, etc..\n\nExamples\n\njulia> Dates.dayofweek(Date(\"2000-01-01\"))\n6\n\n\n\n\n\n","category":"function"},{"location":"stdlib/Dates/#Dates.dayofmonth","page":"日期","title":"Dates.dayofmonth","text":"dayofmonth(dt::TimeType) -> Int64\n\nThe day of month of a Date or DateTime as an Int64.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/Dates/#Dates.dayofweekofmonth","page":"日期","title":"Dates.dayofweekofmonth","text":"dayofweekofmonth(dt::TimeType) -> Int\n\nFor the day of week of dt, return which number it is in dt's month. So if the day of the week of dt is Monday, then 1 = First Monday of the month, 2 = Second Monday of the month, etc. In the range 1:5.\n\nExamples\n\njulia> Dates.dayofweekofmonth(Date(\"2000-02-01\"))\n1\n\njulia> Dates.dayofweekofmonth(Date(\"2000-02-08\"))\n2\n\njulia> Dates.dayofweekofmonth(Date(\"2000-02-15\"))\n3\n\n\n\n\n\n","category":"function"},{"location":"stdlib/Dates/#Dates.daysofweekinmonth","page":"日期","title":"Dates.daysofweekinmonth","text":"daysofweekinmonth(dt::TimeType) -> Int\n\nFor the day of week of dt, return the total number of that day of the week in dt's month. Returns 4 or 5. Useful in temporal expressions for specifying the last day of a week in a month by including dayofweekofmonth(dt) == daysofweekinmonth(dt) in the adjuster function.\n\nExamples\n\njulia> Dates.daysofweekinmonth(Date(\"2005-01-01\"))\n5\n\njulia> Dates.daysofweekinmonth(Date(\"2005-01-04\"))\n4\n\n\n\n\n\n","category":"function"},{"location":"stdlib/Dates/#Dates.monthname","page":"日期","title":"Dates.monthname","text":"monthname(dt::TimeType; locale=\"english\") -> String\nmonthname(month::Integer, locale=\"english\") -> String\n\nReturn the full name of the month of the Date or DateTime or Integer in the given locale.\n\nExamples\n\njulia> Dates.monthname(Date(\"2005-01-04\"))\n\"January\"\n\njulia> Dates.monthname(2)\n\"February\"\n\n\n\n\n\n","category":"function"},{"location":"stdlib/Dates/#Dates.monthabbr","page":"日期","title":"Dates.monthabbr","text":"monthabbr(dt::TimeType; locale=\"english\") -> String\nmonthabbr(month::Integer, locale=\"english\") -> String\n\nReturn the abbreviated month name of the Date or DateTime or Integer in the given locale.\n\nExamples\n\njulia> Dates.monthabbr(Date(\"2005-01-04\"))\n\"Jan\"\n\njulia> monthabbr(2)\n\"Feb\"\n\n\n\n\n\n","category":"function"},{"location":"stdlib/Dates/#Dates.daysinmonth","page":"日期","title":"Dates.daysinmonth","text":"daysinmonth(dt::TimeType) -> Int\n\nReturn the number of days in the month of dt. Value will be 28, 29, 30, or 31.\n\nExamples\n\njulia> Dates.daysinmonth(Date(\"2000-01\"))\n31\n\njulia> Dates.daysinmonth(Date(\"2001-02\"))\n28\n\njulia> Dates.daysinmonth(Date(\"2000-02\"))\n29\n\n\n\n\n\n","category":"function"},{"location":"stdlib/Dates/#Dates.isleapyear","page":"日期","title":"Dates.isleapyear","text":"isleapyear(dt::TimeType) -> Bool\n\nReturn true if the year of dt is a leap year.\n\nExamples\n\njulia> Dates.isleapyear(Date(\"2004\"))\ntrue\n\njulia> Dates.isleapyear(Date(\"2005\"))\nfalse\n\n\n\n\n\n","category":"function"},{"location":"stdlib/Dates/#Dates.dayofyear","page":"日期","title":"Dates.dayofyear","text":"dayofyear(dt::TimeType) -> Int\n\nReturn the day of the year for dt with January 1st being day 1.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/Dates/#Dates.daysinyear","page":"日期","title":"Dates.daysinyear","text":"daysinyear(dt::TimeType) -> Int\n\nReturn 366 if the year of dt is a leap year, otherwise return 365.\n\nExamples\n\njulia> Dates.daysinyear(1999)\n365\n\njulia> Dates.daysinyear(2000)\n366\n\n\n\n\n\n","category":"function"},{"location":"stdlib/Dates/#Dates.quarterofyear","page":"日期","title":"Dates.quarterofyear","text":"quarterofyear(dt::TimeType) -> Int\n\nReturn the quarter that dt resides in. Range of value is 1:4.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/Dates/#Dates.dayofquarter","page":"日期","title":"Dates.dayofquarter","text":"dayofquarter(dt::TimeType) -> Int\n\nReturn the day of the current quarter of dt. Range of value is 1:92.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/Dates/#Adjuster-Functions-2","page":"日期","title":"Adjuster Functions","text":"","category":"section"},{"location":"stdlib/Dates/","page":"日期","title":"日期","text":"Base.trunc(::Dates.TimeType, ::Type{Dates.Period})\nDates.firstdayofweek\nDates.lastdayofweek\nDates.firstdayofmonth\nDates.lastdayofmonth\nDates.firstdayofyear\nDates.lastdayofyear\nDates.firstdayofquarter\nDates.lastdayofquarter\nDates.tonext(::Dates.TimeType, ::Int)\nDates.toprev(::Dates.TimeType, ::Int)\nDates.tofirst\nDates.tolast\nDates.tonext(::Function, ::Dates.TimeType)\nDates.toprev(::Function, ::Dates.TimeType)","category":"page"},{"location":"stdlib/Dates/#Base.trunc-Tuple{TimeType, Type{Period}}","page":"日期","title":"Base.trunc","text":"trunc(dt::TimeType, ::Type{Period}) -> TimeType\n\nTruncates the value of dt according to the provided Period type.\n\nExamples\n\njulia> trunc(Dates.DateTime(\"1996-01-01T12:30:00\"), Dates.Day)\n1996-01-01T00:00:00\n\n\n\n\n\n","category":"method"},{"location":"stdlib/Dates/#Dates.firstdayofweek","page":"日期","title":"Dates.firstdayofweek","text":"firstdayofweek(dt::TimeType) -> TimeType\n\nAdjusts dt to the Monday of its week.\n\nExamples\n\njulia> Dates.firstdayofweek(DateTime(\"1996-01-05T12:30:00\"))\n1996-01-01T00:00:00\n\n\n\n\n\n","category":"function"},{"location":"stdlib/Dates/#Dates.lastdayofweek","page":"日期","title":"Dates.lastdayofweek","text":"lastdayofweek(dt::TimeType) -> TimeType\n\nAdjusts dt to the Sunday of its week.\n\nExamples\n\njulia> Dates.lastdayofweek(DateTime(\"1996-01-05T12:30:00\"))\n1996-01-07T00:00:00\n\n\n\n\n\n","category":"function"},{"location":"stdlib/Dates/#Dates.firstdayofmonth","page":"日期","title":"Dates.firstdayofmonth","text":"firstdayofmonth(dt::TimeType) -> TimeType\n\nAdjusts dt to the first day of its month.\n\nExamples\n\njulia> Dates.firstdayofmonth(DateTime(\"1996-05-20\"))\n1996-05-01T00:00:00\n\n\n\n\n\n","category":"function"},{"location":"stdlib/Dates/#Dates.lastdayofmonth","page":"日期","title":"Dates.lastdayofmonth","text":"lastdayofmonth(dt::TimeType) -> TimeType\n\nAdjusts dt to the last day of its month.\n\nExamples\n\njulia> Dates.lastdayofmonth(DateTime(\"1996-05-20\"))\n1996-05-31T00:00:00\n\n\n\n\n\n","category":"function"},{"location":"stdlib/Dates/#Dates.firstdayofyear","page":"日期","title":"Dates.firstdayofyear","text":"firstdayofyear(dt::TimeType) -> TimeType\n\nAdjusts dt to the first day of its year.\n\nExamples\n\njulia> Dates.firstdayofyear(DateTime(\"1996-05-20\"))\n1996-01-01T00:00:00\n\n\n\n\n\n","category":"function"},{"location":"stdlib/Dates/#Dates.lastdayofyear","page":"日期","title":"Dates.lastdayofyear","text":"lastdayofyear(dt::TimeType) -> TimeType\n\nAdjusts dt to the last day of its year.\n\nExamples\n\njulia> Dates.lastdayofyear(DateTime(\"1996-05-20\"))\n1996-12-31T00:00:00\n\n\n\n\n\n","category":"function"},{"location":"stdlib/Dates/#Dates.firstdayofquarter","page":"日期","title":"Dates.firstdayofquarter","text":"firstdayofquarter(dt::TimeType) -> TimeType\n\nAdjusts dt to the first day of its quarter.\n\nExamples\n\njulia> Dates.firstdayofquarter(DateTime(\"1996-05-20\"))\n1996-04-01T00:00:00\n\njulia> Dates.firstdayofquarter(DateTime(\"1996-08-20\"))\n1996-07-01T00:00:00\n\n\n\n\n\n","category":"function"},{"location":"stdlib/Dates/#Dates.lastdayofquarter","page":"日期","title":"Dates.lastdayofquarter","text":"lastdayofquarter(dt::TimeType) -> TimeType\n\nAdjusts dt to the last day of its quarter.\n\nExamples\n\njulia> Dates.lastdayofquarter(DateTime(\"1996-05-20\"))\n1996-06-30T00:00:00\n\njulia> Dates.lastdayofquarter(DateTime(\"1996-08-20\"))\n1996-09-30T00:00:00\n\n\n\n\n\n","category":"function"},{"location":"stdlib/Dates/#Dates.tonext-Tuple{TimeType, Int64}","page":"日期","title":"Dates.tonext","text":"tonext(dt::TimeType, dow::Int; same::Bool=false) -> TimeType\n\nAdjusts dt to the next day of week corresponding to dow with 1 = Monday, 2 = Tuesday, etc. Setting same=true allows the current dt to be considered as the next dow, allowing for no adjustment to occur.\n\n\n\n\n\n","category":"method"},{"location":"stdlib/Dates/#Dates.toprev-Tuple{TimeType, Int64}","page":"日期","title":"Dates.toprev","text":"toprev(dt::TimeType, dow::Int; same::Bool=false) -> TimeType\n\nAdjusts dt to the previous day of week corresponding to dow with 1 = Monday, 2 = Tuesday, etc. Setting same=true allows the current dt to be considered as the previous dow, allowing for no adjustment to occur.\n\n\n\n\n\n","category":"method"},{"location":"stdlib/Dates/#Dates.tofirst","page":"日期","title":"Dates.tofirst","text":"tofirst(dt::TimeType, dow::Int; of=Month) -> TimeType\n\nAdjusts dt to the first dow of its month. Alternatively, of=Year will adjust to the first dow of the year.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/Dates/#Dates.tolast","page":"日期","title":"Dates.tolast","text":"tolast(dt::TimeType, dow::Int; of=Month) -> TimeType\n\nAdjusts dt to the last dow of its month. Alternatively, of=Year will adjust to the last dow of the year.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/Dates/#Dates.tonext-Tuple{Function, TimeType}","page":"日期","title":"Dates.tonext","text":"tonext(func::Function, dt::TimeType; step=Day(1), limit=10000, same=false) -> TimeType\n\nAdjusts dt by iterating at most limit iterations by step increments until func returns true. func must take a single TimeType argument and return a Bool. same allows dt to be considered in satisfying func.\n\n\n\n\n\n","category":"method"},{"location":"stdlib/Dates/#Dates.toprev-Tuple{Function, TimeType}","page":"日期","title":"Dates.toprev","text":"toprev(func::Function, dt::TimeType; step=Day(-1), limit=10000, same=false) -> TimeType\n\nAdjusts dt by iterating at most limit iterations by step increments until func returns true. func must take a single TimeType argument and return a Bool. same allows dt to be considered in satisfying func.\n\n\n\n\n\n","category":"method"},{"location":"stdlib/Dates/#Periods","page":"日期","title":"Periods","text":"","category":"section"},{"location":"stdlib/Dates/","page":"日期","title":"日期","text":"Dates.Period(::Any)\nDates.CompoundPeriod(::Vector{<:Dates.Period})\nDates.value\nDates.default\nDates.periods","category":"page"},{"location":"stdlib/Dates/#Dates.Period-Tuple{Any}","page":"日期","title":"Dates.Period","text":"Year(v)\nQuarter(v)\nMonth(v)\nWeek(v)\nDay(v)\nHour(v)\nMinute(v)\nSecond(v)\nMillisecond(v)\nMicrosecond(v)\nNanosecond(v)\n\nConstruct a Period type with the given v value. Input must be losslessly convertible to an Int64.\n\n\n\n\n\n","category":"method"},{"location":"stdlib/Dates/#Dates.CompoundPeriod-Tuple{Vector{<:Period}}","page":"日期","title":"Dates.CompoundPeriod","text":"CompoundPeriod(periods) -> CompoundPeriod\n\nConstruct a CompoundPeriod from a Vector of Periods. All Periods of the same type will be added together.\n\nExamples\n\njulia> Dates.CompoundPeriod(Dates.Hour(12), Dates.Hour(13))\n25 hours\n\njulia> Dates.CompoundPeriod(Dates.Hour(-1), Dates.Minute(1))\n-1 hour, 1 minute\n\njulia> Dates.CompoundPeriod(Dates.Month(1), Dates.Week(-2))\n1 month, -2 weeks\n\njulia> Dates.CompoundPeriod(Dates.Minute(50000))\n50000 minutes\n\n\n\n\n\n","category":"method"},{"location":"stdlib/Dates/#Dates.value","page":"日期","title":"Dates.value","text":"Dates.value(x::Period) -> Int64\n\nFor a given period, return the value associated with that period. For example, value(Millisecond(10)) returns 10 as an integer.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/Dates/#Dates.default","page":"日期","title":"Dates.default","text":"default(p::Period) -> Period\n\nReturns a sensible \"default\" value for the input Period by returning T(1) for Year, Month, and Day, and T(0) for Hour, Minute, Second, and Millisecond.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/Dates/#Dates.periods","page":"日期","title":"Dates.periods","text":"Dates.periods(::CompoundPeriod) -> Vector{Period}\n\nReturn the Vector of Periods that comprise the given CompoundPeriod.\n\ncompat: Julia 1.7\nThis function requires Julia 1.7 or later.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/Dates/#Rounding-Functions","page":"日期","title":"Rounding Functions","text":"","category":"section"},{"location":"stdlib/Dates/","page":"日期","title":"日期","text":"Date and DateTime values can be rounded to a specified resolution (e.g., 1 month or 15 minutes) with floor, ceil, or round.","category":"page"},{"location":"stdlib/Dates/","page":"日期","title":"日期","text":"Base.floor(::Dates.TimeType, ::Dates.Period)\nBase.ceil(::Dates.TimeType, ::Dates.Period)\nBase.round(::Dates.TimeType, ::Dates.Period, ::RoundingMode{:NearestTiesUp})","category":"page"},{"location":"stdlib/Dates/#Base.floor-Tuple{TimeType, Period}","page":"日期","title":"Base.floor","text":"floor(dt::TimeType, p::Period) -> TimeType\n\nReturn the nearest Date or DateTime less than or equal to dt at resolution p.\n\nFor convenience, p may be a type instead of a value: floor(dt, Dates.Hour) is a shortcut for floor(dt, Dates.Hour(1)).\n\njulia> floor(Date(1985, 8, 16), Dates.Month)\n1985-08-01\n\njulia> floor(DateTime(2013, 2, 13, 0, 31, 20), Dates.Minute(15))\n2013-02-13T00:30:00\n\njulia> floor(DateTime(2016, 8, 6, 12, 0, 0), Dates.Day)\n2016-08-06T00:00:00\n\n\n\n\n\n","category":"method"},{"location":"stdlib/Dates/#Base.ceil-Tuple{TimeType, Period}","page":"日期","title":"Base.ceil","text":"ceil(dt::TimeType, p::Period) -> TimeType\n\nReturn the nearest Date or DateTime greater than or equal to dt at resolution p.\n\nFor convenience, p may be a type instead of a value: ceil(dt, Dates.Hour) is a shortcut for ceil(dt, Dates.Hour(1)).\n\njulia> ceil(Date(1985, 8, 16), Dates.Month)\n1985-09-01\n\njulia> ceil(DateTime(2013, 2, 13, 0, 31, 20), Dates.Minute(15))\n2013-02-13T00:45:00\n\njulia> ceil(DateTime(2016, 8, 6, 12, 0, 0), Dates.Day)\n2016-08-07T00:00:00\n\n\n\n\n\n","category":"method"},{"location":"stdlib/Dates/#Base.round-Tuple{TimeType, Period, RoundingMode{:NearestTiesUp}}","page":"日期","title":"Base.round","text":"round(dt::TimeType, p::Period, [r::RoundingMode]) -> TimeType\n\nReturn the Date or DateTime nearest to dt at resolution p. By default (RoundNearestTiesUp), ties (e.g., rounding 9:30 to the nearest hour) will be rounded up.\n\nFor convenience, p may be a type instead of a value: round(dt, Dates.Hour) is a shortcut for round(dt, Dates.Hour(1)).\n\njulia> round(Date(1985, 8, 16), Dates.Month)\n1985-08-01\n\njulia> round(DateTime(2013, 2, 13, 0, 31, 20), Dates.Minute(15))\n2013-02-13T00:30:00\n\njulia> round(DateTime(2016, 8, 6, 12, 0, 0), Dates.Day)\n2016-08-07T00:00:00\n\nValid rounding modes for round(::TimeType, ::Period, ::RoundingMode) are RoundNearestTiesUp (default), RoundDown (floor), and RoundUp (ceil).\n\n\n\n\n\n","category":"method"},{"location":"stdlib/Dates/","page":"日期","title":"日期","text":"Most Period values can also be rounded to a specified resolution:","category":"page"},{"location":"stdlib/Dates/","page":"日期","title":"日期","text":"Base.floor(::Dates.ConvertiblePeriod, ::T) where T <: Dates.ConvertiblePeriod\nBase.ceil(::Dates.ConvertiblePeriod, ::Dates.ConvertiblePeriod)\nBase.round(::Dates.ConvertiblePeriod, ::Dates.ConvertiblePeriod, ::RoundingMode{:NearestTiesUp})","category":"page"},{"location":"stdlib/Dates/#Base.floor-Union{Tuple{T}, Tuple{Union{Day, Week, TimePeriod}, T}} where T<:Union{Day, Week, TimePeriod}","page":"日期","title":"Base.floor","text":"floor(x::Period, precision::T) where T <: Union{TimePeriod, Week, Day} -> T\n\nRound x down to the nearest multiple of precision. If x and precision are different subtypes of Period, the return value will have the same type as precision.\n\nFor convenience, precision may be a type instead of a value: floor(x, Dates.Hour) is a shortcut for floor(x, Dates.Hour(1)).\n\njulia> floor(Dates.Day(16), Dates.Week)\n2 weeks\n\njulia> floor(Dates.Minute(44), Dates.Minute(15))\n30 minutes\n\njulia> floor(Dates.Hour(36), Dates.Day)\n1 day\n\nRounding to a precision of Months or Years is not supported, as these Periods are of inconsistent length.\n\n\n\n\n\n","category":"method"},{"location":"stdlib/Dates/#Base.ceil-Tuple{Union{Day, Week, TimePeriod}, Union{Day, Week, TimePeriod}}","page":"日期","title":"Base.ceil","text":"ceil(x::Period, precision::T) where T <: Union{TimePeriod, Week, Day} -> T\n\nRound x up to the nearest multiple of precision. If x and precision are different subtypes of Period, the return value will have the same type as precision.\n\nFor convenience, precision may be a type instead of a value: ceil(x, Dates.Hour) is a shortcut for ceil(x, Dates.Hour(1)).\n\njulia> ceil(Dates.Day(16), Dates.Week)\n3 weeks\n\njulia> ceil(Dates.Minute(44), Dates.Minute(15))\n45 minutes\n\njulia> ceil(Dates.Hour(36), Dates.Day)\n2 days\n\nRounding to a precision of Months or Years is not supported, as these Periods are of inconsistent length.\n\n\n\n\n\n","category":"method"},{"location":"stdlib/Dates/#Base.round-Tuple{Union{Day, Week, TimePeriod}, Union{Day, Week, TimePeriod}, RoundingMode{:NearestTiesUp}}","page":"日期","title":"Base.round","text":"round(x::Period, precision::T, [r::RoundingMode]) where T <: Union{TimePeriod, Week, Day} -> T\n\nRound x to the nearest multiple of precision. If x and precision are different subtypes of Period, the return value will have the same type as precision. By default (RoundNearestTiesUp), ties (e.g., rounding 90 minutes to the nearest hour) will be rounded up.\n\nFor convenience, precision may be a type instead of a value: round(x, Dates.Hour) is a shortcut for round(x, Dates.Hour(1)).\n\njulia> round(Dates.Day(16), Dates.Week)\n2 weeks\n\njulia> round(Dates.Minute(44), Dates.Minute(15))\n45 minutes\n\njulia> round(Dates.Hour(36), Dates.Day)\n2 days\n\nValid rounding modes for round(::Period, ::T, ::RoundingMode) are RoundNearestTiesUp (default), RoundDown (floor), and RoundUp (ceil).\n\nRounding to a precision of Months or Years is not supported, as these Periods are of inconsistent length.\n\n\n\n\n\n","category":"method"},{"location":"stdlib/Dates/","page":"日期","title":"日期","text":"The following functions are not exported:","category":"page"},{"location":"stdlib/Dates/","page":"日期","title":"日期","text":"Dates.floorceil\nDates.epochdays2date\nDates.epochms2datetime\nDates.date2epochdays\nDates.datetime2epochms","category":"page"},{"location":"stdlib/Dates/#Dates.floorceil","page":"日期","title":"Dates.floorceil","text":"floorceil(dt::TimeType, p::Period) -> (TimeType, TimeType)\n\nSimultaneously return the floor and ceil of a Date or DateTime at resolution p. More efficient than calling both floor and ceil individually.\n\n\n\n\n\nfloorceil(x::Period, precision::T) where T <: Union{TimePeriod, Week, Day} -> (T, T)\n\nSimultaneously return the floor and ceil of Period at resolution p. More efficient than calling both floor and ceil individually.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/Dates/#Dates.epochdays2date","page":"日期","title":"Dates.epochdays2date","text":"epochdays2date(days) -> Date\n\nTake the number of days since the rounding epoch (0000-01-01T00:00:00) and return the corresponding Date.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/Dates/#Dates.epochms2datetime","page":"日期","title":"Dates.epochms2datetime","text":"epochms2datetime(milliseconds) -> DateTime\n\nTake the number of milliseconds since the rounding epoch (0000-01-01T00:00:00) and return the corresponding DateTime.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/Dates/#Dates.date2epochdays","page":"日期","title":"Dates.date2epochdays","text":"date2epochdays(dt::Date) -> Int64\n\nTake the given Date and return the number of days since the rounding epoch (0000-01-01T00:00:00) as an Int64.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/Dates/#Dates.datetime2epochms","page":"日期","title":"Dates.datetime2epochms","text":"datetime2epochms(dt::DateTime) -> Int64\n\nTake the given DateTime and return the number of milliseconds since the rounding epoch (0000-01-01T00:00:00) as an Int64.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/Dates/#Conversion-Functions","page":"日期","title":"Conversion Functions","text":"","category":"section"},{"location":"stdlib/Dates/","page":"日期","title":"日期","text":"Dates.today\nDates.unix2datetime\nDates.datetime2unix\nDates.julian2datetime\nDates.datetime2julian\nDates.rata2datetime\nDates.datetime2rata","category":"page"},{"location":"stdlib/Dates/#Dates.today","page":"日期","title":"Dates.today","text":"today() -> Date\n\nReturn the date portion of now().\n\n\n\n\n\n","category":"function"},{"location":"stdlib/Dates/#Dates.unix2datetime","page":"日期","title":"Dates.unix2datetime","text":"unix2datetime(x) -> DateTime\n\nTake the number of seconds since unix epoch 1970-01-01T00:00:00 and convert to the corresponding DateTime.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/Dates/#Dates.datetime2unix","page":"日期","title":"Dates.datetime2unix","text":"datetime2unix(dt::DateTime) -> Float64\n\nTake the given DateTime and return the number of seconds since the unix epoch 1970-01-01T00:00:00 as a Float64.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/Dates/#Dates.julian2datetime","page":"日期","title":"Dates.julian2datetime","text":"julian2datetime(julian_days) -> DateTime\n\nTake the number of Julian calendar days since epoch -4713-11-24T12:00:00 and return the corresponding DateTime.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/Dates/#Dates.datetime2julian","page":"日期","title":"Dates.datetime2julian","text":"datetime2julian(dt::DateTime) -> Float64\n\nTake the given DateTime and return the number of Julian calendar days since the julian epoch -4713-11-24T12:00:00 as a Float64.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/Dates/#Dates.rata2datetime","page":"日期","title":"Dates.rata2datetime","text":"rata2datetime(days) -> DateTime\n\nTake the number of Rata Die days since epoch 0000-12-31T00:00:00 and return the corresponding DateTime.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/Dates/#Dates.datetime2rata","page":"日期","title":"Dates.datetime2rata","text":"datetime2rata(dt::TimeType) -> Int64\n\nReturn the number of Rata Die days since epoch from the given Date or DateTime.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/Dates/#Constants","page":"日期","title":"Constants","text":"","category":"section"},{"location":"stdlib/Dates/","page":"日期","title":"日期","text":"Days of the Week:","category":"page"},{"location":"stdlib/Dates/","page":"日期","title":"日期","text":"Variable Abbr. Value (Int)\nMonday Mon 1\nTuesday Tue 2\nWednesday Wed 3\nThursday Thu 4\nFriday Fri 5\nSaturday Sat 6\nSunday Sun 7","category":"page"},{"location":"stdlib/Dates/","page":"日期","title":"日期","text":"Months of the Year:","category":"page"},{"location":"stdlib/Dates/","page":"日期","title":"日期","text":"Variable Abbr. Value (Int)\nJanuary Jan 1\nFebruary Feb 2\nMarch Mar 3\nApril Apr 4\nMay May 5\nJune Jun 6\nJuly Jul 7\nAugust Aug 8\nSeptember Sep 9\nOctober Oct 10\nNovember Nov 11\nDecember Dec 12","category":"page"},{"location":"stdlib/Dates/#Common-Date-Formatters","page":"日期","title":"Common Date Formatters","text":"","category":"section"},{"location":"stdlib/Dates/","page":"日期","title":"日期","text":"ISODateTimeFormat\nISODateFormat\nISOTimeFormat\nRFC1123Format","category":"page"},{"location":"stdlib/Dates/#Dates.ISODateTimeFormat","page":"日期","title":"Dates.ISODateTimeFormat","text":"Dates.ISODateTimeFormat\n\nDescribes the ISO8601 formatting for a date and time. This is the default value for Dates.format of a DateTime.\n\nExample\n\njulia> Dates.format(DateTime(2018, 8, 8, 12, 0, 43, 1), ISODateTimeFormat)\n\"2018-08-08T12:00:43.001\"\n\n\n\n\n\n","category":"constant"},{"location":"stdlib/Dates/#Dates.ISODateFormat","page":"日期","title":"Dates.ISODateFormat","text":"Dates.ISODateFormat\n\nDescribes the ISO8601 formatting for a date. This is the default value for Dates.format of a Date.\n\nExample\n\njulia> Dates.format(Date(2018, 8, 8), ISODateFormat)\n\"2018-08-08\"\n\n\n\n\n\n","category":"constant"},{"location":"stdlib/Dates/#Dates.ISOTimeFormat","page":"日期","title":"Dates.ISOTimeFormat","text":"Dates.ISOTimeFormat\n\nDescribes the ISO8601 formatting for a time. This is the default value for Dates.format of a Time.\n\nExample\n\njulia> Dates.format(Time(12, 0, 43, 1), ISOTimeFormat)\n\"12:00:43.001\"\n\n\n\n\n\n","category":"constant"},{"location":"stdlib/Dates/#Dates.RFC1123Format","page":"日期","title":"Dates.RFC1123Format","text":"Dates.RFC1123Format\n\nDescribes the RFC1123 formatting for a date and time.\n\nExample\n\njulia> Dates.format(DateTime(2018, 8, 8, 12, 0, 43, 1), RFC1123Format)\n\"Wed, 08 Aug 2018 12:00:43\"\n\n\n\n\n\n","category":"constant"},{"location":"stdlib/Dates/","page":"日期","title":"日期","text":"DocTestSetup = nothing","category":"page"},{"location":"stdlib/TOML/#TOML","page":"TOML","title":"TOML","text":"","category":"section"},{"location":"stdlib/TOML/","page":"TOML","title":"TOML","text":"TOML.jl is a Julia standard library for parsing and writing TOML v1.0 files.","category":"page"},{"location":"stdlib/TOML/#Parsing-TOML-data","page":"TOML","title":"Parsing TOML data","text":"","category":"section"},{"location":"stdlib/TOML/","page":"TOML","title":"TOML","text":"julia> using TOML\n\njulia> data = \"\"\"\n [database]\n server = \"192.168.1.1\"\n ports = [ 8001, 8001, 8002 ]\n \"\"\";\n\njulia> TOML.parse(data)\nDict{String, Any} with 1 entry:\n \"database\" => Dict{String, Any}(\"server\"=>\"192.168.1.1\", \"ports\"=>[8001, 8001…","category":"page"},{"location":"stdlib/TOML/","page":"TOML","title":"TOML","text":"To parse a file, use TOML.parsefile. If the file has a syntax error, an exception is thrown:","category":"page"},{"location":"stdlib/TOML/","page":"TOML","title":"TOML","text":"julia> using TOML\n\njulia> TOML.parse(\"\"\"\n value = 0.0.0\n \"\"\")\nERROR: TOML Parser error:\nnone:1:16 error: failed to parse value\n value = 0.0.0\n ^\n[...]","category":"page"},{"location":"stdlib/TOML/","page":"TOML","title":"TOML","text":"There are other versions of the parse functions (TOML.tryparse and [TOML.tryparsefile]) that instead of throwing exceptions on parser error returns a TOML.ParserError with information:","category":"page"},{"location":"stdlib/TOML/","page":"TOML","title":"TOML","text":"julia> using TOML\n\njulia> err = TOML.tryparse(\"\"\"\n value = 0.0.0\n \"\"\");\n\njulia> err.type\nErrGenericValueError::ErrorType = 14\n\njulia> err.line\n1\n\njulia> err.column\n16","category":"page"},{"location":"stdlib/TOML/#Exporting-data-to-TOML-file","page":"TOML","title":"Exporting data to TOML file","text":"","category":"section"},{"location":"stdlib/TOML/","page":"TOML","title":"TOML","text":"The TOML.print function is used to print (or serialize) data into TOML format.","category":"page"},{"location":"stdlib/TOML/","page":"TOML","title":"TOML","text":"julia> using TOML\n\njulia> data = Dict(\n \"names\" => [\"Julia\", \"Julio\"],\n \"age\" => [10, 20],\n );\n\njulia> TOML.print(data)\nnames = [\"Julia\", \"Julio\"]\nage = [10, 20]\n\njulia> fname = tempname();\n\njulia> open(fname, \"w\") do io\n TOML.print(io, data)\n end\n\njulia> TOML.parsefile(fname)\nDict{String, Any} with 2 entries:\n \"names\" => [\"Julia\", \"Julio\"]\n \"age\" => [10, 20]","category":"page"},{"location":"stdlib/TOML/","page":"TOML","title":"TOML","text":"Keys can be sorted according to some value","category":"page"},{"location":"stdlib/TOML/","page":"TOML","title":"TOML","text":"julia> using TOML\n\njulia> TOML.print(Dict(\n \"abc\" => 1,\n \"ab\" => 2,\n \"abcd\" => 3,\n ); sorted=true, by=length)\nab = 2\nabc = 1\nabcd = 3","category":"page"},{"location":"stdlib/TOML/","page":"TOML","title":"TOML","text":"For custom structs, pass a function that converts the struct to a supported type","category":"page"},{"location":"stdlib/TOML/","page":"TOML","title":"TOML","text":"julia> using TOML\n\njulia> struct MyStruct\n a::Int\n b::String\n end\n\njulia> TOML.print(Dict(\"foo\" => MyStruct(5, \"bar\"))) do x\n x isa MyStruct && return [x.a, x.b]\n error(\"unhandled type $(typeof(x))\")\n end\nfoo = [5, \"bar\"]","category":"page"},{"location":"stdlib/TOML/#References","page":"TOML","title":"References","text":"","category":"section"},{"location":"stdlib/TOML/","page":"TOML","title":"TOML","text":"TOML.parse\nTOML.parsefile\nTOML.tryparse\nTOML.tryparsefile\nTOML.print\nTOML.Parser\nTOML.ParserError","category":"page"},{"location":"stdlib/TOML/#TOML.parse","page":"TOML","title":"TOML.parse","text":"parse(x::Union{AbstractString, IO})\nparse(p::Parser, x::Union{AbstractString, IO})\n\nParse the string or stream x, and return the resulting table (dictionary). Throw a ParserError upon failure.\n\nSee also TOML.tryparse.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/TOML/#TOML.parsefile","page":"TOML","title":"TOML.parsefile","text":"parsefile(f::AbstractString)\nparsefile(p::Parser, f::AbstractString)\n\nParse file f and return the resulting table (dictionary). Throw a ParserError upon failure.\n\nSee also TOML.tryparsefile.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/TOML/#TOML.tryparse","page":"TOML","title":"TOML.tryparse","text":"tryparse(x::Union{AbstractString, IO})\ntryparse(p::Parser, x::Union{AbstractString, IO})\n\nParse the string or stream x, and return the resulting table (dictionary). Return a ParserError upon failure.\n\nSee also TOML.parse.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/TOML/#TOML.tryparsefile","page":"TOML","title":"TOML.tryparsefile","text":"tryparsefile(f::AbstractString)\ntryparsefile(p::Parser, f::AbstractString)\n\nParse file f and return the resulting table (dictionary). Return a ParserError upon failure.\n\nSee also TOML.parsefile.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/TOML/#TOML.print","page":"TOML","title":"TOML.print","text":"print([to_toml::Function], io::IO [=stdout], data::AbstractDict; sorted=false, by=identity)\n\nWrite data as TOML syntax to the stream io. If the keyword argument sorted is set to true, sort tables according to the function given by the keyword argument by.\n\nThe following data types are supported: AbstractDict, Integer, AbstractFloat, Bool, Dates.DateTime, Dates.Time, Dates.Date. Note that the integers and floats need to be convertible to Float64 and Int64 respectively. For other data types, pass the function to_toml that takes the data types and returns a value of a supported type.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/TOML/#TOML.Parser","page":"TOML","title":"TOML.Parser","text":"Parser()\n\nConstructor for a TOML Parser. Note that in most cases one does not need to explicitly create a Parser but instead one directly use use TOML.parsefile or TOML.parse. Using an explicit parser will however reuse some internal data structures which can be beneficial for performance if a larger number of small files are parsed.\n\n\n\n\n\n","category":"type"},{"location":"stdlib/TOML/#TOML.ParserError","page":"TOML","title":"TOML.ParserError","text":"ParserError\n\nType that is returned from tryparse and tryparsefile when parsing fails. It contains (among others) the following fields:\n\npos, the position in the string when the error happened\ntable, the result that so far was successfully parsed\ntype, an error type, different for different types of errors\n\n\n\n\n\n","category":"type"},{"location":"manual/command-line-options/#command-line-options","page":"命令行选项","title":"命令行选项","text":"","category":"section"},{"location":"manual/command-line-options/","page":"命令行选项","title":"命令行选项","text":"以下是启动 julia 时可用的命令行选项的完整列表:","category":"page"},{"location":"manual/command-line-options/","page":"命令行选项","title":"命令行选项","text":"选项 描述\n-v, --version 显示版本信息\n-h, --help 显示命令行参数\n--project[={|@.}] 将 设置为主项目/环境。默认的 @. 选项将搜索父目录,直至找到 Project.toml 或 JuliaProject.toml 文件。\n-J, --sysimage 用指定的系统镜像文件(system image file)启动\n-H, --home 设置 julia 可执行文件的路径\n--startup-file={yes|no} 是否载入 ~/.julia/config/startup.jl\n--handle-signals={yes|no} 开启或关闭 Julia 默认的 signal handlers\n--sysimage-native-code={yes|no} 在可能的情况下,使用系统镜像里的原生代码\n--compiled-modules={yes|no} 开启或关闭 module 的增量预编译功能\n-e, --eval 执行 \n-E, --print 执行 并显示结果\n-L, --load 立即在所有进程中载入 \n-t, --threads {N|auto} 开启 N 个线程:auto 将 N 设置为当前 CPU 线程数,但这个行为可能在以后版本有所变动。\n-p, --procs {N|auto} 这里的整数 N 表示启动 N 个额外的工作进程;auto 表示启动与 CPU 线程数目(logical cores)一样多的进程\n--machine-file 中列出的主机上运行进程\n-i 交互式模式;REPL 运行且 isinteractive() 为 true\n-q, --quiet 安静的启动;REPL 启动时无横幅,不显示警告\n--banner={yes|no|auto} 开启或关闭 REPL 横幅\n--color={yes|no|auto} 开启或关闭文字颜色\n--history-file={yes|no} 载入或导出历史记录\n--depwarn={yes|no|error} 开启或关闭语法弃用警告,error 表示将弃用警告转换为错误。\n--warn-overwrite={yes|no} 开启或关闭“method overwrite”警告\n-C, --cpu-target 设置 来限制使用 CPU 的某些特性;设置为 help 可以查看可用的选项\n-O, --optimize={0,1,2,3} 设置编译器优化级别(若未配置此选项,则默认等级为2;若配置了此选项却没指定具体级别,则默认级别为3)。\n--min-optlevel={0,1,2,3} 设置每个模块加载的优化下限(默认为 0)\n-g, -g 开启或设置 debug 信息的生成等级。若未配置此选项,则默认 debug 信息的级别为 1;若配置了此选项却没指定具体级别,则默认级别为 2。\n--inline={yes|no} 控制是否允许函数内联,此选项会覆盖源文件中的 @inline 声明\n--check-bounds={yes|no|auto} 进行边界检查,总是、从不、或依照宏@inbounds声明\n--math-mode={ieee,fast} 开启或关闭非安全的浮点数代数计算优化,此选项会覆盖源文件中的 @fastmath 声明\n--code-coverage={none|user|all} 对源文件中每行代码执行的次数计数\n--code-coverage 等价于 --code-coverage=user\n--track-allocation={none|user|all} 对源文件中每行代码的内存分配计数,单位 byte\n--track-allocation 等价于 --track-allocation=user","category":"page"},{"location":"manual/command-line-options/","page":"命令行选项","title":"命令行选项","text":"compat: Julia 1.1\n在 Julia 1.0 中,默认的 --project=@. 选项不会在 Git 仓库的根目录中寻找 Project.toml 文件。从 Julia 1.1 开始,此选项会在其中寻找该文件。","category":"page"},{"location":"manual/asynchronous-programming/#man-asynchronous","page":"异步编程","title":"异步编程","text":"","category":"section"},{"location":"manual/asynchronous-programming/","page":"异步编程","title":"异步编程","text":"当程序需要与外部世界交互时,例如通过互联网与另一台机器通信时,程序中的操作可能需要以无法预测的顺序发生。假设你的程序需要下载一个文件。我们想启动下载操作,在等待下载完成的同时执行其他操作,然后在空闲时继续执行下载文件的代码。这种场景属于异步编程,有时也称为并发编程(因为从概念上讲,同时发生多种事情)。","category":"page"},{"location":"manual/asynchronous-programming/","page":"异步编程","title":"异步编程","text":"为了解决这些可能的情况,Julia 提供了任务 Task(也有其他几个名称,例如对称协程、轻量级线程、协作多任务处理或one-shot continuations)。当一项计算工作(实际上,执行特定功能)被指定为 Task 时,可以通过切换到另一个 Task 来中断它。 最初的 Task 稍后可以恢复,此时它将从上次中断的地方开始。 初看这似乎类似于函数调用。 但是,有两个关键区别。 首先,切换任务不占用任何空间,因此可以在不消耗调用堆栈的情况下进行任意数量的任务切换。 其次,任务之间的切换可以以任何顺序发生,这与函数调用不同,在函数调用中,被调用的函数必须在返回到调用函数之前完成执行。","category":"page"},{"location":"manual/asynchronous-programming/#基本-Task-操作","page":"异步编程","title":"基本 Task 操作","text":"","category":"section"},{"location":"manual/asynchronous-programming/","page":"异步编程","title":"异步编程","text":"你可以将Task视为要执行的计算工作单元的句柄。 它有一个创建-开始-运行-结束的生命周期。 Task 是通过在要运行的 0 参数函数上调用 Task 构造函数来创建的,或者使用 @task 宏:","category":"page"},{"location":"manual/asynchronous-programming/","page":"异步编程","title":"异步编程","text":"julia> t = @task begin; sleep(5); println(\"done\"); end\nTask (runnable) @0x00007f13a40c0eb0","category":"page"},{"location":"manual/asynchronous-programming/","page":"异步编程","title":"异步编程","text":"@task x 等价于 Task(()->x)。","category":"page"},{"location":"manual/asynchronous-programming/","page":"异步编程","title":"异步编程","text":"此任务将等待五秒钟,然后打印done。 但是,它还没有开始运行。 我们可以随时通过调用 schedule 来运行它:","category":"page"},{"location":"manual/asynchronous-programming/","page":"异步编程","title":"异步编程","text":"julia> schedule(t);","category":"page"},{"location":"manual/asynchronous-programming/","page":"异步编程","title":"异步编程","text":"如果你在 REPL 中尝试这个,你会看到 schedule 立即有返回值。那是因为它只是将 t 添加到要运行的内部任务队列中。然后,REPL 将打印下一个提示并等待更多输入。等待键盘输入为其他任务提供了运行的机会,因此此时 t 将启动。 t 调用 sleep,它设置一个计时器并停止执行。 如果已经安排了其他任务,那么它们就可以运行了。五秒后,计时器触发并重新启动t,你将看到打印的done。 然后t 执行完毕了。","category":"page"},{"location":"manual/asynchronous-programming/","page":"异步编程","title":"异步编程","text":"wait 函数会阻塞调用任务,直到其他任务完成。 例如,如果输入:","category":"page"},{"location":"manual/asynchronous-programming/","page":"异步编程","title":"异步编程","text":"julia> schedule(t); wait(t)","category":"page"},{"location":"manual/asynchronous-programming/","page":"异步编程","title":"异步编程","text":"在下一个输入提示出现之前,你将看到五秒钟的停顿,而不是只调用 schedule。 那是因为 REPL 等待 t 完成之后才继续。","category":"page"},{"location":"manual/asynchronous-programming/","page":"异步编程","title":"异步编程","text":"一般来说,创建一个任务会想立即执行它,为此提供了宏 @async –- @async x 等价于 schedule(@task x )。","category":"page"},{"location":"manual/asynchronous-programming/#在-Channel-中进行通信","page":"异步编程","title":"在 Channel 中进行通信","text":"","category":"section"},{"location":"manual/asynchronous-programming/","page":"异步编程","title":"异步编程","text":"在某些问题中,所需的各种工作并不是通过函数调用自然关联的; 在需要完成的工作中没有明显的“调用者”或“被调用者”。 一个典型的例子是生产者-消费者问题,其中一个复杂的过程正在生成值,而另一个复杂的过程正在消耗它们。消费者不能简单地调用生产者函数来获取一个值,因为生产者可能有更多的值要生成,因此可能还没有准备好返回。对于任务,生产者和消费者都可以根据需要运行,根据需要来回传递值。","category":"page"},{"location":"manual/asynchronous-programming/","page":"异步编程","title":"异步编程","text":"Julia 提供了 Channel 机制来解决这个问题。一个 Channel 是一个先进先出的队列,允许多个 Task 对它可以进行读和写。","category":"page"},{"location":"manual/asynchronous-programming/","page":"异步编程","title":"异步编程","text":"让我们定义一个生产者任务,调用 put! 来生产数值。为了消费数值,我们需要对生产者开始新任务进行排班。可以使用一个特殊的 Channel 组件来运行一个与其绑定的 Task,它能接受单参数函数作为其参数,然后可以用 take! 从 Channel 对象里不断地提取值:","category":"page"},{"location":"manual/asynchronous-programming/","page":"异步编程","title":"异步编程","text":"julia> function producer(c::Channel)\n put!(c, \"start\")\n for n=1:4\n put!(c, 2n)\n end\n put!(c, \"stop\")\n end;\n\njulia> chnl = Channel(producer);\n\njulia> take!(chnl)\n\"start\"\n\njulia> take!(chnl)\n2\n\njulia> take!(chnl)\n4\n\njulia> take!(chnl)\n6\n\njulia> take!(chnl)\n8\n\njulia> take!(chnl)\n\"stop\"","category":"page"},{"location":"manual/asynchronous-programming/","page":"异步编程","title":"异步编程","text":"一种思考这种行为的方式是,“生产者”能够多次返回。在两次调用 put! 之间,生产者的执行是挂起的,此时由消费者接管控制。","category":"page"},{"location":"manual/asynchronous-programming/","page":"异步编程","title":"异步编程","text":"返回的 Channel 可以被用作一个 for 循环的迭代对象,此时循环变量会依次取到所有产生的值。当 Channel 关闭时,循环就会终止。","category":"page"},{"location":"manual/asynchronous-programming/","page":"异步编程","title":"异步编程","text":"julia> for x in Channel(producer)\n println(x)\n end\nstart\n2\n4\n6\n8\nstop","category":"page"},{"location":"manual/asynchronous-programming/","page":"异步编程","title":"异步编程","text":"注意我们并不需要显式地在生产者中关闭 Channel。这是因为 Channel 对 Task 的绑定同时也意味着 Channel 的生命周期与绑定的 Task 一致。当 Task 结束时,Channel 对象会自动关闭。多个 Channel 可以绑定到一个 Task,反之亦然。","category":"page"},{"location":"manual/asynchronous-programming/","page":"异步编程","title":"异步编程","text":"Task 构造函数需要一个不带参数的函数,而创建任务绑定的 channel 的 Channel 方法需要一个接受 Channel类型的单个参数的函数。 一个常见的模式是对生产者进行参数化,在这种情况下,需要一个偏函数来创建一个 0 或 1 个参数 匿名函数。","category":"page"},{"location":"manual/asynchronous-programming/","page":"异步编程","title":"异步编程","text":"对于 Task 对象,可以直接用,也可以为了方便用宏。","category":"page"},{"location":"manual/asynchronous-programming/","page":"异步编程","title":"异步编程","text":"function mytask(myarg)\n ...\nend\n\ntaskHdl = Task(() -> mytask(7))\n# or, equivalently\ntaskHdl = @task mytask(7)","category":"page"},{"location":"manual/asynchronous-programming/","page":"异步编程","title":"异步编程","text":"为了安排更高级的工作分配模式,bind 和 schedule 可以与 Task 和 Channel 构造函数配合使用,显式地连接一些 Channel 和生产者或消费者 Task。","category":"page"},{"location":"manual/asynchronous-programming/#更多关于-Channel-的知识","page":"异步编程","title":"更多关于 Channel 的知识","text":"","category":"section"},{"location":"manual/asynchronous-programming/","page":"异步编程","title":"异步编程","text":"一个管道可以形象得看做是一个管子,一端可读,另一端可写:","category":"page"},{"location":"manual/asynchronous-programming/","page":"异步编程","title":"异步编程","text":"不同的 task 可以通过 put! 往同一个 channel 并发地写入。\n不同的 task 也可以通过 take! 从同一个 channel 并发地取数据\n举个例子:\n# Given Channels c1 and c2,\nc1 = Channel(32)\nc2 = Channel(32)\n\n# and a function `foo` which reads items from c1, processes the item read\n# and writes a result to c2,\nfunction foo()\n while true\n data = take!(c1)\n [...] # process data\n put!(c2, result) # write out result\n end\nend\n\n# we can schedule `n` instances of `foo` to be active concurrently.\nfor _ in 1:n\n errormonitor(@async foo())\nend\nChannel 可以通过 Channel{T}(sz) 构造,得到的 channel 只能存储类型 T 的数据。如果 T 没有指定,那么 channel 可以存任意类型。sz 表示该 channel 能够存储的最大元素个数。比如 Channel(32) 得到的 channel 最多可以存储32个元素。而 Channel{MyType}(64) 则可以最多存储64个 MyType 类型的数据。\n如果一个 Channel 是空的,读取的 task(即执行 take! 的 task)会被阻塞直到有新的数据准备好了。\n如果一个 Channel 是满的,那么写入的 task(即执行 put! 的 task)则会被阻塞,直到 Channel 有空余。\n\n一个 Channel 一开始处于开启状态,也就是说可以被 take! 读取和 put! 写入。close 会关闭一个 Channel,对于一个已经关闭的 Channel,put! 会失败,例如:\njulia> c = Channel(2);\n\njulia> put!(c, 1) # `put!` on an open channel succeeds\n1\n\njulia> close(c);\n\njulia> put!(c, 2) # `put!` on a closed channel throws an exception.\nERROR: InvalidStateException(\"Channel is closed.\",:closed)\nStacktrace:\n[...]\ntake! 和 fetch (只读取,不会将元素从 channel 中删掉)仍然可以从一个已经关闭的 channel 中读数据,直到 channel 被取空了为止。继续上面的例子:\njulia> fetch(c) # Any number of `fetch` calls succeed.\n1\n\njulia> fetch(c)\n1\n\njulia> take!(c) # The first `take!` removes the value.\n1\n\njulia> take!(c) # No more data available on a closed channel.\nERROR: InvalidStateException(\"Channel is closed.\",:closed)\nStacktrace:\n[...]","category":"page"},{"location":"manual/asynchronous-programming/","page":"异步编程","title":"异步编程","text":"考虑这样一个用 channel 做 task 之间通信的例子。首先,起 4 个 task 来处理一个 jobs channel 中的数据。jobs 中的每个任务通过 job_id 来表示,然后每个 task 模拟读取一个 job_id,然后随机等待一会儿,然后往一个 results channel 中写入一个元组,它分别包含 job_id 和执行的时间,最后将结果打印出来:","category":"page"},{"location":"manual/asynchronous-programming/","page":"异步编程","title":"异步编程","text":"julia> const jobs = Channel{Int}(32);\n\njulia> const results = Channel{Tuple}(32);\n\njulia> function do_work()\n for job_id in jobs\n exec_time = rand()\n sleep(exec_time) # simulates elapsed time doing actual work\n # typically performed externally.\n put!(results, (job_id, exec_time))\n end\n end;\n\njulia> function make_jobs(n)\n for i in 1:n\n put!(jobs, i)\n end\n end;\n\njulia> n = 12;\n\njulia> errormonitor(@async make_jobs(n)); # feed the jobs channel with \"n\" jobs\n\njulia> for i in 1:4 # start 4 tasks to process requests in parallel\n errormonitor(@async do_work())\n end\n\njulia> @elapsed while n > 0 # print out results\n job_id, exec_time = take!(results)\n println(\"$job_id finished in $(round(exec_time; digits=2)) seconds\")\n global n = n - 1\n end\n4 finished in 0.22 seconds\n3 finished in 0.45 seconds\n1 finished in 0.5 seconds\n7 finished in 0.14 seconds\n2 finished in 0.78 seconds\n5 finished in 0.9 seconds\n9 finished in 0.36 seconds\n6 finished in 0.87 seconds\n8 finished in 0.79 seconds\n10 finished in 0.64 seconds\n12 finished in 0.5 seconds\n11 finished in 0.97 seconds\n0.029772311","category":"page"},{"location":"manual/asynchronous-programming/","page":"异步编程","title":"异步编程","text":"不用 errormonitor(t),一个更稳健的解决方案是使用 bind(results, t),这不仅会记录任何意外故障,还会强制相关资源关闭并向上抛出错误。","category":"page"},{"location":"manual/asynchronous-programming/#更多任务操作","page":"异步编程","title":"更多任务操作","text":"","category":"section"},{"location":"manual/asynchronous-programming/","page":"异步编程","title":"异步编程","text":"任务操作建立在称为 yieldto 的底层原始运算上。 yieldto(task, value) 挂起当前 task,然后切换到指定的 task,并使该任务的最后一个 yieldto 调用返回指定的 value。 请注意,yieldto 是使用任务式流程控制所需的唯一操作;我们总是切换到不同的任务,而不是调用和返回。 这就是为什么这个特性也被称为“对称协程”; 每个任务都使用相同的机制来回切换。","category":"page"},{"location":"manual/asynchronous-programming/","page":"异步编程","title":"异步编程","text":"yieldto 功能强大,但大多数 Task 的使用都不会直接调用它。思考为什么会这样。如果你切换当前 Task,你很可能会在某个时候想切换回来。但知道什么时候切换回来和那个 Task 负责切换回来需要大量的协调。例如,put! 和 take! 是阻塞操作,当在渠道环境中使用时,维持状态以记住消费者是谁。不需要人为地记录消费 Task,正是使得 put! 比底层 yieldto 易用的原因。","category":"page"},{"location":"manual/asynchronous-programming/","page":"异步编程","title":"异步编程","text":"除了 yieldto 之外,也需要一些其它的基本函数来更高效地使用 Task。","category":"page"},{"location":"manual/asynchronous-programming/","page":"异步编程","title":"异步编程","text":"current_task 获取当前运行 Task 的索引。\nistaskdone 查询一个 Task 是否退出.\nistaskstarted 查询一个 Task 是否已经开始运行。\ntask_local_storage 操纵针对当前 Task 的键值存储。","category":"page"},{"location":"manual/asynchronous-programming/#Task-和事件","page":"异步编程","title":"Task 和事件","text":"","category":"section"},{"location":"manual/asynchronous-programming/","page":"异步编程","title":"异步编程","text":"多数 Task 切换是在等待如 I/O 请求的事件,由 Julia Base 里的调度器执行。调度器维持一个可运行 Task 的队列,并执行一个事件循环,来根据例如收到消息等外部事件来重启 Task。","category":"page"},{"location":"manual/asynchronous-programming/","page":"异步编程","title":"异步编程","text":"等待一个事件的基本函数是 wait。很多对象都实现了 wait 函数;例如,给定一个 Process 对象,wait 将等待它退出。wait 通常是隐式的,例如,wait 可能发生在调用 read 时等待数据可用。","category":"page"},{"location":"manual/asynchronous-programming/","page":"异步编程","title":"异步编程","text":"在所有这些情况下,wait 最终会操作一个 Condition 对象,由它负责排队和重启 Task。当 Task 在一个 Condition 上调用 wait 时,该 Task 就被标记为不可执行,加到条件的队列中,并切回调度器。调度器将选择另一个 Task 来运行,或者阻止外部事件的等待。如果所有运行良好,最终一个事件处理器将在这个条件下调用 notify,使得等待该条件的 Task 又变成可运行。","category":"page"},{"location":"manual/asynchronous-programming/","page":"异步编程","title":"异步编程","text":"通过调用 Task 显式创建的任务,一开始并不被调度器知道。这允许你根据需要使用 yieldto 手动管理任务。 但是,当此类任务等待事件时,它仍会在事件发生时自动重新启动,正如你所期望。","category":"page"},{"location":"base/strings/#lib-strings","page":"字符串","title":"字符串","text":"","category":"section"},{"location":"base/strings/","page":"字符串","title":"字符串","text":"Core.AbstractChar\nCore.Char\nBase.codepoint\nBase.length(::AbstractString)\nBase.sizeof(::AbstractString)\nBase.:*(::Union{AbstractChar, AbstractString}, ::Union{AbstractChar, AbstractString}...)\nBase.:^(::Union{AbstractString, AbstractChar}, ::Integer)\nBase.string\nBase.repeat(::AbstractString, ::Integer)\nBase.repeat(::AbstractChar, ::Integer)\nBase.repr(::Any)\nCore.String(::AbstractString)\nBase.SubString\nBase.transcode\nBase.unsafe_string\nBase.ncodeunits(::AbstractString)\nBase.codeunit\nBase.codeunits\nBase.ascii\nBase.Regex\nBase.@r_str\nBase.SubstitutionString\nBase.@s_str\nBase.@raw_str\nBase.@b_str\nBase.Docs.@html_str\nBase.Docs.@text_str\nBase.isvalid(::Any)\nBase.isvalid(::Any, ::Any)\nBase.isvalid(::AbstractString, ::Integer)\nBase.match\nBase.eachmatch\nBase.RegexMatch\nBase.keys(::RegexMatch)\nBase.isless(::AbstractString, ::AbstractString)\nBase.:(==)(::AbstractString, ::AbstractString)\nBase.cmp(::AbstractString, ::AbstractString)\nBase.lpad\nBase.rpad\nBase.findfirst(::AbstractString, ::AbstractString)\nBase.findnext(::AbstractString, ::AbstractString, ::Integer)\nBase.findnext(::AbstractChar, ::AbstractString, ::Integer)\nBase.findlast(::AbstractString, ::AbstractString)\nBase.findlast(::AbstractChar, ::AbstractString)\nBase.findprev(::AbstractString, ::AbstractString, ::Integer)\nBase.occursin\nBase.reverse(::Union{String,SubString{String}})\nBase.replace(s::AbstractString, ::Pair)\nBase.split\nBase.rsplit\nBase.strip\nBase.lstrip\nBase.rstrip\nBase.startswith\nBase.endswith\nBase.contains\nBase.first(::AbstractString, ::Integer)\nBase.last(::AbstractString, ::Integer)\nBase.uppercase\nBase.lowercase\nBase.titlecase\nBase.uppercasefirst\nBase.lowercasefirst\nBase.join\nBase.chop\nBase.chomp\nBase.thisind\nBase.nextind\nBase.prevind\nBase.textwidth\nBase.isascii\nBase.iscntrl\nBase.isdigit\nBase.isletter\nBase.islowercase\nBase.isnumeric\nBase.isprint\nBase.ispunct\nBase.isspace\nBase.isuppercase\nBase.isxdigit\nBase.escape_string\nBase.unescape_string","category":"page"},{"location":"base/strings/#Core.AbstractChar","page":"字符串","title":"Core.AbstractChar","text":"The AbstractChar type is the supertype of all character implementations in Julia. A character represents a Unicode code point, and can be converted to an integer via the codepoint function in order to obtain the numerical value of the code point, or constructed from the same integer. These numerical values determine how characters are compared with < and ==, for example. New T <: AbstractChar types should define a codepoint(::T) method and a T(::UInt32) constructor, at minimum.\n\nA given AbstractChar subtype may be capable of representing only a subset of Unicode, in which case conversion from an unsupported UInt32 value may throw an error. Conversely, the built-in Char type represents a superset of Unicode (in order to losslessly encode invalid byte streams), in which case conversion of a non-Unicode value to UInt32 throws an error. The isvalid function can be used to check which codepoints are representable in a given AbstractChar type.\n\nInternally, an AbstractChar type may use a variety of encodings. Conversion via codepoint(char) will not reveal this encoding because it always returns the Unicode value of the character. print(io, c) of any c::AbstractChar produces an encoding determined by io (UTF-8 for all built-in IO types), via conversion to Char if necessary.\n\nwrite(io, c), in contrast, may emit an encoding depending on typeof(c), and read(io, typeof(c)) should read the same encoding as write. New AbstractChar types must provide their own implementations of write and read.\n\n\n\n\n\n","category":"type"},{"location":"base/strings/#Core.Char","page":"字符串","title":"Core.Char","text":"Char(c::Union{Number,AbstractChar})\n\nChar is a 32-bit AbstractChar type that is the default representation of characters in Julia. Char is the type used for character literals like 'x' and it is also the element type of String.\n\nIn order to losslessly represent arbitrary byte streams stored in a String, a Char value may store information that cannot be converted to a Unicode codepoint — converting such a Char to UInt32 will throw an error. The isvalid(c::Char) function can be used to query whether c represents a valid Unicode character.\n\n\n\n\n\n","category":"type"},{"location":"base/strings/#Base.codepoint","page":"字符串","title":"Base.codepoint","text":"codepoint(c::AbstractChar) -> Integer\n\nReturn the Unicode codepoint (an unsigned integer) corresponding to the character c (or throw an exception if c does not represent a valid character). For Char, this is a UInt32 value, but AbstractChar types that represent only a subset of Unicode may return a different-sized integer (e.g. UInt8).\n\n\n\n\n\n","category":"function"},{"location":"base/strings/#Base.length-Tuple{AbstractString}","page":"字符串","title":"Base.length","text":"length(s::AbstractString) -> Int\nlength(s::AbstractString, i::Integer, j::Integer) -> Int\n\nReturn the number of characters in string s from indices i through j.\n\nThis is computed as the number of code unit indices from i to j which are valid character indices. With only a single string argument, this computes the number of characters in the entire string. With i and j arguments it computes the number of indices between i and j inclusive that are valid indices in the string s. In addition to in-bounds values, i may take the out-of-bounds value ncodeunits(s) + 1 and j may take the out-of-bounds value 0.\n\nnote: Note\nThe time complexity of this operation is linear in general. That is, it will take the time proportional to the number of bytes or characters in the string because it counts the value on the fly. This is in contrast to the method for arrays, which is a constant-time operation.\n\nSee also isvalid, ncodeunits, lastindex, thisind, nextind, prevind.\n\nExamples\n\njulia> length(\"jμΛIα\")\n5\n\n\n\n\n\n","category":"method"},{"location":"base/strings/#Base.sizeof-Tuple{AbstractString}","page":"字符串","title":"Base.sizeof","text":"sizeof(str::AbstractString)\n\nSize, in bytes, of the string str. Equal to the number of code units in str multiplied by the size, in bytes, of one code unit in str.\n\nExamples\n\njulia> sizeof(\"\")\n0\n\njulia> sizeof(\"∀\")\n3\n\n\n\n\n\n","category":"method"},{"location":"base/strings/#Base.:*-Tuple{Union{AbstractChar, AbstractString}, Vararg{Union{AbstractChar, AbstractString}}}","page":"字符串","title":"Base.:*","text":"*(s::Union{AbstractString, AbstractChar}, t::Union{AbstractString, AbstractChar}...) -> AbstractString\n\nConcatenate strings and/or characters, producing a String. This is equivalent to calling the string function on the arguments. Concatenation of built-in string types always produces a value of type String but other string types may choose to return a string of a different type as appropriate.\n\nExamples\n\njulia> \"Hello \" * \"world\"\n\"Hello world\"\n\njulia> 'j' * \"ulia\"\n\"julia\"\n\n\n\n\n\n","category":"method"},{"location":"base/strings/#Base.:^-Tuple{Union{AbstractChar, AbstractString}, Integer}","page":"字符串","title":"Base.:^","text":"^(s::Union{AbstractString,AbstractChar}, n::Integer)\n\nRepeat a string or character n times. This can also be written as repeat(s, n).\n\nSee also repeat.\n\nExamples\n\njulia> \"Test \"^3\n\"Test Test Test \"\n\n\n\n\n\n","category":"method"},{"location":"base/strings/#Base.string","page":"字符串","title":"Base.string","text":"string(n::Integer; base::Integer = 10, pad::Integer = 1)\n\nConvert an integer n to a string in the given base, optionally specifying a number of digits to pad to.\n\nSee also digits, bitstring, count_zeros.\n\nExamples\n\njulia> string(5, base = 13, pad = 4)\n\"0005\"\n\njulia> string(-13, base = 5, pad = 4)\n\"-0023\"\n\n\n\n\n\nstring(xs...)\n\nCreate a string from any values using the print function.\n\nstring should usually not be defined directly. Instead, define a method print(io::IO, x::MyType). If string(x) for a certain type needs to be highly efficient, then it may make sense to add a method to string and define print(io::IO, x::MyType) = print(io, string(x)) to ensure the functions are consistent.\n\nSee also: String, repr, sprint, show.\n\nExamples\n\njulia> string(\"a\", 1, true)\n\"a1true\"\n\n\n\n\n\n","category":"function"},{"location":"base/strings/#Base.repeat-Tuple{AbstractString, Integer}","page":"字符串","title":"Base.repeat","text":"repeat(s::AbstractString, r::Integer)\n\nRepeat a string r times. This can be written as s^r.\n\nSee also ^.\n\nExamples\n\njulia> repeat(\"ha\", 3)\n\"hahaha\"\n\n\n\n\n\n","category":"method"},{"location":"base/strings/#Base.repeat-Tuple{AbstractChar, Integer}","page":"字符串","title":"Base.repeat","text":"repeat(c::AbstractChar, r::Integer) -> String\n\nRepeat a character r times. This can equivalently be accomplished by calling c^r.\n\nExamples\n\njulia> repeat('A', 3)\n\"AAA\"\n\n\n\n\n\n","category":"method"},{"location":"base/strings/#Base.repr-Tuple{Any}","page":"字符串","title":"Base.repr","text":"repr(x; context=nothing)\n\nCreate a string from any value using the show function. You should not add methods to repr; define a show method instead.\n\nThe optional keyword argument context can be set to a :key=>value pair, a tuple of :key=>value pairs, or an IO or IOContext object whose attributes are used for the I/O stream passed to show.\n\nNote that repr(x) is usually similar to how the value of x would be entered in Julia. See also repr(MIME(\"text/plain\"), x) to instead return a \"pretty-printed\" version of x designed more for human consumption, equivalent to the REPL display of x.\n\ncompat: Julia 1.7\nPassing a tuple to keyword context requires Julia 1.7 or later.\n\nExamples\n\njulia> repr(1)\n\"1\"\n\njulia> repr(zeros(3))\n\"[0.0, 0.0, 0.0]\"\n\njulia> repr(big(1/3))\n\"0.333333333333333314829616256247390992939472198486328125\"\n\njulia> repr(big(1/3), context=:compact => true)\n\"0.333333\"\n\n\n\n\n\n\n","category":"method"},{"location":"base/strings/#Core.String-Tuple{AbstractString}","page":"字符串","title":"Core.String","text":"String(s::AbstractString)\n\nConvert a string to a contiguous byte array representation encoded as UTF-8 bytes. This representation is often appropriate for passing strings to C.\n\n\n\n\n\n","category":"method"},{"location":"base/strings/#Base.SubString","page":"字符串","title":"Base.SubString","text":"SubString(s::AbstractString, i::Integer, j::Integer=lastindex(s))\nSubString(s::AbstractString, r::UnitRange{<:Integer})\n\nLike getindex, but returns a view into the parent string s within range i:j or r respectively instead of making a copy.\n\nExamples\n\njulia> SubString(\"abc\", 1, 2)\n\"ab\"\n\njulia> SubString(\"abc\", 1:2)\n\"ab\"\n\njulia> SubString(\"abc\", 2)\n\"bc\"\n\n\n\n\n\n","category":"type"},{"location":"base/strings/#Base.transcode","page":"字符串","title":"Base.transcode","text":"transcode(T, src)\n\nConvert string data between Unicode encodings. src is either a String or a Vector{UIntXX} of UTF-XX code units, where XX is 8, 16, or 32. T indicates the encoding of the return value: String to return a (UTF-8 encoded) String or UIntXX to return a Vector{UIntXX} of UTF-XX data. (The alias Cwchar_t can also be used as the integer type, for converting wchar_t* strings used by external C libraries.)\n\nThe transcode function succeeds as long as the input data can be reasonably represented in the target encoding; it always succeeds for conversions between UTF-XX encodings, even for invalid Unicode data.\n\nOnly conversion to/from UTF-8 is currently supported.\n\nExamples\n\njulia> str = \"αβγ\"\n\"αβγ\"\n\njulia> transcode(UInt16, str)\n3-element Vector{UInt16}:\n 0x03b1\n 0x03b2\n 0x03b3\n\njulia> transcode(String, transcode(UInt16, str))\n\"αβγ\"\n\n\n\n\n\n","category":"function"},{"location":"base/strings/#Base.unsafe_string","page":"字符串","title":"Base.unsafe_string","text":"unsafe_string(p::Ptr{UInt8}, [length::Integer])\n\nCopy a string from the address of a C-style (NUL-terminated) string encoded as UTF-8. (The pointer can be safely freed afterwards.) If length is specified (the length of the data in bytes), the string does not have to be NUL-terminated.\n\nThis function is labeled \"unsafe\" because it will crash if p is not a valid memory address to data of the requested length.\n\n\n\n\n\n","category":"function"},{"location":"base/strings/#Base.ncodeunits-Tuple{AbstractString}","page":"字符串","title":"Base.ncodeunits","text":"ncodeunits(s::AbstractString) -> Int\n\nReturn the number of code units in a string. Indices that are in bounds to access this string must satisfy 1 ≤ i ≤ ncodeunits(s). Not all such indices are valid – they may not be the start of a character, but they will return a code unit value when calling codeunit(s,i).\n\nExamples\n\njulia> ncodeunits(\"The Julia Language\")\n18\n\njulia> ncodeunits(\"∫eˣ\")\n6\n\njulia> ncodeunits('∫'), ncodeunits('e'), ncodeunits('ˣ')\n(3, 1, 2)\n\nSee also codeunit, checkbounds, sizeof, length, lastindex.\n\n\n\n\n\n","category":"method"},{"location":"base/strings/#Base.codeunit","page":"字符串","title":"Base.codeunit","text":"codeunit(s::AbstractString) -> Type{<:Union{UInt8, UInt16, UInt32}}\n\nReturn the code unit type of the given string object. For ASCII, Latin-1, or UTF-8 encoded strings, this would be UInt8; for UCS-2 and UTF-16 it would be UInt16; for UTF-32 it would be UInt32. The code unit type need not be limited to these three types, but it's hard to think of widely used string encodings that don't use one of these units. codeunit(s) is the same as typeof(codeunit(s,1)) when s is a non-empty string.\n\nSee also ncodeunits.\n\n\n\n\n\ncodeunit(s::AbstractString, i::Integer) -> Union{UInt8, UInt16, UInt32}\n\nReturn the code unit value in the string s at index i. Note that\n\ncodeunit(s, i) :: codeunit(s)\n\nI.e. the value returned by codeunit(s, i) is of the type returned by codeunit(s).\n\nExamples\n\njulia> a = codeunit(\"Hello\", 2)\n0x65\n\njulia> typeof(a)\nUInt8\n\nSee also ncodeunits, checkbounds.\n\n\n\n\n\n","category":"function"},{"location":"base/strings/#Base.codeunits","page":"字符串","title":"Base.codeunits","text":"codeunits(s::AbstractString)\n\nObtain a vector-like object containing the code units of a string. Returns a CodeUnits wrapper by default, but codeunits may optionally be defined for new string types if necessary.\n\nExamples\n\njulia> codeunits(\"Juλia\")\n6-element Base.CodeUnits{UInt8, String}:\n 0x4a\n 0x75\n 0xce\n 0xbb\n 0x69\n 0x61\n\n\n\n\n\n","category":"function"},{"location":"base/strings/#Base.ascii","page":"字符串","title":"Base.ascii","text":"ascii(s::AbstractString)\n\nConvert a string to String type and check that it contains only ASCII data, otherwise throwing an ArgumentError indicating the position of the first non-ASCII byte.\n\nSee also the isascii predicate to filter or replace non-ASCII characters.\n\nExamples\n\njulia> ascii(\"abcdeγfgh\")\nERROR: ArgumentError: invalid ASCII at index 6 in \"abcdeγfgh\"\nStacktrace:\n[...]\n\njulia> ascii(\"abcdefgh\")\n\"abcdefgh\"\n\n\n\n\n\n","category":"function"},{"location":"base/strings/#Base.Regex","page":"字符串","title":"Base.Regex","text":"Regex(pattern[, flags])\n\nA type representing a regular expression. Regex objects can be used to match strings with match.\n\nRegex objects can be created using the @r_str string macro. The Regex(pattern[, flags]) constructor is usually used if the pattern string needs to be interpolated. See the documentation of the string macro for details on flags.\n\nnote: Note\nTo escape interpolated variables use \\Q and \\E (e.g. Regex(\"\\\\Q$x\\\\E\"))\n\n\n\n\n\n","category":"type"},{"location":"base/strings/#Base.@r_str","page":"字符串","title":"Base.@r_str","text":"@r_str -> Regex\n\nConstruct a regex, such as r\"^[a-z]*$\", without interpolation and unescaping (except for quotation mark \" which still has to be escaped). The regex also accepts one or more flags, listed after the ending quote, to change its behaviour:\n\ni enables case-insensitive matching\nm treats the ^ and $ tokens as matching the start and end of individual lines, as opposed to the whole string.\ns allows the . modifier to match newlines.\nx enables \"comment mode\": whitespace is enabled except when escaped with \\, and # is treated as starting a comment.\na disables UCP mode (enables ASCII mode). By default \\B, \\b, \\D, \\d, \\S, \\s, \\W, \\w, etc. match based on Unicode character properties. With this option, these sequences only match ASCII characters.\n\nSee Regex if interpolation is needed.\n\nExamples\n\njulia> match(r\"a+.*b+.*?d$\"ism, \"Goodbye,\\nOh, angry,\\nBad world\\n\")\nRegexMatch(\"angry,\\nBad world\")\n\nThis regex has the first three flags enabled.\n\n\n\n\n\n","category":"macro"},{"location":"base/strings/#Base.SubstitutionString","page":"字符串","title":"Base.SubstitutionString","text":"SubstitutionString(substr)\n\nStores the given string substr as a SubstitutionString, for use in regular expression substitutions. Most commonly constructed using the @s_str macro.\n\nExamples\n\njulia> SubstitutionString(\"Hello \\\\g, it's \\\\1\")\ns\"Hello \\g, it's \\1\"\n\njulia> subst = s\"Hello \\g, it's \\1\"\ns\"Hello \\g, it's \\1\"\n\njulia> typeof(subst)\nSubstitutionString{String}\n\n\n\n\n\n\n","category":"type"},{"location":"base/strings/#Base.@s_str","page":"字符串","title":"Base.@s_str","text":"@s_str -> SubstitutionString\n\nConstruct a substitution string, used for regular expression substitutions. Within the string, sequences of the form \\N refer to the Nth capture group in the regex, and \\g refers to a named capture group with name groupname.\n\nExamples\n\njulia> msg = \"#Hello# from Julia\";\n\njulia> replace(msg, r\"#(.+)# from (?\\w+)\" => s\"FROM: \\g; MESSAGE: \\1\")\n\"FROM: Julia; MESSAGE: Hello\"\n\n\n\n\n\n","category":"macro"},{"location":"base/strings/#Base.@raw_str","page":"字符串","title":"Base.@raw_str","text":"@raw_str -> String\n\nCreate a raw string without interpolation and unescaping. The exception is that quotation marks still must be escaped. Backslashes escape both quotation marks and other backslashes, but only when a sequence of backslashes precedes a quote character. Thus, 2n backslashes followed by a quote encodes n backslashes and the end of the literal while 2n+1 backslashes followed by a quote encodes n backslashes followed by a quote character.\n\nExamples\n\njulia> println(raw\"\\ $x\")\n\\ $x\n\njulia> println(raw\"\\\"\")\n\"\n\njulia> println(raw\"\\\\\\\"\")\n\\\"\n\njulia> println(raw\"\\\\x \\\\\\\"\")\n\\\\x \\\"\n\n\n\n\n\n","category":"macro"},{"location":"base/strings/#Base.@b_str","page":"字符串","title":"Base.@b_str","text":"@b_str\n\nCreate an immutable byte (UInt8) vector using string syntax.\n\nExamples\n\njulia> v = b\"12\\x01\\x02\"\n4-element Base.CodeUnits{UInt8, String}:\n 0x31\n 0x32\n 0x01\n 0x02\n\njulia> v[2]\n0x32\n\n\n\n\n\n","category":"macro"},{"location":"base/strings/#Base.Docs.@html_str","page":"字符串","title":"Base.Docs.@html_str","text":"@html_str -> Docs.HTML\n\nCreate an HTML object from a literal string.\n\nExamples\n\njulia> html\"Julia\"\nHTML{String}(\"Julia\")\n\n\n\n\n\n","category":"macro"},{"location":"base/strings/#Base.Docs.@text_str","page":"字符串","title":"Base.Docs.@text_str","text":"@text_str -> Docs.Text\n\nCreate a Text object from a literal string.\n\nExamples\n\njulia> text\"Julia\"\nJulia\n\n\n\n\n\n","category":"macro"},{"location":"base/strings/#Base.isvalid-Tuple{Any}","page":"字符串","title":"Base.isvalid","text":"isvalid(value) -> Bool\n\nReturns true if the given value is valid for its type, which currently can be either AbstractChar or String or SubString{String}.\n\nExamples\n\njulia> isvalid(Char(0xd800))\nfalse\n\njulia> isvalid(SubString(String(UInt8[0xfe,0x80,0x80,0x80,0x80,0x80]),1,2))\nfalse\n\njulia> isvalid(Char(0xd799))\ntrue\n\n\n\n\n\n","category":"method"},{"location":"base/strings/#Base.isvalid-Tuple{Any, Any}","page":"字符串","title":"Base.isvalid","text":"isvalid(T, value) -> Bool\n\nReturns true if the given value is valid for that type. Types currently can be either AbstractChar or String. Values for AbstractChar can be of type AbstractChar or UInt32. Values for String can be of that type, SubString{String}, Vector{UInt8}, or a contiguous subarray thereof.\n\nExamples\n\njulia> isvalid(Char, 0xd800)\nfalse\n\njulia> isvalid(String, SubString(\"thisisvalid\",1,5))\ntrue\n\njulia> isvalid(Char, 0xd799)\ntrue\n\ncompat: Julia 1.6\nSupport for subarray values was added in Julia 1.6.\n\n\n\n\n\n","category":"method"},{"location":"base/strings/#Base.isvalid-Tuple{AbstractString, Integer}","page":"字符串","title":"Base.isvalid","text":"isvalid(s::AbstractString, i::Integer) -> Bool\n\nPredicate indicating whether the given index is the start of the encoding of a character in s or not. If isvalid(s, i) is true then s[i] will return the character whose encoding starts at that index, if it's false, then s[i] will raise an invalid index error or a bounds error depending on if i is in bounds. In order for isvalid(s, i) to be an O(1) function, the encoding of s must be self-synchronizing. This is a basic assumption of Julia's generic string support.\n\nSee also getindex, iterate, thisind, nextind, prevind, length.\n\nExamples\n\njulia> str = \"αβγdef\";\n\njulia> isvalid(str, 1)\ntrue\n\njulia> str[1]\n'α': Unicode U+03B1 (category Ll: Letter, lowercase)\n\njulia> isvalid(str, 2)\nfalse\n\njulia> str[2]\nERROR: StringIndexError: invalid index [2], valid nearby indices [1]=>'α', [3]=>'β'\nStacktrace:\n[...]\n\n\n\n\n\n","category":"method"},{"location":"base/strings/#Base.match","page":"字符串","title":"Base.match","text":"match(r::Regex, s::AbstractString[, idx::Integer[, addopts]])\n\nSearch for the first match of the regular expression r in s and return a RegexMatch object containing the match, or nothing if the match failed. The matching substring can be retrieved by accessing m.match and the captured sequences can be retrieved by accessing m.captures The optional idx argument specifies an index at which to start the search.\n\nExamples\n\njulia> rx = r\"a(.)a\"\nr\"a(.)a\"\n\njulia> m = match(rx, \"cabac\")\nRegexMatch(\"aba\", 1=\"b\")\n\njulia> m.captures\n1-element Vector{Union{Nothing, SubString{String}}}:\n \"b\"\n\njulia> m.match\n\"aba\"\n\njulia> match(rx, \"cabac\", 3) === nothing\ntrue\n\n\n\n\n\n","category":"function"},{"location":"base/strings/#Base.eachmatch","page":"字符串","title":"Base.eachmatch","text":"eachmatch(r::Regex, s::AbstractString; overlap::Bool=false)\n\nSearch for all matches of the regular expression r in s and return an iterator over the matches. If overlap is true, the matching sequences are allowed to overlap indices in the original string, otherwise they must be from distinct character ranges.\n\nExamples\n\njulia> rx = r\"a.a\"\nr\"a.a\"\n\njulia> m = eachmatch(rx, \"a1a2a3a\")\nBase.RegexMatchIterator(r\"a.a\", \"a1a2a3a\", false)\n\njulia> collect(m)\n2-element Vector{RegexMatch}:\n RegexMatch(\"a1a\")\n RegexMatch(\"a3a\")\n\njulia> collect(eachmatch(rx, \"a1a2a3a\", overlap = true))\n3-element Vector{RegexMatch}:\n RegexMatch(\"a1a\")\n RegexMatch(\"a2a\")\n RegexMatch(\"a3a\")\n\n\n\n\n\n","category":"function"},{"location":"base/strings/#Base.RegexMatch","page":"字符串","title":"Base.RegexMatch","text":"RegexMatch\n\nA type representing a single match to a Regex found in a string. Typically created from the match function.\n\nThe match field stores the substring of the entire matched string. The captures field stores the substrings for each capture group, indexed by number. To index by capture group name, the entire match object should be indexed instead, as shown in the examples. The location of the start of the match is stored in the offset field. The offsets field stores the locations of the start of each capture group, with 0 denoting a group that was not captured.\n\nThis type can be used as an iterator over the capture groups of the Regex, yielding the substrings captured in each group. Because of this, the captures of a match can be destructured. If a group was not captured, nothing will be yielded instead of a substring.\n\nMethods that accept a RegexMatch object are defined for iterate, length, eltype, keys, haskey, and getindex, where keys are the the names or numbers of a capture group. See keys for more information.\n\nExamples\n\njulia> m = match(r\"(?\\d+):(?\\d+)(am|pm)?\", \"11:30 in the morning\")\nRegexMatch(\"11:30\", hour=\"11\", minute=\"30\", 3=nothing)\n\njulia> hr, min, ampm = m;\n\njulia> hr\n\"11\"\n\njulia> m[\"minute\"]\n\"30\"\n\njulia> m.match\n\"11:30\"\n\n\n\n\n\n","category":"type"},{"location":"base/strings/#Base.keys-Tuple{RegexMatch}","page":"字符串","title":"Base.keys","text":"keys(m::RegexMatch) -> Vector\n\nReturn a vector of keys for all capture groups of the underlying regex. A key is included even if the capture group fails to match. That is, idx will be in the return value even if m[idx] == nothing.\n\nUnnamed capture groups will have integer keys corresponding to their index. Named capture groups will have string keys.\n\ncompat: Julia 1.6\nThis method was added in Julia 1.6\n\nExamples\n\njulia> keys(match(r\"(?\\d+):(?\\d+)(am|pm)?\", \"11:30\"))\n3-element Vector{Any}:\n \"hour\"\n \"minute\"\n 3\n\n\n\n\n\n","category":"method"},{"location":"base/strings/#Base.isless-Tuple{AbstractString, AbstractString}","page":"字符串","title":"Base.isless","text":"isless(a::AbstractString, b::AbstractString) -> Bool\n\nTest whether string a comes before string b in alphabetical order (technically, in lexicographical order by Unicode code points).\n\nExamples\n\njulia> isless(\"a\", \"b\")\ntrue\n\njulia> isless(\"β\", \"α\")\nfalse\n\njulia> isless(\"a\", \"a\")\nfalse\n\n\n\n\n\n","category":"method"},{"location":"base/strings/#Base.:==-Tuple{AbstractString, AbstractString}","page":"字符串","title":"Base.:==","text":"==(a::AbstractString, b::AbstractString) -> Bool\n\nTest whether two strings are equal character by character (technically, Unicode code point by code point).\n\nExamples\n\njulia> \"abc\" == \"abc\"\ntrue\n\njulia> \"abc\" == \"αβγ\"\nfalse\n\n\n\n\n\n","category":"method"},{"location":"base/strings/#Base.cmp-Tuple{AbstractString, AbstractString}","page":"字符串","title":"Base.cmp","text":"cmp(a::AbstractString, b::AbstractString) -> Int\n\nCompare two strings. Return 0 if both strings have the same length and the character at each index is the same in both strings. Return -1 if a is a prefix of b, or if a comes before b in alphabetical order. Return 1 if b is a prefix of a, or if b comes before a in alphabetical order (technically, lexicographical order by Unicode code points).\n\nExamples\n\njulia> cmp(\"abc\", \"abc\")\n0\n\njulia> cmp(\"ab\", \"abc\")\n-1\n\njulia> cmp(\"abc\", \"ab\")\n1\n\njulia> cmp(\"ab\", \"ac\")\n-1\n\njulia> cmp(\"ac\", \"ab\")\n1\n\njulia> cmp(\"α\", \"a\")\n1\n\njulia> cmp(\"b\", \"β\")\n-1\n\n\n\n\n\n","category":"method"},{"location":"base/strings/#Base.lpad","page":"字符串","title":"Base.lpad","text":"lpad(s, n::Integer, p::Union{AbstractChar,AbstractString}=' ') -> String\n\nStringify s and pad the resulting string on the left with p to make it n characters (in textwidth) long. If s is already n characters long, an equal string is returned. Pad with spaces by default.\n\nExamples\n\njulia> lpad(\"March\", 10)\n\" March\"\n\ncompat: Julia 1.7\nIn Julia 1.7, this function was changed to use textwidth rather than a raw character (codepoint) count.\n\n\n\n\n\n","category":"function"},{"location":"base/strings/#Base.rpad","page":"字符串","title":"Base.rpad","text":"rpad(s, n::Integer, p::Union{AbstractChar,AbstractString}=' ') -> String\n\nStringify s and pad the resulting string on the right with p to make it n characters (in textwidth) long. If s is already n characters long, an equal string is returned. Pad with spaces by default.\n\nExamples\n\njulia> rpad(\"March\", 20)\n\"March \"\n\ncompat: Julia 1.7\nIn Julia 1.7, this function was changed to use textwidth rather than a raw character (codepoint) count.\n\n\n\n\n\n","category":"function"},{"location":"base/strings/#Base.findfirst-Tuple{AbstractString, AbstractString}","page":"字符串","title":"Base.findfirst","text":"findfirst(pattern::AbstractString, string::AbstractString)\nfindfirst(pattern::AbstractPattern, string::String)\n\nFind the first occurrence of pattern in string. Equivalent to findnext(pattern, string, firstindex(s)).\n\nExamples\n\njulia> findfirst(\"z\", \"Hello to the world\") # returns nothing, but not printed in the REPL\n\njulia> findfirst(\"Julia\", \"JuliaLang\")\n1:5\n\n\n\n\n\n","category":"method"},{"location":"base/strings/#Base.findnext-Tuple{AbstractString, AbstractString, Integer}","page":"字符串","title":"Base.findnext","text":"findnext(pattern::AbstractString, string::AbstractString, start::Integer)\nfindnext(pattern::AbstractPattern, string::String, start::Integer)\n\nFind the next occurrence of pattern in string starting at position start. pattern can be either a string, or a regular expression, in which case string must be of type String.\n\nThe return value is a range of indices where the matching sequence is found, such that s[findnext(x, s, i)] == x:\n\nfindnext(\"substring\", string, i) == start:stop such that string[start:stop] == \"substring\" and i <= start, or nothing if unmatched.\n\nExamples\n\njulia> findnext(\"z\", \"Hello to the world\", 1) === nothing\ntrue\n\njulia> findnext(\"o\", \"Hello to the world\", 6)\n8:8\n\njulia> findnext(\"Lang\", \"JuliaLang\", 2)\n6:9\n\n\n\n\n\n","category":"method"},{"location":"base/strings/#Base.findnext-Tuple{AbstractChar, AbstractString, Integer}","page":"字符串","title":"Base.findnext","text":"findnext(ch::AbstractChar, string::AbstractString, start::Integer)\n\nFind the next occurrence of character ch in string starting at position start.\n\ncompat: Julia 1.3\nThis method requires at least Julia 1.3.\n\nExamples\n\njulia> findnext('z', \"Hello to the world\", 1) === nothing\ntrue\n\njulia> findnext('o', \"Hello to the world\", 6)\n8\n\n\n\n\n\n","category":"method"},{"location":"base/strings/#Base.findlast-Tuple{AbstractString, AbstractString}","page":"字符串","title":"Base.findlast","text":"findlast(pattern::AbstractString, string::AbstractString)\n\nFind the last occurrence of pattern in string. Equivalent to findprev(pattern, string, lastindex(string)).\n\nExamples\n\njulia> findlast(\"o\", \"Hello to the world\")\n15:15\n\njulia> findfirst(\"Julia\", \"JuliaLang\")\n1:5\n\n\n\n\n\n","category":"method"},{"location":"base/strings/#Base.findlast-Tuple{AbstractChar, AbstractString}","page":"字符串","title":"Base.findlast","text":"findlast(ch::AbstractChar, string::AbstractString)\n\nFind the last occurrence of character ch in string.\n\ncompat: Julia 1.3\nThis method requires at least Julia 1.3.\n\nExamples\n\njulia> findlast('p', \"happy\")\n4\n\njulia> findlast('z', \"happy\") === nothing\ntrue\n\n\n\n\n\n","category":"method"},{"location":"base/strings/#Base.findprev-Tuple{AbstractString, AbstractString, Integer}","page":"字符串","title":"Base.findprev","text":"findprev(pattern::AbstractString, string::AbstractString, start::Integer)\n\nFind the previous occurrence of pattern in string starting at position start.\n\nThe return value is a range of indices where the matching sequence is found, such that s[findprev(x, s, i)] == x:\n\nfindprev(\"substring\", string, i) == start:stop such that string[start:stop] == \"substring\" and stop <= i, or nothing if unmatched.\n\nExamples\n\njulia> findprev(\"z\", \"Hello to the world\", 18) === nothing\ntrue\n\njulia> findprev(\"o\", \"Hello to the world\", 18)\n15:15\n\njulia> findprev(\"Julia\", \"JuliaLang\", 6)\n1:5\n\n\n\n\n\n","category":"method"},{"location":"base/strings/#Base.occursin","page":"字符串","title":"Base.occursin","text":"occursin(needle::Union{AbstractString,AbstractPattern,AbstractChar}, haystack::AbstractString)\n\nDetermine whether the first argument is a substring of the second. If needle is a regular expression, checks whether haystack contains a match.\n\nExamples\n\njulia> occursin(\"Julia\", \"JuliaLang is pretty cool!\")\ntrue\n\njulia> occursin('a', \"JuliaLang is pretty cool!\")\ntrue\n\njulia> occursin(r\"a.a\", \"aba\")\ntrue\n\njulia> occursin(r\"a.a\", \"abba\")\nfalse\n\nSee also contains.\n\n\n\n\n\noccursin(haystack)\n\nCreate a function that checks whether its argument occurs in haystack, i.e. a function equivalent to needle -> occursin(needle, haystack).\n\nThe returned function is of type Base.Fix2{typeof(occursin)}.\n\ncompat: Julia 1.6\nThis method requires Julia 1.6 or later.\n\n\n\n\n\n","category":"function"},{"location":"base/strings/#Base.reverse-Tuple{Union{SubString{String}, String}}","page":"字符串","title":"Base.reverse","text":"reverse(s::AbstractString) -> AbstractString\n\nReverses a string. Technically, this function reverses the codepoints in a string and its main utility is for reversed-order string processing, especially for reversed regular-expression searches. See also reverseind to convert indices in s to indices in reverse(s) and vice-versa, and graphemes from module Unicode to operate on user-visible \"characters\" (graphemes) rather than codepoints. See also Iterators.reverse for reverse-order iteration without making a copy. Custom string types must implement the reverse function themselves and should typically return a string with the same type and encoding. If they return a string with a different encoding, they must also override reverseind for that string type to satisfy s[reverseind(s,i)] == reverse(s)[i].\n\nExamples\n\njulia> reverse(\"JuliaLang\")\n\"gnaLailuJ\"\n\nnote: Note\nThe examples below may be rendered differently on different systems. The comments indicate how they're supposed to be rendered\n\nCombining characters can lead to surprising results:\n\njulia> reverse(\"ax̂e\") # hat is above x in the input, above e in the output\n\"êxa\"\n\njulia> using Unicode\n\njulia> join(reverse(collect(graphemes(\"ax̂e\")))) # reverses graphemes; hat is above x in both in- and output\n\"ex̂a\"\n\n\n\n\n\n","category":"method"},{"location":"base/strings/#Base.replace-Tuple{AbstractString, Pair}","page":"字符串","title":"Base.replace","text":"replace(A, old_new::Pair...; [count::Integer])\n\nReturn a copy of collection A where, for each pair old=>new in old_new, all occurrences of old are replaced by new. Equality is determined using isequal. If count is specified, then replace at most count occurrences in total.\n\nThe element type of the result is chosen using promotion (see promote_type) based on the element type of A and on the types of the new values in pairs. If count is omitted and the element type of A is a Union, the element type of the result will not include singleton types which are replaced with values of a different type: for example, Union{T,Missing} will become T if missing is replaced.\n\nSee also replace!, splice!, delete!, insert!.\n\ncompat: Julia 1.7\nVersion 1.7 is required to replace elements of a Tuple.\n\nExamples\n\njulia> replace([1, 2, 1, 3], 1=>0, 2=>4, count=2)\n4-element Vector{Int64}:\n 0\n 4\n 1\n 3\n\njulia> replace([1, missing], missing=>0)\n2-element Vector{Int64}:\n 1\n 0\n\n\n\n\n\nreplace(s::AbstractString, pat=>r, [pat2=>r2, ...]; [count::Integer])\n\nSearch for the given pattern pat in s, and replace each occurrence with r. If count is provided, replace at most count occurrences. pat may be a single character, a vector or a set of characters, a string, or a regular expression. If r is a function, each occurrence is replaced with r(s) where s is the matched substring (when pat is a AbstractPattern or AbstractString) or character (when pat is an AbstractChar or a collection of AbstractChar). If pat is a regular expression and r is a SubstitutionString, then capture group references in r are replaced with the corresponding matched text. To remove instances of pat from string, set r to the empty String (\"\").\n\nMultiple patterns can be specified, and they will be applied left-to-right simultaneously, so only one pattern will be applied to any character, and the patterns will only be applied to the input text, not the replacements.\n\ncompat: Julia 1.7\nSupport for multiple patterns requires version 1.7.\n\nExamples\n\njulia> replace(\"Python is a programming language.\", \"Python\" => \"Julia\")\n\"Julia is a programming language.\"\n\njulia> replace(\"The quick foxes run quickly.\", \"quick\" => \"slow\", count=1)\n\"The slow foxes run quickly.\"\n\njulia> replace(\"The quick foxes run quickly.\", \"quick\" => \"\", count=1)\n\"The foxes run quickly.\"\n\njulia> replace(\"The quick foxes run quickly.\", r\"fox(es)?\" => s\"bus\\1\")\n\"The quick buses run quickly.\"\n\njulia> replace(\"abcabc\", \"a\" => \"b\", \"b\" => \"c\", r\".+\" => \"a\")\n\"bca\"\n\n\n\n\n\n","category":"method"},{"location":"base/strings/#Base.split","page":"字符串","title":"Base.split","text":"split(str::AbstractString, dlm; limit::Integer=0, keepempty::Bool=true)\nsplit(str::AbstractString; limit::Integer=0, keepempty::Bool=false)\n\nSplit str into an array of substrings on occurrences of the delimiter(s) dlm. dlm can be any of the formats allowed by findnext's first argument (i.e. as a string, regular expression or a function), or as a single character or collection of characters.\n\nIf dlm is omitted, it defaults to isspace.\n\nThe optional keyword arguments are:\n\nlimit: the maximum size of the result. limit=0 implies no maximum (default)\nkeepempty: whether empty fields should be kept in the result. Default is false without a dlm argument, true with a dlm argument.\n\nSee also rsplit, eachsplit.\n\nExamples\n\njulia> a = \"Ma.rch\"\n\"Ma.rch\"\n\njulia> split(a, \".\")\n2-element Vector{SubString{String}}:\n \"Ma\"\n \"rch\"\n\n\n\n\n\n","category":"function"},{"location":"base/strings/#Base.rsplit","page":"字符串","title":"Base.rsplit","text":"rsplit(s::AbstractString; limit::Integer=0, keepempty::Bool=false)\nrsplit(s::AbstractString, chars; limit::Integer=0, keepempty::Bool=true)\n\nSimilar to split, but starting from the end of the string.\n\nExamples\n\njulia> a = \"M.a.r.c.h\"\n\"M.a.r.c.h\"\n\njulia> rsplit(a, \".\")\n5-element Vector{SubString{String}}:\n \"M\"\n \"a\"\n \"r\"\n \"c\"\n \"h\"\n\njulia> rsplit(a, \".\"; limit=1)\n1-element Vector{SubString{String}}:\n \"M.a.r.c.h\"\n\njulia> rsplit(a, \".\"; limit=2)\n2-element Vector{SubString{String}}:\n \"M.a.r.c\"\n \"h\"\n\n\n\n\n\n","category":"function"},{"location":"base/strings/#Base.strip","page":"字符串","title":"Base.strip","text":"strip([pred=isspace,] str::AbstractString) -> SubString\nstrip(str::AbstractString, chars) -> SubString\n\nRemove leading and trailing characters from str, either those specified by chars or those for which the function pred returns true.\n\nThe default behaviour is to remove leading and trailing whitespace and delimiters: see isspace for precise details.\n\nThe optional chars argument specifies which characters to remove: it can be a single character, vector or set of characters.\n\nSee also lstrip and rstrip.\n\ncompat: Julia 1.2\nThe method which accepts a predicate function requires Julia 1.2 or later.\n\nExamples\n\njulia> strip(\"{3, 5}\\n\", ['{', '}', '\\n'])\n\"3, 5\"\n\n\n\n\n\n","category":"function"},{"location":"base/strings/#Base.lstrip","page":"字符串","title":"Base.lstrip","text":"lstrip([pred=isspace,] str::AbstractString) -> SubString\nlstrip(str::AbstractString, chars) -> SubString\n\nRemove leading characters from str, either those specified by chars or those for which the function pred returns true.\n\nThe default behaviour is to remove leading whitespace and delimiters: see isspace for precise details.\n\nThe optional chars argument specifies which characters to remove: it can be a single character, or a vector or set of characters.\n\nSee also strip and rstrip.\n\nExamples\n\njulia> a = lpad(\"March\", 20)\n\" March\"\n\njulia> lstrip(a)\n\"March\"\n\n\n\n\n\n","category":"function"},{"location":"base/strings/#Base.rstrip","page":"字符串","title":"Base.rstrip","text":"rstrip([pred=isspace,] str::AbstractString) -> SubString\nrstrip(str::AbstractString, chars) -> SubString\n\nRemove trailing characters from str, either those specified by chars or those for which the function pred returns true.\n\nThe default behaviour is to remove trailing whitespace and delimiters: see isspace for precise details.\n\nThe optional chars argument specifies which characters to remove: it can be a single character, or a vector or set of characters.\n\nSee also strip and lstrip.\n\nExamples\n\njulia> a = rpad(\"March\", 20)\n\"March \"\n\njulia> rstrip(a)\n\"March\"\n\n\n\n\n\n","category":"function"},{"location":"base/strings/#Base.startswith","page":"字符串","title":"Base.startswith","text":"startswith(s::AbstractString, prefix::AbstractString)\n\nReturn true if s starts with prefix. If prefix is a vector or set of characters, test whether the first character of s belongs to that set.\n\nSee also endswith, contains.\n\nExamples\n\njulia> startswith(\"JuliaLang\", \"Julia\")\ntrue\n\n\n\n\n\nstartswith(prefix)\n\nCreate a function that checks whether its argument starts with prefix, i.e. a function equivalent to y -> startswith(y, prefix).\n\nThe returned function is of type Base.Fix2{typeof(startswith)}, which can be used to implement specialized methods.\n\ncompat: Julia 1.5\nThe single argument startswith(prefix) requires at least Julia 1.5.\n\nExamples\n\njulia> startswith_julia = startswith(\"Julia\");\n\njulia> startswith_julia(\"Julia\")\ntrue\n\njulia> startswith_julia(\"NotJulia\")\nfalse\n\n\n\n\n\nstartswith(s::AbstractString, prefix::Regex)\n\nReturn true if s starts with the regex pattern, prefix.\n\nnote: Note\nstartswith does not compile the anchoring into the regular expression, but instead passes the anchoring as match_option to PCRE. If compile time is amortized, occursin(r\"^...\", s) is faster than startswith(s, r\"...\").\n\nSee also occursin and endswith.\n\ncompat: Julia 1.2\nThis method requires at least Julia 1.2.\n\nExamples\n\njulia> startswith(\"JuliaLang\", r\"Julia|Romeo\")\ntrue\n\n\n\n\n\n","category":"function"},{"location":"base/strings/#Base.endswith","page":"字符串","title":"Base.endswith","text":"endswith(s::AbstractString, suffix::AbstractString)\n\nReturn true if s ends with suffix. If suffix is a vector or set of characters, test whether the last character of s belongs to that set.\n\nSee also startswith, contains.\n\nExamples\n\njulia> endswith(\"Sunday\", \"day\")\ntrue\n\n\n\n\n\nendswith(suffix)\n\nCreate a function that checks whether its argument ends with suffix, i.e. a function equivalent to y -> endswith(y, suffix).\n\nThe returned function is of type Base.Fix2{typeof(endswith)}, which can be used to implement specialized methods.\n\ncompat: Julia 1.5\nThe single argument endswith(suffix) requires at least Julia 1.5.\n\nExamples\n\njulia> endswith_julia = endswith(\"Julia\");\n\njulia> endswith_julia(\"Julia\")\ntrue\n\njulia> endswith_julia(\"JuliaLang\")\nfalse\n\n\n\n\n\nendswith(s::AbstractString, suffix::Regex)\n\nReturn true if s ends with the regex pattern, suffix.\n\nnote: Note\nendswith does not compile the anchoring into the regular expression, but instead passes the anchoring as match_option to PCRE. If compile time is amortized, occursin(r\"...$\", s) is faster than endswith(s, r\"...\").\n\nSee also occursin and startswith.\n\ncompat: Julia 1.2\nThis method requires at least Julia 1.2.\n\nExamples\n\njulia> endswith(\"JuliaLang\", r\"Lang|Roberts\")\ntrue\n\n\n\n\n\n","category":"function"},{"location":"base/strings/#Base.contains","page":"字符串","title":"Base.contains","text":"contains(haystack::AbstractString, needle)\n\nReturn true if haystack contains needle. This is the same as occursin(needle, haystack), but is provided for consistency with startswith(haystack, needle) and endswith(haystack, needle).\n\nSee also occursin, in, issubset.\n\nExamples\n\njulia> contains(\"JuliaLang is pretty cool!\", \"Julia\")\ntrue\n\njulia> contains(\"JuliaLang is pretty cool!\", 'a')\ntrue\n\njulia> contains(\"aba\", r\"a.a\")\ntrue\n\njulia> contains(\"abba\", r\"a.a\")\nfalse\n\ncompat: Julia 1.5\nThe contains function requires at least Julia 1.5.\n\n\n\n\n\ncontains(needle)\n\nCreate a function that checks whether its argument contains needle, i.e. a function equivalent to haystack -> contains(haystack, needle).\n\nThe returned function is of type Base.Fix2{typeof(contains)}, which can be used to implement specialized methods.\n\n\n\n\n\n","category":"function"},{"location":"base/strings/#Base.first-Tuple{AbstractString, Integer}","page":"字符串","title":"Base.first","text":"first(s::AbstractString, n::Integer)\n\nGet a string consisting of the first n characters of s.\n\nExamples\n\njulia> first(\"∀ϵ≠0: ϵ²>0\", 0)\n\"\"\n\njulia> first(\"∀ϵ≠0: ϵ²>0\", 1)\n\"∀\"\n\njulia> first(\"∀ϵ≠0: ϵ²>0\", 3)\n\"∀ϵ≠\"\n\n\n\n\n\n","category":"method"},{"location":"base/strings/#Base.last-Tuple{AbstractString, Integer}","page":"字符串","title":"Base.last","text":"last(s::AbstractString, n::Integer)\n\nGet a string consisting of the last n characters of s.\n\nExamples\n\njulia> last(\"∀ϵ≠0: ϵ²>0\", 0)\n\"\"\n\njulia> last(\"∀ϵ≠0: ϵ²>0\", 1)\n\"0\"\n\njulia> last(\"∀ϵ≠0: ϵ²>0\", 3)\n\"²>0\"\n\n\n\n\n\n","category":"method"},{"location":"base/strings/#Base.Unicode.uppercase","page":"字符串","title":"Base.Unicode.uppercase","text":"uppercase(s::AbstractString)\n\nReturn s with all characters converted to uppercase.\n\nSee also lowercase, titlecase, uppercasefirst.\n\nExamples\n\njulia> uppercase(\"Julia\")\n\"JULIA\"\n\n\n\n\n\n","category":"function"},{"location":"base/strings/#Base.Unicode.lowercase","page":"字符串","title":"Base.Unicode.lowercase","text":"lowercase(s::AbstractString)\n\nReturn s with all characters converted to lowercase.\n\nSee also uppercase, titlecase, lowercasefirst.\n\nExamples\n\njulia> lowercase(\"STRINGS AND THINGS\")\n\"strings and things\"\n\n\n\n\n\n","category":"function"},{"location":"base/strings/#Base.Unicode.titlecase","page":"字符串","title":"Base.Unicode.titlecase","text":"titlecase(s::AbstractString; [wordsep::Function], strict::Bool=true) -> String\n\nCapitalize the first character of each word in s; if strict is true, every other character is converted to lowercase, otherwise they are left unchanged. By default, all non-letters beginning a new grapheme are considered as word separators; a predicate can be passed as the wordsep keyword to determine which characters should be considered as word separators. See also uppercasefirst to capitalize only the first character in s.\n\nSee also uppercase, lowercase, uppercasefirst.\n\nExamples\n\njulia> titlecase(\"the JULIA programming language\")\n\"The Julia Programming Language\"\n\njulia> titlecase(\"ISS - international space station\", strict=false)\n\"ISS - International Space Station\"\n\njulia> titlecase(\"a-a b-b\", wordsep = c->c==' ')\n\"A-a B-b\"\n\n\n\n\n\n","category":"function"},{"location":"base/strings/#Base.Unicode.uppercasefirst","page":"字符串","title":"Base.Unicode.uppercasefirst","text":"uppercasefirst(s::AbstractString) -> String\n\nReturn s with the first character converted to uppercase (technically \"title case\" for Unicode). See also titlecase to capitalize the first character of every word in s.\n\nSee also lowercasefirst, uppercase, lowercase, titlecase.\n\nExamples\n\njulia> uppercasefirst(\"python\")\n\"Python\"\n\n\n\n\n\n","category":"function"},{"location":"base/strings/#Base.Unicode.lowercasefirst","page":"字符串","title":"Base.Unicode.lowercasefirst","text":"lowercasefirst(s::AbstractString)\n\nReturn s with the first character converted to lowercase.\n\nSee also uppercasefirst, uppercase, lowercase, titlecase.\n\nExamples\n\njulia> lowercasefirst(\"Julia\")\n\"julia\"\n\n\n\n\n\n","category":"function"},{"location":"base/strings/#Base.join","page":"字符串","title":"Base.join","text":"join([io::IO,] iterator [, delim [, last]])\n\nJoin any iterator into a single string, inserting the given delimiter (if any) between adjacent items. If last is given, it will be used instead of delim between the last two items. Each item of iterator is converted to a string via print(io::IOBuffer, x). If io is given, the result is written to io rather than returned as a String.\n\nExamples\n\njulia> join([\"apples\", \"bananas\", \"pineapples\"], \", \", \" and \")\n\"apples, bananas and pineapples\"\n\njulia> join([1,2,3,4,5])\n\"12345\"\n\n\n\n\n\n","category":"function"},{"location":"base/strings/#Base.chop","page":"字符串","title":"Base.chop","text":"chop(s::AbstractString; head::Integer = 0, tail::Integer = 1)\n\nRemove the first head and the last tail characters from s. The call chop(s) removes the last character from s. If it is requested to remove more characters than length(s) then an empty string is returned.\n\nSee also chomp, startswith, first.\n\nExamples\n\njulia> a = \"March\"\n\"March\"\n\njulia> chop(a)\n\"Marc\"\n\njulia> chop(a, head = 1, tail = 2)\n\"ar\"\n\njulia> chop(a, head = 5, tail = 5)\n\"\"\n\n\n\n\n\n","category":"function"},{"location":"base/strings/#Base.chomp","page":"字符串","title":"Base.chomp","text":"chomp(s::AbstractString) -> SubString\n\nRemove a single trailing newline from a string.\n\nSee also chop.\n\nExamples\n\njulia> chomp(\"Hello\\n\")\n\"Hello\"\n\n\n\n\n\n","category":"function"},{"location":"base/strings/#Base.thisind","page":"字符串","title":"Base.thisind","text":"thisind(s::AbstractString, i::Integer) -> Int\n\nIf i is in bounds in s return the index of the start of the character whose encoding code unit i is part of. In other words, if i is the start of a character, return i; if i is not the start of a character, rewind until the start of a character and return that index. If i is equal to 0 or ncodeunits(s)+1 return i. In all other cases throw BoundsError.\n\nExamples\n\njulia> thisind(\"α\", 0)\n0\n\njulia> thisind(\"α\", 1)\n1\n\njulia> thisind(\"α\", 2)\n1\n\njulia> thisind(\"α\", 3)\n3\n\njulia> thisind(\"α\", 4)\nERROR: BoundsError: attempt to access 2-codeunit String at index [4]\n[...]\n\njulia> thisind(\"α\", -1)\nERROR: BoundsError: attempt to access 2-codeunit String at index [-1]\n[...]\n\n\n\n\n\n","category":"function"},{"location":"base/strings/#Base.nextind","page":"字符串","title":"Base.nextind","text":"nextind(str::AbstractString, i::Integer, n::Integer=1) -> Int\n\nCase n == 1\nIf i is in bounds in s return the index of the start of the character whose encoding starts after index i. In other words, if i is the start of a character, return the start of the next character; if i is not the start of a character, move forward until the start of a character and return that index. If i is equal to 0 return 1. If i is in bounds but greater or equal to lastindex(str) return ncodeunits(str)+1. Otherwise throw BoundsError.\nCase n > 1\nBehaves like applying n times nextind for n==1. The only difference is that if n is so large that applying nextind would reach ncodeunits(str)+1 then each remaining iteration increases the returned value by 1. This means that in this case nextind can return a value greater than ncodeunits(str)+1.\nCase n == 0\nReturn i only if i is a valid index in s or is equal to 0. Otherwise StringIndexError or BoundsError is thrown.\n\nExamples\n\njulia> nextind(\"α\", 0)\n1\n\njulia> nextind(\"α\", 1)\n3\n\njulia> nextind(\"α\", 3)\nERROR: BoundsError: attempt to access 2-codeunit String at index [3]\n[...]\n\njulia> nextind(\"α\", 0, 2)\n3\n\njulia> nextind(\"α\", 1, 2)\n4\n\n\n\n\n\n","category":"function"},{"location":"base/strings/#Base.prevind","page":"字符串","title":"Base.prevind","text":"prevind(str::AbstractString, i::Integer, n::Integer=1) -> Int\n\nCase n == 1\nIf i is in bounds in s return the index of the start of the character whose encoding starts before index i. In other words, if i is the start of a character, return the start of the previous character; if i is not the start of a character, rewind until the start of a character and return that index. If i is equal to 1 return 0. If i is equal to ncodeunits(str)+1 return lastindex(str). Otherwise throw BoundsError.\nCase n > 1\nBehaves like applying n times prevind for n==1. The only difference is that if n is so large that applying prevind would reach 0 then each remaining iteration decreases the returned value by 1. This means that in this case prevind can return a negative value.\nCase n == 0\nReturn i only if i is a valid index in str or is equal to ncodeunits(str)+1. Otherwise StringIndexError or BoundsError is thrown.\n\nExamples\n\njulia> prevind(\"α\", 3)\n1\n\njulia> prevind(\"α\", 1)\n0\n\njulia> prevind(\"α\", 0)\nERROR: BoundsError: attempt to access 2-codeunit String at index [0]\n[...]\n\njulia> prevind(\"α\", 2, 2)\n0\n\njulia> prevind(\"α\", 2, 3)\n-1\n\n\n\n\n\n","category":"function"},{"location":"base/strings/#Base.Unicode.textwidth","page":"字符串","title":"Base.Unicode.textwidth","text":"textwidth(c)\n\nGive the number of columns needed to print a character.\n\nExamples\n\njulia> textwidth('α')\n1\n\njulia> textwidth('⛵')\n2\n\n\n\n\n\ntextwidth(s::AbstractString)\n\nGive the number of columns needed to print a string.\n\nExamples\n\njulia> textwidth(\"March\")\n5\n\n\n\n\n\n","category":"function"},{"location":"base/strings/#Base.isascii","page":"字符串","title":"Base.isascii","text":"isascii(c::Union{AbstractChar,AbstractString}) -> Bool\n\nTest whether a character belongs to the ASCII character set, or whether this is true for all elements of a string.\n\nExamples\n\njulia> isascii('a')\ntrue\n\njulia> isascii('α')\nfalse\n\njulia> isascii(\"abc\")\ntrue\n\njulia> isascii(\"αβγ\")\nfalse\n\nFor example, isascii can be used as a predicate function for filter or replace to remove or replace non-ASCII characters, respectively:\n\njulia> filter(isascii, \"abcdeγfgh\") # discard non-ASCII chars\n\"abcdefgh\"\n\njulia> replace(\"abcdeγfgh\", !isascii=>' ') # replace non-ASCII chars with spaces\n\"abcde fgh\"\n\n\n\n\n\n","category":"function"},{"location":"base/strings/#Base.Unicode.iscntrl","page":"字符串","title":"Base.Unicode.iscntrl","text":"iscntrl(c::AbstractChar) -> Bool\n\nTests whether a character is a control character. Control characters are the non-printing characters of the Latin-1 subset of Unicode.\n\nExamples\n\njulia> iscntrl('\\x01')\ntrue\n\njulia> iscntrl('a')\nfalse\n\n\n\n\n\n","category":"function"},{"location":"base/strings/#Base.Unicode.isdigit","page":"字符串","title":"Base.Unicode.isdigit","text":"isdigit(c::AbstractChar) -> Bool\n\nTests whether a character is a decimal digit (0-9).\n\nExamples\n\njulia> isdigit('❤')\nfalse\n\njulia> isdigit('9')\ntrue\n\njulia> isdigit('α')\nfalse\n\n\n\n\n\n","category":"function"},{"location":"base/strings/#Base.Unicode.isletter","page":"字符串","title":"Base.Unicode.isletter","text":"isletter(c::AbstractChar) -> Bool\n\nTest whether a character is a letter. A character is classified as a letter if it belongs to the Unicode general category Letter, i.e. a character whose category code begins with 'L'.\n\nExamples\n\njulia> isletter('❤')\nfalse\n\njulia> isletter('α')\ntrue\n\njulia> isletter('9')\nfalse\n\n\n\n\n\n","category":"function"},{"location":"base/strings/#Base.Unicode.islowercase","page":"字符串","title":"Base.Unicode.islowercase","text":"islowercase(c::AbstractChar) -> Bool\n\nTests whether a character is a lowercase letter (according to the Unicode standard's Lowercase derived property).\n\nSee also isuppercase.\n\nExamples\n\njulia> islowercase('α')\ntrue\n\njulia> islowercase('Γ')\nfalse\n\njulia> islowercase('❤')\nfalse\n\n\n\n\n\n","category":"function"},{"location":"base/strings/#Base.Unicode.isnumeric","page":"字符串","title":"Base.Unicode.isnumeric","text":"isnumeric(c::AbstractChar) -> Bool\n\nTests whether a character is numeric. A character is classified as numeric if it belongs to the Unicode general category Number, i.e. a character whose category code begins with 'N'.\n\nNote that this broad category includes characters such as ¾ and ௰. Use isdigit to check whether a character a decimal digit between 0 and 9.\n\nExamples\n\njulia> isnumeric('௰')\ntrue\n\njulia> isnumeric('9')\ntrue\n\njulia> isnumeric('α')\nfalse\n\njulia> isnumeric('❤')\nfalse\n\n\n\n\n\n","category":"function"},{"location":"base/strings/#Base.Unicode.isprint","page":"字符串","title":"Base.Unicode.isprint","text":"isprint(c::AbstractChar) -> Bool\n\nTests whether a character is printable, including spaces, but not a control character.\n\nExamples\n\njulia> isprint('\\x01')\nfalse\n\njulia> isprint('A')\ntrue\n\n\n\n\n\n","category":"function"},{"location":"base/strings/#Base.Unicode.ispunct","page":"字符串","title":"Base.Unicode.ispunct","text":"ispunct(c::AbstractChar) -> Bool\n\nTests whether a character belongs to the Unicode general category Punctuation, i.e. a character whose category code begins with 'P'.\n\nExamples\n\njulia> ispunct('α')\nfalse\n\njulia> ispunct('/')\ntrue\n\njulia> ispunct(';')\ntrue\n\n\n\n\n\n","category":"function"},{"location":"base/strings/#Base.Unicode.isspace","page":"字符串","title":"Base.Unicode.isspace","text":"isspace(c::AbstractChar) -> Bool\n\nTests whether a character is any whitespace character. Includes ASCII characters '\\t', '\\n', '\\v', '\\f', '\\r', and ' ', Latin-1 character U+0085, and characters in Unicode category Zs.\n\nExamples\n\njulia> isspace('\\n')\ntrue\n\njulia> isspace('\\r')\ntrue\n\njulia> isspace(' ')\ntrue\n\njulia> isspace('\\x20')\ntrue\n\n\n\n\n\n","category":"function"},{"location":"base/strings/#Base.Unicode.isuppercase","page":"字符串","title":"Base.Unicode.isuppercase","text":"isuppercase(c::AbstractChar) -> Bool\n\nTests whether a character is an uppercase letter (according to the Unicode standard's Uppercase derived property).\n\nSee also islowercase.\n\nExamples\n\njulia> isuppercase('γ')\nfalse\n\njulia> isuppercase('Γ')\ntrue\n\njulia> isuppercase('❤')\nfalse\n\n\n\n\n\n","category":"function"},{"location":"base/strings/#Base.Unicode.isxdigit","page":"字符串","title":"Base.Unicode.isxdigit","text":"isxdigit(c::AbstractChar) -> Bool\n\nTest whether a character is a valid hexadecimal digit. Note that this does not include x (as in the standard 0x prefix).\n\nExamples\n\njulia> isxdigit('a')\ntrue\n\njulia> isxdigit('x')\nfalse\n\n\n\n\n\n","category":"function"},{"location":"base/strings/#Base.escape_string","page":"字符串","title":"Base.escape_string","text":"escape_string(str::AbstractString[, esc]; keep = ())::AbstractString\nescape_string(io, str::AbstractString[, esc]; keep = ())::Nothing\n\nGeneral escaping of traditional C and Unicode escape sequences. The first form returns the escaped string, the second prints the result to io.\n\nBackslashes (\\) are escaped with a double-backslash (\"\\\\\"). Non-printable characters are escaped either with their standard C escape codes, \"\\0\" for NUL (if unambiguous), unicode code point (\"\\u\" prefix) or hex (\"\\x\" prefix).\n\nThe optional esc argument specifies any additional characters that should also be escaped by a prepending backslash (\" is also escaped by default in the first form).\n\nThe argument keep specifies a collection of characters which are to be kept as they are. Notice that esc has precedence here.\n\nSee also unescape_string for the reverse operation.\n\ncompat: Julia 1.7\nThe keep argument is available as of Julia 1.7.\n\nExamples\n\njulia> escape_string(\"aaa\\nbbb\")\n\"aaa\\\\nbbb\"\n\njulia> escape_string(\"aaa\\nbbb\"; keep = '\\n')\n\"aaa\\nbbb\"\n\njulia> escape_string(\"\\xfe\\xff\") # invalid utf-8\n\"\\\\xfe\\\\xff\"\n\njulia> escape_string(string('\\u2135','\\0')) # unambiguous\n\"ℵ\\\\0\"\n\njulia> escape_string(string('\\u2135','\\0','0')) # \\0 would be ambiguous\n\"ℵ\\\\x000\"\n\n\n\n\n\n","category":"function"},{"location":"base/strings/#Base.unescape_string","page":"字符串","title":"Base.unescape_string","text":"unescape_string(str::AbstractString, keep = ())::AbstractString\nunescape_string(io, s::AbstractString, keep = ())::Nothing\n\nGeneral unescaping of traditional C and Unicode escape sequences. The first form returns the escaped string, the second prints the result to io. The argument keep specifies a collection of characters which (along with backlashes) are to be kept as they are.\n\nThe following escape sequences are recognised:\n\nEscaped backslash (\\\\)\nEscaped double-quote (\\\")\nStandard C escape sequences (\\a, \\b, \\t, \\n, \\v, \\f, \\r, \\e)\nUnicode BMP code points (\\u with 1-4 trailing hex digits)\nAll Unicode code points (\\U with 1-8 trailing hex digits; max value = 0010ffff)\nHex bytes (\\x with 1-2 trailing hex digits)\nOctal bytes (\\ with 1-3 trailing octal digits)\n\nSee also escape_string.\n\nExamples\n\njulia> unescape_string(\"aaa\\\\nbbb\") # C escape sequence\n\"aaa\\nbbb\"\n\njulia> unescape_string(\"\\\\u03c0\") # unicode\n\"π\"\n\njulia> unescape_string(\"\\\\101\") # octal\n\"A\"\n\njulia> unescape_string(\"aaa \\\\g \\\\n\", ['g']) # using `keep` argument\n\"aaa \\\\g \\n\"\n\n\n\n\n\n","category":"function"},{"location":"stdlib/Libdl/#动态链接器","page":"动态链接器","title":"动态链接器","text":"","category":"section"},{"location":"stdlib/Libdl/","page":"动态链接器","title":"动态链接器","text":"Libdl.dlopen\nLibdl.dlopen_e\nLibdl.RTLD_NOW\nLibdl.dlsym\nLibdl.dlsym_e\nLibdl.dlclose\nLibdl.dlext\nLibdl.dllist\nLibdl.dlpath\nLibdl.find_library\nLibdl.DL_LOAD_PATH","category":"page"},{"location":"stdlib/Libdl/#Base.Libc.Libdl.dlopen","page":"动态链接器","title":"Base.Libc.Libdl.dlopen","text":"dlopen(libfile::AbstractString [, flags::Integer]; throw_error:Bool = true)\n\nLoad a shared library, returning an opaque handle.\n\nThe extension given by the constant dlext (.so, .dll, or .dylib) can be omitted from the libfile string, as it is automatically appended if needed. If libfile is not an absolute path name, then the paths in the array DL_LOAD_PATH are searched for libfile, followed by the system load path.\n\nThe optional flags argument is a bitwise-or of zero or more of RTLD_LOCAL, RTLD_GLOBAL, RTLD_LAZY, RTLD_NOW, RTLD_NODELETE, RTLD_NOLOAD, RTLD_DEEPBIND, and RTLD_FIRST. These are converted to the corresponding flags of the POSIX (and/or GNU libc and/or MacOS) dlopen command, if possible, or are ignored if the specified functionality is not available on the current platform. The default flags are platform specific. On MacOS the default dlopen flags are RTLD_LAZY|RTLD_DEEPBIND|RTLD_GLOBAL while on other platforms the defaults are RTLD_LAZY|RTLD_DEEPBIND|RTLD_LOCAL. An important usage of these flags is to specify non default behavior for when the dynamic library loader binds library references to exported symbols and if the bound references are put into process local or global scope. For instance RTLD_LAZY|RTLD_DEEPBIND|RTLD_GLOBAL allows the library's symbols to be available for usage in other shared libraries, addressing situations where there are dependencies between shared libraries.\n\nIf the library cannot be found, this method throws an error, unless the keyword argument throw_error is set to false, in which case this method returns nothing.\n\nnote: Note\nFrom Julia 1.6 on, this method replaces paths starting with @executable_path/ with the path to the Julia executable, allowing for relocatable relative-path loads. In Julia 1.5 and earlier, this only worked on macOS.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/Libdl/#Base.Libc.Libdl.dlopen_e","page":"动态链接器","title":"Base.Libc.Libdl.dlopen_e","text":"dlopen_e(libfile::AbstractString [, flags::Integer])\n\nSimilar to dlopen, except returns C_NULL instead of raising errors. This method is now deprecated in favor of dlopen(libfile::AbstractString [, flags::Integer]; throw_error=false).\n\n\n\n\n\n","category":"function"},{"location":"stdlib/Libdl/#Base.Libc.Libdl.RTLD_NOW","page":"动态链接器","title":"Base.Libc.Libdl.RTLD_NOW","text":"RTLD_DEEPBIND\nRTLD_FIRST\nRTLD_GLOBAL\nRTLD_LAZY\nRTLD_LOCAL\nRTLD_NODELETE\nRTLD_NOLOAD\nRTLD_NOW\n\nEnum constant for dlopen. See your platform man page for details, if applicable.\n\n\n\n\n\n","category":"constant"},{"location":"stdlib/Libdl/#Base.Libc.Libdl.dlsym","page":"动态链接器","title":"Base.Libc.Libdl.dlsym","text":"dlsym(handle, sym; throw_error::Bool = true)\n\nLook up a symbol from a shared library handle, return callable function pointer on success.\n\nIf the symbol cannot be found, this method throws an error, unless the keyword argument throw_error is set to false, in which case this method returns nothing.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/Libdl/#Base.Libc.Libdl.dlsym_e","page":"动态链接器","title":"Base.Libc.Libdl.dlsym_e","text":"dlsym_e(handle, sym)\n\nLook up a symbol from a shared library handle, silently return C_NULL on lookup failure. This method is now deprecated in favor of dlsym(handle, sym; throw_error=false).\n\n\n\n\n\n","category":"function"},{"location":"stdlib/Libdl/#Base.Libc.Libdl.dlclose","page":"动态链接器","title":"Base.Libc.Libdl.dlclose","text":"dlclose(handle)\n\nClose shared library referenced by handle.\n\n\n\n\n\ndlclose(::Nothing)\n\nFor the very common pattern usage pattern of\n\ntry\n hdl = dlopen(library_name)\n ... do something\nfinally\n dlclose(hdl)\nend\n\nWe define a dlclose() method that accepts a parameter of type Nothing, so that user code does not have to change its behavior for the case that library_name was not found.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/Libdl/#Base.Libc.Libdl.dlext","page":"动态链接器","title":"Base.Libc.Libdl.dlext","text":"dlext\n\nFile extension for dynamic libraries (e.g. dll, dylib, so) on the current platform.\n\n\n\n\n\n","category":"constant"},{"location":"stdlib/Libdl/#Base.Libc.Libdl.dllist","page":"动态链接器","title":"Base.Libc.Libdl.dllist","text":"dllist()\n\nReturn the paths of dynamic libraries currently loaded in a Vector{String}.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/Libdl/#Base.Libc.Libdl.dlpath","page":"动态链接器","title":"Base.Libc.Libdl.dlpath","text":"dlpath(handle::Ptr{Cvoid})\n\nGiven a library handle from dlopen, return the full path.\n\n\n\n\n\ndlpath(libname::Union{AbstractString, Symbol})\n\nGet the full path of the library libname.\n\nExample\n\njulia> dlpath(\"libjulia\")\n\n\n\n\n\n","category":"function"},{"location":"stdlib/Libdl/#Base.Libc.Libdl.find_library","page":"动态链接器","title":"Base.Libc.Libdl.find_library","text":"find_library(names, locations)\n\nSearches for the first library in names in the paths in the locations list, DL_LOAD_PATH, or system library paths (in that order) which can successfully be dlopen'd. On success, the return value will be one of the names (potentially prefixed by one of the paths in locations). This string can be assigned to a global const and used as the library name in future ccall's. On failure, it returns the empty string.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/Libdl/#Base.DL_LOAD_PATH","page":"动态链接器","title":"Base.DL_LOAD_PATH","text":"DL_LOAD_PATH\n\nWhen calling dlopen, the paths in this list will be searched first, in order, before searching the system locations for a valid library handle.\n\n\n\n\n\n","category":"constant"},{"location":"base/arrays/#lib-arrays","page":"数组","title":"数组","text":"","category":"section"},{"location":"base/arrays/#构造函数与类型","page":"数组","title":"构造函数与类型","text":"","category":"section"},{"location":"base/arrays/","page":"数组","title":"数组","text":"Core.AbstractArray\nBase.AbstractVector\nBase.AbstractMatrix\nBase.AbstractVecOrMat\nCore.Array\nCore.Array(::UndefInitializer, ::Any)\nCore.Array(::Nothing, ::Any)\nCore.Array(::Missing, ::Any)\nCore.UndefInitializer\nCore.undef\nBase.Vector\nBase.Vector(::UndefInitializer, ::Any)\nBase.Vector(::Nothing, ::Any)\nBase.Vector(::Missing, ::Any)\nBase.Matrix\nBase.Matrix(::UndefInitializer, ::Any, ::Any)\nBase.Matrix(::Nothing, ::Any, ::Any)\nBase.Matrix(::Missing, ::Any, ::Any)\nBase.VecOrMat\nCore.DenseArray\nBase.DenseVector\nBase.DenseMatrix\nBase.DenseVecOrMat\nBase.StridedArray\nBase.StridedVector\nBase.StridedMatrix\nBase.StridedVecOrMat\nBase.getindex(::Type, ::Any...)\nBase.zeros\nBase.ones\nBase.BitArray\nBase.BitArray(::UndefInitializer, ::Integer...)\nBase.BitArray(::Any)\nBase.trues\nBase.falses\nBase.fill\nBase.fill!\nBase.empty\nBase.similar","category":"page"},{"location":"base/arrays/#Core.AbstractArray","page":"数组","title":"Core.AbstractArray","text":"AbstractArray{T,N}\n\nSupertype for N-dimensional arrays (or array-like types) with elements of type T. Array and other types are subtypes of this. See the manual section on the AbstractArray interface.\n\nSee also: AbstractVector, AbstractMatrix, eltype, ndims.\n\n\n\n\n\n","category":"type"},{"location":"base/arrays/#Base.AbstractVector","page":"数组","title":"Base.AbstractVector","text":"AbstractVector{T}\n\nSupertype for one-dimensional arrays (or array-like types) with elements of type T. Alias for AbstractArray{T,1}.\n\n\n\n\n\n","category":"type"},{"location":"base/arrays/#Base.AbstractMatrix","page":"数组","title":"Base.AbstractMatrix","text":"AbstractMatrix{T}\n\nSupertype for two-dimensional arrays (or array-like types) with elements of type T. Alias for AbstractArray{T,2}.\n\n\n\n\n\n","category":"type"},{"location":"base/arrays/#Base.AbstractVecOrMat","page":"数组","title":"Base.AbstractVecOrMat","text":"AbstractVecOrMat{T}\n\nUnion type of AbstractVector{T} and AbstractMatrix{T}.\n\n\n\n\n\n","category":"type"},{"location":"base/arrays/#Core.Array","page":"数组","title":"Core.Array","text":"Array{T,N} <: AbstractArray{T,N}\n\nN-dimensional dense array with elements of type T.\n\n\n\n\n\n","category":"type"},{"location":"base/arrays/#Core.Array-Tuple{UndefInitializer, Any}","page":"数组","title":"Core.Array","text":"Array{T}(undef, dims)\nArray{T,N}(undef, dims)\n\nConstruct an uninitialized N-dimensional Array containing elements of type T. N can either be supplied explicitly, as in Array{T,N}(undef, dims), or be determined by the length or number of dims. dims may be a tuple or a series of integer arguments corresponding to the lengths in each dimension. If the rank N is supplied explicitly, then it must match the length or number of dims. Here undef is the UndefInitializer.\n\nExamples\n\njulia> A = Array{Float64, 2}(undef, 2, 3) # N given explicitly\n2×3 Matrix{Float64}:\n 6.90198e-310 6.90198e-310 6.90198e-310\n 6.90198e-310 6.90198e-310 0.0\n\njulia> B = Array{Float64}(undef, 4) # N determined by the input\n4-element Vector{Float64}:\n 2.360075077e-314\n NaN\n 2.2671131793e-314\n 2.299821756e-314\n\njulia> similar(B, 2, 4, 1) # use typeof(B), and the given size\n2×4×1 Array{Float64, 3}:\n[:, :, 1] =\n 2.26703e-314 2.26708e-314 0.0 2.80997e-314\n 0.0 2.26703e-314 2.26708e-314 0.0\n\n\n\n\n\n","category":"method"},{"location":"base/arrays/#Core.Array-Tuple{Nothing, Any}","page":"数组","title":"Core.Array","text":"Array{T}(nothing, dims)\nArray{T,N}(nothing, dims)\n\nConstruct an N-dimensional Array containing elements of type T, initialized with nothing entries. Element type T must be able to hold these values, i.e. Nothing <: T.\n\nExamples\n\njulia> Array{Union{Nothing, String}}(nothing, 2)\n2-element Vector{Union{Nothing, String}}:\n nothing\n nothing\n\njulia> Array{Union{Nothing, Int}}(nothing, 2, 3)\n2×3 Matrix{Union{Nothing, Int64}}:\n nothing nothing nothing\n nothing nothing nothing\n\n\n\n\n\n","category":"method"},{"location":"base/arrays/#Core.Array-Tuple{Missing, Any}","page":"数组","title":"Core.Array","text":"Array{T}(missing, dims)\nArray{T,N}(missing, dims)\n\nConstruct an N-dimensional Array containing elements of type T, initialized with missing entries. Element type T must be able to hold these values, i.e. Missing <: T.\n\nExamples\n\njulia> Array{Union{Missing, String}}(missing, 2)\n2-element Vector{Union{Missing, String}}:\n missing\n missing\n\njulia> Array{Union{Missing, Int}}(missing, 2, 3)\n2×3 Matrix{Union{Missing, Int64}}:\n missing missing missing\n missing missing missing\n\n\n\n\n\n","category":"method"},{"location":"base/arrays/#Core.UndefInitializer","page":"数组","title":"Core.UndefInitializer","text":"UndefInitializer\n\nSingleton type used in array initialization, indicating the array-constructor-caller would like an uninitialized array. See also undef, an alias for UndefInitializer().\n\nExamples\n\njulia> Array{Float64, 1}(UndefInitializer(), 3)\n3-element Array{Float64, 1}:\n 2.2752528595e-314\n 2.202942107e-314\n 2.275252907e-314\n\n\n\n\n\n","category":"type"},{"location":"base/arrays/#Core.undef","page":"数组","title":"Core.undef","text":"undef\n\nAlias for UndefInitializer(), which constructs an instance of the singleton type UndefInitializer, used in array initialization to indicate the array-constructor-caller would like an uninitialized array.\n\nSee also: missing, similar.\n\nExamples\n\njulia> Array{Float64, 1}(undef, 3)\n3-element Vector{Float64}:\n 2.2752528595e-314\n 2.202942107e-314\n 2.275252907e-314\n\n\n\n\n\n","category":"constant"},{"location":"base/arrays/#Base.Vector","page":"数组","title":"Base.Vector","text":"Vector{T} <: AbstractVector{T}\n\nOne-dimensional dense array with elements of type T, often used to represent a mathematical vector. Alias for Array{T,1}.\n\nSee also empty, similar and zero for creating vectors.\n\n\n\n\n\n","category":"type"},{"location":"base/arrays/#Base.Vector-Tuple{UndefInitializer, Any}","page":"数组","title":"Base.Vector","text":"Vector{T}(undef, n)\n\nConstruct an uninitialized Vector{T} of length n.\n\nExamples\n\njulia> Vector{Float64}(undef, 3)\n3-element Array{Float64, 1}:\n 6.90966e-310\n 6.90966e-310\n 6.90966e-310\n\n\n\n\n\n","category":"method"},{"location":"base/arrays/#Base.Vector-Tuple{Nothing, Any}","page":"数组","title":"Base.Vector","text":"Vector{T}(nothing, m)\n\nConstruct a Vector{T} of length m, initialized with nothing entries. Element type T must be able to hold these values, i.e. Nothing <: T.\n\nExamples\n\njulia> Vector{Union{Nothing, String}}(nothing, 2)\n2-element Vector{Union{Nothing, String}}:\n nothing\n nothing\n\n\n\n\n\n","category":"method"},{"location":"base/arrays/#Base.Vector-Tuple{Missing, Any}","page":"数组","title":"Base.Vector","text":"Vector{T}(missing, m)\n\nConstruct a Vector{T} of length m, initialized with missing entries. Element type T must be able to hold these values, i.e. Missing <: T.\n\nExamples\n\njulia> Vector{Union{Missing, String}}(missing, 2)\n2-element Vector{Union{Missing, String}}:\n missing\n missing\n\n\n\n\n\n","category":"method"},{"location":"base/arrays/#Base.Matrix","page":"数组","title":"Base.Matrix","text":"Matrix{T} <: AbstractMatrix{T}\n\nTwo-dimensional dense array with elements of type T, often used to represent a mathematical matrix. Alias for Array{T,2}.\n\nSee also fill, zeros, undef and similar for creating matrices.\n\n\n\n\n\n","category":"type"},{"location":"base/arrays/#Base.Matrix-Tuple{UndefInitializer, Any, Any}","page":"数组","title":"Base.Matrix","text":"Matrix{T}(undef, m, n)\n\nConstruct an uninitialized Matrix{T} of size m×n.\n\nExamples\n\njulia> Matrix{Float64}(undef, 2, 3)\n2×3 Array{Float64, 2}:\n 2.36365e-314 2.28473e-314 5.0e-324\n 2.26704e-314 2.26711e-314 NaN\n\njulia> similar(ans, Int32, 2, 2)\n2×2 Matrix{Int32}:\n 490537216 1277177453\n 1 1936748399\n\n\n\n\n\n","category":"method"},{"location":"base/arrays/#Base.Matrix-Tuple{Nothing, Any, Any}","page":"数组","title":"Base.Matrix","text":"Matrix{T}(nothing, m, n)\n\nConstruct a Matrix{T} of size m×n, initialized with nothing entries. Element type T must be able to hold these values, i.e. Nothing <: T.\n\nExamples\n\njulia> Matrix{Union{Nothing, String}}(nothing, 2, 3)\n2×3 Matrix{Union{Nothing, String}}:\n nothing nothing nothing\n nothing nothing nothing\n\n\n\n\n\n","category":"method"},{"location":"base/arrays/#Base.Matrix-Tuple{Missing, Any, Any}","page":"数组","title":"Base.Matrix","text":"Matrix{T}(missing, m, n)\n\nConstruct a Matrix{T} of size m×n, initialized with missing entries. Element type T must be able to hold these values, i.e. Missing <: T.\n\nExamples\n\njulia> Matrix{Union{Missing, String}}(missing, 2, 3)\n2×3 Matrix{Union{Missing, String}}:\n missing missing missing\n missing missing missing\n\n\n\n\n\n","category":"method"},{"location":"base/arrays/#Base.VecOrMat","page":"数组","title":"Base.VecOrMat","text":"VecOrMat{T}\n\nUnion type of Vector{T} and Matrix{T} which allows functions to accept either a Matrix or a Vector.\n\nExamples\n\njulia> Vector{Float64} <: VecOrMat{Float64}\ntrue\n\njulia> Matrix{Float64} <: VecOrMat{Float64}\ntrue\n\njulia> Array{Float64, 3} <: VecOrMat{Float64}\nfalse\n\n\n\n\n\n","category":"type"},{"location":"base/arrays/#Core.DenseArray","page":"数组","title":"Core.DenseArray","text":"DenseArray{T, N} <: AbstractArray{T,N}\n\nN-dimensional dense array with elements of type T. The elements of a dense array are stored contiguously in memory.\n\n\n\n\n\n","category":"type"},{"location":"base/arrays/#Base.DenseVector","page":"数组","title":"Base.DenseVector","text":"DenseVector{T}\n\nOne-dimensional DenseArray with elements of type T. Alias for DenseArray{T,1}.\n\n\n\n\n\n","category":"type"},{"location":"base/arrays/#Base.DenseMatrix","page":"数组","title":"Base.DenseMatrix","text":"DenseMatrix{T}\n\nTwo-dimensional DenseArray with elements of type T. Alias for DenseArray{T,2}.\n\n\n\n\n\n","category":"type"},{"location":"base/arrays/#Base.DenseVecOrMat","page":"数组","title":"Base.DenseVecOrMat","text":"DenseVecOrMat{T}\n\nUnion type of DenseVector{T} and DenseMatrix{T}.\n\n\n\n\n\n","category":"type"},{"location":"base/arrays/#Base.StridedArray","page":"数组","title":"Base.StridedArray","text":"StridedArray{T, N}\n\nA hard-coded Union of common array types that follow the strided array interface, with elements of type T and N dimensions.\n\nIf A is a StridedArray, then its elements are stored in memory with offsets, which may vary between dimensions but are constant within a dimension. For example, A could have stride 2 in dimension 1, and stride 3 in dimension 2. Incrementing A along dimension d jumps in memory by [strides(A, d)] slots. Strided arrays are particularly important and useful because they can sometimes be passed directly as pointers to foreign language libraries like BLAS.\n\n\n\n\n\n","category":"type"},{"location":"base/arrays/#Base.StridedVector","page":"数组","title":"Base.StridedVector","text":"StridedVector{T}\n\nOne dimensional StridedArray with elements of type T.\n\n\n\n\n\n","category":"type"},{"location":"base/arrays/#Base.StridedMatrix","page":"数组","title":"Base.StridedMatrix","text":"StridedMatrix{T}\n\nTwo dimensional StridedArray with elements of type T.\n\n\n\n\n\n","category":"type"},{"location":"base/arrays/#Base.StridedVecOrMat","page":"数组","title":"Base.StridedVecOrMat","text":"StridedVecOrMat{T}\n\nUnion type of StridedVector and StridedMatrix with elements of type T.\n\n\n\n\n\n","category":"type"},{"location":"base/arrays/#Base.getindex-Tuple{Type, Vararg{Any}}","page":"数组","title":"Base.getindex","text":"getindex(type[, elements...])\n\nConstruct a 1-d array of the specified type. This is usually called with the syntax Type[]. Element values can be specified using Type[a,b,c,...].\n\nExamples\n\njulia> Int8[1, 2, 3]\n3-element Vector{Int8}:\n 1\n 2\n 3\n\njulia> getindex(Int8, 1, 2, 3)\n3-element Vector{Int8}:\n 1\n 2\n 3\n\n\n\n\n\n","category":"method"},{"location":"base/arrays/#Base.zeros","page":"数组","title":"Base.zeros","text":"zeros([T=Float64,] dims::Tuple)\nzeros([T=Float64,] dims...)\n\nCreate an Array, with element type T, of all zeros with size specified by dims. See also fill, ones, zero.\n\nExamples\n\njulia> zeros(1)\n1-element Vector{Float64}:\n 0.0\n\njulia> zeros(Int8, 2, 3)\n2×3 Matrix{Int8}:\n 0 0 0\n 0 0 0\n\n\n\n\n\n","category":"function"},{"location":"base/arrays/#Base.ones","page":"数组","title":"Base.ones","text":"ones([T=Float64,] dims::Tuple)\nones([T=Float64,] dims...)\n\nCreate an Array, with element type T, of all ones with size specified by dims. See also fill, zeros.\n\nExamples\n\njulia> ones(1,2)\n1×2 Matrix{Float64}:\n 1.0 1.0\n\njulia> ones(ComplexF64, 2, 3)\n2×3 Matrix{ComplexF64}:\n 1.0+0.0im 1.0+0.0im 1.0+0.0im\n 1.0+0.0im 1.0+0.0im 1.0+0.0im\n\n\n\n\n\n","category":"function"},{"location":"base/arrays/#Base.BitArray","page":"数组","title":"Base.BitArray","text":"BitArray{N} <: AbstractArray{Bool, N}\n\nSpace-efficient N-dimensional boolean array, using just one bit for each boolean value.\n\nBitArrays pack up to 64 values into every 8 bytes, resulting in an 8x space efficiency over Array{Bool, N} and allowing some operations to work on 64 values at once.\n\nBy default, Julia returns BitArrays from broadcasting operations that generate boolean elements (including dotted-comparisons like .==) as well as from the functions trues and falses.\n\nnote: Note\nDue to its packed storage format, concurrent access to the elements of a BitArray where at least one of them is a write is not thread safe.\n\n\n\n\n\n","category":"type"},{"location":"base/arrays/#Base.BitArray-Tuple{UndefInitializer, Vararg{Integer}}","page":"数组","title":"Base.BitArray","text":"BitArray(undef, dims::Integer...)\nBitArray{N}(undef, dims::NTuple{N,Int})\n\nConstruct an undef BitArray with the given dimensions. Behaves identically to the Array constructor. See undef.\n\nExamples\n\njulia> BitArray(undef, 2, 2)\n2×2 BitMatrix:\n 0 0\n 0 0\n\njulia> BitArray(undef, (3, 1))\n3×1 BitMatrix:\n 0\n 0\n 0\n\n\n\n\n\n","category":"method"},{"location":"base/arrays/#Base.BitArray-Tuple{Any}","page":"数组","title":"Base.BitArray","text":"BitArray(itr)\n\nConstruct a BitArray generated by the given iterable object. The shape is inferred from the itr object.\n\nExamples\n\njulia> BitArray([1 0; 0 1])\n2×2 BitMatrix:\n 1 0\n 0 1\n\njulia> BitArray(x+y == 3 for x = 1:2, y = 1:3)\n2×3 BitMatrix:\n 0 1 0\n 1 0 0\n\njulia> BitArray(x+y == 3 for x = 1:2 for y = 1:3)\n6-element BitVector:\n 0\n 1\n 0\n 1\n 0\n 0\n\n\n\n\n\n","category":"method"},{"location":"base/arrays/#Base.trues","page":"数组","title":"Base.trues","text":"trues(dims)\n\nCreate a BitArray with all values set to true.\n\nExamples\n\njulia> trues(2,3)\n2×3 BitMatrix:\n 1 1 1\n 1 1 1\n\n\n\n\n\n","category":"function"},{"location":"base/arrays/#Base.falses","page":"数组","title":"Base.falses","text":"falses(dims)\n\nCreate a BitArray with all values set to false.\n\nExamples\n\njulia> falses(2,3)\n2×3 BitMatrix:\n 0 0 0\n 0 0 0\n\n\n\n\n\n","category":"function"},{"location":"base/arrays/#Base.fill","page":"数组","title":"Base.fill","text":"fill(value, dims::Tuple)\nfill(value, dims...)\n\nCreate an array of size dims with every location set to value.\n\nFor example, fill(1.0, (5,5)) returns a 5×5 array of floats, with 1.0 in every location of the array.\n\nThe dimension lengths dims may be specified as either a tuple or a sequence of arguments. An N-length tuple or N arguments following the value specify an N-dimensional array. Thus, a common idiom for creating a zero-dimensional array with its only location set to x is fill(x).\n\nEvery location of the returned array is set to (and is thus === to) the value that was passed; this means that if the value is itself modified, all elements of the filled array will reflect that modification because they're still that very value. This is of no concern with fill(1.0, (5,5)) as the value 1.0 is immutable and cannot itself be modified, but can be unexpected with mutable values like — most commonly — arrays. For example, fill([], 3) places the very same empty array in all three locations of the returned vector:\n\njulia> v = fill([], 3)\n3-element Vector{Vector{Any}}:\n []\n []\n []\n\njulia> v[1] === v[2] === v[3]\ntrue\n\njulia> value = v[1]\nAny[]\n\njulia> push!(value, 867_5309)\n1-element Vector{Any}:\n 8675309\n\njulia> v\n3-element Vector{Vector{Any}}:\n [8675309]\n [8675309]\n [8675309]\n\nTo create an array of many independent inner arrays, use a comprehension instead. This creates a new and distinct array on each iteration of the loop:\n\njulia> v2 = [[] for _ in 1:3]\n3-element Vector{Vector{Any}}:\n []\n []\n []\n\njulia> v2[1] === v2[2] === v2[3]\nfalse\n\njulia> push!(v2[1], 8675309)\n1-element Vector{Any}:\n 8675309\n\njulia> v2\n3-element Vector{Vector{Any}}:\n [8675309]\n []\n []\n\nSee also: fill!, zeros, ones, similar.\n\nExamples\n\njulia> fill(1.0, (2,3))\n2×3 Matrix{Float64}:\n 1.0 1.0 1.0\n 1.0 1.0 1.0\n\njulia> fill(42)\n0-dimensional Array{Int64, 0}:\n42\n\njulia> A = fill(zeros(2), 2) # sets both elements to the same [0.0, 0.0] vector\n2-element Vector{Vector{Float64}}:\n [0.0, 0.0]\n [0.0, 0.0]\n\njulia> A[1][1] = 42; # modifies the filled value to be [42.0, 0.0]\n\njulia> A # both A[1] and A[2] are the very same vector\n2-element Vector{Vector{Float64}}:\n [42.0, 0.0]\n [42.0, 0.0]\n\n\n\n\n\n","category":"function"},{"location":"base/arrays/#Base.fill!","page":"数组","title":"Base.fill!","text":"fill!(A, x)\n\nFill array A with the value x. If x is an object reference, all elements will refer to the same object. fill!(A, Foo()) will return A filled with the result of evaluating Foo() once.\n\nExamples\n\njulia> A = zeros(2,3)\n2×3 Matrix{Float64}:\n 0.0 0.0 0.0\n 0.0 0.0 0.0\n\njulia> fill!(A, 2.)\n2×3 Matrix{Float64}:\n 2.0 2.0 2.0\n 2.0 2.0 2.0\n\njulia> a = [1, 1, 1]; A = fill!(Vector{Vector{Int}}(undef, 3), a); a[1] = 2; A\n3-element Vector{Vector{Int64}}:\n [2, 1, 1]\n [2, 1, 1]\n [2, 1, 1]\n\njulia> x = 0; f() = (global x += 1; x); fill!(Vector{Int}(undef, 3), f())\n3-element Vector{Int64}:\n 1\n 1\n 1\n\n\n\n\n\n","category":"function"},{"location":"base/arrays/#Base.empty","page":"数组","title":"Base.empty","text":"empty(x::Tuple)\n\nReturns an empty tuple, ().\n\n\n\n\n\nempty(v::AbstractVector, [eltype])\n\nCreate an empty vector similar to v, optionally changing the eltype.\n\nSee also: empty!, isempty, isassigned.\n\nExamples\n\njulia> empty([1.0, 2.0, 3.0])\nFloat64[]\n\njulia> empty([1.0, 2.0, 3.0], String)\nString[]\n\n\n\n\n\nempty(a::AbstractDict, [index_type=keytype(a)], [value_type=valtype(a)])\n\nCreate an empty AbstractDict container which can accept indices of type index_type and values of type value_type. The second and third arguments are optional and default to the input's keytype and valtype, respectively. (If only one of the two types is specified, it is assumed to be the value_type, and the index_type we default to keytype(a)).\n\nCustom AbstractDict subtypes may choose which specific dictionary type is best suited to return for the given index and value types, by specializing on the three-argument signature. The default is to return an empty Dict.\n\n\n\n\n\n","category":"function"},{"location":"base/arrays/#Base.similar","page":"数组","title":"Base.similar","text":"similar(array, [element_type=eltype(array)], [dims=size(array)])\n\nCreate an uninitialized mutable array with the given element type and size, based upon the given source array. The second and third arguments are both optional, defaulting to the given array's eltype and size. The dimensions may be specified either as a single tuple argument or as a series of integer arguments.\n\nCustom AbstractArray subtypes may choose which specific array type is best-suited to return for the given element type and dimensionality. If they do not specialize this method, the default is an Array{element_type}(undef, dims...).\n\nFor example, similar(1:10, 1, 4) returns an uninitialized Array{Int,2} since ranges are neither mutable nor support 2 dimensions:\n\njulia> similar(1:10, 1, 4)\n1×4 Matrix{Int64}:\n 4419743872 4374413872 4419743888 0\n\nConversely, similar(trues(10,10), 2) returns an uninitialized BitVector with two elements since BitArrays are both mutable and can support 1-dimensional arrays:\n\njulia> similar(trues(10,10), 2)\n2-element BitVector:\n 0\n 0\n\nSince BitArrays can only store elements of type Bool, however, if you request a different element type it will create a regular Array instead:\n\njulia> similar(falses(10), Float64, 2, 4)\n2×4 Matrix{Float64}:\n 2.18425e-314 2.18425e-314 2.18425e-314 2.18425e-314\n 2.18425e-314 2.18425e-314 2.18425e-314 2.18425e-314\n\nSee also: undef, isassigned.\n\n\n\n\n\nsimilar(storagetype, axes)\n\nCreate an uninitialized mutable array analogous to that specified by storagetype, but with axes specified by the last argument.\n\nExamples:\n\nsimilar(Array{Int}, axes(A))\n\ncreates an array that \"acts like\" an Array{Int} (and might indeed be backed by one), but which is indexed identically to A. If A has conventional indexing, this will be identical to Array{Int}(undef, size(A)), but if A has unconventional indexing then the indices of the result will match A.\n\nsimilar(BitArray, (axes(A, 2),))\n\nwould create a 1-dimensional logical array whose indices match those of the columns of A.\n\n\n\n\n\n","category":"function"},{"location":"base/arrays/#基础函数","page":"数组","title":"基础函数","text":"","category":"section"},{"location":"base/arrays/","page":"数组","title":"数组","text":"Base.ndims\nBase.size\nBase.axes(::Any)\nBase.axes(::AbstractArray, ::Any)\nBase.length(::AbstractArray)\nBase.keys(::AbstractArray)\nBase.eachindex\nBase.IndexStyle\nBase.IndexLinear\nBase.IndexCartesian\nBase.conj!\nBase.stride\nBase.strides","category":"page"},{"location":"base/arrays/#Base.ndims","page":"数组","title":"Base.ndims","text":"ndims(A::AbstractArray) -> Integer\n\nReturn the number of dimensions of A.\n\nSee also: size, axes.\n\nExamples\n\njulia> A = fill(1, (3,4,5));\n\njulia> ndims(A)\n3\n\n\n\n\n\n","category":"function"},{"location":"base/arrays/#Base.size","page":"数组","title":"Base.size","text":"size(A::AbstractArray, [dim])\n\nReturn a tuple containing the dimensions of A. Optionally you can specify a dimension to just get the length of that dimension.\n\nNote that size may not be defined for arrays with non-standard indices, in which case axes may be useful. See the manual chapter on arrays with custom indices.\n\nSee also: length, ndims, eachindex, sizeof.\n\nExamples\n\njulia> A = fill(1, (2,3,4));\n\njulia> size(A)\n(2, 3, 4)\n\njulia> size(A, 2)\n3\n\n\n\n\n\n","category":"function"},{"location":"base/arrays/#Base.axes-Tuple{Any}","page":"数组","title":"Base.axes","text":"axes(A)\n\nReturn the tuple of valid indices for array A.\n\nSee also: size, keys, eachindex.\n\nExamples\n\njulia> A = fill(1, (5,6,7));\n\njulia> axes(A)\n(Base.OneTo(5), Base.OneTo(6), Base.OneTo(7))\n\n\n\n\n\n","category":"method"},{"location":"base/arrays/#Base.axes-Tuple{AbstractArray, Any}","page":"数组","title":"Base.axes","text":"axes(A, d)\n\nReturn the valid range of indices for array A along dimension d.\n\nSee also size, and the manual chapter on arrays with custom indices.\n\nExamples\n\njulia> A = fill(1, (5,6,7));\n\njulia> axes(A, 2)\nBase.OneTo(6)\n\nUsage note\n\nEach of the indices has to be an AbstractUnitRange{<:Integer}, but at the same time can be a type that uses custom indices. So, for example, if you need a subset, use generalized indexing constructs like begin/end or firstindex/lastindex:\n\nix = axes(v, 1)\nix[2:end] # will work for eg Vector, but may fail in general\nix[(begin+1):end] # works for generalized indexes\n\n\n\n\n\n","category":"method"},{"location":"base/arrays/#Base.length-Tuple{AbstractArray}","page":"数组","title":"Base.length","text":"length(A::AbstractArray)\n\nReturn the number of elements in the array, defaults to prod(size(A)).\n\nExamples\n\njulia> length([1, 2, 3, 4])\n4\n\njulia> length([1 2; 3 4])\n4\n\n\n\n\n\n","category":"method"},{"location":"base/arrays/#Base.keys-Tuple{AbstractArray}","page":"数组","title":"Base.keys","text":"keys(a::AbstractArray)\n\nReturn an efficient array describing all valid indices for a arranged in the shape of a itself.\n\nThey keys of 1-dimensional arrays (vectors) are integers, whereas all other N-dimensional arrays use CartesianIndex to describe their locations. Often the special array types LinearIndices and CartesianIndices are used to efficiently represent these arrays of integers and CartesianIndexes, respectively.\n\nNote that the keys of an array might not be the most efficient index type; for maximum performance use eachindex instead.\n\n\n\n\n\n","category":"method"},{"location":"base/arrays/#Base.eachindex","page":"数组","title":"Base.eachindex","text":"eachindex(A...)\n\nCreate an iterable object for visiting each index of an AbstractArray A in an efficient manner. For array types that have opted into fast linear indexing (like Array), this is simply the range 1:length(A). For other array types, return a specialized Cartesian range to efficiently index into the array with indices specified for every dimension. For other iterables, including strings and dictionaries, return an iterator object supporting arbitrary index types (e.g. unevenly spaced or non-integer indices).\n\nIf you supply more than one AbstractArray argument, eachindex will create an iterable object that is fast for all arguments (a UnitRange if all inputs have fast linear indexing, a CartesianIndices otherwise). If the arrays have different sizes and/or dimensionalities, a DimensionMismatch exception will be thrown.\n\nExamples\n\njulia> A = [1 2; 3 4];\n\njulia> for i in eachindex(A) # linear indexing\n println(i)\n end\n1\n2\n3\n4\n\njulia> for i in eachindex(view(A, 1:2, 1:1)) # Cartesian indexing\n println(i)\n end\nCartesianIndex(1, 1)\nCartesianIndex(2, 1)\n\n\n\n\n\n","category":"function"},{"location":"base/arrays/#Base.IndexStyle","page":"数组","title":"Base.IndexStyle","text":"IndexStyle(A)\nIndexStyle(typeof(A))\n\nIndexStyle specifies the \"native indexing style\" for array A. When you define a new AbstractArray type, you can choose to implement either linear indexing (with IndexLinear) or cartesian indexing. If you decide to only implement linear indexing, then you must set this trait for your array type:\n\nBase.IndexStyle(::Type{<:MyArray}) = IndexLinear()\n\nThe default is IndexCartesian().\n\nJulia's internal indexing machinery will automatically (and invisibly) recompute all indexing operations into the preferred style. This allows users to access elements of your array using any indexing style, even when explicit methods have not been provided.\n\nIf you define both styles of indexing for your AbstractArray, this trait can be used to select the most performant indexing style. Some methods check this trait on their inputs, and dispatch to different algorithms depending on the most efficient access pattern. In particular, eachindex creates an iterator whose type depends on the setting of this trait.\n\n\n\n\n\n","category":"type"},{"location":"base/arrays/#Base.IndexLinear","page":"数组","title":"Base.IndexLinear","text":"IndexLinear()\n\nSubtype of IndexStyle used to describe arrays which are optimally indexed by one linear index.\n\nA linear indexing style uses one integer index to describe the position in the array (even if it's a multidimensional array) and column-major ordering is used to efficiently access the elements. This means that requesting eachindex from an array that is IndexLinear will return a simple one-dimensional range, even if it is multidimensional.\n\nA custom array that reports its IndexStyle as IndexLinear only needs to implement indexing (and indexed assignment) with a single Int index; all other indexing expressions — including multidimensional accesses — will be recomputed to the linear index. For example, if A were a 2×3 custom matrix with linear indexing, and we referenced A[1, 3], this would be recomputed to the equivalent linear index and call A[5] since 2*1 + 3 = 5.\n\nSee also IndexCartesian.\n\n\n\n\n\n","category":"type"},{"location":"base/arrays/#Base.IndexCartesian","page":"数组","title":"Base.IndexCartesian","text":"IndexCartesian()\n\nSubtype of IndexStyle used to describe arrays which are optimally indexed by a Cartesian index. This is the default for new custom AbstractArray subtypes.\n\nA Cartesian indexing style uses multiple integer indices to describe the position in a multidimensional array, with exactly one index per dimension. This means that requesting eachindex from an array that is IndexCartesian will return a range of CartesianIndices.\n\nA N-dimensional custom array that reports its IndexStyle as IndexCartesian needs to implement indexing (and indexed assignment) with exactly N Int indices; all other indexing expressions — including linear indexing — will be recomputed to the equivalent Cartesian location. For example, if A were a 2×3 custom matrix with cartesian indexing, and we referenced A[5], this would be recomputed to the equivalent Cartesian index and call A[1, 3] since 5 = 2*1 + 3.\n\nIt is significantly more expensive to compute Cartesian indices from a linear index than it is to go the other way. The former operation requires division — a very costly operation — whereas the latter only uses multiplication and addition and is essentially free. This asymmetry means it is far more costly to use linear indexing with an IndexCartesian array than it is to use Cartesian indexing with an IndexLinear array.\n\nSee also IndexLinear.\n\n\n\n\n\n","category":"type"},{"location":"base/arrays/#Base.conj!","page":"数组","title":"Base.conj!","text":"conj!(A)\n\nTransform an array to its complex conjugate in-place.\n\nSee also conj.\n\nExamples\n\njulia> A = [1+im 2-im; 2+2im 3+im]\n2×2 Matrix{Complex{Int64}}:\n 1+1im 2-1im\n 2+2im 3+1im\n\njulia> conj!(A);\n\njulia> A\n2×2 Matrix{Complex{Int64}}:\n 1-1im 2+1im\n 2-2im 3-1im\n\n\n\n\n\n","category":"function"},{"location":"base/arrays/#Base.stride","page":"数组","title":"Base.stride","text":"stride(A, k::Integer)\n\nReturn the distance in memory (in number of elements) between adjacent elements in dimension k.\n\nSee also: strides.\n\nExamples\n\njulia> A = fill(1, (3,4,5));\n\njulia> stride(A,2)\n3\n\njulia> stride(A,3)\n12\n\n\n\n\n\n","category":"function"},{"location":"base/arrays/#Base.strides","page":"数组","title":"Base.strides","text":"strides(A)\n\nReturn a tuple of the memory strides in each dimension.\n\nSee also: stride.\n\nExamples\n\njulia> A = fill(1, (3,4,5));\n\njulia> strides(A)\n(1, 3, 12)\n\n\n\n\n\n","category":"function"},{"location":"base/arrays/#广播与矢量化","page":"数组","title":"广播与矢量化","text":"","category":"section"},{"location":"base/arrays/","page":"数组","title":"数组","text":"也可参照 dot syntax for vectorizing functions; 例如,f.(args...) 隐式调用 broadcast(f, args...)。 与其依赖如 sin 函数的“已矢量化”方法,你应该使用 sin.(a) 来使用broadcast来矢量化。","category":"page"},{"location":"base/arrays/","page":"数组","title":"数组","text":"Base.broadcast\nBase.Broadcast.broadcast!\nBase.@__dot__","category":"page"},{"location":"base/arrays/#Base.Broadcast.broadcast","page":"数组","title":"Base.Broadcast.broadcast","text":"broadcast(f, As...)\n\nBroadcast the function f over the arrays, tuples, collections, Refs and/or scalars As.\n\nBroadcasting applies the function f over the elements of the container arguments and the scalars themselves in As. Singleton and missing dimensions are expanded to match the extents of the other arguments by virtually repeating the value. By default, only a limited number of types are considered scalars, including Numbers, Strings, Symbols, Types, Functions and some common singletons like missing and nothing. All other arguments are iterated over or indexed into elementwise.\n\nThe resulting container type is established by the following rules:\n\nIf all the arguments are scalars or zero-dimensional arrays, it returns an unwrapped scalar.\nIf at least one argument is a tuple and all others are scalars or zero-dimensional arrays, it returns a tuple.\nAll other combinations of arguments default to returning an Array, but custom container types can define their own implementation and promotion-like rules to customize the result when they appear as arguments.\n\nA special syntax exists for broadcasting: f.(args...) is equivalent to broadcast(f, args...), and nested f.(g.(args...)) calls are fused into a single broadcast loop.\n\nExamples\n\njulia> A = [1, 2, 3, 4, 5]\n5-element Vector{Int64}:\n 1\n 2\n 3\n 4\n 5\n\njulia> B = [1 2; 3 4; 5 6; 7 8; 9 10]\n5×2 Matrix{Int64}:\n 1 2\n 3 4\n 5 6\n 7 8\n 9 10\n\njulia> broadcast(+, A, B)\n5×2 Matrix{Int64}:\n 2 3\n 5 6\n 8 9\n 11 12\n 14 15\n\njulia> parse.(Int, [\"1\", \"2\"])\n2-element Vector{Int64}:\n 1\n 2\n\njulia> abs.((1, -2))\n(1, 2)\n\njulia> broadcast(+, 1.0, (0, -2.0))\n(1.0, -1.0)\n\njulia> (+).([[0,2], [1,3]], Ref{Vector{Int}}([1,-1]))\n2-element Vector{Vector{Int64}}:\n [1, 1]\n [2, 2]\n\njulia> string.((\"one\",\"two\",\"three\",\"four\"), \": \", 1:4)\n4-element Vector{String}:\n \"one: 1\"\n \"two: 2\"\n \"three: 3\"\n \"four: 4\"\n\n\n\n\n\n\n","category":"function"},{"location":"base/arrays/#Base.Broadcast.broadcast!","page":"数组","title":"Base.Broadcast.broadcast!","text":"broadcast!(f, dest, As...)\n\nLike broadcast, but store the result of broadcast(f, As...) in the dest array. Note that dest is only used to store the result, and does not supply arguments to f unless it is also listed in the As, as in broadcast!(f, A, A, B) to perform A[:] = broadcast(f, A, B).\n\nExamples\n\njulia> A = [1.0; 0.0]; B = [0.0; 0.0];\n\njulia> broadcast!(+, B, A, (0, -2.0));\n\njulia> B\n2-element Vector{Float64}:\n 1.0\n -2.0\n\njulia> A\n2-element Vector{Float64}:\n 1.0\n 0.0\n\njulia> broadcast!(+, A, A, (0, -2.0));\n\njulia> A\n2-element Vector{Float64}:\n 1.0\n -2.0\n\n\n\n\n\n","category":"function"},{"location":"base/arrays/#Base.Broadcast.@__dot__","page":"数组","title":"Base.Broadcast.@__dot__","text":"@. expr\n\nConvert every function call or operator in expr into a \"dot call\" (e.g. convert f(x) to f.(x)), and convert every assignment in expr to a \"dot assignment\" (e.g. convert += to .+=).\n\nIf you want to avoid adding dots for selected function calls in expr, splice those function calls in with $. For example, @. sqrt(abs($sort(x))) is equivalent to sqrt.(abs.(sort(x))) (no dot for sort).\n\n(@. is equivalent to a call to @__dot__.)\n\nExamples\n\njulia> x = 1.0:3.0; y = similar(x);\n\njulia> @. y = x + 3 * sin(x)\n3-element Vector{Float64}:\n 3.5244129544236893\n 4.727892280477045\n 3.4233600241796016\n\n\n\n\n\n","category":"macro"},{"location":"base/arrays/","page":"数组","title":"数组","text":"自定义类型的广播,请参照","category":"page"},{"location":"base/arrays/","page":"数组","title":"数组","text":"Base.BroadcastStyle\nBase.Broadcast.AbstractArrayStyle\nBase.Broadcast.ArrayStyle\nBase.Broadcast.DefaultArrayStyle\nBase.Broadcast.broadcastable\nBase.Broadcast.combine_axes\nBase.Broadcast.combine_styles\nBase.Broadcast.result_style","category":"page"},{"location":"base/arrays/#Base.Broadcast.BroadcastStyle","page":"数组","title":"Base.Broadcast.BroadcastStyle","text":"BroadcastStyle is an abstract type and trait-function used to determine behavior of objects under broadcasting. BroadcastStyle(typeof(x)) returns the style associated with x. To customize the broadcasting behavior of a type, one can declare a style by defining a type/method pair\n\nstruct MyContainerStyle <: BroadcastStyle end\nBase.BroadcastStyle(::Type{<:MyContainer}) = MyContainerStyle()\n\nOne then writes method(s) (at least similar) operating on Broadcasted{MyContainerStyle}. There are also several pre-defined subtypes of BroadcastStyle that you may be able to leverage; see the Interfaces chapter for more information.\n\n\n\n\n\n","category":"type"},{"location":"base/arrays/#Base.Broadcast.AbstractArrayStyle","page":"数组","title":"Base.Broadcast.AbstractArrayStyle","text":"Broadcast.AbstractArrayStyle{N} <: BroadcastStyle is the abstract supertype for any style associated with an AbstractArray type. The N parameter is the dimensionality, which can be handy for AbstractArray types that only support specific dimensionalities:\n\nstruct SparseMatrixStyle <: Broadcast.AbstractArrayStyle{2} end\nBase.BroadcastStyle(::Type{<:SparseMatrixCSC}) = SparseMatrixStyle()\n\nFor AbstractArray types that support arbitrary dimensionality, N can be set to Any:\n\nstruct MyArrayStyle <: Broadcast.AbstractArrayStyle{Any} end\nBase.BroadcastStyle(::Type{<:MyArray}) = MyArrayStyle()\n\nIn cases where you want to be able to mix multiple AbstractArrayStyles and keep track of dimensionality, your style needs to support a Val constructor:\n\nstruct MyArrayStyleDim{N} <: Broadcast.AbstractArrayStyle{N} end\n(::Type{<:MyArrayStyleDim})(::Val{N}) where N = MyArrayStyleDim{N}()\n\nNote that if two or more AbstractArrayStyle subtypes conflict, broadcasting machinery will fall back to producing Arrays. If this is undesirable, you may need to define binary BroadcastStyle rules to control the output type.\n\nSee also Broadcast.DefaultArrayStyle.\n\n\n\n\n\n","category":"type"},{"location":"base/arrays/#Base.Broadcast.ArrayStyle","page":"数组","title":"Base.Broadcast.ArrayStyle","text":"Broadcast.ArrayStyle{MyArrayType}() is a BroadcastStyle indicating that an object behaves as an array for broadcasting. It presents a simple way to construct Broadcast.AbstractArrayStyles for specific AbstractArray container types. Broadcast styles created this way lose track of dimensionality; if keeping track is important for your type, you should create your own custom Broadcast.AbstractArrayStyle.\n\n\n\n\n\n","category":"type"},{"location":"base/arrays/#Base.Broadcast.DefaultArrayStyle","page":"数组","title":"Base.Broadcast.DefaultArrayStyle","text":"Broadcast.DefaultArrayStyle{N}() is a BroadcastStyle indicating that an object behaves as an N-dimensional array for broadcasting. Specifically, DefaultArrayStyle is used for any AbstractArray type that hasn't defined a specialized style, and in the absence of overrides from other broadcast arguments the resulting output type is Array. When there are multiple inputs to broadcast, DefaultArrayStyle \"loses\" to any other Broadcast.ArrayStyle.\n\n\n\n\n\n","category":"type"},{"location":"base/arrays/#Base.Broadcast.broadcastable","page":"数组","title":"Base.Broadcast.broadcastable","text":"Broadcast.broadcastable(x)\n\nReturn either x or an object like x such that it supports axes, indexing, and its type supports ndims.\n\nIf x supports iteration, the returned value should have the same axes and indexing behaviors as collect(x).\n\nIf x is not an AbstractArray but it supports axes, indexing, and its type supports ndims, then broadcastable(::typeof(x)) may be implemented to just return itself. Further, if x defines its own BroadcastStyle, then it must define its broadcastable method to return itself for the custom style to have any effect.\n\nExamples\n\njulia> Broadcast.broadcastable([1,2,3]) # like `identity` since arrays already support axes and indexing\n3-element Vector{Int64}:\n 1\n 2\n 3\n\njulia> Broadcast.broadcastable(Int) # Types don't support axes, indexing, or iteration but are commonly used as scalars\nBase.RefValue{Type{Int64}}(Int64)\n\njulia> Broadcast.broadcastable(\"hello\") # Strings break convention of matching iteration and act like a scalar instead\nBase.RefValue{String}(\"hello\")\n\n\n\n\n\n","category":"function"},{"location":"base/arrays/#Base.Broadcast.combine_axes","page":"数组","title":"Base.Broadcast.combine_axes","text":"combine_axes(As...) -> Tuple\n\nDetermine the result axes for broadcasting across all values in As.\n\njulia> Broadcast.combine_axes([1], [1 2; 3 4; 5 6])\n(Base.OneTo(3), Base.OneTo(2))\n\njulia> Broadcast.combine_axes(1, 1, 1)\n()\n\n\n\n\n\n","category":"function"},{"location":"base/arrays/#Base.Broadcast.combine_styles","page":"数组","title":"Base.Broadcast.combine_styles","text":"combine_styles(cs...) -> BroadcastStyle\n\nDecides which BroadcastStyle to use for any number of value arguments. Uses BroadcastStyle to get the style for each argument, and uses result_style to combine styles.\n\nExamples\n\njulia> Broadcast.combine_styles([1], [1 2; 3 4])\nBase.Broadcast.DefaultArrayStyle{2}()\n\n\n\n\n\n","category":"function"},{"location":"base/arrays/#Base.Broadcast.result_style","page":"数组","title":"Base.Broadcast.result_style","text":"result_style(s1::BroadcastStyle[, s2::BroadcastStyle]) -> BroadcastStyle\n\nTakes one or two BroadcastStyles and combines them using BroadcastStyle to determine a common BroadcastStyle.\n\nExamples\n\njulia> Broadcast.result_style(Broadcast.DefaultArrayStyle{0}(), Broadcast.DefaultArrayStyle{3}())\nBase.Broadcast.DefaultArrayStyle{3}()\n\njulia> Broadcast.result_style(Broadcast.Unknown(), Broadcast.DefaultArrayStyle{1}())\nBase.Broadcast.DefaultArrayStyle{1}()\n\n\n\n\n\n","category":"function"},{"location":"base/arrays/#索引与赋值","page":"数组","title":"索引与赋值","text":"","category":"section"},{"location":"base/arrays/","page":"数组","title":"数组","text":"Base.getindex(::AbstractArray, ::Any...)\nBase.setindex!(::AbstractArray, ::Any, ::Any...)\nBase.copyto!(::AbstractArray, ::CartesianIndices, ::AbstractArray, ::CartesianIndices)\nBase.copy!\nBase.isassigned\nBase.Colon\nBase.CartesianIndex\nBase.CartesianIndices\nBase.Dims\nBase.LinearIndices\nBase.to_indices\nBase.checkbounds\nBase.checkindex\nBase.elsize","category":"page"},{"location":"base/arrays/#Base.getindex-Tuple{AbstractArray, Vararg{Any}}","page":"数组","title":"Base.getindex","text":"getindex(A, inds...)\n\nReturn a subset of array A as specified by inds, where each ind may be, for example, an Int, an AbstractRange, or a Vector. See the manual section on array indexing for details.\n\nExamples\n\njulia> A = [1 2; 3 4]\n2×2 Matrix{Int64}:\n 1 2\n 3 4\n\njulia> getindex(A, 1)\n1\n\njulia> getindex(A, [2, 1])\n2-element Vector{Int64}:\n 3\n 1\n\njulia> getindex(A, 2:4)\n3-element Vector{Int64}:\n 3\n 2\n 4\n\n\n\n\n\n","category":"method"},{"location":"base/arrays/#Base.setindex!-Tuple{AbstractArray, Any, Vararg{Any}}","page":"数组","title":"Base.setindex!","text":"setindex!(A, X, inds...)\nA[inds...] = X\n\nStore values from array X within some subset of A as specified by inds. The syntax A[inds...] = X is equivalent to (setindex!(A, X, inds...); X).\n\nExamples\n\njulia> A = zeros(2,2);\n\njulia> setindex!(A, [10, 20], [1, 2]);\n\njulia> A[[3, 4]] = [30, 40];\n\njulia> A\n2×2 Matrix{Float64}:\n 10.0 30.0\n 20.0 40.0\n\n\n\n\n\n","category":"method"},{"location":"base/arrays/#Base.copyto!-Tuple{AbstractArray, CartesianIndices, AbstractArray, CartesianIndices}","page":"数组","title":"Base.copyto!","text":"copyto!(dest, Rdest::CartesianIndices, src, Rsrc::CartesianIndices) -> dest\n\nCopy the block of src in the range of Rsrc to the block of dest in the range of Rdest. The sizes of the two regions must match.\n\nExamples\n\njulia> A = zeros(5, 5);\n\njulia> B = [1 2; 3 4];\n\njulia> Ainds = CartesianIndices((2:3, 2:3));\n\njulia> Binds = CartesianIndices(B);\n\njulia> copyto!(A, Ainds, B, Binds)\n5×5 Matrix{Float64}:\n 0.0 0.0 0.0 0.0 0.0\n 0.0 1.0 2.0 0.0 0.0\n 0.0 3.0 4.0 0.0 0.0\n 0.0 0.0 0.0 0.0 0.0\n 0.0 0.0 0.0 0.0 0.0\n\n\n\n\n\n","category":"method"},{"location":"base/arrays/#Base.copy!","page":"数组","title":"Base.copy!","text":"copy!(dst, src) -> dst\n\nIn-place copy of src into dst, discarding any pre-existing elements in dst. If dst and src are of the same type, dst == src should hold after the call. If dst and src are multidimensional arrays, they must have equal axes.\n\nSee also copyto!.\n\ncompat: Julia 1.1\nThis method requires at least Julia 1.1. In Julia 1.0 this method is available from the Future standard library as Future.copy!.\n\n\n\n\n\n","category":"function"},{"location":"base/arrays/#Base.isassigned","page":"数组","title":"Base.isassigned","text":"isassigned(array, i) -> Bool\n\nTest whether the given array has a value associated with index i. Return false if the index is out of bounds, or has an undefined reference.\n\nExamples\n\njulia> isassigned(rand(3, 3), 5)\ntrue\n\njulia> isassigned(rand(3, 3), 3 * 3 + 1)\nfalse\n\njulia> mutable struct Foo end\n\njulia> v = similar(rand(3), Foo)\n3-element Vector{Foo}:\n #undef\n #undef\n #undef\n\njulia> isassigned(v, 1)\nfalse\n\n\n\n\n\n","category":"function"},{"location":"base/arrays/#Base.Colon","page":"数组","title":"Base.Colon","text":"Colon()\n\nColons (:) are used to signify indexing entire objects or dimensions at once.\n\nVery few operations are defined on Colons directly; instead they are converted by to_indices to an internal vector type (Base.Slice) to represent the collection of indices they span before being used.\n\nThe singleton instance of Colon is also a function used to construct ranges; see :.\n\n\n\n\n\n","category":"type"},{"location":"base/arrays/#Base.IteratorsMD.CartesianIndex","page":"数组","title":"Base.IteratorsMD.CartesianIndex","text":"CartesianIndex(i, j, k...) -> I\nCartesianIndex((i, j, k...)) -> I\n\nCreate a multidimensional index I, which can be used for indexing a multidimensional array A. In particular, A[I] is equivalent to A[i,j,k...]. One can freely mix integer and CartesianIndex indices; for example, A[Ipre, i, Ipost] (where Ipre and Ipost are CartesianIndex indices and i is an Int) can be a useful expression when writing algorithms that work along a single dimension of an array of arbitrary dimensionality.\n\nA CartesianIndex is sometimes produced by eachindex, and always when iterating with an explicit CartesianIndices.\n\nExamples\n\njulia> A = reshape(Vector(1:16), (2, 2, 2, 2))\n2×2×2×2 Array{Int64, 4}:\n[:, :, 1, 1] =\n 1 3\n 2 4\n\n[:, :, 2, 1] =\n 5 7\n 6 8\n\n[:, :, 1, 2] =\n 9 11\n 10 12\n\n[:, :, 2, 2] =\n 13 15\n 14 16\n\njulia> A[CartesianIndex((1, 1, 1, 1))]\n1\n\njulia> A[CartesianIndex((1, 1, 1, 2))]\n9\n\njulia> A[CartesianIndex((1, 1, 2, 1))]\n5\n\n\n\n\n\n","category":"type"},{"location":"base/arrays/#Base.IteratorsMD.CartesianIndices","page":"数组","title":"Base.IteratorsMD.CartesianIndices","text":"CartesianIndices(sz::Dims) -> R\nCartesianIndices((istart:[istep:]istop, jstart:[jstep:]jstop, ...)) -> R\n\nDefine a region R spanning a multidimensional rectangular range of integer indices. These are most commonly encountered in the context of iteration, where for I in R ... end will return CartesianIndex indices I equivalent to the nested loops\n\nfor j = jstart:jstep:jstop\n for i = istart:istep:istop\n ...\n end\nend\n\nConsequently these can be useful for writing algorithms that work in arbitrary dimensions.\n\nCartesianIndices(A::AbstractArray) -> R\n\nAs a convenience, constructing a CartesianIndices from an array makes a range of its indices.\n\ncompat: Julia 1.6\nThe step range method CartesianIndices((istart:istep:istop, jstart:[jstep:]jstop, ...)) requires at least Julia 1.6.\n\nExamples\n\njulia> foreach(println, CartesianIndices((2, 2, 2)))\nCartesianIndex(1, 1, 1)\nCartesianIndex(2, 1, 1)\nCartesianIndex(1, 2, 1)\nCartesianIndex(2, 2, 1)\nCartesianIndex(1, 1, 2)\nCartesianIndex(2, 1, 2)\nCartesianIndex(1, 2, 2)\nCartesianIndex(2, 2, 2)\n\njulia> CartesianIndices(fill(1, (2,3)))\nCartesianIndices((2, 3))\n\nConversion between linear and cartesian indices\n\nLinear index to cartesian index conversion exploits the fact that a CartesianIndices is an AbstractArray and can be indexed linearly:\n\njulia> cartesian = CartesianIndices((1:3, 1:2))\nCartesianIndices((1:3, 1:2))\n\njulia> cartesian[4]\nCartesianIndex(1, 2)\n\njulia> cartesian = CartesianIndices((1:2:5, 1:2))\nCartesianIndices((1:2:5, 1:2))\n\njulia> cartesian[2, 2]\nCartesianIndex(3, 2)\n\nBroadcasting\n\nCartesianIndices support broadcasting arithmetic (+ and -) with a CartesianIndex.\n\ncompat: Julia 1.1\nBroadcasting of CartesianIndices requires at least Julia 1.1.\n\njulia> CIs = CartesianIndices((2:3, 5:6))\nCartesianIndices((2:3, 5:6))\n\njulia> CI = CartesianIndex(3, 4)\nCartesianIndex(3, 4)\n\njulia> CIs .+ CI\nCartesianIndices((5:6, 9:10))\n\nFor cartesian to linear index conversion, see LinearIndices.\n\n\n\n\n\n","category":"type"},{"location":"base/arrays/#Base.Dims","page":"数组","title":"Base.Dims","text":"Dims{N}\n\nAn NTuple of N Ints used to represent the dimensions of an AbstractArray.\n\n\n\n\n\n","category":"type"},{"location":"base/arrays/#Base.LinearIndices","page":"数组","title":"Base.LinearIndices","text":"LinearIndices(A::AbstractArray)\n\nReturn a LinearIndices array with the same shape and axes as A, holding the linear index of each entry in A. Indexing this array with cartesian indices allows mapping them to linear indices.\n\nFor arrays with conventional indexing (indices start at 1), or any multidimensional array, linear indices range from 1 to length(A). However, for AbstractVectors linear indices are axes(A, 1), and therefore do not start at 1 for vectors with unconventional indexing.\n\nCalling this function is the \"safe\" way to write algorithms that exploit linear indexing.\n\nExamples\n\njulia> A = fill(1, (5,6,7));\n\njulia> b = LinearIndices(A);\n\njulia> extrema(b)\n(1, 210)\n\nLinearIndices(inds::CartesianIndices) -> R\nLinearIndices(sz::Dims) -> R\nLinearIndices((istart:istop, jstart:jstop, ...)) -> R\n\nReturn a LinearIndices array with the specified shape or axes.\n\nExample\n\nThe main purpose of this constructor is intuitive conversion from cartesian to linear indexing:\n\njulia> linear = LinearIndices((1:3, 1:2))\n3×2 LinearIndices{2, Tuple{UnitRange{Int64}, UnitRange{Int64}}}:\n 1 4\n 2 5\n 3 6\n\njulia> linear[1,2]\n4\n\n\n\n\n\n","category":"type"},{"location":"base/arrays/#Base.to_indices","page":"数组","title":"Base.to_indices","text":"to_indices(A, I::Tuple)\n\nConvert the tuple I to a tuple of indices for use in indexing into array A.\n\nThe returned tuple must only contain either Ints or AbstractArrays of scalar indices that are supported by array A. It will error upon encountering a novel index type that it does not know how to process.\n\nFor simple index types, it defers to the unexported Base.to_index(A, i) to process each index i. While this internal function is not intended to be called directly, Base.to_index may be extended by custom array or index types to provide custom indexing behaviors.\n\nMore complicated index types may require more context about the dimension into which they index. To support those cases, to_indices(A, I) calls to_indices(A, axes(A), I), which then recursively walks through both the given tuple of indices and the dimensional indices of A in tandem. As such, not all index types are guaranteed to propagate to Base.to_index.\n\n\n\n\n\n","category":"function"},{"location":"base/arrays/#Base.checkbounds","page":"数组","title":"Base.checkbounds","text":"checkbounds(Bool, A, I...)\n\nReturn true if the specified indices I are in bounds for the given array A. Subtypes of AbstractArray should specialize this method if they need to provide custom bounds checking behaviors; however, in many cases one can rely on A's indices and checkindex.\n\nSee also checkindex.\n\nExamples\n\njulia> A = rand(3, 3);\n\njulia> checkbounds(Bool, A, 2)\ntrue\n\njulia> checkbounds(Bool, A, 3, 4)\nfalse\n\njulia> checkbounds(Bool, A, 1:3)\ntrue\n\njulia> checkbounds(Bool, A, 1:3, 2:4)\nfalse\n\n\n\n\n\ncheckbounds(A, I...)\n\nThrow an error if the specified indices I are not in bounds for the given array A.\n\n\n\n\n\n","category":"function"},{"location":"base/arrays/#Base.checkindex","page":"数组","title":"Base.checkindex","text":"checkindex(Bool, inds::AbstractUnitRange, index)\n\nReturn true if the given index is within the bounds of inds. Custom types that would like to behave as indices for all arrays can extend this method in order to provide a specialized bounds checking implementation.\n\nSee also checkbounds.\n\nExamples\n\njulia> checkindex(Bool, 1:20, 8)\ntrue\n\njulia> checkindex(Bool, 1:20, 21)\nfalse\n\n\n\n\n\n","category":"function"},{"location":"base/arrays/#Base.elsize","page":"数组","title":"Base.elsize","text":"elsize(type)\n\nCompute the memory stride in bytes between consecutive elements of eltype stored inside the given type, if the array elements are stored densely with a uniform linear stride.\n\nExamples\n\njulia> Base.elsize(rand(Float32, 10))\n4\n\n\n\n\n\n","category":"function"},{"location":"base/arrays/#Views-(SubArrays-以及其它-view-类型)","page":"数组","title":"Views (SubArrays 以及其它 view 类型)","text":"","category":"section"},{"location":"base/arrays/","page":"数组","title":"数组","text":"“视图”是一种表现和数组相似的数据结构(它是 AbstractArray 的子类型),但是它的底层数据实际上是另一个数组的一部分。","category":"page"},{"location":"base/arrays/","page":"数组","title":"数组","text":"例如,x 是一个数组,v = @view x[1:10],则 v 表现得就像一个含有 10 个元素的数组,但是它的数据实际上是访问 x 的前 10 个元素。对视图的写入,如 v[3] = 2,直接写入了底层的数组 x (这里是修改 x[3])。","category":"page"},{"location":"base/arrays/","page":"数组","title":"数组","text":"在 Julia 中,像 x[1:10] 这样的切片操作会创建一个副本。@view x[1:10] 将它变成创建一个视图。 @views 宏可以用于整个代码块(如 @views function foo() .... end 或 @views begin ... end)来将整个代码块中的切片操作变为使用视图。 如性能建议所描述的,有时候使用数据的副本更快,而有时候使用视图会更快。","category":"page"},{"location":"base/arrays/","page":"数组","title":"数组","text":"Base.view\nBase.@view\nBase.@views\nBase.parent\nBase.parentindices\nBase.selectdim\nBase.reinterpret\nBase.reshape\nBase.dropdims\nBase.vec\nBase.SubArray","category":"page"},{"location":"base/arrays/#Base.view","page":"数组","title":"Base.view","text":"view(A, inds...)\n\nLike getindex, but returns a lightweight array that lazily references (or is effectively a view into) the parent array A at the given index or indices inds instead of eagerly extracting elements or constructing a copied subset. Calling getindex or setindex! on the returned value (often a SubArray) computes the indices to access or modify the parent array on the fly. The behavior is undefined if the shape of the parent array is changed after view is called because there is no bound check for the parent array; e.g., it may cause a segmentation fault.\n\nSome immutable parent arrays (like ranges) may choose to simply recompute a new array in some circumstances instead of returning a SubArray if doing so is efficient and provides compatible semantics.\n\ncompat: Julia 1.6\nIn Julia 1.6 or later, view can be called on an AbstractString, returning a SubString.\n\nExamples\n\njulia> A = [1 2; 3 4]\n2×2 Matrix{Int64}:\n 1 2\n 3 4\n\njulia> b = view(A, :, 1)\n2-element view(::Matrix{Int64}, :, 1) with eltype Int64:\n 1\n 3\n\njulia> fill!(b, 0)\n2-element view(::Matrix{Int64}, :, 1) with eltype Int64:\n 0\n 0\n\njulia> A # Note A has changed even though we modified b\n2×2 Matrix{Int64}:\n 0 2\n 0 4\n\njulia> view(2:5, 2:3) # returns a range as type is immutable\n3:4\n\n\n\n\n\n","category":"function"},{"location":"base/arrays/#Base.@view","page":"数组","title":"Base.@view","text":"@view A[inds...]\n\nTransform the indexing expression A[inds...] into the equivalent view call.\n\nThis can only be applied directly to a single indexing expression and is particularly helpful for expressions that include the special begin or end indexing syntaxes like A[begin, 2:end-1] (as those are not supported by the normal view function).\n\nNote that @view cannot be used as the target of a regular assignment (e.g., @view(A[1, 2:end]) = ...), nor would the un-decorated indexed assignment (A[1, 2:end] = ...) or broadcasted indexed assignment (A[1, 2:end] .= ...) make a copy. It can be useful, however, for updating broadcasted assignments like @view(A[1, 2:end]) .+= 1 because this is a simple syntax for @view(A[1, 2:end]) .= @view(A[1, 2:end]) + 1, and the indexing expression on the right-hand side would otherwise make a copy without the @view.\n\nSee also @views to switch an entire block of code to use views for non-scalar indexing.\n\ncompat: Julia 1.5\nUsing begin in an indexing expression to refer to the first index requires at least Julia 1.5.\n\nExamples\n\njulia> A = [1 2; 3 4]\n2×2 Matrix{Int64}:\n 1 2\n 3 4\n\njulia> b = @view A[:, 1]\n2-element view(::Matrix{Int64}, :, 1) with eltype Int64:\n 1\n 3\n\njulia> fill!(b, 0)\n2-element view(::Matrix{Int64}, :, 1) with eltype Int64:\n 0\n 0\n\njulia> A\n2×2 Matrix{Int64}:\n 0 2\n 0 4\n\n\n\n\n\n","category":"macro"},{"location":"base/arrays/#Base.@views","page":"数组","title":"Base.@views","text":"@views expression\n\nConvert every array-slicing operation in the given expression (which may be a begin/end block, loop, function, etc.) to return a view. Scalar indices, non-array types, and explicit getindex calls (as opposed to array[...]) are unaffected.\n\nnote: Note\nThe @views macro only affects array[...] expressions that appear explicitly in the given expression, not array slicing that occurs in functions called by that code.\n\ncompat: Julia 1.5\nUsing begin in an indexing expression to refer to the first index requires at least Julia 1.5.\n\nExamples\n\njulia> A = zeros(3, 3);\n\njulia> @views for row in 1:3\n b = A[row, :]\n b[:] .= row\n end\n\njulia> A\n3×3 Matrix{Float64}:\n 1.0 1.0 1.0\n 2.0 2.0 2.0\n 3.0 3.0 3.0\n\n\n\n\n\n","category":"macro"},{"location":"base/arrays/#Base.parent","page":"数组","title":"Base.parent","text":"parent(A)\n\nReturn the underlying \"parent array”. This parent array of objects of types SubArray, ReshapedArray or LinearAlgebra.Transpose is what was passed as an argument to view, reshape, transpose, etc. during object creation. If the input is not a wrapped object, return the input itself. If the input is wrapped multiple times, only the outermost wrapper will be removed.\n\nExamples\n\njulia> A = [1 2; 3 4]\n2×2 Matrix{Int64}:\n 1 2\n 3 4\n\njulia> V = view(A, 1:2, :)\n2×2 view(::Matrix{Int64}, 1:2, :) with eltype Int64:\n 1 2\n 3 4\n\njulia> parent(V)\n2×2 Matrix{Int64}:\n 1 2\n 3 4\n\n\n\n\n\n","category":"function"},{"location":"base/arrays/#Base.parentindices","page":"数组","title":"Base.parentindices","text":"parentindices(A)\n\nReturn the indices in the parent which correspond to the array view A.\n\nExamples\n\njulia> A = [1 2; 3 4];\n\njulia> V = view(A, 1, :)\n2-element view(::Matrix{Int64}, 1, :) with eltype Int64:\n 1\n 2\n\njulia> parentindices(V)\n(1, Base.Slice(Base.OneTo(2)))\n\n\n\n\n\n","category":"function"},{"location":"base/arrays/#Base.selectdim","page":"数组","title":"Base.selectdim","text":"selectdim(A, d::Integer, i)\n\nReturn a view of all the data of A where the index for dimension d equals i.\n\nEquivalent to view(A,:,:,...,i,:,:,...) where i is in position d.\n\nSee also: eachslice.\n\nExamples\n\njulia> A = [1 2 3 4; 5 6 7 8]\n2×4 Matrix{Int64}:\n 1 2 3 4\n 5 6 7 8\n\njulia> selectdim(A, 2, 3)\n2-element view(::Matrix{Int64}, :, 3) with eltype Int64:\n 3\n 7\n\njulia> selectdim(A, 2, 3:4)\n2×2 view(::Matrix{Int64}, :, 3:4) with eltype Int64:\n 3 4\n 7 8\n\n\n\n\n\n","category":"function"},{"location":"base/arrays/#Base.reinterpret","page":"数组","title":"Base.reinterpret","text":"reinterpret(type, A)\n\nChange the type-interpretation of a block of memory. For arrays, this constructs a view of the array with the same binary data as the given array, but with the specified element type. For example, reinterpret(Float32, UInt32(7)) interprets the 4 bytes corresponding to UInt32(7) as a Float32.\n\nExamples\n\njulia> reinterpret(Float32, UInt32(7))\n1.0f-44\n\njulia> reinterpret(Float32, UInt32[1 2 3 4 5])\n1×5 reinterpret(Float32, ::Matrix{UInt32}):\n 1.0f-45 3.0f-45 4.0f-45 6.0f-45 7.0f-45\n\n\n\n\n\nreinterpret(reshape, T, A::AbstractArray{S}) -> B\n\nChange the type-interpretation of A while consuming or adding a \"channel dimension.\"\n\nIf sizeof(T) = n*sizeof(S) for n>1, A's first dimension must be of size n and B lacks A's first dimension. Conversely, if sizeof(S) = n*sizeof(T) for n>1, B gets a new first dimension of size n. The dimensionality is unchanged if sizeof(T) == sizeof(S).\n\ncompat: Julia 1.6\nThis method requires at least Julia 1.6.\n\nExamples\n\njulia> A = [1 2; 3 4]\n2×2 Matrix{Int64}:\n 1 2\n 3 4\n\njulia> reinterpret(reshape, Complex{Int}, A) # the result is a vector\n2-element reinterpret(reshape, Complex{Int64}, ::Matrix{Int64}) with eltype Complex{Int64}:\n 1 + 3im\n 2 + 4im\n\njulia> a = [(1,2,3), (4,5,6)]\n2-element Vector{Tuple{Int64, Int64, Int64}}:\n (1, 2, 3)\n (4, 5, 6)\n\njulia> reinterpret(reshape, Int, a) # the result is a matrix\n3×2 reinterpret(reshape, Int64, ::Vector{Tuple{Int64, Int64, Int64}}) with eltype Int64:\n 1 4\n 2 5\n 3 6\n\n\n\n\n\n","category":"function"},{"location":"base/arrays/#Base.reshape","page":"数组","title":"Base.reshape","text":"reshape(A, dims...) -> AbstractArray\nreshape(A, dims) -> AbstractArray\n\nReturn an array with the same data as A, but with different dimension sizes or number of dimensions. The two arrays share the same underlying data, so that the result is mutable if and only if A is mutable, and setting elements of one alters the values of the other.\n\nThe new dimensions may be specified either as a list of arguments or as a shape tuple. At most one dimension may be specified with a :, in which case its length is computed such that its product with all the specified dimensions is equal to the length of the original array A. The total number of elements must not change.\n\nExamples\n\njulia> A = Vector(1:16)\n16-element Vector{Int64}:\n 1\n 2\n 3\n 4\n 5\n 6\n 7\n 8\n 9\n 10\n 11\n 12\n 13\n 14\n 15\n 16\n\njulia> reshape(A, (4, 4))\n4×4 Matrix{Int64}:\n 1 5 9 13\n 2 6 10 14\n 3 7 11 15\n 4 8 12 16\n\njulia> reshape(A, 2, :)\n2×8 Matrix{Int64}:\n 1 3 5 7 9 11 13 15\n 2 4 6 8 10 12 14 16\n\njulia> reshape(1:6, 2, 3)\n2×3 reshape(::UnitRange{Int64}, 2, 3) with eltype Int64:\n 1 3 5\n 2 4 6\n\n\n\n\n\n","category":"function"},{"location":"base/arrays/#Base.dropdims","page":"数组","title":"Base.dropdims","text":"dropdims(A; dims)\n\nReturn an array with the same data as A, but with the dimensions specified by dims removed. size(A,d) must equal 1 for every d in dims, and repeated dimensions or numbers outside 1:ndims(A) are forbidden.\n\nThe result shares the same underlying data as A, such that the result is mutable if and only if A is mutable, and setting elements of one alters the values of the other.\n\nSee also: reshape, vec.\n\nExamples\n\njulia> a = reshape(Vector(1:4),(2,2,1,1))\n2×2×1×1 Array{Int64, 4}:\n[:, :, 1, 1] =\n 1 3\n 2 4\n\njulia> b = dropdims(a; dims=3)\n2×2×1 Array{Int64, 3}:\n[:, :, 1] =\n 1 3\n 2 4\n\njulia> b[1,1,1] = 5; a\n2×2×1×1 Array{Int64, 4}:\n[:, :, 1, 1] =\n 5 3\n 2 4\n\n\n\n\n\n","category":"function"},{"location":"base/arrays/#Base.vec","page":"数组","title":"Base.vec","text":"vec(a::AbstractArray) -> AbstractVector\n\nReshape the array a as a one-dimensional column vector. Return a if it is already an AbstractVector. The resulting array shares the same underlying data as a, so it will only be mutable if a is mutable, in which case modifying one will also modify the other.\n\nExamples\n\njulia> a = [1 2 3; 4 5 6]\n2×3 Matrix{Int64}:\n 1 2 3\n 4 5 6\n\njulia> vec(a)\n6-element Vector{Int64}:\n 1\n 4\n 2\n 5\n 3\n 6\n\njulia> vec(1:3)\n1:3\n\nSee also reshape, dropdims.\n\n\n\n\n\n","category":"function"},{"location":"base/arrays/#Base.SubArray","page":"数组","title":"Base.SubArray","text":"SubArray{T,N,P,I,L} <: AbstractArray{T,N}\n\nN-dimensional view into a parent array (of type P) with an element type T, restricted by a tuple of indices (of type I). L is true for types that support fast linear indexing, and false otherwise.\n\nConstruct SubArrays using the view function.\n\n\n\n\n\n","category":"type"},{"location":"base/arrays/#拼接与排列","page":"数组","title":"拼接与排列","text":"","category":"section"},{"location":"base/arrays/","page":"数组","title":"数组","text":"Base.cat\nBase.vcat\nBase.hcat\nBase.hvcat\nBase.hvncat\nBase.vect\nBase.circshift\nBase.circshift!\nBase.circcopy!\nBase.findall(::Any)\nBase.findall(::Function, ::Any)\nBase.findfirst(::Any)\nBase.findfirst(::Function, ::Any)\nBase.findlast(::Any)\nBase.findlast(::Function, ::Any)\nBase.findnext(::Any, ::Integer)\nBase.findnext(::Function, ::Any, ::Integer)\nBase.findprev(::Any, ::Integer)\nBase.findprev(::Function, ::Any, ::Integer)\nBase.permutedims\nBase.permutedims!\nBase.PermutedDimsArray\nBase.promote_shape","category":"page"},{"location":"base/arrays/#Base.cat","page":"数组","title":"Base.cat","text":"cat(A...; dims)\n\nConcatenate the input arrays along the specified dimensions in the iterable dims. For dimensions not in dims, all input arrays should have the same size, which will also be the size of the output array along that dimension. For dimensions in dims, the size of the output array is the sum of the sizes of the input arrays along that dimension. If dims is a single number, the different arrays are tightly stacked along that dimension. If dims is an iterable containing several dimensions, this allows one to construct block diagonal matrices and their higher-dimensional analogues by simultaneously increasing several dimensions for every new input array and putting zero blocks elsewhere. For example, cat(matrices...; dims=(1,2)) builds a block diagonal matrix, i.e. a block matrix with matrices[1], matrices[2], ... as diagonal blocks and matching zero blocks away from the diagonal.\n\nSee also hcat, vcat, hvcat, repeat.\n\nExamples\n\njulia> cat([1 2; 3 4], [pi, pi], fill(10, 2,3,1); dims=2)\n2×6×1 Array{Float64, 3}:\n[:, :, 1] =\n 1.0 2.0 3.14159 10.0 10.0 10.0\n 3.0 4.0 3.14159 10.0 10.0 10.0\n\njulia> cat(true, trues(2,2), trues(4)', dims=(1,2))\n4×7 Matrix{Bool}:\n 1 0 0 0 0 0 0\n 0 1 1 0 0 0 0\n 0 1 1 0 0 0 0\n 0 0 0 1 1 1 1\n\n\n\n\n\n","category":"function"},{"location":"base/arrays/#Base.vcat","page":"数组","title":"Base.vcat","text":"vcat(A...)\n\nConcatenate along dimension 1. To efficiently concatenate a large vector of arrays, use reduce(vcat, x).\n\nExamples\n\njulia> a = [1 2 3 4 5]\n1×5 Matrix{Int64}:\n 1 2 3 4 5\n\njulia> b = [6 7 8 9 10; 11 12 13 14 15]\n2×5 Matrix{Int64}:\n 6 7 8 9 10\n 11 12 13 14 15\n\njulia> vcat(a,b)\n3×5 Matrix{Int64}:\n 1 2 3 4 5\n 6 7 8 9 10\n 11 12 13 14 15\n\njulia> c = ([1 2 3], [4 5 6])\n([1 2 3], [4 5 6])\n\njulia> vcat(c...)\n2×3 Matrix{Int64}:\n 1 2 3\n 4 5 6\n\njulia> vs = [[1, 2], [3, 4], [5, 6]]\n3-element Vector{Vector{Int64}}:\n [1, 2]\n [3, 4]\n [5, 6]\n\njulia> reduce(vcat, vs)\n6-element Vector{Int64}:\n 1\n 2\n 3\n 4\n 5\n 6\n\n\n\n\n\n","category":"function"},{"location":"base/arrays/#Base.hcat","page":"数组","title":"Base.hcat","text":"hcat(A...)\n\nConcatenate along dimension 2. To efficiently concatenate a large vector of arrays, use reduce(hcat, x).\n\nExamples\n\njulia> a = [1; 2; 3; 4; 5]\n5-element Vector{Int64}:\n 1\n 2\n 3\n 4\n 5\n\njulia> b = [6 7; 8 9; 10 11; 12 13; 14 15]\n5×2 Matrix{Int64}:\n 6 7\n 8 9\n 10 11\n 12 13\n 14 15\n\njulia> hcat(a,b)\n5×3 Matrix{Int64}:\n 1 6 7\n 2 8 9\n 3 10 11\n 4 12 13\n 5 14 15\n\njulia> c = ([1; 2; 3], [4; 5; 6])\n([1, 2, 3], [4, 5, 6])\n\njulia> hcat(c...)\n3×2 Matrix{Int64}:\n 1 4\n 2 5\n 3 6\n\njulia> x = Matrix(undef, 3, 0) # x = [] would have created an Array{Any, 1}, but need an Array{Any, 2}\n3×0 Matrix{Any}\n\njulia> hcat(x, [1; 2; 3])\n3×1 Matrix{Any}:\n 1\n 2\n 3\n\njulia> vs = [[1, 2], [3, 4], [5, 6]]\n3-element Vector{Vector{Int64}}:\n [1, 2]\n [3, 4]\n [5, 6]\n\njulia> reduce(hcat, vs)\n2×3 Matrix{Int64}:\n 1 3 5\n 2 4 6\n\n\n\n\n\n","category":"function"},{"location":"base/arrays/#Base.hvcat","page":"数组","title":"Base.hvcat","text":"hvcat(rows::Tuple{Vararg{Int}}, values...)\n\nHorizontal and vertical concatenation in one call. This function is called for block matrix syntax. The first argument specifies the number of arguments to concatenate in each block row.\n\nExamples\n\njulia> a, b, c, d, e, f = 1, 2, 3, 4, 5, 6\n(1, 2, 3, 4, 5, 6)\n\njulia> [a b c; d e f]\n2×3 Matrix{Int64}:\n 1 2 3\n 4 5 6\n\njulia> hvcat((3,3), a,b,c,d,e,f)\n2×3 Matrix{Int64}:\n 1 2 3\n 4 5 6\n\njulia> [a b; c d; e f]\n3×2 Matrix{Int64}:\n 1 2\n 3 4\n 5 6\n\njulia> hvcat((2,2,2), a,b,c,d,e,f)\n3×2 Matrix{Int64}:\n 1 2\n 3 4\n 5 6\n\nIf the first argument is a single integer n, then all block rows are assumed to have n block columns.\n\n\n\n\n\n","category":"function"},{"location":"base/arrays/#Base.hvncat","page":"数组","title":"Base.hvncat","text":"hvncat(dim::Int, row_first, values...)\nhvncat(dims::Tuple{Vararg{Int}}, row_first, values...)\nhvncat(shape::Tuple{Vararg{Tuple}}, row_first, values...)\n\nHorizontal, vertical, and n-dimensional concatenation of many values in one call.\n\nThis function is called for block matrix syntax. The first argument either specifies the shape of the concatenation, similar to hvcat, as a tuple of tuples, or the dimensions that specify the key number of elements along each axis, and is used to determine the output dimensions. The dims form is more performant, and is used by default when the concatenation operation has the same number of elements along each axis (e.g., [a b; c d;;; e f ; g h]). The shape form is used when the number of elements along each axis is unbalanced (e.g., [a b ; c]). Unbalanced syntax needs additional validation overhead. The dim form is an optimization for concatenation along just one dimension. row_first indicates how values are ordered. The meaning of the first and second elements of shape are also swapped based on row_first.\n\nExamples\n\njulia> a, b, c, d, e, f = 1, 2, 3, 4, 5, 6\n(1, 2, 3, 4, 5, 6)\n\njulia> [a b c;;; d e f]\n1×3×2 Array{Int64, 3}:\n[:, :, 1] =\n 1 2 3\n\n[:, :, 2] =\n 4 5 6\n\njulia> hvncat((2,1,3), false, a,b,c,d,e,f)\n2×1×3 Array{Int64, 3}:\n[:, :, 1] =\n 1\n 2\n\n[:, :, 2] =\n 3\n 4\n\n[:, :, 3] =\n 5\n 6\n\njulia> [a b;;; c d;;; e f]\n1×2×3 Array{Int64, 3}:\n[:, :, 1] =\n 1 2\n\n[:, :, 2] =\n 3 4\n\n[:, :, 3] =\n 5 6\n\njulia> hvncat(((3, 3), (3, 3), (6,)), true, a, b, c, d, e, f)\n1×3×2 Array{Int64, 3}:\n[:, :, 1] =\n 1 2 3\n\n[:, :, 2] =\n 4 5 6\n\nExamples for construction of the arguments:\n\n[a b c ; d e f ;;;\n g h i ; j k l ;;;\n m n o ; p q r ;;;\n s t u ; v w x]\n=> dims = (2, 3, 4)\n\n[a b ; c ;;; d ;;;;]\n ___ _ _\n 2 1 1 = elements in each row (2, 1, 1)\n _______ _\n 3 1 = elements in each column (3, 1)\n _____________\n 4 = elements in each 3d slice (4,)\n _____________\n 4 = elements in each 4d slice (4,)\n => shape = ((2, 1, 1), (3, 1), (4,), (4,)) with `rowfirst` = true\n\n\n\n\n\n","category":"function"},{"location":"base/arrays/#Base.vect","page":"数组","title":"Base.vect","text":"vect(X...)\n\nCreate a Vector with element type computed from the promote_typeof of the argument, containing the argument list.\n\nExamples\n\njulia> a = Base.vect(UInt8(1), 2.5, 1//2)\n3-element Vector{Float64}:\n 1.0\n 2.5\n 0.5\n\n\n\n\n\n","category":"function"},{"location":"base/arrays/#Base.circshift","page":"数组","title":"Base.circshift","text":"circshift(A, shifts)\n\nCircularly shift, i.e. rotate, the data in an array. The second argument is a tuple or vector giving the amount to shift in each dimension, or an integer to shift only in the first dimension.\n\nSee also: circshift!, circcopy!, bitrotate, <<.\n\nExamples\n\njulia> b = reshape(Vector(1:16), (4,4))\n4×4 Matrix{Int64}:\n 1 5 9 13\n 2 6 10 14\n 3 7 11 15\n 4 8 12 16\n\njulia> circshift(b, (0,2))\n4×4 Matrix{Int64}:\n 9 13 1 5\n 10 14 2 6\n 11 15 3 7\n 12 16 4 8\n\njulia> circshift(b, (-1,0))\n4×4 Matrix{Int64}:\n 2 6 10 14\n 3 7 11 15\n 4 8 12 16\n 1 5 9 13\n\njulia> a = BitArray([true, true, false, false, true])\n5-element BitVector:\n 1\n 1\n 0\n 0\n 1\n\njulia> circshift(a, 1)\n5-element BitVector:\n 1\n 1\n 1\n 0\n 0\n\njulia> circshift(a, -1)\n5-element BitVector:\n 1\n 0\n 0\n 1\n 1\n\n\n\n\n\n","category":"function"},{"location":"base/arrays/#Base.circshift!","page":"数组","title":"Base.circshift!","text":"circshift!(dest, src, shifts)\n\nCircularly shift, i.e. rotate, the data in src, storing the result in dest. shifts specifies the amount to shift in each dimension.\n\nThe dest array must be distinct from the src array (they cannot alias each other).\n\nSee also circshift.\n\n\n\n\n\n","category":"function"},{"location":"base/arrays/#Base.circcopy!","page":"数组","title":"Base.circcopy!","text":"circcopy!(dest, src)\n\nCopy src to dest, indexing each dimension modulo its length. src and dest must have the same size, but can be offset in their indices; any offset results in a (circular) wraparound. If the arrays have overlapping indices, then on the domain of the overlap dest agrees with src.\n\nSee also: circshift.\n\nExamples\n\njulia> src = reshape(Vector(1:16), (4,4))\n4×4 Array{Int64,2}:\n 1 5 9 13\n 2 6 10 14\n 3 7 11 15\n 4 8 12 16\n\njulia> dest = OffsetArray{Int}(undef, (0:3,2:5))\n\njulia> circcopy!(dest, src)\nOffsetArrays.OffsetArray{Int64,2,Array{Int64,2}} with indices 0:3×2:5:\n 8 12 16 4\n 5 9 13 1\n 6 10 14 2\n 7 11 15 3\n\njulia> dest[1:3,2:4] == src[1:3,2:4]\ntrue\n\n\n\n\n\n","category":"function"},{"location":"base/arrays/#Base.findall-Tuple{Any}","page":"数组","title":"Base.findall","text":"findall(A)\n\nReturn a vector I of the true indices or keys of A. If there are no such elements of A, return an empty array. To search for other kinds of values, pass a predicate as the first argument.\n\nIndices or keys are of the same type as those returned by keys(A) and pairs(A).\n\nSee also: findfirst, searchsorted.\n\nExamples\n\njulia> A = [true, false, false, true]\n4-element Vector{Bool}:\n 1\n 0\n 0\n 1\n\njulia> findall(A)\n2-element Vector{Int64}:\n 1\n 4\n\njulia> A = [true false; false true]\n2×2 Matrix{Bool}:\n 1 0\n 0 1\n\njulia> findall(A)\n2-element Vector{CartesianIndex{2}}:\n CartesianIndex(1, 1)\n CartesianIndex(2, 2)\n\njulia> findall(falses(3))\nInt64[]\n\n\n\n\n\n","category":"method"},{"location":"base/arrays/#Base.findall-Tuple{Function, Any}","page":"数组","title":"Base.findall","text":"findall(f::Function, A)\n\nReturn a vector I of the indices or keys of A where f(A[I]) returns true. If there are no such elements of A, return an empty array.\n\nIndices or keys are of the same type as those returned by keys(A) and pairs(A).\n\nExamples\n\njulia> x = [1, 3, 4]\n3-element Vector{Int64}:\n 1\n 3\n 4\n\njulia> findall(isodd, x)\n2-element Vector{Int64}:\n 1\n 2\n\njulia> A = [1 2 0; 3 4 0]\n2×3 Matrix{Int64}:\n 1 2 0\n 3 4 0\njulia> findall(isodd, A)\n2-element Vector{CartesianIndex{2}}:\n CartesianIndex(1, 1)\n CartesianIndex(2, 1)\n\njulia> findall(!iszero, A)\n4-element Vector{CartesianIndex{2}}:\n CartesianIndex(1, 1)\n CartesianIndex(2, 1)\n CartesianIndex(1, 2)\n CartesianIndex(2, 2)\n\njulia> d = Dict(:A => 10, :B => -1, :C => 0)\nDict{Symbol, Int64} with 3 entries:\n :A => 10\n :B => -1\n :C => 0\n\njulia> findall(x -> x >= 0, d)\n2-element Vector{Symbol}:\n :A\n :C\n\n\n\n\n\n\n","category":"method"},{"location":"base/arrays/#Base.findfirst-Tuple{Any}","page":"数组","title":"Base.findfirst","text":"findfirst(A)\n\nReturn the index or key of the first true value in A. Return nothing if no such value is found. To search for other kinds of values, pass a predicate as the first argument.\n\nIndices or keys are of the same type as those returned by keys(A) and pairs(A).\n\nSee also: findall, findnext, findlast, searchsortedfirst.\n\nExamples\n\njulia> A = [false, false, true, false]\n4-element Vector{Bool}:\n 0\n 0\n 1\n 0\n\njulia> findfirst(A)\n3\n\njulia> findfirst(falses(3)) # returns nothing, but not printed in the REPL\n\njulia> A = [false false; true false]\n2×2 Matrix{Bool}:\n 0 0\n 1 0\n\njulia> findfirst(A)\nCartesianIndex(2, 1)\n\n\n\n\n\n","category":"method"},{"location":"base/arrays/#Base.findfirst-Tuple{Function, Any}","page":"数组","title":"Base.findfirst","text":"findfirst(predicate::Function, A)\n\nReturn the index or key of the first element of A for which predicate returns true. Return nothing if there is no such element.\n\nIndices or keys are of the same type as those returned by keys(A) and pairs(A).\n\nExamples\n\njulia> A = [1, 4, 2, 2]\n4-element Vector{Int64}:\n 1\n 4\n 2\n 2\n\njulia> findfirst(iseven, A)\n2\n\njulia> findfirst(x -> x>10, A) # returns nothing, but not printed in the REPL\n\njulia> findfirst(isequal(4), A)\n2\n\njulia> A = [1 4; 2 2]\n2×2 Matrix{Int64}:\n 1 4\n 2 2\n\njulia> findfirst(iseven, A)\nCartesianIndex(2, 1)\n\n\n\n\n\n","category":"method"},{"location":"base/arrays/#Base.findlast-Tuple{Any}","page":"数组","title":"Base.findlast","text":"findlast(A)\n\nReturn the index or key of the last true value in A. Return nothing if there is no true value in A.\n\nIndices or keys are of the same type as those returned by keys(A) and pairs(A).\n\nSee also: findfirst, findprev, findall.\n\nExamples\n\njulia> A = [true, false, true, false]\n4-element Vector{Bool}:\n 1\n 0\n 1\n 0\n\njulia> findlast(A)\n3\n\njulia> A = falses(2,2);\n\njulia> findlast(A) # returns nothing, but not printed in the REPL\n\njulia> A = [true false; true false]\n2×2 Matrix{Bool}:\n 1 0\n 1 0\n\njulia> findlast(A)\nCartesianIndex(2, 1)\n\n\n\n\n\n","category":"method"},{"location":"base/arrays/#Base.findlast-Tuple{Function, Any}","page":"数组","title":"Base.findlast","text":"findlast(predicate::Function, A)\n\nReturn the index or key of the last element of A for which predicate returns true. Return nothing if there is no such element.\n\nIndices or keys are of the same type as those returned by keys(A) and pairs(A).\n\nExamples\n\njulia> A = [1, 2, 3, 4]\n4-element Vector{Int64}:\n 1\n 2\n 3\n 4\n\njulia> findlast(isodd, A)\n3\n\njulia> findlast(x -> x > 5, A) # returns nothing, but not printed in the REPL\n\njulia> A = [1 2; 3 4]\n2×2 Matrix{Int64}:\n 1 2\n 3 4\n\njulia> findlast(isodd, A)\nCartesianIndex(2, 1)\n\n\n\n\n\n","category":"method"},{"location":"base/arrays/#Base.findnext-Tuple{Any, Integer}","page":"数组","title":"Base.findnext","text":"findnext(A, i)\n\nFind the next index after or including i of a true element of A, or nothing if not found.\n\nIndices are of the same type as those returned by keys(A) and pairs(A).\n\nExamples\n\njulia> A = [false, false, true, false]\n4-element Vector{Bool}:\n 0\n 0\n 1\n 0\n\njulia> findnext(A, 1)\n3\n\njulia> findnext(A, 4) # returns nothing, but not printed in the REPL\n\njulia> A = [false false; true false]\n2×2 Matrix{Bool}:\n 0 0\n 1 0\n\njulia> findnext(A, CartesianIndex(1, 1))\nCartesianIndex(2, 1)\n\n\n\n\n\n","category":"method"},{"location":"base/arrays/#Base.findnext-Tuple{Function, Any, Integer}","page":"数组","title":"Base.findnext","text":"findnext(predicate::Function, A, i)\n\nFind the next index after or including i of an element of A for which predicate returns true, or nothing if not found.\n\nIndices are of the same type as those returned by keys(A) and pairs(A).\n\nExamples\n\njulia> A = [1, 4, 2, 2];\n\njulia> findnext(isodd, A, 1)\n1\n\njulia> findnext(isodd, A, 2) # returns nothing, but not printed in the REPL\n\njulia> A = [1 4; 2 2];\n\njulia> findnext(isodd, A, CartesianIndex(1, 1))\nCartesianIndex(1, 1)\n\n\n\n\n\n","category":"method"},{"location":"base/arrays/#Base.findprev-Tuple{Any, Integer}","page":"数组","title":"Base.findprev","text":"findprev(A, i)\n\nFind the previous index before or including i of a true element of A, or nothing if not found.\n\nIndices are of the same type as those returned by keys(A) and pairs(A).\n\nSee also: findnext, findfirst, findall.\n\nExamples\n\njulia> A = [false, false, true, true]\n4-element Vector{Bool}:\n 0\n 0\n 1\n 1\n\njulia> findprev(A, 3)\n3\n\njulia> findprev(A, 1) # returns nothing, but not printed in the REPL\n\njulia> A = [false false; true true]\n2×2 Matrix{Bool}:\n 0 0\n 1 1\n\njulia> findprev(A, CartesianIndex(2, 1))\nCartesianIndex(2, 1)\n\n\n\n\n\n","category":"method"},{"location":"base/arrays/#Base.findprev-Tuple{Function, Any, Integer}","page":"数组","title":"Base.findprev","text":"findprev(predicate::Function, A, i)\n\nFind the previous index before or including i of an element of A for which predicate returns true, or nothing if not found.\n\nIndices are of the same type as those returned by keys(A) and pairs(A).\n\nExamples\n\njulia> A = [4, 6, 1, 2]\n4-element Vector{Int64}:\n 4\n 6\n 1\n 2\n\njulia> findprev(isodd, A, 1) # returns nothing, but not printed in the REPL\n\njulia> findprev(isodd, A, 3)\n3\n\njulia> A = [4 6; 1 2]\n2×2 Matrix{Int64}:\n 4 6\n 1 2\n\njulia> findprev(isodd, A, CartesianIndex(1, 2))\nCartesianIndex(2, 1)\n\n\n\n\n\n","category":"method"},{"location":"base/arrays/#Base.permutedims","page":"数组","title":"Base.permutedims","text":"permutedims(A::AbstractArray, perm)\n\nPermute the dimensions of array A. perm is a vector or a tuple of length ndims(A) specifying the permutation.\n\nSee also permutedims!, PermutedDimsArray, transpose, invperm.\n\nExamples\n\njulia> A = reshape(Vector(1:8), (2,2,2))\n2×2×2 Array{Int64, 3}:\n[:, :, 1] =\n 1 3\n 2 4\n\n[:, :, 2] =\n 5 7\n 6 8\n\njulia> permutedims(A, (3, 2, 1))\n2×2×2 Array{Int64, 3}:\n[:, :, 1] =\n 1 3\n 5 7\n\n[:, :, 2] =\n 2 4\n 6 8\n\njulia> B = randn(5, 7, 11, 13);\n\njulia> perm = [4,1,3,2];\n\njulia> size(permutedims(B, perm))\n(13, 5, 11, 7)\n\njulia> size(B)[perm] == ans\ntrue\n\n\n\n\n\npermutedims(m::AbstractMatrix)\n\nPermute the dimensions of the matrix m, by flipping the elements across the diagonal of the matrix. Differs from LinearAlgebra's transpose in that the operation is not recursive.\n\nExamples\n\njulia> a = [1 2; 3 4];\n\njulia> b = [5 6; 7 8];\n\njulia> c = [9 10; 11 12];\n\njulia> d = [13 14; 15 16];\n\njulia> X = [[a] [b]; [c] [d]]\n2×2 Matrix{Matrix{Int64}}:\n [1 2; 3 4] [5 6; 7 8]\n [9 10; 11 12] [13 14; 15 16]\n\njulia> permutedims(X)\n2×2 Matrix{Matrix{Int64}}:\n [1 2; 3 4] [9 10; 11 12]\n [5 6; 7 8] [13 14; 15 16]\n\njulia> transpose(X)\n2×2 transpose(::Matrix{Matrix{Int64}}) with eltype Transpose{Int64, Matrix{Int64}}:\n [1 3; 2 4] [9 11; 10 12]\n [5 7; 6 8] [13 15; 14 16]\n\n\n\n\n\npermutedims(v::AbstractVector)\n\nReshape vector v into a 1 × length(v) row matrix. Differs from LinearAlgebra's transpose in that the operation is not recursive.\n\nExamples\n\njulia> permutedims([1, 2, 3, 4])\n1×4 Matrix{Int64}:\n 1 2 3 4\n\njulia> V = [[[1 2; 3 4]]; [[5 6; 7 8]]]\n2-element Vector{Matrix{Int64}}:\n [1 2; 3 4]\n [5 6; 7 8]\n\njulia> permutedims(V)\n1×2 Matrix{Matrix{Int64}}:\n [1 2; 3 4] [5 6; 7 8]\n\njulia> transpose(V)\n1×2 transpose(::Vector{Matrix{Int64}}) with eltype Transpose{Int64, Matrix{Int64}}:\n [1 3; 2 4] [5 7; 6 8]\n\n\n\n\n\n","category":"function"},{"location":"base/arrays/#Base.permutedims!","page":"数组","title":"Base.permutedims!","text":"permutedims!(dest, src, perm)\n\nPermute the dimensions of array src and store the result in the array dest. perm is a vector specifying a permutation of length ndims(src). The preallocated array dest should have size(dest) == size(src)[perm] and is completely overwritten. No in-place permutation is supported and unexpected results will happen if src and dest have overlapping memory regions.\n\nSee also permutedims.\n\n\n\n\n\n","category":"function"},{"location":"base/arrays/#Base.PermutedDimsArrays.PermutedDimsArray","page":"数组","title":"Base.PermutedDimsArrays.PermutedDimsArray","text":"PermutedDimsArray(A, perm) -> B\n\nGiven an AbstractArray A, create a view B such that the dimensions appear to be permuted. Similar to permutedims, except that no copying occurs (B shares storage with A).\n\nSee also permutedims, invperm.\n\nExamples\n\njulia> A = rand(3,5,4);\n\njulia> B = PermutedDimsArray(A, (3,1,2));\n\njulia> size(B)\n(4, 3, 5)\n\njulia> B[3,1,2] == A[1,2,3]\ntrue\n\n\n\n\n\n","category":"type"},{"location":"base/arrays/#Base.promote_shape","page":"数组","title":"Base.promote_shape","text":"promote_shape(s1, s2)\n\nCheck two array shapes for compatibility, allowing trailing singleton dimensions, and return whichever shape has more dimensions.\n\nExamples\n\njulia> a = fill(1, (3,4,1,1,1));\n\njulia> b = fill(1, (3,4));\n\njulia> promote_shape(a,b)\n(Base.OneTo(3), Base.OneTo(4), Base.OneTo(1), Base.OneTo(1), Base.OneTo(1))\n\njulia> promote_shape((2,3,1,4), (2, 3, 1, 4, 1))\n(2, 3, 1, 4, 1)\n\n\n\n\n\n","category":"function"},{"location":"base/arrays/#数组函数","page":"数组","title":"数组函数","text":"","category":"section"},{"location":"base/arrays/","page":"数组","title":"数组","text":"Base.accumulate\nBase.accumulate!\nBase.cumprod\nBase.cumprod!\nBase.cumsum\nBase.cumsum!\nBase.diff\nBase.repeat\nBase.rot180\nBase.rotl90\nBase.rotr90\nBase.mapslices\nBase.eachrow\nBase.eachcol\nBase.eachslice","category":"page"},{"location":"base/arrays/#Base.accumulate","page":"数组","title":"Base.accumulate","text":"accumulate(op, A; dims::Integer, [init])\n\nCumulative operation op along the dimension dims of A (providing dims is optional for vectors). An initial value init may optionally be provided by a keyword argument. See also accumulate! to use a preallocated output array, both for performance and to control the precision of the output (e.g. to avoid overflow).\n\nFor common operations there are specialized variants of accumulate, see cumsum, cumprod. For a lazy version, see Iterators.accumulate.\n\ncompat: Julia 1.5\naccumulate on a non-array iterator requires at least Julia 1.5.\n\nExamples\n\njulia> accumulate(+, [1,2,3])\n3-element Vector{Int64}:\n 1\n 3\n 6\n\njulia> accumulate(min, (1, -2, 3, -4, 5), init=0)\n(0, -2, -2, -4, -4)\n\njulia> accumulate(/, (2, 4, Inf), init=100)\n(50.0, 12.5, 0.0)\n\njulia> accumulate(=>, i^2 for i in 1:3)\n3-element Vector{Any}:\n 1\n 1 => 4\n (1 => 4) => 9\n\njulia> accumulate(+, fill(1, 3, 4))\n3×4 Matrix{Int64}:\n 1 4 7 10\n 2 5 8 11\n 3 6 9 12\n\njulia> accumulate(+, fill(1, 2, 5), dims=2, init=100.0)\n2×5 Matrix{Float64}:\n 101.0 102.0 103.0 104.0 105.0\n 101.0 102.0 103.0 104.0 105.0\n\n\n\n\n\n","category":"function"},{"location":"base/arrays/#Base.accumulate!","page":"数组","title":"Base.accumulate!","text":"accumulate!(op, B, A; [dims], [init])\n\nCumulative operation op on A along the dimension dims, storing the result in B. Providing dims is optional for vectors. If the keyword argument init is given, its value is used to instantiate the accumulation.\n\nSee also accumulate, cumsum!, cumprod!.\n\nExamples\n\njulia> x = [1, 0, 2, 0, 3];\n\njulia> y = rand(5);\n\njulia> accumulate!(+, y, x);\n\njulia> y\n5-element Vector{Float64}:\n 1.0\n 1.0\n 3.0\n 3.0\n 6.0\n\njulia> A = [1 2 3; 4 5 6];\n\njulia> B = similar(A);\n\njulia> accumulate!(-, B, A, dims=1)\n2×3 Matrix{Int64}:\n 1 2 3\n -3 -3 -3\n\njulia> accumulate!(*, B, A, dims=2, init=10)\n2×3 Matrix{Int64}:\n 10 20 60\n 40 200 1200\n\n\n\n\n\n","category":"function"},{"location":"base/arrays/#Base.cumprod","page":"数组","title":"Base.cumprod","text":"cumprod(A; dims::Integer)\n\nCumulative product along the dimension dim. See also cumprod! to use a preallocated output array, both for performance and to control the precision of the output (e.g. to avoid overflow).\n\nExamples\n\njulia> a = Int8[1 2 3; 4 5 6];\n\njulia> cumprod(a, dims=1)\n2×3 Matrix{Int64}:\n 1 2 3\n 4 10 18\n\njulia> cumprod(a, dims=2)\n2×3 Matrix{Int64}:\n 1 2 6\n 4 20 120\n\n\n\n\n\ncumprod(itr)\n\nCumulative product of an iterator.\n\nSee also cumprod!, accumulate, cumsum.\n\ncompat: Julia 1.5\ncumprod on a non-array iterator requires at least Julia 1.5.\n\nExamples\n\njulia> cumprod(fill(1//2, 3))\n3-element Vector{Rational{Int64}}:\n 1//2\n 1//4\n 1//8\n\njulia> cumprod((1, 2, 1, 3, 1))\n(1, 2, 2, 6, 6)\n\njulia> cumprod(\"julia\")\n5-element Vector{String}:\n \"j\"\n \"ju\"\n \"jul\"\n \"juli\"\n \"julia\"\n\n\n\n\n\n","category":"function"},{"location":"base/arrays/#Base.cumprod!","page":"数组","title":"Base.cumprod!","text":"cumprod!(B, A; dims::Integer)\n\nCumulative product of A along the dimension dims, storing the result in B. See also cumprod.\n\n\n\n\n\ncumprod!(y::AbstractVector, x::AbstractVector)\n\nCumulative product of a vector x, storing the result in y. See also cumprod.\n\n\n\n\n\n","category":"function"},{"location":"base/arrays/#Base.cumsum","page":"数组","title":"Base.cumsum","text":"cumsum(A; dims::Integer)\n\nCumulative sum along the dimension dims. See also cumsum! to use a preallocated output array, both for performance and to control the precision of the output (e.g. to avoid overflow).\n\nExamples\n\njulia> a = [1 2 3; 4 5 6]\n2×3 Matrix{Int64}:\n 1 2 3\n 4 5 6\n\njulia> cumsum(a, dims=1)\n2×3 Matrix{Int64}:\n 1 2 3\n 5 7 9\n\njulia> cumsum(a, dims=2)\n2×3 Matrix{Int64}:\n 1 3 6\n 4 9 15\n\nnote: Note\nThe return array's eltype is Int for signed integers of less than system word size and UInt for unsigned integers of less than system word size. To preserve eltype of arrays with small signed or unsigned integer accumulate(+, A) should be used.julia> cumsum(Int8[100, 28])\n2-element Vector{Int64}:\n 100\n 128\n\njulia> accumulate(+,Int8[100, 28])\n2-element Vector{Int8}:\n 100\n -128In the former case, the integers are widened to system word size and therefore the result is Int64[100, 128]. In the latter case, no such widening happens and integer overflow results in Int8[100, -128].\n\n\n\n\n\ncumsum(itr)\n\nCumulative sum of an iterator.\n\nSee also accumulate to apply functions other than +.\n\ncompat: Julia 1.5\ncumsum on a non-array iterator requires at least Julia 1.5.\n\nExamples\n\njulia> cumsum(1:3)\n3-element Vector{Int64}:\n 1\n 3\n 6\n\njulia> cumsum((true, false, true, false, true))\n(1, 1, 2, 2, 3)\n\njulia> cumsum(fill(1, 2) for i in 1:3)\n3-element Vector{Vector{Int64}}:\n [1, 1]\n [2, 2]\n [3, 3]\n\n\n\n\n\n","category":"function"},{"location":"base/arrays/#Base.cumsum!","page":"数组","title":"Base.cumsum!","text":"cumsum!(B, A; dims::Integer)\n\nCumulative sum of A along the dimension dims, storing the result in B. See also cumsum.\n\n\n\n\n\n","category":"function"},{"location":"base/arrays/#Base.diff","page":"数组","title":"Base.diff","text":"diff(A::AbstractVector)\ndiff(A::AbstractArray; dims::Integer)\n\nFinite difference operator on a vector or a multidimensional array A. In the latter case the dimension to operate on needs to be specified with the dims keyword argument.\n\ncompat: Julia 1.1\ndiff for arrays with dimension higher than 2 requires at least Julia 1.1.\n\nExamples\n\njulia> a = [2 4; 6 16]\n2×2 Matrix{Int64}:\n 2 4\n 6 16\n\njulia> diff(a, dims=2)\n2×1 Matrix{Int64}:\n 2\n 10\n\njulia> diff(vec(a))\n3-element Vector{Int64}:\n 4\n -2\n 12\n\n\n\n\n\n","category":"function"},{"location":"base/arrays/#Base.repeat","page":"数组","title":"Base.repeat","text":"repeat(A::AbstractArray, counts::Integer...)\n\nConstruct an array by repeating array A a given number of times in each dimension, specified by counts.\n\nSee also: fill, Iterators.repeated, Iterators.cycle.\n\nExamples\n\njulia> repeat([1, 2, 3], 2)\n6-element Vector{Int64}:\n 1\n 2\n 3\n 1\n 2\n 3\n\njulia> repeat([1, 2, 3], 2, 3)\n6×3 Matrix{Int64}:\n 1 1 1\n 2 2 2\n 3 3 3\n 1 1 1\n 2 2 2\n 3 3 3\n\n\n\n\n\nrepeat(A::AbstractArray; inner=ntuple(Returns(1), ndims(A)), outer=ntuple(Returns(1), ndims(A)))\n\nConstruct an array by repeating the entries of A. The i-th element of inner specifies the number of times that the individual entries of the i-th dimension of A should be repeated. The i-th element of outer specifies the number of times that a slice along the i-th dimension of A should be repeated. If inner or outer are omitted, no repetition is performed.\n\nExamples\n\njulia> repeat(1:2, inner=2)\n4-element Vector{Int64}:\n 1\n 1\n 2\n 2\n\njulia> repeat(1:2, outer=2)\n4-element Vector{Int64}:\n 1\n 2\n 1\n 2\n\njulia> repeat([1 2; 3 4], inner=(2, 1), outer=(1, 3))\n4×6 Matrix{Int64}:\n 1 2 1 2 1 2\n 1 2 1 2 1 2\n 3 4 3 4 3 4\n 3 4 3 4 3 4\n\n\n\n\n\nrepeat(s::AbstractString, r::Integer)\n\nRepeat a string r times. This can be written as s^r.\n\nSee also ^.\n\nExamples\n\njulia> repeat(\"ha\", 3)\n\"hahaha\"\n\n\n\n\n\nrepeat(c::AbstractChar, r::Integer) -> String\n\nRepeat a character r times. This can equivalently be accomplished by calling c^r.\n\nExamples\n\njulia> repeat('A', 3)\n\"AAA\"\n\n\n\n\n\n","category":"function"},{"location":"base/arrays/#Base.rot180","page":"数组","title":"Base.rot180","text":"rot180(A)\n\nRotate matrix A 180 degrees.\n\nExamples\n\njulia> a = [1 2; 3 4]\n2×2 Matrix{Int64}:\n 1 2\n 3 4\n\njulia> rot180(a)\n2×2 Matrix{Int64}:\n 4 3\n 2 1\n\n\n\n\n\nrot180(A, k)\n\nRotate matrix A 180 degrees an integer k number of times. If k is even, this is equivalent to a copy.\n\nExamples\n\njulia> a = [1 2; 3 4]\n2×2 Matrix{Int64}:\n 1 2\n 3 4\n\njulia> rot180(a,1)\n2×2 Matrix{Int64}:\n 4 3\n 2 1\n\njulia> rot180(a,2)\n2×2 Matrix{Int64}:\n 1 2\n 3 4\n\n\n\n\n\n","category":"function"},{"location":"base/arrays/#Base.rotl90","page":"数组","title":"Base.rotl90","text":"rotl90(A)\n\nRotate matrix A left 90 degrees.\n\nExamples\n\njulia> a = [1 2; 3 4]\n2×2 Matrix{Int64}:\n 1 2\n 3 4\n\njulia> rotl90(a)\n2×2 Matrix{Int64}:\n 2 4\n 1 3\n\n\n\n\n\nrotl90(A, k)\n\nLeft-rotate matrix A 90 degrees counterclockwise an integer k number of times. If k is a multiple of four (including zero), this is equivalent to a copy.\n\nExamples\n\njulia> a = [1 2; 3 4]\n2×2 Matrix{Int64}:\n 1 2\n 3 4\n\njulia> rotl90(a,1)\n2×2 Matrix{Int64}:\n 2 4\n 1 3\n\njulia> rotl90(a,2)\n2×2 Matrix{Int64}:\n 4 3\n 2 1\n\njulia> rotl90(a,3)\n2×2 Matrix{Int64}:\n 3 1\n 4 2\n\njulia> rotl90(a,4)\n2×2 Matrix{Int64}:\n 1 2\n 3 4\n\n\n\n\n\n","category":"function"},{"location":"base/arrays/#Base.rotr90","page":"数组","title":"Base.rotr90","text":"rotr90(A)\n\nRotate matrix A right 90 degrees.\n\nExamples\n\njulia> a = [1 2; 3 4]\n2×2 Matrix{Int64}:\n 1 2\n 3 4\n\njulia> rotr90(a)\n2×2 Matrix{Int64}:\n 3 1\n 4 2\n\n\n\n\n\nrotr90(A, k)\n\nRight-rotate matrix A 90 degrees clockwise an integer k number of times. If k is a multiple of four (including zero), this is equivalent to a copy.\n\nExamples\n\njulia> a = [1 2; 3 4]\n2×2 Matrix{Int64}:\n 1 2\n 3 4\n\njulia> rotr90(a,1)\n2×2 Matrix{Int64}:\n 3 1\n 4 2\n\njulia> rotr90(a,2)\n2×2 Matrix{Int64}:\n 4 3\n 2 1\n\njulia> rotr90(a,3)\n2×2 Matrix{Int64}:\n 2 4\n 1 3\n\njulia> rotr90(a,4)\n2×2 Matrix{Int64}:\n 1 2\n 3 4\n\n\n\n\n\n","category":"function"},{"location":"base/arrays/#Base.mapslices","page":"数组","title":"Base.mapslices","text":"mapslices(f, A; dims)\n\nTransform the given dimensions of array A using function f. f is called on each slice of A of the form A[...,:,...,:,...]. dims is an integer vector specifying where the colons go in this expression. The results are concatenated along the remaining dimensions. For example, if dims is [1,2] and A is 4-dimensional, f is called on A[:,:,i,j] for all i and j.\n\nSee also eachcol, eachslice.\n\nExamples\n\njulia> a = reshape(Vector(1:16),(2,2,2,2))\n2×2×2×2 Array{Int64, 4}:\n[:, :, 1, 1] =\n 1 3\n 2 4\n\n[:, :, 2, 1] =\n 5 7\n 6 8\n\n[:, :, 1, 2] =\n 9 11\n 10 12\n\n[:, :, 2, 2] =\n 13 15\n 14 16\n\njulia> mapslices(sum, a, dims = [1,2])\n1×1×2×2 Array{Int64, 4}:\n[:, :, 1, 1] =\n 10\n\n[:, :, 2, 1] =\n 26\n\n[:, :, 1, 2] =\n 42\n\n[:, :, 2, 2] =\n 58\n\n\n\n\n\n","category":"function"},{"location":"base/arrays/#Base.eachrow","page":"数组","title":"Base.eachrow","text":"eachrow(A::AbstractVecOrMat)\n\nCreate a generator that iterates over the first dimension of vector or matrix A, returning the rows as AbstractVector views.\n\nSee also eachcol, eachslice, mapslices.\n\ncompat: Julia 1.1\nThis function requires at least Julia 1.1.\n\nExample\n\njulia> a = [1 2; 3 4]\n2×2 Matrix{Int64}:\n 1 2\n 3 4\n\njulia> first(eachrow(a))\n2-element view(::Matrix{Int64}, 1, :) with eltype Int64:\n 1\n 2\n\njulia> collect(eachrow(a))\n2-element Vector{SubArray{Int64, 1, Matrix{Int64}, Tuple{Int64, Base.Slice{Base.OneTo{Int64}}}, true}}:\n [1, 2]\n [3, 4]\n\n\n\n\n\n","category":"function"},{"location":"base/arrays/#Base.eachcol","page":"数组","title":"Base.eachcol","text":"eachcol(A::AbstractVecOrMat)\n\nCreate a generator that iterates over the second dimension of matrix A, returning the columns as AbstractVector views.\n\nSee also eachrow and eachslice.\n\ncompat: Julia 1.1\nThis function requires at least Julia 1.1.\n\nExample\n\njulia> a = [1 2; 3 4]\n2×2 Matrix{Int64}:\n 1 2\n 3 4\n\njulia> first(eachcol(a))\n2-element view(::Matrix{Int64}, :, 1) with eltype Int64:\n 1\n 3\n\njulia> collect(eachcol(a))\n2-element Vector{SubArray{Int64, 1, Matrix{Int64}, Tuple{Base.Slice{Base.OneTo{Int64}}, Int64}, true}}:\n [1, 3]\n [2, 4]\n\n\n\n\n\n","category":"function"},{"location":"base/arrays/#Base.eachslice","page":"数组","title":"Base.eachslice","text":"eachslice(A::AbstractArray; dims)\n\nCreate a generator that iterates over dimensions dims of A, returning views that select all the data from the other dimensions in A.\n\nOnly a single dimension in dims is currently supported. Equivalent to (view(A,:,:,...,i,:,: ...)) for i in axes(A, dims)), where i is in position dims.\n\nSee also eachrow, eachcol, mapslices, and selectdim.\n\ncompat: Julia 1.1\nThis function requires at least Julia 1.1.\n\nExample\n\njulia> M = [1 2 3; 4 5 6; 7 8 9]\n3×3 Matrix{Int64}:\n 1 2 3\n 4 5 6\n 7 8 9\n\njulia> first(eachslice(M, dims=1))\n3-element view(::Matrix{Int64}, 1, :) with eltype Int64:\n 1\n 2\n 3\n\njulia> collect(eachslice(M, dims=2))\n3-element Vector{SubArray{Int64, 1, Matrix{Int64}, Tuple{Base.Slice{Base.OneTo{Int64}}, Int64}, true}}:\n [1, 4, 7]\n [2, 5, 8]\n [3, 6, 9]\n\n\n\n\n\n","category":"function"},{"location":"base/arrays/#组合学","page":"数组","title":"组合学","text":"","category":"section"},{"location":"base/arrays/","page":"数组","title":"数组","text":"Base.invperm\nBase.isperm\nBase.permute!(::Any, ::AbstractVector)\nBase.invpermute!\nBase.reverse(::AbstractVector; kwargs...)\nBase.reverseind\nBase.reverse!","category":"page"},{"location":"base/arrays/#Base.invperm","page":"数组","title":"Base.invperm","text":"invperm(v)\n\nReturn the inverse permutation of v. If B = A[v], then A == B[invperm(v)].\n\nSee also sortperm, invpermute!, isperm, permutedims.\n\nExamples\n\njulia> p = (2, 3, 1);\n\njulia> invperm(p)\n(3, 1, 2)\n\njulia> v = [2; 4; 3; 1];\n\njulia> invperm(v)\n4-element Vector{Int64}:\n 4\n 1\n 3\n 2\n\njulia> A = ['a','b','c','d'];\n\njulia> B = A[v]\n4-element Vector{Char}:\n 'b': ASCII/Unicode U+0062 (category Ll: Letter, lowercase)\n 'd': ASCII/Unicode U+0064 (category Ll: Letter, lowercase)\n 'c': ASCII/Unicode U+0063 (category Ll: Letter, lowercase)\n 'a': ASCII/Unicode U+0061 (category Ll: Letter, lowercase)\n\njulia> B[invperm(v)]\n4-element Vector{Char}:\n 'a': ASCII/Unicode U+0061 (category Ll: Letter, lowercase)\n 'b': ASCII/Unicode U+0062 (category Ll: Letter, lowercase)\n 'c': ASCII/Unicode U+0063 (category Ll: Letter, lowercase)\n 'd': ASCII/Unicode U+0064 (category Ll: Letter, lowercase)\n\n\n\n\n\n","category":"function"},{"location":"base/arrays/#Base.isperm","page":"数组","title":"Base.isperm","text":"isperm(v) -> Bool\n\nReturn true if v is a valid permutation.\n\nExamples\n\njulia> isperm([1; 2])\ntrue\n\njulia> isperm([1; 3])\nfalse\n\n\n\n\n\n","category":"function"},{"location":"base/arrays/#Base.permute!-Tuple{Any, AbstractVector}","page":"数组","title":"Base.permute!","text":"permute!(v, p)\n\nPermute vector v in-place, according to permutation p. No checking is done to verify that p is a permutation.\n\nTo return a new permutation, use v[p]. Note that this is generally faster than permute!(v,p) for large vectors.\n\nSee also invpermute!.\n\nExamples\n\njulia> A = [1, 1, 3, 4];\n\njulia> perm = [2, 4, 3, 1];\n\njulia> permute!(A, perm);\n\njulia> A\n4-element Vector{Int64}:\n 1\n 4\n 3\n 1\n\n\n\n\n\n","category":"method"},{"location":"base/arrays/#Base.invpermute!","page":"数组","title":"Base.invpermute!","text":"invpermute!(v, p)\n\nLike permute!, but the inverse of the given permutation is applied.\n\nExamples\n\njulia> A = [1, 1, 3, 4];\n\njulia> perm = [2, 4, 3, 1];\n\njulia> invpermute!(A, perm);\n\njulia> A\n4-element Vector{Int64}:\n 4\n 1\n 3\n 1\n\n\n\n\n\n","category":"function"},{"location":"base/arrays/#Base.reverse-Tuple{AbstractVector}","page":"数组","title":"Base.reverse","text":"reverse(A; dims=:)\n\nReverse A along dimension dims, which can be an integer (a single dimension), a tuple of integers (a tuple of dimensions) or : (reverse along all the dimensions, the default). See also reverse! for in-place reversal.\n\nExamples\n\njulia> b = Int64[1 2; 3 4]\n2×2 Matrix{Int64}:\n 1 2\n 3 4\n\njulia> reverse(b, dims=2)\n2×2 Matrix{Int64}:\n 2 1\n 4 3\n\njulia> reverse(b)\n2×2 Matrix{Int64}:\n 4 3\n 2 1\n\ncompat: Julia 1.6\nPrior to Julia 1.6, only single-integer dims are supported in reverse.\n\n\n\n\n\n","category":"method"},{"location":"base/arrays/#Base.reverseind","page":"数组","title":"Base.reverseind","text":"reverseind(v, i)\n\nGiven an index i in reverse(v), return the corresponding index in v so that v[reverseind(v,i)] == reverse(v)[i]. (This can be nontrivial in cases where v contains non-ASCII characters.)\n\nExamples\n\njulia> s = \"Julia🚀\"\n\"Julia🚀\"\n\njulia> r = reverse(s)\n\"🚀ailuJ\"\n\njulia> for i in eachindex(s)\n print(r[reverseind(r, i)])\n end\nJulia🚀\n\n\n\n\n\n","category":"function"},{"location":"base/arrays/#Base.reverse!","page":"数组","title":"Base.reverse!","text":"reverse!(v [, start=1 [, stop=length(v) ]]) -> v\n\nIn-place version of reverse.\n\nExamples\n\njulia> A = Vector(1:5)\n5-element Vector{Int64}:\n 1\n 2\n 3\n 4\n 5\n\njulia> reverse!(A);\n\njulia> A\n5-element Vector{Int64}:\n 5\n 4\n 3\n 2\n 1\n\n\n\n\n\nreverse!(A; dims=:)\n\nLike reverse, but operates in-place in A.\n\ncompat: Julia 1.6\nMultidimensional reverse! requires Julia 1.6.\n\n\n\n\n\n","category":"function"},{"location":"manual/handling-operating-system-variation/#处理操作系统差异","page":"处理操作系统差异","title":"处理操作系统差异","text":"","category":"section"},{"location":"manual/handling-operating-system-variation/","page":"处理操作系统差异","title":"处理操作系统差异","text":"当编写跨平台的应用或库时,通常需要考虑到操作系统之间的差异。变量 Sys.KERNEL 可以用于这些场合。在 Sys 模块中有一些函数将会使这些事情更加简单:isunix、 islinux、isapple、isbsd、isfreebsd 以及 iswindows。这些函数可以按如下方式使用:","category":"page"},{"location":"manual/handling-operating-system-variation/","page":"处理操作系统差异","title":"处理操作系统差异","text":"if Sys.iswindows()\n windows_specific_thing(a)\nend","category":"page"},{"location":"manual/handling-operating-system-variation/","page":"处理操作系统差异","title":"处理操作系统差异","text":"注意,islinux、isapple 和 isfreebsd 是 isunix 完全互斥的子集。另外,有一个宏 @static 可以使用这些函数有条件地隐藏无效代码,如以下示例所示。","category":"page"},{"location":"manual/handling-operating-system-variation/","page":"处理操作系统差异","title":"处理操作系统差异","text":"简单例子:","category":"page"},{"location":"manual/handling-operating-system-variation/","page":"处理操作系统差异","title":"处理操作系统差异","text":"ccall((@static Sys.iswindows() ? :_fopen : :fopen), ...)","category":"page"},{"location":"manual/handling-operating-system-variation/","page":"处理操作系统差异","title":"处理操作系统差异","text":"复杂例子:","category":"page"},{"location":"manual/handling-operating-system-variation/","page":"处理操作系统差异","title":"处理操作系统差异","text":"@static if Sys.islinux()\n linux_specific_thing(a)\nelse\n generic_thing(a)\nend","category":"page"},{"location":"manual/handling-operating-system-variation/","page":"处理操作系统差异","title":"处理操作系统差异","text":"在链式嵌套的条件表达式中(包括 if/elseif/end),@static 必须在每一层都调用(括号是可选的,但是为了可读性,建议添加)。","category":"page"},{"location":"manual/handling-operating-system-variation/","page":"处理操作系统差异","title":"处理操作系统差异","text":"@static Sys.iswindows() ? :a : (@static Sys.isapple() ? :b : :c)","category":"page"},{"location":"manual/performance-tips/#man-performance-tips","page":"性能建议","title":"性能建议","text":"","category":"section"},{"location":"manual/performance-tips/","page":"性能建议","title":"性能建议","text":"下面几节简要地介绍了一些使 Julia 代码运行得尽可能快的技巧。","category":"page"},{"location":"manual/performance-tips/#影响性能的关键代码应该在函数内部","page":"性能建议","title":"影响性能的关键代码应该在函数内部","text":"","category":"section"},{"location":"manual/performance-tips/","page":"性能建议","title":"性能建议","text":"任何对性能至关重要的代码都应该在函数内部。 由于 Julia 编译器的工作方式,函数内部的代码往往比顶层代码运行得更快。","category":"page"},{"location":"manual/performance-tips/","page":"性能建议","title":"性能建议","text":"函数的使用不仅对性能很重要:函数更可重用和可测试,并阐明正在执行哪些步骤以及它们的输入和输出是什么,[编写函数,而不仅仅是脚本](@ref)也是 Julia 的风格指南。","category":"page"},{"location":"manual/performance-tips/","page":"性能建议","title":"性能建议","text":"函数应该接收参数,而不是直接对全局变量进行操作,请参阅下一点。","category":"page"},{"location":"manual/performance-tips/#避免全局变量","page":"性能建议","title":"避免全局变量","text":"","category":"section"},{"location":"manual/performance-tips/","page":"性能建议","title":"性能建议","text":"全局变量的值和类型随时都会发生变化, 这使编译器难以优化使用全局变量的代码。 变量应该是局部的,或者尽可能作为参数传递给函数。","category":"page"},{"location":"manual/performance-tips/","page":"性能建议","title":"性能建议","text":"我们发现全局变量经常是常量,将它们声明为常量可大幅提升性能。","category":"page"},{"location":"manual/performance-tips/","page":"性能建议","title":"性能建议","text":"const DEFAULT_VAL = 0","category":"page"},{"location":"manual/performance-tips/","page":"性能建议","title":"性能建议","text":"对于非常量的全局变量可以通过在使用的时候标注它们的类型来优化。","category":"page"},{"location":"manual/performance-tips/","page":"性能建议","title":"性能建议","text":"global x = rand(1000)\n\nfunction loop_over_global()\n s = 0.0\n for i in x::Vector{Float64}\n s += i\n end\n return s\nend","category":"page"},{"location":"manual/performance-tips/","page":"性能建议","title":"性能建议","text":"一个更好的编程风格是将变量作为参数传给函数。这样可以使得代码更易复用,以及清晰的展示函数的输入和输出。","category":"page"},{"location":"manual/performance-tips/","page":"性能建议","title":"性能建议","text":"note: Note\n所有的REPL中的代码都是在全局作用域中求值的,因此在顶层的变量的定义与赋值都会成为一个全局变量。在模块的顶层作用域定义的变量也是全局变量。","category":"page"},{"location":"manual/performance-tips/","page":"性能建议","title":"性能建议","text":"在下面的REPL会话中:","category":"page"},{"location":"manual/performance-tips/","page":"性能建议","title":"性能建议","text":"julia> x = 1.0","category":"page"},{"location":"manual/performance-tips/","page":"性能建议","title":"性能建议","text":"等价于:","category":"page"},{"location":"manual/performance-tips/","page":"性能建议","title":"性能建议","text":"julia> global x = 1.0","category":"page"},{"location":"manual/performance-tips/","page":"性能建议","title":"性能建议","text":"因此,所有上文关于性能问题的讨论都适用于它们。","category":"page"},{"location":"manual/performance-tips/#使用-[@time](@ref)评估性能以及注意内存分配","page":"性能建议","title":"使用 @time评估性能以及注意内存分配","text":"","category":"section"},{"location":"manual/performance-tips/","page":"性能建议","title":"性能建议","text":"@time 宏是一个有用的性能评估工具。这里我们将重复上面全局变量的例子,但是这次移除类型声明:","category":"page"},{"location":"manual/performance-tips/","page":"性能建议","title":"性能建议","text":"julia> x = rand(1000);\n\njulia> function sum_global()\n s = 0.0\n for i in x\n s += i\n end\n return s\n end;\n\njulia> @time sum_global()\n 0.010414 seconds (9.07 k allocations: 373.448 KiB, 98.40% compilation time)\n493.6199223951192\n\njulia> @time sum_global()\n 0.000108 seconds (3.49 k allocations: 70.156 KiB)\n493.6199223951192","category":"page"},{"location":"manual/performance-tips/","page":"性能建议","title":"性能建议","text":"在第一次调用(@time sum_global())时,函数被编译。 (如果不在此会话中使用 @time,它还会编译计时所需的函数。)你不用把此次运行的结果放在心上。对于第二次运行,请注意,除了报告时间外,它还表明分配了大量内存。 我们在这里只是计算 64 位浮点数向量中所有元素的总和,因此不需要分配内存(至少不是在堆上,这就是 @time 报告的内容)。","category":"page"},{"location":"manual/performance-tips/","page":"性能建议","title":"性能建议","text":"预料之外的内存分配几乎总是表示你的代码存在问题,通常是类型稳定性问题或创建了许多小的临时数组。 因此,除了分配本身之外,你的函数的代码很可能远非最优。请认真对待此类迹象并遵循以下建议。","category":"page"},{"location":"manual/performance-tips/","page":"性能建议","title":"性能建议","text":"如果我们改为将 x 作为参数传递给函数,它不再分配内存(下面报告的分配是由于在全局范围内运行 @time 宏)并且在第一次调用后明显更快:","category":"page"},{"location":"manual/performance-tips/","page":"性能建议","title":"性能建议","text":"julia> x = rand(1000);\n\njulia> function sum_arg(x)\n s = 0.0\n for i in x\n s += i\n end\n return s\n end;\n\njulia> @time sum_arg(x)\n 0.007971 seconds (3.96 k allocations: 200.171 KiB, 99.83% compilation time)\n493.6199223951192\n\njulia> @time sum_arg(x)\n 0.000003 seconds (1 allocation: 16 bytes)\n493.6199223951192","category":"page"},{"location":"manual/performance-tips/","page":"性能建议","title":"性能建议","text":"看到的 1 allocation 来自在全局范围内运行 @time 宏本身。 如果我们改为在函数中运行计时,我们可以看到确实没有执行任何分配:","category":"page"},{"location":"manual/performance-tips/","page":"性能建议","title":"性能建议","text":"julia> time_sum(x) = @time sum_arg(x);\n\njulia> time_sum(x)\n 0.000001 seconds\n493.6199223951192","category":"page"},{"location":"manual/performance-tips/","page":"性能建议","title":"性能建议","text":"在某些情况下,你的函数可能需要将分配内存作为其操作的一部分,这比上面的简单例子复杂的多。 在这种情况下,请考虑使用下面的 工具 之一来诊断问题,或者编写一个将分配内存与算法方面分开的函数版本(请参阅 输出预分配)。","category":"page"},{"location":"manual/performance-tips/","page":"性能建议","title":"性能建议","text":"note: Note\n对于更严格的基准测试,请考虑 BenchmarkTools.jl 包,该包会多次评估函数以减少噪音。","category":"page"},{"location":"manual/performance-tips/#tools","page":"性能建议","title":"工具","text":"","category":"section"},{"location":"manual/performance-tips/","page":"性能建议","title":"性能建议","text":"Julia 及其包生态系统包括可以帮助您诊断问题和提高代码性能的工具:","category":"page"},{"location":"manual/performance-tips/","page":"性能建议","title":"性能建议","text":"Profiling 允许你测量正在运行的代码的性能并识别作为瓶颈的行。对于复杂的项目,ProfileView 包可以帮助你可视化分析结果。\nTraceur 包可以帮助你找到代码中常见的性能问题。\n预期之外的大内存分配——正如 @time、@allocated 或 Profiler(通过调用垃圾收集例程)所报告的那样——暗示你的代码可能有问题。 如果你没有看到分配的其他原因,请怀疑是类型问题。还可以使用 --track allocation=user 选项启动 Julia 并检查生成的 *.mem 文件以查看有关这些分配发生位置的信息。 参见内存分配分析。\n@code_warntype 生成代码的表示形式,这有助于查找导致类型不确定性的表达式。 请参阅下面的 @code_warntype。","category":"page"},{"location":"manual/performance-tips/#man-performance-abstract-container","page":"性能建议","title":"避免使用抽象类型参数的容器","text":"","category":"section"},{"location":"manual/performance-tips/","page":"性能建议","title":"性能建议","text":"使用参数化类型(包括数组)时,最好尽可能避免使用抽象类型进行参数化。","category":"page"},{"location":"manual/performance-tips/","page":"性能建议","title":"性能建议","text":"考虑如下:","category":"page"},{"location":"manual/performance-tips/","page":"性能建议","title":"性能建议","text":"julia> a = Real[]\nReal[]\n\njulia> push!(a, 1); push!(a, 2.0); push!(a, π)\n3-element Vector{Real}:\n 1\n 2.0\n π = 3.1415926535897...","category":"page"},{"location":"manual/performance-tips/","page":"性能建议","title":"性能建议","text":"因为 a 是一个抽象类型 Real 的数组,所以它能够保存任何 Real 值。 由于Real对象允许具有任意大小和结构,因此a必须表示为指向单独分配的Real对象的指针数组。 但是,如果我们只允许相同类型的数字,例如 Float64, a 可以更有效地存储:","category":"page"},{"location":"manual/performance-tips/","page":"性能建议","title":"性能建议","text":"julia> a = Float64[]\nFloat64[]\n\njulia> push!(a, 1); push!(a, 2.0); push!(a, π)\n3-element Vector{Float64}:\n 1.0\n 2.0\n 3.141592653589793","category":"page"},{"location":"manual/performance-tips/","page":"性能建议","title":"性能建议","text":"把数字赋值给a会即时将数字转换成Float64并且a会按照64位浮点数值的连续的块来储存,这就能高效地处理。","category":"page"},{"location":"manual/performance-tips/","page":"性能建议","title":"性能建议","text":"如果无法避免使用抽象值类型的容器,有时最好使用Any参数化以避免运行时类型检查。 例如。 IdDict{Any, Any} 的性能优于 IdDict{Type, Vector}。","category":"page"},{"location":"manual/performance-tips/","page":"性能建议","title":"性能建议","text":"也请参见在参数类型下的讨论。","category":"page"},{"location":"manual/performance-tips/#类型声明","page":"性能建议","title":"类型声明","text":"","category":"section"},{"location":"manual/performance-tips/","page":"性能建议","title":"性能建议","text":"在有可选类型声明的语言中,添加声明是使代码运行更快的原则性方法。在Julia中并不是这种情况。在Julia中,编译器都知道所有的函数参数,局部变量和表达式的类型。但是,有一些特殊的情况下声明是有帮助的。","category":"page"},{"location":"manual/performance-tips/#避免有抽象类型的字段","page":"性能建议","title":"避免有抽象类型的字段","text":"","category":"section"},{"location":"manual/performance-tips/","page":"性能建议","title":"性能建议","text":"类型能在不指定其字段的类型的情况下被声明:","category":"page"},{"location":"manual/performance-tips/","page":"性能建议","title":"性能建议","text":"julia> struct MyAmbiguousType\n a\n end","category":"page"},{"location":"manual/performance-tips/","page":"性能建议","title":"性能建议","text":"这就允许a可以是任意类型。这经常很有用,但是有个缺点:对于类型MyAmbiguousType的对象,编译器不能够生成高性能的代码。原因是编译器使用对象的类型,而非值,来确定如何构建代码。不幸的是,几乎没有信息可以从类型MyAmbiguousType的对象中推导出来:","category":"page"},{"location":"manual/performance-tips/","page":"性能建议","title":"性能建议","text":"julia> b = MyAmbiguousType(\"Hello\")\nMyAmbiguousType(\"Hello\")\n\njulia> c = MyAmbiguousType(17)\nMyAmbiguousType(17)\n\njulia> typeof(b)\nMyAmbiguousType\n\njulia> typeof(c)\nMyAmbiguousType","category":"page"},{"location":"manual/performance-tips/","page":"性能建议","title":"性能建议","text":"b 和 c 的值具有相同类型,但它们在内存中的数据的底层表示十分不同。即使你只在字段 a 中存储数值,UInt8 的内存表示与 Float64 也是不同的,这也意味着 CPU 需要使用两种不同的指令来处理它们。因为该类型中不提供所需的信息,所以必须在运行时进行这些判断。而这会降低性能。","category":"page"},{"location":"manual/performance-tips/","page":"性能建议","title":"性能建议","text":"通过声明 a 的类型,你能够做得更好。这里我们关注 a 可能是几种类型中任意一种的情况,在这种情况下,自然的一个解决方法是使用参数。例如:","category":"page"},{"location":"manual/performance-tips/","page":"性能建议","title":"性能建议","text":"julia> mutable struct MyType{T<:AbstractFloat}\n a::T\n end","category":"page"},{"location":"manual/performance-tips/","page":"性能建议","title":"性能建议","text":"比下面这种更好","category":"page"},{"location":"manual/performance-tips/","page":"性能建议","title":"性能建议","text":"julia> mutable struct MyStillAmbiguousType\n a::AbstractFloat\n end","category":"page"},{"location":"manual/performance-tips/","page":"性能建议","title":"性能建议","text":"因为第一种通过包装对象的类型指定了 a 的类型。 例如:","category":"page"},{"location":"manual/performance-tips/","page":"性能建议","title":"性能建议","text":"julia> m = MyType(3.2)\nMyType{Float64}(3.2)\n\njulia> t = MyStillAmbiguousType(3.2)\nMyStillAmbiguousType(3.2)\n\njulia> typeof(m)\nMyType{Float64}\n\njulia> typeof(t)\nMyStillAmbiguousType","category":"page"},{"location":"manual/performance-tips/","page":"性能建议","title":"性能建议","text":"字段 a 的类型可以很容易地通过 m 的类型确定,而不是通过 t 的类型确定。事实上,在 t 中是可以改变字段 a 的类型的:","category":"page"},{"location":"manual/performance-tips/","page":"性能建议","title":"性能建议","text":"julia> typeof(t.a)\nFloat64\n\njulia> t.a = 4.5f0\n4.5f0\n\njulia> typeof(t.a)\nFloat32","category":"page"},{"location":"manual/performance-tips/","page":"性能建议","title":"性能建议","text":"反之,一旦 m 被构建出来,m.a 的类型就不能够更改了。","category":"page"},{"location":"manual/performance-tips/","page":"性能建议","title":"性能建议","text":"julia> m.a = 4.5f0\n4.5f0\n\njulia> typeof(m.a)\nFloat64","category":"page"},{"location":"manual/performance-tips/","page":"性能建议","title":"性能建议","text":"m.a 的类型是通过 m 的类型得知这一事实加上它的类型不能改变在函数中改变这一事实,这两者使得对于像 m 这样的对象编译器可以生成高度优化后的代码,但是对 t 这样的对象却不可以。 当然,如果我们将 m 构造成一个具体类型,那么这两者都可以。我们可以通过明确地使用一个抽象类型去构建它来破坏这一点:","category":"page"},{"location":"manual/performance-tips/","page":"性能建议","title":"性能建议","text":"julia> m = MyType{AbstractFloat}(3.2)\nMyType{AbstractFloat}(3.2)\n\njulia> typeof(m.a)\nFloat64\n\njulia> m.a = 4.5f0\n4.5f0\n\njulia> typeof(m.a)\nFloat32","category":"page"},{"location":"manual/performance-tips/","page":"性能建议","title":"性能建议","text":"对于一个实际的目的来说,这样的对象表现起来和那些 MyStillAmbiguousType 的对象一模一样。","category":"page"},{"location":"manual/performance-tips/","page":"性能建议","title":"性能建议","text":"比较为一个简单函数生成的代码的绝对数量是十分有指导意义的,","category":"page"},{"location":"manual/performance-tips/","page":"性能建议","title":"性能建议","text":"func(m::MyType) = m.a+1","category":"page"},{"location":"manual/performance-tips/","page":"性能建议","title":"性能建议","text":"使用","category":"page"},{"location":"manual/performance-tips/","page":"性能建议","title":"性能建议","text":"code_llvm(func, Tuple{MyType{Float64}})\ncode_llvm(func, Tuple{MyType{AbstractFloat}})","category":"page"},{"location":"manual/performance-tips/","page":"性能建议","title":"性能建议","text":"由于长度的原因,代码的结果没有在这里显示出来,但是你可能会希望自己去验证这一点。因为在第一种情况中,类型被完全指定了,在运行时,编译器不需要生成任何代码来决定类型。这就带来了更短和更快的代码。","category":"page"},{"location":"manual/performance-tips/#避免使用带抽象容器的字段","page":"性能建议","title":"避免使用带抽象容器的字段","text":"","category":"section"},{"location":"manual/performance-tips/","page":"性能建议","title":"性能建议","text":"上面的做法同样也适用于容器的类型:","category":"page"},{"location":"manual/performance-tips/","page":"性能建议","title":"性能建议","text":"julia> struct MySimpleContainer{A<:AbstractVector}\n a::A\n end\n\njulia> struct MyAmbiguousContainer{T}\n a::AbstractVector{T}\n end","category":"page"},{"location":"manual/performance-tips/","page":"性能建议","title":"性能建议","text":"例如:","category":"page"},{"location":"manual/performance-tips/","page":"性能建议","title":"性能建议","text":"julia> c = MySimpleContainer(1:3);\n\njulia> typeof(c)\nMySimpleContainer{UnitRange{Int64}}\n\njulia> c = MySimpleContainer([1:3;]);\n\njulia> typeof(c)\nMySimpleContainer{Vector{Int64}}\n\njulia> b = MyAmbiguousContainer(1:3);\n\njulia> typeof(b)\nMyAmbiguousContainer{Int64}\n\njulia> b = MyAmbiguousContainer([1:3;]);\n\njulia> typeof(b)\nMyAmbiguousContainer{Int64}","category":"page"},{"location":"manual/performance-tips/","page":"性能建议","title":"性能建议","text":"对于 MySimpleContainer 来说,它被它的类型和参数完全确定了,因此编译器能够生成优化过的代码。在大多数实例中,这点能够实现。","category":"page"},{"location":"manual/performance-tips/","page":"性能建议","title":"性能建议","text":"尽管编译器现在可以将它的工作做得非常好,但是还是有你可能希望你的代码能够能够根据 a 的元素类型做不同的事情的时候。通常达成这个目的最好的方式是将你的具体操作 (here, foo) 打包到一个独立的函数中。","category":"page"},{"location":"manual/performance-tips/","page":"性能建议","title":"性能建议","text":"julia> function sumfoo(c::MySimpleContainer)\n s = 0\n for x in c.a\n s += foo(x)\n end\n s\n end\nsumfoo (generic function with 1 method)\n\njulia> foo(x::Integer) = x\nfoo (generic function with 1 method)\n\njulia> foo(x::AbstractFloat) = round(x)\nfoo (generic function with 2 methods)","category":"page"},{"location":"manual/performance-tips/","page":"性能建议","title":"性能建议","text":"这使事情变得简单,同时也允许编译器在所有情况下生成经过优化的代码。","category":"page"},{"location":"manual/performance-tips/","page":"性能建议","title":"性能建议","text":"但是,在某些情况下,你可能需要声明外部函数的不同版本,这可能是为了不同的元素类型,也可能是为了 MySimpleContainer 中的字段 a 所具有的不同 AbstractVector 类型。你可以这样做:","category":"page"},{"location":"manual/performance-tips/","page":"性能建议","title":"性能建议","text":"julia> function myfunc(c::MySimpleContainer{<:AbstractArray{<:Integer}})\n return c.a[1]+1\n end\nmyfunc (generic function with 1 method)\n\njulia> function myfunc(c::MySimpleContainer{<:AbstractArray{<:AbstractFloat}})\n return c.a[1]+2\n end\nmyfunc (generic function with 2 methods)\n\njulia> function myfunc(c::MySimpleContainer{Vector{T}}) where T <: Integer\n return c.a[1]+3\n end\nmyfunc (generic function with 3 methods)","category":"page"},{"location":"manual/performance-tips/","page":"性能建议","title":"性能建议","text":"julia> myfunc(MySimpleContainer(1:3))\n2\n\njulia> myfunc(MySimpleContainer(1.0:3))\n3.0\n\njulia> myfunc(MySimpleContainer([1:3;]))\n4","category":"page"},{"location":"manual/performance-tips/#对从无类型位置获取的值进行类型注释","page":"性能建议","title":"对从无类型位置获取的值进行类型注释","text":"","category":"section"},{"location":"manual/performance-tips/","page":"性能建议","title":"性能建议","text":"使用可能包含任何类型的值的数据结构(如类型为 Array{Any} 的数组)经常是很方便的。但是,如果你正在使用这些数据结构之一,并且恰巧知道某个元素的类型,那么让编译器也知道这一点会有所帮助:","category":"page"},{"location":"manual/performance-tips/","page":"性能建议","title":"性能建议","text":"function foo(a::Array{Any,1})\n x = a[1]::Int32\n b = x+1\n ...\nend","category":"page"},{"location":"manual/performance-tips/","page":"性能建议","title":"性能建议","text":"在这里,我们恰巧知道 a 的第一个元素是个 Int32。留下这样的注释还有另外的好处,它将在该值不是预期类型时引发运行时错误,而这可能会更早地捕获某些错误。","category":"page"},{"location":"manual/performance-tips/","page":"性能建议","title":"性能建议","text":"在没有确切知道 a[1] 的类型的情况下,x 可以通过 x = convert(Int32, a[1])::Int32 来声明。使用 convert 函数则允许 a[1] 是可转换为 Int32 的任何对象(比如 UInt8),从而通过放松类型限制来提高代码的通用性。请注意,convert 本身在此上下文中需要类型注释才能实现类型稳定性。这是因为除非该函数所有参数的类型都已知,否则编译器无法推导出该函数返回值的类型,即使其为 convert。","category":"page"},{"location":"manual/performance-tips/","page":"性能建议","title":"性能建议","text":"如果类型是抽象的或在运行时构造的,则类型注释不会增强(实际上可能会阻碍)性能。 这是因为编译器无法使用注解来特例化后续代码,并且类型检查本身需要时间。 例如,在代码中:","category":"page"},{"location":"manual/performance-tips/","page":"性能建议","title":"性能建议","text":"function nr(a, prec)\n ctype = prec == 32 ? Float32 : Float64\n b = Complex{ctype}(a)\n c = (b + 1.0f0)::Complex{ctype}\n abs(c)\nend","category":"page"},{"location":"manual/performance-tips/","page":"性能建议","title":"性能建议","text":"c 的注释会损害性能。要编写涉及在运行时构造类型的高性能代码,请使用下面讨论的 函数障碍技巧,并确保构造的类型出现在内核函数的参数类型中,以便内核操作由编译器合理地特例化。例如,在上面的代码片段中,一旦构建了 b,它就可以传递给另一个函数 k,即内核。 例如,如果函数 k 将 b 声明为类型为 Complex{T} 的参数,其中 T 是一个类型参数,那么出现在k的赋值语句中的类型注释的形式:","category":"page"},{"location":"manual/performance-tips/","page":"性能建议","title":"性能建议","text":"c = (b + 1.0f0)::Complex{T}","category":"page"},{"location":"manual/performance-tips/","page":"性能建议","title":"性能建议","text":"不会降低性能(但也不会有帮助),因为编译器可以在编译 k 时确定 c 的类型。","category":"page"},{"location":"manual/performance-tips/#Be-aware-of-when-Julia-avoids-specializing","page":"性能建议","title":"注意Julia何时避免特例化","text":"","category":"section"},{"location":"manual/performance-tips/","page":"性能建议","title":"性能建议","text":"作为一种启发式方法,Julia 避免在三种特定情况下自动特例化参数类型参数:Type、Function 和 Vararg。 当在方法中使用参数时,Julia 将始终特例化,但如果参数只是传递给另一个函数,则不会。 这通常在运行时没有性能影响并且提高编译器性能。 如果你发现它在你的案例中在运行时确实有性能影响,您可以通过向方法声明添加类型参数来触发特例化。这里有些例子:","category":"page"},{"location":"manual/performance-tips/","page":"性能建议","title":"性能建议","text":"这不会特例化:","category":"page"},{"location":"manual/performance-tips/","page":"性能建议","title":"性能建议","text":"function f_type(t) # or t::Type\n x = ones(t, 10)\n return sum(map(sin, x))\nend","category":"page"},{"location":"manual/performance-tips/","page":"性能建议","title":"性能建议","text":"但是这会:","category":"page"},{"location":"manual/performance-tips/","page":"性能建议","title":"性能建议","text":"function g_type(t::Type{T}) where T\n x = ones(T, 10)\n return sum(map(sin, x))\nend","category":"page"},{"location":"manual/performance-tips/","page":"性能建议","title":"性能建议","text":"这些不会特例化:","category":"page"},{"location":"manual/performance-tips/","page":"性能建议","title":"性能建议","text":"f_func(f, num) = ntuple(f, div(num, 2))\ng_func(g::Function, num) = ntuple(g, div(num, 2))","category":"page"},{"location":"manual/performance-tips/","page":"性能建议","title":"性能建议","text":"但是这会:","category":"page"},{"location":"manual/performance-tips/","page":"性能建议","title":"性能建议","text":"h_func(h::H, num) where {H} = ntuple(h, div(num, 2))","category":"page"},{"location":"manual/performance-tips/","page":"性能建议","title":"性能建议","text":"这不会特例化:","category":"page"},{"location":"manual/performance-tips/","page":"性能建议","title":"性能建议","text":"f_vararg(x::Int...) = tuple(x...)","category":"page"},{"location":"manual/performance-tips/","page":"性能建议","title":"性能建议","text":"但是这会:","category":"page"},{"location":"manual/performance-tips/","page":"性能建议","title":"性能建议","text":"g_vararg(x::Vararg{Int, N}) where {N} = tuple(x...)","category":"page"},{"location":"manual/performance-tips/","page":"性能建议","title":"性能建议","text":"只需要引入一个类型参数就可以强制特例化,即使其他类型不受约束。比如下面这个例子,它会特例化,并且在参数不是全部相同类型时很有用:","category":"page"},{"location":"manual/performance-tips/","page":"性能建议","title":"性能建议","text":"h_vararg(x::Vararg{Any, N}) where {N} = tuple(x...)","category":"page"},{"location":"manual/performance-tips/","page":"性能建议","title":"性能建议","text":"请注意, @code_typed 和你的朋友给你的始终是特例化的代码,即使 Julia 通常不会特例化该方法调用。如果要查看更改参数类型时是否生成特例化,则需要检查 method internals,即是否 (@which f(...)).specializations 包含相关参数的特例化。","category":"page"},{"location":"manual/performance-tips/#将函数拆分为多个定义","page":"性能建议","title":"将函数拆分为多个定义","text":"","category":"section"},{"location":"manual/performance-tips/","page":"性能建议","title":"性能建议","text":"将一个函数写成许多小的定义能让编译器直接调用最适合的代码,甚至能够直接将它内联。","category":"page"},{"location":"manual/performance-tips/","page":"性能建议","title":"性能建议","text":"这是一个真的该被写成许多小的定义的复合函数的例子:","category":"page"},{"location":"manual/performance-tips/","page":"性能建议","title":"性能建议","text":"using LinearAlgebra\n\nfunction mynorm(A)\n if isa(A, Vector)\n return sqrt(real(dot(A,A)))\n elseif isa(A, Matrix)\n return maximum(svdvals(A))\n else\n error(\"mynorm: invalid argument\")\n end\nend","category":"page"},{"location":"manual/performance-tips/","page":"性能建议","title":"性能建议","text":"这可以更简洁有效地写成:","category":"page"},{"location":"manual/performance-tips/","page":"性能建议","title":"性能建议","text":"norm(x::Vector) = sqrt(real(dot(x, x)))\nnorm(A::Matrix) = maximum(svdvals(A))","category":"page"},{"location":"manual/performance-tips/","page":"性能建议","title":"性能建议","text":"然而,应该注意的是,编译器会十分高效地优化掉编写得如同 mynorm 例子的代码中的死分支。","category":"page"},{"location":"manual/performance-tips/#编写「类型稳定的」函数","page":"性能建议","title":"编写「类型稳定的」函数","text":"","category":"section"},{"location":"manual/performance-tips/","page":"性能建议","title":"性能建议","text":"如果可能,确保函数总是返回相同类型的值是有好处的。考虑以下定义:","category":"page"},{"location":"manual/performance-tips/","page":"性能建议","title":"性能建议","text":"pos(x) = x < 0 ? 0 : x","category":"page"},{"location":"manual/performance-tips/","page":"性能建议","title":"性能建议","text":"虽然这看起来挺合法的,但问题是 0 是一个(Int 类型的)整数而 x 可能是任何类型。于是,根据 x 的值,此函数可能返回两种类型中任何一种的值。这种行为是允许的,并且在某些情况下可能是合乎需要的。但它可以很容易地以如下方式修复:","category":"page"},{"location":"manual/performance-tips/","page":"性能建议","title":"性能建议","text":"pos(x) = x < 0 ? zero(x) : x","category":"page"},{"location":"manual/performance-tips/","page":"性能建议","title":"性能建议","text":"还有 oneunit 函数,以及更通用的 oftype(x, y) 函数,它返回被转换为 x 的类型的 y。","category":"page"},{"location":"manual/performance-tips/#避免更改变量类型","page":"性能建议","title":"避免更改变量类型","text":"","category":"section"},{"location":"manual/performance-tips/","page":"性能建议","title":"性能建议","text":"类似的「类型稳定性」问题存在于在函数内重复使用的变量:","category":"page"},{"location":"manual/performance-tips/","page":"性能建议","title":"性能建议","text":"function foo()\n x = 1\n for i = 1:10\n x /= rand()\n end\n return x\nend","category":"page"},{"location":"manual/performance-tips/","page":"性能建议","title":"性能建议","text":"局部变量 x 一开始是整数,在一次循环迭代后变为浮点数(/ 运算符的结果)。这使得编译器更难优化循环体。有几种可能的解决方法:","category":"page"},{"location":"manual/performance-tips/","page":"性能建议","title":"性能建议","text":"使用 x = 1.0 初始化 x\n显式声明 x 的类型:x::Float64 = 1\n使用 x = oneunit(Float64) 进行显式的类型转换\n使用第一个循环迭代初始化,即 x = 1 / rand(),接着循环 for i = 2:10","category":"page"},{"location":"manual/performance-tips/#kernel-functions","page":"性能建议","title":"分离核心函数(又称为函数屏障)","text":"","category":"section"},{"location":"manual/performance-tips/","page":"性能建议","title":"性能建议","text":"许多函数遵循这一模式:先执行一些设置工作,再通过多次迭代来执行核心计算。如果可行,将这些核心计算放在单独的函数中是个好主意。例如,以下做作的函数返回一个数组,其类型是随机选择的。","category":"page"},{"location":"manual/performance-tips/","page":"性能建议","title":"性能建议","text":"julia> function strange_twos(n)\n a = Vector{rand(Bool) ? Int64 : Float64}(undef, n)\n for i = 1:n\n a[i] = 2\n end\n return a\n end;\n\njulia> strange_twos(3)\n3-element Vector{Int64}:\n 2\n 2\n 2","category":"page"},{"location":"manual/performance-tips/","page":"性能建议","title":"性能建议","text":"它应该这么写:","category":"page"},{"location":"manual/performance-tips/","page":"性能建议","title":"性能建议","text":"julia> function fill_twos!(a)\n for i = eachindex(a)\n a[i] = 2\n end\n end;\n\njulia> function strange_twos(n)\n a = Vector{rand(Bool) ? Int64 : Float64}(undef, n)\n fill_twos!(a)\n return a\n end;\n\njulia> strange_twos(3)\n3-element Vector{Int64}:\n 2\n 2\n 2","category":"page"},{"location":"manual/performance-tips/","page":"性能建议","title":"性能建议","text":"Julia 的编译器会在函数边界处针对参数类型特化代码,因此在原始的实现中循环期间无法得知 a 的类型(因为它是随即选择的)。于是,第二个版本通常更快,因为对于不同类型的 a,内层循环都可被重新编译为 fill_twos! 的一部分。","category":"page"},{"location":"manual/performance-tips/","page":"性能建议","title":"性能建议","text":"第二种形式通常是更好的风格,并且可以带来更多的代码的重复利用。","category":"page"},{"location":"manual/performance-tips/","page":"性能建议","title":"性能建议","text":"这个模式在 Julia Base 的几个地方中有使用。相关的例子,请参阅 abstractarray.jl 中的 vcat 和 hcat,或者 fill! 函数,我们可使用该函数而不是编写自己的 fill_twos!。","category":"page"},{"location":"manual/performance-tips/","page":"性能建议","title":"性能建议","text":"诸如 strange_twos 的函数会在处理具有不确定类型的数据时出现,例如从可能包含整数、浮点数、字符串或其它内容的输入文件中加载的数据。","category":"page"},{"location":"manual/performance-tips/#man-performance-value-type","page":"性能建议","title":"具有值作为参数的类型","text":"","category":"section"},{"location":"manual/performance-tips/","page":"性能建议","title":"性能建议","text":"比方说你想创建一个每个维度大小都是3的 N 维数组。这种数组可以这样创建:","category":"page"},{"location":"manual/performance-tips/","page":"性能建议","title":"性能建议","text":"julia> A = fill(5.0, (3, 3))\n3×3 Matrix{Float64}:\n 5.0 5.0 5.0\n 5.0 5.0 5.0\n 5.0 5.0 5.0","category":"page"},{"location":"manual/performance-tips/","page":"性能建议","title":"性能建议","text":"这个方法工作得很好:编译器可以识别出来 A 是一个 Array{Float64,2} 因为它知道填充值 (5.0::Float64) 的类型和维度 ((3, 3)::NTuple{2,Int}).","category":"page"},{"location":"manual/performance-tips/","page":"性能建议","title":"性能建议","text":"但是现在打比方说你想写一个函数,在任何一个维度下,它都创建一个 3×3×... 的数组;你可能会心动地写下一个函数","category":"page"},{"location":"manual/performance-tips/","page":"性能建议","title":"性能建议","text":"julia> function array3(fillval, N)\n fill(fillval, ntuple(d->3, N))\n end\narray3 (generic function with 1 method)\n\njulia> array3(5.0, 2)\n3×3 Matrix{Float64}:\n 5.0 5.0 5.0\n 5.0 5.0 5.0\n 5.0 5.0 5.0","category":"page"},{"location":"manual/performance-tips/","page":"性能建议","title":"性能建议","text":"这确实有用,但是(你可以自己使用 @code_warntype array3(5.0, 2) 来验证)问题是输出地类型不能被推断出来:参数 N 是一个 Int 类型的值,而且类型推断不会(也不能)提前预测它的值。这意味着使用这个函数的结果的代码在每次获取 A 时都不得不保守地检查其类型;这样的代码将会是非常缓慢的。","category":"page"},{"location":"manual/performance-tips/","page":"性能建议","title":"性能建议","text":"现在,解决此类问题的一种很好的方法是使用 函数障碍技巧。 但是,在某些情况下,你可能希望完全消除类型不稳定性。 在这种情况下,一种方法是将维度作为参数传递,例如通过 Val{T}()(参见 \"Value types\"):","category":"page"},{"location":"manual/performance-tips/","page":"性能建议","title":"性能建议","text":"julia> function array3(fillval, ::Val{N}) where N\n fill(fillval, ntuple(d->3, Val(N)))\n end\narray3 (generic function with 1 method)\n\njulia> array3(5.0, Val(2))\n3×3 Matrix{Float64}:\n 5.0 5.0 5.0\n 5.0 5.0 5.0\n 5.0 5.0 5.0","category":"page"},{"location":"manual/performance-tips/","page":"性能建议","title":"性能建议","text":"Julia 有一个特别版本的 ntuple,它接受一个 Val{::Int} 实例作为第二个参数; 通过将 N 作为类型参数传递,你可以让编译器知道它的“值”。 因此,这个版本的 array3 允许编译器预测返回类型。","category":"page"},{"location":"manual/performance-tips/","page":"性能建议","title":"性能建议","text":"然而,使用这些技术可能非常微妙。 例如,如果你从这样的函数中调用 array3 将没有任何帮助:","category":"page"},{"location":"manual/performance-tips/","page":"性能建议","title":"性能建议","text":"function call_array3(fillval, n)\n A = array3(fillval, Val(n))\nend","category":"page"},{"location":"manual/performance-tips/","page":"性能建议","title":"性能建议","text":"在这里,你又一次创造了同样的问题:编译器无法猜测 n 是什么,所以它不知道 Val(n) 的 类型。 在许多情况下,尝试使用 Val 但不正确地使用很容易使性能变差。 (只有在有效地将 Val 与函数障碍技巧结合起来的情况下,为了使内核函数更有效,才应使用上述代码。)","category":"page"},{"location":"manual/performance-tips/","page":"性能建议","title":"性能建议","text":"一个正确使用 Val 的例子是这样的:","category":"page"},{"location":"manual/performance-tips/","page":"性能建议","title":"性能建议","text":"function filter3(A::AbstractArray{T,N}) where {T,N}\n kernel = array3(1, Val(N))\n filter(A, kernel)\nend","category":"page"},{"location":"manual/performance-tips/","page":"性能建议","title":"性能建议","text":"在此示例中,N 作为参数传递,因此编译器知道其“值”。 本质上,Val(T) 仅在 T 是硬编码/i字面量 (Val(3)) 或已在类型域中指定时才起作用。","category":"page"},{"location":"manual/performance-tips/#滥用多重派发的危险(也就是更多关于以值作为参数的类型)","page":"性能建议","title":"滥用多重派发的危险(也就是更多关于以值作为参数的类型)","text":"","category":"section"},{"location":"manual/performance-tips/","page":"性能建议","title":"性能建议","text":"一旦一个人理解了多重派发,就会有一个倾向,即过度使用它并尝试将其用于所有事情。 例如,您可能会想象使用它来存储信息,例如","category":"page"},{"location":"manual/performance-tips/","page":"性能建议","title":"性能建议","text":"struct Car{Make, Model}\n year::Int\n ...more fields...\nend","category":"page"},{"location":"manual/performance-tips/","page":"性能建议","title":"性能建议","text":"然后派发到像 Car{:Honda,:Accord}(year, args...) 的对象上。","category":"page"},{"location":"manual/performance-tips/","page":"性能建议","title":"性能建议","text":"当存在以下任一情况,这可能是值得做的:","category":"page"},{"location":"manual/performance-tips/","page":"性能建议","title":"性能建议","text":"你需要对每个 Car 进行 CPU 密集型处理,如果你在编译时知道 Make 和 Model,并且将使用的不同Make或Model的总数不太大,则效率会大大提高。\n你需要处理相同类型的 Car 的同类列表,因此可以将它们全部存储在一个数组{Car{:Honda,:Accord},N} 中。","category":"page"},{"location":"manual/performance-tips/","page":"性能建议","title":"性能建议","text":"当后者成立时,处理此类同型数组的函数可以高效地特例化:Julia 预先知道每个元素的类型(容器中的所有对象都具有相同的具体类型),因此当函数被编译时, Julia 可以“查找”正确的方法调用(不需要在运行时检查),从而产生有效的代码来处理整个列表。","category":"page"},{"location":"manual/performance-tips/","page":"性能建议","title":"性能建议","text":"当这些都不成立时,你很可能不会获得任何好处;更糟糕的是,由此产生的“类型组合爆炸”将适得其反。 如果 items[i+1] 与 item[i] 的类型不同,Julia 必须在运行时查找类型,在方法表中搜索适当的方法,决定(通过类型交集)哪一个匹配,确定它是否已经被 JIT 编译(如果没有,则执行),然后进行调用。 本质上,你是在要求完整的类型系统和 JIT 编译机制在你自己的代码中基本上执行相当于 switch 语句或字典查找的操作。","category":"page"},{"location":"manual/performance-tips/","page":"性能建议","title":"性能建议","text":"在邮件列表中 可以找到一些运行时基准比较 (1) 类型派发、(2) 字典查找和 (3) “switch”语句 ","category":"page"},{"location":"manual/performance-tips/","page":"性能建议","title":"性能建议","text":"也许比运行时影响更糟糕的是编译期影响:Julia 将为每个不同的 Car{Make, Model} 编译专门的函数; 如果你有成百上千个这样的类型,那么每个接受这样一个对象作为参数的函数(从你可能自己编写的自定义 get_year 函数,到 Julia Base 中的通用 push! 函数)都将成百上千个为它编译了的变体。 这些都会增加编译代码缓存的大小、内部方法列表的长度等。对值作为参数的过度热情很容易浪费大量资源。","category":"page"},{"location":"manual/performance-tips/#man-performance-column-major","page":"性能建议","title":"沿列按内存顺序访问数组","text":"","category":"section"},{"location":"manual/performance-tips/","page":"性能建议","title":"性能建议","text":"Julia 中的多维数组以列主序存储。这意味着数组一次堆叠一列。这可使用 vec 函数或语法 [:] 来验证,如下所示(请注意,数组的顺序是 [1 3 2 4],而不是 [1 2 3 4]):","category":"page"},{"location":"manual/performance-tips/","page":"性能建议","title":"性能建议","text":"julia> x = [1 2; 3 4]\n2×2 Matrix{Int64}:\n 1 2\n 3 4\n\njulia> x[:]\n4-element Vector{Int64}:\n 1\n 3\n 2\n 4","category":"page"},{"location":"manual/performance-tips/","page":"性能建议","title":"性能建议","text":"这种对数组进行排序的约定在许多语言中都很常见,例如 Fortran、Matlab 和 R(仅举几例)。 列优先排序的替代方法是行优先排序,在其它语言中,这是 C 和 Python (numpy) 采用的约定。 在遍历数组时,记住数组的顺序会对性能产生显着的影响。 要记住的一个经验法则是,对于列优先数组,第一个索引变化最快。 本质上,这意味着如果最内层的循环索引是第一个出现在切片表达式中的,则循环会更快。 请记住,使用 : 索引数组是一个隐式循环,它迭代访问特定维度内的所有元素; 例如,提取列比提取行更快。","category":"page"},{"location":"manual/performance-tips/","page":"性能建议","title":"性能建议","text":"考虑以下人为示例。假设我们想编写一个接收 Vector 并返回方阵 Matrix 的函数,所返回方阵的行或列都用输入向量的副本填充。并假设用这些副本填充的是行还是列并不重要(也许可以很容易地相应调整剩余代码)。我们至少可以想到四种方式(除了建议的调用内置函数 repeat):","category":"page"},{"location":"manual/performance-tips/","page":"性能建议","title":"性能建议","text":"function copy_cols(x::Vector{T}) where T\n inds = axes(x, 1)\n out = similar(Array{T}, inds, inds)\n for i = inds\n out[:, i] = x\n end\n return out\nend\n\nfunction copy_rows(x::Vector{T}) where T\n inds = axes(x, 1)\n out = similar(Array{T}, inds, inds)\n for i = inds\n out[i, :] = x\n end\n return out\nend\n\nfunction copy_col_row(x::Vector{T}) where T\n inds = axes(x, 1)\n out = similar(Array{T}, inds, inds)\n for col = inds, row = inds\n out[row, col] = x[row]\n end\n return out\nend\n\nfunction copy_row_col(x::Vector{T}) where T\n inds = axes(x, 1)\n out = similar(Array{T}, inds, inds)\n for row = inds, col = inds\n out[row, col] = x[col]\n end\n return out\nend","category":"page"},{"location":"manual/performance-tips/","page":"性能建议","title":"性能建议","text":"现在,我们使用相同的 10000 乘 1 的随机输入向量来对这些函数计时。","category":"page"},{"location":"manual/performance-tips/","page":"性能建议","title":"性能建议","text":"julia> x = randn(10000);\n\njulia> fmt(f) = println(rpad(string(f)*\": \", 14, ' '), @elapsed f(x))\n\njulia> map(fmt, [copy_cols, copy_rows, copy_col_row, copy_row_col]);\ncopy_cols: 0.331706323\ncopy_rows: 1.799009911\ncopy_col_row: 0.415630047\ncopy_row_col: 1.721531501","category":"page"},{"location":"manual/performance-tips/","page":"性能建议","title":"性能建议","text":"请注意,copy_cols 比 copy_rows 快得多。这与预料的一致,因为 copy_cols 尊重 Matrix 基于列的内存布局。另外,copy_col_row 比 copy_row_col 快得多,因为它遵循我们的经验法则,即切片表达式中出现的第一个元素应该与最内层循环耦合。","category":"page"},{"location":"manual/performance-tips/#Pre-allocating-outputs","page":"性能建议","title":"输出预分配","text":"","category":"section"},{"location":"manual/performance-tips/","page":"性能建议","title":"性能建议","text":"如果函数返回 Array 或其它复杂类型,则可能需要分配内存。不幸的是,内存分配及其反面垃圾收集通常是很大的瓶颈。","category":"page"},{"location":"manual/performance-tips/","page":"性能建议","title":"性能建议","text":"有时,你可以通过预分配输出结果来避免在每个函数调用上分配内存的需要。作为一个简单的例子,比较","category":"page"},{"location":"manual/performance-tips/","page":"性能建议","title":"性能建议","text":"julia> function xinc(x)\n return [x, x+1, x+2]\n end;\n\njulia> function loopinc()\n y = 0\n for i = 1:10^7\n ret = xinc(i)\n y += ret[2]\n end\n return y\n end;","category":"page"},{"location":"manual/performance-tips/","page":"性能建议","title":"性能建议","text":"和","category":"page"},{"location":"manual/performance-tips/","page":"性能建议","title":"性能建议","text":"julia> function xinc!(ret::AbstractVector{T}, x::T) where T\n ret[1] = x\n ret[2] = x+1\n ret[3] = x+2\n nothing\n end;\n\njulia> function loopinc_prealloc()\n ret = Vector{Int}(undef, 3)\n y = 0\n for i = 1:10^7\n xinc!(ret, i)\n y += ret[2]\n end\n return y\n end;","category":"page"},{"location":"manual/performance-tips/","page":"性能建议","title":"性能建议","text":"计时结果:","category":"page"},{"location":"manual/performance-tips/","page":"性能建议","title":"性能建议","text":"julia> @time loopinc()\n 0.529894 seconds (40.00 M allocations: 1.490 GiB, 12.14% gc time)\n50000015000000\n\njulia> @time loopinc_prealloc()\n 0.030850 seconds (6 allocations: 288 bytes)\n50000015000000","category":"page"},{"location":"manual/performance-tips/","page":"性能建议","title":"性能建议","text":"预分配还有其它优点,例如允许调用者在算法中控制「输出」类型。在上述例子中,我们如果需要,可以传递 SubArray 而不是 Array。","category":"page"},{"location":"manual/performance-tips/","page":"性能建议","title":"性能建议","text":"极端情况下,预分配可能会使你的代码更丑陋,所以可能需要做性能测试和一些判断。但是,对于「向量化」(逐元素)函数,方便的语法 x .= f.(y) 可用于具有融合循环的 in-place 操作且无需临时数组(请参阅向量化函数的点语法)。","category":"page"},{"location":"manual/performance-tips/#点语法:融合向量化操作","page":"性能建议","title":"点语法:融合向量化操作","text":"","category":"section"},{"location":"manual/performance-tips/","page":"性能建议","title":"性能建议","text":"Julia 有特殊的点语法,它可以将任何标量函数转换为「向量化」函数调用,将任何运算符转换为「向量化」运算符,其具有的特殊性质是嵌套「点调用」是融合的:它们在语法层级被组合为单个循环,无需分配临时数组。如果你使用 .= 和类似的赋值运算符,则结果也可以 in-place 存储在预分配的数组(参见上文)。","category":"page"},{"location":"manual/performance-tips/","page":"性能建议","title":"性能建议","text":"在线性代数的上下文中,这意味着即使诸如 vector + vector 和 vector * scalar 之类的运算,使用 vector .+ vector 和 vector .* scalar 来替代也可能是有利的,因为生成的循环可与周围的计算融合。例如,考虑两个函数:","category":"page"},{"location":"manual/performance-tips/","page":"性能建议","title":"性能建议","text":"julia> f(x) = 3x.^2 + 4x + 7x.^3;\n\njulia> fdot(x) = @. 3x^2 + 4x + 7x^3 # equivalent to 3 .* x.^2 .+ 4 .* x .+ 7 .* x.^3;","category":"page"},{"location":"manual/performance-tips/","page":"性能建议","title":"性能建议","text":"f 和 fdot 都做相同的计算。但是,fdot(在 @. 宏的帮助下定义)在作用于数组时明显更快:","category":"page"},{"location":"manual/performance-tips/","page":"性能建议","title":"性能建议","text":"julia> x = rand(10^6);\n\njulia> @time f(x);\n 0.019049 seconds (16 allocations: 45.777 MiB, 18.59% gc time)\n\njulia> @time fdot(x);\n 0.002790 seconds (6 allocations: 7.630 MiB)\n\njulia> @time f.(x);\n 0.002626 seconds (8 allocations: 7.630 MiB)","category":"page"},{"location":"manual/performance-tips/","page":"性能建议","title":"性能建议","text":"也就是说,fdot(x) 的速度是 f(x) 的 10 倍,分配的内存是 f(x) 的 1/6,因为 f(x) 中的每个 * 和 + 操作都会分配一个新的临时数组并在单独的循环中执行。 (当然,如果你只做 f.(x) 那么在这个例子中它和 fdot(x) 一样快,但在许多情况下,只在表达式中写一些点比为每个向量化操作定义单独的函数更方便。)","category":"page"},{"location":"manual/performance-tips/#man-performance-views","page":"性能建议","title":"考虑对切片使用视图","text":"","category":"section"},{"location":"manual/performance-tips/","page":"性能建议","title":"性能建议","text":"在 Julia 中,像 array[1:5, :] 这样的数组“切片”表达式会创建该数据的副本(赋值的左侧除外,其中 array[1:5, :] = ... 原地对 array 的那一部分进行赋值)。 如果你在切片上执行许多操作,这对性能有好处,因为使用较小的连续副本比索引原始数组更有效。 另一方面,如果你只是对切片进行一些简单的操作,那么分配和复制操作的成本可能会很高。","category":"page"},{"location":"manual/performance-tips/","page":"性能建议","title":"性能建议","text":"另一种方法是创建数组的“视图”,它是一个数组对象(一个SubArray),它实际上就地引用了原始数组的数据,而不进行复制。(如果你写入视图,它也会修改原始数组的数据。)这可以通过调用 view 对单个切片完成,或者更简单地通过将整个表达式或代码块放入 @views 在该表达式前面。 例如:","category":"page"},{"location":"manual/performance-tips/","page":"性能建议","title":"性能建议","text":"julia> fcopy(x) = sum(x[2:end-1]);\n\njulia> @views fview(x) = sum(x[2:end-1]);\n\njulia> x = rand(10^6);\n\njulia> @time fcopy(x);\n 0.003051 seconds (3 allocations: 7.629 MB)\n\njulia> @time fview(x);\n 0.001020 seconds (1 allocation: 16 bytes)","category":"page"},{"location":"manual/performance-tips/","page":"性能建议","title":"性能建议","text":"请注意,该函数的 fview 版本提速了 3 倍且减少了内存分配。","category":"page"},{"location":"manual/performance-tips/#复制数据不总是坏的","page":"性能建议","title":"复制数据不总是坏的","text":"","category":"section"},{"location":"manual/performance-tips/","page":"性能建议","title":"性能建议","text":"数组被连续地存储在内存中,这使其可被 CPU 向量化,并且会由于缓存减少内存访问。这与建议以列序优先方式访问数组的原因相同(请参见上文)。由于不按顺序访问内存,无规律的访问方式和不连续的视图可能会大大减慢数组上的计算速度。","category":"page"},{"location":"manual/performance-tips/","page":"性能建议","title":"性能建议","text":"在对无规律访问的数据进行操作前,将其复制到连续的数组中可能带来巨大的加速,正如下例所示。其中,矩阵和向量在相乘前会访问其 800,000 个已被随机混洗的索引处的值。将视图复制到普通数组会加速乘法,即使考虑了复制操作的成本。","category":"page"},{"location":"manual/performance-tips/","page":"性能建议","title":"性能建议","text":"julia> using Random\n\njulia> x = randn(1_000_000);\n\njulia> inds = shuffle(1:1_000_000)[1:800000];\n\njulia> A = randn(50, 1_000_000);\n\njulia> xtmp = zeros(800_000);\n\njulia> Atmp = zeros(50, 800_000);\n\njulia> @time sum(view(A, :, inds) * view(x, inds))\n 0.412156 seconds (14 allocations: 960 bytes)\n-4256.759568345458\n\njulia> @time begin\n copyto!(xtmp, view(x, inds))\n copyto!(Atmp, view(A, :, inds))\n sum(Atmp * xtmp)\n end\n 0.285923 seconds (14 allocations: 960 bytes)\n-4256.759568345134","category":"page"},{"location":"manual/performance-tips/","page":"性能建议","title":"性能建议","text":"倘若副本本身的内存足够大,那么将视图复制到数组的成本可能远远超过在连续数组上执行矩阵乘法所带来的加速。","category":"page"},{"location":"manual/performance-tips/#使用-StaticArrays.jl-进行小型固定大小的向量/矩阵运算","page":"性能建议","title":"使用 StaticArrays.jl 进行小型固定大小的向量/矩阵运算","text":"","category":"section"},{"location":"manual/performance-tips/","page":"性能建议","title":"性能建议","text":"如果您的应用程序涉及许多固定大小的小(< 100 个元素)数组(即在执行之前已知大小),那么你可能需要考虑使用 [StaticArrays.jl 包](https://github.com/JuliaArrays/StaticArrays.jl)。 这个包允许你以一种避免不必要的堆分配的方式来表示这样的数组,并允许编译器为数组的大小特例化代码,例如,通过完全展开向量操作(消除循环)并将元素存储在 CPU 寄存器中。","category":"page"},{"location":"manual/performance-tips/","page":"性能建议","title":"性能建议","text":"例如,如果你正在使用 2d 几何图形进行计算,你可能会使用 2-分量向量进行许多计算。 通过使用 StaticArrays.jl 中的 SVector 类型,你可以在向量 v 和 w 上使用方便的向量符号和操作,例如 norm(3v - w),同时允许编译器将代码展开到最小,计算等效于@inbounds hypot(3v[1]-w[1], 3v[2]-w[2])。","category":"page"},{"location":"manual/performance-tips/#避免-I/0-中的字符串插值","page":"性能建议","title":"避免 I/0 中的字符串插值","text":"","category":"section"},{"location":"manual/performance-tips/","page":"性能建议","title":"性能建议","text":"将数据写入到文件(或其他 I/0 设备)中时,生成额外的中间字符串会带来开销。请不要写成这样:","category":"page"},{"location":"manual/performance-tips/","page":"性能建议","title":"性能建议","text":"println(file, \"$a $b\")","category":"page"},{"location":"manual/performance-tips/","page":"性能建议","title":"性能建议","text":"请写成这样:","category":"page"},{"location":"manual/performance-tips/","page":"性能建议","title":"性能建议","text":"println(file, a, \" \", b)","category":"page"},{"location":"manual/performance-tips/","page":"性能建议","title":"性能建议","text":"第一个版本的代码生成一个字符串,然后将其写入到文件中,而第二个版本直接将值写入到文件中。另请注意,在某些情况下,字符串插值可能更难阅读。请考虑:","category":"page"},{"location":"manual/performance-tips/","page":"性能建议","title":"性能建议","text":"println(file, \"$(f(a))$(f(b))\")","category":"page"},{"location":"manual/performance-tips/","page":"性能建议","title":"性能建议","text":"与:","category":"page"},{"location":"manual/performance-tips/","page":"性能建议","title":"性能建议","text":"println(file, f(a), f(b))","category":"page"},{"location":"manual/performance-tips/#并发执行时优化网络-I/O","page":"性能建议","title":"并发执行时优化网络 I/O","text":"","category":"section"},{"location":"manual/performance-tips/","page":"性能建议","title":"性能建议","text":"当并发地执行一个远程函数时:","category":"page"},{"location":"manual/performance-tips/","page":"性能建议","title":"性能建议","text":"using Distributed\n\nresponses = Vector{Any}(undef, nworkers())\n@sync begin\n for (idx, pid) in enumerate(workers())\n @async responses[idx] = remotecall_fetch(foo, pid, args...)\n end\nend","category":"page"},{"location":"manual/performance-tips/","page":"性能建议","title":"性能建议","text":"会快于:","category":"page"},{"location":"manual/performance-tips/","page":"性能建议","title":"性能建议","text":"using Distributed\n\nrefs = Vector{Any}(undef, nworkers())\nfor (idx, pid) in enumerate(workers())\n refs[idx] = @spawnat pid foo(args...)\nend\nresponses = [fetch(r) for r in refs]","category":"page"},{"location":"manual/performance-tips/","page":"性能建议","title":"性能建议","text":"第一种方式导致每个worker一次网络往返,而第二种方式是两次网络调用:一次 @spawnat 一次fetch (甚至是 wait)。 fetch 和wait 都是同步执行,会导致较差的性能。","category":"page"},{"location":"manual/performance-tips/#修复过期警告","page":"性能建议","title":"修复过期警告","text":"","category":"section"},{"location":"manual/performance-tips/","page":"性能建议","title":"性能建议","text":"过期的函数在内部会执行查找,以便仅打印一次相关警告。 这种额外查找可能会显著影响性能,因此应根据警告建议修复掉过期函数的所有使用。","category":"page"},{"location":"manual/performance-tips/#小技巧","page":"性能建议","title":"小技巧","text":"","category":"section"},{"location":"manual/performance-tips/","page":"性能建议","title":"性能建议","text":"有一些小的注意事项可能会帮助改善循环性能。","category":"page"},{"location":"manual/performance-tips/","page":"性能建议","title":"性能建议","text":"避免使用不必要的数组。比如,使用 x+y+z 而不是 sum([x,y,z])。\n对于复数 z,使用 abs2(z) 而不是 abs(z)^2。一般的, 对于复数参数,用 abs2 代替abs。\n对于直接截断的整除,使用 div(x,y) 而不是 trunc(x/y),使用fld(x,y) 而不是 floor(x/y),使用 cld(x,y) 而不是 ceil(x/y)。","category":"page"},{"location":"manual/performance-tips/#man-performance-annotations","page":"性能建议","title":"性能标注","text":"","category":"section"},{"location":"manual/performance-tips/","page":"性能建议","title":"性能建议","text":"有时,你可以通过承诺某些程序性质来启用更好的优化。","category":"page"},{"location":"manual/performance-tips/","page":"性能建议","title":"性能建议","text":"使用 @inbounds 来取消表达式中的数组边界检查。使用前请再三确定,如果下标越界,可能会发生崩溃或潜在的故障。\n使用 @fastmath 来允许对于实数是正确的、但是对于 IEEE 数字会导致差异的浮点数优化。使用时请多多小心,因为这可能改变数值结果。这对应于 clang 的 -ffast-math 选项。\n在 for 循环前编写 @simd 来承诺迭代是相互独立且可以重新排序的。请注意,在许多情况下,Julia 可以在没有 @simd 宏的情况下自动向量化代码;只有在这种转换原本是非法的情况下才有用,包括允许浮点数重新结合和忽略相互依赖的内存访问(@simd ivdep)等情况。此外,在断言 @simd 时要十分小心,因为错误地标注一个具有相互依赖的迭代的循环可能导致意外结果。尤其要注意的是,某些 AbstractArray 子类型的 setindex! 本质上依赖于迭代顺序。此功能是实验性的,在 Julia 未来的版本中可能会更改或消失。","category":"page"},{"location":"manual/performance-tips/","page":"性能建议","title":"性能建议","text":"如果 Array 使用非常规索引,那么使用 1:n 索引到 AbstractArray 的常见习惯用法是不安全的,如果关闭边界检查,可能会导致段错误。请改用LinearIndices(x) 或eachindex(x)(另请参阅具有自定义索引的数组)。","category":"page"},{"location":"manual/performance-tips/","page":"性能建议","title":"性能建议","text":"note: Note\n虽然 @simd 需要直接放在最内层 for 循环前面,但 @inbounds 和 @fastmath 都可作用于单个表达式或在嵌套代码块中出现的所有表达式,例如,可使用 @inbounds begin 或 @inbounds for ...。","category":"page"},{"location":"manual/performance-tips/","page":"性能建议","title":"性能建议","text":"下面是一个具有 @inbounds 和 @simd 标记的例子(我们这里使用 @noinline 来防止因优化器过于智能而破坏我们的基准测试):","category":"page"},{"location":"manual/performance-tips/","page":"性能建议","title":"性能建议","text":"@noinline function inner(x, y)\n s = zero(eltype(x))\n for i=eachindex(x)\n @inbounds s += x[i]*y[i]\n end\n return s\nend\n\n@noinline function innersimd(x, y)\n s = zero(eltype(x))\n @simd for i = eachindex(x)\n @inbounds s += x[i] * y[i]\n end\n return s\nend\n\nfunction timeit(n, reps)\n x = rand(Float32, n)\n y = rand(Float32, n)\n s = zero(Float64)\n time = @elapsed for j in 1:reps\n s += inner(x, y)\n end\n println(\"GFlop/sec = \", 2n*reps / time*1E-9)\n time = @elapsed for j in 1:reps\n s += innersimd(x, y)\n end\n println(\"GFlop/sec (SIMD) = \", 2n*reps / time*1E-9)\nend\n\ntimeit(1000, 1000)","category":"page"},{"location":"manual/performance-tips/","page":"性能建议","title":"性能建议","text":"在配备 2.4GHz Intel Core i5 处理器的计算机上,其结果为:","category":"page"},{"location":"manual/performance-tips/","page":"性能建议","title":"性能建议","text":"GFlop/sec = 1.9467069505224963\nGFlop/sec (SIMD) = 17.578554163920018","category":"page"},{"location":"manual/performance-tips/","page":"性能建议","title":"性能建议","text":"(GFlop/sec 用来测试性能,数值越大越好。)","category":"page"},{"location":"manual/performance-tips/","page":"性能建议","title":"性能建议","text":"下面是一个具有三种标记的例子。此程序首先计算一个一维数组的有限差分,然后计算结果的 L2 范数:","category":"page"},{"location":"manual/performance-tips/","page":"性能建议","title":"性能建议","text":"function init!(u::Vector)\n n = length(u)\n dx = 1.0 / (n-1)\n @fastmath @inbounds @simd for i in 1:n # 通过断言 `u` 是一个 `Vector`,我们可以假定它具有 1-based 索引\n u[i] = sin(2pi*dx*i)\n end\nend\n\nfunction deriv!(u::Vector, du)\n n = length(u)\n dx = 1.0 / (n-1)\n @fastmath @inbounds du[1] = (u[2] - u[1]) / dx\n @fastmath @inbounds @simd for i in 2:n-1\n du[i] = (u[i+1] - u[i-1]) / (2*dx)\n end\n @fastmath @inbounds du[n] = (u[n] - u[n-1]) / dx\nend\n\nfunction mynorm(u::Vector)\n n = length(u)\n T = eltype(u)\n s = zero(T)\n @fastmath @inbounds @simd for i in 1:n\n s += u[i]^2\n end\n @fastmath @inbounds return sqrt(s)\nend\n\nfunction main()\n n = 2000\n u = Vector{Float64}(undef, n)\n init!(u)\n du = similar(u)\n\n deriv!(u, du)\n nu = mynorm(du)\n\n @time for i in 1:10^6\n deriv!(u, du)\n nu = mynorm(du)\n end\n\n println(nu)\nend\n\nmain()","category":"page"},{"location":"manual/performance-tips/","page":"性能建议","title":"性能建议","text":"在配备 2.7 GHz Intel Core i7 处理器的计算机上,其结果为:","category":"page"},{"location":"manual/performance-tips/","page":"性能建议","title":"性能建议","text":"$ julia wave.jl;\n 1.207814709 seconds\n4.443986180758249\n\n$ julia --math-mode=ieee wave.jl;\n 4.487083643 seconds\n4.443986180758249","category":"page"},{"location":"manual/performance-tips/","page":"性能建议","title":"性能建议","text":"在这里,选项 --math-mode=ieee 禁用 @fastmath 宏,好让我们可以比较结果。","category":"page"},{"location":"manual/performance-tips/","page":"性能建议","title":"性能建议","text":"在这种情况下,@fastmath 加速了大约 3.7 倍。这非常大——通常来说,加速会更小。(在这个特定的例子中,基准测试的工作集足够小,可以放在该处理器的 L1 缓存中,因此内存访问延迟不起作用,计算时间主要由 CPU 使用率决定。在许多现实世界的程序中,情况并非如此。)此外,在这种情况下,此优化不会改变计算结果——通常来说,结果会略有不同。在某些情况下,尤其是数值不稳定的算法,计算结果可能会差很多。","category":"page"},{"location":"manual/performance-tips/","page":"性能建议","title":"性能建议","text":"标注 @fastmath 会重新排列浮点数表达式,例如更改求值顺序,或者假设某些特殊情况(如 inf、nan)不出现。在这种情况中(以及在这个特定的计算机上),主要区别是函数 deriv 中的表达式 1 / (2*dx) 会被提升出循环(即在循环外计算),就像编写了 idx = 1 / (2*dx),然后,在循环中,表达式 ... / (2*dx) 变为 ... * idx,后者计算起来快得多。当然,编译器实际上采用的优化以及由此产生的加速都在很大程度上取决于硬件。你可以使用 Julia 的 code_native 函数来检查所生成代码的更改。","category":"page"},{"location":"manual/performance-tips/","page":"性能建议","title":"性能建议","text":"请注意,@fastmath 也假设了在计算中不会出现 NaN,这可能导致意想不到的行为:","category":"page"},{"location":"manual/performance-tips/","page":"性能建议","title":"性能建议","text":"julia> f(x) = isnan(x);\n\njulia> f(NaN)\ntrue\n\njulia> f_fast(x) = @fastmath isnan(x);\n\njulia> f_fast(NaN)\nfalse","category":"page"},{"location":"manual/performance-tips/#将次正规数视为零","page":"性能建议","title":"将次正规数视为零","text":"","category":"section"},{"location":"manual/performance-tips/","page":"性能建议","title":"性能建议","text":"次正规数,以前称为 非正规数,在许多情况下都很有用,但会在某些硬件上造成性能损失。 调用 set_zero_subnormals(true) 授予浮点运算权限,将次正规输入或输出视为零,这可能会提高某些硬件的性能。 调用 set_zero_subnormals(false) 对次正规数强制执行严格的 IEEE 行为。","category":"page"},{"location":"manual/performance-tips/","page":"性能建议","title":"性能建议","text":"下面是一个示例,其中次正规数显着影响某些硬件的性能:","category":"page"},{"location":"manual/performance-tips/","page":"性能建议","title":"性能建议","text":"function timestep(b::Vector{T}, a::Vector{T}, Δt::T) where T\n @assert length(a)==length(b)\n n = length(b)\n b[1] = 1 # Boundary condition\n for i=2:n-1\n b[i] = a[i] + (a[i-1] - T(2)*a[i] + a[i+1]) * Δt\n end\n b[n] = 0 # Boundary condition\nend\n\nfunction heatflow(a::Vector{T}, nstep::Integer) where T\n b = similar(a)\n for t=1:div(nstep,2) # Assume nstep is even\n timestep(b,a,T(0.1))\n timestep(a,b,T(0.1))\n end\nend\n\nheatflow(zeros(Float32,10),2) # Force compilation\nfor trial=1:6\n a = zeros(Float32,1000)\n set_zero_subnormals(iseven(trial)) # Odd trials use strict IEEE arithmetic\n @time heatflow(a,1000)\nend","category":"page"},{"location":"manual/performance-tips/","page":"性能建议","title":"性能建议","text":"它的输出类似于","category":"page"},{"location":"manual/performance-tips/","page":"性能建议","title":"性能建议","text":" 0.002202 seconds (1 allocation: 4.063 KiB)\n 0.001502 seconds (1 allocation: 4.063 KiB)\n 0.002139 seconds (1 allocation: 4.063 KiB)\n 0.001454 seconds (1 allocation: 4.063 KiB)\n 0.002115 seconds (1 allocation: 4.063 KiB)\n 0.001455 seconds (1 allocation: 4.063 KiB)","category":"page"},{"location":"manual/performance-tips/","page":"性能建议","title":"性能建议","text":"注意,每个偶数迭代的速度明显更快。","category":"page"},{"location":"manual/performance-tips/","page":"性能建议","title":"性能建议","text":"这个例子产生了许多次正规数,因为a中的值变成了一个指数递减的曲线,随着时间的推移慢慢渐进趋于0。","category":"page"},{"location":"manual/performance-tips/","page":"性能建议","title":"性能建议","text":"应谨慎使用将次正规数视为零,因为这样做会破坏某些等式,例如 x-y == 0 意味着 x == y:","category":"page"},{"location":"manual/performance-tips/","page":"性能建议","title":"性能建议","text":"julia> x = 3f-38; y = 2f-38;\n\njulia> set_zero_subnormals(true); (x - y, x == y)\n(0.0f0, false)\n\njulia> set_zero_subnormals(false); (x - y, x == y)\n(1.0000001f-38, false)","category":"page"},{"location":"manual/performance-tips/","page":"性能建议","title":"性能建议","text":"在某些应用程序中,将次正规数归零的另一种方法是加入一点点噪音。 例如,不是用零初始化a,而是用以下方法初始化它:","category":"page"},{"location":"manual/performance-tips/","page":"性能建议","title":"性能建议","text":"a = rand(Float32,1000) * 1.f-9","category":"page"},{"location":"manual/performance-tips/#man-code-warntype","page":"性能建议","title":"@code_warntype","text":"","category":"section"},{"location":"manual/performance-tips/","page":"性能建议","title":"性能建议","text":"宏 @code_warntype(或其函数变体 code_warntype)有时可以帮助诊断类型相关的问题。这是一个例子:","category":"page"},{"location":"manual/performance-tips/","page":"性能建议","title":"性能建议","text":"julia> @noinline pos(x) = x < 0 ? 0 : x;\n\njulia> function f(x)\n y = pos(x)\n return sin(y*x + 1)\n end;\n\njulia> @code_warntype f(3.2)\nVariables\n #self#::Core.Const(f)\n x::Float64\n y::UNION{FLOAT64, INT64}\n\nBody::Float64\n1 ─ (y = Main.pos(x))\n│ %2 = (y * x)::Float64\n│ %3 = (%2 + 1)::Float64\n│ %4 = Main.sin(%3)::Float64\n└── return %4","category":"page"},{"location":"manual/performance-tips/","page":"性能建议","title":"性能建议","text":"理解 @code_warntype 的输出,就像理解它的同类工具 @code_lowered, @code_typed, @code_llvm 和 @code_native 一样需要一些练习。你的代码以在生成编译机器代码的过程中经过大量摘要的形式呈现。大多数表达式都由类型注释,由 ::T 表示(例如,其中 T 可能是 Float64)。 @code_warntype 最大的特点就是非具体类型用红色显示; 由于本文档是用Markdown 编写的,没有颜色,所以本文档中红色文字用大写表示。","category":"page"},{"location":"manual/performance-tips/","page":"性能建议","title":"性能建议","text":"在顶部,该函数类型推导后的返回类型显示为 Body::Float64。下一行以 Julia 的 SSA IR 形式表示了 f 的主体。被数字标记的方块表示代码中(通过 goto)跳转的目标。查看主体,你会看到首先调用了 pos,其返回值经类型推导为 Union 类型 UNION{FLOAT64, INT64} 并以大写字母显示,因为它是非具体类型。这意味着我们无法根据输入类型知道 pos 的确切返回类型。但是,无论 y 是 Float64 还是 Int64,y*x 的结果都是 Float64。最终的结果是 f(x::Float64) 在其输出中不会是类型不稳定的,即使有些中间计算是类型不稳定的。","category":"page"},{"location":"manual/performance-tips/","page":"性能建议","title":"性能建议","text":"如何使用这些信息取决于你。显然,最好将 pos 修改为类型稳定的:如果这样做,f 中的所有变量都是具体的,其性能将是最佳的。但是,在某些情况下,这种短暂的类型不稳定性可能无关紧要:例如,如果 pos 从不单独使用,那么 f 的输出(对于 Float64 输入)是类型稳定的这一事实将保护之后的代码免受类型不稳定性的传播影响。这与类型不稳定性难以或不可能修复的情况密切相关。在这些情况下,上面的建议(例如,添加类型注释并/或分解函数)是你控制类型不稳定性的「损害」的最佳工具。另请注意,即使是 Julia Base 也有类型不稳定的函数。例如,函数 findfirst 如果找到键则返回数组索引,如果没有找到键则返回 nothing,这是明显的类型不稳定性。为了更易于找到可能很重要的类型不稳定性,包含 missing 或 nothing 的 Union 会用黄色着重显示,而不是用红色。","category":"page"},{"location":"manual/performance-tips/","page":"性能建议","title":"性能建议","text":"以下示例可以帮助你解释被标记为包含非叶类型的表达式:","category":"page"},{"location":"manual/performance-tips/","page":"性能建议","title":"性能建议","text":"函数体以 Body::UNION{T1,T2}) 开头\n解释:函数具有不稳定返回类型\n建议:使返回值类型稳定,即使你必须对其进行类型注释\ninvoke Main.g(%%x::Int64)::UNION{FLOAT64, INT64}\n解释:调用类型不稳定的函数 g。\n建议:修改该函数,或在必要时对其返回值进行类型注释\ninvoke Base.getindex(%%x::Array{Any,1}, 1::Int64)::ANY\n解释:访问缺乏类型信息的数组的元素\n建议:使用具有更佳定义的类型的数组,或在必要时对访问的单个元素进行类型注释\nBase.getfield(%%x, :(:data))::ARRAY{FLOAT64,N} WHERE N\n解释:获取一个非叶子类型的字段。 在这种情况下,x 的类型,比如说 ArrayContainer,有一个字段 data::Array{T}。 但是 Array 也需要维度 N 作为具体类型。\n建议:使用类似于 Array{T,3} 或 Array{T,N} 的具体类型,其中的 N 现在是 ArrayContainer 的参数","category":"page"},{"location":"manual/performance-tips/#man-performance-captured","page":"性能建议","title":"被捕获变量的性能","text":"","category":"section"},{"location":"manual/performance-tips/","page":"性能建议","title":"性能建议","text":"请考虑以下定义内部函数的示例:","category":"page"},{"location":"manual/performance-tips/","page":"性能建议","title":"性能建议","text":"function abmult(r::Int)\n if r < 0\n r = -r\n end\n f = x -> x * r\n return f\nend","category":"page"},{"location":"manual/performance-tips/","page":"性能建议","title":"性能建议","text":"函数 abmult 返回一个函数 f,它将其参数乘以 r 的绝对值。赋值给 f 的函数称为「闭包」。内部函数还被语言用于 do 代码块和生成器表达式。","category":"page"},{"location":"manual/performance-tips/","page":"性能建议","title":"性能建议","text":"这种代码风格为语言带来了性能挑战。解析器在将其转换为较低级别的指令时,基本上通过将内部函数提取到单独的代码块来重新组织上述代码。「被捕获的」变量,比如 r,被内部函数共享,且包含它们的作用域会被提取到内部函数和外部函数皆可访问的堆分配「box」中,这是因为语言指定内部作用域中的 r 必须与外部作用域中的 r 相同,就算在外部作用域(或另一个内部函数)修改 r 后也需如此。","category":"page"},{"location":"manual/performance-tips/","page":"性能建议","title":"性能建议","text":"前一段的讨论中提到了「解析器」,也就是,包含 abmult 的模块被首次加载时发生的编译前期,而不是首次调用它的编译后期。解析器不「知道」Int 是固定类型,也不知道语句 r = -r 将一个 Int 转换为另一个 Int。类型推断的魔力在编译后期生效。","category":"page"},{"location":"manual/performance-tips/","page":"性能建议","title":"性能建议","text":"因此,解析器不知道 r 具有固定类型(Int)。一旦内部函数被创建,r 的值也不会改变(因此也不需要 box)。因此,解析器向包含具有抽象类型(比如 Any)的对象的 box 发出代码,这对于每次出现的 r 都需要运行时类型分派。这可以通过在上述函数中使用 @code_warntype 来验证。装箱和运行时的类型分派都有可能导致性能损失。","category":"page"},{"location":"manual/performance-tips/","page":"性能建议","title":"性能建议","text":"如果捕获的变量用于代码的性能关键部分,那么以下提示有助于确保它们的使用具有高效性。首先,如果已经知道被捕获的变量不会改变类型,则可以使用类型注释来显式声明类型(在变量上,而不是在右侧):","category":"page"},{"location":"manual/performance-tips/","page":"性能建议","title":"性能建议","text":"function abmult2(r0::Int)\n r::Int = r0\n if r < 0\n r = -r\n end\n f = x -> x * r\n return f\nend","category":"page"},{"location":"manual/performance-tips/","page":"性能建议","title":"性能建议","text":"类型注释部分恢复由于捕获而导致的丢失性能,因为解析器可以将具体类型与 box 中的对象相关联。更进一步,如果被捕获的变量不再需要 box(因为它不会在闭包创建后被重新分配),就可以用 let 代码块表示,如下所示。","category":"page"},{"location":"manual/performance-tips/","page":"性能建议","title":"性能建议","text":"function abmult3(r::Int)\n if r < 0\n r = -r\n end\n f = let r = r\n x -> x * r\n end\n return f\nend","category":"page"},{"location":"manual/performance-tips/","page":"性能建议","title":"性能建议","text":"let 代码块创建了一个新的变量 r,它的作用域只是内部函数。第二种技术在捕获变量存在时完全恢复了语言性能。请注意,这是编译器的一个快速发展的方面,未来的版本可能不需要依靠这种程度的程序员注释来获得性能。与此同时,一些用户提供的包(如 FastClosures)会自动插入像在 abmult3 中那样的 let 语句。","category":"page"},{"location":"manual/strings/#man-strings","page":"字符串","title":"字符串","text":"","category":"section"},{"location":"manual/strings/","page":"字符串","title":"字符串","text":"字符串是由有限个字符组成的序列。而字符在英文中一般包括字母 A,B, C 等、数字和常用的标点符号。这些字符由 ASCII 标准统一标准化并且与 0 到 127 范围内的整数一一对应。当然,还有很多非英文字符,包括 ASCII 字符在注音或其他方面的变体,例如西里尔字母和希腊字母,以及与 ASCII 和英文均完全无关的字母系统,包括阿拉伯语,中文, 希伯来语,印度语, 日本语, 和韩语。Unicode 标准对这些复杂的字符做了统一的定义,是一种大家普遍接受标准。 根据需求,写代码时可以忽略这种复杂性而只处理 ASCII 字符,也可针对可能出现的非 ASCII 文本而处理所有的字符或编码。Julia 可以简单高效地处理纯粹的 ASCII 文本以及 Unicode 文本。 甚至,在 Julia 中用 C 语言风格的代码来处理 ASCII 字符串,可以在不失性能和易读性的前提下达到预期效果。当遇到非 ASCII 文本时,Julia会优雅明确地提示错误信息而不是引入乱码。 这时,直接修改代码使其可以处理非 ASCII 数据即可。","category":"page"},{"location":"manual/strings/","page":"字符串","title":"字符串","text":"关于 Julia 的字符串类型有一些值得注意的高级特性:","category":"page"},{"location":"manual/strings/","page":"字符串","title":"字符串","text":"Julia 中用于字符串(和字符串字面量)的内置具体类型是 String。 它支持全部 Unicode 字符 通过 UTF-8 编码。(transcode 函数是 提供 Unicode 编码和其他编码转换的函数。)\n所有的字符串类型都是抽象类型 AbstractString 的子类型,而一些外部包定义了别的 AbstractString 子类型(例如为其它的编码定义的子类型)。若要定义需要字符串参数的函数,你应当声明此类型为 AbstractString 来让这函数接受任何字符串类型。\n类似 C 和 Java,但是和大多数动态语言不同的是,Julia 有优秀的表示单字符的类型,即 AbstractChar。Char 是 AbstractChar 的内置子类型,它能表示任何 Unicode 字符的 32 位原始类型(基于 UTF-8 编码)。\n如 Java 中那样,字符串不可改——任何 AbstractString 对象的值不可改变。 若要构造不同的字符串值,应当从其它字符串的部分构造一个新的字符串。\n从概念上讲,字符串是从索引到字符的部分函数:对于某些索引值,它不返回字符值,而是引发异常。这允许通过编码表示形式的字节索引来实现高效的字符串索引,而不是通过字符索引——它不能简单高效地实现可变宽度的 Unicode 字符串编码。","category":"page"},{"location":"manual/strings/#man-characters","page":"字符串","title":"字符","text":"","category":"section"},{"location":"manual/strings/","page":"字符串","title":"字符串","text":"Char 类型的值代表单个字符:它只是带有特殊文本表示法和适当算术行为的 32 位原始类型,不能转化为代表 Unicode 代码 的数值。(Julia 的包可能会定义别的 AbstractChar 子类型,比如当为了优化对其它 字符编码 的操作时)Char 类型的值以这样的方式输入和显示:","category":"page"},{"location":"manual/strings/","page":"字符串","title":"字符串","text":"julia> c = 'x'\n'x': ASCII/Unicode U+0078 (category Ll: Letter, lowercase)\n\njulia> typeof(c)\nChar","category":"page"},{"location":"manual/strings/","page":"字符串","title":"字符串","text":"你可以轻松地将 Char 转换为其对应的整数值,即 Unicode 代码:","category":"page"},{"location":"manual/strings/","page":"字符串","title":"字符串","text":"julia> c = Int('x')\n120\n\njulia> typeof(c)\nInt64","category":"page"},{"location":"manual/strings/","page":"字符串","title":"字符串","text":"在 32 位的计算机中,typeof(c) 将显示为 Int32。你可以轻松地将一个整数值转回 Char:","category":"page"},{"location":"manual/strings/","page":"字符串","title":"字符串","text":"julia> Char(120)\n'x': ASCII/Unicode U+0078 (category Ll: Letter, lowercase)","category":"page"},{"location":"manual/strings/","page":"字符串","title":"字符串","text":"并非所有的整数值都是有效的 Unicode 代码,但是为了性能,Char 的转化不会检查每个值是否有效。如果你想检查每个转换的值是否为有效值,请使用 isvalid 函数:","category":"page"},{"location":"manual/strings/","page":"字符串","title":"字符串","text":"julia> Char(0x110000)\n'\\U110000': Unicode U+110000 (category In: Invalid, too high)\n\njulia> isvalid(Char, 0x110000)\nfalse","category":"page"},{"location":"manual/strings/","page":"字符串","title":"字符串","text":"目前,有效的 Unicode 码点为,从 U+0000 至 U+D7FF,以及从 U+E000 至 U+10FFFF。 它们还未全部被赋予明确的含义,也还没必要能被程序识别;然而,所有的这些值都被认为是有效的 Unicode 字符。","category":"page"},{"location":"manual/strings/","page":"字符串","title":"字符串","text":"你可以在单引号中输入任何 Unicode 字符,通过使用 \\u 加上至多 4 个十六进制数字或者 \\U 加上至多 8 个十六进制数(最长的有效值也只需要 6 个):","category":"page"},{"location":"manual/strings/","page":"字符串","title":"字符串","text":"julia> '\\u0'\n'\\0': ASCII/Unicode U+0000 (category Cc: Other, control)\n\njulia> '\\u78'\n'x': ASCII/Unicode U+0078 (category Ll: Letter, lowercase)\n\njulia> '\\u2200'\n'∀': Unicode U+2200 (category Sm: Symbol, math)\n\njulia> '\\U10ffff'\n'\\U10ffff': Unicode U+10FFFF (category Cn: Other, not assigned)","category":"page"},{"location":"manual/strings/","page":"字符串","title":"字符串","text":"Julia 使用系统默认的区域和语言设置来确定,哪些字符可以被正确显示,哪些需要用 \\u 或 \\U 的转义来显示。除 Unicode 转义格式之外,还可以使用所有的传统 C 语言转义输入形式:","category":"page"},{"location":"manual/strings/","page":"字符串","title":"字符串","text":"julia> Int('\\0')\n0\n\njulia> Int('\\t')\n9\n\njulia> Int('\\n')\n10\n\njulia> Int('\\e')\n27\n\njulia> Int('\\x7f')\n127\n\njulia> Int('\\177')\n127","category":"page"},{"location":"manual/strings/","page":"字符串","title":"字符串","text":"你可以对 Char 的值进行比较和有限的算术运算:","category":"page"},{"location":"manual/strings/","page":"字符串","title":"字符串","text":"julia> 'A' < 'a'\ntrue\n\njulia> 'A' <= 'a' <= 'Z'\nfalse\n\njulia> 'A' <= 'X' <= 'Z'\ntrue\n\njulia> 'x' - 'a'\n23\n\njulia> 'A' + 1\n'B': ASCII/Unicode U+0042 (category Lu: Letter, uppercase)","category":"page"},{"location":"manual/strings/#字符串基础","page":"字符串","title":"字符串基础","text":"","category":"section"},{"location":"manual/strings/","page":"字符串","title":"字符串","text":"字符串字面量由双引号或三重双引号分隔:","category":"page"},{"location":"manual/strings/","page":"字符串","title":"字符串","text":"julia> str = \"Hello, world.\\n\"\n\"Hello, world.\\n\"\n\njulia> \"\"\"Contains \"quote\" characters\"\"\"\n\"Contains \\\"quote\\\" characters\"","category":"page"},{"location":"manual/strings/","page":"字符串","title":"字符串","text":"Long lines in strings can be broken up by preceding the newline with a backslash (\\):","category":"page"},{"location":"manual/strings/","page":"字符串","title":"字符串","text":"julia> \"This is a long \\\n line\"\n\"This is a long line\"","category":"page"},{"location":"manual/strings/","page":"字符串","title":"字符串","text":"如果要字符串中提取字符,可以对其进行索引:","category":"page"},{"location":"manual/strings/","page":"字符串","title":"字符串","text":"julia> str[begin]\n'H': ASCII/Unicode U+0048 (category Lu: Letter, uppercase)\n\njulia> str[1]\n'H': ASCII/Unicode U+0048 (category Lu: Letter, uppercase)\n\njulia> str[6]\n',': ASCII/Unicode U+002C (category Po: Punctuation, other)\n\njulia> str[end]\n'\\n': ASCII/Unicode U+000A (category Cc: Other, control)","category":"page"},{"location":"manual/strings/","page":"字符串","title":"字符串","text":"许多的 Julia 对象,包括字符串,都可以用整数进行索引。第一个元素的索引(字符串的第一个字符)由 firstindex(str) 返回,最后一个元素(字符)的索引由 lastindex(str) 返回。关键字 begin 和 end 可以在索引操作中使用,它们分别表示给定维度上的第一个和最后一个索引。字符串索引就像 Julia 中的大多数索引一样,是从 1 开始的:对于任何 AbstractString, firstindex 方法总是返回 1。但是,下面我们将会看到,对于一个字符串来说 lastindex(str) 和 length(str) 的结果不一定相同,因为 Unicode 字符可能由多个编码单元组成。","category":"page"},{"location":"manual/strings/","page":"字符串","title":"字符串","text":"你可以用 end 进行算术以及其它操作,就像一个普通值一样:","category":"page"},{"location":"manual/strings/","page":"字符串","title":"字符串","text":"julia> str[end-1]\n'.': ASCII/Unicode U+002E (category Po: Punctuation, other)\n\njulia> str[end÷2]\n' ': ASCII/Unicode U+0020 (category Zs: Separator, space)","category":"page"},{"location":"manual/strings/","page":"字符串","title":"字符串","text":"使用小于 begin (1) 或大于 end 的索引会引发错误:","category":"page"},{"location":"manual/strings/","page":"字符串","title":"字符串","text":"julia> str[begin-1]\nERROR: BoundsError: attempt to access 14-codeunit String at index [0]\n[...]\n\njulia> str[end+1]\nERROR: BoundsError: attempt to access 14-codeunit String at index [15]\n[...]","category":"page"},{"location":"manual/strings/","page":"字符串","title":"字符串","text":"你也可以用范围索引来提取子字符串:","category":"page"},{"location":"manual/strings/","page":"字符串","title":"字符串","text":"julia> str[4:9]\n\"lo, wo\"","category":"page"},{"location":"manual/strings/","page":"字符串","title":"字符串","text":"注意,表达式 str[k] 和 str[k:k] 不会给出相同的结果:","category":"page"},{"location":"manual/strings/","page":"字符串","title":"字符串","text":"julia> str[6]\n',': ASCII/Unicode U+002C (category Po: Punctuation, other)\n\njulia> str[6:6]\n\",\"","category":"page"},{"location":"manual/strings/","page":"字符串","title":"字符串","text":"前者是一个 Char 类型的单个字符,而后者是一个恰好只包含一个字符的字符串。在 Julia 中,这些是不同的。","category":"page"},{"location":"manual/strings/","page":"字符串","title":"字符串","text":"范围索引复制原始字符串的选定部分。此外,可以使用类型 SubString,将视图创建为字符串, 例如:","category":"page"},{"location":"manual/strings/","page":"字符串","title":"字符串","text":"julia> str = \"long string\"\n\"long string\"\n\njulia> substr = SubString(str, 1, 4)\n\"long\"\n\njulia> typeof(substr)\nSubString{String}","category":"page"},{"location":"manual/strings/","page":"字符串","title":"字符串","text":"几个标准函数,像 chop, chomp 或者 strip 都会返回一个 SubString。","category":"page"},{"location":"manual/strings/#Unicode-和-UTF-8","page":"字符串","title":"Unicode 和 UTF-8","text":"","category":"section"},{"location":"manual/strings/","page":"字符串","title":"字符串","text":"Julia 完全支持 Unicode 字符和字符串。如上所述,在字符字面量中,Unicode 代码可以用 Unicode \\u 和 \\U 转义序列表示,也可以用所有标准 C 转义序列表示。这些同样可以用来写字符串字面量:","category":"page"},{"location":"manual/strings/","page":"字符串","title":"字符串","text":"julia> s = \"\\u2200 x \\u2203 y\"\n\"∀ x ∃ y\"","category":"page"},{"location":"manual/strings/","page":"字符串","title":"字符串","text":"这些 Unicode 字符是作为转义还是特殊字符显示,取决于你终端的语言环境设置以及它对 Unicode 的支持。字符串字面量用 UTF-8 编码。UTF-8 是一种可变长度的编码,也就是说并非所有字符都以相同的字节数(code units)编码。在 UTF-8 中,ASCII 字符(小于 0x80(128) 的那些)如它们在 ASCII 中一样使用单字节编码;而 0x80 及以上的字符使用最多 4 个字节编码。","category":"page"},{"location":"manual/strings/","page":"字符串","title":"字符串","text":"在 Julia 中字符串索引指的是代码单元(对于 UTF-8 来说等同于字节/byte),固定宽度的构建块用于编码任意字符(code point)。这意味着并非每个索引到 UTF-8 字符串的字节都必须是一个字符的有效索引。如果在这种无效字节索引处索引字符串,将会报错:","category":"page"},{"location":"manual/strings/","page":"字符串","title":"字符串","text":"julia> s[1]\n'∀': Unicode U+2200 (category Sm: Symbol, math)\n\njulia> s[2]\nERROR: StringIndexError: invalid index [2], valid nearby indices [1]=>'∀', [4]=>' '\nStacktrace:\n[...]\n\njulia> s[3]\nERROR: StringIndexError: invalid index [3], valid nearby indices [1]=>'∀', [4]=>' '\nStacktrace:\n[...]\n\njulia> s[4]\n' ': ASCII/Unicode U+0020 (category Zs: Separator, space)","category":"page"},{"location":"manual/strings/","page":"字符串","title":"字符串","text":"在这种情况下,字符 ∀ 是一个三字节字符,因此索引 2 和 3 都是无效的,而下一个字符的索引是 4;这个接下来的有效索引可以用 nextind(s,1) 来计算,再接下来的用 nextind(s,4),依此类推。","category":"page"},{"location":"manual/strings/","page":"字符串","title":"字符串","text":"如果倒数第二个字符是多字节字符,由于 end 总是集合中最后一个有效索引,这时 end-1 将会是无效索引。","category":"page"},{"location":"manual/strings/","page":"字符串","title":"字符串","text":"julia> s[end-1]\n' ': ASCII/Unicode U+0020 (category Zs: Separator, space)\n\njulia> s[end-2]\nERROR: StringIndexError: invalid index [9], valid nearby indices [7]=>'∃', [10]=>' '\nStacktrace:\n[...]\n\njulia> s[prevind(s, end, 2)]\n'∃': Unicode U+2203 (category Sm: Symbol, math)","category":"page"},{"location":"manual/strings/","page":"字符串","title":"字符串","text":"第一种情况可以,因为最后一个字符 y 和空格都是一字节的字符,而 end-2 索引到中间的 ∃ 由多字节表示。正确的方法是使用 prevind(s, lastindex(s), 2),或者,如果你使用该值来索引s,则可以写为s[prevind(s, end, 2) ] , end 展开为 lastindex(s)。","category":"page"},{"location":"manual/strings/","page":"字符串","title":"字符串","text":"使用范围索引提取子字符串也需要有效的字节索引,不然就会抛出错误:  ","category":"page"},{"location":"manual/strings/","page":"字符串","title":"字符串","text":"julia> s[1:1]\n\"∀\"\n\njulia> s[1:2]\nERROR: StringIndexError: invalid index [2], valid nearby indices [1]=>'∀', [4]=>' '\nStacktrace:\n[...]\n\njulia> s[1:4]\n\"∀ \"","category":"page"},{"location":"manual/strings/","page":"字符串","title":"字符串","text":"由于可变长度的编码,字符串中的字符数(由 length(s) 给出)并不总是等于最后一个索引的数字。如果你从 1 到 lastindex(s) 迭代并索引到 s,未报错时返回的字符序列是包含字符串 s 的字符序列。所以,总是有 length(s) <= lastindex(s),这是因为字符串中的每个字符必须有它自己的索引。下面是对 s 的字符进行迭代的一个冗长而低效的方式:","category":"page"},{"location":"manual/strings/","page":"字符串","title":"字符串","text":"julia> for i = firstindex(s):lastindex(s)\n try\n println(s[i])\n catch\n # ignore the index error\n end\n end\n∀\n\nx\n\n∃\n\ny","category":"page"},{"location":"manual/strings/","page":"字符串","title":"字符串","text":"空行上面其实是有空格的。幸运的是,上面的笨拙写法不是对字符串中字符进行迭代所必须的——因为你只需把字符串本身用作迭代对象,而不需要额外处理:","category":"page"},{"location":"manual/strings/","page":"字符串","title":"字符串","text":"julia> for c in s\n println(c)\n end\n∀\n\nx\n\n∃\n\ny","category":"page"},{"location":"manual/strings/","page":"字符串","title":"字符串","text":"如果需要为字符串获取有效索引,可以使用 nextind 和 prevind 函数递增/递减到下一个/前一个有效索引,如前所述。你也可以使用 eachindex 函数迭代有效的字符索引:","category":"page"},{"location":"manual/strings/","page":"字符串","title":"字符串","text":"julia> collect(eachindex(s))\n7-element Vector{Int64}:\n 1\n 4\n 5\n 6\n 7\n 10\n 11","category":"page"},{"location":"manual/strings/","page":"字符串","title":"字符串","text":"要访问编码的原始代码单位(UTF-8 的字节),可以使用 codeunit(s,i)函数,其中索引 i 从 1 连续运行到 ncodeunits(s)。 codeunits(s) 函数返回一个 AbstractVector{UInt8} 包装器,允许您以数组的形式访问这些原始代码单元(字节)。","category":"page"},{"location":"manual/strings/","page":"字符串","title":"字符串","text":"Julia 中的字符串可以包含无效的 UTF-8 代码单元序列。这个惯例允许把任何字序列当作 String。在这种情形下的一个规则是,当从左到右解析代码单元序列时,字符由匹配下面开头位模式之一的最长的 8 位代码单元序列组成(每个 x 可以是 0 或者 1):","category":"page"},{"location":"manual/strings/","page":"字符串","title":"字符串","text":"0xxxxxxx;\n110xxxxx 10xxxxxx;\n1110xxxx 10xxxxxx 10xxxxxx;\n11110xxx 10xxxxxx 10xxxxxx 10xxxxxx;\n10xxxxxx;\n11111xxx.","category":"page"},{"location":"manual/strings/","page":"字符串","title":"字符串","text":"特别地,这意味着过长和过高的代码单元序列及其前缀将被视为单个无效字符,而不是多个无效字符。这个规则最好用一个例子来解释:","category":"page"},{"location":"manual/strings/","page":"字符串","title":"字符串","text":"julia> s = \"\\xc0\\xa0\\xe2\\x88\\xe2|\"\n\"\\xc0\\xa0\\xe2\\x88\\xe2|\"\n\njulia> foreach(display, s)\n'\\xc0\\xa0': [overlong] ASCII/Unicode U+0020 (category Zs: Separator, space)\n'\\xe2\\x88': Malformed UTF-8 (category Ma: Malformed, bad data)\n'\\xe2': Malformed UTF-8 (category Ma: Malformed, bad data)\n'|': ASCII/Unicode U+007C (category Sm: Symbol, math)\n\njulia> isvalid.(collect(s))\n4-element BitArray{1}:\n 0\n 0\n 0\n 1\n\njulia> s2 = \"\\xf7\\xbf\\xbf\\xbf\"\n\"\\U1fffff\"\n\njulia> foreach(display, s2)\n'\\U1fffff': Unicode U+1FFFFF (category In: Invalid, too high)","category":"page"},{"location":"manual/strings/","page":"字符串","title":"字符串","text":"我们可以看到字符串 s 中的前两个代码单元形成了一个过长的空格字符编码。这是无效的,但是在字符串中作为单个字符是可以接受的。接下来的两个代码单元形成了一个有效的 3 位 UTF-8 序列开头。然而,第五个代码单元 \\xe2 不是它的有效延续,所以代码单元 3 和 4 在这个字符串中也被解释为格式错误的字符。同理,由于 | 不是它的有效延续,代码单元 5 形成了一个格式错误的字符。最后字符串 s2 包含了一个太高的代码。","category":"page"},{"location":"manual/strings/","page":"字符串","title":"字符串","text":"Julia 默认使用 UTF-8 编码,对于新编码的支持可以通过包加上。例如,LegacyStrings.jl 包实现了 UTF16String 和 UTF32String 类型。关于其它编码的额外讨论以及如何实现对它们的支持暂时超过了这篇文档的讨论范围。UTF-8 编码相关问题的进一步讨论参见下面的字节数组字面量章节。transcode 函数可在各种 UTF-xx 编码之间转换,主要用于外部数据和包。","category":"page"},{"location":"manual/strings/#man-concatenation","page":"字符串","title":"拼接","text":"","category":"section"},{"location":"manual/strings/","page":"字符串","title":"字符串","text":"最常见最有用的字符串操作是级联:","category":"page"},{"location":"manual/strings/","page":"字符串","title":"字符串","text":"julia> greet = \"Hello\"\n\"Hello\"\n\njulia> whom = \"world\"\n\"world\"\n\njulia> string(greet, \", \", whom, \".\\n\")\n\"Hello, world.\\n\"","category":"page"},{"location":"manual/strings/","page":"字符串","title":"字符串","text":"意识到像对无效 UTF-8 字符进行级联这样的潜在危险情形是非常重要的。生成的字符串可能会包含和输入字符串不同的字符,并且其中字符的数目也可能少于被级联字符串中字符数目之和,例如:","category":"page"},{"location":"manual/strings/","page":"字符串","title":"字符串","text":"julia> a, b = \"\\xe2\\x88\", \"\\x80\"\n(\"\\xe2\\x88\", \"\\x80\")\n\njulia> c = a*b\n\"∀\"\n\njulia> collect.([a, b, c])\n3-element Array{Array{Char,1},1}:\n ['\\xe2\\x88']\n ['\\x80']\n ['∀']\n\njulia> length.([a, b, c])\n3-element Array{Int64,1}:\n 1\n 1\n 1","category":"page"},{"location":"manual/strings/","page":"字符串","title":"字符串","text":"这种情形只可能发生于无效 UTF-8 字符串上。对于有效 UTF-8 字符串,级联保留字符串中的所有字符和字符串的总长度。","category":"page"},{"location":"manual/strings/","page":"字符串","title":"字符串","text":"Julia 也提供 * 用于字符串级联:","category":"page"},{"location":"manual/strings/","page":"字符串","title":"字符串","text":"julia> greet * \", \" * whom * \".\\n\"\n\"Hello, world.\\n\"","category":"page"},{"location":"manual/strings/","page":"字符串","title":"字符串","text":"尽管对于提供 + 函数用于字符串拼接的语言使用者而言,* 似乎是一个令人惊讶的选择,但 * 的这种用法在数学中早有先例,尤其是在抽象代数中。","category":"page"},{"location":"manual/strings/","page":"字符串","title":"字符串","text":"在数学上,+ 通常表示可交换运算(commutative operation)——运算对象的顺序不重要。一个例子是矩阵加法:对于任何形状相同的矩阵 A 和 B,都有 A + B == B + A。与之相反,* 通常表示不可交换运算——运算对象的顺序很重要。例如,对于矩阵乘法,一般 A * B != B * A。同矩阵乘法类似,字符串拼接是不可交换的:greet * whom != whom * greet。在这一点上,对于插入字符串的拼接操作,* 是一个自然而然的选择,与它在数学中的用法一致。","category":"page"},{"location":"manual/strings/","page":"字符串","title":"字符串","text":"更确切地说,有限长度字符串集合 S 和字符串拼接操作 * 构成了一个自由幺半群 (S, *)。该集合的单位元是空字符串,\"\"。当一个自由幺半群不是交换的时,它的运算通常表示为 \\cdot,*,或者类似的符号,而非暗示交换性的 +。","category":"page"},{"location":"manual/strings/#string-interpolation","page":"字符串","title":"插值","text":"","category":"section"},{"location":"manual/strings/","page":"字符串","title":"字符串","text":"拼接构造字符串的方式有时有些麻烦。为了减少对于 string 的冗余调用或者重复地做乘法,Julia 允许像 Perl 中一样使用 $ 对字符串字面量进行插值:","category":"page"},{"location":"manual/strings/","page":"字符串","title":"字符串","text":"julia> \"$greet, $whom.\\n\"\n\"Hello, world.\\n\"","category":"page"},{"location":"manual/strings/","page":"字符串","title":"字符串","text":"这更易读更方便,而且等效于上面的字符串拼接——系统把这个显然一行的字符串字面量重写成带参数的字符串字面量拼接 string(greet, \", \", whom, \".\\n\")。","category":"page"},{"location":"manual/strings/","page":"字符串","title":"字符串","text":"在 $ 之后最短的完整表达式被视为插入其值于字符串中的表达式。因此,你可以用括号向字符串中插入任何表达式:","category":"page"},{"location":"manual/strings/","page":"字符串","title":"字符串","text":"julia> \"1 + 2 = $(1 + 2)\"\n\"1 + 2 = 3\"","category":"page"},{"location":"manual/strings/","page":"字符串","title":"字符串","text":"拼接和插值都调用 string 以转换对象为字符串形式。 然而,string 实际上仅仅返回了 print 的输出,因此,新的类型应该添加 print 或 show 方法,而不是 string 方法。","category":"page"},{"location":"manual/strings/","page":"字符串","title":"字符串","text":"多数非 AbstractString 对象被转换为和它们作为文本表达式输入的方式密切对应的字符串:","category":"page"},{"location":"manual/strings/","page":"字符串","title":"字符串","text":"julia> v = [1,2,3]\n3-element Vector{Int64}:\n 1\n 2\n 3\n\njulia> \"v: $v\"\n\"v: [1, 2, 3]\"","category":"page"},{"location":"manual/strings/","page":"字符串","title":"字符串","text":"string 是 AbstractString 和 AbstractChar 值的标识,所以它们作为自身被插入字符串,无需引用,无需转义:","category":"page"},{"location":"manual/strings/","page":"字符串","title":"字符串","text":"julia> c = 'x'\n'x': ASCII/Unicode U+0078 (category Ll: Letter, lowercase)\n\njulia> \"hi, $c\"\n\"hi, x\"","category":"page"},{"location":"manual/strings/","page":"字符串","title":"字符串","text":"若要在字符串字面量中包含文本 $,就用反斜杠转义:","category":"page"},{"location":"manual/strings/","page":"字符串","title":"字符串","text":"julia> print(\"I have \\$100 in my account.\\n\")\nI have $100 in my account.","category":"page"},{"location":"manual/strings/#三引号字符串字面量","page":"字符串","title":"三引号字符串字面量","text":"","category":"section"},{"location":"manual/strings/","page":"字符串","title":"字符串","text":"当使用三引号(\"\"\"...\"\"\")创建字符串时,它们有一些在创建更长文本块时可能用到的特殊行为。","category":"page"},{"location":"manual/strings/","page":"字符串","title":"字符串","text":"首先,三引号字符串也被反缩进到最小缩进线的水平。这在定义包含缩进的字符串时很有用。例如:","category":"page"},{"location":"manual/strings/","page":"字符串","title":"字符串","text":"julia> str = \"\"\"\n Hello,\n world.\n \"\"\"\n\" Hello,\\n world.\\n\"","category":"page"},{"location":"manual/strings/","page":"字符串","title":"字符串","text":"在这里,后三引号 \"\"\" 前面的最后一(空)行设置了缩进级别。","category":"page"},{"location":"manual/strings/","page":"字符串","title":"字符串","text":"反缩进级别被确定为所有行中空格或制表符的最大公共起始序列,不包括前三引号 \"\"\" 后面的一行以及只包含空格或制表符的行(总包含结尾 \"\"\" 的行)。那么对于所有不包括前三引号 \"\"\" 后面文本的行而言,公共起始序列就被移除了(包括只含空格和制表符而以此序列开始的行),例如:","category":"page"},{"location":"manual/strings/","page":"字符串","title":"字符串","text":"julia> \"\"\" This\n is\n a test\"\"\"\n\" This\\nis\\n a test\"","category":"page"},{"location":"manual/strings/","page":"字符串","title":"字符串","text":"接下来,如果前三引号 \"\"\" 后面紧跟换行符,那么换行符就从生成的字符串中被剥离。","category":"page"},{"location":"manual/strings/","page":"字符串","title":"字符串","text":"\"\"\"hello\"\"\"","category":"page"},{"location":"manual/strings/","page":"字符串","title":"字符串","text":"等价于","category":"page"},{"location":"manual/strings/","page":"字符串","title":"字符串","text":"\"\"\"\nhello\"\"\"","category":"page"},{"location":"manual/strings/","page":"字符串","title":"字符串","text":"但是","category":"page"},{"location":"manual/strings/","page":"字符串","title":"字符串","text":"\"\"\"\n\nhello\"\"\"","category":"page"},{"location":"manual/strings/","page":"字符串","title":"字符串","text":"将在开头包含一个文本换行符。","category":"page"},{"location":"manual/strings/","page":"字符串","title":"字符串","text":"换行符的移除是在反缩进之后进行的。例如:","category":"page"},{"location":"manual/strings/","page":"字符串","title":"字符串","text":"julia> \"\"\"\n Hello,\n world.\"\"\"\n\"Hello,\\nworld.\"","category":"page"},{"location":"manual/strings/","page":"字符串","title":"字符串","text":"如果使用反斜杠消除换行符,下一行的缩进也会被消除:","category":"page"},{"location":"manual/strings/","page":"字符串","title":"字符串","text":"julia> \"\"\"\n Averylong\\\n word\"\"\"\n\"Averylongword\"","category":"page"},{"location":"manual/strings/","page":"字符串","title":"字符串","text":"尾随空格保持不变。","category":"page"},{"location":"manual/strings/","page":"字符串","title":"字符串","text":"三引号字符串字面量可不带转义地包含 \" 符号。","category":"page"},{"location":"manual/strings/","page":"字符串","title":"字符串","text":"注意,无论是用单引号还是三引号,在文本字符串中换行符都会生成一个换行 (LF) 字符 \\n,即使你的编辑器使用回车组合符 \\r (CR) 或 CRLF 来结束行。为了在字符串中包含 CR,总是应该使用显式转义符 \\r;比如,可以输入文本字符串 \"a CRLF line ending\\r\\n\"。","category":"page"},{"location":"manual/strings/#常见操作","page":"字符串","title":"常见操作","text":"","category":"section"},{"location":"manual/strings/","page":"字符串","title":"字符串","text":"你可以使用标准的比较操作符按照字典顺序比较字符串:","category":"page"},{"location":"manual/strings/","page":"字符串","title":"字符串","text":"julia> \"abracadabra\" < \"xylophone\"\ntrue\n\njulia> \"abracadabra\" == \"xylophone\"\nfalse\n\njulia> \"Hello, world.\" != \"Goodbye, world.\"\ntrue\n\njulia> \"1 + 2 = 3\" == \"1 + 2 = $(1 + 2)\"\ntrue","category":"page"},{"location":"manual/strings/","page":"字符串","title":"字符串","text":"你可以使用 findfirst 与 findlast 函数搜索特定字符的索引:","category":"page"},{"location":"manual/strings/","page":"字符串","title":"字符串","text":"julia> findfirst(isequal('o'), \"xylophone\")\n4\n\njulia> findlast(isequal('o'), \"xylophone\")\n7\n\njulia> findfirst(isequal('z'), \"xylophone\")","category":"page"},{"location":"manual/strings/","page":"字符串","title":"字符串","text":"你可以带上第三个参数,用 findnext 与 findprev 函数来在给定偏移量处搜索字符:","category":"page"},{"location":"manual/strings/","page":"字符串","title":"字符串","text":"julia> findnext(isequal('o'), \"xylophone\", 1)\n4\n\njulia> findnext(isequal('o'), \"xylophone\", 5)\n7\n\njulia> findprev(isequal('o'), \"xylophone\", 5)\n4\n\njulia> findnext(isequal('o'), \"xylophone\", 8)","category":"page"},{"location":"manual/strings/","page":"字符串","title":"字符串","text":"你可以用 occursin 函数检查在字符串中某子字符串可否找到。","category":"page"},{"location":"manual/strings/","page":"字符串","title":"字符串","text":"julia> occursin(\"world\", \"Hello, world.\")\ntrue\n\njulia> occursin(\"o\", \"Xylophon\")\ntrue\n\njulia> occursin(\"a\", \"Xylophon\")\nfalse\n\njulia> occursin('o', \"Xylophon\")\ntrue","category":"page"},{"location":"manual/strings/","page":"字符串","title":"字符串","text":"最后那个例子表明 occursin 也可用于搜寻字符字面量。","category":"page"},{"location":"manual/strings/","page":"字符串","title":"字符串","text":"另外还有两个方便的字符串函数 repeat 和 join:","category":"page"},{"location":"manual/strings/","page":"字符串","title":"字符串","text":"julia> repeat(\".:Z:.\", 10)\n\".:Z:..:Z:..:Z:..:Z:..:Z:..:Z:..:Z:..:Z:..:Z:..:Z:.\"\n\njulia> join([\"apples\", \"bananas\", \"pineapples\"], \", \", \" and \")\n\"apples, bananas and pineapples\"","category":"page"},{"location":"manual/strings/","page":"字符串","title":"字符串","text":"其它有用的函数还包括:","category":"page"},{"location":"manual/strings/","page":"字符串","title":"字符串","text":"firstindex(str) 给出可用来索引到 str 的最小(字节)索引(对字符串来说这总是 1,对于别的容器来说却不一定如此)。\nlastindex(str) 给出可用来索引到 str 的最大(字节)索引。\nlength(str),str 中的字符个数。\nlength(str, i, j),str 中从 i 到 j 的有效字符索引个数。\nncodeunits(str),字符串中代码单元(码元)的数目。\ncodeunit(str, i) 给出在字符串 str 中索引为 i 的代码单元值。\nthisind(str, i),给定一个字符串的任意索引,查找索引点所在的首个索引。\nnextind(str, i, n=1) 查找在索引 i 之后第 n 个字符的开头。\nprevind(str, i, n=1) 查找在索引 i 之前第 n 个字符的开始。","category":"page"},{"location":"manual/strings/#non-standard-string-literals","page":"字符串","title":"非标准字符串字面量","text":"","category":"section"},{"location":"manual/strings/","page":"字符串","title":"字符串","text":"有时当你想构造字符串或者使用字符串语义,标准的字符串构造却不能很好的满足需求。Julia 为这种情形提供了非标准字符串字面量。非标准字符串字面量看似常规双引号字符串字面量,但却直接加上了标识符前缀因而并不那么像普通的字符串字面量。","category":"page"},{"location":"manual/strings/","page":"字符串","title":"字符串","text":"下面将提到,正则表达式,字节数组字面量 和 版本号字面量 都是非标准字符串字面量的例子。 更详细的文档见 元编程 章。","category":"page"},{"location":"manual/strings/#man-regex-literals","page":"字符串","title":"正则表达式","text":"","category":"section"},{"location":"manual/strings/","page":"字符串","title":"字符串","text":"Julia 具有与 Perl 兼容的正则表达式 (regexes),就像 PCRE 包所提供的那样,详细信息参见 PCRE 的语法说明。 正则表达式以两种方式和字符串相关:一个显然的关联是,正则表达式被用于找到字符串中的正则模式;另一个关联是,正则表达式自身就是作为字符串输入,它们被解析到可用来高效搜索字符串中模式的状态机中。 在 Julia 中正则表达式的输入使用了前缀各类以 r 开头的标识符的非标准字符串字面量。最基本的不打开任何选项的正则表达式只用到了 r\"...\":","category":"page"},{"location":"manual/strings/","page":"字符串","title":"字符串","text":"julia> re = r\"^\\s*(?:#|$)\"\nr\"^\\s*(?:#|$)\"\n\njulia> typeof(re)\nRegex","category":"page"},{"location":"manual/strings/","page":"字符串","title":"字符串","text":"若要检查正则表达式是否匹配某字符串,就用 occursin:","category":"page"},{"location":"manual/strings/","page":"字符串","title":"字符串","text":"julia> occursin(r\"^\\s*(?:#|$)\", \"not a comment\")\nfalse\n\njulia> occursin(r\"^\\s*(?:#|$)\", \"# a comment\")\ntrue","category":"page"},{"location":"manual/strings/","page":"字符串","title":"字符串","text":"可以看到,occursin 只返回正确或错误,表明给定正则表达式是否在该字符串中出现。然而,通常我们不只想知道字符串是否匹配,更想了解它是如何匹配的。要捕获匹配的信息,可以改用 match 函数:","category":"page"},{"location":"manual/strings/","page":"字符串","title":"字符串","text":"julia> match(r\"^\\s*(?:#|$)\", \"not a comment\")\n\njulia> match(r\"^\\s*(?:#|$)\", \"# a comment\")\nRegexMatch(\"#\")","category":"page"},{"location":"manual/strings/","page":"字符串","title":"字符串","text":"若正则表达式与给定字符串不匹配,match 返回 nothing——在交互式提示框中不打印任何东西的特殊值。除了不打印,它是一个完全正常的值,这可以用程序来测试:","category":"page"},{"location":"manual/strings/","page":"字符串","title":"字符串","text":"m = match(r\"^\\s*(?:#|$)\", line)\nif m === nothing\n println(\"not a comment\")\nelse\n println(\"blank or comment\")\nend","category":"page"},{"location":"manual/strings/","page":"字符串","title":"字符串","text":"如果正则表达式匹配,match 的返回值是一个 RegexMatch 对象。这些对象记录了表达式是如何匹配的,包括该模式匹配的子字符串和任何可能被捕获的子字符串。上面的例子仅仅捕获了匹配的部分子字符串,但也许我们想要捕获的是注释字符后面的任何非空文本。我们可以这样做:","category":"page"},{"location":"manual/strings/","page":"字符串","title":"字符串","text":"julia> m = match(r\"^\\s*(?:#\\s*(.*?)\\s*$|$)\", \"# a comment \")\nRegexMatch(\"# a comment \", 1=\"a comment\")","category":"page"},{"location":"manual/strings/","page":"字符串","title":"字符串","text":"当调用 match 时,你可以选择指定开始搜索的索引。例如:","category":"page"},{"location":"manual/strings/","page":"字符串","title":"字符串","text":"julia> m = match(r\"[0-9]\",\"aaaa1aaaa2aaaa3\",1)\nRegexMatch(\"1\")\n\njulia> m = match(r\"[0-9]\",\"aaaa1aaaa2aaaa3\",6)\nRegexMatch(\"2\")\n\njulia> m = match(r\"[0-9]\",\"aaaa1aaaa2aaaa3\",11)\nRegexMatch(\"3\")","category":"page"},{"location":"manual/strings/","page":"字符串","title":"字符串","text":"你可以从 RegexMatch 对象中提取如下信息:","category":"page"},{"location":"manual/strings/","page":"字符串","title":"字符串","text":"匹配的整个子字符串:m.match\n作为字符串数组捕获的子字符串:m.captures\n整个匹配开始处的偏移:m.offset\n作为向量的捕获子字符串的偏移:m.offsets","category":"page"},{"location":"manual/strings/","page":"字符串","title":"字符串","text":"当捕获不匹配时,m.captures 在该处不再包含一个子字符串,而是 什么也不 包含;此外,m.offsets 的偏移量为 0(回想一下,Julia 的索引是从 1 开始的,因此字符串的零偏移是无效的)。下面是两个有些牵强的例子:","category":"page"},{"location":"manual/strings/","page":"字符串","title":"字符串","text":"julia> m = match(r\"(a|b)(c)?(d)\", \"acd\")\nRegexMatch(\"acd\", 1=\"a\", 2=\"c\", 3=\"d\")\n\njulia> m.match\n\"acd\"\n\njulia> m.captures\n3-element Vector{Union{Nothing, SubString{String}}}:\n \"a\"\n \"c\"\n \"d\"\n\njulia> m.offset\n1\n\njulia> m.offsets\n3-element Vector{Int64}:\n 1\n 2\n 3\n\njulia> m = match(r\"(a|b)(c)?(d)\", \"ad\")\nRegexMatch(\"ad\", 1=\"a\", 2=nothing, 3=\"d\")\n\njulia> m.match\n\"ad\"\n\njulia> m.captures\n3-element Vector{Union{Nothing, SubString{String}}}:\n \"a\"\n nothing\n \"d\"\n\njulia> m.offset\n1\n\njulia> m.offsets\n3-element Vector{Int64}:\n 1\n 0\n 2","category":"page"},{"location":"manual/strings/","page":"字符串","title":"字符串","text":"让捕获作为数组返回是很方便的,这样就可以用解构语法把它们和局域变量绑定起来。为了方便,RegexMatch 对象实现了传递到 captures 字段的迭代器方法,因此您可以直接解构匹配对象:","category":"page"},{"location":"manual/strings/","page":"字符串","title":"字符串","text":"julia> first, second, third = m; first\n\"a\"","category":"page"},{"location":"manual/strings/","page":"字符串","title":"字符串","text":"通过使用捕获组的编号或名称对 RegexMatch 对象进行索引,也可实现对捕获的访问:","category":"page"},{"location":"manual/strings/","page":"字符串","title":"字符串","text":"julia> m=match(r\"(?\\d+):(?\\d+)\",\"12:45\")\nRegexMatch(\"12:45\", hour=\"12\", minute=\"45\")\n\njulia> m[:minute]\n\"45\"\n\njulia> m[2]\n\"45\"","category":"page"},{"location":"manual/strings/","page":"字符串","title":"字符串","text":"使用 replace 时利用 \\n 引用第 n 个捕获组和给替换字符串加上 s 的前缀,可以实现替换字符串中对捕获的引用。捕获组 0 指的是整个匹配对象。可在替换中用 \\g 对命名捕获组进行引用。例如:","category":"page"},{"location":"manual/strings/","page":"字符串","title":"字符串","text":"julia> replace(\"first second\", r\"(\\w+) (?\\w+)\" => s\"\\g \\1\")\n\"second first\"","category":"page"},{"location":"manual/strings/","page":"字符串","title":"字符串","text":"为明确起见,编号捕获组也可用 \\g 进行引用,例如:","category":"page"},{"location":"manual/strings/","page":"字符串","title":"字符串","text":"julia> replace(\"a\", r\".\" => s\"\\g<0>1\")\n\"a1\"","category":"page"},{"location":"manual/strings/","page":"字符串","title":"字符串","text":"你可以在后双引号的后面加上 i, m, s 和 x 等标志对正则表达式进行修改。这些标志和 Perl 里面的含义一样,详见以下对 perlre 手册的摘录:","category":"page"},{"location":"manual/strings/","page":"字符串","title":"字符串","text":"i 不区分大小写的模式匹配。\n\n 若区域设置规则有效,相应映射中代码点小于 255 的部分取自当前区域设置,更大代码点的部分取自 Unicode 规则。然而,跨越 Unicode 规则(ords 255/256)和 非 Unicode 规则边界的匹配将失败。\n\nm 将字符串视为多行。也即更改 \"^\" 和 \"$\", 使其从匹配字符串的开头和结尾变为匹配字符串中任意一行的开头或结尾。\n\ns 将字符串视为单行。也即更改 \".\" 以匹配任何字符,即使是通常不能匹配的换行符。\n\n 像这样一起使用,r\"\"ms,它们让 \".\" 匹配任何字符,同时也支持分别在字符串中换行符的后面和前面用 \"^\" 和 \"$\" 进行匹配。\n\nx 令正则表达式解析器忽略多数既不是反斜杠也不属于字符类的空白。它可以用来把正则表达式分解成(略为)更易读的部分。和普通代码中一样,`#` 字符也被当作引入注释的元字符。","category":"page"},{"location":"manual/strings/","page":"字符串","title":"字符串","text":"例如,下面的正则表达式已打开所有三个标志:","category":"page"},{"location":"manual/strings/","page":"字符串","title":"字符串","text":"julia> r\"a+.*b+.*?d$\"ism\nr\"a+.*b+.*?d$\"ims\n\njulia> match(r\"a+.*b+.*?d$\"ism, \"Goodbye,\\nOh, angry,\\nBad world\\n\")\nRegexMatch(\"angry,\\nBad world\")","category":"page"},{"location":"manual/strings/","page":"字符串","title":"字符串","text":"r\"...\" 文本的构造没有插值和转义(除了引号 \" 仍然需要转义)。下面例子展示了它和标准字符串字面量之间的差别:","category":"page"},{"location":"manual/strings/","page":"字符串","title":"字符串","text":"julia> x = 10\n10\n\njulia> r\"$x\"\nr\"$x\"\n\njulia> \"$x\"\n\"10\"\n\njulia> r\"\\x\"\nr\"\\x\"\n\njulia> \"\\x\"\nERROR: syntax: invalid escape sequence","category":"page"},{"location":"manual/strings/","page":"字符串","title":"字符串","text":"Julia 也支持 r\"\"\"...\"\"\" 形式的三引号正则表达式字符串(或许便于处理包含引号和换行符的正则表达式)。","category":"page"},{"location":"manual/strings/","page":"字符串","title":"字符串","text":"Regex() 构造函数可以用于以编程方式创建合法的正则表达式字符串。这允许在构造正则表达式字符串时使用字符串变量的内容和其他字符串操作。上面的任何正则表达式代码可以在 Regex() 的单字符串参数中使用。下面是一些例子:","category":"page"},{"location":"manual/strings/","page":"字符串","title":"字符串","text":"julia> using Dates\n\njulia> d = Date(1962,7,10)\n1962-07-10\n\njulia> regex_d = Regex(\"Day \" * string(day(d)))\nr\"Day 10\"\n\njulia> match(regex_d, \"It happened on Day 10\")\nRegexMatch(\"Day 10\")\n\njulia> name = \"Jon\"\n\"Jon\"\n\njulia> regex_name = Regex(\"[\\\"( ]\\\\Q$name\\\\E[\\\") ]\") # interpolate value of name\nr\"[\\\"( ]\\QJon\\E[\\\") ]\"\n\njulia> match(regex_name, \" Jon \")\nRegexMatch(\" Jon \")\n\njulia> match(regex_name, \"[Jon]\") === nothing\ntrue","category":"page"},{"location":"manual/strings/","page":"字符串","title":"字符串","text":"注意 \\Q...\\E 转义序列的使用。 \\Q 和 \\E 之间的所有字符都被解释为字符字面量(在字符串插值之后)。在插入可能是恶意的用户输入时,此转义序列非常有用。","category":"page"},{"location":"manual/strings/#man-byte-array-literals","page":"字符串","title":"字节数组字面量","text":"","category":"section"},{"location":"manual/strings/","page":"字符串","title":"字符串","text":"另一个有用的非标准字符串字面量是字节数组字面量:b\"...\"。这种形式使你能够用字符串表示法来表达只读字面量字节数组,也即 UInt8 值的数组。字节数组字面量的规则如下:","category":"page"},{"location":"manual/strings/","page":"字符串","title":"字符串","text":"ASCII 字符和 ASCII 转义生成单个字节。\n\\x 和八进制转义序列生成与转义值对应的字节。\nUnicode 转义序列生成编码 UTF-8 中该代码点的字节序列。","category":"page"},{"location":"manual/strings/","page":"字符串","title":"字符串","text":"这些规则有一些重叠,这是因为 \\x 的行为和小于 0x80(128) 的八进制转义被前两个规则同时包括了;但这两个规则又是一致的。通过这些规则可以方便地同时使用 ASCII 字符,任意字节值,以及 UTF-8 序列来生成字节数组。下面是一个用到全部三个规则的例子:","category":"page"},{"location":"manual/strings/","page":"字符串","title":"字符串","text":"julia> b\"DATA\\xff\\u2200\"\n8-element Base.CodeUnits{UInt8, String}:\n 0x44\n 0x41\n 0x54\n 0x41\n 0xff\n 0xe2\n 0x88\n 0x80","category":"page"},{"location":"manual/strings/","page":"字符串","title":"字符串","text":"其中,ASCII 字符串 \"DATA\" 对应于字节 68, 65, 84, 65。\\xff 生成单个字节 255。Unicode 转义 \\u2200 在 UTF-8 中被编码为三个字节 226, 136, 128。注意生成的字节数组不对应任何有效 UTF-8 字符串。","category":"page"},{"location":"manual/strings/","page":"字符串","title":"字符串","text":"julia> isvalid(\"DATA\\xff\\u2200\")\nfalse","category":"page"},{"location":"manual/strings/","page":"字符串","title":"字符串","text":"正如前面所述,CodeUnits{UInt8,String} 类型的行为类似于只读 UInt8 数组。如果需要标准数组,你可使用 Vector{UInt8} 进行转换。","category":"page"},{"location":"manual/strings/","page":"字符串","title":"字符串","text":" ","category":"page"},{"location":"manual/strings/","page":"字符串","title":"字符串","text":"julia> x = b\"123\"\n3-element Base.CodeUnits{UInt8, String}:\n 0x31\n 0x32\n 0x33\n\njulia> x[1]\n0x31\n\njulia> x[1] = 0x32\nERROR: setindex! not defined for Base.CodeUnits{UInt8, String}\n[...]\n\njulia> Vector{UInt8}(x)\n3-element Vector{UInt8}:\n 0x31\n 0x32\n 0x33","category":"page"},{"location":"manual/strings/","page":"字符串","title":"字符串","text":"同时,要注意到 \\xff 和 \\uff 之间的显著差别:前面的转义序列编码为字节 255,而后者代表 代码 255,它在 UTF-8 中编码为两个字节:","category":"page"},{"location":"manual/strings/","page":"字符串","title":"字符串","text":"julia> b\"\\xff\"\n1-element Base.CodeUnits{UInt8, String}:\n 0xff\n\njulia> b\"\\uff\"\n2-element Base.CodeUnits{UInt8, String}:\n 0xc3\n 0xbf","category":"page"},{"location":"manual/strings/","page":"字符串","title":"字符串","text":"字符字面量也用到了相同的行为。","category":"page"},{"location":"manual/strings/","page":"字符串","title":"字符串","text":"对于小于 \\u80 的代码,每个代码的 UTF-8 编码恰好只是由相应 \\x 转义产生的单个字节,因此忽略两者的差别无伤大雅。然而,从 x80 到 \\xff 的转义比起从 u80 到 \\uff 的转义来,就有一个主要的差别:前者都只编码为一个字节,它没有形成任何有效 UTF-8 数据,除非它后面有非常特殊的连接字节;而后者则都代表 2 字节编码的 Unicode 代码。","category":"page"},{"location":"manual/strings/","page":"字符串","title":"字符串","text":"如果这些还是太难理解,试着读一下 \"每个软件开发人员绝对必须知道的最基础 Unicode 和字符集知识\"。它是一个优质的 Unicode 和 UTF-8 指南,或许能帮助解除一些这方面的疑惑。","category":"page"},{"location":"manual/strings/#man-version-number-literals","page":"字符串","title":"版本号字面量","text":"","category":"section"},{"location":"manual/strings/","page":"字符串","title":"字符串","text":"版本号很容易用 v\"...\" 形式的非标准字符串字面量表示。版本号字面量生成遵循语义版本规范的 VersionNumber 对象,因此由主、次、补丁号构成,后跟预发行 (pre-release) 和生成阿尔法数注释(build alpha-numeric)。例如,v\"0.2.1-rc1+win64\" 可分为主版本号 0,次版本号 2,补丁版本号 1,预发行版号 rc1,以及生成版本 win64。输入版本字面量时,除了主版本号以外所有内容都是可选的,因此 v\"0.2\" 等效于 v\"0.2.0\"(预发行号和生成注释为空),v\"2\" 等效于 v\"2.0.0\",等等。","category":"page"},{"location":"manual/strings/","page":"字符串","title":"字符串","text":"VersionNumber 对象在轻松正确地比较两个(或更多)版本时非常有用。例如,常数 VERSION 把 Julia 的版本号保留为一个 VersionNumber 对象,因此可以像下面这样用简单的声明定义一些特定版本的行为:","category":"page"},{"location":"manual/strings/","page":"字符串","title":"字符串","text":"if v\"0.2\" <= VERSION < v\"0.3-\"\n # 针对 0.2 发行版系列做些事情\nend","category":"page"},{"location":"manual/strings/","page":"字符串","title":"字符串","text":"注意在上例中用到了非标准版本号 v\"0.3-\",其中有尾随符 -:这个符号是 Julia 标准的扩展,它可以用来表明低于任何 0.3 发行版的版本,包括所有的预发行版。所以上例中代码只能在稳定版本 0.2 上运行,而不能在 v\"0.3.0-rc1\" 这样的版本上运行。为了支持非稳定(即预发行)的 0.2 版本,下限检查应像这样应该改为:v\"0.2-\" <= VERSION。","category":"page"},{"location":"manual/strings/","page":"字符串","title":"字符串","text":"另一个非标准版本规范扩展使得能够使用 + 来表示生成版本的上限,例如 VERSION > v\"0.2-rc1+\" 可以用来表示任意高于 0.2-rc1 和其任意生成版本的版本:它对 v\"0.2-rc1+win64\" 返回 false 而对 v\"0.2-rc2\" 返回 true。","category":"page"},{"location":"manual/strings/","page":"字符串","title":"字符串","text":"在比较中使用这样的特殊版本是个好办法(特别是,总是应该对高版本使用尾随 -,除非有好理由不这样),但它们不应该被用作任何内容的实际版本,因为它们在语义版本控制方案中无效。","category":"page"},{"location":"manual/strings/","page":"字符串","title":"字符串","text":"除了用于定义常数 VERSION,VersionNumber 对象在 Pkg 模块应用广泛,常用于指定软件包的版本及其依赖。","category":"page"},{"location":"manual/strings/#man-raw-string-literals","page":"字符串","title":"原始字符串字面量","text":"","category":"section"},{"location":"manual/strings/","page":"字符串","title":"字符串","text":"无插值和非转义的原始字符串可用 raw\"...\" 形式的非标准字符串字面量表示。原始字符串字面量生成普通的 String 对象,它无需插值和非转义地包含和输入完全一样的封闭式内容。这对于包含其他语言中使用 \" 或 \\\" 作为特殊字符的代码或标记的字符串很有用。","category":"page"},{"location":"manual/strings/","page":"字符串","title":"字符串","text":"例外的是,引号仍必须转义,例如 raw\"\\\"\" 等效于 \"\\\"\"。为了能够表达所有字符串,反斜杠也必须转义,不过只是当它刚好出现在引号前面时。","category":"page"},{"location":"manual/strings/","page":"字符串","title":"字符串","text":"julia> println(raw\"\\\\ \\\\\\\"\")\n\\\\ \\\"","category":"page"},{"location":"manual/strings/","page":"字符串","title":"字符串","text":"请注意,前两个反斜杠在输出中逐字显示,这是因为它们不是在引号前面。然而,接下来的一个反斜杠字符转义了后面的一个反斜杠;又由于这些反斜杠出现在引号前面,最后一个反斜杠转义了一个引号。","category":"page"},{"location":"base/base/#基本功能","page":"基本功能","title":"基本功能","text":"","category":"section"},{"location":"base/base/#介绍","page":"基本功能","title":"介绍","text":"","category":"section"},{"location":"base/base/","page":"基本功能","title":"基本功能","text":"Julia Base 中包含一系列适用于科学及数值计算的函数和宏,但也可以用于通用编程,其它功能则由 Julia 生态圈中的各种库来提供。函数按主题划分如下:","category":"page"},{"location":"base/base/","page":"基本功能","title":"基本功能","text":"一些通用的提示:","category":"page"},{"location":"base/base/","page":"基本功能","title":"基本功能","text":"可以通过 Import Module 导入想要使用的模块,并利用 Module.fn(x) 语句来实现对模块内函数的调用。\n此外,using Module 语句会将名为 Module 的模块中的所有可调函数引入当前的命名空间。\n按照约定,名字以感叹号(!)结尾的函数会改变其输入参数的内容。 一些函数同时拥有改变参数(例如 sort!)和不改变参数(sort)的版本","category":"page"},{"location":"base/base/","page":"基本功能","title":"基本功能","text":"The behaviors of Base and standard libraries are stable as defined in SemVer only if they are documented; i.e., included in the Julia documentation and not marked as unstable. See API FAQ for more information.","category":"page"},{"location":"base/base/#Getting-Around","page":"基本功能","title":"Getting Around","text":"","category":"section"},{"location":"base/base/","page":"基本功能","title":"基本功能","text":"Base.exit\nBase.atexit\nBase.isinteractive\nBase.summarysize\nBase.require\nBase.compilecache\nBase.__precompile__\nBase.include\nBase.MainInclude.include\nBase.include_string\nBase.include_dependency\nBase.which(::Any, ::Any)\nBase.methods\nBase.@show\nans\nBase.active_project","category":"page"},{"location":"base/base/#Base.exit","page":"基本功能","title":"Base.exit","text":"exit(code=0)\n\nStop the program with an exit code. The default exit code is zero, indicating that the program completed successfully. In an interactive session, exit() can be called with the keyboard shortcut ^D.\n\n\n\n\n\n","category":"function"},{"location":"base/base/#Base.atexit","page":"基本功能","title":"Base.atexit","text":"atexit(f)\n\nRegister a zero-argument function f() to be called at process exit. atexit() hooks are called in last in first out (LIFO) order and run before object finalizers.\n\nExit hooks are allowed to call exit(n), in which case Julia will exit with exit code n (instead of the original exit code). If more than one exit hook calls exit(n), then Julia will exit with the exit code corresponding to the last called exit hook that calls exit(n). (Because exit hooks are called in LIFO order, \"last called\" is equivalent to \"first registered\".)\n\n\n\n\n\n","category":"function"},{"location":"base/base/#Base.isinteractive","page":"基本功能","title":"Base.isinteractive","text":"isinteractive() -> Bool\n\nDetermine whether Julia is running an interactive session.\n\n\n\n\n\n","category":"function"},{"location":"base/base/#Base.summarysize","page":"基本功能","title":"Base.summarysize","text":"Base.summarysize(obj; exclude=Union{...}, chargeall=Union{...}) -> Int\n\nCompute the amount of memory, in bytes, used by all unique objects reachable from the argument.\n\nKeyword Arguments\n\nexclude: specifies the types of objects to exclude from the traversal.\nchargeall: specifies the types of objects to always charge the size of all of their fields, even if those fields would normally be excluded.\n\nSee also sizeof.\n\nExamples\n\njulia> Base.summarysize(1.0)\n8\n\njulia> Base.summarysize(Ref(rand(100)))\n848\n\njulia> sizeof(Ref(rand(100)))\n8\n\n\n\n\n\n","category":"function"},{"location":"base/base/#Base.require","page":"基本功能","title":"Base.require","text":"require(into::Module, module::Symbol)\n\nThis function is part of the implementation of using / import, if a module is not already defined in Main. It can also be called directly to force reloading a module, regardless of whether it has been loaded before (for example, when interactively developing libraries).\n\nLoads a source file, in the context of the Main module, on every active node, searching standard locations for files. require is considered a top-level operation, so it sets the current include path but does not use it to search for files (see help for include). This function is typically used to load library code, and is implicitly called by using to load packages.\n\nWhen searching for files, require first looks for package code in the global array LOAD_PATH. require is case-sensitive on all platforms, including those with case-insensitive filesystems like macOS and Windows.\n\nFor more details regarding code loading, see the manual sections on modules and parallel computing.\n\n\n\n\n\n","category":"function"},{"location":"base/base/#Base.compilecache","page":"基本功能","title":"Base.compilecache","text":"Base.compilecache(module::PkgId)\n\nCreates a precompiled cache file for a module and all of its dependencies. This can be used to reduce package load times. Cache files are stored in DEPOT_PATH[1]/compiled. See Module initialization and precompilation for important notes.\n\n\n\n\n\n","category":"function"},{"location":"base/base/#Base.__precompile__","page":"基本功能","title":"Base.__precompile__","text":"__precompile__(isprecompilable::Bool)\n\nSpecify whether the file calling this function is precompilable, defaulting to true. If a module or file is not safely precompilable, it should call __precompile__(false) in order to throw an error if Julia attempts to precompile it.\n\n\n\n\n\n","category":"function"},{"location":"base/base/#Base.include","page":"基本功能","title":"Base.include","text":"Base.include([mapexpr::Function,] [m::Module,] path::AbstractString)\n\nEvaluate the contents of the input source file in the global scope of module m. Every module (except those defined with baremodule) has its own definition of include omitting the m argument, which evaluates the file in that module. Returns the result of the last evaluated expression of the input file. During including, a task-local include path is set to the directory containing the file. Nested calls to include will search relative to that path. This function is typically used to load source interactively, or to combine files in packages that are broken into multiple source files.\n\nThe optional first argument mapexpr can be used to transform the included code before it is evaluated: for each parsed expression expr in path, the include function actually evaluates mapexpr(expr). If it is omitted, mapexpr defaults to identity.\n\ncompat: Julia 1.5\nJulia 1.5 is required for passing the mapexpr argument.\n\n\n\n\n\n","category":"function"},{"location":"base/base/#Base.MainInclude.include","page":"基本功能","title":"Base.MainInclude.include","text":"include([mapexpr::Function,] path::AbstractString)\n\nEvaluate the contents of the input source file in the global scope of the containing module. Every module (except those defined with baremodule) has its own definition of include, which evaluates the file in that module. Returns the result of the last evaluated expression of the input file. During including, a task-local include path is set to the directory containing the file. Nested calls to include will search relative to that path. This function is typically used to load source interactively, or to combine files in packages that are broken into multiple source files. The argument path is normalized using normpath which will resolve relative path tokens such as .. and convert / to the appropriate path separator.\n\nThe optional first argument mapexpr can be used to transform the included code before it is evaluated: for each parsed expression expr in path, the include function actually evaluates mapexpr(expr). If it is omitted, mapexpr defaults to identity.\n\nUse Base.include to evaluate a file into another module.\n\ncompat: Julia 1.5\nJulia 1.5 is required for passing the mapexpr argument.\n\n\n\n\n\n","category":"function"},{"location":"base/base/#Base.include_string","page":"基本功能","title":"Base.include_string","text":"include_string([mapexpr::Function,] m::Module, code::AbstractString, filename::AbstractString=\"string\")\n\nLike include, except reads code from the given string rather than from a file.\n\nThe optional first argument mapexpr can be used to transform the included code before it is evaluated: for each parsed expression expr in code, the include_string function actually evaluates mapexpr(expr). If it is omitted, mapexpr defaults to identity.\n\ncompat: Julia 1.5\nJulia 1.5 is required for passing the mapexpr argument.\n\n\n\n\n\n","category":"function"},{"location":"base/base/#Base.include_dependency","page":"基本功能","title":"Base.include_dependency","text":"include_dependency(path::AbstractString)\n\nIn a module, declare that the file specified by path (relative or absolute) is a dependency for precompilation; that is, the module will need to be recompiled if this file changes.\n\nThis is only needed if your module depends on a file that is not used via include. It has no effect outside of compilation.\n\n\n\n\n\n","category":"function"},{"location":"base/base/#Base.which-Tuple{Any, Any}","page":"基本功能","title":"Base.which","text":"which(f, types)\n\nReturns the method of f (a Method object) that would be called for arguments of the given types.\n\nIf types is an abstract type, then the method that would be called by invoke is returned.\n\nSee also: parentmodule, and @which and @edit in InteractiveUtils.\n\n\n\n\n\n","category":"method"},{"location":"base/base/#Base.methods","page":"基本功能","title":"Base.methods","text":"methods(f, [types], [module])\n\nReturn the method table for f.\n\nIf types is specified, return an array of methods whose types match. If module is specified, return an array of methods defined in that module. A list of modules can also be specified as an array.\n\ncompat: Julia 1.4\nAt least Julia 1.4 is required for specifying a module.\n\nSee also: which and @which.\n\n\n\n\n\n","category":"function"},{"location":"base/base/#Base.@show","page":"基本功能","title":"Base.@show","text":"@show exs...\n\nPrints one or more expressions, and their results, to stdout, and returns the last result.\n\nSee also: show, @info, println.\n\nExamples\n\njulia> x = @show 1+2\n1 + 2 = 3\n3\n\njulia> @show x^2 x/2;\nx ^ 2 = 9\nx / 2 = 1.5\n\n\n\n\n\n","category":"macro"},{"location":"base/base/#ans","page":"基本功能","title":"ans","text":"ans\n\nA variable referring to the last computed value, automatically set at the interactive prompt.\n\n\n\n\n\n","category":"keyword"},{"location":"base/base/#Base.active_project","page":"基本功能","title":"Base.active_project","text":"active_project()\n\nReturn the path of the active Project.toml file. See also Base.set_active_project.\n\n\n\n\n\n","category":"function"},{"location":"base/base/#Keywords","page":"基本功能","title":"Keywords","text":"","category":"section"},{"location":"base/base/","page":"基本功能","title":"基本功能","text":"This is the list of reserved keywords in 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. Those keywords are not allowed to be used as variable names.","category":"page"},{"location":"base/base/","page":"基本功能","title":"基本功能","text":"The following two-word sequences are reserved: abstract type, mutable struct, primitive type. However, you can create variables with names: abstract, mutable, primitive and type.","category":"page"},{"location":"base/base/","page":"基本功能","title":"基本功能","text":"Finally: where is parsed as an infix operator for writing parametric method and type definitions; in and isa are parsed as infix operators; and outer is parsed as a keyword when used to modify the scope of a variable in an iteration specification of a for loop or generator expression. Creation of variables named where, in, isa or outer is allowed though.","category":"page"},{"location":"base/base/","page":"基本功能","title":"基本功能","text":"module\nexport\nimport\nusing\nbaremodule\nfunction\nmacro\nreturn\ndo\nbegin\nend\nlet\nif\nfor\nwhile\nbreak\ncontinue\ntry\nfinally\nquote\nlocal\nglobal\nconst\nstruct\nmutable struct\nabstract type\nprimitive type\nwhere\n...\n;\n=\n?:","category":"page"},{"location":"base/base/#module","page":"基本功能","title":"module","text":"module\n\nmodule declares a Module, which is a separate global variable workspace. Within a module, you can control which names from other modules are visible (via importing), and specify which of your names are intended to be public (via exporting). Modules allow you to create top-level definitions without worrying about name conflicts when your code is used together with somebody else’s. See the manual section about modules for more details.\n\nExamples\n\nmodule Foo\nimport Base.show\nexport MyType, foo\n\nstruct MyType\n x\nend\n\nbar(x) = 2x\nfoo(a::MyType) = bar(a.x) + 1\nshow(io::IO, a::MyType) = print(io, \"MyType $(a.x)\")\nend\n\n\n\n\n\n","category":"keyword"},{"location":"base/base/#export","page":"基本功能","title":"export","text":"export\n\nexport is used within modules to tell Julia which functions should be made available to the user. For example: export foo makes the name foo available when using the module. See the manual section about modules for details.\n\n\n\n\n\n","category":"keyword"},{"location":"base/base/#import","page":"基本功能","title":"import","text":"import\n\nimport Foo will load the module or package Foo. Names from the imported Foo module can be accessed with dot syntax (e.g. Foo.foo to access the name foo). See the manual section about modules for details.\n\n\n\n\n\n","category":"keyword"},{"location":"base/base/#using","page":"基本功能","title":"using","text":"using\n\nusing Foo will load the module or package Foo and make its exported names available for direct use. Names can also be used via dot syntax (e.g. Foo.foo to access the name foo), whether they are exported or not. See the manual section about modules for details.\n\n\n\n\n\n","category":"keyword"},{"location":"base/base/#baremodule","page":"基本功能","title":"baremodule","text":"baremodule\n\nbaremodule declares a module that does not contain using Base or local definitions of eval and include. It does still import Core. In other words,\n\nmodule Mod\n\n...\n\nend\n\nis equivalent to\n\nbaremodule Mod\n\nusing Base\n\neval(x) = Core.eval(Mod, x)\ninclude(p) = Base.include(Mod, p)\n\n...\n\nend\n\n\n\n\n\n","category":"keyword"},{"location":"base/base/#function","page":"基本功能","title":"function","text":"function\n\nFunctions are defined with the function keyword:\n\nfunction add(a, b)\n return a + b\nend\n\nOr the short form notation:\n\nadd(a, b) = a + b\n\nThe use of the return keyword is exactly the same as in other languages, but is often optional. A function without an explicit return statement will return the last expression in the function body.\n\n\n\n\n\n","category":"keyword"},{"location":"base/base/#macro","page":"基本功能","title":"macro","text":"macro\n\nmacro defines a method for inserting generated code into a program. A macro maps a sequence of argument expressions to a returned expression, and the resulting expression is substituted directly into the program at the point where the macro is invoked. Macros are a way to run generated code without calling eval, since the generated code instead simply becomes part of the surrounding program. Macro arguments may include expressions, literal values, and symbols. Macros can be defined for variable number of arguments (varargs), but do not accept keyword arguments. Every macro also implicitly gets passed the arguments __source__, which contains the line number and file name the macro is called from, and __module__, which is the module the macro is expanded in.\n\nExamples\n\njulia> macro sayhello(name)\n return :( println(\"Hello, \", $name, \"!\") )\n end\n@sayhello (macro with 1 method)\n\njulia> @sayhello \"Charlie\"\nHello, Charlie!\n\njulia> macro saylots(x...)\n return :( println(\"Say: \", $(x...)) )\n end\n@saylots (macro with 1 method)\n\njulia> @saylots \"hey \" \"there \" \"friend\"\nSay: hey there friend\n\n\n\n\n\n","category":"keyword"},{"location":"base/base/#return","page":"基本功能","title":"return","text":"return\n\nreturn x causes the enclosing function to exit early, passing the given value x back to its caller. return by itself with no value is equivalent to return nothing (see nothing).\n\nfunction compare(a, b)\n a == b && return \"equal to\"\n a < b ? \"less than\" : \"greater than\"\nend\n\nIn general you can place a return statement anywhere within a function body, including within deeply nested loops or conditionals, but be careful with do blocks. For example:\n\nfunction test1(xs)\n for x in xs\n iseven(x) && return 2x\n end\nend\n\nfunction test2(xs)\n map(xs) do x\n iseven(x) && return 2x\n x\n end\nend\n\nIn the first example, the return breaks out of test1 as soon as it hits an even number, so test1([5,6,7]) returns 12.\n\nYou might expect the second example to behave the same way, but in fact the return there only breaks out of the inner function (inside the do block) and gives a value back to map. test2([5,6,7]) then returns [5,12,7].\n\nWhen used in a top-level expression (i.e. outside any function), return causes the entire current top-level expression to terminate early.\n\n\n\n\n\n","category":"keyword"},{"location":"base/base/#do","page":"基本功能","title":"do","text":"do\n\nCreate an anonymous function and pass it as the first argument to a function call. For example:\n\nmap(1:10) do x\n 2x\nend\n\nis equivalent to map(x->2x, 1:10).\n\nUse multiple arguments like so:\n\nmap(1:10, 11:20) do x, y\n x + y\nend\n\n\n\n\n\n","category":"keyword"},{"location":"base/base/#begin","page":"基本功能","title":"begin","text":"begin\n\nbegin...end denotes a block of code.\n\nbegin\n println(\"Hello, \")\n println(\"World!\")\nend\n\nUsually begin will not be necessary, since keywords such as function and let implicitly begin blocks of code. See also ;.\n\nbegin may also be used when indexing to represent the first index of a collection or the first index of a dimension of an array.\n\nExamples\n\njulia> A = [1 2; 3 4]\n2×2 Array{Int64,2}:\n 1 2\n 3 4\n\njulia> A[begin, :]\n2-element Array{Int64,1}:\n 1\n 2\n\n\n\n\n\n","category":"keyword"},{"location":"base/base/#end","page":"基本功能","title":"end","text":"end\n\nend marks the conclusion of a block of expressions, for example module, struct, mutable struct, begin, let, for etc.\n\nend may also be used when indexing to represent the last index of a collection or the last index of a dimension of an array.\n\nExamples\n\njulia> A = [1 2; 3 4]\n2×2 Array{Int64, 2}:\n 1 2\n 3 4\n\njulia> A[end, :]\n2-element Array{Int64, 1}:\n 3\n 4\n\n\n\n\n\n","category":"keyword"},{"location":"base/base/#let","page":"基本功能","title":"let","text":"let\n\nlet statements create a new hard scope block and introduce new variable bindings each time they run. Whereas assignments might reassign a new value to an existing value location, let always creates a new location. This difference is only detectable in the case of variables that outlive their scope via closures. The let syntax accepts a comma-separated series of assignments and variable names:\n\nlet var1 = value1, var2, var3 = value3\n code\nend\n\nThe assignments are evaluated in order, with each right-hand side evaluated in the scope before the new variable on the left-hand side has been introduced. Therefore it makes sense to write something like let x = x, since the two x variables are distinct and have separate storage.\n\n\n\n\n\n","category":"keyword"},{"location":"base/base/#if","page":"基本功能","title":"if","text":"if/elseif/else\n\nif/elseif/else performs conditional evaluation, which allows portions of code to be evaluated or not evaluated depending on the value of a boolean expression. Here is the anatomy of the if/elseif/else conditional syntax:\n\nif x < y\n println(\"x is less than y\")\nelseif x > y\n println(\"x is greater than y\")\nelse\n println(\"x is equal to y\")\nend\n\nIf the condition expression x < y is true, then the corresponding block is evaluated; otherwise the condition expression x > y is evaluated, and if it is true, the corresponding block is evaluated; if neither expression is true, the else block is evaluated. The elseif and else blocks are optional, and as many elseif blocks as desired can be used.\n\nIn contrast to some other languages conditions must be of type Bool. It does not suffice for conditions to be convertible to Bool.\n\njulia> if 1 end\nERROR: TypeError: non-boolean (Int64) used in boolean context\n\n\n\n\n\n","category":"keyword"},{"location":"base/base/#for","page":"基本功能","title":"for","text":"for\n\nfor loops repeatedly evaluate a block of statements while iterating over a sequence of values.\n\nExamples\n\njulia> for i in [1, 4, 0]\n println(i)\n end\n1\n4\n0\n\n\n\n\n\n","category":"keyword"},{"location":"base/base/#while","page":"基本功能","title":"while","text":"while\n\nwhile loops repeatedly evaluate a conditional expression, and continue evaluating the body of the while loop as long as the expression remains true. If the condition expression is false when the while loop is first reached, the body is never evaluated.\n\nExamples\n\njulia> i = 1\n1\n\njulia> while i < 5\n println(i)\n global i += 1\n end\n1\n2\n3\n4\n\n\n\n\n\n","category":"keyword"},{"location":"base/base/#break","page":"基本功能","title":"break","text":"break\n\nBreak out of a loop immediately.\n\nExamples\n\njulia> i = 0\n0\n\njulia> while true\n global i += 1\n i > 5 && break\n println(i)\n end\n1\n2\n3\n4\n5\n\n\n\n\n\n","category":"keyword"},{"location":"base/base/#continue","page":"基本功能","title":"continue","text":"continue\n\nSkip the rest of the current loop iteration.\n\nExamples\n\njulia> for i = 1:6\n iseven(i) && continue\n println(i)\n end\n1\n3\n5\n\n\n\n\n\n","category":"keyword"},{"location":"base/base/#try","page":"基本功能","title":"try","text":"try/catch\n\nA try/catch statement allows intercepting errors (exceptions) thrown by throw so that program execution can continue. For example, the following code attempts to write a file, but warns the user and proceeds instead of terminating execution if the file cannot be written:\n\ntry\n open(\"/danger\", \"w\") do f\n println(f, \"Hello\")\n end\ncatch\n @warn \"Could not write file.\"\nend\n\nor, when the file cannot be read into a variable:\n\nlines = try\n open(\"/danger\", \"r\") do f\n readlines(f)\n end\ncatch\n @warn \"File not found.\"\nend\n\nThe syntax catch e (where e is any variable) assigns the thrown exception object to the given variable within the catch block.\n\nThe power of the try/catch construct lies in the ability to unwind a deeply nested computation immediately to a much higher level in the stack of calling functions.\n\n\n\n\n\n","category":"keyword"},{"location":"base/base/#finally","page":"基本功能","title":"finally","text":"finally\n\nRun some code when a given block of code exits, regardless of how it exits. For example, here is how we can guarantee that an opened file is closed:\n\nf = open(\"file\")\ntry\n operate_on_file(f)\nfinally\n close(f)\nend\n\nWhen control leaves the try block (for example, due to a return, or just finishing normally), close(f) will be executed. If the try block exits due to an exception, the exception will continue propagating. A catch block may be combined with try and finally as well. In this case the finally block will run after catch has handled the error.\n\n\n\n\n\n","category":"keyword"},{"location":"base/base/#quote","page":"基本功能","title":"quote","text":"quote\n\nquote creates multiple expression objects in a block without using the explicit Expr constructor. For example:\n\nex = quote\n x = 1\n y = 2\n x + y\nend\n\nUnlike the other means of quoting, :( ... ), this form introduces QuoteNode elements to the expression tree, which must be considered when directly manipulating the tree. For other purposes, :( ... ) and quote .. end blocks are treated identically.\n\n\n\n\n\n","category":"keyword"},{"location":"base/base/#local","page":"基本功能","title":"local","text":"local\n\nlocal introduces a new local variable. See the manual section on variable scoping for more information.\n\nExamples\n\njulia> function foo(n)\n x = 0\n for i = 1:n\n local x # introduce a loop-local x\n x = i\n end\n x\n end\nfoo (generic function with 1 method)\n\njulia> foo(10)\n0\n\n\n\n\n\n","category":"keyword"},{"location":"base/base/#global","page":"基本功能","title":"global","text":"global\n\nglobal x makes x in the current scope and its inner scopes refer to the global variable of that name. See the manual section on variable scoping for more information.\n\nExamples\n\njulia> z = 3\n3\n\njulia> function foo()\n global z = 6 # use the z variable defined outside foo\n end\nfoo (generic function with 1 method)\n\njulia> foo()\n6\n\njulia> z\n6\n\n\n\n\n\n","category":"keyword"},{"location":"base/base/#const","page":"基本功能","title":"const","text":"const\n\nconst is used to declare global variables whose values will not change. In almost all code (and particularly performance sensitive code) global variables should be declared constant in this way.\n\nconst x = 5\n\nMultiple variables can be declared within a single const:\n\nconst y, z = 7, 11\n\nNote that const only applies to one = operation, therefore const x = y = 1 declares x to be constant but not y. On the other hand, const x = const y = 1 declares both x and y constant.\n\nNote that \"constant-ness\" does not extend into mutable containers; only the association between a variable and its value is constant. If x is an array or dictionary (for example) you can still modify, add, or remove elements.\n\nIn some cases changing the value of a const variable gives a warning instead of an error. However, this can produce unpredictable behavior or corrupt the state of your program, and so should be avoided. This feature is intended only for convenience during interactive use.\n\n\n\n\n\n","category":"keyword"},{"location":"base/base/#struct","page":"基本功能","title":"struct","text":"struct\n\nThe most commonly used kind of type in Julia is a struct, specified as a name and a set of fields.\n\nstruct Point\n x\n y\nend\n\nFields can have type restrictions, which may be parameterized:\n\nstruct Point{X}\n x::X\n y::Float64\nend\n\nA struct can also declare an abstract super type via <: syntax:\n\nstruct Point <: AbstractPoint\n x\n y\nend\n\nstructs are immutable by default; an instance of one of these types cannot be modified after construction. Use mutable struct instead to declare a type whose instances can be modified.\n\nSee the manual section on Composite Types for more details, such as how to define constructors.\n\n\n\n\n\n","category":"keyword"},{"location":"base/base/#mutable struct","page":"基本功能","title":"mutable struct","text":"mutable struct\n\nmutable struct is similar to struct, but additionally allows the fields of the type to be set after construction. See the manual section on Composite Types for more information.\n\n\n\n\n\n","category":"keyword"},{"location":"base/base/#abstract type","page":"基本功能","title":"abstract type","text":"abstract type\n\nabstract type declares a type that cannot be instantiated, and serves only as a node in the type graph, thereby describing sets of related concrete types: those concrete types which are their descendants. Abstract types form the conceptual hierarchy which makes Julia’s type system more than just a collection of object implementations. For example:\n\nabstract type Number end\nabstract type Real <: Number end\n\nNumber has no supertype, whereas Real is an abstract subtype of Number.\n\n\n\n\n\n","category":"keyword"},{"location":"base/base/#primitive type","page":"基本功能","title":"primitive type","text":"primitive type\n\nprimitive type declares a concrete type whose data consists only of a series of bits. Classic examples of primitive types are integers and floating-point values. Some example built-in primitive type declarations:\n\nprimitive type Char 32 end\nprimitive type Bool <: Integer 8 end\n\nThe number after the name indicates how many bits of storage the type requires. Currently, only sizes that are multiples of 8 bits are supported. The Bool declaration shows how a primitive type can be optionally declared to be a subtype of some supertype.\n\n\n\n\n\n","category":"keyword"},{"location":"base/base/#where","page":"基本功能","title":"where","text":"where\n\nThe where keyword creates a type that is an iterated union of other types, over all values of some variable. For example Vector{T} where T<:Real includes all Vectors where the element type is some kind of Real number.\n\nThe variable bound defaults to Any if it is omitted:\n\nVector{T} where T # short for `where T<:Any`\n\nVariables can also have lower bounds:\n\nVector{T} where T>:Int\nVector{T} where Int<:T<:Real\n\nThere is also a concise syntax for nested where expressions. For example, this:\n\nPair{T, S} where S<:Array{T} where T<:Number\n\ncan be shortened to:\n\nPair{T, S} where {T<:Number, S<:Array{T}}\n\nThis form is often found on method signatures.\n\nNote that in this form, the variables are listed outermost-first. This matches the order in which variables are substituted when a type is \"applied\" to parameter values using the syntax T{p1, p2, ...}.\n\n\n\n\n\n","category":"keyword"},{"location":"base/base/#...","page":"基本功能","title":"...","text":"...\n\nThe \"splat\" operator, ..., represents a sequence of arguments. ... can be used in function definitions, to indicate that the function accepts an arbitrary number of arguments. ... can also be used to apply a function to a sequence of arguments.\n\nExamples\n\njulia> add(xs...) = reduce(+, xs)\nadd (generic function with 1 method)\n\njulia> add(1, 2, 3, 4, 5)\n15\n\njulia> add([1, 2, 3]...)\n6\n\njulia> add(7, 1:100..., 1000:1100...)\n111107\n\n\n\n\n\n","category":"keyword"},{"location":"base/base/#;","page":"基本功能","title":";","text":";\n\n; has a similar role in Julia as in many C-like languages, and is used to delimit the end of the previous statement.\n\n; is not necessary at the end of a line, but can be used to separate statements on a single line or to join statements into a single expression.\n\nAdding ; at the end of a line in the REPL will suppress printing the result of that expression.\n\nIn function declarations, and optionally in calls, ; separates regular arguments from keywords.\n\nWhile constructing arrays, if the arguments inside the square brackets are separated by ; then their contents are vertically concatenated together.\n\nIn the standard REPL, typing ; on an empty line will switch to shell mode.\n\nExamples\n\njulia> function foo()\n x = \"Hello, \"; x *= \"World!\"\n return x\n end\nfoo (generic function with 1 method)\n\njulia> bar() = (x = \"Hello, Mars!\"; return x)\nbar (generic function with 1 method)\n\njulia> foo();\n\njulia> bar()\n\"Hello, Mars!\"\n\njulia> function plot(x, y; style=\"solid\", width=1, color=\"black\")\n ###\n end\n\njulia> [1 2; 3 4]\n2×2 Matrix{Int64}:\n 1 2\n 3 4\n\njulia> ; # upon typing ;, the prompt changes (in place) to: shell>\nshell> echo hello\nhello\n\n\n\n\n\n","category":"keyword"},{"location":"base/base/#=","page":"基本功能","title":"=","text":"=\n\n= is the assignment operator.\n\nFor variable a and expression b, a = b makes a refer to the value of b.\nFor functions f(x), f(x) = x defines a new function constant f, or adds a new method to f if f is already defined; this usage is equivalent to function f(x); x; end.\na[i] = v calls setindex!(a,v,i).\na.b = c calls setproperty!(a,:b,c).\nInside a function call, f(a=b) passes b as the value of keyword argument a.\nInside parentheses with commas, (a=1,) constructs a NamedTuple.\n\nExamples\n\nAssigning a to b does not create a copy of b; instead use copy or deepcopy.\n\njulia> b = [1]; a = b; b[1] = 2; a\n1-element Array{Int64, 1}:\n 2\n\njulia> b = [1]; a = copy(b); b[1] = 2; a\n1-element Array{Int64, 1}:\n 1\n\n\nCollections passed to functions are also not copied. Functions can modify (mutate) the contents of the objects their arguments refer to. (The names of functions which do this are conventionally suffixed with '!'.)\n\njulia> function f!(x); x[:] .+= 1; end\nf! (generic function with 1 method)\n\njulia> a = [1]; f!(a); a\n1-element Array{Int64, 1}:\n 2\n\n\nAssignment can operate on multiple variables in parallel, taking values from an iterable:\n\njulia> a, b = 4, 5\n(4, 5)\n\njulia> a, b = 1:3\n1:3\n\njulia> a, b\n(1, 2)\n\n\nAssignment can operate on multiple variables in series, and will return the value of the right-hand-most expression:\n\njulia> a = [1]; b = [2]; c = [3]; a = b = c\n1-element Array{Int64, 1}:\n 3\n\njulia> b[1] = 2; a, b, c\n([2], [2], [2])\n\n\nAssignment at out-of-bounds indices does not grow a collection. If the collection is a Vector it can instead be grown with push! or append!.\n\njulia> a = [1, 1]; a[3] = 2\nERROR: BoundsError: attempt to access 2-element Array{Int64, 1} at index [3]\n[...]\n\njulia> push!(a, 2, 3)\n4-element Array{Int64, 1}:\n 1\n 1\n 2\n 3\n\n\nAssigning [] does not eliminate elements from a collection; instead use filter!.\n\njulia> a = collect(1:3); a[a .<= 1] = []\nERROR: DimensionMismatch: tried to assign 0 elements to 1 destinations\n[...]\n\njulia> filter!(x -> x > 1, a) # in-place & thus more efficient than a = a[a .> 1]\n2-element Array{Int64, 1}:\n 2\n 3\n\n\n\n\n\n\n","category":"keyword"},{"location":"base/base/#?:","page":"基本功能","title":"?:","text":"a ? b : c\n\nShort form for conditionals; read \"if a, evaluate b otherwise evaluate c\". Also known as the ternary operator.\n\nThis syntax is equivalent to if a; b else c end, but is often used to emphasize the value b-or-c which is being used as part of a larger expression, rather than the side effects that evaluating b or c may have.\n\nSee the manual section on control flow for more details.\n\nExamples\n\njulia> x = 1; y = 2;\n\njulia> x > y ? println(\"x is larger\") : println(\"y is larger\")\ny is larger\n\n\n\n\n\n","category":"keyword"},{"location":"base/base/#Standard-Modules","page":"基本功能","title":"Standard Modules","text":"","category":"section"},{"location":"base/base/","page":"基本功能","title":"基本功能","text":"Main\nCore\nBase","category":"page"},{"location":"base/base/#Core","page":"基本功能","title":"Core","text":"Core\n\nCore is the module that contains all identifiers considered \"built in\" to the language, i.e. part of the core language and not libraries. Every module implicitly specifies using Core, since you can't do anything without those definitions.\n\n\n\n\n\n","category":"module"},{"location":"base/base/#Base","page":"基本功能","title":"Base","text":"Base\n\nThe base library of Julia. Base is a module that contains basic functionality (the contents of base/). All modules implicitly contain using Base, since this is needed in the vast majority of cases.\n\n\n\n\n\n","category":"module"},{"location":"base/base/#Base-Submodules","page":"基本功能","title":"Base Submodules","text":"","category":"section"},{"location":"base/base/","page":"基本功能","title":"基本功能","text":"Base.Broadcast\nBase.Docs\nBase.Iterators\nBase.Libc\nBase.Meta\nBase.StackTraces\nBase.Sys\nBase.Threads\nBase.GC","category":"page"},{"location":"base/base/#Base.Broadcast","page":"基本功能","title":"Base.Broadcast","text":"Base.Broadcast\n\nModule containing the broadcasting implementation.\n\n\n\n\n\n","category":"module"},{"location":"base/base/#Base.Docs","page":"基本功能","title":"Base.Docs","text":"Docs\n\nThe Docs module provides the @doc macro which can be used to set and retrieve documentation metadata for Julia objects.\n\nPlease see the manual section on documentation for more information.\n\n\n\n\n\n","category":"module"},{"location":"base/base/#Base.Iterators","page":"基本功能","title":"Base.Iterators","text":"Methods for working with Iterators.\n\n\n\n\n\n","category":"module"},{"location":"base/base/#Base.Libc","page":"基本功能","title":"Base.Libc","text":"Interface to libc, the C standard library.\n\n\n\n\n\n","category":"module"},{"location":"base/base/#Base.Meta","page":"基本功能","title":"Base.Meta","text":"Convenience functions for metaprogramming.\n\n\n\n\n\n","category":"module"},{"location":"base/base/#Base.StackTraces","page":"基本功能","title":"Base.StackTraces","text":"Tools for collecting and manipulating stack traces. Mainly used for building errors.\n\n\n\n\n\n","category":"module"},{"location":"base/base/#Base.Sys","page":"基本功能","title":"Base.Sys","text":"Provide methods for retrieving information about hardware and the operating system.\n\n\n\n\n\n","category":"module"},{"location":"base/base/#Base.Threads","page":"基本功能","title":"Base.Threads","text":"Multithreading support.\n\n\n\n\n\n","category":"module"},{"location":"base/base/#Base.GC","page":"基本功能","title":"Base.GC","text":"Base.GC\n\nModule with garbage collection utilities.\n\n\n\n\n\n","category":"module"},{"location":"base/base/#All-Objects","page":"基本功能","title":"All Objects","text":"","category":"section"},{"location":"base/base/","page":"基本功能","title":"基本功能","text":"Core.:(===)\nCore.isa\nBase.isequal\nBase.isless\nBase.ifelse\nCore.typeassert\nCore.typeof\nCore.tuple\nBase.ntuple\nBase.objectid\nBase.hash\nBase.finalizer\nBase.finalize\nBase.copy\nBase.deepcopy\nBase.getproperty\nBase.setproperty!\nBase.propertynames\nBase.hasproperty\nCore.getfield\nCore.setfield!\nCore.isdefined\nBase.@isdefined\nBase.convert\nBase.promote\nBase.oftype\nBase.widen\nBase.identity","category":"page"},{"location":"base/base/#Core.:===","page":"基本功能","title":"Core.:===","text":"===(x,y) -> Bool\n≡(x,y) -> Bool\n\nDetermine whether x and y are identical, in the sense that no program could distinguish them. First the types of x and y are compared. If those are identical, mutable objects are compared by address in memory and immutable objects (such as numbers) are compared by contents at the bit level. This function is sometimes called \"egal\". It always returns a Bool value.\n\nExamples\n\njulia> a = [1, 2]; b = [1, 2];\n\njulia> a == b\ntrue\n\njulia> a === b\nfalse\n\njulia> a === a\ntrue\n\n\n\n\n\n","category":"function"},{"location":"base/base/#Core.isa","page":"基本功能","title":"Core.isa","text":"isa(x, type) -> Bool\n\nDetermine whether x is of the given type. Can also be used as an infix operator, e.g. x isa type.\n\nExamples\n\njulia> isa(1, Int)\ntrue\n\njulia> isa(1, Matrix)\nfalse\n\njulia> isa(1, Char)\nfalse\n\njulia> isa(1, Number)\ntrue\n\njulia> 1 isa Number\ntrue\n\n\n\n\n\n","category":"function"},{"location":"base/base/#Base.isequal","page":"基本功能","title":"Base.isequal","text":"isequal(x, y)\n\nSimilar to ==, except for the treatment of floating point numbers and of missing values. isequal treats all floating-point NaN values as equal to each other, treats -0.0 as unequal to 0.0, and missing as equal to missing. Always returns a Bool value.\n\nisequal is an equivalence relation - it is reflexive (=== implies isequal), symmetric (isequal(a, b) implies isequal(b, a)) and transitive (isequal(a, b) and isequal(b, c) implies isequal(a, c)).\n\nImplementation\n\nThe default implementation of isequal calls ==, so a type that does not involve floating-point values generally only needs to define ==.\n\nisequal is the comparison function used by hash tables (Dict). isequal(x,y) must imply that hash(x) == hash(y).\n\nThis typically means that types for which a custom == or isequal method exists must implement a corresponding hash method (and vice versa). Collections typically implement isequal by calling isequal recursively on all contents.\n\nFurthermore, isequal is linked with isless, and they work together to define a fixed total ordering, where exactly one of isequal(x, y), isless(x, y), or isless(y, x) must be true (and the other two false).\n\nScalar types generally do not need to implement isequal separate from ==, unless they represent floating-point numbers amenable to a more efficient implementation than that provided as a generic fallback (based on isnan, signbit, and ==).\n\nExamples\n\njulia> isequal([1., NaN], [1., NaN])\ntrue\n\njulia> [1., NaN] == [1., NaN]\nfalse\n\njulia> 0.0 == -0.0\ntrue\n\njulia> isequal(0.0, -0.0)\nfalse\n\njulia> missing == missing\nmissing\n\njulia> isequal(missing, missing)\ntrue\n\n\n\n\n\nisequal(x)\n\nCreate a function that compares its argument to x using isequal, i.e. a function equivalent to y -> isequal(y, x).\n\nThe returned function is of type Base.Fix2{typeof(isequal)}, which can be used to implement specialized methods.\n\n\n\n\n\n","category":"function"},{"location":"base/base/#Base.isless","page":"基本功能","title":"Base.isless","text":"isless(x, y)\n\nTest whether x is less than y, according to a fixed total order (defined together with isequal). isless is not defined on all pairs of values (x, y). However, if it is defined, it is expected to satisfy the following:\n\nIf isless(x, y) is defined, then so is isless(y, x) and isequal(x, y), and exactly one of those three yields true.\nThe relation defined by isless is transitive, i.e., isless(x, y) && isless(y, z) implies isless(x, z).\n\nValues that are normally unordered, such as NaN, are ordered after regular values. missing values are ordered last.\n\nThis is the default comparison used by sort.\n\nImplementation\n\nNon-numeric types with a total order should implement this function. Numeric types only need to implement it if they have special values such as NaN. Types with a partial order should implement <. See the documentation on Alternate orderings for how to define alternate ordering methods that can be used in sorting and related functions.\n\nExamples\n\njulia> isless(1, 3)\ntrue\n\njulia> isless(\"Red\", \"Blue\")\nfalse\n\n\n\n\n\n","category":"function"},{"location":"base/base/#Base.ifelse","page":"基本功能","title":"Base.ifelse","text":"ifelse(condition::Bool, x, y)\n\nReturn x if condition is true, otherwise return y. This differs from ? or if in that it is an ordinary function, so all the arguments are evaluated first. In some cases, using ifelse instead of an if statement can eliminate the branch in generated code and provide higher performance in tight loops.\n\nExamples\n\njulia> ifelse(1 > 2, 1, 2)\n2\n\n\n\n\n\n","category":"function"},{"location":"base/base/#Core.typeassert","page":"基本功能","title":"Core.typeassert","text":"typeassert(x, type)\n\nThrow a TypeError unless x isa type. The syntax x::type calls this function.\n\nExamples\n\njulia> typeassert(2.5, Int)\nERROR: TypeError: in typeassert, expected Int64, got a value of type Float64\nStacktrace:\n[...]\n\n\n\n\n\n","category":"function"},{"location":"base/base/#Core.typeof","page":"基本功能","title":"Core.typeof","text":"typeof(x)\n\nGet the concrete type of x.\n\nSee also eltype.\n\nExamples\n\njulia> a = 1//2;\n\njulia> typeof(a)\nRational{Int64}\n\njulia> M = [1 2; 3.5 4];\n\njulia> typeof(M)\nMatrix{Float64} (alias for Array{Float64, 2})\n\n\n\n\n\n","category":"function"},{"location":"base/base/#Core.tuple","page":"基本功能","title":"Core.tuple","text":"tuple(xs...)\n\nConstruct a tuple of the given objects.\n\nSee also Tuple, NamedTuple.\n\nExamples\n\njulia> tuple(1, 'b', pi)\n(1, 'b', π)\n\njulia> ans === (1, 'b', π)\ntrue\n\njulia> Tuple(Real[1, 2, pi]) # takes a collection\n(1, 2, π)\n\n\n\n\n\n","category":"function"},{"location":"base/base/#Base.ntuple","page":"基本功能","title":"Base.ntuple","text":"ntuple(f::Function, n::Integer)\n\nCreate a tuple of length n, computing each element as f(i), where i is the index of the element.\n\nExamples\n\njulia> ntuple(i -> 2*i, 4)\n(2, 4, 6, 8)\n\n\n\n\n\nntuple(f, ::Val{N})\n\nCreate a tuple of length N, computing each element as f(i), where i is the index of the element. By taking a Val(N) argument, it is possible that this version of ntuple may generate more efficient code than the version taking the length as an integer. But ntuple(f, N) is preferable to ntuple(f, Val(N)) in cases where N cannot be determined at compile time.\n\nExamples\n\njulia> ntuple(i -> 2*i, Val(4))\n(2, 4, 6, 8)\n\n\n\n\n\n","category":"function"},{"location":"base/base/#Base.objectid","page":"基本功能","title":"Base.objectid","text":"objectid(x) -> UInt\n\nGet a hash value for x based on object identity. objectid(x)==objectid(y) if x === y.\n\nSee also hash, IdDict.\n\n\n\n\n\n","category":"function"},{"location":"base/base/#Base.hash","page":"基本功能","title":"Base.hash","text":"hash(x[, h::UInt]) -> UInt\n\nCompute an integer hash code such that isequal(x,y) implies hash(x)==hash(y). The optional second argument h is a hash code to be mixed with the result.\n\nNew types should implement the 2-argument form, typically by calling the 2-argument hash method recursively in order to mix hashes of the contents with each other (and with h). Typically, any type that implements hash should also implement its own == (hence isequal) to guarantee the property mentioned above. Types supporting subtraction (operator -) should also implement widen, which is required to hash values inside heterogeneous arrays.\n\nSee also: objectid, Dict, Set.\n\n\n\n\n\n","category":"function"},{"location":"base/base/#Base.finalizer","page":"基本功能","title":"Base.finalizer","text":"finalizer(f, x)\n\nRegister a function f(x) to be called when there are no program-accessible references to x, and return x. The type of x must be a mutable struct, otherwise the behavior of this function is unpredictable.\n\nf must not cause a task switch, which excludes most I/O operations such as println. Using the @async macro (to defer context switching to outside of the finalizer) or ccall to directly invoke IO functions in C may be helpful for debugging purposes.\n\nExamples\n\nfinalizer(my_mutable_struct) do x\n @async println(\"Finalizing $x.\")\nend\n\nfinalizer(my_mutable_struct) do x\n ccall(:jl_safe_printf, Cvoid, (Cstring, Cstring), \"Finalizing %s.\", repr(x))\nend\n\nA finalizer may be registered at object construction. In the following example note that we implicitly rely on the finalizer returning the newly created mutable struct x.\n\nExample\n\nmutable struct MyMutableStruct\n bar\n function MyMutableStruct(bar)\n x = new(bar)\n f(t) = @async println(\"Finalizing $t.\")\n finalizer(f, x)\n end\nend\n\n\n\n\n\n","category":"function"},{"location":"base/base/#Base.finalize","page":"基本功能","title":"Base.finalize","text":"finalize(x)\n\nImmediately run finalizers registered for object x.\n\n\n\n\n\n","category":"function"},{"location":"base/base/#Base.copy","page":"基本功能","title":"Base.copy","text":"copy(x)\n\nCreate a shallow copy of x: the outer structure is copied, but not all internal values. For example, copying an array produces a new array with identically-same elements as the original.\n\nSee also copy!, copyto!.\n\n\n\n\n\n","category":"function"},{"location":"base/base/#Base.deepcopy","page":"基本功能","title":"Base.deepcopy","text":"deepcopy(x)\n\nCreate a deep copy of x: everything is copied recursively, resulting in a fully independent object. For example, deep-copying an array produces a new array whose elements are deep copies of the original elements. Calling deepcopy on an object should generally have the same effect as serializing and then deserializing it.\n\nWhile it isn't normally necessary, user-defined types can override the default deepcopy behavior by defining a specialized version of the function deepcopy_internal(x::T, dict::IdDict) (which shouldn't otherwise be used), where T is the type to be specialized for, and dict keeps track of objects copied so far within the recursion. Within the definition, deepcopy_internal should be used in place of deepcopy, and the dict variable should be updated as appropriate before returning.\n\n\n\n\n\n","category":"function"},{"location":"base/base/#Base.getproperty","page":"基本功能","title":"Base.getproperty","text":"getproperty(value, name::Symbol)\ngetproperty(value, name::Symbol, order::Symbol)\n\nThe syntax a.b calls getproperty(a, :b). The syntax @atomic order a.b calls getproperty(a, :b, :order) and the syntax @atomic a.b calls getproperty(a, :b, :sequentially_consistent).\n\nExamples\n\njulia> struct MyType\n x\n end\n\njulia> function Base.getproperty(obj::MyType, sym::Symbol)\n if sym === :special\n return obj.x + 1\n else # fallback to getfield\n return getfield(obj, sym)\n end\n end\n\njulia> obj = MyType(1);\n\njulia> obj.special\n2\n\njulia> obj.x\n1\n\nSee also getfield, propertynames and setproperty!.\n\n\n\n\n\n","category":"function"},{"location":"base/base/#Base.setproperty!","page":"基本功能","title":"Base.setproperty!","text":"setproperty!(value, name::Symbol, x)\nsetproperty!(value, name::Symbol, x, order::Symbol)\n\nThe syntax a.b = c calls setproperty!(a, :b, c). The syntax @atomic order a.b = c calls setproperty!(a, :b, c, :order) and the syntax @atomic a.b = c calls getproperty(a, :b, :sequentially_consistent).\n\nSee also setfield!, propertynames and getproperty.\n\n\n\n\n\n","category":"function"},{"location":"base/base/#Base.propertynames","page":"基本功能","title":"Base.propertynames","text":"propertynames(x, private=false)\n\nGet a tuple or a vector of the properties (x.property) of an object x. This is typically the same as fieldnames(typeof(x)), but types that overload getproperty should generally overload propertynames as well to get the properties of an instance of the type.\n\npropertynames(x) may return only \"public\" property names that are part of the documented interface of x. If you want it to also return \"private\" fieldnames intended for internal use, pass true for the optional second argument. REPL tab completion on x. shows only the private=false properties.\n\nSee also: hasproperty, hasfield.\n\n\n\n\n\n","category":"function"},{"location":"base/base/#Base.hasproperty","page":"基本功能","title":"Base.hasproperty","text":"hasproperty(x, s::Symbol)\n\nReturn a boolean indicating whether the object x has s as one of its own properties.\n\ncompat: Julia 1.2\nThis function requires at least Julia 1.2.\n\nSee also: propertynames, hasfield.\n\n\n\n\n\n","category":"function"},{"location":"base/base/#Core.getfield","page":"基本功能","title":"Core.getfield","text":"getfield(value, name::Symbol, [order::Symbol])\ngetfield(value, i::Int, [order::Symbol])\n\nExtract a field from a composite value by name or position. Optionally, an ordering can be defined for the operation. If the field was declared @atomic, the specification is strongly recommended to be compatible with the stores to that location. Otherwise, if not declared as @atomic, this parameter must be :not_atomic if specified. See also getproperty and fieldnames.\n\nExamples\n\njulia> a = 1//2\n1//2\n\njulia> getfield(a, :num)\n1\n\njulia> a.num\n1\n\njulia> getfield(a, 1)\n1\n\n\n\n\n\n","category":"function"},{"location":"base/base/#Core.setfield!","page":"基本功能","title":"Core.setfield!","text":"setfield!(value, name::Symbol, x, [order::Symbol])\nsetfield!(value, i::Int, x, [order::Symbol])\n\nAssign x to a named field in value of composite type. The value must be mutable and x must be a subtype of fieldtype(typeof(value), name). Additionally, an ordering can be specified for this operation. If the field was declared @atomic, this specification is mandatory. Otherwise, if not declared as @atomic, it must be :not_atomic if specified. See also setproperty!.\n\nExamples\n\njulia> mutable struct MyMutableStruct\n field::Int\n end\n\njulia> a = MyMutableStruct(1);\n\njulia> setfield!(a, :field, 2);\n\njulia> getfield(a, :field)\n2\n\njulia> a = 1//2\n1//2\n\njulia> setfield!(a, :num, 3);\nERROR: setfield!: immutable struct of type Rational cannot be changed\n\n\n\n\n\n","category":"function"},{"location":"base/base/#Core.isdefined","page":"基本功能","title":"Core.isdefined","text":"isdefined(m::Module, s::Symbol, [order::Symbol])\nisdefined(object, s::Symbol, [order::Symbol])\nisdefined(object, index::Int, [order::Symbol])\n\nTests whether a global variable or object field is defined. The arguments can be a module and a symbol or a composite object and field name (as a symbol) or index. Optionally, an ordering can be defined for the operation. If the field was declared @atomic, the specification is strongly recommended to be compatible with the stores to that location. Otherwise, if not declared as @atomic, this parameter must be :not_atomic if specified.\n\nTo test whether an array element is defined, use isassigned instead.\n\nSee also @isdefined.\n\nExamples\n\njulia> isdefined(Base, :sum)\ntrue\n\njulia> isdefined(Base, :NonExistentMethod)\nfalse\n\njulia> a = 1//2;\n\njulia> isdefined(a, 2)\ntrue\n\njulia> isdefined(a, 3)\nfalse\n\njulia> isdefined(a, :num)\ntrue\n\njulia> isdefined(a, :numerator)\nfalse\n\n\n\n\n\n","category":"function"},{"location":"base/base/#Base.@isdefined","page":"基本功能","title":"Base.@isdefined","text":"@isdefined s -> Bool\n\nTests whether variable s is defined in the current scope.\n\nSee also isdefined for field properties and isassigned for array indexes or haskey for other mappings.\n\nExamples\n\njulia> @isdefined newvar\nfalse\n\njulia> newvar = 1\n1\n\njulia> @isdefined newvar\ntrue\n\njulia> function f()\n println(@isdefined x)\n x = 3\n println(@isdefined x)\n end\nf (generic function with 1 method)\n\njulia> f()\nfalse\ntrue\n\n\n\n\n\n","category":"macro"},{"location":"base/base/#Base.convert","page":"基本功能","title":"Base.convert","text":"convert(T, x)\n\nConvert x to a value of type T.\n\nIf T is an Integer type, an InexactError will be raised if x is not representable by T, for example if x is not integer-valued, or is outside the range supported by T.\n\nExamples\n\njulia> convert(Int, 3.0)\n3\n\njulia> convert(Int, 3.5)\nERROR: InexactError: Int64(3.5)\nStacktrace:\n[...]\n\nIf T is a AbstractFloat type, then it will return the closest value to x representable by T.\n\njulia> x = 1/3\n0.3333333333333333\n\njulia> convert(Float32, x)\n0.33333334f0\n\njulia> convert(BigFloat, x)\n0.333333333333333314829616256247390992939472198486328125\n\nIf T is a collection type and x a collection, the result of convert(T, x) may alias all or part of x.\n\njulia> x = Int[1, 2, 3];\n\njulia> y = convert(Vector{Int}, x);\n\njulia> y === x\ntrue\n\nSee also: round, trunc, oftype, reinterpret.\n\n\n\n\n\n","category":"function"},{"location":"base/base/#Base.promote","page":"基本功能","title":"Base.promote","text":"promote(xs...)\n\nConvert all arguments to a common type, and return them all (as a tuple). If no arguments can be converted, an error is raised.\n\nSee also: [promote_type], [promote_rule].\n\nExamples\n\njulia> promote(Int8(1), Float16(4.5), Float32(4.1))\n(1.0f0, 4.5f0, 4.1f0)\n\n\n\n\n\n","category":"function"},{"location":"base/base/#Base.oftype","page":"基本功能","title":"Base.oftype","text":"oftype(x, y)\n\nConvert y to the type of x (convert(typeof(x), y)).\n\nExamples\n\njulia> x = 4;\n\njulia> y = 3.;\n\njulia> oftype(x, y)\n3\n\njulia> oftype(y, x)\n4.0\n\n\n\n\n\n","category":"function"},{"location":"base/base/#Base.widen","page":"基本功能","title":"Base.widen","text":"widen(x)\n\nIf x is a type, return a \"larger\" type, defined so that arithmetic operations + and - are guaranteed not to overflow nor lose precision for any combination of values that type x can hold.\n\nFor fixed-size integer types less than 128 bits, widen will return a type with twice the number of bits.\n\nIf x is a value, it is converted to widen(typeof(x)).\n\nExamples\n\njulia> widen(Int32)\nInt64\n\njulia> widen(1.5f0)\n1.5\n\n\n\n\n\n","category":"function"},{"location":"base/base/#Base.identity","page":"基本功能","title":"Base.identity","text":"identity(x)\n\nThe identity function. Returns its argument.\n\nSee also: one, oneunit, and LinearAlgebra's I.\n\nExamples\n\njulia> identity(\"Well, what did you expect?\")\n\"Well, what did you expect?\"\n\n\n\n\n\n","category":"function"},{"location":"base/base/#Properties-of-Types","page":"基本功能","title":"Properties of Types","text":"","category":"section"},{"location":"base/base/#Type-relations","page":"基本功能","title":"Type relations","text":"","category":"section"},{"location":"base/base/","page":"基本功能","title":"基本功能","text":"Base.supertype\nCore.Type\nCore.DataType\nCore.:(<:)\nBase.:(>:)\nBase.typejoin\nBase.typeintersect\nBase.promote_type\nBase.promote_rule\nBase.promote_typejoin\nBase.isdispatchtuple","category":"page"},{"location":"base/base/#Base.supertype","page":"基本功能","title":"Base.supertype","text":"supertype(T::DataType)\n\nReturn the supertype of DataType T.\n\nExamples\n\njulia> supertype(Int32)\nSigned\n\n\n\n\n\n","category":"function"},{"location":"base/base/#Core.Type","page":"基本功能","title":"Core.Type","text":"Core.Type{T}\n\nCore.Type is an abstract type which has all type objects as its instances. The only instance of the singleton type Core.Type{T} is the object T.\n\nExamples\n\njulia> isa(Type{Float64}, Type)\ntrue\n\njulia> isa(Float64, Type)\ntrue\n\njulia> isa(Real, Type{Float64})\nfalse\n\njulia> isa(Real, Type{Real})\ntrue\n\n\n\n\n\n","category":"type"},{"location":"base/base/#Core.DataType","page":"基本功能","title":"Core.DataType","text":"DataType <: Type{T}\n\nDataType represents explicitly declared types that have names, explicitly declared supertypes, and, optionally, parameters. Every concrete value in the system is an instance of some DataType.\n\nExamples\n\njulia> typeof(Real)\nDataType\n\njulia> typeof(Int)\nDataType\n\njulia> struct Point\n x::Int\n y\n end\n\njulia> typeof(Point)\nDataType\n\n\n\n\n\n","category":"type"},{"location":"base/base/#Core.:<:","page":"基本功能","title":"Core.:<:","text":"<:(T1, T2)\n\nSubtype operator: returns true if and only if all values of type T1 are also of type T2.\n\nExamples\n\njulia> Float64 <: AbstractFloat\ntrue\n\njulia> Vector{Int} <: AbstractArray\ntrue\n\njulia> Matrix{Float64} <: Matrix{AbstractFloat}\nfalse\n\n\n\n\n\n","category":"function"},{"location":"base/base/#Base.:>:","page":"基本功能","title":"Base.:>:","text":">:(T1, T2)\n\nSupertype operator, equivalent to T2 <: T1.\n\n\n\n\n\n","category":"function"},{"location":"base/base/#Base.typejoin","page":"基本功能","title":"Base.typejoin","text":"typejoin(T, S)\n\nReturn the closest common ancestor of T and S, i.e. the narrowest type from which they both inherit.\n\n\n\n\n\n","category":"function"},{"location":"base/base/#Base.typeintersect","page":"基本功能","title":"Base.typeintersect","text":"typeintersect(T::Type, S::Type)\n\nCompute a type that contains the intersection of T and S. Usually this will be the smallest such type or one close to it.\n\n\n\n\n\n","category":"function"},{"location":"base/base/#Base.promote_type","page":"基本功能","title":"Base.promote_type","text":"promote_type(type1, type2)\n\nPromotion refers to converting values of mixed types to a single common type. promote_type represents the default promotion behavior in Julia when operators (usually mathematical) are given arguments of differing types. promote_type generally tries to return a type which can at least approximate most values of either input type without excessively widening. Some loss is tolerated; for example, promote_type(Int64, Float64) returns Float64 even though strictly, not all Int64 values can be represented exactly as Float64 values.\n\nSee also: promote, promote_typejoin, promote_rule.\n\nExamples\n\njulia> promote_type(Int64, Float64)\nFloat64\n\njulia> promote_type(Int32, Int64)\nInt64\n\njulia> promote_type(Float32, BigInt)\nBigFloat\n\njulia> promote_type(Int16, Float16)\nFloat16\n\njulia> promote_type(Int64, Float16)\nFloat16\n\njulia> promote_type(Int8, UInt16)\nUInt16\n\nwarning: Don't overload this directly\nTo overload promotion for your own types you should overload promote_rule. promote_type calls promote_rule internally to determine the type. Overloading promote_type directly can cause ambiguity errors.\n\n\n\n\n\n","category":"function"},{"location":"base/base/#Base.promote_rule","page":"基本功能","title":"Base.promote_rule","text":"promote_rule(type1, type2)\n\nSpecifies what type should be used by promote when given values of types type1 and type2. This function should not be called directly, but should have definitions added to it for new types as appropriate.\n\n\n\n\n\n","category":"function"},{"location":"base/base/#Base.promote_typejoin","page":"基本功能","title":"Base.promote_typejoin","text":"promote_typejoin(T, S)\n\nCompute a type that contains both T and S, which could be either a parent of both types, or a Union if appropriate. Falls back to typejoin.\n\nSee instead promote, promote_type.\n\nExamples\n\njulia> Base.promote_typejoin(Int, Float64)\nReal\n\njulia> Base.promote_type(Int, Float64)\nFloat64\n\n\n\n\n\n","category":"function"},{"location":"base/base/#Base.isdispatchtuple","page":"基本功能","title":"Base.isdispatchtuple","text":"isdispatchtuple(T)\n\nDetermine whether type T is a tuple \"leaf type\", meaning it could appear as a type signature in dispatch and has no subtypes (or supertypes) which could appear in a call.\n\n\n\n\n\n","category":"function"},{"location":"base/base/#Declared-structure","page":"基本功能","title":"Declared structure","text":"","category":"section"},{"location":"base/base/","page":"基本功能","title":"基本功能","text":"Base.ismutable\nBase.isimmutable\nBase.isabstracttype\nBase.isprimitivetype\nBase.issingletontype\nBase.isstructtype\nBase.nameof(::DataType)\nBase.fieldnames\nBase.fieldname\nBase.hasfield","category":"page"},{"location":"base/base/#Base.ismutable","page":"基本功能","title":"Base.ismutable","text":"ismutable(v) -> Bool\n\nReturn true if and only if value v is mutable. See Mutable Composite Types for a discussion of immutability. Note that this function works on values, so if you give it a type, it will tell you that a value of DataType is mutable.\n\nSee also isbits, isstructtype.\n\nExamples\n\njulia> ismutable(1)\nfalse\n\njulia> ismutable([1,2])\ntrue\n\ncompat: Julia 1.5\nThis function requires at least Julia 1.5.\n\n\n\n\n\n","category":"function"},{"location":"base/base/#Base.isimmutable","page":"基本功能","title":"Base.isimmutable","text":"isimmutable(v) -> Bool\n\nwarning: Warning\nConsider using !ismutable(v) instead, as isimmutable(v) will be replaced by !ismutable(v) in a future release. (Since Julia 1.5)\n\nReturn true iff value v is immutable. See Mutable Composite Types for a discussion of immutability. Note that this function works on values, so if you give it a type, it will tell you that a value of DataType is mutable.\n\nExamples\n\njulia> isimmutable(1)\ntrue\n\njulia> isimmutable([1,2])\nfalse\n\n\n\n\n\n","category":"function"},{"location":"base/base/#Base.isabstracttype","page":"基本功能","title":"Base.isabstracttype","text":"isabstracttype(T)\n\nDetermine whether type T was declared as an abstract type (i.e. using the abstract keyword).\n\nExamples\n\njulia> isabstracttype(AbstractArray)\ntrue\n\njulia> isabstracttype(Vector)\nfalse\n\n\n\n\n\n","category":"function"},{"location":"base/base/#Base.isprimitivetype","page":"基本功能","title":"Base.isprimitivetype","text":"isprimitivetype(T) -> Bool\n\nDetermine whether type T was declared as a primitive type (i.e. using the primitive keyword).\n\n\n\n\n\n","category":"function"},{"location":"base/base/#Base.issingletontype","page":"基本功能","title":"Base.issingletontype","text":"Base.issingletontype(T)\n\nDetermine whether type T has exactly one possible instance; for example, a struct type with no fields.\n\n\n\n\n\n","category":"function"},{"location":"base/base/#Base.isstructtype","page":"基本功能","title":"Base.isstructtype","text":"isstructtype(T) -> Bool\n\nDetermine whether type T was declared as a struct type (i.e. using the struct or mutable struct keyword).\n\n\n\n\n\n","category":"function"},{"location":"base/base/#Base.nameof-Tuple{DataType}","page":"基本功能","title":"Base.nameof","text":"nameof(t::DataType) -> Symbol\n\nGet the name of a (potentially UnionAll-wrapped) DataType (without its parent module) as a symbol.\n\nExamples\n\njulia> module Foo\n struct S{T}\n end\n end\nFoo\n\njulia> nameof(Foo.S{T} where T)\n:S\n\n\n\n\n\n","category":"method"},{"location":"base/base/#Base.fieldnames","page":"基本功能","title":"Base.fieldnames","text":"fieldnames(x::DataType)\n\nGet a tuple with the names of the fields of a DataType.\n\nSee also propertynames, hasfield.\n\nExamples\n\njulia> fieldnames(Rational)\n(:num, :den)\n\njulia> fieldnames(typeof(1+im))\n(:re, :im)\n\n\n\n\n\n","category":"function"},{"location":"base/base/#Base.fieldname","page":"基本功能","title":"Base.fieldname","text":"fieldname(x::DataType, i::Integer)\n\nGet the name of field i of a DataType.\n\nExamples\n\njulia> fieldname(Rational, 1)\n:num\n\njulia> fieldname(Rational, 2)\n:den\n\n\n\n\n\n","category":"function"},{"location":"base/base/#Base.hasfield","page":"基本功能","title":"Base.hasfield","text":"hasfield(T::Type, name::Symbol)\n\nReturn a boolean indicating whether T has name as one of its own fields.\n\nSee also fieldnames, fieldcount, hasproperty.\n\ncompat: Julia 1.2\nThis function requires at least Julia 1.2.\n\nExamples\n\njulia> struct Foo\n bar::Int\n end\n\njulia> hasfield(Foo, :bar)\ntrue\n\njulia> hasfield(Foo, :x)\nfalse\n\n\n\n\n\n","category":"function"},{"location":"base/base/#Memory-layout","page":"基本功能","title":"Memory layout","text":"","category":"section"},{"location":"base/base/","page":"基本功能","title":"基本功能","text":"Base.sizeof(::Type)\nBase.isconcretetype\nBase.isbits\nBase.isbitstype\nCore.fieldtype\nBase.fieldtypes\nBase.fieldcount\nBase.fieldoffset\nBase.datatype_alignment\nBase.datatype_haspadding\nBase.datatype_pointerfree","category":"page"},{"location":"base/base/#Base.sizeof-Tuple{Type}","page":"基本功能","title":"Base.sizeof","text":"sizeof(T::DataType)\nsizeof(obj)\n\nSize, in bytes, of the canonical binary representation of the given DataType T, if any. Or the size, in bytes, of object obj if it is not a DataType.\n\nSee also summarysize.\n\nExamples\n\njulia> sizeof(Float32)\n4\n\njulia> sizeof(ComplexF64)\n16\n\njulia> sizeof(1.0)\n8\n\njulia> sizeof(collect(1.0:10.0))\n80\n\nIf DataType T does not have a specific size, an error is thrown.\n\njulia> sizeof(AbstractArray)\nERROR: Abstract type AbstractArray does not have a definite size.\nStacktrace:\n[...]\n\n\n\n\n\n","category":"method"},{"location":"base/base/#Base.isconcretetype","page":"基本功能","title":"Base.isconcretetype","text":"isconcretetype(T)\n\nDetermine whether type T is a concrete type, meaning it could have direct instances (values x such that typeof(x) === T).\n\nSee also: isbits, isabstracttype, issingletontype.\n\nExamples\n\njulia> isconcretetype(Complex)\nfalse\n\njulia> isconcretetype(Complex{Float32})\ntrue\n\njulia> isconcretetype(Vector{Complex})\ntrue\n\njulia> isconcretetype(Vector{Complex{Float32}})\ntrue\n\njulia> isconcretetype(Union{})\nfalse\n\njulia> isconcretetype(Union{Int,String})\nfalse\n\n\n\n\n\n","category":"function"},{"location":"base/base/#Base.isbits","page":"基本功能","title":"Base.isbits","text":"isbits(x)\n\nReturn true if x is an instance of an isbitstype type.\n\n\n\n\n\n","category":"function"},{"location":"base/base/#Base.isbitstype","page":"基本功能","title":"Base.isbitstype","text":"isbitstype(T)\n\nReturn true if type T is a \"plain data\" type, meaning it is immutable and contains no references to other values, only primitive types and other isbitstype types. Typical examples are numeric types such as UInt8, Float64, and Complex{Float64}. This category of types is significant since they are valid as type parameters, may not track isdefined / isassigned status, and have a defined layout that is compatible with C.\n\nSee also isbits, isprimitivetype, ismutable.\n\nExamples\n\njulia> isbitstype(Complex{Float64})\ntrue\n\njulia> isbitstype(Complex)\nfalse\n\n\n\n\n\n","category":"function"},{"location":"base/base/#Core.fieldtype","page":"基本功能","title":"Core.fieldtype","text":"fieldtype(T, name::Symbol | index::Int)\n\nDetermine the declared type of a field (specified by name or index) in a composite DataType T.\n\nExamples\n\njulia> struct Foo\n x::Int64\n y::String\n end\n\njulia> fieldtype(Foo, :x)\nInt64\n\njulia> fieldtype(Foo, 2)\nString\n\n\n\n\n\n","category":"function"},{"location":"base/base/#Base.fieldtypes","page":"基本功能","title":"Base.fieldtypes","text":"fieldtypes(T::Type)\n\nThe declared types of all fields in a composite DataType T as a tuple.\n\ncompat: Julia 1.1\nThis function requires at least Julia 1.1.\n\nExamples\n\njulia> struct Foo\n x::Int64\n y::String\n end\n\njulia> fieldtypes(Foo)\n(Int64, String)\n\n\n\n\n\n","category":"function"},{"location":"base/base/#Base.fieldcount","page":"基本功能","title":"Base.fieldcount","text":"fieldcount(t::Type)\n\nGet the number of fields that an instance of the given type would have. An error is thrown if the type is too abstract to determine this.\n\n\n\n\n\n","category":"function"},{"location":"base/base/#Base.fieldoffset","page":"基本功能","title":"Base.fieldoffset","text":"fieldoffset(type, i)\n\nThe byte offset of field i of a type relative to the data start. For example, we could use it in the following manner to summarize information about a struct:\n\njulia> structinfo(T) = [(fieldoffset(T,i), fieldname(T,i), fieldtype(T,i)) for i = 1:fieldcount(T)];\n\njulia> structinfo(Base.Filesystem.StatStruct)\n13-element Vector{Tuple{UInt64, Symbol, Type}}:\n (0x0000000000000000, :desc, Union{RawFD, String})\n (0x0000000000000008, :device, UInt64)\n (0x0000000000000010, :inode, UInt64)\n (0x0000000000000018, :mode, UInt64)\n (0x0000000000000020, :nlink, Int64)\n (0x0000000000000028, :uid, UInt64)\n (0x0000000000000030, :gid, UInt64)\n (0x0000000000000038, :rdev, UInt64)\n (0x0000000000000040, :size, Int64)\n (0x0000000000000048, :blksize, Int64)\n (0x0000000000000050, :blocks, Int64)\n (0x0000000000000058, :mtime, Float64)\n (0x0000000000000060, :ctime, Float64)\n\n\n\n\n\n","category":"function"},{"location":"base/base/#Base.datatype_alignment","page":"基本功能","title":"Base.datatype_alignment","text":"Base.datatype_alignment(dt::DataType) -> Int\n\nMemory allocation minimum alignment for instances of this type. Can be called on any isconcretetype.\n\n\n\n\n\n","category":"function"},{"location":"base/base/#Base.datatype_haspadding","page":"基本功能","title":"Base.datatype_haspadding","text":"Base.datatype_haspadding(dt::DataType) -> Bool\n\nReturn whether the fields of instances of this type are packed in memory, with no intervening padding bytes. Can be called on any isconcretetype.\n\n\n\n\n\n","category":"function"},{"location":"base/base/#Base.datatype_pointerfree","page":"基本功能","title":"Base.datatype_pointerfree","text":"Base.datatype_pointerfree(dt::DataType) -> Bool\n\nReturn whether instances of this type can contain references to gc-managed memory. Can be called on any isconcretetype.\n\n\n\n\n\n","category":"function"},{"location":"base/base/#Special-values","page":"基本功能","title":"Special values","text":"","category":"section"},{"location":"base/base/","page":"基本功能","title":"基本功能","text":"Base.typemin\nBase.typemax\nBase.floatmin\nBase.floatmax\nBase.maxintfloat\nBase.eps(::Type{<:AbstractFloat})\nBase.eps(::AbstractFloat)\nBase.instances","category":"page"},{"location":"base/base/#Base.typemin","page":"基本功能","title":"Base.typemin","text":"typemin(T)\n\nThe lowest value representable by the given (real) numeric DataType T.\n\nExamples\n\njulia> typemin(Float16)\n-Inf16\n\njulia> typemin(Float32)\n-Inf32\n\n\n\n\n\n","category":"function"},{"location":"base/base/#Base.typemax","page":"基本功能","title":"Base.typemax","text":"typemax(T)\n\nThe highest value representable by the given (real) numeric DataType.\n\nSee also: floatmax, typemin, eps.\n\nExamples\n\njulia> typemax(Int8)\n127\n\njulia> typemax(UInt32)\n0xffffffff\n\njulia> typemax(Float64)\nInf\n\njulia> floatmax(Float32) # largest finite floating point number\n3.4028235f38\n\n\n\n\n\n","category":"function"},{"location":"base/base/#Base.floatmin","page":"基本功能","title":"Base.floatmin","text":"floatmin(T = Float64)\n\nReturn the smallest positive normal number representable by the floating-point type T.\n\nExamples\n\njulia> floatmin(Float16)\nFloat16(6.104e-5)\n\njulia> floatmin(Float32)\n1.1754944f-38\n\njulia> floatmin()\n2.2250738585072014e-308\n\n\n\n\n\n","category":"function"},{"location":"base/base/#Base.floatmax","page":"基本功能","title":"Base.floatmax","text":"floatmax(T = Float64)\n\nReturn the largest finite number representable by the floating-point type T.\n\nSee also: typemax, floatmin, eps.\n\nExamples\n\njulia> floatmax(Float16)\nFloat16(6.55e4)\n\njulia> floatmax(Float32)\n3.4028235f38\n\njulia> floatmax()\n1.7976931348623157e308\n\njulia> typemax(Float64)\nInf\n\n\n\n\n\n","category":"function"},{"location":"base/base/#Base.maxintfloat","page":"基本功能","title":"Base.maxintfloat","text":"maxintfloat(T=Float64)\n\nThe largest consecutive integer-valued floating-point number that is exactly represented in the given floating-point type T (which defaults to Float64).\n\nThat is, maxintfloat returns the smallest positive integer-valued floating-point number n such that n+1 is not exactly representable in the type T.\n\nWhen an Integer-type value is needed, use Integer(maxintfloat(T)).\n\n\n\n\n\nmaxintfloat(T, S)\n\nThe largest consecutive integer representable in the given floating-point type T that also does not exceed the maximum integer representable by the integer type S. Equivalently, it is the minimum of maxintfloat(T) and typemax(S).\n\n\n\n\n\n","category":"function"},{"location":"base/base/#Base.eps-Tuple{Type{<:AbstractFloat}}","page":"基本功能","title":"Base.eps","text":"eps(::Type{T}) where T<:AbstractFloat\neps()\n\nReturn the machine epsilon of the floating point type T (T = Float64 by default). This is defined as the gap between 1 and the next largest value representable by typeof(one(T)), and is equivalent to eps(one(T)). (Since eps(T) is a bound on the relative error of T, it is a \"dimensionless\" quantity like one.)\n\nExamples\n\njulia> eps()\n2.220446049250313e-16\n\njulia> eps(Float32)\n1.1920929f-7\n\njulia> 1.0 + eps()\n1.0000000000000002\n\njulia> 1.0 + eps()/2\n1.0\n\n\n\n\n\n","category":"method"},{"location":"base/base/#Base.eps-Tuple{AbstractFloat}","page":"基本功能","title":"Base.eps","text":"eps(x::AbstractFloat)\n\nReturn the unit in last place (ulp) of x. This is the distance between consecutive representable floating point values at x. In most cases, if the distance on either side of x is different, then the larger of the two is taken, that is\n\neps(x) == max(x-prevfloat(x), nextfloat(x)-x)\n\nThe exceptions to this rule are the smallest and largest finite values (e.g. nextfloat(-Inf) and prevfloat(Inf) for Float64), which round to the smaller of the values.\n\nThe rationale for this behavior is that eps bounds the floating point rounding error. Under the default RoundNearest rounding mode, if y is a real number and x is the nearest floating point number to y, then\n\ny-x leq operatornameeps(x)2\n\nSee also: nextfloat, issubnormal, floatmax.\n\nExamples\n\njulia> eps(1.0)\n2.220446049250313e-16\n\njulia> eps(prevfloat(2.0))\n2.220446049250313e-16\n\njulia> eps(2.0)\n4.440892098500626e-16\n\njulia> x = prevfloat(Inf) # largest finite Float64\n1.7976931348623157e308\n\njulia> x + eps(x)/2 # rounds up\nInf\n\njulia> x + prevfloat(eps(x)/2) # rounds down\n1.7976931348623157e308\n\n\n\n\n\n","category":"method"},{"location":"base/base/#Base.instances","page":"基本功能","title":"Base.instances","text":"instances(T::Type)\n\nReturn a collection of all instances of the given type, if applicable. Mostly used for enumerated types (see @enum).\n\nExample\n\njulia> @enum Color red blue green\n\njulia> instances(Color)\n(red, blue, green)\n\n\n\n\n\n","category":"function"},{"location":"base/base/#Special-Types","page":"基本功能","title":"Special Types","text":"","category":"section"},{"location":"base/base/","page":"基本功能","title":"基本功能","text":"Core.Any\nCore.Union\nUnion{}\nCore.UnionAll\nCore.Tuple\nCore.NTuple\nCore.NamedTuple\nBase.@NamedTuple\nBase.Val\nCore.Vararg\nCore.Nothing\nBase.isnothing\nBase.notnothing\nBase.Some\nBase.something\nBase.@something\nBase.Enums.Enum\nBase.Enums.@enum\nCore.Expr\nCore.Symbol\nCore.Symbol(x...)\nCore.Module","category":"page"},{"location":"base/base/#Core.Any","page":"基本功能","title":"Core.Any","text":"Any::DataType\n\nAny is the union of all types. It has the defining property isa(x, Any) == true for any x. Any therefore describes the entire universe of possible values. For example Integer is a subset of Any that includes Int, Int8, and other integer types.\n\n\n\n\n\n","category":"type"},{"location":"base/base/#Core.Union","page":"基本功能","title":"Core.Union","text":"Union{Types...}\n\nA type union is an abstract type which includes all instances of any of its argument types. The empty union Union{} is the bottom type of Julia.\n\nExamples\n\njulia> IntOrString = Union{Int,AbstractString}\nUnion{Int64, AbstractString}\n\njulia> 1 :: IntOrString\n1\n\njulia> \"Hello!\" :: IntOrString\n\"Hello!\"\n\njulia> 1.0 :: IntOrString\nERROR: TypeError: in typeassert, expected Union{Int64, AbstractString}, got a value of type Float64\n\n\n\n\n\n","category":"type"},{"location":"base/base/#Union{}","page":"基本功能","title":"Union{}","text":"Union{}\n\nUnion{}, the empty Union of types, is the type that has no values. That is, it has the defining property isa(x, Union{}) == false for any x. Base.Bottom is defined as its alias and the type of Union{} is Core.TypeofBottom.\n\nExamples\n\njulia> isa(nothing, Union{})\nfalse\n\n\n\n\n\n","category":"keyword"},{"location":"base/base/#Core.UnionAll","page":"基本功能","title":"Core.UnionAll","text":"UnionAll\n\nA union of types over all values of a type parameter. UnionAll is used to describe parametric types where the values of some parameters are not known.\n\nExamples\n\njulia> typeof(Vector)\nUnionAll\n\njulia> typeof(Vector{Int})\nDataType\n\n\n\n\n\n","category":"type"},{"location":"base/base/#Core.Tuple","page":"基本功能","title":"Core.Tuple","text":"Tuple{Types...}\n\nTuples are an abstraction of the arguments of a function – without the function itself. The salient aspects of a function's arguments are their order and their types. Therefore a tuple type is similar to a parameterized immutable type where each parameter is the type of one field. Tuple types may have any number of parameters.\n\nTuple types are covariant in their parameters: Tuple{Int} is a subtype of Tuple{Any}. Therefore Tuple{Any} is considered an abstract type, and tuple types are only concrete if their parameters are. Tuples do not have field names; fields are only accessed by index.\n\nSee the manual section on Tuple Types.\n\nSee also Vararg, NTuple, tuple, NamedTuple.\n\n\n\n\n\n","category":"type"},{"location":"base/base/#Core.NTuple","page":"基本功能","title":"Core.NTuple","text":"NTuple{N, T}\n\nA compact way of representing the type for a tuple of length N where all elements are of type T.\n\nExamples\n\njulia> isa((1, 2, 3, 4, 5, 6), NTuple{6, Int})\ntrue\n\n\n\n\n\n","category":"type"},{"location":"base/base/#Core.NamedTuple","page":"基本功能","title":"Core.NamedTuple","text":"NamedTuple\n\nNamedTuples are, as their name suggests, named Tuples. That is, they're a tuple-like collection of values, where each entry has a unique name, represented as a Symbol. Like Tuples, NamedTuples are immutable; neither the names nor the values can be modified in place after construction.\n\nAccessing the value associated with a name in a named tuple can be done using field access syntax, e.g. x.a, or using getindex, e.g. x[:a] or x[(:a, :b)]. A tuple of the names can be obtained using keys, and a tuple of the values can be obtained using values.\n\nnote: Note\nIteration over NamedTuples produces the values without the names. (See example below.) To iterate over the name-value pairs, use the pairs function.\n\nThe @NamedTuple macro can be used for conveniently declaring NamedTuple types.\n\nExamples\n\njulia> x = (a=1, b=2)\n(a = 1, b = 2)\n\njulia> x.a\n1\n\njulia> x[:a]\n1\n\njulia> x[(:a,)]\n(a = 1,)\n\njulia> keys(x)\n(:a, :b)\n\njulia> values(x)\n(1, 2)\n\njulia> collect(x)\n2-element Vector{Int64}:\n 1\n 2\n\njulia> collect(pairs(x))\n2-element Vector{Pair{Symbol, Int64}}:\n :a => 1\n :b => 2\n\nIn a similar fashion as to how one can define keyword arguments programmatically, a named tuple can be created by giving a pair name::Symbol => value or splatting an iterator yielding such pairs after a semicolon inside a tuple literal:\n\njulia> (; :a => 1)\n(a = 1,)\n\njulia> keys = (:a, :b, :c); values = (1, 2, 3);\n\njulia> (; zip(keys, values)...)\n(a = 1, b = 2, c = 3)\n\nAs in keyword arguments, identifiers and dot expressions imply names:\n\njulia> x = 0\n0\n\njulia> t = (; x)\n(x = 0,)\n\njulia> (; t.x)\n(x = 0,)\n\ncompat: Julia 1.5\nImplicit names from identifiers and dot expressions are available as of Julia 1.5.\n\ncompat: Julia 1.7\nUse of getindex methods with multiple Symbols is available as of Julia 1.7.\n\n\n\n\n\n","category":"type"},{"location":"base/base/#Base.@NamedTuple","page":"基本功能","title":"Base.@NamedTuple","text":"@NamedTuple{key1::Type1, key2::Type2, ...}\n@NamedTuple begin key1::Type1; key2::Type2; ...; end\n\nThis macro gives a more convenient syntax for declaring NamedTuple types. It returns a NamedTuple type with the given keys and types, equivalent to NamedTuple{(:key1, :key2, ...), Tuple{Type1,Type2,...}}. If the ::Type declaration is omitted, it is taken to be Any. The begin ... end form allows the declarations to be split across multiple lines (similar to a struct declaration), but is otherwise equivalent.\n\nFor example, the tuple (a=3.1, b=\"hello\") has a type NamedTuple{(:a, :b),Tuple{Float64,String}}, which can also be declared via @NamedTuple as:\n\njulia> @NamedTuple{a::Float64, b::String}\nNamedTuple{(:a, :b), Tuple{Float64, String}}\n\njulia> @NamedTuple begin\n a::Float64\n b::String\n end\nNamedTuple{(:a, :b), Tuple{Float64, String}}\n\ncompat: Julia 1.5\nThis macro is available as of Julia 1.5.\n\n\n\n\n\n","category":"macro"},{"location":"base/base/#Base.Val","page":"基本功能","title":"Base.Val","text":"Val(c)\n\nReturn Val{c}(), which contains no run-time data. Types like this can be used to pass the information between functions through the value c, which must be an isbits value or a Symbol. The intent of this construct is to be able to dispatch on constants directly (at compile time) without having to test the value of the constant at run time.\n\nExamples\n\njulia> f(::Val{true}) = \"Good\"\nf (generic function with 1 method)\n\njulia> f(::Val{false}) = \"Bad\"\nf (generic function with 2 methods)\n\njulia> f(Val(true))\n\"Good\"\n\n\n\n\n\n","category":"type"},{"location":"base/base/#Core.Vararg","page":"基本功能","title":"Core.Vararg","text":"Vararg{T,N}\n\nThe last parameter of a tuple type Tuple can be the special value Vararg, which denotes any number of trailing elements. Vararg{T,N} corresponds to exactly N elements of type T. Finally Vararg{T} corresponds to zero or more elements of type T. Vararg tuple types are used to represent the arguments accepted by varargs methods (see the section on Varargs Functions in the manual.)\n\nSee also NTuple.\n\nExamples\n\njulia> mytupletype = Tuple{AbstractString, Vararg{Int}}\nTuple{AbstractString, Vararg{Int64}}\n\njulia> isa((\"1\",), mytupletype)\ntrue\n\njulia> isa((\"1\",1), mytupletype)\ntrue\n\njulia> isa((\"1\",1,2), mytupletype)\ntrue\n\njulia> isa((\"1\",1,2,3.0), mytupletype)\nfalse\n\n\n\n\n\n","category":"constant"},{"location":"base/base/#Core.Nothing","page":"基本功能","title":"Core.Nothing","text":"Nothing\n\nA type with no fields that is the type of nothing.\n\nSee also: isnothing, Some, Missing.\n\n\n\n\n\n","category":"type"},{"location":"base/base/#Base.isnothing","page":"基本功能","title":"Base.isnothing","text":"isnothing(x)\n\nReturn true if x === nothing, and return false if not.\n\ncompat: Julia 1.1\nThis function requires at least Julia 1.1.\n\nSee also something, notnothing, ismissing.\n\n\n\n\n\n","category":"function"},{"location":"base/base/#Base.notnothing","page":"基本功能","title":"Base.notnothing","text":"notnothing(x)\n\nThrow an error if x === nothing, and return x if not.\n\n\n\n\n\n","category":"function"},{"location":"base/base/#Base.Some","page":"基本功能","title":"Base.Some","text":"Some{T}\n\nA wrapper type used in Union{Some{T}, Nothing} to distinguish between the absence of a value (nothing) and the presence of a nothing value (i.e. Some(nothing)).\n\nUse something to access the value wrapped by a Some object.\n\n\n\n\n\n","category":"type"},{"location":"base/base/#Base.something","page":"基本功能","title":"Base.something","text":"something(x...)\n\nReturn the first value in the arguments which is not equal to nothing, if any. Otherwise throw an error. Arguments of type Some are unwrapped.\n\nSee also coalesce, skipmissing, @something.\n\nExamples\n\njulia> something(nothing, 1)\n1\n\njulia> something(Some(1), nothing)\n1\n\njulia> something(missing, nothing)\nmissing\n\njulia> something(nothing, nothing)\nERROR: ArgumentError: No value arguments present\n\n\n\n\n\n","category":"function"},{"location":"base/base/#Base.@something","page":"基本功能","title":"Base.@something","text":"@something(x...)\n\nShort-circuiting version of something.\n\nExamples\n\njulia> f(x) = (println(\"f($x)\"); nothing);\n\njulia> a = 1;\n\njulia> a = @something a f(2) f(3) error(\"Unable to find default for `a`\")\n1\n\njulia> b = nothing;\n\njulia> b = @something b f(2) f(3) error(\"Unable to find default for `b`\")\nf(2)\nf(3)\nERROR: Unable to find default for `b`\n[...]\n\njulia> b = @something b f(2) f(3) Some(nothing)\nf(2)\nf(3)\n\njulia> b === nothing\ntrue\n\ncompat: Julia 1.7\nThis macro is available as of Julia 1.7.\n\n\n\n\n\n","category":"macro"},{"location":"base/base/#Base.Enums.Enum","page":"基本功能","title":"Base.Enums.Enum","text":"Enum{T<:Integer}\n\nThe abstract supertype of all enumerated types defined with @enum.\n\n\n\n\n\n","category":"type"},{"location":"base/base/#Base.Enums.@enum","page":"基本功能","title":"Base.Enums.@enum","text":"@enum EnumName[::BaseType] value1[=x] value2[=y]\n\nCreate an Enum{BaseType} subtype with name EnumName and enum member values of value1 and value2 with optional assigned values of x and y, respectively. EnumName can be used just like other types and enum member values as regular values, such as\n\nExamples\n\njulia> @enum Fruit apple=1 orange=2 kiwi=3\n\njulia> f(x::Fruit) = \"I'm a Fruit with value: $(Int(x))\"\nf (generic function with 1 method)\n\njulia> f(apple)\n\"I'm a Fruit with value: 1\"\n\njulia> Fruit(1)\napple::Fruit = 1\n\nValues can also be specified inside a begin block, e.g.\n\n@enum EnumName begin\n value1\n value2\nend\n\nBaseType, which defaults to Int32, must be a primitive subtype of Integer. Member values can be converted between the enum type and BaseType. read and write perform these conversions automatically. In case the enum is created with a non-default BaseType, Integer(value1) will return the integer value1 with the type BaseType.\n\nTo list all the instances of an enum use instances, e.g.\n\njulia> instances(Fruit)\n(apple, orange, kiwi)\n\n\n\n\n\n","category":"macro"},{"location":"base/base/#Core.Expr","page":"基本功能","title":"Core.Expr","text":"Expr(head::Symbol, args...)\n\nA type representing compound expressions in parsed julia code (ASTs). Each expression consists of a head Symbol identifying which kind of expression it is (e.g. a call, for loop, conditional statement, etc.), and subexpressions (e.g. the arguments of a call). The subexpressions are stored in a Vector{Any} field called args.\n\nSee the manual chapter on Metaprogramming and the developer documentation Julia ASTs.\n\nExamples\n\njulia> Expr(:call, :+, 1, 2)\n:(1 + 2)\n\njulia> dump(:(a ? b : c))\nExpr\n head: Symbol if\n args: Array{Any}((3,))\n 1: Symbol a\n 2: Symbol b\n 3: Symbol c\n\n\n\n\n\n","category":"type"},{"location":"base/base/#Core.Symbol","page":"基本功能","title":"Core.Symbol","text":"Symbol\n\nThe type of object used to represent identifiers in parsed julia code (ASTs). Also often used as a name or label to identify an entity (e.g. as a dictionary key). Symbols can be entered using the : quote operator:\n\njulia> :name\n:name\n\njulia> typeof(:name)\nSymbol\n\njulia> x = 42\n42\n\njulia> eval(:x)\n42\n\nSymbols can also be constructed from strings or other values by calling the constructor Symbol(x...).\n\nSymbols are immutable and should be compared using ===. The implementation re-uses the same object for all Symbols with the same name, so comparison tends to be efficient (it can just compare pointers).\n\nUnlike strings, Symbols are \"atomic\" or \"scalar\" entities that do not support iteration over characters.\n\n\n\n\n\n","category":"type"},{"location":"base/base/#Core.Symbol-Tuple","page":"基本功能","title":"Core.Symbol","text":"Symbol(x...) -> Symbol\n\nCreate a Symbol by concatenating the string representations of the arguments together.\n\nExamples\n\njulia> Symbol(\"my\", \"name\")\n:myname\n\njulia> Symbol(\"day\", 4)\n:day4\n\n\n\n\n\n","category":"method"},{"location":"base/base/#Core.Module","page":"基本功能","title":"Core.Module","text":"Module\n\nA Module is a separate global variable workspace. See module and the manual section about modules for details.\n\nModule(name::Symbol=:anonymous, std_imports=true, default_names=true)\n\nReturn a module with the specified name. A baremodule corresponds to Module(:ModuleName, false)\n\nAn empty module containing no names at all can be created with Module(:ModuleName, false, false). This module will not import Base or Core and does not contain a reference to itself.\n\n\n\n\n\n","category":"type"},{"location":"base/base/#Generic-Functions","page":"基本功能","title":"Generic Functions","text":"","category":"section"},{"location":"base/base/","page":"基本功能","title":"基本功能","text":"Core.Function\nBase.hasmethod\nCore.applicable\nBase.isambiguous\nCore.invoke\nBase.@invoke\nBase.invokelatest\nBase.@invokelatest\nnew\nBase.:(|>)\nBase.:(∘)\nBase.ComposedFunction\nBase.splat\nBase.Fix1\nBase.Fix2","category":"page"},{"location":"base/base/#Core.Function","page":"基本功能","title":"Core.Function","text":"Function\n\nAbstract type of all functions.\n\nExamples\n\njulia> isa(+, Function)\ntrue\n\njulia> typeof(sin)\ntypeof(sin) (singleton type of function sin, subtype of Function)\n\njulia> ans <: Function\ntrue\n\n\n\n\n\n","category":"type"},{"location":"base/base/#Base.hasmethod","page":"基本功能","title":"Base.hasmethod","text":"hasmethod(f, t::Type{<:Tuple}[, kwnames]; world=get_world_counter()) -> Bool\n\nDetermine whether the given generic function has a method matching the given Tuple of argument types with the upper bound of world age given by world.\n\nIf a tuple of keyword argument names kwnames is provided, this also checks whether the method of f matching t has the given keyword argument names. If the matching method accepts a variable number of keyword arguments, e.g. with kwargs..., any names given in kwnames are considered valid. Otherwise the provided names must be a subset of the method's keyword arguments.\n\nSee also applicable.\n\ncompat: Julia 1.2\nProviding keyword argument names requires Julia 1.2 or later.\n\nExamples\n\njulia> hasmethod(length, Tuple{Array})\ntrue\n\njulia> f(; oranges=0) = oranges;\n\njulia> hasmethod(f, Tuple{}, (:oranges,))\ntrue\n\njulia> hasmethod(f, Tuple{}, (:apples, :bananas))\nfalse\n\njulia> g(; xs...) = 4;\n\njulia> hasmethod(g, Tuple{}, (:a, :b, :c, :d)) # g accepts arbitrary kwargs\ntrue\n\n\n\n\n\n","category":"function"},{"location":"base/base/#Core.applicable","page":"基本功能","title":"Core.applicable","text":"applicable(f, args...) -> Bool\n\nDetermine whether the given generic function has a method applicable to the given arguments.\n\nSee also hasmethod.\n\nExamples\n\njulia> function f(x, y)\n x + y\n end;\n\njulia> applicable(f, 1)\nfalse\n\njulia> applicable(f, 1, 2)\ntrue\n\n\n\n\n\n","category":"function"},{"location":"base/base/#Base.isambiguous","page":"基本功能","title":"Base.isambiguous","text":"Base.isambiguous(m1, m2; ambiguous_bottom=false) -> Bool\n\nDetermine whether two methods m1 and m2 may be ambiguous for some call signature. This test is performed in the context of other methods of the same function; in isolation, m1 and m2 might be ambiguous, but if a third method resolving the ambiguity has been defined, this returns false. Alternatively, in isolation m1 and m2 might be ordered, but if a third method cannot be sorted with them, they may cause an ambiguity together.\n\nFor parametric types, the ambiguous_bottom keyword argument controls whether Union{} counts as an ambiguous intersection of type parameters – when true, it is considered ambiguous, when false it is not.\n\nExamples\n\njulia> foo(x::Complex{<:Integer}) = 1\nfoo (generic function with 1 method)\n\njulia> foo(x::Complex{<:Rational}) = 2\nfoo (generic function with 2 methods)\n\njulia> m1, m2 = collect(methods(foo));\n\njulia> typeintersect(m1.sig, m2.sig)\nTuple{typeof(foo), Complex{Union{}}}\n\njulia> Base.isambiguous(m1, m2, ambiguous_bottom=true)\ntrue\n\njulia> Base.isambiguous(m1, m2, ambiguous_bottom=false)\nfalse\n\n\n\n\n\n","category":"function"},{"location":"base/base/#Core.invoke","page":"基本功能","title":"Core.invoke","text":"invoke(f, argtypes::Type, args...; kwargs...)\n\nInvoke a method for the given generic function f matching the specified types argtypes on the specified arguments args and passing the keyword arguments kwargs. The arguments args must conform with the specified types in argtypes, i.e. conversion is not automatically performed. This method allows invoking a method other than the most specific matching method, which is useful when the behavior of a more general definition is explicitly needed (often as part of the implementation of a more specific method of the same function).\n\nBe careful when using invoke for functions that you don't write. What definition is used for given argtypes is an implementation detail unless the function is explicitly states that calling with certain argtypes is a part of public API. For example, the change between f1 and f2 in the example below is usually considered compatible because the change is invisible by the caller with a normal (non-invoke) call. However, the change is visible if you use invoke.\n\nExamples\n\njulia> f(x::Real) = x^2;\n\njulia> f(x::Integer) = 1 + invoke(f, Tuple{Real}, x);\n\njulia> f(2)\n5\n\njulia> f1(::Integer) = Integer\n f1(::Real) = Real;\n\njulia> f2(x::Real) = _f2(x)\n _f2(::Integer) = Integer\n _f2(_) = Real;\n\njulia> f1(1)\nInteger\n\njulia> f2(1)\nInteger\n\njulia> invoke(f1, Tuple{Real}, 1)\nReal\n\njulia> invoke(f2, Tuple{Real}, 1)\nInteger\n\n\n\n\n\n","category":"function"},{"location":"base/base/#Base.@invoke","page":"基本功能","title":"Base.@invoke","text":"@invoke f(arg::T, ...; kwargs...)\n\nProvides a convenient way to call invoke; @invoke f(arg1::T1, arg2::T2; kwargs...) will be expanded into invoke(f, Tuple{T1,T2}, arg1, arg2; kwargs...). When an argument's type annotation is omitted, it's specified as Any argument, e.g. @invoke f(arg1::T, arg2) will be expanded into invoke(f, Tuple{T,Any}, arg1, arg2).\n\ncompat: Julia 1.7\nThis macro requires Julia 1.7 or later.\n\n\n\n\n\n","category":"macro"},{"location":"base/base/#Base.invokelatest","page":"基本功能","title":"Base.invokelatest","text":"invokelatest(f, args...; kwargs...)\n\nCalls f(args...; kwargs...), but guarantees that the most recent method of f will be executed. This is useful in specialized circumstances, e.g. long-running event loops or callback functions that may call obsolete versions of a function f. (The drawback is that invokelatest is somewhat slower than calling f directly, and the type of the result cannot be inferred by the compiler.)\n\n\n\n\n\n","category":"function"},{"location":"base/base/#Base.@invokelatest","page":"基本功能","title":"Base.@invokelatest","text":"@invokelatest f(args...; kwargs...)\n\nProvides a convenient way to call Base.invokelatest. @invokelatest f(args...; kwargs...) will simply be expanded into Base.invokelatest(f, args...; kwargs...).\n\ncompat: Julia 1.7\nThis macro requires Julia 1.7 or later.\n\n\n\n\n\n","category":"macro"},{"location":"base/base/#new","page":"基本功能","title":"new","text":"new, or new{A,B,...}\n\nSpecial function available to inner constructors which creates a new object of the type. The form new{A,B,...} explicitly specifies values of parameters for parametric types. See the manual section on Inner Constructor Methods for more information.\n\n\n\n\n\n","category":"keyword"},{"location":"base/base/#Base.:|>","page":"基本功能","title":"Base.:|>","text":"|>(x, f)\n\nApplies a function to the preceding argument. This allows for easy function chaining.\n\nExamples\n\njulia> [1:5;] |> (x->x.^2) |> sum |> inv\n0.01818181818181818\n\n\n\n\n\n","category":"function"},{"location":"base/base/#Base.:∘","page":"基本功能","title":"Base.:∘","text":"f ∘ g\n\nCompose functions: i.e. (f ∘ g)(args...; kwargs...) means f(g(args...; kwargs...)). The ∘ symbol can be entered in the Julia REPL (and most editors, appropriately configured) by typing \\circ.\n\nFunction composition also works in prefix form: ∘(f, g) is the same as f ∘ g. The prefix form supports composition of multiple functions: ∘(f, g, h) = f ∘ g ∘ h and splatting ∘(fs...) for composing an iterable collection of functions.\n\ncompat: Julia 1.4\nMultiple function composition requires at least Julia 1.4.\n\ncompat: Julia 1.5\nComposition of one function ∘(f) requires at least Julia 1.5.\n\ncompat: Julia 1.7\nUsing keyword arguments requires at least Julia 1.7.\n\nExamples\n\njulia> map(uppercase∘first, [\"apple\", \"banana\", \"carrot\"])\n3-element Vector{Char}:\n 'A': ASCII/Unicode U+0041 (category Lu: Letter, uppercase)\n 'B': ASCII/Unicode U+0042 (category Lu: Letter, uppercase)\n 'C': ASCII/Unicode U+0043 (category Lu: Letter, uppercase)\n\njulia> fs = [\n x -> 2x\n x -> x/2\n x -> x-1\n x -> x+1\n ];\n\njulia> ∘(fs...)(3)\n3.0\n\nSee also ComposedFunction, !f::Function.\n\n\n\n\n\n","category":"function"},{"location":"base/base/#Base.ComposedFunction","page":"基本功能","title":"Base.ComposedFunction","text":"ComposedFunction{Outer,Inner} <: Function\n\nRepresents the composition of two callable objects outer::Outer and inner::Inner. That is\n\nComposedFunction(outer, inner)(args...; kw...) === outer(inner(args...; kw...))\n\nThe preferred way to construct instance of ComposedFunction is to use the composition operator ∘:\n\njulia> sin ∘ cos === ComposedFunction(sin, cos)\ntrue\n\njulia> typeof(sin∘cos)\nComposedFunction{typeof(sin), typeof(cos)}\n\nThe composed pieces are stored in the fields of ComposedFunction and can be retrieved as follows:\n\njulia> composition = sin ∘ cos\nsin ∘ cos\n\njulia> composition.outer === sin\ntrue\n\njulia> composition.inner === cos\ntrue\n\ncompat: Julia 1.6\nComposedFunction requires at least Julia 1.6. In earlier versions ∘ returns an anonymous function instead.\n\nSee also ∘.\n\n\n\n\n\n","category":"type"},{"location":"base/base/#Base.splat","page":"基本功能","title":"Base.splat","text":"splat(f)\n\nDefined as\n\n splat(f) = args->f(args...)\n\ni.e. given a function returns a new function that takes one argument and splats its argument into the original function. This is useful as an adaptor to pass a multi-argument function in a context that expects a single argument, but passes a tuple as that single argument.\n\nExample usage:\n\njulia> map(Base.splat(+), zip(1:3,4:6))\n3-element Vector{Int64}:\n 5\n 7\n 9\n\n\n\n\n\n","category":"function"},{"location":"base/base/#Base.Fix1","page":"基本功能","title":"Base.Fix1","text":"Fix1(f, x)\n\nA type representing a partially-applied version of the two-argument function f, with the first argument fixed to the value \"x\". In other words, Fix1(f, x) behaves similarly to y->f(x, y).\n\nSee also Fix2.\n\n\n\n\n\n","category":"type"},{"location":"base/base/#Base.Fix2","page":"基本功能","title":"Base.Fix2","text":"Fix2(f, x)\n\nA type representing a partially-applied version of the two-argument function f, with the second argument fixed to the value \"x\". In other words, Fix2(f, x) behaves similarly to y->f(y, x).\n\n\n\n\n\n","category":"type"},{"location":"base/base/#Syntax","page":"基本功能","title":"Syntax","text":"","category":"section"},{"location":"base/base/","page":"基本功能","title":"基本功能","text":"Core.eval\nBase.MainInclude.eval\nBase.@eval\nBase.evalfile\nBase.esc\nBase.@inbounds\nBase.@boundscheck\nBase.@propagate_inbounds\nBase.@inline\nBase.@noinline\nBase.@nospecialize\nBase.@specialize\nBase.gensym\nBase.@gensym\nvar\"name\"\nBase.@goto\nBase.@label\nBase.@simd\nBase.@polly\nBase.@generated\nBase.@pure\nBase.@deprecate","category":"page"},{"location":"base/base/#Core.eval","page":"基本功能","title":"Core.eval","text":"Core.eval(m::Module, expr)\n\nEvaluate an expression in the given module and return the result.\n\n\n\n\n\n","category":"function"},{"location":"base/base/#Base.MainInclude.eval","page":"基本功能","title":"Base.MainInclude.eval","text":"eval(expr)\n\nEvaluate an expression in the global scope of the containing module. Every Module (except those defined with baremodule) has its own 1-argument definition of eval, which evaluates expressions in that module.\n\n\n\n\n\n","category":"function"},{"location":"base/base/#Base.@eval","page":"基本功能","title":"Base.@eval","text":"@eval [mod,] ex\n\nEvaluate an expression with values interpolated into it using eval. If two arguments are provided, the first is the module to evaluate in.\n\n\n\n\n\n","category":"macro"},{"location":"base/base/#Base.evalfile","page":"基本功能","title":"Base.evalfile","text":"evalfile(path::AbstractString, args::Vector{String}=String[])\n\nLoad the file using include, evaluate all expressions, and return the value of the last one.\n\n\n\n\n\n","category":"function"},{"location":"base/base/#Base.esc","page":"基本功能","title":"Base.esc","text":"esc(e)\n\nOnly valid in the context of an Expr returned from a macro. Prevents the macro hygiene pass from turning embedded variables into gensym variables. See the Macros section of the Metaprogramming chapter of the manual for more details and examples.\n\n\n\n\n\n","category":"function"},{"location":"base/base/#Base.@inbounds","page":"基本功能","title":"Base.@inbounds","text":"@inbounds(blk)\n\nEliminates array bounds checking within expressions.\n\nIn the example below the in-range check for referencing element i of array A is skipped to improve performance.\n\nfunction sum(A::AbstractArray)\n r = zero(eltype(A))\n for i in eachindex(A)\n @inbounds r += A[i]\n end\n return r\nend\n\nwarning: Warning\nUsing @inbounds may return incorrect results/crashes/corruption for out-of-bounds indices. The user is responsible for checking it manually. Only use @inbounds when it is certain from the information locally available that all accesses are in bounds.\n\n\n\n\n\n","category":"macro"},{"location":"base/base/#Base.@boundscheck","page":"基本功能","title":"Base.@boundscheck","text":"@boundscheck(blk)\n\nAnnotates the expression blk as a bounds checking block, allowing it to be elided by @inbounds.\n\nnote: Note\nThe function in which @boundscheck is written must be inlined into its caller in order for @inbounds to have effect.\n\nExamples\n\njulia> @inline function g(A, i)\n @boundscheck checkbounds(A, i)\n return \"accessing ($A)[$i]\"\n end;\n\njulia> f1() = return g(1:2, -1);\n\njulia> f2() = @inbounds return g(1:2, -1);\n\njulia> f1()\nERROR: BoundsError: attempt to access 2-element UnitRange{Int64} at index [-1]\nStacktrace:\n [1] throw_boundserror(::UnitRange{Int64}, ::Tuple{Int64}) at ./abstractarray.jl:455\n [2] checkbounds at ./abstractarray.jl:420 [inlined]\n [3] g at ./none:2 [inlined]\n [4] f1() at ./none:1\n [5] top-level scope\n\njulia> f2()\n\"accessing (1:2)[-1]\"\n\nwarning: Warning\nThe @boundscheck annotation allows you, as a library writer, to opt-in to allowing other code to remove your bounds checks with @inbounds. As noted there, the caller must verify—using information they can access—that their accesses are valid before using @inbounds. For indexing into your AbstractArray subclasses, for example, this involves checking the indices against its axes. Therefore, @boundscheck annotations should only be added to a getindex or setindex! implementation after you are certain its behavior is correct.\n\n\n\n\n\n","category":"macro"},{"location":"base/base/#Base.@propagate_inbounds","page":"基本功能","title":"Base.@propagate_inbounds","text":"@propagate_inbounds\n\nTells the compiler to inline a function while retaining the caller's inbounds context.\n\n\n\n\n\n","category":"macro"},{"location":"base/base/#Base.@inline","page":"基本功能","title":"Base.@inline","text":"@inline\n\nGive a hint to the compiler that this function is worth inlining.\n\nSmall functions typically do not need the @inline annotation, as the compiler does it automatically. By using @inline on bigger functions, an extra nudge can be given to the compiler to inline it.\n\n@inline can be applied immediately before the definition or in its function body.\n\n# annotate long-form definition\n@inline function longdef(x)\n ...\nend\n\n# annotate short-form definition\n@inline shortdef(x) = ...\n\n# annotate anonymous function that a `do` block creates\nf() do\n @inline\n ...\nend\n\ncompat: Julia 1.8\nThe usage within a function body requires at least Julia 1.8.\n\n\n\n@inline block\n\nGive a hint to the compiler that calls within block are worth inlining.\n\n# The compiler will try to inline `f`\n@inline f(...)\n\n# The compiler will try to inline `f`, `g` and `+`\n@inline f(...) + g(...)\n\nnote: Note\nA callsite annotation always has the precedence over the annotation applied to the definition of the called function:@noinline function explicit_noinline(args...)\n # body\nend\n\nlet\n @inline explicit_noinline(args...) # will be inlined\nend\n\nnote: Note\nWhen there are nested callsite annotations, the innermost annotation has the precedence:@noinline let a0, b0 = ...\n a = @inline f(a0) # the compiler will try to inline this call\n b = f(b0) # the compiler will NOT try to inline this call\n return a, b\nend\n\nwarning: Warning\nAlthough a callsite annotation will try to force inlining in regardless of the cost model, there are still chances it can't succeed in it. Especially, recursive calls can not be inlined even if they are annotated as @inlined.\n\ncompat: Julia 1.8\nThe callsite annotation requires at least Julia 1.8.\n\n\n\n\n\n","category":"macro"},{"location":"base/base/#Base.@noinline","page":"基本功能","title":"Base.@noinline","text":"@noinline\n\nGive a hint to the compiler that it should not inline a function.\n\nSmall functions are typically inlined automatically. By using @noinline on small functions, auto-inlining can be prevented.\n\n@noinline can be applied immediately before the definition or in its function body.\n\n# annotate long-form definition\n@noinline function longdef(x)\n ...\nend\n\n# annotate short-form definition\n@noinline shortdef(x) = ...\n\n# annotate anonymous function that a `do` block creates\nf() do\n @noinline\n ...\nend\n\ncompat: Julia 1.8\nThe usage within a function body requires at least Julia 1.8.\n\n\n\n@noinline block\n\nGive a hint to the compiler that it should not inline the calls within block.\n\n# The compiler will try to not inline `f`\n@noinline f(...)\n\n# The compiler will try to not inline `f`, `g` and `+`\n@noinline f(...) + g(...)\n\nnote: Note\nA callsite annotation always has the precedence over the annotation applied to the definition of the called function:@inline function explicit_inline(args...)\n # body\nend\n\nlet\n @noinline explicit_inline(args...) # will not be inlined\nend\n\nnote: Note\nWhen there are nested callsite annotations, the innermost annotation has the precedence:@inline let a0, b0 = ...\n a = @noinline f(a0) # the compiler will NOT try to inline this call\n b = f(b0) # the compiler will try to inline this call\n return a, b\nend\n\ncompat: Julia 1.8\nThe callsite annotation requires at least Julia 1.8.\n\n\n\nnote: Note\nIf the function is trivial (for example returning a constant) it might get inlined anyway.\n\n\n\n\n\n","category":"macro"},{"location":"base/base/#Base.@nospecialize","page":"基本功能","title":"Base.@nospecialize","text":"@nospecialize\n\nApplied to a function argument name, hints to the compiler that the method should not be specialized for different types of that argument, but instead to use precisely the declared type for each argument. This is only a hint for avoiding excess code generation. Can be applied to an argument within a formal argument list, or in the function body. When applied to an argument, the macro must wrap the entire argument expression. When used in a function body, the macro must occur in statement position and before any code.\n\nWhen used without arguments, it applies to all arguments of the parent scope. In local scope, this means all arguments of the containing function. In global (top-level) scope, this means all methods subsequently defined in the current module.\n\nSpecialization can reset back to the default by using @specialize.\n\nfunction example_function(@nospecialize x)\n ...\nend\n\nfunction example_function(x, @nospecialize(y = 1))\n ...\nend\n\nfunction example_function(x, y, z)\n @nospecialize x y\n ...\nend\n\n@nospecialize\nf(y) = [x for x in y]\n@specialize\n\n\n\n\n\n","category":"macro"},{"location":"base/base/#Base.@specialize","page":"基本功能","title":"Base.@specialize","text":"@specialize\n\nReset the specialization hint for an argument back to the default. For details, see @nospecialize.\n\n\n\n\n\n","category":"macro"},{"location":"base/base/#Base.gensym","page":"基本功能","title":"Base.gensym","text":"gensym([tag])\n\nGenerates a symbol which will not conflict with other variable names.\n\n\n\n\n\n","category":"function"},{"location":"base/base/#Base.@gensym","page":"基本功能","title":"Base.@gensym","text":"@gensym\n\nGenerates a gensym symbol for a variable. For example, @gensym x y is transformed into x = gensym(\"x\"); y = gensym(\"y\").\n\n\n\n\n\n","category":"macro"},{"location":"base/base/#var\"name\"","page":"基本功能","title":"var\"name\"","text":"var\n\nThe syntax var\"#example#\" refers to a variable named Symbol(\"#example#\"), even though #example# is not a valid Julia identifier name.\n\nThis can be useful for interoperability with programming languages which have different rules for the construction of valid identifiers. For example, to refer to the R variable draw.segments, you can use var\"draw.segments\" in your Julia code.\n\nIt is also used to show julia source code which has gone through macro hygiene or otherwise contains variable names which can't be parsed normally.\n\nNote that this syntax requires parser support so it is expanded directly by the parser rather than being implemented as a normal string macro @var_str.\n\ncompat: Julia 1.3\nThis syntax requires at least Julia 1.3.\n\n\n\n\n\n","category":"keyword"},{"location":"base/base/#Base.@goto","page":"基本功能","title":"Base.@goto","text":"@goto name\n\n@goto name unconditionally jumps to the statement at the location @label name.\n\n@label and @goto cannot create jumps to different top-level statements. Attempts cause an error. To still use @goto, enclose the @label and @goto in a block.\n\n\n\n\n\n","category":"macro"},{"location":"base/base/#Base.@label","page":"基本功能","title":"Base.@label","text":"@label name\n\nLabels a statement with the symbolic label name. The label marks the end-point of an unconditional jump with @goto name.\n\n\n\n\n\n","category":"macro"},{"location":"base/base/#Base.SimdLoop.@simd","page":"基本功能","title":"Base.SimdLoop.@simd","text":"@simd\n\nAnnotate a for loop to allow the compiler to take extra liberties to allow loop re-ordering\n\nwarning: Warning\nThis feature is experimental and could change or disappear in future versions of Julia. Incorrect use of the @simd macro may cause unexpected results.\n\nThe object iterated over in a @simd for loop should be a one-dimensional range. By using @simd, you are asserting several properties of the loop:\n\nIt is safe to execute iterations in arbitrary or overlapping order, with special consideration for reduction variables.\nFloating-point operations on reduction variables can be reordered, possibly causing different results than without @simd.\n\nIn many cases, Julia is able to automatically vectorize inner for loops without the use of @simd. Using @simd gives the compiler a little extra leeway to make it possible in more situations. In either case, your inner loop should have the following properties to allow vectorization:\n\nThe loop must be an innermost loop\nThe loop body must be straight-line code. Therefore, @inbounds is currently needed for all array accesses. The compiler can sometimes turn short &&, ||, and ?: expressions into straight-line code if it is safe to evaluate all operands unconditionally. Consider using the ifelse function instead of ?: in the loop if it is safe to do so.\nAccesses must have a stride pattern and cannot be \"gathers\" (random-index reads) or \"scatters\" (random-index writes).\nThe stride should be unit stride.\n\nnote: Note\nThe @simd does not assert by default that the loop is completely free of loop-carried memory dependencies, which is an assumption that can easily be violated in generic code. If you are writing non-generic code, you can use @simd ivdep for ... end to also assert that:\n\nThere exists no loop-carried memory dependencies\nNo iteration ever waits on a previous iteration to make forward progress.\n\n\n\n\n\n","category":"macro"},{"location":"base/base/#Base.@polly","page":"基本功能","title":"Base.@polly","text":"@polly\n\nTells the compiler to apply the polyhedral optimizer Polly to a function.\n\n\n\n\n\n","category":"macro"},{"location":"base/base/#Base.@generated","page":"基本功能","title":"Base.@generated","text":"@generated f\n\n@generated is used to annotate a function which will be generated. In the body of the generated function, only types of arguments can be read (not the values). The function returns a quoted expression evaluated when the function is called. The @generated macro should not be used on functions mutating the global scope or depending on mutable elements.\n\nSee Metaprogramming for further details.\n\nExample:\n\njulia> @generated function bar(x)\n if x <: Integer\n return :(x ^ 2)\n else\n return :(x)\n end\n end\nbar (generic function with 1 method)\n\njulia> bar(4)\n16\n\njulia> bar(\"baz\")\n\"baz\"\n\n\n\n\n\n","category":"macro"},{"location":"base/base/#Base.@pure","page":"基本功能","title":"Base.@pure","text":"@pure ex\n\n@pure gives the compiler a hint for the definition of a pure function, helping for type inference.\n\nwarning: Warning\nThis macro is intended for internal compiler use and may be subject to changes.\n\nwarning: Warning\nIn Julia 1.8 and higher, it is favorable to use @assume_effects instead of @pure. This is because @assume_effects allows a finer grained control over Julia's purity modeling and the effect system enables a wider range of optimizations.\n\n\n\n\n\n","category":"macro"},{"location":"base/base/#Base.@deprecate","page":"基本功能","title":"Base.@deprecate","text":"@deprecate old new [export_old=true]\n\nDeprecate method old and specify the replacement call new. Prevent @deprecate from exporting old by setting export_old to false. @deprecate defines a new method with the same signature as old.\n\ncompat: Julia 1.5\nAs of Julia 1.5, functions defined by @deprecate do not print warning when julia is run without the --depwarn=yes flag set, as the default value of --depwarn option is no. The warnings are printed from tests run by Pkg.test().\n\nExamples\n\njulia> @deprecate old(x) new(x)\nold (generic function with 1 method)\n\njulia> @deprecate old(x) new(x) false\nold (generic function with 1 method)\n\n\n\n\n\n","category":"macro"},{"location":"base/base/#Missing-Values","page":"基本功能","title":"Missing Values","text":"","category":"section"},{"location":"base/base/","page":"基本功能","title":"基本功能","text":"Base.Missing\nBase.missing\nBase.coalesce\nBase.@coalesce\nBase.ismissing\nBase.skipmissing\nBase.nonmissingtype","category":"page"},{"location":"base/base/#Base.Missing","page":"基本功能","title":"Base.Missing","text":"Missing\n\nA type with no fields whose singleton instance missing is used to represent missing values.\n\nSee also: skipmissing, nonmissingtype, Nothing.\n\n\n\n\n\n","category":"type"},{"location":"base/base/#Base.missing","page":"基本功能","title":"Base.missing","text":"missing\n\nThe singleton instance of type Missing representing a missing value.\n\nSee also: NaN, skipmissing, nonmissingtype.\n\n\n\n\n\n","category":"constant"},{"location":"base/base/#Base.coalesce","page":"基本功能","title":"Base.coalesce","text":"coalesce(x...)\n\nReturn the first value in the arguments which is not equal to missing, if any. Otherwise return missing.\n\nSee also skipmissing, something, @coalesce.\n\nExamples\n\njulia> coalesce(missing, 1)\n1\n\njulia> coalesce(1, missing)\n1\n\njulia> coalesce(nothing, 1) # returns `nothing`\n\njulia> coalesce(missing, missing)\nmissing\n\n\n\n\n\n","category":"function"},{"location":"base/base/#Base.@coalesce","page":"基本功能","title":"Base.@coalesce","text":"@coalesce(x...)\n\nShort-circuiting version of coalesce.\n\nExamples\n\njulia> f(x) = (println(\"f($x)\"); missing);\n\njulia> a = 1;\n\njulia> a = @coalesce a f(2) f(3) error(\"`a` is still missing\")\n1\n\njulia> b = missing;\n\njulia> b = @coalesce b f(2) f(3) error(\"`b` is still missing\")\nf(2)\nf(3)\nERROR: `b` is still missing\n[...]\n\ncompat: Julia 1.7\nThis macro is available as of Julia 1.7.\n\n\n\n\n\n","category":"macro"},{"location":"base/base/#Base.ismissing","page":"基本功能","title":"Base.ismissing","text":"ismissing(x)\n\nIndicate whether x is missing.\n\nSee also: skipmissing, isnothing, isnan.\n\n\n\n\n\n","category":"function"},{"location":"base/base/#Base.skipmissing","page":"基本功能","title":"Base.skipmissing","text":"skipmissing(itr)\n\nReturn an iterator over the elements in itr skipping missing values. The returned object can be indexed using indices of itr if the latter is indexable. Indices corresponding to missing values are not valid: they are skipped by keys and eachindex, and a MissingException is thrown when trying to use them.\n\nUse collect to obtain an Array containing the non-missing values in itr. Note that even if itr is a multidimensional array, the result will always be a Vector since it is not possible to remove missings while preserving dimensions of the input.\n\nSee also coalesce, ismissing, something.\n\nExamples\n\njulia> x = skipmissing([1, missing, 2])\nskipmissing(Union{Missing, Int64}[1, missing, 2])\n\njulia> sum(x)\n3\n\njulia> x[1]\n1\n\njulia> x[2]\nERROR: MissingException: the value at index (2,) is missing\n[...]\n\njulia> argmax(x)\n3\n\njulia> collect(keys(x))\n2-element Vector{Int64}:\n 1\n 3\n\njulia> collect(skipmissing([1, missing, 2]))\n2-element Vector{Int64}:\n 1\n 2\n\njulia> collect(skipmissing([1 missing; 2 missing]))\n2-element Vector{Int64}:\n 1\n 2\n\n\n\n\n\n","category":"function"},{"location":"base/base/#Base.nonmissingtype","page":"基本功能","title":"Base.nonmissingtype","text":"nonmissingtype(T::Type)\n\nIf T is a union of types containing Missing, return a new type with Missing removed.\n\nExamples\n\njulia> nonmissingtype(Union{Int64,Missing})\nInt64\n\njulia> nonmissingtype(Any)\nAny\n\ncompat: Julia 1.3\nThis function is exported as of Julia 1.3.\n\n\n\n\n\n","category":"function"},{"location":"base/base/#System","page":"基本功能","title":"System","text":"","category":"section"},{"location":"base/base/","page":"基本功能","title":"基本功能","text":"Base.run\nBase.devnull\nBase.success\nBase.process_running\nBase.process_exited\nBase.kill(::Base.Process, ::Integer)\nBase.Sys.set_process_title\nBase.Sys.get_process_title\nBase.ignorestatus\nBase.detach\nBase.Cmd\nBase.setenv\nBase.addenv\nBase.withenv\nBase.pipeline(::Any, ::Any, ::Any, ::Any...)\nBase.pipeline(::Base.AbstractCmd)\nBase.Libc.gethostname\nBase.Libc.getpid\nBase.Libc.time()\nBase.time_ns\nBase.@time\nBase.@timev\nBase.@timed\nBase.@elapsed\nBase.@allocated\nBase.EnvDict\nBase.ENV\nBase.Sys.isunix\nBase.Sys.isapple\nBase.Sys.islinux\nBase.Sys.isbsd\nBase.Sys.isfreebsd\nBase.Sys.isopenbsd\nBase.Sys.isnetbsd\nBase.Sys.isdragonfly\nBase.Sys.iswindows\nBase.Sys.windows_version\nBase.Sys.free_memory\nBase.Sys.total_memory\nBase.@static","category":"page"},{"location":"base/base/#Base.run","page":"基本功能","title":"Base.run","text":"run(command, args...; wait::Bool = true)\n\nRun a command object, constructed with backticks (see the Running External Programs section in the manual). Throws an error if anything goes wrong, including the process exiting with a non-zero status (when wait is true).\n\nThe args... allow you to pass through file descriptors to the command, and are ordered like regular unix file descriptors (eg stdin, stdout, stderr, FD(3), FD(4)...).\n\nIf wait is false, the process runs asynchronously. You can later wait for it and check its exit status by calling success on the returned process object.\n\nWhen wait is false, the process' I/O streams are directed to devnull. When wait is true, I/O streams are shared with the parent process. Use pipeline to control I/O redirection.\n\n\n\n\n\n","category":"function"},{"location":"base/base/#Base.devnull","page":"基本功能","title":"Base.devnull","text":"devnull\n\nUsed in a stream redirect to discard all data written to it. Essentially equivalent to /dev/null on Unix or NUL on Windows. Usage:\n\nrun(pipeline(`cat test.txt`, devnull))\n\n\n\n\n\n","category":"constant"},{"location":"base/base/#Base.success","page":"基本功能","title":"Base.success","text":"success(command)\n\nRun a command object, constructed with backticks (see the Running External Programs section in the manual), and tell whether it was successful (exited with a code of 0). An exception is raised if the process cannot be started.\n\n\n\n\n\n","category":"function"},{"location":"base/base/#Base.process_running","page":"基本功能","title":"Base.process_running","text":"process_running(p::Process)\n\nDetermine whether a process is currently running.\n\n\n\n\n\n","category":"function"},{"location":"base/base/#Base.process_exited","page":"基本功能","title":"Base.process_exited","text":"process_exited(p::Process)\n\nDetermine whether a process has exited.\n\n\n\n\n\n","category":"function"},{"location":"base/base/#Base.kill-Tuple{Base.Process, Integer}","page":"基本功能","title":"Base.kill","text":"kill(p::Process, signum=Base.SIGTERM)\n\nSend a signal to a process. The default is to terminate the process. Returns successfully if the process has already exited, but throws an error if killing the process failed for other reasons (e.g. insufficient permissions).\n\n\n\n\n\n","category":"method"},{"location":"base/base/#Base.Sys.set_process_title","page":"基本功能","title":"Base.Sys.set_process_title","text":"Sys.set_process_title(title::AbstractString)\n\nSet the process title. No-op on some operating systems.\n\n\n\n\n\n","category":"function"},{"location":"base/base/#Base.Sys.get_process_title","page":"基本功能","title":"Base.Sys.get_process_title","text":"Sys.get_process_title()\n\nGet the process title. On some systems, will always return an empty string.\n\n\n\n\n\n","category":"function"},{"location":"base/base/#Base.ignorestatus","page":"基本功能","title":"Base.ignorestatus","text":"ignorestatus(command)\n\nMark a command object so that running it will not throw an error if the result code is non-zero.\n\n\n\n\n\n","category":"function"},{"location":"base/base/#Base.detach","page":"基本功能","title":"Base.detach","text":"detach(command)\n\nMark a command object so that it will be run in a new process group, allowing it to outlive the julia process, and not have Ctrl-C interrupts passed to it.\n\n\n\n\n\n","category":"function"},{"location":"base/base/#Base.Cmd","page":"基本功能","title":"Base.Cmd","text":"Cmd(cmd::Cmd; ignorestatus, detach, windows_verbatim, windows_hide, env, dir)\n\nConstruct a new Cmd object, representing an external program and arguments, from cmd, while changing the settings of the optional keyword arguments:\n\nignorestatus::Bool: If true (defaults to false), then the Cmd will not throw an error if the return code is nonzero.\ndetach::Bool: If true (defaults to false), then the Cmd will be run in a new process group, allowing it to outlive the julia process and not have Ctrl-C passed to it.\nwindows_verbatim::Bool: If true (defaults to false), then on Windows the Cmd will send a command-line string to the process with no quoting or escaping of arguments, even arguments containing spaces. (On Windows, arguments are sent to a program as a single \"command-line\" string, and programs are responsible for parsing it into arguments. By default, empty arguments and arguments with spaces or tabs are quoted with double quotes \" in the command line, and \\ or \" are preceded by backslashes. windows_verbatim=true is useful for launching programs that parse their command line in nonstandard ways.) Has no effect on non-Windows systems.\nwindows_hide::Bool: If true (defaults to false), then on Windows no new console window is displayed when the Cmd is executed. This has no effect if a console is already open or on non-Windows systems.\nenv: Set environment variables to use when running the Cmd. env is either a dictionary mapping strings to strings, an array of strings of the form \"var=val\", an array or tuple of \"var\"=>val pairs. In order to modify (rather than replace) the existing environment, initialize env with copy(ENV) and then set env[\"var\"]=val as desired. To add to an environment block within a Cmd object without replacing all elements, use addenv() which will return a Cmd object with the updated environment.\ndir::AbstractString: Specify a working directory for the command (instead of the current directory).\n\nFor any keywords that are not specified, the current settings from cmd are used. Normally, to create a Cmd object in the first place, one uses backticks, e.g.\n\nCmd(`echo \"Hello world\"`, ignorestatus=true, detach=false)\n\n\n\n\n\n","category":"type"},{"location":"base/base/#Base.setenv","page":"基本功能","title":"Base.setenv","text":"setenv(command::Cmd, env; dir)\n\nSet environment variables to use when running the given command. env is either a dictionary mapping strings to strings, an array of strings of the form \"var=val\", or zero or more \"var\"=>val pair arguments. In order to modify (rather than replace) the existing environment, create env through copy(ENV) and then setting env[\"var\"]=val as desired, or use addenv.\n\nThe dir keyword argument can be used to specify a working directory for the command. dir defaults to the currently set dir for command (which is the current working directory if not specified already).\n\nSee also Cmd, addenv, ENV, pwd.\n\n\n\n\n\n","category":"function"},{"location":"base/base/#Base.addenv","page":"基本功能","title":"Base.addenv","text":"addenv(command::Cmd, env...; inherit::Bool = true)\n\nMerge new environment mappings into the given Cmd object, returning a new Cmd object. Duplicate keys are replaced. If command does not contain any environment values set already, it inherits the current environment at time of addenv() call if inherit is true. Keys with value nothing are deleted from the env.\n\nSee also Cmd, setenv, ENV.\n\ncompat: Julia 1.6\nThis function requires Julia 1.6 or later.\n\n\n\n\n\n","category":"function"},{"location":"base/base/#Base.withenv","page":"基本功能","title":"Base.withenv","text":"withenv(f, kv::Pair...)\n\nExecute f in an environment that is temporarily modified (not replaced as in setenv) by zero or more \"var\"=>val arguments kv. withenv is generally used via the withenv(kv...) do ... end syntax. A value of nothing can be used to temporarily unset an environment variable (if it is set). When withenv returns, the original environment has been restored.\n\n\n\n\n\n","category":"function"},{"location":"base/base/#Base.pipeline-Tuple{Any, Any, Any, Vararg{Any}}","page":"基本功能","title":"Base.pipeline","text":"pipeline(from, to, ...)\n\nCreate a pipeline from a data source to a destination. The source and destination can be commands, I/O streams, strings, or results of other pipeline calls. At least one argument must be a command. Strings refer to filenames. When called with more than two arguments, they are chained together from left to right. For example, pipeline(a,b,c) is equivalent to pipeline(pipeline(a,b),c). This provides a more concise way to specify multi-stage pipelines.\n\nExamples:\n\nrun(pipeline(`ls`, `grep xyz`))\nrun(pipeline(`ls`, \"out.txt\"))\nrun(pipeline(\"out.txt\", `grep xyz`))\n\n\n\n\n\n","category":"method"},{"location":"base/base/#Base.pipeline-Tuple{Base.AbstractCmd}","page":"基本功能","title":"Base.pipeline","text":"pipeline(command; stdin, stdout, stderr, append=false)\n\nRedirect I/O to or from the given command. Keyword arguments specify which of the command's streams should be redirected. append controls whether file output appends to the file. This is a more general version of the 2-argument pipeline function. pipeline(from, to) is equivalent to pipeline(from, stdout=to) when from is a command, and to pipeline(to, stdin=from) when from is another kind of data source.\n\nExamples:\n\nrun(pipeline(`dothings`, stdout=\"out.txt\", stderr=\"errs.txt\"))\nrun(pipeline(`update`, stdout=\"log.txt\", append=true))\n\n\n\n\n\n","category":"method"},{"location":"base/base/#Base.Libc.gethostname","page":"基本功能","title":"Base.Libc.gethostname","text":"gethostname() -> AbstractString\n\nGet the local machine's host name.\n\n\n\n\n\n","category":"function"},{"location":"base/base/#Base.Libc.getpid","page":"基本功能","title":"Base.Libc.getpid","text":"getpid() -> Int32\n\nGet Julia's process ID.\n\n\n\n\n\ngetpid(process) -> Int32\n\nGet the child process ID, if it still exists.\n\ncompat: Julia 1.1\nThis function requires at least Julia 1.1.\n\n\n\n\n\n","category":"function"},{"location":"base/base/#Base.Libc.time-Tuple{}","page":"基本功能","title":"Base.Libc.time","text":"time()\n\nGet the system time in seconds since the epoch, with fairly high (typically, microsecond) resolution.\n\n\n\n\n\n","category":"method"},{"location":"base/base/#Base.time_ns","page":"基本功能","title":"Base.time_ns","text":"time_ns()\n\nGet the time in nanoseconds. The time corresponding to 0 is undefined, and wraps every 5.8 years.\n\n\n\n\n\n","category":"function"},{"location":"base/base/#Base.@time","page":"基本功能","title":"Base.@time","text":"@time expr\n@time \"description\" expr\n\nA macro to execute an expression, printing the time it took to execute, the number of allocations, and the total number of bytes its execution caused to be allocated, before returning the value of the expression. Any time spent garbage collecting (gc), compiling new code, or recompiling invalidated code is shown as a percentage.\n\nOptionally provide a description string to print before the time report.\n\nIn some cases the system will look inside the @time expression and compile some of the called code before execution of the top-level expression begins. When that happens, some compilation time will not be counted. To include this time you can run @time @eval ....\n\nSee also @showtime, @timev, @timed, @elapsed, and @allocated.\n\nnote: Note\nFor more serious benchmarking, consider the @btime macro from the BenchmarkTools.jl package which among other things evaluates the function multiple times in order to reduce noise.\n\ncompat: Julia 1.8\nThe option to add a description was introduced in Julia 1.8.Recompilation time being shown separately from compilation time was introduced in Julia 1.8\n\njulia> x = rand(10,10);\n\njulia> @time x * x;\n 0.606588 seconds (2.19 M allocations: 116.555 MiB, 3.75% gc time, 99.94% compilation time)\n\njulia> @time x * x;\n 0.000009 seconds (1 allocation: 896 bytes)\n\njulia> @time begin\n sleep(0.3)\n 1+1\n end\n 0.301395 seconds (8 allocations: 336 bytes)\n2\n\njulia> @time \"A one second sleep\" sleep(1)\nA one second sleep: 1.005750 seconds (5 allocations: 144 bytes)\n\njulia> for loop in 1:3\n @time loop sleep(1)\n end\n1: 1.006760 seconds (5 allocations: 144 bytes)\n2: 1.001263 seconds (5 allocations: 144 bytes)\n3: 1.003676 seconds (5 allocations: 144 bytes)\n\n\n\n\n\n","category":"macro"},{"location":"base/base/#Base.@timev","page":"基本功能","title":"Base.@timev","text":"@timev expr\n@timev \"description\" expr\n\nThis is a verbose version of the @time macro. It first prints the same information as @time, then any non-zero memory allocation counters, and then returns the value of the expression.\n\nOptionally provide a description string to print before the time report.\n\ncompat: Julia 1.8\nThe option to add a description was introduced in Julia 1.8.\n\nSee also @time, @timed, @elapsed, and @allocated.\n\njulia> x = rand(10,10);\n\njulia> @timev x * x;\n 0.546770 seconds (2.20 M allocations: 116.632 MiB, 4.23% gc time, 99.94% compilation time)\nelapsed time (ns): 546769547\ngc time (ns): 23115606\nbytes allocated: 122297811\npool allocs: 2197930\nnon-pool GC allocs:1327\nmalloc() calls: 36\nrealloc() calls: 5\nGC pauses: 3\n\njulia> @timev x * x;\n 0.000010 seconds (1 allocation: 896 bytes)\nelapsed time (ns): 9848\nbytes allocated: 896\npool allocs: 1\n\n\n\n\n\n","category":"macro"},{"location":"base/base/#Base.@timed","page":"基本功能","title":"Base.@timed","text":"@timed\n\nA macro to execute an expression, and return the value of the expression, elapsed time, total bytes allocated, garbage collection time, and an object with various memory allocation counters.\n\nIn some cases the system will look inside the @timed expression and compile some of the called code before execution of the top-level expression begins. When that happens, some compilation time will not be counted. To include this time you can run @timed @eval ....\n\nSee also @time, @timev, @elapsed, and @allocated.\n\njulia> stats = @timed rand(10^6);\n\njulia> stats.time\n0.006634834\n\njulia> stats.bytes\n8000256\n\njulia> stats.gctime\n0.0055765\n\njulia> propertynames(stats.gcstats)\n(:allocd, :malloc, :realloc, :poolalloc, :bigalloc, :freecall, :total_time, :pause, :full_sweep)\n\njulia> stats.gcstats.total_time\n5576500\n\ncompat: Julia 1.5\nThe return type of this macro was changed from Tuple to NamedTuple in Julia 1.5.\n\n\n\n\n\n","category":"macro"},{"location":"base/base/#Base.@elapsed","page":"基本功能","title":"Base.@elapsed","text":"@elapsed\n\nA macro to evaluate an expression, discarding the resulting value, instead returning the number of seconds it took to execute as a floating-point number.\n\nIn some cases the system will look inside the @elapsed expression and compile some of the called code before execution of the top-level expression begins. When that happens, some compilation time will not be counted. To include this time you can run @elapsed @eval ....\n\nSee also @time, @timev, @timed, and @allocated.\n\njulia> @elapsed sleep(0.3)\n0.301391426\n\n\n\n\n\n","category":"macro"},{"location":"base/base/#Base.@allocated","page":"基本功能","title":"Base.@allocated","text":"@allocated\n\nA macro to evaluate an expression, discarding the resulting value, instead returning the total number of bytes allocated during evaluation of the expression.\n\nSee also @time, @timev, @timed, and @elapsed.\n\njulia> @allocated rand(10^6)\n8000080\n\n\n\n\n\n","category":"macro"},{"location":"base/base/#Base.EnvDict","page":"基本功能","title":"Base.EnvDict","text":"EnvDict() -> EnvDict\n\nA singleton of this type provides a hash table interface to environment variables.\n\n\n\n\n\n","category":"type"},{"location":"base/base/#Base.ENV","page":"基本功能","title":"Base.ENV","text":"ENV\n\nReference to the singleton EnvDict, providing a dictionary interface to system environment variables.\n\n(On Windows, system environment variables are case-insensitive, and ENV correspondingly converts all keys to uppercase for display, iteration, and copying. Portable code should not rely on the ability to distinguish variables by case, and should beware that setting an ostensibly lowercase variable may result in an uppercase ENV key.)\n\n\n\n\n\n","category":"constant"},{"location":"base/base/#Base.Sys.isunix","page":"基本功能","title":"Base.Sys.isunix","text":"Sys.isunix([os])\n\nPredicate for testing if the OS provides a Unix-like interface. See documentation in Handling Operating System Variation.\n\n\n\n\n\n","category":"function"},{"location":"base/base/#Base.Sys.isapple","page":"基本功能","title":"Base.Sys.isapple","text":"Sys.isapple([os])\n\nPredicate for testing if the OS is a derivative of Apple Macintosh OS X or Darwin. See documentation in Handling Operating System Variation.\n\n\n\n\n\n","category":"function"},{"location":"base/base/#Base.Sys.islinux","page":"基本功能","title":"Base.Sys.islinux","text":"Sys.islinux([os])\n\nPredicate for testing if the OS is a derivative of Linux. See documentation in Handling Operating System Variation.\n\n\n\n\n\n","category":"function"},{"location":"base/base/#Base.Sys.isbsd","page":"基本功能","title":"Base.Sys.isbsd","text":"Sys.isbsd([os])\n\nPredicate for testing if the OS is a derivative of BSD. See documentation in Handling Operating System Variation.\n\nnote: Note\nThe Darwin kernel descends from BSD, which means that Sys.isbsd() is true on macOS systems. To exclude macOS from a predicate, use Sys.isbsd() && !Sys.isapple().\n\n\n\n\n\n","category":"function"},{"location":"base/base/#Base.Sys.isfreebsd","page":"基本功能","title":"Base.Sys.isfreebsd","text":"Sys.isfreebsd([os])\n\nPredicate for testing if the OS is a derivative of FreeBSD. See documentation in Handling Operating System Variation.\n\nnote: Note\nNot to be confused with Sys.isbsd(), which is true on FreeBSD but also on other BSD-based systems. Sys.isfreebsd() refers only to FreeBSD.\n\ncompat: Julia 1.1\nThis function requires at least Julia 1.1.\n\n\n\n\n\n","category":"function"},{"location":"base/base/#Base.Sys.isopenbsd","page":"基本功能","title":"Base.Sys.isopenbsd","text":"Sys.isopenbsd([os])\n\nPredicate for testing if the OS is a derivative of OpenBSD. See documentation in Handling Operating System Variation.\n\nnote: Note\nNot to be confused with Sys.isbsd(), which is true on OpenBSD but also on other BSD-based systems. Sys.isopenbsd() refers only to OpenBSD.\n\ncompat: Julia 1.1\nThis function requires at least Julia 1.1.\n\n\n\n\n\n","category":"function"},{"location":"base/base/#Base.Sys.isnetbsd","page":"基本功能","title":"Base.Sys.isnetbsd","text":"Sys.isnetbsd([os])\n\nPredicate for testing if the OS is a derivative of NetBSD. See documentation in Handling Operating System Variation.\n\nnote: Note\nNot to be confused with Sys.isbsd(), which is true on NetBSD but also on other BSD-based systems. Sys.isnetbsd() refers only to NetBSD.\n\ncompat: Julia 1.1\nThis function requires at least Julia 1.1.\n\n\n\n\n\n","category":"function"},{"location":"base/base/#Base.Sys.isdragonfly","page":"基本功能","title":"Base.Sys.isdragonfly","text":"Sys.isdragonfly([os])\n\nPredicate for testing if the OS is a derivative of DragonFly BSD. See documentation in Handling Operating System Variation.\n\nnote: Note\nNot to be confused with Sys.isbsd(), which is true on DragonFly but also on other BSD-based systems. Sys.isdragonfly() refers only to DragonFly.\n\ncompat: Julia 1.1\nThis function requires at least Julia 1.1.\n\n\n\n\n\n","category":"function"},{"location":"base/base/#Base.Sys.iswindows","page":"基本功能","title":"Base.Sys.iswindows","text":"Sys.iswindows([os])\n\nPredicate for testing if the OS is a derivative of Microsoft Windows NT. See documentation in Handling Operating System Variation.\n\n\n\n\n\n","category":"function"},{"location":"base/base/#Base.Sys.windows_version","page":"基本功能","title":"Base.Sys.windows_version","text":"Sys.windows_version()\n\nReturn the version number for the Windows NT Kernel as a VersionNumber, i.e. v\"major.minor.build\", or v\"0.0.0\" if this is not running on Windows.\n\n\n\n\n\n","category":"function"},{"location":"base/base/#Base.Sys.free_memory","page":"基本功能","title":"Base.Sys.free_memory","text":"Sys.free_memory()\n\nGet the total free memory in RAM in bytes.\n\n\n\n\n\n","category":"function"},{"location":"base/base/#Base.Sys.total_memory","page":"基本功能","title":"Base.Sys.total_memory","text":"Sys.total_memory()\n\nGet the total memory in RAM (including that which is currently used) in bytes. This amount may be constrained, e.g., by Linux control groups. For the unconstrained amount, see Sys.physical_memory().\n\n\n\n\n\n","category":"function"},{"location":"base/base/#Base.@static","page":"基本功能","title":"Base.@static","text":"@static\n\nPartially evaluate an expression at parse time.\n\nFor example, @static Sys.iswindows() ? foo : bar will evaluate Sys.iswindows() and insert either foo or bar into the expression. This is useful in cases where a construct would be invalid on other platforms, such as a ccall to a non-existent function. @static if Sys.isapple() foo end and @static foo <&&,||> bar are also valid syntax.\n\n\n\n\n\n","category":"macro"},{"location":"base/base/#Versioning","page":"基本功能","title":"Versioning","text":"","category":"section"},{"location":"base/base/","page":"基本功能","title":"基本功能","text":"Base.VersionNumber\nBase.@v_str","category":"page"},{"location":"base/base/#Base.VersionNumber","page":"基本功能","title":"Base.VersionNumber","text":"VersionNumber\n\nVersion number type which follows the specifications of semantic versioning (semver), composed of major, minor and patch numeric values, followed by pre-release and build alpha-numeric annotations.\n\nVersionNumber objects can be compared with all of the standard comparison operators (==, <, <=, etc.), with the result following semver rules.\n\nSee also @v_str to efficiently construct VersionNumber objects from semver-format literal strings, VERSION for the VersionNumber of Julia itself, and Version Number Literals in the manual.\n\nExamples\n\njulia> a = VersionNumber(1, 2, 3)\nv\"1.2.3\"\n\njulia> a >= v\"1.2\"\ntrue\n\njulia> b = VersionNumber(\"2.0.1-rc1\")\nv\"2.0.1-rc1\"\n\njulia> b >= v\"2.0.1\"\nfalse\n\n\n\n\n\n","category":"type"},{"location":"base/base/#Base.@v_str","page":"基本功能","title":"Base.@v_str","text":"@v_str\n\nString macro used to parse a string to a VersionNumber.\n\nExamples\n\njulia> v\"1.2.3\"\nv\"1.2.3\"\n\njulia> v\"2.0.1-rc1\"\nv\"2.0.1-rc1\"\n\n\n\n\n\n","category":"macro"},{"location":"base/base/#Errors","page":"基本功能","title":"Errors","text":"","category":"section"},{"location":"base/base/","page":"基本功能","title":"基本功能","text":"Base.error\nCore.throw\nBase.rethrow\nBase.backtrace\nBase.catch_backtrace\nBase.current_exceptions\nBase.@assert\nBase.Experimental.register_error_hint\nBase.Experimental.show_error_hints\nBase.ArgumentError\nBase.AssertionError\nCore.BoundsError\nBase.CompositeException\nBase.DimensionMismatch\nCore.DivideError\nCore.DomainError\nBase.EOFError\nCore.ErrorException\nCore.InexactError\nCore.InterruptException\nBase.KeyError\nBase.LoadError\nBase.MethodError\nBase.MissingException\nCore.OutOfMemoryError\nCore.ReadOnlyMemoryError\nCore.OverflowError\nBase.ProcessFailedException\nCore.StackOverflowError\nBase.SystemError\nCore.TypeError\nCore.UndefKeywordError\nCore.UndefRefError\nCore.UndefVarError\nBase.StringIndexError\nBase.InitError\nBase.retry\nBase.ExponentialBackOff","category":"page"},{"location":"base/base/#Base.error","page":"基本功能","title":"Base.error","text":"error(message::AbstractString)\n\nRaise an ErrorException with the given message.\n\n\n\n\n\nerror(msg...)\n\nRaise an ErrorException with the given message.\n\n\n\n\n\n","category":"function"},{"location":"base/base/#Core.throw","page":"基本功能","title":"Core.throw","text":"throw(e)\n\nThrow an object as an exception.\n\nSee also: rethrow, error.\n\n\n\n\n\n","category":"function"},{"location":"base/base/#Base.rethrow","page":"基本功能","title":"Base.rethrow","text":"rethrow()\n\nRethrow the current exception from within a catch block. The rethrown exception will continue propagation as if it had not been caught.\n\nnote: Note\nThe alternative form rethrow(e) allows you to associate an alternative exception object e with the current backtrace. However this misrepresents the program state at the time of the error so you're encouraged to instead throw a new exception using throw(e). In Julia 1.1 and above, using throw(e) will preserve the root cause exception on the stack, as described in current_exceptions.\n\n\n\n\n\n","category":"function"},{"location":"base/base/#Base.backtrace","page":"基本功能","title":"Base.backtrace","text":"backtrace()\n\nGet a backtrace object for the current program point.\n\n\n\n\n\n","category":"function"},{"location":"base/base/#Base.catch_backtrace","page":"基本功能","title":"Base.catch_backtrace","text":"catch_backtrace()\n\nGet the backtrace of the current exception, for use within catch blocks.\n\n\n\n\n\n","category":"function"},{"location":"base/base/#Base.current_exceptions","page":"基本功能","title":"Base.current_exceptions","text":"current_exceptions(task::Task=current_task(); [backtrace::Bool=true])\n\nGet the stack of exceptions currently being handled. For nested catch blocks there may be more than one current exception in which case the most recently thrown exception is last in the stack. The stack is returned as an ExceptionStack which is an AbstractVector of named tuples (exception,backtrace). If backtrace is false, the backtrace in each pair will be set to nothing.\n\nExplicitly passing task will return the current exception stack on an arbitrary task. This is useful for inspecting tasks which have failed due to uncaught exceptions.\n\ncompat: Julia 1.7\nThis function went by the experimental name catch_stack() in Julia 1.1–1.6, and had a plain Vector-of-tuples as a return type.\n\n\n\n\n\n","category":"function"},{"location":"base/base/#Base.@assert","page":"基本功能","title":"Base.@assert","text":"@assert cond [text]\n\nThrow an AssertionError if cond is false. Preferred syntax for writing assertions. Message text is optionally displayed upon assertion failure.\n\nwarning: Warning\nAn assert might be disabled at various optimization levels. Assert should therefore only be used as a debugging tool and not used for authentication verification (e.g., verifying passwords), nor should side effects needed for the function to work correctly be used inside of asserts.\n\nExamples\n\njulia> @assert iseven(3) \"3 is an odd number!\"\nERROR: AssertionError: 3 is an odd number!\n\njulia> @assert isodd(3) \"What even are numbers?\"\n\n\n\n\n\n","category":"macro"},{"location":"base/base/#Base.Experimental.register_error_hint","page":"基本功能","title":"Base.Experimental.register_error_hint","text":"Experimental.register_error_hint(handler, exceptiontype)\n\nRegister a \"hinting\" function handler(io, exception) that can suggest potential ways for users to circumvent errors. handler should examine exception to see whether the conditions appropriate for a hint are met, and if so generate output to io. Packages should call register_error_hint from within their __init__ function.\n\nFor specific exception types, handler is required to accept additional arguments:\n\nMethodError: provide handler(io, exc::MethodError, argtypes, kwargs), which splits the combined arguments into positional and keyword arguments.\n\nWhen issuing a hint, the output should typically start with \\n.\n\nIf you define custom exception types, your showerror method can support hints by calling Experimental.show_error_hints.\n\nExample\n\njulia> module Hinter\n\n only_int(x::Int) = 1\n any_number(x::Number) = 2\n\n function __init__()\n Base.Experimental.register_error_hint(MethodError) do io, exc, argtypes, kwargs\n if exc.f == only_int\n # Color is not necessary, this is just to show it's possible.\n print(io, \"\\nDid you mean to call \")\n printstyled(io, \"`any_number`?\", color=:cyan)\n end\n end\n end\n\n end\n\nThen if you call Hinter.only_int on something that isn't an Int (thereby triggering a MethodError), it issues the hint:\n\njulia> Hinter.only_int(1.0)\nERROR: MethodError: no method matching only_int(::Float64)\nDid you mean to call `any_number`?\nClosest candidates are:\n ...\n\ncompat: Julia 1.5\nCustom error hints are available as of Julia 1.5.\n\nwarning: Warning\nThis interface is experimental and subject to change or removal without notice. To insulate yourself against changes, consider putting any registrations inside an if isdefined(Base.Experimental, :register_error_hint) ... end block.\n\n\n\n\n\n","category":"function"},{"location":"base/base/#Base.Experimental.show_error_hints","page":"基本功能","title":"Base.Experimental.show_error_hints","text":"Experimental.show_error_hints(io, ex, args...)\n\nInvoke all handlers from Experimental.register_error_hint for the particular exception type typeof(ex). args must contain any other arguments expected by the handler for that type.\n\ncompat: Julia 1.5\nCustom error hints are available as of Julia 1.5.\n\nwarning: Warning\nThis interface is experimental and subject to change or removal without notice.\n\n\n\n\n\n","category":"function"},{"location":"base/base/#Core.ArgumentError","page":"基本功能","title":"Core.ArgumentError","text":"ArgumentError(msg)\n\nThe arguments passed to a function are invalid. msg is a descriptive error message.\n\n\n\n\n\n","category":"type"},{"location":"base/base/#Core.AssertionError","page":"基本功能","title":"Core.AssertionError","text":"AssertionError([msg])\n\nThe asserted condition did not evaluate to true. Optional argument msg is a descriptive error string.\n\nExamples\n\njulia> @assert false \"this is not true\"\nERROR: AssertionError: this is not true\n\nAssertionError is usually thrown from @assert.\n\n\n\n\n\n","category":"type"},{"location":"base/base/#Core.BoundsError","page":"基本功能","title":"Core.BoundsError","text":"BoundsError([a],[i])\n\nAn indexing operation into an array, a, tried to access an out-of-bounds element at index i.\n\nExamples\n\njulia> A = fill(1.0, 7);\n\njulia> A[8]\nERROR: BoundsError: attempt to access 7-element Vector{Float64} at index [8]\n\n\njulia> B = fill(1.0, (2,3));\n\njulia> B[2, 4]\nERROR: BoundsError: attempt to access 2×3 Matrix{Float64} at index [2, 4]\n\n\njulia> B[9]\nERROR: BoundsError: attempt to access 2×3 Matrix{Float64} at index [9]\n\n\n\n\n\n\n","category":"type"},{"location":"base/base/#Base.CompositeException","page":"基本功能","title":"Base.CompositeException","text":"CompositeException\n\nWrap a Vector of exceptions thrown by a Task (e.g. generated from a remote worker over a channel or an asynchronously executing local I/O write or a remote worker under pmap) with information about the series of exceptions. For example, if a group of workers are executing several tasks, and multiple workers fail, the resulting CompositeException will contain a \"bundle\" of information from each worker indicating where and why the exception(s) occurred.\n\n\n\n\n\n","category":"type"},{"location":"base/base/#Base.DimensionMismatch","page":"基本功能","title":"Base.DimensionMismatch","text":"DimensionMismatch([msg])\n\nThe objects called do not have matching dimensionality. Optional argument msg is a descriptive error string.\n\n\n\n\n\n","category":"type"},{"location":"base/base/#Core.DivideError","page":"基本功能","title":"Core.DivideError","text":"DivideError()\n\nInteger division was attempted with a denominator value of 0.\n\nExamples\n\njulia> 2/0\nInf\n\njulia> div(2, 0)\nERROR: DivideError: integer division error\nStacktrace:\n[...]\n\n\n\n\n\n","category":"type"},{"location":"base/base/#Core.DomainError","page":"基本功能","title":"Core.DomainError","text":"DomainError(val)\nDomainError(val, msg)\n\nThe argument val to a function or constructor is outside the valid domain.\n\nExamples\n\njulia> sqrt(-1)\nERROR: DomainError with -1.0:\nsqrt will only return a complex result if called with a complex argument. Try sqrt(Complex(x)).\nStacktrace:\n[...]\n\n\n\n\n\n","category":"type"},{"location":"base/base/#Base.EOFError","page":"基本功能","title":"Base.EOFError","text":"EOFError()\n\nNo more data was available to read from a file or stream.\n\n\n\n\n\n","category":"type"},{"location":"base/base/#Core.ErrorException","page":"基本功能","title":"Core.ErrorException","text":"ErrorException(msg)\n\nGeneric error type. The error message, in the .msg field, may provide more specific details.\n\nExamples\n\njulia> ex = ErrorException(\"I've done a bad thing\");\n\njulia> ex.msg\n\"I've done a bad thing\"\n\n\n\n\n\n","category":"type"},{"location":"base/base/#Core.InexactError","page":"基本功能","title":"Core.InexactError","text":"InexactError(name::Symbol, T, val)\n\nCannot exactly convert val to type T in a method of function name.\n\nExamples\n\njulia> convert(Float64, 1+2im)\nERROR: InexactError: Float64(1 + 2im)\nStacktrace:\n[...]\n\n\n\n\n\n","category":"type"},{"location":"base/base/#Core.InterruptException","page":"基本功能","title":"Core.InterruptException","text":"InterruptException()\n\nThe process was stopped by a terminal interrupt (CTRL+C).\n\nNote that, in Julia script started without -i (interactive) option, InterruptException is not thrown by default. Calling Base.exit_on_sigint(false) in the script can recover the behavior of the REPL. Alternatively, a Julia script can be started with\n\njulia -e \"include(popfirst!(ARGS))\" script.jl\n\nto let InterruptException be thrown by CTRL+C during the execution.\n\n\n\n\n\n","category":"type"},{"location":"base/base/#Base.KeyError","page":"基本功能","title":"Base.KeyError","text":"KeyError(key)\n\nAn indexing operation into an AbstractDict (Dict) or Set like object tried to access or delete a non-existent element.\n\n\n\n\n\n","category":"type"},{"location":"base/base/#Core.LoadError","page":"基本功能","title":"Core.LoadError","text":"LoadError(file::AbstractString, line::Int, error)\n\nAn error occurred while includeing, requireing, or using a file. The error specifics should be available in the .error field.\n\ncompat: Julia 1.7\nLoadErrors are no longer emitted by @macroexpand, @macroexpand1, and macroexpand as of Julia 1.7.\n\n\n\n\n\n","category":"type"},{"location":"base/base/#Core.MethodError","page":"基本功能","title":"Core.MethodError","text":"MethodError(f, args)\n\nA method with the required type signature does not exist in the given generic function. Alternatively, there is no unique most-specific method.\n\n\n\n\n\n","category":"type"},{"location":"base/base/#Base.MissingException","page":"基本功能","title":"Base.MissingException","text":"MissingException(msg)\n\nException thrown when a missing value is encountered in a situation where it is not supported. The error message, in the msg field may provide more specific details.\n\n\n\n\n\n","category":"type"},{"location":"base/base/#Core.OutOfMemoryError","page":"基本功能","title":"Core.OutOfMemoryError","text":"OutOfMemoryError()\n\nAn operation allocated too much memory for either the system or the garbage collector to handle properly.\n\n\n\n\n\n","category":"type"},{"location":"base/base/#Core.ReadOnlyMemoryError","page":"基本功能","title":"Core.ReadOnlyMemoryError","text":"ReadOnlyMemoryError()\n\nAn operation tried to write to memory that is read-only.\n\n\n\n\n\n","category":"type"},{"location":"base/base/#Core.OverflowError","page":"基本功能","title":"Core.OverflowError","text":"OverflowError(msg)\n\nThe result of an expression is too large for the specified type and will cause a wraparound.\n\n\n\n\n\n","category":"type"},{"location":"base/base/#Base.ProcessFailedException","page":"基本功能","title":"Base.ProcessFailedException","text":"ProcessFailedException\n\nIndicates problematic exit status of a process. When running commands or pipelines, this is thrown to indicate a nonzero exit code was returned (i.e. that the invoked process failed).\n\n\n\n\n\n","category":"type"},{"location":"base/base/#Core.StackOverflowError","page":"基本功能","title":"Core.StackOverflowError","text":"StackOverflowError()\n\nThe function call grew beyond the size of the call stack. This usually happens when a call recurses infinitely.\n\n\n\n\n\n","category":"type"},{"location":"base/base/#Base.SystemError","page":"基本功能","title":"Base.SystemError","text":"SystemError(prefix::AbstractString, [errno::Int32])\n\nA system call failed with an error code (in the errno global variable).\n\n\n\n\n\n","category":"type"},{"location":"base/base/#Core.TypeError","page":"基本功能","title":"Core.TypeError","text":"TypeError(func::Symbol, context::AbstractString, expected::Type, got)\n\nA type assertion failure, or calling an intrinsic function with an incorrect argument type.\n\n\n\n\n\n","category":"type"},{"location":"base/base/#Core.UndefKeywordError","page":"基本功能","title":"Core.UndefKeywordError","text":"UndefKeywordError(var::Symbol)\n\nThe required keyword argument var was not assigned in a function call.\n\nExamples\n\njulia> function my_func(;my_arg)\n return my_arg + 1\n end\nmy_func (generic function with 1 method)\n\njulia> my_func()\nERROR: UndefKeywordError: keyword argument my_arg not assigned\nStacktrace:\n [1] my_func() at ./REPL[1]:2\n [2] top-level scope at REPL[2]:1\n\n\n\n\n\n","category":"type"},{"location":"base/base/#Core.UndefRefError","page":"基本功能","title":"Core.UndefRefError","text":"UndefRefError()\n\nThe item or field is not defined for the given object.\n\nExamples\n\njulia> struct MyType\n a::Vector{Int}\n MyType() = new()\n end\n\njulia> A = MyType()\nMyType(#undef)\n\njulia> A.a\nERROR: UndefRefError: access to undefined reference\nStacktrace:\n[...]\n\n\n\n\n\n","category":"type"},{"location":"base/base/#Core.UndefVarError","page":"基本功能","title":"Core.UndefVarError","text":"UndefVarError(var::Symbol)\n\nA symbol in the current scope is not defined.\n\nExamples\n\njulia> a\nERROR: UndefVarError: a not defined\n\njulia> a = 1;\n\njulia> a\n1\n\n\n\n\n\n","category":"type"},{"location":"base/base/#Base.StringIndexError","page":"基本功能","title":"Base.StringIndexError","text":"StringIndexError(str, i)\n\nAn error occurred when trying to access str at index i that is not valid.\n\n\n\n\n\n","category":"type"},{"location":"base/base/#Core.InitError","page":"基本功能","title":"Core.InitError","text":"InitError(mod::Symbol, error)\n\nAn error occurred when running a module's __init__ function. The actual error thrown is available in the .error field.\n\n\n\n\n\n","category":"type"},{"location":"base/base/#Base.retry","page":"基本功能","title":"Base.retry","text":"retry(f; delays=ExponentialBackOff(), check=nothing) -> Function\n\nReturn an anonymous function that calls function f. If an exception arises, f is repeatedly called again, each time check returns true, after waiting the number of seconds specified in delays. check should input delays's current state and the Exception.\n\ncompat: Julia 1.2\nBefore Julia 1.2 this signature was restricted to f::Function.\n\nExamples\n\nretry(f, delays=fill(5.0, 3))\nretry(f, delays=rand(5:10, 2))\nretry(f, delays=Base.ExponentialBackOff(n=3, first_delay=5, max_delay=1000))\nretry(http_get, check=(s,e)->e.status == \"503\")(url)\nretry(read, check=(s,e)->isa(e, IOError))(io, 128; all=false)\n\n\n\n\n\n","category":"function"},{"location":"base/base/#Base.ExponentialBackOff","page":"基本功能","title":"Base.ExponentialBackOff","text":"ExponentialBackOff(; n=1, first_delay=0.05, max_delay=10.0, factor=5.0, jitter=0.1)\n\nA Float64 iterator of length n whose elements exponentially increase at a rate in the interval factor * (1 ± jitter). The first element is first_delay and all elements are clamped to max_delay.\n\n\n\n\n\n","category":"type"},{"location":"base/base/#Events","page":"基本功能","title":"Events","text":"","category":"section"},{"location":"base/base/","page":"基本功能","title":"基本功能","text":"Base.Timer(::Function, ::Real)\nBase.Timer\nBase.AsyncCondition\nBase.AsyncCondition(::Function)","category":"page"},{"location":"base/base/#Base.Timer-Tuple{Function, Real}","page":"基本功能","title":"Base.Timer","text":"Timer(callback::Function, delay; interval = 0)\n\nCreate a timer that runs the function callback at each timer expiration.\n\nWaiting tasks are woken and the function callback is called after an initial delay of delay seconds, and then repeating with the given interval in seconds. If interval is equal to 0, the callback is only run once. The function callback is called with a single argument, the timer itself. Stop a timer by calling close. The cb may still be run one final time, if the timer has already expired.\n\nExamples\n\nHere the first number is printed after a delay of two seconds, then the following numbers are printed quickly.\n\njulia> begin\n i = 0\n cb(timer) = (global i += 1; println(i))\n t = Timer(cb, 2, interval=0.2)\n wait(t)\n sleep(0.5)\n close(t)\n end\n1\n2\n3\n\n\n\n\n\n","category":"method"},{"location":"base/base/#Base.Timer","page":"基本功能","title":"Base.Timer","text":"Timer(delay; interval = 0)\n\nCreate a timer that wakes up tasks waiting for it (by calling wait on the timer object).\n\nWaiting tasks are woken after an initial delay of at least delay seconds, and then repeating after at least interval seconds again elapse. If interval is equal to 0, the timer is only triggered once. When the timer is closed (by close) waiting tasks are woken with an error. Use isopen to check whether a timer is still active.\n\nnote: Note\ninterval is subject to accumulating time skew. If you need precise events at a particular absolute time, create a new timer at each expiration with the difference to the next time computed.\n\nnote: Note\nA Timer requires yield points to update its state. For instance, isopen(t::Timer) cannot be used to timeout a non-yielding while loop.\n\n\n\n\n\n","category":"type"},{"location":"base/base/#Base.AsyncCondition","page":"基本功能","title":"Base.AsyncCondition","text":"AsyncCondition()\n\nCreate a async condition that wakes up tasks waiting for it (by calling wait on the object) when notified from C by a call to uv_async_send. Waiting tasks are woken with an error when the object is closed (by close). Use isopen to check whether it is still active.\n\nThis provides an implicit acquire & release memory ordering between the sending and waiting threads.\n\n\n\n\n\n","category":"type"},{"location":"base/base/#Base.AsyncCondition-Tuple{Function}","page":"基本功能","title":"Base.AsyncCondition","text":"AsyncCondition(callback::Function)\n\nCreate a async condition that calls the given callback function. The callback is passed one argument, the async condition object itself.\n\n\n\n\n\n","category":"method"},{"location":"base/base/#Reflection","page":"基本功能","title":"Reflection","text":"","category":"section"},{"location":"base/base/","page":"基本功能","title":"基本功能","text":"Base.nameof(::Module)\nBase.parentmodule\nBase.pathof(::Module)\nBase.pkgdir(::Module)\nBase.moduleroot\n__module__\n__source__\nBase.@__MODULE__\nBase.@__FILE__\nBase.@__DIR__\nBase.@__LINE__\nBase.fullname\nBase.names\nCore.nfields\nBase.isconst\nBase.nameof(::Function)\nBase.functionloc(::Any, ::Any)\nBase.functionloc(::Method)\nBase.@locals","category":"page"},{"location":"base/base/#Base.nameof-Tuple{Module}","page":"基本功能","title":"Base.nameof","text":"nameof(m::Module) -> Symbol\n\nGet the name of a Module as a Symbol.\n\nExamples\n\njulia> nameof(Base.Broadcast)\n:Broadcast\n\n\n\n\n\n","category":"method"},{"location":"base/base/#Base.parentmodule","page":"基本功能","title":"Base.parentmodule","text":"parentmodule(m::Module) -> Module\n\nGet a module's enclosing Module. Main is its own parent.\n\nSee also: names, nameof, fullname, @__MODULE__.\n\nExamples\n\njulia> parentmodule(Main)\nMain\n\njulia> parentmodule(Base.Broadcast)\nBase\n\n\n\n\n\nparentmodule(t::DataType) -> Module\n\nDetermine the module containing the definition of a (potentially UnionAll-wrapped) DataType.\n\nExamples\n\njulia> module Foo\n struct Int end\n end\nFoo\n\njulia> parentmodule(Int)\nCore\n\njulia> parentmodule(Foo.Int)\nFoo\n\n\n\n\n\nparentmodule(f::Function) -> Module\n\nDetermine the module containing the (first) definition of a generic function.\n\n\n\n\n\nparentmodule(f::Function, types) -> Module\n\nDetermine the module containing a given definition of a generic function.\n\n\n\n\n\n","category":"function"},{"location":"base/base/#Base.pathof-Tuple{Module}","page":"基本功能","title":"Base.pathof","text":"pathof(m::Module)\n\nReturn the path of the m.jl file that was used to import module m, or nothing if m was not imported from a package.\n\nUse dirname to get the directory part and basename to get the file name part of the path.\n\n\n\n\n\n","category":"method"},{"location":"base/base/#Base.pkgdir-Tuple{Module}","page":"基本功能","title":"Base.pkgdir","text":"pkgdir(m::Module[, paths::String...])\n\nReturn the root directory of the package that imported module m, or nothing if m was not imported from a package. Optionally further path component strings can be provided to construct a path within the package root.\n\njulia> pkgdir(Foo)\n\"/path/to/Foo.jl\"\n\njulia> pkgdir(Foo, \"src\", \"file.jl\")\n\"/path/to/Foo.jl/src/file.jl\"\n\ncompat: Julia 1.7\nThe optional argument paths requires at least Julia 1.7.\n\n\n\n\n\n","category":"method"},{"location":"base/base/#Base.moduleroot","page":"基本功能","title":"Base.moduleroot","text":"moduleroot(m::Module) -> Module\n\nFind the root module of a given module. This is the first module in the chain of parent modules of m which is either a registered root module or which is its own parent module.\n\n\n\n\n\n","category":"function"},{"location":"base/base/#__module__","page":"基本功能","title":"__module__","text":"__module__\n\nThe argument __module__ is only visible inside the macro, and it provides information (in the form of a Module object) about the expansion context of the macro invocation. See the manual section on Macro invocation for more information.\n\n\n\n\n\n","category":"keyword"},{"location":"base/base/#__source__","page":"基本功能","title":"__source__","text":"__source__\n\nThe argument __source__ is only visible inside the macro, and it provides information (in the form of a LineNumberNode object) about the parser location of the @ sign from the macro invocation. See the manual section on Macro invocation for more information.\n\n\n\n\n\n","category":"keyword"},{"location":"base/base/#Base.@__MODULE__","page":"基本功能","title":"Base.@__MODULE__","text":"@__MODULE__ -> Module\n\nGet the Module of the toplevel eval, which is the Module code is currently being read from.\n\n\n\n\n\n","category":"macro"},{"location":"base/base/#Base.@__FILE__","page":"基本功能","title":"Base.@__FILE__","text":"@__FILE__ -> AbstractString\n\nExpand to a string with the path to the file containing the macrocall, or an empty string if evaluated by julia -e . Return nothing if the macro was missing parser source information. Alternatively see PROGRAM_FILE.\n\n\n\n\n\n","category":"macro"},{"location":"base/base/#Base.@__DIR__","page":"基本功能","title":"Base.@__DIR__","text":"@__DIR__ -> AbstractString\n\nExpand to a string with the absolute path to the directory of the file containing the macrocall. Return the current working directory if run from a REPL or if evaluated by julia -e .\n\n\n\n\n\n","category":"macro"},{"location":"base/base/#Base.@__LINE__","page":"基本功能","title":"Base.@__LINE__","text":"@__LINE__ -> Int\n\nExpand to the line number of the location of the macrocall. Return 0 if the line number could not be determined.\n\n\n\n\n\n","category":"macro"},{"location":"base/base/#Base.fullname","page":"基本功能","title":"Base.fullname","text":"fullname(m::Module)\n\nGet the fully-qualified name of a module as a tuple of symbols. For example,\n\nExamples\n\njulia> fullname(Base.Iterators)\n(:Base, :Iterators)\n\njulia> fullname(Main)\n(:Main,)\n\n\n\n\n\n","category":"function"},{"location":"base/base/#Base.names","page":"基本功能","title":"Base.names","text":"names(x::Module; all::Bool = false, imported::Bool = false)\n\nGet an array of the names exported by a Module, excluding deprecated names. If all is true, then the list also includes non-exported names defined in the module, deprecated names, and compiler-generated names. If imported is true, then names explicitly imported from other modules are also included.\n\nAs a special case, all names defined in Main are considered \"exported\", since it is not idiomatic to explicitly export names from Main.\n\nSee also: @locals, @__MODULE__.\n\n\n\n\n\n","category":"function"},{"location":"base/base/#Core.nfields","page":"基本功能","title":"Core.nfields","text":"nfields(x) -> Int\n\nGet the number of fields in the given object.\n\nExamples\n\njulia> a = 1//2;\n\njulia> nfields(a)\n2\n\njulia> b = 1\n1\n\njulia> nfields(b)\n0\n\njulia> ex = ErrorException(\"I've done a bad thing\");\n\njulia> nfields(ex)\n1\n\nIn these examples, a is a Rational, which has two fields. b is an Int, which is a primitive bitstype with no fields at all. ex is an ErrorException, which has one field.\n\n\n\n\n\n","category":"function"},{"location":"base/base/#Base.isconst","page":"基本功能","title":"Base.isconst","text":"isconst(m::Module, s::Symbol) -> Bool\n\nDetermine whether a global is declared const in a given module m.\n\n\n\n\n\nisconst(t::DataType, s::Union{Int,Symbol}) -> Bool\n\nDetermine whether a field s is declared const in a given type t.\n\n\n\n\n\n","category":"function"},{"location":"base/base/#Base.nameof-Tuple{Function}","page":"基本功能","title":"Base.nameof","text":"nameof(f::Function) -> Symbol\n\nGet the name of a generic Function as a symbol. For anonymous functions, this is a compiler-generated name. For explicitly-declared subtypes of Function, it is the name of the function's type.\n\n\n\n\n\n","category":"method"},{"location":"base/base/#Base.functionloc-Tuple{Any, Any}","page":"基本功能","title":"Base.functionloc","text":"functionloc(f::Function, types)\n\nReturns a tuple (filename,line) giving the location of a generic Function definition.\n\n\n\n\n\n","category":"method"},{"location":"base/base/#Base.functionloc-Tuple{Method}","page":"基本功能","title":"Base.functionloc","text":"functionloc(m::Method)\n\nReturns a tuple (filename,line) giving the location of a Method definition.\n\n\n\n\n\n","category":"method"},{"location":"base/base/#Base.@locals","page":"基本功能","title":"Base.@locals","text":"@locals()\n\nConstruct a dictionary of the names (as symbols) and values of all local variables defined as of the call site.\n\ncompat: Julia 1.1\nThis macro requires at least Julia 1.1.\n\nExamples\n\njulia> let x = 1, y = 2\n Base.@locals\n end\nDict{Symbol, Any} with 2 entries:\n :y => 2\n :x => 1\n\njulia> function f(x)\n local y\n show(Base.@locals); println()\n for i = 1:1\n show(Base.@locals); println()\n end\n y = 2\n show(Base.@locals); println()\n nothing\n end;\n\njulia> f(42)\nDict{Symbol, Any}(:x => 42)\nDict{Symbol, Any}(:i => 1, :x => 42)\nDict{Symbol, Any}(:y => 2, :x => 42)\n\n\n\n\n\n","category":"macro"},{"location":"base/base/#Internals","page":"基本功能","title":"Internals","text":"","category":"section"},{"location":"base/base/","page":"基本功能","title":"基本功能","text":"Base.GC.gc\nBase.GC.enable\nBase.GC.@preserve\nBase.GC.safepoint\nMeta.lower\nMeta.@lower\nMeta.parse(::AbstractString, ::Int)\nMeta.parse(::AbstractString)\nMeta.ParseError\nCore.QuoteNode\nBase.macroexpand\nBase.@macroexpand\nBase.@macroexpand1\nBase.code_lowered\nBase.code_typed\nBase.precompile","category":"page"},{"location":"base/base/#Base.GC.gc","page":"基本功能","title":"Base.GC.gc","text":"GC.gc([full=true])\n\nPerform garbage collection. The argument full determines the kind of collection: A full collection (default) sweeps all objects, which makes the next GC scan much slower, while an incremental collection may only sweep so-called young objects.\n\nwarning: Warning\nExcessive use will likely lead to poor performance.\n\n\n\n\n\n","category":"function"},{"location":"base/base/#Base.GC.enable","page":"基本功能","title":"Base.GC.enable","text":"GC.enable(on::Bool)\n\nControl whether garbage collection is enabled using a boolean argument (true for enabled, false for disabled). Return previous GC state.\n\nwarning: Warning\nDisabling garbage collection should be used only with caution, as it can cause memory use to grow without bound.\n\n\n\n\n\n","category":"function"},{"location":"base/base/#Base.GC.@preserve","page":"基本功能","title":"Base.GC.@preserve","text":"GC.@preserve x1 x2 ... xn expr\n\nMark the objects x1, x2, ... as being in use during the evaluation of the expression expr. This is only required in unsafe code where expr implicitly uses memory or other resources owned by one of the xs.\n\nImplicit use of x covers any indirect use of resources logically owned by x which the compiler cannot see. Some examples:\n\nAccessing memory of an object directly via a Ptr\nPassing a pointer to x to ccall\nUsing resources of x which would be cleaned up in the finalizer.\n\n@preserve should generally not have any performance impact in typical use cases where it briefly extends object lifetime. In implementation, @preserve has effects such as protecting dynamically allocated objects from garbage collection.\n\nExamples\n\nWhen loading from a pointer with unsafe_load, the underlying object is implicitly used, for example x is implicitly used by unsafe_load(p) in the following:\n\njulia> let\n x = Ref{Int}(101)\n p = Base.unsafe_convert(Ptr{Int}, x)\n GC.@preserve x unsafe_load(p)\n end\n101\n\nWhen passing pointers to ccall, the pointed-to object is implicitly used and should be preserved. (Note however that you should normally just pass x directly to ccall which counts as an explicit use.)\n\njulia> let\n x = \"Hello\"\n p = pointer(x)\n Int(GC.@preserve x @ccall strlen(p::Cstring)::Csize_t)\n # Preferred alternative\n Int(@ccall strlen(x::Cstring)::Csize_t)\n end\n5\n\n\n\n\n\n","category":"macro"},{"location":"base/base/#Base.GC.safepoint","page":"基本功能","title":"Base.GC.safepoint","text":"GC.safepoint()\n\nInserts a point in the program where garbage collection may run. This can be useful in rare cases in multi-threaded programs where some threads are allocating memory (and hence may need to run GC) but other threads are doing only simple operations (no allocation, task switches, or I/O). Calling this function periodically in non-allocating threads allows garbage collection to run.\n\ncompat: Julia 1.4\nThis function is available as of Julia 1.4.\n\n\n\n\n\n","category":"function"},{"location":"base/base/#Base.Meta.lower","page":"基本功能","title":"Base.Meta.lower","text":"lower(m, x)\n\nTakes the expression x and returns an equivalent expression in lowered form for executing in module m. See also code_lowered.\n\n\n\n\n\n","category":"function"},{"location":"base/base/#Base.Meta.@lower","page":"基本功能","title":"Base.Meta.@lower","text":"@lower [m] x\n\nReturn lowered form of the expression x in module m. By default m is the module in which the macro is called. See also lower.\n\n\n\n\n\n","category":"macro"},{"location":"base/base/#Base.Meta.parse-Tuple{AbstractString, Int64}","page":"基本功能","title":"Base.Meta.parse","text":"parse(str, start; greedy=true, raise=true, depwarn=true)\n\nParse the expression string and return an expression (which could later be passed to eval for execution). start is the code unit index into str of the first character to start parsing at (as with all string indexing, these are not character indices). If greedy is true (default), parse will try to consume as much input as it can; otherwise, it will stop as soon as it has parsed a valid expression. Incomplete but otherwise syntactically valid expressions will return Expr(:incomplete, \"(error message)\"). If raise is true (default), syntax errors other than incomplete expressions will raise an error. If raise is false, parse will return an expression that will raise an error upon evaluation. If depwarn is false, deprecation warnings will be suppressed.\n\njulia> Meta.parse(\"(α, β) = 3, 5\", 1) # start of string\n(:((α, β) = (3, 5)), 16)\n\njulia> Meta.parse(\"(α, β) = 3, 5\", 1, greedy=false)\n(:((α, β)), 9)\n\njulia> Meta.parse(\"(α, β) = 3, 5\", 16) # end of string\n(nothing, 16)\n\njulia> Meta.parse(\"(α, β) = 3, 5\", 11) # index of 3\n(:((3, 5)), 16)\n\njulia> Meta.parse(\"(α, β) = 3, 5\", 11, greedy=false)\n(3, 13)\n\n\n\n\n\n","category":"method"},{"location":"base/base/#Base.Meta.parse-Tuple{AbstractString}","page":"基本功能","title":"Base.Meta.parse","text":"parse(str; raise=true, depwarn=true)\n\nParse the expression string greedily, returning a single expression. An error is thrown if there are additional characters after the first expression. If raise is true (default), syntax errors will raise an error; otherwise, parse will return an expression that will raise an error upon evaluation. If depwarn is false, deprecation warnings will be suppressed.\n\njulia> Meta.parse(\"x = 3\")\n:(x = 3)\n\njulia> Meta.parse(\"x = \")\n:($(Expr(:incomplete, \"incomplete: premature end of input\")))\n\njulia> Meta.parse(\"1.0.2\")\nERROR: Base.Meta.ParseError(\"invalid numeric constant \\\"1.0.\\\"\")\nStacktrace:\n[...]\n\njulia> Meta.parse(\"1.0.2\"; raise = false)\n:($(Expr(:error, \"invalid numeric constant \\\"1.0.\\\"\")))\n\n\n\n\n\n","category":"method"},{"location":"base/base/#Base.Meta.ParseError","page":"基本功能","title":"Base.Meta.ParseError","text":"ParseError(msg)\n\nThe expression passed to the parse function could not be interpreted as a valid Julia expression.\n\n\n\n\n\n","category":"type"},{"location":"base/base/#Core.QuoteNode","page":"基本功能","title":"Core.QuoteNode","text":"QuoteNode\n\nA quoted piece of code, that does not support interpolation. See the manual section about QuoteNodes for details.\n\n\n\n\n\n","category":"type"},{"location":"base/base/#Base.macroexpand","page":"基本功能","title":"Base.macroexpand","text":"macroexpand(m::Module, x; recursive=true)\n\nTake the expression x and return an equivalent expression with all macros removed (expanded) for executing in module m. The recursive keyword controls whether deeper levels of nested macros are also expanded. This is demonstrated in the example below:\n\njulia> module M\n macro m1()\n 42\n end\n macro m2()\n :(@m1())\n end\n end\nM\n\njulia> macroexpand(M, :(@m2()), recursive=true)\n42\n\njulia> macroexpand(M, :(@m2()), recursive=false)\n:(#= REPL[16]:6 =# M.@m1)\n\n\n\n\n\n","category":"function"},{"location":"base/base/#Base.@macroexpand","page":"基本功能","title":"Base.@macroexpand","text":"@macroexpand\n\nReturn equivalent expression with all macros removed (expanded).\n\nThere are differences between @macroexpand and macroexpand.\n\nWhile macroexpand takes a keyword argument recursive, @macroexpand is always recursive. For a non recursive macro version, see @macroexpand1.\nWhile macroexpand has an explicit module argument, @macroexpand always expands with respect to the module in which it is called.\n\nThis is best seen in the following example:\n\njulia> module M\n macro m()\n 1\n end\n function f()\n (@macroexpand(@m),\n macroexpand(M, :(@m)),\n macroexpand(Main, :(@m))\n )\n end\n end\nM\n\njulia> macro m()\n 2\n end\n@m (macro with 1 method)\n\njulia> M.f()\n(1, 1, 2)\n\nWith @macroexpand the expression expands where @macroexpand appears in the code (module M in the example). With macroexpand the expression expands in the module given as the first argument.\n\n\n\n\n\n","category":"macro"},{"location":"base/base/#Base.@macroexpand1","page":"基本功能","title":"Base.@macroexpand1","text":"@macroexpand1\n\nNon recursive version of @macroexpand.\n\n\n\n\n\n","category":"macro"},{"location":"base/base/#Base.code_lowered","page":"基本功能","title":"Base.code_lowered","text":"code_lowered(f, types; generated=true, debuginfo=:default)\n\nReturn an array of the lowered forms (IR) for the methods matching the given generic function and type signature.\n\nIf generated is false, the returned CodeInfo instances will correspond to fallback implementations. An error is thrown if no fallback implementation exists. If generated is true, these CodeInfo instances will correspond to the method bodies yielded by expanding the generators.\n\nThe keyword debuginfo controls the amount of code metadata present in the output.\n\nNote that an error will be thrown if types are not leaf types when generated is true and any of the corresponding methods are an @generated method.\n\n\n\n\n\n","category":"function"},{"location":"base/base/#Base.code_typed","page":"基本功能","title":"Base.code_typed","text":"code_typed(f, types; kw...)\n\nReturns an array of type-inferred lowered form (IR) for the methods matching the given generic function and type signature.\n\nKeyword Arguments\n\noptimize=true: controls whether additional optimizations, such as inlining, are also applied.\ndebuginfo=:default: controls the amount of code metadata present in the output,\n\npossible options are :source or :none.\n\nInternal Keyword Arguments\n\nThis section should be considered internal, and is only for who understands Julia compiler internals.\n\nworld=Base.get_world_counter(): optional, controls the world age to use when looking up methods,\n\nuse current world age if not specified.\n\ninterp=Core.Compiler.NativeInterpreter(world): optional, controls the interpreter to use,\n\nuse the native interpreter Julia uses if not specified.\n\nExample\n\nOne can put the argument types in a tuple to get the corresponding code_typed.\n\njulia> code_typed(+, (Float64, Float64))\n1-element Vector{Any}:\n CodeInfo(\n1 ─ %1 = Base.add_float(x, y)::Float64\n└── return %1\n) => Float64\n\n\n\n\n\n","category":"function"},{"location":"base/base/#Base.precompile","page":"基本功能","title":"Base.precompile","text":"precompile(f, args::Tuple{Vararg{Any}})\n\nCompile the given function f for the argument tuple (of types) args, but do not execute it.\n\n\n\n\n\n","category":"function"},{"location":"base/base/#Meta","page":"基本功能","title":"Meta","text":"","category":"section"},{"location":"base/base/","page":"基本功能","title":"基本功能","text":"Meta.quot\nMeta.isexpr\nMeta.isidentifier\nMeta.isoperator\nMeta.isunaryoperator\nMeta.isbinaryoperator\nMeta.show_sexpr","category":"page"},{"location":"base/base/#Base.Meta.quot","page":"基本功能","title":"Base.Meta.quot","text":"Meta.quot(ex)::Expr\n\nQuote expression ex to produce an expression with head quote. This can for instance be used to represent objects of type Expr in the AST. See also the manual section about QuoteNode.\n\nExamples\n\njulia> eval(Meta.quot(:x))\n:x\n\njulia> dump(Meta.quot(:x))\nExpr\n head: Symbol quote\n args: Array{Any}((1,))\n 1: Symbol x\n\njulia> eval(Meta.quot(:(1+2)))\n:(1 + 2)\n\n\n\n\n\n","category":"function"},{"location":"base/base/#Base.isexpr","page":"基本功能","title":"Base.isexpr","text":"Meta.isexpr(ex, head[, n])::Bool\n\nReturn true if ex is an Expr with the given type head and optionally that the argument list is of length n. head may be a Symbol or collection of Symbols. For example, to check that a macro was passed a function call expression, you might use isexpr(ex, :call).\n\nExamples\n\njulia> ex = :(f(x))\n:(f(x))\n\njulia> Meta.isexpr(ex, :block)\nfalse\n\njulia> Meta.isexpr(ex, :call)\ntrue\n\njulia> Meta.isexpr(ex, [:block, :call]) # multiple possible heads\ntrue\n\njulia> Meta.isexpr(ex, :call, 1)\nfalse\n\njulia> Meta.isexpr(ex, :call, 2)\ntrue\n\n\n\n\n\n","category":"function"},{"location":"base/base/#Base.isidentifier","page":"基本功能","title":"Base.isidentifier","text":" isidentifier(s) -> Bool\n\nReturn whether the symbol or string s contains characters that are parsed as a valid ordinary identifier (not a binary/unary operator) in Julia code; see also Base.isoperator.\n\nInternally Julia allows any sequence of characters in a Symbol (except \\0s), and macros automatically use variable names containing # in order to avoid naming collision with the surrounding code. In order for the parser to recognize a variable, it uses a limited set of characters (greatly extended by Unicode). isidentifier() makes it possible to query the parser directly whether a symbol contains valid characters.\n\nExamples\n\njulia> Meta.isidentifier(:x), Meta.isidentifier(\"1x\")\n(true, false)\n\n\n\n\n\n","category":"function"},{"location":"base/base/#Base.isoperator","page":"基本功能","title":"Base.isoperator","text":"isoperator(s::Symbol)\n\nReturn true if the symbol can be used as an operator, false otherwise.\n\nExamples\n\njulia> Meta.isoperator(:+), Meta.isoperator(:f)\n(true, false)\n\n\n\n\n\n","category":"function"},{"location":"base/base/#Base.isunaryoperator","page":"基本功能","title":"Base.isunaryoperator","text":"isunaryoperator(s::Symbol)\n\nReturn true if the symbol can be used as a unary (prefix) operator, false otherwise.\n\nExamples\n\njulia> Meta.isunaryoperator(:-), Meta.isunaryoperator(:√), Meta.isunaryoperator(:f)\n(true, true, false)\n\n\n\n\n\n","category":"function"},{"location":"base/base/#Base.isbinaryoperator","page":"基本功能","title":"Base.isbinaryoperator","text":"isbinaryoperator(s::Symbol)\n\nReturn true if the symbol can be used as a binary (infix) operator, false otherwise.\n\nExamples\n\njulia> Meta.isbinaryoperator(:-), Meta.isbinaryoperator(:√), Meta.isbinaryoperator(:f)\n(true, false, false)\n\n\n\n\n\n","category":"function"},{"location":"base/base/#Base.Meta.show_sexpr","page":"基本功能","title":"Base.Meta.show_sexpr","text":"Meta.show_sexpr([io::IO,], ex)\n\nShow expression ex as a lisp style S-expression.\n\nExamples\n\njulia> Meta.show_sexpr(:(f(x, g(y,z))))\n(:call, :f, :x, (:call, :g, :y, :z))\n\n\n\n\n\n","category":"function"},{"location":"manual/unicode-input/#Unicode-Input","page":"Unicode 输入表","title":"Unicode 输入表","text":"","category":"section"},{"location":"manual/unicode-input/","page":"Unicode 输入表","title":"Unicode 输入表","text":"在 Julia REPL 或其它编辑器中,可以像输入 LaTeX 符号一样,用 tab 补全下表列出的 Unicode 字符。在 REPL 中,可以先按 ? 进入帮助模式,然后将 Unicode 字符复制粘贴进去,一般在文档开头就会写输入方式。","category":"page"},{"location":"manual/unicode-input/","page":"Unicode 输入表","title":"Unicode 输入表","text":"warning: Warning\n此表第二列可能会缺失一些字符,对某些字符的显示效果也可能会与在 Julia REPL 中不一致。如果发生了这种状况,强烈建议用户检查一下浏览器或 REPL 的字体设置,目前已知很多字体都有显示问题。","category":"page"},{"location":"manual/unicode-input/","page":"Unicode 输入表","title":"Unicode 输入表","text":"#\n# Generate a table containing all LaTeX and Emoji tab completions available in the REPL.\n#\nimport REPL, Markdown\nconst NBSP = '\\u00A0'\n\nfunction tab_completions(symbols...)\n completions = Dict{String, Vector{String}}()\n for each in symbols, (k, v) in each\n completions[v] = push!(get!(completions, v, String[]), k)\n end\n return completions\nend\n\nfunction unicode_data()\n file = normpath(Sys.BINDIR, \"..\", \"UnicodeData.txt\")\n names = Dict{UInt32, String}()\n open(file) do unidata\n for line in readlines(unidata)\n id, name, desc = split(line, \";\")[[1, 2, 11]]\n codepoint = parse(UInt32, \"0x$id\")\n names[codepoint] = titlecase(lowercase(\n name == \"\" ? desc : desc == \"\" ? name : \"$name / $desc\"))\n end\n end\n return names\nend\n\n# Surround combining characters with no-break spaces (i.e '\\u00A0'). Follows the same format\n# for how unicode is displayed on the unicode.org website:\n# http://unicode.org/cldr/utility/character.jsp?a=0300\nfunction fix_combining_chars(char)\n cat = Base.Unicode.category_code(char)\n return cat == 6 || cat == 8 ? \"$NBSP$char$NBSP\" : \"$char\"\nend\n\n\nfunction table_entries(completions, unicode_dict)\n entries = [[\n \"Code point(s)\", \"Character(s)\",\n \"Tab completion sequence(s)\", \"Unicode name(s)\"\n ]]\n for (chars, inputs) in sort!(collect(completions), by = first)\n code_points, unicode_names, characters = String[], String[], String[]\n for char in chars\n push!(code_points, \"U+$(uppercase(string(UInt32(char), base = 16, pad = 5)))\")\n push!(unicode_names, get(unicode_dict, UInt32(char), \"(No Unicode name)\"))\n push!(characters, isempty(characters) ? fix_combining_chars(char) : \"$char\")\n end\n push!(entries, [\n join(code_points, \" + \"), join(characters),\n join(inputs, \", \"), join(unicode_names, \" + \")\n ])\n end\n return Markdown.Table(entries, [:l, :l, :l, :l])\nend\n\ntable_entries(\n tab_completions(\n REPL.REPLCompletions.latex_symbols,\n REPL.REPLCompletions.emoji_symbols\n ),\n unicode_data()\n)","category":"page"},{"location":"manual/integers-and-floating-point-numbers/#整数和浮点数","page":"整数和浮点数","title":"整数和浮点数","text":"","category":"section"},{"location":"manual/integers-and-floating-point-numbers/","page":"整数和浮点数","title":"整数和浮点数","text":"整数和浮点值是算术和计算的基础。这些数值的内置表示被称作原始数值类型(numeric primitive),且整数和浮点数在代码中作为立即数时称作数值字面量(numeric literal)。例如,1 是个整型字面量,1.0 是个浮点型字面量,它们在内存中作为对象的二进制表示就是原始数值类型。","category":"page"},{"location":"manual/integers-and-floating-point-numbers/","page":"整数和浮点数","title":"整数和浮点数","text":"Julia 提供了很丰富的原始数值类型,并基于它们定义了一整套算术操作,还提供按位运算符以及一些标准数学函数。这些函数能够直接映射到现代计算机原生支持的数值类型及运算上,因此 Julia 可以充分地利用运算资源。此外,Julia 还为任意精度算术提供了软件支持,对于无法使用原生硬件表示的数值类型,Julia 也能够高效地处理其数值运算。当然,这需要相对的牺牲一些性能。","category":"page"},{"location":"manual/integers-and-floating-point-numbers/","page":"整数和浮点数","title":"整数和浮点数","text":"以下是 Julia 的原始数值类型:","category":"page"},{"location":"manual/integers-and-floating-point-numbers/","page":"整数和浮点数","title":"整数和浮点数","text":"整数类型:","category":"page"},{"location":"manual/integers-and-floating-point-numbers/","page":"整数和浮点数","title":"整数和浮点数","text":"类型 带符号? 比特数 最小值 最大值\nInt8 ✓ 8 -2^7 2^7 - 1\nUInt8 8 0 2^8 - 1\nInt16 ✓ 16 -2^15 2^15 - 1\nUInt16 16 0 2^16 - 1\nInt32 ✓ 32 -2^31 2^31 - 1\nUInt32 32 0 2^32 - 1\nInt64 ✓ 64 -2^63 2^63 - 1\nUInt64 64 0 2^64 - 1\nInt128 ✓ 128 -2^127 2^127 - 1\nUInt128 128 0 2^128 - 1\nBool N/A 8 false (0) true (1)","category":"page"},{"location":"manual/integers-and-floating-point-numbers/","page":"整数和浮点数","title":"整数和浮点数","text":"浮点类型:","category":"page"},{"location":"manual/integers-and-floating-point-numbers/","page":"整数和浮点数","title":"整数和浮点数","text":"类型 精度 比特数\nFloat16 半精度 16\nFloat32 单精度 32\nFloat64 双精度 64","category":"page"},{"location":"manual/integers-and-floating-point-numbers/","page":"整数和浮点数","title":"整数和浮点数","text":"此外,对复数和有理数的完整支持是在这些原始数据类型之上建立起来的。多亏了 Julia 有一个很灵活的、用户可扩展的类型提升系统,所有的数值类型都无需显式转换就可以很自然地相互进行运算。","category":"page"},{"location":"manual/integers-and-floating-point-numbers/#整数","page":"整数和浮点数","title":"整数","text":"","category":"section"},{"location":"manual/integers-and-floating-point-numbers/","page":"整数和浮点数","title":"整数和浮点数","text":"整数字面量以标准形式表示:","category":"page"},{"location":"manual/integers-and-floating-point-numbers/","page":"整数和浮点数","title":"整数和浮点数","text":"julia> 1\n1\n\njulia> 1234\n1234","category":"page"},{"location":"manual/integers-and-floating-point-numbers/","page":"整数和浮点数","title":"整数和浮点数","text":"整型字面量的默认类型取决于目标系统是 32 位还是 64 位架构:","category":"page"},{"location":"manual/integers-and-floating-point-numbers/","page":"整数和浮点数","title":"整数和浮点数","text":"# 32 位系统:\njulia> typeof(1)\nInt32\n\n# 64 位系统:\njulia> typeof(1)\nInt64","category":"page"},{"location":"manual/integers-and-floating-point-numbers/","page":"整数和浮点数","title":"整数和浮点数","text":"Julia 的内置变量 Sys.WORD_SIZE 表明了目标系统是 32 位还是 64 位架构:","category":"page"},{"location":"manual/integers-and-floating-point-numbers/","page":"整数和浮点数","title":"整数和浮点数","text":"# 32 位系统:\njulia> Sys.WORD_SIZE\n32\n\n# 64 位系统:\njulia> Sys.WORD_SIZE\n64","category":"page"},{"location":"manual/integers-and-floating-point-numbers/","page":"整数和浮点数","title":"整数和浮点数","text":"Julia 也定义了 Int 与 UInt 类型,它们分别是系统有符号和无符号的原生整数类型的别名。","category":"page"},{"location":"manual/integers-and-floating-point-numbers/","page":"整数和浮点数","title":"整数和浮点数","text":"# 32 位系统:\njulia> Int\nInt32\njulia> UInt\nUInt32\n\n# 64 位系统:\njulia> Int\nInt64\njulia> UInt\nUInt64","category":"page"},{"location":"manual/integers-and-floating-point-numbers/","page":"整数和浮点数","title":"整数和浮点数","text":"那些超过 32 位表示范围的大整数,如果能用 64 位表示,那么无论是什么系统都会用 64 位表示:","category":"page"},{"location":"manual/integers-and-floating-point-numbers/","page":"整数和浮点数","title":"整数和浮点数","text":"# 32 位或 64 位系统:\njulia> typeof(3000000000)\nInt64","category":"page"},{"location":"manual/integers-and-floating-point-numbers/","page":"整数和浮点数","title":"整数和浮点数","text":"无符号整数会通过 0x 前缀以及十六进制数 0-9a-f 来输入和输出(输入也可以使用大写的 A-F)。无符号值的位数取决于十六进制数字使用的数量:","category":"page"},{"location":"manual/integers-and-floating-point-numbers/","page":"整数和浮点数","title":"整数和浮点数","text":"julia> x = 0x1\n0x01\n\njulia> typeof(x)\nUInt8\n\njulia> x = 0x123\n0x0123\n\njulia> typeof(x)\nUInt16\n\njulia> x = 0x1234567\n0x01234567\n\njulia> typeof(x)\nUInt32\n\njulia> x = 0x123456789abcdef\n0x0123456789abcdef\n\njulia> typeof(x)\nUInt64\n\njulia> x = 0x11112222333344445555666677778888\n0x11112222333344445555666677778888\n\njulia> typeof(x)\nUInt128","category":"page"},{"location":"manual/integers-and-floating-point-numbers/","page":"整数和浮点数","title":"整数和浮点数","text":"采用这种做法是因为,当人们使用无符号十六进制字面量表示整数值的时候,通常会用它们来表示一个固定的数值字节序列,而不仅仅是个整数值。","category":"page"},{"location":"manual/integers-and-floating-point-numbers/","page":"整数和浮点数","title":"整数和浮点数","text":"二进制和八进制字面量也是支持的:","category":"page"},{"location":"manual/integers-and-floating-point-numbers/","page":"整数和浮点数","title":"整数和浮点数","text":"julia> x = 0b10\n0x02\n\njulia> typeof(x)\nUInt8\n\njulia> x = 0o010\n0x08\n\njulia> typeof(x)\nUInt8\n\njulia> x = 0x00000000000000001111222233334444\n0x00000000000000001111222233334444\n\njulia> typeof(x)\nUInt128","category":"page"},{"location":"manual/integers-and-floating-point-numbers/","page":"整数和浮点数","title":"整数和浮点数","text":"二进制、八进制和十六进制的字面量都会产生无符号的整数类型。当字面量不是开头全是 0 时,它们二进制数据项的位数会是最少需要的位数。当开头都是 0 时,位数取决于一个字面量需要的最少位数,这里的字面量指的是一个有着同样长度但开头都为 1 的数。这样用户就可以控制位数了。那些无法使用 UInt128 类型存储下的值无法写成这样的字面量。","category":"page"},{"location":"manual/integers-and-floating-point-numbers/","page":"整数和浮点数","title":"整数和浮点数","text":"二进制、八进制和十六进制的字面量前面加一个负号 -,这样可以产生一个和原字面量有着同样位数而值为原数的补码的数(二补数):","category":"page"},{"location":"manual/integers-and-floating-point-numbers/","page":"整数和浮点数","title":"整数和浮点数","text":"julia> -0x2\n0xfe\n\njulia> -0x0002\n0xfffe","category":"page"},{"location":"manual/integers-and-floating-point-numbers/","page":"整数和浮点数","title":"整数和浮点数","text":"整型等原始数值类型的最小和最大可表示的值可用 typemin 和 typemax 函数得到:","category":"page"},{"location":"manual/integers-and-floating-point-numbers/","page":"整数和浮点数","title":"整数和浮点数","text":"julia> (typemin(Int32), typemax(Int32))\n(-2147483648, 2147483647)\n\njulia> for T in [Int8,Int16,Int32,Int64,Int128,UInt8,UInt16,UInt32,UInt64,UInt128]\n println(\"$(lpad(T,7)): [$(typemin(T)),$(typemax(T))]\")\n end\n Int8: [-128,127]\n Int16: [-32768,32767]\n Int32: [-2147483648,2147483647]\n Int64: [-9223372036854775808,9223372036854775807]\n Int128: [-170141183460469231731687303715884105728,170141183460469231731687303715884105727]\n UInt8: [0,255]\n UInt16: [0,65535]\n UInt32: [0,4294967295]\n UInt64: [0,18446744073709551615]\nUInt128: [0,340282366920938463463374607431768211455]","category":"page"},{"location":"manual/integers-and-floating-point-numbers/","page":"整数和浮点数","title":"整数和浮点数","text":"typemin 和 typemax 返回的值的类型总与所给参数的类型相同。(上面的表达式用了一些目前还没有介绍的功能,包括 for 循环、字符串和字符串插值,但这对于已有一些编程经验的用户应该是很容易理解的。)","category":"page"},{"location":"manual/integers-and-floating-point-numbers/#溢出行为","page":"整数和浮点数","title":"溢出行为","text":"","category":"section"},{"location":"manual/integers-and-floating-point-numbers/","page":"整数和浮点数","title":"整数和浮点数","text":"在 Julia 里,超出一个类型可表示的最大值会导致环绕 (wraparound) 行为:","category":"page"},{"location":"manual/integers-and-floating-point-numbers/","page":"整数和浮点数","title":"整数和浮点数","text":"julia> x = typemax(Int64)\n9223372036854775807\n\njulia> x + 1\n-9223372036854775808\n\njulia> x + 1 == typemin(Int64)\ntrue","category":"page"},{"location":"manual/integers-and-floating-point-numbers/","page":"整数和浮点数","title":"整数和浮点数","text":"因此,Julia 的整数算术实际上是模算数的一种形式,它反映了现代计算机实现底层算术的特点。在可能有溢出产生的程序中,对最值边界出现循环进行显式检查是必要的。否则,推荐使用任意精度算术中的 BigInt 类型作为替代。","category":"page"},{"location":"manual/integers-and-floating-point-numbers/","page":"整数和浮点数","title":"整数和浮点数","text":"下面是溢出行为的一个例子以及如何解决溢出:","category":"page"},{"location":"manual/integers-and-floating-point-numbers/","page":"整数和浮点数","title":"整数和浮点数","text":"julia> 10^19\n-8446744073709551616\n\njulia> big(10)^19\n10000000000000000000","category":"page"},{"location":"manual/integers-and-floating-point-numbers/#除法错误","page":"整数和浮点数","title":"除法错误","text":"","category":"section"},{"location":"manual/integers-and-floating-point-numbers/","page":"整数和浮点数","title":"整数和浮点数","text":"div 函数的整数除法有两种异常情况:除以零,以及使用 -1 去除最小的负数(typemin)。 这两种情况都会抛出一个 DivideError 错误。 rem 取余函数和 mod 取模函数在除零时抛出 DivideError 错误。","category":"page"},{"location":"manual/integers-and-floating-point-numbers/#浮点数","page":"整数和浮点数","title":"浮点数","text":"","category":"section"},{"location":"manual/integers-and-floating-point-numbers/","page":"整数和浮点数","title":"整数和浮点数","text":"浮点数字面量以标准格式表示,必要时可使用E-表示法。","category":"page"},{"location":"manual/integers-and-floating-point-numbers/","page":"整数和浮点数","title":"整数和浮点数","text":"julia> 1.0\n1.0\n\njulia> 1.\n1.0\n\njulia> 0.5\n0.5\n\njulia> .5\n0.5\n\njulia> -1.23\n-1.23\n\njulia> 1e10\n1.0e10\n\njulia> 2.5e-4\n0.00025","category":"page"},{"location":"manual/integers-and-floating-point-numbers/","page":"整数和浮点数","title":"整数和浮点数","text":"上面的结果都是 Float64 类型的值。使用 f 替代 e 可以得到 Float32 类型的字面量:","category":"page"},{"location":"manual/integers-and-floating-point-numbers/","page":"整数和浮点数","title":"整数和浮点数","text":"julia> x = 0.5f0\n0.5f0\n\njulia> typeof(x)\nFloat32\n\njulia> 2.5f-4\n0.00025f0","category":"page"},{"location":"manual/integers-and-floating-point-numbers/","page":"整数和浮点数","title":"整数和浮点数","text":"数值可以很容易地转换为 Float32 类型:","category":"page"},{"location":"manual/integers-and-floating-point-numbers/","page":"整数和浮点数","title":"整数和浮点数","text":"julia> x = Float32(-1.5)\n-1.5f0\n\njulia> typeof(x)\nFloat32","category":"page"},{"location":"manual/integers-and-floating-point-numbers/","page":"整数和浮点数","title":"整数和浮点数","text":"也存在十六进制的浮点数字面量,但只适用于 Float64 类型的值。一般使用 p 前缀及以 2 为底的指数来表示:","category":"page"},{"location":"manual/integers-and-floating-point-numbers/","page":"整数和浮点数","title":"整数和浮点数","text":"julia> 0x1p0\n1.0\n\njulia> 0x1.8p3\n12.0\n\njulia> x = 0x.4p-1\n0.125\n\njulia> typeof(x)\nFloat64","category":"page"},{"location":"manual/integers-and-floating-point-numbers/","page":"整数和浮点数","title":"整数和浮点数","text":"Julia 也支持半精度浮点数(Float16),但它们是使用 Float32 进行软件模拟实现的。","category":"page"},{"location":"manual/integers-and-floating-point-numbers/","page":"整数和浮点数","title":"整数和浮点数","text":"julia> sizeof(Float16(4.))\n2\n\njulia> 2*Float16(4.)\nFloat16(8.0)","category":"page"},{"location":"manual/integers-and-floating-point-numbers/","page":"整数和浮点数","title":"整数和浮点数","text":"下划线 _ 可用作数字分隔符:","category":"page"},{"location":"manual/integers-and-floating-point-numbers/","page":"整数和浮点数","title":"整数和浮点数","text":"julia> 10_000, 0.000_000_005, 0xdead_beef, 0b1011_0010\n(10000, 5.0e-9, 0xdeadbeef, 0xb2)","category":"page"},{"location":"manual/integers-and-floating-point-numbers/#浮点数中的零","page":"整数和浮点数","title":"浮点数中的零","text":"","category":"section"},{"location":"manual/integers-and-floating-point-numbers/","page":"整数和浮点数","title":"整数和浮点数","text":"浮点数有两种零,正零和负零。它们相互相等但有着不同的二进制表示,可以使用 bitstring 函数来查看:","category":"page"},{"location":"manual/integers-and-floating-point-numbers/","page":"整数和浮点数","title":"整数和浮点数","text":"julia> 0.0 == -0.0\ntrue\n\njulia> bitstring(0.0)\n\"0000000000000000000000000000000000000000000000000000000000000000\"\n\njulia> bitstring(-0.0)\n\"1000000000000000000000000000000000000000000000000000000000000000\"","category":"page"},{"location":"manual/integers-and-floating-point-numbers/#特殊的浮点值","page":"整数和浮点数","title":"特殊的浮点值","text":"","category":"section"},{"location":"manual/integers-and-floating-point-numbers/","page":"整数和浮点数","title":"整数和浮点数","text":"有三种特定的标准浮点值不和实数轴上任何一点对应:","category":"page"},{"location":"manual/integers-and-floating-point-numbers/","page":"整数和浮点数","title":"整数和浮点数","text":"Float16 Float32 Float64 名称 描述\nInf16 Inf32 Inf 正无穷 一个大于所有有限浮点数的数\n-Inf16 -Inf32 -Inf 负无穷 一个小于所有有限浮点数的数\nNaN16 NaN32 NaN 不是数(Not a Number) 一个不和任何浮点值(包括自己)相等(==)的值","category":"page"},{"location":"manual/integers-and-floating-point-numbers/","page":"整数和浮点数","title":"整数和浮点数","text":"对于这些非有限浮点值相互之间以及关于其它浮点值的顺序的更多讨论,请参见数值比较。根据 IEEE 754 标准,这些浮点值是某些算术运算的结果:","category":"page"},{"location":"manual/integers-and-floating-point-numbers/","page":"整数和浮点数","title":"整数和浮点数","text":"julia> 1/Inf\n0.0\n\njulia> 1/0\nInf\n\njulia> -5/0\n-Inf\n\njulia> 0.000001/0\nInf\n\njulia> 0/0\nNaN\n\njulia> 500 + Inf\nInf\n\njulia> 500 - Inf\n-Inf\n\njulia> Inf + Inf\nInf\n\njulia> Inf - Inf\nNaN\n\njulia> Inf * Inf\nInf\n\njulia> Inf / Inf\nNaN\n\njulia> 0 * Inf\nNaN\n\njulia> NaN == NaN\nfalse\n\njulia> NaN != NaN\ntrue\n\njulia> NaN < NaN\nfalse\n\njulia> NaN > NaN\nfalse","category":"page"},{"location":"manual/integers-and-floating-point-numbers/","page":"整数和浮点数","title":"整数和浮点数","text":"typemin 和 typemax 函数同样适用于浮点类型:","category":"page"},{"location":"manual/integers-and-floating-point-numbers/","page":"整数和浮点数","title":"整数和浮点数","text":"julia> (typemin(Float16),typemax(Float16))\n(-Inf16, Inf16)\n\njulia> (typemin(Float32),typemax(Float32))\n(-Inf32, Inf32)\n\njulia> (typemin(Float64),typemax(Float64))\n(-Inf, Inf)","category":"page"},{"location":"manual/integers-and-floating-point-numbers/#机器精度","page":"整数和浮点数","title":"机器精度","text":"","category":"section"},{"location":"manual/integers-and-floating-point-numbers/","page":"整数和浮点数","title":"整数和浮点数","text":"大多数实数都无法用浮点数准确地表示,因此有必要知道两个相邻可表示的浮点数间的距离。它通常被叫做机器精度。","category":"page"},{"location":"manual/integers-and-floating-point-numbers/","page":"整数和浮点数","title":"整数和浮点数","text":"Julia 提供了 eps 函数,它可以给出 1.0 与下一个 Julia 能表示的浮点数之间的差值:","category":"page"},{"location":"manual/integers-and-floating-point-numbers/","page":"整数和浮点数","title":"整数和浮点数","text":"julia> eps(Float32)\n1.1920929f-7\n\njulia> eps(Float64)\n2.220446049250313e-16\n\njulia> eps() # 与 eps(Float64) 相同\n2.220446049250313e-16","category":"page"},{"location":"manual/integers-and-floating-point-numbers/","page":"整数和浮点数","title":"整数和浮点数","text":"这些值分别是 Float32 中的 2.0^-23 和 Float64 中的 2.0^-52。eps 函数也可以接受一个浮点值作为参数,然后给出这个值与下一个可表示的浮点数值之间的绝对差。也就是说,eps(x) 产生一个和 x 类型相同的值,并且 x + eps(x) 恰好是比 x 更大的下一个可表示的浮点值:","category":"page"},{"location":"manual/integers-and-floating-point-numbers/","page":"整数和浮点数","title":"整数和浮点数","text":"julia> eps(1.0)\n2.220446049250313e-16\n\njulia> eps(1000.)\n1.1368683772161603e-13\n\njulia> eps(1e-27)\n1.793662034335766e-43\n\njulia> eps(0.0)\n5.0e-324","category":"page"},{"location":"manual/integers-and-floating-point-numbers/","page":"整数和浮点数","title":"整数和浮点数","text":"两个相邻可表示的浮点数之间的距离并不是常数,数值越小,间距越小,数值越大,间距越大。换句话说,可表示的浮点数在实数轴上的零点附近最稠密,并沿着远离零点的方向以指数型的速度变得越来越稀疏。根据定义,eps(1.0) 与 eps(Float64) 相等,因为 1.0 是个 64 位浮点值。","category":"page"},{"location":"manual/integers-and-floating-point-numbers/","page":"整数和浮点数","title":"整数和浮点数","text":"Julia 也提供了 nextfloat 和 prevfloat 两个函数分别返回基于参数的下一个更大或更小的可表示的浮点数:","category":"page"},{"location":"manual/integers-and-floating-point-numbers/","page":"整数和浮点数","title":"整数和浮点数","text":"julia> x = 1.25f0\n1.25f0\n\njulia> nextfloat(x)\n1.2500001f0\n\njulia> prevfloat(x)\n1.2499999f0\n\njulia> bitstring(prevfloat(x))\n\"00111111100111111111111111111111\"\n\njulia> bitstring(x)\n\"00111111101000000000000000000000\"\n\njulia> bitstring(nextfloat(x))\n\"00111111101000000000000000000001\"","category":"page"},{"location":"manual/integers-and-floating-point-numbers/","page":"整数和浮点数","title":"整数和浮点数","text":"这个例子体现了一般原则,即相邻可表示的浮点数也有着相邻的二进制整数表示。","category":"page"},{"location":"manual/integers-and-floating-point-numbers/#舍入模式","page":"整数和浮点数","title":"舍入模式","text":"","category":"section"},{"location":"manual/integers-and-floating-point-numbers/","page":"整数和浮点数","title":"整数和浮点数","text":"一个数如果没有精确的浮点表示,就必须被舍入到一个合适的可表示的值。然而,如果想的话,可以根据舍入模式改变舍入的方式,如 IEEE 754 标准 所述。 ","category":"page"},{"location":"manual/integers-and-floating-point-numbers/","page":"整数和浮点数","title":"整数和浮点数","text":"Julia 所使用的默认模式总是 RoundNearest,指舍入到最接近的可表示的值,这个被舍入的值会使用尽量少的有效位数。","category":"page"},{"location":"manual/integers-and-floating-point-numbers/#背景知识与参考文献","page":"整数和浮点数","title":"背景知识与参考文献","text":"","category":"section"},{"location":"manual/integers-and-floating-point-numbers/","page":"整数和浮点数","title":"整数和浮点数","text":"浮点算术带来了很多微妙之处,它们可能对于那些不熟悉底层实现细节的用户会是很出人意料的。然而,这些微妙之处在大部分科学计算的书籍中以及以下的参考资料中都有详细介绍:","category":"page"},{"location":"manual/integers-and-floating-point-numbers/","page":"整数和浮点数","title":"整数和浮点数","text":"浮点数算术的权威指南是 IEEE 754-2008 标准; 然而这篇标准在网上无法免费获得。\n关于浮点数是如何表示的,想要一个简单而明白的介绍的话,可以看 John D. Cook 的文章以及他关于从这种表示与实数理想的抽象化的差别中产生的一些问题的介绍\n同样推荐 Bruce Dawson 的一系列关于浮点数的博客文章。\n想要一个对浮点数和使用浮点数计算时产生的数值精度问题的极好的、有深度的讨论,可以参见 David Goldberg 的文章 What Every Computer Scientist Should Know About Floating-Point Arithmetic。\n更多延伸文档,包括浮点数的历史、基础理论、问题以及数值计算中很多其它主题的讨论,可以参见 William Kahan 的写作集。他以“浮点数之父”闻名。特别感兴趣的话可以看 An Interview with the Old Man of Floating-Point。","category":"page"},{"location":"manual/integers-and-floating-point-numbers/#Arbitrary-Precision-Arithmetic","page":"整数和浮点数","title":"任意精度算术","text":"","category":"section"},{"location":"manual/integers-and-floating-point-numbers/","page":"整数和浮点数","title":"整数和浮点数","text":"为了允许使用任意精度的整数与浮点数,Julia 分别包装了 GNU Multiple Precision Arithmetic Library (GMP) 以及 GNU MPFR Library。Julia 中的 BigInt 与 BigFloat 两种类型分别提供了任意精度的整数和浮点数。","category":"page"},{"location":"manual/integers-and-floating-point-numbers/","page":"整数和浮点数","title":"整数和浮点数","text":"可以使用构造函数从原始数据类型创建任意精度的整数和浮点数,或是使用字符串字面量 @big_str、parse函数从 AbstractString 类型来创建。当创建的整型字面量过大而无法被其它内置的整数类型表示时,也会被输入为 BigInt 类型。注意到 Julia 的Base中并没有无符号的任意精度的整型(BigInt在多数情况下已经够用了),(除十进制外)也可以使用十六进制、八进制、二进制的字面量。","category":"page"},{"location":"manual/integers-and-floating-point-numbers/","page":"整数和浮点数","title":"整数和浮点数","text":"得益于 Julia 的类型提升和类型转换机制,一旦被创建,它们就可以像其它数值类型一样参与算术运算。","category":"page"},{"location":"manual/integers-and-floating-point-numbers/","page":"整数和浮点数","title":"整数和浮点数","text":"julia> BigInt(typemax(Int64)) + 1\n9223372036854775808\n\njulia> big\"123456789012345678901234567890\" + 1\n123456789012345678901234567891\n\njulia> parse(BigInt, \"123456789012345678901234567890\") + 1\n123456789012345678901234567891\n\njulia> string(big\"2\"^200, base=16)\n\"100000000000000000000000000000000000000000000000000\"\n\njulia> 0x100000000000000000000000000000000-1 == typemax(UInt128)\ntrue\n\njulia> 0x000000000000000000000000000000000\n0\n\njulia> typeof(ans)\nBigInt\n\njulia> big\"1.23456789012345678901\"\n1.234567890123456789010000000000000000000000000000000000000000000000000000000004\n\njulia> parse(BigFloat, \"1.23456789012345678901\")\n1.234567890123456789010000000000000000000000000000000000000000000000000000000004\n\njulia> BigFloat(2.0^66) / 3\n2.459565876494606882133333333333333333333333333333333333333333333333333333333344e+19\n\njulia> factorial(BigInt(40))\n815915283247897734345611269596115894272000000000","category":"page"},{"location":"manual/integers-and-floating-point-numbers/","page":"整数和浮点数","title":"整数和浮点数","text":"然而,上面的原始类型与 BigInt/BigFloat 之间的类型提升并不是自动的,需要明确地指定:","category":"page"},{"location":"manual/integers-and-floating-point-numbers/","page":"整数和浮点数","title":"整数和浮点数","text":"julia> x = typemin(Int64)\n-9223372036854775808\n\njulia> x = x - 1\n9223372036854775807\n\njulia> typeof(x)\nInt64\n\njulia> y = BigInt(typemin(Int64))\n-9223372036854775808\n\njulia> y = y - 1\n-9223372036854775809\n\njulia> typeof(y)\nBigInt","category":"page"},{"location":"manual/integers-and-floating-point-numbers/","page":"整数和浮点数","title":"整数和浮点数","text":"BigFloat 的默认精度(有效数字的位数)和舍入模式可以通过调用 setprecision 和 setrounding 来全局地改变,所有之后的计算都会根据这些改变进行。还有一种方法,可以使用同样的函数以及 do-block 来只在运行一个特定代码块时改变精度和舍入模式:","category":"page"},{"location":"manual/integers-and-floating-point-numbers/","page":"整数和浮点数","title":"整数和浮点数","text":"julia> setrounding(BigFloat, RoundUp) do\n BigFloat(1) + parse(BigFloat, \"0.1\")\n end\n1.100000000000000000000000000000000000000000000000000000000000000000000000000003\n\njulia> setrounding(BigFloat, RoundDown) do\n BigFloat(1) + parse(BigFloat, \"0.1\")\n end\n1.099999999999999999999999999999999999999999999999999999999999999999999999999986\n\njulia> setprecision(40) do\n BigFloat(1) + parse(BigFloat, \"0.1\")\n end\n1.1000000000004","category":"page"},{"location":"manual/integers-and-floating-point-numbers/#man-numeric-literal-coefficients","page":"整数和浮点数","title":"数值字面量系数","text":"","category":"section"},{"location":"manual/integers-and-floating-point-numbers/","page":"整数和浮点数","title":"整数和浮点数","text":"为了让常见的数值公式和表达式更清楚,Julia 允许变量直接跟在一个数值字面量后,暗指乘法。这可以让写多项式变得很清楚:","category":"page"},{"location":"manual/integers-and-floating-point-numbers/","page":"整数和浮点数","title":"整数和浮点数","text":"julia> x = 3\n3\n\njulia> 2x^2 - 3x + 1\n10\n\njulia> 1.5x^2 - .5x + 1\n13.0","category":"page"},{"location":"manual/integers-and-floating-point-numbers/","page":"整数和浮点数","title":"整数和浮点数","text":"也会让写指数函数变得更加优雅:","category":"page"},{"location":"manual/integers-and-floating-point-numbers/","page":"整数和浮点数","title":"整数和浮点数","text":"julia> 2^2x\n64","category":"page"},{"location":"manual/integers-and-floating-point-numbers/","page":"整数和浮点数","title":"整数和浮点数","text":"数值字面量系数的优先级跟一元运算符相同,比如说取相反数。所以 2^3x 会被解析成 2^(3x),而 2x^3 会被解析成 2*(x^3)。","category":"page"},{"location":"manual/integers-and-floating-point-numbers/","page":"整数和浮点数","title":"整数和浮点数","text":"数值字面量也能作为被括号表达式的系数:","category":"page"},{"location":"manual/integers-and-floating-point-numbers/","page":"整数和浮点数","title":"整数和浮点数","text":"julia> 2(x-1)^2 - 3(x-1) + 1\n3","category":"page"},{"location":"manual/integers-and-floating-point-numbers/","page":"整数和浮点数","title":"整数和浮点数","text":"note: Note\n用于隐式乘法的数值字面量系数的优先级高于其它的二元运算符,例如乘法(*)和除法(/、\\ 以及 //)。这意味着,比如说,1 / 2im 等于 -0.5im 以及 6 // 2(2+1) 等于 1 // 1。","category":"page"},{"location":"manual/integers-and-floating-point-numbers/","page":"整数和浮点数","title":"整数和浮点数","text":"此外,括号表达式可以被用作变量的系数,暗指表达式与变量相乘:","category":"page"},{"location":"manual/integers-and-floating-point-numbers/","page":"整数和浮点数","title":"整数和浮点数","text":"julia> (x-1)x\n6","category":"page"},{"location":"manual/integers-and-floating-point-numbers/","page":"整数和浮点数","title":"整数和浮点数","text":"但是,无论是把两个括号表达式并列,还是把变量放在括号表达式之前,都不会被用作暗指乘法:","category":"page"},{"location":"manual/integers-and-floating-point-numbers/","page":"整数和浮点数","title":"整数和浮点数","text":"julia> (x-1)(x+1)\nERROR: MethodError: objects of type Int64 are not callable\n\njulia> x(x+1)\nERROR: MethodError: objects of type Int64 are not callable","category":"page"},{"location":"manual/integers-and-floating-point-numbers/","page":"整数和浮点数","title":"整数和浮点数","text":"这两种表达式都会被解释成函数调用:所有不是数值字面量的表达式,后面紧跟一个括号,就会被解释成使用括号内的值来调用函数(更多关于函数的信息请参见函数)。因此,在这两种情况中,都会因为左边的值并不是函数而产生错误。","category":"page"},{"location":"manual/integers-and-floating-point-numbers/","page":"整数和浮点数","title":"整数和浮点数","text":"上述的语法糖显著地降低了在写普通数学公式时的视觉干扰。注意数值字面量系数和后面用来相乘的标识符或括号表达式之间不能有空格。","category":"page"},{"location":"manual/integers-and-floating-point-numbers/#语法冲突","page":"整数和浮点数","title":"语法冲突","text":"","category":"section"},{"location":"manual/integers-and-floating-point-numbers/","page":"整数和浮点数","title":"整数和浮点数","text":"并列的字面量系数语法可能和两种数值字面量语法产生冲突:十六进制、八进制、二进制整数字面量以及浮点字面量的工程表示法。下面是几种会产生语法冲突的情况:","category":"page"},{"location":"manual/integers-and-floating-point-numbers/","page":"整数和浮点数","title":"整数和浮点数","text":"十六进制整数字面量 0xff 可能被解释成数值字面量 0 乘以变量 xff。类似的,像 0o777 或0b01001010 使用八进制或二进制表示法也会形成冲突。\n浮点字面量表达式 1e10 可以被解释成数值字面量 1 乘以变量 e10,与之等价的 E-表示法也存在类似的情况。\n32-bit 的浮点数字面量 1.5f22 被解释成数值字面量 1.5 乘以变量 f22。","category":"page"},{"location":"manual/integers-and-floating-point-numbers/","page":"整数和浮点数","title":"整数和浮点数","text":"在这些所有的情况中,歧义都优先解释为数值字面量:","category":"page"},{"location":"manual/integers-and-floating-point-numbers/","page":"整数和浮点数","title":"整数和浮点数","text":"0x /0o/0b 开头的表达式总是十六进制/八进制/二进制字面量。\n数值开头跟着 e 和 E 的表达式总是浮点字面量。\n数值开头跟着 f 的表达式总是 32-bit 浮点字面量。","category":"page"},{"location":"manual/integers-and-floating-point-numbers/","page":"整数和浮点数","title":"整数和浮点数","text":"由于历史原因 E 和 e 在数值字面量上是等价的,与之不同的是,F 只是一个行为和 f 不同的字母。因此开头为 F 的表达式将会被 解析为一个数值字面量乘以一个变量,例如 1.5F22等价于 1.5 * F22。","category":"page"},{"location":"manual/integers-and-floating-point-numbers/#零和一的字面量","page":"整数和浮点数","title":"零和一的字面量","text":"","category":"section"},{"location":"manual/integers-and-floating-point-numbers/","page":"整数和浮点数","title":"整数和浮点数","text":"Julia 提供了 0 和 1 的字面量函数,可以返回特定类型或所给变量的类型。","category":"page"},{"location":"manual/integers-and-floating-point-numbers/","page":"整数和浮点数","title":"整数和浮点数","text":"函数 描述\nzero(x) x 类型或变量 x 的类型的零字面量\none(x) x 类型或变量 x 的类型的一字面量","category":"page"},{"location":"manual/integers-and-floating-point-numbers/","page":"整数和浮点数","title":"整数和浮点数","text":"这些函数在数值比较中可以用来避免不必要的类型转换带来的开销。","category":"page"},{"location":"manual/integers-and-floating-point-numbers/","page":"整数和浮点数","title":"整数和浮点数","text":"例如:","category":"page"},{"location":"manual/integers-and-floating-point-numbers/","page":"整数和浮点数","title":"整数和浮点数","text":"julia> zero(Float32)\n0.0f0\n\njulia> zero(1.0)\n0.0\n\njulia> one(Int32)\n1\n\njulia> one(BigFloat)\n1.0","category":"page"},{"location":"stdlib/Statistics/#统计","page":"统计","title":"统计","text":"","category":"section"},{"location":"stdlib/Statistics/","page":"统计","title":"统计","text":"DocTestSetup = :(using Statistics)","category":"page"},{"location":"stdlib/Statistics/","page":"统计","title":"统计","text":"统计模块包含了基本的统计函数。","category":"page"},{"location":"stdlib/Statistics/","page":"统计","title":"统计","text":"Statistics.std\nStatistics.stdm\nStatistics.var\nStatistics.varm\nStatistics.cor\nStatistics.cov\nStatistics.mean!\nStatistics.mean\nStatistics.median!\nStatistics.median\nStatistics.middle\nStatistics.quantile!\nStatistics.quantile","category":"page"},{"location":"stdlib/Statistics/#Statistics.std","page":"统计","title":"Statistics.std","text":"std(itr; corrected::Bool=true, mean=nothing[, dims])\n\nCompute the sample standard deviation of collection itr.\n\nThe algorithm returns an estimator of the generative distribution's standard deviation under the assumption that each entry of itr is a sample drawn from the same unknown distribution, with the samples uncorrelated. For arrays, this computation is equivalent to calculating sqrt(sum((itr .- mean(itr)).^2) / (length(itr) - 1)). If corrected is true, then the sum is scaled with n-1, whereas the sum is scaled with n if corrected is false with n the number of elements in itr.\n\nIf itr is an AbstractArray, dims can be provided to compute the standard deviation over dimensions, and means may contain means for each dimension of itr.\n\nA pre-computed mean may be provided. When dims is specified, mean must be an array with the same shape as mean(itr, dims=dims) (additional trailing singleton dimensions are allowed).\n\nnote: Note\nIf array contains NaN or missing values, the result is also NaN or missing (missing takes precedence if array contains both). Use the skipmissing function to omit missing entries and compute the standard deviation of non-missing values.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/Statistics/#Statistics.stdm","page":"统计","title":"Statistics.stdm","text":"stdm(itr, mean; corrected::Bool=true[, dims])\n\nCompute the sample standard deviation of collection itr, with known mean(s) mean.\n\nThe algorithm returns an estimator of the generative distribution's standard deviation under the assumption that each entry of itr is a sample drawn from the same unknown distribution, with the samples uncorrelated. For arrays, this computation is equivalent to calculating sqrt(sum((itr .- mean(itr)).^2) / (length(itr) - 1)). If corrected is true, then the sum is scaled with n-1, whereas the sum is scaled with n if corrected is false with n the number of elements in itr.\n\nIf itr is an AbstractArray, dims can be provided to compute the standard deviation over dimensions. In that case, mean must be an array with the same shape as mean(itr, dims=dims) (additional trailing singleton dimensions are allowed).\n\nnote: Note\nIf array contains NaN or missing values, the result is also NaN or missing (missing takes precedence if array contains both). Use the skipmissing function to omit missing entries and compute the standard deviation of non-missing values.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/Statistics/#Statistics.var","page":"统计","title":"Statistics.var","text":"var(itr; corrected::Bool=true, mean=nothing[, dims])\n\nCompute the sample variance of collection itr.\n\nThe algorithm returns an estimator of the generative distribution's variance under the assumption that each entry of itr is a sample drawn from the same unknown distribution, with the samples uncorrelated. For arrays, this computation is equivalent to calculating sum((itr .- mean(itr)).^2) / (length(itr) - 1)). If corrected is true, then the sum is scaled with n-1, whereas the sum is scaled with n if corrected is false where n is the number of elements in itr.\n\nIf itr is an AbstractArray, dims can be provided to compute the variance over dimensions.\n\nA pre-computed mean may be provided. When dims is specified, mean must be an array with the same shape as mean(itr, dims=dims) (additional trailing singleton dimensions are allowed).\n\nnote: Note\nIf array contains NaN or missing values, the result is also NaN or missing (missing takes precedence if array contains both). Use the skipmissing function to omit missing entries and compute the variance of non-missing values.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/Statistics/#Statistics.varm","page":"统计","title":"Statistics.varm","text":"varm(itr, mean; dims, corrected::Bool=true)\n\nCompute the sample variance of collection itr, with known mean(s) mean.\n\nThe algorithm returns an estimator of the generative distribution's variance under the assumption that each entry of itr is a sample drawn from the same unknown distribution, with the samples uncorrelated. For arrays, this computation is equivalent to calculating sum((itr .- mean(itr)).^2) / (length(itr) - 1). If corrected is true, then the sum is scaled with n-1, whereas the sum is scaled with n if corrected is false with n the number of elements in itr.\n\nIf itr is an AbstractArray, dims can be provided to compute the variance over dimensions. In that case, mean must be an array with the same shape as mean(itr, dims=dims) (additional trailing singleton dimensions are allowed).\n\nnote: Note\nIf array contains NaN or missing values, the result is also NaN or missing (missing takes precedence if array contains both). Use the skipmissing function to omit missing entries and compute the variance of non-missing values.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/Statistics/#Statistics.cor","page":"统计","title":"Statistics.cor","text":"cor(x::AbstractVector)\n\nReturn the number one.\n\n\n\n\n\ncor(X::AbstractMatrix; dims::Int=1)\n\nCompute the Pearson correlation matrix of the matrix X along the dimension dims.\n\n\n\n\n\ncor(x::AbstractVector, y::AbstractVector)\n\nCompute the Pearson correlation between the vectors x and y.\n\n\n\n\n\ncor(X::AbstractVecOrMat, Y::AbstractVecOrMat; dims=1)\n\nCompute the Pearson correlation between the vectors or matrices X and Y along the dimension dims.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/Statistics/#Statistics.cov","page":"统计","title":"Statistics.cov","text":"cov(x::AbstractVector; corrected::Bool=true)\n\nCompute the variance of the vector x. If corrected is true (the default) then the sum is scaled with n-1, whereas the sum is scaled with n if corrected is false where n = length(x).\n\n\n\n\n\ncov(X::AbstractMatrix; dims::Int=1, corrected::Bool=true)\n\nCompute the covariance matrix of the matrix X along the dimension dims. If corrected is true (the default) then the sum is scaled with n-1, whereas the sum is scaled with n if corrected is false where n = size(X, dims).\n\n\n\n\n\ncov(x::AbstractVector, y::AbstractVector; corrected::Bool=true)\n\nCompute the covariance between the vectors x and y. If corrected is true (the default), computes frac1n-1sum_i=1^n (x_i-bar x) (y_i-bar y)^* where * denotes the complex conjugate and n = length(x) = length(y). If corrected is false, computes frac1nsum_i=1^n (x_i-bar x) (y_i-bar y)^*.\n\n\n\n\n\ncov(X::AbstractVecOrMat, Y::AbstractVecOrMat; dims::Int=1, corrected::Bool=true)\n\nCompute the covariance between the vectors or matrices X and Y along the dimension dims. If corrected is true (the default) then the sum is scaled with n-1, whereas the sum is scaled with n if corrected is false where n = size(X, dims) = size(Y, dims).\n\n\n\n\n\n","category":"function"},{"location":"stdlib/Statistics/#Statistics.mean!","page":"统计","title":"Statistics.mean!","text":"mean!(r, v)\n\nCompute the mean of v over the singleton dimensions of r, and write results to r.\n\nExamples\n\njulia> using Statistics\n\njulia> v = [1 2; 3 4]\n2×2 Matrix{Int64}:\n 1 2\n 3 4\n\njulia> mean!([1., 1.], v)\n2-element Vector{Float64}:\n 1.5\n 3.5\n\njulia> mean!([1. 1.], v)\n1×2 Matrix{Float64}:\n 2.0 3.0\n\n\n\n\n\n","category":"function"},{"location":"stdlib/Statistics/#Statistics.mean","page":"统计","title":"Statistics.mean","text":"mean(itr)\n\nCompute the mean of all elements in a collection.\n\nnote: Note\nIf itr contains NaN or missing values, the result is also NaN or missing (missing takes precedence if array contains both). Use the skipmissing function to omit missing entries and compute the mean of non-missing values.\n\nExamples\n\njulia> using Statistics\n\njulia> mean(1:20)\n10.5\n\njulia> mean([1, missing, 3])\nmissing\n\njulia> mean(skipmissing([1, missing, 3]))\n2.0\n\n\n\n\n\nmean(f::Function, itr)\n\nApply the function f to each element of collection itr and take the mean.\n\njulia> using Statistics\n\njulia> mean(√, [1, 2, 3])\n1.3820881233139908\n\njulia> mean([√1, √2, √3])\n1.3820881233139908\n\n\n\n\n\nmean(f::Function, A::AbstractArray; dims)\n\nApply the function f to each element of array A and take the mean over dimensions dims.\n\ncompat: Julia 1.3\nThis method requires at least Julia 1.3.\n\njulia> using Statistics\n\njulia> mean(√, [1, 2, 3])\n1.3820881233139908\n\njulia> mean([√1, √2, √3])\n1.3820881233139908\n\njulia> mean(√, [1 2 3; 4 5 6], dims=2)\n2×1 Matrix{Float64}:\n 1.3820881233139908\n 2.2285192400943226\n\n\n\n\n\nmean(A::AbstractArray; dims)\n\nCompute the mean of an array over the given dimensions.\n\ncompat: Julia 1.1\nmean for empty arrays requires at least Julia 1.1.\n\nExamples\n\njulia> using Statistics\n\njulia> A = [1 2; 3 4]\n2×2 Matrix{Int64}:\n 1 2\n 3 4\n\njulia> mean(A, dims=1)\n1×2 Matrix{Float64}:\n 2.0 3.0\n\njulia> mean(A, dims=2)\n2×1 Matrix{Float64}:\n 1.5\n 3.5\n\n\n\n\n\n","category":"function"},{"location":"stdlib/Statistics/#Statistics.median!","page":"统计","title":"Statistics.median!","text":"median!(v)\n\nLike median, but may overwrite the input vector.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/Statistics/#Statistics.median","page":"统计","title":"Statistics.median","text":"median(itr)\n\nCompute the median of all elements in a collection. For an even number of elements no exact median element exists, so the result is equivalent to calculating mean of two median elements.\n\nnote: Note\nIf itr contains NaN or missing values, the result is also NaN or missing (missing takes precedence if itr contains both). Use the skipmissing function to omit missing entries and compute the median of non-missing values.\n\nExamples\n\njulia> using Statistics\n\njulia> median([1, 2, 3])\n2.0\n\njulia> median([1, 2, 3, 4])\n2.5\n\njulia> median([1, 2, missing, 4])\nmissing\n\njulia> median(skipmissing([1, 2, missing, 4]))\n2.0\n\n\n\n\n\nmedian(A::AbstractArray; dims)\n\nCompute the median of an array along the given dimensions.\n\nExamples\n\njulia> using Statistics\n\njulia> median([1 2; 3 4], dims=1)\n1×2 Matrix{Float64}:\n 2.0 3.0\n\n\n\n\n\n","category":"function"},{"location":"stdlib/Statistics/#Statistics.middle","page":"统计","title":"Statistics.middle","text":"middle(x)\n\nCompute the middle of a scalar value, which is equivalent to x itself, but of the type of middle(x, x) for consistency.\n\n\n\n\n\nmiddle(x, y)\n\nCompute the middle of two numbers x and y, which is equivalent in both value and type to computing their mean ((x + y) / 2).\n\n\n\n\n\nmiddle(range)\n\nCompute the middle of a range, which consists of computing the mean of its extrema. Since a range is sorted, the mean is performed with the first and last element.\n\njulia> using Statistics\n\njulia> middle(1:10)\n5.5\n\n\n\n\n\nmiddle(a)\n\nCompute the middle of an array a, which consists of finding its extrema and then computing their mean.\n\njulia> using Statistics\n\njulia> a = [1,2,3.6,10.9]\n4-element Vector{Float64}:\n 1.0\n 2.0\n 3.6\n 10.9\n\njulia> middle(a)\n5.95\n\n\n\n\n\n","category":"function"},{"location":"stdlib/Statistics/#Statistics.quantile!","page":"统计","title":"Statistics.quantile!","text":"quantile!([q::AbstractArray, ] v::AbstractVector, p; sorted=false, alpha::Real=1.0, beta::Real=alpha)\n\nCompute the quantile(s) of a vector v at a specified probability or vector or tuple of probabilities p on the interval [0,1]. If p is a vector, an optional output array q may also be specified. (If not provided, a new output array is created.) The keyword argument sorted indicates whether v can be assumed to be sorted; if false (the default), then the elements of v will be partially sorted in-place.\n\nBy default (alpha = beta = 1), quantiles are computed via linear interpolation between the points ((k-1)/(n-1), v[k]), for k = 1:n where n = length(v). This corresponds to Definition 7 of Hyndman and Fan (1996), and is the same as the R and NumPy default.\n\nThe keyword arguments alpha and beta correspond to the same parameters in Hyndman and Fan, setting them to different values allows to calculate quantiles with any of the methods 4-9 defined in this paper:\n\nDef. 4: alpha=0, beta=1\nDef. 5: alpha=0.5, beta=0.5\nDef. 6: alpha=0, beta=0 (Excel PERCENTILE.EXC, Python default, Stata altdef)\nDef. 7: alpha=1, beta=1 (Julia, R and NumPy default, Excel PERCENTILE and PERCENTILE.INC, Python 'inclusive')\nDef. 8: alpha=1/3, beta=1/3\nDef. 9: alpha=3/8, beta=3/8\n\nnote: Note\nAn ArgumentError is thrown if v contains NaN or missing values.\n\nReferences\n\nHyndman, R.J and Fan, Y. (1996) \"Sample Quantiles in Statistical Packages\", The American Statistician, Vol. 50, No. 4, pp. 361-365\nQuantile on Wikipedia details the different quantile definitions\n\nExamples\n\njulia> using Statistics\n\njulia> x = [3, 2, 1];\n\njulia> quantile!(x, 0.5)\n2.0\n\njulia> x\n3-element Vector{Int64}:\n 1\n 2\n 3\n\njulia> y = zeros(3);\n\njulia> quantile!(y, x, [0.1, 0.5, 0.9]) === y\ntrue\n\njulia> y\n3-element Vector{Float64}:\n 1.2000000000000002\n 2.0\n 2.8000000000000003\n\n\n\n\n\n","category":"function"},{"location":"stdlib/Statistics/#Statistics.quantile","page":"统计","title":"Statistics.quantile","text":"quantile(itr, p; sorted=false, alpha::Real=1.0, beta::Real=alpha)\n\nCompute the quantile(s) of a collection itr at a specified probability or vector or tuple of probabilities p on the interval [0,1]. The keyword argument sorted indicates whether itr can be assumed to be sorted.\n\nSamples quantile are defined by Q(p) = (1-γ)*x[j] + γ*x[j+1], where xj is the j-th order statistic, and γ is a function of j = floor(n*p + m), m = alpha + p*(1 - alpha - beta) and g = n*p + m - j.\n\nBy default (alpha = beta = 1), quantiles are computed via linear interpolation between the points ((k-1)/(n-1), v[k]), for k = 1:n where n = length(itr). This corresponds to Definition 7 of Hyndman and Fan (1996), and is the same as the R and NumPy default.\n\nThe keyword arguments alpha and beta correspond to the same parameters in Hyndman and Fan, setting them to different values allows to calculate quantiles with any of the methods 4-9 defined in this paper:\n\nDef. 4: alpha=0, beta=1\nDef. 5: alpha=0.5, beta=0.5\nDef. 6: alpha=0, beta=0 (Excel PERCENTILE.EXC, Python default, Stata altdef)\nDef. 7: alpha=1, beta=1 (Julia, R and NumPy default, Excel PERCENTILE and PERCENTILE.INC, Python 'inclusive')\nDef. 8: alpha=1/3, beta=1/3\nDef. 9: alpha=3/8, beta=3/8\n\nnote: Note\nAn ArgumentError is thrown if v contains NaN or missing values. Use the skipmissing function to omit missing entries and compute the quantiles of non-missing values.\n\nReferences\n\nHyndman, R.J and Fan, Y. (1996) \"Sample Quantiles in Statistical Packages\", The American Statistician, Vol. 50, No. 4, pp. 361-365\nQuantile on Wikipedia details the different quantile definitions\n\nExamples\n\njulia> using Statistics\n\njulia> quantile(0:20, 0.5)\n10.0\n\njulia> quantile(0:20, [0.1, 0.5, 0.9])\n3-element Vector{Float64}:\n 2.0\n 10.0\n 18.000000000000004\n\njulia> quantile(skipmissing([1, 10, missing]), 0.5)\n5.5\n\n\n\n\n\n","category":"function"},{"location":"stdlib/Statistics/","page":"统计","title":"统计","text":"DocTestSetup = nothing","category":"page"},{"location":"devdocs/require/#Module-loading","page":"Module loading","title":"Module loading","text":"","category":"section"},{"location":"devdocs/require/","page":"Module loading","title":"Module loading","text":"Base.require is responsible for loading modules and it also manages the precompilation cache. It is the implementation of the import statement.","category":"page"},{"location":"devdocs/require/#Experimental-features","page":"Module loading","title":"Experimental features","text":"","category":"section"},{"location":"devdocs/require/","page":"Module loading","title":"Module loading","text":"The features below are experimental and not part of the stable Julia API. Before building upon them inform yourself about the current thinking and whether they might change soon.","category":"page"},{"location":"devdocs/require/#Module-loading-callbacks","page":"Module loading","title":"Module loading callbacks","text":"","category":"section"},{"location":"devdocs/require/","page":"Module loading","title":"Module loading","text":"It is possible to listen to the modules loaded by Base.require, by registering a callback.","category":"page"},{"location":"devdocs/require/","page":"Module loading","title":"Module loading","text":"loaded_packages = Channel{Symbol}()\ncallback = (mod::Symbol) -> put!(loaded_packages, mod)\npush!(Base.package_callbacks, callback)","category":"page"},{"location":"devdocs/require/","page":"Module loading","title":"Module loading","text":"Please note that the symbol given to the callback is a non-unique identifier and it is the responsibility of the callback provider to walk the module chain to determine the fully qualified name of the loaded binding.","category":"page"},{"location":"devdocs/require/","page":"Module loading","title":"Module loading","text":"The callback below is an example of how to do that:","category":"page"},{"location":"devdocs/require/","page":"Module loading","title":"Module loading","text":"# Get the fully-qualified name of a module.\nfunction module_fqn(name::Symbol)\n fqn = fullname(Base.root_module(name))\n return join(fqn, '.')\nend","category":"page"},{"location":"manual/embedding/#嵌入-Julia","page":"嵌入 Julia","title":"嵌入 Julia","text":"","category":"section"},{"location":"manual/embedding/","page":"嵌入 Julia","title":"嵌入 Julia","text":"正如我们在 调用 C 和 Fortran 代码 中看到的, Julia 有着简单高效的方法来调用 C 编写的函数。但有时恰恰相反,我们需要在 C 中调用 Julia 的函数。这可以将 Julia 代码集成到一个更大的 C/C++ 项目而无需在 C/C++ 中重写所有内容。Julia 有一个 C API 来实现这一目标。几乎所有编程语言都能以某种方式来调用 C 语言的函数,因此 Julia 的 C API 也就能够进行更多语言的桥接。(例如在 Python 或是 C# 中调用 Julia ).","category":"page"},{"location":"manual/embedding/#高级别嵌入","page":"嵌入 Julia","title":"高级别嵌入","text":"","category":"section"},{"location":"manual/embedding/","page":"嵌入 Julia","title":"嵌入 Julia","text":"Note: 本节包含可运行在类 Unix 系统上的、使用 C 编写的嵌入式 Julia 代码。Windows 平台请参阅下一节。","category":"page"},{"location":"manual/embedding/","page":"嵌入 Julia","title":"嵌入 Julia","text":"我们从一个简单的 C 程序开始初始化 Julia 并调用一些 Julia 代码:","category":"page"},{"location":"manual/embedding/","page":"嵌入 Julia","title":"嵌入 Julia","text":"#include \nJULIA_DEFINE_FAST_TLS // only define this once, in an executable (not in a shared library) if you want fast code.\n\nint main(int argc, char *argv[])\n{\n /* required: setup the Julia context */\n jl_init();\n\n /* run Julia commands */\n jl_eval_string(\"print(sqrt(2.0))\");\n\n /* strongly recommended: notify Julia that the\n program is about to terminate. this allows\n Julia time to cleanup pending write requests\n and run all finalizers\n */\n jl_atexit_hook(0);\n return 0;\n}","category":"page"},{"location":"manual/embedding/","page":"嵌入 Julia","title":"嵌入 Julia","text":"为构建这个程序,你必须将 Julia 头文件的路径放入 include 路径并链接 libjulia 。例如 Julia 被安装到 $JULIA_DIR,则可以用 gcc 来编译上面的测试程序 test.c:","category":"page"},{"location":"manual/embedding/","page":"嵌入 Julia","title":"嵌入 Julia","text":"gcc -o test -fPIC -I$JULIA_DIR/include/julia -L$JULIA_DIR/lib -Wl,-rpath,$JULIA_DIR/lib test.c -ljulia","category":"page"},{"location":"manual/embedding/","page":"嵌入 Julia","title":"嵌入 Julia","text":"或者,查看 test/embedding/ 文件夹中 Julia 源代码树中的 embedding.c 程序。 文件 cli/loader_exe.c 程序是另一个简单的例子,说明如何在链接 libjulia 时设置 jl_options 选项。","category":"page"},{"location":"manual/embedding/","page":"嵌入 Julia","title":"嵌入 Julia","text":"在调用任何其他 Julia C 函数之前第一件必须要做的事是初始化 Julia,通过调用 jl_init 尝试自动确定 Julia 的安装位置来实现。如果需要自定义位置或指定要加载的系统映像,请改用 jl_init_with_image。","category":"page"},{"location":"manual/embedding/","page":"嵌入 Julia","title":"嵌入 Julia","text":"测试程序中的第二个语句通过调用 jl_eval_string 来执行 Julia 语句。","category":"page"},{"location":"manual/embedding/","page":"嵌入 Julia","title":"嵌入 Julia","text":"在程序结束之前,强烈建议调用 jl_atexit_hook。上面的示例程序在 main 返回之前进行了调用。","category":"page"},{"location":"manual/embedding/","page":"嵌入 Julia","title":"嵌入 Julia","text":"note: Note\n现在,动态链接 libjulia 的共享库需要传递选项 RTLD_GLOBAL 。比如在 Python 中像这样调用:>>> julia=CDLL('./libjulia.dylib',RTLD_GLOBAL)\n>>> julia.jl_init.argtypes = []\n>>> julia.jl_init()\n250593296","category":"page"},{"location":"manual/embedding/","page":"嵌入 Julia","title":"嵌入 Julia","text":"note: Note\n如果 Julia 程序需要访问 主可执行文件 中的符号,那么除了下面描述的由 julia-config.jl 生成的标记之外,可能还需要在 Linux 上的编译时添加 -Wl,--export-dynamic 链接器标志。编译共享库时则不必要。","category":"page"},{"location":"manual/embedding/#使用-julia-config-自动确定构建参数","page":"嵌入 Julia","title":"使用 julia-config 自动确定构建参数","text":"","category":"section"},{"location":"manual/embedding/","page":"嵌入 Julia","title":"嵌入 Julia","text":"julia-config.jl 创建脚本是为了帮助确定使用嵌入的 Julia 程序所需的构建参数。此脚本使用由其调用的特定 Julia 分发的构建参数和系统配置来导出嵌入程序的必要编译器标志以与该分发交互。此脚本位于 Julia 的 share 目录中。","category":"page"},{"location":"manual/embedding/#例子","page":"嵌入 Julia","title":"例子","text":"","category":"section"},{"location":"manual/embedding/","page":"嵌入 Julia","title":"嵌入 Julia","text":"#include \n\nint main(int argc, char *argv[])\n{\n jl_init();\n (void)jl_eval_string(\"println(sqrt(2.0))\");\n jl_atexit_hook(0);\n return 0;\n}","category":"page"},{"location":"manual/embedding/#在命令行中","page":"嵌入 Julia","title":"在命令行中","text":"","category":"section"},{"location":"manual/embedding/","page":"嵌入 Julia","title":"嵌入 Julia","text":"命令行脚本简单用法:假设 julia-config.jl 位于 /usr/local/julia/share/julia,它可以直接在命令行上调用,并采用 3 个标志的任意组合:","category":"page"},{"location":"manual/embedding/","page":"嵌入 Julia","title":"嵌入 Julia","text":"/usr/local/julia/share/julia/julia-config.jl\nUsage: julia-config [--cflags|--ldflags|--ldlibs]","category":"page"},{"location":"manual/embedding/","page":"嵌入 Julia","title":"嵌入 Julia","text":"如果上面的示例源代码保存为文件 embed_example.c,则以下命令将其编译为 Linux 和 Windows 上运行的程序(MSYS2 环境),或者如果在 OS/X 上,则用 clang 替换 gcc。:","category":"page"},{"location":"manual/embedding/","page":"嵌入 Julia","title":"嵌入 Julia","text":"/usr/local/julia/share/julia/julia-config.jl --cflags --ldflags --ldlibs | xargs gcc embed_example.c","category":"page"},{"location":"manual/embedding/#在-Makefiles-中使用","page":"嵌入 Julia","title":"在 Makefiles 中使用","text":"","category":"section"},{"location":"manual/embedding/","page":"嵌入 Julia","title":"嵌入 Julia","text":"但通常来说,嵌入的项目会比上面更复杂,因此一般会提供 makefile 支持。由于使用了 shell 宏扩展,我们就假设用 GNU make 。 另外,尽管很多时候 julia-config.jl 会在目录 /usr/local 中出现多次,不过也未必如此,但 Julia 也定位 julia-config.jl,并且可以使用 makefile 来利用它。上面的示例程序使用 Makefile 来扩展。:","category":"page"},{"location":"manual/embedding/","page":"嵌入 Julia","title":"嵌入 Julia","text":"JL_SHARE = $(shell julia -e 'print(joinpath(Sys.BINDIR, Base.DATAROOTDIR, \"julia\"))')\nCFLAGS += $(shell $(JL_SHARE)/julia-config.jl --cflags)\nCXXFLAGS += $(shell $(JL_SHARE)/julia-config.jl --cflags)\nLDFLAGS += $(shell $(JL_SHARE)/julia-config.jl --ldflags)\nLDLIBS += $(shell $(JL_SHARE)/julia-config.jl --ldlibs)\n\nall: embed_example","category":"page"},{"location":"manual/embedding/","page":"嵌入 Julia","title":"嵌入 Julia","text":"现在构建的命令就只需要简简单单的make了。","category":"page"},{"location":"manual/embedding/#在-Windows-使用-Visual-Studio-进行高级别嵌入","page":"嵌入 Julia","title":"在 Windows 使用 Visual Studio 进行高级别嵌入","text":"","category":"section"},{"location":"manual/embedding/","page":"嵌入 Julia","title":"嵌入 Julia","text":"如果尚未设置JULIA_DIR环境变量,请在启动 Visual Studio 之前使用系统面板添加它。JULIA_DIR 下的bin 文件夹应该在系统路径上。","category":"page"},{"location":"manual/embedding/","page":"嵌入 Julia","title":"嵌入 Julia","text":"我们首先打开 Visual Studio 并创建一个新的控制台应用程序项目。 在stdafx.h头文件的末尾添加以下几行:","category":"page"},{"location":"manual/embedding/","page":"嵌入 Julia","title":"嵌入 Julia","text":"#include ","category":"page"},{"location":"manual/embedding/","page":"嵌入 Julia","title":"嵌入 Julia","text":"然后,将项目中的 main() 函数替换为以下代码:","category":"page"},{"location":"manual/embedding/","page":"嵌入 Julia","title":"嵌入 Julia","text":"int main(int argc, char *argv[])\n{\n /* required: setup the Julia context */\n jl_init();\n\n /* run Julia commands */\n jl_eval_string(\"print(sqrt(2.0))\");\n\n /* strongly recommended: notify Julia that the\n program is about to terminate. this allows\n Julia time to cleanup pending write requests\n and run all finalizers\n */\n jl_atexit_hook(0);\n return 0;\n}","category":"page"},{"location":"manual/embedding/","page":"嵌入 Julia","title":"嵌入 Julia","text":"下一步是设置项目以查找 Julia 包含的文件和库。 了解 Julia 安装的是 32 位还是 64 位非常重要。 在继续之前删除与 Julia 安装不对应的任何平台配置。","category":"page"},{"location":"manual/embedding/","page":"嵌入 Julia","title":"嵌入 Julia","text":"使用项目属性对话框,转到C/C++ | General 并将 $(JULIA_DIR)\\include\\julia\\ 添加到 Additional Include Directories 属性。 然后,转到Linker | General 部分并将 $(JULIA_DIR)\\lib 添加到 Additional Library Directories 属性。最后,在Linker| Input下,将libjulia.dll.a;libopenlibm.dll.a;添加到库列表中。","category":"page"},{"location":"manual/embedding/","page":"嵌入 Julia","title":"嵌入 Julia","text":"到这里,该项目应该成功构建和运行。","category":"page"},{"location":"manual/embedding/#转换类型","page":"嵌入 Julia","title":"转换类型","text":"","category":"section"},{"location":"manual/embedding/","page":"嵌入 Julia","title":"嵌入 Julia","text":"真正的应用程序不仅仅要执行表达式,还要返回表达式的值给宿主程序。jl_eval_string 返回 一个 jl_value_t*,它是指向堆分配的 Julia 对象的指针。存储像 Float64 这些简单数据类型叫做 装箱,然后提取存储的基础类型数据叫 拆箱。我们改进的示例程序在 Julia 中计算 2 的平方根,并在 C 中读取回结果,如下所示:","category":"page"},{"location":"manual/embedding/","page":"嵌入 Julia","title":"嵌入 Julia","text":"jl_value_t *ret = jl_eval_string(\"sqrt(2.0)\");\n\nif (jl_typeis(ret, jl_float64_type)) {\n double ret_unboxed = jl_unbox_float64(ret);\n printf(\"sqrt(2.0) in C: %e \\n\", ret_unboxed);\n}\nelse {\n printf(\"ERROR: unexpected return type from sqrt(::Float64)\\n\");\n}","category":"page"},{"location":"manual/embedding/","page":"嵌入 Julia","title":"嵌入 Julia","text":"为了检查 ret 是否为特定的 Julia 类型,我们可以使用 jl_isa,jl_typeis 或 jl_is_... 函数。通过输入 typeof(sqrt(2.0))到 Julia shell,我们可以看到返回类型是 Float64(在C中是 double 类型)。要将装箱的 Julia 值转换为 C 的double,上面的代码片段使用了 jl_unbox_float64函数。","category":"page"},{"location":"manual/embedding/","page":"嵌入 Julia","title":"嵌入 Julia","text":"相应的, 用 jl_box_... 函数是另一种转换的方式。","category":"page"},{"location":"manual/embedding/","page":"嵌入 Julia","title":"嵌入 Julia","text":"jl_value_t *a = jl_box_float64(3.0);\njl_value_t *b = jl_box_float32(3.0f);\njl_value_t *c = jl_box_int32(3);","category":"page"},{"location":"manual/embedding/","page":"嵌入 Julia","title":"嵌入 Julia","text":"正如我们将在下面看到的那样,装箱需要在调用 Julia 函数时使用特定参数。","category":"page"},{"location":"manual/embedding/#调用-Julia-函数","page":"嵌入 Julia","title":"调用 Julia 函数","text":"","category":"section"},{"location":"manual/embedding/","page":"嵌入 Julia","title":"嵌入 Julia","text":"虽然 jl_eval_string 允许 C 获取 Julia 表达式的结果,但它不允许将在 C 中计算的参数传递给 Julia。因此需要使用 jl_call 来直接调用Julia函数:","category":"page"},{"location":"manual/embedding/","page":"嵌入 Julia","title":"嵌入 Julia","text":"jl_function_t *func = jl_get_function(jl_base_module, \"sqrt\");\njl_value_t *argument = jl_box_float64(2.0);\njl_value_t *ret = jl_call1(func, argument);","category":"page"},{"location":"manual/embedding/","page":"嵌入 Julia","title":"嵌入 Julia","text":"在第一步中,通过调用 jl_get_function 检索出 Julia 函数 sqrt 的句柄(handle)。 传递给 jl_get_function 的第一个参数是 指向 定义sqrt所在的 Base 模块 的指针。 然后,double 值通过 jl_box_float64 被装箱。 最后,使用 jl_call1 调用该函数。也有 jl_call0,jl_call2和jl_call3 函数,方便地处理不同数量的参数。 要传递更多参数,使用 jl_call:","category":"page"},{"location":"manual/embedding/","page":"嵌入 Julia","title":"嵌入 Julia","text":"jl_value_t *jl_call(jl_function_t *f, jl_value_t **args, int32_t nargs)","category":"page"},{"location":"manual/embedding/","page":"嵌入 Julia","title":"嵌入 Julia","text":"它的第二个参数 args 是 jl_value_t* 类型的数组,nargs 是参数的个数 ","category":"page"},{"location":"manual/embedding/#内存管理","page":"嵌入 Julia","title":"内存管理","text":"","category":"section"},{"location":"manual/embedding/","page":"嵌入 Julia","title":"嵌入 Julia","text":"正如我们所见,Julia 对象在 C 中表示为指针。这就出现了 谁来负责释放这些对象的问题。","category":"page"},{"location":"manual/embedding/","page":"嵌入 Julia","title":"嵌入 Julia","text":"通常,Julia 对象由垃圾收集器(GC)释放,但 GC 不会自动就懂我们正C中保留对Julia值的引用。这意味着 GC 会在你的掌控之外释放对象,从而使指针无效。","category":"page"},{"location":"manual/embedding/","page":"嵌入 Julia","title":"嵌入 Julia","text":"GC 只能在分配 Julia 对象时运行。 像 jl_box_float64 这样的调用执行分配,分配可能发生在运行 Julia 代码的任何时候。 然而,在 jl_... 调用之间使用指针通常是安全的。 但是为了确保值可以在 jl_... 调用后留存下来,我们必须告诉 Julia 我们仍然持有对 Julia root 的引用,这个过程称为“GC rooting”。把一个值”扎根“将确保垃圾收集器不会意外地将此值识别为未使用并释放该值的内存。 这可以使用 JL_GC_PUSH 宏来完成:","category":"page"},{"location":"manual/embedding/","page":"嵌入 Julia","title":"嵌入 Julia","text":"jl_value_t *ret = jl_eval_string(\"sqrt(2.0)\");\nJL_GC_PUSH1(&ret);\n// Do something with ret\nJL_GC_POP();","category":"page"},{"location":"manual/embedding/","page":"嵌入 Julia","title":"嵌入 Julia","text":"JL_GC_POP 调用会释放之前的 JL_GC_PUSH 建立的引用。 请注意,JL_GC_PUSH 将引用存储在 C 堆栈上,因此在退出作用域之前,它必须与一个 JL_GC_POP 精确配对。 也就是说,在函数返回之前,或者流程控制以其他方式离开调用了JL_GC_PUSH 的块。","category":"page"},{"location":"manual/embedding/","page":"嵌入 Julia","title":"嵌入 Julia","text":"可以使用 JL_GC_PUSH2、JL_GC_PUSH3、JL_GC_PUSH4、JL_GC_PUSH5 和 JL_GC_PUSH6 宏一次推送多个 Julia 值。 要推送一个 Julia 数组,可以使用 JL_GC_PUSHARGS 宏,其用法如下:","category":"page"},{"location":"manual/embedding/","page":"嵌入 Julia","title":"嵌入 Julia","text":"jl_value_t **args;\nJL_GC_PUSHARGS(args, 2); // args can now hold 2 `jl_value_t*` objects\nargs[0] = some_value;\nargs[1] = some_other_value;\n// Do something with args (e.g. call jl_... functions)\nJL_GC_POP();","category":"page"},{"location":"manual/embedding/","page":"嵌入 Julia","title":"嵌入 Julia","text":"每个作用域必须只有一次对 JL_GC_PUSH* 的调用。 因此,如果不能通过一次调用JL_GC_PUSH* 一次推送所有变量,或者如果要推送的变量超过 6 个并且使用参数数组不是一种选择,那么可以使用内部块:","category":"page"},{"location":"manual/embedding/","page":"嵌入 Julia","title":"嵌入 Julia","text":"jl_value_t *ret1 = jl_eval_string(\"sqrt(2.0)\");\nJL_GC_PUSH1(&ret1);\njl_value_t *ret2 = 0;\n{\n jl_function_t *func = jl_get_function(jl_base_module, \"exp\");\n ret2 = jl_call1(func, ret1);\n JL_GC_PUSH1(&ret2);\n // Do something with ret2.\n JL_GC_POP(); // This pops ret2.\n}\nJL_GC_POP(); // This pops ret1.","category":"page"},{"location":"manual/embedding/","page":"嵌入 Julia","title":"嵌入 Julia","text":"如果需要在函数(或块作用域)之间保存指向变量的指针,则不能使用 JL_GC_PUSH*。 在这种情况下,有必要在 Julia 全局作用域内创建并保留对变量的引用。 实现这一点的一种简单方法是使用一个全局的IdDict来保存引用,避免 GC 释放。 但是,此方法仅适用于可变类型。","category":"page"},{"location":"manual/embedding/","page":"嵌入 Julia","title":"嵌入 Julia","text":"// This functions shall be executed only once, during the initialization.\njl_value_t* refs = jl_eval_string(\"refs = IdDict()\");\njl_function_t* setindex = jl_get_function(jl_base_module, \"setindex!\");\n\n...\n\n// `var` is the variable we want to protect between function calls.\njl_value_t* var = 0;\n\n...\n\n// `var` is a `Vector{Float64}`, which is mutable.\nvar = jl_eval_string(\"[sqrt(2.0); sqrt(4.0); sqrt(6.0)]\");\n\n// To protect `var`, add its reference to `refs`.\njl_call3(setindex, refs, var, var);","category":"page"},{"location":"manual/embedding/","page":"嵌入 Julia","title":"嵌入 Julia","text":"如果变量是不可变的,则需要将其包装在等效的可变容器中,或者最好在将其推送到IdDict之前包装在RefValue{Any}中。 在这种方法中,容器必须通过 C 代码创建或填充,例如使用函数jl_new_struct。 如果容器是由jl_call* 创建的,那么你将需要重新加载要在 C 代码中使用的指针。","category":"page"},{"location":"manual/embedding/","page":"嵌入 Julia","title":"嵌入 Julia","text":"// This functions shall be executed only once, during the initialization.\njl_value_t* refs = jl_eval_string(\"refs = IdDict()\");\njl_function_t* setindex = jl_get_function(jl_base_module, \"setindex!\");\njl_datatype_t* reft = (jl_datatype_t*)jl_eval_string(\"Base.RefValue{Any}\");\n\n...\n\n// `var` is the variable we want to protect between function calls.\njl_value_t* var = 0;\n\n...\n\n// `var` is a `Float64`, which is immutable.\nvar = jl_eval_string(\"sqrt(2.0)\");\n\n// Protect `var` until we add its reference to `refs`.\nJL_GC_PUSH1(&var);\n\n// Wrap `var` in `RefValue{Any}` and push to `refs` to protect it.\njl_value_t* rvar = jl_new_struct(reft, var);\nJL_GC_POP();\n\njl_call3(setindex, refs, rvar, rvar);","category":"page"},{"location":"manual/embedding/","page":"嵌入 Julia","title":"嵌入 Julia","text":"GC 可以通过使用函数delete! 从refs 中删除对变量的引用来释放变量,前提是没有其它对该变量的引用保留在任何地方:","category":"page"},{"location":"manual/embedding/","page":"嵌入 Julia","title":"嵌入 Julia","text":"jl_function_t* delete = jl_get_function(jl_base_module, \"delete!\");\njl_call2(delete, refs, rvar);","category":"page"},{"location":"manual/embedding/","page":"嵌入 Julia","title":"嵌入 Julia","text":"作为非常简单情况的替代方案,可以只创建一个类型为Vector{Any}的全局容器,并在必要时从中获取元素,甚至可以使用以下方法为每个指针创建一个全局变量","category":"page"},{"location":"manual/embedding/","page":"嵌入 Julia","title":"嵌入 Julia","text":"jl_set_global(jl_main_module, jl_symbol(\"var\"), var);","category":"page"},{"location":"manual/embedding/#更新-GC-管理对象的字段","page":"嵌入 Julia","title":"更新 GC 管理对象的字段","text":"","category":"section"},{"location":"manual/embedding/","page":"嵌入 Julia","title":"嵌入 Julia","text":"垃圾回收器的运行假设它知道每个年老代对象都指向一个年轻代对象。 任何时候一个指针被更新打破了这个假设,它必须用jl_gc_wb(写屏障)函数向回收器发出信号,如下所示:","category":"page"},{"location":"manual/embedding/","page":"嵌入 Julia","title":"嵌入 Julia","text":"jl_value_t *parent = some_old_value, *child = some_young_value;\n((some_specific_type*)parent)->field = child;\njl_gc_wb(parent, child);","category":"page"},{"location":"manual/embedding/","page":"嵌入 Julia","title":"嵌入 Julia","text":"通常情况下不可能在运行时预测 值是否是旧的,因此 写屏障 必须被插入在所有显式存储之后。一个需要注意的例外是如果 parent 对象刚分配,垃圾收集之后并不执行。请记住大多数 jl_... 函数有时候都会执行垃圾收集。","category":"page"},{"location":"manual/embedding/","page":"嵌入 Julia","title":"嵌入 Julia","text":"直接更新数据时,对于指针数组来说 写屏障 也是必需的 例如:","category":"page"},{"location":"manual/embedding/","page":"嵌入 Julia","title":"嵌入 Julia","text":"jl_array_t *some_array = ...; // e.g. a Vector{Any}\nvoid **data = (void**)jl_array_data(some_array);\njl_value_t *some_value = ...;\ndata[0] = some_value;\njl_gc_wb(some_array, some_value);","category":"page"},{"location":"manual/embedding/#控制垃圾收集器","page":"嵌入 Julia","title":"控制垃圾收集器","text":"","category":"section"},{"location":"manual/embedding/","page":"嵌入 Julia","title":"嵌入 Julia","text":"有一些函数能够控制GC。在正常使用情况下这些不是必要的。","category":"page"},{"location":"manual/embedding/","page":"嵌入 Julia","title":"嵌入 Julia","text":"函数 描述\njl_gc_collect() 强制执行 GC\njl_gc_enable(0) 禁用 GC, 返回前一个状态作为 int 类型\njl_gc_enable(1) 启用 GC, 返回前一个状态作为 int 类型\njl_gc_is_enabled() 返回当前状态作为 int 类型","category":"page"},{"location":"manual/embedding/#使用数组","page":"嵌入 Julia","title":"使用数组","text":"","category":"section"},{"location":"manual/embedding/","page":"嵌入 Julia","title":"嵌入 Julia","text":"Julia 和 C 可以不通过复制而共享数组数据。下面一个例子将展示它是如何工作的。","category":"page"},{"location":"manual/embedding/","page":"嵌入 Julia","title":"嵌入 Julia","text":"Julia数组用数据类型 jl_array_t * 表示。基本上,jl_array_t 是一个包含以下内容的结构:","category":"page"},{"location":"manual/embedding/","page":"嵌入 Julia","title":"嵌入 Julia","text":"关于数据类型的信息\n指向数据块的指针\n关于数组长度的信息","category":"page"},{"location":"manual/embedding/","page":"嵌入 Julia","title":"嵌入 Julia","text":"为了让事情比较简单,我们从一维数组开始,创建一个存有 10 个 FLoat64 类型的数组如下所示:","category":"page"},{"location":"manual/embedding/","page":"嵌入 Julia","title":"嵌入 Julia","text":"jl_value_t* array_type = jl_apply_array_type((jl_value_t*)jl_float64_type, 1);\njl_array_t* x = jl_alloc_array_1d(array_type, 10);","category":"page"},{"location":"manual/embedding/","page":"嵌入 Julia","title":"嵌入 Julia","text":"或者,如果您已经分配了数组,则可以生成一个简易的包装器来包裹其数据:","category":"page"},{"location":"manual/embedding/","page":"嵌入 Julia","title":"嵌入 Julia","text":"double *existingArray = (double*)malloc(sizeof(double)*10);\njl_array_t *x = jl_ptr_to_array_1d(array_type, existingArray, 10, 0);","category":"page"},{"location":"manual/embedding/","page":"嵌入 Julia","title":"嵌入 Julia","text":"最后一个参数是一个布尔值,表示 Julia 是否应该获取数据的所有权。 如果这个参数 不为零,当数组不再被引用时,GC 会在数据的指针上调用 free 。","category":"page"},{"location":"manual/embedding/","page":"嵌入 Julia","title":"嵌入 Julia","text":"为了访问 x 的数据,我们可以使用 jl_array_data:","category":"page"},{"location":"manual/embedding/","page":"嵌入 Julia","title":"嵌入 Julia","text":"double *xData = (double*)jl_array_data(x);","category":"page"},{"location":"manual/embedding/","page":"嵌入 Julia","title":"嵌入 Julia","text":"现在我们可以填充这个数组:","category":"page"},{"location":"manual/embedding/","page":"嵌入 Julia","title":"嵌入 Julia","text":"for(size_t i=0; i\n$ make debug","category":"page"},{"location":"devdocs/backtraces/","page":"报告和分析崩溃(段错误)","title":"报告和分析崩溃(段错误)","text":"Note that this process will likely fail with the same error as a normal make incantation, however this will create a debug executable that will offer gdb the debugging symbols needed to get accurate backtraces. Next, manually run the bootstrap process inside of gdb:","category":"page"},{"location":"devdocs/backtraces/","page":"报告和分析崩溃(段错误)","title":"报告和分析崩溃(段错误)","text":"$ cd base/\n$ gdb -x ../contrib/debug_bootstrap.gdb","category":"page"},{"location":"devdocs/backtraces/","page":"报告和分析崩溃(段错误)","title":"报告和分析崩溃(段错误)","text":"This will start gdb, attempt to run the bootstrap process using the debug build of Julia, and print out a backtrace if (when) it segfaults. You may need to hit a few times to get the full backtrace. Create a gist with the backtrace, the version info, and any other pertinent information you can think of and open a new issue on Github with a link to the gist.","category":"page"},{"location":"devdocs/backtraces/#Segfaults-when-running-a-script","page":"报告和分析崩溃(段错误)","title":"Segfaults when running a script","text":"","category":"section"},{"location":"devdocs/backtraces/","page":"报告和分析崩溃(段错误)","title":"报告和分析崩溃(段错误)","text":"The procedure is very similar to Segfaults during bootstrap (sysimg.jl). Create a debug build of Julia, and run your script inside of a debugged Julia process:","category":"page"},{"location":"devdocs/backtraces/","page":"报告和分析崩溃(段错误)","title":"报告和分析崩溃(段错误)","text":"$ cd \n$ make debug\n$ gdb --args usr/bin/julia-debug ","category":"page"},{"location":"devdocs/backtraces/","page":"报告和分析崩溃(段错误)","title":"报告和分析崩溃(段错误)","text":"Note that gdb will sit there, waiting for instructions. Type r to run the process, and bt to generate a backtrace once it segfaults:","category":"page"},{"location":"devdocs/backtraces/","page":"报告和分析崩溃(段错误)","title":"报告和分析崩溃(段错误)","text":"(gdb) r\nStarting program: /home/sabae/src/julia/usr/bin/julia-debug ./test.jl\n...\n(gdb) bt","category":"page"},{"location":"devdocs/backtraces/","page":"报告和分析崩溃(段错误)","title":"报告和分析崩溃(段错误)","text":"Create a gist with the backtrace, the version info, and any other pertinent information you can think of and open a new issue on Github with a link to the gist.","category":"page"},{"location":"devdocs/backtraces/#Errors-during-Julia-startup","page":"报告和分析崩溃(段错误)","title":"Errors during Julia startup","text":"","category":"section"},{"location":"devdocs/backtraces/","page":"报告和分析崩溃(段错误)","title":"报告和分析崩溃(段错误)","text":"Occasionally errors occur during Julia's startup process (especially when using binary distributions, as opposed to compiling from source) such as the following:","category":"page"},{"location":"devdocs/backtraces/","page":"报告和分析崩溃(段错误)","title":"报告和分析崩溃(段错误)","text":"$ julia\nexec: error -5","category":"page"},{"location":"devdocs/backtraces/","page":"报告和分析崩溃(段错误)","title":"报告和分析崩溃(段错误)","text":"These errors typically indicate something is not getting loaded properly very early on in the bootup phase, and our best bet in determining what's going wrong is to use external tools to audit the disk activity of the julia process:","category":"page"},{"location":"devdocs/backtraces/","page":"报告和分析崩溃(段错误)","title":"报告和分析崩溃(段错误)","text":"On Linux, use strace:\n$ strace julia\nOn OSX, use dtruss:\n$ dtruss -f julia","category":"page"},{"location":"devdocs/backtraces/","page":"报告和分析崩溃(段错误)","title":"报告和分析崩溃(段错误)","text":"Create a gist with the strace/ dtruss output, the version info, and any other pertinent information and open a new issue on Github with a link to the gist.","category":"page"},{"location":"devdocs/backtraces/#Other-generic-segfaults-or-unreachables-reached","page":"报告和分析崩溃(段错误)","title":"Other generic segfaults or unreachables reached","text":"","category":"section"},{"location":"devdocs/backtraces/","page":"报告和分析崩溃(段错误)","title":"报告和分析崩溃(段错误)","text":"As mentioned elsewhere, julia has good integration with rr for generating traces; this includes, on Linux, the ability to automatically run julia under rr and share the trace after a crash. This can be immensely helpful when debugging such crashes and is strongly encouraged when reporting crash issues to the JuliaLang/julia repo. To run julia under rr automatically, do:","category":"page"},{"location":"devdocs/backtraces/","page":"报告和分析崩溃(段错误)","title":"报告和分析崩溃(段错误)","text":"julia --bug-report=rr","category":"page"},{"location":"devdocs/backtraces/","page":"报告和分析崩溃(段错误)","title":"报告和分析崩溃(段错误)","text":"To generate the rr trace locally, but not share, you can do:","category":"page"},{"location":"devdocs/backtraces/","page":"报告和分析崩溃(段错误)","title":"报告和分析崩溃(段错误)","text":"julia --bug-report=rr-local","category":"page"},{"location":"devdocs/backtraces/","page":"报告和分析崩溃(段错误)","title":"报告和分析崩溃(段错误)","text":"Note that this is only works on Linux. The blog post on Time Travelling Bug Reporting has many more details.","category":"page"},{"location":"devdocs/backtraces/#Glossary","page":"报告和分析崩溃(段错误)","title":"Glossary","text":"","category":"section"},{"location":"devdocs/backtraces/","page":"报告和分析崩溃(段错误)","title":"报告和分析崩溃(段错误)","text":"A few terms have been used as shorthand in this guide:","category":"page"},{"location":"devdocs/backtraces/","page":"报告和分析崩溃(段错误)","title":"报告和分析崩溃(段错误)","text":" refers to the root directory of the Julia source tree; e.g. it should contain folders such as base, deps, src, test, etc.....","category":"page"},{"location":"devdocs/init/#Julia-运行时的初始化","page":"Julia 运行时的初始化","title":"Julia 运行时的初始化","text":"","category":"section"},{"location":"devdocs/init/","page":"Julia 运行时的初始化","title":"Julia 运行时的初始化","text":"How does the Julia runtime execute julia -e 'println(\"Hello World!\")' ?","category":"page"},{"location":"devdocs/init/#main()","page":"Julia 运行时的初始化","title":"main()","text":"","category":"section"},{"location":"devdocs/init/","page":"Julia 运行时的初始化","title":"Julia 运行时的初始化","text":"Execution starts at main() in cli/loader_exe.c, which calls jl_load_repl() in cli/loader_lib.c which loads a few libraries, eventually calling repl_entrypoint() in src/jlapi.c.","category":"page"},{"location":"devdocs/init/","page":"Julia 运行时的初始化","title":"Julia 运行时的初始化","text":"repl_entrypoint() calls libsupport_init() to set the C library locale and to initialize the \"ios\" library (see ios_init_stdstreams() and Legacy ios.c library).","category":"page"},{"location":"devdocs/init/","page":"Julia 运行时的初始化","title":"Julia 运行时的初始化","text":"Next jl_parse_opts() is called to process command line options. Note that jl_parse_opts() only deals with options that affect code generation or early initialization. Other options are handled later by process_options() in base/client.jl.","category":"page"},{"location":"devdocs/init/","page":"Julia 运行时的初始化","title":"Julia 运行时的初始化","text":"jl_parse_opts() stores command line options in the global jl_options struct.","category":"page"},{"location":"devdocs/init/#julia_init()","page":"Julia 运行时的初始化","title":"julia_init()","text":"","category":"section"},{"location":"devdocs/init/","page":"Julia 运行时的初始化","title":"Julia 运行时的初始化","text":"julia_init() in task.c is called by main() and calls _julia_init() in init.c.","category":"page"},{"location":"devdocs/init/","page":"Julia 运行时的初始化","title":"Julia 运行时的初始化","text":"_julia_init() begins by calling libsupport_init() again (it does nothing the second time).","category":"page"},{"location":"devdocs/init/","page":"Julia 运行时的初始化","title":"Julia 运行时的初始化","text":"restore_signals() is called to zero the signal handler mask.","category":"page"},{"location":"devdocs/init/","page":"Julia 运行时的初始化","title":"Julia 运行时的初始化","text":"jl_resolve_sysimg_location() searches configured paths for the base system image. See Building the Julia system image.","category":"page"},{"location":"devdocs/init/","page":"Julia 运行时的初始化","title":"Julia 运行时的初始化","text":"jl_gc_init() sets up allocation pools and lists for weak refs, preserved values and finalization.","category":"page"},{"location":"devdocs/init/","page":"Julia 运行时的初始化","title":"Julia 运行时的初始化","text":"jl_init_frontend() loads and initializes a pre-compiled femtolisp image containing the scanner/parser.","category":"page"},{"location":"devdocs/init/","page":"Julia 运行时的初始化","title":"Julia 运行时的初始化","text":"jl_init_types() creates jl_datatype_t type description objects for the built-in types defined in julia.h. e.g.","category":"page"},{"location":"devdocs/init/","page":"Julia 运行时的初始化","title":"Julia 运行时的初始化","text":"jl_any_type = jl_new_abstracttype(jl_symbol(\"Any\"), core, NULL, jl_emptysvec);\njl_any_type->super = jl_any_type;\n\njl_type_type = jl_new_abstracttype(jl_symbol(\"Type\"), core, jl_any_type, jl_emptysvec);\n\njl_int32_type = jl_new_primitivetype(jl_symbol(\"Int32\"), core,\n jl_any_type, jl_emptysvec, 32);","category":"page"},{"location":"devdocs/init/","page":"Julia 运行时的初始化","title":"Julia 运行时的初始化","text":"jl_init_tasks() creates the jl_datatype_t* jl_task_type object; initializes the global jl_root_task struct; and sets jl_current_task to the root task.","category":"page"},{"location":"devdocs/init/","page":"Julia 运行时的初始化","title":"Julia 运行时的初始化","text":"jl_init_codegen() initializes the LLVM library.","category":"page"},{"location":"devdocs/init/","page":"Julia 运行时的初始化","title":"Julia 运行时的初始化","text":"jl_init_serializer() initializes 8-bit serialization tags for builtin jl_value_t values.","category":"page"},{"location":"devdocs/init/","page":"Julia 运行时的初始化","title":"Julia 运行时的初始化","text":"If there is no sysimg file (!jl_options.image_file) then the Core and Main modules are created and boot.jl is evaluated:","category":"page"},{"location":"devdocs/init/","page":"Julia 运行时的初始化","title":"Julia 运行时的初始化","text":"jl_core_module = jl_new_module(jl_symbol(\"Core\")) creates the Julia Core module.","category":"page"},{"location":"devdocs/init/","page":"Julia 运行时的初始化","title":"Julia 运行时的初始化","text":"jl_init_intrinsic_functions() creates a new Julia module Intrinsics containing constant jl_intrinsic_type symbols. These define an integer code for each intrinsic function. emit_intrinsic() translates these symbols into LLVM instructions during code generation.","category":"page"},{"location":"devdocs/init/","page":"Julia 运行时的初始化","title":"Julia 运行时的初始化","text":"jl_init_primitives() hooks C functions up to Julia function symbols. e.g. the symbol Core.:(===)() is bound to C function pointer jl_f_is() by calling add_builtin_func(\"===\", jl_f_is).","category":"page"},{"location":"devdocs/init/","page":"Julia 运行时的初始化","title":"Julia 运行时的初始化","text":"jl_new_main_module() creates the global \"Main\" module and sets jl_current_task->current_module = jl_main_module.","category":"page"},{"location":"devdocs/init/","page":"Julia 运行时的初始化","title":"Julia 运行时的初始化","text":"Note: _julia_init() then sets jl_root_task->current_module = jl_core_module. jl_root_task is an alias of jl_current_task at this point, so the current_module set by jl_new_main_module() above is overwritten.","category":"page"},{"location":"devdocs/init/","page":"Julia 运行时的初始化","title":"Julia 运行时的初始化","text":"jl_load(\"boot.jl\", sizeof(\"boot.jl\")) calls jl_parse_eval_all which repeatedly calls jl_toplevel_eval_flex() to execute boot.jl. ","category":"page"},{"location":"devdocs/init/","page":"Julia 运行时的初始化","title":"Julia 运行时的初始化","text":"jl_get_builtin_hooks() initializes global C pointers to Julia globals defined in boot.jl.","category":"page"},{"location":"devdocs/init/","page":"Julia 运行时的初始化","title":"Julia 运行时的初始化","text":"jl_init_box_caches() pre-allocates global boxed integer value objects for values up to 1024. This speeds up allocation of boxed ints later on. e.g.:","category":"page"},{"location":"devdocs/init/","page":"Julia 运行时的初始化","title":"Julia 运行时的初始化","text":"jl_value_t *jl_box_uint8(uint32_t x)\n{\n return boxed_uint8_cache[(uint8_t)x];\n}","category":"page"},{"location":"devdocs/init/","page":"Julia 运行时的初始化","title":"Julia 运行时的初始化","text":"_julia_init() iterates over the jl_core_module->bindings.table looking for jl_datatype_t values and sets the type name's module prefix to jl_core_module.","category":"page"},{"location":"devdocs/init/","page":"Julia 运行时的初始化","title":"Julia 运行时的初始化","text":"jl_add_standard_imports(jl_main_module) does \"using Base\" in the \"Main\" module.","category":"page"},{"location":"devdocs/init/","page":"Julia 运行时的初始化","title":"Julia 运行时的初始化","text":"Note: _julia_init() now reverts to jl_root_task->current_module = jl_main_module as it was before being set to jl_core_module above.","category":"page"},{"location":"devdocs/init/","page":"Julia 运行时的初始化","title":"Julia 运行时的初始化","text":"Platform specific signal handlers are initialized for SIGSEGV (OSX, Linux), and SIGFPE (Windows).","category":"page"},{"location":"devdocs/init/","page":"Julia 运行时的初始化","title":"Julia 运行时的初始化","text":"Other signals (SIGINFO, SIGBUS, SIGILL, SIGTERM, SIGABRT, SIGQUIT, SIGSYS and SIGPIPE) are hooked up to sigdie_handler() which prints a backtrace.","category":"page"},{"location":"devdocs/init/","page":"Julia 运行时的初始化","title":"Julia 运行时的初始化","text":"jl_init_restored_modules() calls jl_module_run_initializer() for each deserialized module to run the __init__() function.","category":"page"},{"location":"devdocs/init/","page":"Julia 运行时的初始化","title":"Julia 运行时的初始化","text":"Finally sigint_handler() is hooked up to SIGINT and calls jl_throw(jl_interrupt_exception).","category":"page"},{"location":"devdocs/init/","page":"Julia 运行时的初始化","title":"Julia 运行时的初始化","text":"_julia_init() then returns back to main() in cli/loader_exe.c and main() calls repl_entrypoint(argc, (char**)argv).","category":"page"},{"location":"devdocs/init/","page":"Julia 运行时的初始化","title":"Julia 运行时的初始化","text":"sidebar: sysimg\nIf there is a sysimg file, it contains a pre-cooked image of the Core and Main modules (and whatever else is created by boot.jl). See Building the Julia system image.jl_restore_system_image() deserializes the saved sysimg into the current Julia runtime environment and initialization continues after jl_init_box_caches() below...Note: jl_restore_system_image() (and staticdata.c in general) uses the Legacy ios.c library.","category":"page"},{"location":"devdocs/init/#repl_entrypoint()","page":"Julia 运行时的初始化","title":"repl_entrypoint()","text":"","category":"section"},{"location":"devdocs/init/","page":"Julia 运行时的初始化","title":"Julia 运行时的初始化","text":"repl_entrypoint() loads the contents of argv[] into Base.ARGS.","category":"page"},{"location":"devdocs/init/","page":"Julia 运行时的初始化","title":"Julia 运行时的初始化","text":"If a .jl \"program\" file was supplied on the command line, then exec_program() calls jl_load(program,len) which calls jl_parse_eval_all which repeatedly calls jl_toplevel_eval_flex() to execute the program.","category":"page"},{"location":"devdocs/init/","page":"Julia 运行时的初始化","title":"Julia 运行时的初始化","text":"However, in our example (julia -e 'println(\"Hello World!\")'), jl_get_global(jl_base_module, jl_symbol(\"_start\")) looks up Base._start and jl_apply() executes it.","category":"page"},{"location":"devdocs/init/#Base._start","page":"Julia 运行时的初始化","title":"Base._start","text":"","category":"section"},{"location":"devdocs/init/","page":"Julia 运行时的初始化","title":"Julia 运行时的初始化","text":"Base._start calls Base.process_options which calls jl_parse_input_line(\"println(\"Hello World!\")\") to create an expression object and Base.eval() to execute it.","category":"page"},{"location":"devdocs/init/#Base.eval","page":"Julia 运行时的初始化","title":"Base.eval","text":"","category":"section"},{"location":"devdocs/init/","page":"Julia 运行时的初始化","title":"Julia 运行时的初始化","text":"Base.eval() was mapped to jl_f_top_eval by jl_init_primitives().","category":"page"},{"location":"devdocs/init/","page":"Julia 运行时的初始化","title":"Julia 运行时的初始化","text":"jl_f_top_eval() calls jl_toplevel_eval_in(jl_main_module, ex), where ex is the parsed expression println(\"Hello World!\").","category":"page"},{"location":"devdocs/init/","page":"Julia 运行时的初始化","title":"Julia 运行时的初始化","text":"jl_toplevel_eval_in() calls jl_toplevel_eval_flex() which calls eval() in interpreter.c.","category":"page"},{"location":"devdocs/init/","page":"Julia 运行时的初始化","title":"Julia 运行时的初始化","text":"The stack dump below shows how the interpreter works its way through various methods of Base.println() and Base.print() before arriving at write(s::IO, a::Array{T}) where T which does ccall(jl_uv_write()).","category":"page"},{"location":"devdocs/init/","page":"Julia 运行时的初始化","title":"Julia 运行时的初始化","text":"jl_uv_write() calls uv_write() to write \"Hello World!\" to JL_STDOUT. See Libuv wrappers for stdio.:","category":"page"},{"location":"devdocs/init/","page":"Julia 运行时的初始化","title":"Julia 运行时的初始化","text":"Hello World!","category":"page"},{"location":"devdocs/init/","page":"Julia 运行时的初始化","title":"Julia 运行时的初始化","text":"Stack frame Source code Notes\njl_uv_write() jl_uv.c called though ccall\njulia_write_282942 stream.jl function write!(s::IO, a::Array{T}) where T\njulia_print_284639 ascii.jl print(io::IO, s::String) = (write(io, s); nothing)\njlcall_print_284639 \njl_apply() julia.h \njl_trampoline() builtins.c \njl_apply() julia.h \njl_apply_generic() gf.c Base.print(Base.TTY, String)\njl_apply() julia.h \njl_trampoline() builtins.c \njl_apply() julia.h \njl_apply_generic() gf.c Base.print(Base.TTY, String, Char, Char...)\njl_apply() julia.h \njl_f_apply() builtins.c \njl_apply() julia.h \njl_trampoline() builtins.c \njl_apply() julia.h \njl_apply_generic() gf.c Base.println(Base.TTY, String, String...)\njl_apply() julia.h \njl_trampoline() builtins.c \njl_apply() julia.h \njl_apply_generic() gf.c Base.println(String,)\njl_apply() julia.h \ndo_call() interpreter.c \neval() interpreter.c \njl_interpret_toplevel_expr() interpreter.c \njl_toplevel_eval_flex() toplevel.c \njl_toplevel_eval() toplevel.c \njl_toplevel_eval_in() builtins.c \njl_f_top_eval() builtins.c ","category":"page"},{"location":"devdocs/init/","page":"Julia 运行时的初始化","title":"Julia 运行时的初始化","text":"Since our example has just one function call, which has done its job of printing \"Hello World!\", the stack now rapidly unwinds back to main().","category":"page"},{"location":"devdocs/init/#jl_atexit_hook()","page":"Julia 运行时的初始化","title":"jl_atexit_hook()","text":"","category":"section"},{"location":"devdocs/init/","page":"Julia 运行时的初始化","title":"Julia 运行时的初始化","text":"main() calls jl_atexit_hook(). This calls Base._atexit, then calls jl_gc_run_all_finalizers() and cleans up libuv handles.","category":"page"},{"location":"devdocs/init/#julia_save()","page":"Julia 运行时的初始化","title":"julia_save()","text":"","category":"section"},{"location":"devdocs/init/","page":"Julia 运行时的初始化","title":"Julia 运行时的初始化","text":"Finally, main() calls julia_save(), which if requested on the command line, saves the runtime state to a new system image. See jl_compile_all() and jl_save_system_image().","category":"page"},{"location":"manual/workflow-tips/#man-workflow-tips","page":"工作流程建议","title":"工作流程建议","text":"","category":"section"},{"location":"manual/workflow-tips/","page":"工作流程建议","title":"工作流程建议","text":"这里是高效使用 Julia 的一些建议。","category":"page"},{"location":"manual/workflow-tips/#基于-REPL-的工作流程","page":"工作流程建议","title":"基于 REPL 的工作流程","text":"","category":"section"},{"location":"manual/workflow-tips/","page":"工作流程建议","title":"工作流程建议","text":"正如在 Julia REPL 中演示的那样,Julia 的 REPL 为高效的交互式工作流程提供了丰富的功能。这里是一些可能进一步提升你在命令行下的体验的建议。","category":"page"},{"location":"manual/workflow-tips/#一个基本的编辑器-/-REPL-工作流程","page":"工作流程建议","title":"一个基本的编辑器 / REPL 工作流程","text":"","category":"section"},{"location":"manual/workflow-tips/","page":"工作流程建议","title":"工作流程建议","text":"最基本的 Julia 工作流程是将一个文本编辑器配合 julia 的命令行使用。一般会包含下面一些步骤:","category":"page"},{"location":"manual/workflow-tips/","page":"工作流程建议","title":"工作流程建议","text":"把还在开发中的代码放到一个临时的模块中。新建一个文件,例如 Tmp.jl,并放到模块中。\nmodule Tmp\nexport say_hello\n\nsay_hello() = println(\"Hello!\")\n\n# your other definitions here\n\nend\n把测试代码放到另一个文件中。新建另一个文件,例如 tst.jl,开头为\ninclude(\"Tmp.jl\")\nimport .Tmp\n# using .Tmp # we can use `using` to bring the exported symbols in `Tmp` into our namespace\n\nTmp.say_hello()\n# say_hello()\n\n# your other test code here\n并把测试作为 Tmp 的内容。或者,你可以把测试文件的内容打包到一个模块中,例如\nmodule Tst\n include(\"Tmp.jl\")\n import .Tmp\n #using .Tmp\n\n Tmp.say_hello()\n # say_hello()\n\n # your other test code here\nend\n优点是你的测试代码现在包含在一个模块中,并且不会在 Main 的全局作用域中引入新定义,这样更加整洁。\n使用 include(\"tst.jl\") 来在 Julia REPL 中 include tst.jl 文件。\n打肥皂,冲洗,重复。(译者注:此为英语幽默,被称为“洗发算法”在 julia REPL 中摸索不同的想法,把好的想法存入 tst.jl。要在 tst.jl 被更改后执行它,只需再次 include 它。","category":"page"},{"location":"manual/workflow-tips/#基于浏览器的工作流程","page":"工作流程建议","title":"基于浏览器的工作流程","text":"","category":"section"},{"location":"manual/workflow-tips/","page":"工作流程建议","title":"工作流程建议","text":"也可以通过 IJulia 在浏览器中与 Julia REPL 进行交互,请到该库的主页查看详细用法。","category":"page"},{"location":"manual/workflow-tips/#基于Revise的工作流程","page":"工作流程建议","title":"基于Revise的工作流程","text":"","category":"section"},{"location":"manual/workflow-tips/","page":"工作流程建议","title":"工作流程建议","text":"无论你是在REPL还是在IJulia,你通常可以通过 Revise优化 你的开发经历。 通常情况,无论何时启动Julia,就请按照Revise文档中的说明配置好Revise。 一旦配置好,Revise将跟踪任何加载模块中的文件变化。 和任何用includet加载到 REPL 的文件 (但不包括普通的include); 然后你就可以编辑这些文件,并且更改会在不重新启动julia会话的情况下生效。 标准工作流与上面基于 REPL 的工作流类似,区别如下:","category":"page"},{"location":"manual/workflow-tips/","page":"工作流程建议","title":"工作流程建议","text":"把你的代码放到一个在你的加载路径里的模块中。 要这样做有很多种方法,通常推荐以下两种选择:\n对于长期的项目,使用PkgTemplates:\nusing PkgTemplates\nt = Template()\nt(\"MyPkg\")\n这将在 .julia/dev 目录中创建一个空白包\"MyPkg\"。 请注意,通过它的 Template 构造器,PkgTemplates 允许控制许多不同的选项。\n在下面的第 2 步中,编辑 MyPkg/src/MyPkg.jl 以更改源代码,并编辑 MyPkg/test/runtests.jl 以进行测试。\n对于“一次性”项目,您可以通过在临时目录(例如 /tmp)中进行工作来避免任何清理需求。\n切换到临时目录并启动 Julia,然后执行以下操作:\npkg> generate MyPkg # type ] to enter pkg mode\njulia> push!(LOAD_PATH, pwd()) # hit backspace to exit pkg mode\n如果你重新启动 Julia 会话,则必须重新发出修改 LOAD_PATH 的命令。\n在下面的第 2 步中,编辑 MyPkg/src/MyPkg.jl 以更改源代码,并创建你选择的任何测试文件。\n构建你自己的包\n在加载任何代码之前, 确保 Revise 已经被启用: using Revise 或者按照教程设置自动加载。\n然后切换到包含测试文件(假设文件为\"runtests.jl\")的目录下,并:\njulia> using MyPkg\n\njulia> include(\"runtests.jl\")\n你可以修改在 MyPkg 文件夹中的代码然后用include(\"runtests.jl\")重新跑一遍测试。 通常,你可能需要重新启动Julia 会话来使得这些变化生效(受一些 限制)。","category":"page"},{"location":"stdlib/LazyArtifacts/#Lazy-Artifacts","page":"Lazy Artifacts","title":"Lazy Artifacts","text":"","category":"section"},{"location":"stdlib/LazyArtifacts/","page":"Lazy Artifacts","title":"Lazy Artifacts","text":"DocTestSetup = :(using LazyArtifacts)","category":"page"},{"location":"stdlib/LazyArtifacts/","page":"Lazy Artifacts","title":"Lazy Artifacts","text":"In order for a package to download artifacts lazily, LazyArtifacts must be explicitly listed as a dependency of that package.","category":"page"},{"location":"stdlib/LazyArtifacts/","page":"Lazy Artifacts","title":"Lazy Artifacts","text":"For further information on artifacts, see Artifacts.","category":"page"},{"location":"base/numbers/#lib-numbers","page":"Numbers","title":"Numbers","text":"","category":"section"},{"location":"base/numbers/#标准数值类型","page":"Numbers","title":"标准数值类型","text":"","category":"section"},{"location":"base/numbers/#抽象数值类型","page":"Numbers","title":"抽象数值类型","text":"","category":"section"},{"location":"base/numbers/","page":"Numbers","title":"Numbers","text":"Core.Number\nCore.Real\nCore.AbstractFloat\nCore.Integer\nCore.Signed\nCore.Unsigned\nBase.AbstractIrrational","category":"page"},{"location":"base/numbers/#Core.Number","page":"Numbers","title":"Core.Number","text":"Number\n\nAbstract supertype for all number types.\n\n\n\n\n\n","category":"type"},{"location":"base/numbers/#Core.Real","page":"Numbers","title":"Core.Real","text":"Real <: Number\n\nAbstract supertype for all real numbers.\n\n\n\n\n\n","category":"type"},{"location":"base/numbers/#Core.AbstractFloat","page":"Numbers","title":"Core.AbstractFloat","text":"AbstractFloat <: Real\n\nAbstract supertype for all floating point numbers.\n\n\n\n\n\n","category":"type"},{"location":"base/numbers/#Core.Integer","page":"Numbers","title":"Core.Integer","text":"Integer <: Real\n\nAbstract supertype for all integers.\n\n\n\n\n\n","category":"type"},{"location":"base/numbers/#Core.Signed","page":"Numbers","title":"Core.Signed","text":"Signed <: Integer\n\nAbstract supertype for all signed integers.\n\n\n\n\n\n","category":"type"},{"location":"base/numbers/#Core.Unsigned","page":"Numbers","title":"Core.Unsigned","text":"Unsigned <: Integer\n\nAbstract supertype for all unsigned integers.\n\n\n\n\n\n","category":"type"},{"location":"base/numbers/#Base.AbstractIrrational","page":"Numbers","title":"Base.AbstractIrrational","text":"AbstractIrrational <: Real\n\nNumber type representing an exact irrational value, which is automatically rounded to the correct precision in arithmetic operations with other numeric quantities.\n\nSubtypes MyIrrational <: AbstractIrrational should implement at least ==(::MyIrrational, ::MyIrrational), hash(x::MyIrrational, h::UInt), and convert(::Type{F}, x::MyIrrational) where {F <: Union{BigFloat,Float32,Float64}}.\n\nIf a subtype is used to represent values that may occasionally be rational (e.g. a square-root type that represents √n for integers n will give a rational result when n is a perfect square), then it should also implement isinteger, iszero, isone, and == with Real values (since all of these default to false for AbstractIrrational types), as well as defining hash to equal that of the corresponding Rational.\n\n\n\n\n\n","category":"type"},{"location":"base/numbers/#具象数值类型","page":"Numbers","title":"具象数值类型","text":"","category":"section"},{"location":"base/numbers/","page":"Numbers","title":"Numbers","text":"Core.Float16\nCore.Float32\nCore.Float64\nBase.BigFloat\nCore.Bool\nCore.Int8\nCore.UInt8\nCore.Int16\nCore.UInt16\nCore.Int32\nCore.UInt32\nCore.Int64\nCore.UInt64\nCore.Int128\nCore.UInt128\nBase.BigInt\nBase.Complex\nBase.Rational\nBase.Irrational","category":"page"},{"location":"base/numbers/#Core.Float16","page":"Numbers","title":"Core.Float16","text":"Float16 <: AbstractFloat\n\n16-bit floating point number type (IEEE 754 standard).\n\nBinary format: 1 sign, 5 exponent, 10 fraction bits.\n\n\n\n\n\n","category":"type"},{"location":"base/numbers/#Core.Float32","page":"Numbers","title":"Core.Float32","text":"Float32 <: AbstractFloat\n\n32-bit floating point number type (IEEE 754 standard).\n\nBinary format: 1 sign, 8 exponent, 23 fraction bits.\n\n\n\n\n\n","category":"type"},{"location":"base/numbers/#Core.Float64","page":"Numbers","title":"Core.Float64","text":"Float64 <: AbstractFloat\n\n64-bit floating point number type (IEEE 754 standard).\n\nBinary format: 1 sign, 11 exponent, 52 fraction bits.\n\n\n\n\n\n","category":"type"},{"location":"base/numbers/#Base.MPFR.BigFloat","page":"Numbers","title":"Base.MPFR.BigFloat","text":"BigFloat <: AbstractFloat\n\nArbitrary precision floating point number type.\n\n\n\n\n\n","category":"type"},{"location":"base/numbers/#Core.Bool","page":"Numbers","title":"Core.Bool","text":"Bool <: Integer\n\nBoolean type, containing the values true and false.\n\nBool is a kind of number: false is numerically equal to 0 and true is numerically equal to 1. Moreover, false acts as a multiplicative \"strong zero\":\n\njulia> false == 0\ntrue\n\njulia> true == 1\ntrue\n\njulia> 0 * NaN\nNaN\n\njulia> false * NaN\n0.0\n\nSee also: digits, iszero, NaN.\n\n\n\n\n\n","category":"type"},{"location":"base/numbers/#Core.Int8","page":"Numbers","title":"Core.Int8","text":"Int8 <: Signed\n\n8-bit signed integer type.\n\n\n\n\n\n","category":"type"},{"location":"base/numbers/#Core.UInt8","page":"Numbers","title":"Core.UInt8","text":"UInt8 <: Unsigned\n\n8-bit unsigned integer type.\n\n\n\n\n\n","category":"type"},{"location":"base/numbers/#Core.Int16","page":"Numbers","title":"Core.Int16","text":"Int16 <: Signed\n\n16-bit signed integer type.\n\n\n\n\n\n","category":"type"},{"location":"base/numbers/#Core.UInt16","page":"Numbers","title":"Core.UInt16","text":"UInt16 <: Unsigned\n\n16-bit unsigned integer type.\n\n\n\n\n\n","category":"type"},{"location":"base/numbers/#Core.Int32","page":"Numbers","title":"Core.Int32","text":"Int32 <: Signed\n\n32-bit signed integer type.\n\n\n\n\n\n","category":"type"},{"location":"base/numbers/#Core.UInt32","page":"Numbers","title":"Core.UInt32","text":"UInt32 <: Unsigned\n\n32-bit unsigned integer type.\n\n\n\n\n\n","category":"type"},{"location":"base/numbers/#Core.Int64","page":"Numbers","title":"Core.Int64","text":"Int64 <: Signed\n\n64-bit signed integer type.\n\n\n\n\n\n","category":"type"},{"location":"base/numbers/#Core.UInt64","page":"Numbers","title":"Core.UInt64","text":"UInt64 <: Unsigned\n\n64-bit unsigned integer type.\n\n\n\n\n\n","category":"type"},{"location":"base/numbers/#Core.Int128","page":"Numbers","title":"Core.Int128","text":"Int128 <: Signed\n\n128-bit signed integer type.\n\n\n\n\n\n","category":"type"},{"location":"base/numbers/#Core.UInt128","page":"Numbers","title":"Core.UInt128","text":"UInt128 <: Unsigned\n\n128-bit unsigned integer type.\n\n\n\n\n\n","category":"type"},{"location":"base/numbers/#Base.GMP.BigInt","page":"Numbers","title":"Base.GMP.BigInt","text":"BigInt <: Signed\n\nArbitrary precision integer type.\n\n\n\n\n\n","category":"type"},{"location":"base/numbers/#Base.Complex","page":"Numbers","title":"Base.Complex","text":"Complex{T<:Real} <: Number\n\nComplex number type with real and imaginary part of type T.\n\nComplexF16, ComplexF32 and ComplexF64 are aliases for Complex{Float16}, Complex{Float32} and Complex{Float64} respectively.\n\nSee also: Real, complex, real.\n\n\n\n\n\n","category":"type"},{"location":"base/numbers/#Base.Rational","page":"Numbers","title":"Base.Rational","text":"Rational{T<:Integer} <: Real\n\nRational number type, with numerator and denominator of type T. Rationals are checked for overflow.\n\n\n\n\n\n","category":"type"},{"location":"base/numbers/#Base.Irrational","page":"Numbers","title":"Base.Irrational","text":"Irrational{sym} <: AbstractIrrational\n\nNumber type representing an exact irrational value denoted by the symbol sym, such as π, ℯ and γ.\n\nSee also [@irrational], AbstractIrrational.\n\n\n\n\n\n","category":"type"},{"location":"base/numbers/#数据格式","page":"Numbers","title":"数据格式","text":"","category":"section"},{"location":"base/numbers/","page":"Numbers","title":"Numbers","text":"Base.digits\nBase.digits!\nBase.bitstring\nBase.parse\nBase.tryparse\nBase.big\nBase.signed\nBase.unsigned\nBase.float(::Any)\nBase.Math.significand\nBase.Math.exponent\nBase.complex(::Complex)\nBase.bswap\nBase.hex2bytes\nBase.hex2bytes!\nBase.bytes2hex","category":"page"},{"location":"base/numbers/#Base.digits","page":"Numbers","title":"Base.digits","text":"digits([T<:Integer], n::Integer; base::T = 10, pad::Integer = 1)\n\nReturn an array with element type T (default Int) of the digits of n in the given base, optionally padded with zeros to a specified size. More significant digits are at higher indices, such that n == sum(digits[k]*base^(k-1) for k=1:length(digits)).\n\nSee also ndigits, digits!, and for base 2 also bitstring, count_ones.\n\nExamples\n\njulia> digits(10)\n2-element Vector{Int64}:\n 0\n 1\n\njulia> digits(10, base = 2)\n4-element Vector{Int64}:\n 0\n 1\n 0\n 1\n\njulia> digits(-256, base = 10, pad = 5)\n5-element Vector{Int64}:\n -6\n -5\n -2\n 0\n 0\n\njulia> n = rand(-999:999);\n\njulia> n == evalpoly(13, digits(n, base = 13))\ntrue\n\n\n\n\n\n","category":"function"},{"location":"base/numbers/#Base.digits!","page":"Numbers","title":"Base.digits!","text":"digits!(array, n::Integer; base::Integer = 10)\n\nFills an array of the digits of n in the given base. More significant digits are at higher indices. If the array length is insufficient, the least significant digits are filled up to the array length. If the array length is excessive, the excess portion is filled with zeros.\n\nExamples\n\njulia> digits!([2, 2, 2, 2], 10, base = 2)\n4-element Vector{Int64}:\n 0\n 1\n 0\n 1\n\njulia> digits!([2, 2, 2, 2, 2, 2], 10, base = 2)\n6-element Vector{Int64}:\n 0\n 1\n 0\n 1\n 0\n 0\n\n\n\n\n\n","category":"function"},{"location":"base/numbers/#Base.bitstring","page":"Numbers","title":"Base.bitstring","text":"bitstring(n)\n\nA string giving the literal bit representation of a primitive type.\n\nSee also count_ones, count_zeros, digits.\n\nExamples\n\njulia> bitstring(Int32(4))\n\"00000000000000000000000000000100\"\n\njulia> bitstring(2.2)\n\"0100000000000001100110011001100110011001100110011001100110011010\"\n\n\n\n\n\n","category":"function"},{"location":"base/numbers/#Base.parse","page":"Numbers","title":"Base.parse","text":"parse(type, str; base)\n\nParse a string as a number. For Integer types, a base can be specified (the default is 10). For floating-point types, the string is parsed as a decimal floating-point number. Complex types are parsed from decimal strings of the form \"R±Iim\" as a Complex(R,I) of the requested type; \"i\" or \"j\" can also be used instead of \"im\", and \"R\" or \"Iim\" are also permitted. If the string does not contain a valid number, an error is raised.\n\ncompat: Julia 1.1\nparse(Bool, str) requires at least Julia 1.1.\n\nExamples\n\njulia> parse(Int, \"1234\")\n1234\n\njulia> parse(Int, \"1234\", base = 5)\n194\n\njulia> parse(Int, \"afc\", base = 16)\n2812\n\njulia> parse(Float64, \"1.2e-3\")\n0.0012\n\njulia> parse(Complex{Float64}, \"3.2e-1 + 4.5im\")\n0.32 + 4.5im\n\n\n\n\n\nparse(::Type{Platform}, triplet::AbstractString)\n\nParses a string platform triplet back into a Platform object.\n\n\n\n\n\n","category":"function"},{"location":"base/numbers/#Base.tryparse","page":"Numbers","title":"Base.tryparse","text":"tryparse(type, str; base)\n\nLike parse, but returns either a value of the requested type, or nothing if the string does not contain a valid number.\n\n\n\n\n\n","category":"function"},{"location":"base/numbers/#Base.big","page":"Numbers","title":"Base.big","text":"big(x)\n\nConvert a number to a maximum precision representation (typically BigInt or BigFloat). See BigFloat for information about some pitfalls with floating-point numbers.\n\n\n\n\n\n","category":"function"},{"location":"base/numbers/#Base.signed","page":"Numbers","title":"Base.signed","text":"signed(T::Integer)\n\nConvert an integer bitstype to the signed type of the same size.\n\nExamples\n\njulia> signed(UInt16)\nInt16\njulia> signed(UInt64)\nInt64\n\n\n\n\n\nsigned(x)\n\nConvert a number to a signed integer. If the argument is unsigned, it is reinterpreted as signed without checking for overflow.\n\nSee also: unsigned, sign, signbit.\n\n\n\n\n\n","category":"function"},{"location":"base/numbers/#Base.unsigned","page":"Numbers","title":"Base.unsigned","text":"unsigned(T::Integer)\n\nConvert an integer bitstype to the unsigned type of the same size.\n\nExamples\n\njulia> unsigned(Int16)\nUInt16\njulia> unsigned(UInt64)\nUInt64\n\n\n\n\n\n","category":"function"},{"location":"base/numbers/#Base.float-Tuple{Any}","page":"Numbers","title":"Base.float","text":"float(x)\n\nConvert a number or array to a floating point data type.\n\nSee also: complex, oftype, convert.\n\nExamples\n\njulia> float(1:1000)\n1.0:1.0:1000.0\n\njulia> float(typemax(Int32))\n2.147483647e9\n\n\n\n\n\n","category":"method"},{"location":"base/numbers/#Base.Math.significand","page":"Numbers","title":"Base.Math.significand","text":"significand(x)\n\nExtract the significand (a.k.a. mantissa) of a floating-point number. If x is a non-zero finite number, then the result will be a number of the same type and sign as x, and whose absolute value is on the interval 12). Otherwise x is returned.\n\nExamples\n\njulia> significand(15.2)\n1.9\n\njulia> significand(-15.2)\n-1.9\n\njulia> significand(-15.2) * 2^3\n-15.2\n\njulia> significand(-Inf), significand(Inf), significand(NaN)\n(-Inf, Inf, NaN)\n\n\n\n\n\n","category":"function"},{"location":"base/numbers/#Base.Math.exponent","page":"Numbers","title":"Base.Math.exponent","text":"exponent(x::AbstractFloat) -> Int\n\nGet the exponent of a normalized floating-point number. Returns the largest integer y such that 2^y ≤ abs(x).\n\nExamples\n\njulia> exponent(6.5)\n2\n\njulia> exponent(16.0)\n4\n\n\n\n\n\n","category":"function"},{"location":"base/numbers/#Base.complex-Tuple{Complex}","page":"Numbers","title":"Base.complex","text":"complex(r, [i])\n\nConvert real numbers or arrays to complex. i defaults to zero.\n\nExamples\n\njulia> complex(7)\n7 + 0im\n\njulia> complex([1, 2, 3])\n3-element Vector{Complex{Int64}}:\n 1 + 0im\n 2 + 0im\n 3 + 0im\n\n\n\n\n\n","category":"method"},{"location":"base/numbers/#Base.bswap","page":"Numbers","title":"Base.bswap","text":"bswap(n)\n\nReverse the byte order of n.\n\n(See also ntoh and hton to convert between the current native byte order and big-endian order.)\n\nExamples\n\njulia> a = bswap(0x10203040)\n0x40302010\n\njulia> bswap(a)\n0x10203040\n\njulia> string(1, base = 2)\n\"1\"\n\njulia> string(bswap(1), base = 2)\n\"100000000000000000000000000000000000000000000000000000000\"\n\n\n\n\n\n","category":"function"},{"location":"base/numbers/#Base.hex2bytes","page":"Numbers","title":"Base.hex2bytes","text":"hex2bytes(itr)\n\nGiven an iterable itr of ASCII codes for a sequence of hexadecimal digits, returns a Vector{UInt8} of bytes corresponding to the binary representation: each successive pair of hexadecimal digits in itr gives the value of one byte in the return vector.\n\nThe length of itr must be even, and the returned array has half of the length of itr. See also hex2bytes! for an in-place version, and bytes2hex for the inverse.\n\ncompat: Julia 1.7\nCalling hex2bytes with iterators producing UInt8 values requires Julia 1.7 or later. In earlier versions, you can collect the iterator before calling hex2bytes.\n\nExamples\n\njulia> s = string(12345, base = 16)\n\"3039\"\n\njulia> hex2bytes(s)\n2-element Vector{UInt8}:\n 0x30\n 0x39\n\njulia> a = b\"01abEF\"\n6-element Base.CodeUnits{UInt8, String}:\n 0x30\n 0x31\n 0x61\n 0x62\n 0x45\n 0x46\n\njulia> hex2bytes(a)\n3-element Vector{UInt8}:\n 0x01\n 0xab\n 0xef\n\n\n\n\n\n","category":"function"},{"location":"base/numbers/#Base.hex2bytes!","page":"Numbers","title":"Base.hex2bytes!","text":"hex2bytes!(dest::AbstractVector{UInt8}, itr)\n\nConvert an iterable itr of bytes representing a hexadecimal string to its binary representation, similar to hex2bytes except that the output is written in-place to dest. The length of dest must be half the length of itr.\n\ncompat: Julia 1.7\nCalling hex2bytes! with iterators producing UInt8 requires version 1.7. In earlier versions, you can collect the iterable before calling instead.\n\n\n\n\n\n","category":"function"},{"location":"base/numbers/#Base.bytes2hex","page":"Numbers","title":"Base.bytes2hex","text":"bytes2hex(itr) -> String\nbytes2hex(io::IO, itr)\n\nConvert an iterator itr of bytes to its hexadecimal string representation, either returning a String via bytes2hex(itr) or writing the string to an io stream via bytes2hex(io, itr). The hexadecimal characters are all lowercase.\n\ncompat: Julia 1.7\nCalling bytes2hex with arbitrary iterators producing UInt8 values requires Julia 1.7 or later. In earlier versions, you can collect the iterator before calling bytes2hex.\n\nExamples\n\njulia> a = string(12345, base = 16)\n\"3039\"\n\njulia> b = hex2bytes(a)\n2-element Vector{UInt8}:\n 0x30\n 0x39\n\njulia> bytes2hex(b)\n\"3039\"\n\n\n\n\n\n","category":"function"},{"location":"base/numbers/#常用数值函数和常量","page":"Numbers","title":"常用数值函数和常量","text":"","category":"section"},{"location":"base/numbers/","page":"Numbers","title":"Numbers","text":"Base.one\nBase.oneunit\nBase.zero\nBase.im\nBase.MathConstants.pi\nBase.MathConstants.ℯ\nBase.MathConstants.catalan\nBase.MathConstants.eulergamma\nBase.MathConstants.golden\nBase.Inf\nBase.Inf32\nBase.Inf16\nBase.NaN\nBase.NaN32\nBase.NaN16\nBase.issubnormal\nBase.isfinite\nBase.isinf\nBase.isnan\nBase.iszero\nBase.isone\nBase.nextfloat\nBase.prevfloat\nBase.isinteger\nBase.isreal\nCore.Float32(::Any)\nCore.Float64(::Any)\nBase.Rounding.rounding\nBase.Rounding.setrounding(::Type, ::Any)\nBase.Rounding.setrounding(::Function, ::Type, ::RoundingMode)\nBase.Rounding.get_zero_subnormals\nBase.Rounding.set_zero_subnormals","category":"page"},{"location":"base/numbers/#Base.one","page":"Numbers","title":"Base.one","text":"one(x)\none(T::type)\n\nReturn a multiplicative identity for x: a value such that one(x)*x == x*one(x) == x. Alternatively one(T) can take a type T, in which case one returns a multiplicative identity for any x of type T.\n\nIf possible, one(x) returns a value of the same type as x, and one(T) returns a value of type T. However, this may not be the case for types representing dimensionful quantities (e.g. time in days), since the multiplicative identity must be dimensionless. In that case, one(x) should return an identity value of the same precision (and shape, for matrices) as x.\n\nIf you want a quantity that is of the same type as x, or of type T, even if x is dimensionful, use oneunit instead.\n\nSee also the identity function, and I in LinearAlgebra for the identity matrix.\n\nExamples\n\njulia> one(3.7)\n1.0\n\njulia> one(Int)\n1\n\njulia> import Dates; one(Dates.Day(1))\n1\n\n\n\n\n\n","category":"function"},{"location":"base/numbers/#Base.oneunit","page":"Numbers","title":"Base.oneunit","text":"oneunit(x::T)\noneunit(T::Type)\n\nReturns T(one(x)), where T is either the type of the argument or (if a type is passed) the argument. This differs from one for dimensionful quantities: one is dimensionless (a multiplicative identity) while oneunit is dimensionful (of the same type as x, or of type T).\n\nExamples\n\njulia> oneunit(3.7)\n1.0\n\njulia> import Dates; oneunit(Dates.Day)\n1 day\n\n\n\n\n\n","category":"function"},{"location":"base/numbers/#Base.zero","page":"Numbers","title":"Base.zero","text":"zero(x)\nzero(::Type)\n\nGet the additive identity element for the type of x (x can also specify the type itself).\n\nSee also iszero, one, oneunit, oftype.\n\nExamples\n\njulia> zero(1)\n0\n\njulia> zero(big\"2.0\")\n0.0\n\njulia> zero(rand(2,2))\n2×2 Matrix{Float64}:\n 0.0 0.0\n 0.0 0.0\n\n\n\n\n\n","category":"function"},{"location":"base/numbers/#Base.im","page":"Numbers","title":"Base.im","text":"im\n\nThe imaginary unit.\n\nSee also: imag, angle, complex.\n\nExamples\n\njulia> im * im\n-1 + 0im\n\njulia> (2.0 + 3im)^2\n-5.0 + 12.0im\n\n\n\n\n\n","category":"constant"},{"location":"base/numbers/#Base.MathConstants.pi","page":"Numbers","title":"Base.MathConstants.pi","text":"π\npi\n\nThe constant pi.\n\nUnicode π can be typed by writing \\pi then pressing tab in the Julia REPL, and in many editors.\n\nSee also: sinpi, sincospi, deg2rad.\n\nExamples\n\njulia> pi\nπ = 3.1415926535897...\n\njulia> 1/2pi\n0.15915494309189535\n\n\n\n\n\n","category":"constant"},{"location":"base/numbers/#Base.MathConstants.ℯ","page":"Numbers","title":"Base.MathConstants.ℯ","text":"ℯ\ne\n\nThe constant ℯ.\n\nUnicode ℯ can be typed by writing \\euler and pressing tab in the Julia REPL, and in many editors.\n\nSee also: exp, cis, cispi.\n\nExamples\n\njulia> ℯ\nℯ = 2.7182818284590...\n\njulia> log(ℯ)\n1\n\njulia> ℯ^(im)π ≈ -1\ntrue\n\n\n\n\n\n","category":"constant"},{"location":"base/numbers/#Base.MathConstants.catalan","page":"Numbers","title":"Base.MathConstants.catalan","text":"catalan\n\nCatalan's constant.\n\nExamples\n\njulia> Base.MathConstants.catalan\ncatalan = 0.9159655941772...\n\njulia> sum(log(x)/(1+x^2) for x in 1:0.01:10^6) * 0.01\n0.9159466120554123\n\n\n\n\n\n","category":"constant"},{"location":"base/numbers/#Base.MathConstants.eulergamma","page":"Numbers","title":"Base.MathConstants.eulergamma","text":"γ\neulergamma\n\nEuler's constant.\n\nExamples\n\njulia> Base.MathConstants.eulergamma\nγ = 0.5772156649015...\n\njulia> dx = 10^-6;\n\njulia> sum(-exp(-x) * log(x) for x in dx:dx:100) * dx\n0.5772078382499133\n\n\n\n\n\n","category":"constant"},{"location":"base/numbers/#Base.MathConstants.golden","page":"Numbers","title":"Base.MathConstants.golden","text":"φ\ngolden\n\nThe golden ratio.\n\nExamples\n\njulia> Base.MathConstants.golden\nφ = 1.6180339887498...\n\njulia> (2ans - 1)^2 ≈ 5\ntrue\n\n\n\n\n\n","category":"constant"},{"location":"base/numbers/#Base.Inf","page":"Numbers","title":"Base.Inf","text":"Inf, Inf64\n\nPositive infinity of type Float64.\n\nSee also: isfinite, typemax, NaN, Inf32.\n\nExamples\n\njulia> π/0\nInf\n\njulia> +1.0 / -0.0\n-Inf\n\njulia> ℯ^-Inf\n0.0\n\n\n\n\n\n","category":"constant"},{"location":"base/numbers/#Base.Inf32","page":"Numbers","title":"Base.Inf32","text":"Inf32\n\nPositive infinity of type Float32.\n\n\n\n\n\n","category":"constant"},{"location":"base/numbers/#Base.Inf16","page":"Numbers","title":"Base.Inf16","text":"Inf16\n\nPositive infinity of type Float16.\n\n\n\n\n\n","category":"constant"},{"location":"base/numbers/#Base.NaN","page":"Numbers","title":"Base.NaN","text":"NaN, NaN64\n\nA not-a-number value of type Float64.\n\nSee also: isnan, missing, NaN32, Inf.\n\nExamples\n\njulia> 0/0\nNaN\n\njulia> Inf - Inf\nNaN\n\njulia> NaN == NaN, isequal(NaN, NaN), NaN === NaN\n(false, true, true)\n\n\n\n\n\n","category":"constant"},{"location":"base/numbers/#Base.NaN32","page":"Numbers","title":"Base.NaN32","text":"NaN32\n\nA not-a-number value of type Float32.\n\n\n\n\n\n","category":"constant"},{"location":"base/numbers/#Base.NaN16","page":"Numbers","title":"Base.NaN16","text":"NaN16\n\nA not-a-number value of type Float16.\n\n\n\n\n\n","category":"constant"},{"location":"base/numbers/#Base.issubnormal","page":"Numbers","title":"Base.issubnormal","text":"issubnormal(f) -> Bool\n\nTest whether a floating point number is subnormal.\n\n\n\n\n\n","category":"function"},{"location":"base/numbers/#Base.isfinite","page":"Numbers","title":"Base.isfinite","text":"isfinite(f) -> Bool\n\nTest whether a number is finite.\n\nExamples\n\njulia> isfinite(5)\ntrue\n\njulia> isfinite(NaN32)\nfalse\n\n\n\n\n\n","category":"function"},{"location":"base/numbers/#Base.isinf","page":"Numbers","title":"Base.isinf","text":"isinf(f) -> Bool\n\nTest whether a number is infinite.\n\nSee also: Inf, iszero, isfinite, isnan.\n\n\n\n\n\n","category":"function"},{"location":"base/numbers/#Base.isnan","page":"Numbers","title":"Base.isnan","text":"isnan(f) -> Bool\n\nTest whether a number value is a NaN, an indeterminate value which is neither an infinity nor a finite number (\"not a number\").\n\nSee also: iszero, isone, isinf, ismissing.\n\n\n\n\n\n","category":"function"},{"location":"base/numbers/#Base.iszero","page":"Numbers","title":"Base.iszero","text":"iszero(x)\n\nReturn true if x == zero(x); if x is an array, this checks whether all of the elements of x are zero.\n\nSee also: isone, isinteger, isfinite, isnan.\n\nExamples\n\njulia> iszero(0.0)\ntrue\n\njulia> iszero([1, 9, 0])\nfalse\n\njulia> iszero([false, 0, 0])\ntrue\n\n\n\n\n\n","category":"function"},{"location":"base/numbers/#Base.isone","page":"Numbers","title":"Base.isone","text":"isone(x)\n\nReturn true if x == one(x); if x is an array, this checks whether x is an identity matrix.\n\nExamples\n\njulia> isone(1.0)\ntrue\n\njulia> isone([1 0; 0 2])\nfalse\n\njulia> isone([1 0; 0 true])\ntrue\n\n\n\n\n\n","category":"function"},{"location":"base/numbers/#Base.nextfloat","page":"Numbers","title":"Base.nextfloat","text":"nextfloat(x::AbstractFloat, n::Integer)\n\nThe result of n iterative applications of nextfloat to x if n >= 0, or -n applications of prevfloat if n < 0.\n\n\n\n\n\nnextfloat(x::AbstractFloat)\n\nReturn the smallest floating point number y of the same type as x such x < y. If no such y exists (e.g. if x is Inf or NaN), then return x.\n\nSee also: prevfloat, eps, issubnormal.\n\n\n\n\n\n","category":"function"},{"location":"base/numbers/#Base.prevfloat","page":"Numbers","title":"Base.prevfloat","text":"prevfloat(x::AbstractFloat, n::Integer)\n\nThe result of n iterative applications of prevfloat to x if n >= 0, or -n applications of nextfloat if n < 0.\n\n\n\n\n\nprevfloat(x::AbstractFloat)\n\nReturn the largest floating point number y of the same type as x such y < x. If no such y exists (e.g. if x is -Inf or NaN), then return x.\n\n\n\n\n\n","category":"function"},{"location":"base/numbers/#Base.isinteger","page":"Numbers","title":"Base.isinteger","text":"isinteger(x) -> Bool\n\nTest whether x is numerically equal to some integer.\n\nExamples\n\njulia> isinteger(4.0)\ntrue\n\n\n\n\n\n","category":"function"},{"location":"base/numbers/#Base.isreal","page":"Numbers","title":"Base.isreal","text":"isreal(x) -> Bool\n\nTest whether x or all its elements are numerically equal to some real number including infinities and NaNs. isreal(x) is true if isequal(x, real(x)) is true.\n\nExamples\n\njulia> isreal(5.)\ntrue\n\njulia> isreal(Inf + 0im)\ntrue\n\njulia> isreal([4.; complex(0,1)])\nfalse\n\n\n\n\n\n","category":"function"},{"location":"base/numbers/#Core.Float32-Tuple{Any}","page":"Numbers","title":"Core.Float32","text":"Float32(x [, mode::RoundingMode])\n\nCreate a Float32 from x. If x is not exactly representable then mode determines how x is rounded.\n\nExamples\n\njulia> Float32(1/3, RoundDown)\n0.3333333f0\n\njulia> Float32(1/3, RoundUp)\n0.33333334f0\n\nSee RoundingMode for available rounding modes.\n\n\n\n\n\n","category":"method"},{"location":"base/numbers/#Core.Float64-Tuple{Any}","page":"Numbers","title":"Core.Float64","text":"Float64(x [, mode::RoundingMode])\n\nCreate a Float64 from x. If x is not exactly representable then mode determines how x is rounded.\n\nExamples\n\njulia> Float64(pi, RoundDown)\n3.141592653589793\n\njulia> Float64(pi, RoundUp)\n3.1415926535897936\n\nSee RoundingMode for available rounding modes.\n\n\n\n\n\n","category":"method"},{"location":"base/numbers/#Base.Rounding.rounding","page":"Numbers","title":"Base.Rounding.rounding","text":"rounding(T)\n\nGet the current floating point rounding mode for type T, controlling the rounding of basic arithmetic functions (+, -, *, / and sqrt) and type conversion.\n\nSee RoundingMode for available modes.\n\n\n\n\n\n","category":"function"},{"location":"base/numbers/#Base.Rounding.setrounding-Tuple{Type, Any}","page":"Numbers","title":"Base.Rounding.setrounding","text":"setrounding(T, mode)\n\nSet the rounding mode of floating point type T, controlling the rounding of basic arithmetic functions (+, -, *, / and sqrt) and type conversion. Other numerical functions may give incorrect or invalid values when using rounding modes other than the default RoundNearest.\n\nNote that this is currently only supported for T == BigFloat.\n\nwarning: Warning\nThis function is not thread-safe. It will affect code running on all threads, but its behavior is undefined if called concurrently with computations that use the setting.\n\n\n\n\n\n","category":"method"},{"location":"base/numbers/#Base.Rounding.setrounding-Tuple{Function, Type, RoundingMode}","page":"Numbers","title":"Base.Rounding.setrounding","text":"setrounding(f::Function, T, mode)\n\nChange the rounding mode of floating point type T for the duration of f. It is logically equivalent to:\n\nold = rounding(T)\nsetrounding(T, mode)\nf()\nsetrounding(T, old)\n\nSee RoundingMode for available rounding modes.\n\n\n\n\n\n","category":"method"},{"location":"base/numbers/#Base.Rounding.get_zero_subnormals","page":"Numbers","title":"Base.Rounding.get_zero_subnormals","text":"get_zero_subnormals() -> Bool\n\nReturn false if operations on subnormal floating-point values (\"denormals\") obey rules for IEEE arithmetic, and true if they might be converted to zeros.\n\nwarning: Warning\nThis function only affects the current thread.\n\n\n\n\n\n","category":"function"},{"location":"base/numbers/#Base.Rounding.set_zero_subnormals","page":"Numbers","title":"Base.Rounding.set_zero_subnormals","text":"set_zero_subnormals(yes::Bool) -> Bool\n\nIf yes is false, subsequent floating-point operations follow rules for IEEE arithmetic on subnormal values (\"denormals\"). Otherwise, floating-point operations are permitted (but not required) to convert subnormal inputs or outputs to zero. Returns true unless yes==true but the hardware does not support zeroing of subnormal numbers.\n\nset_zero_subnormals(true) can speed up some computations on some hardware. However, it can break identities such as (x-y==0) == (x==y).\n\nwarning: Warning\nThis function only affects the current thread.\n\n\n\n\n\n","category":"function"},{"location":"base/numbers/#整型","page":"Numbers","title":"整型","text":"","category":"section"},{"location":"base/numbers/","page":"Numbers","title":"Numbers","text":"Base.count_ones\nBase.count_zeros\nBase.leading_zeros\nBase.leading_ones\nBase.trailing_zeros\nBase.trailing_ones\nBase.isodd\nBase.iseven\nBase.@int128_str\nBase.@uint128_str","category":"page"},{"location":"base/numbers/#Base.count_ones","page":"Numbers","title":"Base.count_ones","text":"count_ones(x::Integer) -> Integer\n\nNumber of ones in the binary representation of x.\n\nExamples\n\njulia> count_ones(7)\n3\n\njulia> count_ones(Int32(-1))\n32\n\n\n\n\n\n","category":"function"},{"location":"base/numbers/#Base.count_zeros","page":"Numbers","title":"Base.count_zeros","text":"count_zeros(x::Integer) -> Integer\n\nNumber of zeros in the binary representation of x.\n\nExamples\n\njulia> count_zeros(Int32(2 ^ 16 - 1))\n16\n\njulia> count_zeros(-1)\n0\n\n\n\n\n\n","category":"function"},{"location":"base/numbers/#Base.leading_zeros","page":"Numbers","title":"Base.leading_zeros","text":"leading_zeros(x::Integer) -> Integer\n\nNumber of zeros leading the binary representation of x.\n\nExamples\n\njulia> leading_zeros(Int32(1))\n31\n\n\n\n\n\n","category":"function"},{"location":"base/numbers/#Base.leading_ones","page":"Numbers","title":"Base.leading_ones","text":"leading_ones(x::Integer) -> Integer\n\nNumber of ones leading the binary representation of x.\n\nExamples\n\njulia> leading_ones(UInt32(2 ^ 32 - 2))\n31\n\n\n\n\n\n","category":"function"},{"location":"base/numbers/#Base.trailing_zeros","page":"Numbers","title":"Base.trailing_zeros","text":"trailing_zeros(x::Integer) -> Integer\n\nNumber of zeros trailing the binary representation of x.\n\nExamples\n\njulia> trailing_zeros(2)\n1\n\n\n\n\n\n","category":"function"},{"location":"base/numbers/#Base.trailing_ones","page":"Numbers","title":"Base.trailing_ones","text":"trailing_ones(x::Integer) -> Integer\n\nNumber of ones trailing the binary representation of x.\n\nExamples\n\njulia> trailing_ones(3)\n2\n\n\n\n\n\n","category":"function"},{"location":"base/numbers/#Base.isodd","page":"Numbers","title":"Base.isodd","text":"isodd(x::Number) -> Bool\n\nReturn true if x is an odd integer (that is, an integer not divisible by 2), and false otherwise.\n\ncompat: Julia 1.7\nNon-Integer arguments require Julia 1.7 or later.\n\nExamples\n\njulia> isodd(9)\ntrue\n\njulia> isodd(10)\nfalse\n\n\n\n\n\n","category":"function"},{"location":"base/numbers/#Base.iseven","page":"Numbers","title":"Base.iseven","text":"iseven(x::Number) -> Bool\n\nReturn true if x is an even integer (that is, an integer divisible by 2), and false otherwise.\n\ncompat: Julia 1.7\nNon-Integer arguments require Julia 1.7 or later.\n\nExamples\n\njulia> iseven(9)\nfalse\n\njulia> iseven(10)\ntrue\n\n\n\n\n\n","category":"function"},{"location":"base/numbers/#Core.@int128_str","page":"Numbers","title":"Core.@int128_str","text":"@int128_str str\n@int128_str(str)\n\n@int128_str parses a string into a Int128. Throws an ArgumentError if the string is not a valid integer.\n\n\n\n\n\n","category":"macro"},{"location":"base/numbers/#Core.@uint128_str","page":"Numbers","title":"Core.@uint128_str","text":"@uint128_str str\n@uint128_str(str)\n\n@uint128_str parses a string into a UInt128. Throws an ArgumentError if the string is not a valid integer.\n\n\n\n\n\n","category":"macro"},{"location":"base/numbers/#BigFloats-and-BigInts","page":"Numbers","title":"BigFloats and BigInts","text":"","category":"section"},{"location":"base/numbers/","page":"Numbers","title":"Numbers","text":"The BigFloat and BigInt types implements arbitrary-precision floating point and integer arithmetic, respectively. For BigFloat the GNU MPFR library is used, and for BigInt the GNU Multiple Precision Arithmetic Library (GMP) is used.","category":"page"},{"location":"base/numbers/","page":"Numbers","title":"Numbers","text":"Base.MPFR.BigFloat(::Any, rounding::RoundingMode)\nBase.precision\nBase.MPFR.precision(::Type{BigFloat})\nBase.MPFR.setprecision\nBase.GMP.BigInt(::Any)\nBase.@big_str","category":"page"},{"location":"base/numbers/#Base.MPFR.BigFloat-Tuple{Any, RoundingMode}","page":"Numbers","title":"Base.MPFR.BigFloat","text":"BigFloat(x::Union{Real, AbstractString} [, rounding::RoundingMode=rounding(BigFloat)]; [precision::Integer=precision(BigFloat)])\n\nCreate an arbitrary precision floating point number from x, with precision precision. The rounding argument specifies the direction in which the result should be rounded if the conversion cannot be done exactly. If not provided, these are set by the current global values.\n\nBigFloat(x::Real) is the same as convert(BigFloat,x), except if x itself is already BigFloat, in which case it will return a value with the precision set to the current global precision; convert will always return x.\n\nBigFloat(x::AbstractString) is identical to parse. This is provided for convenience since decimal literals are converted to Float64 when parsed, so BigFloat(2.1) may not yield what you expect.\n\nSee also:\n\n@big_str\nrounding and setrounding\nprecision and setprecision\n\ncompat: Julia 1.1\nprecision as a keyword argument requires at least Julia 1.1. In Julia 1.0 precision is the second positional argument (BigFloat(x, precision)).\n\nExamples\n\njulia> BigFloat(2.1) # 2.1 here is a Float64\n2.100000000000000088817841970012523233890533447265625\n\njulia> BigFloat(\"2.1\") # the closest BigFloat to 2.1\n2.099999999999999999999999999999999999999999999999999999999999999999999999999986\n\njulia> BigFloat(\"2.1\", RoundUp)\n2.100000000000000000000000000000000000000000000000000000000000000000000000000021\n\njulia> BigFloat(\"2.1\", RoundUp, precision=128)\n2.100000000000000000000000000000000000007\n\n\n\n\n\n","category":"method"},{"location":"base/numbers/#Base.precision","page":"Numbers","title":"Base.precision","text":"precision(num::AbstractFloat; base::Integer=2)\nprecision(T::Type; base::Integer=2)\n\nGet the precision of a floating point number, as defined by the effective number of bits in the significand, or the precision of a floating-point type T (its current default, if T is a variable-precision type like BigFloat).\n\nIf base is specified, then it returns the maximum corresponding number of significand digits in that base.\n\ncompat: Julia 1.8\nThe base keyword requires at least Julia 1.8.\n\n\n\n\n\n","category":"function"},{"location":"base/numbers/#Base.MPFR.setprecision","page":"Numbers","title":"Base.MPFR.setprecision","text":"setprecision([T=BigFloat,] precision::Int; base=2)\n\nSet the precision (in bits, by default) to be used for T arithmetic. If base is specified, then the precision is the minimum required to give at least precision digits in the given base.\n\nwarning: Warning\nThis function is not thread-safe. It will affect code running on all threads, but its behavior is undefined if called concurrently with computations that use the setting.\n\ncompat: Julia 1.8\nThe base keyword requires at least Julia 1.8.\n\n\n\n\n\nsetprecision(f::Function, [T=BigFloat,] precision::Integer; base=2)\n\nChange the T arithmetic precision (in the given base) for the duration of f. It is logically equivalent to:\n\nold = precision(BigFloat)\nsetprecision(BigFloat, precision)\nf()\nsetprecision(BigFloat, old)\n\nOften used as setprecision(T, precision) do ... end\n\nNote: nextfloat(), prevfloat() do not use the precision mentioned by setprecision.\n\ncompat: Julia 1.8\nThe base keyword requires at least Julia 1.8.\n\n\n\n\n\n","category":"function"},{"location":"base/numbers/#Base.GMP.BigInt-Tuple{Any}","page":"Numbers","title":"Base.GMP.BigInt","text":"BigInt(x)\n\nCreate an arbitrary precision integer. x may be an Int (or anything that can be converted to an Int). The usual mathematical operators are defined for this type, and results are promoted to a BigInt.\n\nInstances can be constructed from strings via parse, or using the big string literal.\n\nExamples\n\njulia> parse(BigInt, \"42\")\n42\n\njulia> big\"313\"\n313\n\njulia> BigInt(10)^19\n10000000000000000000\n\n\n\n\n\n","category":"method"},{"location":"base/numbers/#Core.@big_str","page":"Numbers","title":"Core.@big_str","text":"@big_str str\n@big_str(str)\n\nParse a string into a BigInt or BigFloat, and throw an ArgumentError if the string is not a valid number. For integers _ is allowed in the string as a separator.\n\nExamples\n\njulia> big\"123_456\"\n123456\n\njulia> big\"7891.5\"\n7891.5\n\n\n\n\n\n","category":"macro"},{"location":"manual/missing/#missing","page":"缺失值","title":"缺失值","text":"","category":"section"},{"location":"manual/missing/","page":"缺失值","title":"缺失值","text":"Julia 支持表示统计意义上的缺失值,即某个变量在观察中没有可用值,但在理论上存在有效值的情况。缺失值由 missing 对象表示,该对象是 Missing 类型的唯一实例。missing 等价于 SQL 中的 NULL 以及 R 中的 NA,并在大多数情况下表现得与它们一样。","category":"page"},{"location":"manual/missing/#缺失值的传播","page":"缺失值","title":"缺失值的传播","text":"","category":"section"},{"location":"manual/missing/","page":"缺失值","title":"缺失值","text":"missing 值会自动在标准数学运算符和函数中传播。对于这类函数,其某个运算对象的值的不确定性会导致其结果的不确定性。在应用中,上述情形意味着若在数学操作中包括 missing 值,其结果也常常返回 missing 值。","category":"page"},{"location":"manual/missing/","page":"缺失值","title":"缺失值","text":"julia> missing + 1\nmissing\n\njulia> \"a\" * missing\nmissing\n\njulia> abs(missing)\nmissing","category":"page"},{"location":"manual/missing/","page":"缺失值","title":"缺失值","text":"由于missing 是 Julia 中的正常对象,此传播规则仅在可实现该对象的函数中应用。这可通过定义包含 Missing 类的实参的特定方法,或是简单地让函数可接受此类实参,并将该它们传入已具备传播规则的函数(如标准数学运算符)中实现。在包中定义新传播规则时,应考虑缺失值的传播是否具有实际意义,并在传播有意义时定义合适的方法。在某个不包含接受 Missing 类实参方法的函数中传递缺失值,则抛出 MethodError的报错,正如其它类型一样。","category":"page"},{"location":"manual/missing/","page":"缺失值","title":"缺失值","text":"若希望函数不传播缺失值,可将其按照 Missings.jl 库中的 passmissing 函数封装起来。例如,将 f(x) 封装为 passmissing(f)(x)。","category":"page"},{"location":"manual/missing/#相等和比较运算符","page":"缺失值","title":"相等和比较运算符","text":"","category":"section"},{"location":"manual/missing/","page":"缺失值","title":"缺失值","text":"标准相等和比较运算符遵循上面给出的传播规则:如果任何操作数是 missing,那么结果是 missing。这是一些例子","category":"page"},{"location":"manual/missing/","page":"缺失值","title":"缺失值","text":"julia> missing == 1\nmissing\n\njulia> missing == missing\nmissing\n\njulia> missing < 1\nmissing\n\njulia> 2 >= missing\nmissing","category":"page"},{"location":"manual/missing/","page":"缺失值","title":"缺失值","text":"特别要注意,missing == missing 返回 missing,所以 == 不能用于测试值是否为缺失值。要测试 x 是否为 missing,请用 ismissing(x)。","category":"page"},{"location":"manual/missing/","page":"缺失值","title":"缺失值","text":"特殊的比较运算符 isequal 和 === 是传播规则的例外:它们总返回一个 Bool 值,即使存在 missing 值,并认为 missing 与 missing 相等且其与任何其它值不同。因此,它们可用于测试某个值是否为 missing。","category":"page"},{"location":"manual/missing/","page":"缺失值","title":"缺失值","text":"julia> missing === 1\nfalse\n\njulia> isequal(missing, 1)\nfalse\n\njulia> missing === missing\ntrue\n\njulia> isequal(missing, missing)\ntrue","category":"page"},{"location":"manual/missing/","page":"缺失值","title":"缺失值","text":"isless 运算符是另一个例外:missing 被认为比任何其它值大。此运算符被用于 sort,因此 missing 值被放置在所有其它值之后。","category":"page"},{"location":"manual/missing/","page":"缺失值","title":"缺失值","text":"julia> isless(1, missing)\ntrue\n\njulia> isless(missing, Inf)\nfalse\n\njulia> isless(missing, missing)\nfalse","category":"page"},{"location":"manual/missing/#逻辑运算符","page":"缺失值","title":"逻辑运算符","text":"","category":"section"},{"location":"manual/missing/","page":"缺失值","title":"缺失值","text":"逻辑(或布尔)运算符 |、& 和 xor 是另一种特殊情况,因为它们只有在逻辑上是必需的时传递 missing 值。对于这些运算符来说,结果是否不确定取决于具体操作,其遵循三值逻辑的既定规则,这些规则也由 SQL 中的 NULL 以及 R 中的 NA 实现。这个抽象的定义实际上对应于一系列相对自然的行为,这最好通过具体的例子来解释。","category":"page"},{"location":"manual/missing/","page":"缺失值","title":"缺失值","text":"让我们用逻辑「或」运算符 | 来说明这个原理。按照布尔逻辑的规则,如果其中一个操作数是 true,则另一个操作数对结果没影响,结果总是 true。","category":"page"},{"location":"manual/missing/","page":"缺失值","title":"缺失值","text":"julia> true | true\ntrue\n\njulia> true | false\ntrue\n\njulia> false | true\ntrue","category":"page"},{"location":"manual/missing/","page":"缺失值","title":"缺失值","text":"基于观察,我们可以得出结论,如果其中一个操作数是 true 而另一个是 missing,我们知道结果为 true,尽管另一个参数的实际值存在不确定性。如果我们能观察到第二个操作数的实际值,那么它只能是 true 或 false,在两种情况下结果都是 true。因此,在这种特殊情况下,值的缺失不会传播","category":"page"},{"location":"manual/missing/","page":"缺失值","title":"缺失值","text":"julia> true | missing\ntrue\n\njulia> missing | true\ntrue","category":"page"},{"location":"manual/missing/","page":"缺失值","title":"缺失值","text":"相反地,如果其中一个操作数是 false,结果可能是 true 或 false,这取决于另一个操作数的值。因此,如果一个操作数是 missing,那么结果也是 missing。","category":"page"},{"location":"manual/missing/","page":"缺失值","title":"缺失值","text":"julia> false | true\ntrue\n\njulia> true | false\ntrue\n\njulia> false | false\nfalse\n\njulia> false | missing\nmissing\n\njulia> missing | false\nmissing","category":"page"},{"location":"manual/missing/","page":"缺失值","title":"缺失值","text":"逻辑「且」运算符 & 的行为与 | 运算符相似,区别在于当其中一个操作数为 false 时,值的缺失不会传播。例如,当第一个操作数是 false 时","category":"page"},{"location":"manual/missing/","page":"缺失值","title":"缺失值","text":"julia> false & false\nfalse\n\njulia> false & true\nfalse\n\njulia> false & missing\nfalse","category":"page"},{"location":"manual/missing/","page":"缺失值","title":"缺失值","text":"另一方面,当其中一个操作数为 true 时,值的缺失会传播,例如,当第一个操作数是 true 时","category":"page"},{"location":"manual/missing/","page":"缺失值","title":"缺失值","text":"julia> true & true\ntrue\n\njulia> true & false\nfalse\n\njulia> true & missing\nmissing","category":"page"},{"location":"manual/missing/","page":"缺失值","title":"缺失值","text":"最后,逻辑「异或」运算符 xor 总传播 missing 值,因为两个操作数都总是对结果产生影响。还要注意,否定运算符 ! 在操作数是 missing 时返回 missing,这就像其它一元运算符。","category":"page"},{"location":"manual/missing/#流程控制和短路运算符","page":"缺失值","title":"流程控制和短路运算符","text":"","category":"section"},{"location":"manual/missing/","page":"缺失值","title":"缺失值","text":"流程控制操作符,包括 if、while 和三元运算符 x ? y : z,不允许缺失值。这是因为如果我们能够观察实际值,它是 true 还是 false 是不确定的,这意味着我们不知道程序应该如何运行。一旦在以下上下文中遇到 missing 值,就会抛出 TypeError","category":"page"},{"location":"manual/missing/","page":"缺失值","title":"缺失值","text":"julia> if missing\n println(\"here\")\n end\nERROR: TypeError: non-boolean (Missing) used in boolean context","category":"page"},{"location":"manual/missing/","page":"缺失值","title":"缺失值","text":"出于同样的原因,并与上面给出的逻辑运算符相反,短路布尔运算符 && 和 || 在当前操作数的值决定下一个操作数是否求值时不允许 missing 值。例如","category":"page"},{"location":"manual/missing/","page":"缺失值","title":"缺失值","text":"julia> missing || false\nERROR: TypeError: non-boolean (Missing) used in boolean context\n\njulia> missing && false\nERROR: TypeError: non-boolean (Missing) used in boolean context\n\njulia> true && missing && false\nERROR: TypeError: non-boolean (Missing) used in boolean context","category":"page"},{"location":"manual/missing/","page":"缺失值","title":"缺失值","text":"另一方面,如果无需 missing 值即可确定结果,则不会引发错误。代码在对 missing 操作数求值前短路,以及 missing 是最后一个操作数都是这种情况。","category":"page"},{"location":"manual/missing/","page":"缺失值","title":"缺失值","text":"julia> true && missing\nmissing\n\njulia> false && missing\nfalse","category":"page"},{"location":"manual/missing/#包含缺失值的数组","page":"缺失值","title":"包含缺失值的数组","text":"","category":"section"},{"location":"manual/missing/","page":"缺失值","title":"缺失值","text":"包含缺失值的数组的创建就像其它数组","category":"page"},{"location":"manual/missing/","page":"缺失值","title":"缺失值","text":"julia> [1, missing]\n2-element Vector{Union{Missing, Int64}}:\n 1\n missing","category":"page"},{"location":"manual/missing/","page":"缺失值","title":"缺失值","text":"如此示例所示,此类数组的元素类型为 Union{Missing, T},其中 T 为非缺失值的类型。这简单地反映了以下事实:数组条目可以具有类型 T(此处为 Int64)或类型 Missing。此类数组使用高效的内存存储,其等价于一个 Array{T} 和一个 Array{UInt8} 的组合,前者保存实际值,后者表示条目类型(即它是 Missing 还是 T)。","category":"page"},{"location":"manual/missing/","page":"缺失值","title":"缺失值","text":"允许缺失值的数组可以使用标准语法构造。使用 Array{Union{Missing, T}}(missing, dims) 来创建填充缺失值的数组:","category":"page"},{"location":"manual/missing/","page":"缺失值","title":"缺失值","text":"julia> Array{Union{Missing, String}}(missing, 2, 3)\n2×3 Matrix{Union{Missing, String}}:\n missing missing missing\n missing missing missing","category":"page"},{"location":"manual/missing/","page":"缺失值","title":"缺失值","text":"note: Note\n使用 undef 或 similar 目前可能会给出一个填充有 missing 的数组,但这不是获得这样一个数组的正确方法。 请使用如上所示的 missing 构造函数。","category":"page"},{"location":"manual/missing/","page":"缺失值","title":"缺失值","text":"允许但不包含 missing 值的数组可使用 convert 转换回不允许缺失值的数组。如果该数组包含 missing 值,在类型转换时会抛出 MethodError","category":"page"},{"location":"manual/missing/","page":"缺失值","title":"缺失值","text":"julia> x = Union{Missing, String}[\"a\", \"b\"]\n2-element Vector{Union{Missing, String}}:\n \"a\"\n \"b\"\n\njulia> convert(Array{String}, x)\n2-element Vector{String}:\n \"a\"\n \"b\"\n\njulia> y = Union{Missing, String}[missing, \"b\"]\n2-element Vector{Union{Missing, String}}:\n missing\n \"b\"\n\njulia> convert(Array{String}, y)\nERROR: MethodError: Cannot `convert` an object of type Missing to an object of type String","category":"page"},{"location":"manual/missing/#跳过缺失值","page":"缺失值","title":"跳过缺失值","text":"","category":"section"},{"location":"manual/missing/","page":"缺失值","title":"缺失值","text":"由于 missing 会随着标准数学运算符传播,归约函数会在调用的数组包含缺失值时返回 missing","category":"page"},{"location":"manual/missing/","page":"缺失值","title":"缺失值","text":"julia> sum([1, missing])\nmissing","category":"page"},{"location":"manual/missing/","page":"缺失值","title":"缺失值","text":"在这种情况下,使用 skipmissing 即可跳过缺失值","category":"page"},{"location":"manual/missing/","page":"缺失值","title":"缺失值","text":"julia> sum(skipmissing([1, missing]))\n1","category":"page"},{"location":"manual/missing/","page":"缺失值","title":"缺失值","text":"此函数方便地返回一个可高效滤除 missing 值的迭代器。因此,它可应用于所有支持迭代器的函数 ","category":"page"},{"location":"manual/missing/","page":"缺失值","title":"缺失值","text":"julia> x = skipmissing([3, missing, 2, 1])\nskipmissing(Union{Missing, Int64}[3, missing, 2, 1])\n\njulia> maximum(x)\n3\n\njulia> mean(x)\n2.0\n\njulia> mapreduce(sqrt, +, x)\n4.146264369941973\n","category":"page"},{"location":"manual/missing/","page":"缺失值","title":"缺失值","text":"通过在某数组中调用 skipmissing 生成的对象能以其在所属数组中的位置进行索引。对应缺失值的指标并不有效,若尝试使用之会丢出报错(它们在 keys 和 eachindex 中同样是被跳过的)。","category":"page"},{"location":"manual/missing/","page":"缺失值","title":"缺失值","text":"julia> x[1]\n3\n\njulia> x[2]\nERROR: MissingException: the value at index (2,) is missing\n[...]","category":"page"},{"location":"manual/missing/","page":"缺失值","title":"缺失值","text":"这允许对索引进行操作的函数与skipmissing结合使用。搜索和查找函数尤其如此,它们返回对skipmissing 函数返回的对象有效的索引,这些索引也是在父数组中匹配条目的索引。","category":"page"},{"location":"manual/missing/","page":"缺失值","title":"缺失值","text":"julia> findall(==(1), x)\n1-element Vector{Int64}:\n 4\n\njulia> findfirst(!iszero, x)\n1\n\njulia> argmax(x)\n1","category":"page"},{"location":"manual/missing/","page":"缺失值","title":"缺失值","text":"使用 collect 提取非 missing 值并将它们存储在一个数组里","category":"page"},{"location":"manual/missing/","page":"缺失值","title":"缺失值","text":"julia> collect(x)\n3-element Vector{Int64}:\n 3\n 2\n 1","category":"page"},{"location":"manual/missing/#数组上的逻辑运算","page":"缺失值","title":"数组上的逻辑运算","text":"","category":"section"},{"location":"manual/missing/","page":"缺失值","title":"缺失值","text":"上面描述的逻辑运算符的三值逻辑也适用于针对数组的函数。因此,使用 == 运算符的数组相等性测试中,若在未知 missing 条目实际值时无法确定结果,就返回 missing。在实际应用中意味着,在待比较数组中所有非缺失值都相等,且某个或全部数组包含缺失值(也许在不同位置)时会返回 missing。","category":"page"},{"location":"manual/missing/","page":"缺失值","title":"缺失值","text":"julia> [1, missing] == [2, missing]\nfalse\n\njulia> [1, missing] == [1, missing]\nmissing\n\njulia> [1, 2, missing] == [1, missing, 2]\nmissing","category":"page"},{"location":"manual/missing/","page":"缺失值","title":"缺失值","text":"对于单个值,isequal 会将 missing 值视为与其它 missing 值相等但与非缺失值不同。","category":"page"},{"location":"manual/missing/","page":"缺失值","title":"缺失值","text":"julia> isequal([1, missing], [1, missing])\ntrue\n\njulia> isequal([1, 2, missing], [1, missing, 2])\nfalse","category":"page"},{"location":"manual/missing/","page":"缺失值","title":"缺失值","text":"函数 any 和 all 遵循三值逻辑的规则,会在结果无法被确定时返回 missing。","category":"page"},{"location":"manual/missing/","page":"缺失值","title":"缺失值","text":"julia> all([true, missing])\nmissing\n\njulia> all([false, missing])\nfalse\n\njulia> any([true, missing])\ntrue\n\njulia> any([false, missing])\nmissing","category":"page"},{"location":"base/multi-threading/#lib-multithreading","page":"Multi-Threading","title":"Multi-Threading","text":"","category":"section"},{"location":"base/multi-threading/","page":"Multi-Threading","title":"Multi-Threading","text":"Base.Threads.@threads\nBase.Threads.foreach\nBase.Threads.@spawn\nBase.Threads.threadid\nBase.Threads.nthreads","category":"page"},{"location":"base/multi-threading/#Base.Threads.@threads","page":"Multi-Threading","title":"Base.Threads.@threads","text":"Threads.@threads [schedule] for ... end\n\nA macro to execute a for loop in parallel. The iteration space is distributed to coarse-grained tasks. This policy can be specified by the schedule argument. The execution of the loop waits for the evaluation of all iterations.\n\nSee also: @spawn and pmap in Distributed.\n\nExtended help\n\nSemantics\n\nUnless stronger guarantees are specified by the scheduling option, the loop executed by @threads macro have the following semantics.\n\nThe @threads macro executes the loop body in an unspecified order and potentially concurrently. It does not specify the exact assignments of the tasks and the worker threads. The assignments can be different for each execution. The loop body code (including any code transitively called from it) must not make any assumptions about the distribution of iterations to tasks or the worker thread in which they are executed. The loop body for each iteration must be able to make forward progress independent of other iterations and be free from data races. As such, invalid synchronizations across iterations may deadlock while unsynchronized memory accesses may result in undefined behavior.\n\nFor example, the above conditions imply that:\n\nThe lock taken in an iteration must be released within the same iteration.\nCommunicating between iterations using blocking primitives like Channels is incorrect.\nWrite only to locations not shared across iterations (unless a lock or atomic operation is used).\nThe value of threadid() may change even within a single iteration.\n\nSchedulers\n\nWithout the scheduler argument, the exact scheduling is unspecified and varies across Julia releases. Currently, :dynamic is used when the scheduler is not specified.\n\ncompat: Julia 1.5\nThe schedule argument is available as of Julia 1.5.\n\n:dynamic (default)\n\n:dynamic scheduler executes iterations dynamically to available worker threads. Current implementation assumes that the workload for each iteration is uniform. However, this assumption may be removed in the future.\n\nThis scheduling option is merely a hint to the underlying execution mechanism. However, a few properties can be expected. The number of Tasks used by :dynamic scheduler is bounded by a small constant multiple of the number of available worker threads (nthreads()). Each task processes contiguous regions of the iteration space. Thus, @threads :dynamic for x in xs; f(x); end is typically more efficient than @sync for x in xs; @spawn f(x); end if length(xs) is significantly larger than the number of the worker threads and the run-time of f(x) is relatively smaller than the cost of spawning and synchronizaing a task (typically less than 10 microseconds).\n\ncompat: Julia 1.8\nThe :dynamic option for the schedule argument is available and the default as of Julia 1.8.\n\n:static\n\n:static scheduler creates one task per thread and divides the iterations equally among them, assigning each task specifically to each thread. In particular, the value of threadid() is guranteed to be constant within one iteration. Specifying :static is an error if used from inside another @threads loop or from a thread other than 1.\n\nnote: Note\n:static scheduling exists for supporting transition of code written before Julia 1.3. In newly written library functions, :static scheduling is discouraged because the functions using this option cannot be called from arbitrary worker threads.\n\nExample\n\nTo illustrate of the different scheduling strategies, consider the following function busywait containing a non-yielding timed loop that runs for a given number of seconds.\n\njulia> function busywait(seconds)\n tstart = time_ns()\n while (time_ns() - tstart) / 1e9 < seconds\n end\n end\n\njulia> @time begin\n Threads.@spawn busywait(5)\n Threads.@threads :static for i in 1:Threads.nthreads()\n busywait(1)\n end\n end\n6.003001 seconds (16.33 k allocations: 899.255 KiB, 0.25% compilation time)\n\njulia> @time begin\n Threads.@spawn busywait(5)\n Threads.@threads :dynamic for i in 1:Threads.nthreads()\n busywait(1)\n end\n end\n2.012056 seconds (16.05 k allocations: 883.919 KiB, 0.66% compilation time)\n\nThe :dynamic example takes 2 seconds since one of the non-occupied threads is able to run two of the 1-second iterations to complete the for loop.\n\n\n\n\n\n","category":"macro"},{"location":"base/multi-threading/#Base.Threads.foreach","page":"Multi-Threading","title":"Base.Threads.foreach","text":"Threads.foreach(f, channel::Channel;\n schedule::Threads.AbstractSchedule=Threads.FairSchedule(),\n ntasks=Threads.nthreads())\n\nSimilar to foreach(f, channel), but iteration over channel and calls to f are split across ntasks tasks spawned by Threads.@spawn. This function will wait for all internally spawned tasks to complete before returning.\n\nIf schedule isa FairSchedule, Threads.foreach will attempt to spawn tasks in a manner that enables Julia's scheduler to more freely load-balance work items across threads. This approach generally has higher per-item overhead, but may perform better than StaticSchedule in concurrence with other multithreaded workloads.\n\nIf schedule isa StaticSchedule, Threads.foreach will spawn tasks in a manner that incurs lower per-item overhead than FairSchedule, but is less amenable to load-balancing. This approach thus may be more suitable for fine-grained, uniform workloads, but may perform worse than FairSchedule in concurrence with other multithreaded workloads.\n\ncompat: Julia 1.6\nThis function requires Julia 1.6 or later.\n\n\n\n\n\n","category":"function"},{"location":"base/multi-threading/#Base.Threads.@spawn","page":"Multi-Threading","title":"Base.Threads.@spawn","text":"Threads.@spawn expr\n\nCreate a Task and schedule it to run on any available thread. The task is allocated to a thread after it becomes available. To wait for the task to finish, call wait on the result of this macro, or call fetch to wait and then obtain its return value.\n\nValues can be interpolated into @spawn via $, which copies the value directly into the constructed underlying closure. This allows you to insert the value of a variable, isolating the asynchronous code from changes to the variable's value in the current task.\n\nnote: Note\nSee the manual chapter on threading for important caveats.\n\ncompat: Julia 1.3\nThis macro is available as of Julia 1.3.\n\ncompat: Julia 1.4\nInterpolating values via $ is available as of Julia 1.4.\n\n\n\n\n\n","category":"macro"},{"location":"base/multi-threading/#Base.Threads.threadid","page":"Multi-Threading","title":"Base.Threads.threadid","text":"Threads.threadid()\n\nGet the ID number of the current thread of execution. The master thread has ID 1.\n\n\n\n\n\n","category":"function"},{"location":"base/multi-threading/#Base.Threads.nthreads","page":"Multi-Threading","title":"Base.Threads.nthreads","text":"Threads.nthreads()\n\nGet the number of threads available to the Julia process. This is the inclusive upper bound on threadid().\n\nSee also: BLAS.get_num_threads and BLAS.set_num_threads in the LinearAlgebra standard library, and nprocs() in the Distributed standard library.\n\n\n\n\n\n","category":"function"},{"location":"base/multi-threading/#同步","page":"Multi-Threading","title":"同步","text":"","category":"section"},{"location":"base/multi-threading/","page":"Multi-Threading","title":"Multi-Threading","text":"Base.Threads.Condition\nBase.Threads.Event","category":"page"},{"location":"base/multi-threading/#Base.Threads.Condition","page":"Multi-Threading","title":"Base.Threads.Condition","text":"Threads.Condition([lock])\n\nA thread-safe version of Base.Condition.\n\nTo call wait or notify on a Threads.Condition, you must first call lock on it. When wait is called, the lock is atomically released during blocking, and will be reacquired before wait returns. Therefore idiomatic use of a Threads.Condition c looks like the following:\n\nlock(c)\ntry\n while !thing_we_are_waiting_for\n wait(c)\n end\nfinally\n unlock(c)\nend\n\ncompat: Julia 1.2\nThis functionality requires at least Julia 1.2.\n\n\n\n\n\n","category":"type"},{"location":"base/multi-threading/#Base.Event","page":"Multi-Threading","title":"Base.Event","text":"Event([autoreset=false])\n\nCreate a level-triggered event source. Tasks that call wait on an Event are suspended and queued until notify is called on the Event. After notify is called, the Event remains in a signaled state and tasks will no longer block when waiting for it, until reset is called.\n\nIf autoreset is true, at most one task will be released from wait for each call to notify.\n\nThis provides an acquire & release memory ordering on notify/wait.\n\ncompat: Julia 1.1\nThis functionality requires at least Julia 1.1.\n\ncompat: Julia 1.8\nThe autoreset functionality and memory ordering guarantee requires at least Julia 1.8.\n\n\n\n\n\n","category":"type"},{"location":"base/multi-threading/","page":"Multi-Threading","title":"Multi-Threading","text":"另见 同步 。","category":"page"},{"location":"base/multi-threading/#原子操作","page":"Multi-Threading","title":"原子操作","text":"","category":"section"},{"location":"base/multi-threading/","page":"Multi-Threading","title":"Multi-Threading","text":"Base.@atomic\nBase.@atomicswap\nBase.@atomicreplace","category":"page"},{"location":"base/multi-threading/#Base.@atomic","page":"Multi-Threading","title":"Base.@atomic","text":"@atomic var\n@atomic order ex\n\nMark var or ex as being performed atomically, if ex is a supported expression.\n\n@atomic a.b.x = new\n@atomic a.b.x += addend\n@atomic :release a.b.x = new\n@atomic :acquire_release a.b.x += addend\n\nPerform the store operation expressed on the right atomically and return the new value.\n\nWith =, this operation translates to a setproperty!(a.b, :x, new) call. With any operator also, this operation translates to a modifyproperty!(a.b, :x, +, addend)[2] call.\n\n@atomic a.b.x max arg2\n@atomic a.b.x + arg2\n@atomic max(a.b.x, arg2)\n@atomic :acquire_release max(a.b.x, arg2)\n@atomic :acquire_release a.b.x + arg2\n@atomic :acquire_release a.b.x max arg2\n\nPerform the binary operation expressed on the right atomically. Store the result into the field in the first argument and return the values (old, new).\n\nThis operation translates to a modifyproperty!(a.b, :x, func, arg2) call.\n\nSee Per-field atomics section in the manual for more details.\n\njulia> mutable struct Atomic{T}; @atomic x::T; end\n\njulia> a = Atomic(1)\nAtomic{Int64}(1)\n\njulia> @atomic a.x # fetch field x of a, with sequential consistency\n1\n\njulia> @atomic :sequentially_consistent a.x = 2 # set field x of a, with sequential consistency\n2\n\njulia> @atomic a.x += 1 # increment field x of a, with sequential consistency\n3\n\njulia> @atomic a.x + 1 # increment field x of a, with sequential consistency\n3 => 4\n\njulia> @atomic a.x # fetch field x of a, with sequential consistency\n4\n\njulia> @atomic max(a.x, 10) # change field x of a to the max value, with sequential consistency\n4 => 10\n\njulia> @atomic a.x max 5 # again change field x of a to the max value, with sequential consistency\n10 => 10\n\ncompat: Julia 1.7\nThis functionality requires at least Julia 1.7.\n\n\n\n\n\n","category":"macro"},{"location":"base/multi-threading/#Base.@atomicswap","page":"Multi-Threading","title":"Base.@atomicswap","text":"@atomicswap a.b.x = new\n@atomicswap :sequentially_consistent a.b.x = new\n\nStores new into a.b.x and returns the old value of a.b.x.\n\nThis operation translates to a swapproperty!(a.b, :x, new) call.\n\nSee Per-field atomics section in the manual for more details.\n\njulia> mutable struct Atomic{T}; @atomic x::T; end\n\njulia> a = Atomic(1)\nAtomic{Int64}(1)\n\njulia> @atomicswap a.x = 2+2 # replace field x of a with 4, with sequential consistency\n1\n\njulia> @atomic a.x # fetch field x of a, with sequential consistency\n4\n\ncompat: Julia 1.7\nThis functionality requires at least Julia 1.7.\n\n\n\n\n\n","category":"macro"},{"location":"base/multi-threading/#Base.@atomicreplace","page":"Multi-Threading","title":"Base.@atomicreplace","text":"@atomicreplace a.b.x expected => desired\n@atomicreplace :sequentially_consistent a.b.x expected => desired\n@atomicreplace :sequentially_consistent :monotonic a.b.x expected => desired\n\nPerform the conditional replacement expressed by the pair atomically, returning the values (old, success::Bool). Where success indicates whether the replacement was completed.\n\nThis operation translates to a replaceproperty!(a.b, :x, expected, desired) call.\n\nSee Per-field atomics section in the manual for more details.\n\njulia> mutable struct Atomic{T}; @atomic x::T; end\n\njulia> a = Atomic(1)\nAtomic{Int64}(1)\n\njulia> @atomicreplace a.x 1 => 2 # replace field x of a with 2 if it was 1, with sequential consistency\n(old = 1, success = true)\n\njulia> @atomic a.x # fetch field x of a, with sequential consistency\n2\n\njulia> @atomicreplace a.x 1 => 2 # replace field x of a with 2 if it was 1, with sequential consistency\n(old = 2, success = false)\n\njulia> xchg = 2 => 0; # replace field x of a with 0 if it was 1, with sequential consistency\n\njulia> @atomicreplace a.x xchg\n(old = 2, success = true)\n\njulia> @atomic a.x # fetch field x of a, with sequential consistency\n0\n\ncompat: Julia 1.7\nThis functionality requires at least Julia 1.7.\n\n\n\n\n\n","category":"macro"},{"location":"base/multi-threading/","page":"Multi-Threading","title":"Multi-Threading","text":"note: Note\nThe following APIs are fairly primitive, and will likely be exposed through an unsafe_*-like wrapper.","category":"page"},{"location":"base/multi-threading/","page":"Multi-Threading","title":"Multi-Threading","text":"Core.Intrinsics.atomic_pointerref(pointer::Ptr{T}, order::Symbol) --> T\nCore.Intrinsics.atomic_pointerset(pointer::Ptr{T}, new::T, order::Symbol) --> pointer\nCore.Intrinsics.atomic_pointerswap(pointer::Ptr{T}, new::T, order::Symbol) --> old\nCore.Intrinsics.atomic_pointermodify(pointer::Ptr{T}, function::(old::T,arg::S)->T, arg::S, order::Symbol) --> old\nCore.Intrinsics.atomic_pointerreplace(pointer::Ptr{T}, expected::Any, new::T, success_order::Symbol, failure_order::Symbol) --> (old, cmp)","category":"page"},{"location":"base/multi-threading/","page":"Multi-Threading","title":"Multi-Threading","text":"warning: Warning\nThe following APIs are deprecated, though support for them is likely to remain for several releases.","category":"page"},{"location":"base/multi-threading/","page":"Multi-Threading","title":"Multi-Threading","text":"Base.Threads.Atomic\nBase.Threads.atomic_cas!\nBase.Threads.atomic_xchg!\nBase.Threads.atomic_add!\nBase.Threads.atomic_sub!\nBase.Threads.atomic_and!\nBase.Threads.atomic_nand!\nBase.Threads.atomic_or!\nBase.Threads.atomic_xor!\nBase.Threads.atomic_max!\nBase.Threads.atomic_min!\nBase.Threads.atomic_fence","category":"page"},{"location":"base/multi-threading/#Base.Threads.Atomic","page":"Multi-Threading","title":"Base.Threads.Atomic","text":"Threads.Atomic{T}\n\nHolds a reference to an object of type T, ensuring that it is only accessed atomically, i.e. in a thread-safe manner.\n\nOnly certain \"simple\" types can be used atomically, namely the primitive boolean, integer, and float-point types. These are Bool, Int8...Int128, UInt8...UInt128, and Float16...Float64.\n\nNew atomic objects can be created from a non-atomic values; if none is specified, the atomic object is initialized with zero.\n\nAtomic objects can be accessed using the [] notation:\n\nExamples\n\njulia> x = Threads.Atomic{Int}(3)\nBase.Threads.Atomic{Int64}(3)\n\njulia> x[] = 1\n1\n\njulia> x[]\n1\n\nAtomic operations use an atomic_ prefix, such as atomic_add!, atomic_xchg!, etc.\n\n\n\n\n\n","category":"type"},{"location":"base/multi-threading/#Base.Threads.atomic_cas!","page":"Multi-Threading","title":"Base.Threads.atomic_cas!","text":"Threads.atomic_cas!(x::Atomic{T}, cmp::T, newval::T) where T\n\nAtomically compare-and-set x\n\nAtomically compares the value in x with cmp. If equal, write newval to x. Otherwise, leaves x unmodified. Returns the old value in x. By comparing the returned value to cmp (via ===) one knows whether x was modified and now holds the new value newval.\n\nFor further details, see LLVM's cmpxchg instruction.\n\nThis function can be used to implement transactional semantics. Before the transaction, one records the value in x. After the transaction, the new value is stored only if x has not been modified in the mean time.\n\nExamples\n\njulia> x = Threads.Atomic{Int}(3)\nBase.Threads.Atomic{Int64}(3)\n\njulia> Threads.atomic_cas!(x, 4, 2);\n\njulia> x\nBase.Threads.Atomic{Int64}(3)\n\njulia> Threads.atomic_cas!(x, 3, 2);\n\njulia> x\nBase.Threads.Atomic{Int64}(2)\n\n\n\n\n\n","category":"function"},{"location":"base/multi-threading/#Base.Threads.atomic_xchg!","page":"Multi-Threading","title":"Base.Threads.atomic_xchg!","text":"Threads.atomic_xchg!(x::Atomic{T}, newval::T) where T\n\nAtomically exchange the value in x\n\nAtomically exchanges the value in x with newval. Returns the old value.\n\nFor further details, see LLVM's atomicrmw xchg instruction.\n\nExamples\n\njulia> x = Threads.Atomic{Int}(3)\nBase.Threads.Atomic{Int64}(3)\n\njulia> Threads.atomic_xchg!(x, 2)\n3\n\njulia> x[]\n2\n\n\n\n\n\n","category":"function"},{"location":"base/multi-threading/#Base.Threads.atomic_add!","page":"Multi-Threading","title":"Base.Threads.atomic_add!","text":"Threads.atomic_add!(x::Atomic{T}, val::T) where T <: ArithmeticTypes\n\nAtomically add val to x\n\nPerforms x[] += val atomically. Returns the old value. Not defined for Atomic{Bool}.\n\nFor further details, see LLVM's atomicrmw add instruction.\n\nExamples\n\njulia> x = Threads.Atomic{Int}(3)\nBase.Threads.Atomic{Int64}(3)\n\njulia> Threads.atomic_add!(x, 2)\n3\n\njulia> x[]\n5\n\n\n\n\n\n","category":"function"},{"location":"base/multi-threading/#Base.Threads.atomic_sub!","page":"Multi-Threading","title":"Base.Threads.atomic_sub!","text":"Threads.atomic_sub!(x::Atomic{T}, val::T) where T <: ArithmeticTypes\n\nAtomically subtract val from x\n\nPerforms x[] -= val atomically. Returns the old value. Not defined for Atomic{Bool}.\n\nFor further details, see LLVM's atomicrmw sub instruction.\n\nExamples\n\njulia> x = Threads.Atomic{Int}(3)\nBase.Threads.Atomic{Int64}(3)\n\njulia> Threads.atomic_sub!(x, 2)\n3\n\njulia> x[]\n1\n\n\n\n\n\n","category":"function"},{"location":"base/multi-threading/#Base.Threads.atomic_and!","page":"Multi-Threading","title":"Base.Threads.atomic_and!","text":"Threads.atomic_and!(x::Atomic{T}, val::T) where T\n\nAtomically bitwise-and x with val\n\nPerforms x[] &= val atomically. Returns the old value.\n\nFor further details, see LLVM's atomicrmw and instruction.\n\nExamples\n\njulia> x = Threads.Atomic{Int}(3)\nBase.Threads.Atomic{Int64}(3)\n\njulia> Threads.atomic_and!(x, 2)\n3\n\njulia> x[]\n2\n\n\n\n\n\n","category":"function"},{"location":"base/multi-threading/#Base.Threads.atomic_nand!","page":"Multi-Threading","title":"Base.Threads.atomic_nand!","text":"Threads.atomic_nand!(x::Atomic{T}, val::T) where T\n\nAtomically bitwise-nand (not-and) x with val\n\nPerforms x[] = ~(x[] & val) atomically. Returns the old value.\n\nFor further details, see LLVM's atomicrmw nand instruction.\n\nExamples\n\njulia> x = Threads.Atomic{Int}(3)\nBase.Threads.Atomic{Int64}(3)\n\njulia> Threads.atomic_nand!(x, 2)\n3\n\njulia> x[]\n-3\n\n\n\n\n\n","category":"function"},{"location":"base/multi-threading/#Base.Threads.atomic_or!","page":"Multi-Threading","title":"Base.Threads.atomic_or!","text":"Threads.atomic_or!(x::Atomic{T}, val::T) where T\n\nAtomically bitwise-or x with val\n\nPerforms x[] |= val atomically. Returns the old value.\n\nFor further details, see LLVM's atomicrmw or instruction.\n\nExamples\n\njulia> x = Threads.Atomic{Int}(5)\nBase.Threads.Atomic{Int64}(5)\n\njulia> Threads.atomic_or!(x, 7)\n5\n\njulia> x[]\n7\n\n\n\n\n\n","category":"function"},{"location":"base/multi-threading/#Base.Threads.atomic_xor!","page":"Multi-Threading","title":"Base.Threads.atomic_xor!","text":"Threads.atomic_xor!(x::Atomic{T}, val::T) where T\n\nAtomically bitwise-xor (exclusive-or) x with val\n\nPerforms x[] $= val atomically. Returns the old value.\n\nFor further details, see LLVM's atomicrmw xor instruction.\n\nExamples\n\njulia> x = Threads.Atomic{Int}(5)\nBase.Threads.Atomic{Int64}(5)\n\njulia> Threads.atomic_xor!(x, 7)\n5\n\njulia> x[]\n2\n\n\n\n\n\n","category":"function"},{"location":"base/multi-threading/#Base.Threads.atomic_max!","page":"Multi-Threading","title":"Base.Threads.atomic_max!","text":"Threads.atomic_max!(x::Atomic{T}, val::T) where T\n\nAtomically store the maximum of x and val in x\n\nPerforms x[] = max(x[], val) atomically. Returns the old value.\n\nFor further details, see LLVM's atomicrmw max instruction.\n\nExamples\n\njulia> x = Threads.Atomic{Int}(5)\nBase.Threads.Atomic{Int64}(5)\n\njulia> Threads.atomic_max!(x, 7)\n5\n\njulia> x[]\n7\n\n\n\n\n\n","category":"function"},{"location":"base/multi-threading/#Base.Threads.atomic_min!","page":"Multi-Threading","title":"Base.Threads.atomic_min!","text":"Threads.atomic_min!(x::Atomic{T}, val::T) where T\n\nAtomically store the minimum of x and val in x\n\nPerforms x[] = min(x[], val) atomically. Returns the old value.\n\nFor further details, see LLVM's atomicrmw min instruction.\n\nExamples\n\njulia> x = Threads.Atomic{Int}(7)\nBase.Threads.Atomic{Int64}(7)\n\njulia> Threads.atomic_min!(x, 5)\n7\n\njulia> x[]\n5\n\n\n\n\n\n","category":"function"},{"location":"base/multi-threading/#Base.Threads.atomic_fence","page":"Multi-Threading","title":"Base.Threads.atomic_fence","text":"Threads.atomic_fence()\n\nInsert a sequential-consistency memory fence\n\nInserts a memory fence with sequentially-consistent ordering semantics. There are algorithms where this is needed, i.e. where an acquire/release ordering is insufficient.\n\nThis is likely a very expensive operation. Given that all other atomic operations in Julia already have acquire/release semantics, explicit fences should not be necessary in most cases.\n\nFor further details, see LLVM's fence instruction.\n\n\n\n\n\n","category":"function"},{"location":"base/multi-threading/#ccall-using-a-threadpool-(Experimental)","page":"Multi-Threading","title":"ccall using a threadpool (Experimental)","text":"","category":"section"},{"location":"base/multi-threading/","page":"Multi-Threading","title":"Multi-Threading","text":"Base.@threadcall","category":"page"},{"location":"base/multi-threading/#Base.@threadcall","page":"Multi-Threading","title":"Base.@threadcall","text":"@threadcall((cfunc, clib), rettype, (argtypes...), argvals...)\n\nThe @threadcall macro is called in the same way as ccall but does the work in a different thread. This is useful when you want to call a blocking C function without causing the main julia thread to become blocked. Concurrency is limited by size of the libuv thread pool, which defaults to 4 threads but can be increased by setting the UV_THREADPOOL_SIZE environment variable and restarting the julia process.\n\nNote that the called function should never call back into Julia.\n\n\n\n\n\n","category":"macro"},{"location":"base/multi-threading/#Low-level-synchronization-primitives","page":"Multi-Threading","title":"Low-level synchronization primitives","text":"","category":"section"},{"location":"base/multi-threading/","page":"Multi-Threading","title":"Multi-Threading","text":"These building blocks are used to create the regular synchronization objects.","category":"page"},{"location":"base/multi-threading/","page":"Multi-Threading","title":"Multi-Threading","text":"Base.Threads.SpinLock","category":"page"},{"location":"base/multi-threading/#Base.Threads.SpinLock","page":"Multi-Threading","title":"Base.Threads.SpinLock","text":"SpinLock()\n\nCreate a non-reentrant, test-and-test-and-set spin lock. Recursive use will result in a deadlock. This kind of lock should only be used around code that takes little time to execute and does not block (e.g. perform I/O). In general, ReentrantLock should be used instead.\n\nEach lock must be matched with an unlock.\n\nTest-and-test-and-set spin locks are quickest up to about 30ish contending threads. If you have more contention than that, different synchronization approaches should be considered.\n\n\n\n\n\n","category":"type"},{"location":"devdocs/callconv/#Calling-Conventions","page":"Calling Conventions","title":"Calling Conventions","text":"","category":"section"},{"location":"devdocs/callconv/","page":"Calling Conventions","title":"Calling Conventions","text":"Julia uses three calling conventions for four distinct purposes:","category":"page"},{"location":"devdocs/callconv/","page":"Calling Conventions","title":"Calling Conventions","text":"Name Prefix Purpose\nNative julia_ Speed via specialized signatures\nJL Call jlcall_ Wrapper for generic calls\nJL Call jl_ Builtins\nC ABI jlcapi_ Wrapper callable from C","category":"page"},{"location":"devdocs/callconv/#Julia-Native-Calling-Convention","page":"Calling Conventions","title":"Julia Native Calling Convention","text":"","category":"section"},{"location":"devdocs/callconv/","page":"Calling Conventions","title":"Calling Conventions","text":"The native calling convention is designed for fast non-generic calls. It usually uses a specialized signature.","category":"page"},{"location":"devdocs/callconv/","page":"Calling Conventions","title":"Calling Conventions","text":"LLVM ghosts (zero-length types) are omitted.\nLLVM scalars and vectors are passed by value.\nLLVM aggregates (arrays and structs) are passed by reference.","category":"page"},{"location":"devdocs/callconv/","page":"Calling Conventions","title":"Calling Conventions","text":"A small return values is returned as LLVM return values. A large return values is returned via the \"structure return\" (sret) convention, where the caller provides a pointer to a return slot.","category":"page"},{"location":"devdocs/callconv/","page":"Calling Conventions","title":"Calling Conventions","text":"An argument or return values that is a homogeneous tuple is sometimes represented as an LLVM vector instead of an LLVM array.","category":"page"},{"location":"devdocs/callconv/#JL-Call-Convention","page":"Calling Conventions","title":"JL Call Convention","text":"","category":"section"},{"location":"devdocs/callconv/","page":"Calling Conventions","title":"Calling Conventions","text":"The JL Call convention is for builtins and generic dispatch. Hand-written functions using this convention are declared via the macro JL_CALLABLE. The convention uses exactly 3 parameters:","category":"page"},{"location":"devdocs/callconv/","page":"Calling Conventions","title":"Calling Conventions","text":"F - Julia representation of function that is being applied\nargs - pointer to array of pointers to boxes\nnargs - length of the array","category":"page"},{"location":"devdocs/callconv/","page":"Calling Conventions","title":"Calling Conventions","text":"The return value is a pointer to a box.","category":"page"},{"location":"devdocs/callconv/#C-ABI","page":"Calling Conventions","title":"C ABI","text":"","category":"section"},{"location":"devdocs/callconv/","page":"Calling Conventions","title":"Calling Conventions","text":"C ABI wrappers enable calling Julia from C. The wrapper calls a function using the native calling convention.","category":"page"},{"location":"devdocs/callconv/","page":"Calling Conventions","title":"Calling Conventions","text":"Tuples are always represented as C arrays.","category":"page"},{"location":"devdocs/compiler/#本机代码生成过程的高级概述","page":"本机代码生成过程的高级概述","title":"本机代码生成过程的高级概述","text":"","category":"section"},{"location":"devdocs/compiler/#指针的表示","page":"本机代码生成过程的高级概述","title":"指针的表示","text":"","category":"section"},{"location":"devdocs/compiler/","page":"本机代码生成过程的高级概述","title":"本机代码生成过程的高级概述","text":"When emitting code to an object file, pointers will be emitted as relocations. The deserialization code will ensure any object that pointed to one of these constants gets recreated and contains the right runtime pointer.","category":"page"},{"location":"devdocs/compiler/","page":"本机代码生成过程的高级概述","title":"本机代码生成过程的高级概述","text":"Otherwise, they will be emitted as literal constants.","category":"page"},{"location":"devdocs/compiler/","page":"本机代码生成过程的高级概述","title":"本机代码生成过程的高级概述","text":"To emit one of these objects, call literal_pointer_val. It'll handle tracking the Julia value and the LLVM global, ensuring they are valid both for the current runtime and after deserialization.","category":"page"},{"location":"devdocs/compiler/","page":"本机代码生成过程的高级概述","title":"本机代码生成过程的高级概述","text":"When emitted into the object file, these globals are stored as references in a large gvals table. This allows the deserializer to reference them by index, and implement a custom manual mechanism similar to a Global Offset Table (GOT) to restore them.","category":"page"},{"location":"devdocs/compiler/","page":"本机代码生成过程的高级概述","title":"本机代码生成过程的高级概述","text":"Function pointers are handled similarly. They are stored as values in a large fvals table. Like globals, this allows the deserializer to reference them by index.","category":"page"},{"location":"devdocs/compiler/","page":"本机代码生成过程的高级概述","title":"本机代码生成过程的高级概述","text":"Note that extern functions are handled separately, with names, via the usual symbol resolution mechanism in the linker.","category":"page"},{"location":"devdocs/compiler/","page":"本机代码生成过程的高级概述","title":"本机代码生成过程的高级概述","text":"Note too that ccall functions are also handled separately, via a manual GOT and Procedure Linkage Table (PLT).","category":"page"},{"location":"devdocs/compiler/#Representation-of-Intermediate-Values","page":"本机代码生成过程的高级概述","title":"Representation of Intermediate Values","text":"","category":"section"},{"location":"devdocs/compiler/","page":"本机代码生成过程的高级概述","title":"本机代码生成过程的高级概述","text":"Values are passed around in a jl_cgval_t struct. This represents an R-value, and includes enough information to determine how to assign or pass it somewhere.","category":"page"},{"location":"devdocs/compiler/","page":"本机代码生成过程的高级概述","title":"本机代码生成过程的高级概述","text":"They are created via one of the helper constructors, usually: mark_julia_type (for immediate values) and mark_julia_slot (for pointers to values).","category":"page"},{"location":"devdocs/compiler/","page":"本机代码生成过程的高级概述","title":"本机代码生成过程的高级概述","text":"The function convert_julia_type can transform between any two types. It returns an R-value with cgval.typ set to typ. It'll cast the object to the requested representation, making heap boxes, allocating stack copies, and computing tagged unions as needed to change the representation.","category":"page"},{"location":"devdocs/compiler/","page":"本机代码生成过程的高级概述","title":"本机代码生成过程的高级概述","text":"By contrast update_julia_type will change cgval.typ to typ, only if it can be done at zero-cost (i.e. without emitting any code).","category":"page"},{"location":"devdocs/compiler/#Union-representation","page":"本机代码生成过程的高级概述","title":"Union representation","text":"","category":"section"},{"location":"devdocs/compiler/","page":"本机代码生成过程的高级概述","title":"本机代码生成过程的高级概述","text":"Inferred union types may be stack allocated via a tagged type representation.","category":"page"},{"location":"devdocs/compiler/","page":"本机代码生成过程的高级概述","title":"本机代码生成过程的高级概述","text":"The primitive routines that need to be able to handle tagged unions are:","category":"page"},{"location":"devdocs/compiler/","page":"本机代码生成过程的高级概述","title":"本机代码生成过程的高级概述","text":"mark-type\nload-local\nstore-local\nisa\nis\nemit_typeof\nemit_sizeof\nboxed\nunbox\nspecialized cc-ret","category":"page"},{"location":"devdocs/compiler/","page":"本机代码生成过程的高级概述","title":"本机代码生成过程的高级概述","text":"Everything else should be possible to handle in inference by using these primitives to implement union-splitting.","category":"page"},{"location":"devdocs/compiler/","page":"本机代码生成过程的高级概述","title":"本机代码生成过程的高级概述","text":"The representation of the tagged-union is as a pair of < void* union, byte selector >. The selector is fixed-size as byte & 0x7f, and will union-tag the first 126 isbits. It records the one-based depth-first count into the type-union of the isbits objects inside. An index of zero indicates that the union* is actually a tagged heap-allocated jl_value_t*, and needs to be treated as normal for a boxed object rather than as a tagged union.","category":"page"},{"location":"devdocs/compiler/","page":"本机代码生成过程的高级概述","title":"本机代码生成过程的高级概述","text":"The high bit of the selector (byte & 0x80) can be tested to determine if the void* is actually a heap-allocated (jl_value_t*) box, thus avoiding the cost of re-allocating a box, while maintaining the ability to efficiently handle union-splitting based on the low bits.","category":"page"},{"location":"devdocs/compiler/","page":"本机代码生成过程的高级概述","title":"本机代码生成过程的高级概述","text":"It is guaranteed that byte & 0x7f is an exact test for the type, if the value can be represented by a tag – it will never be marked byte = 0x80. It is not necessary to also test the type-tag when testing isa.","category":"page"},{"location":"devdocs/compiler/","page":"本机代码生成过程的高级概述","title":"本机代码生成过程的高级概述","text":"The union* memory region may be allocated at any size. The only constraint is that it is big enough to contain the data currently specified by selector. It might not be big enough to contain the union of all types that could be stored there according to the associated Union type field. Use appropriate care when copying.","category":"page"},{"location":"devdocs/compiler/#Specialized-Calling-Convention-Signature-Representation","page":"本机代码生成过程的高级概述","title":"Specialized Calling Convention Signature Representation","text":"","category":"section"},{"location":"devdocs/compiler/","page":"本机代码生成过程的高级概述","title":"本机代码生成过程的高级概述","text":"A jl_returninfo_t object describes the calling convention details of any callable.","category":"page"},{"location":"devdocs/compiler/","page":"本机代码生成过程的高级概述","title":"本机代码生成过程的高级概述","text":"If any of the arguments or return type of a method can be represented unboxed, and the method is not varargs, it'll be given an optimized calling convention signature based on its specTypes and rettype fields.","category":"page"},{"location":"devdocs/compiler/","page":"本机代码生成过程的高级概述","title":"本机代码生成过程的高级概述","text":"The general principles are that:","category":"page"},{"location":"devdocs/compiler/","page":"本机代码生成过程的高级概述","title":"本机代码生成过程的高级概述","text":"Primitive types get passed in int/float registers.\nTuples of VecElement types get passed in vector registers.\nStructs get passed on the stack.\nReturn values are handle similarly to arguments, with a size-cutoff at which they will instead be returned via a hidden sret argument.","category":"page"},{"location":"devdocs/compiler/","page":"本机代码生成过程的高级概述","title":"本机代码生成过程的高级概述","text":"The total logic for this is implemented by get_specsig_function and deserves_sret.","category":"page"},{"location":"devdocs/compiler/","page":"本机代码生成过程的高级概述","title":"本机代码生成过程的高级概述","text":"Additionally, if the return type is a union, it may be returned as a pair of values (a pointer and a tag). If the union values can be stack-allocated, then sufficient space to store them will also be passed as a hidden first argument. It is up to the callee whether the returned pointer will point to this space, a boxed object, or even other constant memory.","category":"page"},{"location":"base/parallel/#Tasks","page":"Tasks","title":"Tasks","text":"","category":"section"},{"location":"base/parallel/","page":"Tasks","title":"Tasks","text":"Core.Task\nBase.@task\nBase.@async\nBase.asyncmap\nBase.asyncmap!\nBase.current_task\nBase.istaskdone\nBase.istaskstarted\nBase.istaskfailed\nBase.task_local_storage(::Any)\nBase.task_local_storage(::Any, ::Any)\nBase.task_local_storage(::Function, ::Any, ::Any)","category":"page"},{"location":"base/parallel/#Core.Task","page":"Tasks","title":"Core.Task","text":"Task(func)\n\nCreate a Task (i.e. coroutine) to execute the given function func (which must be callable with no arguments). The task exits when this function returns. The task will run in the \"world age\" from the parent at construction when scheduled.\n\nExamples\n\njulia> a() = sum(i for i in 1:1000);\n\njulia> b = Task(a);\n\nIn this example, b is a runnable Task that hasn't started yet.\n\n\n\n\n\n","category":"type"},{"location":"base/parallel/#Base.@task","page":"Tasks","title":"Base.@task","text":"@task\n\nWrap an expression in a Task without executing it, and return the Task. This only creates a task, and does not run it.\n\nExamples\n\njulia> a1() = sum(i for i in 1:1000);\n\njulia> b = @task a1();\n\njulia> istaskstarted(b)\nfalse\n\njulia> schedule(b);\n\njulia> yield();\n\njulia> istaskdone(b)\ntrue\n\n\n\n\n\n","category":"macro"},{"location":"base/parallel/#Base.@async","page":"Tasks","title":"Base.@async","text":"@async\n\nWrap an expression in a Task and add it to the local machine's scheduler queue.\n\nValues can be interpolated into @async via $, which copies the value directly into the constructed underlying closure. This allows you to insert the value of a variable, isolating the asynchronous code from changes to the variable's value in the current task.\n\ncompat: Julia 1.4\nInterpolating values via $ is available as of Julia 1.4.\n\n\n\n\n\n","category":"macro"},{"location":"base/parallel/#Base.asyncmap","page":"Tasks","title":"Base.asyncmap","text":"asyncmap(f, c...; ntasks=0, batch_size=nothing)\n\nUses multiple concurrent tasks to map f over a collection (or multiple equal length collections). For multiple collection arguments, f is applied elementwise.\n\nntasks specifies the number of tasks to run concurrently. Depending on the length of the collections, if ntasks is unspecified, up to 100 tasks will be used for concurrent mapping.\n\nntasks can also be specified as a zero-arg function. In this case, the number of tasks to run in parallel is checked before processing every element and a new task started if the value of ntasks_func is greater than the current number of tasks.\n\nIf batch_size is specified, the collection is processed in batch mode. f must then be a function that must accept a Vector of argument tuples and must return a vector of results. The input vector will have a length of batch_size or less.\n\nThe following examples highlight execution in different tasks by returning the objectid of the tasks in which the mapping function is executed.\n\nFirst, with ntasks undefined, each element is processed in a different task.\n\njulia> tskoid() = objectid(current_task());\n\njulia> asyncmap(x->tskoid(), 1:5)\n5-element Array{UInt64,1}:\n 0x6e15e66c75c75853\n 0x440f8819a1baa682\n 0x9fb3eeadd0c83985\n 0xebd3e35fe90d4050\n 0x29efc93edce2b961\n\njulia> length(unique(asyncmap(x->tskoid(), 1:5)))\n5\n\nWith ntasks=2 all elements are processed in 2 tasks.\n\njulia> asyncmap(x->tskoid(), 1:5; ntasks=2)\n5-element Array{UInt64,1}:\n 0x027ab1680df7ae94\n 0xa23d2f80cd7cf157\n 0x027ab1680df7ae94\n 0xa23d2f80cd7cf157\n 0x027ab1680df7ae94\n\njulia> length(unique(asyncmap(x->tskoid(), 1:5; ntasks=2)))\n2\n\nWith batch_size defined, the mapping function needs to be changed to accept an array of argument tuples and return an array of results. map is used in the modified mapping function to achieve this.\n\njulia> batch_func(input) = map(x->string(\"args_tuple: \", x, \", element_val: \", x[1], \", task: \", tskoid()), input)\nbatch_func (generic function with 1 method)\n\njulia> asyncmap(batch_func, 1:5; ntasks=2, batch_size=2)\n5-element Array{String,1}:\n \"args_tuple: (1,), element_val: 1, task: 9118321258196414413\"\n \"args_tuple: (2,), element_val: 2, task: 4904288162898683522\"\n \"args_tuple: (3,), element_val: 3, task: 9118321258196414413\"\n \"args_tuple: (4,), element_val: 4, task: 4904288162898683522\"\n \"args_tuple: (5,), element_val: 5, task: 9118321258196414413\"\n\nnote: Note\nCurrently, all tasks in Julia are executed in a single OS thread co-operatively. Consequently, asyncmap is beneficial only when the mapping function involves any I/O - disk, network, remote worker invocation, etc.\n\n\n\n\n\n","category":"function"},{"location":"base/parallel/#Base.asyncmap!","page":"Tasks","title":"Base.asyncmap!","text":"asyncmap!(f, results, c...; ntasks=0, batch_size=nothing)\n\nLike asyncmap, but stores output in results rather than returning a collection.\n\n\n\n\n\n","category":"function"},{"location":"base/parallel/#Base.current_task","page":"Tasks","title":"Base.current_task","text":"current_task()\n\nGet the currently running Task.\n\n\n\n\n\n","category":"function"},{"location":"base/parallel/#Base.istaskdone","page":"Tasks","title":"Base.istaskdone","text":"istaskdone(t::Task) -> Bool\n\nDetermine whether a task has exited.\n\nExamples\n\njulia> a2() = sum(i for i in 1:1000);\n\njulia> b = Task(a2);\n\njulia> istaskdone(b)\nfalse\n\njulia> schedule(b);\n\njulia> yield();\n\njulia> istaskdone(b)\ntrue\n\n\n\n\n\n","category":"function"},{"location":"base/parallel/#Base.istaskstarted","page":"Tasks","title":"Base.istaskstarted","text":"istaskstarted(t::Task) -> Bool\n\nDetermine whether a task has started executing.\n\nExamples\n\njulia> a3() = sum(i for i in 1:1000);\n\njulia> b = Task(a3);\n\njulia> istaskstarted(b)\nfalse\n\n\n\n\n\n","category":"function"},{"location":"base/parallel/#Base.istaskfailed","page":"Tasks","title":"Base.istaskfailed","text":"istaskfailed(t::Task) -> Bool\n\nDetermine whether a task has exited because an exception was thrown.\n\nExamples\n\njulia> a4() = error(\"task failed\");\n\njulia> b = Task(a4);\n\njulia> istaskfailed(b)\nfalse\n\njulia> schedule(b);\n\njulia> yield();\n\njulia> istaskfailed(b)\ntrue\n\ncompat: Julia 1.3\nThis function requires at least Julia 1.3.\n\n\n\n\n\n","category":"function"},{"location":"base/parallel/#Base.task_local_storage-Tuple{Any}","page":"Tasks","title":"Base.task_local_storage","text":"task_local_storage(key)\n\nLook up the value of a key in the current task's task-local storage.\n\n\n\n\n\n","category":"method"},{"location":"base/parallel/#Base.task_local_storage-Tuple{Any, Any}","page":"Tasks","title":"Base.task_local_storage","text":"task_local_storage(key, value)\n\nAssign a value to a key in the current task's task-local storage.\n\n\n\n\n\n","category":"method"},{"location":"base/parallel/#Base.task_local_storage-Tuple{Function, Any, Any}","page":"Tasks","title":"Base.task_local_storage","text":"task_local_storage(body, key, value)\n\nCall the function body with a modified task-local storage, in which value is assigned to key; the previous value of key, or lack thereof, is restored afterwards. Useful for emulating dynamic scoping.\n\n\n\n\n\n","category":"method"},{"location":"base/parallel/#Scheduling","page":"Tasks","title":"Scheduling","text":"","category":"section"},{"location":"base/parallel/","page":"Tasks","title":"Tasks","text":"Base.yield\nBase.yieldto\nBase.sleep\nBase.schedule","category":"page"},{"location":"base/parallel/#Base.yield","page":"Tasks","title":"Base.yield","text":"yield()\n\nSwitch to the scheduler to allow another scheduled task to run. A task that calls this function is still runnable, and will be restarted immediately if there are no other runnable tasks.\n\n\n\n\n\nyield(t::Task, arg = nothing)\n\nA fast, unfair-scheduling version of schedule(t, arg); yield() which immediately yields to t before calling the scheduler.\n\n\n\n\n\n","category":"function"},{"location":"base/parallel/#Base.yieldto","page":"Tasks","title":"Base.yieldto","text":"yieldto(t::Task, arg = nothing)\n\nSwitch to the given task. The first time a task is switched to, the task's function is called with no arguments. On subsequent switches, arg is returned from the task's last call to yieldto. This is a low-level call that only switches tasks, not considering states or scheduling in any way. Its use is discouraged.\n\n\n\n\n\n","category":"function"},{"location":"base/parallel/#Base.sleep","page":"Tasks","title":"Base.sleep","text":"sleep(seconds)\n\nBlock the current task for a specified number of seconds. The minimum sleep time is 1 millisecond or input of 0.001.\n\n\n\n\n\n","category":"function"},{"location":"base/parallel/#Base.schedule","page":"Tasks","title":"Base.schedule","text":"schedule(t::Task, [val]; error=false)\n\nAdd a Task to the scheduler's queue. This causes the task to run constantly when the system is otherwise idle, unless the task performs a blocking operation such as wait.\n\nIf a second argument val is provided, it will be passed to the task (via the return value of yieldto) when it runs again. If error is true, the value is raised as an exception in the woken task.\n\nwarning: Warning\nIt is incorrect to use schedule on an arbitrary Task that has already been started. See the API reference for more information.\n\nExamples\n\njulia> a5() = sum(i for i in 1:1000);\n\njulia> b = Task(a5);\n\njulia> istaskstarted(b)\nfalse\n\njulia> schedule(b);\n\njulia> yield();\n\njulia> istaskstarted(b)\ntrue\n\njulia> istaskdone(b)\ntrue\n\n\n\n\n\n","category":"function"},{"location":"base/parallel/#lib-task-sync","page":"Tasks","title":"Synchronization","text":"","category":"section"},{"location":"base/parallel/","page":"Tasks","title":"Tasks","text":"Base.errormonitor\nBase.@sync\nBase.wait\nBase.fetch(t::Task)\nBase.timedwait\n\nBase.Condition\nBase.notify\n\nBase.Semaphore\nBase.acquire\nBase.release\n\nBase.AbstractLock\nBase.lock\nBase.unlock\nBase.trylock\nBase.islocked\nBase.ReentrantLock","category":"page"},{"location":"base/parallel/#Base.errormonitor","page":"Tasks","title":"Base.errormonitor","text":"errormonitor(t::Task)\n\nPrint an error log to stderr if task t fails.\n\n\n\n\n\n","category":"function"},{"location":"base/parallel/#Base.@sync","page":"Tasks","title":"Base.@sync","text":"@sync\n\nWait until all lexically-enclosed uses of @async, @spawn, @spawnat and @distributed are complete. All exceptions thrown by enclosed async operations are collected and thrown as a CompositeException.\n\n\n\n\n\n","category":"macro"},{"location":"base/parallel/#Base.wait","page":"Tasks","title":"Base.wait","text":"wait(r::Future)\n\nWait for a value to become available for the specified Future.\n\n\n\n\n\nwait(r::RemoteChannel, args...)\n\nWait for a value to become available on the specified RemoteChannel.\n\n\n\n\n\nSpecial note for Threads.Condition:\n\nThe caller must be holding the lock that owns a Threads.Condition before calling this method. The calling task will be blocked until some other task wakes it, usually by calling notify on the same Threads.Condition object. The lock will be atomically released when blocking (even if it was locked recursively), and will be reacquired before returning.\n\n\n\n\n\nwait([x])\n\nBlock the current task until some event occurs, depending on the type of the argument:\n\nChannel: Wait for a value to be appended to the channel.\nCondition: Wait for notify on a condition and return the val parameter passed to notify.\nProcess: Wait for a process or process chain to exit. The exitcode field of a process can be used to determine success or failure.\nTask: Wait for a Task to finish. If the task fails with an exception, a TaskFailedException (which wraps the failed task) is thrown.\nRawFD: Wait for changes on a file descriptor (see the FileWatching package).\n\nIf no argument is passed, the task blocks for an undefined period. A task can only be restarted by an explicit call to schedule or yieldto.\n\nOften wait is called within a while loop to ensure a waited-for condition is met before proceeding.\n\n\n\n\n\n","category":"function"},{"location":"base/parallel/#Base.fetch-Tuple{Task}","page":"Tasks","title":"Base.fetch","text":"fetch(t::Task)\n\nWait for a Task to finish, then return its result value. If the task fails with an exception, a TaskFailedException (which wraps the failed task) is thrown.\n\n\n\n\n\n","category":"method"},{"location":"base/parallel/#Base.timedwait","page":"Tasks","title":"Base.timedwait","text":"timedwait(callback::Function, timeout::Real; pollint::Real=0.1)\n\nWaits until callback returns true or timeout seconds have passed, whichever is earlier. callback is polled every pollint seconds. The minimum value for timeout and pollint is 0.001, that is, 1 millisecond.\n\nReturns :ok or :timed_out\n\n\n\n\n\n","category":"function"},{"location":"base/parallel/#Base.Condition","page":"Tasks","title":"Base.Condition","text":"Condition()\n\nCreate an edge-triggered event source that tasks can wait for. Tasks that call wait on a Condition are suspended and queued. Tasks are woken up when notify is later called on the Condition. Edge triggering means that only tasks waiting at the time notify is called can be woken up. For level-triggered notifications, you must keep extra state to keep track of whether a notification has happened. The Channel and Threads.Event types do this, and can be used for level-triggered events.\n\nThis object is NOT thread-safe. See Threads.Condition for a thread-safe version.\n\n\n\n\n\n","category":"type"},{"location":"base/parallel/#Base.notify","page":"Tasks","title":"Base.notify","text":"notify(condition, val=nothing; all=true, error=false)\n\nWake up tasks waiting for a condition, passing them val. If all is true (the default), all waiting tasks are woken, otherwise only one is. If error is true, the passed value is raised as an exception in the woken tasks.\n\nReturn the count of tasks woken up. Return 0 if no tasks are waiting on condition.\n\n\n\n\n\n","category":"function"},{"location":"base/parallel/#Base.Semaphore","page":"Tasks","title":"Base.Semaphore","text":"Semaphore(sem_size)\n\nCreate a counting semaphore that allows at most sem_size acquires to be in use at any time. Each acquire must be matched with a release.\n\nThis provides a acquire & release memory ordering on acquire/release calls.\n\n\n\n\n\n","category":"type"},{"location":"base/parallel/#Base.acquire","page":"Tasks","title":"Base.acquire","text":"acquire(s::Semaphore)\n\nWait for one of the sem_size permits to be available, blocking until one can be acquired.\n\n\n\n\n\nacquire(f, s::Semaphore)\n\nExecute f after acquiring from Semaphore s, and release on completion or error.\n\nFor example, a do-block form that ensures only 2 calls of foo will be active at the same time:\n\ns = Base.Semaphore(2)\n@sync for _ in 1:100\n Threads.@spawn begin\n Base.acquire(s) do\n foo()\n end\n end\nend\n\ncompat: Julia 1.8\nThis method requires at least Julia 1.8.\n\n\n\n\n\n","category":"function"},{"location":"base/parallel/#Base.release","page":"Tasks","title":"Base.release","text":"release(s::Semaphore)\n\nReturn one permit to the pool, possibly allowing another task to acquire it and resume execution.\n\n\n\n\n\n","category":"function"},{"location":"base/parallel/#Base.AbstractLock","page":"Tasks","title":"Base.AbstractLock","text":"AbstractLock\n\nAbstract supertype describing types that implement the synchronization primitives: lock, trylock, unlock, and islocked.\n\n\n\n\n\n","category":"type"},{"location":"base/parallel/#Base.lock","page":"Tasks","title":"Base.lock","text":"lock(lock)\n\nAcquire the lock when it becomes available. If the lock is already locked by a different task/thread, wait for it to become available.\n\nEach lock must be matched by an unlock.\n\n\n\n\n\nlock(f::Function, lock)\n\nAcquire the lock, execute f with the lock held, and release the lock when f returns. If the lock is already locked by a different task/thread, wait for it to become available.\n\nWhen this function returns, the lock has been released, so the caller should not attempt to unlock it.\n\ncompat: Julia 1.7\nUsing a Channel as the second argument requires Julia 1.7 or later.\n\n\n\n\n\n","category":"function"},{"location":"base/parallel/#Base.unlock","page":"Tasks","title":"Base.unlock","text":"unlock(lock)\n\nReleases ownership of the lock.\n\nIf this is a recursive lock which has been acquired before, decrement an internal counter and return immediately.\n\n\n\n\n\n","category":"function"},{"location":"base/parallel/#Base.trylock","page":"Tasks","title":"Base.trylock","text":"trylock(lock) -> Success (Boolean)\n\nAcquire the lock if it is available, and return true if successful. If the lock is already locked by a different task/thread, return false.\n\nEach successful trylock must be matched by an unlock.\n\n\n\n\n\n","category":"function"},{"location":"base/parallel/#Base.islocked","page":"Tasks","title":"Base.islocked","text":"islocked(lock) -> Status (Boolean)\n\nCheck whether the lock is held by any task/thread. This should not be used for synchronization (see instead trylock).\n\n\n\n\n\n","category":"function"},{"location":"base/parallel/#Base.ReentrantLock","page":"Tasks","title":"Base.ReentrantLock","text":"ReentrantLock()\n\nCreates a re-entrant lock for synchronizing Tasks. The same task can acquire the lock as many times as required. Each lock must be matched with an unlock.\n\nCalling 'lock' will also inhibit running of finalizers on that thread until the corresponding 'unlock'. Use of the standard lock pattern illustrated below should naturally be supported, but beware of inverting the try/lock order or missing the try block entirely (e.g. attempting to return with the lock still held):\n\nThis provides a acquire/release memory ordering on lock/unlock calls.\n\nlock(l)\ntry\n \nfinally\n unlock(l)\nend\n\n\n\n\n\n","category":"type"},{"location":"base/parallel/#Channels","page":"Tasks","title":"Channels","text":"","category":"section"},{"location":"base/parallel/","page":"Tasks","title":"Tasks","text":"Base.Channel\nBase.Channel(::Function)\nBase.put!(::Channel, ::Any)\nBase.take!(::Channel)\nBase.isready(::Channel)\nBase.fetch(::Channel)\nBase.close(::Channel)\nBase.bind(c::Channel, task::Task)","category":"page"},{"location":"base/parallel/#Base.Channel","page":"Tasks","title":"Base.Channel","text":"Channel{T=Any}(size::Int=0)\n\nConstructs a Channel with an internal buffer that can hold a maximum of size objects of type T. put! calls on a full channel block until an object is removed with take!.\n\nChannel(0) constructs an unbuffered channel. put! blocks until a matching take! is called. And vice-versa.\n\nOther constructors:\n\nChannel(): default constructor, equivalent to Channel{Any}(0)\nChannel(Inf): equivalent to Channel{Any}(typemax(Int))\nChannel(sz): equivalent to Channel{Any}(sz)\n\ncompat: Julia 1.3\nThe default constructor Channel() and default size=0 were added in Julia 1.3.\n\n\n\n\n\n","category":"type"},{"location":"base/parallel/#Base.Channel-Tuple{Function}","page":"Tasks","title":"Base.Channel","text":"Channel{T=Any}(func::Function, size=0; taskref=nothing, spawn=false)\n\nCreate a new task from func, bind it to a new channel of type T and size size, and schedule the task, all in a single call. The channel is automatically closed when the task terminates.\n\nfunc must accept the bound channel as its only argument.\n\nIf you need a reference to the created task, pass a Ref{Task} object via the keyword argument taskref.\n\nIf spawn = true, the Task created for func may be scheduled on another thread in parallel, equivalent to creating a task via Threads.@spawn.\n\nReturn a Channel.\n\nExamples\n\njulia> chnl = Channel() do ch\n foreach(i -> put!(ch, i), 1:4)\n end;\n\njulia> typeof(chnl)\nChannel{Any}\n\njulia> for i in chnl\n @show i\n end;\ni = 1\ni = 2\ni = 3\ni = 4\n\nReferencing the created task:\n\njulia> taskref = Ref{Task}();\n\njulia> chnl = Channel(taskref=taskref) do ch\n println(take!(ch))\n end;\n\njulia> istaskdone(taskref[])\nfalse\n\njulia> put!(chnl, \"Hello\");\nHello\n\njulia> istaskdone(taskref[])\ntrue\n\ncompat: Julia 1.3\nThe spawn= parameter was added in Julia 1.3. This constructor was added in Julia 1.3. In earlier versions of Julia, Channel used keyword arguments to set size and T, but those constructors are deprecated.\n\njulia> chnl = Channel{Char}(1, spawn=true) do ch\n for c in \"hello world\"\n put!(ch, c)\n end\n end\nChannel{Char}(1) (2 items available)\n\njulia> String(collect(chnl))\n\"hello world\"\n\n\n\n\n\n","category":"method"},{"location":"base/parallel/#Base.put!-Tuple{Channel, Any}","page":"Tasks","title":"Base.put!","text":"put!(c::Channel, v)\n\nAppend an item v to the channel c. Blocks if the channel is full.\n\nFor unbuffered channels, blocks until a take! is performed by a different task.\n\ncompat: Julia 1.1\nv now gets converted to the channel's type with convert as put! is called.\n\n\n\n\n\n","category":"method"},{"location":"base/parallel/#Base.take!-Tuple{Channel}","page":"Tasks","title":"Base.take!","text":"take!(c::Channel)\n\nRemove and return a value from a Channel. Blocks until data is available.\n\nFor unbuffered channels, blocks until a put! is performed by a different task.\n\n\n\n\n\n","category":"method"},{"location":"base/parallel/#Base.isready-Tuple{Channel}","page":"Tasks","title":"Base.isready","text":"isready(c::Channel)\n\nDetermine whether a Channel has a value stored to it. Returns immediately, does not block.\n\nFor unbuffered channels returns true if there are tasks waiting on a put!.\n\n\n\n\n\n","category":"method"},{"location":"base/parallel/#Base.fetch-Tuple{Channel}","page":"Tasks","title":"Base.fetch","text":"fetch(c::Channel)\n\nWait for and get the first available item from the channel. Does not remove the item. fetch is unsupported on an unbuffered (0-size) channel.\n\n\n\n\n\n","category":"method"},{"location":"base/parallel/#Base.close-Tuple{Channel}","page":"Tasks","title":"Base.close","text":"close(c::Channel[, excp::Exception])\n\nClose a channel. An exception (optionally given by excp), is thrown by:\n\nput! on a closed channel.\ntake! and fetch on an empty, closed channel.\n\n\n\n\n\n","category":"method"},{"location":"base/parallel/#Base.bind-Tuple{Channel, Task}","page":"Tasks","title":"Base.bind","text":"bind(chnl::Channel, task::Task)\n\nAssociate the lifetime of chnl with a task. Channel chnl is automatically closed when the task terminates. Any uncaught exception in the task is propagated to all waiters on chnl.\n\nThe chnl object can be explicitly closed independent of task termination. Terminating tasks have no effect on already closed Channel objects.\n\nWhen a channel is bound to multiple tasks, the first task to terminate will close the channel. When multiple channels are bound to the same task, termination of the task will close all of the bound channels.\n\nExamples\n\njulia> c = Channel(0);\n\njulia> task = @async foreach(i->put!(c, i), 1:4);\n\njulia> bind(c,task);\n\njulia> for i in c\n @show i\n end;\ni = 1\ni = 2\ni = 3\ni = 4\n\njulia> isopen(c)\nfalse\n\njulia> c = Channel(0);\n\njulia> task = @async (put!(c, 1); error(\"foo\"));\n\njulia> bind(c, task);\n\njulia> take!(c)\n1\n\njulia> put!(c, 1);\nERROR: TaskFailedException\nStacktrace:\n[...]\n nested task error: foo\n[...]\n\n\n\n\n\n","category":"method"},{"location":"manual/arrays/#man-multi-dim-arrays","page":"多维数组","title":"多维数组","text":"","category":"section"},{"location":"manual/arrays/","page":"多维数组","title":"多维数组","text":"与大多数科学计算语言一样,Julia 提供原生的数组实现。 大多数科学计算语言非常重视其数组实现,而牺牲了其他容器。Julia 没有以任何特殊方式处理数组。就像和其它用 Julia 写的代码一样,Julia 的数组库几乎完全是用 Julia 自身实现的,并且由编译器保证其性能。因此,也可以通过继承 AbstractArray 来定义自定义数组类型。 有关实现自定义数组类型的更多详细信息,请参阅 AbstractArray 接口的手册部分。","category":"page"},{"location":"manual/arrays/","page":"多维数组","title":"多维数组","text":"数组是存储在多维网格中对象的集合。在最一般的情况下, 数组中的对象可能是 Any 类型。 对于大多数计算上的需求,数组中对象的类型应该更加具体,例如 Float64 或 Int32。","category":"page"},{"location":"manual/arrays/","page":"多维数组","title":"多维数组","text":"一般来说,与许多其他科学计算语言不同,Julia 不希望为了性能而以向量化的方式编写程序。Julia 的编译器使用类型推断,并为标量数组索引生成优化的代码,从而能够令用户方便地编写可读性良好的程序,而不牺牲性能,并且时常会减少内存使用。","category":"page"},{"location":"manual/arrays/","page":"多维数组","title":"多维数组","text":"在 Julia 中,所有函数的参数都是 非复制的方式进行传递的(比如说,通过指针传递)。一些科学计算语言用传值的方式传递数组,尽管这样做可以防止数组在被调函数中被意外地篡改,但这也会导致不必要的数组拷贝。作为 Julia 的一个惯例,以一个 ! 结尾的函数名它会对自己的一个或者多个参数的值进行修改或者销毁(例如,请比较 sort 和 sort!)。被调函数必须进行显式拷贝,以确保它们不会无意中修改输入参数。很多不以!结尾的函数在实现的时候,都会先进行显式拷贝,然后调用一个以 ! 结尾的同名函数,最后返回之前拷贝的副本。","category":"page"},{"location":"manual/arrays/#基本函数","page":"多维数组","title":"基本函数","text":"","category":"section"},{"location":"manual/arrays/","page":"多维数组","title":"多维数组","text":"函数 描述\neltype(A) A 中元素的类型\nlength(A) A 中元素的数量\nndims(A) A 的维数\nsize(A) 一个包含 A 各个维度上元素数量的元组\nsize(A,n) A 第 n 维中的元素数量\naxes(A) 一个包含 A 有效索引的元组\naxes(A,n) 第 n 维有效索引的范围\neachindex(A) 一个访问 A 中每一个位置的高效迭代器\nstride(A,k) 在第 k 维上的间隔(stride)(相邻元素间的线性索引距离)\nstrides(A) 包含每一维上的间隔(stride)的元组","category":"page"},{"location":"manual/arrays/#构造和初始化","page":"多维数组","title":"构造和初始化","text":"","category":"section"},{"location":"manual/arrays/","page":"多维数组","title":"多维数组","text":"Julia 提供了许多用于构造和初始化数组的函数。在下列函数中,参数 dims ... 可以是一个元组 tuple 来表示维数,也可以是一个可变长度的整数值作为维数。大部分函数的第一个参数都表示数组的元素类型 T 。如果类型 T 被省略,那么将默认为 Float64。","category":"page"},{"location":"manual/arrays/","page":"多维数组","title":"多维数组","text":"函数 描述\nArray{T}(undef, dims...) 一个没有初始化的密集 Array\nzeros(T, dims...) 一个全零 Array\nones(T, dims...) 一个元素均为 1 的 Array\ntrues(dims...) 一个每个元素都为 true 的 BitArray\nfalses(dims...) 一个每个元素都为 false 的 BitArray\nreshape(A, dims...) 一个包含跟 A 相同数据但维数不同的数组\ncopy(A) 拷贝 A\ndeepcopy(A) 深拷贝,即拷贝 A,并递归地拷贝其元素\nsimilar(A, T, dims...) 一个与A具有相同类型(这里指的是密集,稀疏等)的未初始化数组,但具有指定的元素类型和维数。第二个和第三个参数都是可选的,如果省略则默认为元素类型和 A 的维数。\nreinterpret(T, A) 与 A 具有相同二进制数据的数组,但元素类型为 T\nrand(T, dims...) 一个随机 Array,元素值是 0 1) 半开区间中的均匀分布且服从一阶独立同分布 [1]\nrandn(T, dims...) 一个随机 Array,元素为标准正态分布,服从独立同分布\nMatrix{T}(I, m, n) m 行 n 列的单位矩阵 (需要先执行 using LinearAlgebra 来才能使用 I)\nrange(start, stop=stop, length=n) 从 start 到 stop 的带有 n 个线性间隔元素的范围\nfill!(A, x) 用值 x 填充数组 A\nfill(x, dims...) 一个被值 x 填充的 Array","category":"page"},{"location":"manual/arrays/","page":"多维数组","title":"多维数组","text":"[1]: iid,独立同分布","category":"page"},{"location":"manual/arrays/","page":"多维数组","title":"多维数组","text":"要查看各种方法,我们可以将不同维数传递给这些构造函数,请考虑以下示例:","category":"page"},{"location":"manual/arrays/","page":"多维数组","title":"多维数组","text":"julia> zeros(Int8, 2, 3)\n2×3 Matrix{Int8}:\n 0 0 0\n 0 0 0\n\njulia> zeros(Int8, (2, 3))\n2×3 Matrix{Int8}:\n 0 0 0\n 0 0 0\n\njulia> zeros((2, 3))\n2×3 Matrix{Float64}:\n 0.0 0.0 0.0\n 0.0 0.0 0.0","category":"page"},{"location":"manual/arrays/","page":"多维数组","title":"多维数组","text":"此处, (2, 3) 是一个元组 Tuple 并且第一个参数——元素类型是可选的, 默认值为 Float64.","category":"page"},{"location":"manual/arrays/#man-array-literals","page":"多维数组","title":"数组常量","text":"","category":"section"},{"location":"manual/arrays/","page":"多维数组","title":"多维数组","text":"数组也可以直接用方括号来构造; 语法为 [A, B, C, ...] 创建一个一维数组(即一个向量),该一维数组的元素用逗号分隔。所创建的数组中元素的类型(eltype) 自动由括号内参数的类型确定。如果所有参数类型都相同,则该类型称为数组的 eltype。 如果所有元素都有相同的promotion type,那么个元素都由convert转换成该类型并且该类型为数组的 eltype. 否则, 生成一个可以包含任意类型的异构数组—— Vector{Any} ;该构造方法包含字符 [],此时构造过程无参数给出。","category":"page"},{"location":"manual/arrays/","page":"多维数组","title":"多维数组","text":"julia> [1,2,3] # 元素类型为 Int 的向量\n3-element Vector{Int64}:\n 1\n 2\n 3\n\njulia> promote(1, 2.3, 4//5) # Int, Float64 以及 Rational 类型放在一起则会提升到 Float64\n(1.0, 2.3, 0.8)\n\njulia> [1, 2.3, 4//5] # 从而它就是这个矩阵的元素类型\n3-element Vector{Float64}:\n 1.0\n 2.3\n 0.8\n\njulia> []\nAny[]","category":"page"},{"location":"manual/arrays/#man-array-concatenation","page":"多维数组","title":"数组拼接","text":"","category":"section"},{"location":"manual/arrays/","page":"多维数组","title":"多维数组","text":"如果方括号里的参数不是由逗号分隔,而是由单个分号(;) 或者换行符分隔,那么每一个参数就不再解析为一个单独的数组元素,而是纵向拼接起来。  ","category":"page"},{"location":"manual/arrays/","page":"多维数组","title":"多维数组","text":"julia> [1:2, 4:5] # 这里有一个逗号,因此并不会发生矩阵的拼接。这里居然的元素本身就是这些 range\n2-element Vector{UnitRange{Int64}}:\n 1:2\n 4:5\n\njulia> [1:2; 4:5]\n4-element Vector{Int64}:\n 1\n 2\n 4\n 5\n\njulia> [1:2\n 4:5\n 6]\n5-element Vector{Int64}:\n 1\n 2\n 4\n 5\n 6","category":"page"},{"location":"manual/arrays/","page":"多维数组","title":"多维数组","text":"类似的,如果这些参数是被制表符、空格符或者两个分号所分隔,那么它们的内容就横向拼接在一起。","category":"page"},{"location":"manual/arrays/","page":"多维数组","title":"多维数组","text":"julia> [1:2 4:5 7:8]\n2×3 Matrix{Int64}:\n 1 4 7\n 2 5 8\n\njulia> [[1,2] [4,5] [7,8]]\n2×3 Matrix{Int64}:\n 1 4 7\n 2 5 8\n\njulia> [1 2 3] # 数字可以被横向拼接\n1×3 Matrix{Int64}:\n 1 2 3\n\njulia> [1;; 2;; 3;; 4]\n1×4 Matrix{Int64}:\n 1 2 3 4","category":"page"},{"location":"manual/arrays/","page":"多维数组","title":"多维数组","text":"单个分号(或换行符)和空格(或制表符)可以被结合起来使用进行横向或者纵向的拼接。","category":"page"},{"location":"manual/arrays/","page":"多维数组","title":"多维数组","text":"julia> [1 2\n 3 4]\n2×2 Matrix{Int64}:\n 1 2\n 3 4\n\njulia> [zeros(Int, 2, 2) [1; 2]\n [3 4] 5]\n3×3 Matrix{Int64}:\n 0 0 1\n 0 0 2\n 3 4 5\n\njulia> [[1 1]; 2 3; [4 4]]\n3×2 Matrix{Int64}:\n 1 1\n 2 3\n 4 4","category":"page"},{"location":"manual/arrays/","page":"多维数组","title":"多维数组","text":"空格(和制表符)的优先级高于分号,首先执行任何纵向拼接,然后拼接结果。 另一方面,使用双分号进行水平连接时,先纵向拼接再横向拼接。","category":"page"},{"location":"manual/arrays/","page":"多维数组","title":"多维数组","text":"julia> [zeros(Int, 2, 2) ; [3 4] ;; [1; 2] ; 5]\n3×3 Matrix{Int64}:\n 0 0 1\n 0 0 2\n 3 4 5\n\njulia> [1:2; 4;; 1; 3:4]\n3×2 Matrix{Int64}:\n 1 1\n 2 3\n 4 4","category":"page"},{"location":"manual/arrays/","page":"多维数组","title":"多维数组","text":"正如 ; 和 ;; 在第一维和第二维中拼接一样,使用更多的分号扩展了相同的通用方案。 分隔符中的分号数指定了特定的维度,因此;;; 在第三个维度中拼接,;;;; 在第四个维度中,依此类推。 较少的分号优先级高,因此较低的维度通常首先拼接。","category":"page"},{"location":"manual/arrays/","page":"多维数组","title":"多维数组","text":"julia> [1; 2;; 3; 4;; 5; 6;;;\n 7; 8;; 9; 10;; 11; 12]\n2×3×2 Array{Int64, 3}:\n[:, :, 1] =\n 1 3 5\n 2 4 6\n\n[:, :, 2] =\n 7 9 11\n 8 10 12","category":"page"},{"location":"manual/arrays/","page":"多维数组","title":"多维数组","text":"像之前一样,用于水平拼接的空格(和制表符)的优先级高于任何数量的分号。 因此,高维数组也可以通过首先指定它们的行来编写,它们的元素以类似于它们的布局的方式进行文本排列:","category":"page"},{"location":"manual/arrays/","page":"多维数组","title":"多维数组","text":"julia> [1 3 5\n 2 4 6;;;\n 7 9 11\n 8 10 12]\n2×3×2 Array{Int64, 3}:\n[:, :, 1] =\n 1 3 5\n 2 4 6\n\n[:, :, 2] =\n 7 9 11\n 8 10 12\n\njulia> [1 2;;; 3 4;;;; 5 6;;; 7 8]\n1×2×2×2 Array{Int64, 4}:\n[:, :, 1, 1] =\n 1 2\n\n[:, :, 2, 1] =\n 3 4\n\n[:, :, 1, 2] =\n 5 6\n\n[:, :, 2, 2] =\n 7 8\n\njulia> [[1 2;;; 3 4];;;; [5 6];;; [7 8]]\n1×2×2×2 Array{Int64, 4}:\n[:, :, 1, 1] =\n 1 2\n\n[:, :, 2, 1] =\n 3 4\n\n[:, :, 1, 2] =\n 5 6\n\n[:, :, 2, 2] =\n 7 8","category":"page"},{"location":"manual/arrays/","page":"多维数组","title":"多维数组","text":"尽管它们都表示第二维中的连接,但空格(或制表符)和 ;; 不能出现在同一个数组表达式中,除非双分号只是作为“行继续”字符。 这允许单个水平拼接跨越多行(不会将换行符解释为垂直拼接)。","category":"page"},{"location":"manual/arrays/","page":"多维数组","title":"多维数组","text":"julia> [1 2 ;;\n 3 4]\n1×4 Matrix{Int64}:\n 1 2 3 4","category":"page"},{"location":"manual/arrays/","page":"多维数组","title":"多维数组","text":"终止分号也可用于在最后添加 1 个长度为1的维度。","category":"page"},{"location":"manual/arrays/","page":"多维数组","title":"多维数组","text":"julia> [1;;]\n1×1 Matrix{Int64}:\n 1\n\njulia> [2; 3;;;]\n2×1×1 Array{Int64, 3}:\n[:, :, 1] =\n 2\n 3","category":"page"},{"location":"manual/arrays/","page":"多维数组","title":"多维数组","text":"更一般地,可以通过cat 函数来实现数组元素的拼接功能。 以下这些的语法为这些函数的简写形式,它们本身也是非常方便使用的:","category":"page"},{"location":"manual/arrays/","page":"多维数组","title":"多维数组","text":"语法 函数 描述\n cat 沿着 s 的第 k 维拼接数组\n[A; B; C; ...] vcat `cat(A...; dims=1) 的简写\n[A B C ...] hcat `cat(A...; dims=2) 的简写\n[A B; C D; ...] hvcat 同时沿垂直和水平方向拼接\n[A; C;; B; D;;; ...] hvncat 同时进行 n 维拼接,其中分号的数量表示拼接所在的维度","category":"page"},{"location":"manual/arrays/#指定类型的数组字面量","page":"多维数组","title":"指定类型的数组字面量","text":"","category":"section"},{"location":"manual/arrays/","page":"多维数组","title":"多维数组","text":"可以用 T[A, B, C, ...] 的方式声明一个元素为某种特定类型的数组。该方法定义一个元素类型为 T 的一维数组并且初始化元素为 A, B, C, ....。比如,Any[x, y, z] 会构建一个异构数组,该数组可以包含任意类型的元素。","category":"page"},{"location":"manual/arrays/","page":"多维数组","title":"多维数组","text":"类似的,拼接也可以用类型为前缀来指定结果的元素类型。","category":"page"},{"location":"manual/arrays/","page":"多维数组","title":"多维数组","text":"julia> [[1 2] [3 4]]\n1×4 Matrix{Int64}:\n 1 2 3 4\n\njulia> Int8[[1 2] [3 4]]\n1×4 Matrix{Int8}:\n 1 2 3 4","category":"page"},{"location":"manual/arrays/#man-comprehensions","page":"多维数组","title":"数组推导","text":"","category":"section"},{"location":"manual/arrays/","page":"多维数组","title":"多维数组","text":"(数组)推导提供了构造数组的通用且强大的方法。其语法类似于数学中的集合构造的写法:","category":"page"},{"location":"manual/arrays/","page":"多维数组","title":"多维数组","text":"A = [ F(x,y,...) for x=rx, y=ry, ... ]","category":"page"},{"location":"manual/arrays/","page":"多维数组","title":"多维数组","text":"这种形式的含义是 F(x,y,...) 取其给定列表中变量 x,y 等的每个值进行计算。值可以指定为任何可迭代对象,但通常是 1:n 或 2:(n-1) 之类的范围,或者像 [1.2, 3.4, 5.7] 这样的显式数组值。结果是一个 N 维密集数组,将变量范围 rx,ry 等的维数拼接起来得到其维数,并且每次 F(x,y,...) 计算返回一个标量。","category":"page"},{"location":"manual/arrays/","page":"多维数组","title":"多维数组","text":"下面的示例计算当前元素和沿一维网格其左,右相邻元素的加权平均值:","category":"page"},{"location":"manual/arrays/","page":"多维数组","title":"多维数组","text":"julia> x = rand(8)\n8-element Array{Float64,1}:\n 0.843025\n 0.869052\n 0.365105\n 0.699456\n 0.977653\n 0.994953\n 0.41084\n 0.809411\n\njulia> [ 0.25*x[i-1] + 0.5*x[i] + 0.25*x[i+1] for i=2:length(x)-1 ]\n6-element Array{Float64,1}:\n 0.736559\n 0.57468\n 0.685417\n 0.912429\n 0.8446\n 0.656511","category":"page"},{"location":"manual/arrays/","page":"多维数组","title":"多维数组","text":"生成的数组的类型取决于参与计算元素的类型,就像数组字面量一样。为了显式地控制类型,可以在数组推导之前指定类型。例如,我们可以要求推导的结果为单精度类型:","category":"page"},{"location":"manual/arrays/","page":"多维数组","title":"多维数组","text":"Float32[ 0.25*x[i-1] + 0.5*x[i] + 0.25*x[i+1] for i=2:length(x)-1 ]","category":"page"},{"location":"manual/arrays/#生成器表达式","page":"多维数组","title":"生成器表达式","text":"","category":"section"},{"location":"manual/arrays/","page":"多维数组","title":"多维数组","text":"也可以在没有方括号的情况下编写(数组)推导,从而产生称为生成器的对象。可以迭代此对象以按需生成值,而不是预先分配数组并存储它们(请参阅 迭代)。例如,以下表达式在不分配内存的情况下对一个序列进行求和:","category":"page"},{"location":"manual/arrays/","page":"多维数组","title":"多维数组","text":"julia> sum(1/n^2 for n=1:1000)\n1.6439345666815615","category":"page"},{"location":"manual/arrays/","page":"多维数组","title":"多维数组","text":"在参数列表中使用具有多个维度的生成器表达式时,需要使用括号将生成器与后续参数分开:","category":"page"},{"location":"manual/arrays/","page":"多维数组","title":"多维数组","text":"julia> map(tuple, 1/(i+j) for i=1:2, j=1:2, [1:4;])\nERROR: syntax: invalid iteration specification","category":"page"},{"location":"manual/arrays/","page":"多维数组","title":"多维数组","text":"for 后面所有逗号分隔的表达式都被解释为范围。 添加括号让我们可以向 map 中添加第三个参数:","category":"page"},{"location":"manual/arrays/","page":"多维数组","title":"多维数组","text":"julia> map(tuple, (1/(i+j) for i=1:2, j=1:2), [1 3; 2 4])\n2×2 Matrix{Tuple{Float64, Int64}}:\n (0.5, 1) (0.333333, 3)\n (0.333333, 2) (0.25, 4)","category":"page"},{"location":"manual/arrays/","page":"多维数组","title":"多维数组","text":"生成器是通过内部函数实现。 与本语言中别处使用的内部函数一样,封闭作用域中的变量可以在内部函数中被「捕获」。例如,sum(p[i] - q[i] for i=1:n) 从封闭作用域中捕获三个变量 p、q 和 n。但是变量捕获可能会带来性能挑战;请参阅 性能提示。","category":"page"},{"location":"manual/arrays/","page":"多维数组","title":"多维数组","text":"通过编写多个 for 关键字,生成器和推导中的范围可以取决于之前的范围:","category":"page"},{"location":"manual/arrays/","page":"多维数组","title":"多维数组","text":"julia> [(i,j) for i=1:3 for j=1:i]\n6-element Vector{Tuple{Int64, Int64}}:\n (1, 1)\n (2, 1)\n (2, 2)\n (3, 1)\n (3, 2)\n (3, 3)","category":"page"},{"location":"manual/arrays/","page":"多维数组","title":"多维数组","text":"在这些情况下,结果都是一维的。","category":"page"},{"location":"manual/arrays/","page":"多维数组","title":"多维数组","text":"可以使用 if 关键字过滤生成的值:","category":"page"},{"location":"manual/arrays/","page":"多维数组","title":"多维数组","text":"julia> [(i,j) for i=1:3 for j=1:i if i+j == 4]\n2-element Vector{Tuple{Int64, Int64}}:\n (2, 2)\n (3, 1)","category":"page"},{"location":"manual/arrays/#man-array-indexing","page":"多维数组","title":"索引","text":"","category":"section"},{"location":"manual/arrays/","page":"多维数组","title":"多维数组","text":"索引 n 维数组 A 的一般语法是:","category":"page"},{"location":"manual/arrays/","page":"多维数组","title":"多维数组","text":"X = A[I_1, I_2, ..., I_n]","category":"page"},{"location":"manual/arrays/","page":"多维数组","title":"多维数组","text":"其中每个 I_k 可以是标量整数,整数数组或任何其他支持的索引类型。这包括 Colon (:) 来选择整个维度中的所有索引,形式为 a:c 或 a:b:c 的范围来选择连续或跨步的子区间,以及布尔数组以选择索引为 true 的元素。","category":"page"},{"location":"manual/arrays/","page":"多维数组","title":"多维数组","text":"如果所有索引都是标量,则结果 X 是数组 A 中的单个元素。否则,X 是一个数组,其维数与所有索引的维数之和相同。","category":"page"},{"location":"manual/arrays/","page":"多维数组","title":"多维数组","text":"如果所有索引 I_k 都是向量,则 X 的形状将是 (length(I_1), length(I_2), ..., length(I_n)),其中,X 中位于 i_1, i_2, ..., i_n 处的元素为 A[I_1[i_1], I_2[i_2], ..., I_n[i_n]]。","category":"page"},{"location":"manual/arrays/","page":"多维数组","title":"多维数组","text":"例如:","category":"page"},{"location":"manual/arrays/","page":"多维数组","title":"多维数组","text":"julia> A = reshape(collect(1:16), (2, 2, 2, 2))\n2×2×2×2 Array{Int64, 4}:\n[:, :, 1, 1] =\n 1 3\n 2 4\n\n[:, :, 2, 1] =\n 5 7\n 6 8\n\n[:, :, 1, 2] =\n 9 11\n 10 12\n\n[:, :, 2, 2] =\n 13 15\n 14 16\n\njulia> A[1, 2, 1, 1] # 全部为标量索引\n3\n\njulia> A[[1, 2], [1], [1, 2], [1]] # 全部为向量索引\n2×1×2×1 Array{Int64, 4}:\n[:, :, 1, 1] =\n 1\n 2\n\n[:, :, 2, 1] =\n 5\n 6\n\njulia> A[[1, 2], [1], [1, 2], 1] # 标量与向量索引的混合使用\n2×1×2 Array{Int64, 3}:\n[:, :, 1] =\n 1\n 2\n\n[:, :, 2] =\n 5\n 6","category":"page"},{"location":"manual/arrays/","page":"多维数组","title":"多维数组","text":"请注意最后两种情况下得到的数组大小为何是不同的。","category":"page"},{"location":"manual/arrays/","page":"多维数组","title":"多维数组","text":"如果 I_1 是二维矩阵,则 X 是 n+1 维数组,其形状为 (size(I_1, 1), size(I_1, 2), length(I_2), ..., length(I_n))。矩阵会添加一个维度。","category":"page"},{"location":"manual/arrays/","page":"多维数组","title":"多维数组","text":"例如:","category":"page"},{"location":"manual/arrays/","page":"多维数组","title":"多维数组","text":"julia> A = reshape(collect(1:16), (2, 2, 2, 2));\n\njulia> A[[1 2; 1 2]]\n2×2 Matrix{Int64}:\n 1 2\n 1 2\n\njulia> A[[1 2; 1 2], 1, 2, 1]\n2×2 Matrix{Int64}:\n 5 6\n 5 6","category":"page"},{"location":"manual/arrays/","page":"多维数组","title":"多维数组","text":"位于 i_1, i_2, i_3, ..., i_{n+1} 处的元素值是 A[I_1[i_1, i_2], I_2[i_3], ..., I_n[i_{n+1}]]。所有使用标量索引的维度都将被丢弃,例如,假设 J 是索引数组,那么 A[2,J,3] 的结果是一个大小为 size(J) 的数组、其第 j 个元素由 A[2, J[j], 3] 填充。","category":"page"},{"location":"manual/arrays/","page":"多维数组","title":"多维数组","text":"作为此语法的特殊部分,end 关键字可用于表示索引括号内每个维度的最后一个索引,由索引的最内层数组的大小决定。没有 end 关键字的索引语法相当于调用getindex:","category":"page"},{"location":"manual/arrays/","page":"多维数组","title":"多维数组","text":"X = getindex(A, I_1, I_2, ..., I_n)","category":"page"},{"location":"manual/arrays/","page":"多维数组","title":"多维数组","text":"例如:","category":"page"},{"location":"manual/arrays/","page":"多维数组","title":"多维数组","text":"julia> x = reshape(1:16, 4, 4)\n4×4 reshape(::UnitRange{Int64}, 4, 4) with eltype Int64:\n 1 5 9 13\n 2 6 10 14\n 3 7 11 15\n 4 8 12 16\n\njulia> x[2:3, 2:end-1]\n2×2 Matrix{Int64}:\n 6 10\n 7 11\n\njulia> x[1, [2 3; 4 1]]\n2×2 Matrix{Int64}:\n 5 9\n 13 1","category":"page"},{"location":"manual/arrays/#man-indexed-assignment","page":"多维数组","title":"索引赋值","text":"","category":"section"},{"location":"manual/arrays/","page":"多维数组","title":"多维数组","text":"在 n 维数组 A 中赋值的一般语法是:","category":"page"},{"location":"manual/arrays/","page":"多维数组","title":"多维数组","text":"A[I_1, I_2, ..., I_n] = X","category":"page"},{"location":"manual/arrays/","page":"多维数组","title":"多维数组","text":"其中每个 I_k 可以是标量整数,整数数组或任何其他支持的索引类型。这包括 Colon (:) 来选择整个维度中的所有索引,形式为 a:c 或 a:b:c 的范围来选择连续或跨步的子区间,以及布尔数组以选择索引为 true 的元素。","category":"page"},{"location":"manual/arrays/","page":"多维数组","title":"多维数组","text":"如果所有 I_k 都为整数,则数组 A 中 I_1, I_2, ..., I_n 位置的值将被 X 的值覆盖,必要时将 convert 为数组 A 的 eltype。","category":"page"},{"location":"manual/arrays/","page":"多维数组","title":"多维数组","text":"如果索引 I_k 本身就是一个数组,那么右侧的 X 也必须是一个与索引 A[I_1, I_2, ..., I_n] 的结果具有相同形状的数组或是具有相同数量元素的向量。 A 的位置 I_1[i_1], I_2[i_2], ..., I_n[i_n] 中的值被值 X[I_1, I_2, ..., I_n] 覆盖,如果必要也会进行类型转换。 元素分配运算符 .= 可以用于沿着所选区域 广播 X:","category":"page"},{"location":"manual/arrays/","page":"多维数组","title":"多维数组","text":"A[I_1, I_2, ..., I_n] .= X","category":"page"},{"location":"manual/arrays/","page":"多维数组","title":"多维数组","text":"就像在索引中一样,end关键字可用于表示索引括号中每个维度的最后一个索引,由被赋值的数组大小决定。 没有end关键字的索引赋值语法相当于调用setindex!:","category":"page"},{"location":"manual/arrays/","page":"多维数组","title":"多维数组","text":"setindex!(A, X, I_1, I_2, ..., I_n)","category":"page"},{"location":"manual/arrays/","page":"多维数组","title":"多维数组","text":"例如:","category":"page"},{"location":"manual/arrays/","page":"多维数组","title":"多维数组","text":"julia> x = collect(reshape(1:9, 3, 3))\n3×3 Matrix{Int64}:\n 1 4 7\n 2 5 8\n 3 6 9\n\njulia> x[3, 3] = -9;\n\njulia> x[1:2, 1:2] = [-1 -4; -2 -5];\n\njulia> x\n3×3 Matrix{Int64}:\n -1 -4 7\n -2 -5 8\n 3 6 -9","category":"page"},{"location":"manual/arrays/#man-supported-index-types","page":"多维数组","title":"支持的索引类型","text":"","category":"section"},{"location":"manual/arrays/","page":"多维数组","title":"多维数组","text":"在表达式 A[I_1, I_2, ..., I_n] 中,每个 I_k 可以是标量索引,标量索引数组,或者用 to_indices 转换成的表示标量索引数组的对象:","category":"page"},{"location":"manual/arrays/","page":"多维数组","title":"多维数组","text":"标量索引。默认情况下,这包括:\n非布尔的整数\nCartesianIndex{N} 用来表达多个维度的信息(详见下文),其内部实际为 N个整数组成的元组。\n标量索引数组。这包括:\n整数向量和多维整数数组\n像 [] 这样的空数组,它不选择任何元素\n如 a:c 或 a:b:c 的范围,从 a 到 c(包括)选择连续或间隔的部分元素\n任何自定义标量索引数组,它是 AbstractArray 的子类型\nCartesianIndex{N} 数组(详见下文)\n一个表示标量索引数组的对象,可以通过to_indices转换为这样的对象。 默认情况下,这包括:\nColon() (:),表示整个维度内或整个数组中的所有索引\n布尔数组,选择其中值为 true 的索引对应的元素(更多细节见下文)","category":"page"},{"location":"manual/arrays/","page":"多维数组","title":"多维数组","text":"一些例子:","category":"page"},{"location":"manual/arrays/","page":"多维数组","title":"多维数组","text":"julia> A = reshape(collect(1:2:18), (3, 3))\n3×3 Matrix{Int64}:\n 1 7 13\n 3 9 15\n 5 11 17\n\njulia> A[4]\n7\n\njulia> A[[2, 5, 8]]\n3-element Vector{Int64}:\n 3\n 9\n 15\n\njulia> A[[1 4; 3 8]]\n2×2 Matrix{Int64}:\n 1 7\n 5 15\n\njulia> A[[]]\nInt64[]\n\njulia> A[1:2:5]\n3-element Vector{Int64}:\n 1\n 5\n 9\n\njulia> A[2, :]\n3-element Vector{Int64}:\n 3\n 9\n 15\n\njulia> A[:, 3]\n3-element Vector{Int64}:\n 13\n 15\n 17","category":"page"},{"location":"manual/arrays/#笛卡尔索引","page":"多维数组","title":"笛卡尔索引","text":"","category":"section"},{"location":"manual/arrays/","page":"多维数组","title":"多维数组","text":"特殊的 CartesianIndex{N} 对象表示一个标量索引,其行为类似于张成多个维度的 N 维整数元组。例如:","category":"page"},{"location":"manual/arrays/","page":"多维数组","title":"多维数组","text":"julia> A = reshape(1:32, 4, 4, 2);\n\njulia> A[3, 2, 1]\n7\n\njulia> A[CartesianIndex(3, 2, 1)] == A[3, 2, 1] == 7\ntrue","category":"page"},{"location":"manual/arrays/","page":"多维数组","title":"多维数组","text":"单独来看的话,这看起来很平凡:CartesianIndex 单纯只是将多个整数捆绑在一起作为一个对象来表示一个多维下标。当与其他取下标方式和生成 CartesianIndex 的迭代器进行工作的时候,它才真正能展现出它的简洁与高效。关于这个你可以参考 迭代器 这一部分,你也可以参考 关于多维算法和迭代器的介绍 这篇博客来了解更进阶的用法。","category":"page"},{"location":"manual/arrays/","page":"多维数组","title":"多维数组","text":"元素类型为 CartesianIndex{N} 的矩阵也是支持的。每一个元素都单独表示一个 N 维空间的 索引下标,作为一个整体这样一个矩阵则表示一些 N 维空间的点的坐标,因此这种形式有时 也称为逐点索引。例如:你可以通过它来访问上面所定义的三维矩阵 A 的第一页 (第三维指标为1)的对角线元素:","category":"page"},{"location":"manual/arrays/","page":"多维数组","title":"多维数组","text":"julia> page = A[:,:,1]\n4×4 Matrix{Int64}:\n 1 5 9 13\n 2 6 10 14\n 3 7 11 15\n 4 8 12 16\n\njulia> page[[CartesianIndex(1,1),\n CartesianIndex(2,2),\n CartesianIndex(3,3),\n CartesianIndex(4,4)]]\n4-element Vector{Int64}:\n 1\n 6\n 11\n 16","category":"page"},{"location":"manual/arrays/","page":"多维数组","title":"多维数组","text":"这可以通过 dot broadcasting 以及普通整数索引(而不是把从 A 中提取第一“页”作为单独的步骤)更加简单地表达。它甚至可以与 : 结合使用,同时从两个页面中提取两个对角线:","category":"page"},{"location":"manual/arrays/","page":"多维数组","title":"多维数组","text":"julia> A[CartesianIndex.(axes(A, 1), axes(A, 2)), 1]\n4-element Vector{Int64}:\n 1\n 6\n 11\n 16\n\njulia> A[CartesianIndex.(axes(A, 1), axes(A, 2)), :]\n4×2 Matrix{Int64}:\n 1 17\n 6 22\n 11 27\n 16 32","category":"page"},{"location":"manual/arrays/","page":"多维数组","title":"多维数组","text":"warning: Warning\nCartesianIndex 和 CartesianIndex 数组与用来表示维度的最后一个索引的 end 关键字不兼容。 不要在可能包含CartesianIndex或其数组的索引表达式中使用end。","category":"page"},{"location":"manual/arrays/#逻辑索引","page":"多维数组","title":"逻辑索引","text":"","category":"section"},{"location":"manual/arrays/","page":"多维数组","title":"多维数组","text":"通常被称为逻辑索引或带有逻辑掩码的索引,通过布尔数组进行索引选择其值为true的索引处的元素。 通过布尔向量B进行索引实际上与通过findall(B)返回的整数向量进行索引相同。 类似地,通过N维布尔数组进行索引与通过其值为true的CartesianIndex{N}的向量进行索引实际上是相同的。 一个逻辑索引必须是一个与它所索引的维度长度相同的向量,或者它必须是唯一提供的索引并且匹配它所索引到的数组的大小和维度。 通常直接使用布尔数组作为索引更有效,而不是调用 findall。","category":"page"},{"location":"manual/arrays/","page":"多维数组","title":"多维数组","text":"julia> x = reshape(1:16, 4, 4)\n4×4 reshape(::UnitRange{Int64}, 4, 4) with eltype Int64:\n 1 5 9 13\n 2 6 10 14\n 3 7 11 15\n 4 8 12 16\n\njulia> x[[false, true, true, false], :]\n2×4 Matrix{Int64}:\n 2 6 10 14\n 3 7 11 15\n\njulia> mask = map(ispow2, x)\n4×4 Matrix{Bool}:\n 1 0 0 0\n 1 0 0 0\n 0 0 0 0\n 1 1 0 1\n\njulia> x[mask]\n5-element Vector{Int64}:\n 1\n 2\n 4\n 8\n 16","category":"page"},{"location":"manual/arrays/#索引数","page":"多维数组","title":"索引数","text":"","category":"section"},{"location":"manual/arrays/#笛卡尔索引-2","page":"多维数组","title":"笛卡尔索引","text":"","category":"section"},{"location":"manual/arrays/","page":"多维数组","title":"多维数组","text":"通常,为一个N维数组元素使用索引的方式是使用N个数字作为索引,每一个索引值确定一个具体的维度。例如,一个三维数组A = rand(4, 3, 2), A[2, 3, 1] 将选择的第二行第三列第一“页”中的元素。这种方式通常也被成为笛卡尔索引。","category":"page"},{"location":"manual/arrays/#线性索引","page":"多维数组","title":"线性索引","text":"","category":"section"},{"location":"manual/arrays/","page":"多维数组","title":"多维数组","text":"当恰好提供了一个索引i时,该索引不再表示数组特定维度中的位置。 相反,它使用线性遍历整个数组的列主迭代顺序选择第 i 个元素。 这称为线性索引。 它本质上将数组视为使用 vec 将其重新整形为一维向量。","category":"page"},{"location":"manual/arrays/","page":"多维数组","title":"多维数组","text":"julia> A = [2 6; 4 7; 3 1]\n3×2 Matrix{Int64}:\n 2 6\n 4 7\n 3 1\n\njulia> A[5]\n7\n\njulia> vec(A)[5]\n7","category":"page"},{"location":"manual/arrays/","page":"多维数组","title":"多维数组","text":"数组 A 中的线性索引可以转换为 CartesianIndex 以使用 CartesianIndices(A)[i] 进行笛卡尔索引(参见 CartesianIndices),一组 N 维笛卡尔索引可以通过LinearIndices(A)[i_1, i_2, ..., i_N] 转换为线性索引(参见LinearIndices)。","category":"page"},{"location":"manual/arrays/","page":"多维数组","title":"多维数组","text":"julia> CartesianIndices(A)[5]\nCartesianIndex(2, 2)\n\njulia> LinearIndices(A)[2, 2]\n5","category":"page"},{"location":"manual/arrays/","page":"多维数组","title":"多维数组","text":"需要注意的是,这些转换的性能存在很大的不对称性。 将线性索引转换为一组笛卡尔索引需要做除法取余数,而相反的转换只是相乘和相加。 在现代处理器中,整数除法比乘法慢 10-50 倍。 虽然一些数组——比如 Array 本身——是使用线性内存块实现的,并在它们的实现中直接使用线性索引,但其他数组——比如 Diagonal——需要完整的笛卡尔索引集进行查找(请参阅 IndexStyle 以仔细推敲)。 因此,当遍历整个数组时,最好遍历 eachindex(A) 而不是 1:length(A)。 在 A 是 IndexCartesian 的情况下,前者不仅会快得多,而且它还支持 OffsetArrays(译者注:OffsetArrays.jl是Julia的一个包,支持矩阵的下标不从1开始)。","category":"page"},{"location":"manual/arrays/#Omitted-and-extra-indices","page":"多维数组","title":"省略和额外的索引","text":"","category":"section"},{"location":"manual/arrays/","page":"多维数组","title":"多维数组","text":"除了线性索引,在某些情况下, N 维数组的可能少于或多余 N 。","category":"page"},{"location":"manual/arrays/","page":"多维数组","title":"多维数组","text":"如果未索引的剩余维度的长度均为 1,则可以省略索引。 换句话说,只有当那些省略的索引对于索引表达式只有一个可能的值时,才可以省略剩余索引。 例如,一个大小为(3, 4, 2, 1)的四维数组可能只用三个索引进行索引,因为被跳过的维度(第四维)的长度为 1。 请注意,线性索引优先级高于此规则。","category":"page"},{"location":"manual/arrays/","page":"多维数组","title":"多维数组","text":"julia> A = reshape(1:24, 3, 4, 2, 1)\n3×4×2×1 reshape(::UnitRange{Int64}, 3, 4, 2, 1) with eltype Int64:\n[:, :, 1, 1] =\n 1 4 7 10\n 2 5 8 11\n 3 6 9 12\n\n[:, :, 2, 1] =\n 13 16 19 22\n 14 17 20 23\n 15 18 21 24\n\njulia> A[1, 3, 2] # Omits the fourth dimension (length 1)\n19\n\njulia> A[1, 3] # Attempts to omit dimensions 3 & 4 (lengths 2 and 1)\nERROR: BoundsError: attempt to access 3×4×2×1 reshape(::UnitRange{Int64}, 3, 4, 2, 1) with eltype Int64 at index [1, 3]\n\njulia> A[19] # Linear indexing\n19","category":"page"},{"location":"manual/arrays/","page":"多维数组","title":"多维数组","text":"当用A[] 省略全部 索引时,这种语义提供了一种简单的习惯用法来检索数组中的唯一元素,同时确保只有一个元素。","category":"page"},{"location":"manual/arrays/","page":"多维数组","title":"多维数组","text":"类似地,如果超出数组维数的所有索引都是1(或更一般地说是axes(A, d)的第一个也是唯一的元素,其中d是特定的维数),可以使用超过N维的索引。这允许向量像一列矩阵一样被索引,例如:","category":"page"},{"location":"manual/arrays/","page":"多维数组","title":"多维数组","text":"julia> A = [8,6,7]\n3-element Vector{Int64}:\n 8\n 6\n 7\n\njulia> A[2,1]\n6","category":"page"},{"location":"manual/arrays/#Iteration","page":"多维数组","title":"迭代","text":"","category":"section"},{"location":"manual/arrays/","page":"多维数组","title":"多维数组","text":"迭代整个数组的推荐方法是","category":"page"},{"location":"manual/arrays/","page":"多维数组","title":"多维数组","text":"for a in A\n # Do something with the element a\nend\n\nfor i in eachindex(A)\n # Do something with i and/or A[i]\nend","category":"page"},{"location":"manual/arrays/","page":"多维数组","title":"多维数组","text":"当你需要每个元素的值而不是索引时,使用第一个构造。 在第二个构造中,如果 A 是具有快速线性索引的数组类型,i 将是 Int; 否则,它将是一个 CartesianIndex:","category":"page"},{"location":"manual/arrays/","page":"多维数组","title":"多维数组","text":"julia> A = rand(4,3);\n\njulia> B = view(A, 1:3, 2:3);\n\njulia> for i in eachindex(B)\n @show i\n end\ni = CartesianIndex(1, 1)\ni = CartesianIndex(2, 1)\ni = CartesianIndex(3, 1)\ni = CartesianIndex(1, 2)\ni = CartesianIndex(2, 2)\ni = CartesianIndex(3, 2)","category":"page"},{"location":"manual/arrays/","page":"多维数组","title":"多维数组","text":"与 for i = 1:length(A) 相比,eachindex 提供了一种迭代任何数组类型的有效方法。","category":"page"},{"location":"manual/arrays/#Array-traits","page":"多维数组","title":"Array traits","text":"","category":"section"},{"location":"manual/arrays/","page":"多维数组","title":"多维数组","text":"如果你编写一个自定义的 AbstractArray 类型,你可以用以下代码指定它使用快速线性索引","category":"page"},{"location":"manual/arrays/","page":"多维数组","title":"多维数组","text":"Base.IndexStyle(::Type{<:MyArray}) = IndexLinear()","category":"page"},{"location":"manual/arrays/","page":"多维数组","title":"多维数组","text":"此设置将导致 myArray 上的 eachindex 迭代使用整数。如果未指定此特征,则使用默认值 IndexCartesian()。","category":"page"},{"location":"manual/arrays/#man-array-and-vectorized-operators-and-functions","page":"多维数组","title":"数组和向量化的算子与函数","text":"","category":"section"},{"location":"manual/arrays/","page":"多维数组","title":"多维数组","text":"以下运算符支持对数组操作","category":"page"},{"location":"manual/arrays/","page":"多维数组","title":"多维数组","text":"一元运算符 – -, +\n二元运算符 – -, +, *, /, \\, ^\n比较操作符 – ==, !=, ≈ (isapprox), ≉","category":"page"},{"location":"manual/arrays/","page":"多维数组","title":"多维数组","text":"另外,为了便于数学上和其他运算的向量化,Julia 提供了点语法(dot syntax) f.(args...),例如,sin.(x) 或 min.(x,y),用于数组或数组和标量的混合上的按元素运算(广播运算);当与其他点调用(dot call)结合使用时,它们的额外优点是能「融合」到单个循环中,例如,sin.(cos.(x))。","category":"page"},{"location":"manual/arrays/","page":"多维数组","title":"多维数组","text":"此外,每个二元运算符支持相应的点操作版本,可以应用于此类融合 broadcasting 操作的数组(以及数组和标量的组合),例如 z .== sin.(x .* y)。","category":"page"},{"location":"manual/arrays/","page":"多维数组","title":"多维数组","text":"请注意,类似 == 的比较运算在作用于整个数组时,得到一个布尔结果。使用像 .== 这样的点运算符进行按元素的比较。(对于像 < 这样的比较操作,只有按元素运算的版本 .< 适用于数组。)","category":"page"},{"location":"manual/arrays/","page":"多维数组","title":"多维数组","text":"还要注意 max.(a,b) 和 maximum(a) 之间的区别,max.(a,b) 对 a 和 b 的每个元素 broadcasts max,maximum(a) 寻找在 a 中的最大值。min.(a,b) 和 minimum(a) 也有同样的关系。","category":"page"},{"location":"manual/arrays/#Broadcasting","page":"多维数组","title":"广播","text":"","category":"section"},{"location":"manual/arrays/","page":"多维数组","title":"多维数组","text":"有时需要在不同尺寸的数组上执行元素对元素的操作,例如将矩阵的每一列加一个向量。一种低效的方法是将向量复制成矩阵的大小:","category":"page"},{"location":"manual/arrays/","page":"多维数组","title":"多维数组","text":"julia> a = rand(2,1); A = rand(2,3);\n\njulia> repeat(a,1,3)+A\n2×3 Array{Float64,2}:\n 1.20813 1.82068 1.25387\n 1.56851 1.86401 1.67846","category":"page"},{"location":"manual/arrays/","page":"多维数组","title":"多维数组","text":"当维度较大的时候,这种方法将会十分浪费,所以 Julia 提供了广播 broadcast,它将会将参数中低维度的参数扩展,使得其与其他维度匹配,且不会使用额外的内存,并将所给的函数逐元素地应用。","category":"page"},{"location":"manual/arrays/","page":"多维数组","title":"多维数组","text":"julia> broadcast(+, a, A)\n2×3 Array{Float64,2}:\n 1.20813 1.82068 1.25387\n 1.56851 1.86401 1.67846\n\njulia> b = rand(1,2)\n1×2 Array{Float64,2}:\n 0.867535 0.00457906\n\njulia> broadcast(+, a, b)\n2×2 Array{Float64,2}:\n 1.71056 0.847604\n 1.73659 0.873631","category":"page"},{"location":"manual/arrays/","page":"多维数组","title":"多维数组","text":"点运算符 如.+ 和.* 等价于broadcast 调用(除了它们结合使用,如上所述)。 还有一个 broadcast! 函数来指定一个明确的方式(也可以通过.= 赋值以融合方式访问)。 事实上,f.(args...) 等价于broadcast(f, args...),提供了一种方便的语法来广播任何函数(dot syntax)。 嵌套的“点运算符调用”f.(...)(包括对.+ 等的调用)自动融合 到单个broadcast 调用中。","category":"page"},{"location":"manual/arrays/","page":"多维数组","title":"多维数组","text":"此外,broadcast 不限于数组(参见函数文档); 它还处理标量、元组和其它容器。 默认情况下,只有一些参数类型被认为是标量,包括(但不限于)Numbers、Strings、Symbols、Types、Functions 和一些常见的单例,如 missing 和nothing。 所有其他参数都被迭代或逐个索引。","category":"page"},{"location":"manual/arrays/","page":"多维数组","title":"多维数组","text":"julia> convert.(Float32, [1, 2])\n2-element Vector{Float32}:\n 1.0\n 2.0\n\njulia> ceil.(UInt8, [1.2 3.4; 5.6 6.7])\n2×2 Matrix{UInt8}:\n 0x02 0x04\n 0x06 0x07\n\njulia> string.(1:3, \". \", [\"First\", \"Second\", \"Third\"])\n3-element Vector{String}:\n \"1. First\"\n \"2. Second\"\n \"3. Third\"","category":"page"},{"location":"manual/arrays/","page":"多维数组","title":"多维数组","text":"有时,你希望一个通常参与广播的容器(如数组)受到“保护”,使其免受广播迭代其所有元素的行为的影响。 通过将其放置在另一个容器中(如单个元素 Tuple),广播会将其视为单个值。","category":"page"},{"location":"manual/arrays/","page":"多维数组","title":"多维数组","text":"julia> ([1, 2, 3], [4, 5, 6]) .+ ([1, 2, 3],)\n([2, 4, 6], [5, 7, 9])\n\njulia> ([1, 2, 3], [4, 5, 6]) .+ tuple([1, 2, 3])\n([2, 4, 6], [5, 7, 9])","category":"page"},{"location":"manual/arrays/#实现","page":"多维数组","title":"实现","text":"","category":"section"},{"location":"manual/arrays/","page":"多维数组","title":"多维数组","text":"Julia 中的基本数组类型是抽象类型 AbstractArray{T,N}。它通过维数 N 和元素类型 T 进行参数化。AbstractVector 和 AbstractMatrix 是一维和二维情况下的别名。AbstractArray 对象的操作是使用更高级别的运算符和函数定义的,其方式独立于底层存储。这些操作可以正确地被用于任何特定数组实现的回退操作。","category":"page"},{"location":"manual/arrays/","page":"多维数组","title":"多维数组","text":"AbstractArray 类型包括任何类似数组的东西,它的实现可能与传统数组完全不同。例如,元素可能根据请求计算而不是存储。然而,任何具体的 AbstractArray{T,N} 类型通常应该至少实现 size(A)(返回一个 Int 元组),getindex(A,i) 和 getindex(A,i1,...,iN);可变数组也应该实现 setindex!。建议这些操作具有常数时间复杂度,否则某些数组函数可能会出乎意料的慢。具体类型通常还应该提供一个 similar(A,T=eltype(A),dims=size(A)) 方法,用于为 copy 和其他不合适的操作。无论 AbstractArray{T,N} 在内部如何表示,T 都是由 整数 索引(A[1, ..., 1],当 A 非空) 返回的对象类型并且 N 应该是 size 返回的元组的长度。有关自定义 AbstractArray 实现的更多详细信息,请参阅 接口章节中的数组接口指南。","category":"page"},{"location":"manual/arrays/","page":"多维数组","title":"多维数组","text":"DenseArray 是 AbstractArray 的抽象子类型,旨在包括元素以列优先顺序连续存储的所有数组(请参阅 性能提示中的附加说明)。 Array 类型是DenseArray 的一个特定实例; Vector 和 Matrix 是一维和二维情况的别名。 除了所有AbstractArrays所需的操作之外,很少有专门为Array实现的操作;大部分数组库都是以泛型方式实现的,允许所有自定义数组的行为类似。","category":"page"},{"location":"manual/arrays/","page":"多维数组","title":"多维数组","text":"SubArray 是 AbstractArray 的特例,它通过与原始数组共享内存而不是复制它来执行索引。 使用view 函数创建 SubArray,它的调用方式与getindex 相同(作用于数组和一系列索引参数)。 view 的结果看起来与 getindex 的结果相同,只是数据保持不变。 view 将输入索引向量存储在 SubArray 对象中,该对象稍后可用于间接索引原始数组。 通过将 @views 宏放在表达式或代码块之前,该表达式中的任何 array [...] 切片将被转换为创建一个 SubArray 视图。","category":"page"},{"location":"manual/arrays/","page":"多维数组","title":"多维数组","text":"BitArray 是节省空间“压缩”的布尔数组,每个比特(bit)存储一个布尔值。 它们可以类似于 Array{Bool} 数组(每个字节(byte)存储一个布尔值),并且可以分别通过 Array(bitarray) 和 BitArray(array) 相互转换。","category":"page"},{"location":"manual/arrays/","page":"多维数组","title":"多维数组","text":"如果数组存储在内存中,其元素之间具有明确定义的间距(步长),则该数组是“等步长的”的。 通过简单地传递其 pointer 和每个维度的步长,可以将有支持元素类型的等步长数组传递给外部(非 Julia)库,如 BLAS 或 LAPACK。 stride(A, d) 是元素之间沿维度 d 的距离。 例如,rand(5,7,2) 返回的内置 Array 的元素按列优先顺序连续排列。 这意味着第一个维度的步长——同一列中元素之间的间距——是1:","category":"page"},{"location":"manual/arrays/","page":"多维数组","title":"多维数组","text":"julia> A = rand(5,7,2);\n\njulia> stride(A,1)\n1","category":"page"},{"location":"manual/arrays/","page":"多维数组","title":"多维数组","text":"第二个维度的步长是同一行中元素之间的间距,跳过与单列(5)中的元素一样多的元素。 类似地,在两个“页面”(在第三维中)之间跳转需要跳过 5*7 == 35 元素。 这个数组的 strides 是这三个数字组成的元组:","category":"page"},{"location":"manual/arrays/","page":"多维数组","title":"多维数组","text":"julia> strides(A)\n(1, 5, 35)","category":"page"},{"location":"manual/arrays/","page":"多维数组","title":"多维数组","text":"在这种特殊情况下,在内存中跳过的元素数与跳过的线性索引数相匹配。 这仅适用于像 Array(和其他 DenseArray 子类型)这样的连续数组,通常情况下并非如此。 具有范围索引的视图是 非连续 等步长数组的一个很好的例子; 考虑V = @view A[1:3:4, 2:2:6, 2:-1:1]。 这个视图 V 与 A 引用了相同的内存,但它跳过并重新排列了它的一些元素。 V 的第一维的步幅是 3,因为我们只从原始数组中选择每第三行:","category":"page"},{"location":"manual/arrays/","page":"多维数组","title":"多维数组","text":"julia> V = @view A[1:3:4, 2:2:6, 2:-1:1];\n\njulia> stride(V, 1)\n3","category":"page"},{"location":"manual/arrays/","page":"多维数组","title":"多维数组","text":"这个视图类似于从我们原来的A中每隔一列选择一列——因此当在第二维的索引之间移动时,它需要跳过相当于两个五元素列的内容:","category":"page"},{"location":"manual/arrays/","page":"多维数组","title":"多维数组","text":"julia> stride(V, 2)\n10","category":"page"},{"location":"manual/arrays/","page":"多维数组","title":"多维数组","text":"第三维很有趣因为它的顺序颠倒了! 因此从第一 \"页\" 到第二页它必须在内存中到 backwards,所以它在这一维的 strides 是负的!","category":"page"},{"location":"manual/arrays/","page":"多维数组","title":"多维数组","text":"julia> stride(V, 3)\n-35","category":"page"},{"location":"manual/arrays/","page":"多维数组","title":"多维数组","text":"这意味着V 的pointer 实际上指向A 的内存块的中间,并且它在内存中指向元素是同时向后和向前的。 有关定义你自己的跨距数组的更多详细信息,请参阅 等步长数组的接口指南。 StridedVector 和 StridedMatrix 被认为是等步长数组的内置数组类型的方便别名,允许它们仅使用指针和步幅,来分派选择调用调整和优化后的 BLAS 和 LAPACK 函数。","category":"page"},{"location":"manual/arrays/","page":"多维数组","title":"多维数组","text":"需要强调的是 strides 是关于内存而不是索引中的偏移。如果你在找在线性(单索引)索引和笛卡尔(多索引)索引间切换的方法,见 LinearIndices 和 CartesianIndices.","category":"page"},{"location":"base/file/#文件系统","page":"文件系统","title":"文件系统","text":"","category":"section"},{"location":"base/file/","page":"文件系统","title":"文件系统","text":"Base.Filesystem.pwd\nBase.Filesystem.cd(::AbstractString)\nBase.Filesystem.cd(::Function)\nBase.Filesystem.readdir\nBase.Filesystem.walkdir\nBase.Filesystem.mkdir\nBase.Filesystem.mkpath\nBase.Filesystem.symlink\nBase.Filesystem.readlink\nBase.Filesystem.chmod\nBase.Filesystem.chown\nBase.RawFD\nBase.stat\nBase.Filesystem.lstat\nBase.Filesystem.ctime\nBase.Filesystem.mtime\nBase.Filesystem.filemode\nBase.Filesystem.filesize\nBase.Filesystem.uperm\nBase.Filesystem.gperm\nBase.Filesystem.operm\nBase.Filesystem.cp\nBase.download\nBase.Filesystem.mv\nBase.Filesystem.rm\nBase.Filesystem.touch\nBase.Filesystem.tempname\nBase.Filesystem.tempdir\nBase.Filesystem.mktemp(::AbstractString)\nBase.Filesystem.mktemp(::Function, ::AbstractString)\nBase.Filesystem.mktempdir(::AbstractString)\nBase.Filesystem.mktempdir(::Function, ::AbstractString)\nBase.Filesystem.isblockdev\nBase.Filesystem.ischardev\nBase.Filesystem.isdir\nBase.Filesystem.isfifo\nBase.Filesystem.isfile\nBase.Filesystem.islink\nBase.Filesystem.ismount\nBase.Filesystem.ispath\nBase.Filesystem.issetgid\nBase.Filesystem.issetuid\nBase.Filesystem.issocket\nBase.Filesystem.issticky\nBase.Filesystem.homedir\nBase.Filesystem.dirname\nBase.Filesystem.basename\nBase.Filesystem.isabspath\nBase.Filesystem.isdirpath\nBase.Filesystem.joinpath\nBase.Filesystem.abspath\nBase.Filesystem.normpath\nBase.Filesystem.realpath\nBase.Filesystem.relpath\nBase.Filesystem.expanduser\nBase.Filesystem.splitdir\nBase.Filesystem.splitdrive\nBase.Filesystem.splitext\nBase.Filesystem.splitpath","category":"page"},{"location":"base/file/#Base.Filesystem.pwd","page":"文件系统","title":"Base.Filesystem.pwd","text":"pwd() -> AbstractString\n\nGet the current working directory.\n\nSee also: cd, tempdir.\n\nExamples\n\njulia> pwd()\n\"/home/JuliaUser\"\n\njulia> cd(\"/home/JuliaUser/Projects/julia\")\n\njulia> pwd()\n\"/home/JuliaUser/Projects/julia\"\n\n\n\n\n\n","category":"function"},{"location":"base/file/#Base.Filesystem.cd-Tuple{AbstractString}","page":"文件系统","title":"Base.Filesystem.cd","text":"cd(dir::AbstractString=homedir())\n\nSet the current working directory.\n\nSee also: pwd, mkdir, mkpath, mktempdir.\n\nExamples\n\njulia> cd(\"/home/JuliaUser/Projects/julia\")\n\njulia> pwd()\n\"/home/JuliaUser/Projects/julia\"\n\njulia> cd()\n\njulia> pwd()\n\"/home/JuliaUser\"\n\n\n\n\n\n","category":"method"},{"location":"base/file/#Base.Filesystem.cd-Tuple{Function}","page":"文件系统","title":"Base.Filesystem.cd","text":"cd(f::Function, dir::AbstractString=homedir())\n\nTemporarily change the current working directory to dir, apply function f and finally return to the original directory.\n\nExamples\n\njulia> pwd()\n\"/home/JuliaUser\"\n\njulia> cd(readdir, \"/home/JuliaUser/Projects/julia\")\n34-element Array{String,1}:\n \".circleci\"\n \".freebsdci.sh\"\n \".git\"\n \".gitattributes\"\n \".github\"\n ⋮\n \"test\"\n \"ui\"\n \"usr\"\n \"usr-staging\"\n\njulia> pwd()\n\"/home/JuliaUser\"\n\n\n\n\n\n","category":"method"},{"location":"base/file/#Base.Filesystem.readdir","page":"文件系统","title":"Base.Filesystem.readdir","text":"readdir(dir::AbstractString=pwd();\n join::Bool = false,\n sort::Bool = true,\n) -> Vector{String}\n\nReturn the names in the directory dir or the current working directory if not given. When join is false, readdir returns just the names in the directory as is; when join is true, it returns joinpath(dir, name) for each name so that the returned strings are full paths. If you want to get absolute paths back, call readdir with an absolute directory path and join set to true.\n\nBy default, readdir sorts the list of names it returns. If you want to skip sorting the names and get them in the order that the file system lists them, you can use readdir(dir, sort=false) to opt out of sorting.\n\ncompat: Julia 1.4\nThe join and sort keyword arguments require at least Julia 1.4.\n\nExamples\n\njulia> cd(\"/home/JuliaUser/dev/julia\")\n\njulia> readdir()\n30-element Array{String,1}:\n \".appveyor.yml\"\n \".git\"\n \".gitattributes\"\n ⋮\n \"ui\"\n \"usr\"\n \"usr-staging\"\n\njulia> readdir(join=true)\n30-element Array{String,1}:\n \"/home/JuliaUser/dev/julia/.appveyor.yml\"\n \"/home/JuliaUser/dev/julia/.git\"\n \"/home/JuliaUser/dev/julia/.gitattributes\"\n ⋮\n \"/home/JuliaUser/dev/julia/ui\"\n \"/home/JuliaUser/dev/julia/usr\"\n \"/home/JuliaUser/dev/julia/usr-staging\"\n\njulia> readdir(\"base\")\n145-element Array{String,1}:\n \".gitignore\"\n \"Base.jl\"\n \"Enums.jl\"\n ⋮\n \"version_git.sh\"\n \"views.jl\"\n \"weakkeydict.jl\"\n\njulia> readdir(\"base\", join=true)\n145-element Array{String,1}:\n \"base/.gitignore\"\n \"base/Base.jl\"\n \"base/Enums.jl\"\n ⋮\n \"base/version_git.sh\"\n \"base/views.jl\"\n \"base/weakkeydict.jl\"```\n\njulia> readdir(abspath(\"base\"), join=true)\n145-element Array{String,1}:\n \"/home/JuliaUser/dev/julia/base/.gitignore\"\n \"/home/JuliaUser/dev/julia/base/Base.jl\"\n \"/home/JuliaUser/dev/julia/base/Enums.jl\"\n ⋮\n \"/home/JuliaUser/dev/julia/base/version_git.sh\"\n \"/home/JuliaUser/dev/julia/base/views.jl\"\n \"/home/JuliaUser/dev/julia/base/weakkeydict.jl\"\n\n\n\n\n\n","category":"function"},{"location":"base/file/#Base.Filesystem.walkdir","page":"文件系统","title":"Base.Filesystem.walkdir","text":"walkdir(dir; topdown=true, follow_symlinks=false, onerror=throw)\n\nReturn an iterator that walks the directory tree of a directory. The iterator returns a tuple containing (rootpath, dirs, files). The directory tree can be traversed top-down or bottom-up. If walkdir or stat encounters a IOError it will rethrow the error by default. A custom error handling function can be provided through onerror keyword argument. onerror is called with a IOError as argument.\n\nExamples\n\nfor (root, dirs, files) in walkdir(\".\")\n println(\"Directories in $root\")\n for dir in dirs\n println(joinpath(root, dir)) # path to directories\n end\n println(\"Files in $root\")\n for file in files\n println(joinpath(root, file)) # path to files\n end\nend\n\njulia> mkpath(\"my/test/dir\");\n\njulia> itr = walkdir(\"my\");\n\njulia> (root, dirs, files) = first(itr)\n(\"my\", [\"test\"], String[])\n\njulia> (root, dirs, files) = first(itr)\n(\"my/test\", [\"dir\"], String[])\n\njulia> (root, dirs, files) = first(itr)\n(\"my/test/dir\", String[], String[])\n\n\n\n\n\n","category":"function"},{"location":"base/file/#Base.Filesystem.mkdir","page":"文件系统","title":"Base.Filesystem.mkdir","text":"mkdir(path::AbstractString; mode::Unsigned = 0o777)\n\nMake a new directory with name path and permissions mode. mode defaults to 0o777, modified by the current file creation mask. This function never creates more than one directory. If the directory already exists, or some intermediate directories do not exist, this function throws an error. See mkpath for a function which creates all required intermediate directories. Return path.\n\nExamples\n\njulia> mkdir(\"testingdir\")\n\"testingdir\"\n\njulia> cd(\"testingdir\")\n\njulia> pwd()\n\"/home/JuliaUser/testingdir\"\n\n\n\n\n\n","category":"function"},{"location":"base/file/#Base.Filesystem.mkpath","page":"文件系统","title":"Base.Filesystem.mkpath","text":"mkpath(path::AbstractString; mode::Unsigned = 0o777)\n\nCreate all intermediate directories in the path as required. Directories are created with the permissions mode which defaults to 0o777 and is modified by the current file creation mask. Unlike mkdir, mkpath does not error if path (or parts of it) already exists. However, an error will be thrown if path (or parts of it) points to an existing file. Return path.\n\nIf path includes a filename you will probably want to use mkpath(dirname(path)) to avoid creating a directory using the filename.\n\nExamples\n\njulia> cd(mktempdir())\n\njulia> mkpath(\"my/test/dir\") # creates three directories\n\"my/test/dir\"\n\njulia> readdir()\n1-element Array{String,1}:\n \"my\"\n\njulia> cd(\"my\")\n\njulia> readdir()\n1-element Array{String,1}:\n \"test\"\n\njulia> readdir(\"test\")\n1-element Array{String,1}:\n \"dir\"\n\njulia> mkpath(\"intermediate_dir/actually_a_directory.txt\") # creates two directories\n\"intermediate_dir/actually_a_directory.txt\"\n\njulia> isdir(\"intermediate_dir/actually_a_directory.txt\")\ntrue\n\n\n\n\n\n\n","category":"function"},{"location":"base/file/#Base.Filesystem.symlink","page":"文件系统","title":"Base.Filesystem.symlink","text":"symlink(target::AbstractString, link::AbstractString; dir_target = false)\n\nCreates a symbolic link to target with the name link.\n\nOn Windows, symlinks must be explicitly declared as referring to a directory or not. If target already exists, by default the type of link will be auto- detected, however if target does not exist, this function defaults to creating a file symlink unless dir_target is set to true. Note that if the user sets dir_target but target exists and is a file, a directory symlink will still be created, but dereferencing the symlink will fail, just as if the user creates a file symlink (by calling symlink() with dir_target set to false before the directory is created) and tries to dereference it to a directory.\n\nAdditionally, there are two methods of making a link on Windows; symbolic links and junction points. Junction points are slightly more efficient, but do not support relative paths, so if a relative directory symlink is requested (as denoted by isabspath(target) returning false) a symlink will be used, else a junction point will be used. Best practice for creating symlinks on Windows is to create them only after the files/directories they reference are already created.\n\nSee also: hardlink.\n\nnote: Note\nThis function raises an error under operating systems that do not support soft symbolic links, such as Windows XP.\n\ncompat: Julia 1.6\nThe dir_target keyword argument was added in Julia 1.6. Prior to this, symlinks to nonexistant paths on windows would always be file symlinks, and relative symlinks to directories were not supported.\n\n\n\n\n\n","category":"function"},{"location":"base/file/#Base.Filesystem.readlink","page":"文件系统","title":"Base.Filesystem.readlink","text":"readlink(path::AbstractString) -> AbstractString\n\nReturn the target location a symbolic link path points to.\n\n\n\n\n\n","category":"function"},{"location":"base/file/#Base.Filesystem.chmod","page":"文件系统","title":"Base.Filesystem.chmod","text":"chmod(path::AbstractString, mode::Integer; recursive::Bool=false)\n\nChange the permissions mode of path to mode. Only integer modes (e.g. 0o777) are currently supported. If recursive=true and the path is a directory all permissions in that directory will be recursively changed. Return path.\n\nnote: Note\nPrior to Julia 1.6, this did not correctly manipulate filesystem ACLs on Windows, therefore it would only set read-only bits on files. It now is able to manipulate ACLs.\n\n\n\n\n\n","category":"function"},{"location":"base/file/#Base.Filesystem.chown","page":"文件系统","title":"Base.Filesystem.chown","text":"chown(path::AbstractString, owner::Integer, group::Integer=-1)\n\nChange the owner and/or group of path to owner and/or group. If the value entered for owner or group is -1 the corresponding ID will not change. Only integer owners and groups are currently supported. Return path.\n\n\n\n\n\n","category":"function"},{"location":"base/file/#Base.Libc.RawFD","page":"文件系统","title":"Base.Libc.RawFD","text":"RawFD\n\nPrimitive type which wraps the native OS file descriptor. RawFDs can be passed to methods like stat to discover information about the underlying file, and can also be used to open streams, with the RawFD describing the OS file backing the stream.\n\n\n\n\n\n","category":"type"},{"location":"base/file/#Base.stat","page":"文件系统","title":"Base.stat","text":"stat(file)\n\nReturns a structure whose fields contain information about the file. The fields of the structure are:\n\nName Description\ndesc The path or OS file descriptor\nsize The size (in bytes) of the file\ndevice ID of the device that contains the file\ninode The inode number of the file\nmode The protection mode of the file\nnlink The number of hard links to the file\nuid The user id of the owner of the file\ngid The group id of the file owner\nrdev If this file refers to a device, the ID of the device it refers to\nblksize The file-system preferred block size for the file\nblocks The number of such blocks allocated\nmtime Unix timestamp of when the file was last modified\nctime Unix timestamp of when the file's metadata was changed\n\n\n\n\n\n","category":"function"},{"location":"base/file/#Base.Filesystem.lstat","page":"文件系统","title":"Base.Filesystem.lstat","text":"lstat(file)\n\nLike stat, but for symbolic links gets the info for the link itself rather than the file it refers to. This function must be called on a file path rather than a file object or a file descriptor.\n\n\n\n\n\n","category":"function"},{"location":"base/file/#Base.Filesystem.ctime","page":"文件系统","title":"Base.Filesystem.ctime","text":"ctime(file)\n\nEquivalent to stat(file).ctime.\n\n\n\n\n\n","category":"function"},{"location":"base/file/#Base.Filesystem.mtime","page":"文件系统","title":"Base.Filesystem.mtime","text":"mtime(file)\n\nEquivalent to stat(file).mtime.\n\n\n\n\n\n","category":"function"},{"location":"base/file/#Base.Filesystem.filemode","page":"文件系统","title":"Base.Filesystem.filemode","text":"filemode(file)\n\nEquivalent to stat(file).mode.\n\n\n\n\n\n","category":"function"},{"location":"base/file/#Base.filesize","page":"文件系统","title":"Base.filesize","text":"filesize(path...)\n\nEquivalent to stat(file).size.\n\n\n\n\n\n","category":"function"},{"location":"base/file/#Base.Filesystem.uperm","page":"文件系统","title":"Base.Filesystem.uperm","text":"uperm(file)\n\nGet the permissions of the owner of the file as a bitfield of\n\nValue Description\n01 Execute Permission\n02 Write Permission\n04 Read Permission\n\nFor allowed arguments, see stat.\n\n\n\n\n\n","category":"function"},{"location":"base/file/#Base.Filesystem.gperm","page":"文件系统","title":"Base.Filesystem.gperm","text":"gperm(file)\n\nLike uperm but gets the permissions of the group owning the file.\n\n\n\n\n\n","category":"function"},{"location":"base/file/#Base.Filesystem.operm","page":"文件系统","title":"Base.Filesystem.operm","text":"operm(file)\n\nLike uperm but gets the permissions for people who neither own the file nor are a member of the group owning the file\n\n\n\n\n\n","category":"function"},{"location":"base/file/#Base.Filesystem.cp","page":"文件系统","title":"Base.Filesystem.cp","text":"cp(src::AbstractString, dst::AbstractString; force::Bool=false, follow_symlinks::Bool=false)\n\nCopy the file, link, or directory from src to dst. force=true will first remove an existing dst.\n\nIf follow_symlinks=false, and src is a symbolic link, dst will be created as a symbolic link. If follow_symlinks=true and src is a symbolic link, dst will be a copy of the file or directory src refers to. Return dst.\n\nnote: Note\nThe cp function is different from the cp command. The cp function always operates on the assumption that dst is a file, while the command does different things depending on whether dst is a directory or a file. Using force=true when dst is a directory will result in loss of all the contents present in the dst directory, and dst will become a file that has the contents of src instead.\n\n\n\n\n\n","category":"function"},{"location":"base/file/#Base.download","page":"文件系统","title":"Base.download","text":"download(url::AbstractString, [path::AbstractString = tempname()]) -> path\n\nDownload a file from the given url, saving it to the location path, or if not specified, a temporary path. Returns the path of the downloaded file.\n\nnote: Note\nSince Julia 1.6, this function is deprecated and is just a thin wrapper around Downloads.download. In new code, you should use that function directly instead of calling this.\n\n\n\n\n\n","category":"function"},{"location":"base/file/#Base.Filesystem.mv","page":"文件系统","title":"Base.Filesystem.mv","text":"mv(src::AbstractString, dst::AbstractString; force::Bool=false)\n\nMove the file, link, or directory from src to dst. force=true will first remove an existing dst. Return dst.\n\nExamples\n\njulia> write(\"hello.txt\", \"world\");\n\njulia> mv(\"hello.txt\", \"goodbye.txt\")\n\"goodbye.txt\"\n\njulia> \"hello.txt\" in readdir()\nfalse\n\njulia> readline(\"goodbye.txt\")\n\"world\"\n\njulia> write(\"hello.txt\", \"world2\");\n\njulia> mv(\"hello.txt\", \"goodbye.txt\")\nERROR: ArgumentError: 'goodbye.txt' exists. `force=true` is required to remove 'goodbye.txt' before moving.\nStacktrace:\n [1] #checkfor_mv_cp_cptree#10(::Bool, ::Function, ::String, ::String, ::String) at ./file.jl:293\n[...]\n\njulia> mv(\"hello.txt\", \"goodbye.txt\", force=true)\n\"goodbye.txt\"\n\njulia> rm(\"goodbye.txt\");\n\n\n\n\n\n\n","category":"function"},{"location":"base/file/#Base.Filesystem.rm","page":"文件系统","title":"Base.Filesystem.rm","text":"rm(path::AbstractString; force::Bool=false, recursive::Bool=false)\n\nDelete the file, link, or empty directory at the given path. If force=true is passed, a non-existing path is not treated as error. If recursive=true is passed and the path is a directory, then all contents are removed recursively.\n\nExamples\n\njulia> mkpath(\"my/test/dir\");\n\njulia> rm(\"my\", recursive=true)\n\njulia> rm(\"this_file_does_not_exist\", force=true)\n\njulia> rm(\"this_file_does_not_exist\")\nERROR: IOError: unlink(\"this_file_does_not_exist\"): no such file or directory (ENOENT)\nStacktrace:\n[...]\n\n\n\n\n\n","category":"function"},{"location":"base/file/#Base.Filesystem.touch","page":"文件系统","title":"Base.Filesystem.touch","text":"touch(path::AbstractString)\n\nUpdate the last-modified timestamp on a file to the current time.\n\nIf the file does not exist a new file is created.\n\nReturn path.\n\nExamples\n\njulia> write(\"my_little_file\", 2);\n\njulia> mtime(\"my_little_file\")\n1.5273815391135583e9\n\njulia> touch(\"my_little_file\");\n\njulia> mtime(\"my_little_file\")\n1.527381559163435e9\n\nWe can see the mtime has been modified by touch.\n\n\n\n\n\n","category":"function"},{"location":"base/file/#Base.Filesystem.tempname","page":"文件系统","title":"Base.Filesystem.tempname","text":"tempname(parent=tempdir(); cleanup=true) -> String\n\nGenerate a temporary file path. This function only returns a path; no file is created. The path is likely to be unique, but this cannot be guaranteed due to the very remote posibility of two simultaneous calls to tempname generating the same file name. The name is guaranteed to differ from all files already existing at the time of the call to tempname.\n\nWhen called with no arguments, the temporary name will be an absolute path to a temporary name in the system temporary directory as given by tempdir(). If a parent directory argument is given, the temporary path will be in that directory instead.\n\nThe cleanup option controls whether the process attempts to delete the returned path automatically when the process exits. Note that the tempname function does not create any file or directory at the returned location, so there is nothing to cleanup unless you create a file or directory there. If you do and clean is true it will be deleted upon process termination.\n\ncompat: Julia 1.4\nThe parent and cleanup arguments were added in 1.4. Prior to Julia 1.4 the path tempname would never be cleaned up at process termination.\n\nwarning: Warning\nThis can lead to security holes if another process obtains the same file name and creates the file before you are able to. Open the file with JL_O_EXCL if this is a concern. Using mktemp() is also recommended instead.\n\n\n\n\n\n","category":"function"},{"location":"base/file/#Base.Filesystem.tempdir","page":"文件系统","title":"Base.Filesystem.tempdir","text":"tempdir()\n\nGets the path of the temporary directory. On Windows, tempdir() uses the first environment variable found in the ordered list TMP, TEMP, USERPROFILE. On all other operating systems, tempdir() uses the first environment variable found in the ordered list TMPDIR, TMP, TEMP, and TEMPDIR. If none of these are found, the path \"/tmp\" is used.\n\n\n\n\n\n","category":"function"},{"location":"base/file/#Base.Filesystem.mktemp-Tuple{AbstractString}","page":"文件系统","title":"Base.Filesystem.mktemp","text":"mktemp(parent=tempdir(); cleanup=true) -> (path, io)\n\nReturn (path, io), where path is the path of a new temporary file in parent and io is an open file object for this path. The cleanup option controls whether the temporary file is automatically deleted when the process exits.\n\ncompat: Julia 1.3\nThe cleanup keyword argument was added in Julia 1.3. Relatedly, starting from 1.3, Julia will remove the temporary paths created by mktemp when the Julia process exits, unless cleanup is explicitly set to false.\n\n\n\n\n\n","category":"method"},{"location":"base/file/#Base.Filesystem.mktemp-Tuple{Function, AbstractString}","page":"文件系统","title":"Base.Filesystem.mktemp","text":"mktemp(f::Function, parent=tempdir())\n\nApply the function f to the result of mktemp(parent) and remove the temporary file upon completion.\n\nSee also: mktempdir.\n\n\n\n\n\n","category":"method"},{"location":"base/file/#Base.Filesystem.mktempdir-Tuple{AbstractString}","page":"文件系统","title":"Base.Filesystem.mktempdir","text":"mktempdir(parent=tempdir(); prefix=\"jl_\", cleanup=true) -> path\n\nCreate a temporary directory in the parent directory with a name constructed from the given prefix and a random suffix, and return its path. Additionally, any trailing X characters may be replaced with random characters. If parent does not exist, throw an error. The cleanup option controls whether the temporary directory is automatically deleted when the process exits.\n\ncompat: Julia 1.2\nThe prefix keyword argument was added in Julia 1.2.\n\ncompat: Julia 1.3\nThe cleanup keyword argument was added in Julia 1.3. Relatedly, starting from 1.3, Julia will remove the temporary paths created by mktempdir when the Julia process exits, unless cleanup is explicitly set to false.\n\nSee also: mktemp, mkdir.\n\n\n\n\n\n","category":"method"},{"location":"base/file/#Base.Filesystem.mktempdir-Tuple{Function, AbstractString}","page":"文件系统","title":"Base.Filesystem.mktempdir","text":"mktempdir(f::Function, parent=tempdir(); prefix=\"jl_\")\n\nApply the function f to the result of mktempdir(parent; prefix) and remove the temporary directory all of its contents upon completion.\n\nSee also: mktemp, mkdir.\n\ncompat: Julia 1.2\nThe prefix keyword argument was added in Julia 1.2.\n\n\n\n\n\n","category":"method"},{"location":"base/file/#Base.Filesystem.isblockdev","page":"文件系统","title":"Base.Filesystem.isblockdev","text":"isblockdev(path) -> Bool\n\nReturn true if path is a block device, false otherwise.\n\n\n\n\n\n","category":"function"},{"location":"base/file/#Base.Filesystem.ischardev","page":"文件系统","title":"Base.Filesystem.ischardev","text":"ischardev(path) -> Bool\n\nReturn true if path is a character device, false otherwise.\n\n\n\n\n\n","category":"function"},{"location":"base/file/#Base.Filesystem.isdir","page":"文件系统","title":"Base.Filesystem.isdir","text":"isdir(path) -> Bool\n\nReturn true if path is a directory, false otherwise.\n\nExamples\n\njulia> isdir(homedir())\ntrue\n\njulia> isdir(\"not/a/directory\")\nfalse\n\nSee also isfile and ispath.\n\n\n\n\n\n","category":"function"},{"location":"base/file/#Base.Filesystem.isfifo","page":"文件系统","title":"Base.Filesystem.isfifo","text":"isfifo(path) -> Bool\n\nReturn true if path is a FIFO, false otherwise.\n\n\n\n\n\n","category":"function"},{"location":"base/file/#Base.Filesystem.isfile","page":"文件系统","title":"Base.Filesystem.isfile","text":"isfile(path) -> Bool\n\nReturn true if path is a regular file, false otherwise.\n\nExamples\n\njulia> isfile(homedir())\nfalse\n\njulia> f = open(\"test_file.txt\", \"w\");\n\njulia> isfile(f)\ntrue\n\njulia> close(f); rm(\"test_file.txt\")\n\nSee also isdir and ispath.\n\n\n\n\n\n","category":"function"},{"location":"base/file/#Base.Filesystem.islink","page":"文件系统","title":"Base.Filesystem.islink","text":"islink(path) -> Bool\n\nReturn true if path is a symbolic link, false otherwise.\n\n\n\n\n\n","category":"function"},{"location":"base/file/#Base.Filesystem.ismount","page":"文件系统","title":"Base.Filesystem.ismount","text":"ismount(path) -> Bool\n\nReturn true if path is a mount point, false otherwise.\n\n\n\n\n\n","category":"function"},{"location":"base/file/#Base.Filesystem.ispath","page":"文件系统","title":"Base.Filesystem.ispath","text":"ispath(path) -> Bool\n\nReturn true if a valid filesystem entity exists at path, otherwise returns false. This is the generalization of isfile, isdir etc.\n\n\n\n\n\n","category":"function"},{"location":"base/file/#Base.Filesystem.issetgid","page":"文件系统","title":"Base.Filesystem.issetgid","text":"issetgid(path) -> Bool\n\nReturn true if path has the setgid flag set, false otherwise.\n\n\n\n\n\n","category":"function"},{"location":"base/file/#Base.Filesystem.issetuid","page":"文件系统","title":"Base.Filesystem.issetuid","text":"issetuid(path) -> Bool\n\nReturn true if path has the setuid flag set, false otherwise.\n\n\n\n\n\n","category":"function"},{"location":"base/file/#Base.Filesystem.issocket","page":"文件系统","title":"Base.Filesystem.issocket","text":"issocket(path) -> Bool\n\nReturn true if path is a socket, false otherwise.\n\n\n\n\n\n","category":"function"},{"location":"base/file/#Base.Filesystem.issticky","page":"文件系统","title":"Base.Filesystem.issticky","text":"issticky(path) -> Bool\n\nReturn true if path has the sticky bit set, false otherwise.\n\n\n\n\n\n","category":"function"},{"location":"base/file/#Base.Filesystem.homedir","page":"文件系统","title":"Base.Filesystem.homedir","text":"homedir() -> String\n\nReturn the current user's home directory.\n\nnote: Note\nhomedir determines the home directory via libuv's uv_os_homedir. For details (for example on how to specify the home directory via environment variables), see the uv_os_homedir documentation.\n\n\n\n\n\n","category":"function"},{"location":"base/file/#Base.Filesystem.dirname","page":"文件系统","title":"Base.Filesystem.dirname","text":"dirname(path::AbstractString) -> AbstractString\n\nGet the directory part of a path. Trailing characters ('/' or '\\') in the path are counted as part of the path.\n\nExamples\n\njulia> dirname(\"/home/myuser\")\n\"/home\"\n\njulia> dirname(\"/home/myuser/\")\n\"/home/myuser\"\n\nSee also basename.\n\n\n\n\n\n","category":"function"},{"location":"base/file/#Base.Filesystem.basename","page":"文件系统","title":"Base.Filesystem.basename","text":"basename(path::AbstractString) -> AbstractString\n\nGet the file name part of a path.\n\nnote: Note\nThis function differs slightly from the Unix basename program, where trailing slashes are ignored, i.e. $ basename /foo/bar/ returns bar, whereas basename in Julia returns an empty string \"\".\n\nExamples\n\njulia> basename(\"/home/myuser/example.jl\")\n\"example.jl\"\n\njulia> basename(\"/home/myuser/\")\n\"\"\n\nSee also dirname.\n\n\n\n\n\n","category":"function"},{"location":"base/file/#Base.Filesystem.isabspath","page":"文件系统","title":"Base.Filesystem.isabspath","text":"isabspath(path::AbstractString) -> Bool\n\nDetermine whether a path is absolute (begins at the root directory).\n\nExamples\n\njulia> isabspath(\"/home\")\ntrue\n\njulia> isabspath(\"home\")\nfalse\n\n\n\n\n\n","category":"function"},{"location":"base/file/#Base.Filesystem.isdirpath","page":"文件系统","title":"Base.Filesystem.isdirpath","text":"isdirpath(path::AbstractString) -> Bool\n\nDetermine whether a path refers to a directory (for example, ends with a path separator).\n\nExamples\n\njulia> isdirpath(\"/home\")\nfalse\n\njulia> isdirpath(\"/home/\")\ntrue\n\n\n\n\n\n","category":"function"},{"location":"base/file/#Base.Filesystem.joinpath","page":"文件系统","title":"Base.Filesystem.joinpath","text":"joinpath(parts::AbstractString...) -> String\njoinpath(parts::Vector{AbstractString}) -> String\njoinpath(parts::Tuple{AbstractString}) -> String\n\nJoin path components into a full path. If some argument is an absolute path or (on Windows) has a drive specification that doesn't match the drive computed for the join of the preceding paths, then prior components are dropped.\n\nNote on Windows since there is a current directory for each drive, joinpath(\"c:\", \"foo\") represents a path relative to the current directory on drive \"c:\" so this is equal to \"c:foo\", not \"c:\\foo\". Furthermore, joinpath treats this as a non-absolute path and ignores the drive letter casing, hence joinpath(\"C:\\A\",\"c:b\") = \"C:\\A\\b\".\n\nExamples\n\njulia> joinpath(\"/home/myuser\", \"example.jl\")\n\"/home/myuser/example.jl\"\n\njulia> joinpath([\"/home/myuser\", \"example.jl\"])\n\"/home/myuser/example.jl\"\n\n\n\n\n\n","category":"function"},{"location":"base/file/#Base.Filesystem.abspath","page":"文件系统","title":"Base.Filesystem.abspath","text":"abspath(path::AbstractString) -> String\n\nConvert a path to an absolute path by adding the current directory if necessary. Also normalizes the path as in normpath.\n\n\n\n\n\nabspath(path::AbstractString, paths::AbstractString...) -> String\n\nConvert a set of paths to an absolute path by joining them together and adding the current directory if necessary. Equivalent to abspath(joinpath(path, paths...)).\n\n\n\n\n\n","category":"function"},{"location":"base/file/#Base.Filesystem.normpath","page":"文件系统","title":"Base.Filesystem.normpath","text":"normpath(path::AbstractString) -> String\n\nNormalize a path, removing \".\" and \"..\" entries and changing \"/\" to the canonical path separator for the system.\n\nExamples\n\njulia> normpath(\"/home/myuser/../example.jl\")\n\"/home/example.jl\"\n\njulia> normpath(\"Documents/Julia\") == joinpath(\"Documents\", \"Julia\")\ntrue\n\n\n\n\n\nnormpath(path::AbstractString, paths::AbstractString...) -> String\n\nConvert a set of paths to a normalized path by joining them together and removing \".\" and \"..\" entries. Equivalent to normpath(joinpath(path, paths...)).\n\n\n\n\n\n","category":"function"},{"location":"base/file/#Base.Filesystem.realpath","page":"文件系统","title":"Base.Filesystem.realpath","text":"realpath(path::AbstractString) -> String\n\nCanonicalize a path by expanding symbolic links and removing \".\" and \"..\" entries. On case-insensitive case-preserving filesystems (typically Mac and Windows), the filesystem's stored case for the path is returned.\n\n(This function throws an exception if path does not exist in the filesystem.)\n\n\n\n\n\n","category":"function"},{"location":"base/file/#Base.Filesystem.relpath","page":"文件系统","title":"Base.Filesystem.relpath","text":"relpath(path::AbstractString, startpath::AbstractString = \".\") -> AbstractString\n\nReturn a relative filepath to path either from the current directory or from an optional start directory. This is a path computation: the filesystem is not accessed to confirm the existence or nature of path or startpath.\n\nOn Windows, case sensitivity is applied to every part of the path except drive letters. If path and startpath refer to different drives, the absolute path of path is returned.\n\n\n\n\n\n","category":"function"},{"location":"base/file/#Base.Filesystem.expanduser","page":"文件系统","title":"Base.Filesystem.expanduser","text":"expanduser(path::AbstractString) -> AbstractString\n\nOn Unix systems, replace a tilde character at the start of a path with the current user's home directory.\n\n\n\n\n\n","category":"function"},{"location":"base/file/#Base.Filesystem.splitdir","page":"文件系统","title":"Base.Filesystem.splitdir","text":"splitdir(path::AbstractString) -> (AbstractString, AbstractString)\n\nSplit a path into a tuple of the directory name and file name.\n\nExamples\n\njulia> splitdir(\"/home/myuser\")\n(\"/home\", \"myuser\")\n\n\n\n\n\n","category":"function"},{"location":"base/file/#Base.Filesystem.splitdrive","page":"文件系统","title":"Base.Filesystem.splitdrive","text":"splitdrive(path::AbstractString) -> (AbstractString, AbstractString)\n\nOn Windows, split a path into the drive letter part and the path part. On Unix systems, the first component is always the empty string.\n\n\n\n\n\n","category":"function"},{"location":"base/file/#Base.Filesystem.splitext","page":"文件系统","title":"Base.Filesystem.splitext","text":"splitext(path::AbstractString) -> (AbstractString, AbstractString)\n\nIf the last component of a path contains one or more dots, split the path into everything before the last dot and everything including and after the dot. Otherwise, return a tuple of the argument unmodified and the empty string. \"splitext\" is short for \"split extension\".\n\nExamples\n\njulia> splitext(\"/home/myuser/example.jl\")\n(\"/home/myuser/example\", \".jl\")\n\njulia> splitext(\"/home/myuser/example.tar.gz\")\n(\"/home/myuser/example.tar\", \".gz\")\n\njulia> splitext(\"/home/my.user/example\")\n(\"/home/my.user/example\", \"\")\n\n\n\n\n\n","category":"function"},{"location":"base/file/#Base.Filesystem.splitpath","page":"文件系统","title":"Base.Filesystem.splitpath","text":"splitpath(path::AbstractString) -> Vector{String}\n\nSplit a file path into all its path components. This is the opposite of joinpath. Returns an array of substrings, one for each directory or file in the path, including the root directory if present.\n\ncompat: Julia 1.1\nThis function requires at least Julia 1.1.\n\nExamples\n\njulia> splitpath(\"/home/myuser/example.jl\")\n4-element Vector{String}:\n \"/\"\n \"home\"\n \"myuser\"\n \"example.jl\"\n\n\n\n\n\n","category":"function"},{"location":"manual/functions/#man-functions","page":"函数","title":"函数","text":"","category":"section"},{"location":"manual/functions/","page":"函数","title":"函数","text":"在 Julia 里,函数是将参数值组成的元组映射到返回值的一个对象。Julia 的函数不是纯粹的数学函数,因为这些函数可以改变程序的全局状态并且可能受其影响。在Julia中定义函数的基本语法是:","category":"page"},{"location":"manual/functions/","page":"函数","title":"函数","text":"julia> function f(x,y)\n x + y\n end\nf (generic function with 1 method)","category":"page"},{"location":"manual/functions/","page":"函数","title":"函数","text":"这个函数接收两个参数 x 和 y 并返回最后一个表达式的值,这里是 x + y。","category":"page"},{"location":"manual/functions/","page":"函数","title":"函数","text":"在 Julia 中定义函数还有第二种更简洁的语法。上述的传统函数声明语法等效于以下紧凑性的“赋值形式”:","category":"page"},{"location":"manual/functions/","page":"函数","title":"函数","text":"julia> f(x,y) = x + y\nf (generic function with 1 method)","category":"page"},{"location":"manual/functions/","page":"函数","title":"函数","text":"尽管函数可以是复合表达式 (见 复合表达式),但在赋值形式下,函数体必须是一个一行的表达式。简短的函数定义在 Julia 中是很常见的。非常惯用的短函数语法大大减少了打字和视觉方面的干扰。","category":"page"},{"location":"manual/functions/","page":"函数","title":"函数","text":"使用传统的括号语法调用函数:","category":"page"},{"location":"manual/functions/","page":"函数","title":"函数","text":"julia> f(2,3)\n5","category":"page"},{"location":"manual/functions/","page":"函数","title":"函数","text":"没有括号时,表达式 f 指的是函数对象,可以像任何值一样被传递:","category":"page"},{"location":"manual/functions/","page":"函数","title":"函数","text":"julia> g = f;\n\njulia> g(2,3)\n5","category":"page"},{"location":"manual/functions/","page":"函数","title":"函数","text":"和变量名一样,Unicode 字符也可以用作函数名:","category":"page"},{"location":"manual/functions/","page":"函数","title":"函数","text":"julia> ∑(x,y) = x + y\n∑ (generic function with 1 method)\n\njulia> ∑(2, 3)\n5","category":"page"},{"location":"manual/functions/#参数传递行为","page":"函数","title":"参数传递行为","text":"","category":"section"},{"location":"manual/functions/","page":"函数","title":"函数","text":"Julia 函数参数遵循有时称为 “pass-by-sharing” 的约定,这意味着变量在被传递给函数时其值并不会被复制。函数参数本身充当新的变量绑定(指向变量值的新地址),它们所指向的值与所传递变量的值完全相同。调用者可以看到对函数内可变值(如数组)的修改。这与 Scheme,大多数 Lisps,Python,Ruby 和 Perl 以及其他动态语言中的行为相同。","category":"page"},{"location":"manual/functions/#参数类型声明","page":"函数","title":"参数类型声明","text":"","category":"section"},{"location":"manual/functions/","page":"函数","title":"函数","text":"您可以通过将 ::TypeName 附加到参数名称来声明函数参数的类型,就像 Julia 中的 类型声明 一样。 例如,以下函数递归计算 斐波那契数列:","category":"page"},{"location":"manual/functions/","page":"函数","title":"函数","text":"fib(n::Integer) = n ≤ 2 ? one(n) : fib(n-1) + fib(n-2)","category":"page"},{"location":"manual/functions/","page":"函数","title":"函数","text":"并且 ::Integer 规范意味着它只有在 n 是 抽象 Integer 类型的子类型时才可调用。","category":"page"},{"location":"manual/functions/","page":"函数","title":"函数","text":"参数类型声明通常对性能没有影响:无论声明什么参数类型(如果有),Julia 都会为实际参数类型编译函数的特例版本。 例如,调用 fib(1) 将触发专门为 Int 参数优化的特例化的fib 的编译,它会在 fib(7) 或 fib(15) 调用时重新使用。 (参数类型声明不触发额外的编译器特化的情况很少;请参阅:注意 Julia 何时不触发特例化。)在 Julia 中声明参数类型的最常见原因是:","category":"page"},{"location":"manual/functions/","page":"函数","title":"函数","text":"派发: 如 方法 中所述,对于不同的参数类型,你可以有不同版本(“方法”)的函数,在这种情况下,参数类型用于确定调用哪个版本的函数。例如,你可以使用 Binet 公式 实现一个完全不同的算法 fib(x::Number) = ...,该算法扩展为了非整数值,适用于任何 Number 类型。\n正确性: 如果函数只为某些参数类型返回正确的结果,则类型声明会很有用。例如,如果我们省略参数类型并写成 fib(n) = n ≤ 2 ? one(n) : fib(n-1) + fib(n-2),然后fib(1.5)会默默地给我们无意义的答案1.0。\n清晰性: 类型声明可以作为一种关于预期参数的文档形式。","category":"page"},{"location":"manual/functions/","page":"函数","title":"函数","text":"但是,过分限制参数类型是常见的错误,这会不必要地限制函数的适用性,并防止它在未预料到的情况下被重用。例如,上面的 fib(n::Integer) 函数同样适用于 Int 参数(机器整数)和 BigInt 任意精度整数(参见 BigFloats 和 BigInts),这样十分有效,因为斐波那契数以指数方式快速增长,并且会迅速溢出任何固定精度类型,如 Int(参见 溢出行为)。但是,如果我们将函数声明为 fib(n::Int),那么 BigInt 的应用就会被阻止。通常,应该对参数使用最通用的适用抽象类型,并且如有不确定,就省略参数类型。如果有必要,你可以随时添加参数类型规范,并且不会因为省略它们而牺牲性能或功能。","category":"page"},{"location":"manual/functions/#return-关键字","page":"函数","title":"return 关键字","text":"","category":"section"},{"location":"manual/functions/","page":"函数","title":"函数","text":"函数返回的值是最后计算的表达式的值,默认情况下,它是函数定义主体中的最后一个表达式。在上一小节的示例函数 f 中,返回值是表达式的 x + y 值。与在 C 语言和大多数其他命令式或函数式语言中一样,return 关键字会让函数立即返回,从而提供返回值的表达式:","category":"page"},{"location":"manual/functions/","page":"函数","title":"函数","text":"function g(x,y)\n return x * y\n x + y\nend","category":"page"},{"location":"manual/functions/","page":"函数","title":"函数","text":"由于函数定义可以输入到交互式会话中,因此可以很容易的比较这些定义:","category":"page"},{"location":"manual/functions/","page":"函数","title":"函数","text":"julia> f(x,y) = x + y\nf (generic function with 1 method)\n\njulia> function g(x,y)\n return x * y\n x + y\n end\ng (generic function with 1 method)\n\njulia> f(2,3)\n5\n\njulia> g(2,3)\n6","category":"page"},{"location":"manual/functions/","page":"函数","title":"函数","text":"当然,在一个单纯的线性执行的函数体内,例如 g,使用 return 是没有意义的,因为表达式 x + y 永远不会被执行到,我们可以简单地把 x * y 写为最后一个表达式从而省略掉 return。 然而在使用其他控制流程的函数体内,return 却是有用的。 例如,在计算两条边长分别为 x 和 y 的三角形的斜边长度时可以避免溢出:","category":"page"},{"location":"manual/functions/","page":"函数","title":"函数","text":"julia> function hypot(x,y)\n x = abs(x)\n y = abs(y)\n if x > y\n r = y/x\n return x*sqrt(1+r*r)\n end\n if y == 0\n return zero(x)\n end\n r = x/y\n return y*sqrt(1+r*r)\n end\nhypot (generic function with 1 method)\n\njulia> hypot(3, 4)\n5.0","category":"page"},{"location":"manual/functions/","page":"函数","title":"函数","text":"这个函数有三个可能的返回处,返回三个不同表达式的值,具体取决于 x 和 y 的值。 最后一行的 return 可以省略,因为它是最后一个表达式。","category":"page"},{"location":"manual/functions/#返回类型","page":"函数","title":"返回类型","text":"","category":"section"},{"location":"manual/functions/","page":"函数","title":"函数","text":"也可以使用 :: 运算符在函数声明中指定返回类型。 这可以将返回值转换为指定的类型。","category":"page"},{"location":"manual/functions/","page":"函数","title":"函数","text":"julia> function g(x, y)::Int8\n return x * y\n end;\n\njulia> typeof(g(1, 2))\nInt8","category":"page"},{"location":"manual/functions/","page":"函数","title":"函数","text":"这个函数将忽略 x 和 y 的类型,返回 Int8 类型的值。有关返回类型的更多信息,请参见类型声明。","category":"page"},{"location":"manual/functions/","page":"函数","title":"函数","text":"返回类型声明在 Julia 中很少使用:通常,你应该编写“类型稳定”的函数,Julia 的编译器可以在其中自动推断返回类型。更多信息请参阅 性能提示 一章。","category":"page"},{"location":"manual/functions/#返回-nothing","page":"函数","title":"返回 nothing","text":"","category":"section"},{"location":"manual/functions/","page":"函数","title":"函数","text":"对于不需要任何返回值的函数(只用来产生副作用的函数), Julia 中的写法为返回值nothing:","category":"page"},{"location":"manual/functions/","page":"函数","title":"函数","text":"function printx(x)\n println(\"x = $x\")\n return nothing\nend","category":"page"},{"location":"manual/functions/","page":"函数","title":"函数","text":"这在某种意义上是一个“惯例”,在 Julia 中 nothing 不是一个关键字,而是 Nothing 类型的一个单例(singleton)。 也许你已经注意到 printx 函数有点不自然,因为 println 实际上已经会返回 nothing,所以 return 语句是多余的。","category":"page"},{"location":"manual/functions/","page":"函数","title":"函数","text":"有两种比 return nothing 更短的写法:一种是直接写 return 这会隐式的返回 nothing。 另一种是在函数的会后一行写上 nothing,因为函数会隐式的返回最后一个表达式的值。 三种写法使用哪一种取决于代码风格的偏好。","category":"page"},{"location":"manual/functions/#操作符也是函数","page":"函数","title":"操作符也是函数","text":"","category":"section"},{"location":"manual/functions/","page":"函数","title":"函数","text":"在 Julia中,大多数操作符只不过是支持特殊语法的函数( && 和|| 等具有特殊评估语义的操作符除外,他们不能是函数,因为短路求值要求在计算整个表达式的值之前不计算每个操作数)。因此,您也可以使用带括号的参数列表来使用它们,就和任何其他函数一样:","category":"page"},{"location":"manual/functions/","page":"函数","title":"函数","text":"julia> 1 + 2 + 3\n6\n\njulia> +(1,2,3)\n6","category":"page"},{"location":"manual/functions/","page":"函数","title":"函数","text":"中缀表达式和函数形式完全等价。—— 事实上,前一种形式会被编译器转换为函数调用。这也意味着你可以对操作符,例如 + 和 * ,进行赋值和传参,就像其它函数传参一样。","category":"page"},{"location":"manual/functions/","page":"函数","title":"函数","text":"julia> f = +;\n\njulia> f(1,2,3)\n6","category":"page"},{"location":"manual/functions/","page":"函数","title":"函数","text":"然而,函数以f命名时不再支持中缀表达式。","category":"page"},{"location":"manual/functions/#具有特殊名称的操作符","page":"函数","title":"具有特殊名称的操作符","text":"","category":"section"},{"location":"manual/functions/","page":"函数","title":"函数","text":"有一些特殊的表达式对应的函数调用没有显示的函数名称,它们是:","category":"page"},{"location":"manual/functions/","page":"函数","title":"函数","text":"表达式 函数调用\n[A B C ...] hcat\n[A; B; C; ...] vcat\n[A B; C D; ...] hvcat\nA' adjoint\nA[i] getindex\nA[i] = x setindex!\nA.n getproperty\nA.n = x setproperty!","category":"page"},{"location":"manual/functions/#man-anonymous-functions","page":"函数","title":"匿名函数","text":"","category":"section"},{"location":"manual/functions/","page":"函数","title":"函数","text":"函数在Julia里是一等公民:可以指定给变量,并使用标准函数调用语法通过被指定的变量调用。函数可以用作参数,也可以当作返回值。函数也可以不带函数名称地匿名创建,使用语法如下:","category":"page"},{"location":"manual/functions/","page":"函数","title":"函数","text":"julia> x -> x^2 + 2x - 1\n#1 (generic function with 1 method)\n\njulia> function (x)\n x^2 + 2x - 1\n end\n#3 (generic function with 1 method)","category":"page"},{"location":"manual/functions/","page":"函数","title":"函数","text":"这样就创建了一个接受一个参数 x 并返回当前值的多项式 x^2+2x-1 的函数。注意结果是个泛型函数,但是带了编译器生成的连续编号的名字。","category":"page"},{"location":"manual/functions/","page":"函数","title":"函数","text":"匿名函数最主要的用法是传递给接收函数作为参数的函数。一个经典的例子是 map ,为数组的每个元素应用一次函数,然后返回一个包含结果值的新数组:","category":"page"},{"location":"manual/functions/","page":"函数","title":"函数","text":"julia> map(round, [1.2, 3.5, 1.7])\n3-element Vector{Float64}:\n 1.0\n 4.0\n 2.0","category":"page"},{"location":"manual/functions/","page":"函数","title":"函数","text":"如果做为第一个参数传递给 map 的转换函数已经存在,那直接使用函数名称是没问题的。但是通常要使用的函数还没有定义好,这样使用匿名函数就更加方便:","category":"page"},{"location":"manual/functions/","page":"函数","title":"函数","text":"julia> map(x -> x^2 + 2x - 1, [1, 3, -1])\n3-element Vector{Int64}:\n 2\n 14\n -2","category":"page"},{"location":"manual/functions/","page":"函数","title":"函数","text":"接受多个参数的匿名函数写法可以使用语法 (x,y,z)->2x+y-z,而无参匿名函数写作 ()->3 。无参函数的这种写法看起来可能有些奇怪,不过它对于延迟计算很有必要。这种用法会把代码块包进一个无参函数中,后续把它当做 f 调用。","category":"page"},{"location":"manual/functions/","page":"函数","title":"函数","text":"例如,考虑对 get 的调用:","category":"page"},{"location":"manual/functions/","page":"函数","title":"函数","text":"get(dict, key) do\n # default value calculated here\n time()\nend","category":"page"},{"location":"manual/functions/","page":"函数","title":"函数","text":"上面的代码等效于使用包含代码的匿名函数调用get。 被包围在do和end之间,如下所示","category":"page"},{"location":"manual/functions/","page":"函数","title":"函数","text":"get(()->time(), dict, key)","category":"page"},{"location":"manual/functions/","page":"函数","title":"函数","text":"这里对 time 的调用,被包裹了它的一个无参数的匿名函数延迟了。该匿名函数只当 dict 缺少被请求的键时,才被调用。","category":"page"},{"location":"manual/functions/#元组","page":"函数","title":"元组","text":"","category":"section"},{"location":"manual/functions/","page":"函数","title":"函数","text":"Julia 有一个和函数参数与返回值密切相关的内置数据结构叫做元组(tuple)。 一个元组是一个固定长度的容器,可以容纳任何值,但不可以被修改(是immutable的)。 元组通过圆括号和逗号来构造,其内容可以通过索引来访问:","category":"page"},{"location":"manual/functions/","page":"函数","title":"函数","text":"julia> (1, 1+1)\n(1, 2)\n\njulia> (1,)\n(1,)\n\njulia> x = (0.0, \"hello\", 6*7)\n(0.0, \"hello\", 42)\n\njulia> x[2]\n\"hello\"","category":"page"},{"location":"manual/functions/","page":"函数","title":"函数","text":"注意,长度为1的元组必须使用逗号 (1,),而 (1) 只是一个带括号的值。() 表示空元组(长度为0)。","category":"page"},{"location":"manual/functions/#具名元组","page":"函数","title":"具名元组","text":"","category":"section"},{"location":"manual/functions/","page":"函数","title":"函数","text":"元组的元素可以有名字,这时候就有了具名元组:","category":"page"},{"location":"manual/functions/","page":"函数","title":"函数","text":"julia> x = (a=2, b=1+2)\n(a = 2, b = 3)\n\njulia> x[1]\n2\n\njulia> x.a\n2","category":"page"},{"location":"manual/functions/","page":"函数","title":"函数","text":"具名元组和元组十分类似,区别在于除了一般的下标语法(x[1]),还可以使用点运算符语法(x.a)通过元素的名字来访问它的元素。","category":"page"},{"location":"manual/functions/#destructuring-assignment","page":"函数","title":"解构赋值和多返回值","text":"","category":"section"},{"location":"manual/functions/","page":"函数","title":"函数","text":"逗号分隔的变量列表(可选地用括号括起来)可以出现在赋值的左侧:右侧的值通过迭代并依次分配给每个变量来解构:","category":"page"},{"location":"manual/functions/","page":"函数","title":"函数","text":"julia> (a,b,c) = 1:3\n1:3\n\njulia> b\n2","category":"page"},{"location":"manual/functions/","page":"函数","title":"函数","text":"右边的值应该是一个至少与左边的变量数量一样长的迭代器(参见迭代接口)(迭代器的任何多余元素会被忽略)。","category":"page"},{"location":"manual/functions/","page":"函数","title":"函数","text":"可用于通过返回元组或其他可迭代值从函数返回多个值。例如,以下函数返回两个值:","category":"page"},{"location":"manual/functions/","page":"函数","title":"函数","text":"julia> function foo(a,b)\n a+b, a*b\n end\nfoo (generic function with 1 method)","category":"page"},{"location":"manual/functions/","page":"函数","title":"函数","text":"如果你在交互式会话中调用它且不把返回值赋值给任何变量,你会看到返回的元组:","category":"page"},{"location":"manual/functions/","page":"函数","title":"函数","text":"julia> foo(2,3)\n(5, 6)","category":"page"},{"location":"manual/functions/","page":"函数","title":"函数","text":"解构赋值将每个值提取到一个变量中:","category":"page"},{"location":"manual/functions/","page":"函数","title":"函数","text":"julia> x, y = foo(2,3)\n(5, 6)\n\njulia> x\n5\n\njulia> y\n6","category":"page"},{"location":"manual/functions/","page":"函数","title":"函数","text":"另一个常见用途是交换变量:","category":"page"},{"location":"manual/functions/","page":"函数","title":"函数","text":"julia> y, x = x, y\n(5, 6)\n\njulia> x\n6\n\njulia> y\n5","category":"page"},{"location":"manual/functions/","page":"函数","title":"函数","text":"如果只需要迭代器元素的一个子集,一个常见的惯例是将忽略的元素分配给一个只包含下划线 _ 的变量(这是一个无效的变量名,请参阅 [合法的变量名](@ref man -allowed-variable-names)):","category":"page"},{"location":"manual/functions/","page":"函数","title":"函数","text":"julia> _, _, _, d = 1:10\n1:10\n\njulia> d\n4","category":"page"},{"location":"manual/functions/","page":"函数","title":"函数","text":"其他有效的左侧表达式可以用作赋值列表的元素,它们将调用 setindex! 或 setproperty!,或者递归地解构迭代器的各个元素:","category":"page"},{"location":"manual/functions/","page":"函数","title":"函数","text":"julia> X = zeros(3);\n\njulia> X[1], (a,b) = (1, (2, 3))\n(1, (2, 3))\n\njulia> X\n3-element Vector{Float64}:\n 1.0\n 0.0\n 0.0\n\njulia> a\n2\n\njulia> b\n3","category":"page"},{"location":"manual/functions/","page":"函数","title":"函数","text":"compat: Julia 1.6\n带 ... 的赋值需要 Julia 1.6","category":"page"},{"location":"manual/functions/","page":"函数","title":"函数","text":"如果赋值列表中的最后一个符号后缀为 ...(称为 slurping),那么它将被分配给右侧迭代器剩余元素的集合或其惰性迭代器:","category":"page"},{"location":"manual/functions/","page":"函数","title":"函数","text":"julia> a, b... = \"hello\"\n\"hello\"\n\njulia> a\n'h': ASCII/Unicode U+0068 (category Ll: Letter, lowercase)\n\njulia> b\n\"ello\"\n\njulia> a, b... = Iterators.map(abs2, 1:4)\nBase.Generator{UnitRange{Int64}, typeof(abs2)}(abs2, 1:4)\n\njulia> a\n1\n\njulia> b\nBase.Iterators.Rest{Base.Generator{UnitRange{Int64}, typeof(abs2)}, Int64}(Base.Generator{UnitRange{Int64}, typeof(abs2)}(abs2, 1:4), 1)","category":"page"},{"location":"manual/functions/","page":"函数","title":"函数","text":"有关特定迭代器的精确处理和自定义的详细信息,请参阅 Base.rest。","category":"page"},{"location":"manual/functions/#参数解构","page":"函数","title":"参数解构","text":"","category":"section"},{"location":"manual/functions/","page":"函数","title":"函数","text":"析构特性也可以被用在函数参数中。 如果一个函数的参数被写成了元组形式 (如 (x, y)) 而不是简单的符号,那么一个赋值运算 (x, y) = argument 将会被默认插入:","category":"page"},{"location":"manual/functions/","page":"函数","title":"函数","text":"julia> minmax(x, y) = (y < x) ? (y, x) : (x, y)\n\njulia> gap((min, max)) = max - min\n\njulia> gap(minmax(10, 2))\n8","category":"page"},{"location":"manual/functions/","page":"函数","title":"函数","text":"注意在定义函数 gap 时额外的括号。 没有它们,gap 函数将会是一个双参数函数,这个例子也会无法正常运行。","category":"page"},{"location":"manual/functions/","page":"函数","title":"函数","text":"对于匿名函数,解构单个元组需要一个额外的逗号:","category":"page"},{"location":"manual/functions/","page":"函数","title":"函数","text":"julia> map(((x,y),) -> x + y, [(1,2), (3,4)])\n2-element Array{Int64,1}:\n 3\n 7","category":"page"},{"location":"manual/functions/#变参函数","page":"函数","title":"变参函数","text":"","category":"section"},{"location":"manual/functions/","page":"函数","title":"函数","text":"定义有任意个参数的函数会带来很多便利。这类函数通常被称为“变参”函数,即“参数数量可变”的简称。你可以通过在最后一个参数后增加省略号来定义一个变参函数:","category":"page"},{"location":"manual/functions/","page":"函数","title":"函数","text":"julia> bar(a,b,x...) = (a,b,x)\nbar (generic function with 1 method)","category":"page"},{"location":"manual/functions/","page":"函数","title":"函数","text":"变量 a 和 b 和以前一样被绑定给前两个参数,后面的参数整个做为迭代集合被绑定到变量 x 上 :","category":"page"},{"location":"manual/functions/","page":"函数","title":"函数","text":"julia> bar(1,2)\n(1, 2, ())\n\njulia> bar(1,2,3)\n(1, 2, (3,))\n\njulia> bar(1, 2, 3, 4)\n(1, 2, (3, 4))\n\njulia> bar(1,2,3,4,5,6)\n(1, 2, (3, 4, 5, 6))","category":"page"},{"location":"manual/functions/","page":"函数","title":"函数","text":"在所有这些情况下,x 被绑定到传递给 bar 的尾随值的元组。","category":"page"},{"location":"manual/functions/","page":"函数","title":"函数","text":"也可以限制可以传递给函数的参数的数量,这部分内容稍后在 参数化约束的可变参数方法 中讨论。","category":"page"},{"location":"manual/functions/","page":"函数","title":"函数","text":"另一方面,将可迭代集中包含的值拆解为单独的参数进行函数调用通常很方便。 要实现这一点,需要在函数调用中额外使用 ... 而不仅仅只是变量:","category":"page"},{"location":"manual/functions/","page":"函数","title":"函数","text":"julia> x = (3, 4)\n(3, 4)\n\njulia> bar(1,2,x...)\n(1, 2, (3, 4))","category":"page"},{"location":"manual/functions/","page":"函数","title":"函数","text":"在这个情况下一组值会被精确切片成一个可变参数调用,这里参数的数量是可变的。但是并不需要成为这种情况:","category":"page"},{"location":"manual/functions/","page":"函数","title":"函数","text":"julia> x = (2, 3, 4)\n(2, 3, 4)\n\njulia> bar(1,x...)\n(1, 2, (3, 4))\n\njulia> x = (1, 2, 3, 4)\n(1, 2, 3, 4)\n\njulia> bar(x...)\n(1, 2, (3, 4))","category":"page"},{"location":"manual/functions/","page":"函数","title":"函数","text":"进一步,拆解给函数调用中的可迭代对象不需要是个元组:","category":"page"},{"location":"manual/functions/","page":"函数","title":"函数","text":"julia> x = [3,4]\n2-element Vector{Int64}:\n 3\n 4\n\njulia> bar(1,2,x...)\n(1, 2, (3, 4))\n\njulia> x = [1,2,3,4]\n4-element Vector{Int64}:\n 1\n 2\n 3\n 4\n\njulia> bar(x...)\n(1, 2, (3, 4))","category":"page"},{"location":"manual/functions/","page":"函数","title":"函数","text":"此外,参数被放入的函数不一定是可变参数函数(尽管经常是):","category":"page"},{"location":"manual/functions/","page":"函数","title":"函数","text":"julia> baz(a,b) = a + b;\n\njulia> args = [1,2]\n2-element Vector{Int64}:\n 1\n 2\n\njulia> baz(args...)\n3\n\njulia> args = [1,2,3]\n3-element Vector{Int64}:\n 1\n 2\n 3\n\njulia> baz(args...)\nERROR: MethodError: no method matching baz(::Int64, ::Int64, ::Int64)\nClosest candidates are:\n baz(::Any, ::Any) at none:1","category":"page"},{"location":"manual/functions/","page":"函数","title":"函数","text":"正如你所见,如果要拆解的容器(比如元组或数组)元素数量不匹配就会报错,和直接给多个参数报错一样。","category":"page"},{"location":"manual/functions/#可选参数","page":"函数","title":"可选参数","text":"","category":"section"},{"location":"manual/functions/","page":"函数","title":"函数","text":"在很多情况下,函数参数有合理的默认值,因此也许不需要显式地传递。例如,Dates 模块中的 Date(y, [m, d]) 函数对于给定的年(year)y、月(mouth)m、日(data)d 构造了 Date 类型。但是,m 和 d 参数都是可选的,默认值都是 1。这行为可以简述为:","category":"page"},{"location":"manual/functions/","page":"函数","title":"函数","text":"function Date(y::Int64, m::Int64=1, d::Int64=1)\n err = validargs(Date, y, m, d)\n err === nothing || throw(err)\n return Date(UTD(totaldays(y, m, d)))\nend","category":"page"},{"location":"manual/functions/","page":"函数","title":"函数","text":"注意,这个定义调用了 Date 函数的另一个方法,该方法带有一个 UTInstant{Day} 类型的参数。","category":"page"},{"location":"manual/functions/","page":"函数","title":"函数","text":"通过此定义,函数调用时可以带有一个、两个或三个参数,并且在只有一个或两个参数被指定时后,自动传递 1 为未指定参数值:","category":"page"},{"location":"manual/functions/","page":"函数","title":"函数","text":"julia> using Dates\n\njulia> Date(2000, 12, 12)\n2000-12-12\n\njulia> Date(2000, 12)\n2000-12-01\n\njulia> Date(2000)\n2000-01-01","category":"page"},{"location":"manual/functions/","page":"函数","title":"函数","text":"可选参数实际上只是一种方便的语法,用于编写多种具有不同数量参数的方法定义(请参阅 可选参数和关键字的参数的注意事项)。这可通过调用 methods 函数来检查我们的 Date 函数示例。","category":"page"},{"location":"manual/functions/#关键字参数","page":"函数","title":"关键字参数","text":"","category":"section"},{"location":"manual/functions/","page":"函数","title":"函数","text":"某些函数需要大量参数,或者具有大量行为。记住如何调用这样的函数可能很困难。关键字参数允许通过名称而不是仅通过位置来识别参数,使得这些复杂接口易于使用和扩展。","category":"page"},{"location":"manual/functions/","page":"函数","title":"函数","text":"例如,考虑绘制一条线的函数 plot。这个函数可能有很多选项,用来控制线条的样式、宽度、颜色等。如果它接受关键字参数,一个可行的调用可能看起来像 plot(x, y, width=2),这里我们仅指定线的宽度。请注意,这样做有两个目的。调用更可读,因为我们能以其意义标记参数。也使得大量参数的任意子集都能以任意次序传递。","category":"page"},{"location":"manual/functions/","page":"函数","title":"函数","text":"具有关键字参数的函数在签名中使用分号定义:","category":"page"},{"location":"manual/functions/","page":"函数","title":"函数","text":"function plot(x, y; style=\"solid\", width=1, color=\"black\")\n ###\nend","category":"page"},{"location":"manual/functions/","page":"函数","title":"函数","text":"在函数调用时,分号是可选的:可以调用 plot(x, y, width=2) 或 plot(x, y; width=2),但前者的风格更为常见。显式的分号只有在传递可变参数或下文中描述的需计算的关键字时是必要的。","category":"page"},{"location":"manual/functions/","page":"函数","title":"函数","text":"关键字参数的默认值只在必需时求值(当相应的关键字参数没有被传入),并且按从左到右的顺序求值,因为默认值的表达式可能会参照先前的关键字参数。","category":"page"},{"location":"manual/functions/","page":"函数","title":"函数","text":"关键字参数的类型可以通过如下的方式显式指定:","category":"page"},{"location":"manual/functions/","page":"函数","title":"函数","text":"function f(;x::Int=1)\n ###\nend","category":"page"},{"location":"manual/functions/","page":"函数","title":"函数","text":"关键字参数也可以在变参函数中使用:","category":"page"},{"location":"manual/functions/","page":"函数","title":"函数","text":"function plot(x...; style=\"solid\")\n ###\nend","category":"page"},{"location":"manual/functions/","page":"函数","title":"函数","text":"附加的关键字参数可用 ... 收集,正如在变参函数中:","category":"page"},{"location":"manual/functions/","page":"函数","title":"函数","text":"function f(x; y=0, kwargs...)\n ###\nend","category":"page"},{"location":"manual/functions/","page":"函数","title":"函数","text":"在 f 中,kwargs 将是一个在命名元组上的不可变键值迭代器。 具名元组(以及带有Symbol键的字典)可以在调用中使用分号作为关键字参数传递,例如 f(x, z=1; kwargs...)。","category":"page"},{"location":"manual/functions/","page":"函数","title":"函数","text":"如果一个关键字参数在方法定义中未指定默认值,那么它就是必需的:如果调用者没有为其赋值,那么将会抛出一个 UndefKeywordError 异常:","category":"page"},{"location":"manual/functions/","page":"函数","title":"函数","text":"function f(x; y)\n ###\nend\nf(3, y=5) # ok, y is assigned\nf(3) # throws UndefKeywordError(:y)","category":"page"},{"location":"manual/functions/","page":"函数","title":"函数","text":"在分号后也可传递 key => value 表达式。例如,plot(x, y; :width => 2) 等价于 plot(x, y, width=2)。当关键字名称需要在运行时被计算时,这就很实用了。","category":"page"},{"location":"manual/functions/","page":"函数","title":"函数","text":"当分号后出现裸标识符或点表达式时,标识符或字段名称隐含关键字参数名称。 例如plot(x, y; width) 等价于plot(x, y; width=width),plot(x, y; options.width) 等价于plot(x, y; width=options.width)。","category":"page"},{"location":"manual/functions/","page":"函数","title":"函数","text":"可选参数的性质使得可以多次指定同一参数的值。例如,在调用 plot(x, y; options..., width=2) 的过程中,options 结构也能包含一个 width 的值。在这种情况下,最右边的值优先级最高;在此例中,width 的值可以确定是 2。但是,显式地多次指定同一参数的值是不允许的,例如 plot(x, y, width=2, width=3),这会导致语法错误。","category":"page"},{"location":"manual/functions/#默认值作用域的计算","page":"函数","title":"默认值作用域的计算","text":"","category":"section"},{"location":"manual/functions/","page":"函数","title":"函数","text":"当计算可选和关键字参数的默认值表达式时,只有先前的参数才在作用域内。例如,给出以下定义:","category":"page"},{"location":"manual/functions/","page":"函数","title":"函数","text":"function f(x, a=b, b=1)\n ###\nend","category":"page"},{"location":"manual/functions/","page":"函数","title":"函数","text":"a=b 中的 b 指的是外部作用域内的 b,而不是后续参数中的 b。","category":"page"},{"location":"manual/functions/#Do-Block-Syntax-for-Function-Arguments","page":"函数","title":"函数参数中的 Do 结构","text":"","category":"section"},{"location":"manual/functions/","page":"函数","title":"函数","text":"把函数作为参数传递给其他函数是一种强大的技术,但它的语法并不总是很方便。当函数参数占据多行时,这样的调用便特别难以编写。例如,考虑在具有多种情况的函数上调用 map:","category":"page"},{"location":"manual/functions/","page":"函数","title":"函数","text":"map(x->begin\n if x < 0 && iseven(x)\n return 0\n elseif x == 0\n return 1\n else\n return x\n end\n end,\n [A, B, C])","category":"page"},{"location":"manual/functions/","page":"函数","title":"函数","text":"Julia 提供了一个保留字 do,用于更清楚地重写此代码:","category":"page"},{"location":"manual/functions/","page":"函数","title":"函数","text":"map([A, B, C]) do x\n if x < 0 && iseven(x)\n return 0\n elseif x == 0\n return 1\n else\n return x\n end\nend","category":"page"},{"location":"manual/functions/","page":"函数","title":"函数","text":"do x 语法创建一个带有参数 x 的匿名函数,并将其作为第一个参数传递给 map。 类似地,do a,b 将创建一个有两个参数的匿名函数。 请注意,do (a,b) 将创建一个单参数匿名函数,其参数是一个要解构的元组。 一个简单的 do 会声明接下来是一个形式为 () -> ... 的匿名函数。","category":"page"},{"location":"manual/functions/","page":"函数","title":"函数","text":"这些参数如何初始化取决于「外部」函数;在这里,map 将会依次将 x 设置为 A、B、C,再分别调用调用匿名函数,正如在 map(func, [A, B, C]) 语法中所发生的。","category":"page"},{"location":"manual/functions/","page":"函数","title":"函数","text":"这种语法使得更容易使用函数来有效地扩展语言,因为调用看起来就像普通代码块。有许多可能的用法与 map 完全不同,比如管理系统状态。例如,有一个版本的 open 可以通过运行代码来确保已经打开的文件最终会被关闭:","category":"page"},{"location":"manual/functions/","page":"函数","title":"函数","text":"open(\"outfile\", \"w\") do io\n write(io, data)\nend","category":"page"},{"location":"manual/functions/","page":"函数","title":"函数","text":"这是通过以下定义实现的:","category":"page"},{"location":"manual/functions/","page":"函数","title":"函数","text":"function open(f::Function, args...)\n io = open(args...)\n try\n f(io)\n finally\n close(io)\n end\nend","category":"page"},{"location":"manual/functions/","page":"函数","title":"函数","text":"在这里,open 首先打开要写入的文件,接着将结果输出流传递给你在 do ... end 代码快中定义的匿名函数。在你的函数退出后,open 将确保流被正确关闭,无论你的函数是正常退出还是抛出了一个异常(try/finally 结构会在 流程控制 中描述)。","category":"page"},{"location":"manual/functions/","page":"函数","title":"函数","text":"使用 do 代码块语法时,查阅文档或实现有助于了解用户函数的参数是如何初始化的。","category":"page"},{"location":"manual/functions/","page":"函数","title":"函数","text":"类似于其他的内部函数, do 代码块也可以“捕获”上一个作用域的变量。例如,上一个 open...do 的例子中变量 data 是从外部作用域捕获的。捕获变量可能会给性能优化带来挑战,详见 性能建议。","category":"page"},{"location":"manual/functions/#函数的复合与链式调用","page":"函数","title":"函数的复合与链式调用","text":"","category":"section"},{"location":"manual/functions/","page":"函数","title":"函数","text":"Julia中的多个函数可以用函数复合或管道连接(链式调用)组合起来。","category":"page"},{"location":"manual/functions/","page":"函数","title":"函数","text":"函数的复合指的是把多个函数绑定到一起,然后作用于最先调用那个函数的参数。 你可以使用函数复合运算符 (∘) 来组合函数,这样一来 (f ∘ g)(args...) 就等价于 f(g(args...)).","category":"page"},{"location":"manual/functions/","page":"函数","title":"函数","text":"你可以在REPL和合理配置的编辑器中用 \\circ 输入函数复合运算符。","category":"page"},{"location":"manual/functions/","page":"函数","title":"函数","text":"例如, sqrt 和 + 可以用下面这种方式组合:","category":"page"},{"location":"manual/functions/","page":"函数","title":"函数","text":"julia> (sqrt ∘ +)(3, 6)\n3.0","category":"page"},{"location":"manual/functions/","page":"函数","title":"函数","text":"这个语句先把数字相加,再对结果求平方根。","category":"page"},{"location":"manual/functions/","page":"函数","title":"函数","text":"下一个例子组合了三个函数并把新函数作用到一个字符串组成的数组上:","category":"page"},{"location":"manual/functions/","page":"函数","title":"函数","text":"julia> map(first ∘ reverse ∘ uppercase, split(\"you can compose functions like this\"))\n6-element Vector{Char}:\n 'U': ASCII/Unicode U+0055 (category Lu: Letter, uppercase)\n 'N': ASCII/Unicode U+004E (category Lu: Letter, uppercase)\n 'E': ASCII/Unicode U+0045 (category Lu: Letter, uppercase)\n 'S': ASCII/Unicode U+0053 (category Lu: Letter, uppercase)\n 'E': ASCII/Unicode U+0045 (category Lu: Letter, uppercase)\n 'S': ASCII/Unicode U+0053 (category Lu: Letter, uppercase)","category":"page"},{"location":"manual/functions/","page":"函数","title":"函数","text":"函数的链式调用(有时也称“使用管道”把数据送到一系列函数中去)指的是把一个函数作用到前一个函数的输出上:","category":"page"},{"location":"manual/functions/","page":"函数","title":"函数","text":"julia> 1:10 |> sum |> sqrt\n7.416198487095663","category":"page"},{"location":"manual/functions/","page":"函数","title":"函数","text":"在这里, sum 函数求出的和被传递到 sqrt 函数作为参数。等价的函数复合写法是:","category":"page"},{"location":"manual/functions/","page":"函数","title":"函数","text":"julia> (sqrt ∘ sum)(1:10)\n7.416198487095663","category":"page"},{"location":"manual/functions/","page":"函数","title":"函数","text":"管道运算符还可以和广播一起使用(.|>),这提供了一个有用的链式调用/管道+向量化运算的组合语法(接下来将描述)。","category":"page"},{"location":"manual/functions/","page":"函数","title":"函数","text":"julia> [\"a\", \"list\", \"of\", \"strings\"] .|> [uppercase, reverse, titlecase, length]\n4-element Vector{Any}:\n \"A\"\n \"tsil\"\n \"Of\"\n 7","category":"page"},{"location":"manual/functions/#man-vectorized","page":"函数","title":"向量化函数的点语法","text":"","category":"section"},{"location":"manual/functions/","page":"函数","title":"函数","text":"在科学计算语言中,通常会有函数的「向量化」版本,它简单地将给定函数 f(x) 作用于数组 A 的每个元素,接着通过 f(A) 生成一个新数组。这种语法便于数据处理,但在其它语言中,向量化通常也是性能所需要的:如果循环很慢,函数的「向量化」版本可以调用由低级语言编写的、快速的库代码。在 Julia 中,向量化函数不是性能所必需的,实际上编写自己的循环通常也是有益的(请参阅 Performance Tips),但它们仍然很方便。因此,任何 Julia 函数 f 能够以元素方式作用于任何数组(或者其它集合),这通过语法 f.(A) 实现。例如,sin 可以作用于向量 A 中的所有元素,如下所示:","category":"page"},{"location":"manual/functions/","page":"函数","title":"函数","text":"julia> A = [1.0, 2.0, 3.0]\n3-element Vector{Float64}:\n 1.0\n 2.0\n 3.0\n\njulia> sin.(A)\n3-element Vector{Float64}:\n 0.8414709848078965\n 0.9092974268256817\n 0.1411200080598672","category":"page"},{"location":"manual/functions/","page":"函数","title":"函数","text":"当然,你如果为 f 编写了一个专门的「向量化」方法,例如通过 f(A::AbstractArray) = map(f, A),可以省略点号,这和 f.(A) 一样高效。但这种方法要求你事先决定要进行向量化的函数。","category":"page"},{"location":"manual/functions/","page":"函数","title":"函数","text":"更一般地,f.(args...) 实际上等价于 broadcast(f, args...),它允许你操作多个数组(甚至是不同形状的),或是数组和标量的混合(请参阅 Broadcasting)。例如,如果有 f(x,y) = 3x + 4y,那么 f.(pi,A) 将为 A 中的每个 a 返回一个由 f(pi,a) 组成的新数组,而 f.(vector1,vector2) 将为每个索引 i 返回一个由 f(vector1[i],vector2[i]) 组成的新向量(如果向量具有不同的长度则会抛出异常)。","category":"page"},{"location":"manual/functions/","page":"函数","title":"函数","text":"julia> f(x,y) = 3x + 4y;\n\njulia> A = [1.0, 2.0, 3.0];\n\njulia> B = [4.0, 5.0, 6.0];\n\njulia> f.(pi, A)\n3-element Vector{Float64}:\n 13.42477796076938\n 17.42477796076938\n 21.42477796076938\n\njulia> f.(A, B)\n3-element Vector{Float64}:\n 19.0\n 26.0\n 33.0","category":"page"},{"location":"manual/functions/","page":"函数","title":"函数","text":"此外,嵌套的 f.(args...) 调用会被融合到一个 broadcast 循环中。例如,sin.(cos.(X)) 等价于 broadcast(x -> sin(cos(x)), X),类似于 [sin(cos(x)) for x in X]:在 X 上只有一个循环,并且只为结果分配了一个数组。[ 相反,在典型的「向量化」语言中,sin(cos(X)) 首先会为 tmp=cos(X) 分配第一个临时数组,然后在单独的循环中计算 sin(tmp),再分配第二个数组。] 这种循环融合不是可能发生也可能不发生的编译器优化,只要遇到了嵌套的 f.(args...) 调用,它就是一个语法保证。技术上,一旦遇到「非点」函数调用,融合就会停止;例如,在 sin.(sort(cos.(X))) 中,由于插入的 sort 函数,sin 和 cos 无法被合并。","category":"page"},{"location":"manual/functions/","page":"函数","title":"函数","text":"最后,最大效率通常在向量化操作的输出数组被预分配时实现,这样重复调用就不会一次又一次地为结果分配新数组(请参阅 输出预分配)。一个方便的语法是 X .= ...,它等价于 broadcast!(identity, X, ...),除了上面提到的,broadcast! 循环可与任何嵌套的「点」调用融合。例如,X .= sin.(Y) 等价于 broadcast!(sin, X, Y),用 sin.(Y) in-place 覆盖 X。如果左边是数组索引表达式,例如 X[2:end] .= sin.(Y),那就将 broadcast! 转换在一个 view 上,例如 broadcast!(sin, view(X, 2:lastindex(X)), Y),这样左侧就被 in-place 更新了。","category":"page"},{"location":"manual/functions/","page":"函数","title":"函数","text":"由于在表达式中为许多操作和函数调用添加点可能很乏味并导致难以阅读的代码,宏 @. 用于将表达式中的每个函数调用、操作和赋值转换为「点」版本。","category":"page"},{"location":"manual/functions/","page":"函数","title":"函数","text":"julia> Y = [1.0, 2.0, 3.0, 4.0];\n\njulia> X = similar(Y); # pre-allocate output array\n\njulia> @. X = sin(cos(Y)) # equivalent to X .= sin.(cos.(Y))\n4-element Vector{Float64}:\n 0.5143952585235492\n -0.4042391538522658\n -0.8360218615377305\n -0.6080830096407656","category":"page"},{"location":"manual/functions/","page":"函数","title":"函数","text":"像 .+ 这样的二元(或一元)运算符使用相同的机制进行管理:它们等价于 broadcast 调用且可与其它嵌套的「点」调用融合。X .+= Y 等等价于 X .= X .+ Y,结果为一个融合的 in-place 赋值;另见 dot operators。","category":"page"},{"location":"manual/functions/","page":"函数","title":"函数","text":"您也可以使用 |> 将点操作与函数链组合在一起,如本例所示:","category":"page"},{"location":"manual/functions/","page":"函数","title":"函数","text":"julia> [1:5;] .|> [x->x^2, inv, x->2*x, -, isodd]\n5-element Vector{Real}:\n 1\n 0.5\n 6\n -4\n true","category":"page"},{"location":"manual/functions/#更多阅读","page":"函数","title":"更多阅读","text":"","category":"section"},{"location":"manual/functions/","page":"函数","title":"函数","text":"我们应该在这里提到,这远不是定义函数的完整图景。Julia 拥有一个复杂的类型系统并且允许对参数类型进行多重分派。这里给出的示例都没有为它们的参数提供任何类型注释,意味着它们可以作用于任何类型的参数。类型系统在类型中描述,而方法则描述了根据运行时参数类型上的多重分派所选择的方法定义函数。","category":"page"},{"location":"stdlib/Mmap/#内存映射-I/O","page":"内存映射 I/O","title":"内存映射 I/O","text":"","category":"section"},{"location":"stdlib/Mmap/","page":"内存映射 I/O","title":"内存映射 I/O","text":"Mmap.Anonymous\nMmap.mmap\nMmap.sync!","category":"page"},{"location":"stdlib/Mmap/#Mmap.Anonymous","page":"内存映射 I/O","title":"Mmap.Anonymous","text":"Mmap.Anonymous(name::AbstractString=\"\", readonly::Bool=false, create::Bool=true)\n\nCreate an IO-like object for creating zeroed-out mmapped-memory that is not tied to a file for use in mmap. Used by SharedArray for creating shared memory arrays.\n\nExamples\n\njulia> using Mmap\n\njulia> anon = Mmap.Anonymous();\n\njulia> isreadable(anon)\ntrue\n\njulia> iswritable(anon)\ntrue\n\njulia> isopen(anon)\ntrue\n\n\n\n\n\n","category":"type"},{"location":"stdlib/Mmap/#Mmap.mmap","page":"内存映射 I/O","title":"Mmap.mmap","text":"mmap(io::Union{IOStream,AbstractString,Mmap.AnonymousMmap}[, type::Type{Array{T,N}}, dims, offset]; grow::Bool=true, shared::Bool=true)\nmmap(type::Type{Array{T,N}}, dims)\n\nCreate an Array whose values are linked to a file, using memory-mapping. This provides a convenient way of working with data too large to fit in the computer's memory.\n\nThe type is an Array{T,N} with a bits-type element of T and dimension N that determines how the bytes of the array are interpreted. Note that the file must be stored in binary format, and no format conversions are possible (this is a limitation of operating systems, not Julia).\n\ndims is a tuple or single Integer specifying the size or length of the array.\n\nThe file is passed via the stream argument, either as an open IOStream or filename string. When you initialize the stream, use \"r\" for a \"read-only\" array, and \"w+\" to create a new array used to write values to disk.\n\nIf no type argument is specified, the default is Vector{UInt8}.\n\nOptionally, you can specify an offset (in bytes) if, for example, you want to skip over a header in the file. The default value for the offset is the current stream position for an IOStream.\n\nThe grow keyword argument specifies whether the disk file should be grown to accommodate the requested size of array (if the total file size is < requested array size). Write privileges are required to grow the file.\n\nThe shared keyword argument specifies whether the resulting Array and changes made to it will be visible to other processes mapping the same file.\n\nFor example, the following code\n\n# Create a file for mmapping\n# (you could alternatively use mmap to do this step, too)\nusing Mmap\nA = rand(1:20, 5, 30)\ns = open(\"/tmp/mmap.bin\", \"w+\")\n# We'll write the dimensions of the array as the first two Ints in the file\nwrite(s, size(A,1))\nwrite(s, size(A,2))\n# Now write the data\nwrite(s, A)\nclose(s)\n\n# Test by reading it back in\ns = open(\"/tmp/mmap.bin\") # default is read-only\nm = read(s, Int)\nn = read(s, Int)\nA2 = mmap(s, Matrix{Int}, (m,n))\n\ncreates a m-by-n Matrix{Int}, linked to the file associated with stream s.\n\nA more portable file would need to encode the word size – 32 bit or 64 bit – and endianness information in the header. In practice, consider encoding binary data using standard formats like HDF5 (which can be used with memory-mapping).\n\n\n\n\n\nmmap(io, BitArray, [dims, offset])\n\nCreate a BitArray whose values are linked to a file, using memory-mapping; it has the same purpose, works in the same way, and has the same arguments, as mmap, but the byte representation is different.\n\nExamples\n\njulia> using Mmap\n\njulia> io = open(\"mmap.bin\", \"w+\");\n\njulia> B = mmap(io, BitArray, (25,30000));\n\njulia> B[3, 4000] = true;\n\njulia> Mmap.sync!(B);\n\njulia> close(io);\n\njulia> io = open(\"mmap.bin\", \"r+\");\n\njulia> C = mmap(io, BitArray, (25,30000));\n\njulia> C[3, 4000]\ntrue\n\njulia> C[2, 4000]\nfalse\n\njulia> close(io)\n\njulia> rm(\"mmap.bin\")\n\nThis creates a 25-by-30000 BitArray, linked to the file associated with stream io.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/Mmap/#Mmap.sync!","page":"内存映射 I/O","title":"Mmap.sync!","text":"Mmap.sync!(array)\n\nForces synchronization between the in-memory version of a memory-mapped Array or BitArray and the on-disk version.\n\n\n\n\n\n","category":"function"},{"location":"devdocs/sysimg/#System-Image-Building","page":"System Image Building","title":"System Image Building","text":"","category":"section"},{"location":"devdocs/sysimg/#Building-the-Julia-system-image","page":"System Image Building","title":"Building the Julia system image","text":"","category":"section"},{"location":"devdocs/sysimg/","page":"System Image Building","title":"System Image Building","text":"Julia ships with a preparsed system image containing the contents of the Base module, named sys.ji. This file is also precompiled into a shared library called sys.{so,dll,dylib} on as many platforms as possible, so as to give vastly improved startup times. On systems that do not ship with a precompiled system image file, one can be generated from the source files shipped in Julia's DATAROOTDIR/julia/base folder.","category":"page"},{"location":"devdocs/sysimg/","page":"System Image Building","title":"System Image Building","text":"This operation is useful for multiple reasons. A user may:","category":"page"},{"location":"devdocs/sysimg/","page":"System Image Building","title":"System Image Building","text":"Build a precompiled shared library system image on a platform that did not ship with one, thereby improving startup times.\nModify Base, rebuild the system image and use the new Base next time Julia is started.\nInclude a userimg.jl file that includes packages into the system image, thereby creating a system image that has packages embedded into the startup environment.","category":"page"},{"location":"devdocs/sysimg/","page":"System Image Building","title":"System Image Building","text":"The PackageCompiler.jl package contains convenient wrapper functions to automate this process.","category":"page"},{"location":"devdocs/sysimg/#System-image-optimized-for-multiple-microarchitectures","page":"System Image Building","title":"System image optimized for multiple microarchitectures","text":"","category":"section"},{"location":"devdocs/sysimg/","page":"System Image Building","title":"System Image Building","text":"The system image can be compiled simultaneously for multiple CPU microarchitectures under the same instruction set architecture (ISA). Multiple versions of the same function may be created with minimum dispatch point inserted into shared functions in order to take advantage of different ISA extensions or other microarchitecture features. The version that offers the best performance will be selected automatically at runtime based on available CPU features.","category":"page"},{"location":"devdocs/sysimg/#Specifying-multiple-system-image-targets","page":"System Image Building","title":"Specifying multiple system image targets","text":"","category":"section"},{"location":"devdocs/sysimg/","page":"System Image Building","title":"System Image Building","text":"A multi-microarchitecture system image can be enabled by passing multiple targets during system image compilation. This can be done either with the JULIA_CPU_TARGET make option or with the -C command line option when running the compilation command manually. Multiple targets are separated by ; in the option string. The syntax for each target is a CPU name followed by multiple features separated by ,. All features supported by LLVM are supported and a feature can be disabled with a - prefix. (+ prefix is also allowed and ignored to be consistent with LLVM syntax). Additionally, a few special features are supported to control the function cloning behavior.","category":"page"},{"location":"devdocs/sysimg/","page":"System Image Building","title":"System Image Building","text":"clone_all\nBy default, only functions that are the most likely to benefit from the microarchitecture features will be cloned. When clone_all is specified for a target, however, all functions in the system image will be cloned for the target. The negative form -clone_all can be used to prevent the built-in heuristic from cloning all functions.\nbase()\nWhere is a placeholder for a non-negative number (e.g. base(0), base(1)). By default, a partially cloned (i.e. not clone_all) target will use functions from the default target (first one specified) if a function is not cloned. This behavior can be changed by specifying a different base with the base() option. The nth target (0-based) will be used as the base target instead of the default (0th) one. The base target has to be either 0 or another clone_all target. Specifying a non-clone_all target as the base target will cause an error.\nopt_size\nThis causes the function for the target to be optimized for size when there isn't a significant runtime performance impact. This corresponds to -Os GCC and Clang option.\nmin_size\nThis causes the function for the target to be optimized for size that might have a significant runtime performance impact. This corresponds to -Oz Clang option.","category":"page"},{"location":"devdocs/sysimg/","page":"System Image Building","title":"System Image Building","text":"As an example, at the time of this writing, the following string is used in the creation of the official x86_64 Julia binaries downloadable from julialang.org:","category":"page"},{"location":"devdocs/sysimg/","page":"System Image Building","title":"System Image Building","text":"generic;sandybridge,-xsaveopt,clone_all;haswell,-rdrnd,base(1)","category":"page"},{"location":"devdocs/sysimg/","page":"System Image Building","title":"System Image Building","text":"This creates a system image with three separate targets; one for a generic x86_64 processor, one with a sandybridge ISA (explicitly excluding xsaveopt) that explicitly clones all functions, and one targeting the haswell ISA, based off of the sandybridge sysimg version, and also excluding rdrnd. When a Julia implementation loads the generated sysimg, it will check the host processor for matching CPU capability flags, enabling the highest ISA level possible. Note that the base level (generic) requires the cx16 instruction, which is disabled in some virtualization software and must be enabled for the generic target to be loaded. Alternatively, a sysimg could be generated with the target generic,-cx16 for greater compatibility, however note that this may cause performance and stability problems in some code.","category":"page"},{"location":"devdocs/sysimg/#Implementation-overview","page":"System Image Building","title":"Implementation overview","text":"","category":"section"},{"location":"devdocs/sysimg/","page":"System Image Building","title":"System Image Building","text":"This is a brief overview of different part involved in the implementation. See code comments for each components for more implementation details.","category":"page"},{"location":"devdocs/sysimg/","page":"System Image Building","title":"System Image Building","text":"System image compilation\nThe parsing and cloning decision are done in src/processor*. We currently support cloning of function based on the present of loops, simd instructions, or other math operations (e.g. fastmath, fma, muladd). This information is passed on to src/llvm-multiversioning.cpp which does the actual cloning. In addition to doing the cloning and insert dispatch slots (see comments in MultiVersioning::runOnModule for how this is done), the pass also generates metadata so that the runtime can load and initialize the system image correctly. A detail description of the metadata is available in src/processor.h.\nSystem image loading\nThe loading and initialization of the system image is done in src/processor* by parsing the metadata saved during system image generation. Host feature detection and selection decision are done in src/processor_*.cpp depending on the ISA. The target selection will prefer exact CPU name match, larger vector register size, and larger number of features. An overview of this process is in src/processor.cpp.","category":"page"},{"location":"devdocs/functions/#Julia-函数","page":"Julia 函数","title":"Julia 函数","text":"","category":"section"},{"location":"devdocs/functions/","page":"Julia 函数","title":"Julia 函数","text":"本文档将解释函数、方法定义以及方法表是如何工作的。","category":"page"},{"location":"devdocs/functions/#方法表","page":"Julia 函数","title":"方法表","text":"","category":"section"},{"location":"devdocs/functions/","page":"Julia 函数","title":"Julia 函数","text":"Julia 中的每个函数都是泛型函数。泛型函数在概念上是单个函数,但由许多定义或方法组成。泛型函数的方法储存在方法表中。方法表(类型 MethodTable)与 TypeName 相关。TypeName 描述了一系列参数化类型。例如,Complex{Float32} 和 Complex{Float64} 共享相同的 type name 对象 Complex。","category":"page"},{"location":"devdocs/functions/","page":"Julia 函数","title":"Julia 函数","text":"Julia 中的所有对象都可能是可调用的,因为每个对象都有类型,而类型又有 TypeName。","category":"page"},{"location":"devdocs/functions/#函数调用","page":"Julia 函数","title":"函数调用","text":"","category":"section"},{"location":"devdocs/functions/","page":"Julia 函数","title":"Julia 函数","text":"给定调用 f(x,y),会执行以下步骤:首先,用 typeof(f).name.mt 访问要使用的方法表。其次,生成一个参数元组类型 Tuple{typeof(f), typeof(x), typeof(y)}。请注意,函数本身的类型是第一个元素。这因为该类型可能有参数,所以需要参与派发。这个元组类型会在方法表中查找。","category":"page"},{"location":"devdocs/functions/","page":"Julia 函数","title":"Julia 函数","text":"这个派发过程由 jl_apply_generic 执行,它有两个参数:一个指向由值 f、x 和 y 组成的数组的指针,以及值的数量(此例中是 3)。","category":"page"},{"location":"devdocs/functions/","page":"Julia 函数","title":"Julia 函数","text":"在整个系统中,处理函数和参数列表的 API 有两种:一种单独接收函数和参数,一种接收一个单独的参数结构。在第一种 API 中,「参数」部分不包含函数的相关信息,因为它是单独传递的。在第二种 API 中,函数是参数结构的第一个元素。","category":"page"},{"location":"devdocs/functions/","page":"Julia 函数","title":"Julia 函数","text":"例如,以下用于执行调用的函数只接收 args 指针,因此 args 数组的第一个元素将会是要调用的函数:","category":"page"},{"location":"devdocs/functions/","page":"Julia 函数","title":"Julia 函数","text":"jl_value_t *jl_apply(jl_value_t **args, uint32_t nargs)","category":"page"},{"location":"devdocs/functions/","page":"Julia 函数","title":"Julia 函数","text":"这个用于相同功能的入口点单独接收该函数,因此 args 数组中不包含该函数:","category":"page"},{"location":"devdocs/functions/","page":"Julia 函数","title":"Julia 函数","text":"jl_value_t *jl_call(jl_function_t *f, jl_value_t **args, int32_t nargs);","category":"page"},{"location":"devdocs/functions/#添加方法","page":"Julia 函数","title":"添加方法","text":"","category":"section"},{"location":"devdocs/functions/","page":"Julia 函数","title":"Julia 函数","text":"在上述派发过程中,添加一个新方法在概念上所需的只是(1)一个元组类型,以及(2)方法体的代码。jl_method_def 实现了此操作。jl_first_argument_datatype 会被调用,用来从第一个参数的类型中提取相关的方法表。这比派发期间的相应过程复杂得多,因为参数元组类型可能是抽象类型。例如,我们可以定义:","category":"page"},{"location":"devdocs/functions/","page":"Julia 函数","title":"Julia 函数","text":"(::Union{Foo{Int},Foo{Int8}})(x) = 0","category":"page"},{"location":"devdocs/functions/","page":"Julia 函数","title":"Julia 函数","text":"这是可行的,因为所有可能的匹配方法都属于同一方法表。","category":"page"},{"location":"devdocs/functions/#创建泛型函数","page":"Julia 函数","title":"创建泛型函数","text":"","category":"section"},{"location":"devdocs/functions/","page":"Julia 函数","title":"Julia 函数","text":"因为每个对象都是可调用的,所以创建泛型函数不需要特殊的东西。因此,jl_new_generic_function 只是创建一个新的 Function 的单态类型(大小为 0)并返回它的实例。函数可有一个帮助记忆的「显示名称」,用于调试信息和打印对象。例如,Base.sin 的名称为 sin。按照约定,所创建类型的名称与函数名称相同,带前缀 #。所以 typeof(sin) 即 Base.#sin。","category":"page"},{"location":"devdocs/functions/#闭包","page":"Julia 函数","title":"闭包","text":"","category":"section"},{"location":"devdocs/functions/","page":"Julia 函数","title":"Julia 函数","text":"闭包只是一个可调用对象,其字段名称对应于被捕获的变量。例如,以下代码:","category":"page"},{"location":"devdocs/functions/","page":"Julia 函数","title":"Julia 函数","text":"function adder(x)\n return y->x+y\nend","category":"page"},{"location":"devdocs/functions/","page":"Julia 函数","title":"Julia 函数","text":"(大致)降低为:","category":"page"},{"location":"devdocs/functions/","page":"Julia 函数","title":"Julia 函数","text":"struct ##1{T}\n x::T\nend\n\n(_::##1)(y) = _.x + y\n\nfunction adder(x)\n return ##1(x)\nend","category":"page"},{"location":"devdocs/functions/#构造函数","page":"Julia 函数","title":"构造函数","text":"","category":"section"},{"location":"devdocs/functions/","page":"Julia 函数","title":"Julia 函数","text":"构造函数调用只是对类型的调用。Type 的方法表包含所有的构造函数定义。Type 的所有子类型(Type、UnionAll、Union 和 DataType)目前通过特殊的安排方式共享一个方法表。","category":"page"},{"location":"devdocs/functions/#内置函数","page":"Julia 函数","title":"内置函数","text":"","category":"section"},{"location":"devdocs/functions/","page":"Julia 函数","title":"Julia 函数","text":"「内置」函数定义在 Core 模块中,有:","category":"page"},{"location":"devdocs/functions/","page":"Julia 函数","title":"Julia 函数","text":"=== typeof sizeof <: isa typeassert throw tuple getfield setfield! fieldtype\nnfields isdefined arrayref arrayset arraysize applicable invoke apply_type _apply\n_expr svec","category":"page"},{"location":"devdocs/functions/","page":"Julia 函数","title":"Julia 函数","text":"这些都是单态对象,其类型为 Builtin 的子类型,而或后者为 Function 的子类型。它们的用处是在运行时暴露遵循「jlcall」调用约定的入口点。","category":"page"},{"location":"devdocs/functions/","page":"Julia 函数","title":"Julia 函数","text":"jl_value_t *(jl_value_t*, jl_value_t**, uint32_t)","category":"page"},{"location":"devdocs/functions/","page":"Julia 函数","title":"Julia 函数","text":"内建函数的方法表是空的。相反地,它们具有单独的 catch-all 方法缓存条目(Tuple{Vararg{Any}}),其 jlcall fptr 指向正确的函数。这是一种 hack,但效果相当不错。","category":"page"},{"location":"devdocs/functions/#关键字参数","page":"Julia 函数","title":"关键字参数","text":"","category":"section"},{"location":"devdocs/functions/","page":"Julia 函数","title":"Julia 函数","text":"关键字参数的工作方式是将每个具有关键字参数的方法表与一个特殊的隐藏函数对象相关联。该函数称为「keyword argument sorter」、「keyword sorter」或「kwsorter」,存储在 MethodTable 对象的 kwsorter 字段中。在 kwsorter 函数的每个定义与通常的方法表中的某个函数具有相同的参数,除了前面还有一个 NamedTuple 参数,该参数给出所传递关键字参数的名称和值。kwsorter 的作用是根据名称将关键字参数移到预先要求的位置,并对任何所需的默认值表达式进行求值和替换。其返回结果是一个通常的位置参数列表,接着会被传递给另一个由编译器生成的函数。","category":"page"},{"location":"devdocs/functions/","page":"Julia 函数","title":"Julia 函数","text":"理解该过程的最简单方法是查看关键字参数方法的定义的降低方式。代码:","category":"page"},{"location":"devdocs/functions/","page":"Julia 函数","title":"Julia 函数","text":"function circle(center, radius; color = black, fill::Bool = true, options...)\n # draw\nend","category":"page"},{"location":"devdocs/functions/","page":"Julia 函数","title":"Julia 函数","text":"实际上生成三个方法定义。第一个方法是一个接收所有参数(包括关键字参数)作为其位置参数的函数,其代码包含该方法体。它有一个自动生成的名称:","category":"page"},{"location":"devdocs/functions/","page":"Julia 函数","title":"Julia 函数","text":"function #circle#1(color, fill::Bool, options, circle, center, radius)\n # draw\nend","category":"page"},{"location":"devdocs/functions/","page":"Julia 函数","title":"Julia 函数","text":"第二个方法是原始 circle 函数的普通定义,负责处理没有传递关键字参数的情况:","category":"page"},{"location":"devdocs/functions/","page":"Julia 函数","title":"Julia 函数","text":"function circle(center, radius)\n #circle#1(black, true, pairs(NamedTuple()), circle, center, radius)\nend","category":"page"},{"location":"devdocs/functions/","page":"Julia 函数","title":"Julia 函数","text":"这只是派发到第一个方法,传递默认值。pairs 应用于其余的参数组成的具名元组,以提供键值对迭代。请注意,如果方法不接受其余的关键字参数,那么此参数不存在。","category":"page"},{"location":"devdocs/functions/","page":"Julia 函数","title":"Julia 函数","text":"最后,kwsorter 定义为:","category":"page"},{"location":"devdocs/functions/","page":"Julia 函数","title":"Julia 函数","text":"function (::Core.kwftype(typeof(circle)))(kws, circle, center, radius)\n if haskey(kws, :color)\n color = kws.color\n else\n color = black\n end\n # etc.\n\n # put remaining kwargs in `options`\n options = structdiff(kws, NamedTuple{(:color, :fill)})\n\n # if the method doesn't accept rest keywords, throw an error\n # unless `options` is empty\n\n #circle#1(color, fill, pairs(options), circle, center, radius)\nend","category":"page"},{"location":"devdocs/functions/","page":"Julia 函数","title":"Julia 函数","text":"函数 Core.kwftype(t) 创建字段 t.name.mt.kwsorter(如果它未被创建),并返回该函数的类型。","category":"page"},{"location":"devdocs/functions/","page":"Julia 函数","title":"Julia 函数","text":"此设计的特点是不使用关键字参数的调用点不需要特殊处理;这一切的工作方式好像它们根本不是语言的一部分。不使用关键字参数的调用点直接派发到被调用函数的 kwsorter。例如,调用:","category":"page"},{"location":"devdocs/functions/","page":"Julia 函数","title":"Julia 函数","text":"circle((0,0), 1.0, color = red; other...)","category":"page"},{"location":"devdocs/functions/","page":"Julia 函数","title":"Julia 函数","text":"降低为:","category":"page"},{"location":"devdocs/functions/","page":"Julia 函数","title":"Julia 函数","text":"kwfunc(circle)(merge((color = red,), other), circle, (0,0), 1.0)","category":"page"},{"location":"devdocs/functions/","page":"Julia 函数","title":"Julia 函数","text":"kwfunc(也在 Core 中)可获取被调用函数的 kwsorter。关键字 splatting 函数(编写为 other...)调用具名元组 merge 函数。此函数进一步解包了 other 的每个元素,预期中每个元素包含两个值(一个符号和一个值)。当然,如果所有 splatted 参数都是具名元组,则可使用更高效的实现。请注意,原来的 circle 被传递,以处理闭包。","category":"page"},{"location":"devdocs/functions/#compiler-efficiency-issues","page":"Julia 函数","title":"Compiler efficiency issues","text":"","category":"section"},{"location":"devdocs/functions/","page":"Julia 函数","title":"Julia 函数","text":"为每个函数生成新类型在与 Julia 的「默认专门化所有参数」这一设计理念结合使用时,可能对编译器资源的使用产生严重后果。实际上,此设计的初始实现经历了更长的测试和构造时间、高内存占用以及比基线大近乎 2 倍的系统镜像。在一个幼稚的实现中,该问题非常严重,以至于系统几乎无法使用。需要进行几项重要的优化才能使设计变得可行。","category":"page"},{"location":"devdocs/functions/","page":"Julia 函数","title":"Julia 函数","text":"第一个问题是函数值参数的不同值导致函数的过度专门化。许多函数只是将参数「传递」到其它地方,例如,到另一个函数或存储位置。这种函数不需要为每个可能传入的闭包专门化。幸运的是,这种情况很容易区分,只需考虑函数是否调用它的某个参数(即,参数出现在某处的「头部位置」)。性能关键的高阶函数,如 map,肯定会直接调用它们的参数函数,因此仍然会按预期进行专门化。此优化通过在前端记录 analyze-variables 传递期间所调用的参数来实现。当 cache_method 看到某个在 Function 类型层次结构的参数传递到声明为 Any 或 Function 的槽时,它的行为就好像应用了 @nospecialize 注释一样。这种启发式方法在实践中似乎非常有效。","category":"page"},{"location":"devdocs/functions/","page":"Julia 函数","title":"Julia 函数","text":"下一个问题涉及方法缓存哈希表的结构。经验研究表明,绝大多数动态分派调用只涉及一个或两个元素。反过来看,只考虑第一个元素便可解决许多这些情况。(旁白:单派发的支持者根本不会对此感到惊讶。但是,这个观点意味着「多重派发在实践中很容易优化」,因此我们应该使用它,而不是「我们应该使用单派发」!)因此,方法缓存使用第一个参数作为其主键。但请注意,这对应于函数调用的元组类型的第二个元素(第一个元素是函数本身的类型)。通常,头部位置的类型非常少变化——实际上,大多数函数属于没有参数的单态类型。但是,构造函数不是这种情况,一个方法表便保存了所有类型的构造函数。因此,Type 方法表是特殊的,使用元组类型的第一个元素而不是第二个。","category":"page"},{"location":"devdocs/functions/","page":"Julia 函数","title":"Julia 函数","text":"前端为所有闭包生成类型声明。起初,这通过生成通常的类型声明来实现。但是,这产生了大量的构造函数,这些构造函数全都很简单(只是将所有参数传递给 new)。因为方法是部分排序的,所以插入所有这些方法是 O(n^2),此外要保留的方法实在太多了。这可通过直接生成 struct_type 表达式(绕过默认的构造函数生成)并直接使用 new 来创建闭包的实例来优化。这事并不漂亮,但你需要做你该做的。","category":"page"},{"location":"devdocs/functions/","page":"Julia 函数","title":"Julia 函数","text":"下个问题是 @test 宏,它为每个测试用例生成一个 0 参数闭包。这不是必需的,因为每个用例只需运行一次。因此,@test 被改写以展开到一个 try-catch 块中,该块记录测试结果(true、false 或所引发的异常)并对它调用测试套件处理程序。","category":"page"},{"location":"stdlib/Profile/#lib-profiling","page":"性能分析","title":"性能分析","text":"","category":"section"},{"location":"stdlib/Profile/","page":"性能分析","title":"性能分析","text":"Profile.@profile","category":"page"},{"location":"stdlib/Profile/#Profile.@profile","page":"性能分析","title":"Profile.@profile","text":"@profile\n\n@profile runs your expression while taking periodic backtraces. These are appended to an internal buffer of backtraces.\n\n\n\n\n\n","category":"macro"},{"location":"stdlib/Profile/","page":"性能分析","title":"性能分析","text":"Profile 里的方法均未导出,需要通过 Profile.print() 的方式调用。","category":"page"},{"location":"stdlib/Profile/","page":"性能分析","title":"性能分析","text":"Profile.clear\nProfile.print\nProfile.init\nProfile.fetch\nProfile.retrieve\nProfile.callers\nProfile.clear_malloc_data","category":"page"},{"location":"stdlib/Profile/#Profile.clear","page":"性能分析","title":"Profile.clear","text":"clear()\n\nClear any existing backtraces from the internal buffer.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/Profile/#Profile.print","page":"性能分析","title":"Profile.print","text":"print([io::IO = stdout,] [data::Vector = fetch()], [lidict::Union{LineInfoDict, LineInfoFlatDict} = getdict(data)]; kwargs...)\n\nPrints profiling results to io (by default, stdout). If you do not supply a data vector, the internal buffer of accumulated backtraces will be used.\n\nThe keyword arguments can be any combination of:\n\nformat – Determines whether backtraces are printed with (default, :tree) or without (:flat) indentation indicating tree structure.\nC – If true, backtraces from C and Fortran code are shown (normally they are excluded).\ncombine – If true (default), instruction pointers are merged that correspond to the same line of code.\nmaxdepth – Limits the depth higher than maxdepth in the :tree format.\nsortedby – Controls the order in :flat format. :filefuncline (default) sorts by the source line, :count sorts in order of number of collected samples, and :overhead sorts by the number of samples incurred by each function by itself.\ngroupby – Controls grouping over tasks and threads, or no grouping. Options are :none (default), :thread, :task, [:thread, :task], or [:task, :thread] where the last two provide nested grouping.\nnoisefloor – Limits frames that exceed the heuristic noise floor of the sample (only applies to format :tree). A suggested value to try for this is 2.0 (the default is 0). This parameter hides samples for which n <= noisefloor * √N, where n is the number of samples on this line, and N is the number of samples for the callee.\nmincount – Limits the printout to only those lines with at least mincount occurrences.\nrecur – Controls the recursion handling in :tree format. :off (default) prints the tree as normal. :flat instead compresses any recursion (by ip), showing the approximate effect of converting any self-recursion into an iterator. :flatc does the same but also includes collapsing of C frames (may do odd things around jl_apply).\nthreads::Union{Int,AbstractVector{Int}} – Specify which threads to include snapshots from in the report. Note that this does not control which threads samples are collected on (which may also have been collected on another machine).\ntasks::Union{Int,AbstractVector{Int}} – Specify which tasks to include snapshots from in the report. Note that this does not control which tasks samples are collected within.\n\n\n\n\n\nprint([io::IO = stdout,] data::Vector, lidict::LineInfoDict; kwargs...)\n\nPrints profiling results to io. This variant is used to examine results exported by a previous call to retrieve. Supply the vector data of backtraces and a dictionary lidict of line information.\n\nSee Profile.print([io], data) for an explanation of the valid keyword arguments.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/Profile/#Profile.init","page":"性能分析","title":"Profile.init","text":"init(; n::Integer, delay::Real)\n\nConfigure the delay between backtraces (measured in seconds), and the number n of instruction pointers that may be stored per thread. Each instruction pointer corresponds to a single line of code; backtraces generally consist of a long list of instruction pointers. Note that 6 spaces for instruction pointers per backtrace are used to store metadata and two NULL end markers. Current settings can be obtained by calling this function with no arguments, and each can be set independently using keywords or in the order (n, delay).\n\ncompat: Julia 1.8\nAs of Julia 1.8, this function allocates space for n instruction pointers per thread being profiled. Previously this was n total.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/Profile/#Profile.fetch","page":"性能分析","title":"Profile.fetch","text":"fetch(;include_meta = true) -> data\n\nReturns a copy of the buffer of profile backtraces. Note that the values in data have meaning only on this machine in the current session, because it depends on the exact memory addresses used in JIT-compiling. This function is primarily for internal use; retrieve may be a better choice for most users. By default metadata such as threadid and taskid is included. Set include_meta to false to strip metadata.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/Profile/#Profile.retrieve","page":"性能分析","title":"Profile.retrieve","text":"retrieve(; kwargs...) -> data, lidict\n\n\"Exports\" profiling results in a portable format, returning the set of all backtraces (data) and a dictionary that maps the (session-specific) instruction pointers in data to LineInfo values that store the file name, function name, and line number. This function allows you to save profiling results for future analysis.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/Profile/#Profile.callers","page":"性能分析","title":"Profile.callers","text":"callers(funcname, [data, lidict], [filename=], [linerange=]) -> Vector{Tuple{count, lineinfo}}\n\nGiven a previous profiling run, determine who called a particular function. Supplying the filename (and optionally, range of line numbers over which the function is defined) allows you to disambiguate an overloaded method. The returned value is a vector containing a count of the number of calls and line information about the caller. One can optionally supply backtrace data obtained from retrieve; otherwise, the current internal profile buffer is used.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/Profile/#Profile.clear_malloc_data","page":"性能分析","title":"Profile.clear_malloc_data","text":"clear_malloc_data()\n\nClears any stored memory allocation data when running julia with --track-allocation. Execute the command(s) you want to test (to force JIT-compilation), then call clear_malloc_data. Then execute your command(s) again, quit Julia, and examine the resulting *.mem files.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/UUIDs/#UUIDs","page":"UUIDs","title":"UUIDs","text":"","category":"section"},{"location":"stdlib/UUIDs/","page":"UUIDs","title":"UUIDs","text":"UUIDs.uuid1\nUUIDs.uuid4\nUUIDs.uuid5\nUUIDs.uuid_version","category":"page"},{"location":"stdlib/UUIDs/#UUIDs.uuid1","page":"UUIDs","title":"UUIDs.uuid1","text":"uuid1([rng::AbstractRNG]) -> UUID\n\nGenerates a version 1 (time-based) universally unique identifier (UUID), as specified by RFC 4122. Note that the Node ID is randomly generated (does not identify the host) according to section 4.5 of the RFC.\n\nThe default rng used by uuid1 is not GLOBAL_RNG and every invocation of uuid1() without an argument should be expected to return a unique identifier. Importantly, the outputs of uuid1 do not repeat even when Random.seed!(seed) is called. Currently (as of Julia 1.6), uuid1 uses Random.RandomDevice as the default rng. However, this is an implementation detail that may change in the future.\n\ncompat: Julia 1.6\nThe output of uuid1 does not depend on GLOBAL_RNG as of Julia 1.6.\n\nExamples\n\njulia> rng = MersenneTwister(1234);\n\njulia> uuid1(rng)\nUUID(\"cfc395e8-590f-11e8-1f13-43a2532b2fa8\")\n\n\n\n\n\n","category":"function"},{"location":"stdlib/UUIDs/#UUIDs.uuid4","page":"UUIDs","title":"UUIDs.uuid4","text":"uuid4([rng::AbstractRNG]) -> UUID\n\nGenerates a version 4 (random or pseudo-random) universally unique identifier (UUID), as specified by RFC 4122.\n\nThe default rng used by uuid4 is not GLOBAL_RNG and every invocation of uuid4() without an argument should be expected to return a unique identifier. Importantly, the outputs of uuid4 do not repeat even when Random.seed!(seed) is called. Currently (as of Julia 1.6), uuid4 uses Random.RandomDevice as the default rng. However, this is an implementation detail that may change in the future.\n\ncompat: Julia 1.6\nThe output of uuid4 does not depend on GLOBAL_RNG as of Julia 1.6.\n\nExamples\n\njulia> rng = MersenneTwister(1234);\n\njulia> uuid4(rng)\nUUID(\"7a052949-c101-4ca3-9a7e-43a2532b2fa8\")\n\n\n\n\n\n","category":"function"},{"location":"stdlib/UUIDs/#UUIDs.uuid5","page":"UUIDs","title":"UUIDs.uuid5","text":"uuid5(ns::UUID, name::String) -> UUID\n\nGenerates a version 5 (namespace and domain-based) universally unique identifier (UUID), as specified by RFC 4122.\n\ncompat: Julia 1.1\nThis function requires at least Julia 1.1.\n\nExamples\n\njulia> rng = MersenneTwister(1234);\n\njulia> u4 = uuid4(rng)\nUUID(\"7a052949-c101-4ca3-9a7e-43a2532b2fa8\")\n\njulia> u5 = uuid5(u4, \"julia\")\nUUID(\"086cc5bb-2461-57d8-8068-0aed7f5b5cd1\")\n\n\n\n\n\n","category":"function"},{"location":"stdlib/UUIDs/#UUIDs.uuid_version","page":"UUIDs","title":"UUIDs.uuid_version","text":"uuid_version(u::UUID) -> Int\n\nInspects the given UUID and returns its version (see RFC 4122).\n\nExamples\n\njulia> uuid_version(uuid4())\n4\n\n\n\n\n\n","category":"function"},{"location":"base/iterators/#迭代相关","page":"迭代相关","title":"迭代相关","text":"","category":"section"},{"location":"base/iterators/","page":"迭代相关","title":"迭代相关","text":"Base.Iterators.Stateful\nBase.Iterators.zip\nBase.Iterators.enumerate\nBase.Iterators.rest\nBase.Iterators.countfrom\nBase.Iterators.take\nBase.Iterators.takewhile\nBase.Iterators.drop\nBase.Iterators.dropwhile\nBase.Iterators.cycle\nBase.Iterators.repeated\nBase.Iterators.product\nBase.Iterators.flatten\nBase.Iterators.partition\nBase.Iterators.map\nBase.Iterators.filter\nBase.Iterators.accumulate\nBase.Iterators.reverse\nBase.Iterators.only\nBase.Iterators.peel","category":"page"},{"location":"base/iterators/#Base.Iterators.Stateful","page":"迭代相关","title":"Base.Iterators.Stateful","text":"Stateful(itr)\n\nThere are several different ways to think about this iterator wrapper:\n\nIt provides a mutable wrapper around an iterator and its iteration state.\nIt turns an iterator-like abstraction into a Channel-like abstraction.\nIt's an iterator that mutates to become its own rest iterator whenever an item is produced.\n\nStateful provides the regular iterator interface. Like other mutable iterators (e.g. Channel), if iteration is stopped early (e.g. by a break in a for loop), iteration can be resumed from the same spot by continuing to iterate over the same iterator object (in contrast, an immutable iterator would restart from the beginning).\n\nExamples\n\njulia> a = Iterators.Stateful(\"abcdef\");\n\njulia> isempty(a)\nfalse\n\njulia> popfirst!(a)\n'a': ASCII/Unicode U+0061 (category Ll: Letter, lowercase)\n\njulia> collect(Iterators.take(a, 3))\n3-element Vector{Char}:\n 'b': ASCII/Unicode U+0062 (category Ll: Letter, lowercase)\n 'c': ASCII/Unicode U+0063 (category Ll: Letter, lowercase)\n 'd': ASCII/Unicode U+0064 (category Ll: Letter, lowercase)\n\njulia> collect(a)\n2-element Vector{Char}:\n 'e': ASCII/Unicode U+0065 (category Ll: Letter, lowercase)\n 'f': ASCII/Unicode U+0066 (category Ll: Letter, lowercase)\n\njulia> Iterators.reset!(a); popfirst!(a)\n'a': ASCII/Unicode U+0061 (category Ll: Letter, lowercase)\n\njulia> Iterators.reset!(a, \"hello\"); popfirst!(a)\n'h': ASCII/Unicode U+0068 (category Ll: Letter, lowercase)\n\njulia> a = Iterators.Stateful([1,1,1,2,3,4]);\n\njulia> for x in a; x == 1 || break; end\n\njulia> peek(a)\n3\n\njulia> sum(a) # Sum the remaining elements\n7\n\n\n\n\n\n","category":"type"},{"location":"base/iterators/#Base.Iterators.zip","page":"迭代相关","title":"Base.Iterators.zip","text":"zip(iters...)\n\nRun multiple iterators at the same time, until any of them is exhausted. The value type of the zip iterator is a tuple of values of its subiterators.\n\nnote: Note\nzip orders the calls to its subiterators in such a way that stateful iterators will not advance when another iterator finishes in the current iteration.\n\nSee also: enumerate, splat.\n\nExamples\n\njulia> a = 1:5\n1:5\n\njulia> b = [\"e\",\"d\",\"b\",\"c\",\"a\"]\n5-element Vector{String}:\n \"e\"\n \"d\"\n \"b\"\n \"c\"\n \"a\"\n\njulia> c = zip(a,b)\nzip(1:5, [\"e\", \"d\", \"b\", \"c\", \"a\"])\n\njulia> length(c)\n5\n\njulia> first(c)\n(1, \"e\")\n\n\n\n\n\n","category":"function"},{"location":"base/iterators/#Base.Iterators.enumerate","page":"迭代相关","title":"Base.Iterators.enumerate","text":"enumerate(iter)\n\nAn iterator that yields (i, x) where i is a counter starting at 1, and x is the ith value from the given iterator. It's useful when you need not only the values x over which you are iterating, but also the number of iterations so far. Note that i may not be valid for indexing iter; it's also possible that x != iter[i], if iter has indices that do not start at 1. See the pairs(IndexLinear(), iter) method if you want to ensure that i is an index.\n\nExamples\n\njulia> a = [\"a\", \"b\", \"c\"];\n\njulia> for (index, value) in enumerate(a)\n println(\"$index $value\")\n end\n1 a\n2 b\n3 c\n\n\n\n\n\n","category":"function"},{"location":"base/iterators/#Base.Iterators.rest","page":"迭代相关","title":"Base.Iterators.rest","text":"rest(iter, state)\n\nAn iterator that yields the same elements as iter, but starting at the given state.\n\nSee also: Iterators.drop, Iterators.peel, Base.rest.\n\nExamples\n\njulia> collect(Iterators.rest([1,2,3,4], 2))\n3-element Vector{Int64}:\n 2\n 3\n 4\n\n\n\n\n\n","category":"function"},{"location":"base/iterators/#Base.Iterators.countfrom","page":"迭代相关","title":"Base.Iterators.countfrom","text":"countfrom(start=1, step=1)\n\nAn iterator that counts forever, starting at start and incrementing by step.\n\nExamples\n\njulia> for v in Iterators.countfrom(5, 2)\n v > 10 && break\n println(v)\n end\n5\n7\n9\n\n\n\n\n\n","category":"function"},{"location":"base/iterators/#Base.Iterators.take","page":"迭代相关","title":"Base.Iterators.take","text":"take(iter, n)\n\nAn iterator that generates at most the first n elements of iter.\n\nSee also: drop, peel, first, take!.\n\nExamples\n\njulia> a = 1:2:11\n1:2:11\n\njulia> collect(a)\n6-element Vector{Int64}:\n 1\n 3\n 5\n 7\n 9\n 11\n\njulia> collect(Iterators.take(a,3))\n3-element Vector{Int64}:\n 1\n 3\n 5\n\n\n\n\n\n","category":"function"},{"location":"base/iterators/#Base.Iterators.takewhile","page":"迭代相关","title":"Base.Iterators.takewhile","text":"takewhile(pred, iter)\n\nAn iterator that generates element from iter as long as predicate pred is true, afterwards, drops every element.\n\ncompat: Julia 1.4\nThis function requires at least Julia 1.4.\n\nExamples\n\njulia> s = collect(1:5)\n5-element Vector{Int64}:\n 1\n 2\n 3\n 4\n 5\n\njulia> collect(Iterators.takewhile(<(3),s))\n2-element Vector{Int64}:\n 1\n 2\n\n\n\n\n\n","category":"function"},{"location":"base/iterators/#Base.Iterators.drop","page":"迭代相关","title":"Base.Iterators.drop","text":"drop(iter, n)\n\nAn iterator that generates all but the first n elements of iter.\n\nExamples\n\njulia> a = 1:2:11\n1:2:11\n\njulia> collect(a)\n6-element Vector{Int64}:\n 1\n 3\n 5\n 7\n 9\n 11\n\njulia> collect(Iterators.drop(a,4))\n2-element Vector{Int64}:\n 9\n 11\n\n\n\n\n\n","category":"function"},{"location":"base/iterators/#Base.Iterators.dropwhile","page":"迭代相关","title":"Base.Iterators.dropwhile","text":"dropwhile(pred, iter)\n\nAn iterator that drops element from iter as long as predicate pred is true, afterwards, returns every element.\n\ncompat: Julia 1.4\nThis function requires at least Julia 1.4.\n\nExamples\n\njulia> s = collect(1:5)\n5-element Vector{Int64}:\n 1\n 2\n 3\n 4\n 5\n\njulia> collect(Iterators.dropwhile(<(3),s))\n3-element Vector{Int64}:\n 3\n 4\n 5\n\n\n\n\n\n","category":"function"},{"location":"base/iterators/#Base.Iterators.cycle","page":"迭代相关","title":"Base.Iterators.cycle","text":"cycle(iter)\n\nAn iterator that cycles through iter forever. If iter is empty, so is cycle(iter).\n\nSee also: Iterators.repeated, repeat.\n\nExamples\n\njulia> for (i, v) in enumerate(Iterators.cycle(\"hello\"))\n print(v)\n i > 10 && break\n end\nhellohelloh\n\n\n\n\n\n","category":"function"},{"location":"base/iterators/#Base.Iterators.repeated","page":"迭代相关","title":"Base.Iterators.repeated","text":"repeated(x[, n::Int])\n\nAn iterator that generates the value x forever. If n is specified, generates x that many times (equivalent to take(repeated(x), n)).\n\nSee also: Iterators.cycle, repeat.\n\nExamples\n\njulia> a = Iterators.repeated([1 2], 4);\n\njulia> collect(a)\n4-element Vector{Matrix{Int64}}:\n [1 2]\n [1 2]\n [1 2]\n [1 2]\n\n\n\n\n\n","category":"function"},{"location":"base/iterators/#Base.Iterators.product","page":"迭代相关","title":"Base.Iterators.product","text":"product(iters...)\n\nReturn an iterator over the product of several iterators. Each generated element is a tuple whose ith element comes from the ith argument iterator. The first iterator changes the fastest.\n\nSee also: zip, Iterators.flatten.\n\nExamples\n\njulia> collect(Iterators.product(1:2, 3:5))\n2×3 Matrix{Tuple{Int64, Int64}}:\n (1, 3) (1, 4) (1, 5)\n (2, 3) (2, 4) (2, 5)\n\njulia> ans == [(x,y) for x in 1:2, y in 3:5] # collects a generator involving Iterators.product\ntrue\n\n\n\n\n\n","category":"function"},{"location":"base/iterators/#Base.Iterators.flatten","page":"迭代相关","title":"Base.Iterators.flatten","text":"flatten(iter)\n\nGiven an iterator that yields iterators, return an iterator that yields the elements of those iterators. Put differently, the elements of the argument iterator are concatenated.\n\nExamples\n\njulia> collect(Iterators.flatten((1:2, 8:9)))\n4-element Vector{Int64}:\n 1\n 2\n 8\n 9\n\njulia> [(x,y) for x in 0:1 for y in 'a':'c'] # collects generators involving Iterators.flatten\n6-element Vector{Tuple{Int64, Char}}:\n (0, 'a')\n (0, 'b')\n (0, 'c')\n (1, 'a')\n (1, 'b')\n (1, 'c')\n\n\n\n\n\n","category":"function"},{"location":"base/iterators/#Base.Iterators.partition","page":"迭代相关","title":"Base.Iterators.partition","text":"partition(collection, n)\n\nIterate over a collection n elements at a time.\n\nExamples\n\njulia> collect(Iterators.partition([1,2,3,4,5], 2))\n3-element Vector{SubArray{Int64, 1, Vector{Int64}, Tuple{UnitRange{Int64}}, true}}:\n [1, 2]\n [3, 4]\n [5]\n\n\n\n\n\n","category":"function"},{"location":"base/iterators/#Base.Iterators.map","page":"迭代相关","title":"Base.Iterators.map","text":"Iterators.map(f, iterators...)\n\nCreate a lazy mapping. This is another syntax for writing (f(args...) for args in zip(iterators...)).\n\ncompat: Julia 1.6\nThis function requires at least Julia 1.6.\n\nExamples\n\njulia> collect(Iterators.map(x -> x^2, 1:3))\n3-element Vector{Int64}:\n 1\n 4\n 9\n\n\n\n\n\n","category":"function"},{"location":"base/iterators/#Base.Iterators.filter","page":"迭代相关","title":"Base.Iterators.filter","text":"Iterators.filter(flt, itr)\n\nGiven a predicate function flt and an iterable object itr, return an iterable object which upon iteration yields the elements x of itr that satisfy flt(x). The order of the original iterator is preserved.\n\nThis function is lazy; that is, it is guaranteed to return in Θ(1) time and use Θ(1) additional space, and flt will not be called by an invocation of filter. Calls to flt will be made when iterating over the returned iterable object. These calls are not cached and repeated calls will be made when reiterating.\n\nSee Base.filter for an eager implementation of filtering for arrays.\n\nExamples\n\njulia> f = Iterators.filter(isodd, [1, 2, 3, 4, 5])\nBase.Iterators.Filter{typeof(isodd), Vector{Int64}}(isodd, [1, 2, 3, 4, 5])\n\njulia> foreach(println, f)\n1\n3\n5\n\njulia> [x for x in [1, 2, 3, 4, 5] if isodd(x)] # collects a generator over Iterators.filter\n3-element Vector{Int64}:\n 1\n 3\n 5\n\n\n\n\n\n","category":"function"},{"location":"base/iterators/#Base.Iterators.accumulate","page":"迭代相关","title":"Base.Iterators.accumulate","text":"Iterators.accumulate(f, itr; [init])\n\nGiven a 2-argument function f and an iterator itr, return a new iterator that successively applies f to the previous value and the next element of itr.\n\nThis is effectively a lazy version of Base.accumulate.\n\ncompat: Julia 1.5\nKeyword argument init is added in Julia 1.5.\n\nExamples\n\njulia> a = Iterators.accumulate(+, [1,2,3,4]);\n\njulia> foreach(println, a)\n1\n3\n6\n10\n\njulia> b = Iterators.accumulate(/, (2, 5, 2, 5); init = 100);\n\njulia> collect(b)\n4-element Vector{Float64}:\n 50.0\n 10.0\n 5.0\n 1.0\n\n\n\n\n\n","category":"function"},{"location":"base/iterators/#Base.Iterators.reverse","page":"迭代相关","title":"Base.Iterators.reverse","text":"Iterators.reverse(itr)\n\nGiven an iterator itr, then reverse(itr) is an iterator over the same collection but in the reverse order.\n\nThis iterator is \"lazy\" in that it does not make a copy of the collection in order to reverse it; see Base.reverse for an eager implementation.\n\nNot all iterator types T support reverse-order iteration. If T doesn't, then iterating over Iterators.reverse(itr::T) will throw a MethodError because of the missing iterate methods for Iterators.Reverse{T}. (To implement these methods, the original iterator itr::T can be obtained from r = Iterators.reverse(itr) by r.itr.)\n\nExamples\n\njulia> foreach(println, Iterators.reverse(1:5))\n5\n4\n3\n2\n1\n\n\n\n\n\n","category":"function"},{"location":"base/iterators/#Base.Iterators.only","page":"迭代相关","title":"Base.Iterators.only","text":"only(x)\n\nReturn the one and only element of collection x, or throw an ArgumentError if the collection has zero or multiple elements.\n\nSee also first, last.\n\ncompat: Julia 1.4\nThis method requires at least Julia 1.4.\n\nExamples\n\njulia> only([\"a\"])\n\"a\"\n\njulia> only(\"a\")\n'a': ASCII/Unicode U+0061 (category Ll: Letter, lowercase)\n\njulia> only(())\nERROR: ArgumentError: Tuple contains 0 elements, must contain exactly 1 element\nStacktrace:\n[...]\n\njulia> only(('a', 'b'))\nERROR: ArgumentError: Tuple contains 2 elements, must contain exactly 1 element\nStacktrace:\n[...]\n\n\n\n\n\n","category":"function"},{"location":"base/iterators/#Base.Iterators.peel","page":"迭代相关","title":"Base.Iterators.peel","text":"peel(iter)\n\nReturns the first element and an iterator over the remaining elements.\n\nIf the iterator is empty return nothing (like iterate).\n\ncompat: Julia 1.7\nPrior versions throw a BoundsError if the iterator is empty.\n\nSee also: Iterators.drop, Iterators.take.\n\nExamples\n\njulia> (a, rest) = Iterators.peel(\"abc\");\n\njulia> a\n'a': ASCII/Unicode U+0061 (category Ll: Letter, lowercase)\n\njulia> collect(rest)\n2-element Vector{Char}:\n 'b': ASCII/Unicode U+0062 (category Ll: Letter, lowercase)\n 'c': ASCII/Unicode U+0063 (category Ll: Letter, lowercase)\n\n\n\n\n\n","category":"function"},{"location":"#Julia-1.7-中文文档","page":"主页","title":"Julia 1.7 中文文档","text":"","category":"section"},{"location":"","page":"主页","title":"主页","text":"欢迎来到 Julia 1.7 中文文档(PDF版本)!","category":"page"},{"location":"","page":"主页","title":"主页","text":"请先阅读 Julia 1.0 正式发布博文 以获得对这门语言的总体概观。我们推荐刚刚开始学习 Julia 语言的朋友阅读中文社区提供的 Julia入门指引,也推荐你在中文论坛对遇到的问题进行提问。","category":"page"},{"location":"","page":"主页","title":"主页","text":"tip: 镜像加速\n使用镜像站来加速下载几乎是每个国内用户都需要了解的事情,关于镜像站的使用说明及汇总可以在 Julia PkgServer 镜像服务及镜像站索引 中可以看到。","category":"page"},{"location":"","page":"主页","title":"主页","text":"note: 关于中文文档\nJulia 语言相关的本地化工作是一个由社区驱动的开源项目 JuliaZH.jl,旨在方便 Julia 的中文用户。我们目前使用 Transifex 作为翻译平台。翻译工作正在进行,有任何疑问或建议请到社区论坛文档区反馈。若有意参与翻译工作,请参考翻译指南。","category":"page"},{"location":"#鸣谢","page":"主页","title":"鸣谢","text":"","category":"section"},{"location":"","page":"主页","title":"主页","text":"\n\n","category":"page"},{"location":"","page":"主页","title":"主页","text":"特别感谢集智俱乐部对Julia中文文档和Julia中文论坛相关服务器资源的赞助!","category":"page"},{"location":"","page":"主页","title":"主页","text":"❤❤❤如果您或您所属的组织有意资助Julia中文社区的发展,欢迎前往论坛的社区板块发帖咨询。❤❤❤","category":"page"},{"location":"#其它中文资料","page":"主页","title":"其它中文资料","text":"","category":"section"},{"location":"","page":"主页","title":"主页","text":"Julia Data Science 中文版","category":"page"},{"location":"#man-introduction","page":"主页","title":"简介","text":"","category":"section"},{"location":"","page":"主页","title":"主页","text":"科学计算对性能一直有着最高的需求,但目前各领域的专家却大量使用较慢的动态语言来开展他们的日常工作。 偏爱动态语言有很多很好的理由,因此我们不会舍弃动态的特性。 幸运的是,现代编程语言设计与编译器技术可以大大消除性能折衷(trade-off),并提供有足够生产力的单一环境进行原型设计,而且能高效地部署性能密集型应用程序。 Julia 语言在这其中扮演了这样一个角色:它是一门灵活的动态语言,适合用于科学计算和数值计算,并且性能可与传统的静态类型语言媲美。","category":"page"},{"location":"","page":"主页","title":"主页","text":"由于 Julia 的编译器和其它语言比如 Python 或 R 的解释器有所不同,一开始你可能发现 Julia 的性能并不是很突出。 如果你觉得速度有点慢,我们强烈建议在尝试其他功能前,先读一读文档中的提高性能的窍门。 在理解了 Julia 的运作方式后,写出和 C 一样快的代码对你而言就是小菜一碟。","category":"page"},{"location":"","page":"主页","title":"主页","text":"Julia 拥有可选类型标注和多重派发这两个特性,同时还拥有很棒的性能。 这些都得归功于使用 LLVM 实现的类型推导和即时编译(JIT)技术。Julia 是一门支持过程式、函数式和面向对象的多范式语言。 它像 R、MATLAB 和 Python 一样简单,在高级数值计算方面有丰富的表现力,并且支持通用编程。 为了实现这个目标,Julia 以数学编程语言(mathematical programming languages)为基础,同时也参考了不少流行的动态语言,例如 Lisp、Perl、Python、Lua、和 Ruby。","category":"page"},{"location":"","page":"主页","title":"主页","text":"Julia 与传统动态语言最重要的区别是:","category":"page"},{"location":"","page":"主页","title":"主页","text":"核心语言很小:标准库是用 Julia 自身写的,包括整数运算这样的基础运算\n丰富的基础类型:既可用于定义和描述对象,也可用于做可选的类型标注\n通过多重派发,可以根据类型的不同,来调用同名函数的不同实现\n为不同的参数类型,自动生成高效、专用的代码\n接近 C 语言的性能","category":"page"},{"location":"","page":"主页","title":"主页","text":"尽管人们有时会说动态语言是“无类型的”,但实际上绝对不是这样的:每一个对象都有一个类型,无论它是基础的类型(primitive)还是用户自定义的类型。 大多数的动态语言都缺乏类型声明,这意味着程序员无法告诉编译器值的类型,也就无法显式地讨论类型。 另一方面,在静态语言中,往往必须标注对象的类型。但类型只在编译期才存在,而无法在运行时进行操作和表达。 而在 Julia 中,类型本身是运行时的对象,并可用于向编译器传达信息。","category":"page"},{"location":"","page":"主页","title":"主页","text":"类型系统和多重派发是 Julia 语言最主要的特征,但一般不需要显式地手动标注或使用:函数通过函数名称和不同类型参数的组合进行定义,在调用时会派发到最接近(most specific)的定义上去。这样的编程模型非常适合数学化的编程,尤其是在传统的面向对象派发中,一些函数的第一个变量理论上并不“拥有”这样一个操作时。 在 Julia 中运算符只是函数的一个特殊标记——例如,为用户定义的新类型添加加法运算,你只要为 + 函数定义一个新的方法就可以了。 已有的代码就可以无缝接入这个新的类型。","category":"page"},{"location":"","page":"主页","title":"主页","text":"Julia 在设计之初就非常看重性能,再加上它的动态类型推导(可以被可选的类型标注增强),使得 Julia 的计算性能超过了其它的动态语言,甚至能够与静态编译语言竞争。对于大型数值问题,速度一直都是,也一直会是一个重要的关注点:在过去的几十年里,需要处理的数据量很容易与摩尔定律保持同步。","category":"page"},{"location":"","page":"主页","title":"主页","text":"Julia 的目标是创建一个前所未有的集易用、强大、高效于一体的语言。除此之外,Julia 还拥有以下优势:","category":"page"},{"location":"","page":"主页","title":"主页","text":"采用 MIT 许可证:免费又开源\n用户自定义类型的速度与兼容性和内建类型一样好\n无需特意编写向量化的代码:非向量化的代码就很快\n为并行计算和分布式计算设计\n轻量级的“绿色”线程:协程\n低调又牛逼的类型系统\n优雅、可扩展的类型转换和类型提升\n对 Unicode 的有效支持,包括但不限于 UTF-8\n直接调用 C 函数,无需封装或调用特别的 API\n像 Shell 一样强大的管理其他进程的能力\n像 Lisp 一样的宏和其他元编程工具","category":"page"},{"location":"devdocs/isbitsunionarrays/#isbits-Union-Optimizations","page":"isbits Union Optimizations","title":"isbits Union Optimizations","text":"","category":"section"},{"location":"devdocs/isbitsunionarrays/","page":"isbits Union Optimizations","title":"isbits Union Optimizations","text":"In Julia, the Array type holds both \"bits\" values as well as heap-allocated \"boxed\" values. The distinction is whether the value itself is stored inline (in the direct allocated memory of the array), or if the memory of the array is simply a collection of pointers to objects allocated elsewhere. In terms of performance, accessing values inline is clearly an advantage over having to follow a pointer to the actual value. The definition of \"isbits\" generally means any Julia type with a fixed, determinate size, meaning no \"pointer\" fields, see ?isbitstype.","category":"page"},{"location":"devdocs/isbitsunionarrays/","page":"isbits Union Optimizations","title":"isbits Union Optimizations","text":"Julia also supports Union types, quite literally the union of a set of types. Custom Union type definitions can be extremely handy for applications wishing to \"cut across\" the nominal type system (i.e. explicit subtype relationships) and define methods or functionality on these, otherwise unrelated, set of types. A compiler challenge, however, is in determining how to treat these Union types. The naive approach (and indeed, what Julia itself did pre-0.7), is to simply make a \"box\" and then a pointer in the box to the actual value, similar to the previously mentioned \"boxed\" values. This is unfortunate, however, because of the number of small, primitive \"bits\" types (think UInt8, Int32, Float64, etc.) that would easily fit themselves inline in this \"box\" without needing any indirection for value access. There are two main ways Julia can take advantage of this optimization as of 0.7: isbits Union fields in types, and isbits Union Arrays.","category":"page"},{"location":"devdocs/isbitsunionarrays/#isbits-Union-Structs","page":"isbits Union Optimizations","title":"isbits Union Structs","text":"","category":"section"},{"location":"devdocs/isbitsunionarrays/","page":"isbits Union Optimizations","title":"isbits Union Optimizations","text":"Julia now includes an optimization wherein \"isbits Union\" fields in types (mutable struct, struct, etc.) will be stored inline. This is accomplished by determining the \"inline size\" of the Union type (e.g. Union{UInt8, Int16} will have a size of two bytes, which represents the size needed of the largest Union type Int16), and in addition, allocating an extra \"type tag byte\" (UInt8), whose value signals the type of the actual value stored inline of the \"Union bytes\". The type tag byte value is the index of the actual value's type in the Union type's order of types. For example, a type tag value of 0x02 for a field with type Union{Nothing, UInt8, Int16} would indicate that an Int16 value is stored in the 16 bits of the field in the structure's memory; a 0x01 value would indicate that a UInt8 value was stored in the first 8 bits of the 16 bits of the field's memory. Lastly, a value of 0x00 signals that the nothing value will be returned for this field, even though, as a singleton type with a single type instance, it technically has a size of 0. The type tag byte for a type's Union field is stored directly after the field's computed Union memory.","category":"page"},{"location":"devdocs/isbitsunionarrays/#isbits-Union-Arrays","page":"isbits Union Optimizations","title":"isbits Union Arrays","text":"","category":"section"},{"location":"devdocs/isbitsunionarrays/","page":"isbits Union Optimizations","title":"isbits Union Optimizations","text":"Julia can now also store \"isbits Union\" values inline in an Array, as opposed to requiring an indirection box. The optimization is accomplished by storing an extra \"type tag array\" of bytes, one byte per array element, alongside the bytes of the actual array data. This type tag array serves the same function as the type field case: its value signals the type of the actual stored Union value in the array. In terms of layout, a Julia Array can include extra \"buffer\" space before and after its actual data values, which are tracked in the a->offset and a->maxsize fields of the jl_array_t* type. The \"type tag array\" is treated exactly as another jl_array_t*, but which shares the same a->offset, a->maxsize, and a->len fields. So the formula to access an isbits Union Array's type tag bytes is a->data + (a->maxsize - a->offset) * a->elsize + a->offset; i.e. the Array's a->data pointer is already shifted by a->offset, so correcting for that, we follow the data all the way to the max of what it can hold a->maxsize, then adjust by a->offset more bytes to account for any present \"front buffering\" the array might be doing. This layout in particular allows for very efficient resizing operations as the type tag data only ever has to move when the actual array's data has to move.","category":"page"},{"location":"manual/environment-variables/#环境变量","page":"环境变量","title":"环境变量","text":"","category":"section"},{"location":"manual/environment-variables/","page":"环境变量","title":"环境变量","text":"Julia 可以配置许多环境变量,一种常见的方式是直接配置操作系统环境变量,另一种更便携的方式是在 Julia 中配置。假设你要将环境变量 JULIA_EDITOR 设置为 vim,可以直接在 REPL 中输入 ENV[\"JULIA_EDITOR\"] = \"vim\"(请根据具体情况对此进行修改),也可以将其添加到用户主目录中的配置文件 ~/.julia/config/startup.jl,这样做会使其永久生效。环境变量的当前值是通过执行 ENV[\"JULIA_EDITOR\"] 来确定的。","category":"page"},{"location":"manual/environment-variables/","page":"环境变量","title":"环境变量","text":"Julia 使用的环境变量通常以 JULIA 开头。如果调用 InteractiveUtils.versioninfo 时使用关键字参数 verbose = true,那么输出结果将列出与 Julia 相关的已定义环境变量,即包括那些名称中包含 JULIA 的环境变量。","category":"page"},{"location":"manual/environment-variables/","page":"环境变量","title":"环境变量","text":"note: Note\n某些变量需要在 Julia 启动之前设置,比如 JULIA_NUM_THREADS 和 JULIA_PROJECT,因为在启动过程中将这些变量添加到 ~/.julia/config/startup.jl 中为时已晚。在 Bash 中,环境变量可以手动设置,这可通过在 Julia 启动前运行诸如 export JULIA_NUM_THREADS=4 的命令,亦可通过向 ~/.bashrc 或 ~/.bash_profile 添加相同命令来在 Bash 每次启动时设置该变量。","category":"page"},{"location":"manual/environment-variables/#文件位置","page":"环境变量","title":"文件位置","text":"","category":"section"},{"location":"manual/environment-variables/#JULIA_BINDIR","page":"环境变量","title":"JULIA_BINDIR","text":"","category":"section"},{"location":"manual/environment-variables/","page":"环境变量","title":"环境变量","text":"包含 Julia 可执行文件的目录的绝对路径,它会设置全局变量 Sys.BINDIR。$JULIA_BINDIR 如果没有设置,那么 Julia 会在运行时确定 Sys.BINDIR 的值。","category":"page"},{"location":"manual/environment-variables/","page":"环境变量","title":"环境变量","text":"在默认情况下,可执行文件是指:","category":"page"},{"location":"manual/environment-variables/","page":"环境变量","title":"环境变量","text":"$JULIA_BINDIR/julia\n$JULIA_BINDIR/julia-debug","category":"page"},{"location":"manual/environment-variables/","page":"环境变量","title":"环境变量","text":"全局变量 Base.DATAROOTDIR 是一个从 Sys.BINDIR 到 Julia 数据目录的相对路径。","category":"page"},{"location":"manual/environment-variables/","page":"环境变量","title":"环境变量","text":"$JULIA_BINDIR/$DATAROOTDIR/julia/base","category":"page"},{"location":"manual/environment-variables/","page":"环境变量","title":"环境变量","text":"上述路径是 Julia 最初搜索源文件的路径(通过 Base.find_source_file())。","category":"page"},{"location":"manual/environment-variables/","page":"环境变量","title":"环境变量","text":"同样,全局变量 Base.SYSCONFDIR 是一个到配置文件目录的相对路径。在默认情况下,Julia 会在下列文件中搜索 startup.jl 文件(通过 Base.load_julia_startup())","category":"page"},{"location":"manual/environment-variables/","page":"环境变量","title":"环境变量","text":"$JULIA_BINDIR/$SYSCONFDIR/julia/startup.jl\n$JULIA_BINDIR/../etc/julia/startup.jl","category":"page"},{"location":"manual/environment-variables/","page":"环境变量","title":"环境变量","text":"例如,在 Linux 下安装的 Julia 可执行文件位于 /bin/julia,DATAROOTDIR 为 ../share,SYSCONFDIR 为 ../etc,JULIA_BINDIR 会被设置为 /bin,会有一个源文件搜索路径:","category":"page"},{"location":"manual/environment-variables/","page":"环境变量","title":"环境变量","text":"/share/julia/base","category":"page"},{"location":"manual/environment-variables/","page":"环境变量","title":"环境变量","text":"和一个全局配置文件搜索路径:","category":"page"},{"location":"manual/environment-variables/","page":"环境变量","title":"环境变量","text":"/etc/julia/startup.jl","category":"page"},{"location":"manual/environment-variables/#JULIA_PROJECT","page":"环境变量","title":"JULIA_PROJECT","text":"","category":"section"},{"location":"manual/environment-variables/","page":"环境变量","title":"环境变量","text":"指示哪个项目应该是初始活动项目的目录路径。 设置这个环境变量和指定--project启动选项效果一样,但是--project优先级更高。 如果变量设置为 @.,那么 Julia 会尝试从当前目录及其父目录中查找包含 Project.toml 或 JuliaProject.toml 文件的项目目录。 另请参阅有关 代码加载 的章节。","category":"page"},{"location":"manual/environment-variables/","page":"环境变量","title":"环境变量","text":"note: Note\nJULIA_PROJECT 必须在启动 julia 前定义;于 startup.jl 中定义它对于启动的过程为时已晚。","category":"page"},{"location":"manual/environment-variables/#JULIA_LOAD_PATH","page":"环境变量","title":"JULIA_LOAD_PATH","text":"","category":"section"},{"location":"manual/environment-variables/","page":"环境变量","title":"环境变量","text":"JULIA_LOAD_PATH 环境变量用于补充全局的 Julia 变量 LOAD_PATH ,该变量可用于确定通过 import 和 using 可以加载哪些包(请参阅 Code Loading)。","category":"page"},{"location":"manual/environment-variables/","page":"环境变量","title":"环境变量","text":"与 shell 使用的 PATH 变量不同, 在 JULIA_LOAD_PATH 中的空条目将会在填充 LOAD_PATH 时被扩展为 LOAD_PATH 的默认值 [\"@\", \"@v#.#\", \"@stdlib\"] 。这样,无论 JULIA_LOAD_PATH 是否已被设置,均可以使用 shell 脚本轻松地在加载路径前面或后面添加值。例如要将 /foo/bar 添加到 LOAD_PATH 之前,只需要使用下列脚本:","category":"page"},{"location":"manual/environment-variables/","page":"环境变量","title":"环境变量","text":"export JULIA_LOAD_PATH=\"/foo/bar:$JULIA_LOAD_PATH\"","category":"page"},{"location":"manual/environment-variables/","page":"环境变量","title":"环境变量","text":"如果已经设置了 JULIA_LOAD_PATH 环境变量,那么 /foo/bar 将被添加在原有值之前。另一方面,如果 JULIA_LOAD_PATH 尚未设置,那么它会被设置为 /foo/bar: ,而这将使用 LOAD_PATH 的值扩展为 [\"/foo/bar\", \"@\", \"@v#.#\", \"@stdlib\"] 。如果 JULIA_LOAD_PATH 被设置为空字符串,那么它将被扩展为一个空的 LOAD_PATH 数组。换句话说,这个空字符串数组将被认为是零元素的数组,而非是一个空字符串单元素的数组。使用这样的加载行为是为了可以通过环境变量设置空的加载路径。如果你需要使用默认的加载路径,请不要设置这一环境变量,如果它必须有值,那么可将其设置为字符串 : 。","category":"page"},{"location":"manual/environment-variables/","page":"环境变量","title":"环境变量","text":"note: Note\n在 Windows 上,路径元素由 ; 字符分隔,就像 Windows 上的大多数路径列表一样。 将上一段中的 : 替换为 ;。","category":"page"},{"location":"manual/environment-variables/#JULIA_DEPOT_PATH","page":"环境变量","title":"JULIA_DEPOT_PATH","text":"","category":"section"},{"location":"manual/environment-variables/","page":"环境变量","title":"环境变量","text":"JULIA_DEPOT_PATH 环境变量用于填充全局的 Julia 变量 DEPOT_PATH ,该变量用于控制包管理器以及 Juila 代码加载机制在何处查找包注册表、已安装的包、命名环境、克隆的存储库、缓存的预编译包映像、配置文件和 REPL 历史记录文件的默认位置。","category":"page"},{"location":"manual/environment-variables/","page":"环境变量","title":"环境变量","text":"与 shell 使用的 PATH 变量不同,但与 JULIA_LOAD_PATH 类似, 在 JULIA_DEPOT_PATH 中的空条目将会被扩展为 DEPOT_PATH 的默认值。这样,无论 JULIA_DEPOT_PATH 是否已被设置,均可以使用 shell 脚本轻松地在仓库路径前面或后面添加值。例如要将 /foo/bar 添加到 DEPOT_PATH 之前,只需要使用下列脚本:","category":"page"},{"location":"manual/environment-variables/","page":"环境变量","title":"环境变量","text":"export JULIA_DEPOT_PATH=\"/foo/bar:$JULIA_DEPOT_PATH\"","category":"page"},{"location":"manual/environment-variables/","page":"环境变量","title":"环境变量","text":"如果已经设置了 JULIA_DEPOT_PATH 环境变量,那么 /foo/bar 将被添加在原有值之前。另一方面,如果 JULIA_DEPOT_PATH 尚未设置,那么它会被设置为 /foo/bar: ,而这将使 /foo/bar 被添加到默认仓库路径之前。如果 JULIA_DEPOT_PATH 被设置为空字符串,那么它将扩展为一个空的 DEPOT_PATH 数组。换句话说,这个空字符串数组将被认为是零元素的数组,而非是一个空字符串单元素的数组。使用这样的加载行为是为了可以通过环境变量设置空的仓库路径。如果你需要使用默认的仓库路径,请不要设置这一环境变量,如果它必须有值,那么可将其设置为字符串 : 。","category":"page"},{"location":"manual/environment-variables/","page":"环境变量","title":"环境变量","text":"note: Note\n在 Windows 上,路径元素由 ; 字符分隔,就像 Windows 上的大多数路径列表一样。 将上一段中的 : 替换为 ;。","category":"page"},{"location":"manual/environment-variables/#JULIA_HISTORY","page":"环境变量","title":"JULIA_HISTORY","text":"","category":"section"},{"location":"manual/environment-variables/","page":"环境变量","title":"环境变量","text":"REPL 历史文件中 REPL.find_hist_file() 的绝对路径。如果没有设置 $JULIA_HISTORY,那么 REPL.find_hist_file() 默认为","category":"page"},{"location":"manual/environment-variables/","page":"环境变量","title":"环境变量","text":"$(DEPOT_PATH[1])/logs/repl_history.jl","category":"page"},{"location":"manual/environment-variables/#JULIA_PKG_SERVER","page":"环境变量","title":"JULIA_PKG_SERVER","text":"","category":"section"},{"location":"manual/environment-variables/","page":"环境变量","title":"环境变量","text":"由Pkg.jl 使用,用于下载软件包和更新注册表。默认情况下,Pkg 使用 https://pkg.julialang.org 来获取 Julia 包。你可以使用此环境变量来选择不同的服务器。 此外,你可以禁用 PkgServer 协议的使用,并通过设置直接从它们的主机(GitHub、GitLab 等)访问包:","category":"page"},{"location":"manual/environment-variables/","page":"环境变量","title":"环境变量","text":"export JULIA_PKG_SERVER=\"\"","category":"page"},{"location":"manual/environment-variables/#外部应用","page":"环境变量","title":"外部应用","text":"","category":"section"},{"location":"manual/environment-variables/#JULIA_SHELL","page":"环境变量","title":"JULIA_SHELL","text":"","category":"section"},{"location":"manual/environment-variables/","page":"环境变量","title":"环境变量","text":"Julia 用来执行外部命令的 shell 的绝对路径(通过 Base.repl_cmd())。默认为环境变量 $SHELL,如果 $SHELL 未设置,则为 /bin/sh。","category":"page"},{"location":"manual/environment-variables/","page":"环境变量","title":"环境变量","text":"note: Note\n在 Windows 上,此环境变量将被忽略,并且外部命令会直接被执行。","category":"page"},{"location":"manual/environment-variables/#JULIA_EDITOR","page":"环境变量","title":"JULIA_EDITOR","text":"","category":"section"},{"location":"manual/environment-variables/","page":"环境变量","title":"环境变量","text":"InteractiveUtils.editor() 的返回值–编辑器,例如,InteractiveUtils.edit,会启动偏好编辑器,比如 vim。","category":"page"},{"location":"manual/environment-variables/","page":"环境变量","title":"环境变量","text":"$JULIA_EDITOR 优先于 $VISUAL,而后者优先于 $EDITOR。如果这些环境变量都没有设置,那么在 Windows 和 OS X 上会设置为 open,或者 /etc/alternatives/editor(如果存在的话),否则为 emacs。","category":"page"},{"location":"manual/environment-variables/#并行","page":"环境变量","title":"并行","text":"","category":"section"},{"location":"manual/environment-variables/#JULIA_CPU_THREADS","page":"环境变量","title":"JULIA_CPU_THREADS","text":"","category":"section"},{"location":"manual/environment-variables/","page":"环境变量","title":"环境变量","text":"改写全局变量 Base.Sys.CPU_THREADS,逻辑 CPU 核心数。","category":"page"},{"location":"manual/environment-variables/#JULIA_WORKER_TIMEOUT","page":"环境变量","title":"JULIA_WORKER_TIMEOUT","text":"","category":"section"},{"location":"manual/environment-variables/","page":"环境变量","title":"环境变量","text":"一个 Float64 值,用来确定 Distributed.worker_timeout() 的值(默认:60.0)。此函数提供 worker 进程在死亡之前等待 master 进程建立连接的秒数。","category":"page"},{"location":"manual/environment-variables/#JULIA_NUM_THREADS","page":"环境变量","title":"JULIA_NUM_THREADS","text":"","category":"section"},{"location":"manual/environment-variables/","page":"环境变量","title":"环境变量","text":"一个无符号 64 位整数 (uint64_t),用于设置 Julia 可用的最大线程数。 如果$JULIA_NUM_THREADS 不为正数或未设置,或者无法通过系统调用确定CPU 线程数,则将线程数设置为1。","category":"page"},{"location":"manual/environment-variables/","page":"环境变量","title":"环境变量","text":"如果$JULIA_NUM_THREADS 设置为auto,则线程数将设置为CPU线程数。","category":"page"},{"location":"manual/environment-variables/","page":"环境变量","title":"环境变量","text":"note: Note\nJULIA_NUM_THREADS 必须在启动 julia 之前定义; 启动过程中在startup.jl 中定义它是不能奏效的。","category":"page"},{"location":"manual/environment-variables/","page":"环境变量","title":"环境变量","text":"compat: Julia 1.5\n在 Julia 1.5 和更高版本中,也可在启动时使用 -t/--threads 命令行参数指定线程数。","category":"page"},{"location":"manual/environment-variables/","page":"环境变量","title":"环境变量","text":"compat: Julia 1.7\n$JULIA_NUM_THREADS 的 auto 值需要 Julia 1.7 或更高版本。","category":"page"},{"location":"manual/environment-variables/#JULIA_THREAD_SLEEP_THRESHOLD","page":"环境变量","title":"JULIA_THREAD_SLEEP_THRESHOLD","text":"","category":"section"},{"location":"manual/environment-variables/","page":"环境变量","title":"环境变量","text":"如果被设置为字符串,并且以大小写敏感的子字符串 \"infinite\" 开头,那么自旋线程从不睡眠。否则,$JULIA_THREAD_SLEEP_THRESHOLD 被解释为一个无符号 64 位整数(uint64_t),并且提供以纳秒为单位的自旋线程睡眠的时间量。","category":"page"},{"location":"manual/environment-variables/#JULIA_EXCLUSIVE","page":"环境变量","title":"JULIA_EXCLUSIVE","text":"","category":"section"},{"location":"manual/environment-variables/","page":"环境变量","title":"环境变量","text":"如果设置为 0 以外的任何值,那么 Julia 的线程策略与在专用计算机上一致:主线程在 proc 0 上且线程间是关联的。否则,Julia 让操作系统处理线程策略。","category":"page"},{"location":"manual/environment-variables/#REPL-格式化输出","page":"环境变量","title":"REPL 格式化输出","text":"","category":"section"},{"location":"manual/environment-variables/","page":"环境变量","title":"环境变量","text":"决定 REPL 应当如何格式化输出的环境变量。通常,这些变量应当被设置为 ANSI 终端转义序列。Julia 提供了具有相同功能的高级接口;请参阅 Julia REPL 章节。","category":"page"},{"location":"manual/environment-variables/#JULIA_ERROR_COLOR","page":"环境变量","title":"JULIA_ERROR_COLOR","text":"","category":"section"},{"location":"manual/environment-variables/","page":"环境变量","title":"环境变量","text":"Base.error_color()(默认值:亮红,\"\\033[91m\"),errors 在终端中的格式。","category":"page"},{"location":"manual/environment-variables/#JULIA_WARN_COLOR","page":"环境变量","title":"JULIA_WARN_COLOR","text":"","category":"section"},{"location":"manual/environment-variables/","page":"环境变量","title":"环境变量","text":"Base.warn_color()(默认值:黄,\"\\033[93m\"),warnings 在终端中的格式。","category":"page"},{"location":"manual/environment-variables/#JULIA_INFO_COLOR","page":"环境变量","title":"JULIA_INFO_COLOR","text":"","category":"section"},{"location":"manual/environment-variables/","page":"环境变量","title":"环境变量","text":"Base.info_color()(默认值:青,\"\\033[36m\"),info 在终端中的格式。","category":"page"},{"location":"manual/environment-variables/#JULIA_INPUT_COLOR","page":"环境变量","title":"JULIA_INPUT_COLOR","text":"","category":"section"},{"location":"manual/environment-variables/","page":"环境变量","title":"环境变量","text":"Base.input_color()(默认值:标准,\"\\033[0m\"),在终端中,输入应有的格式。","category":"page"},{"location":"manual/environment-variables/#JULIA_ANSWER_COLOR","page":"环境变量","title":"JULIA_ANSWER_COLOR","text":"","category":"section"},{"location":"manual/environment-variables/","page":"环境变量","title":"环境变量","text":"Base.answer_color()(默认值:标准,\"\\033[0m\"),在终端中,输出应有的格式。","category":"page"},{"location":"manual/environment-variables/#调试和性能分析","page":"环境变量","title":"调试和性能分析","text":"","category":"section"},{"location":"manual/environment-variables/#JULIA_DEBUG","page":"环境变量","title":"JULIA_DEBUG","text":"","category":"section"},{"location":"manual/environment-variables/","page":"环境变量","title":"环境变量","text":"为文件或模块启动调试日志记录,请参阅 日志 了解更多信息。","category":"page"},{"location":"manual/environment-variables/#JULIA_GC_ALLOC_POOL,-JULIA_GC_ALLOC_OTHER,-JULIA_GC_ALLOC_PRINT","page":"环境变量","title":"JULIA_GC_ALLOC_POOL, JULIA_GC_ALLOC_OTHER, JULIA_GC_ALLOC_PRINT","text":"","category":"section"},{"location":"manual/environment-variables/","page":"环境变量","title":"环境变量","text":"这些环境变量取值为字符串,可以以字符 ‘r’ 开头,后接一个由三个带符号 64 位整数(int64_t)组成的、以冒号分割的列表的插值字符串。这个整数的三元组 a:b:c 代表算术序列 a, a + b, a + 2*b, ... c。","category":"page"},{"location":"manual/environment-variables/","page":"环境变量","title":"环境变量","text":"如果是第 n 次调用 jl_gc_pool_alloc(),并且 n 属于 $JULIA_GC_ALLOC_POOL 代表的算术序列, 那么垃圾回收是强制的。\n如果是第 n 次调用 maybe_collect(),并且 n 属于 $JULIA_GC_ALLOC_OTHER 代表的算术序列,那么垃圾 回收是强制的。\n如果是第 n 次调用 jl_gc_alloc(),并且 n 属于 $JULIA_GC_ALLOC_PRINT 代表的算术序列,那么 调用 jl_gc_pool_alloc() 和 maybe_collect() 的次数会 被打印。","category":"page"},{"location":"manual/environment-variables/","page":"环境变量","title":"环境变量","text":"如果这些环境变量的值以字符 ‘r' 开头,那么垃圾回收事件间的间隔是随机的。","category":"page"},{"location":"manual/environment-variables/","page":"环境变量","title":"环境变量","text":"note: Note\n这些环境变量生效要求 Julia 在编译时带有垃圾收集调试支持(也就是,在构建配置中将 WITH_GC_DEBUG_ENV 设置为 1)。","category":"page"},{"location":"manual/environment-variables/#JULIA_GC_NO_GENERATIONAL","page":"环境变量","title":"JULIA_GC_NO_GENERATIONAL","text":"","category":"section"},{"location":"manual/environment-variables/","page":"环境变量","title":"环境变量","text":"如果设置为 0 以外的任何值,那么 Julia 的垃圾收集器将从不执行「快速扫描」内存。","category":"page"},{"location":"manual/environment-variables/","page":"环境变量","title":"环境变量","text":"note: Note\n此环境变量生效要求 Julia 在编译时带有垃圾收集调试支持(也就是,在构建配置中将 WITH_GC_DEBUG_ENV 设置为 1)。","category":"page"},{"location":"manual/environment-variables/#JULIA_GC_WAIT_FOR_DEBUGGER","page":"环境变量","title":"JULIA_GC_WAIT_FOR_DEBUGGER","text":"","category":"section"},{"location":"manual/environment-variables/","page":"环境变量","title":"环境变量","text":"如果设置为 0 以外的任何值,Julia 的垃圾收集器每当出现严重错误时将等待调试器连接而不是中止。","category":"page"},{"location":"manual/environment-variables/","page":"环境变量","title":"环境变量","text":"note: Note\n此环境变量生效要求 Julia 在编译时带有垃圾收集调试支持(也就是,在构建配置中将 WITH_GC_DEBUG_ENV 设置为 1)。","category":"page"},{"location":"manual/environment-variables/#ENABLE_JITPROFILING","page":"环境变量","title":"ENABLE_JITPROFILING","text":"","category":"section"},{"location":"manual/environment-variables/","page":"环境变量","title":"环境变量","text":"如果设置为 0 以外的任何值,那么编译器将为即时(JIT)性能分析创建并注册一个事件监听器。","category":"page"},{"location":"manual/environment-variables/","page":"环境变量","title":"环境变量","text":"note: Note\n此环境变量仅在使用 JIT 性能分析支持编译 Julia 时有效,使用如下之一:Intel's VTune™ Amplifier(USE_INTEL_JITEVENTS 在配置中设置为1), 或\nOProfile(USE_OPROFILE_JITEVENTS 在配置中设置为1)。\nPerf (USE_PERF_JITEVENTS 在构建配置中设置为 1)。 默认情况下启用此集成。","category":"page"},{"location":"manual/environment-variables/#ENABLE_GDBLISTENER","page":"环境变量","title":"ENABLE_GDBLISTENER","text":"","category":"section"},{"location":"manual/environment-variables/","page":"环境变量","title":"环境变量","text":"如果设置为除0之外的任何内容,则在发布版本上启用 Julia 代码的 GDB 注册。 在 Julia 的调试版本中,这始终处于启用状态。 推荐与 -g 2 一起使用。","category":"page"},{"location":"manual/environment-variables/#JULIA_LLVM_ARGS","page":"环境变量","title":"JULIA_LLVM_ARGS","text":"","category":"section"},{"location":"manual/environment-variables/","page":"环境变量","title":"环境变量","text":"传递给 LLVM 后端的参数。","category":"page"},{"location":"manual/faq/#常见问题","page":"常见问题","title":"常见问题","text":"","category":"section"},{"location":"manual/faq/#概述","page":"常见问题","title":"概述","text":"","category":"section"},{"location":"manual/faq/#Julia-的名字来源于某人或某事物吗?","page":"常见问题","title":"Julia 的名字来源于某人或某事物吗?","text":"","category":"section"},{"location":"manual/faq/","page":"常见问题","title":"常见问题","text":"不。","category":"page"},{"location":"manual/faq/#为什么不把-Matlab/Python/R-或者其他语言的代码编译为-Julia-呢?","page":"常见问题","title":"为什么不把 Matlab/Python/R 或者其他语言的代码编译为 Julia 呢?","text":"","category":"section"},{"location":"manual/faq/","page":"常见问题","title":"常见问题","text":"由于大多数人对其他动态语言的语法很熟悉,而且已经在这些动态语言中编写了很多代码,人们也许会问:为什么我们不直接设计以Julia为后端的Matlab或是Python前端(也就是把其他代码“转译”到Julia)?这样既能获得Julia的高性能,也能避免程序员花费精力来学一门新的语言。这是一个简单的解决方案,不是吗?","category":"page"},{"location":"manual/faq/","page":"常见问题","title":"常见问题","text":"总的来说,我们这样做是因为 Julia 编译器没有什么特别之处:我们使用的是普通的编译器(LLVM),这里面没有什么其他语言开发者所不知道的“独家秘方”。诚然,Julia编译器在许多地方比其他动态语言的编译器更简单(比如 PyPy 和 LuaJIT)。Julia 的性能优势几乎完全来自其前端:它的语义学使得 高质量的 Julia 程序 能够给予编译器更多的机会来产生高效的代码和内存结构。如果你尝试将 Matlab 或 Python 代码编译为 Julia,我们的编译器会被其语义学限制而不能产生相对现有编译器更好的代码(甚至更差)。语义学的关键角色也正是一些现存的 Python 编译器(像 Numba 和 Pythran)仅仅尝试优化语言的一小部分(比如 Numpy 的矢量与标量运算)的原因,而这些部分已经至少在相同的语义学上与我们做的一样好。致力于这些项目的人员难以置信得聪明并且已经取得了令人惊叹的成就,但为被解释而设计的语言加装编译器是十分困难的。","category":"page"},{"location":"manual/faq/","page":"常见问题","title":"常见问题","text":"Julia 的优势在于好的性能不止被限制在一小部分的内置类型与操作,用户能够写出使用任意自定义类型的高级泛型代码,同时也能保证很高的运行与内存效率。在如 Python 一般的语言中,类型没有给编译器提供太多的信息来达成这样的目的,当你试图像使用 Julia 前端一样使用这些语言时,你会遇到困难。","category":"page"},{"location":"manual/faq/","page":"常见问题","title":"常见问题","text":"出于类似的原因,自动翻译为 Julia 的代码一般来说会是可读性差、缓慢且违反习惯的代码。这些代码不是从其他语言迁移到 Julia 的好的起点。","category":"page"},{"location":"manual/faq/","page":"常见问题","title":"常见问题","text":"另一方面,语言可迁移性是极其有用的:我们会在一些时候想要将其他语言的高质量代码迁移到 Julia 中(也可能相反)。这一工作的最佳实践不是翻译器,而是使用简单的跨语言调用。我们对此有许多工作,从内置的 ccall (来调用 C 和 Fortran 模块)到JuliaInterop 包来链接 Julia 和 Python、Matlab、C++ 以及更多语言。","category":"page"},{"location":"manual/faq/#man-api","page":"常见问题","title":"公共 API","text":"","category":"section"},{"location":"manual/faq/#Julia-如何定义其公共-API?","page":"常见问题","title":"Julia 如何定义其公共 API?","text":"","category":"section"},{"location":"manual/faq/","page":"常见问题","title":"常见问题","text":"对于 julia 版本的 SemVer,唯一稳定的接口是 Julia 的 Base 和 文档 中的标准库接口中且未标记为不稳定(例如,实验性的和内部性的)的部分。 如果函数、类型和常量未包含在文档中,则它们不是公共 API 的一部分,即使它们具有文档。","category":"page"},{"location":"manual/faq/#有一个有用的非官方的函数/类型/常量。我可以使用它吗?","page":"常见问题","title":"有一个有用的非官方的函数/类型/常量。我可以使用它吗?","text":"","category":"section"},{"location":"manual/faq/","page":"常见问题","title":"常见问题","text":"如果您使用非公共 API,更新 Julia 可能会使你的代码失效。 如果代码是自洽的,最好将其复制到你的项目中。 如果你想依赖一个复杂的非公共 API,尤其是从稳定的包中使用它时,最好打开发起 issue 或 pull request 开始讨论将其转换为公共 API。 尽管你可以在下游自己开发一个包来封装这个内部实现,并且屏蔽不同的 Julia 版本差异,但我们并不鼓励这样做。","category":"page"},{"location":"manual/faq/#文档不够准确。-我可以依赖现有的行为吗?","page":"常见问题","title":"文档不够准确。 我可以依赖现有的行为吗?","text":"","category":"section"},{"location":"manual/faq/","page":"常见问题","title":"常见问题","text":"请发起一个 issue 或 pull request 开始讨论将现有行为转换为公共 API。","category":"page"},{"location":"manual/faq/#会话和-REPL","page":"常见问题","title":"会话和 REPL","text":"","category":"section"},{"location":"manual/faq/#如何从内存中删除某个对象?","page":"常见问题","title":"如何从内存中删除某个对象?","text":"","category":"section"},{"location":"manual/faq/","page":"常见问题","title":"常见问题","text":"Julia 没有类似于 MATLAB 的 clear 函数,某个名称一旦定义在 Julia 的会话中(准确地说,在 Main 模块中),它就会一直存在下去。","category":"page"},{"location":"manual/faq/","page":"常见问题","title":"常见问题","text":"如果关心内存使用情况,你可以用消耗较少内存的对象替换原对象。 例如,如果 A 是一个你不再需要的千兆字节大小的数组,你可以使用 A = nothing 来释放内存。 下次垃圾收集器运行时会释放内存; 您可以使用 GC.gc() 强制执行此操作。 此外,尝试使用 A 可能会导致错误,因为大多数方法都没有在类型 Nothing 上定义。","category":"page"},{"location":"manual/faq/#如何在会话中修改某个类型的声明?","page":"常见问题","title":"如何在会话中修改某个类型的声明?","text":"","category":"section"},{"location":"manual/faq/","page":"常见问题","title":"常见问题","text":"也许你定义了某个类型,后来发现需要向其中增加一个新的域。如果在 REPL 中尝试这样做,会得到一个错误:","category":"page"},{"location":"manual/faq/","page":"常见问题","title":"常见问题","text":"ERROR: invalid redefinition of constant MyType","category":"page"},{"location":"manual/faq/","page":"常见问题","title":"常见问题","text":"模块 Main 中的类型不能重新定义。","category":"page"},{"location":"manual/faq/","page":"常见问题","title":"常见问题","text":"尽管这在开发新代码时会造成不便,但是这个问题仍然有一个不错的解决办法:可以用重新定义的模块替换原有的模块,把所有新代码封装在一个模块里,这样就能重新定义类型和常量了。虽说不能将类型名称导入到 Main 模块中再去重新定义,但是可以用模块名来改变作用范围。换言之,开发时的工作流可能类似这样:","category":"page"},{"location":"manual/faq/","page":"常见问题","title":"常见问题","text":"include(\"mynewcode.jl\") # this defines a module MyModule\nobj1 = MyModule.ObjConstructor(a, b)\nobj2 = MyModule.somefunction(obj1)\n# Got an error. Change something in \"mynewcode.jl\"\ninclude(\"mynewcode.jl\") # reload the module\nobj1 = MyModule.ObjConstructor(a, b) # old objects are no longer valid, must reconstruct\nobj2 = MyModule.somefunction(obj1) # this time it worked!\nobj3 = MyModule.someotherfunction(obj2, c)\n...","category":"page"},{"location":"manual/faq/#man-scripting","page":"常见问题","title":"脚本","text":"","category":"section"},{"location":"manual/faq/#该如何检查当前文件是否正在以主脚本运行?","page":"常见问题","title":"该如何检查当前文件是否正在以主脚本运行?","text":"","category":"section"},{"location":"manual/faq/","page":"常见问题","title":"常见问题","text":"当一个文件通过使用 julia file.jl 来当做主脚本运行时,有人也希望激活另外的功能例如命令行参数操作。确定文件是以这个方式运行的一个方法是检查 abspath(PROGRAM_FILE) == @__FILE__ 是不是 true。","category":"page"},{"location":"manual/faq/#catch-ctrl-c","page":"常见问题","title":"怎样在脚本中捕获 CTRL-C ?","text":"","category":"section"},{"location":"manual/faq/","page":"常见问题","title":"常见问题","text":"通过 julia file.jl 方式运行的 Julia 脚本,在你尝试按 CTRL-C (SIGINT) 中止它时,并不会抛出 InterruptException。如果希望在脚本终止之后运行一些代码,请使用 atexit,注意:脚本的中止不一定是由 CTRL-C 导致的。 另外你也可以通过 julia -e 'include(popfirst!(ARGS))' file.jl 命令运行脚本,然后可以通过 try 捕获 InterruptException。","category":"page"},{"location":"manual/faq/#怎样通过-#!/usr/bin/env-传递参数给-julia?","page":"常见问题","title":"怎样通过 #!/usr/bin/env 传递参数给 julia?","text":"","category":"section"},{"location":"manual/faq/","page":"常见问题","title":"常见问题","text":"通过类似 #!/usr/bin/env julia --startup-file=no 的方式,使用 shebang 传递选项给 Julia 的方法,可能在像 Linux 这样的平台上无法正常工作。这是因为各平台上 shebang 的参数解析是平台相关的,并且尚未标准化。 在类 Unix 的环境中,可以通过以 bash 脚本作为可执行脚本的开头,并使用 exec 代替给 julia 传递选项的过程,来可靠的为 julia 传递选项。","category":"page"},{"location":"manual/faq/","page":"常见问题","title":"常见问题","text":"#!/bin/bash\n#=\nexec julia --color=yes --startup-file=no \"${BASH_SOURCE[0]}\" \"$@\"\n=#\n\n@show ARGS # put any Julia code here","category":"page"},{"location":"manual/faq/","page":"常见问题","title":"常见问题","text":"在以上例子中,位于 #= 和 =# 之间的代码可以当作一个 bash 脚本。 因为这些代码放在 Julia 的多行注释中,所以 Julia 会忽略它们。 在 =# 之后的 Julia 代码会被 bash 忽略,J因为当文件解析到 exec 语句时会停止解析,开始执行命令。","category":"page"},{"location":"manual/faq/","page":"常见问题","title":"常见问题","text":"note: Note\n为了在脚本中捕获 catch CTRL-C ,我们可以使用#!/bin/bash\n#=\nexec julia --color=yes --startup-file=no -e 'include(popfirst!(ARGS))' \\\n \"${BASH_SOURCE[0]}\" \"$@\"\n=#\n\n@show ARGS # put any Julia code hereinstead. Note that with this strategy PROGRAM_FILE will not be set.","category":"page"},{"location":"manual/faq/#函数","page":"常见问题","title":"函数","text":"","category":"section"},{"location":"manual/faq/#向函数传递了参数-x,在函数中做了修改,但是在函数外变量-x-的值还是没有变。为什么?","page":"常见问题","title":"向函数传递了参数 x,在函数中做了修改,但是在函数外变量 x 的值还是没有变。为什么?","text":"","category":"section"},{"location":"manual/faq/","page":"常见问题","title":"常见问题","text":"假设函数被如此调用:","category":"page"},{"location":"manual/faq/","page":"常见问题","title":"常见问题","text":"julia> x = 10\n10\n\njulia> function change_value!(y)\n y = 17\n end\nchange_value! (generic function with 1 method)\n\njulia> change_value!(x)\n17\n\njulia> x # x is unchanged!\n10","category":"page"},{"location":"manual/faq/","page":"常见问题","title":"常见问题","text":"在 Julia 中,通过将 x 作为参数传递给函数,不能改变变量 x 的绑定。在上例中,调用 change_value!(x) 时,y 是一个新建变量,初始时与 x 的值绑定,即 10。然后 y 与常量 17 重新绑定,此时变量外作用域中的 x 并没有变动。","category":"page"},{"location":"manual/faq/","page":"常见问题","title":"常见问题","text":"假设 x 被绑定至 Array 类型 (也有可能是其他 可变 的类型)。在函数中,你无法将 x 与 Array 解绑,但是你可以改变其内容。","category":"page"},{"location":"manual/faq/","page":"常见问题","title":"常见问题","text":"julia> x = [1,2,3]\n3-element Vector{Int64}:\n 1\n 2\n 3\n\njulia> function change_array!(A)\n A[1] = 5\n end\nchange_array! (generic function with 1 method)\n\njulia> change_array!(x)\n5\n\njulia> x\n3-element Vector{Int64}:\n 5\n 2\n 3","category":"page"},{"location":"manual/faq/","page":"常见问题","title":"常见问题","text":"这里我们新建了一个函数 chang_array!,它把 5 赋值给传入的数组(在调用处与 x 绑定,在函数中与 A 绑定)的第一个元素。注意,在函数调用之后,x 依旧与同一个数组绑定,但是数组的内容变化了:变量 A 和 x 是不同的绑定,引用同一个可变的 Array 对象。","category":"page"},{"location":"manual/faq/#函数内部能否使用-using-或-import?","page":"常见问题","title":"函数内部能否使用 using 或 import?","text":"","category":"section"},{"location":"manual/faq/","page":"常见问题","title":"常见问题","text":"不可以,不能在函数内部使用 using 或 import 语句。如果你希望导入一个模块,但只在特定的一个或一组函数中使用它的符号,有以下两种方式:","category":"page"},{"location":"manual/faq/","page":"常见问题","title":"常见问题","text":"使用 import:\nimport Foo\nfunction bar(...)\n # ... refer to Foo symbols via Foo.baz ...\nend\n这会加载 Foo 模块,同时定义一个变量 Foo 引用该模块,但并不会 将其他任何符号从该模块中导入当前的命名空间。 Foo 等符号可以由限定的名称 Foo.bar 等引用。\n将函数封装到模块中:\nmodule Bar\nexport bar\nusing Foo\nfunction bar(...)\n # ... refer to Foo.baz as simply baz ....\nend\nend\nusing Bar\n这会从 Foo 中导入所有符号,但仅限于 Bar 模块内。","category":"page"},{"location":"manual/faq/#运算符-...-有何作用?","page":"常见问题","title":"运算符 ... 有何作用?","text":"","category":"section"},{"location":"manual/faq/#...-运算符的两个用法:slurping-和-splatting","page":"常见问题","title":"... 运算符的两个用法:slurping 和 splatting","text":"","category":"section"},{"location":"manual/faq/","page":"常见问题","title":"常见问题","text":"很多 Julia 的新手会对运算符 ... 的用法感到困惑。让 ... 用法如此困惑的部分原因是根据上下文它有两种不同的含义。","category":"page"},{"location":"manual/faq/#...-在函数定义中将多个参数组合成一个参数","page":"常见问题","title":"... 在函数定义中将多个参数组合成一个参数","text":"","category":"section"},{"location":"manual/faq/","page":"常见问题","title":"常见问题","text":"在函数定义的上下文中,...运算符用来将多个不同的参数组合成单个参数。...运算符的这种将多个不同参数组合成单个参数的用法称为slurping:","category":"page"},{"location":"manual/faq/","page":"常见问题","title":"常见问题","text":"julia> function printargs(args...)\n println(typeof(args))\n for (i, arg) in enumerate(args)\n println(\"Arg #$i = $arg\")\n end\n end\nprintargs (generic function with 1 method)\n\njulia> printargs(1, 2, 3)\nTuple{Int64, Int64, Int64}\nArg #1 = 1\nArg #2 = 2\nArg #3 = 3","category":"page"},{"location":"manual/faq/","page":"常见问题","title":"常见问题","text":"如果Julia是一个使用ASCII字符更加自由的语言的话,slurping运算符可能会写作<-...而非...。","category":"page"},{"location":"manual/faq/#...在函数调用中将一个参数分解成多个不同参数","page":"常见问题","title":"...在函数调用中将一个参数分解成多个不同参数","text":"","category":"section"},{"location":"manual/faq/","page":"常见问题","title":"常见问题","text":"与在定义函数时表示将多个不同参数组合成一个参数的...运算符用法相对,当用在函数调用的上下文中...运算符也用来将单个的函数参数分成多个不同的参数。...函数的这个用法叫做splatting:","category":"page"},{"location":"manual/faq/","page":"常见问题","title":"常见问题","text":"julia> function threeargs(a, b, c)\n println(\"a = $a::$(typeof(a))\")\n println(\"b = $b::$(typeof(b))\")\n println(\"c = $c::$(typeof(c))\")\n end\nthreeargs (generic function with 1 method)\n\njulia> x = [1, 2, 3]\n3-element Vector{Int64}:\n 1\n 2\n 3\n\njulia> threeargs(x...)\na = 1::Int64\nb = 2::Int64\nc = 3::Int64","category":"page"},{"location":"manual/faq/","page":"常见问题","title":"常见问题","text":"如果Julia是一个使用ASCII字符更加自由的语言的话,splatting运算符可能会写作...->而非...。","category":"page"},{"location":"manual/faq/#赋值语句的返回值是什么?","page":"常见问题","title":"赋值语句的返回值是什么?","text":"","category":"section"},{"location":"manual/faq/","page":"常见问题","title":"常见问题","text":"=运算符始终返回右侧的值,所以:","category":"page"},{"location":"manual/faq/","page":"常见问题","title":"常见问题","text":"julia> function threeint()\n x::Int = 3.0\n x # returns variable x\n end\nthreeint (generic function with 1 method)\n\njulia> function threefloat()\n x::Int = 3.0 # returns 3.0\n end\nthreefloat (generic function with 1 method)\n\njulia> threeint()\n3\n\njulia> threefloat()\n3.0","category":"page"},{"location":"manual/faq/","page":"常见问题","title":"常见问题","text":"相似地:","category":"page"},{"location":"manual/faq/","page":"常见问题","title":"常见问题","text":"julia> function twothreetup()\n x, y = [2, 3] # assigns 2 to x and 3 to y\n x, y # returns a tuple\n end\ntwothreetup (generic function with 1 method)\n\njulia> function twothreearr()\n x, y = [2, 3] # returns an array\n end\ntwothreearr (generic function with 1 method)\n\njulia> twothreetup()\n(2, 3)\n\njulia> twothreearr()\n2-element Vector{Int64}:\n 2\n 3","category":"page"},{"location":"manual/faq/#类型,类型声明和构造函数","page":"常见问题","title":"类型,类型声明和构造函数","text":"","category":"section"},{"location":"manual/faq/#man-type-stability","page":"常见问题","title":"何谓“类型稳定”?","text":"","category":"section"},{"location":"manual/faq/","page":"常见问题","title":"常见问题","text":"这意味着输出的类型可以由输入的类型预测出来。特别地,这意味着输出的类型不会因输入的值的不同而变化。以下代码不是类型稳定的:","category":"page"},{"location":"manual/faq/","page":"常见问题","title":"常见问题","text":"julia> function unstable(flag::Bool)\n if flag\n return 1\n else\n return 1.0\n end\n end\nunstable (generic function with 1 method)","category":"page"},{"location":"manual/faq/","page":"常见问题","title":"常见问题","text":"根据参数值的不同,该函数可能返回 Int 或 Float64。由于 Julia 无法在编译期预测该函数的返回值类型,任何使用该函数的计算都需要考虑这两种可能的返回类型,这样难以生成高效的机器码。","category":"page"},{"location":"manual/faq/#faq-domain-errors","page":"常见问题","title":"为何 Julia 对某个看似合理的操作返回 DomainError?","text":"","category":"section"},{"location":"manual/faq/","page":"常见问题","title":"常见问题","text":"某些运算在数学上有意义,但会产生错误:","category":"page"},{"location":"manual/faq/","page":"常见问题","title":"常见问题","text":"julia> sqrt(-2.0)\nERROR: DomainError with -2.0:\nsqrt will only return a complex result if called with a complex argument. Try sqrt(Complex(x)).\nStacktrace:\n[...]","category":"page"},{"location":"manual/faq/","page":"常见问题","title":"常见问题","text":"这一行为是为了保证类型稳定而带来的不便。对于 sqrt,许多用户会希望 sqrt(2.0) 产生一个实数,如果得到了复数 1.4142135623730951 + 0.0im 则会不高兴。也可以编写 sqrt 函数,只有当传递一个负数时才切换到复值输出,但结果将不是类型稳定的,而且 sqrt 函数的性能会很差。","category":"page"},{"location":"manual/faq/","page":"常见问题","title":"常见问题","text":"在这样那样的情况下,若你想得到希望的结果,你可以选择一个输入类型,它可以使根据你的想法接受一个输出类型,从而结果可以这样表示:","category":"page"},{"location":"manual/faq/","page":"常见问题","title":"常见问题","text":"julia> sqrt(-2.0+0im)\n0.0 + 1.4142135623730951im","category":"page"},{"location":"manual/faq/#怎样限制或计算类型参数?","page":"常见问题","title":"怎样限制或计算类型参数?","text":"","category":"section"},{"location":"manual/faq/","page":"常见问题","title":"常见问题","text":"参数类型 的参数可以包含类型或比特值,并且类型本身选择如何使用这些参数。例如,Array{Float64, 2} 由类型 Float64 参数化以表示其元素类型,并通过整数值 2 来表示其维度数。在定义自己的参数类型时,可以使用子类型约束来声明某个参数必须是某个抽象类型的子类型 (<:) 或以前的类型参数。但是,没有专用的语法来声明参数必须是给定类型的值 — 也就是说,例如,你不能在struct定义中直接声明一个维度参数 isa Int。同样,你不能对类型参数进行计算(包括简单的加法或减法)。相反,这些类型的约束和关系可以通过在类型的 构造函数 中计算和强制执行的附加类型参数来表达。","category":"page"},{"location":"manual/faq/","page":"常见问题","title":"常见问题","text":"例如,考虑","category":"page"},{"location":"manual/faq/","page":"常见问题","title":"常见问题","text":"struct ConstrainedType{T,N,N+1} # NOTE: INVALID SYNTAX\n A::Array{T,N}\n B::Array{T,N+1}\nend","category":"page"},{"location":"manual/faq/","page":"常见问题","title":"常见问题","text":"其中,用户希望强制第三个类型参数始终是第二个参数加一。 这可以使用显式类型参数来实现,该参数由 内部构造函数方法(可以与其他检查结合使用)进行检查:","category":"page"},{"location":"manual/faq/","page":"常见问题","title":"常见问题","text":"struct ConstrainedType{T,N,M}\n A::Array{T,N}\n B::Array{T,M}\n function ConstrainedType(A::Array{T,N}, B::Array{T,M}) where {T,N,M}\n N + 1 == M || throw(ArgumentError(\"second argument should have one more axis\" ))\n new{T,N,M}(A, B)\n end\nend","category":"page"},{"location":"manual/faq/","page":"常见问题","title":"常见问题","text":"这种检查通常是无成本的,因为编译器可以省略对有效具体类型的检查。 如果还计算了第二个参数,则提供执行此计算的 外部构造函数方法 可能更好:","category":"page"},{"location":"manual/faq/","page":"常见问题","title":"常见问题","text":"ConstrainedType(A) = ConstrainedType(A, compute_B(A))","category":"page"},{"location":"manual/faq/#faq-integer-arithmetic","page":"常见问题","title":"为什么Julia使用机器算法进行整数运算?","text":"","category":"section"},{"location":"manual/faq/","page":"常见问题","title":"常见问题","text":"Julia使用机器算法进行整数计算。这意味着Int的范围是有界的,值在范围的两端循环,也就是说整数的加法,减法和乘法会出现上溢或者下溢,导致出现某些从开始就令人不安的结果:","category":"page"},{"location":"manual/faq/","page":"常见问题","title":"常见问题","text":"julia> x = typemax(Int)\n9223372036854775807\n\njulia> y = x+1\n-9223372036854775808\n\njulia> z = -y\n-9223372036854775808\n\njulia> 2*z\n0","category":"page"},{"location":"manual/faq/","page":"常见问题","title":"常见问题","text":"无疑,这与数学上的整数的行为很不一样,并且你会想对于高阶编程语言来说把这个暴露给用户难称完美。然而,对于效率优先和透明度优先的数值计算来说,其他的备选方案可谓更糟。","category":"page"},{"location":"manual/faq/","page":"常见问题","title":"常见问题","text":"一个备选方案是去检查每个整数运算是否溢出,如果溢出则将结果提升到更大的整数类型比如Int128或者BigInt。 不幸的是,这会给所有的整数操作(比如让循环计数器自增)带来巨大的额外开销 — 这需要生成代码去在算法指令后进行运行溢出检测,并生成分支去处理潜在的溢出。更糟糕的是,这会让涉及整数的所有运算变得类型不稳定。如同上面提到的,对于高效生成高效的代码类型稳定很重要。如果不指望整数运算的结果是整数,就无法想C和Fortran编译器一样生成快速简单的代码。","category":"page"},{"location":"manual/faq/","page":"常见问题","title":"常见问题","text":"这个方法有个变体可以避免类型不稳定的出现,这个变体是将类型Int和BigInt合并成单个混合整数类型,当结果不再满足机器整数的大小时会内部自动切换表示。虽然表面上在Julia代码层面解决了类型不稳定,但是这个只是通过将所有的困难硬塞给实现混合整数类型的C代码而掩盖了这个问题。这个方法可能有用,甚至在很多情况下速度很快,但是它有很多缺点。一个缺点是整数和整数数组的内存上的表示不再与C、Fortran和其他使用原生机器整数的怨言所使用的自然表示一样。所以,为了与那些语言协作,我们无论如何最终都需要引入原生整数类型。任何整数的无界表示都不会占用固定的比特数,所以无法使用固定大小的槽来内联地存储在数组中 — 大的整数值通常需要单独的堆分配的存储。并且无论使用的混合整数实现多么智能,总会存在性能陷阱 — 无法预期的性能下降的情况。复杂的表示,与C和Fortran协作能力的缺乏,无法在不使用另外的堆存储的情况下表示整数数组,和无法预测的性能特性让即使是最智能化的混合整数实现对于高性能数值计算来说也是个很差的选择。","category":"page"},{"location":"manual/faq/","page":"常见问题","title":"常见问题","text":"除了使用混合整数和提升到BigInt,另一个备选方案是使用饱和整数算法,此时最大整数值加一个数时值保持不变,最小整数值减一个数时也是同样的。这就是Matlab™的做法:","category":"page"},{"location":"manual/faq/","page":"常见问题","title":"常见问题","text":">> int64(9223372036854775807)\n\nans =\n\n 9223372036854775807\n\n>> int64(9223372036854775807) + 1\n\nans =\n\n 9223372036854775807\n\n>> int64(-9223372036854775808)\n\nans =\n\n -9223372036854775808\n\n>> int64(-9223372036854775808) - 1\n\nans =\n\n -9223372036854775808","category":"page"},{"location":"manual/faq/","page":"常见问题","title":"常见问题","text":"乍一看,这个似乎足够合理,因为9223372036854775807比-9223372036854775808更接近于9223372036854775808并且整数还是以固定大小的自然方式表示的,这与C和Fortran相兼容。但是饱和整数算法是很有问题的。首先最明显的问题是这并不是机器整数算法的工作方式,所以实现饱和整数算法需要生成指令,在每个机器整数运算后检查上溢或者下溢并正确地讲这些结果用typemin(Int)或者typemax(Int)取代。单单这个就将整数运算从单语句的快速的指令扩展成六个指令,还可能包括分支。哎呦喂~~但是还有更糟的 — 饱和整数算法并不满足结合律。考虑下列的Matlab计算:","category":"page"},{"location":"manual/faq/","page":"常见问题","title":"常见问题","text":">> n = int64(2)^62\n4611686018427387904\n\n>> n + (n - 1)\n9223372036854775807\n\n>> (n + n) - 1\n9223372036854775806","category":"page"},{"location":"manual/faq/","page":"常见问题","title":"常见问题","text":"这就让写很多基础整数算法变得困难因为很多常用技术都是基于有溢出的机器加法是满足结合律这一事实的。考虑一下在Julia中求整数值lo和hi之间的中点值,使用表达式(lo + hi) >>> 1:","category":"page"},{"location":"manual/faq/","page":"常见问题","title":"常见问题","text":"julia> n = 2^62\n4611686018427387904\n\njulia> (n + 2n) >>> 1\n6917529027641081856","category":"page"},{"location":"manual/faq/","page":"常见问题","title":"常见问题","text":"看到了吗?没有任何问题。那就是2^62和2^63之间的正确地中点值,虽然n + 2n的值是 -4611686018427387904。现在使用Matlab试一下:","category":"page"},{"location":"manual/faq/","page":"常见问题","title":"常见问题","text":">> (n + 2*n)/2\n\nans =\n\n 4611686018427387904","category":"page"},{"location":"manual/faq/","page":"常见问题","title":"常见问题","text":"哎呦喂。在Matlab中添加>>>运算符没有任何作用,因为在将n与2n相加时已经破坏了能计算出正确地中点值的必要信息,已经出现饱和。","category":"page"},{"location":"manual/faq/","page":"常见问题","title":"常见问题","text":"没有结合性不但对于不能依靠像这样的技术的程序员是不幸的,并且让几乎所有的希望优化整数算法的编译器铩羽而归。例如,因为Julia中的整数使用平常的机器整数算法,LLVM就可以自由地激进地优化像f(k) = 5k-1这样的简单地小函数。这个函数的机器码如下所示:","category":"page"},{"location":"manual/faq/","page":"常见问题","title":"常见问题","text":"julia> code_native(f, Tuple{Int})\n .text\nFilename: none\n pushq %rbp\n movq %rsp, %rbp\nSource line: 1\n leaq -1(%rdi,%rdi,4), %rax\n popq %rbp\n retq\n nopl (%rax,%rax)","category":"page"},{"location":"manual/faq/","page":"常见问题","title":"常见问题","text":"这个函数的实际函数体只是一个简单地leap指令,可以立马计算整数乘法与加法。当f内联在其他函数中的时候这个更加有益:","category":"page"},{"location":"manual/faq/","page":"常见问题","title":"常见问题","text":"julia> function g(k, n)\n for i = 1:n\n k = f(k)\n end\n return k\n end\ng (generic function with 1 methods)\n\njulia> code_native(g, Tuple{Int,Int})\n .text\nFilename: none\n pushq %rbp\n movq %rsp, %rbp\nSource line: 2\n testq %rsi, %rsi\n jle L26\n nopl (%rax)\nSource line: 3\nL16:\n leaq -1(%rdi,%rdi,4), %rdi\nSource line: 2\n decq %rsi\n jne L16\nSource line: 5\nL26:\n movq %rdi, %rax\n popq %rbp\n retq\n nop","category":"page"},{"location":"manual/faq/","page":"常见问题","title":"常见问题","text":"因为f的调用内联化,循环体就只是简单地leap指令。接着,考虑一下如果循环迭代的次数固定的时候会发生什么:","category":"page"},{"location":"manual/faq/","page":"常见问题","title":"常见问题","text":"julia> function g(k)\n for i = 1:10\n k = f(k)\n end\n return k\n end\ng (generic function with 2 methods)\n\njulia> code_native(g,(Int,))\n .text\nFilename: none\n pushq %rbp\n movq %rsp, %rbp\nSource line: 3\n imulq $9765625, %rdi, %rax # imm = 0x9502F9\n addq $-2441406, %rax # imm = 0xFFDABF42\nSource line: 5\n popq %rbp\n retq\n nopw %cs:(%rax,%rax)","category":"page"},{"location":"manual/faq/","page":"常见问题","title":"常见问题","text":"因为编译器知道整数加法和乘法是满足结合律的并且乘法可以在加法上使用分配律 — 两者在饱和算法中都不成立 — 所以编译器就可以把整个循环优化到只有一个乘法和一个加法。饱和算法完全无法使用这种优化,因为在每个循环迭代中结合律和分配律都会失效导致不同的失效位置会得到不同的结果。编译器可以展开循环,但是不能代数上将多个操作简化到更少的等效操作。","category":"page"},{"location":"manual/faq/","page":"常见问题","title":"常见问题","text":"让整数算术沉默地溢出的最合理替代方法是在任何地方进行检查算术,在加法、减法和乘法溢出时引发错误,产生不正确的值。 在这篇博文中,Dan Luu 对此进行了分析,并发现这种方法在理论上应该具有的微不足道的成本,但由于编译器(LLVM 和 GCC)没有优雅地围绕添加的溢出检查进行优化,它最终会产生大量成本。 如果这在未来有所改善,我们可以考虑在 Julia 中默认使用检查整数算法,但现在,我们必须忍受可能会溢出这一现状。","category":"page"},{"location":"manual/faq/","page":"常见问题","title":"常见问题","text":"同时,可以通过使用SaferIntegers.jl等外部库来实现溢出安全的整数运算。 请注意,如前所述,使用这些库会显着增加使用已检查整数类型的代码的执行时间。 但是,对于有限的使用,这远比将其用于所有整数运算时的问题要小得多。你可以在 此处 中关注讨论的状态。","category":"page"},{"location":"manual/faq/#在远程执行中UndefVarError的可能原因有哪些?","page":"常见问题","title":"在远程执行中UndefVarError的可能原因有哪些?","text":"","category":"section"},{"location":"manual/faq/","page":"常见问题","title":"常见问题","text":"如同这个错误表述的,远程结点上的UndefVarError的直接原因是变量名的绑定并不存在。让我们探索一下一些可能的原因。","category":"page"},{"location":"manual/faq/","page":"常见问题","title":"常见问题","text":"julia> module Foo\n foo() = remotecall_fetch(x->x, 2, \"Hello\")\n end\n\njulia> Foo.foo()\nERROR: On worker 2:\nUndefVarError: Foo not defined\nStacktrace:\n[...]","category":"page"},{"location":"manual/faq/","page":"常见问题","title":"常见问题","text":"闭包x->x中有Foo的引用,因为Foo在节点2上不存在,所以UndefVarError被扔出。","category":"page"},{"location":"manual/faq/","page":"常见问题","title":"常见问题","text":"在模块中而非Main中的全局变量不会在远程节点上按值序列化。只传递了一个引用。新建全局绑定的函数(除了Main中)可能会导致之后扔出UndefVarError。","category":"page"},{"location":"manual/faq/","page":"常见问题","title":"常见问题","text":"julia> @everywhere module Foo\n function foo()\n global gvar = \"Hello\"\n remotecall_fetch(()->gvar, 2)\n end\n end\n\njulia> Foo.foo()\nERROR: On worker 2:\nUndefVarError: gvar not defined\nStacktrace:\n[...]","category":"page"},{"location":"manual/faq/","page":"常见问题","title":"常见问题","text":"在上面的例子中,@everywhere module Foo在所有节点上定义了Foo。但是调用Foo.foo()在本地节点上新建了新的全局绑定gvar,但是节点2中并没有找到这个绑定,这会导致UndefVarError错误。","category":"page"},{"location":"manual/faq/","page":"常见问题","title":"常见问题","text":"注意着并不适用于在模块Main下新建的全局变量。模块Main下的全局变量会被序列化并且在远程节点的Main下新建新的绑定。","category":"page"},{"location":"manual/faq/","page":"常见问题","title":"常见问题","text":"julia> gvar_self = \"Node1\"\n\"Node1\"\n\njulia> remotecall_fetch(()->gvar_self, 2)\n\"Node1\"\n\njulia> remotecall_fetch(varinfo, 2)\nname size summary\n––––––––– –––––––– –––––––\nBase Module\nCore Module\nMain Module\ngvar_self 13 bytes String","category":"page"},{"location":"manual/faq/","page":"常见问题","title":"常见问题","text":"这并不适用于函数或者结构体声明。但是绑定到全局变量的匿名函数被序列化,如下例所示。","category":"page"},{"location":"manual/faq/","page":"常见问题","title":"常见问题","text":"julia> bar() = 1\nbar (generic function with 1 method)\n\njulia> remotecall_fetch(bar, 2)\nERROR: On worker 2:\nUndefVarError: #bar not defined\n[...]\n\njulia> anon_bar = ()->1\n(::#21) (generic function with 1 method)\n\njulia> remotecall_fetch(anon_bar, 2)\n1","category":"page"},{"location":"manual/faq/#“method-not-matched”故障排除:参数类型不变性和MethodError","page":"常见问题","title":"“method not matched”故障排除:参数类型不变性和MethodError","text":"","category":"section"},{"location":"manual/faq/#为什么声明-foo(bar::Vector{Real})-42-然后调用-foo([1])-不起作用?","page":"常见问题","title":"为什么声明 foo(bar::Vector{Real}) = 42 然后调用 foo([1]) 不起作用?","text":"","category":"section"},{"location":"manual/faq/","page":"常见问题","title":"常见问题","text":"如果你尝试了,结果就会看到MethodError:","category":"page"},{"location":"manual/faq/","page":"常见问题","title":"常见问题","text":"julia> foo(x::Vector{Real}) = 42\nfoo (generic function with 1 method)\n\njulia> foo([1])\nERROR: MethodError: no method matching foo(::Vector{Int64})\nClosest candidates are:\n foo(!Matched::Vector{Real}) at none:1","category":"page"},{"location":"manual/faq/","page":"常见问题","title":"常见问题","text":"这是因为 Vector{Real} 不是 Vector{Int} 的超类型! 您可以使用类似 foo(bar::Vector{T}) where {T<:Real}(或缩写 foo(bar::Vector{<:Real}) 如果静态参数函数体中不需要T)。T 是一个通配符:首先指定它必须是 Real 的子类型,然后指定函数采用具有该类型元素的 Vector 。","category":"page"},{"location":"manual/faq/","page":"常见问题","title":"常见问题","text":"同样的问题适用于任何复合类型Comp,而不仅仅是Vector。 如果Comp 有一个声明为Y 类型的参数,那么另一个带有X<:Y 类型参数的类型Comp2 不是Comp 的子类型。 这是类型不变性(相比之下,元组在其参数中是类型协变的)。 有关这些的更多解释,请参阅 参数复合类型。","category":"page"},{"location":"manual/faq/#为什么-Julia-使用-*-进行字符串拼接?而不是使用-或其他符号?","page":"常见问题","title":"为什么 Julia 使用 * 进行字符串拼接?而不是使用 + 或其他符号?","text":"","category":"section"},{"location":"manual/faq/","page":"常见问题","title":"常见问题","text":"使用 + 的主要依据是:字符串拼接是不可交换的操作,而 + 通常是一个具有可交换性的操作符。Julia 社区也意识到其他语言使用了不同的操作符,一些用户也可能不熟悉 * 包含的特定代数性值。","category":"page"},{"location":"manual/faq/","page":"常见问题","title":"常见问题","text":"注意:你也可以用 string(...) 来拼接字符串和其他能转换成字符串的值; 类似的 repeat 函数可以用于替代用于重复字符串的 ^ 操作符。 字符串插值语法在构造字符串时也很常用。","category":"page"},{"location":"manual/faq/#包和模块","page":"常见问题","title":"包和模块","text":"","category":"section"},{"location":"manual/faq/#\"using\"和\"import\"的区别是什么?","page":"常见问题","title":"\"using\"和\"import\"的区别是什么?","text":"","category":"section"},{"location":"manual/faq/","page":"常见问题","title":"常见问题","text":"只有一个区别,并且在表面上(语法层面)这个区别看来很小。using和import的区别是使用using时你需要写function Foo.bar(..来用一个新方法来扩展模块Foo的函数bar,但是使用import Foo.bar时,你只需要写function bar(...,会自动扩展模块Foo的函数bar。","category":"page"},{"location":"manual/faq/","page":"常见问题","title":"常见问题","text":"这个区别足够重要以至于提供不同的语法的原因是你不希望意外地扩展一个你根本不知道其存在的函数,因为这很容易造成bug。对于使用像字符串后者整数这样的常用类型的方法最有可能出现这个问题,因为你和其他模块都可能定义了方法来处理这样的常用类型。如果你使用import,你会用你自己的新实现覆盖别的函数的bar(s::AbstractString)实现,这会导致做的事情天差地别(并且破坏模块Foo中其他的依赖于调用bar的函数的所有/大部分的将来的使用)。","category":"page"},{"location":"manual/faq/#空值与缺失值","page":"常见问题","title":"空值与缺失值","text":"","category":"section"},{"location":"manual/faq/#faq-nothing","page":"常见问题","title":"在Julia中\"null\",\"空\"或者\"缺失\"是怎么工作的?","text":"","category":"section"},{"location":"manual/faq/","page":"常见问题","title":"常见问题","text":"不像其它很多语言(例如 C 和 Java),Julia 对象默认不能为\"null\"。当一个引用(变量,对象域,或者数组元素)没有被初始化,访问它会立即扔出一个错误。这种情况可以使用函数 isdefined 或者 isassigned 检测到。","category":"page"},{"location":"manual/faq/","page":"常见问题","title":"常见问题","text":"一些函数只为了其副作用使用,并不需要返回一个值。在这些情况下,约定的是返回 nothing 这个值,这只是 Nothing 类型的一个单例对象。这是一个没有域的一般类型;除了这个约定之外没有任何特殊点,REPL 不会为它打印任何东西。有些语言结构不会有值,也产生 nothing,例如 if false; end。","category":"page"},{"location":"manual/faq/","page":"常见问题","title":"常见问题","text":"对于类型T的值x只会有时存在的情况,Union{T,Nothing}类型可以用作函数参数,对象域和数组元素的类型,与其他语言中的Nullable, Option or Maybe相等。如果值本身可以是nothing(显然当T是Any时),Union{Some{T}, Nothing}类型更加准确因为x == nothing表示值的缺失,x == Some(nothing)表示与nothing相等的值的存在。something函数允许使用默认值的展开的Some对象,而非nothing参数。注意在使用Union{T,Nothing}参数或者域时编译器能够生成高效的代码。","category":"page"},{"location":"manual/faq/","page":"常见问题","title":"常见问题","text":"在统计环境下表示缺失的数据(R 中的 NA 或者 SQL 中的 NULL)请使用 missing 对象。请参照缺失值章节来获取详细信息。","category":"page"},{"location":"manual/faq/","page":"常见问题","title":"常见问题","text":"在某些语言中,空元组 (()) 被认为是\"没有“的规范形式。但是,在 julia 中,最好将其视为恰好包含零个值的常规元组。","category":"page"},{"location":"manual/faq/","page":"常见问题","title":"常见问题","text":"空(或者\"底层\")类型,写作Union{}(空的union类型)是没有值和子类型(除了自己)的类型。通常你没有必要用这个类型。","category":"page"},{"location":"manual/faq/#内存","page":"常见问题","title":"内存","text":"","category":"section"},{"location":"manual/faq/#为什么当x和y都是数组时x-y还会申请内存?","page":"常见问题","title":"为什么当x和y都是数组时x += y还会申请内存?","text":"","category":"section"},{"location":"manual/faq/","page":"常见问题","title":"常见问题","text":"在 Julia 中,x += y 在语法分析中会用 x = x + y 代替。对于数组,结果就是它会申请一个新数组来存储结果,而非把结果存在 x 同一位置的内存上。","category":"page"},{"location":"manual/faq/","page":"常见问题","title":"常见问题","text":"这个行为可能会让一些人吃惊,但是这个结果是经过深思熟虑的。主要原因是Julia中的不可变对象,这些对象一旦新建就不能改变他们的值。实际上,数字是不可变对象,语句x = 5; x += 1不会改变5的意义,改变的是与x绑定的值。对于不可变对象,改变其值的唯一方法是重新赋值。","category":"page"},{"location":"manual/faq/","page":"常见问题","title":"常见问题","text":"为了稍微详细一点,考虑下列的函数:","category":"page"},{"location":"manual/faq/","page":"常见问题","title":"常见问题","text":"function power_by_squaring(x, n::Int)\n ispow2(n) || error(\"此实现只适用于2的幂\")\n while n >= 2\n x *= x\n n >>= 1\n end\n x\nend","category":"page"},{"location":"manual/faq/","page":"常见问题","title":"常见问题","text":"在x = 5; y = power_by_squaring(x, 4)调用后,你可以得到期望的结果x == 5 && y == 625。然而,现在假设当*=与矩阵一起使用时会改变左边的值,这会有两个问题:","category":"page"},{"location":"manual/faq/","page":"常见问题","title":"常见问题","text":"对于普通的方阵,A = A*B 不能在没有临时存储的情况下实现:A[1,1] 会被计算并且在被右边使用完之前存储在左边。\n假设你愿意申请一个计算的临时存储(这会消除 *=就地计算的大部分要点);如果你利用了x的可变性, 这个函数会对于可变和不可变的输入有不同的行为。特别地, 对于不可变的x,在调用后(通常)你会得到y != x,而对可变的x,你会有y == x。","category":"page"},{"location":"manual/faq/","page":"常见问题","title":"常见问题","text":"因为支持范用计算被认为比能使用其他方法完成的潜在的性能优化(比如使用显式循环)更加重要,所以像+=和*=运算符以绑定新值的方式工作。","category":"page"},{"location":"manual/faq/#faq-async-io","page":"常见问题","title":"异步 IO 与并发同步写入","text":"","category":"section"},{"location":"manual/faq/#为什么对于同一个流的并发写入会导致相互混合的输出?","page":"常见问题","title":"为什么对于同一个流的并发写入会导致相互混合的输出?","text":"","category":"section"},{"location":"manual/faq/","page":"常见问题","title":"常见问题","text":"虽然流式 I/O 的 API 是同步的,底层的实现是完全异步的。","category":"page"},{"location":"manual/faq/","page":"常见问题","title":"常见问题","text":"思考一下下面的输出:","category":"page"},{"location":"manual/faq/","page":"常见问题","title":"常见问题","text":"julia> @sync for i in 1:3\n @async write(stdout, string(i), \" Foo \", \" Bar \")\n end\n123 Foo Foo Foo Bar Bar Bar","category":"page"},{"location":"manual/faq/","page":"常见问题","title":"常见问题","text":"这是因为,虽然write调用是同步的,每个参数的写入在等待那一部分I/O完成时会生成其他的Tasks。","category":"page"},{"location":"manual/faq/","page":"常见问题","title":"常见问题","text":"print和println在调用中会\"锁定\"该流。因此把上例中的write改成println会导致:","category":"page"},{"location":"manual/faq/","page":"常见问题","title":"常见问题","text":"julia> @sync for i in 1:3\n @async println(stdout, string(i), \" Foo \", \" Bar \")\n end\n1 Foo Bar\n2 Foo Bar\n3 Foo Bar","category":"page"},{"location":"manual/faq/","page":"常见问题","title":"常见问题","text":"你可以使用ReentrantLock来锁定你的写入,就像这样:","category":"page"},{"location":"manual/faq/","page":"常见问题","title":"常见问题","text":"julia> l = ReentrantLock();\n\njulia> @sync for i in 1:3\n @async begin\n lock(l)\n try\n write(stdout, string(i), \" Foo \", \" Bar \")\n finally\n unlock(l)\n end\n end\n end\n1 Foo Bar 2 Foo Bar 3 Foo Bar","category":"page"},{"location":"manual/faq/#数组","page":"常见问题","title":"数组","text":"","category":"section"},{"location":"manual/faq/#零维数组和标量之间的有什么差别?","page":"常见问题","title":"零维数组和标量之间的有什么差别?","text":"","category":"section"},{"location":"manual/faq/","page":"常见问题","title":"常见问题","text":"零维数组是Array{T,0}形式的数组,它与标量的行为相似,但是有很多重要的不同。这值得一提,因为这是使用数组的范用定义来解释也符合逻辑的特殊情况,虽然最开始看起来有些非直觉。下面一行定义了一个零维数组:","category":"page"},{"location":"manual/faq/","page":"常见问题","title":"常见问题","text":"julia> A = zeros()\n0-dimensional Array{Float64,0}:\n0.0","category":"page"},{"location":"manual/faq/","page":"常见问题","title":"常见问题","text":"在这个例子中,A是一个含有一个元素的可变容器,这个元素可以通过A[] = 1.0来设置,通过A[]来读取。所有的零维数组都有同样的大小(size(A) == ())和长度(length(A) == 1)。特别地,零维数组不是空数组。如果你觉得这个非直觉,这里有些想法可以帮助理解Julia的这个定义。","category":"page"},{"location":"manual/faq/","page":"常见问题","title":"常见问题","text":"类比的话,零维数组是\"点\",向量是\"线\"而矩阵 是\"面\"。就像线没有面积一样(但是也能代表事物的一个集合), 点没有长度和任意一个维度(但是也能表示一个事物)。\n我们定义prod(())为1,一个数组中的所有的元素个数是 大小的乘积。零维数组的大小为(),所以 它的长度为1。\n零维数组没有任何你可以索引的维度——它们仅仅是A[]。我们可以给它们应用同样的\"尾一\"规则就像对其它维度数组那样,比如A[1],A[1,1],等;参见Omitted and extra indices.","category":"page"},{"location":"manual/faq/","page":"常见问题","title":"常见问题","text":"理解它与普通的标量之间的区别也很重要。标量不是一个可变的容器(尽管它们是可迭代的,可以定义像length,getindex这样的东西,例如1[] == 1)。特别地,如果x = 0.0是以一个标量来定义,尝试通过x[] = 1.0来改变它的值会报错。标量x能够通过fill(x)转化成包含它的零维数组,并且相对地,一个零维数组a可以通过a[]转化成其包含的标量。另外一个区别是标量可以参与到线性代数运算中,比如2 * rand(2,2),但是零维数组的相似操作fill(2) * rand(2,2)会报错。","category":"page"},{"location":"manual/faq/#为什么我的Julia的线性代数操作测试与其他的语言不同。","page":"常见问题","title":"为什么我的Julia的线性代数操作测试与其他的语言不同。","text":"","category":"section"},{"location":"manual/faq/","page":"常见问题","title":"常见问题","text":"你可能找到一些简单的线性代数测试,比如,","category":"page"},{"location":"manual/faq/","page":"常见问题","title":"常见问题","text":"using BenchmarkTools\nA = randn(1000, 1000)\nB = randn(1000, 1000)\n@btime $A \\ $B\n@btime $A * $B","category":"page"},{"location":"manual/faq/","page":"常见问题","title":"常见问题","text":"也许和其他语言不同比如Matlab或R。","category":"page"},{"location":"manual/faq/","page":"常见问题","title":"常见问题","text":"由于像这样的操作都非常直接地从相关的BLAS函数调用,这样做的原因是,","category":"page"},{"location":"manual/faq/","page":"常见问题","title":"常见问题","text":"在每种语言中使用的BLAS库\n并发线程的数量","category":"page"},{"location":"manual/faq/","page":"常见问题","title":"常见问题","text":"Julia 编译并使用自己的 OpenBLAS 副本,当前线程数上限为 8(或内核数)。","category":"page"},{"location":"manual/faq/","page":"常见问题","title":"常见问题","text":"修改 OpenBLAS 设置或使用不同的 BLAS 库编译 Julia,例如 Intel MKL,可能会提高性能。 你可以使用 MKL.jl,这是一个使 Julia 的线性代数使用英特尔 MKL BLAS 和 LAPACK 而不是 OpenBLAS 的包,或搜索论坛以获取有关如何使用的建议。 请注意,英特尔 MKL 不能与 Julia 捆绑在一起,因为它不是开源的。","category":"page"},{"location":"manual/faq/#计算集群","page":"常见问题","title":"计算集群","text":"","category":"section"},{"location":"manual/faq/#我该如何管理分布式文件系统的预编译缓存?","page":"常见问题","title":"我该如何管理分布式文件系统的预编译缓存?","text":"","category":"section"},{"location":"manual/faq/","page":"常见问题","title":"常见问题","text":"在高性能计算 (HPC) 设施中使用 julia 时,同时调用 n 个 julia 进程最多会创建 n 个预编译缓存文件的临时副本。 如果这是一个问题(缓慢和/或小型分布式文件系统),你可以:","category":"page"},{"location":"manual/faq/","page":"常见问题","title":"常见问题","text":"使用 julia的 --compiled-modules=no 标志来关掉预编译。\n使用 pushfirst!(DEPOT_PATH, private_path) 配置一个私有的可写仓库 在这里private_path是一个路径单独地到这个julia进程 也可以通过设置环境变量 JULIA_DEPOT_PATH 到 $private_path:$HOME/.julia.\n在scratch里创建到 ~/.julia/compiled的符号链接。","category":"page"},{"location":"manual/faq/#Julia-版本发布","page":"常见问题","title":"Julia 版本发布","text":"","category":"section"},{"location":"manual/faq/#你希望使用稳定的、长期支持的或是每日构建版本的Julia?","page":"常见问题","title":"你希望使用稳定的、长期支持的或是每日构建版本的Julia?","text":"","category":"section"},{"location":"manual/faq/","page":"常见问题","title":"常见问题","text":"Julia 的稳定版是最新发布的 Julia 版本,这是大多数人想要运行的版本。 它具有最新的功能,包括改进的性能。 Julia 的稳定版本根据 SemVer 版本化为 v1.x.y。 在作为候选版本进行几周的测试后,大约每 4-5 个月就会发布一个与新稳定版本相对应的新 Julia 次要版本。 与 LTS 版本不同,在 Julia 的另一个稳定版本发布后,稳定版本通常不会收到错误修正。 但是,始终可以升级到下一个稳定版本,因为 Julia v1.x 的每个版本都将继续运行为早期版本编写的代码。","category":"page"},{"location":"manual/faq/","page":"常见问题","title":"常见问题","text":"如果正在寻找非常稳定的代码库,你可能更喜欢 Julia 的 LTS(长期支持)版本。 Julia 当前的 LTS 版本根据 SemVer 版本为 v1.0.x; 此分支将继续接收错误修复,直到选择新的 LTS 分支,此时 v1.0.x 系列将不再收到常规错误修复,建议除最保守的用户之外的所有用户升级到新的 LTS 版本系列。作为软件包开发人员,你可能更喜欢针对 LTS 版本进行开发,以最大限度地增加可以使用你的软件包的用户数量。 根据 SemVer,为 v1.0 编写的代码将继续适用于所有未来的 LTS 和稳定版本。 一般来说,即使针对 LTS,也可以在最新的 Stable 版本中开发和运行代码,以利用改进的性能; 只要避免使用新功能(例如添加的库函数或新方法)。","category":"page"},{"location":"manual/faq/","page":"常见问题","title":"常见问题","text":"如果您想利用该语言的最新更新,您可能更喜欢 Julia 的每日构建版本,并且不介意今天可用的版本是否偶尔无法正常工作。 顾名思义,每日构建版本的发布大约每晚发布一次(取决于构建基础设施的稳定性)。 一般来说,每日构建的发布是相当安全的——你的代码不会着火。 然而,它们可能出现偶尔的版本倒退和问题,直到更彻底的预发布测试才会发现。 你可能希望针对每日构建版本进行测试,以确保在发布之前捕获影响你的用例的版本倒退。","category":"page"},{"location":"manual/faq/","page":"常见问题","title":"常见问题","text":"最后,您也可以考虑为自己从源代码构建 Julia。 此选项主要适用于那些熟悉命令行或对学习感兴趣的人。 如果你是这样的人,你可能也有兴趣阅读我们的 贡献指南。","category":"page"},{"location":"manual/faq/","page":"常见问题","title":"常见问题","text":"可以在https://julialang.org/downloads/的下载页面上找到每种下载类型的链接。 请注意,并非所有版本的Julia都适用于所有平台。","category":"page"},{"location":"manual/faq/#更新我的-Julia-版本后,如何转移已安装软件包的列表?","page":"常见问题","title":"更新我的 Julia 版本后,如何转移已安装软件包的列表?","text":"","category":"section"},{"location":"manual/faq/","page":"常见问题","title":"常见问题","text":"julia 的每个次要版本都有自己的默认 环境。 因此,在安装新的 Julia 次要版本时,默认情况下你使用先前次要版本添加的包将不可用。 给定 julia 版本的环境由文件Project.toml和Manifest.toml定义,文件夹中的文件与.julia/environments/中的版本号匹配,例如.julia/environments/v1.3。","category":"page"},{"location":"manual/faq/","page":"常见问题","title":"常见问题","text":"如果你安装了一个新的 Julia 次要版本,比如 1.4,并且想要在它的默认环境中使用与以前版本(例如 1.3)相同的包,你可以从1.3 文件夹复制文件 Project.toml 的内容到1.4。然后,在新的 Julia 版本的会话中,输入] 键进入“包管理模式”,并运行命令 instantiate。","category":"page"},{"location":"manual/faq/","page":"常见问题","title":"常见问题","text":"此操作将从复制的文件中解析一组与目标 Julia 版本兼容的可行包,并在合适时安装或更新它们。 如果你不仅要重现软件包,还要重现在以前的 Julia 版本中使用的版本,您还应该在运行 Pkg 命令 instantiate 之前复制 Manifest.toml 文件。 但是,请注意,包可能定义了兼容性约束,这些约束可能会受到更改 Julia 版本的影响,因此你在1.3中拥有的确切版本集可能不适用于1.4。","category":"page"},{"location":"devdocs/eval/#Julia-代码的-eval","page":"Julia 代码的 eval","title":"Julia 代码的 eval","text":"","category":"section"},{"location":"devdocs/eval/","page":"Julia 代码的 eval","title":"Julia 代码的 eval","text":"学习 Julia 语言如何运行代码的最难的一部分是 学习如何让所有的小部分工作协同工作来执行一段代码。 ","category":"page"},{"location":"devdocs/eval/","page":"Julia 代码的 eval","title":"Julia 代码的 eval","text":"每个代码块通常会通过许多步骤来执行,在转变为期望的结果之前(但愿如此)。并且你可能不熟悉它们的名称,例如(非特定顺序): flisp,AST,C++,LLVM,eval,typeinf,macroexpand,sysimg(或 system image),启动,变异,解析,执行,即时编译器,解释器解释,装箱,拆箱,内部函数,原始函数","category":"page"},{"location":"devdocs/eval/","page":"Julia 代码的 eval","title":"Julia 代码的 eval","text":"sidebar: Definitions\nREPL\nREPL 表示 读取-求值-输出-循环(Read-Eval-Print Loop)。 我们管这个命令行环境的简称就叫REPL。\nAST\n抽象语法树(Abstract Syntax Tree)是代码结构的数据表现。在这种表现形式下代码被符号化,因此更加方便操作和执行。","category":"page"},{"location":"devdocs/eval/#Julia-Execution","page":"Julia 代码的 eval","title":"Julia Execution","text":"","category":"section"},{"location":"devdocs/eval/","page":"Julia 代码的 eval","title":"Julia 代码的 eval","text":"整个进程的千里之行如下:","category":"page"},{"location":"devdocs/eval/","page":"Julia 代码的 eval","title":"Julia 代码的 eval","text":"用户打开了 julia。\nThe C function main() from cli/loader_exe.c gets called. This function processes the command line arguments, filling in the jl_options struct and setting the variable ARGS. It then initializes 在 ui/repl.c 中的 C 语言的函数 main() 被调用。这个函数处理命令行参数,填充到 jl_options 结构图并且设置变了 ARGS 。接下来初始化 Julia (通过调用 julia_init in task.c which may load a previously compiled sysimg). Finally, it passes off control to Julia by calling Base._start().\nWhen _start() takes over control, the subsequent sequence of commands depends on the command line arguments given. For example, if a filename was supplied, it will proceed to execute that file. Otherwise, it will start an interactive REPL.\nSkipping the details about how the REPL interacts with the user, let's just say the program ends up with a block of code that it wants to run.\nIf the block of code to run is in a file, jl_load(char *filename) gets invoked to load the file and parse it. Each fragment of code is then passed to eval to execute.\nEach fragment of code (or AST), is handed off to eval() to turn into results.\neval() takes each code fragment and tries to run it in jl_toplevel_eval_flex().\njl_toplevel_eval_flex() decides whether the code is a \"toplevel\" action (such as using or module), which would be invalid inside a function. If so, it passes off the code to the toplevel interpreter.\njl_toplevel_eval_flex() then expands the code to eliminate any macros and to \"lower\" the AST to make it simpler to execute.\njl_toplevel_eval_flex() then uses some simple heuristics to decide whether to JIT compiler the AST or to interpret it directly.\nThe bulk of the work to interpret code is handled by eval in interpreter.c.\nIf instead, the code is compiled, the bulk of the work is handled by codegen.cpp. Whenever a Julia function is called for the first time with a given set of argument types, type inference will be run on that function. This information is used by the codegen step to generate faster code.\nEventually, the user quits the REPL, or the end of the program is reached, and the _start() method returns.\nJust before exiting, main() calls jl_atexit_hook(exit_code). This calls Base._atexit() (which calls any functions registered to atexit() inside Julia). Then it calls jl_gc_run_all_finalizers(). Finally, it gracefully cleans up all libuv handles and waits for them to flush and close.","category":"page"},{"location":"devdocs/eval/#dev-parsing","page":"Julia 代码的 eval","title":"Parsing","text":"","category":"section"},{"location":"devdocs/eval/","page":"Julia 代码的 eval","title":"Julia 代码的 eval","text":"The Julia parser is a small lisp program written in femtolisp, the source-code for which is distributed inside Julia in src/flisp.","category":"page"},{"location":"devdocs/eval/","page":"Julia 代码的 eval","title":"Julia 代码的 eval","text":"The interface functions for this are primarily defined in jlfrontend.scm. The code in ast.c handles this handoff on the Julia side.","category":"page"},{"location":"devdocs/eval/","page":"Julia 代码的 eval","title":"Julia 代码的 eval","text":"The other relevant files at this stage are julia-parser.scm, which handles tokenizing Julia code and turning it into an AST, and julia-syntax.scm, which handles transforming complex AST representations into simpler, \"lowered\" AST representations which are more suitable for analysis and execution.","category":"page"},{"location":"devdocs/eval/","page":"Julia 代码的 eval","title":"Julia 代码的 eval","text":"If you want to test the parser without re-building Julia in its entirety, you can run the frontend on its own as follows:","category":"page"},{"location":"devdocs/eval/","page":"Julia 代码的 eval","title":"Julia 代码的 eval","text":"$ cd src\n$ flisp/flisp\n> (load \"jlfrontend.scm\")\n> (jl-parse-file \"\")","category":"page"},{"location":"devdocs/eval/#dev-macro-expansion","page":"Julia 代码的 eval","title":"Macro Expansion","text":"","category":"section"},{"location":"devdocs/eval/","page":"Julia 代码的 eval","title":"Julia 代码的 eval","text":"When eval() encounters a macro, it expands that AST node before attempting to evaluate the expression. Macro expansion involves a handoff from eval() (in Julia), to the parser function jl_macroexpand() (written in flisp) to the Julia macro itself (written in - what else - Julia) via fl_invoke_julia_macro(), and back.","category":"page"},{"location":"devdocs/eval/","page":"Julia 代码的 eval","title":"Julia 代码的 eval","text":"Typically, macro expansion is invoked as a first step during a call to Meta.lower()/jl_expand(), although it can also be invoked directly by a call to macroexpand()/jl_macroexpand().","category":"page"},{"location":"devdocs/eval/#dev-type-inference","page":"Julia 代码的 eval","title":"Type Inference","text":"","category":"section"},{"location":"devdocs/eval/","page":"Julia 代码的 eval","title":"Julia 代码的 eval","text":"Type inference is implemented in Julia by typeinf() in compiler/typeinfer.jl. Type inference is the process of examining a Julia function and determining bounds for the types of each of its variables, as well as bounds on the type of the return value from the function. This enables many future optimizations, such as unboxing of known immutable values, and compile-time hoisting of various run-time operations such as computing field offsets and function pointers. Type inference may also include other steps such as constant propagation and inlining.","category":"page"},{"location":"devdocs/eval/","page":"Julia 代码的 eval","title":"Julia 代码的 eval","text":"sidebar: More Definitions\nJIT\nJust-In-Time Compilation The process of generating native-machine code into memory right when it is needed.\nLLVM\nLow-Level Virtual Machine (a compiler) The Julia JIT compiler is a program/library called libLLVM. Codegen in Julia refers both to the process of taking a Julia AST and turning it into LLVM instructions, and the process of LLVM optimizing that and turning it into native assembly instructions.\nC++\nThe programming language that LLVM is implemented in, which means that codegen is also implemented in this language. The rest of Julia's library is implemented in C, in part because its smaller feature set makes it more usable as a cross-language interface layer.\nbox\nThis term is used to describe the process of taking a value and allocating a wrapper around the data that is tracked by the garbage collector (gc) and is tagged with the object's type.\nunbox\nThe reverse of boxing a value. This operation enables more efficient manipulation of data when the type of that data is fully known at compile-time (through type inference).\ngeneric function\nA Julia function composed of multiple \"methods\" that are selected for dynamic dispatch based on the argument type-signature\nanonymous function or \"method\"\nA Julia function without a name and without type-dispatch capabilities\nprimitive function\nA function implemented in C but exposed in Julia as a named function \"method\" (albeit without generic function dispatch capabilities, similar to a anonymous function)\nintrinsic function\nA low-level operation exposed as a function in Julia. These pseudo-functions implement operations on raw bits such as add and sign extend that cannot be expressed directly in any other way. Since they operate on bits directly, they must be compiled into a function and surrounded by a call to Core.Intrinsics.box(T, ...) to reassign type information to the value.","category":"page"},{"location":"devdocs/eval/#dev-codegen","page":"Julia 代码的 eval","title":"JIT Code Generation","text":"","category":"section"},{"location":"devdocs/eval/","page":"Julia 代码的 eval","title":"Julia 代码的 eval","text":"Codegen is the process of turning a Julia AST into native machine code.","category":"page"},{"location":"devdocs/eval/","page":"Julia 代码的 eval","title":"Julia 代码的 eval","text":"The JIT environment is initialized by an early call to jl_init_codegen in codegen.cpp.","category":"page"},{"location":"devdocs/eval/","page":"Julia 代码的 eval","title":"Julia 代码的 eval","text":"On demand, a Julia method is converted into a native function by the function emit_function(jl_method_instance_t*). (note, when using the MCJIT (in LLVM v3.4+), each function must be JIT into a new module.) This function recursively calls emit_expr() until the entire function has been emitted.","category":"page"},{"location":"devdocs/eval/","page":"Julia 代码的 eval","title":"Julia 代码的 eval","text":"Much of the remaining bulk of this file is devoted to various manual optimizations of specific code patterns. For example, emit_known_call() knows how to inline many of the primitive functions (defined in builtins.c) for various combinations of argument types.","category":"page"},{"location":"devdocs/eval/","page":"Julia 代码的 eval","title":"Julia 代码的 eval","text":"Other parts of codegen are handled by various helper files:","category":"page"},{"location":"devdocs/eval/","page":"Julia 代码的 eval","title":"Julia 代码的 eval","text":"debuginfo.cpp\nHandles backtraces for JIT functions\nccall.cpp\nHandles the ccall and llvmcall FFI, along with various abi_*.cpp files\nintrinsics.cpp\nHandles the emission of various low-level intrinsic functions","category":"page"},{"location":"devdocs/eval/","page":"Julia 代码的 eval","title":"Julia 代码的 eval","text":"sidebar: Bootstrapping\nThe process of creating a new system image is called \"bootstrapping\".The etymology of this word comes from the phrase \"pulling oneself up by the bootstraps\", and refers to the idea of starting from a very limited set of available functions and definitions and ending with the creation of a full-featured environment.","category":"page"},{"location":"devdocs/eval/#dev-sysimg","page":"Julia 代码的 eval","title":"System Image","text":"","category":"section"},{"location":"devdocs/eval/","page":"Julia 代码的 eval","title":"Julia 代码的 eval","text":"The system image is a precompiled archive of a set of Julia files. The sys.ji file distributed with Julia is one such system image, generated by executing the file sysimg.jl, and serializing the resulting environment (including Types, Functions, Modules, and all other defined values) into a file. Therefore, it contains a frozen version of the Main, Core, and Base modules (and whatever else was in the environment at the end of bootstrapping). This serializer/deserializer is implemented by jl_save_system_image/jl_restore_system_image in staticdata.c.","category":"page"},{"location":"devdocs/eval/","page":"Julia 代码的 eval","title":"Julia 代码的 eval","text":"If there is no sysimg file (jl_options.image_file == NULL), this also implies that --build was given on the command line, so the final result should be a new sysimg file. During Julia initialization, minimal Core and Main modules are created. Then a file named boot.jl is evaluated from the current directory. Julia then evaluates any file given as a command line argument until it reaches the end. Finally, it saves the resulting environment to a \"sysimg\" file for use as a starting point for a future Julia run.","category":"page"},{"location":"devdocs/gc-sa/#Static-analyzer-annotations-for-GC-correctness-in-C-code","page":"Static analyzer annotations for GC correctness in C code","title":"Static analyzer annotations for GC correctness in C code","text":"","category":"section"},{"location":"devdocs/gc-sa/#Running-the-analysis","page":"Static analyzer annotations for GC correctness in C code","title":"Running the analysis","text":"","category":"section"},{"location":"devdocs/gc-sa/","page":"Static analyzer annotations for GC correctness in C code","title":"Static analyzer annotations for GC correctness in C code","text":"The analyzer plugin that drives the anlysis ships with julia. Its source code can be found in src/clangsa. Running it requires the clang dependency to be build. Set the BUILD_LLVM_CLANG variable in your Make.user in order to build an appropriate version of clang. You may also want to use the prebuilt binaries using the USE_BINARYBUILDER_LLVM options. Afterwards, running the analysis over the source tree is as simple as running make -C src analyzegc.","category":"page"},{"location":"devdocs/gc-sa/#General-Overview","page":"Static analyzer annotations for GC correctness in C code","title":"General Overview","text":"","category":"section"},{"location":"devdocs/gc-sa/","page":"Static analyzer annotations for GC correctness in C code","title":"Static analyzer annotations for GC correctness in C code","text":"Since Julia's GC is precise, it needs to maintain correct rooting information for any value that may be referenced at any time GC may occur. These places are known as safepoints and in the function local context, we extend this designation to any function call that may recursively end up at a safepoint.","category":"page"},{"location":"devdocs/gc-sa/","page":"Static analyzer annotations for GC correctness in C code","title":"Static analyzer annotations for GC correctness in C code","text":"In generated code, this is taken care of automatically by the GC root placement pass (see the chapter on GC rooting in the LLVM codegen devdocs). However, in C code, we need to inform the runtime of any GC roots manually. This is done using the following macros:","category":"page"},{"location":"devdocs/gc-sa/","page":"Static analyzer annotations for GC correctness in C code","title":"Static analyzer annotations for GC correctness in C code","text":"// The value assigned to any slot passed as an argument to these\n// is rooted for the duration of this GC frame.\nJL_GC_PUSH{1,...,6}(args...)\n// The values assigned into the size `n` array `rts` are rooted\n// for the duration of this GC frame.\nJL_GC_PUSHARGS(rts, n)\n// Pop a GC frame\nJL_GC_POP","category":"page"},{"location":"devdocs/gc-sa/","page":"Static analyzer annotations for GC correctness in C code","title":"Static analyzer annotations for GC correctness in C code","text":"If these macros are not used where they need to be, or they are used incorrectly, the result is silent memory corruption. As such it is very important that they are placed correctly in all applicable code.","category":"page"},{"location":"devdocs/gc-sa/","page":"Static analyzer annotations for GC correctness in C code","title":"Static analyzer annotations for GC correctness in C code","text":"As such, we employ static analysis (and in particular the clang static analyzer) to help ensure that these macros are used correctly. The remainder of this document gives an overview of this static analysis and describes the support needed in the julia code base to make things work.","category":"page"},{"location":"devdocs/gc-sa/#GC-Invariants","page":"Static analyzer annotations for GC correctness in C code","title":"GC Invariants","text":"","category":"section"},{"location":"devdocs/gc-sa/","page":"Static analyzer annotations for GC correctness in C code","title":"Static analyzer annotations for GC correctness in C code","text":"There is two simple invariants correctness:","category":"page"},{"location":"devdocs/gc-sa/","page":"Static analyzer annotations for GC correctness in C code","title":"Static analyzer annotations for GC correctness in C code","text":"All GC_PUSH calls need to be followed by an appropriate GC_POP (in practice we enforce this at the function level)\nIf a value was previously not rooted at any safepoint, it may no longer be referenced afterwards","category":"page"},{"location":"devdocs/gc-sa/","page":"Static analyzer annotations for GC correctness in C code","title":"Static analyzer annotations for GC correctness in C code","text":"Of course the devil is in the details here. In particular to satisfy the second of the above conditions, we need to know:","category":"page"},{"location":"devdocs/gc-sa/","page":"Static analyzer annotations for GC correctness in C code","title":"Static analyzer annotations for GC correctness in C code","text":"Which calls are safepoints and which are not\nWhich values are rooted at any given safepoint and which are not\nWhen is a value referenced","category":"page"},{"location":"devdocs/gc-sa/","page":"Static analyzer annotations for GC correctness in C code","title":"Static analyzer annotations for GC correctness in C code","text":"For the second point in particular, we need to know which memory locations will be considered rooting at runtime (i.e. values assigned to such locations are rooted). This includes locations explicitly designated as such by passing them to one of the GC_PUSH macros, globally rooted locations and values, as well as any location recursively reachable from one of those locations.","category":"page"},{"location":"devdocs/gc-sa/#Static-Analysis-Algorithm","page":"Static analyzer annotations for GC correctness in C code","title":"Static Analysis Algorithm","text":"","category":"section"},{"location":"devdocs/gc-sa/","page":"Static analyzer annotations for GC correctness in C code","title":"Static analyzer annotations for GC correctness in C code","text":"The idea itself is very simple, although the implementation is quite a bit more complicated (mainly due to a large number of special cases and intricacies of C and C++). In essence, we keep track of all locations that are rooting, all values that are rootable and any expression (assignments, allocations, etc) affect the rootedness of any rootable values. Then, at any safepoint, we perform a \"symbolic GC\" and poison any values that are not rooted at said location. If these values are later referenced, we emit an error.","category":"page"},{"location":"devdocs/gc-sa/","page":"Static analyzer annotations for GC correctness in C code","title":"Static analyzer annotations for GC correctness in C code","text":"The clang static analyzer works by constructing a graph of states and exploring this graph for sources of errors. Several nodes in this graph are generated by the analyzer itself (e.g. for control flow), but the definitions above augment this graph with our own state.","category":"page"},{"location":"devdocs/gc-sa/","page":"Static analyzer annotations for GC correctness in C code","title":"Static analyzer annotations for GC correctness in C code","text":"The static analyzer is interprocedural and can analyze control flow across function boundaries. However, the static analyzer is not fully recursive and makes heuristic decisions about which calls to explore (additionally some calls are cross-translation unit and invisible to the analyzer). In our case, our definition of correctness requires total information. As such, we need to annotate the prototypes of all function calls with whatever information the analysis required, even if that information would otherwise be available by interprocedural static analysis.","category":"page"},{"location":"devdocs/gc-sa/","page":"Static analyzer annotations for GC correctness in C code","title":"Static analyzer annotations for GC correctness in C code","text":"Luckily however, we can still use this interprocedural analysis to ensure that the annotations we place on a given function are indeed correct given the implementation of said function.","category":"page"},{"location":"devdocs/gc-sa/#The-analyzer-annotations","page":"Static analyzer annotations for GC correctness in C code","title":"The analyzer annotations","text":"","category":"section"},{"location":"devdocs/gc-sa/","page":"Static analyzer annotations for GC correctness in C code","title":"Static analyzer annotations for GC correctness in C code","text":"These annotations are found in src/support/analyzer_annotations.h. The are only active when the analyzer is being used and expand either to nothing (for prototype annotations) or to no-ops (for function like annotations).","category":"page"},{"location":"devdocs/gc-sa/#JL_NOTSAFEPOINT","page":"Static analyzer annotations for GC correctness in C code","title":"JL_NOTSAFEPOINT","text":"","category":"section"},{"location":"devdocs/gc-sa/","page":"Static analyzer annotations for GC correctness in C code","title":"Static analyzer annotations for GC correctness in C code","text":"This is perhaps the most common annotation, and should be placed on any function that is known not to possibly lead to reaching a GC safepoint. In general, it is only safe for such a function to perform arithmetic, memory accesses and calls to functions either annotated JL_NOTSAFEPOINT or otherwise known not to be safepoints (e.g. function in the C standard library, which are hardcoded as such in the analyzer)","category":"page"},{"location":"devdocs/gc-sa/","page":"Static analyzer annotations for GC correctness in C code","title":"Static analyzer annotations for GC correctness in C code","text":"It is valid to keep values unrooted across calls to any function annotated with this attribute:","category":"page"},{"location":"devdocs/gc-sa/","page":"Static analyzer annotations for GC correctness in C code","title":"Static analyzer annotations for GC correctness in C code","text":"Usage Example:","category":"page"},{"location":"devdocs/gc-sa/","page":"Static analyzer annotations for GC correctness in C code","title":"Static analyzer annotations for GC correctness in C code","text":"void jl_get_one() JL_NOTSAFEPOINT {\n return 1;\n}\n\njl_value_t *example() {\n jl_value_t *val = jl_alloc_whatever();\n // This is valid, even though `val` is unrooted, because\n // jl_get_one is not a safepoint\n jl_get_one();\n return val;\n}","category":"page"},{"location":"devdocs/gc-sa/#JL_MAYBE_UNROOTED/JL_ROOTS_TEMPORARILY","page":"Static analyzer annotations for GC correctness in C code","title":"JL_MAYBE_UNROOTED/JL_ROOTS_TEMPORARILY","text":"","category":"section"},{"location":"devdocs/gc-sa/","page":"Static analyzer annotations for GC correctness in C code","title":"Static analyzer annotations for GC correctness in C code","text":"When JL_MAYBE_UNROOTED is annotated as an argument on a function, indicates that said argument may be passed, even if it is not rooted. In the ordinary course of events, the julia ABI guarantees that callers root values before passing them to callees. However, some functions do not follow this ABI and allow values to be passed to them even though they are not rooted. Note however, that this does not automatically imply that said argument will be preserved. The ROOTS_TEMPORARILY annotation provides the stronger guarantee that, not only may the value be unrooted when passed, it will also be preserved across any internal safepoints by the callee.","category":"page"},{"location":"devdocs/gc-sa/","page":"Static analyzer annotations for GC correctness in C code","title":"Static analyzer annotations for GC correctness in C code","text":"Note that JL_NOTSAFEPOINT essentially implies JL_MAYBE_UNROOTED/JL_ROOTS_TEMPORARILY, because the rootedness of an argument is irrelevant if the function contains no safepoints.","category":"page"},{"location":"devdocs/gc-sa/","page":"Static analyzer annotations for GC correctness in C code","title":"Static analyzer annotations for GC correctness in C code","text":"One additional point to note is that these annotations apply on both the caller and the callee side. On the caller side, they lift rootedness restrictions that are normally required for julia ABI functions. On the callee side, they have the reverse effect of preventing these arguments from being considered implicitly rooted.","category":"page"},{"location":"devdocs/gc-sa/","page":"Static analyzer annotations for GC correctness in C code","title":"Static analyzer annotations for GC correctness in C code","text":"If either of these annotations is applied to the function as a whole, it applies to all arguments of the function. This should generally only be necessary for varargs functions.","category":"page"},{"location":"devdocs/gc-sa/","page":"Static analyzer annotations for GC correctness in C code","title":"Static analyzer annotations for GC correctness in C code","text":"Usage example:","category":"page"},{"location":"devdocs/gc-sa/","page":"Static analyzer annotations for GC correctness in C code","title":"Static analyzer annotations for GC correctness in C code","text":"JL_DLLEXPORT void JL_NORETURN jl_throw(jl_value_t *e JL_MAYBE_UNROOTED);\njl_value_t *jl_alloc_error();\n\nvoid example() {\n // The return value of the allocation is unrooted. This would normally\n // be an error, but is allowed because of the above annotation.\n jl_throw(jl_alloc_error());\n}","category":"page"},{"location":"devdocs/gc-sa/#JL_PROPAGATES_ROOT","page":"Static analyzer annotations for GC correctness in C code","title":"JL_PROPAGATES_ROOT","text":"","category":"section"},{"location":"devdocs/gc-sa/","page":"Static analyzer annotations for GC correctness in C code","title":"Static analyzer annotations for GC correctness in C code","text":"This annotation is commonly found on accessor functions that return one rootable object stored within another. When annotated on a function argument, it tells the analyzer that the root for that argument also applies to the value returned by the function.","category":"page"},{"location":"devdocs/gc-sa/","page":"Static analyzer annotations for GC correctness in C code","title":"Static analyzer annotations for GC correctness in C code","text":"Usage Example:","category":"page"},{"location":"devdocs/gc-sa/","page":"Static analyzer annotations for GC correctness in C code","title":"Static analyzer annotations for GC correctness in C code","text":"jl_value_t *jl_svecref(jl_svec_t *t JL_PROPAGATES_ROOT, size_t i) JL_NOTSAFEPOINT;\n\nsize_t example(jl_svec_t *svec) {\n jl_value_t *val = jl_svecref(svec, 1)\n // This is valid, because, as annotated by the PROPAGATES_ROOT annotation,\n // jl_svecref propagates the rooted-ness from `svec` to `val`\n jl_gc_safepoint();\n return jl_unbox_long(val);\n}","category":"page"},{"location":"devdocs/gc-sa/#JL_ROOTING_ARGUMENT/JL_ROOTED_ARGUMENT","page":"Static analyzer annotations for GC correctness in C code","title":"JL_ROOTING_ARGUMENT/JL_ROOTED_ARGUMENT","text":"","category":"section"},{"location":"devdocs/gc-sa/","page":"Static analyzer annotations for GC correctness in C code","title":"Static analyzer annotations for GC correctness in C code","text":"This is essentially the assignment counterpart to JL_PROPAGATES_ROOT. When assigning a value to a field of another value that is already rooted, the assigned value will inherit the root of the value it is assigned into.","category":"page"},{"location":"devdocs/gc-sa/","page":"Static analyzer annotations for GC correctness in C code","title":"Static analyzer annotations for GC correctness in C code","text":"Usage Example:","category":"page"},{"location":"devdocs/gc-sa/","page":"Static analyzer annotations for GC correctness in C code","title":"Static analyzer annotations for GC correctness in C code","text":"void jl_svecset(void *t JL_ROOTING_ARGUMENT, size_t i, void *x JL_ROOTED_ARGUMENT) JL_NOTSAFEPOINT\n\n\nsize_t example(jl_svec_t *svec) {\n jl_value_t *val = jl_box_long(10000);\n jl_svecset(svec, val);\n // This is valid, because the annotations imply that the\n // jl_svecset propagates the rooted-ness from `svec` to `val`\n jl_gc_safepoint();\n return jl_unbox_long(val);\n}","category":"page"},{"location":"devdocs/gc-sa/#JL_GC_DISABLED","page":"Static analyzer annotations for GC correctness in C code","title":"JL_GC_DISABLED","text":"","category":"section"},{"location":"devdocs/gc-sa/","page":"Static analyzer annotations for GC correctness in C code","title":"Static analyzer annotations for GC correctness in C code","text":"This annotation implies that this function is only called with the GC runtime-disabled. Functions of this kind are most often encountered during startup and in the GC code itself. Note that this annotation is checked against the runtime enable/disable calls, so clang will know if you lie. This is not a good way to disable processing of a given function if the GC is not actually disabled (use ifdef __clang_analyzer__ for that if you must).","category":"page"},{"location":"devdocs/gc-sa/","page":"Static analyzer annotations for GC correctness in C code","title":"Static analyzer annotations for GC correctness in C code","text":"Usage example:","category":"page"},{"location":"devdocs/gc-sa/","page":"Static analyzer annotations for GC correctness in C code","title":"Static analyzer annotations for GC correctness in C code","text":"void jl_do_magic() JL_GC_DISABLED {\n // Wildly allocate here with no regard for roots\n}\n\nvoid example() {\n int en = jl_gc_enable(0);\n jl_do_magic();\n jl_gc_enable(en);\n}","category":"page"},{"location":"devdocs/gc-sa/#JL_REQUIRE_ROOTED_SLOT","page":"Static analyzer annotations for GC correctness in C code","title":"JL_REQUIRE_ROOTED_SLOT","text":"","category":"section"},{"location":"devdocs/gc-sa/","page":"Static analyzer annotations for GC correctness in C code","title":"Static analyzer annotations for GC correctness in C code","text":"This annotation requires the caller to pass in a slot that is rooted (i.e. values assigned to this slot will be rooted).","category":"page"},{"location":"devdocs/gc-sa/","page":"Static analyzer annotations for GC correctness in C code","title":"Static analyzer annotations for GC correctness in C code","text":"Usage example:","category":"page"},{"location":"devdocs/gc-sa/","page":"Static analyzer annotations for GC correctness in C code","title":"Static analyzer annotations for GC correctness in C code","text":"void jl_do_processing(jl_value_t **slot JL_REQUIRE_ROOTED_SLOT) {\n *slot = jl_box_long(1);\n // Ok, only, because the slot was annotated as rooting\n jl_gc_safepoint();\n}\n\nvoid example() {\n jl_value_t *slot = NULL;\n JL_GC_PUSH1(&slot);\n jl_do_processing(&slot);\n JL_GC_POP();\n}","category":"page"},{"location":"devdocs/gc-sa/#JL_GLOBALLY_ROOTED","page":"Static analyzer annotations for GC correctness in C code","title":"JL_GLOBALLY_ROOTED","text":"","category":"section"},{"location":"devdocs/gc-sa/","page":"Static analyzer annotations for GC correctness in C code","title":"Static analyzer annotations for GC correctness in C code","text":"This annotation implies that a given value is always globally rooted. It can be applied to global variable declarations, in which case it will apply to the value of those variables (or values if the declaration if for an array), or to functions, in which case it will apply to the return value of such functions (e.g. for functions that always return some private, globally rooted value).","category":"page"},{"location":"devdocs/gc-sa/","page":"Static analyzer annotations for GC correctness in C code","title":"Static analyzer annotations for GC correctness in C code","text":"Usage example:","category":"page"},{"location":"devdocs/gc-sa/","page":"Static analyzer annotations for GC correctness in C code","title":"Static analyzer annotations for GC correctness in C code","text":"extern JL_DLLEXPORT jl_datatype_t *jl_any_type JL_GLOBALLY_ROOTED;\njl_ast_context_t *jl_ast_ctx(fl_context_t *fl) JL_GLOBALLY_ROOTED;","category":"page"},{"location":"devdocs/gc-sa/#JL_ALWAYS_LEAFTYPE","page":"Static analyzer annotations for GC correctness in C code","title":"JL_ALWAYS_LEAFTYPE","text":"","category":"section"},{"location":"devdocs/gc-sa/","page":"Static analyzer annotations for GC correctness in C code","title":"Static analyzer annotations for GC correctness in C code","text":"This annotations is essentially equivalent to JL_GLOBALLY_ROOTED, except that is should only be used if those values are globally rooted by virtue of being a leaftype. The rooting of leaftypes is a bit complicated. They are generally rooted through cache field of the corresponding TypeName, which itself is rooted by the containing module (so they're rooted as long as the containing module is ok) and we can generally assume that leaftypes are rooted where they are used, but we may refine this property in the future, so the separate annotation helps split out the reason for being globally rooted.","category":"page"},{"location":"devdocs/gc-sa/","page":"Static analyzer annotations for GC correctness in C code","title":"Static analyzer annotations for GC correctness in C code","text":"The analyzer also automatically detects checks for leaftype-ness and will not complain about missing GC roots on these paths.","category":"page"},{"location":"devdocs/gc-sa/","page":"Static analyzer annotations for GC correctness in C code","title":"Static analyzer annotations for GC correctness in C code","text":"JL_DLLEXPORT jl_value_t *jl_apply_array_type(jl_value_t *type, size_t dim) JL_ALWAYS_LEAFTYPE;","category":"page"},{"location":"devdocs/gc-sa/#JL_GC_PROMISE_ROOTED","page":"Static analyzer annotations for GC correctness in C code","title":"JL_GC_PROMISE_ROOTED","text":"","category":"section"},{"location":"devdocs/gc-sa/","page":"Static analyzer annotations for GC correctness in C code","title":"Static analyzer annotations for GC correctness in C code","text":"This is a function-like annotation. Any value passed to this annotation will be considered rooted for the scope of the current function. It is designed as an escape hatch for analyzer inadequacy or complicated situations. However, it should be used sparingly, in favor of improving the analyzer itself.","category":"page"},{"location":"devdocs/gc-sa/","page":"Static analyzer annotations for GC correctness in C code","title":"Static analyzer annotations for GC correctness in C code","text":"void example() {\n jl_value_t *val = jl_alloc_something();\n if (some_condition) {\n // We happen to know for complicated external reasons\n // that val is rooted under these conditions\n JL_GC_PROMISE_ROOTED(val);\n }\n}","category":"page"},{"location":"devdocs/gc-sa/#Completeness-of-analysis","page":"Static analyzer annotations for GC correctness in C code","title":"Completeness of analysis","text":"","category":"section"},{"location":"devdocs/gc-sa/","page":"Static analyzer annotations for GC correctness in C code","title":"Static analyzer annotations for GC correctness in C code","text":"The analyzer only looks at local information. In particular, e.g. in the PROPAGATES_ROOT case above, it assumes that such memory is only modified in ways it can see, not in any called functions (unless it happens to decide to consider them in its analysis) and not in any concurrently running threads. As such, it may miss a few problematic cases, though in practice such concurrent modification is fairly rare. Improving the analyzer to handle more such cases may be an interesting topic for future work.","category":"page"},{"location":"devdocs/llvm/#Working-with-LLVM","page":"Working with LLVM","title":"Working with LLVM","text":"","category":"section"},{"location":"devdocs/llvm/","page":"Working with LLVM","title":"Working with LLVM","text":"This is not a replacement for the LLVM documentation, but a collection of tips for working on LLVM for Julia.","category":"page"},{"location":"devdocs/llvm/#Overview-of-Julia-to-LLVM-Interface","page":"Working with LLVM","title":"Overview of Julia to LLVM Interface","text":"","category":"section"},{"location":"devdocs/llvm/","page":"Working with LLVM","title":"Working with LLVM","text":"Julia dynamically links against LLVM by default. Build with USE_LLVM_SHLIB=0 to link statically.","category":"page"},{"location":"devdocs/llvm/","page":"Working with LLVM","title":"Working with LLVM","text":"The code for lowering Julia AST to LLVM IR or interpreting it directly is in directory src/.","category":"page"},{"location":"devdocs/llvm/","page":"Working with LLVM","title":"Working with LLVM","text":"File Description\nbuiltins.c Builtin functions\nccall.cpp Lowering ccall\ncgutils.cpp Lowering utilities, notably for array and tuple accesses\ncodegen.cpp Top-level of code generation, pass list, lowering builtins\ndebuginfo.cpp Tracks debug information for JIT code\ndisasm.cpp Handles native object file and JIT code diassembly\ngf.c Generic functions\nintrinsics.cpp Lowering intrinsics\nllvm-simdloop.cpp Custom LLVM pass for @simd\nsys.c I/O and operating system utility functions","category":"page"},{"location":"devdocs/llvm/","page":"Working with LLVM","title":"Working with LLVM","text":"Some of the .cpp files form a group that compile to a single object.","category":"page"},{"location":"devdocs/llvm/","page":"Working with LLVM","title":"Working with LLVM","text":"The difference between an intrinsic and a builtin is that a builtin is a first class function that can be used like any other Julia function. An intrinsic can operate only on unboxed data, and therefore its arguments must be statically typed.","category":"page"},{"location":"devdocs/llvm/#Alias-Analysis","page":"Working with LLVM","title":"Alias Analysis","text":"","category":"section"},{"location":"devdocs/llvm/","page":"Working with LLVM","title":"Working with LLVM","text":"Julia currently uses LLVM's Type Based Alias Analysis. To find the comments that document the inclusion relationships, look for static MDNode* in src/codegen.cpp.","category":"page"},{"location":"devdocs/llvm/","page":"Working with LLVM","title":"Working with LLVM","text":"The -O option enables LLVM's Basic Alias Analysis.","category":"page"},{"location":"devdocs/llvm/#Building-Julia-with-a-different-version-of-LLVM","page":"Working with LLVM","title":"Building Julia with a different version of LLVM","text":"","category":"section"},{"location":"devdocs/llvm/","page":"Working with LLVM","title":"Working with LLVM","text":"The default version of LLVM is specified in deps/Versions.make. You can override it by creating a file called Make.user in the top-level directory and adding a line to it such as:","category":"page"},{"location":"devdocs/llvm/","page":"Working with LLVM","title":"Working with LLVM","text":"LLVM_VER = 12.0.1","category":"page"},{"location":"devdocs/llvm/","page":"Working with LLVM","title":"Working with LLVM","text":"Besides the LLVM release numerals, you can also use LLVM_VER = svn to build against the latest development version of LLVM.","category":"page"},{"location":"devdocs/llvm/","page":"Working with LLVM","title":"Working with LLVM","text":"You can also specify to build a debug version of LLVM, by setting either LLVM_DEBUG = 1 or LLVM_DEBUG = Release in your Make.user file. The former will be a fully unoptimized build of LLVM and the latter will produce an optimized build of LLVM. Depending on your needs the latter will suffice and it quite a bit faster. If you use LLVM_DEBUG = Release you will also want to set LLVM_ASSERTIONS = 1 to enable diagnostics for different passes. Only LLVM_DEBUG = 1 implies that option by default.","category":"page"},{"location":"devdocs/llvm/#Passing-options-to-LLVM","page":"Working with LLVM","title":"Passing options to LLVM","text":"","category":"section"},{"location":"devdocs/llvm/","page":"Working with LLVM","title":"Working with LLVM","text":"You can pass options to LLVM via the environment variable JULIA_LLVM_ARGS. Here are example settings using bash syntax:","category":"page"},{"location":"devdocs/llvm/","page":"Working with LLVM","title":"Working with LLVM","text":"export JULIA_LLVM_ARGS=-print-after-all dumps IR after each pass.\nexport JULIA_LLVM_ARGS=-debug-only=loop-vectorize dumps LLVM DEBUG(...) diagnostics for loop vectorizer. If you get warnings about \"Unknown command line argument\", rebuild LLVM with LLVM_ASSERTIONS = 1.","category":"page"},{"location":"devdocs/llvm/#Debugging-LLVM-transformations-in-isolation","page":"Working with LLVM","title":"Debugging LLVM transformations in isolation","text":"","category":"section"},{"location":"devdocs/llvm/","page":"Working with LLVM","title":"Working with LLVM","text":"On occasion, it can be useful to debug LLVM's transformations in isolation from the rest of the Julia system, e.g. because reproducing the issue inside julia would take too long, or because one wants to take advantage of LLVM's tooling (e.g. bugpoint). To get unoptimized IR for the entire system image, pass the --output-unopt-bc unopt.bc option to the system image build process, which will output the unoptimized IR to an unopt.bc file. This file can then be passed to LLVM tools as usual. libjulia can function as an LLVM pass plugin and can be loaded into LLVM tools, to make julia-specific passes available in this environment. In addition, it exposes the -julia meta-pass, which runs the entire Julia pass-pipeline over the IR. As an example, to generate a system image, one could do:","category":"page"},{"location":"devdocs/llvm/","page":"Working with LLVM","title":"Working with LLVM","text":"opt -load libjulia-internal.so -julia -o opt.bc unopt.bc\nllc -o sys.o opt.bc\ncc -shared -o sys.so sys.o","category":"page"},{"location":"devdocs/llvm/","page":"Working with LLVM","title":"Working with LLVM","text":"This system image can then be loaded by julia as usual.","category":"page"},{"location":"devdocs/llvm/","page":"Working with LLVM","title":"Working with LLVM","text":"It is also possible to dump an LLVM IR module for just one Julia function, using:","category":"page"},{"location":"devdocs/llvm/","page":"Working with LLVM","title":"Working with LLVM","text":"fun, T = +, Tuple{Int,Int} # Substitute your function of interest here\noptimize = false\nopen(\"plus.ll\", \"w\") do file\n println(file, InteractiveUtils._dump_function(fun, T, false, false, false, true, :att, optimize, :default))\nend","category":"page"},{"location":"devdocs/llvm/","page":"Working with LLVM","title":"Working with LLVM","text":"These files can be processed the same way as the unoptimized sysimg IR shown above.","category":"page"},{"location":"devdocs/llvm/#Improving-LLVM-optimizations-for-Julia","page":"Working with LLVM","title":"Improving LLVM optimizations for Julia","text":"","category":"section"},{"location":"devdocs/llvm/","page":"Working with LLVM","title":"Working with LLVM","text":"Improving LLVM code generation usually involves either changing Julia lowering to be more friendly to LLVM's passes, or improving a pass.","category":"page"},{"location":"devdocs/llvm/","page":"Working with LLVM","title":"Working with LLVM","text":"If you are planning to improve a pass, be sure to read the LLVM developer policy. The best strategy is to create a code example in a form where you can use LLVM's opt tool to study it and the pass of interest in isolation.","category":"page"},{"location":"devdocs/llvm/","page":"Working with LLVM","title":"Working with LLVM","text":"Create an example Julia code of interest.\nUse JULIA_LLVM_ARGS=-print-after-all to dump the IR.\nPick out the IR at the point just before the pass of interest runs.\nStrip the debug metadata and fix up the TBAA metadata by hand.","category":"page"},{"location":"devdocs/llvm/","page":"Working with LLVM","title":"Working with LLVM","text":"The last step is labor intensive. Suggestions on a better way would be appreciated.","category":"page"},{"location":"devdocs/llvm/#The-jlcall-calling-convention","page":"Working with LLVM","title":"The jlcall calling convention","text":"","category":"section"},{"location":"devdocs/llvm/","page":"Working with LLVM","title":"Working with LLVM","text":"Julia has a generic calling convention for unoptimized code, which looks somewhat as follows:","category":"page"},{"location":"devdocs/llvm/","page":"Working with LLVM","title":"Working with LLVM","text":"jl_value_t *any_unoptimized_call(jl_value_t *, jl_value_t **, int);","category":"page"},{"location":"devdocs/llvm/","page":"Working with LLVM","title":"Working with LLVM","text":"where the first argument is the boxed function object, the second argument is an on-stack array of arguments and the third is the number of arguments. Now, we could perform a straightforward lowering and emit an alloca for the argument array. However, this would betray the SSA nature of the uses at the call site, making optimizations (including GC root placement), significantly harder. Instead, we emit it as follows:","category":"page"},{"location":"devdocs/llvm/","page":"Working with LLVM","title":"Working with LLVM","text":"%bitcast = bitcast @any_unoptimized_call to %jl_value_t *(*)(%jl_value_t *, %jl_value_t *)\ncall cc 37 %jl_value_t *%bitcast(%jl_value_t *%arg1, %jl_value_t *%arg2)","category":"page"},{"location":"devdocs/llvm/","page":"Working with LLVM","title":"Working with LLVM","text":"The special cc 37 annotation marks the fact that this call site is really using the jlcall calling convention. This allows us to retain the SSA-ness of the uses throughout the optimizer. GC root placement will later lower this call to the original C ABI. In the code the calling convention number is represented by the JLCALL_F_CC constant. In addition, there is the JLCALL_CC calling convention which functions similarly, but omits the first argument.","category":"page"},{"location":"devdocs/llvm/#GC-root-placement","page":"Working with LLVM","title":"GC root placement","text":"","category":"section"},{"location":"devdocs/llvm/","page":"Working with LLVM","title":"Working with LLVM","text":"GC root placement is done by an LLVM pass late in the pass pipeline. Doing GC root placement this late enables LLVM to make more aggressive optimizations around code that requires GC roots, as well as allowing us to reduce the number of required GC roots and GC root store operations (since LLVM doesn't understand our GC, it wouldn't otherwise know what it is and is not allowed to do with values stored to the GC frame, so it'll conservatively do very little). As an example, consider an error path","category":"page"},{"location":"devdocs/llvm/","page":"Working with LLVM","title":"Working with LLVM","text":"if some_condition()\n #= Use some variables maybe =#\n error(\"An error occurred\")\nend","category":"page"},{"location":"devdocs/llvm/","page":"Working with LLVM","title":"Working with LLVM","text":"During constant folding, LLVM may discover that the condition is always false, and can remove the basic block. However, if GC root lowering is done early, the GC root slots used in the deleted block, as well as any values kept alive in those slots only because they were used in the error path, would be kept alive by LLVM. By doing GC root lowering late, we give LLVM the license to do any of its usual optimizations (constant folding, dead code elimination, etc.), without having to worry (too much) about which values may or may not be GC tracked.","category":"page"},{"location":"devdocs/llvm/","page":"Working with LLVM","title":"Working with LLVM","text":"However, in order to be able to do late GC root placement, we need to be able to identify a) which pointers are GC tracked and b) all uses of such pointers. The goal of the GC placement pass is thus simple:","category":"page"},{"location":"devdocs/llvm/","page":"Working with LLVM","title":"Working with LLVM","text":"Minimize the number of needed GC roots/stores to them subject to the constraint that at every safepoint, any live GC-tracked pointer (i.e. for which there is a path after this point that contains a use of this pointer) is in some GC slot.","category":"page"},{"location":"devdocs/llvm/#Representation","page":"Working with LLVM","title":"Representation","text":"","category":"section"},{"location":"devdocs/llvm/","page":"Working with LLVM","title":"Working with LLVM","text":"The primary difficulty is thus choosing an IR representation that allows us to identify GC-tracked pointers and their uses, even after the program has been run through the optimizer. Our design makes use of three LLVM features to achieve this:","category":"page"},{"location":"devdocs/llvm/","page":"Working with LLVM","title":"Working with LLVM","text":"Custom address spaces\nOperand Bundles\nNon-integral pointers","category":"page"},{"location":"devdocs/llvm/","page":"Working with LLVM","title":"Working with LLVM","text":"Custom address spaces allow us to tag every point with an integer that needs to be preserved through optimizations. The compiler may not insert casts between address spaces that did not exist in the original program and it must never change the address space of a pointer on a load/store/etc operation. This allows us to annotate which pointers are GC-tracked in an optimizer-resistant way. Note that metadata would not be able to achieve the same purpose. Metadata is supposed to always be discardable without altering the semantics of the program. However, failing to identify a GC-tracked pointer alters the resulting program behavior dramatically - it'll probably crash or return wrong results. We currently use three different address spaces (their numbers are defined in src/codegen_shared.cpp):","category":"page"},{"location":"devdocs/llvm/","page":"Working with LLVM","title":"Working with LLVM","text":"GC Tracked Pointers (currently 10): These are pointers to boxed values that may be put into a GC frame. It is loosely equivalent to a jl_value_t* pointer on the C side. N.B. It is illegal to ever have a pointer in this address space that may not be stored to a GC slot.\nDerived Pointers (currently 11): These are pointers that are derived from some GC tracked pointer. Uses of these pointers generate uses of the original pointer. However, they need not themselves be known to the GC. The GC root placement pass MUST always find the GC tracked pointer from which this pointer is derived and use that as the pointer to root.\nCallee Rooted Pointers (currently 12): This is a utility address space to express the notion of a callee rooted value. All values of this address space MUST be storable to a GC root (though it is possible to relax this condition in the future), but unlike the other pointers need not be rooted if passed to a call (they do still need to be rooted if they are live across another safepoint between the definition and the call).\nPointers loaded from tracked object (currently 13): This is used by arrays, which themselves contain a pointer to the managed data. This data area is owned by the array, but is not a GC-tracked object by itself. The compiler guarantees that as long as this pointer is live, the object that this pointer was loaded from will keep being live.","category":"page"},{"location":"devdocs/llvm/#Invariants","page":"Working with LLVM","title":"Invariants","text":"","category":"section"},{"location":"devdocs/llvm/","page":"Working with LLVM","title":"Working with LLVM","text":"The GC root placement pass makes use of several invariants, which need to be observed by the frontend and are preserved by the optimizer.","category":"page"},{"location":"devdocs/llvm/","page":"Working with LLVM","title":"Working with LLVM","text":"First, only the following address space casts are allowed:","category":"page"},{"location":"devdocs/llvm/","page":"Working with LLVM","title":"Working with LLVM","text":"0->{Tracked,Derived,CalleeRooted}: It is allowable to decay an untracked pointer to any of the others. However, do note that the optimizer has broad license to not root such a value. It is never safe to have a value in address space 0 in any part of the program if it is (or is derived from) a value that requires a GC root.\nTracked->Derived: This is the standard decay route for interior values. The placement pass will look for these to identify the base pointer for any use.\nTracked->CalleeRooted: Addrspace CalleeRooted serves merely as a hint that a GC root is not required. However, do note that the Derived->CalleeRooted decay is prohibited, since pointers should generally be storable to a GC slot, even in this address space.","category":"page"},{"location":"devdocs/llvm/","page":"Working with LLVM","title":"Working with LLVM","text":"Now let us consider what constitutes a use:","category":"page"},{"location":"devdocs/llvm/","page":"Working with LLVM","title":"Working with LLVM","text":"Loads whose loaded values is in one of the address spaces\nStores of a value in one of the address spaces to a location\nStores to a pointer in one of the address spaces\nCalls for which a value in one of the address spaces is an operand\nCalls in jlcall ABI, for which the argument array contains a value\nReturn instructions.","category":"page"},{"location":"devdocs/llvm/","page":"Working with LLVM","title":"Working with LLVM","text":"We explicitly allow load/stores and simple calls in address spaces Tracked/Derived. Elements of jlcall argument arrays must always be in address space Tracked (it is required by the ABI that they are valid jl_value_t* pointers). The same is true for return instructions (though note that struct return arguments are allowed to have any of the address spaces). The only allowable use of an address space CalleeRooted pointer is to pass it to a call (which must have an appropriately typed operand).","category":"page"},{"location":"devdocs/llvm/","page":"Working with LLVM","title":"Working with LLVM","text":"Further, we disallow getelementptr in addrspace Tracked. This is because unless the operation is a noop, the resulting pointer will not be validly storable to a GC slot and may thus not be in this address space. If such a pointer is required, it should be decayed to addrspace Derived first.","category":"page"},{"location":"devdocs/llvm/","page":"Working with LLVM","title":"Working with LLVM","text":"Lastly, we disallow inttoptr/ptrtoint instructions in these address spaces. Having these instructions would mean that some i64 values are really GC tracked. This is problematic, because it breaks that stated requirement that we're able to identify GC-relevant pointers. This invariant is accomplished using the LLVM \"non-integral pointers\" feature, which is new in LLVM 5.0. It prohibits the optimizer from making optimizations that would introduce these operations. Note we can still insert static constants at JIT time by using inttoptr in address space 0 and then decaying to the appropriate address space afterwards.","category":"page"},{"location":"devdocs/llvm/#Supporting-[ccall](@ref)","page":"Working with LLVM","title":"Supporting ccall","text":"","category":"section"},{"location":"devdocs/llvm/","page":"Working with LLVM","title":"Working with LLVM","text":"One important aspect missing from the discussion so far is the handling of ccall. ccall has the peculiar feature that the location and scope of a use do not coincide. As an example consider:","category":"page"},{"location":"devdocs/llvm/","page":"Working with LLVM","title":"Working with LLVM","text":"A = randn(1024)\nccall(:foo, Cvoid, (Ptr{Float64},), A)","category":"page"},{"location":"devdocs/llvm/","page":"Working with LLVM","title":"Working with LLVM","text":"In lowering, the compiler will insert a conversion from the array to the pointer which drops the reference to the array value. However, we of course need to make sure that the array does stay alive while we're doing the ccall. To understand how this is done, first recall the lowering of the above code:","category":"page"},{"location":"devdocs/llvm/","page":"Working with LLVM","title":"Working with LLVM","text":"return $(Expr(:foreigncall, :(:foo), Cvoid, svec(Ptr{Float64}), 0, :(:ccall), Expr(:foreigncall, :(:jl_array_ptr), Ptr{Float64}, svec(Any), 0, :(:ccall), :(A)), :(A)))","category":"page"},{"location":"devdocs/llvm/","page":"Working with LLVM","title":"Working with LLVM","text":"The last :(A), is an extra argument list inserted during lowering that informs the code generator which Julia level values need to be kept alive for the duration of this ccall. We then take this information and represent it in an \"operand bundle\" at the IR level. An operand bundle is essentially a fake use that is attached to the call site. At the IR level, this looks like so:","category":"page"},{"location":"devdocs/llvm/","page":"Working with LLVM","title":"Working with LLVM","text":"call void inttoptr (i64 ... to void (double*)*)(double* %5) [ \"jl_roots\"(%jl_value_t addrspace(10)* %A) ]","category":"page"},{"location":"devdocs/llvm/","page":"Working with LLVM","title":"Working with LLVM","text":"The GC root placement pass will treat the jl_roots operand bundle as if it were a regular operand. However, as a final step, after the GC roots are inserted, it will drop the operand bundle to avoid confusing instruction selection.","category":"page"},{"location":"devdocs/llvm/#Supporting-[pointer_from_objref](@ref)","page":"Working with LLVM","title":"Supporting pointer_from_objref","text":"","category":"section"},{"location":"devdocs/llvm/","page":"Working with LLVM","title":"Working with LLVM","text":"pointer_from_objref is special because it requires the user to take explicit control of GC rooting. By our above invariants, this function is illegal, because it performs an address space cast from 10 to 0. However, it can be useful, in certain situations, so we provide a special intrinsic:","category":"page"},{"location":"devdocs/llvm/","page":"Working with LLVM","title":"Working with LLVM","text":"declared %jl_value_t *julia.pointer_from_objref(%jl_value_t addrspace(10)*)","category":"page"},{"location":"devdocs/llvm/","page":"Working with LLVM","title":"Working with LLVM","text":"which is lowered to the corresponding address space cast after GC root lowering. Do note however that by using this intrinsic, the caller assumes all responsibility for making sure that the value in question is rooted. Further this intrinsic is not considered a use, so the GC root placement pass will not provide a GC root for the function. As a result, the external rooting must be arranged while the value is still tracked by the system. I.e. it is not valid to attempt to use the result of this operation to establish a global root - the optimizer may have already dropped the value.","category":"page"},{"location":"devdocs/llvm/#Keeping-values-alive-in-the-absence-of-uses","page":"Working with LLVM","title":"Keeping values alive in the absence of uses","text":"","category":"section"},{"location":"devdocs/llvm/","page":"Working with LLVM","title":"Working with LLVM","text":"In certain cases it is necessary to keep an object alive, even though there is no compiler-visible use of said object. This may be case for low level code that operates on the memory-representation of an object directly or code that needs to interface with C code. In order to allow this, we provide the following intrinsics at the LLVM level:","category":"page"},{"location":"devdocs/llvm/","page":"Working with LLVM","title":"Working with LLVM","text":"token @llvm.julia.gc_preserve_begin(...)\nvoid @llvm.julia.gc_preserve_end(token)","category":"page"},{"location":"devdocs/llvm/","page":"Working with LLVM","title":"Working with LLVM","text":"(The llvm. in the name is required in order to be able to use the token type). The semantics of these intrinsics are as follows: At any safepoint that is dominated by a gc_preserve_begin call, but that is not not dominated by a corresponding gc_preserve_end call (i.e. a call whose argument is the token returned by a gc_preserve_begin call), the values passed as arguments to that gc_preserve_begin will be kept live. Note that the gc_preserve_begin still counts as a regular use of those values, so the standard lifetime semantics will ensure that the values will be kept alive before entering the preserve region.","category":"page"},{"location":"manual/variables-and-scoping/#scope-of-variables","page":"变量作用域","title":"变量作用域","text":"","category":"section"},{"location":"manual/variables-and-scoping/","page":"变量作用域","title":"变量作用域","text":"变量的 作用域 是代码的一个区域,在这个区域中这个变量是可见的。给变量划分作用域有助于解决变量命名冲突。这个概念是符合直觉的:两个函数可能同时都有叫做 x 的参量,而这两个 x 并不指向同一个东西。 相似地,也有很多其他的情况,代码的不同块会使用同样名字,但并不指向同一个东西。相同的变量名是否指向同一个东西的规则被称为作用域规则;这一节会详细地把这个规则讲清楚。","category":"page"},{"location":"manual/variables-and-scoping/","page":"变量作用域","title":"变量作用域","text":"语言中的某些结构会引入作用域块,这是可以成为一些变量集合的作用域的代码区域。一个变量的作用域不是源代码行的任意集合;相反,它始终与这些块之一关系密切。在 Julia 中主要有两种作用域,全局作用域 与 局部作用域,后者可以嵌套。 在 Julia 中还存在引入“硬作用域”的构造和只引入“软作用域”的构造之间的区别,这影响到是否允许以相同的名称遮蔽全局变量。","category":"page"},{"location":"manual/variables-and-scoping/#man-scope-table","page":"变量作用域","title":"作用域结构","text":"","category":"section"},{"location":"manual/variables-and-scoping/","page":"变量作用域","title":"变量作用域","text":"引入作用域块的结构有:","category":"page"},{"location":"manual/variables-and-scoping/","page":"变量作用域","title":"变量作用域","text":"结构 作用域类型 允许使用在\nmodule, baremodule 全局 全局\nstruct 局部(软) 全局\nfor, while, try 局部(软) global, local\nmacro 局部(硬) 全局\n函数, do 语句块, let语句块, 数组推导, 生成器 局部(硬) global, local","category":"page"},{"location":"manual/variables-and-scoping/","page":"变量作用域","title":"变量作用域","text":"值得注意的是,这个表内没有的是 begin 块和 if 块,这两个块不会引进新的作用域块。这两种作用域遵循的规则有点不一样,会在下面解释。","category":"page"},{"location":"manual/variables-and-scoping/","page":"变量作用域","title":"变量作用域","text":"Julia 使用词法作用域,也就是说一个函数的作用域不继承自调用了函数的调用者作用域,而继承自该函数定义处作用域。举例如下,foo 中的 x 指向模块 Bar 的全局作用域中 x。","category":"page"},{"location":"manual/variables-and-scoping/","page":"变量作用域","title":"变量作用域","text":"julia> module Bar\n x = 1\n foo() = x\n end;","category":"page"},{"location":"manual/variables-and-scoping/","page":"变量作用域","title":"变量作用域","text":"而非调用了 foo 的作用域中的 x:","category":"page"},{"location":"manual/variables-and-scoping/","page":"变量作用域","title":"变量作用域","text":"julia> import .Bar\n\njulia> x = -1;\n\njulia> Bar.foo()\n1","category":"page"},{"location":"manual/variables-and-scoping/","page":"变量作用域","title":"变量作用域","text":"因此词法作用域意味着,某段代码内某变量的指向只从它出现之处就可以推断出来,而不依赖于程序的执行方式。在嵌套的作用域结构里,内层作用域能”看“到所有外层作用域内变量。相对地,外层作用域不能看到内层作用域的变量。","category":"page"},{"location":"manual/variables-and-scoping/#全局作用域","page":"变量作用域","title":"全局作用域","text":"","category":"section"},{"location":"manual/variables-and-scoping/","page":"变量作用域","title":"变量作用域","text":"每个模块会引进一个新全局作用域,与其他所有模块的全局作用域分开;无所不包的全局作用域不存在。模块可以把其他模块的变量引入到它的作用域中,通过using 或者 import语句或者通过点符号这种有资格的通路,也就是说每个模块都是所谓的命名空间或者关联着含值的名字的第一类数据结构。值得注意的是,即便变量绑定能在外部被读取,变量绑定也只能在它们的全局作用域中改变。 作为一个逃生窗口,你总是可以执行该模块内代码来修改一个变量;这特别保证了不调用 eval 的外部代码绝不会修改模块绑定。","category":"page"},{"location":"manual/variables-and-scoping/","page":"变量作用域","title":"变量作用域","text":"julia> module A\n a = 1 # a global in A's scope\n end;\n\njulia> module B\n module C\n c = 2\n end\n b = C.c # can access the namespace of a nested global scope\n # through a qualified access\n import ..A # makes module A available\n d = A.a\n end;\n\njulia> module D\n b = a # errors as D's global scope is separate from A's\n end;\nERROR: UndefVarError: a not defined\n\njulia> module E\n import ..A # make module A available\n A.a = 2 # throws below error\n end;\nERROR: cannot assign variables in other modules","category":"page"},{"location":"manual/variables-and-scoping/","page":"变量作用域","title":"变量作用域","text":"注意交互式提示行(即REPL)是在模块Main的全局作用域中。","category":"page"},{"location":"manual/variables-and-scoping/#局部作用域","page":"变量作用域","title":"局部作用域","text":"","category":"section"},{"location":"manual/variables-and-scoping/","page":"变量作用域","title":"变量作用域","text":"大多数代码块都引入了新的局部作用域(完整列表请参见上表)。如果这样的代码块在语法上嵌套在另一个局部作用域内,则它创建的作用域嵌套在它出现的所有局部作用域内,这些局部作用域最终都嵌套在评估代码的模块的全局作用域内。 外部作用域中的变量在它们包含的任何作用域中都是可见的——这意味着它们可以在内部作用域中读取和写入——除非有一个同名的局部变量“遮蔽”了同名的外部变量。 即使外部的本地变量是在内部块之后(在下面的文本意义上)声明的,也是如此。 当我们说一个变量在给定范围内“存在”时,这意味着具有该名称的变量存在于当前范围嵌套在其中的任何范围内,包括当前范围。","category":"page"},{"location":"manual/variables-and-scoping/","page":"变量作用域","title":"变量作用域","text":"一些编程语言需要在使用新变量之前显式声明它们。显式声明也适用于 Julia:在任何局部作用域中,编写 local x 都会在该作用域中声明一个新的局部变量,无论外部作用域中是否已经存在名为 x 的变量。像这样声明每个新变量有点冗长乏味,但是,与许多其他语言一样,Julia 考虑对不存在的变量名称进行赋值以隐式声明该变量。如果当前作用域是全局的,则新变量是全局的;如果当前作用域是局部的,则新变量对最内部的局部作用域是局部的,并且在该作用域内可见,但在该作用域外不可见。如果你给现有的局部变量赋值,它总是更新现有的局部变量:你只能通过使用 local 关键字在嵌套范围内显式声明新的局部变量来隐藏原局部变量。特别是,这适用于在内部函数中分配的变量,这可能会让来自 Python 的用户感到惊讶,其中内部函数中的赋值会创建一个新的局部变量,除非该变量被明确声明为非局部变量。","category":"page"},{"location":"manual/variables-and-scoping/","page":"变量作用域","title":"变量作用域","text":"大多数情况下,这是非常直观的,但与许多直觉行为一样,细节比人们天真地想象的要微妙得多。","category":"page"},{"location":"manual/variables-and-scoping/","page":"变量作用域","title":"变量作用域","text":"当 x = 出现在某局部作用域,Julia 根据赋值表达式出现位置、 x 在此处已经引用的内容,采取如下规则确定表达式的意义:","category":"page"},{"location":"manual/variables-and-scoping/","page":"变量作用域","title":"变量作用域","text":"现存的局部变量:如果 x 已经是一个局部变量,那现存的局部变量 x 将被 赋值;\n**硬作用域:如果 x 还不是局部变量并且赋值发生的作用域结构是硬作用域(即在 let 语句块、函数体、宏、推导式或生成器中),则会在赋值作用域中创建一个名为 x 的新局部变量;\n软作用域:如果 x 并非已经是局部变量,并且所有包含 此次赋值的作用域结构是软作用域(循环、try/catch 块、或者 struct 块), 最后行为取决于全局变量 x 是否被定义:\n如果全局变量 x 是未定义,最终此次赋值会在该作用域创建一个名为 x 的新局部变量 ;\n如果全局变量 x 是已定义,此次赋值会被认为是有歧义的:\n在非交互的上下文(文件、eval)中,会打印一个有歧义警告,同时创建一个新 局部变量;\n在交互的上下文(REPL, notebooks)中,会向全局变量 x 赋值。","category":"page"},{"location":"manual/variables-and-scoping/","page":"变量作用域","title":"变量作用域","text":"你或许注意到,当某隐性局部变量(比如未经 local x 声明)遮掩某全局变量,非交互的上下文中硬作用域和软作用域有相同行为,除了会输出警告。方便起见,交互的上下文遵从一套更复杂的启发式规则。下面的例子将会深入讲解。","category":"page"},{"location":"manual/variables-and-scoping/","page":"变量作用域","title":"变量作用域","text":"既然你知道这个规则,那就看看一些例子。每个例子都是一个新的REPL会话中进行的,因此每个片段中唯一的全局变量就是在该代码块中分配的全局变量。","category":"page"},{"location":"manual/variables-and-scoping/","page":"变量作用域","title":"变量作用域","text":"我们将从一个良好且明确的情况开始——在一个硬作用域内赋值,在这个情况下是一个函数体,当同名的局部变量不存在时:","category":"page"},{"location":"manual/variables-and-scoping/","page":"变量作用域","title":"变量作用域","text":"julia> function greet()\n x = \"hello\" # new local\n println(x)\n end\ngreet (generic function with 1 method)\n\njulia> greet()\nhello\n\njulia> x # global\nERROR: UndefVarError: x not defined","category":"page"},{"location":"manual/variables-and-scoping/","page":"变量作用域","title":"变量作用域","text":"在 greet 函数内部,赋值 x = \"hello\" 导致 x 成为函数作用域中的一个新局部变量。 有两个相关的事实:赋值发生在局部作用域内,并且没有现有的局部 x 变量。 由于 x 是局部的,所以是否存在名为 x 的全局变量并不重要。 例如,我们在定义和调用 greet 之前定义了 x = 123:","category":"page"},{"location":"manual/variables-and-scoping/","page":"变量作用域","title":"变量作用域","text":"julia> x = 123 # global\n123\n\njulia> function greet()\n x = \"hello\" # new local\n println(x)\n end\ngreet (generic function with 1 method)\n\njulia> greet()\nhello\n\njulia> x # global\n123","category":"page"},{"location":"manual/variables-and-scoping/","page":"变量作用域","title":"变量作用域","text":"由于 greet 中的 x 是局部的,全局 x 的值(或缺少值)不会受到调用 greet 的影响。 硬作用域规则不关心名为 x 的全局变量是否存在:在硬作用域中对 x 的赋值是局部的(除非 x 被声明为全局的)。","category":"page"},{"location":"manual/variables-and-scoping/","page":"变量作用域","title":"变量作用域","text":"我们将考虑的下一个明确的情况是已经有一个名为x的局部变量,在这种情况下,x = 1总是赋值给这个现有的局部x。 无论赋值发生在同一局部作用域、同一函数体的内部局部作用域,还是嵌套在另一个函数内部的函数体(也称为 闭包)。","category":"page"},{"location":"manual/variables-and-scoping/","page":"变量作用域","title":"变量作用域","text":"我们将使用 sum_to 函数,它计算从 1 到 n 的整数之和,例如:","category":"page"},{"location":"manual/variables-and-scoping/","page":"变量作用域","title":"变量作用域","text":"function sum_to(n)\n s = 0 # new local\n for i = 1:n\n s = s + i # assign existing local\n end\n return s # same local\nend","category":"page"},{"location":"manual/variables-and-scoping/","page":"变量作用域","title":"变量作用域","text":"与前面的示例一样,在 sum_to 函数先对 s 的第一次赋值导致 s 成为函数体中的一个新局部变量。 for 循环在函数作用域内有自己的内部局部作用域。 在 s = s + i 出现的地方,s 已经是一个局部变量,所以赋值更新了现有的 s 而不是创建一个新的局部变量。 我们可以通过在 REPL 中调用 sum_to 来测试:","category":"page"},{"location":"manual/variables-and-scoping/","page":"变量作用域","title":"变量作用域","text":"julia> function sum_to(n)\n s = 0 # new local\n for i = 1:n\n s = s + i # assign existing local\n end\n return s # same local\n end\nsum_to (generic function with 1 method)\n\njulia> sum_to(10)\n55\n\njulia> s # global\nERROR: UndefVarError: s not defined","category":"page"},{"location":"manual/variables-and-scoping/","page":"变量作用域","title":"变量作用域","text":"由于 s 是函数 sum_to 的局部变量,调用该函数对全局变量 s 没有影响。 我们还可以看到,for 循环中的更新 s = s + i 必须更新由初始化 s = 0 创建的相同 s,因为我们得到了整数 1 到 10 的正确总和 55。","category":"page"},{"location":"manual/variables-and-scoping/","page":"变量作用域","title":"变量作用域","text":"让我们通过编写一个稍微详细一点的变体来深入了解一下 for 循环体有自己的作用域,我们将其称为 sum_to_def,其中,在更新 s 之前,我们将和 s + i 保存在一个变量中t :","category":"page"},{"location":"manual/variables-and-scoping/","page":"变量作用域","title":"变量作用域","text":"julia> function sum_to_def(n)\n s = 0 # new local\n for i = 1:n\n t = s + i # new local `t`\n s = t # assign existing local `s`\n end\n return s, @isdefined(t)\n end\nsum_to_def (generic function with 1 method)\n\njulia> sum_to_def(10)\n(55, false)","category":"page"},{"location":"manual/variables-and-scoping/","page":"变量作用域","title":"变量作用域","text":"这个版本像先前一样返回 s,但它也使用 @isdefined 宏返回一个布尔值,指示是否在函数的最外层局部作用域中定义了一个名为 t 的局部变量。 正如你所看到的,在 for 循环体之外没有定义 t。 这又是因为硬作用域规则:由于对 t 的赋值发生在一个函数内部,这引入了一个硬作用域,赋值导致 t 在它出现的局部作用域中成为一个新的局部变量,即循环体内部。 即使有一个名为 t 的全局变量,它也没有任何区别——硬作用域规则不受全局作用域中的任何内容的影响。","category":"page"},{"location":"manual/variables-and-scoping/","page":"变量作用域","title":"变量作用域","text":"请注意,for 循环体的局部作用域与内部函数的局部作用域没有区别。 这意味着我们可以重写此示例,以便将循环体实现为对内部辅助函数的调用,并且其行为方式相同:","category":"page"},{"location":"manual/variables-and-scoping/","page":"变量作用域","title":"变量作用域","text":"julia> function sum_to_def_closure(n)\n function loop_body(i)\n t = s + i # new local `t`\n s = t # assign same local `s` as below\n end\n s = 0 # new local\n for i = 1:n\n loop_body(i)\n end\n return s, @isdefined(t)\n end\nsum_to_def_closure (generic function with 1 method)\n\njulia> sum_to_def_closure(10)\n(55, false)","category":"page"},{"location":"manual/variables-and-scoping/","page":"变量作用域","title":"变量作用域","text":"这个例子说明了几个要点:","category":"page"},{"location":"manual/variables-and-scoping/","page":"变量作用域","title":"变量作用域","text":"内部函数作用域就像任何其他嵌套的局部作用域一样。 特别是,如果一个变量已经是内部函数之外的局部变量,并且你在内部函数中为其赋值,则外部局部变量会被更新。\n外部的局部变量的定义是否发生在更新位置的下方并不重要,规则保持不变。在解析内部的局部变量含义之前,解析整个封闭局部作用域并确定其局部变量。","category":"page"},{"location":"manual/variables-and-scoping/","page":"变量作用域","title":"变量作用域","text":"这种设计意味着你通常可以将代码移入或移出内部函数而不改变其含义,这给使用闭包语言中的许多常见习语提供了便利。(参见 do blocks)。","category":"page"},{"location":"manual/variables-and-scoping/","page":"变量作用域","title":"变量作用域","text":"让我们继续讨论软作用域规则涵盖的一些更模糊的情况。 我们将通过将 greet 和 sum_to_def函数的主体提取到软作用域上下文中来探索这一点。 首先,让我们将 greet 的主体放在一个 for 循环中——它是软的,而不是硬的——并在 REPL 中运行:","category":"page"},{"location":"manual/variables-and-scoping/","page":"变量作用域","title":"变量作用域","text":"julia> for i = 1:3\n x = \"hello\" # new local\n println(x)\n end\nhello\nhello\nhello\n\njulia> x\nERROR: UndefVarError: x not defined","category":"page"},{"location":"manual/variables-and-scoping/","page":"变量作用域","title":"变量作用域","text":"由于在执行for循环时未定义全局变量x,因此软作用域规则的第一个子句适用,并且x被创建为for循环内的局部变量,因此循环执行完后全局变量x一直没有定义 。 接下来,让我们考虑提取到全局作用域内的 sum_to_def 的函数体,将其参数固定为 n = 10","category":"page"},{"location":"manual/variables-and-scoping/","page":"变量作用域","title":"变量作用域","text":"s = 0\nfor i = 1:10\n t = s + i\n s = t\nend\ns\n@isdefined(t)","category":"page"},{"location":"manual/variables-and-scoping/","page":"变量作用域","title":"变量作用域","text":"这段代码有什么作用? 提示:这是一个小把戏。 答案是“视情况而定”。 如果此代码以交互方式输入,则其行为方式与在函数体中的行为方式相同。 但是如果代码出现在文件中,它会打印一个歧义警告并抛出一个未定义的变量错误。 让我们先看看它在 REPL 中的情况:","category":"page"},{"location":"manual/variables-and-scoping/","page":"变量作用域","title":"变量作用域","text":"julia> s = 0 # global\n0\n\njulia> for i = 1:10\n t = s + i # new local `t`\n s = t # assign global `s`\n end\n\njulia> s # global\n55\n\njulia> @isdefined(t) # global\nfalse","category":"page"},{"location":"manual/variables-and-scoping/","page":"变量作用域","title":"变量作用域","text":"REPL 内行为接近于函数体内,决定循环内部的赋值是分配给一个全局变量还是创建新的局部变量,取决于是否定义了具有该名称的全局变量。 如果存在同名的全局变量,则赋值会更新它。 如果不存在全局变量,则赋值会创建一个新的局部变量。 在这个例子中,我们看到两种情况都在起作用:","category":"page"},{"location":"manual/variables-and-scoping/","page":"变量作用域","title":"变量作用域","text":"没有名为 t 的全局变量,因此 t = s + i 创建了一个新的 t,它是 for 循环的局部变量;\n有一个名为 s 的全局变量,因此将 s = t 赋值给它。","category":"page"},{"location":"manual/variables-and-scoping/","page":"变量作用域","title":"变量作用域","text":"第二个情况解释了为什么循环的执行会改变 s 的全局值,第一个情况解释了为什么在循环执行后 t 仍未定义。 现在,让我们尝试运行相同的代码,就像它在文件中一样:","category":"page"},{"location":"manual/variables-and-scoping/","page":"变量作用域","title":"变量作用域","text":"julia> code = \"\"\"\n s = 0 # global\n for i = 1:10\n t = s + i # new local `t`\n s = t # new local `s` with warning\n end\n s, # global\n @isdefined(t) # global\n \"\"\";\n\njulia> include_string(Main, code)\n┌ Warning: Assignment to `s` in soft scope is ambiguous because a global variable by the same name exists: `s` will be treated as a new local. Disambiguate by using `local s` to suppress this warning or `global s` to assign to the existing global variable.\n└ @ string:4\nERROR: LoadError: UndefVarError: s not defined","category":"page"},{"location":"manual/variables-and-scoping/","page":"变量作用域","title":"变量作用域","text":"这里我们使用 include_string 来评估 code,就好像它是文件的内容一样。 我们也可以将 code 保存到一个文件中,然后对该文件调用 include——结果是一样的。 如你所见,这与在 REPL 中评估相同代码的行为完全不同。 让我们分解一下这里发生的事情:","category":"page"},{"location":"manual/variables-and-scoping/","page":"变量作用域","title":"变量作用域","text":"在循环运行之前,全局 s 被定义为值 0\n赋值 s = t 发生在软作用域中——任何函数体或其他硬作用域结构之外的 for 循环\n因此软作用域规则的第二个子句适用,并且分配不明确,因此发出警告\n继续执行,使 s 成为 for 循环体中的局部作用域\n由于 s 是 for 循环的局部变量,所以在计算 t = s + i 时它是未定义的,从而导致错误\n求值到此就结束了,但如果到了 s 和 @isdefined(t),它将返回 0 和 false。","category":"page"},{"location":"manual/variables-and-scoping/","page":"变量作用域","title":"变量作用域","text":"这展示了作用域的一些重要方面:在一个作用域中,每个变量只能有一个含义,而该含义的确定与表达式的顺序无关。 循环中表达式 s = t 的存在导致 s 在循环中是局部的,这意味着当它出现在 t = s + i 的右侧时它也是局部的,即使该表达式首先出现并首先计算。 有人可能会想象循环第一行上的 s 可以是全局的,而循环第二行上的 s 是局部的,但这是不可能的,因为这两行在同一个作用域块中并且每个变量 在给定的作用域内只能有一种含义。","category":"page"},{"location":"manual/variables-and-scoping/#在软作用域","page":"变量作用域","title":"在软作用域","text":"","category":"section"},{"location":"manual/variables-and-scoping/","page":"变量作用域","title":"变量作用域","text":"我们现在已经涵盖了所有局部作用域规则,但在结束本节之前,也许应该说几句关于为什么在交互式和非交互式上下文中处理模糊软作用域的情况不同。 人们可以问两个明显的问题:","category":"page"},{"location":"manual/variables-and-scoping/","page":"变量作用域","title":"变量作用域","text":"为什么不都像REPL那样?\n为什么不都表现得像在文件中那样?并跳过警告?","category":"page"},{"location":"manual/variables-and-scoping/","page":"变量作用域","title":"变量作用域","text":"在 Julia ≤ 0.6 的版本中,所有全局作用域确实像当前的 REPL 一样工作:当 x = 发生在循环中(或 try/catch ,struct内)但在函数体(或 let 语句块或推导式)之外时,它根据是否定义了一个名为 x 的全局变量来决定 x 是否应该是循环的局部变量。这种行为具有直观和方便的优点,因为它尽可能接近函数体内部的行为。特别是,当尝试调试函数时,它可以轻松地在函数体和 REPL 之间来回移动代码。 但是,它有一些缺点。首先,这是一种相当复杂的行为:多年来,许多人对这种行为感到困惑,并抱怨说它既复杂又难以解释和理解。这是有道理的。其次,可以说更糟的是,它不利于“大规模”编程。 当你在这样的地方看到一小段代码时,很清楚发生了什么:","category":"page"},{"location":"manual/variables-and-scoping/","page":"变量作用域","title":"变量作用域","text":"s = 0\nfor i = 1:10\n s += i\nend","category":"page"},{"location":"manual/variables-and-scoping/","page":"变量作用域","title":"变量作用域","text":"显然,代码的意图是修改现有的全局变量s。 这还能是什么意思? 然而,并非所有现实世界的代码都如此简短或清晰。 我们发现像下面这样的代码经常出现:","category":"page"},{"location":"manual/variables-and-scoping/","page":"变量作用域","title":"变量作用域","text":"x = 123\n\n# much later\n# maybe in a different file\n\nfor i = 1:10\n x = \"hello\"\n println(x)\nend\n\n# much later\n# maybe in yet another file\n# or maybe back in the first one where `x = 123`\n\ny = x + 234","category":"page"},{"location":"manual/variables-and-scoping/","page":"变量作用域","title":"变量作用域","text":"我们非常不清楚这里应该发生什么。 由于 x + \"hello\" 是一个方法错误,似乎意图是让 x 在 for 循环中是局部的。 但是运行时值和碰巧存在的方法不能用于确定变量的范围。 对于 Julia ≤ 0.6 的行为,尤其令人担忧的是,有人可能先编写了 for 循环,让它工作得很好,但后来当其他人在远处添加了一个新的全局时——可能是在不同的文件——代码突然改变了含义,要么中断,要么更糟糕的是,默默地做执行了错误的命令。 这种 “幽灵般的远距离动作” 是好的编程语言设计应该防止的。","category":"page"},{"location":"manual/variables-and-scoping/","page":"变量作用域","title":"变量作用域","text":"因此,在 Julia 1.0 中,我们简化了作用域的规则:在任何局部作用域中,对一个还不是局部变量的名称进行赋值会创建一个新的局部变量。 这完全消除了软作用域的概念,并消除了幽灵行为的可能性。 由于移除了软作用域,我们发现并修复了大量错误,证明我们选择摆脱它是正确的。我们有很多的欣喜! 嗯,不,不是真的。 因为有些人很生气,他们现在不得不写:","category":"page"},{"location":"manual/variables-and-scoping/","page":"变量作用域","title":"变量作用域","text":"s = 0\nfor i = 1:10\n global s += i\nend","category":"page"},{"location":"manual/variables-and-scoping/","page":"变量作用域","title":"变量作用域","text":"你看到那里的global注解了吗?非常令人讨厌。 显然,这种情况是不能容忍的。但更严重的是,这种需要global顶层代码的情况有两个主要问题:","category":"page"},{"location":"manual/variables-and-scoping/","page":"变量作用域","title":"变量作用域","text":"从函数体内部复制和粘贴代码到 REPL 来debug不再方便——你必须加上global注释,然后把它删了再复制回去。\n初学者编写这种代码往往不会加 global ,并且不知道为什么他们的代码不起作用 - 他们得到的错误是 s 未定义,这似乎并没有启发犯错的人。","category":"page"},{"location":"manual/variables-and-scoping/","page":"变量作用域","title":"变量作用域","text":"从 Julia 1.5 开始,此代码在 REPL 或 Jupyter 笔记本(就像 Julia 0.6)等交互式上下文中无需global注解即可正确执行,同时,在文件和其他非交互式上下文中,它会打印出以下非常直接的警告:","category":"page"},{"location":"manual/variables-and-scoping/","page":"变量作用域","title":"变量作用域","text":"在软作用域中对 s 的赋值是不明确的,因为存在同名的全局变量:s 将被视为新的局部变量。 通过使用 local s 来消除此警告或使用 global s 赋值给现有的全局变量来消除歧义。","category":"page"},{"location":"manual/variables-and-scoping/","page":"变量作用域","title":"变量作用域","text":"这解决了这两个问题,同时保留了 1.0 行为的“大规模编程”好处:全局变量对可能很远的代码的含义没有幽灵般的影响; 在 REPL 复制粘贴调试工作,初学者没有任何问题; 任何时候有人忘记global注解或不小心用软作用域中的局部变量遮蔽了现有的全局变量,这无论如何都会令人困惑,他们会得到一个很好的明确警告。","category":"page"},{"location":"manual/variables-and-scoping/","page":"变量作用域","title":"变量作用域","text":"这种设计的一个重要特点是,在没有警告的情况下在文件中执行的任何代码在新的 REPL 中的行为方式相同。 另一方面,如果您使用 REPL 会话并将其保存到文件中,如果它的行为与 REPL 中的行为不同,那么您将收到警告。","category":"page"},{"location":"manual/variables-and-scoping/#Let-块","page":"变量作用域","title":"Let 块","text":"","category":"section"},{"location":"manual/variables-and-scoping/","page":"变量作用域","title":"变量作用域","text":"let 语句创建一个新的 硬作用域 块(见上文)并在每次运行时引入新的变量绑定。 赋值可能会为现有值地址重新分配一个新值,而 let 总是会创建一个新地址。 这种差异通常并不重要,并且只有在通过闭包超出其作用域的变量的情况下才能检测到。 let 语法接受以逗号分隔的一系列赋值和变量名:","category":"page"},{"location":"manual/variables-and-scoping/","page":"变量作用域","title":"变量作用域","text":"julia> x, y, z = -1, -1, -1;\n\njulia> let x = 1, z\n println(\"x: $x, y: $y\") # x is local variable, y the global\n println(\"z: $z\") # errors as z has not been assigned yet but is local\n end\nx: 1, y: -1\nERROR: UndefVarError: z not defined","category":"page"},{"location":"manual/variables-and-scoping/","page":"变量作用域","title":"变量作用域","text":"赋值将按次序执行:作用域右侧先于左侧引入新变量前被执行。这使得类似 let x = x 的写法是有意义的,因为这两个 x 变量并不一样,拥有不同存储位置。let 的行为在如下例子中是必要的:","category":"page"},{"location":"manual/variables-and-scoping/","page":"变量作用域","title":"变量作用域","text":"julia> Fs = Vector{Any}(undef, 2); i = 1;\n\njulia> while i <= 2\n Fs[i] = ()->i\n global i += 1\n end\n\njulia> Fs[1]()\n3\n\njulia> Fs[2]()\n3","category":"page"},{"location":"manual/variables-and-scoping/","page":"变量作用域","title":"变量作用域","text":"在这里,我们创建并存储了两个返回变量 i 的闭包。但是因为始终是同一个变量i,所以这两个闭包行为是相同的。我们可以使用 let 为 i 创建新绑定:","category":"page"},{"location":"manual/variables-and-scoping/","page":"变量作用域","title":"变量作用域","text":"julia> Fs = Vector{Any}(undef, 2); i = 1;\n\njulia> while i <= 2\n let i = i\n Fs[i] = ()->i\n end\n global i += 1\n end\n\njulia> Fs[1]()\n1\n\njulia> Fs[2]()\n2","category":"page"},{"location":"manual/variables-and-scoping/","page":"变量作用域","title":"变量作用域","text":"由于 begin 结构不会引入新的作用域,使用零参数 let 来引入一个新的作用域块而不立即创建任何新的绑定是很有用的:","category":"page"},{"location":"manual/variables-and-scoping/","page":"变量作用域","title":"变量作用域","text":"julia> let\n local x = 1\n let\n local x = 2\n end\n x\n end\n1","category":"page"},{"location":"manual/variables-and-scoping/","page":"变量作用域","title":"变量作用域","text":"由于let 引入了一个新的作用域块,内部局部变量x 与外部局部变量x 是一个不同的变量。这个特定的例子相当于:","category":"page"},{"location":"manual/variables-and-scoping/","page":"变量作用域","title":"变量作用域","text":"julia> let x = 1\n let x = 2\n end\n x\n end\n1","category":"page"},{"location":"manual/variables-and-scoping/#循环和数组推导","page":"变量作用域","title":"循环和数组推导","text":"","category":"section"},{"location":"manual/variables-and-scoping/","page":"变量作用域","title":"变量作用域","text":"对于循环和数组推导:在其内部作用域中引入的新变量在每次循环迭代中都会被新分配一块内存,如同被 let 块包围。","category":"page"},{"location":"manual/variables-and-scoping/","page":"变量作用域","title":"变量作用域","text":"julia> Fs = Vector{Any}(undef, 2);\n\njulia> for j = 1:2\n Fs[j] = ()->j\n end\n\njulia> Fs[1]()\n1\n\njulia> Fs[2]()\n2","category":"page"},{"location":"manual/variables-and-scoping/","page":"变量作用域","title":"变量作用域","text":"for 循环或者推导式的迭代变量始终是个新变量:","category":"page"},{"location":"manual/variables-and-scoping/","page":"变量作用域","title":"变量作用域","text":"julia> function f()\n i = 0\n for i = 1:3\n # empty\n end\n return i\n end;\n\njulia> f()\n0","category":"page"},{"location":"manual/variables-and-scoping/","page":"变量作用域","title":"变量作用域","text":"但是偶然地,把一个已有的局部变量作为迭代变量也是有用的。 添加关键字 outer 就能方便地做到:","category":"page"},{"location":"manual/variables-and-scoping/","page":"变量作用域","title":"变量作用域","text":"julia> function f()\n i = 0\n for outer i = 1:3\n # empty\n end\n return i\n end;\n\njulia> f()\n3","category":"page"},{"location":"manual/variables-and-scoping/#常量","page":"变量作用域","title":"常量","text":"","category":"section"},{"location":"manual/variables-and-scoping/","page":"变量作用域","title":"变量作用域","text":"变量普遍地用于命名一个特定、不变的值。这些变量只被赋值一次。向编译器传递 const 关键字,即可声明这个意图:","category":"page"},{"location":"manual/variables-and-scoping/","page":"变量作用域","title":"变量作用域","text":"julia> const e = 2.71828182845904523536;\n\njulia> const pi = 3.14159265358979323846;","category":"page"},{"location":"manual/variables-and-scoping/","page":"变量作用域","title":"变量作用域","text":"单个 const 关键字能同时声明多个变量:","category":"page"},{"location":"manual/variables-and-scoping/","page":"变量作用域","title":"变量作用域","text":"julia> const a, b = 1, 2\n(1, 2)","category":"page"},{"location":"manual/variables-and-scoping/","page":"变量作用域","title":"变量作用域","text":"const 声明只应使用在全局作用域中的全局变量。因为全局变量的值(甚至类型)可以随时改变,编译器很难优化包含全局变量的代码。而用 const 声明一个不变的全局变量,就能处理这个问题。","category":"page"},{"location":"manual/variables-and-scoping/","page":"变量作用域","title":"变量作用域","text":"局部常量却大有不同。编译器能够自动确定一个局部变量什么时候是不变的,所以局部常量声明是不必要的,其实现在也并不支持。","category":"page"},{"location":"manual/variables-and-scoping/","page":"变量作用域","title":"变量作用域","text":"一些特殊的顶层赋值,比如用了 function 和 structure 关键字,默认就是常量。","category":"page"},{"location":"manual/variables-and-scoping/","page":"变量作用域","title":"变量作用域","text":"注意 const 只会影响变量绑定;变量可能会绑定到一个可变的对象上(比如一个数组)使得其仍然能被改变。另外当尝试给一个声明为常量的变量赋值时,可能出现下列情景:","category":"page"},{"location":"manual/variables-and-scoping/","page":"变量作用域","title":"变量作用域","text":"如果新赋值的类型与原常量类型不一样,会扔出一个错误:","category":"page"},{"location":"manual/variables-and-scoping/","page":"变量作用域","title":"变量作用域","text":"julia> const x = 1.0\n1.0\n\njulia> x = 1\nERROR: invalid redefinition of constant x","category":"page"},{"location":"manual/variables-and-scoping/","page":"变量作用域","title":"变量作用域","text":"如果新赋值的类型与原常量一样,会打印一个警告:","category":"page"},{"location":"manual/variables-and-scoping/","page":"变量作用域","title":"变量作用域","text":"julia> const y = 1.0\n1.0\n\njulia> y = 2.0\nWARNING: redefinition of constant y. This may fail, cause incorrect answers, or produce other errors.\n2.0","category":"page"},{"location":"manual/variables-and-scoping/","page":"变量作用域","title":"变量作用域","text":"如果赋值不导致原变量值变化,则不会给出任何信息:","category":"page"},{"location":"manual/variables-and-scoping/","page":"变量作用域","title":"变量作用域","text":"julia> const z = 100\n100\n\njulia> z = 100\n100","category":"page"},{"location":"manual/variables-and-scoping/","page":"变量作用域","title":"变量作用域","text":"最后一条规则也适用于不可变对象,即使变量绑定的地址改变了,例如:","category":"page"},{"location":"manual/variables-and-scoping/","page":"变量作用域","title":"变量作用域","text":"julia> const s1 = \"1\"\n\"1\"\n\njulia> s2 = \"1\"\n\"1\"\n\njulia> pointer.([s1, s2], 1)\n2-element Array{Ptr{UInt8},1}:\n Ptr{UInt8} @0x00000000132c9638\n Ptr{UInt8} @0x0000000013dd3d18\n\njulia> s1 = s2\n\"1\"\n\njulia> pointer.([s1, s2], 1)\n2-element Array{Ptr{UInt8},1}:\n Ptr{UInt8} @0x0000000013dd3d18\n Ptr{UInt8} @0x0000000013dd3d18","category":"page"},{"location":"manual/variables-and-scoping/","page":"变量作用域","title":"变量作用域","text":"然而对于可变对象,警告会如预期出现:","category":"page"},{"location":"manual/variables-and-scoping/","page":"变量作用域","title":"变量作用域","text":"julia> const a = [1]\n1-element Vector{Int64}:\n 1\n\njulia> a = [1]\nWARNING: redefinition of constant a. This may fail, cause incorrect answers, or produce other errors.\n1-element Vector{Int64}:\n 1","category":"page"},{"location":"manual/variables-and-scoping/","page":"变量作用域","title":"变量作用域","text":"注意,虽然有时是可能更改常量的值,但是十分不推荐这样做。这样做仅仅是为了便于交互式使用。更改常量可引发多种问题或者非预期行为。举个例子,如果一个方法引用了一个常量并且在常量被更改前已经被编译了,那么该函数很有可能继续使用旧值:","category":"page"},{"location":"manual/variables-and-scoping/","page":"变量作用域","title":"变量作用域","text":"julia> const x = 1\n1\n\njulia> f() = x\nf (generic function with 1 method)\n\njulia> f()\n1\n\njulia> x = 2\nWARNING: redefinition of constant x. This may fail, cause incorrect answers, or produce other errors.\n2\n\njulia> f()\n1","category":"page"},{"location":"base/simd-types/#SIMD-支持","page":"SIMD 支持","title":"SIMD 支持","text":"","category":"section"},{"location":"base/simd-types/","page":"SIMD 支持","title":"SIMD 支持","text":"VecElement{T} 类型是为了构建 SIMD 运算符的库。实际使用中要求使用 llvmcall。类型按下文定义:","category":"page"},{"location":"base/simd-types/","page":"SIMD 支持","title":"SIMD 支持","text":"struct VecElement{T}\n value::T\nend","category":"page"},{"location":"base/simd-types/","page":"SIMD 支持","title":"SIMD 支持","text":"It has a special compilation rule: a homogeneous tuple of VecElement{T} maps to an LLVM vector type when T is a primitive bits type.","category":"page"},{"location":"base/simd-types/","page":"SIMD 支持","title":"SIMD 支持","text":"使用 -O3 参数时,编译器 可能 自动为这样的元组向量化运算符。 例如接下来的程序,使用 julia -O3 编译,在x86系统中会生成两个 SIMD 附加指令(addps):","category":"page"},{"location":"base/simd-types/","page":"SIMD 支持","title":"SIMD 支持","text":"const m128 = NTuple{4,VecElement{Float32}}\n\nfunction add(a::m128, b::m128)\n (VecElement(a[1].value+b[1].value),\n VecElement(a[2].value+b[2].value),\n VecElement(a[3].value+b[3].value),\n VecElement(a[4].value+b[4].value))\nend\n\ntriple(c::m128) = add(add(c,c),c)\n\ncode_native(triple,(m128,))","category":"page"},{"location":"base/simd-types/","page":"SIMD 支持","title":"SIMD 支持","text":"然而,因为无法依靠自动向量化,以后将主要通过使用基于 llvmcall 的库来提供 SIMD 支持。","category":"page"},{"location":"stdlib/Artifacts/#Artifacts","page":"Artifacts","title":"Artifacts","text":"","category":"section"},{"location":"stdlib/Artifacts/","page":"Artifacts","title":"Artifacts","text":"DocTestSetup = :(using Artifacts)","category":"page"},{"location":"stdlib/Artifacts/","page":"Artifacts","title":"Artifacts","text":"Starting with Julia 1.6, the artifacts support has moved from Pkg.jl to Julia itself. Until proper documentation can be added here, you can learn more about artifacts in the Pkg.jl manual at https://julialang.github.io/Pkg.jl/v1/artifacts/.","category":"page"},{"location":"stdlib/Artifacts/","page":"Artifacts","title":"Artifacts","text":"compat: Julia 1.6\nJulia's artifacts API requires at least Julia 1.6. In Julia versions 1.3 to 1.5, you can use Pkg.Artifacts instead.","category":"page"},{"location":"stdlib/Artifacts/","page":"Artifacts","title":"Artifacts","text":"Artifacts.artifact_meta\nArtifacts.artifact_hash\nArtifacts.find_artifacts_toml\nArtifacts.@artifact_str","category":"page"},{"location":"stdlib/Artifacts/#Artifacts.artifact_meta","page":"Artifacts","title":"Artifacts.artifact_meta","text":"artifact_meta(name::String, artifacts_toml::String;\n platform::AbstractPlatform = HostPlatform(),\n pkg_uuid::Union{Base.UUID,Nothing}=nothing)\n\nGet metadata about a given artifact (identified by name) stored within the given (Julia)Artifacts.toml file. If the artifact is platform-specific, use platform to choose the most appropriate mapping. If none is found, return nothing.\n\ncompat: Julia 1.3\nThis function requires at least Julia 1.3.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/Artifacts/#Artifacts.artifact_hash","page":"Artifacts","title":"Artifacts.artifact_hash","text":"artifact_hash(name::String, artifacts_toml::String;\n platform::AbstractPlatform = HostPlatform())\n\nThin wrapper around artifact_meta() to return the hash of the specified, platform- collapsed artifact. Returns nothing if no mapping can be found.\n\ncompat: Julia 1.3\nThis function requires at least Julia 1.3.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/Artifacts/#Artifacts.find_artifacts_toml","page":"Artifacts","title":"Artifacts.find_artifacts_toml","text":"find_artifacts_toml(path::String)\n\nGiven the path to a .jl file, (such as the one returned by __source__.file in a macro context), find the (Julia)Artifacts.toml that is contained within the containing project (if it exists), otherwise return nothing.\n\ncompat: Julia 1.3\nThis function requires at least Julia 1.3.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/Artifacts/#Artifacts.@artifact_str","page":"Artifacts","title":"Artifacts.@artifact_str","text":"macro artifact_str(name)\n\nReturn the on-disk path to an artifact. Automatically looks the artifact up by name in the project's (Julia)Artifacts.toml file. Throws an error on if the requested artifact is not present. If run in the REPL, searches for the toml file starting in the current directory, see find_artifacts_toml() for more.\n\nIf the artifact is marked \"lazy\" and the package has using LazyArtifacts defined, the artifact will be downloaded on-demand with Pkg the first time this macro tries to compute the path. The files will then be left installed locally for later.\n\nIf name contains a forward or backward slash, all elements after the first slash will be taken to be path names indexing into the artifact, allowing for an easy one-liner to access a single file/directory within an artifact. Example:\n\nffmpeg_path = @artifact\"FFMPEG/bin/ffmpeg\"\n\ncompat: Julia 1.3\nThis macro requires at least Julia 1.3.\n\ncompat: Julia 1.6\nSlash-indexing requires at least Julia 1.6.\n\n\n\n\n\n","category":"macro"},{"location":"devdocs/inference/#类型推导","page":"类型推导","title":"类型推导","text":"","category":"section"},{"location":"devdocs/inference/#类型推导是如何工作的","page":"类型推导","title":"类型推导是如何工作的","text":"","category":"section"},{"location":"devdocs/inference/","page":"类型推导","title":"类型推导","text":"Type inference refers to the process of deducing the types of later values from the types of input values. Julia's approach to inference has been described in blog posts (1, 2).","category":"page"},{"location":"devdocs/inference/#调试-compiler.jl","page":"类型推导","title":"调试 compiler.jl","text":"","category":"section"},{"location":"devdocs/inference/","page":"类型推导","title":"类型推导","text":"You can start a Julia session, edit compiler/*.jl (for example to insert print statements), and then replace Core.Compiler in your running session by navigating to base and executing include(\"compiler/compiler.jl\"). This trick typically leads to much faster development than if you rebuild Julia for each change.","category":"page"},{"location":"devdocs/inference/","page":"类型推导","title":"类型推导","text":"Alternatively, you can use the Revise.jl package to track the compiler changes by using the command Revise.track(Core.Compiler) at the beginning of your Julia session. As explained in the Revise documentation, the modifications to the compiler will be reflected when the modified files are saved.","category":"page"},{"location":"devdocs/inference/","page":"类型推导","title":"类型推导","text":"A convenient entry point into inference is typeinf_code. Here's a demo running inference on convert(Int, UInt(1)):","category":"page"},{"location":"devdocs/inference/","page":"类型推导","title":"类型推导","text":"# Get the method\natypes = Tuple{Type{Int}, UInt} # argument types\nmths = methods(convert, atypes) # worth checking that there is only one\nm = first(mths)\n\n# Create variables needed to call `typeinf_code`\ninterp = Core.Compiler.NativeInterpreter()\nsparams = Core.svec() # this particular method doesn't have type-parameters\noptimize = true # run all inference optimizations\ntypes = Tuple{typeof(convert), atypes.parameters...} # Tuple{typeof(convert), Type{Int}, UInt}\nCore.Compiler.typeinf_code(interp, m, types, sparams, optimize)","category":"page"},{"location":"devdocs/inference/","page":"类型推导","title":"类型推导","text":"If your debugging adventures require a MethodInstance, you can look it up by calling Core.Compiler.specialize_method using many of the variables above. A CodeInfo object may be obtained with","category":"page"},{"location":"devdocs/inference/","page":"类型推导","title":"类型推导","text":"# Returns the CodeInfo object for `convert(Int, ::UInt)`:\nci = (@code_typed convert(Int, UInt(1)))[1]","category":"page"},{"location":"devdocs/inference/#The-inlining-algorithm-(inline_worthy)","page":"类型推导","title":"The inlining algorithm (inline_worthy)","text":"","category":"section"},{"location":"devdocs/inference/","page":"类型推导","title":"类型推导","text":"Much of the hardest work for inlining runs in inlining_pass. However, if your question is \"why didn't my function inline?\" then you will most likely be interested in isinlineable and its primary callee, inline_worthy. isinlineable handles a number of special cases (e.g., critical functions like next and done, incorporating a bonus for functions that return tuples, etc.). The main decision-making happens in inline_worthy, which returns true if the function should be inlined.","category":"page"},{"location":"devdocs/inference/","page":"类型推导","title":"类型推导","text":"inline_worthy implements a cost-model, where \"cheap\" functions get inlined; more specifically, we inline functions if their anticipated run-time is not large compared to the time it would take to issue a call to them if they were not inlined. The cost-model is extremely simple and ignores many important details: for example, all for loops are analyzed as if they will be executed once, and the cost of an if...else...end includes the summed cost of all branches. It's also worth acknowledging that we currently lack a suite of functions suitable for testing how well the cost model predicts the actual run-time cost, although BaseBenchmarks provides a great deal of indirect information about the successes and failures of any modification to the inlining algorithm.","category":"page"},{"location":"devdocs/inference/","page":"类型推导","title":"类型推导","text":"The foundation of the cost-model is a lookup table, implemented in add_tfunc and its callers, that assigns an estimated cost (measured in CPU cycles) to each of Julia's intrinsic functions. These costs are based on standard ranges for common architectures (see Agner Fog's analysis for more detail).","category":"page"},{"location":"devdocs/inference/","page":"类型推导","title":"类型推导","text":"We supplement this low-level lookup table with a number of special cases. For example, an :invoke expression (a call for which all input and output types were inferred in advance) is assigned a fixed cost (currently 20 cycles). In contrast, a :call expression, for functions other than intrinsics/builtins, indicates that the call will require dynamic dispatch, in which case we assign a cost set by Params.inline_nonleaf_penalty (currently set at 1000). Note that this is not a \"first-principles\" estimate of the raw cost of dynamic dispatch, but a mere heuristic indicating that dynamic dispatch is extremely expensive.","category":"page"},{"location":"devdocs/inference/","page":"类型推导","title":"类型推导","text":"Each statement gets analyzed for its total cost in a function called statement_cost. You can display the cost associated with each statement as follows:","category":"page"},{"location":"devdocs/inference/","page":"类型推导","title":"类型推导","text":"julia> Base.print_statement_costs(stdout, map, (typeof(sqrt), Tuple{Int},)) # map(sqrt, (2,))\nmap(f, t::Tuple{Any}) in Base at tuple.jl:179\n 0 1 ─ %1 = Base.getfield(_3, 1, true)::Int64\n 1 │ %2 = Base.sitofp(Float64, %1)::Float64\n 2 │ %3 = Base.lt_float(%2, 0.0)::Bool\n 0 └── goto #3 if not %3\n 0 2 ─ invoke Base.Math.throw_complex_domainerror(:sqrt::Symbol, %2::Float64)::Union{}\n 0 └── unreachable\n 20 3 ─ %7 = Base.Math.sqrt_llvm(%2)::Float64\n 0 └── goto #4\n 0 4 ─ goto #5\n 0 5 ─ %10 = Core.tuple(%7)::Tuple{Float64}\n 0 └── return %10","category":"page"},{"location":"devdocs/inference/","page":"类型推导","title":"类型推导","text":"The line costs are in the left column. This includes the consequences of inlining and other forms of optimization.","category":"page"},{"location":"manual/complex-and-rational-numbers/#复数和有理数","page":"复数和有理数","title":"复数和有理数","text":"","category":"section"},{"location":"manual/complex-and-rational-numbers/","page":"复数和有理数","title":"复数和有理数","text":"Julia 语言包含了预定义的复数和有理数类型,并且支持它们的各种标准数学运算和初等函数。由于也定义了复数与分数的类型转换与类型提升,因此对预定义数值类型(无论是原始的还是复合的)的任意组合进行的操作都会表现得如预期的一样。","category":"page"},{"location":"manual/complex-and-rational-numbers/#复数","page":"复数和有理数","title":"复数","text":"","category":"section"},{"location":"manual/complex-and-rational-numbers/","page":"复数和有理数","title":"复数和有理数","text":"全局常量 im 被绑定到复数 i,表示 -1 的主平方根。(不应使用数学家习惯的 i 或工程师习惯的 j 来表示此全局常量,因为它们是非常常用的索引变量名。)由于 Julia 允许数值字面量作为数值字面量系数,这种绑定就足以为复数提供很方便的语法,类似于传统的数学记法:","category":"page"},{"location":"manual/complex-and-rational-numbers/","page":"复数和有理数","title":"复数和有理数","text":"julia> 1+2im\n1 + 2im","category":"page"},{"location":"manual/complex-and-rational-numbers/","page":"复数和有理数","title":"复数和有理数","text":"你可以对复数进行各种标准算术操作:","category":"page"},{"location":"manual/complex-and-rational-numbers/","page":"复数和有理数","title":"复数和有理数","text":"julia> (1 + 2im)*(2 - 3im)\n8 + 1im\n\njulia> (1 + 2im)/(1 - 2im)\n-0.6 + 0.8im\n\njulia> (1 + 2im) + (1 - 2im)\n2 + 0im\n\njulia> (-3 + 2im) - (5 - 1im)\n-8 + 3im\n\njulia> (-1 + 2im)^2\n-3 - 4im\n\njulia> (-1 + 2im)^2.5\n2.729624464784009 - 6.9606644595719im\n\njulia> (-1 + 2im)^(1 + 1im)\n-0.27910381075826657 + 0.08708053414102428im\n\njulia> 3(2 - 5im)\n6 - 15im\n\njulia> 3(2 - 5im)^2\n-63 - 60im\n\njulia> 3(2 - 5im)^-1.0\n0.20689655172413796 + 0.5172413793103449im","category":"page"},{"location":"manual/complex-and-rational-numbers/","page":"复数和有理数","title":"复数和有理数","text":"类型提升机制也确保你可以使用不同类型的操作数的组合:","category":"page"},{"location":"manual/complex-and-rational-numbers/","page":"复数和有理数","title":"复数和有理数","text":"julia> 2(1 - 1im)\n2 - 2im\n\njulia> (2 + 3im) - 1\n1 + 3im\n\njulia> (1 + 2im) + 0.5\n1.5 + 2.0im\n\njulia> (2 + 3im) - 0.5im\n2.0 + 2.5im\n\njulia> 0.75(1 + 2im)\n0.75 + 1.5im\n\njulia> (2 + 3im) / 2\n1.0 + 1.5im\n\njulia> (1 - 3im) / (2 + 2im)\n-0.5 - 1.0im\n\njulia> 2im^2\n-2 + 0im\n\njulia> 1 + 3/4im\n1.0 - 0.75im","category":"page"},{"location":"manual/complex-and-rational-numbers/","page":"复数和有理数","title":"复数和有理数","text":"注意 3/4im == 3/(4*im) == -(3/4*im),因为系数比除法的优先级更高。","category":"page"},{"location":"manual/complex-and-rational-numbers/","page":"复数和有理数","title":"复数和有理数","text":"Julia 提供了一些操作复数的标准函数:","category":"page"},{"location":"manual/complex-and-rational-numbers/","page":"复数和有理数","title":"复数和有理数","text":"julia> z = 1 + 2im\n1 + 2im\n\njulia> real(1 + 2im) # z 的实部\n1\n\njulia> imag(1 + 2im) # z 的虚部\n2\n\njulia> conj(1 + 2im) # z 的复共轭\n1 - 2im\n\njulia> abs(1 + 2im) # z 的绝对值\n2.23606797749979\n\njulia> abs2(1 + 2im) # 取平方后的绝对值\n5\n\njulia> angle(1 + 2im) # 以弧度为单位的相位角\n1.1071487177940904","category":"page"},{"location":"manual/complex-and-rational-numbers/","page":"复数和有理数","title":"复数和有理数","text":"按照惯例,复数的绝对值(abs)是从零点到它的距离。abs2 给出绝对值的平方,作用于复数上时非常有用,因为它避免了取平方根。angle 返回以弧度为单位的相位角(也被称为辐角函数)。所有其它的初等函数在复数上也都有完整的定义:","category":"page"},{"location":"manual/complex-and-rational-numbers/","page":"复数和有理数","title":"复数和有理数","text":"julia> sqrt(1im)\n0.7071067811865476 + 0.7071067811865475im\n\njulia> sqrt(1 + 2im)\n1.272019649514069 + 0.7861513777574233im\n\njulia> cos(1 + 2im)\n2.0327230070196656 - 3.0518977991517997im\n\njulia> exp(1 + 2im)\n-1.1312043837568135 + 2.4717266720048188im\n\njulia> sinh(1 + 2im)\n-0.4890562590412937 + 1.4031192506220405im","category":"page"},{"location":"manual/complex-and-rational-numbers/","page":"复数和有理数","title":"复数和有理数","text":"注意数学函数通常应用于实数就返回实数值,应用于复数就返回复数值。例如,当 sqrt 应用于 -1 与 -1 + 0im 会有不同的表现,虽然 -1 == -1 + 0im:","category":"page"},{"location":"manual/complex-and-rational-numbers/","page":"复数和有理数","title":"复数和有理数","text":"julia> sqrt(-1)\nERROR: DomainError with -1.0:\nsqrt will only return a complex result if called with a complex argument. Try sqrt(Complex(x)).\nStacktrace:\n[...]\n\njulia> sqrt(-1 + 0im)\n0.0 + 1.0im","category":"page"},{"location":"manual/complex-and-rational-numbers/","page":"复数和有理数","title":"复数和有理数","text":"从变量构建复数时,文本型数值系数记法不再适用。相反地,乘法必须显式地写出:","category":"page"},{"location":"manual/complex-and-rational-numbers/","page":"复数和有理数","title":"复数和有理数","text":"julia> a = 1; b = 2; a + b*im\n1 + 2im","category":"page"},{"location":"manual/complex-and-rational-numbers/","page":"复数和有理数","title":"复数和有理数","text":"然而,我们并不推荐这样做,而应改为使用更高效的 complex 函数直接通过实部与虚部构建一个复数值:","category":"page"},{"location":"manual/complex-and-rational-numbers/","page":"复数和有理数","title":"复数和有理数","text":"julia> a = 1; b = 2; complex(a, b)\n1 + 2im","category":"page"},{"location":"manual/complex-and-rational-numbers/","page":"复数和有理数","title":"复数和有理数","text":"这种构建避免了乘法和加法操作。","category":"page"},{"location":"manual/complex-and-rational-numbers/","page":"复数和有理数","title":"复数和有理数","text":"Inf 和 NaN 可能出现在复数的实部和虚部,正如特殊的浮点值章节所描述的:","category":"page"},{"location":"manual/complex-and-rational-numbers/","page":"复数和有理数","title":"复数和有理数","text":"julia> 1 + Inf*im\n1.0 + Inf*im\n\njulia> 1 + NaN*im\n1.0 + NaN*im","category":"page"},{"location":"manual/complex-and-rational-numbers/#有理数","page":"复数和有理数","title":"有理数","text":"","category":"section"},{"location":"manual/complex-and-rational-numbers/","page":"复数和有理数","title":"复数和有理数","text":"Julia 有一个用于表示整数精确比值的分数类型。分数通过 // 运算符构建:","category":"page"},{"location":"manual/complex-and-rational-numbers/","page":"复数和有理数","title":"复数和有理数","text":"julia> 2//3\n2//3","category":"page"},{"location":"manual/complex-and-rational-numbers/","page":"复数和有理数","title":"复数和有理数","text":"如果一个分数的分子和分母含有公因子,它们会被约分到最简形式且分母非负:","category":"page"},{"location":"manual/complex-and-rational-numbers/","page":"复数和有理数","title":"复数和有理数","text":"julia> 6//9\n2//3\n\njulia> -4//8\n-1//2\n\njulia> 5//-15\n-1//3\n\njulia> -4//-12\n1//3","category":"page"},{"location":"manual/complex-and-rational-numbers/","page":"复数和有理数","title":"复数和有理数","text":"整数比值的这种标准化形式是唯一的,所以分数值的相等性可由校验分子与分母都相等来测试。分数值的标准化分子和分母可以使用 numerator 和 denominator 函数得到:","category":"page"},{"location":"manual/complex-and-rational-numbers/","page":"复数和有理数","title":"复数和有理数","text":"julia> numerator(2//3)\n2\n\njulia> denominator(2//3)\n3","category":"page"},{"location":"manual/complex-and-rational-numbers/","page":"复数和有理数","title":"复数和有理数","text":"分子和分母的直接比较通常是不必要的,因为标准算术和比较操作对分数值也有定义:","category":"page"},{"location":"manual/complex-and-rational-numbers/","page":"复数和有理数","title":"复数和有理数","text":"julia> 2//3 == 6//9\ntrue\n\njulia> 2//3 == 9//27\nfalse\n\njulia> 3//7 < 1//2\ntrue\n\njulia> 3//4 > 2//3\ntrue\n\njulia> 2//4 + 1//6\n2//3\n\njulia> 5//12 - 1//4\n1//6\n\njulia> 5//8 * 3//12\n5//32\n\njulia> 6//5 / 10//7\n21//25","category":"page"},{"location":"manual/complex-and-rational-numbers/","page":"复数和有理数","title":"复数和有理数","text":"分数可以很容易地转换成浮点数:","category":"page"},{"location":"manual/complex-and-rational-numbers/","page":"复数和有理数","title":"复数和有理数","text":"julia> float(3//4)\n0.75","category":"page"},{"location":"manual/complex-and-rational-numbers/","page":"复数和有理数","title":"复数和有理数","text":"对任意整数值 a 和 b(除了 a == 0 且 b == 0 时),从分数到浮点数的转换遵从以下的一致性:","category":"page"},{"location":"manual/complex-and-rational-numbers/","page":"复数和有理数","title":"复数和有理数","text":"julia> a = 1; b = 2;\n\njulia> isequal(float(a//b), a/b)\ntrue","category":"page"},{"location":"manual/complex-and-rational-numbers/","page":"复数和有理数","title":"复数和有理数","text":"Julia接受构建无穷分数值:","category":"page"},{"location":"manual/complex-and-rational-numbers/","page":"复数和有理数","title":"复数和有理数","text":"julia> 5//0\n1//0\n\njulia> x = -3//0\n-1//0\n\njulia> typeof(x)\nRational{Int64}","category":"page"},{"location":"manual/complex-and-rational-numbers/","page":"复数和有理数","title":"复数和有理数","text":"但不接受试图构建一个 NaN 分数值:","category":"page"},{"location":"manual/complex-and-rational-numbers/","page":"复数和有理数","title":"复数和有理数","text":"julia> 0//0\nERROR: ArgumentError: invalid rational: zero(Int64)//zero(Int64)\nStacktrace:\n[...]","category":"page"},{"location":"manual/complex-and-rational-numbers/","page":"复数和有理数","title":"复数和有理数","text":"像往常一样,类型提升系统使得分数可以轻松地同其它数值类型进行交互:","category":"page"},{"location":"manual/complex-and-rational-numbers/","page":"复数和有理数","title":"复数和有理数","text":"julia> 3//5 + 1\n8//5\n\njulia> 3//5 - 0.5\n0.09999999999999998\n\njulia> 2//7 * (1 + 2im)\n2//7 + 4//7*im\n\njulia> 2//7 * (1.5 + 2im)\n0.42857142857142855 + 0.5714285714285714im\n\njulia> 3//2 / (1 + 2im)\n3//10 - 3//5*im\n\njulia> 1//2 + 2im\n1//2 + 2//1*im\n\njulia> 1 + 2//3im\n1//1 - 2//3*im\n\njulia> 0.5 == 1//2\ntrue\n\njulia> 0.33 == 1//3\nfalse\n\njulia> 0.33 < 1//3\ntrue\n\njulia> 1//3 - 0.33\n0.0033333333333332993","category":"page"},{"location":"devdocs/types/#More-about-types","page":"More about types","title":"More about types","text":"","category":"section"},{"location":"devdocs/types/","page":"More about types","title":"More about types","text":"使用Julia一段时间之后,你就会体会到类型在其中的基础性作用。本部分我们将深入到类型体系的内部,并着重关注 Parametric Types。","category":"page"},{"location":"devdocs/types/#Types-and-sets-(and-Any-and-Union{}/Bottom)","page":"More about types","title":"Types and sets (and Any and Union{}/Bottom)","text":"","category":"section"},{"location":"devdocs/types/","page":"More about types","title":"More about types","text":"Julia的类型系统很容易会被看作是一种集合(set)。程序处理个体值,类型处理值的集合。但是集合与类型是两个不同的概念。一组值组成的集合 Set 本身也是一个值的集合。而类型描述的是一个组可能值组成的集合,即类型的值是不确定的。 ","category":"page"},{"location":"devdocs/types/","page":"More about types","title":"More about types","text":"函数 typeof 可以返回具体类型 T 包含的值的直接标签 T。而抽象类型描述的集合则可能会更大。","category":"page"},{"location":"devdocs/types/","page":"More about types","title":"More about types","text":"类型 Any 包含所有可能值。类型 Integer 是 Any 的一个子类型,而 Integer的子类型有包括 Int,Int8 等其他具体类型。在内部表征上,Julia 类型系统还非常依赖类型 Bottom,也记做Union{}。这对应于集合中的空集。","category":"page"},{"location":"devdocs/types/","page":"More about types","title":"More about types","text":"Julia类型系统支持集合理论的标准操作:你可以用 T1 <: T2 来判断类型 T1 是否是T2 的子集(子类型)。 typeintersect 和 typejoin 可用来计算两个类型的交集和合集;用 Union 用于集合所有列出的类型。","category":"page"},{"location":"devdocs/types/","page":"More about types","title":"More about types","text":"julia> typeintersect(Int, Float64)\nUnion{}\n\njulia> Union{Int, Float64}\nUnion{Float64, Int64}\n\njulia> typejoin(Int, Float64)\nReal\n\njulia> typeintersect(Signed, Union{UInt8, Int8})\nInt8\n\njulia> Union{Signed, Union{UInt8, Int8}}\nUnion{UInt8, Signed}\n\njulia> typejoin(Signed, Union{UInt8, Int8})\nInteger\n\njulia> typeintersect(Tuple{Integer, Float64}, Tuple{Int, Real})\nTuple{Int64, Float64}\n\njulia> Union{Tuple{Integer, Float64}, Tuple{Int, Real}}\nUnion{Tuple{Int64, Real}, Tuple{Integer, Float64}}\n\njulia> typejoin(Tuple{Integer, Float64}, Tuple{Int, Real})\nTuple{Integer, Real}","category":"page"},{"location":"devdocs/types/","page":"More about types","title":"More about types","text":"这些操作看起来很抽象,但是他们处于 Julia 语言的核心位置。例如,方法的派发过程就是对方法列表中的项目进行逐步搜索,直到找到一个其类型是方法标签子类型的参数元组为止。该算法有效的前提是方法必须按照特异性(specificity)进行排序,搜索过程必须从最具特异性的开始。所以,Julia 也需要对类型进行偏序排序(partial order),该函数与 <: 类似但又不完全相同。","category":"page"},{"location":"devdocs/types/#UnionAll类型","page":"More about types","title":"UnionAll类型","text":"","category":"section"},{"location":"devdocs/types/","page":"More about types","title":"More about types","text":"Julia 的类型系统也可以表征类型的迭代合集(iterated union),即某个变量的所有值的集合。当参数化类型的某些参数值是未知数时,迭代合集是非常有用的。","category":"page"},{"location":"devdocs/types/","page":"More about types","title":"More about types","text":"例如,下面这个数组 Array{Int,2} 有两个参数。如果其成分类型未知,该数组可以写成 Array{T,2} where T。该数组是取所有不同 T 值后的所有数组Array{T,2} 的合集:Union{Array{Int8,2}, Array{Int16,2}, ...}。","category":"page"},{"location":"devdocs/types/","page":"More about types","title":"More about types","text":"类型的迭代集合由类型为UnionAll的对象表征。UnionAll对象有一个类型为 TypeVar 的变量,此处为T,和一个包裹化的类型,此处为 Array{T,2}。","category":"page"},{"location":"devdocs/types/","page":"More about types","title":"More about types","text":"考虑下面的例子:","category":"page"},{"location":"devdocs/types/","page":"More about types","title":"More about types","text":"f1(A::Array) = 1\nf2(A::Array{Int}) = 2\nf3(A::Array{T}) where {T<:Any} = 3\nf4(A::Array{Any}) = 4","category":"page"},{"location":"devdocs/types/","page":"More about types","title":"More about types","text":"如 Function calls 中描述的,函数 f3 的签名是元组类型的 UnionAll 类型包裹:Tuple{typeof(f3), Array{T}} where T。此处除 f4 外所有函数都可以被a = [1,2]调用;除 f2 外所有函数都可以被 b = Any[1,2] 调用。","category":"page"},{"location":"devdocs/types/","page":"More about types","title":"More about types","text":"dump() 函数可用于进一步查看这些类型:","category":"page"},{"location":"devdocs/types/","page":"More about types","title":"More about types","text":"julia> dump(Array)\nUnionAll\n var: TypeVar\n name: Symbol T\n lb: Union{}\n ub: Any\n body: UnionAll\n var: TypeVar\n name: Symbol N\n lb: Union{}\n ub: Any\n body: Array{T, N} <: DenseArray{T, N}","category":"page"},{"location":"devdocs/types/","page":"More about types","title":"More about types","text":"这说明数组 Array 实际上命名了一个 UnionAll 类型。嵌套其中的参数也都是 UnionAll 类型。句法 Array{Int,2} 等价于Array{Int}{2}。UnionAll 在内部会被实例化为变量的特定值,每次一个,从最外侧开始。这使得省略尾端参数是自然而有意义的:类型 Array{Int} 与类型 Array{Int, N} where N。 ","category":"page"},{"location":"devdocs/types/","page":"More about types","title":"More about types","text":"TypeVar 本身不是类型,而是 UnionAll 类型的一个内部结构成分。类型变量的值会有上界和下界,分别由字段lb 和 ub 表示。符号 name 是纯装饰性的(cosmetic)。在内部 TypeVar 是通过地址比较的。所以为了区分“不同”变量类型,TypeVar 是一个可更改类型,但通常不应修改它们。","category":"page"},{"location":"devdocs/types/","page":"More about types","title":"More about types","text":"你也可以手动创建 TypeVar:","category":"page"},{"location":"devdocs/types/","page":"More about types","title":"More about types","text":"julia> TypeVar(:V, Signed, Real)\nSigned<:V<:Real","category":"page"},{"location":"devdocs/types/","page":"More about types","title":"More about types","text":"你可以用更简便的方式省掉除 name 之外的任意参数。","category":"page"},{"location":"devdocs/types/","page":"More about types","title":"More about types","text":"句法 Array{T} where T<:Integer 会被降级为如下格式。","category":"page"},{"location":"devdocs/types/","page":"More about types","title":"More about types","text":"let T = TypeVar(:T,Integer)\n UnionAll(T, Array{T})\nend","category":"page"},{"location":"devdocs/types/","page":"More about types","title":"More about types","text":"所以极少需要手动建构 TypeVar(实际上这也应该是尽量避免的)。","category":"page"},{"location":"devdocs/types/#自由变量","page":"More about types","title":"自由变量","text":"","category":"section"},{"location":"devdocs/types/","page":"More about types","title":"More about types","text":"自由类型变量在类型系统中是至关重要的。如果类型 T 不包含一个引入变量 V 的 UnionAll 类型,那么类型 T 中的变量 V 就是自由的 (free)。例如,类型 Array{Array{V} where V<:Integer} 没有自由变量,但该类型的子成分 Array{V} 则包含了一个自由变量 V。","category":"page"},{"location":"devdocs/types/","page":"More about types","title":"More about types","text":"从某种程度上讲,一个包含自由变量的类型根本就不是一个类型。例如,类型 Array{Array{T}} where T 是一个成分为数组的数组,且所有子数组元素的类型都相同。其内部类型 Array{T} 乍一看似乎包含所有数组类型。但外部数组的成分必须有相同类型,所以 Array{T} 不能指向所有数组。我们可以说 Array{T} 出现了很多次,但每次 T 值都必须相同。","category":"page"},{"location":"devdocs/types/","page":"More about types","title":"More about types","text":"故此, C 应用程序接口函数 jl_has_free_typevars 是非常重要的。若该函数的返回值为真,则说明类型中存在自由变量。此时子类型判断和其他类型函数中的返回结果没有太多意义。","category":"page"},{"location":"devdocs/types/#类型名称TypeNames","page":"More about types","title":"类型名称TypeNames","text":"","category":"section"},{"location":"devdocs/types/","page":"More about types","title":"More about types","text":"下面两个数组 Array 类型在功能上是相同的,但有不同的打印方式:","category":"page"},{"location":"devdocs/types/","page":"More about types","title":"More about types","text":"julia> TV, NV = TypeVar(:T), TypeVar(:N)\n(T, N)\n\njulia> Array\nArray\n\njulia> Array{TV, NV}\nArray{T, N}","category":"page"},{"location":"devdocs/types/","page":"More about types","title":"More about types","text":"二者之间的差别可以通过类型的名称 name 字段来区分。名称 name 字段是一个类型为 TypeName 的对象。 ","category":"page"},{"location":"devdocs/types/","page":"More about types","title":"More about types","text":"julia> dump(Array{Int,1}.name)\nTypeName\n name: Symbol Array\n module: Module Core\n names: empty SimpleVector\n wrapper: UnionAll\n var: TypeVar\n name: Symbol T\n lb: Union{}\n ub: Any\n body: UnionAll\n var: TypeVar\n name: Symbol N\n lb: Union{}\n ub: Any\n body: Array{T, N} <: DenseArray{T, N}\n cache: SimpleVector\n ...\n\n linearcache: SimpleVector\n ...\n\n hash: Int64 -7900426068641098781\n mt: MethodTable\n name: Symbol Array\n defs: Nothing nothing\n cache: Nothing nothing\n max_args: Int64 0\n kwsorter: #undef\n module: Module Core\n : Int64 0\n : Int64 0","category":"page"},{"location":"devdocs/types/","page":"More about types","title":"More about types","text":"与此相关的字段是包装器 wrapper,该字段存储了一个指向顶层类型(tip-level)的引用,用以产生新的数组 Array 类型。","category":"page"},{"location":"devdocs/types/","page":"More about types","title":"More about types","text":"julia> pointer_from_objref(Array)\nPtr{Cvoid} @0x00007fcc7de64850\n\njulia> pointer_from_objref(Array.body.body.name.wrapper)\nPtr{Cvoid} @0x00007fcc7de64850\n\njulia> pointer_from_objref(Array{TV,NV})\nPtr{Cvoid} @0x00007fcc80c4d930\n\njulia> pointer_from_objref(Array{TV,NV}.name.wrapper)\nPtr{Cvoid} @0x00007fcc7de64850","category":"page"},{"location":"devdocs/types/","page":"More about types","title":"More about types","text":"数组 Array 的包装器 wrapper 字段指向它自己,而在数组 Array{TV,NV} 中,该字段则指回该类型的原始定义。","category":"page"},{"location":"devdocs/types/","page":"More about types","title":"More about types","text":"那其他字段都是什么作用呢?字段hash 会给每个类型指派一个整数。要查看 cache 字段的内容,最好选不像数组那么常用的类型。我们可以自己创造一个类型:","category":"page"},{"location":"devdocs/types/","page":"More about types","title":"More about types","text":"julia> struct MyType{T,N} end\n\njulia> MyType{Int,2}\nMyType{Int64, 2}\n\njulia> MyType{Float32, 5}\nMyType{Float32, 5}","category":"page"},{"location":"devdocs/types/","page":"More about types","title":"More about types","text":"当参数类型被实例化时,每个具体类型都会被存储到类型缓存中(MyType.body.body.name.cache)。不过含有自由变量的实例是不会被缓存的。","category":"page"},{"location":"devdocs/types/#元组类型","page":"More about types","title":"元组类型","text":"","category":"section"},{"location":"devdocs/types/","page":"More about types","title":"More about types","text":"元组类型是一个有趣的特例。为了使派发在诸如 x::Tuple 之类的声明中正常工作,该类型必须能包含所有元组。我们可以查看一下元组的参数:","category":"page"},{"location":"devdocs/types/","page":"More about types","title":"More about types","text":"julia> Tuple\nTuple\n\njulia> Tuple.parameters\nsvec(Vararg{Any})","category":"page"},{"location":"devdocs/types/","page":"More about types","title":"More about types","text":"与其他类型不同,元组类型的参数是共变的(covariant),所以类型 Tuple 能与任何类型的元组相匹配。","category":"page"},{"location":"devdocs/types/","page":"More about types","title":"More about types","text":"julia> typeintersect(Tuple, Tuple{Int,Float64})\nTuple{Int64, Float64}\n\njulia> typeintersect(Tuple{Vararg{Any}}, Tuple{Int,Float64})\nTuple{Int64, Float64}","category":"page"},{"location":"devdocs/types/","page":"More about types","title":"More about types","text":"但是,如果一个可变元组 (Vararg) 类型含有自由变量,那么他描述的元组类型则可能就是不同的:","category":"page"},{"location":"devdocs/types/","page":"More about types","title":"More about types","text":"julia> typeintersect(Tuple{Vararg{T} where T}, Tuple{Int,Float64})\nTuple{Int64, Float64}\n\njulia> typeintersect(Tuple{Vararg{T}} where T, Tuple{Int,Float64})\nUnion{}","category":"page"},{"location":"devdocs/types/","page":"More about types","title":"More about types","text":"当 T 绑定的 UnionAll 类型位于元组 Tuple 之外,即 T 是元组 Tuple 的自由变量时,一个唯一的 T 值必须作用与整个类型。此时异质的元组是不匹配的。","category":"page"},{"location":"devdocs/types/","page":"More about types","title":"More about types","text":"最后,意识到元组 Tuple{} 的独特性是有意义的:","category":"page"},{"location":"devdocs/types/","page":"More about types","title":"More about types","text":"julia> Tuple{}\nTuple{}\n\njulia> Tuple{}.parameters\nsvec()\n\njulia> typeintersect(Tuple{}, Tuple{Int})\nUnion{}","category":"page"},{"location":"devdocs/types/","page":"More about types","title":"More about types","text":"那么什么是元组类型的基本(primary)类型呢?","category":"page"},{"location":"devdocs/types/","page":"More about types","title":"More about types","text":"julia> pointer_from_objref(Tuple)\nPtr{Cvoid} @0x00007f5998a04370\n\njulia> pointer_from_objref(Tuple{})\nPtr{Cvoid} @0x00007f5998a570d0\n\njulia> pointer_from_objref(Tuple.name.wrapper)\nPtr{Cvoid} @0x00007f5998a04370\n\njulia> pointer_from_objref(Tuple{}.name.wrapper)\nPtr{Cvoid} @0x00007f5998a04370","category":"page"},{"location":"devdocs/types/","page":"More about types","title":"More about types","text":"所以 Tuple == Tuple{Vararg{Any}} 事实上就是其基本类型。","category":"page"},{"location":"devdocs/types/#对角变量","page":"More about types","title":"对角变量","text":"","category":"section"},{"location":"devdocs/types/","page":"More about types","title":"More about types","text":"考虑类型 Tuple{T,T} where T。使用该标签的方法看起来会是下面的样子:","category":"page"},{"location":"devdocs/types/","page":"More about types","title":"More about types","text":"f(x::T, y::T) where {T} = ...","category":"page"},{"location":"devdocs/types/","page":"More about types","title":"More about types","text":"根据对类型 UnionAll 的通常理解, T 将覆盖所有的类型,包括 T,所以此类型应该等价于 Tuple{Any,Any}。但是这种理解会面临很多实际的问题。","category":"page"},{"location":"devdocs/types/","page":"More about types","title":"More about types","text":"首先,T 值需要在方法定之内可及。对诸如 f(1, 1.0) 的调用来说,T 的值是不明确的。T 可以是 Union{Int,Float64} 或 Real。直觉上,声明 x::T 意味着 T 应该为 x 的类型,即 T === typeof(x)。为了保有这种不变性, 该方法应满足如下关系: typeof(x) === typeof(y) === T。 这说明该方法只能被拥有相同类型的参数元组调用。","category":"page"},{"location":"devdocs/types/","page":"More about types","title":"More about types","text":"能依据两个值的类型是否相同进行派发是非常有用的(例如类型提升系统就用到了该机制)。所以我们有很多理由给 Tuple{T,T} where T 一个不同的含义。为此,我们在子类型系统中增加了如下规则:\\textbf{如果一个变量在共变位置上出现了不止一次,那么其作用范围将仅局限于具体类型}。共变位置指在一个变量和引入该变量的 UnionAll 类型之间,只出现了元组 Tuple 类型和联合 Union 类型。这些变量被称为对角变量(diagonal variables)或具体变量(concrete variables)。","category":"page"},{"location":"devdocs/types/","page":"More about types","title":"More about types","text":"例如,元组 Tuple{T,T} where T 可以被看作是如下元组的集合 Union{Tuple{Int8,Int8}, Tuple{Int16,Int16}, ...}, 即 T 包括所有的具体类型。该规则会产生一些有趣的子类型结果。例如 Tuple{Real,Real} 不是 Tuple{T,T} where T 的子类型,因为前者包含了诸如 Tuple{Int8,Int16} 的子类型,该子类型的元素类型是不同的。Tuple{Real,Real} 和 Tuple{T,T} where T 又一个不容小视的交集 Tuple{T,T} where T<:Real。但是 Tuple{Real} 是 Tuple{T} where T 的子集,因为此时 T 只出现了一次,所以是不对角的。","category":"page"},{"location":"devdocs/types/","page":"More about types","title":"More about types","text":"现在考虑如下签名:","category":"page"},{"location":"devdocs/types/","page":"More about types","title":"More about types","text":"f(a::Array{T}, x::T, y::T) where {T} = ...","category":"page"},{"location":"devdocs/types/","page":"More about types","title":"More about types","text":"此例中, T 出现在了非共变位置,即 Array{T} 之内。 这意味着无论数组传递的类型是什么,该类型都会无歧义的决定 T,即 T 又一个等价性限制(equality constraint)。此时是不需要对角规则的,因为数组决定了 T,然后 x 和 y 则可以是 T 的任何子类型。所以非共变位置的变量均不受对角线规则的限制。上述定义的行为选择有一点矛盾,或许应该写成:","category":"page"},{"location":"devdocs/types/","page":"More about types","title":"More about types","text":"f(a::Array{T}, x::S, y::S) where {T, S<:T} = ...","category":"page"},{"location":"devdocs/types/","page":"More about types","title":"More about types","text":"为明确 x 和 y 应该有相同的类型。如果 x 和 y 可以有不同类型,这个版本的签名可以引入针对类型 y 的第三个变量。","category":"page"},{"location":"devdocs/types/","page":"More about types","title":"More about types","text":"下面一个难题是合集 Union{} 和对角线变量的交互作用,例如","category":"page"},{"location":"devdocs/types/","page":"More about types","title":"More about types","text":"f(x::Union{Nothing,T}, y::T) where {T} = ...","category":"page"},{"location":"devdocs/types/","page":"More about types","title":"More about types","text":"考虑一下这个生命的含义。y 的类型是 T。 而 x 的类型或者与 y 相同 T 或类型为空 Nothing。下面调用都是匹配的。","category":"page"},{"location":"devdocs/types/","page":"More about types","title":"More about types","text":"f(1, 1)\nf(\"\", \"\")\nf(2.0, 2.0)\nf(nothing, 1)\nf(nothing, \"\")\nf(nothing, 2.0)","category":"page"},{"location":"devdocs/types/","page":"More about types","title":"More about types","text":"上述例子告诉我们:当 x 的类型是空集 nothing::Nothing 时,y 的类型就没有任何限制了。此时方法标签中字段 y 可以是任何类型,即 y::Any。确实,下面两个类型是等价的:","category":"page"},{"location":"devdocs/types/","page":"More about types","title":"More about types","text":"(Tuple{Union{Nothing,T},T} where T) == Union{Tuple{Nothing,Any}, Tuple{T,T} where T}","category":"page"},{"location":"devdocs/types/","page":"More about types","title":"More about types","text":"一般的规则是:如果出现在共变位置的一个具体变量只被子类型算法(subtyping algorithm)使用一次,则该具体变量的行为就会像一个抽象变量。上例中,当 x 类型为空时 Nothing,集合 Union{Nothing,T} 中的类型 T 不起作用,即 T 只在第二个槽中被用到。此时,无论把 Tuple{T} where T 中的 T 限制为具体类型还是不限制,该类型都等价于 Tuple{Any}。","category":"page"},{"location":"devdocs/types/","page":"More about types","title":"More about types","text":"当变量出现在非共变 位置时,无论是否被使用,该变量都不再是具体变量。否则类型的行为就会因为比较对象类型的不同而不同,从而违反传递律(transitive)。例如,","category":"page"},{"location":"devdocs/types/","page":"More about types","title":"More about types","text":"Tuple{Int,Int8,Vector{Integer}} <: Tuple{T,T,Vector{Union{Integer,T}}} where T","category":"page"},{"location":"devdocs/types/","page":"More about types","title":"More about types","text":"如果忽略掉合集 Union 内部的 T,则 T 就是具体的,且上述判断结果是 “否”,因为左侧元组前两个成分的类型是不同的。这两个类型不相同。再看下例:","category":"page"},{"location":"devdocs/types/","page":"More about types","title":"More about types","text":"Tuple{Int,Int8,Vector{Any}} <: Tuple{T,T,Vector{Union{Integer,T}}} where T","category":"page"},{"location":"devdocs/types/","page":"More about types","title":"More about types","text":"此处合集 Union 内的 T 是不能被忽略的,因为 T 必须等于 Any,即 T == Any。所以 T 不能是具体的,且判断结果为“真”。所以,类型 T 的具体还是抽象是受制于其他类型特征的。这是不被接受的,因为类型的含义必须是清晰和自洽的。所以,向量 Vector 之内的 T 需要同时考虑这两种情况。","category":"page"},{"location":"devdocs/types/#对角变量的子类型","page":"More about types","title":"对角变量的子类型","text":"","category":"section"},{"location":"devdocs/types/","page":"More about types","title":"More about types","text":"对角变量的子系统算法(substyping algorithm)有两个成分:(1)确定变量出现次数;(2)确保对角变量只包含具体类型。","category":"page"},{"location":"devdocs/types/","page":"More about types","title":"More about types","text":"第一个任务由两个计数器完成。环境中的每个自由变量都有两个计数器 occurs_inv 和 occurs_cov (在文件 src/subtype.c 中),分别用于追踪不变和共变的出现次数。如果 occurs_inv == 0 && occurs_cov > 1 则这个变量就是对角的。","category":"page"},{"location":"devdocs/types/","page":"More about types","title":"More about types","text":"第二个任务通过在变量下界添加一个条件实现。子类型算法在运行过程中会逐渐压缩每个变量的界限(提高下界和降低上界),以保证子类型关系在该变量范围内能继续保持。评估完对角变量合集类型 UnionAll 后,可以查看边界的最终值。因为变量必须是具体的,所以如果其下边界不是具体类型的子类型,就会产生矛盾。例如,抽象类型 AbstractArray 不可能是一个具体类型的子类型,而具体类型 Int 则可以,空类型 Bottom 也可以。如果下边界没通过该测试,算法将终止并返回 false。","category":"page"},{"location":"devdocs/types/","page":"More about types","title":"More about types","text":"例如,如果 T 是 Union{Int,String} 的上位类型,则 Tuple{Int,String} 将是 Tuple{T,T} where T 的子集,即 Tuple{Int,String} <: Tuple{T,T} where T 的返回值将为真。但 Union{Int,String} 是一个抽象类型,所以上述关系不成立。","category":"page"},{"location":"devdocs/types/","page":"More about types","title":"More about types","text":"具体性判断是由函数 is_leaf_bound 完成的。注意该函数与函数 jl_is_leaf_type 稍微有点不同,因为其对类型 Bottom 的返回值也为真 true。该函数目前是启发式的,无法捕获所有的具体类型。该函数的困难在于,其他变量类型的界限会影响当下变量下界限的具体与否。例如,只有当 T 的上界限和下界限都是 Int 时,类型 Vector{T} 才和具体类型 Vector{Int} 相同。目前,设计者还没有想出一个完备的算法来解决该问题。","category":"page"},{"location":"devdocs/types/#内部机制","page":"More about types","title":"内部机制","text":"","category":"section"},{"location":"devdocs/types/","page":"More about types","title":"More about types","text":"大部分类型处理操作都存储在 jltypes.c 和 subtype.c 这两个文件中。了解自类型系统的最好方式是查看其工作方式。用 make debug 创建且在调试器中运行程序。手册gdb debugging tips章中有一些有用的建议。","category":"page"},{"location":"devdocs/types/","page":"More about types","title":"More about types","text":"因为 REPL 中也经常使用子类型代码 – 这些代码中的断点也经常被触发。所以定义下面函数并在 jl_breakpoint 中设定一个断点将非常方便:","category":"page"},{"location":"devdocs/types/","page":"More about types","title":"More about types","text":"julia> function mysubtype(a,b)\n ccall(:jl_breakpoint, Cvoid, (Any,), nothing)\n a <: b\n end","category":"page"},{"location":"devdocs/types/","page":"More about types","title":"More about types","text":"一旦该断点被触发,你就可以在其他函数中设定断点了。","category":"page"},{"location":"devdocs/types/","page":"More about types","title":"More about types","text":"作为热身,试一下下面代码","category":"page"},{"location":"devdocs/types/","page":"More about types","title":"More about types","text":"mysubtype(Tuple{Int, Float64}, Tuple{Integer, Real})","category":"page"},{"location":"devdocs/types/","page":"More about types","title":"More about types","text":"你也可以用一个更复杂的例子让其变得更有趣:","category":"page"},{"location":"devdocs/types/","page":"More about types","title":"More about types","text":"mysubtype(Tuple{Array{Int,2}, Int8}, Tuple{Array{T}, T} where T)","category":"page"},{"location":"devdocs/types/#子类型和方法排序","page":"More about types","title":"子类型和方法排序","text":"","category":"section"},{"location":"devdocs/types/","page":"More about types","title":"More about types","text":"函数 type_morespecific 可用来对函数的方法列表从最具特异行到最不具特异性进行部分排序(partial order)。特异性是严格的:如果 a 比 b 更特异,则 b 就不比 a 更特异。","category":"page"},{"location":"devdocs/types/","page":"More about types","title":"More about types","text":"如果 a 是 b 的严格子类型(strict subtype),那么 a 就自动的比 b 更特异。接下来,函数 type_morespecific 还引进了一些不太形式化的规则。例如,子类型 subtype 对参数的数量敏感,而函数 type_morespecific 则不敏感。特别的,Tuple{Int,AbstractFloat} 比 Tuple{Integer} 更特异,虽然前者不是后者的子类型。此外, Tuple{Int,AbstractFloat} 和 Tuple{Integer,Float64} 不存在特异性关系。类似的,Tuple{Int,Vararg{Int}} 不是 Tuple{Integer} 的子类型,但前者比后者更特异。但是,长度确实也影响特异性关系morespecific,如 Tuple{Int,Int} 比 Tuple{Int,Vararg{Int}} 更特异。","category":"page"},{"location":"devdocs/types/","page":"More about types","title":"More about types","text":"要调试方法的排序,定义下面的函数很方便:","category":"page"},{"location":"devdocs/types/","page":"More about types","title":"More about types","text":"type_morespecific(a, b) = ccall(:jl_type_morespecific, Cint, (Any,Any), a, b)","category":"page"},{"location":"devdocs/types/","page":"More about types","title":"More about types","text":"它可以被用来测试元组 a 是否比元组 b 更特异。","category":"page"},{"location":"devdocs/locks/#Proper-maintenance-and-care-of-multi-threading-locks","page":"Proper maintenance and care of multi-threading locks","title":"Proper maintenance and care of multi-threading locks","text":"","category":"section"},{"location":"devdocs/locks/","page":"Proper maintenance and care of multi-threading locks","title":"Proper maintenance and care of multi-threading locks","text":"The following strategies are used to ensure that the code is dead-lock free (generally by addressing the 4th Coffman condition: circular wait).","category":"page"},{"location":"devdocs/locks/","page":"Proper maintenance and care of multi-threading locks","title":"Proper maintenance and care of multi-threading locks","text":"structure code such that only one lock will need to be acquired at a time\nalways acquire shared locks in the same order, as given by the table below\navoid constructs that expect to need unrestricted recursion","category":"page"},{"location":"devdocs/locks/#Locks","page":"Proper maintenance and care of multi-threading locks","title":"Locks","text":"","category":"section"},{"location":"devdocs/locks/","page":"Proper maintenance and care of multi-threading locks","title":"Proper maintenance and care of multi-threading locks","text":"Below are all of the locks that exist in the system and the mechanisms for using them that avoid the potential for deadlocks (no Ostrich algorithm allowed here):","category":"page"},{"location":"devdocs/locks/","page":"Proper maintenance and care of multi-threading locks","title":"Proper maintenance and care of multi-threading locks","text":"The following are definitely leaf locks (level 1), and must not try to acquire any other lock:","category":"page"},{"location":"devdocs/locks/","page":"Proper maintenance and care of multi-threading locks","title":"Proper maintenance and care of multi-threading locks","text":"safepoint\nNote that this lock is acquired implicitly by JL_LOCK and JL_UNLOCK. use the _NOGC variants to avoid that for level 1 locks.While holding this lock, the code must not do any allocation or hit any safepoints. Note that there are safepoints when doing allocation, enabling / disabling GC, entering / restoring exception frames, and taking / releasing locks.\nshared_map\nfinalizers\npagealloc\ngcpermlock\nflisp\njlinstackwalk (Win32)\nflisp itself is already threadsafe, this lock only protects the jl_ast_context_list_t pool","category":"page"},{"location":"devdocs/locks/","page":"Proper maintenance and care of multi-threading locks","title":"Proper maintenance and care of multi-threading locks","text":"The following is a leaf lock (level 2), and only acquires level 1 locks (safepoint) internally:","category":"page"},{"location":"devdocs/locks/","page":"Proper maintenance and care of multi-threading locks","title":"Proper maintenance and care of multi-threading locks","text":"typecache\nModule->lock","category":"page"},{"location":"devdocs/locks/","page":"Proper maintenance and care of multi-threading locks","title":"Proper maintenance and care of multi-threading locks","text":"The following is a level 3 lock, which can only acquire level 1 or level 2 locks internally:","category":"page"},{"location":"devdocs/locks/","page":"Proper maintenance and care of multi-threading locks","title":"Proper maintenance and care of multi-threading locks","text":"Method->writelock","category":"page"},{"location":"devdocs/locks/","page":"Proper maintenance and care of multi-threading locks","title":"Proper maintenance and care of multi-threading locks","text":"The following is a level 4 lock, which can only recurse to acquire level 1, 2, or 3 locks:","category":"page"},{"location":"devdocs/locks/","page":"Proper maintenance and care of multi-threading locks","title":"Proper maintenance and care of multi-threading locks","text":"MethodTable->writelock","category":"page"},{"location":"devdocs/locks/","page":"Proper maintenance and care of multi-threading locks","title":"Proper maintenance and care of multi-threading locks","text":"No Julia code may be called while holding a lock above this point.","category":"page"},{"location":"devdocs/locks/","page":"Proper maintenance and care of multi-threading locks","title":"Proper maintenance and care of multi-threading locks","text":"The following are a level 6 lock, which can only recurse to acquire locks at lower levels:","category":"page"},{"location":"devdocs/locks/","page":"Proper maintenance and care of multi-threading locks","title":"Proper maintenance and care of multi-threading locks","text":"codegen\njlmodulesmutex","category":"page"},{"location":"devdocs/locks/","page":"Proper maintenance and care of multi-threading locks","title":"Proper maintenance and care of multi-threading locks","text":"The following is an almost root lock (level end-1), meaning only the root look may be held when trying to acquire it:","category":"page"},{"location":"devdocs/locks/","page":"Proper maintenance and care of multi-threading locks","title":"Proper maintenance and care of multi-threading locks","text":"typeinf\nthis one is perhaps one of the most tricky ones, since type-inference can be invoked from many pointscurrently the lock is merged with the codegen lock, since they call each other recursively","category":"page"},{"location":"devdocs/locks/","page":"Proper maintenance and care of multi-threading locks","title":"Proper maintenance and care of multi-threading locks","text":"The following lock synchronizes IO operation. Be aware that doing any I/O (for example, printing warning messages or debug information) while holding any other lock listed above may result in pernicious and hard-to-find deadlocks. BE VERY CAREFUL!","category":"page"},{"location":"devdocs/locks/","page":"Proper maintenance and care of multi-threading locks","title":"Proper maintenance and care of multi-threading locks","text":"iolock\nIndividual ThreadSynchronizers locks\nthis may continue to be held after releasing the iolock, or acquired without it, but be very careful to never attempt to acquire the iolock while holding it","category":"page"},{"location":"devdocs/locks/","page":"Proper maintenance and care of multi-threading locks","title":"Proper maintenance and care of multi-threading locks","text":"The following is the root lock, meaning no other lock shall be held when trying to acquire it:","category":"page"},{"location":"devdocs/locks/","page":"Proper maintenance and care of multi-threading locks","title":"Proper maintenance and care of multi-threading locks","text":"toplevel\nthis should be held while attempting a top-level action (such as making a new type or defining a new method): trying to obtain this lock inside a staged function will cause a deadlock condition!additionally, it's unclear if any code can safely run in parallel with an arbitrary toplevel expression, so it may require all threads to get to a safepoint first","category":"page"},{"location":"devdocs/locks/#Broken-Locks","page":"Proper maintenance and care of multi-threading locks","title":"Broken Locks","text":"","category":"section"},{"location":"devdocs/locks/","page":"Proper maintenance and care of multi-threading locks","title":"Proper maintenance and care of multi-threading locks","text":"The following locks are broken:","category":"page"},{"location":"devdocs/locks/","page":"Proper maintenance and care of multi-threading locks","title":"Proper maintenance and care of multi-threading locks","text":"toplevel\ndoesn't exist right nowfix: create it\nModule->lock\nThis is vulnerable to deadlocks since it can't be certain it is acquired in sequence. Some operations (such as import_module) are missing a lock.fix: replace with jl_modules_mutex?\nloading.jl: require and register_root_module\nThis file potentially has numerous problems.fix: needs locks","category":"page"},{"location":"devdocs/locks/#Shared-Global-Data-Structures","page":"Proper maintenance and care of multi-threading locks","title":"Shared Global Data Structures","text":"","category":"section"},{"location":"devdocs/locks/","page":"Proper maintenance and care of multi-threading locks","title":"Proper maintenance and care of multi-threading locks","text":"These data structures each need locks due to being shared mutable global state. It is the inverse list for the above lock priority list. This list does not include level 1 leaf resources due to their simplicity.","category":"page"},{"location":"devdocs/locks/","page":"Proper maintenance and care of multi-threading locks","title":"Proper maintenance and care of multi-threading locks","text":"MethodTable modifications (def, cache, kwsorter type) : MethodTable->writelock","category":"page"},{"location":"devdocs/locks/","page":"Proper maintenance and care of multi-threading locks","title":"Proper maintenance and care of multi-threading locks","text":"Type declarations : toplevel lock","category":"page"},{"location":"devdocs/locks/","page":"Proper maintenance and care of multi-threading locks","title":"Proper maintenance and care of multi-threading locks","text":"Type application : typecache lock","category":"page"},{"location":"devdocs/locks/","page":"Proper maintenance and care of multi-threading locks","title":"Proper maintenance and care of multi-threading locks","text":"Global variable tables : Module->lock","category":"page"},{"location":"devdocs/locks/","page":"Proper maintenance and care of multi-threading locks","title":"Proper maintenance and care of multi-threading locks","text":"Module serializer : toplevel lock","category":"page"},{"location":"devdocs/locks/","page":"Proper maintenance and care of multi-threading locks","title":"Proper maintenance and care of multi-threading locks","text":"JIT & type-inference : codegen lock","category":"page"},{"location":"devdocs/locks/","page":"Proper maintenance and care of multi-threading locks","title":"Proper maintenance and care of multi-threading locks","text":"MethodInstance/CodeInstance updates : Method->writelock, codegen lock","category":"page"},{"location":"devdocs/locks/","page":"Proper maintenance and care of multi-threading locks","title":"Proper maintenance and care of multi-threading locks","text":"These are set at construction and immutable:\nspecTypes\nsparam_vals\ndef","category":"page"},{"location":"devdocs/locks/","page":"Proper maintenance and care of multi-threading locks","title":"Proper maintenance and care of multi-threading locks","text":"These are set by jl_type_infer (while holding codegen lock):\ncache\nrettype\ninferred","category":"page"},{"location":"devdocs/locks/","page":"Proper maintenance and care of multi-threading locks","title":"Proper maintenance and care of multi-threading locks","text":" * valid ages","category":"page"},{"location":"devdocs/locks/","page":"Proper maintenance and care of multi-threading locks","title":"Proper maintenance and care of multi-threading locks","text":"inInference flag:\noptimization to quickly avoid recurring into jl_type_infer while it is already running\nactual state (of setting inferred, then fptr) is protected by codegen lock","category":"page"},{"location":"devdocs/locks/","page":"Proper maintenance and care of multi-threading locks","title":"Proper maintenance and care of multi-threading locks","text":"Function pointers:\nthese transition once, from NULL to a value, while the codegen lock is held\nCode-generator cache (the contents of functionObjectsDecls):\nthese can transition multiple times, but only while the codegen lock is held\nit is valid to use old version of this, or block for new versions of this, so races are benign, as long as the code is careful not to reference other data in the method instance (such as rettype) and assume it is coordinated, unless also holding the codegen lock","category":"page"},{"location":"devdocs/locks/","page":"Proper maintenance and care of multi-threading locks","title":"Proper maintenance and care of multi-threading locks","text":"LLVMContext : codegen lock","category":"page"},{"location":"devdocs/locks/","page":"Proper maintenance and care of multi-threading locks","title":"Proper maintenance and care of multi-threading locks","text":"Method : Method->writelock","category":"page"},{"location":"devdocs/locks/","page":"Proper maintenance and care of multi-threading locks","title":"Proper maintenance and care of multi-threading locks","text":"roots array (serializer and codegen)\ninvoke / specializations / tfunc modifications","category":"page"},{"location":"manual/parallel-computing/#并行计算","page":"并行计算","title":"并行计算","text":"","category":"section"},{"location":"manual/parallel-computing/","page":"并行计算","title":"并行计算","text":"Julia 支持这四类并发和并行编程:","category":"page"},{"location":"manual/parallel-computing/","page":"并行计算","title":"并行计算","text":"异步“任务”或协程:\nJulia Tasks 允许暂停和恢复 I/O、事件处理、生产者-消费者进程和类似模式的计算。 Tasks 可以通过wail 和fetch 等操作进行同步,并通过 Channel 进行通信。 虽然严格来说不是并行计算,但 Julia 允许在多个线程上调度任务。\n多线程:\nJulia 的多线程提供了在多个线程、CPU 内核或共享内存上同时调度任务的能力。这通常是在个人 PC 或单个大型多核服务器上获得并行性的最简单方法。 Julia 的多线程是可组合的。当一个多线程函数调用另一个多线程函数时,Julia 将在可用资源上全局调度所有线程,而不会超额使用。\n分布式计算:\n分布式计算运行多个具有独立内存空间的 Julia 进程。 这些可以在同一台计算机或多台计算机上。 Distributed 标准库提供了远程执行 Julia 函数的能力。 使用这个基本构建块,可以构建许多不同类型的分布式计算抽象。 像 DistributedArrays.jl 这样的包就是这种抽象的一个示例。 另一方面,像 MPI.jl 和 Elemental.jl 这样的包提供对现有 MPI 生态库的访问。\nGPU 计算:\nJulia GPU 编译器提供了在 GPU 上本地运行 Julia 代码的能力。 有一个针对 GPU 的丰富的 Julia 软件包生态系统。 JuliaGPU.org 网站提供了功能列表、支持的 GPU、相关包和文档。","category":"page"},{"location":"manual/style-guide/#代码风格指南","page":"代码风格指南","title":"代码风格指南","text":"","category":"section"},{"location":"manual/style-guide/","page":"代码风格指南","title":"代码风格指南","text":"接下来的部分将介绍如何写出具有 Julia 风格的代码。当然,这些规则并不是绝对的,它们只是一些建议,以便更好地帮助你熟悉这门语言,以及在不同的代码设计中做出选择。","category":"page"},{"location":"manual/style-guide/#缩进","page":"代码风格指南","title":"缩进","text":"","category":"section"},{"location":"manual/style-guide/","page":"代码风格指南","title":"代码风格指南","text":"每个缩进级别使用 4 个空格。","category":"page"},{"location":"manual/style-guide/#写函数,而不是仅仅写脚本","page":"代码风格指南","title":"写函数,而不是仅仅写脚本","text":"","category":"section"},{"location":"manual/style-guide/","page":"代码风格指南","title":"代码风格指南","text":"一开始解决问题的时候,直接从最外层一步步写代码的确很便捷,但你应该尽早地将代码组织成函数。函数有更强的复用性和可测试性,并且能更清楚地让人知道哪些步骤做完了,以及每一步骤的输入输出分别是什么。此外,由于 Julia 编译器特殊的工作方式,写在函数中的代码往往要比最外层的代码运行地快得多。","category":"page"},{"location":"manual/style-guide/","page":"代码风格指南","title":"代码风格指南","text":"此外值得一提的是,函数应当接受参数,而不是直接使用全局变量进行操作(pi 等常数除外)。","category":"page"},{"location":"manual/style-guide/#类型不要写得过于具体","page":"代码风格指南","title":"类型不要写得过于具体","text":"","category":"section"},{"location":"manual/style-guide/","page":"代码风格指南","title":"代码风格指南","text":"代码应该写得尽可能通用。例如,下面这段代码:","category":"page"},{"location":"manual/style-guide/","page":"代码风格指南","title":"代码风格指南","text":"Complex{Float64}(x)","category":"page"},{"location":"manual/style-guide/","page":"代码风格指南","title":"代码风格指南","text":"更好的写法是写成下面的通用函数:","category":"page"},{"location":"manual/style-guide/","page":"代码风格指南","title":"代码风格指南","text":"complex(float(x))","category":"page"},{"location":"manual/style-guide/","page":"代码风格指南","title":"代码风格指南","text":"第二个版本会把 x 转换成合适的类型,而不是某个写死的类型。","category":"page"},{"location":"manual/style-guide/","page":"代码风格指南","title":"代码风格指南","text":"这种代码风格与函数的参数尤其相关。例如,当一个参数可以是任何整型时,不要将它的类型声明为 Int 或 Int32,而要使用抽象类型(abstract type)Integer 来表示。事实上,除非确实需要将其与其它的方法定义区分开,很多情况下你可以干脆完全省略掉参数的类型,因为如果你的操作中有不支持某种参数类型的操作的话,反正都会抛出 MethodError 的。这也称作 鸭子类型)。","category":"page"},{"location":"manual/style-guide/","page":"代码风格指南","title":"代码风格指南","text":"例如,考虑这样的一个叫做 addone 的函数,其返回值为它的参数加 1 :","category":"page"},{"location":"manual/style-guide/","page":"代码风格指南","title":"代码风格指南","text":"addone(x::Int) = x + 1 # works only for Int\naddone(x::Integer) = x + oneunit(x) # any integer type\naddone(x::Number) = x + oneunit(x) # any numeric type\naddone(x) = x + oneunit(x) # any type supporting + and oneunit","category":"page"},{"location":"manual/style-guide/","page":"代码风格指南","title":"代码风格指南","text":"最后一种定义可以处理所有支持 oneunit (返回和 x 相同类型的 1,以避免不需要的类型提升(type promotion))以及 + 函数的类型。这里的关键点在于,只定义通用的 addone(x) = x + oneunit(x) 并不会带来性能上的损失,因为 Julia 会在需要的时候自动编译特定的版本。比如说,当第一次调用 addone(12) 时,Julia 会自动编译一个特定的 addone 函数,它接受一个 x::Int 的参数,并把调用的 oneunit 替换为内连的值 1。因此,上述的前三种 addone 的定义对于第四种来说是完全多余的。","category":"page"},{"location":"manual/style-guide/#让调用者处理多余的参数多样性","page":"代码风格指南","title":"让调用者处理多余的参数多样性","text":"","category":"section"},{"location":"manual/style-guide/","page":"代码风格指南","title":"代码风格指南","text":"如下的代码:","category":"page"},{"location":"manual/style-guide/","page":"代码风格指南","title":"代码风格指南","text":"function foo(x, y)\n x = Int(x); y = Int(y)\n ...\nend\nfoo(x, y)","category":"page"},{"location":"manual/style-guide/","page":"代码风格指南","title":"代码风格指南","text":"请写成这样:","category":"page"},{"location":"manual/style-guide/","page":"代码风格指南","title":"代码风格指南","text":"function foo(x::Int, y::Int)\n ...\nend\nfoo(Int(x), Int(y))","category":"page"},{"location":"manual/style-guide/","page":"代码风格指南","title":"代码风格指南","text":"这种风格更好,因为 foo 函数其实不需要接受所有类型的数,而只需要接受 Int。","category":"page"},{"location":"manual/style-guide/","page":"代码风格指南","title":"代码风格指南","text":"这里的关键在于,如果一个函数需要处理的是整数,强制让调用者来决定非整数如何被转换(比如说向下还是向上取整)会更好。同时,把类型声明得具体一些的话可以为以后的方法定义留有更多的空间。","category":"page"},{"location":"manual/style-guide/#bang-convention","page":"代码风格指南","title":"在修改其参数的函数名称后加 !","text":"","category":"section"},{"location":"manual/style-guide/","page":"代码风格指南","title":"代码风格指南","text":"如下的代码:","category":"page"},{"location":"manual/style-guide/","page":"代码风格指南","title":"代码风格指南","text":"function double(a::AbstractArray{<:Number})\n for i = firstindex(a):lastindex(a)\n a[i] *= 2\n end\n return a\nend","category":"page"},{"location":"manual/style-guide/","page":"代码风格指南","title":"代码风格指南","text":"请写成这样:","category":"page"},{"location":"manual/style-guide/","page":"代码风格指南","title":"代码风格指南","text":"function double!(a::AbstractArray{<:Number})\n for i = firstindex(a):lastindex(a)\n a[i] *= 2\n end\n return a\nend","category":"page"},{"location":"manual/style-guide/","page":"代码风格指南","title":"代码风格指南","text":"Julia 的 Base 模块中的函数都遵循了这种规范,且包含很多例子:有的函数同时有拷贝和修改的形式(比如 sort 和 sort!),还有一些只有修改(比如 push!,pop! 和 splice!)。为了方便起见,这类函数通常也会把修改后的数组作为返回值。","category":"page"},{"location":"manual/style-guide/#避免使用奇怪的-Union-类型","page":"代码风格指南","title":"避免使用奇怪的 Union 类型","text":"","category":"section"},{"location":"manual/style-guide/","page":"代码风格指南","title":"代码风格指南","text":"使用 Union{Function,AbstractString} 这样的类型的时候通常意味着设计还不够清晰。","category":"page"},{"location":"manual/style-guide/#避免复杂的容器类型","page":"代码风格指南","title":"避免复杂的容器类型","text":"","category":"section"},{"location":"manual/style-guide/","page":"代码风格指南","title":"代码风格指南","text":"像下面这样构造数组通常没有什么好处:","category":"page"},{"location":"manual/style-guide/","page":"代码风格指南","title":"代码风格指南","text":"a = Vector{Union{Int,AbstractString,Tuple,Array}}(undef, n)","category":"page"},{"location":"manual/style-guide/","page":"代码风格指南","title":"代码风格指南","text":"这种情况下,Vector{Any}(undef, n)更合适些。此外,相比将所有可能的类型都打包在一起,直接在使用时标注具体的数据类型(比如:a[i]::Int)对编译器来说更有用。","category":"page"},{"location":"manual/style-guide/#方法导出优先于直接字段访问","page":"代码风格指南","title":"方法导出优先于直接字段访问","text":"","category":"section"},{"location":"manual/style-guide/","page":"代码风格指南","title":"代码风格指南","text":"惯例上,Julia 代码通常应将模块的导出方法视为其类型的接口。 一个对象的字段通常被认为是实现细节,如果这被声明为 API,用户代码应该只直接访问它们。 这有几个好处:","category":"page"},{"location":"manual/style-guide/","page":"代码风格指南","title":"代码风格指南","text":"包开发人员可以更自由地更改实现而不会破坏用户代码。","category":"page"},{"location":"manual/style-guide/","page":"代码风格指南","title":"代码风格指南","text":"\n方法可以传递给高阶结构,如 map(例如 map(imag, zs))而不是 [z.im for z in zs])。\n方法可以定义在抽象类型上。\n方法可以描述可以在不同类型之间共享的概念操作(例如 real(z) 适用于复数或四元数)。","category":"page"},{"location":"manual/style-guide/","page":"代码风格指南","title":"代码风格指南","text":"Julia 的调度系统鼓励这种风格,因为 play(x::MyType) 只在该特定类型上定义了 play 方法,其它类型有自己的实现。","category":"page"},{"location":"manual/style-guide/","page":"代码风格指南","title":"代码风格指南","text":"同样,除非文档另有说明,否则非导出函数通常是内部的并且可能会发生变化。 名称有时会被赋予一个 _ 前缀(或后缀)以进一步暗示某些是“内部”或实现细节,但这不是规则。","category":"page"},{"location":"manual/style-guide/","page":"代码风格指南","title":"代码风格指南","text":"该规则的反例包括 NamedTuple、RegexMatch、StatStruct。","category":"page"},{"location":"manual/style-guide/#使用和-Julia-base/-文件夹中的代码一致的命名习惯","page":"代码风格指南","title":"使用和 Julia base/ 文件夹中的代码一致的命名习惯","text":"","category":"section"},{"location":"manual/style-guide/","page":"代码风格指南","title":"代码风格指南","text":"module 和 type 的名字使用大写开头的驼峰命名法:module SparseArrays,struct UnitRange。\n函数名使用小写字母,且当可读时可以将多个单词拼在一起。必要的时候,可以使用下划线作为单词分隔符。下划线也被用于指明概念的组合(比如 remotecall_fetch 作为 fetch(remotecall(...)) 的一个更高效的实现)或者变化。\n至少改变其中一个参数的函数名称以!结尾。\n虽然简洁性很重要,但避免使用缩写(用 indexin 而不是 indxin),因为这会让记住单词有没有被缩写或如何被缩写变得十分困难。","category":"page"},{"location":"manual/style-guide/","page":"代码风格指南","title":"代码风格指南","text":"如果一个函数名需要多个单词,请考虑这个函数是否代表了超过一个概念,是不是分成几个更小的部分更好。","category":"page"},{"location":"manual/style-guide/#使用与-Julia-Base-中的函数类似的参数顺序","page":"代码风格指南","title":"使用与 Julia Base 中的函数类似的参数顺序","text":"","category":"section"},{"location":"manual/style-guide/","page":"代码风格指南","title":"代码风格指南","text":"一般来说,Base 库使用以下的函数参数顺序(如适用):","category":"page"},{"location":"manual/style-guide/","page":"代码风格指南","title":"代码风格指南","text":"函数参数. 函数的第一个参数可以接受 Function 类型,以便使用 do blocks 来传递多行匿名函数。\nI/O stream. 函数的第一个参数可以接受 IO 对象,以便将函数传递给 sprint 之类的函数,例如 sprint(show, x)。\n在输入参数的内容会被更改的情况下. 比如,在 fill!(x, v) 中,x 是要被修改的对象,所以放在要被插入 x 中的值前面。\nType. 把类型作为参数传入函数通常意味着返回值也会是同样的类型。 在 parse(Int, \"1\") 中,类型在需要解析的字符串之前。 还有很多类似的将类型作为函数第一个参数的例子,但是同时也需要注意到例如 read(io, String) 这样的函数中,会把 IO 参数放在类型的更前面,这样还是保持着这里描述的顺序。\n在输入参数的内容不会被更改的情况下. 比如在 fill!(x, v) 中的不被修改的 v,会放在 x 之后传入。\nKey. 对于关联集合来说,指的是键值对的键。 对于其它有索引的集合来说,指的是索引。\nValue. 对于关联集合来说,指的是键值对的值。 像fill!(x, v)这样的情况, 是v。\nEverything else. 任何的其它参数。\nVarargs. 指的是在函数调用时可以被无限列在后面的参数。 比如在 Matrix{T}(uninitialized, dims) 中,维数(dims)可以作为 Tuple 被传入(如 Matrix{T}(uninitialized, (1,2))),也可以作为可变参数(Vararg,如 Matrix{T}(uninitialized, 1, 2)。\nKeyword arguments. 在 Julia 中,关键字参数本来就不得不定义在函数定义的最后,列在这里仅仅是为了完整性。","category":"page"},{"location":"manual/style-guide/","page":"代码风格指南","title":"代码风格指南","text":"大多数函数并不会接受上述所有种类的参数,这些数字仅仅是表示当适用时的优先权。","category":"page"},{"location":"manual/style-guide/","page":"代码风格指南","title":"代码风格指南","text":"当然,在一些情况下有例外。例如,convert 函数总是把类型作为第一个参数。setindex! 函数的值参数在索引参数之前,这样可以让索引作为可变参数传入。","category":"page"},{"location":"manual/style-guide/","page":"代码风格指南","title":"代码风格指南","text":"设计 API 时,尽可能秉承着这种一般顺序会让函数的使用者有一种更一致的体验。","category":"page"},{"location":"manual/style-guide/#不要过度使用-try-catch","page":"代码风格指南","title":"不要过度使用 try-catch","text":"","category":"section"},{"location":"manual/style-guide/","page":"代码风格指南","title":"代码风格指南","text":"比起依赖于捕获错误,更好的是避免错误。","category":"page"},{"location":"manual/style-guide/#不要给条件语句加括号","page":"代码风格指南","title":"不要给条件语句加括号","text":"","category":"section"},{"location":"manual/style-guide/","page":"代码风格指南","title":"代码风格指南","text":"Julia 不要求在 if 和 while 后的条件两边加括号。使用如下写法:","category":"page"},{"location":"manual/style-guide/","page":"代码风格指南","title":"代码风格指南","text":"if a == b","category":"page"},{"location":"manual/style-guide/","page":"代码风格指南","title":"代码风格指南","text":"而不是:","category":"page"},{"location":"manual/style-guide/","page":"代码风格指南","title":"代码风格指南","text":"if (a == b)","category":"page"},{"location":"manual/style-guide/#不要过度使用-...","page":"代码风格指南","title":"不要过度使用 ...","text":"","category":"section"},{"location":"manual/style-guide/","page":"代码风格指南","title":"代码风格指南","text":"拼接函数参数是会上瘾的。请用简单的 [a; b] 来代替 [a..., b...],因为前者已经是被拼接的数组了。collect(a) 也比 [a...] 更好,但因为 a 已经是一个可迭代的变量了,通常不把它转换成数组就直接使用甚至更好。","category":"page"},{"location":"manual/style-guide/#不要使用不必要的静态参数","page":"代码风格指南","title":"不要使用不必要的静态参数","text":"","category":"section"},{"location":"manual/style-guide/","page":"代码风格指南","title":"代码风格指南","text":"如下的函数签名:","category":"page"},{"location":"manual/style-guide/","page":"代码风格指南","title":"代码风格指南","text":"foo(x::T) where {T<:Real} = ...","category":"page"},{"location":"manual/style-guide/","page":"代码风格指南","title":"代码风格指南","text":"应当被写作:","category":"page"},{"location":"manual/style-guide/","page":"代码风格指南","title":"代码风格指南","text":"foo(x::Real) = ...","category":"page"},{"location":"manual/style-guide/","page":"代码风格指南","title":"代码风格指南","text":"尤其是当 T 没有被用在函数体中时格外有意义。即使 T 被用到了,通常也可以被替换为 typeof(x),后者不会导致性能上的差别。注意这并不是针对静态参数的一般警告,而仅仅是针对那些不必要的情况。","category":"page"},{"location":"manual/style-guide/","page":"代码风格指南","title":"代码风格指南","text":"同样需要注意的是,容器类型在函数调用中可能明确地需要类型参数。详情参见避免使用带抽象容器的字段。","category":"page"},{"location":"manual/style-guide/#避免判断变量是实例还是类型的混乱","page":"代码风格指南","title":"避免判断变量是实例还是类型的混乱","text":"","category":"section"},{"location":"manual/style-guide/","page":"代码风格指南","title":"代码风格指南","text":"如下的一组定义容易令人困惑:","category":"page"},{"location":"manual/style-guide/","page":"代码风格指南","title":"代码风格指南","text":"foo(::Type{MyType}) = ...\nfoo(::MyType) = foo(MyType)","category":"page"},{"location":"manual/style-guide/","page":"代码风格指南","title":"代码风格指南","text":"请决定问题里的概念应当是 MyType 还是 MyType(),然后坚持使用其一。","category":"page"},{"location":"manual/style-guide/","page":"代码风格指南","title":"代码风格指南","text":"首选风格应是默认使用实例,只有在需要解决某些问题时才添加涉及Type{MyType}的方法。","category":"page"},{"location":"manual/style-guide/","page":"代码风格指南","title":"代码风格指南","text":"如果一个类型实际上是个枚举,它应该被定义成一个单一的类型(理想的情况是不可变结构或原始类型),把枚举值作为它的实例。构造器和转换器可以检查那些值是否有效。这种设计比把枚举做成抽象类型,并把“值”做成子类型来得更受推崇。","category":"page"},{"location":"manual/style-guide/#不要过度使用宏","page":"代码风格指南","title":"不要过度使用宏","text":"","category":"section"},{"location":"manual/style-guide/","page":"代码风格指南","title":"代码风格指南","text":"请注意有的宏实际上可以被写成一个函数。","category":"page"},{"location":"manual/style-guide/","page":"代码风格指南","title":"代码风格指南","text":"在宏内部调用 eval 是一个特别危险的警告标志,它意味着这个宏仅在被最外层调用时起作用。如果这样的宏被写成函数,它会自然地访问得到它所需要的运行时值。","category":"page"},{"location":"manual/style-guide/#不要把不安全的操作暴露在接口层","page":"代码风格指南","title":"不要把不安全的操作暴露在接口层","text":"","category":"section"},{"location":"manual/style-guide/","page":"代码风格指南","title":"代码风格指南","text":"如果你有一个使用本地指针的类型:","category":"page"},{"location":"manual/style-guide/","page":"代码风格指南","title":"代码风格指南","text":"mutable struct NativeType\n p::Ptr{UInt8}\n ...\nend","category":"page"},{"location":"manual/style-guide/","page":"代码风格指南","title":"代码风格指南","text":"不要定义类似如下的函数:","category":"page"},{"location":"manual/style-guide/","page":"代码风格指南","title":"代码风格指南","text":"getindex(x::NativeType, i) = unsafe_load(x.p, i)","category":"page"},{"location":"manual/style-guide/","page":"代码风格指南","title":"代码风格指南","text":"这里的问题在于,这个类型的用户可能会在意识不到这个操作不安全的情况下写出 x[i],然后容易遇到内存错误。","category":"page"},{"location":"manual/style-guide/","page":"代码风格指南","title":"代码风格指南","text":"在这样的函数中,可以加上对操作的检查来确保安全,或者可以在名字的某处加上 unsafe 来警告调用者。","category":"page"},{"location":"manual/style-guide/#不要重载基础容器类型的方法","page":"代码风格指南","title":"不要重载基础容器类型的方法","text":"","category":"section"},{"location":"manual/style-guide/","page":"代码风格指南","title":"代码风格指南","text":"有时可能会想要写这样的定义:","category":"page"},{"location":"manual/style-guide/","page":"代码风格指南","title":"代码风格指南","text":"show(io::IO, v::Vector{MyType}) = ...","category":"page"},{"location":"manual/style-guide/","page":"代码风格指南","title":"代码风格指南","text":"这样可以提供对特定的某种新元素类型的向量的自定义显示。这种做法虽然很诱人,但应当被避免。这里的问题在于用户会想着一个像 Vector() 这样熟知的类型以某种方式表现,但过度自定义的行为会让使用变得更难。","category":"page"},{"location":"manual/style-guide/#避免类型盗版","page":"代码风格指南","title":"避免类型盗版","text":"","category":"section"},{"location":"manual/style-guide/","page":"代码风格指南","title":"代码风格指南","text":"“类型盗版”(type piracy)指的是扩展或是重定义 Base 或其它包中的并不是你所定义的类型的方法。在某些情况下,你可以几乎毫无副作用地逃避类型盗版。但在极端情况下,你甚至会让 Julia 崩溃(比如说你的方法扩展或重定义造成了对 ccall 传入了无效的输入)。类型盗版也让代码推导变得更复杂,且可能会引入难以预料和诊断的不兼容性。","category":"page"},{"location":"manual/style-guide/","page":"代码风格指南","title":"代码风格指南","text":"例如,你也许想在一个模块中定义符号上的乘法:","category":"page"},{"location":"manual/style-guide/","page":"代码风格指南","title":"代码风格指南","text":"module A\nimport Base.*\n*(x::Symbol, y::Symbol) = Symbol(x,y)\nend","category":"page"},{"location":"manual/style-guide/","page":"代码风格指南","title":"代码风格指南","text":"这里的问题时现在其它用到 Base.* 的模块同样会看到这个定义。由于 Symbol 是定义在 Base 里再被其它模块所使用的,这可能不可预料地改变无关代码的行为。这里有几种替代的方式,包括使用一个不同的函数名称,或是把 Symbol 给包在另一个你自己定义的类型中。","category":"page"},{"location":"manual/style-guide/","page":"代码风格指南","title":"代码风格指南","text":"有时候,耦合的包可能会使用类型盗版,以此来从定义分隔特性,尤其是当那些包是一些合作的作者设计的时候,且那些定义是可重用的时候。例如,一个包可能提供一些对处理色彩有用的类型,另一个包可能为那些类型定义色彩空间之间转换的方法。再举一个例子,一个包可能是一些 C 代码的简易包装,另一个包可能就“盗版”来实现一些更高级别的、对 Julia 友好的 API。","category":"page"},{"location":"manual/style-guide/#注意类型相等","page":"代码风格指南","title":"注意类型相等","text":"","category":"section"},{"location":"manual/style-guide/","page":"代码风格指南","title":"代码风格指南","text":"通常会用 isa 和 <: 来对类型进行测试,而不会用到 ==。检测类型的相等通常只对和一个已知的具体类型比较有意义(例如 T == Float64),或者你真的真的知道自己在做什么。","category":"page"},{"location":"manual/style-guide/#不要写-x-f(x)","page":"代码风格指南","title":"不要写 x->f(x)","text":"","category":"section"},{"location":"manual/style-guide/","page":"代码风格指南","title":"代码风格指南","text":"因为调用高阶函数时经常会用到匿名函数,很容易认为这是合理甚至必要的。但任何函数都可以被直接传递,并不需要被“包\"在一个匿名函数中。比如 map(x->f(x), a) 应当被写成 map(f, a)。","category":"page"},{"location":"manual/style-guide/#尽可能避免使用浮点数作为通用代码的字面量","page":"代码风格指南","title":"尽可能避免使用浮点数作为通用代码的字面量","text":"","category":"section"},{"location":"manual/style-guide/","page":"代码风格指南","title":"代码风格指南","text":"当写处理数字,且可以处理多种不同数字类型的参数的通用代码时,请使用对参数影响(通过类型提升)尽可能少的类型的字面量。","category":"page"},{"location":"manual/style-guide/","page":"代码风格指南","title":"代码风格指南","text":"例如,","category":"page"},{"location":"manual/style-guide/","page":"代码风格指南","title":"代码风格指南","text":"julia> f(x) = 2.0 * x\nf (generic function with 1 method)\n\njulia> f(1//2)\n1.0\n\njulia> f(1/2)\n1.0\n\njulia> f(1)\n2.0","category":"page"},{"location":"manual/style-guide/","page":"代码风格指南","title":"代码风格指南","text":"而应当被写作:","category":"page"},{"location":"manual/style-guide/","page":"代码风格指南","title":"代码风格指南","text":"julia> g(x) = 2 * x\ng (generic function with 1 method)\n\njulia> g(1//2)\n1//1\n\njulia> g(1/2)\n1.0\n\njulia> g(1)\n2","category":"page"},{"location":"manual/style-guide/","page":"代码风格指南","title":"代码风格指南","text":"如你所见,使用了 Int 字面量的第二个版本保留了输入参数的类型,而第一个版本没有。这是因为例如 promote_type(Int, Float64) == Float64,且做乘法时会需要类型提升。类似地,Rational 字面量比 Float64 字面量对类型有着更小的破坏性,但比 Int 大。","category":"page"},{"location":"manual/style-guide/","page":"代码风格指南","title":"代码风格指南","text":"julia> h(x) = 2//1 * x\nh (generic function with 1 method)\n\njulia> h(1//2)\n1//1\n\njulia> h(1/2)\n1.0\n\njulia> h(1)\n2//1","category":"page"},{"location":"manual/style-guide/","page":"代码风格指南","title":"代码风格指南","text":"所以,可能时尽量使用 Int 字面量,对非整数字面量使用 Rational{Int},这样可以让代码变得更容易使用。","category":"page"},{"location":"base/math/#数学相关","page":"数学相关","title":"数学相关","text":"","category":"section"},{"location":"base/math/#math-ops","page":"数学相关","title":"数学运算符","text":"","category":"section"},{"location":"base/math/","page":"数学相关","title":"数学相关","text":"Base.:-(::Any)\nBase.:(+)\nBase.:-(::Any, ::Any)\nBase.:*(::Any, ::Any...)\nBase.:(/)\nBase.:\\(::Any, ::Any)\nBase.:^(::Number, ::Number)\nBase.fma\nBase.muladd\nBase.inv(::Number)\nBase.div\nBase.fld\nBase.cld\nBase.mod\nBase.rem\nBase.rem2pi\nBase.Math.mod2pi\nBase.divrem\nBase.fldmod\nBase.fld1\nBase.mod1\nBase.fldmod1\nBase.:(//)\nBase.rationalize\nBase.numerator\nBase.denominator\nBase.:(<<)\nBase.:(>>)\nBase.:(>>>)\nBase.bitrotate\nBase.:(:)\nBase.range\nBase.OneTo\nBase.StepRangeLen\nBase.:(==)\nBase.:(!=)\nBase.:(!==)\nBase.:(<)\nBase.:(<=)\nBase.:(>)\nBase.:(>=)\nBase.cmp\nBase.:(~)\nBase.:(&)\nBase.:(|)\nBase.xor\nBase.nand\nBase.nor\nBase.:(!)\n&&\n||","category":"page"},{"location":"base/math/#Base.:--Tuple{Any}","page":"数学相关","title":"Base.:-","text":"-(x)\n\nUnary minus operator.\n\nSee also: abs, flipsign.\n\nExamples\n\njulia> -1\n-1\n\njulia> -(2)\n-2\n\njulia> -[1 2; 3 4]\n2×2 Matrix{Int64}:\n -1 -2\n -3 -4\n\n\n\n\n\n","category":"method"},{"location":"base/math/#Base.:+","page":"数学相关","title":"Base.:+","text":"dt::Date + t::Time -> DateTime\n\nThe addition of a Date with a Time produces a DateTime. The hour, minute, second, and millisecond parts of the Time are used along with the year, month, and day of the Date to create the new DateTime. Non-zero microseconds or nanoseconds in the Time type will result in an InexactError being thrown.\n\n\n\n\n\n+(x, y...)\n\nAddition operator. x+y+z+... calls this function with all arguments, i.e. +(x, y, z, ...).\n\nExamples\n\njulia> 1 + 20 + 4\n25\n\njulia> +(1, 20, 4)\n25\n\n\n\n\n\n","category":"function"},{"location":"base/math/#Base.:--Tuple{Any, Any}","page":"数学相关","title":"Base.:-","text":"-(x, y)\n\nSubtraction operator.\n\nExamples\n\njulia> 2 - 3\n-1\n\njulia> -(2, 4.5)\n-2.5\n\n\n\n\n\n","category":"method"},{"location":"base/math/#Base.:*-Tuple{Any, Vararg{Any}}","page":"数学相关","title":"Base.:*","text":"*(x, y...)\n\nMultiplication operator. x*y*z*... calls this function with all arguments, i.e. *(x, y, z, ...).\n\nExamples\n\njulia> 2 * 7 * 8\n112\n\njulia> *(2, 7, 8)\n112\n\n\n\n\n\n","category":"method"},{"location":"base/math/#Base.:/","page":"数学相关","title":"Base.:/","text":"/(x, y)\n\nRight division operator: multiplication of x by the inverse of y on the right. Gives floating-point results for integer arguments.\n\nExamples\n\njulia> 1/2\n0.5\n\njulia> 4/2\n2.0\n\njulia> 4.5/2\n2.25\n\n\n\n\n\nA / B\n\nMatrix right-division: A / B is equivalent to (B' \\ A')' where \\ is the left-division operator. For square matrices, the result X is such that A == X*B.\n\nSee also: rdiv!.\n\nExamples\n\njulia> A = Float64[1 4 5; 3 9 2]; B = Float64[1 4 2; 3 4 2; 8 7 1];\n\njulia> X = A / B\n2×3 Matrix{Float64}:\n -0.65 3.75 -1.2\n 3.25 -2.75 1.0\n\njulia> isapprox(A, X*B)\ntrue\n\njulia> isapprox(X, A*pinv(B))\ntrue\n\n\n\n\n\n","category":"function"},{"location":"base/math/#Base.:\\-Tuple{Any, Any}","page":"数学相关","title":"Base.:\\","text":"\\(x, y)\n\nLeft division operator: multiplication of y by the inverse of x on the left. Gives floating-point results for integer arguments.\n\nExamples\n\njulia> 3 \\ 6\n2.0\n\njulia> inv(3) * 6\n2.0\n\njulia> A = [4 3; 2 1]; x = [5, 6];\n\njulia> A \\ x\n2-element Vector{Float64}:\n 6.5\n -7.0\n\njulia> inv(A) * x\n2-element Vector{Float64}:\n 6.5\n -7.0\n\n\n\n\n\n","category":"method"},{"location":"base/math/#Base.:^-Tuple{Number, Number}","page":"数学相关","title":"Base.:^","text":"^(x, y)\n\nExponentiation operator. If x is a matrix, computes matrix exponentiation.\n\nIf y is an Int literal (e.g. 2 in x^2 or -3 in x^-3), the Julia code x^y is transformed by the compiler to Base.literal_pow(^, x, Val(y)), to enable compile-time specialization on the value of the exponent. (As a default fallback we have Base.literal_pow(^, x, Val(y)) = ^(x,y), where usually ^ == Base.^ unless ^ has been defined in the calling namespace.) If y is a negative integer literal, then Base.literal_pow transforms the operation to inv(x)^-y by default, where -y is positive.\n\nExamples\n\njulia> 3^5\n243\n\njulia> A = [1 2; 3 4]\n2×2 Matrix{Int64}:\n 1 2\n 3 4\n\njulia> A^3\n2×2 Matrix{Int64}:\n 37 54\n 81 118\n\n\n\n\n\n","category":"method"},{"location":"base/math/#Base.fma","page":"数学相关","title":"Base.fma","text":"fma(x, y, z)\n\nComputes x*y+z without rounding the intermediate result x*y. On some systems this is significantly more expensive than x*y+z. fma is used to improve accuracy in certain algorithms. See muladd.\n\n\n\n\n\n","category":"function"},{"location":"base/math/#Base.muladd","page":"数学相关","title":"Base.muladd","text":"muladd(x, y, z)\n\nCombined multiply-add: computes x*y+z, but allowing the add and multiply to be merged with each other or with surrounding operations for performance. For example, this may be implemented as an fma if the hardware supports it efficiently. The result can be different on different machines and can also be different on the same machine due to constant propagation or other optimizations. See fma.\n\nExamples\n\njulia> muladd(3, 2, 1)\n7\n\njulia> 3 * 2 + 1\n7\n\n\n\n\n\nmuladd(A, y, z)\n\nCombined multiply-add, A*y .+ z, for matrix-matrix or matrix-vector multiplication. The result is always the same size as A*y, but z may be smaller, or a scalar.\n\ncompat: Julia 1.6\nThese methods require Julia 1.6 or later.\n\nExamples\n\njulia> A=[1.0 2.0; 3.0 4.0]; B=[1.0 1.0; 1.0 1.0]; z=[0, 100];\n\njulia> muladd(A, B, z)\n2×2 Matrix{Float64}:\n 3.0 3.0\n 107.0 107.0\n\n\n\n\n\n","category":"function"},{"location":"base/math/#Base.inv-Tuple{Number}","page":"数学相关","title":"Base.inv","text":"inv(x)\n\nReturn the multiplicative inverse of x, such that x*inv(x) or inv(x)*x yields one(x) (the multiplicative identity) up to roundoff errors.\n\nIf x is a number, this is essentially the same as one(x)/x, but for some types inv(x) may be slightly more efficient.\n\nExamples\n\njulia> inv(2)\n0.5\n\njulia> inv(1 + 2im)\n0.2 - 0.4im\n\njulia> inv(1 + 2im) * (1 + 2im)\n1.0 + 0.0im\n\njulia> inv(2//3)\n3//2\n\ncompat: Julia 1.2\ninv(::Missing) requires at least Julia 1.2.\n\n\n\n\n\n","category":"method"},{"location":"base/math/#Base.div","page":"数学相关","title":"Base.div","text":"div(x, y)\n÷(x, y)\n\nThe quotient from Euclidean (integer) division. Generally equivalent to a mathematical operation x/y without a fractional part.\n\nSee also: cld, fld, rem, divrem.\n\nExamples\n\njulia> 9 ÷ 4\n2\n\njulia> -5 ÷ 3\n-1\n\njulia> 5.0 ÷ 2\n2.0\n\njulia> div.(-5:5, 3)'\n1×11 adjoint(::Vector{Int64}) with eltype Int64:\n -1 -1 -1 0 0 0 0 0 1 1 1\n\n\n\n\n\n","category":"function"},{"location":"base/math/#Base.fld","page":"数学相关","title":"Base.fld","text":"fld(x, y)\n\nLargest integer less than or equal to x/y. Equivalent to div(x, y, RoundDown).\n\nSee also div, cld, fld1.\n\nExamples\n\njulia> fld(7.3,5.5)\n1.0\n\njulia> fld.(-5:5, 3)'\n1×11 adjoint(::Vector{Int64}) with eltype Int64:\n -2 -2 -1 -1 -1 0 0 0 1 1 1\n\nBecause fld(x, y) implements strictly correct floored rounding based on the true value of floating-point numbers, unintuitive situations can arise. For example:\n\njulia> fld(6.0,0.1)\n59.0\njulia> 6.0/0.1\n60.0\njulia> 6.0/big(0.1)\n59.99999999999999666933092612453056361837965690217069245739573412231113406246995\n\nWhat is happening here is that the true value of the floating-point number written as 0.1 is slightly larger than the numerical value 1/10 while 6.0 represents the number 6 precisely. Therefore the true value of 6.0 / 0.1 is slightly less than 60. When doing division, this is rounded to precisely 60.0, but fld(6.0, 0.1) always takes the floor of the true value, so the result is 59.0.\n\n\n\n\n\n","category":"function"},{"location":"base/math/#Base.cld","page":"数学相关","title":"Base.cld","text":"cld(x, y)\n\nSmallest integer larger than or equal to x/y. Equivalent to div(x, y, RoundUp).\n\nSee also div, fld.\n\nExamples\n\njulia> cld(5.5,2.2)\n3.0\n\njulia> cld.(-5:5, 3)'\n1×11 adjoint(::Vector{Int64}) with eltype Int64:\n -1 -1 -1 0 0 0 1 1 1 2 2\n\n\n\n\n\n","category":"function"},{"location":"base/math/#Base.mod","page":"数学相关","title":"Base.mod","text":"mod(x::Integer, r::AbstractUnitRange)\n\nFind y in the range r such that x y (mod n), where n = length(r), i.e. y = mod(x - first(r), n) + first(r).\n\nSee also mod1.\n\nExamples\n\njulia> mod(0, Base.OneTo(3)) # mod1(0, 3)\n3\n\njulia> mod(3, 0:2) # mod(3, 3)\n0\n\ncompat: Julia 1.3\nThis method requires at least Julia 1.3.\n\n\n\n\n\nmod(x, y)\nrem(x, y, RoundDown)\n\nThe reduction of x modulo y, or equivalently, the remainder of x after floored division by y, i.e. x - y*fld(x,y) if computed without intermediate rounding.\n\nThe result will have the same sign as y, and magnitude less than abs(y) (with some exceptions, see note below).\n\nnote: Note\nWhen used with floating point values, the exact result may not be representable by the type, and so rounding error may occur. In particular, if the exact result is very close to y, then it may be rounded to y.\n\nSee also: rem, div, fld, mod1, invmod.\n\njulia> mod(8, 3)\n2\n\njulia> mod(9, 3)\n0\n\njulia> mod(8.9, 3)\n2.9000000000000004\n\njulia> mod(eps(), 3)\n2.220446049250313e-16\n\njulia> mod(-eps(), 3)\n3.0\n\njulia> mod.(-5:5, 3)'\n1×11 adjoint(::Vector{Int64}) with eltype Int64:\n 1 2 0 1 2 0 1 2 0 1 2\n\n\n\n\n\nrem(x::Integer, T::Type{<:Integer}) -> T\nmod(x::Integer, T::Type{<:Integer}) -> T\n%(x::Integer, T::Type{<:Integer}) -> T\n\nFind y::T such that x ≡ y (mod n), where n is the number of integers representable in T, and y is an integer in [typemin(T),typemax(T)]. If T can represent any integer (e.g. T == BigInt), then this operation corresponds to a conversion to T.\n\nExamples\n\njulia> 129 % Int8\n-127\n\n\n\n\n\n","category":"function"},{"location":"base/math/#Base.rem","page":"数学相关","title":"Base.rem","text":"rem(x, y)\n%(x, y)\n\nRemainder from Euclidean division, returning a value of the same sign as x, and smaller in magnitude than y. This value is always exact.\n\nSee also: div, mod, mod1, divrem.\n\nExamples\n\njulia> x = 15; y = 4;\n\njulia> x % y\n3\n\njulia> x == div(x, y) * y + rem(x, y)\ntrue\n\njulia> rem.(-5:5, 3)'\n1×11 adjoint(::Vector{Int64}) with eltype Int64:\n -2 -1 0 -2 -1 0 1 2 0 1 2\n\n\n\n\n\n","category":"function"},{"location":"base/math/#Base.Math.rem2pi","page":"数学相关","title":"Base.Math.rem2pi","text":"rem2pi(x, r::RoundingMode)\n\nCompute the remainder of x after integer division by 2π, with the quotient rounded according to the rounding mode r. In other words, the quantity\n\nx - 2π*round(x/(2π),r)\n\nwithout any intermediate rounding. This internally uses a high precision approximation of 2π, and so will give a more accurate result than rem(x,2π,r)\n\nif r == RoundNearest, then the result is in the interval -π π. This will generally be the most accurate result. See also RoundNearest.\nif r == RoundToZero, then the result is in the interval 0 2π if x is positive,. or -2π 0 otherwise. See also RoundToZero.\nif r == RoundDown, then the result is in the interval 0 2π. See also RoundDown.\nif r == RoundUp, then the result is in the interval -2π 0. See also RoundUp.\n\nExamples\n\njulia> rem2pi(7pi/4, RoundNearest)\n-0.7853981633974485\n\njulia> rem2pi(7pi/4, RoundDown)\n5.497787143782138\n\n\n\n\n\n","category":"function"},{"location":"base/math/#Base.Math.mod2pi","page":"数学相关","title":"Base.Math.mod2pi","text":"mod2pi(x)\n\nModulus after division by 2π, returning in the range 02π).\n\nThis function computes a floating point representation of the modulus after division by numerically exact 2π, and is therefore not exactly the same as mod(x,2π), which would compute the modulus of x relative to division by the floating-point number 2π.\n\nnote: Note\nDepending on the format of the input value, the closest representable value to 2π may be less than 2π. For example, the expression mod2pi(2π) will not return 0, because the intermediate value of 2*π is a Float64 and 2*Float64(π) < 2*big(π). See rem2pi for more refined control of this behavior.\n\nExamples\n\njulia> mod2pi(9*pi/4)\n0.7853981633974481\n\n\n\n\n\n","category":"function"},{"location":"base/math/#Base.divrem","page":"数学相关","title":"Base.divrem","text":"divrem(x, y, r::RoundingMode=RoundToZero)\n\nThe quotient and remainder from Euclidean division. Equivalent to (div(x,y,r), rem(x,y,r)). Equivalently, with the default value of r, this call is equivalent to (x÷y, x%y).\n\nSee also: fldmod, cld.\n\nExamples\n\njulia> divrem(3,7)\n(0, 3)\n\njulia> divrem(7,3)\n(2, 1)\n\n\n\n\n\n","category":"function"},{"location":"base/math/#Base.fldmod","page":"数学相关","title":"Base.fldmod","text":"fldmod(x, y)\n\nThe floored quotient and modulus after division. A convenience wrapper for divrem(x, y, RoundDown). Equivalent to (fld(x,y), mod(x,y)).\n\nSee also: fld, cld, fldmod1.\n\n\n\n\n\n","category":"function"},{"location":"base/math/#Base.fld1","page":"数学相关","title":"Base.fld1","text":"fld1(x, y)\n\nFlooring division, returning a value consistent with mod1(x,y)\n\nSee also mod1, fldmod1.\n\nExamples\n\njulia> x = 15; y = 4;\n\njulia> fld1(x, y)\n4\n\njulia> x == fld(x, y) * y + mod(x, y)\ntrue\n\njulia> x == (fld1(x, y) - 1) * y + mod1(x, y)\ntrue\n\n\n\n\n\n","category":"function"},{"location":"base/math/#Base.mod1","page":"数学相关","title":"Base.mod1","text":"mod1(x, y)\n\nModulus after flooring division, returning a value r such that mod(r, y) == mod(x, y) in the range (0 y for positive y and in the range y0) for negative y.\n\nWith integer arguments and positive y, this is equal to mod(x, 1:y), and hence natural for 1-based indexing. By comparison, mod(x, y) == mod(x, 0:y-1) is natural for computations with offsets or strides.\n\nSee also mod, fld1, fldmod1.\n\nExamples\n\njulia> mod1(4, 2)\n2\n\njulia> mod1.(-5:5, 3)'\n1×11 adjoint(::Vector{Int64}) with eltype Int64:\n 1 2 3 1 2 3 1 2 3 1 2\n\njulia> mod1.([-0.1, 0, 0.1, 1, 2, 2.9, 3, 3.1]', 3)\n1×8 Matrix{Float64}:\n 2.9 3.0 0.1 1.0 2.0 2.9 3.0 0.1\n\n\n\n\n\n","category":"function"},{"location":"base/math/#Base.fldmod1","page":"数学相关","title":"Base.fldmod1","text":"fldmod1(x, y)\n\nReturn (fld1(x,y), mod1(x,y)).\n\nSee also fld1, mod1.\n\n\n\n\n\n","category":"function"},{"location":"base/math/#Base.://","page":"数学相关","title":"Base.://","text":"//(num, den)\n\nDivide two integers or rational numbers, giving a Rational result.\n\nExamples\n\njulia> 3 // 5\n3//5\n\njulia> (3 // 5) // (2 // 1)\n3//10\n\n\n\n\n\n","category":"function"},{"location":"base/math/#Base.rationalize","page":"数学相关","title":"Base.rationalize","text":"rationalize([T<:Integer=Int,] x; tol::Real=eps(x))\n\nApproximate floating point number x as a Rational number with components of the given integer type. The result will differ from x by no more than tol.\n\nExamples\n\njulia> rationalize(5.6)\n28//5\n\njulia> a = rationalize(BigInt, 10.3)\n103//10\n\njulia> typeof(numerator(a))\nBigInt\n\n\n\n\n\n","category":"function"},{"location":"base/math/#Base.numerator","page":"数学相关","title":"Base.numerator","text":"numerator(x)\n\nNumerator of the rational representation of x.\n\nExamples\n\njulia> numerator(2//3)\n2\n\njulia> numerator(4)\n4\n\n\n\n\n\n","category":"function"},{"location":"base/math/#Base.denominator","page":"数学相关","title":"Base.denominator","text":"denominator(x)\n\nDenominator of the rational representation of x.\n\nExamples\n\njulia> denominator(2//3)\n3\n\njulia> denominator(4)\n1\n\n\n\n\n\n","category":"function"},{"location":"base/math/#Base.:<<","page":"数学相关","title":"Base.:<<","text":"<<(x, n)\n\nLeft bit shift operator, x << n. For n >= 0, the result is x shifted left by n bits, filling with 0s. This is equivalent to x * 2^n. For n < 0, this is equivalent to x >> -n.\n\nExamples\n\njulia> Int8(3) << 2\n12\n\njulia> bitstring(Int8(3))\n\"00000011\"\n\njulia> bitstring(Int8(12))\n\"00001100\"\n\nSee also >>, >>>, exp2, ldexp.\n\n\n\n\n\n<<(B::BitVector, n) -> BitVector\n\nLeft bit shift operator, B << n. For n >= 0, the result is B with elements shifted n positions backwards, filling with false values. If n < 0, elements are shifted forwards. Equivalent to B >> -n.\n\nExamples\n\njulia> B = BitVector([true, false, true, false, false])\n5-element BitVector:\n 1\n 0\n 1\n 0\n 0\n\njulia> B << 1\n5-element BitVector:\n 0\n 1\n 0\n 0\n 0\n\njulia> B << -1\n5-element BitVector:\n 0\n 1\n 0\n 1\n 0\n\n\n\n\n\n","category":"function"},{"location":"base/math/#Base.:>>","page":"数学相关","title":"Base.:>>","text":">>(x, n)\n\nRight bit shift operator, x >> n. For n >= 0, the result is x shifted right by n bits, where n >= 0, filling with 0s if x >= 0, 1s if x < 0, preserving the sign of x. This is equivalent to fld(x, 2^n). For n < 0, this is equivalent to x << -n.\n\nExamples\n\njulia> Int8(13) >> 2\n3\n\njulia> bitstring(Int8(13))\n\"00001101\"\n\njulia> bitstring(Int8(3))\n\"00000011\"\n\njulia> Int8(-14) >> 2\n-4\n\njulia> bitstring(Int8(-14))\n\"11110010\"\n\njulia> bitstring(Int8(-4))\n\"11111100\"\n\nSee also >>>, <<.\n\n\n\n\n\n>>(B::BitVector, n) -> BitVector\n\nRight bit shift operator, B >> n. For n >= 0, the result is B with elements shifted n positions forward, filling with false values. If n < 0, elements are shifted backwards. Equivalent to B << -n.\n\nExamples\n\njulia> B = BitVector([true, false, true, false, false])\n5-element BitVector:\n 1\n 0\n 1\n 0\n 0\n\njulia> B >> 1\n5-element BitVector:\n 0\n 1\n 0\n 1\n 0\n\njulia> B >> -1\n5-element BitVector:\n 0\n 1\n 0\n 0\n 0\n\n\n\n\n\n","category":"function"},{"location":"base/math/#Base.:>>>","page":"数学相关","title":"Base.:>>>","text":">>>(x, n)\n\nUnsigned right bit shift operator, x >>> n. For n >= 0, the result is x shifted right by n bits, where n >= 0, filling with 0s. For n < 0, this is equivalent to x << -n.\n\nFor Unsigned integer types, this is equivalent to >>. For Signed integer types, this is equivalent to signed(unsigned(x) >> n).\n\nExamples\n\njulia> Int8(-14) >>> 2\n60\n\njulia> bitstring(Int8(-14))\n\"11110010\"\n\njulia> bitstring(Int8(60))\n\"00111100\"\n\nBigInts are treated as if having infinite size, so no filling is required and this is equivalent to >>.\n\nSee also >>, <<.\n\n\n\n\n\n>>>(B::BitVector, n) -> BitVector\n\nUnsigned right bitshift operator, B >>> n. Equivalent to B >> n. See >> for details and examples.\n\n\n\n\n\n","category":"function"},{"location":"base/math/#Base.bitrotate","page":"数学相关","title":"Base.bitrotate","text":"bitrotate(x::Base.BitInteger, k::Integer)\n\nbitrotate(x, k) implements bitwise rotation. It returns the value of x with its bits rotated left k times. A negative value of k will rotate to the right instead.\n\ncompat: Julia 1.5\nThis function requires Julia 1.5 or later.\n\nSee also: <<, circshift, BitArray.\n\njulia> bitrotate(UInt8(114), 2)\n0xc9\n\njulia> bitstring(bitrotate(0b01110010, 2))\n\"11001001\"\n\njulia> bitstring(bitrotate(0b01110010, -2))\n\"10011100\"\n\njulia> bitstring(bitrotate(0b01110010, 8))\n\"01110010\"\n\n\n\n\n\n","category":"function"},{"location":"base/math/#Base.::","page":"数学相关","title":"Base.::","text":"(:)(start, [step], stop)\n\nRange operator. a:b constructs a range from a to b with a step size of 1 (a UnitRange) , and a:s:b is similar but uses a step size of s (a StepRange).\n\n: is also used in indexing to select whole dimensions and for Symbol literals, as in e.g. :hello.\n\n\n\n\n\n(:)(start::CartesianIndex, [step::CartesianIndex], stop::CartesianIndex)\n\nConstruct CartesianIndices from two CartesianIndex and an optional step.\n\ncompat: Julia 1.1\nThis method requires at least Julia 1.1.\n\ncompat: Julia 1.6\nThe step range method start:step:stop requires at least Julia 1.6.\n\nExamples\n\njulia> I = CartesianIndex(2,1);\n\njulia> J = CartesianIndex(3,3);\n\njulia> I:J\nCartesianIndices((2:3, 1:3))\n\njulia> I:CartesianIndex(1, 2):J\nCartesianIndices((2:1:3, 1:2:3))\n\n\n\n\n\n","category":"function"},{"location":"base/math/#Base.range","page":"数学相关","title":"Base.range","text":"range(start, stop, length)\nrange(start, stop; length, step)\nrange(start; length, stop, step)\nrange(;start, length, stop, step)\n\nConstruct a specialized array with evenly spaced elements and optimized storage (an AbstractRange) from the arguments. Mathematically a range is uniquely determined by any three of start, step, stop and length. Valid invocations of range are:\n\nCall range with any three of start, step, stop, length.\nCall range with two of start, stop, length. In this case step will be assumed to be one. If both arguments are Integers, a UnitRange will be returned.\nCall range with one of stop or length. start and step will be assumed to be one.\n\nSee Extended Help for additional details on the returned type.\n\nExamples\n\njulia> range(1, length=100)\n1:100\n\njulia> range(1, stop=100)\n1:100\n\njulia> range(1, step=5, length=100)\n1:5:496\n\njulia> range(1, step=5, stop=100)\n1:5:96\n\njulia> range(1, 10, length=101)\n1.0:0.09:10.0\n\njulia> range(1, 100, step=5)\n1:5:96\n\njulia> range(stop=10, length=5)\n6:10\n\njulia> range(stop=10, step=1, length=5)\n6:1:10\n\njulia> range(start=1, step=1, stop=10)\n1:1:10\n\njulia> range(; length = 10)\nBase.OneTo(10)\n\njulia> range(; stop = 6)\nBase.OneTo(6)\n\njulia> range(; stop = 6.5)\n1.0:1.0:6.0\n\nIf length is not specified and stop - start is not an integer multiple of step, a range that ends before stop will be produced.\n\njulia> range(1, 3.5, step=2)\n1.0:2.0:3.0\n\nSpecial care is taken to ensure intermediate values are computed rationally. To avoid this induced overhead, see the LinRange constructor.\n\ncompat: Julia 1.1\nstop as a positional argument requires at least Julia 1.1.\n\ncompat: Julia 1.7\nThe versions without keyword arguments and start as a keyword argument require at least Julia 1.7.\n\ncompat: Julia 1.8\nThe versions with stop as a sole keyword argument, or length as a sole keyword argument require at least Julia 1.8.\n\nExtended Help\n\nrange will produce a Base.OneTo when the arguments are Integers and\n\nOnly length is provided\nOnly stop is provided\n\nrange will produce a UnitRange when the arguments are Integers and\n\nOnly start and stop are provided\nOnly length and stop are provided\n\nA UnitRange is not produced if step is provided even if specified as one.\n\n\n\n\n\n","category":"function"},{"location":"base/math/#Base.OneTo","page":"数学相关","title":"Base.OneTo","text":"Base.OneTo(n)\n\nDefine an AbstractUnitRange that behaves like 1:n, with the added distinction that the lower limit is guaranteed (by the type system) to be 1.\n\n\n\n\n\n","category":"type"},{"location":"base/math/#Base.StepRangeLen","page":"数学相关","title":"Base.StepRangeLen","text":"StepRangeLen( ref::R, step::S, len, [offset=1]) where { R,S}\nStepRangeLen{T,R,S}( ref::R, step::S, len, [offset=1]) where {T,R,S}\nStepRangeLen{T,R,S,L}(ref::R, step::S, len, [offset=1]) where {T,R,S,L}\n\nA range r where r[i] produces values of type T (in the first form, T is deduced automatically), parameterized by a reference value, a step, and the length. By default ref is the starting value r[1], but alternatively you can supply it as the value of r[offset] for some other index 1 <= offset <= len. In conjunction with TwicePrecision this can be used to implement ranges that are free of roundoff error.\n\n\n\n\n\n","category":"type"},{"location":"base/math/#Base.:==","page":"数学相关","title":"Base.:==","text":"==(x, y)\n\nGeneric equality operator. Falls back to ===. Should be implemented for all types with a notion of equality, based on the abstract value that an instance represents. For example, all numeric types are compared by numeric value, ignoring type. Strings are compared as sequences of characters, ignoring encoding. For collections, == is generally called recursively on all contents, though other properties (like the shape for arrays) may also be taken into account.\n\nThis operator follows IEEE semantics for floating-point numbers: 0.0 == -0.0 and NaN != NaN.\n\nThe result is of type Bool, except when one of the operands is missing, in which case missing is returned (three-valued logic). For collections, missing is returned if at least one of the operands contains a missing value and all non-missing values are equal. Use isequal or === to always get a Bool result.\n\nImplementation\n\nNew numeric types should implement this function for two arguments of the new type, and handle comparison to other types via promotion rules where possible.\n\nisequal falls back to ==, so new methods of == will be used by the Dict type to compare keys. If your type will be used as a dictionary key, it should therefore also implement hash.\n\nIf some type defines ==, isequal, and isless then it should also implement < to ensure consistency of comparisons.\n\n\n\n\n\n","category":"function"},{"location":"base/math/#Base.:!=","page":"数学相关","title":"Base.:!=","text":"!=(x, y)\n≠(x,y)\n\nNot-equals comparison operator. Always gives the opposite answer as ==.\n\nImplementation\n\nNew types should generally not implement this, and rely on the fallback definition !=(x,y) = !(x==y) instead.\n\nExamples\n\njulia> 3 != 2\ntrue\n\njulia> \"foo\" ≠ \"foo\"\nfalse\n\n\n\n\n\n!=(x)\n\nCreate a function that compares its argument to x using !=, i.e. a function equivalent to y -> y != x. The returned function is of type Base.Fix2{typeof(!=)}, which can be used to implement specialized methods.\n\ncompat: Julia 1.2\nThis functionality requires at least Julia 1.2.\n\n\n\n\n\n","category":"function"},{"location":"base/math/#Base.:!==","page":"数学相关","title":"Base.:!==","text":"!==(x, y)\n≢(x,y)\n\nAlways gives the opposite answer as ===.\n\nExamples\n\njulia> a = [1, 2]; b = [1, 2];\n\njulia> a ≢ b\ntrue\n\njulia> a ≢ a\nfalse\n\n\n\n\n\n","category":"function"},{"location":"base/math/#Base.:<","page":"数学相关","title":"Base.:<","text":"<(x, y)\n\nLess-than comparison operator. Falls back to isless. Because of the behavior of floating-point NaN values, this operator implements a partial order.\n\nImplementation\n\nNew numeric types with a canonical partial order should implement this function for two arguments of the new type. Types with a canonical total order should implement isless instead.\n\nExamples\n\njulia> 'a' < 'b'\ntrue\n\njulia> \"abc\" < \"abd\"\ntrue\n\njulia> 5 < 3\nfalse\n\n\n\n\n\n<(x)\n\nCreate a function that compares its argument to x using <, i.e. a function equivalent to y -> y < x. The returned function is of type Base.Fix2{typeof(<)}, which can be used to implement specialized methods.\n\ncompat: Julia 1.2\nThis functionality requires at least Julia 1.2.\n\n\n\n\n\n","category":"function"},{"location":"base/math/#Base.:<=","page":"数学相关","title":"Base.:<=","text":"<=(x, y)\n≤(x,y)\n\nLess-than-or-equals comparison operator. Falls back to (x < y) | (x == y).\n\nExamples\n\njulia> 'a' <= 'b'\ntrue\n\njulia> 7 ≤ 7 ≤ 9\ntrue\n\njulia> \"abc\" ≤ \"abc\"\ntrue\n\njulia> 5 <= 3\nfalse\n\n\n\n\n\n<=(x)\n\nCreate a function that compares its argument to x using <=, i.e. a function equivalent to y -> y <= x. The returned function is of type Base.Fix2{typeof(<=)}, which can be used to implement specialized methods.\n\ncompat: Julia 1.2\nThis functionality requires at least Julia 1.2.\n\n\n\n\n\n","category":"function"},{"location":"base/math/#Base.:>","page":"数学相关","title":"Base.:>","text":">(x, y)\n\nGreater-than comparison operator. Falls back to y < x.\n\nImplementation\n\nGenerally, new types should implement < instead of this function, and rely on the fallback definition >(x, y) = y < x.\n\nExamples\n\njulia> 'a' > 'b'\nfalse\n\njulia> 7 > 3 > 1\ntrue\n\njulia> \"abc\" > \"abd\"\nfalse\n\njulia> 5 > 3\ntrue\n\n\n\n\n\n>(x)\n\nCreate a function that compares its argument to x using >, i.e. a function equivalent to y -> y > x. The returned function is of type Base.Fix2{typeof(>)}, which can be used to implement specialized methods.\n\ncompat: Julia 1.2\nThis functionality requires at least Julia 1.2.\n\n\n\n\n\n","category":"function"},{"location":"base/math/#Base.:>=","page":"数学相关","title":"Base.:>=","text":">=(x, y)\n≥(x,y)\n\nGreater-than-or-equals comparison operator. Falls back to y <= x.\n\nExamples\n\njulia> 'a' >= 'b'\nfalse\n\njulia> 7 ≥ 7 ≥ 3\ntrue\n\njulia> \"abc\" ≥ \"abc\"\ntrue\n\njulia> 5 >= 3\ntrue\n\n\n\n\n\n>=(x)\n\nCreate a function that compares its argument to x using >=, i.e. a function equivalent to y -> y >= x. The returned function is of type Base.Fix2{typeof(>=)}, which can be used to implement specialized methods.\n\ncompat: Julia 1.2\nThis functionality requires at least Julia 1.2.\n\n\n\n\n\n","category":"function"},{"location":"base/math/#Base.cmp","page":"数学相关","title":"Base.cmp","text":"cmp(x,y)\n\nReturn -1, 0, or 1 depending on whether x is less than, equal to, or greater than y, respectively. Uses the total order implemented by isless.\n\nExamples\n\njulia> cmp(1, 2)\n-1\n\njulia> cmp(2, 1)\n1\n\njulia> cmp(2+im, 3-im)\nERROR: MethodError: no method matching isless(::Complex{Int64}, ::Complex{Int64})\n[...]\n\n\n\n\n\ncmp(<, x, y)\n\nReturn -1, 0, or 1 depending on whether x is less than, equal to, or greater than y, respectively. The first argument specifies a less-than comparison function to use.\n\n\n\n\n\ncmp(a::AbstractString, b::AbstractString) -> Int\n\nCompare two strings. Return 0 if both strings have the same length and the character at each index is the same in both strings. Return -1 if a is a prefix of b, or if a comes before b in alphabetical order. Return 1 if b is a prefix of a, or if b comes before a in alphabetical order (technically, lexicographical order by Unicode code points).\n\nExamples\n\njulia> cmp(\"abc\", \"abc\")\n0\n\njulia> cmp(\"ab\", \"abc\")\n-1\n\njulia> cmp(\"abc\", \"ab\")\n1\n\njulia> cmp(\"ab\", \"ac\")\n-1\n\njulia> cmp(\"ac\", \"ab\")\n1\n\njulia> cmp(\"α\", \"a\")\n1\n\njulia> cmp(\"b\", \"β\")\n-1\n\n\n\n\n\n","category":"function"},{"location":"base/math/#Base.:~","page":"数学相关","title":"Base.:~","text":"~(x)\n\nBitwise not.\n\nSee also: !, &, |.\n\nExamples\n\njulia> ~4\n-5\n\njulia> ~10\n-11\n\njulia> ~true\nfalse\n\n\n\n\n\n","category":"function"},{"location":"base/math/#Base.:&","page":"数学相关","title":"Base.:&","text":"x & y\n\nBitwise and. Implements three-valued logic, returning missing if one operand is missing and the other is true. Add parentheses for function application form: (&)(x, y).\n\nSee also: |, xor, &&.\n\nExamples\n\njulia> 4 & 10\n0\n\njulia> 4 & 12\n4\n\njulia> true & missing\nmissing\n\njulia> false & missing\nfalse\n\n\n\n\n\n","category":"function"},{"location":"base/math/#Base.:|","page":"数学相关","title":"Base.:|","text":"x | y\n\nBitwise or. Implements three-valued logic, returning missing if one operand is missing and the other is false.\n\nSee also: &, xor, ||.\n\nExamples\n\njulia> 4 | 10\n14\n\njulia> 4 | 1\n5\n\njulia> true | missing\ntrue\n\njulia> false | missing\nmissing\n\n\n\n\n\n","category":"function"},{"location":"base/math/#Base.xor","page":"数学相关","title":"Base.xor","text":"xor(x, y)\n⊻(x, y)\n\nBitwise exclusive or of x and y. Implements three-valued logic, returning missing if one of the arguments is missing.\n\nThe infix operation a ⊻ b is a synonym for xor(a,b), and ⊻ can be typed by tab-completing \\xor or \\veebar in the Julia REPL.\n\nExamples\n\njulia> xor(true, false)\ntrue\n\njulia> xor(true, true)\nfalse\n\njulia> xor(true, missing)\nmissing\n\njulia> false ⊻ false\nfalse\n\njulia> [true; true; false] .⊻ [true; false; false]\n3-element BitVector:\n 0\n 1\n 0\n\n\n\n\n\n","category":"function"},{"location":"base/math/#Base.nand","page":"数学相关","title":"Base.nand","text":"nand(x, y)\n⊼(x, y)\n\nBitwise nand (not and) of x and y. Implements three-valued logic, returning missing if one of the arguments is missing.\n\nThe infix operation a ⊼ b is a synonym for nand(a,b), and ⊼ can be typed by tab-completing \\nand or \\barwedge in the Julia REPL.\n\nExamples\n\njulia> nand(true, false)\ntrue\n\njulia> nand(true, true)\nfalse\n\njulia> nand(true, missing)\nmissing\n\njulia> false ⊼ false\ntrue\n\njulia> [true; true; false] .⊼ [true; false; false]\n3-element BitVector:\n 0\n 1\n 1\n\n\n\n\n\n","category":"function"},{"location":"base/math/#Base.nor","page":"数学相关","title":"Base.nor","text":"nor(x, y)\n⊽(x, y)\n\nBitwise nor (not or) of x and y. Implements three-valued logic, returning missing if one of the arguments is missing.\n\nThe infix operation a ⊽ b is a synonym for nor(a,b), and ⊽ can be typed by tab-completing \\nor or \\barvee in the Julia REPL.\n\nExamples\n\njulia> nor(true, false)\nfalse\n\njulia> nor(true, true)\nfalse\n\njulia> nor(true, missing)\nfalse\n\njulia> false ⊽ false\ntrue\n\njulia> [true; true; false] .⊽ [true; false; false]\n3-element BitVector:\n 0\n 0\n 1\n\n\n\n\n\n","category":"function"},{"location":"base/math/#Base.:!","page":"数学相关","title":"Base.:!","text":"!(x)\n\nBoolean not. Implements three-valued logic, returning missing if x is missing.\n\nSee also ~ for bitwise not.\n\nExamples\n\njulia> !true\nfalse\n\njulia> !false\ntrue\n\njulia> !missing\nmissing\n\njulia> .![true false true]\n1×3 BitMatrix:\n 0 1 0\n\n\n\n\n\n!f::Function\n\nPredicate function negation: when the argument of ! is a function, it returns a function which computes the boolean negation of f.\n\nSee also ∘.\n\nExamples\n\njulia> str = \"∀ ε > 0, ∃ δ > 0: |x-y| < δ ⇒ |f(x)-f(y)| < ε\"\n\"∀ ε > 0, ∃ δ > 0: |x-y| < δ ⇒ |f(x)-f(y)| < ε\"\n\njulia> filter(isletter, str)\n\"εδxyδfxfyε\"\n\njulia> filter(!isletter, str)\n\"∀ > 0, ∃ > 0: |-| < ⇒ |()-()| < \"\n\n\n\n\n\n","category":"function"},{"location":"base/math/#&&","page":"数学相关","title":"&&","text":"x && y\n\nShort-circuiting boolean AND.\n\nSee also &, the ternary operator ? :, and the manual section on control flow.\n\nExamples\n\njulia> x = 3;\n\njulia> x > 1 && x < 10 && x isa Int\ntrue\n\njulia> x < 0 && error(\"expected positive x\")\nfalse\n\n\n\n\n\n","category":"keyword"},{"location":"base/math/#||","page":"数学相关","title":"||","text":"x || y\n\nShort-circuiting boolean OR.\n\nSee also: |, xor, &&.\n\nExamples\n\njulia> pi < 3 || ℯ < 3\ntrue\n\njulia> false || true || println(\"neither is true!\")\ntrue\n\n\n\n\n\n","category":"keyword"},{"location":"base/math/#数学函数","page":"数学相关","title":"数学函数","text":"","category":"section"},{"location":"base/math/","page":"数学相关","title":"数学相关","text":"Base.isapprox\nBase.sin(::Number)\nBase.cos(::Number)\nBase.sincos(::Float64)\nBase.tan(::Number)\nBase.Math.sind\nBase.Math.cosd\nBase.Math.tand\nBase.Math.sincosd\nBase.Math.sinpi\nBase.Math.cospi\nBase.Math.sincospi\nBase.sinh(::Number)\nBase.cosh(::Number)\nBase.tanh(::Number)\nBase.asin(::Number)\nBase.acos(::Number)\nBase.atan(::Number)\nBase.Math.asind\nBase.Math.acosd\nBase.Math.atand\nBase.Math.sec(::Number)\nBase.Math.csc(::Number)\nBase.Math.cot(::Number)\nBase.Math.secd\nBase.Math.cscd\nBase.Math.cotd\nBase.Math.asec(::Number)\nBase.Math.acsc(::Number)\nBase.Math.acot(::Number)\nBase.Math.asecd\nBase.Math.acscd\nBase.Math.acotd\nBase.Math.sech(::Number)\nBase.Math.csch(::Number)\nBase.Math.coth(::Number)\nBase.asinh(::Number)\nBase.acosh(::Number)\nBase.atanh(::Number)\nBase.Math.asech(::Number)\nBase.Math.acsch(::Number)\nBase.Math.acoth(::Number)\nBase.Math.sinc\nBase.Math.cosc\nBase.Math.deg2rad\nBase.Math.rad2deg\nBase.Math.hypot\nBase.log(::Number)\nBase.log(::Number, ::Number)\nBase.log2\nBase.log10\nBase.log1p\nBase.Math.frexp\nBase.exp(::Float64)\nBase.exp2\nBase.exp10\nBase.Math.ldexp\nBase.Math.modf\nBase.expm1\nBase.round(::Type, ::Any)\nBase.Rounding.RoundingMode\nBase.Rounding.RoundNearest\nBase.Rounding.RoundNearestTiesAway\nBase.Rounding.RoundNearestTiesUp\nBase.Rounding.RoundToZero\nBase.Rounding.RoundFromZero\nBase.Rounding.RoundUp\nBase.Rounding.RoundDown\nBase.round(::Complex{<: AbstractFloat}, ::RoundingMode, ::RoundingMode)\nBase.ceil\nBase.floor\nBase.trunc\nBase.unsafe_trunc\nBase.min\nBase.max\nBase.minmax\nBase.Math.clamp\nBase.Math.clamp!\nBase.abs\nBase.Checked.checked_abs\nBase.Checked.checked_neg\nBase.Checked.checked_add\nBase.Checked.checked_sub\nBase.Checked.checked_mul\nBase.Checked.checked_div\nBase.Checked.checked_rem\nBase.Checked.checked_fld\nBase.Checked.checked_mod\nBase.Checked.checked_cld\nBase.Checked.add_with_overflow\nBase.Checked.sub_with_overflow\nBase.Checked.mul_with_overflow\nBase.abs2\nBase.copysign\nBase.sign\nBase.signbit\nBase.flipsign\nBase.sqrt(::Real)\nBase.isqrt\nBase.Math.cbrt\nBase.real(::Complex)\nBase.imag\nBase.reim\nBase.conj\nBase.angle\nBase.cis\nBase.cispi\nBase.binomial\nBase.factorial\nBase.gcd\nBase.lcm\nBase.gcdx\nBase.ispow2\nBase.nextpow\nBase.prevpow\nBase.nextprod\nBase.invmod\nBase.powermod\nBase.ndigits\nBase.add_sum\nBase.widemul\nBase.Math.evalpoly\nBase.Math.@evalpoly\nBase.FastMath.@fastmath","category":"page"},{"location":"base/math/#Base.isapprox","page":"数学相关","title":"Base.isapprox","text":"isapprox(x, y; atol::Real=0, rtol::Real=atol>0 ? 0 : √eps, nans::Bool=false[, norm::Function])\n\nInexact equality comparison. Two numbers compare equal if their relative distance or their absolute distance is within tolerance bounds: isapprox returns true if norm(x-y) <= max(atol, rtol*max(norm(x), norm(y))). The default atol is zero and the default rtol depends on the types of x and y. The keyword argument nans determines whether or not NaN values are considered equal (defaults to false).\n\nFor real or complex floating-point values, if an atol > 0 is not specified, rtol defaults to the square root of eps of the type of x or y, whichever is bigger (least precise). This corresponds to requiring equality of about half of the significant digits. Otherwise, e.g. for integer arguments or if an atol > 0 is supplied, rtol defaults to zero.\n\nThe norm keyword defaults to abs for numeric (x,y) and to LinearAlgebra.norm for arrays (where an alternative norm choice is sometimes useful). When x and y are arrays, if norm(x-y) is not finite (i.e. ±Inf or NaN), the comparison falls back to checking whether all elements of x and y are approximately equal component-wise.\n\nThe binary operator ≈ is equivalent to isapprox with the default arguments, and x ≉ y is equivalent to !isapprox(x,y).\n\nNote that x ≈ 0 (i.e., comparing to zero with the default tolerances) is equivalent to x == 0 since the default atol is 0. In such cases, you should either supply an appropriate atol (or use norm(x) ≤ atol) or rearrange your code (e.g. use x ≈ y rather than x - y ≈ 0). It is not possible to pick a nonzero atol automatically because it depends on the overall scaling (the \"units\") of your problem: for example, in x - y ≈ 0, atol=1e-9 is an absurdly small tolerance if x is the radius of the Earth in meters, but an absurdly large tolerance if x is the radius of a Hydrogen atom in meters.\n\ncompat: Julia 1.6\nPassing the norm keyword argument when comparing numeric (non-array) arguments requires Julia 1.6 or later.\n\nExamples\n\njulia> isapprox(0.1, 0.15; atol=0.05)\ntrue\n\njulia> isapprox(0.1, 0.15; rtol=0.34)\ntrue\n\njulia> isapprox(0.1, 0.15; rtol=0.33)\nfalse\n\njulia> 0.1 + 1e-10 ≈ 0.1\ntrue\n\njulia> 1e-10 ≈ 0\nfalse\n\njulia> isapprox(1e-10, 0, atol=1e-8)\ntrue\n\njulia> isapprox([10.0^9, 1.0], [10.0^9, 2.0]) # using `norm`\ntrue\n\n\n\n\n\nisapprox(x; kwargs...) / ≈(x; kwargs...)\n\nCreate a function that compares its argument to x using ≈, i.e. a function equivalent to y -> y ≈ x.\n\nThe keyword arguments supported here are the same as those in the 2-argument isapprox.\n\ncompat: Julia 1.5\nThis method requires Julia 1.5 or later.\n\n\n\n\n\n","category":"function"},{"location":"base/math/#Base.sin-Tuple{Number}","page":"数学相关","title":"Base.sin","text":"sin(x)\n\nCompute sine of x, where x is in radians.\n\nSee also [sind], [sinpi], [sincos], [cis].\n\n\n\n\n\n","category":"method"},{"location":"base/math/#Base.cos-Tuple{Number}","page":"数学相关","title":"Base.cos","text":"cos(x)\n\nCompute cosine of x, where x is in radians.\n\nSee also [cosd], [cospi], [sincos], [cis].\n\n\n\n\n\n","category":"method"},{"location":"base/math/#Base.Math.sincos-Tuple{Float64}","page":"数学相关","title":"Base.Math.sincos","text":"sincos(x)\n\nSimultaneously compute the sine and cosine of x, where x is in radians, returning a tuple (sine, cosine).\n\nSee also cis, sincospi, sincosd.\n\n\n\n\n\n","category":"method"},{"location":"base/math/#Base.tan-Tuple{Number}","page":"数学相关","title":"Base.tan","text":"tan(x)\n\nCompute tangent of x, where x is in radians.\n\n\n\n\n\n","category":"method"},{"location":"base/math/#Base.Math.sind","page":"数学相关","title":"Base.Math.sind","text":"sind(x)\n\nCompute sine of x, where x is in degrees. If x is a matrix, x needs to be a square matrix.\n\ncompat: Julia 1.7\nMatrix arguments require Julia 1.7 or later.\n\n\n\n\n\n","category":"function"},{"location":"base/math/#Base.Math.cosd","page":"数学相关","title":"Base.Math.cosd","text":"cosd(x)\n\nCompute cosine of x, where x is in degrees. If x is a matrix, x needs to be a square matrix.\n\ncompat: Julia 1.7\nMatrix arguments require Julia 1.7 or later.\n\n\n\n\n\n","category":"function"},{"location":"base/math/#Base.Math.tand","page":"数学相关","title":"Base.Math.tand","text":"tand(x)\n\nCompute tangent of x, where x is in degrees. If x is a matrix, x needs to be a square matrix.\n\ncompat: Julia 1.7\nMatrix arguments require Julia 1.7 or later.\n\n\n\n\n\n","category":"function"},{"location":"base/math/#Base.Math.sincosd","page":"数学相关","title":"Base.Math.sincosd","text":"sincosd(x)\n\nSimultaneously compute the sine and cosine of x, where x is in degrees.\n\ncompat: Julia 1.3\nThis function requires at least Julia 1.3.\n\n\n\n\n\n","category":"function"},{"location":"base/math/#Base.Math.sinpi","page":"数学相关","title":"Base.Math.sinpi","text":"sinpi(x)\n\nCompute sin(pi x) more accurately than sin(pi*x), especially for large x.\n\nSee also sind, cospi, sincospi.\n\n\n\n\n\n","category":"function"},{"location":"base/math/#Base.Math.cospi","page":"数学相关","title":"Base.Math.cospi","text":"cospi(x)\n\nCompute cos(pi x) more accurately than cos(pi*x), especially for large x.\n\n\n\n\n\n","category":"function"},{"location":"base/math/#Base.Math.sincospi","page":"数学相关","title":"Base.Math.sincospi","text":"sincospi(x)\n\nSimultaneously compute sinpi(x) and cospi(x) (the sine and cosine of π*x, where x is in radians), returning a tuple (sine, cosine).\n\ncompat: Julia 1.6\nThis function requires Julia 1.6 or later.\n\nSee also: cispi, sincosd, sinpi.\n\n\n\n\n\n","category":"function"},{"location":"base/math/#Base.sinh-Tuple{Number}","page":"数学相关","title":"Base.sinh","text":"sinh(x)\n\nCompute hyperbolic sine of x.\n\n\n\n\n\n","category":"method"},{"location":"base/math/#Base.cosh-Tuple{Number}","page":"数学相关","title":"Base.cosh","text":"cosh(x)\n\nCompute hyperbolic cosine of x.\n\n\n\n\n\n","category":"method"},{"location":"base/math/#Base.tanh-Tuple{Number}","page":"数学相关","title":"Base.tanh","text":"tanh(x)\n\nCompute hyperbolic tangent of x.\n\n\n\n\n\n","category":"method"},{"location":"base/math/#Base.asin-Tuple{Number}","page":"数学相关","title":"Base.asin","text":"asin(x)\n\nCompute the inverse sine of x, where the output is in radians.\n\n\n\n\n\n","category":"method"},{"location":"base/math/#Base.acos-Tuple{Number}","page":"数学相关","title":"Base.acos","text":"acos(x)\n\nCompute the inverse cosine of x, where the output is in radians\n\n\n\n\n\n","category":"method"},{"location":"base/math/#Base.atan-Tuple{Number}","page":"数学相关","title":"Base.atan","text":"atan(y)\natan(y, x)\n\nCompute the inverse tangent of y or y/x, respectively.\n\nFor one argument, this is the angle in radians between the positive x-axis and the point (1, y), returning a value in the interval -pi2 pi2.\n\nFor two arguments, this is the angle in radians between the positive x-axis and the point (x, y), returning a value in the interval -pi pi. This corresponds to a standard atan2 function. Note that by convention atan(0.0,x) is defined as pi and atan(-0.0,x) is defined as -pi when x < 0.\n\n\n\n\n\n","category":"method"},{"location":"base/math/#Base.Math.asind","page":"数学相关","title":"Base.Math.asind","text":"asind(x)\n\nCompute the inverse sine of x, where the output is in degrees. If x is a matrix, x needs to be a square matrix.\n\ncompat: Julia 1.7\nMatrix arguments require Julia 1.7 or later.\n\n\n\n\n\n","category":"function"},{"location":"base/math/#Base.Math.acosd","page":"数学相关","title":"Base.Math.acosd","text":"acosd(x)\n\nCompute the inverse cosine of x, where the output is in degrees. If x is a matrix, x needs to be a square matrix.\n\ncompat: Julia 1.7\nMatrix arguments require Julia 1.7 or later.\n\n\n\n\n\n","category":"function"},{"location":"base/math/#Base.Math.atand","page":"数学相关","title":"Base.Math.atand","text":"atand(y)\natand(y,x)\n\nCompute the inverse tangent of y or y/x, respectively, where the output is in degrees.\n\ncompat: Julia 1.7\nThe one-argument method supports square matrix arguments as of Julia 1.7.\n\n\n\n\n\n","category":"function"},{"location":"base/math/#Base.Math.sec-Tuple{Number}","page":"数学相关","title":"Base.Math.sec","text":"sec(x)\n\nCompute the secant of x, where x is in radians.\n\n\n\n\n\n","category":"method"},{"location":"base/math/#Base.Math.csc-Tuple{Number}","page":"数学相关","title":"Base.Math.csc","text":"csc(x)\n\nCompute the cosecant of x, where x is in radians.\n\n\n\n\n\n","category":"method"},{"location":"base/math/#Base.Math.cot-Tuple{Number}","page":"数学相关","title":"Base.Math.cot","text":"cot(x)\n\nCompute the cotangent of x, where x is in radians.\n\n\n\n\n\n","category":"method"},{"location":"base/math/#Base.Math.secd","page":"数学相关","title":"Base.Math.secd","text":"secd(x)\n\nCompute the secant of x, where x is in degrees.\n\n\n\n\n\n","category":"function"},{"location":"base/math/#Base.Math.cscd","page":"数学相关","title":"Base.Math.cscd","text":"cscd(x)\n\nCompute the cosecant of x, where x is in degrees.\n\n\n\n\n\n","category":"function"},{"location":"base/math/#Base.Math.cotd","page":"数学相关","title":"Base.Math.cotd","text":"cotd(x)\n\nCompute the cotangent of x, where x is in degrees.\n\n\n\n\n\n","category":"function"},{"location":"base/math/#Base.Math.asec-Tuple{Number}","page":"数学相关","title":"Base.Math.asec","text":"asec(x)\n\nCompute the inverse secant of x, where the output is in radians. \n\n\n\n\n\n","category":"method"},{"location":"base/math/#Base.Math.acsc-Tuple{Number}","page":"数学相关","title":"Base.Math.acsc","text":"acsc(x)\n\nCompute the inverse cosecant of x, where the output is in radians. \n\n\n\n\n\n","category":"method"},{"location":"base/math/#Base.Math.acot-Tuple{Number}","page":"数学相关","title":"Base.Math.acot","text":"acot(x)\n\nCompute the inverse cotangent of x, where the output is in radians. \n\n\n\n\n\n","category":"method"},{"location":"base/math/#Base.Math.asecd","page":"数学相关","title":"Base.Math.asecd","text":"asecd(x)\n\nCompute the inverse secant of x, where the output is in degrees. If x is a matrix, x needs to be a square matrix.\n\ncompat: Julia 1.7\nMatrix arguments require Julia 1.7 or later.\n\n\n\n\n\n","category":"function"},{"location":"base/math/#Base.Math.acscd","page":"数学相关","title":"Base.Math.acscd","text":"acscd(x)\n\nCompute the inverse cosecant of x, where the output is in degrees. If x is a matrix, x needs to be a square matrix.\n\ncompat: Julia 1.7\nMatrix arguments require Julia 1.7 or later.\n\n\n\n\n\n","category":"function"},{"location":"base/math/#Base.Math.acotd","page":"数学相关","title":"Base.Math.acotd","text":"acotd(x)\n\nCompute the inverse cotangent of x, where the output is in degrees. If x is a matrix, x needs to be a square matrix.\n\ncompat: Julia 1.7\nMatrix arguments require Julia 1.7 or later.\n\n\n\n\n\n","category":"function"},{"location":"base/math/#Base.Math.sech-Tuple{Number}","page":"数学相关","title":"Base.Math.sech","text":"sech(x)\n\nCompute the hyperbolic secant of x.\n\n\n\n\n\n","category":"method"},{"location":"base/math/#Base.Math.csch-Tuple{Number}","page":"数学相关","title":"Base.Math.csch","text":"csch(x)\n\nCompute the hyperbolic cosecant of x.\n\n\n\n\n\n","category":"method"},{"location":"base/math/#Base.Math.coth-Tuple{Number}","page":"数学相关","title":"Base.Math.coth","text":"coth(x)\n\nCompute the hyperbolic cotangent of x.\n\n\n\n\n\n","category":"method"},{"location":"base/math/#Base.asinh-Tuple{Number}","page":"数学相关","title":"Base.asinh","text":"asinh(x)\n\nCompute the inverse hyperbolic sine of x.\n\n\n\n\n\n","category":"method"},{"location":"base/math/#Base.acosh-Tuple{Number}","page":"数学相关","title":"Base.acosh","text":"acosh(x)\n\nCompute the inverse hyperbolic cosine of x.\n\n\n\n\n\n","category":"method"},{"location":"base/math/#Base.atanh-Tuple{Number}","page":"数学相关","title":"Base.atanh","text":"atanh(x)\n\nCompute the inverse hyperbolic tangent of x.\n\n\n\n\n\n","category":"method"},{"location":"base/math/#Base.Math.asech-Tuple{Number}","page":"数学相关","title":"Base.Math.asech","text":"asech(x)\n\nCompute the inverse hyperbolic secant of x. \n\n\n\n\n\n","category":"method"},{"location":"base/math/#Base.Math.acsch-Tuple{Number}","page":"数学相关","title":"Base.Math.acsch","text":"acsch(x)\n\nCompute the inverse hyperbolic cosecant of x. \n\n\n\n\n\n","category":"method"},{"location":"base/math/#Base.Math.acoth-Tuple{Number}","page":"数学相关","title":"Base.Math.acoth","text":"acoth(x)\n\nCompute the inverse hyperbolic cotangent of x. \n\n\n\n\n\n","category":"method"},{"location":"base/math/#Base.Math.sinc","page":"数学相关","title":"Base.Math.sinc","text":"sinc(x)\n\nCompute sin(pi x) (pi x) if x neq 0, and 1 if x = 0.\n\nSee also cosc, its derivative.\n\n\n\n\n\n","category":"function"},{"location":"base/math/#Base.Math.cosc","page":"数学相关","title":"Base.Math.cosc","text":"cosc(x)\n\nCompute cos(pi x) x - sin(pi x) (pi x^2) if x neq 0, and 0 if x = 0. This is the derivative of sinc(x).\n\n\n\n\n\n","category":"function"},{"location":"base/math/#Base.Math.deg2rad","page":"数学相关","title":"Base.Math.deg2rad","text":"deg2rad(x)\n\nConvert x from degrees to radians.\n\nSee also: rad2deg, sind.\n\nExamples\n\njulia> deg2rad(90)\n1.5707963267948966\n\n\n\n\n\n","category":"function"},{"location":"base/math/#Base.Math.rad2deg","page":"数学相关","title":"Base.Math.rad2deg","text":"rad2deg(x)\n\nConvert x from radians to degrees.\n\nExamples\n\njulia> rad2deg(pi)\n180.0\n\n\n\n\n\n","category":"function"},{"location":"base/math/#Base.Math.hypot","page":"数学相关","title":"Base.Math.hypot","text":"hypot(x, y)\n\nCompute the hypotenuse sqrtx^2+y^2 avoiding overflow and underflow.\n\nThis code is an implementation of the algorithm described in: An Improved Algorithm for hypot(a,b) by Carlos F. Borges The article is available online at ArXiv at the link https://arxiv.org/abs/1904.09481\n\nhypot(x...)\n\nCompute the hypotenuse sqrtsum x_i^2 avoiding overflow and underflow.\n\nSee also norm in the LinearAlgebra standard library.\n\nExamples\n\njulia> a = Int64(10)^10;\n\njulia> hypot(a, a)\n1.4142135623730951e10\n\njulia> √(a^2 + a^2) # a^2 overflows\nERROR: DomainError with -2.914184810805068e18:\nsqrt will only return a complex result if called with a complex argument. Try sqrt(Complex(x)).\nStacktrace:\n[...]\n\njulia> hypot(3, 4im)\n5.0\n\njulia> hypot(-5.7)\n5.7\n\njulia> hypot(3, 4im, 12.0)\n13.0\n\njulia> using LinearAlgebra\n\njulia> norm([a, a, a, a]) == hypot(a, a, a, a)\ntrue\n\n\n\n\n\n","category":"function"},{"location":"base/math/#Base.log-Tuple{Number}","page":"数学相关","title":"Base.log","text":"log(x)\n\nCompute the natural logarithm of x. Throws DomainError for negative Real arguments. Use complex negative arguments to obtain complex results.\n\nSee also [log1p], [log2], [log10].\n\nExamples\n\njulia> log(2)\n0.6931471805599453\n\njulia> log(-3)\nERROR: DomainError with -3.0:\nlog will only return a complex result if called with a complex argument. Try log(Complex(x)).\nStacktrace:\n [1] throw_complex_domainerror(::Symbol, ::Float64) at ./math.jl:31\n[...]\n\n\n\n\n\n","category":"method"},{"location":"base/math/#Base.log-Tuple{Number, Number}","page":"数学相关","title":"Base.log","text":"log(b,x)\n\nCompute the base b logarithm of x. Throws DomainError for negative Real arguments.\n\nExamples\n\njulia> log(4,8)\n1.5\n\njulia> log(4,2)\n0.5\n\njulia> log(-2, 3)\nERROR: DomainError with -2.0:\nlog will only return a complex result if called with a complex argument. Try log(Complex(x)).\nStacktrace:\n [1] throw_complex_domainerror(::Symbol, ::Float64) at ./math.jl:31\n[...]\n\njulia> log(2, -3)\nERROR: DomainError with -3.0:\nlog will only return a complex result if called with a complex argument. Try log(Complex(x)).\nStacktrace:\n [1] throw_complex_domainerror(::Symbol, ::Float64) at ./math.jl:31\n[...]\n\nnote: Note\nIf b is a power of 2 or 10, log2 or log10 should be used, as these will typically be faster and more accurate. For example,julia> log(100,1000000)\n2.9999999999999996\n\njulia> log10(1000000)/2\n3.0\n\n\n\n\n\n","category":"method"},{"location":"base/math/#Base.log2","page":"数学相关","title":"Base.log2","text":"log2(x)\n\nCompute the logarithm of x to base 2. Throws DomainError for negative Real arguments.\n\nSee also: exp2, ldexp, ispow2.\n\nExamples\n\njulia> log2(4)\n2.0\n\njulia> log2(10)\n3.321928094887362\n\njulia> log2(-2)\nERROR: DomainError with -2.0:\nlog2 will only return a complex result if called with a complex argument. Try log2(Complex(x)).\nStacktrace:\n [1] throw_complex_domainerror(f::Symbol, x::Float64) at ./math.jl:31\n[...]\n\n\n\n\n\n","category":"function"},{"location":"base/math/#Base.log10","page":"数学相关","title":"Base.log10","text":"log10(x)\n\nCompute the logarithm of x to base 10. Throws DomainError for negative Real arguments.\n\nExamples\n\njulia> log10(100)\n2.0\n\njulia> log10(2)\n0.3010299956639812\n\njulia> log10(-2)\nERROR: DomainError with -2.0:\nlog10 will only return a complex result if called with a complex argument. Try log10(Complex(x)).\nStacktrace:\n [1] throw_complex_domainerror(f::Symbol, x::Float64) at ./math.jl:31\n[...]\n\n\n\n\n\n","category":"function"},{"location":"base/math/#Base.log1p","page":"数学相关","title":"Base.log1p","text":"log1p(x)\n\nAccurate natural logarithm of 1+x. Throws DomainError for Real arguments less than -1.\n\nExamples\n\njulia> log1p(-0.5)\n-0.6931471805599453\n\njulia> log1p(0)\n0.0\n\njulia> log1p(-2)\nERROR: DomainError with -2.0:\nlog1p will only return a complex result if called with a complex argument. Try log1p(Complex(x)).\nStacktrace:\n [1] throw_complex_domainerror(::Symbol, ::Float64) at ./math.jl:31\n[...]\n\n\n\n\n\n","category":"function"},{"location":"base/math/#Base.Math.frexp","page":"数学相关","title":"Base.Math.frexp","text":"frexp(val)\n\nReturn (x,exp) such that x has a magnitude in the interval 12 1) or 0, and val is equal to x times 2^exp.\n\nExamples\n\njulia> frexp(12.8)\n(0.8, 4)\n\n\n\n\n\n","category":"function"},{"location":"base/math/#Base.exp-Tuple{Float64}","page":"数学相关","title":"Base.exp","text":"exp(x)\n\nCompute the natural base exponential of x, in other words ℯ^x.\n\nSee also exp2, exp10 and cis.\n\nExamples\n\njulia> exp(1.0)\n2.718281828459045\n\njulia> exp(im * pi) ≈ cis(pi)\ntrue\n\n\n\n\n\n","category":"method"},{"location":"base/math/#Base.exp2","page":"数学相关","title":"Base.exp2","text":"exp2(x)\n\nCompute the base 2 exponential of x, in other words 2^x.\n\nSee also ldexp, <<.\n\nExamples\n\njulia> exp2(5)\n32.0\n\njulia> 2^5\n32\n\njulia> exp2(63) > typemax(Int)\ntrue\n\n\n\n\n\n","category":"function"},{"location":"base/math/#Base.exp10","page":"数学相关","title":"Base.exp10","text":"exp10(x)\n\nCompute the base 10 exponential of x, in other words 10^x.\n\nExamples\n\njulia> exp10(2)\n100.0\n\njulia> 10^2\n100\n\n\n\n\n\n","category":"function"},{"location":"base/math/#Base.Math.ldexp","page":"数学相关","title":"Base.Math.ldexp","text":"ldexp(x, n)\n\nCompute x times 2^n.\n\nExamples\n\njulia> ldexp(5., 2)\n20.0\n\n\n\n\n\n","category":"function"},{"location":"base/math/#Base.Math.modf","page":"数学相关","title":"Base.Math.modf","text":"modf(x)\n\nReturn a tuple (fpart, ipart) of the fractional and integral parts of a number. Both parts have the same sign as the argument.\n\nExamples\n\njulia> modf(3.5)\n(0.5, 3.0)\n\njulia> modf(-3.5)\n(-0.5, -3.0)\n\n\n\n\n\n","category":"function"},{"location":"base/math/#Base.expm1","page":"数学相关","title":"Base.expm1","text":"expm1(x)\n\nAccurately compute e^x-1. It avoids the loss of precision involved in the direct evaluation of exp(x)-1 for small values of x.\n\nExamples\n\njulia> expm1(1e-16)\n1.0e-16\n\njulia> exp(1e-16) - 1\n0.0\n\n\n\n\n\n","category":"function"},{"location":"base/math/#Base.round-Tuple{Type, Any}","page":"数学相关","title":"Base.round","text":"round([T,] x, [r::RoundingMode])\nround(x, [r::RoundingMode]; digits::Integer=0, base = 10)\nround(x, [r::RoundingMode]; sigdigits::Integer, base = 10)\n\nRounds the number x.\n\nWithout keyword arguments, x is rounded to an integer value, returning a value of type T, or of the same type of x if no T is provided. An InexactError will be thrown if the value is not representable by T, similar to convert.\n\nIf the digits keyword argument is provided, it rounds to the specified number of digits after the decimal place (or before if negative), in base base.\n\nIf the sigdigits keyword argument is provided, it rounds to the specified number of significant digits, in base base.\n\nThe RoundingMode r controls the direction of the rounding; the default is RoundNearest, which rounds to the nearest integer, with ties (fractional values of 0.5) being rounded to the nearest even integer. Note that round may give incorrect results if the global rounding mode is changed (see rounding).\n\nExamples\n\njulia> round(1.7)\n2.0\n\njulia> round(Int, 1.7)\n2\n\njulia> round(1.5)\n2.0\n\njulia> round(2.5)\n2.0\n\njulia> round(pi; digits=2)\n3.14\n\njulia> round(pi; digits=3, base=2)\n3.125\n\njulia> round(123.456; sigdigits=2)\n120.0\n\njulia> round(357.913; sigdigits=4, base=2)\n352.0\n\nnote: Note\nRounding to specified digits in bases other than 2 can be inexact when operating on binary floating point numbers. For example, the Float64 value represented by 1.15 is actually less than 1.15, yet will be rounded to 1.2. For example:julia> x = 1.15\n1.15\n\njulia> @sprintf \"%.20f\" x\n\"1.14999999999999991118\"\n\njulia> x < 115//100\ntrue\n\njulia> round(x, digits=1)\n1.2\n\nExtensions\n\nTo extend round to new numeric types, it is typically sufficient to define Base.round(x::NewType, r::RoundingMode).\n\n\n\n\n\n","category":"method"},{"location":"base/math/#Base.Rounding.RoundingMode","page":"数学相关","title":"Base.Rounding.RoundingMode","text":"RoundingMode\n\nA type used for controlling the rounding mode of floating point operations (via rounding/setrounding functions), or as optional arguments for rounding to the nearest integer (via the round function).\n\nCurrently supported rounding modes are:\n\nRoundNearest (default)\nRoundNearestTiesAway\nRoundNearestTiesUp\nRoundToZero\nRoundFromZero (BigFloat only)\nRoundUp\nRoundDown\n\n\n\n\n\n","category":"type"},{"location":"base/math/#Base.Rounding.RoundNearest","page":"数学相关","title":"Base.Rounding.RoundNearest","text":"RoundNearest\n\nThe default rounding mode. Rounds to the nearest integer, with ties (fractional values of 0.5) being rounded to the nearest even integer.\n\n\n\n\n\n","category":"constant"},{"location":"base/math/#Base.Rounding.RoundNearestTiesAway","page":"数学相关","title":"Base.Rounding.RoundNearestTiesAway","text":"RoundNearestTiesAway\n\nRounds to nearest integer, with ties rounded away from zero (C/C++ round behaviour).\n\n\n\n\n\n","category":"constant"},{"location":"base/math/#Base.Rounding.RoundNearestTiesUp","page":"数学相关","title":"Base.Rounding.RoundNearestTiesUp","text":"RoundNearestTiesUp\n\nRounds to nearest integer, with ties rounded toward positive infinity (Java/JavaScript round behaviour).\n\n\n\n\n\n","category":"constant"},{"location":"base/math/#Base.Rounding.RoundToZero","page":"数学相关","title":"Base.Rounding.RoundToZero","text":"RoundToZero\n\nround using this rounding mode is an alias for trunc.\n\n\n\n\n\n","category":"constant"},{"location":"base/math/#Base.Rounding.RoundFromZero","page":"数学相关","title":"Base.Rounding.RoundFromZero","text":"RoundFromZero\n\nRounds away from zero. This rounding mode may only be used with T == BigFloat inputs to round.\n\nExamples\n\njulia> BigFloat(\"1.0000000000000001\", 5, RoundFromZero)\n1.06\n\n\n\n\n\n","category":"constant"},{"location":"base/math/#Base.Rounding.RoundUp","page":"数学相关","title":"Base.Rounding.RoundUp","text":"RoundUp\n\nround using this rounding mode is an alias for ceil.\n\n\n\n\n\n","category":"constant"},{"location":"base/math/#Base.Rounding.RoundDown","page":"数学相关","title":"Base.Rounding.RoundDown","text":"RoundDown\n\nround using this rounding mode is an alias for floor.\n\n\n\n\n\n","category":"constant"},{"location":"base/math/#Base.round-Tuple{Complex{<:AbstractFloat}, RoundingMode, RoundingMode}","page":"数学相关","title":"Base.round","text":"round(z::Complex[, RoundingModeReal, [RoundingModeImaginary]])\nround(z::Complex[, RoundingModeReal, [RoundingModeImaginary]]; digits=, base=10)\nround(z::Complex[, RoundingModeReal, [RoundingModeImaginary]]; sigdigits=, base=10)\n\nReturn the nearest integral value of the same type as the complex-valued z to z, breaking ties using the specified RoundingModes. The first RoundingMode is used for rounding the real components while the second is used for rounding the imaginary components.\n\nExample\n\njulia> round(3.14 + 4.5im)\n3.0 + 4.0im\n\n\n\n\n\n","category":"method"},{"location":"base/math/#Base.ceil","page":"数学相关","title":"Base.ceil","text":"ceil([T,] x)\nceil(x; digits::Integer= [, base = 10])\nceil(x; sigdigits::Integer= [, base = 10])\n\nceil(x) returns the nearest integral value of the same type as x that is greater than or equal to x.\n\nceil(T, x) converts the result to type T, throwing an InexactError if the value is not representable.\n\nKeywords digits, sigdigits and base work as for round.\n\n\n\n\n\n","category":"function"},{"location":"base/math/#Base.floor","page":"数学相关","title":"Base.floor","text":"floor([T,] x)\nfloor(x; digits::Integer= [, base = 10])\nfloor(x; sigdigits::Integer= [, base = 10])\n\nfloor(x) returns the nearest integral value of the same type as x that is less than or equal to x.\n\nfloor(T, x) converts the result to type T, throwing an InexactError if the value is not representable.\n\nKeywords digits, sigdigits and base work as for round.\n\n\n\n\n\n","category":"function"},{"location":"base/math/#Base.trunc","page":"数学相关","title":"Base.trunc","text":"trunc([T,] x)\ntrunc(x; digits::Integer= [, base = 10])\ntrunc(x; sigdigits::Integer= [, base = 10])\n\ntrunc(x) returns the nearest integral value of the same type as x whose absolute value is less than or equal to the absolute value of x.\n\ntrunc(T, x) converts the result to type T, throwing an InexactError if the value is not representable.\n\nKeywords digits, sigdigits and base work as for round.\n\nSee also: %, floor, unsigned, unsafe_trunc.\n\nExamples\n\njulia> trunc(2.22)\n2.0\n\njulia> trunc(-2.22, digits=1)\n-2.2\n\njulia> trunc(Int, -2.22)\n-2\n\n\n\n\n\n","category":"function"},{"location":"base/math/#Base.unsafe_trunc","page":"数学相关","title":"Base.unsafe_trunc","text":"unsafe_trunc(T, x)\n\nReturn the nearest integral value of type T whose absolute value is less than or equal to the absolute value of x. If the value is not representable by T, an arbitrary value will be returned. See also trunc.\n\nExamples\n\njulia> unsafe_trunc(Int, -2.2)\n-2\n\njulia> unsafe_trunc(Int, NaN)\n-9223372036854775808\n\n\n\n\n\n","category":"function"},{"location":"base/math/#Base.min","page":"数学相关","title":"Base.min","text":"min(x, y, ...)\n\nReturn the minimum of the arguments (with respect to isless). See also the minimum function to take the minimum element from a collection.\n\nExamples\n\njulia> min(2, 5, 1)\n1\n\n\n\n\n\n","category":"function"},{"location":"base/math/#Base.max","page":"数学相关","title":"Base.max","text":"max(x, y, ...)\n\nReturn the maximum of the arguments (with respect to isless). See also the maximum function to take the maximum element from a collection.\n\nExamples\n\njulia> max(2, 5, 1)\n5\n\n\n\n\n\n","category":"function"},{"location":"base/math/#Base.minmax","page":"数学相关","title":"Base.minmax","text":"minmax(x, y)\n\nReturn (min(x,y), max(x,y)).\n\nSee also extrema that returns (minimum(x), maximum(x)).\n\nExamples\n\njulia> minmax('c','b')\n('b', 'c')\n\n\n\n\n\n","category":"function"},{"location":"base/math/#Base.Math.clamp","page":"数学相关","title":"Base.Math.clamp","text":"clamp(x, lo, hi)\n\nReturn x if lo <= x <= hi. If x > hi, return hi. If x < lo, return lo. Arguments are promoted to a common type.\n\nSee also clamp!, min, max.\n\ncompat: Julia 1.3\nmissing as the first argument requires at least Julia 1.3.\n\nExamples\n\njulia> clamp.([pi, 1.0, big(10)], 2.0, 9.0)\n3-element Vector{BigFloat}:\n 3.141592653589793238462643383279502884197169399375105820974944592307816406286198\n 2.0\n 9.0\n\njulia> clamp.([11, 8, 5], 10, 6) # an example where lo > hi\n3-element Vector{Int64}:\n 6\n 6\n 10\n\n\n\n\n\nclamp(x, T)::T\n\nClamp x between typemin(T) and typemax(T) and convert the result to type T.\n\nSee also trunc.\n\nExamples\n\njulia> clamp(200, Int8)\n127\n\njulia> clamp(-200, Int8)\n-128\n\njulia> trunc(Int, 4pi^2)\n39\n\n\n\n\n\nclamp(x::Integer, r::AbstractUnitRange)\n\nClamp x to lie within range r.\n\ncompat: Julia 1.6\nThis method requires at least Julia 1.6.\n\n\n\n\n\n","category":"function"},{"location":"base/math/#Base.Math.clamp!","page":"数学相关","title":"Base.Math.clamp!","text":"clamp!(array::AbstractArray, lo, hi)\n\nRestrict values in array to the specified range, in-place. See also clamp.\n\ncompat: Julia 1.3\nmissing entries in array require at least Julia 1.3.\n\nExamples\n\njulia> row = collect(-4:4)';\n\njulia> clamp!(row, 0, Inf)\n1×9 adjoint(::Vector{Int64}) with eltype Int64:\n 0 0 0 0 0 1 2 3 4\n\njulia> clamp.((-4:4)', 0, Inf)\n1×9 Matrix{Float64}:\n 0.0 0.0 0.0 0.0 0.0 1.0 2.0 3.0 4.0\n\n\n\n\n\n","category":"function"},{"location":"base/math/#Base.abs","page":"数学相关","title":"Base.abs","text":"abs(x)\n\nThe absolute value of x.\n\nWhen abs is applied to signed integers, overflow may occur, resulting in the return of a negative value. This overflow occurs only when abs is applied to the minimum representable value of a signed integer. That is, when x == typemin(typeof(x)), abs(x) == x < 0, not -x as might be expected.\n\nSee also: abs2, unsigned, sign.\n\nExamples\n\njulia> abs(-3)\n3\n\njulia> abs(1 + im)\n1.4142135623730951\n\njulia> abs(typemin(Int64))\n-9223372036854775808\n\n\n\n\n\n","category":"function"},{"location":"base/math/#Base.Checked.checked_abs","page":"数学相关","title":"Base.Checked.checked_abs","text":"Base.checked_abs(x)\n\nCalculates abs(x), checking for overflow errors where applicable. For example, standard two's complement signed integers (e.g. Int) cannot represent abs(typemin(Int)), thus leading to an overflow.\n\nThe overflow protection may impose a perceptible performance penalty.\n\n\n\n\n\n","category":"function"},{"location":"base/math/#Base.Checked.checked_neg","page":"数学相关","title":"Base.Checked.checked_neg","text":"Base.checked_neg(x)\n\nCalculates -x, checking for overflow errors where applicable. For example, standard two's complement signed integers (e.g. Int) cannot represent -typemin(Int), thus leading to an overflow.\n\nThe overflow protection may impose a perceptible performance penalty.\n\n\n\n\n\n","category":"function"},{"location":"base/math/#Base.Checked.checked_add","page":"数学相关","title":"Base.Checked.checked_add","text":"Base.checked_add(x, y)\n\nCalculates x+y, checking for overflow errors where applicable.\n\nThe overflow protection may impose a perceptible performance penalty.\n\n\n\n\n\n","category":"function"},{"location":"base/math/#Base.Checked.checked_sub","page":"数学相关","title":"Base.Checked.checked_sub","text":"Base.checked_sub(x, y)\n\nCalculates x-y, checking for overflow errors where applicable.\n\nThe overflow protection may impose a perceptible performance penalty.\n\n\n\n\n\n","category":"function"},{"location":"base/math/#Base.Checked.checked_mul","page":"数学相关","title":"Base.Checked.checked_mul","text":"Base.checked_mul(x, y)\n\nCalculates x*y, checking for overflow errors where applicable.\n\nThe overflow protection may impose a perceptible performance penalty.\n\n\n\n\n\n","category":"function"},{"location":"base/math/#Base.Checked.checked_div","page":"数学相关","title":"Base.Checked.checked_div","text":"Base.checked_div(x, y)\n\nCalculates div(x,y), checking for overflow errors where applicable.\n\nThe overflow protection may impose a perceptible performance penalty.\n\n\n\n\n\n","category":"function"},{"location":"base/math/#Base.Checked.checked_rem","page":"数学相关","title":"Base.Checked.checked_rem","text":"Base.checked_rem(x, y)\n\nCalculates x%y, checking for overflow errors where applicable.\n\nThe overflow protection may impose a perceptible performance penalty.\n\n\n\n\n\n","category":"function"},{"location":"base/math/#Base.Checked.checked_fld","page":"数学相关","title":"Base.Checked.checked_fld","text":"Base.checked_fld(x, y)\n\nCalculates fld(x,y), checking for overflow errors where applicable.\n\nThe overflow protection may impose a perceptible performance penalty.\n\n\n\n\n\n","category":"function"},{"location":"base/math/#Base.Checked.checked_mod","page":"数学相关","title":"Base.Checked.checked_mod","text":"Base.checked_mod(x, y)\n\nCalculates mod(x,y), checking for overflow errors where applicable.\n\nThe overflow protection may impose a perceptible performance penalty.\n\n\n\n\n\n","category":"function"},{"location":"base/math/#Base.Checked.checked_cld","page":"数学相关","title":"Base.Checked.checked_cld","text":"Base.checked_cld(x, y)\n\nCalculates cld(x,y), checking for overflow errors where applicable.\n\nThe overflow protection may impose a perceptible performance penalty.\n\n\n\n\n\n","category":"function"},{"location":"base/math/#Base.Checked.add_with_overflow","page":"数学相关","title":"Base.Checked.add_with_overflow","text":"Base.add_with_overflow(x, y) -> (r, f)\n\nCalculates r = x+y, with the flag f indicating whether overflow has occurred.\n\n\n\n\n\n","category":"function"},{"location":"base/math/#Base.Checked.sub_with_overflow","page":"数学相关","title":"Base.Checked.sub_with_overflow","text":"Base.sub_with_overflow(x, y) -> (r, f)\n\nCalculates r = x-y, with the flag f indicating whether overflow has occurred.\n\n\n\n\n\n","category":"function"},{"location":"base/math/#Base.Checked.mul_with_overflow","page":"数学相关","title":"Base.Checked.mul_with_overflow","text":"Base.mul_with_overflow(x, y) -> (r, f)\n\nCalculates r = x*y, with the flag f indicating whether overflow has occurred.\n\n\n\n\n\n","category":"function"},{"location":"base/math/#Base.abs2","page":"数学相关","title":"Base.abs2","text":"abs2(x)\n\nSquared absolute value of x.\n\nExamples\n\njulia> abs2(-3)\n9\n\n\n\n\n\n","category":"function"},{"location":"base/math/#Base.copysign","page":"数学相关","title":"Base.copysign","text":"copysign(x, y) -> z\n\nReturn z which has the magnitude of x and the same sign as y.\n\nExamples\n\njulia> copysign(1, -2)\n-1\n\njulia> copysign(-1, 2)\n1\n\n\n\n\n\n","category":"function"},{"location":"base/math/#Base.sign","page":"数学相关","title":"Base.sign","text":"sign(x)\n\nReturn zero if x==0 and xx otherwise (i.e., ±1 for real x).\n\nSee also signbit, zero, copysign, flipsign.\n\nExamples\n\njulia> sign(-4.0)\n-1.0\n\njulia> sign(99)\n1\n\njulia> sign(-0.0)\n-0.0\n\njulia> sign(0 + im)\n0.0 + 1.0im\n\n\n\n\n\n","category":"function"},{"location":"base/math/#Base.signbit","page":"数学相关","title":"Base.signbit","text":"signbit(x)\n\nReturns true if the value of the sign of x is negative, otherwise false.\n\nSee also sign and copysign.\n\nExamples\n\njulia> signbit(-4)\ntrue\n\njulia> signbit(5)\nfalse\n\njulia> signbit(5.5)\nfalse\n\njulia> signbit(-4.1)\ntrue\n\n\n\n\n\n","category":"function"},{"location":"base/math/#Base.flipsign","page":"数学相关","title":"Base.flipsign","text":"flipsign(x, y)\n\nReturn x with its sign flipped if y is negative. For example abs(x) = flipsign(x,x).\n\nExamples\n\njulia> flipsign(5, 3)\n5\n\njulia> flipsign(5, -3)\n-5\n\n\n\n\n\n","category":"function"},{"location":"base/math/#Base.sqrt-Tuple{Real}","page":"数学相关","title":"Base.sqrt","text":"sqrt(x)\n\nReturn sqrtx. Throws DomainError for negative Real arguments. Use complex negative arguments instead. The prefix operator √ is equivalent to sqrt.\n\nSee also: hypot.\n\nExamples\n\njulia> sqrt(big(81))\n9.0\n\njulia> sqrt(big(-81))\nERROR: DomainError with -81.0:\nNaN result for non-NaN input.\nStacktrace:\n [1] sqrt(::BigFloat) at ./mpfr.jl:501\n[...]\n\njulia> sqrt(big(complex(-81)))\n0.0 + 9.0im\n\njulia> .√(1:4)\n4-element Vector{Float64}:\n 1.0\n 1.4142135623730951\n 1.7320508075688772\n 2.0\n\n\n\n\n\n","category":"method"},{"location":"base/math/#Base.isqrt","page":"数学相关","title":"Base.isqrt","text":"isqrt(n::Integer)\n\nInteger square root: the largest integer m such that m*m <= n.\n\njulia> isqrt(5)\n2\n\n\n\n\n\n","category":"function"},{"location":"base/math/#Base.Math.cbrt","page":"数学相关","title":"Base.Math.cbrt","text":"cbrt(x::Real)\n\nReturn the cube root of x, i.e. x^13. Negative values are accepted (returning the negative real root when x 0).\n\nThe prefix operator ∛ is equivalent to cbrt.\n\nExamples\n\njulia> cbrt(big(27))\n3.0\n\njulia> cbrt(big(-27))\n-3.0\n\n\n\n\n\n","category":"function"},{"location":"base/math/#Base.real-Tuple{Complex}","page":"数学相关","title":"Base.real","text":"real(z)\n\nReturn the real part of the complex number z.\n\nSee also: imag, reim, complex, isreal, Real.\n\nExamples\n\njulia> real(1 + 3im)\n1\n\n\n\n\n\n","category":"method"},{"location":"base/math/#Base.imag","page":"数学相关","title":"Base.imag","text":"imag(z)\n\nReturn the imaginary part of the complex number z.\n\nSee also: conj, reim, adjoint, angle.\n\nExamples\n\njulia> imag(1 + 3im)\n3\n\n\n\n\n\nimag(A::AbstractArray)\n\nReturn an array containing the imaginary part of each entry in array A.\n\nEquivalent to imag.(A), except that when A has zero dimensions, a 0-dimensional array is returned (rather than a scalar).\n\nExamples\n\njulia> imag([1, 2im, 3 + 4im])\n3-element Vector{Int64}:\n 0\n 2\n 4\n\njulia> imag(fill(2 - im))\n0-dimensional Array{Int64, 0}:\n-1\n\n\n\n\n\n","category":"function"},{"location":"base/math/#Base.reim","page":"数学相关","title":"Base.reim","text":"reim(z)\n\nReturn a tuple of the real and imaginary parts of the complex number z.\n\nExamples\n\njulia> reim(1 + 3im)\n(1, 3)\n\n\n\n\n\nreim(A::AbstractArray)\n\nReturn a tuple of two arrays containing respectively the real and the imaginary part of each entry in A.\n\nEquivalent to (real.(A), imag.(A)), except that when eltype(A) <: Real A is returned without copying to represent the real part, and that when A has zero dimensions, a 0-dimensional array is returned (rather than a scalar).\n\nExamples\n\njulia> reim([1, 2im, 3 + 4im])\n([1, 0, 3], [0, 2, 4])\n\njulia> reim(fill(2 - im))\n(fill(2), fill(-1))\n\n\n\n\n\n","category":"function"},{"location":"base/math/#Base.conj","page":"数学相关","title":"Base.conj","text":"conj(z)\n\nCompute the complex conjugate of a complex number z.\n\nSee also: angle, adjoint.\n\nExamples\n\njulia> conj(1 + 3im)\n1 - 3im\n\n\n\n\n\nconj(A::AbstractArray)\n\nReturn an array containing the complex conjugate of each entry in array A.\n\nEquivalent to conj.(A), except that when eltype(A) <: Real A is returned without copying, and that when A has zero dimensions, a 0-dimensional array is returned (rather than a scalar).\n\nExamples\n\njulia> conj([1, 2im, 3 + 4im])\n3-element Vector{Complex{Int64}}:\n 1 + 0im\n 0 - 2im\n 3 - 4im\n\njulia> conj(fill(2 - im))\n0-dimensional Array{Complex{Int64}, 0}:\n2 + 1im\n\n\n\n\n\n","category":"function"},{"location":"base/math/#Base.angle","page":"数学相关","title":"Base.angle","text":"angle(z)\n\nCompute the phase angle in radians of a complex number z.\n\nSee also: atan, cis.\n\nExamples\n\njulia> rad2deg(angle(1 + im))\n45.0\n\njulia> rad2deg(angle(1 - im))\n-45.0\n\njulia> rad2deg(angle(-1 - im))\n-135.0\n\n\n\n\n\n","category":"function"},{"location":"base/math/#Base.cis","page":"数学相关","title":"Base.cis","text":"cis(x)\n\nMore efficient method for exp(im*x) by using Euler's formula: cos(x) + i sin(x) = exp(i x).\n\nSee also cispi, sincos, exp, angle.\n\nExamples\n\njulia> cis(π) ≈ -1\ntrue\n\n\n\n\n\n","category":"function"},{"location":"base/math/#Base.cispi","page":"数学相关","title":"Base.cispi","text":"cispi(x)\n\nMore accurate method for cis(pi*x) (especially for large x).\n\nSee also cis, sincospi, exp, angle.\n\nExamples\n\njulia> cispi(10000)\n1.0 + 0.0im\n\njulia> cispi(0.25 + 1im)\n0.030556854645952924 + 0.030556854645952924im\n\ncompat: Julia 1.6\nThis function requires Julia 1.6 or later.\n\n\n\n\n\n","category":"function"},{"location":"base/math/#Base.binomial","page":"数学相关","title":"Base.binomial","text":"binomial(n::Integer, k::Integer)\n\nThe binomial coefficient binomnk, being the coefficient of the kth term in the polynomial expansion of (1+x)^n.\n\nIf n is non-negative, then it is the number of ways to choose k out of n items:\n\nbinomnk = fracnk (n-k)\n\nwhere n is the factorial function.\n\nIf n is negative, then it is defined in terms of the identity\n\nbinomnk = (-1)^k binomk-n-1k\n\nSee also factorial.\n\nExamples\n\njulia> binomial(5, 3)\n10\n\njulia> factorial(5) ÷ (factorial(5-3) * factorial(3))\n10\n\njulia> binomial(-5, 3)\n-35\n\nExternal links\n\nBinomial coefficient on Wikipedia.\n\n\n\n\n\n","category":"function"},{"location":"base/math/#Base.factorial","page":"数学相关","title":"Base.factorial","text":"factorial(n::Integer)\n\nFactorial of n. If n is an Integer, the factorial is computed as an integer (promoted to at least 64 bits). Note that this may overflow if n is not small, but you can use factorial(big(n)) to compute the result exactly in arbitrary precision.\n\nSee also binomial.\n\nExamples\n\njulia> factorial(6)\n720\n\njulia> factorial(21)\nERROR: OverflowError: 21 is too large to look up in the table; consider using `factorial(big(21))` instead\nStacktrace:\n[...]\n\njulia> factorial(big(21))\n51090942171709440000\n\nExternal links\n\nFactorial on Wikipedia.\n\n\n\n\n\n","category":"function"},{"location":"base/math/#Base.gcd","page":"数学相关","title":"Base.gcd","text":"gcd(x, y...)\n\nGreatest common (positive) divisor (or zero if all arguments are zero). The arguments may be integer and rational numbers.\n\ncompat: Julia 1.4\nRational arguments require Julia 1.4 or later.\n\nExamples\n\njulia> gcd(6, 9)\n3\n\njulia> gcd(6, -9)\n3\n\njulia> gcd(6, 0)\n6\n\njulia> gcd(0, 0)\n0\n\njulia> gcd(1//3, 2//3)\n1//3\n\njulia> gcd(1//3, -2//3)\n1//3\n\njulia> gcd(1//3, 2)\n1//3\n\njulia> gcd(0, 0, 10, 15)\n5\n\n\n\n\n\n","category":"function"},{"location":"base/math/#Base.lcm","page":"数学相关","title":"Base.lcm","text":"lcm(x, y...)\n\nLeast common (positive) multiple (or zero if any argument is zero). The arguments may be integer and rational numbers.\n\ncompat: Julia 1.4\nRational arguments require Julia 1.4 or later.\n\nExamples\n\njulia> lcm(2, 3)\n6\n\njulia> lcm(-2, 3)\n6\n\njulia> lcm(0, 3)\n0\n\njulia> lcm(0, 0)\n0\n\njulia> lcm(1//3, 2//3)\n2//3\n\njulia> lcm(1//3, -2//3)\n2//3\n\njulia> lcm(1//3, 2)\n2//1\n\njulia> lcm(1, 3, 5, 7)\n105\n\n\n\n\n\n","category":"function"},{"location":"base/math/#Base.gcdx","page":"数学相关","title":"Base.gcdx","text":"gcdx(a, b)\n\nComputes the greatest common (positive) divisor of a and b and their Bézout coefficients, i.e. the integer coefficients u and v that satisfy ua+vb = d = gcd(a b). gcdx(a b) returns (d u v).\n\nThe arguments may be integer and rational numbers.\n\ncompat: Julia 1.4\nRational arguments require Julia 1.4 or later.\n\nExamples\n\njulia> gcdx(12, 42)\n(6, -3, 1)\n\njulia> gcdx(240, 46)\n(2, -9, 47)\n\nnote: Note\nBézout coefficients are not uniquely defined. gcdx returns the minimal Bézout coefficients that are computed by the extended Euclidean algorithm. (Ref: D. Knuth, TAoCP, 2/e, p. 325, Algorithm X.) For signed integers, these coefficients u and v are minimal in the sense that u yd and v xd. Furthermore, the signs of u and v are chosen so that d is positive. For unsigned integers, the coefficients u and v might be near their typemax, and the identity then holds only via the unsigned integers' modulo arithmetic.\n\n\n\n\n\n","category":"function"},{"location":"base/math/#Base.ispow2","page":"数学相关","title":"Base.ispow2","text":"ispow2(n::Number) -> Bool\n\nTest whether n is an integer power of two.\n\nSee also count_ones, prevpow, nextpow.\n\nExamples\n\njulia> ispow2(4)\ntrue\n\njulia> ispow2(5)\nfalse\n\njulia> ispow2(4.5)\nfalse\n\njulia> ispow2(0.25)\ntrue\n\njulia> ispow2(1//8)\ntrue\n\ncompat: Julia 1.6\nSupport for non-Integer arguments was added in Julia 1.6.\n\n\n\n\n\n","category":"function"},{"location":"base/math/#Base.nextpow","page":"数学相关","title":"Base.nextpow","text":"nextpow(a, x)\n\nThe smallest a^n not less than x, where n is a non-negative integer. a must be greater than 1, and x must be greater than 0.\n\nSee also prevpow.\n\nExamples\n\njulia> nextpow(2, 7)\n8\n\njulia> nextpow(2, 9)\n16\n\njulia> nextpow(5, 20)\n25\n\njulia> nextpow(4, 16)\n16\n\n\n\n\n\n","category":"function"},{"location":"base/math/#Base.prevpow","page":"数学相关","title":"Base.prevpow","text":"prevpow(a, x)\n\nThe largest a^n not greater than x, where n is a non-negative integer. a must be greater than 1, and x must not be less than 1.\n\nSee also nextpow, isqrt.\n\nExamples\n\njulia> prevpow(2, 7)\n4\n\njulia> prevpow(2, 9)\n8\n\njulia> prevpow(5, 20)\n5\n\njulia> prevpow(4, 16)\n16\n\n\n\n\n\n","category":"function"},{"location":"base/math/#Base.nextprod","page":"数学相关","title":"Base.nextprod","text":"nextprod(factors::Union{Tuple,AbstractVector}, n)\n\nNext integer greater than or equal to n that can be written as prod k_i^p_i for integers p_1, p_2, etcetera, for factors k_i in factors.\n\nExamples\n\njulia> nextprod((2, 3), 105)\n108\n\njulia> 2^2 * 3^3\n108\n\ncompat: Julia 1.6\nThe method that accepts a tuple requires Julia 1.6 or later.\n\n\n\n\n\n","category":"function"},{"location":"base/math/#Base.invmod","page":"数学相关","title":"Base.invmod","text":"invmod(n, m)\n\nTake the inverse of n modulo m: y such that n y = 1 pmod m, and div(ym) = 0. This will throw an error if m = 0, or if gcd(nm) neq 1.\n\nExamples\n\njulia> invmod(2, 5)\n3\n\njulia> invmod(2, 3)\n2\n\njulia> invmod(5, 6)\n5\n\n\n\n\n\n","category":"function"},{"location":"base/math/#Base.powermod","page":"数学相关","title":"Base.powermod","text":"powermod(x::Integer, p::Integer, m)\n\nCompute x^p pmod m.\n\nExamples\n\njulia> powermod(2, 6, 5)\n4\n\njulia> mod(2^6, 5)\n4\n\njulia> powermod(5, 2, 20)\n5\n\njulia> powermod(5, 2, 19)\n6\n\njulia> powermod(5, 3, 19)\n11\n\n\n\n\n\n","category":"function"},{"location":"base/math/#Base.ndigits","page":"数学相关","title":"Base.ndigits","text":"ndigits(n::Integer; base::Integer=10, pad::Integer=1)\n\nCompute the number of digits in integer n written in base base (base must not be in [-1, 0, 1]), optionally padded with zeros to a specified size (the result will never be less than pad).\n\nSee also digits, count_ones.\n\nExamples\n\njulia> ndigits(12345)\n5\n\njulia> ndigits(1022, base=16)\n3\n\njulia> string(1022, base=16)\n\"3fe\"\n\njulia> ndigits(123, pad=5)\n5\n\njulia> ndigits(-123)\n3\n\n\n\n\n\n","category":"function"},{"location":"base/math/#Base.add_sum","page":"数学相关","title":"Base.add_sum","text":"Base.add_sum(x, y)\n\nThe reduction operator used in sum. The main difference from + is that small integers are promoted to Int/UInt.\n\n\n\n\n\n","category":"function"},{"location":"base/math/#Base.widemul","page":"数学相关","title":"Base.widemul","text":"widemul(x, y)\n\nMultiply x and y, giving the result as a larger type.\n\nSee also promote, Base.add_sum.\n\nExamples\n\njulia> widemul(Float32(3.0), 4.0) isa BigFloat\ntrue\n\njulia> typemax(Int8) * typemax(Int8)\n1\n\njulia> widemul(typemax(Int8), typemax(Int8)) # == 127^2\n16129\n\n\n\n\n\n","category":"function"},{"location":"base/math/#Base.Math.evalpoly","page":"数学相关","title":"Base.Math.evalpoly","text":"evalpoly(x, p)\n\nEvaluate the polynomial sum_k x^k-1 pk for the coefficients p[1], p[2], ...; that is, the coefficients are given in ascending order by power of x. Loops are unrolled at compile time if the number of coefficients is statically known, i.e. when p is a Tuple. This function generates efficient code using Horner's method if x is real, or using a Goertzel-like [DK62] algorithm if x is complex.\n\n[DK62]: Donald Knuth, Art of Computer Programming, Volume 2: Seminumerical Algorithms, Sec. 4.6.4.\n\ncompat: Julia 1.4\nThis function requires Julia 1.4 or later.\n\nExample\n\njulia> evalpoly(2, (1, 2, 3))\n17\n\n\n\n\n\n","category":"function"},{"location":"base/math/#Base.Math.@evalpoly","page":"数学相关","title":"Base.Math.@evalpoly","text":"@evalpoly(z, c...)\n\nEvaluate the polynomial sum_k z^k-1 ck for the coefficients c[1], c[2], ...; that is, the coefficients are given in ascending order by power of z. This macro expands to efficient inline code that uses either Horner's method or, for complex z, a more efficient Goertzel-like algorithm.\n\nSee also evalpoly.\n\nExamples\n\njulia> @evalpoly(3, 1, 0, 1)\n10\n\njulia> @evalpoly(2, 1, 0, 1)\n5\n\njulia> @evalpoly(2, 1, 1, 1)\n7\n\n\n\n\n\n","category":"macro"},{"location":"base/math/#Base.FastMath.@fastmath","page":"数学相关","title":"Base.FastMath.@fastmath","text":"@fastmath expr\n\nExecute a transformed version of the expression, which calls functions that may violate strict IEEE semantics. This allows the fastest possible operation, but results are undefined – be careful when doing this, as it may change numerical results.\n\nThis sets the LLVM Fast-Math flags, and corresponds to the -ffast-math option in clang. See the notes on performance annotations for more details.\n\nExamples\n\njulia> @fastmath 1+2\n3\n\njulia> @fastmath(sin(3))\n0.1411200080598672\n\n\n\n\n\n","category":"macro"},{"location":"base/math/#自定义二元运算符","page":"数学相关","title":"自定义二元运算符","text":"","category":"section"},{"location":"base/math/","page":"数学相关","title":"数学相关","text":"某些 unicode 字符可用于定义新的支持中缀表示法的二元运算符。 例如, ⊗(x,y) = kron(x,y) 定义 ⊗ (otimes) 为 Kronecker 积, 并且可以通过中缀语法将它作为一个二元运算符调用: C = A ⊗ B 也可以使用常用的前缀语法 C = ⊗(A,B)。","category":"page"},{"location":"base/math/","page":"数学相关","title":"数学相关","text":"其他支持这种扩展的字符包括 \\odot ⊙ 和 \\oplus ⊕","category":"page"},{"location":"base/math/","page":"数学相关","title":"数学相关","text":"The complete list is in the parser code: https://github.com/JuliaLang/julia/blob/master/src/julia-parser.scm","category":"page"},{"location":"base/math/","page":"数学相关","title":"数学相关","text":"像 * 一样解析的包括(按优先级排列) * / ÷ % & ⋅ ∘ × |\\\\| ∩ ∧ ⊗ ⊘ ⊙ ⊚ ⊛ ⊠ ⊡ ⊓ ∗ ∙ ∤ ⅋ ≀ ⊼ ⋄ ⋆ ⋇ ⋉ ⋊ ⋋ ⋌ ⋏ ⋒ ⟑ ⦸ ⦼ ⦾ ⦿ ⧶ ⧷ ⨇ ⨰ ⨱ ⨲ ⨳ ⨴ ⨵ ⨶ ⨷ ⨸ ⨻ ⨼ ⨽ ⩀ ⩃ ⩄ ⩋ ⩍ ⩎ ⩑ ⩓ ⩕ ⩘ ⩚ ⩜ ⩞ ⩟ ⩠ ⫛ ⊍ ▷ ⨝ ⟕ ⟖ ⟗ 像 + 一样解析的包括 + - |\\|| ⊕ ⊖ ⊞ ⊟ |++| ∪ ∨ ⊔ ± ∓ ∔ ∸ ≏ ⊎ ⊻ ⊽ ⋎ ⋓ ⧺ ⧻ ⨈ ⨢ ⨣ ⨤ ⨥ ⨦ ⨧ ⨨ ⨩ ⨪ ⨫ ⨬ ⨭ ⨮ ⨹ ⨺ ⩁ ⩂ ⩅ ⩊ ⩌ ⩏ ⩐ ⩒ ⩔ ⩖ ⩗ ⩛ ⩝ ⩡ ⩢ ⩣ 还有许多其他的与箭头、比较和幂相关的符号。","category":"page"},{"location":"stdlib/Markdown/#markdown_stdlib","page":"Markdown","title":"Markdown","text":"","category":"section"},{"location":"stdlib/Markdown/","page":"Markdown","title":"Markdown","text":"本节描述 Julia 的 markdown 语法,它是由 Markdown 标准库启用的。它支持以下的 Markdown 元素:","category":"page"},{"location":"stdlib/Markdown/#内联元素","page":"Markdown","title":"内联元素","text":"","category":"section"},{"location":"stdlib/Markdown/","page":"Markdown","title":"Markdown","text":"此处的“内联”指可以在段落中找到的元素。包括下面的元素。","category":"page"},{"location":"stdlib/Markdown/#粗体","page":"Markdown","title":"粗体","text":"","category":"section"},{"location":"stdlib/Markdown/","page":"Markdown","title":"Markdown","text":"用两个 ** 包围来将其内部的文本显示为粗体。","category":"page"},{"location":"stdlib/Markdown/","page":"Markdown","title":"Markdown","text":"A paragraph containing a **bold** word.","category":"page"},{"location":"stdlib/Markdown/#斜体","page":"Markdown","title":"斜体","text":"","category":"section"},{"location":"stdlib/Markdown/","page":"Markdown","title":"Markdown","text":"用单个 * 包围来将其内部的文本显示为斜体。","category":"page"},{"location":"stdlib/Markdown/","page":"Markdown","title":"Markdown","text":"A paragraph containing an *italicized* word.","category":"page"},{"location":"stdlib/Markdown/#文字","page":"Markdown","title":"文字","text":"","category":"section"},{"location":"stdlib/Markdown/","page":"Markdown","title":"Markdown","text":"用一个重音符号 ` 包围的文本将会原封不动地显示出来。","category":"page"},{"location":"stdlib/Markdown/","page":"Markdown","title":"Markdown","text":"A paragraph containing a `literal` word.","category":"page"},{"location":"stdlib/Markdown/","page":"Markdown","title":"Markdown","text":"当文本指代变量名、函数名或者 Julia 程序的其他部分时,应当使用字面量。","category":"page"},{"location":"stdlib/Markdown/","page":"Markdown","title":"Markdown","text":"tip: Tip\n为了在字面量中包含一个重音符,需要使用三个重音符而不是一个来包围文本。A paragraph containing ``` `backtick` characters ```.通过扩展,可以使用任何奇数个反引号来包围较少数量的反引号。","category":"page"},{"location":"stdlib/Markdown/#\\LaTeX","page":"Markdown","title":"LaTeX","text":"","category":"section"},{"location":"stdlib/Markdown/","page":"Markdown","title":"Markdown","text":"使用两个重音符的 LaTeX 语法来包围那些是数学表达式的文本, `` .","category":"page"},{"location":"stdlib/Markdown/","page":"Markdown","title":"Markdown","text":"A paragraph containing some ``\\LaTeX`` markup.","category":"page"},{"location":"stdlib/Markdown/","page":"Markdown","title":"Markdown","text":"tip: Tip\nAs with literals in the previous section, if literal backticks need to be written within double backticks use an even number greater than two. Note that if a single literal backtick needs to be included within LaTeX markup then two enclosing backticks is sufficient.","category":"page"},{"location":"stdlib/Markdown/","page":"Markdown","title":"Markdown","text":"note: Note\nThe \\ character should be escaped appropriately if the text is embedded in a Julia source code, for example, \"``\\\\LaTeX`` syntax in a docstring.\", since it is interpreted as a string literal. Alternatively, in order to avoid escaping, it is possible to use the raw string macro together with the @doc macro:@doc raw\"``\\LaTeX`` syntax in a docstring.\" functionname","category":"page"},{"location":"stdlib/Markdown/#Links","page":"Markdown","title":"Links","text":"","category":"section"},{"location":"stdlib/Markdown/","page":"Markdown","title":"Markdown","text":"Links to either external or internal targets can be written using the following syntax, where the text enclosed in square brackets, [ ], is the name of the link and the text enclosed in parentheses, ( ), is the URL.","category":"page"},{"location":"stdlib/Markdown/","page":"Markdown","title":"Markdown","text":"A paragraph containing a link to [Julia](http://www.julialang.org).","category":"page"},{"location":"stdlib/Markdown/","page":"Markdown","title":"Markdown","text":"It's also possible to add cross-references to other documented functions/methods/variables within the Julia documentation itself. For example:","category":"page"},{"location":"stdlib/Markdown/","page":"Markdown","title":"Markdown","text":"\"\"\"\n tryparse(type, str; base)\n\nLike [`parse`](@ref), but returns either a value of the requested type,\nor [`nothing`](@ref) if the string does not contain a valid number.\n\"\"\"","category":"page"},{"location":"stdlib/Markdown/","page":"Markdown","title":"Markdown","text":"This will create a link in the generated docs to the parse documentation (which has more information about what this function actually does), and to the nothing documentation. It's good to include cross references to mutating/non-mutating versions of a function, or to highlight a difference between two similar-seeming functions.","category":"page"},{"location":"stdlib/Markdown/","page":"Markdown","title":"Markdown","text":"note: Note\nThe above cross referencing is not a Markdown feature, and relies on Documenter.jl, which is used to build base Julia's documentation.","category":"page"},{"location":"stdlib/Markdown/#Footnote-references","page":"Markdown","title":"Footnote references","text":"","category":"section"},{"location":"stdlib/Markdown/","page":"Markdown","title":"Markdown","text":"Named and numbered footnote references can be written using the following syntax. A footnote name must be a single alphanumeric word containing no punctuation.","category":"page"},{"location":"stdlib/Markdown/","page":"Markdown","title":"Markdown","text":"A paragraph containing a numbered footnote [^1] and a named one [^named].","category":"page"},{"location":"stdlib/Markdown/","page":"Markdown","title":"Markdown","text":"note: Note\nThe text associated with a footnote can be written anywhere within the same page as the footnote reference. The syntax used to define the footnote text is discussed in the Footnotes section below.","category":"page"},{"location":"stdlib/Markdown/#Toplevel-elements","page":"Markdown","title":"Toplevel elements","text":"","category":"section"},{"location":"stdlib/Markdown/","page":"Markdown","title":"Markdown","text":"The following elements can be written either at the \"toplevel\" of a document or within another \"toplevel\" element.","category":"page"},{"location":"stdlib/Markdown/#Paragraphs","page":"Markdown","title":"Paragraphs","text":"","category":"section"},{"location":"stdlib/Markdown/","page":"Markdown","title":"Markdown","text":"A paragraph is a block of plain text, possibly containing any number of inline elements defined in the Inline elements section above, with one or more blank lines above and below it.","category":"page"},{"location":"stdlib/Markdown/","page":"Markdown","title":"Markdown","text":"This is a paragraph.\n\nAnd this is *another* paragraph containing some emphasized text.\nA new line, but still part of the same paragraph.","category":"page"},{"location":"stdlib/Markdown/#Headers","page":"Markdown","title":"Headers","text":"","category":"section"},{"location":"stdlib/Markdown/","page":"Markdown","title":"Markdown","text":"A document can be split up into different sections using headers. Headers use the following syntax:","category":"page"},{"location":"stdlib/Markdown/","page":"Markdown","title":"Markdown","text":"# Level One\n## Level Two\n### Level Three\n#### Level Four\n##### Level Five\n###### Level Six","category":"page"},{"location":"stdlib/Markdown/","page":"Markdown","title":"Markdown","text":"A header line can contain any inline syntax in the same way as a paragraph can.","category":"page"},{"location":"stdlib/Markdown/","page":"Markdown","title":"Markdown","text":"tip: Tip\nTry to avoid using too many levels of header within a single document. A heavily nested document may be indicative of a need to restructure it or split it into several pages covering separate topics.","category":"page"},{"location":"stdlib/Markdown/#Code-blocks","page":"Markdown","title":"Code blocks","text":"","category":"section"},{"location":"stdlib/Markdown/","page":"Markdown","title":"Markdown","text":"Source code can be displayed as a literal block using an indent of four spaces as shown in the following example.","category":"page"},{"location":"stdlib/Markdown/","page":"Markdown","title":"Markdown","text":"This is a paragraph.\n\n function func(x)\n # ...\n end\n\nAnother paragraph.","category":"page"},{"location":"stdlib/Markdown/","page":"Markdown","title":"Markdown","text":"Additionally, code blocks can be enclosed using triple backticks with an optional \"language\" to specify how a block of code should be highlighted.","category":"page"},{"location":"stdlib/Markdown/","page":"Markdown","title":"Markdown","text":"A code block without a \"language\":\n\n```\nfunction func(x)\n # ...\nend\n```\n\nand another one with the \"language\" specified as `julia`:\n\n```julia\nfunction func(x)\n # ...\nend\n```","category":"page"},{"location":"stdlib/Markdown/","page":"Markdown","title":"Markdown","text":"note: Note\n\"Fenced\" code blocks, as shown in the last example, should be preferred over indented code blocks since there is no way to specify what language an indented code block is written in.","category":"page"},{"location":"stdlib/Markdown/#Block-quotes","page":"Markdown","title":"Block quotes","text":"","category":"section"},{"location":"stdlib/Markdown/","page":"Markdown","title":"Markdown","text":"Text from external sources, such as quotations from books or websites, can be quoted using > characters prepended to each line of the quote as follows.","category":"page"},{"location":"stdlib/Markdown/","page":"Markdown","title":"Markdown","text":"Here's a quote:\n\n> Julia is a high-level, high-performance dynamic programming language for\n> technical computing, with syntax that is familiar to users of other\n> technical computing environments.","category":"page"},{"location":"stdlib/Markdown/","page":"Markdown","title":"Markdown","text":"Note that a single space must appear after the > character on each line. Quoted blocks may themselves contain other toplevel or inline elements.","category":"page"},{"location":"stdlib/Markdown/#Images","page":"Markdown","title":"Images","text":"","category":"section"},{"location":"stdlib/Markdown/","page":"Markdown","title":"Markdown","text":"The syntax for images is similar to the link syntax mentioned above. Prepending a ! character to a link will display an image from the specified URL rather than a link to it.","category":"page"},{"location":"stdlib/Markdown/","page":"Markdown","title":"Markdown","text":"![alternative text](link/to/image.png)","category":"page"},{"location":"stdlib/Markdown/#Lists","page":"Markdown","title":"Lists","text":"","category":"section"},{"location":"stdlib/Markdown/","page":"Markdown","title":"Markdown","text":"Unordered lists can be written by prepending each item in a list with either *, +, or -.","category":"page"},{"location":"stdlib/Markdown/","page":"Markdown","title":"Markdown","text":"A list of items:\n\n * item one\n * item two\n * item three","category":"page"},{"location":"stdlib/Markdown/","page":"Markdown","title":"Markdown","text":"Note the two spaces before each * and the single space after each one.","category":"page"},{"location":"stdlib/Markdown/","page":"Markdown","title":"Markdown","text":"Lists can contain other nested toplevel elements such as lists, code blocks, or quoteblocks. A blank line should be left between each list item when including any toplevel elements within a list.","category":"page"},{"location":"stdlib/Markdown/","page":"Markdown","title":"Markdown","text":"Another list:\n\n * item one\n\n * item two\n\n ```\n f(x) = x\n ```\n\n * And a sublist:\n\n + sub-item one\n + sub-item two","category":"page"},{"location":"stdlib/Markdown/","page":"Markdown","title":"Markdown","text":"note: Note\nThe contents of each item in the list must line up with the first line of the item. In the above example the fenced code block must be indented by four spaces to align with the i in item two.","category":"page"},{"location":"stdlib/Markdown/","page":"Markdown","title":"Markdown","text":"Ordered lists are written by replacing the \"bullet\" character, either *, +, or -, with a positive integer followed by either . or ).","category":"page"},{"location":"stdlib/Markdown/","page":"Markdown","title":"Markdown","text":"Two ordered lists:\n\n 1. item one\n 2. item two\n 3. item three\n\n 5) item five\n 6) item six\n 7) item seven","category":"page"},{"location":"stdlib/Markdown/","page":"Markdown","title":"Markdown","text":"An ordered list may start from a number other than one, as in the second list of the above example, where it is numbered from five. As with unordered lists, ordered lists can contain nested toplevel elements.","category":"page"},{"location":"stdlib/Markdown/#Display-equations","page":"Markdown","title":"Display equations","text":"","category":"section"},{"location":"stdlib/Markdown/","page":"Markdown","title":"Markdown","text":"Large LaTeX equations that do not fit inline within a paragraph may be written as display equations using a fenced code block with the \"language\" math as in the example below.","category":"page"},{"location":"stdlib/Markdown/","page":"Markdown","title":"Markdown","text":"```math\nf(a) = \\frac{1}{2\\pi}\\int_{0}^{2\\pi} (\\alpha+R\\cos(\\theta))d\\theta\n```","category":"page"},{"location":"stdlib/Markdown/#Footnotes","page":"Markdown","title":"Footnotes","text":"","category":"section"},{"location":"stdlib/Markdown/","page":"Markdown","title":"Markdown","text":"This syntax is paired with the inline syntax for Footnote references. Make sure to read that section as well.","category":"page"},{"location":"stdlib/Markdown/","page":"Markdown","title":"Markdown","text":"Footnote text is defined using the following syntax, which is similar to footnote reference syntax, aside from the : character that is appended to the footnote label.","category":"page"},{"location":"stdlib/Markdown/","page":"Markdown","title":"Markdown","text":"[^1]: Numbered footnote text.\n\n[^note]:\n\n Named footnote text containing several toplevel elements.\n\n * item one\n * item two\n * item three\n\n ```julia\n function func(x)\n # ...\n end\n ```","category":"page"},{"location":"stdlib/Markdown/","page":"Markdown","title":"Markdown","text":"note: Note\nNo checks are done during parsing to make sure that all footnote references have matching footnotes.","category":"page"},{"location":"stdlib/Markdown/#Horizontal-rules","page":"Markdown","title":"Horizontal rules","text":"","category":"section"},{"location":"stdlib/Markdown/","page":"Markdown","title":"Markdown","text":"The equivalent of an
        HTML tag can be achieved using three hyphens (---). For example:","category":"page"},{"location":"stdlib/Markdown/","page":"Markdown","title":"Markdown","text":"Text above the line.\n\n---\n\nAnd text below the line.","category":"page"},{"location":"stdlib/Markdown/#Tables","page":"Markdown","title":"Tables","text":"","category":"section"},{"location":"stdlib/Markdown/","page":"Markdown","title":"Markdown","text":"Basic tables can be written using the syntax described below. Note that markdown tables have limited features and cannot contain nested toplevel elements unlike other elements discussed above – only inline elements are allowed. Tables must always contain a header row with column names. Cells cannot span multiple rows or columns of the table.","category":"page"},{"location":"stdlib/Markdown/","page":"Markdown","title":"Markdown","text":"| Column One | Column Two | Column Three |\n|:---------- | ---------- |:------------:|\n| Row `1` | Column `2` | |\n| *Row* 2 | **Row** 2 | Column ``3`` |","category":"page"},{"location":"stdlib/Markdown/","page":"Markdown","title":"Markdown","text":"note: Note\nAs illustrated in the above example each column of | characters must be aligned vertically.A : character on either end of a column's header separator (the row containing - characters) specifies whether the row is left-aligned, right-aligned, or (when : appears on both ends) center-aligned. Providing no : characters will default to right-aligning the column.","category":"page"},{"location":"stdlib/Markdown/#Admonitions","page":"Markdown","title":"Admonitions","text":"","category":"section"},{"location":"stdlib/Markdown/","page":"Markdown","title":"Markdown","text":"Specially formatted blocks, known as admonitions, can be used to highlight particular remarks. They can be defined using the following !!! syntax:","category":"page"},{"location":"stdlib/Markdown/","page":"Markdown","title":"Markdown","text":"!!! note\n\n This is the content of the note.\n\n!!! warning \"Beware!\"\n\n And this is another one.\n\n This warning admonition has a custom title: `\"Beware!\"`.","category":"page"},{"location":"stdlib/Markdown/","page":"Markdown","title":"Markdown","text":"The first word after !!! declares the type of the admonition. There are standard admonition types that should produce special styling. Namely (in order of decreasing severity): danger, warning, info/note, and tip.","category":"page"},{"location":"stdlib/Markdown/","page":"Markdown","title":"Markdown","text":"You can also use your own admonition types, as long as the type name only contains lowercase Latin characters (a-z). For example, you could have a terminology block like this:","category":"page"},{"location":"stdlib/Markdown/","page":"Markdown","title":"Markdown","text":"!!! terminology \"julia vs Julia\"\n\n Strictly speaking, \"Julia\" refers to the language,\n and \"julia\" to the standard implementation.","category":"page"},{"location":"stdlib/Markdown/","page":"Markdown","title":"Markdown","text":"However, unless the code rendering the Markdown special-cases that particular admonition type, it will get the default styling.","category":"page"},{"location":"stdlib/Markdown/","page":"Markdown","title":"Markdown","text":"A custom title for the box can be provided as a string (in double quotes) after the admonition type. If no title text is specified after the admonition type, then the type name will be used as the title (e.g. \"Note\" for the note admonition).","category":"page"},{"location":"stdlib/Markdown/","page":"Markdown","title":"Markdown","text":"Admonitions, like most other toplevel elements, can contain other toplevel elements (e.g. lists, images).","category":"page"},{"location":"stdlib/Markdown/#Markdown-Syntax-Extensions","page":"Markdown","title":"Markdown Syntax Extensions","text":"","category":"section"},{"location":"stdlib/Markdown/","page":"Markdown","title":"Markdown","text":"Julia's markdown supports interpolation in a very similar way to basic string literals, with the difference that it will store the object itself in the Markdown tree (as opposed to converting it to a string). When the Markdown content is rendered the usual show methods will be called, and these can be overridden as usual. This design allows the Markdown to be extended with arbitrarily complex features (such as references) without cluttering the basic syntax.","category":"page"},{"location":"stdlib/Markdown/","page":"Markdown","title":"Markdown","text":"In principle, the Markdown parser itself can also be arbitrarily extended by packages, or an entirely custom flavour of Markdown can be used, but this should generally be unnecessary.","category":"page"},{"location":"devdocs/subarrays/#子数组","page":"子数组","title":"子数组","text":"","category":"section"},{"location":"devdocs/subarrays/","page":"子数组","title":"子数组","text":"Julia 的 SubArray 类型是编码父类型 AbstractArray 的“视图”的一个容器。本页介绍了 SubArray 的一些设计原则和实现。","category":"page"},{"location":"devdocs/subarrays/","page":"子数组","title":"子数组","text":"One of the major design goals is to ensure high performance for views of both IndexLinear and IndexCartesian arrays. Furthermore, views of IndexLinear arrays should themselves be IndexLinear to the extent that it is possible.","category":"page"},{"location":"devdocs/subarrays/#Index-replacement","page":"子数组","title":"Index replacement","text":"","category":"section"},{"location":"devdocs/subarrays/","page":"子数组","title":"子数组","text":"Consider making 2d slices of a 3d array:","category":"page"},{"location":"devdocs/subarrays/","page":"子数组","title":"子数组","text":"DocTestSetup = :(import Random; Random.seed!(1234))","category":"page"},{"location":"devdocs/subarrays/","page":"子数组","title":"子数组","text":"julia> A = rand(2,3,4);\n\njulia> S1 = view(A, :, 1, 2:3)\n2×2 view(::Array{Float64, 3}, :, 1, 2:3) with eltype Float64:\n 0.342284 0.831961\n 0.237287 0.435938\n\njulia> S2 = view(A, 1, :, 2:3)\n3×2 view(::Array{Float64, 3}, 1, :, 2:3) with eltype Float64:\n 0.342284 0.831961\n 0.988944 0.927795\n 0.178426 0.404876","category":"page"},{"location":"devdocs/subarrays/","page":"子数组","title":"子数组","text":"DocTestSetup = nothing","category":"page"},{"location":"devdocs/subarrays/","page":"子数组","title":"子数组","text":"view drops \"singleton\" dimensions (ones that are specified by an Int), so both S1 and S2 are two-dimensional SubArrays. Consequently, the natural way to index these is with S1[i,j]. To extract the value from the parent array A, the natural approach is to replace S1[i,j] with A[i,1,(2:3)[j]] and S2[i,j] with A[1,i,(2:3)[j]].","category":"page"},{"location":"devdocs/subarrays/","page":"子数组","title":"子数组","text":"The key feature of the design of SubArrays is that this index replacement can be performed without any runtime overhead.","category":"page"},{"location":"devdocs/subarrays/#SubArray-design","page":"子数组","title":"SubArray design","text":"","category":"section"},{"location":"devdocs/subarrays/#Type-parameters-and-fields","page":"子数组","title":"Type parameters and fields","text":"","category":"section"},{"location":"devdocs/subarrays/","page":"子数组","title":"子数组","text":"The strategy adopted is first and foremost expressed in the definition of the type:","category":"page"},{"location":"devdocs/subarrays/","page":"子数组","title":"子数组","text":"struct SubArray{T,N,P,I,L} <: AbstractArray{T,N}\n parent::P\n indices::I\n offset1::Int # for linear indexing and pointer, only valid when L==true\n stride1::Int # used only for linear indexing\n ...\nend","category":"page"},{"location":"devdocs/subarrays/","page":"子数组","title":"子数组","text":"SubArray has 5 type parameters. The first two are the standard element type and dimensionality. The next is the type of the parent AbstractArray. The most heavily-used is the fourth parameter, a Tuple of the types of the indices for each dimension. The final one, L, is only provided as a convenience for dispatch; it's a boolean that represents whether the index types support fast linear indexing. More on that later.","category":"page"},{"location":"devdocs/subarrays/","page":"子数组","title":"子数组","text":"If in our example above A is a Array{Float64, 3}, our S1 case above would be a SubArray{Float64,2,Array{Float64,3},Tuple{Base.Slice{Base.OneTo{Int64}},Int64,UnitRange{Int64}},false}. Note in particular the tuple parameter, which stores the types of the indices used to create S1. Likewise,","category":"page"},{"location":"devdocs/subarrays/","page":"子数组","title":"子数组","text":"julia> S1.indices\n(Base.Slice(Base.OneTo(2)), 1, 2:3)","category":"page"},{"location":"devdocs/subarrays/","page":"子数组","title":"子数组","text":"Storing these values allows index replacement, and having the types encoded as parameters allows one to dispatch to efficient algorithms.","category":"page"},{"location":"devdocs/subarrays/#Index-translation","page":"子数组","title":"Index translation","text":"","category":"section"},{"location":"devdocs/subarrays/","page":"子数组","title":"子数组","text":"Performing index translation requires that you do different things for different concrete SubArray types. For example, for S1, one needs to apply the i,j indices to the first and third dimensions of the parent array, whereas for S2 one needs to apply them to the second and third. The simplest approach to indexing would be to do the type-analysis at runtime:","category":"page"},{"location":"devdocs/subarrays/","page":"子数组","title":"子数组","text":"parentindices = Vector{Any}()\nfor thisindex in S.indices\n ...\n if isa(thisindex, Int)\n # Don't consume one of the input indices\n push!(parentindices, thisindex)\n elseif isa(thisindex, AbstractVector)\n # Consume an input index\n push!(parentindices, thisindex[inputindex[j]])\n j += 1\n elseif isa(thisindex, AbstractMatrix)\n # Consume two input indices\n push!(parentindices, thisindex[inputindex[j], inputindex[j+1]])\n j += 2\n elseif ...\nend\nS.parent[parentindices...]","category":"page"},{"location":"devdocs/subarrays/","page":"子数组","title":"子数组","text":"Unfortunately, this would be disastrous in terms of performance: each element access would allocate memory, and involves the running of a lot of poorly-typed code.","category":"page"},{"location":"devdocs/subarrays/","page":"子数组","title":"子数组","text":"The better approach is to dispatch to specific methods to handle each type of stored index. That's what reindex does: it dispatches on the type of the first stored index and consumes the appropriate number of input indices, and then it recurses on the remaining indices. In the case of S1, this expands to","category":"page"},{"location":"devdocs/subarrays/","page":"子数组","title":"子数组","text":"Base.reindex(S1, S1.indices, (i, j)) == (i, S1.indices[2], S1.indices[3][j])","category":"page"},{"location":"devdocs/subarrays/","page":"子数组","title":"子数组","text":"for any pair of indices (i,j) (except CartesianIndexs and arrays thereof, see below).","category":"page"},{"location":"devdocs/subarrays/","page":"子数组","title":"子数组","text":"This is the core of a SubArray; indexing methods depend upon reindex to do this index translation. Sometimes, though, we can avoid the indirection and make it even faster.","category":"page"},{"location":"devdocs/subarrays/#Linear-indexing","page":"子数组","title":"Linear indexing","text":"","category":"section"},{"location":"devdocs/subarrays/","page":"子数组","title":"子数组","text":"Linear indexing can be implemented efficiently when the entire array has a single stride that separates successive elements, starting from some offset. This means that we can pre-compute these values and represent linear indexing simply as an addition and multiplication, avoiding the indirection of reindex and (more importantly) the slow computation of the cartesian coordinates entirely.","category":"page"},{"location":"devdocs/subarrays/","page":"子数组","title":"子数组","text":"For SubArray types, the availability of efficient linear indexing is based purely on the types of the indices, and does not depend on values like the size of the parent array. You can ask whether a given set of indices supports fast linear indexing with the internal Base.viewindexing function:","category":"page"},{"location":"devdocs/subarrays/","page":"子数组","title":"子数组","text":"julia> Base.viewindexing(S1.indices)\nIndexCartesian()\n\njulia> Base.viewindexing(S2.indices)\nIndexLinear()","category":"page"},{"location":"devdocs/subarrays/","page":"子数组","title":"子数组","text":"This is computed during construction of the SubArray and stored in the L type parameter as a boolean that encodes fast linear indexing support. While not strictly necessary, it means that we can define dispatch directly on SubArray{T,N,A,I,true} without any intermediaries.","category":"page"},{"location":"devdocs/subarrays/","page":"子数组","title":"子数组","text":"Since this computation doesn't depend on runtime values, it can miss some cases in which the stride happens to be uniform:","category":"page"},{"location":"devdocs/subarrays/","page":"子数组","title":"子数组","text":"julia> A = reshape(1:4*2, 4, 2)\n4×2 reshape(::UnitRange{Int64}, 4, 2) with eltype Int64:\n 1 5\n 2 6\n 3 7\n 4 8\n\njulia> diff(A[2:2:4,:][:])\n3-element Vector{Int64}:\n 2\n 2\n 2","category":"page"},{"location":"devdocs/subarrays/","page":"子数组","title":"子数组","text":"A view constructed as view(A, 2:2:4, :) happens to have uniform stride, and therefore linear indexing indeed could be performed efficiently. However, success in this case depends on the size of the array: if the first dimension instead were odd,","category":"page"},{"location":"devdocs/subarrays/","page":"子数组","title":"子数组","text":"julia> A = reshape(1:5*2, 5, 2)\n5×2 reshape(::UnitRange{Int64}, 5, 2) with eltype Int64:\n 1 6\n 2 7\n 3 8\n 4 9\n 5 10\n\njulia> diff(A[2:2:4,:][:])\n3-element Vector{Int64}:\n 2\n 3\n 2","category":"page"},{"location":"devdocs/subarrays/","page":"子数组","title":"子数组","text":"then A[2:2:4,:] does not have uniform stride, so we cannot guarantee efficient linear indexing. Since we have to base this decision based purely on types encoded in the parameters of the SubArray, S = view(A, 2:2:4, :) cannot implement efficient linear indexing.","category":"page"},{"location":"devdocs/subarrays/#A-few-details","page":"子数组","title":"A few details","text":"","category":"section"},{"location":"devdocs/subarrays/","page":"子数组","title":"子数组","text":"Note that the Base.reindex function is agnostic to the types of the input indices; it simply determines how and where the stored indices should be reindexed. It not only supports integer indices, but it supports non-scalar indexing, too. This means that views of views don't need two levels of indirection; they can simply re-compute the indices into the original parent array!\nHopefully by now it's fairly clear that supporting slices means that the dimensionality, given by the parameter N, is not necessarily equal to the dimensionality of the parent array or the length of the indices tuple. Neither do user-supplied indices necessarily line up with entries in the indices tuple (e.g., the second user-supplied index might correspond to the third dimension of the parent array, and the third element in the indices tuple).\nWhat might be less obvious is that the dimensionality of the stored parent array must be equal to the number of effective indices in the indices tuple. Some examples:\nA = reshape(1:35, 5, 7) # A 2d parent Array\nS = view(A, 2:7) # A 1d view created by linear indexing\nS = view(A, :, :, 1:1) # Appending extra indices is supported\nNaively, you'd think you could just set S.parent = A and S.indices = (:,:,1:1), but supporting this dramatically complicates the reindexing process, especially for views of views. Not only do you need to dispatch on the types of the stored indices, but you need to examine whether a given index is the final one and \"merge\" any remaining stored indices together. This is not an easy task, and even worse: it's slow since it implicitly depends upon linear indexing.\nFortunately, this is precisely the computation that ReshapedArray performs, and it does so linearly if possible. Consequently, view ensures that the parent array is the appropriate dimensionality for the given indices by reshaping it if needed. The inner SubArray constructor ensures that this invariant is satisfied.\nCartesianIndex and arrays thereof throw a nasty wrench into the reindex scheme. Recall that reindex simply dispatches on the type of the stored indices in order to determine how many passed indices should be used and where they should go. But with CartesianIndex, there's no longer a one-to-one correspondence between the number of passed arguments and the number of dimensions that they index into. If we return to the above example of Base.reindex(S1, S1.indices, (i, j)), you can see that the expansion is incorrect for i, j = CartesianIndex(), CartesianIndex(2,1). It should skip the CartesianIndex() entirely and return:\n(CartesianIndex(2,1)[1], S1.indices[2], S1.indices[3][CartesianIndex(2,1)[2]])\nInstead, though, we get:\n(CartesianIndex(), S1.indices[2], S1.indices[3][CartesianIndex(2,1)])\nDoing this correctly would require combined dispatch on both the stored and passed indices across all combinations of dimensionalities in an intractable manner. As such, reindex must never be called with CartesianIndex indices. Fortunately, the scalar case is easily handled by first flattening the CartesianIndex arguments to plain integers. Arrays of CartesianIndex, however, cannot be split apart into orthogonal pieces so easily. Before attempting to use reindex, view must ensure that there are no arrays of CartesianIndex in the argument list. If there are, it can simply \"punt\" by avoiding the reindex calculation entirely, constructing a nested SubArray with two levels of indirection instead.","category":"page"},{"location":"devdocs/object/#Memory-layout-of-Julia-Objects","page":"Memory layout of Julia Objects","title":"Memory layout of Julia Objects","text":"","category":"section"},{"location":"devdocs/object/#Object-layout-(jl_value_t)","page":"Memory layout of Julia Objects","title":"Object layout (jl_value_t)","text":"","category":"section"},{"location":"devdocs/object/","page":"Memory layout of Julia Objects","title":"Memory layout of Julia Objects","text":"The jl_value_t struct is the name for a block of memory owned by the Julia Garbage Collector, representing the data associated with a Julia object in memory. Absent any type information, it is simply an opaque pointer:","category":"page"},{"location":"devdocs/object/","page":"Memory layout of Julia Objects","title":"Memory layout of Julia Objects","text":"typedef struct jl_value_t* jl_pvalue_t;","category":"page"},{"location":"devdocs/object/","page":"Memory layout of Julia Objects","title":"Memory layout of Julia Objects","text":"Each jl_value_t struct is contained in a jl_typetag_t struct that contains metadata information about the Julia object, such as its type and garbage collector (gc) reachability:","category":"page"},{"location":"devdocs/object/","page":"Memory layout of Julia Objects","title":"Memory layout of Julia Objects","text":"typedef struct {\n opaque metadata;\n jl_value_t value;\n} jl_typetag_t;","category":"page"},{"location":"devdocs/object/","page":"Memory layout of Julia Objects","title":"Memory layout of Julia Objects","text":"The type of any Julia object is an instance of a leaf jl_datatype_t object. The jl_typeof() function can be used to query for it:","category":"page"},{"location":"devdocs/object/","page":"Memory layout of Julia Objects","title":"Memory layout of Julia Objects","text":"jl_value_t *jl_typeof(jl_value_t *v);","category":"page"},{"location":"devdocs/object/","page":"Memory layout of Julia Objects","title":"Memory layout of Julia Objects","text":"The layout of the object depends on its type. Reflection methods can be used to inspect that layout. A field can be accessed by calling one of the get-field methods:","category":"page"},{"location":"devdocs/object/","page":"Memory layout of Julia Objects","title":"Memory layout of Julia Objects","text":"jl_value_t *jl_get_nth_field_checked(jl_value_t *v, size_t i);\njl_value_t *jl_get_field(jl_value_t *o, char *fld);","category":"page"},{"location":"devdocs/object/","page":"Memory layout of Julia Objects","title":"Memory layout of Julia Objects","text":"If the field types are known, a priori, to be all pointers, the values can also be extracted directly as an array access:","category":"page"},{"location":"devdocs/object/","page":"Memory layout of Julia Objects","title":"Memory layout of Julia Objects","text":"jl_value_t *v = value->fieldptr[n];","category":"page"},{"location":"devdocs/object/","page":"Memory layout of Julia Objects","title":"Memory layout of Julia Objects","text":"As an example, a \"boxed\" uint16_t is stored as follows:","category":"page"},{"location":"devdocs/object/","page":"Memory layout of Julia Objects","title":"Memory layout of Julia Objects","text":"struct {\n opaque metadata;\n struct {\n uint16_t data; // -- 2 bytes\n } jl_value_t;\n};","category":"page"},{"location":"devdocs/object/","page":"Memory layout of Julia Objects","title":"Memory layout of Julia Objects","text":"This object is created by jl_box_uint16(). Note that the jl_value_t pointer references the data portion, not the metadata at the top of the struct.","category":"page"},{"location":"devdocs/object/","page":"Memory layout of Julia Objects","title":"Memory layout of Julia Objects","text":"A value may be stored \"unboxed\" in many circumstances (just the data, without the metadata, and possibly not even stored but just kept in registers), so it is unsafe to assume that the address of a box is a unique identifier. The \"egal\" test (corresponding to the === function in Julia), should instead be used to compare two unknown objects for equivalence:","category":"page"},{"location":"devdocs/object/","page":"Memory layout of Julia Objects","title":"Memory layout of Julia Objects","text":"int jl_egal(jl_value_t *a, jl_value_t *b);","category":"page"},{"location":"devdocs/object/","page":"Memory layout of Julia Objects","title":"Memory layout of Julia Objects","text":"This optimization should be relatively transparent to the API, since the object will be \"boxed\" on-demand, whenever a jl_value_t pointer is needed.","category":"page"},{"location":"devdocs/object/","page":"Memory layout of Julia Objects","title":"Memory layout of Julia Objects","text":"Note that modification of a jl_value_t pointer in memory is permitted only if the object is mutable. Otherwise, modification of the value may corrupt the program and the result will be undefined. The mutability property of a value can be queried for with:","category":"page"},{"location":"devdocs/object/","page":"Memory layout of Julia Objects","title":"Memory layout of Julia Objects","text":"int jl_is_mutable(jl_value_t *v);","category":"page"},{"location":"devdocs/object/","page":"Memory layout of Julia Objects","title":"Memory layout of Julia Objects","text":"If the object being stored is a jl_value_t, the Julia garbage collector must be notified also:","category":"page"},{"location":"devdocs/object/","page":"Memory layout of Julia Objects","title":"Memory layout of Julia Objects","text":"void jl_gc_wb(jl_value_t *parent, jl_value_t *ptr);","category":"page"},{"location":"devdocs/object/","page":"Memory layout of Julia Objects","title":"Memory layout of Julia Objects","text":"However, the Embedding Julia section of the manual is also required reading at this point, for covering other details of boxing and unboxing various types, and understanding the gc interactions.","category":"page"},{"location":"devdocs/object/","page":"Memory layout of Julia Objects","title":"Memory layout of Julia Objects","text":"Mirror structs for some of the built-in types are defined in julia.h. The corresponding global jl_datatype_t objects are created by jl_init_types in jltypes.c.","category":"page"},{"location":"devdocs/object/#Garbage-collector-mark-bits","page":"Memory layout of Julia Objects","title":"Garbage collector mark bits","text":"","category":"section"},{"location":"devdocs/object/","page":"Memory layout of Julia Objects","title":"Memory layout of Julia Objects","text":"The garbage collector uses several bits from the metadata portion of the jl_typetag_t to track each object in the system. Further details about this algorithm can be found in the comments of the garbage collector implementation in gc.c.","category":"page"},{"location":"devdocs/object/#Object-allocation","page":"Memory layout of Julia Objects","title":"Object allocation","text":"","category":"section"},{"location":"devdocs/object/","page":"Memory layout of Julia Objects","title":"Memory layout of Julia Objects","text":"Most new objects are allocated by jl_new_structv():","category":"page"},{"location":"devdocs/object/","page":"Memory layout of Julia Objects","title":"Memory layout of Julia Objects","text":"jl_value_t *jl_new_struct(jl_datatype_t *type, ...);\njl_value_t *jl_new_structv(jl_datatype_t *type, jl_value_t **args, uint32_t na);","category":"page"},{"location":"devdocs/object/","page":"Memory layout of Julia Objects","title":"Memory layout of Julia Objects","text":"Although, isbits objects can be also constructed directly from memory:","category":"page"},{"location":"devdocs/object/","page":"Memory layout of Julia Objects","title":"Memory layout of Julia Objects","text":"jl_value_t *jl_new_bits(jl_value_t *bt, void *data)","category":"page"},{"location":"devdocs/object/","page":"Memory layout of Julia Objects","title":"Memory layout of Julia Objects","text":"And some objects have special constructors that must be used instead of the above functions:","category":"page"},{"location":"devdocs/object/","page":"Memory layout of Julia Objects","title":"Memory layout of Julia Objects","text":"Types:","category":"page"},{"location":"devdocs/object/","page":"Memory layout of Julia Objects","title":"Memory layout of Julia Objects","text":"jl_datatype_t *jl_apply_type(jl_datatype_t *tc, jl_tuple_t *params);\njl_datatype_t *jl_apply_array_type(jl_datatype_t *type, size_t dim);","category":"page"},{"location":"devdocs/object/","page":"Memory layout of Julia Objects","title":"Memory layout of Julia Objects","text":"While these are the most commonly used options, there are more low-level constructors too, which you can find declared in julia.h. These are used in jl_init_types() to create the initial types needed to bootstrap the creation of the Julia system image.","category":"page"},{"location":"devdocs/object/","page":"Memory layout of Julia Objects","title":"Memory layout of Julia Objects","text":"Tuples:","category":"page"},{"location":"devdocs/object/","page":"Memory layout of Julia Objects","title":"Memory layout of Julia Objects","text":"jl_tuple_t *jl_tuple(size_t n, ...);\njl_tuple_t *jl_tuplev(size_t n, jl_value_t **v);\njl_tuple_t *jl_alloc_tuple(size_t n);","category":"page"},{"location":"devdocs/object/","page":"Memory layout of Julia Objects","title":"Memory layout of Julia Objects","text":"The representation of tuples is highly unique in the Julia object representation ecosystem. In some cases, a Base.tuple() object may be an array of pointers to the objects contained by the tuple equivalent to:","category":"page"},{"location":"devdocs/object/","page":"Memory layout of Julia Objects","title":"Memory layout of Julia Objects","text":"typedef struct {\n size_t length;\n jl_value_t *data[length];\n} jl_tuple_t;","category":"page"},{"location":"devdocs/object/","page":"Memory layout of Julia Objects","title":"Memory layout of Julia Objects","text":"However, in other cases, the tuple may be converted to an anonymous isbits type and stored unboxed, or it may not stored at all (if it is not being used in a generic context as a jl_value_t*).","category":"page"},{"location":"devdocs/object/","page":"Memory layout of Julia Objects","title":"Memory layout of Julia Objects","text":"Symbols:","category":"page"},{"location":"devdocs/object/","page":"Memory layout of Julia Objects","title":"Memory layout of Julia Objects","text":"jl_sym_t *jl_symbol(const char *str);","category":"page"},{"location":"devdocs/object/","page":"Memory layout of Julia Objects","title":"Memory layout of Julia Objects","text":"Functions and MethodInstance:","category":"page"},{"location":"devdocs/object/","page":"Memory layout of Julia Objects","title":"Memory layout of Julia Objects","text":"jl_function_t *jl_new_generic_function(jl_sym_t *name);\njl_method_instance_t *jl_new_method_instance(jl_value_t *ast, jl_tuple_t *sparams);","category":"page"},{"location":"devdocs/object/","page":"Memory layout of Julia Objects","title":"Memory layout of Julia Objects","text":"Arrays:","category":"page"},{"location":"devdocs/object/","page":"Memory layout of Julia Objects","title":"Memory layout of Julia Objects","text":"jl_array_t *jl_new_array(jl_value_t *atype, jl_tuple_t *dims);\njl_array_t *jl_new_arrayv(jl_value_t *atype, ...);\njl_array_t *jl_alloc_array_1d(jl_value_t *atype, size_t nr);\njl_array_t *jl_alloc_array_2d(jl_value_t *atype, size_t nr, size_t nc);\njl_array_t *jl_alloc_array_3d(jl_value_t *atype, size_t nr, size_t nc, size_t z);\njl_array_t *jl_alloc_vec_any(size_t n);","category":"page"},{"location":"devdocs/object/","page":"Memory layout of Julia Objects","title":"Memory layout of Julia Objects","text":"Note that many of these have alternative allocation functions for various special-purposes. The list here reflects the more common usages, but a more complete list can be found by reading the julia.h header file.","category":"page"},{"location":"devdocs/object/","page":"Memory layout of Julia Objects","title":"Memory layout of Julia Objects","text":"Internal to Julia, storage is typically allocated by newstruct() (or newobj() for the special types):","category":"page"},{"location":"devdocs/object/","page":"Memory layout of Julia Objects","title":"Memory layout of Julia Objects","text":"jl_value_t *newstruct(jl_value_t *type);\njl_value_t *newobj(jl_value_t *type, size_t nfields);","category":"page"},{"location":"devdocs/object/","page":"Memory layout of Julia Objects","title":"Memory layout of Julia Objects","text":"And at the lowest level, memory is getting allocated by a call to the garbage collector (in gc.c), then tagged with its type:","category":"page"},{"location":"devdocs/object/","page":"Memory layout of Julia Objects","title":"Memory layout of Julia Objects","text":"jl_value_t *jl_gc_allocobj(size_t nbytes);\nvoid jl_set_typeof(jl_value_t *v, jl_datatype_t *type);","category":"page"},{"location":"devdocs/object/","page":"Memory layout of Julia Objects","title":"Memory layout of Julia Objects","text":"Note that all objects are allocated in multiples of 4 bytes and aligned to the platform pointer size. Memory is allocated from a pool for smaller objects, or directly with malloc() for large objects.","category":"page"},{"location":"devdocs/object/","page":"Memory layout of Julia Objects","title":"Memory layout of Julia Objects","text":"sidebar: Singleton Types\nSingleton types have only one instance and no data fields. Singleton instances have a size of 0 bytes, and consist only of their metadata. e.g. nothing::Nothing.See Singleton Types and Nothingness and missing values","category":"page"},{"location":"devdocs/reflection/#反射-与-自我检查","page":"反射 与 自我检查","title":"反射 与 自我检查","text":"","category":"section"},{"location":"devdocs/reflection/","page":"反射 与 自我检查","title":"反射 与 自我检查","text":"Julia 提供了多种运行时的反射功能。","category":"page"},{"location":"devdocs/reflection/#模块绑定","page":"反射 与 自我检查","title":"模块绑定","text":"","category":"section"},{"location":"devdocs/reflection/","page":"反射 与 自我检查","title":"反射 与 自我检查","text":"由 Module 导出的名称可用 names(m::Module) 获得,它会返回一个元素为 Symbol 的数组来表示模块导出的绑定。不管导出状态如何,names(m::Module, all = true) 返回 m 中所有绑定的符号。","category":"page"},{"location":"devdocs/reflection/#DateType-字段","page":"反射 与 自我检查","title":"DateType 字段","text":"","category":"section"},{"location":"devdocs/reflection/","page":"反射 与 自我检查","title":"反射 与 自我检查","text":"DataType 的所有字段名称可以使用 fieldnames 来获取。例如,对于下面给定的类型,fieldnames(Point) 会返回一个表示字段名称的 Symbol 元组:","category":"page"},{"location":"devdocs/reflection/","page":"反射 与 自我检查","title":"反射 与 自我检查","text":"julia> struct Point\n x::Int\n y\n end\n\njulia> fieldnames(Point)\n(:x, :y)","category":"page"},{"location":"devdocs/reflection/","page":"反射 与 自我检查","title":"反射 与 自我检查","text":"Point 对象中每个字段的类型存储在 Point 本身的 types 变量中:","category":"page"},{"location":"devdocs/reflection/","page":"反射 与 自我检查","title":"反射 与 自我检查","text":"julia> Point.types\nsvec(Int64, Any)","category":"page"},{"location":"devdocs/reflection/","page":"反射 与 自我检查","title":"反射 与 自我检查","text":"虽然 x 被注释为 Int,但 y 在类型定义里没有注释,因此 y 默认为 Any 类型。","category":"page"},{"location":"devdocs/reflection/","page":"反射 与 自我检查","title":"反射 与 自我检查","text":"类型本身表示为一个叫做 DataType 的结构:","category":"page"},{"location":"devdocs/reflection/","page":"反射 与 自我检查","title":"反射 与 自我检查","text":"julia> typeof(Point)\nDataType","category":"page"},{"location":"devdocs/reflection/","page":"反射 与 自我检查","title":"反射 与 自我检查","text":"Note that fieldnames(DataType) gives the names for each field of DataType itself, and one of these fields is the types field observed in the example above.","category":"page"},{"location":"devdocs/reflection/#Subtypes","page":"反射 与 自我检查","title":"Subtypes","text":"","category":"section"},{"location":"devdocs/reflection/","page":"反射 与 自我检查","title":"反射 与 自我检查","text":"The direct subtypes of any DataType may be listed using subtypes. For example, the abstract DataType AbstractFloat has four (concrete) subtypes:","category":"page"},{"location":"devdocs/reflection/","page":"反射 与 自我检查","title":"反射 与 自我检查","text":"julia> subtypes(AbstractFloat)\n4-element Vector{Any}:\n BigFloat\n Float16\n Float32\n Float64","category":"page"},{"location":"devdocs/reflection/","page":"反射 与 自我检查","title":"反射 与 自我检查","text":"任何抽象子类型也包括此列表中,但子类型的子类型不在其中。递归使用 subtypes 可以遍历出整个类型树。","category":"page"},{"location":"devdocs/reflection/#DataType-布局","page":"反射 与 自我检查","title":"DataType 布局","text":"","category":"section"},{"location":"devdocs/reflection/","page":"反射 与 自我检查","title":"反射 与 自我检查","text":"用 C 代码接口时,DataType 的内部表现非常重要。有几个函数可以检查这些细节。","category":"page"},{"location":"devdocs/reflection/","page":"反射 与 自我检查","title":"反射 与 自我检查","text":"isbits(T::DataType) 如果 T 类型是以 C 兼容的对齐方式存储,则为 true。 fieldoffset(T::DataType, i::Integer) 返回字段 i 相对于类型开始的 (字节) 偏移量。","category":"page"},{"location":"devdocs/reflection/#函数方法","page":"反射 与 自我检查","title":"函数方法","text":"","category":"section"},{"location":"devdocs/reflection/","page":"反射 与 自我检查","title":"反射 与 自我检查","text":"任何泛型函数的方法都可以使用 methods 来列出。用 methodswith 搜索 方法调度表 来查找 接收给定类型的方法。","category":"page"},{"location":"devdocs/reflection/#扩展和更底层","page":"反射 与 自我检查","title":"扩展和更底层","text":"","category":"section"},{"location":"devdocs/reflection/","page":"反射 与 自我检查","title":"反射 与 自我检查","text":"As discussed in the Metaprogramming section, the macroexpand function gives the unquoted and interpolated expression (Expr) form for a given macro. To use macroexpand, quote the expression block itself (otherwise, the macro will be evaluated and the result will be passed instead!). For example:","category":"page"},{"location":"devdocs/reflection/","page":"反射 与 自我检查","title":"反射 与 自我检查","text":"julia> macroexpand(@__MODULE__, :(@edit println(\"\")) )\n:(InteractiveUtils.edit(println, (Base.typesof)(\"\")))","category":"page"},{"location":"devdocs/reflection/","page":"反射 与 自我检查","title":"反射 与 自我检查","text":"The functions Base.Meta.show_sexpr and dump are used to display S-expr style views and depth-nested detail views for any expression.","category":"page"},{"location":"devdocs/reflection/","page":"反射 与 自我检查","title":"反射 与 自我检查","text":"Finally, the Meta.lower function gives the lowered form of any expression and is of particular interest for understanding how language constructs map to primitive operations such as assignments, branches, and calls:","category":"page"},{"location":"devdocs/reflection/","page":"反射 与 自我检查","title":"反射 与 自我检查","text":"julia> Meta.lower(@__MODULE__, :( [1+2, sin(0.5)] ))\n:($(Expr(:thunk, CodeInfo(\n @ none within `top-level scope`\n1 ─ %1 = 1 + 2\n│ %2 = sin(0.5)\n│ %3 = Base.vect(%1, %2)\n└── return %3\n))))","category":"page"},{"location":"devdocs/reflection/#中间表示和编译后表示","page":"反射 与 自我检查","title":"中间表示和编译后表示","text":"","category":"section"},{"location":"devdocs/reflection/","page":"反射 与 自我检查","title":"反射 与 自我检查","text":"检查函数的底层形式 需要选择所要显示的特定方法,因为泛型函数可能会有许多具有不同类型签名的方法。为此, 用 code_lowered 可以指定代码底层中的方法。 并且可以用 code_typed 来进行类型推断。 code_warntype 增加 code_typed 输出的高亮。","category":"page"},{"location":"devdocs/reflection/","page":"反射 与 自我检查","title":"反射 与 自我检查","text":"更加接近于机器, 一个函数的 LLVM-IR 可以通过使用 code_llvm 打印出。 最终编译的机器码使用 code_native 查看(这将触发 之前未调用过的任何函数的 JIT 编译/代码生成)。","category":"page"},{"location":"devdocs/reflection/","page":"反射 与 自我检查","title":"反射 与 自我检查","text":"为方便起见,上述函数有 宏的版本,它们接受标准函数调用并自动展开参数类型:","category":"page"},{"location":"devdocs/reflection/","page":"反射 与 自我检查","title":"反射 与 自我检查","text":"julia> @code_llvm +(1,1)\n\ndefine i64 @\"julia_+_130862\"(i64, i64) {\ntop:\n %2 = add i64 %1, %0\n ret i64 %2\n}","category":"page"},{"location":"devdocs/reflection/","page":"反射 与 自我检查","title":"反射 与 自我检查","text":"For more informations see @code_lowered, @code_typed, @code_warntype, @code_llvm, and @code_native.","category":"page"},{"location":"devdocs/reflection/#Printing-of-debug-information","page":"反射 与 自我检查","title":"Printing of debug information","text":"","category":"section"},{"location":"devdocs/reflection/","page":"反射 与 自我检查","title":"反射 与 自我检查","text":"The aforementioned functions and macros take the keyword argument debuginfo that controls the level debug information printed.","category":"page"},{"location":"devdocs/reflection/","page":"反射 与 自我检查","title":"反射 与 自我检查","text":"julia> @code_typed debuginfo=:source +(1,1)\nCodeInfo(\n @ int.jl:53 within `+'\n1 ─ %1 = Base.add_int(x, y)::Int64\n└── return %1\n) => Int64","category":"page"},{"location":"devdocs/reflection/","page":"反射 与 自我检查","title":"反射 与 自我检查","text":"Possible values for debuginfo are: :none, :source, and:default. Per default debug information is not printed, but that can be changed by setting Base.IRShow.default_debuginfo[] = :source.","category":"page"},{"location":"manual/code-loading/#code-loading","page":"代码加载","title":"代码加载","text":"","category":"section"},{"location":"manual/code-loading/","page":"代码加载","title":"代码加载","text":"note: Note\n这一章包含了加载包的技术细节。如果要安装包,使用 Julia 的内置包管理器Pkg将包加入到你的活跃环境中。如果要使用已经在你的活跃环境中的包,使用 import X 或 using X,正如在模块中所描述的那样。","category":"page"},{"location":"manual/code-loading/#定义","page":"代码加载","title":"定义","text":"","category":"section"},{"location":"manual/code-loading/","page":"代码加载","title":"代码加载","text":"Julia加载代码有两种机制:","category":"page"},{"location":"manual/code-loading/","page":"代码加载","title":"代码加载","text":"代码包含:例如 include(\"source.jl\")。包含允许你把一个程序拆分为多个源文件。表达式 include(\"source.jl\") 使得文件 source.jl 的内容在出现 include 调用的模块的全局作用域中执行。如果多次调用 include(\"source.jl\"),source.jl 就被执行多次。source.jl 的包含路径解释为相对于出现 include 调用的文件路径。重定位源文件子树因此变得简单。在 REPL 中,包含路径为当前工作目录,即 pwd()。\n加载包:例如 import X 或 using X。import 通过加载包(一个独立的,可重用的 Julia 代码集合,包含在一个模块中),并导入模块内部的名称 X,使得模块 X 可用。 如果在同一个 Julia 会话中,多次导入包 X,那么后续导入模块为第一次导入模块的引用。但请注意,import X 可以在不同的上下文中加载不同的包:X 可以引用主工程中名为 X 的一个包,但它在各个依赖中可以引用不同的、名称同为 X 的包。更多机制说明如下。","category":"page"},{"location":"manual/code-loading/","page":"代码加载","title":"代码加载","text":"代码包含是非常直接和简单的:其在调用者的上下文中解释运行给定的源文件。包加载是建立在代码包含之上的,它具有不同的用途。本章的其余部分将重点介绍程序包加载的行为和机制。","category":"page"},{"location":"manual/code-loading/","page":"代码加载","title":"代码加载","text":"一个 包(package) 就是一个源码树,其标准布局中提供了其他 Julia 项目可以复用的功能。包可以使用 import X 或 using X 语句加载,名为 X 的模块在加载包代码时生成,并在包含该 import 语句的模块中可用。import X 中 X 的含义与上下文有关:程序加载哪个 X 包取决于 import 语句出现的位置。因此,处理 import X 分为两步:首先,确定在此上下文中是哪个包被定义为 X;其次,确定到哪里找特定的 X 包。","category":"page"},{"location":"manual/code-loading/","page":"代码加载","title":"代码加载","text":"这些问题可通过查询各项目文件(Project.toml 或 JuliaProject.toml)、清单文件(Manifest.toml 或 JuliaManifest.toml),或是源文件的文件夹列在LOAD_PATH 中的项目环境解决。","category":"page"},{"location":"manual/code-loading/#Federation-of-packages","page":"代码加载","title":"包的联合生态","text":"","category":"section"},{"location":"manual/code-loading/","page":"代码加载","title":"代码加载","text":"大多数时候,一个包可以通过它的名字唯一确定。但有时在一个项目中,可能需要使用两个有着相同名字的不同的包。尽管你可以通过重命名其中一个包来解决这个问题,但在一个大型的、共享的代码库中被迫做这件事可能是有高度破坏性的。相反,Julia的包加载机制允许相同的包名在一个应用的不同部分指向不同的包。","category":"page"},{"location":"manual/code-loading/","page":"代码加载","title":"代码加载","text":"Julia 支持联合的包管理,这意味着多个独立的部分可以维护公有包、私有包以及包的注册表,并且项目可以依赖于一系列来自不同注册表的公有包和私有包。您也可以使用一组通用工具和工作流(workflow)来安装和管理来自各种注册表的包。Julia 附带的 Pkg 软件包管理器允许安装和管理项目的依赖项,它会帮助创建并操作项目文件(其描述了项目所依赖的其他项目)和清单文件(其为项目完整依赖库的确切版本的快照)。","category":"page"},{"location":"manual/code-loading/","page":"代码加载","title":"代码加载","text":"联合管理的一个可能后果是没有包命名的中央权限。不同组织可以使用相同的名称来引用不相关的包。这并不是没有可能的,因为这些组织可能没有协作,甚至不知道彼此。由于缺乏中央命名权限,单个项目可能最终依赖着具有相同名称的不同包。Julia 的包加载机制不要求包名称是全局唯一的,即使在单个项目的依赖关系图中也是如此。相反,包由通用唯一标识符 (UUID)进行标识,它在每个包创建时进行分配。通常,您不必直接使用这些有点麻烦的 128 位标识符,因为 Pkg 将负责生成和跟踪它们。但是,这些 UUID 为问题「X 所指的包是什么?」提供了确定的答案","category":"page"},{"location":"manual/code-loading/","page":"代码加载","title":"代码加载","text":"由于去中心化的命名问题有些抽象,因此可以通过具体情境来理解问题。假设你正在开发一个名为 App 的应用程序,它使用两个包:Pub 和 Priv。Priv 是你创建的私有包,而 Pub 是你使用但不控制的公共包。当你创建 Priv 时,没有名为 Priv 的公共包。然而,随后一个名为 Priv 的不相关软件包发布并变得流行起来,而且 Pub 包已经开始使用它了。因此,当你下次升级 Pub 以获取最新的错误修复和特性时,App 将依赖于两个名为 Priv 的不同包——尽管你除了升级之外什么都没做。App 直接依赖于你的私有 Priv 包,以及通过 Pub 在新的公共 Priv 包上的间接依赖。由于这两个 Priv 包是不同的,但是 App 继续正常工作依赖于他们两者,因此表达式 import Priv 必须引用不同的 Priv 包,具体取决于它是出现在 App 的代码中还是出现在 Pub 的代码中。为了处理这种情况,Julia 的包加载机制通过 UUID 区分两个 Priv 包并根据它(调用 import 的模块)的上下文选择正确的包。这种区分的工作原理取决于环境,如以下各节所述。","category":"page"},{"location":"manual/code-loading/#环境(Environments)","page":"代码加载","title":"环境(Environments)","text":"","category":"section"},{"location":"manual/code-loading/","page":"代码加载","title":"代码加载","text":"环境决定了 import X 和 using X 语句在不同的代码上下文中的含义以及什么文件会被加载。Julia 有两类环境(environment):","category":"page"},{"location":"manual/code-loading/","page":"代码加载","title":"代码加载","text":"项目环境(project environment)是包含项目文件和清单文件(可选)的目录,并形成一个显式环境。项目文件确定项目的直接依赖项的名称和标识。清单文件(如果存在)提供完整的依赖关系图,包括所有直接和间接依赖关系,每个依赖的确切版本以及定位和加载正确版本的足够信息。\n包目录(package directory)是包含一组包的源码树子目录的目录,并形成一个隐式环境。如果 X 是包目录的子目录并且存在 X/src/X.jl,那么程序包 X 在包目录环境中可用,而 X/src/X.jl 是加载它使用的源文件。","category":"page"},{"location":"manual/code-loading/","page":"代码加载","title":"代码加载","text":"这些环境可以混合并用来创建堆栈环境(stacked environment):是一组有序的项目环境和包目录,重叠为一个复合环境。然后,结合优先级规则和可见性规则,确定哪些包是可用的以及从哪里加载它们。例如,Julia 的负载路径是一个堆栈环境。","category":"page"},{"location":"manual/code-loading/","page":"代码加载","title":"代码加载","text":"这些环境各有不同的用途:","category":"page"},{"location":"manual/code-loading/","page":"代码加载","title":"代码加载","text":"项目环境提供可迁移性。通过将项目环境以及项目源代码的其余部分存放到版本控制(例如一个 git 存储库),您可以重现项目的确切状态和所有依赖项。特别是,清单文件会记录每个依赖项的确切版本,而依赖项由其源码树的加密哈希值标识;这使得 Pkg 可以检索出正确的版本,并确保你正在运行准确的已记录的所有依赖项的代码。\n当不需要完全仔细跟踪的项目环境时,包目录更方便。当你想要把一组包放在某处,并且希望能够直接使用它们而不必为之创建项目环境时,包目录是很实用的。\n堆栈环境允许向基本环境添加工具。您可以将包含开发工具在内的环境堆到堆栈环境的末尾,使它们在 REPL 和脚本中可用,但在包内部不可用。","category":"page"},{"location":"manual/code-loading/","page":"代码加载","title":"代码加载","text":"从更高层次上,每个环境在概念上定义了三个映射:roots、graph 和 paths。当解析 import X 的含义时,roots 和 graph 映射用于确定 X 的身份,同时 paths 映射用于定位 X 的源代码。这三个映射的具体作用是:","category":"page"},{"location":"manual/code-loading/","page":"代码加载","title":"代码加载","text":"roots: name::Symbol ⟶ uuid::UUID\n环境的 roots 映射将包名称分配给UUID,以获取环境可用于主项目的所有顶级依赖项(即可以在 Main 中加载的那些依赖项)。当 Julia 在主项目中遇到 import X 时,它会将 X 的标识作为 roots[:X]。\ngraph: context::UUID ⟶ name::Symbol ⟶ uuid::UUID\n环境的 graph 是一个多级映射,它为每个 context UUID 分配一个从名称到 UUID 的映射——类似于 roots 映射,但专一于那个 context。当 Julia 在 UUID 为 context 的包代码中运行到 import X 时,它会将 X 的标识看作为 graph[context][:X]。正是因为如此,import X 可以根据 context 引用不同的包。\npaths: uuid::UUID × name::Symbol ⟶ path::String\npaths 映射会为每个包分配 UUID-name 对,即该包的入口点源文件的位置。在 import X 中,X 的标识已经通过 roots 或 graph 解析为 UUID(取决于它是从主项目还是从依赖项加载),Julia 确定要加载哪个文件来获取 X 是通过在环境中查找 paths[uuid,:X]。要包含此文件应该定义一个名为 X 的模块。一旦加载了此包,任何解析为相同的 uuid 的后续导入只会创建一个到同一个已加载的包模块的绑定。","category":"page"},{"location":"manual/code-loading/","page":"代码加载","title":"代码加载","text":"每种环境都以不同的方式定义这三种映射,详见以下各节。","category":"page"},{"location":"manual/code-loading/","page":"代码加载","title":"代码加载","text":"note: Note\n为了清楚地说明,本章中的示例包括 roots、graph 和 paths 的完整数据结构。但是,为了提高效率,Julia 的包加载代码并没有显式地创建它们。相反,加载一个给定包只会简单地计算所需的结构。","category":"page"},{"location":"manual/code-loading/#项目环境(Project-environments)","page":"代码加载","title":"项目环境(Project environments)","text":"","category":"section"},{"location":"manual/code-loading/","page":"代码加载","title":"代码加载","text":"项目环境由包含名为 Project.toml 的项目文件的目录以及名为 Manifest.toml 的清单文件(可选)确定。这些文件也可以命名为 JuliaProject.toml 和 JuliaManifest.toml,此时 Project.toml 和 Manifest.toml 被忽略——这允许项目与可能需要名为 Project.toml 和 Manifest.toml 文件的其他重要工具共存。但是对于纯 Julia 项目,名称 Project.toml 和 Manifest.toml 是首选。","category":"page"},{"location":"manual/code-loading/","page":"代码加载","title":"代码加载","text":"项目环境的 roots、graph 和 paths 映射定义如下:","category":"page"},{"location":"manual/code-loading/","page":"代码加载","title":"代码加载","text":"roots 映射 在环境中由其项目文件的内容决定,特别是它的顶级 name 和 uuid 条目及其 [deps] 部分(全部是可选的)。考虑以下一个假想的应用程序 App 的示例项目文件,如先前所述:","category":"page"},{"location":"manual/code-loading/","page":"代码加载","title":"代码加载","text":"name = \"App\"\nuuid = \"8f986787-14fe-4607-ba5d-fbff2944afa9\"\n\n[deps]\nPriv = \"ba13f791-ae1d-465a-978b-69c3ad90f72b\"\nPub = \"c07ecb7d-0dc9-4db7-8803-fadaaeaf08e1\"","category":"page"},{"location":"manual/code-loading/","page":"代码加载","title":"代码加载","text":"如果将它表示为 Julia 字典,那么这个项目文件意味着以下 roots 映射:","category":"page"},{"location":"manual/code-loading/","page":"代码加载","title":"代码加载","text":"roots = Dict(\n :App => UUID(\"8f986787-14fe-4607-ba5d-fbff2944afa9\"),\n :Priv => UUID(\"ba13f791-ae1d-465a-978b-69c3ad90f72b\"),\n :Pub => UUID(\"c07ecb7d-0dc9-4db7-8803-fadaaeaf08e1\"),\n)","category":"page"},{"location":"manual/code-loading/","page":"代码加载","title":"代码加载","text":"基于这个 root 映射,在 App 的代码中,语句 import Priv 将使 Julia 查找 roots[:Priv],这将得到 ba13f791-ae1d-465a-978b-69c3ad90f72b,也就是要在这一部分加载的 Priv 包的 UUID。当主应用程序解释运行到 import Priv 时,此 UUID 标识了要加载和使用的 Priv 包。","category":"page"},{"location":"manual/code-loading/","page":"代码加载","title":"代码加载","text":"依赖图(dependency graph) 在项目环境中其清单文件的内容决定,如果其存在。如果没有清单文件,则 graph 为空。清单文件包含项目的直接或间接依赖项的节(stanza)。对于每个依赖项,该文件列出该包的 UUID 以及源码树的哈希值或源代码的显式路径。考虑以下 App 的示例清单文件:","category":"page"},{"location":"manual/code-loading/","page":"代码加载","title":"代码加载","text":"[[Priv]] # 私有的那个\ndeps = [\"Pub\", \"Zebra\"]\nuuid = \"ba13f791-ae1d-465a-978b-69c3ad90f72b\"\npath = \"deps/Priv\"\n\n[[Priv]] # 公共的那个\nuuid = \"2d15fe94-a1f7-436c-a4d8-07a9a496e01c\"\ngit-tree-sha1 = \"1bf63d3be994fe83456a03b874b409cfd59a6373\"\nversion = \"0.1.5\"\n\n[[Pub]]\nuuid = \"c07ecb7d-0dc9-4db7-8803-fadaaeaf08e1\"\ngit-tree-sha1 = \"9ebd50e2b0dd1e110e842df3b433cb5869b0dd38\"\nversion = \"2.1.4\"\n\n [Pub.deps]\n Priv = \"2d15fe94-a1f7-436c-a4d8-07a9a496e01c\"\n Zebra = \"f7a24cb4-21fc-4002-ac70-f0e3a0dd3f62\"\n\n[[Zebra]]\nuuid = \"f7a24cb4-21fc-4002-ac70-f0e3a0dd3f62\"\ngit-tree-sha1 = \"e808e36a5d7173974b90a15a353b564f3494092f\"\nversion = \"3.4.2\"","category":"page"},{"location":"manual/code-loading/","page":"代码加载","title":"代码加载","text":"这个清单文件描述了 App 项目可能的完整依赖关系图:","category":"page"},{"location":"manual/code-loading/","page":"代码加载","title":"代码加载","text":"应用程序使用两个名为 Priv 的不同包,一个作为根依赖项的私有包,以及一个通过 Pub 作为间接依赖项的公共包。它们通过不同 UUID 来区分,并且有不同的依赖项:\n私有的 Priv 依赖于 Pub 和 Zebra 包。\n公有的 Priv 没有依赖关系。\n该应用程序还依赖于 Pub 包,而后者依赖于公有的 Priv 以及私有的 Priv 包所依赖的那个 Zebra 包。","category":"page"},{"location":"manual/code-loading/","page":"代码加载","title":"代码加载","text":"此依赖图以字典表示后如下所示:","category":"page"},{"location":"manual/code-loading/","page":"代码加载","title":"代码加载","text":"graph = Dict(\n # Priv——私有的那个:\n UUID(\"ba13f791-ae1d-465a-978b-69c3ad90f72b\") => Dict(\n :Pub => UUID(\"c07ecb7d-0dc9-4db7-8803-fadaaeaf08e1\"),\n :Zebra => UUID(\"f7a24cb4-21fc-4002-ac70-f0e3a0dd3f62\"),\n ),\n # Priv——公共的那个:\n UUID(\"2d15fe94-a1f7-436c-a4d8-07a9a496e01c\") => Dict(),\n # Pub:\n UUID(\"c07ecb7d-0dc9-4db7-8803-fadaaeaf08e1\") => Dict(\n :Priv => UUID(\"2d15fe94-a1f7-436c-a4d8-07a9a496e01c\"),\n :Zebra => UUID(\"f7a24cb4-21fc-4002-ac70-f0e3a0dd3f62\"),\n ),\n # Zebra:\n UUID(\"f7a24cb4-21fc-4002-ac70-f0e3a0dd3f62\") => Dict(),\n)","category":"page"},{"location":"manual/code-loading/","page":"代码加载","title":"代码加载","text":"给定这个依赖图,当 Julia 看到 Pub 包中的 import Priv ——它有 UUIDc07ecb7d-0dc9-4db7-8803-fadaaeaf08e1 时,它会查找:","category":"page"},{"location":"manual/code-loading/","page":"代码加载","title":"代码加载","text":"graph[UUID(\"c07ecb7d-0dc9-4db7-8803-fadaaeaf08e1\")][:Priv]","category":"page"},{"location":"manual/code-loading/","page":"代码加载","title":"代码加载","text":"会得到 2d15fe94-a1f7-436c-a4d8-07a9a496e01c,这意味着 Pub 包中的内容,import Priv 指代的是公有的 Priv 内容,而非应用程序直接依赖的私有包。这也是为何 Priv 在主项目中可指代不同的包,而不像其在某个依赖包中另有含义。在包生态中,该特性允许重名的出现。","category":"page"},{"location":"manual/code-loading/","page":"代码加载","title":"代码加载","text":"如果在 App 主代码库中 import Zebra 会如何?因为Zebra 不存在于项目文件,即使它 确实 存在于清单文件中,其导入会是失败的。此外,import Zebra 这个行为若发生在公有的 Priv 包——UUID 为 2d15fe94-a1f7-436c-a4d8-07a9a496e01c 的包中,同样会失败。因为公有的 Priv 包未在清单文件中声明依赖,故而无法加载包。仅有在清单文件:Pub 包和一个 Priv 包中作为显式依赖的包可用于加载 Zebra。","category":"page"},{"location":"manual/code-loading/","page":"代码加载","title":"代码加载","text":"项目环境的 路径映射 从 manifest 文件中提取得到。而包的路径 uuid 和名称 X 则 (循序) 依据这些规则确定。","category":"page"},{"location":"manual/code-loading/","page":"代码加载","title":"代码加载","text":"如果目录中的项目文件与要求的 uuid 以及名称 X 匹配,那么可能出现以下情况的一种:\n若该文件具有顶层 路径 入口,则 uuid 会被映射到该路径,文件的执行与包含项目文件的目录相关。\n此外,uuid 依照包含项目文件的目录,映射至与src/X.jl。\n若非上述情况,且项目文件具有对应的清单文件,且该清单文件包含匹配 uuid 的节(stanza),那么:\n若其具有一个 路径 入口,则使用该路径(与包含清单文件的目录相关)。\n若其具有一个 git-tree-sha1 入口,计算一个确定的 uuid 与 git-tree-sha1 函数——我们把这个函数称为 slug——并在每个 Julia DEPOT_PATH 的全局序列中的目录查询名为 packages/X/$slug 的目录。使用存在的第一个此类目录。","category":"page"},{"location":"manual/code-loading/","page":"代码加载","title":"代码加载","text":"若某些结果成功,源码入口点的路径会是这些结果中的某个,结果的相对路径+src/X.jl;否则,uuid 不存在路径映射。当加载 X 时,如果没找到源码路径,查找即告失败,用户可能会被提示安装适当的包版本或采取其他纠正措施(例如,将 X 声明为某种依赖性)。","category":"page"},{"location":"manual/code-loading/","page":"代码加载","title":"代码加载","text":"在上述样例清单文件中,为找到首个 Priv 包的路径——该包 UUID 为 ba13f791-ae1d-465a-978b-69c3ad90f72b——Julia 寻找其在清单中的节(stanza)。发现其有 路径入口,查看App项目目录中相关的deps/Priv——不妨设App代码在/home/me/projects/App中—则 Julia 发现/home/me/projects/App/deps/Priv存在,并因此从中加载Priv`。","category":"page"},{"location":"manual/code-loading/","page":"代码加载","title":"代码加载","text":"另一方面,如果Julia加载的是带有other Priv 包——即UUID为2d15fe94-a1f7-436c-a4d8-07a9a496e01c——它在清单中找到了它的节,请注意它没有path条目,但是它有一个git-tree-sha1 条目。然后计算这个slug 的UUID/SHA-1对,具体是HDkrT(这个计算的确切细节并不重要,但它是始终一致的和确定的)。这意味着这个Priv包的路径packages/Priv/HDkrT/src/Priv.jl将在其中一个包仓库中。假设DEPOT_PATH 的内容是[\"/home/me/.julia\", \"/usr/local/julia\"],Julia将根据下面的路径来查看它们是否存在:","category":"page"},{"location":"manual/code-loading/","page":"代码加载","title":"代码加载","text":"/home/me/.julia/packages/Priv/HDkrT\n/usr/local/julia/packages/Priv/HDkrT","category":"page"},{"location":"manual/code-loading/","page":"代码加载","title":"代码加载","text":"Julia使用以上路径信息在仓库里依次查找 packages/Priv/HDKrT/src/Priv.jl文件,并从第一个查找到的文件中加载公共的 Priv包。","category":"page"},{"location":"manual/code-loading/","page":"代码加载","title":"代码加载","text":"这是我们的示例App项目环境的可能路径映射的表示, 如上面Manifest 中所提供的依赖关系图, 在 搜索本地文件系统后:","category":"page"},{"location":"manual/code-loading/","page":"代码加载","title":"代码加载","text":"paths = Dict(\n # Priv – the private one:\n (UUID(\"ba13f791-ae1d-465a-978b-69c3ad90f72b\"), :Priv) =>\n # relative entry-point inside `App` repo:\n \"/home/me/projects/App/deps/Priv/src/Priv.jl\",\n # Priv – the public one:\n (UUID(\"2d15fe94-a1f7-436c-a4d8-07a9a496e01c\"), :Priv) =>\n # package installed in the system depot:\n \"/usr/local/julia/packages/Priv/HDkr/src/Priv.jl\",\n # Pub:\n (UUID(\"c07ecb7d-0dc9-4db7-8803-fadaaeaf08e1\"), :Pub) =>\n # package installed in the user depot:\n \"/home/me/.julia/packages/Pub/oKpw/src/Pub.jl\",\n # Zebra:\n (UUID(\"f7a24cb4-21fc-4002-ac70-f0e3a0dd3f62\"), :Zebra) =>\n # package installed in the system depot:\n \"/usr/local/julia/packages/Zebra/me9k/src/Zebra.jl\",\n)","category":"page"},{"location":"manual/code-loading/","page":"代码加载","title":"代码加载","text":"这个例子包含三种不同类型的包位置信息(第一个和第三个是默认加载路径的一部分)","category":"page"},{"location":"manual/code-loading/","page":"代码加载","title":"代码加载","text":"私有 Priv 包 \"vendored\"包括在App仓库中。\n公共 Priv 与 Zebra 包位于系统仓库,系统管理员在此对相关包进行实时安装与管理。这些包允许系统上的所有用户使用。\nPub 包位于用户仓库,用户实时安装的包都储存在此。 这些包仅限原安装用户使用。","category":"page"},{"location":"manual/code-loading/#包目录","page":"代码加载","title":"包目录","text":"","category":"section"},{"location":"manual/code-loading/","page":"代码加载","title":"代码加载","text":"包目录提供了一种更简单的环境,但不能处理名称冲突。在包目录中, 顶层包集合是“类似”包的子目录集合。X包存在于包目录中的条件,是目录包含下列“入口点”文件之一:","category":"page"},{"location":"manual/code-loading/","page":"代码加载","title":"代码加载","text":"X.jl\nX/src/X.jl\nX.jl/src/X.jl","category":"page"},{"location":"manual/code-loading/","page":"代码加载","title":"代码加载","text":"包目录中的包可以导入哪些依赖项,取决于该包是否含有项目文件:","category":"page"},{"location":"manual/code-loading/","page":"代码加载","title":"代码加载","text":"如果它有一个项目文件,那么它只能导入那些在项目文件的[deps] 部分中已标识的包。\n如果没有项目文件,它可以导入任何顶层包,即与在Main 或者 REPL中可加载的包相同。","category":"page"},{"location":"manual/code-loading/","page":"代码加载","title":"代码加载","text":"根图是根据包目录的所有内容而形成的一个列表,包含所有已存在的包。 此外,一个UUID 将被赋予给每一个条目,例如对一个在文件夹X中找到的包","category":"page"},{"location":"manual/code-loading/","page":"代码加载","title":"代码加载","text":"如果X/Project.toml文件存在并且有一个uuid 条目,那么这个 uuid就是上述所要赋予的值。\n如果X/Project.toml文件存在,但没有包含一个顶层UUID条目, 该uuid将是一个虚构的UUID,是对X/Project.toml文件所在的规范(真实的)路径信息进行哈希处理而生成。\n否则(如果Project.toml文件不存在), uuid将是一个全零值 nil UUID。","category":"page"},{"location":"manual/code-loading/","page":"代码加载","title":"代码加载","text":"项目目录的依赖关系图是根据每个包的子目录中其项目文件的存在与否以及内容而形成。规则是:","category":"page"},{"location":"manual/code-loading/","page":"代码加载","title":"代码加载","text":"如果包子目录没有项目文件,则在该图中忽略它, 其代码中的import语句按顶层处理,与main项目和REPL相同。\n如果包子目录有一个项目文件,那么图条目的UUID是项目文件的[deps]映射, 如果该信息项不存在,则视为空。","category":"page"},{"location":"manual/code-loading/","page":"代码加载","title":"代码加载","text":"作为一个例子,假设包目录具有以下结构和内容:","category":"page"},{"location":"manual/code-loading/","page":"代码加载","title":"代码加载","text":"Aardvark/\n src/Aardvark.jl:\n import Bobcat\n import Cobra\n\nBobcat/\n Project.toml:\n [deps]\n Cobra = \"4725e24d-f727-424b-bca0-c4307a3456fa\"\n Dingo = \"7a7925be-828c-4418-bbeb-bac8dfc843bc\"\n\n src/Bobcat.jl:\n import Cobra\n import Dingo\n\nCobra/\n Project.toml:\n uuid = \"4725e24d-f727-424b-bca0-c4307a3456fa\"\n [deps]\n Dingo = \"7a7925be-828c-4418-bbeb-bac8dfc843bc\"\n\n src/Cobra.jl:\n import Dingo\n\nDingo/\n Project.toml:\n uuid = \"7a7925be-828c-4418-bbeb-bac8dfc843bc\"\n\n src/Dingo.jl:\n # no imports","category":"page"},{"location":"manual/code-loading/","page":"代码加载","title":"代码加载","text":"下面是相应的根结构,表示为字典:","category":"page"},{"location":"manual/code-loading/","page":"代码加载","title":"代码加载","text":"roots = Dict(\n :Aardvark => UUID(\"00000000-0000-0000-0000-000000000000\"), # no project file, nil UUID\n :Bobcat => UUID(\"85ad11c7-31f6-5d08-84db-0a4914d4cadf\"), # dummy UUID based on path\n :Cobra => UUID(\"4725e24d-f727-424b-bca0-c4307a3456fa\"), # UUID from project file\n :Dingo => UUID(\"7a7925be-828c-4418-bbeb-bac8dfc843bc\"), # UUID from project file\n)","category":"page"},{"location":"manual/code-loading/","page":"代码加载","title":"代码加载","text":"下面是对应的图结构,表示为字典:","category":"page"},{"location":"manual/code-loading/","page":"代码加载","title":"代码加载","text":"graph = Dict(\n # Bobcat:\n UUID(\"85ad11c7-31f6-5d08-84db-0a4914d4cadf\") => Dict(\n :Cobra => UUID(\"4725e24d-f727-424b-bca0-c4307a3456fa\"),\n :Dingo => UUID(\"7a7925be-828c-4418-bbeb-bac8dfc843bc\"),\n ),\n # Cobra:\n UUID(\"4725e24d-f727-424b-bca0-c4307a3456fa\") => Dict(\n :Dingo => UUID(\"7a7925be-828c-4418-bbeb-bac8dfc843bc\"),\n ),\n # Dingo:\n UUID(\"7a7925be-828c-4418-bbeb-bac8dfc843bc\") => Dict(),\n)","category":"page"},{"location":"manual/code-loading/","page":"代码加载","title":"代码加载","text":"值得注意的一些通用规则:","category":"page"},{"location":"manual/code-loading/","page":"代码加载","title":"代码加载","text":"缺少项目文件的包能依赖于任何顶层依赖项, 并且由于包目录中的每个包在顶层依赖中可用,因此它可以导入在环境中的所有包。\n含有项目文件的包不能依赖于缺少项目文件的包。 因为有项目文件的包只能加载那些在graph中的包,而没有项目文件的包不会出现在graph。\n具有项目文件但没有明确UUID的包只能被由没有项目文件的包所依赖, since dummy UUIDs assigned to these packages are strictly internal.","category":"page"},{"location":"manual/code-loading/","page":"代码加载","title":"代码加载","text":",因为赋予给这些包的虚构UUID全是项目内部的。","category":"page"},{"location":"manual/code-loading/","page":"代码加载","title":"代码加载","text":"Observe the following specific instances of these rules in our example: 请注意以下我们例子中的规则具体实例:","category":"page"},{"location":"manual/code-loading/","page":"代码加载","title":"代码加载","text":"Aardvark 包可以导入Bobcat、Cobra 或Dingo中的所有包;它确实导入Bobcat and Cobra包.\nBobcat 包能导入Cobra与Dingo包。因为它们都有带有UUID的项目文件,并在Bobcat包的[deps]信息项声明为依赖项。\nBobcat包不能依赖于Aardvark包,因为Aardvark包缺少项目文件。\nCobra包能导入Dingo包。因为Dingo包有项目文件和UUID,并在Cobra的[deps] 信息项中声明为依赖项。\nCobra包不能依赖Aardvark或Bobcat包, 因为两者都没有真实的UUID。\nDingo包不能导入任何包,因为它的项目文件中缺少[deps]信息项。","category":"page"},{"location":"manual/code-loading/","page":"代码加载","title":"代码加载","text":"包目录中的路径映射很简单: 它将子目录名映射到相应的入口点路径。换句话说,如果指向我们示例项目目录的路径是/home/me/animals,那么路径映射可以用此字典表示:","category":"page"},{"location":"manual/code-loading/","page":"代码加载","title":"代码加载","text":"paths = Dict(\n (UUID(\"00000000-0000-0000-0000-000000000000\"), :Aardvark) =>\n \"/home/me/AnimalPackages/Aardvark/src/Aardvark.jl\",\n (UUID(\"85ad11c7-31f6-5d08-84db-0a4914d4cadf\"), :Bobcat) =>\n \"/home/me/AnimalPackages/Bobcat/src/Bobcat.jl\",\n (UUID(\"4725e24d-f727-424b-bca0-c4307a3456fa\"), :Cobra) =>\n \"/home/me/AnimalPackages/Cobra/src/Cobra.jl\",\n (UUID(\"7a7925be-828c-4418-bbeb-bac8dfc843bc\"), :Dingo) =>\n \"/home/me/AnimalPackages/Dingo/src/Dingo.jl\",\n)","category":"page"},{"location":"manual/code-loading/","page":"代码加载","title":"代码加载","text":"根据定义,包目录环境中的所有包都是具有预期入口点文件的子目录,因此它们的路径 映射条目始终具有此格式。","category":"page"},{"location":"manual/code-loading/#环境堆栈","page":"代码加载","title":"环境堆栈","text":"","category":"section"},{"location":"manual/code-loading/","page":"代码加载","title":"代码加载","text":"第三种也是最后一种环境是通过覆盖其中的几个环境来组合其他环境,使每个环境中的包在单个组合环境中可用。这些复合环境称为环境堆栈。Julia的LOAD_PATH全局定义一个环境堆栈——Julia进程在其中运行的环境。如果希望Julia进程只能访问一个项目或包目录中的包,请将其设置为LOAD_PATH中的唯一条目。然而,访问一些您喜爱的工具(标准库、探查器、调试器、个人实用程序等)通常是非常有用的,即使它们不是您正在处理的项目的依赖项。通过将包含这些工具的环境添加到加载路径,您可以立即在顶层代码中访问它们,而无需将它们添加到项目中。","category":"page"},{"location":"manual/code-loading/","page":"代码加载","title":"代码加载","text":"组合环境堆栈组件中根、图和路径的数据结构的机制很简单:它们被作为字典进行合并, 在发生键冲突时,优先使用前面的条目而不是后面的条目。换言之,如果我们有stack = [env₁, env₂, …],那么我们有:","category":"page"},{"location":"manual/code-loading/","page":"代码加载","title":"代码加载","text":"roots = reduce(merge, reverse([roots₁, roots₂, …]))\ngraph = reduce(merge, reverse([graph₁, graph₂, …]))\npaths = reduce(merge, reverse([paths₁, paths₂, …]))","category":"page"},{"location":"manual/code-loading/","page":"代码加载","title":"代码加载","text":"带下标的 rootsᵢ, graphᵢ and pathsᵢ变量对应于在stack中包含的下标环境变量envᵢ。 使用reverse 是因为当参数字典中的键之间发生冲突时,使merge 倾向于使用最后一个参数,而不是第一个参数。这种设计有几个值得注意的特点:","category":"page"},{"location":"manual/code-loading/","page":"代码加载","title":"代码加载","text":"主环境——即堆栈中的第一个环境,被准确地嵌入到堆栈环境中。堆栈中第一个环境的完整依赖关系图是必然被完整包括在含有所有相同版本的依赖项的堆栈环境中。\n非主环境中的包能最终使用与其依赖项不兼容的版本,即使它们自己的环境是完全兼容。这种情况可能发生,当它们的一个依赖项被堆栈(通过图或路径,或两者)中某个早期环境中的版本所覆盖。","category":"page"},{"location":"manual/code-loading/","page":"代码加载","title":"代码加载","text":"由于主环境通常是您正在处理的项目所在的环境,而堆栈中稍后的环境包含其他工具, 因此这是正确的权衡:最好改进您的开发工具,但保持项目能工作。当这种不兼容发生时,你通常要将开发工具升级到与主项目兼容的版本。","category":"page"},{"location":"manual/code-loading/#总结","page":"代码加载","title":"总结","text":"","category":"section"},{"location":"manual/code-loading/","page":"代码加载","title":"代码加载","text":"在软件包系统中,联邦软件包管理和精确的软件可复制性是困难但有价值的目标。结合起来,这些目标导致了一个比大多数动态语言更加复杂的包加载机制,但它也产生了通常与静态语言相关的可伸缩性和可复制性。通常,Julia用户应该能够使用内置的包管理器来管理他们的项目,而无需精确理解这些交互细节。通过调用Pkg.add(\"X\")添加X包到对应的项目,并清晰显示相关文件,选择Pkg.activate(\"Y\")后, 可调用import X 即可加载X包,而无需作过多考虑。","category":"page"},{"location":"base/io-network/#I/O-与网络","page":"I/O 与网络","title":"I/O 与网络","text":"","category":"section"},{"location":"base/io-network/#通用-I/O","page":"I/O 与网络","title":"通用 I/O","text":"","category":"section"},{"location":"base/io-network/","page":"I/O 与网络","title":"I/O 与网络","text":"Base.stdout\nBase.stderr\nBase.stdin\nBase.open\nBase.IOStream\nBase.IOBuffer\nBase.take!(::Base.GenericIOBuffer)\nBase.fdio\nBase.flush\nBase.close\nBase.write\nBase.read\nBase.read!\nBase.readbytes!\nBase.unsafe_read\nBase.unsafe_write\nBase.readeach\nBase.peek\nBase.position\nBase.seek\nBase.seekstart\nBase.seekend\nBase.skip\nBase.mark\nBase.unmark\nBase.reset\nBase.ismarked\nBase.eof\nBase.isreadonly\nBase.iswritable\nBase.isreadable\nBase.isopen\nBase.fd\nBase.redirect_stdio\nBase.redirect_stdout\nBase.redirect_stdout(::Function, ::Any)\nBase.redirect_stderr\nBase.redirect_stderr(::Function, ::Any)\nBase.redirect_stdin\nBase.redirect_stdin(::Function, ::Any)\nBase.readchomp\nBase.truncate\nBase.skipchars\nBase.countlines\nBase.PipeBuffer\nBase.readavailable\nBase.IOContext\nBase.IOContext(::IO, ::Pair)\nBase.IOContext(::IO, ::IOContext)","category":"page"},{"location":"base/io-network/#Base.stdout","page":"I/O 与网络","title":"Base.stdout","text":"stdout::IO\n\nGlobal variable referring to the standard out stream.\n\n\n\n\n\n","category":"constant"},{"location":"base/io-network/#Base.stderr","page":"I/O 与网络","title":"Base.stderr","text":"stderr::IO\n\nGlobal variable referring to the standard error stream.\n\n\n\n\n\n","category":"constant"},{"location":"base/io-network/#Base.stdin","page":"I/O 与网络","title":"Base.stdin","text":"stdin::IO\n\nGlobal variable referring to the standard input stream.\n\n\n\n\n\n","category":"constant"},{"location":"base/io-network/#Base.open","page":"I/O 与网络","title":"Base.open","text":"open(f::Function, args...; kwargs...)\n\nApply the function f to the result of open(args...; kwargs...) and close the resulting file descriptor upon completion.\n\nExamples\n\njulia> open(\"myfile.txt\", \"w\") do io\n write(io, \"Hello world!\")\n end;\n\njulia> open(f->read(f, String), \"myfile.txt\")\n\"Hello world!\"\n\njulia> rm(\"myfile.txt\")\n\n\n\n\n\nopen(filename::AbstractString; lock = true, keywords...) -> IOStream\n\nOpen a file in a mode specified by five boolean keyword arguments:\n\nKeyword Description Default\nread open for reading !write\nwrite open for writing truncate | append\ncreate create if non-existent !read & write | truncate | append\ntruncate truncate to zero size !read & write\nappend seek to end false\n\nThe default when no keywords are passed is to open files for reading only. Returns a stream for accessing the opened file.\n\nThe lock keyword argument controls whether operations will be locked for safe multi-threaded access.\n\ncompat: Julia 1.5\nThe lock argument is available as of Julia 1.5.\n\n\n\n\n\nopen(filename::AbstractString, [mode::AbstractString]; lock = true) -> IOStream\n\nAlternate syntax for open, where a string-based mode specifier is used instead of the five booleans. The values of mode correspond to those from fopen(3) or Perl open, and are equivalent to setting the following boolean groups:\n\nMode Description Keywords\nr read none\nw write, create, truncate write = true\na write, create, append append = true\nr+ read, write read = true, write = true\nw+ read, write, create, truncate truncate = true, read = true\na+ read, write, create, append append = true, read = true\n\nThe lock keyword argument controls whether operations will be locked for safe multi-threaded access.\n\nExamples\n\njulia> io = open(\"myfile.txt\", \"w\");\n\njulia> write(io, \"Hello world!\");\n\njulia> close(io);\n\njulia> io = open(\"myfile.txt\", \"r\");\n\njulia> read(io, String)\n\"Hello world!\"\n\njulia> write(io, \"This file is read only\")\nERROR: ArgumentError: write failed, IOStream is not writeable\n[...]\n\njulia> close(io)\n\njulia> io = open(\"myfile.txt\", \"a\");\n\njulia> write(io, \"This stream is not read only\")\n28\n\njulia> close(io)\n\njulia> rm(\"myfile.txt\")\n\ncompat: Julia 1.5\nThe lock argument is available as of Julia 1.5.\n\n\n\n\n\nopen(fd::OS_HANDLE) -> IO\n\nTake a raw file descriptor wrap it in a Julia-aware IO type, and take ownership of the fd handle. Call open(Libc.dup(fd)) to avoid the ownership capture of the original handle.\n\nwarning: Warning\nDo not call this on a handle that's already owned by some other part of the system.\n\n\n\n\n\nopen(command, mode::AbstractString, stdio=devnull)\n\nRun command asynchronously. Like open(command, stdio; read, write) except specifying the read and write flags via a mode string instead of keyword arguments. Possible mode strings are:\n\nMode Description Keywords\nr read none\nw write write = true\nr+ read, write read = true, write = true\nw+ read, write read = true, write = true\n\n\n\n\n\nopen(command, stdio=devnull; write::Bool = false, read::Bool = !write)\n\nStart running command asynchronously, and return a process::IO object. If read is true, then reads from the process come from the process's standard output and stdio optionally specifies the process's standard input stream. If write is true, then writes go to the process's standard input and stdio optionally specifies the process's standard output stream. The process's standard error stream is connected to the current global stderr.\n\n\n\n\n\nopen(f::Function, command, args...; kwargs...)\n\nSimilar to open(command, args...; kwargs...), but calls f(stream) on the resulting process stream, then closes the input stream and waits for the process to complete. Return the value returned by f on success. Throw an error if the process failed, or if the process attempts to print anything to stdout.\n\n\n\n\n\n","category":"function"},{"location":"base/io-network/#Base.IOStream","page":"I/O 与网络","title":"Base.IOStream","text":"IOStream\n\nA buffered IO stream wrapping an OS file descriptor. Mostly used to represent files returned by open.\n\n\n\n\n\n","category":"type"},{"location":"base/io-network/#Base.IOBuffer","page":"I/O 与网络","title":"Base.IOBuffer","text":"IOBuffer([data::AbstractVector{UInt8}]; keywords...) -> IOBuffer\n\nCreate an in-memory I/O stream, which may optionally operate on a pre-existing array.\n\nIt may take optional keyword arguments:\n\nread, write, append: restricts operations to the buffer; see open for details.\ntruncate: truncates the buffer size to zero length.\nmaxsize: specifies a size beyond which the buffer may not be grown.\nsizehint: suggests a capacity of the buffer (data must implement sizehint!(data, size)).\n\nWhen data is not given, the buffer will be both readable and writable by default.\n\nExamples\n\njulia> io = IOBuffer();\n\njulia> write(io, \"JuliaLang is a GitHub organization.\", \" It has many members.\")\n56\n\njulia> String(take!(io))\n\"JuliaLang is a GitHub organization. It has many members.\"\n\njulia> io = IOBuffer(b\"JuliaLang is a GitHub organization.\")\nIOBuffer(data=UInt8[...], readable=true, writable=false, seekable=true, append=false, size=35, maxsize=Inf, ptr=1, mark=-1)\n\njulia> read(io, String)\n\"JuliaLang is a GitHub organization.\"\n\njulia> write(io, \"This isn't writable.\")\nERROR: ArgumentError: ensureroom failed, IOBuffer is not writeable\n\njulia> io = IOBuffer(UInt8[], read=true, write=true, maxsize=34)\nIOBuffer(data=UInt8[...], readable=true, writable=true, seekable=true, append=false, size=0, maxsize=34, ptr=1, mark=-1)\n\njulia> write(io, \"JuliaLang is a GitHub organization.\")\n34\n\njulia> String(take!(io))\n\"JuliaLang is a GitHub organization\"\n\njulia> length(read(IOBuffer(b\"data\", read=true, truncate=false)))\n4\n\njulia> length(read(IOBuffer(b\"data\", read=true, truncate=true)))\n0\n\n\n\n\n\nIOBuffer(string::String)\n\nCreate a read-only IOBuffer on the data underlying the given string.\n\nExamples\n\njulia> io = IOBuffer(\"Haho\");\n\njulia> String(take!(io))\n\"Haho\"\n\njulia> String(take!(io))\n\"Haho\"\n\n\n\n\n\n","category":"type"},{"location":"base/io-network/#Base.take!-Tuple{Base.GenericIOBuffer}","page":"I/O 与网络","title":"Base.take!","text":"take!(b::IOBuffer)\n\nObtain the contents of an IOBuffer as an array. Afterwards, the IOBuffer is reset to its initial state.\n\nExamples\n\njulia> io = IOBuffer();\n\njulia> write(io, \"JuliaLang is a GitHub organization.\", \" It has many members.\")\n56\n\njulia> String(take!(io))\n\"JuliaLang is a GitHub organization. It has many members.\"\n\n\n\n\n\n","category":"method"},{"location":"base/io-network/#Base.fdio","page":"I/O 与网络","title":"Base.fdio","text":"fdio([name::AbstractString, ]fd::Integer[, own::Bool=false]) -> IOStream\n\nCreate an IOStream object from an integer file descriptor. If own is true, closing this object will close the underlying descriptor. By default, an IOStream is closed when it is garbage collected. name allows you to associate the descriptor with a named file.\n\n\n\n\n\n","category":"function"},{"location":"base/io-network/#Base.flush","page":"I/O 与网络","title":"Base.flush","text":"flush(stream)\n\nCommit all currently buffered writes to the given stream.\n\n\n\n\n\n","category":"function"},{"location":"base/io-network/#Base.close","page":"I/O 与网络","title":"Base.close","text":"close(stream)\n\nClose an I/O stream. Performs a flush first.\n\n\n\n\n\n","category":"function"},{"location":"base/io-network/#Base.write","page":"I/O 与网络","title":"Base.write","text":"write(io::IO, x)\nwrite(filename::AbstractString, x)\n\nWrite the canonical binary representation of a value to the given I/O stream or file. Return the number of bytes written into the stream. See also print to write a text representation (with an encoding that may depend upon io).\n\nThe endianness of the written value depends on the endianness of the host system. Convert to/from a fixed endianness when writing/reading (e.g. using htol and ltoh) to get results that are consistent across platforms.\n\nYou can write multiple values with the same write call. i.e. the following are equivalent:\n\nwrite(io, x, y...)\nwrite(io, x) + write(io, y...)\n\nExamples\n\nConsistent serialization:\n\njulia> fname = tempname(); # random temporary filename\n\njulia> open(fname,\"w\") do f\n # Make sure we write 64bit integer in little-endian byte order\n write(f,htol(Int64(42)))\n end\n8\n\njulia> open(fname,\"r\") do f\n # Convert back to host byte order and host integer type\n Int(ltoh(read(f,Int64)))\n end\n42\n\nMerging write calls:\n\njulia> io = IOBuffer();\n\njulia> write(io, \"JuliaLang is a GitHub organization.\", \" It has many members.\")\n56\n\njulia> String(take!(io))\n\"JuliaLang is a GitHub organization. It has many members.\"\n\njulia> write(io, \"Sometimes those members\") + write(io, \" write documentation.\")\n44\n\njulia> String(take!(io))\n\"Sometimes those members write documentation.\"\n\nUser-defined plain-data types without write methods can be written when wrapped in a Ref:\n\njulia> struct MyStruct; x::Float64; end\n\njulia> io = IOBuffer()\nIOBuffer(data=UInt8[...], readable=true, writable=true, seekable=true, append=false, size=0, maxsize=Inf, ptr=1, mark=-1)\n\njulia> write(io, Ref(MyStruct(42.0)))\n8\n\njulia> seekstart(io); read!(io, Ref(MyStruct(NaN)))\nBase.RefValue{MyStruct}(MyStruct(42.0))\n\n\n\n\n\n","category":"function"},{"location":"base/io-network/#Base.read","page":"I/O 与网络","title":"Base.read","text":"read(io::IO, T)\n\nRead a single value of type T from io, in canonical binary representation.\n\nNote that Julia does not convert the endianness for you. Use ntoh or ltoh for this purpose.\n\nread(io::IO, String)\n\nRead the entirety of io, as a String (see also readchomp).\n\nExamples\n\njulia> io = IOBuffer(\"JuliaLang is a GitHub organization\");\n\njulia> read(io, Char)\n'J': ASCII/Unicode U+004A (category Lu: Letter, uppercase)\n\njulia> io = IOBuffer(\"JuliaLang is a GitHub organization\");\n\njulia> read(io, String)\n\"JuliaLang is a GitHub organization\"\n\n\n\n\n\nread(filename::AbstractString, args...)\n\nOpen a file and read its contents. args is passed to read: this is equivalent to open(io->read(io, args...), filename).\n\nread(filename::AbstractString, String)\n\nRead the entire contents of a file as a string.\n\n\n\n\n\nread(s::IO, nb=typemax(Int))\n\nRead at most nb bytes from s, returning a Vector{UInt8} of the bytes read.\n\n\n\n\n\nread(s::IOStream, nb::Integer; all=true)\n\nRead at most nb bytes from s, returning a Vector{UInt8} of the bytes read.\n\nIf all is true (the default), this function will block repeatedly trying to read all requested bytes, until an error or end-of-file occurs. If all is false, at most one read call is performed, and the amount of data returned is device-dependent. Note that not all stream types support the all option.\n\n\n\n\n\nread(command::Cmd)\n\nRun command and return the resulting output as an array of bytes.\n\n\n\n\n\nread(command::Cmd, String)\n\nRun command and return the resulting output as a String.\n\n\n\n\n\n","category":"function"},{"location":"base/io-network/#Base.read!","page":"I/O 与网络","title":"Base.read!","text":"read!(stream::IO, array::AbstractArray)\nread!(filename::AbstractString, array::AbstractArray)\n\nRead binary data from an I/O stream or file, filling in array.\n\n\n\n\n\n","category":"function"},{"location":"base/io-network/#Base.readbytes!","page":"I/O 与网络","title":"Base.readbytes!","text":"readbytes!(stream::IO, b::AbstractVector{UInt8}, nb=length(b))\n\nRead at most nb bytes from stream into b, returning the number of bytes read. The size of b will be increased if needed (i.e. if nb is greater than length(b) and enough bytes could be read), but it will never be decreased.\n\n\n\n\n\nreadbytes!(stream::IOStream, b::AbstractVector{UInt8}, nb=length(b); all::Bool=true)\n\nRead at most nb bytes from stream into b, returning the number of bytes read. The size of b will be increased if needed (i.e. if nb is greater than length(b) and enough bytes could be read), but it will never be decreased.\n\nIf all is true (the default), this function will block repeatedly trying to read all requested bytes, until an error or end-of-file occurs. If all is false, at most one read call is performed, and the amount of data returned is device-dependent. Note that not all stream types support the all option.\n\n\n\n\n\n","category":"function"},{"location":"base/io-network/#Base.unsafe_read","page":"I/O 与网络","title":"Base.unsafe_read","text":"unsafe_read(io::IO, ref, nbytes::UInt)\n\nCopy nbytes from the IO stream object into ref (converted to a pointer).\n\nIt is recommended that subtypes T<:IO override the following method signature to provide more efficient implementations: unsafe_read(s::T, p::Ptr{UInt8}, n::UInt)\n\n\n\n\n\n","category":"function"},{"location":"base/io-network/#Base.unsafe_write","page":"I/O 与网络","title":"Base.unsafe_write","text":"unsafe_write(io::IO, ref, nbytes::UInt)\n\nCopy nbytes from ref (converted to a pointer) into the IO object.\n\nIt is recommended that subtypes T<:IO override the following method signature to provide more efficient implementations: unsafe_write(s::T, p::Ptr{UInt8}, n::UInt)\n\n\n\n\n\n","category":"function"},{"location":"base/io-network/#Base.readeach","page":"I/O 与网络","title":"Base.readeach","text":"readeach(io::IO, T)\n\nReturn an iterable object yielding read(io, T).\n\nSee also skipchars, eachline, readuntil.\n\ncompat: Julia 1.6\nreadeach requires Julia 1.6 or later.\n\nExamples\n\njulia> io = IOBuffer(\"JuliaLang is a GitHub organization.\\n It has many members.\\n\");\n\njulia> for c in readeach(io, Char)\n c == '\\n' && break\n print(c)\n end\nJuliaLang is a GitHub organization.\n\n\n\n\n\n","category":"function"},{"location":"base/io-network/#Base.peek","page":"I/O 与网络","title":"Base.peek","text":"peek(stream[, T=UInt8])\n\nRead and return a value of type T from a stream without advancing the current position in the stream.\n\nExamples\n\njulia> b = IOBuffer(\"julia\");\n\njulia> peek(b)\n0x6a\n\njulia> position(b)\n0\n\njulia> peek(b, Char)\n'j': ASCII/Unicode U+006A (category Ll: Letter, lowercase)\n\ncompat: Julia 1.5\nThe method which accepts a type requires Julia 1.5 or later.\n\n\n\n\n\n","category":"function"},{"location":"base/io-network/#Base.position","page":"I/O 与网络","title":"Base.position","text":"position(s)\n\nGet the current position of a stream.\n\nExamples\n\njulia> io = IOBuffer(\"JuliaLang is a GitHub organization.\");\n\njulia> seek(io, 5);\n\njulia> position(io)\n5\n\njulia> skip(io, 10);\n\njulia> position(io)\n15\n\njulia> seekend(io);\n\njulia> position(io)\n35\n\n\n\n\n\n","category":"function"},{"location":"base/io-network/#Base.seek","page":"I/O 与网络","title":"Base.seek","text":"seek(s, pos)\n\nSeek a stream to the given position.\n\nExamples\n\njulia> io = IOBuffer(\"JuliaLang is a GitHub organization.\");\n\njulia> seek(io, 5);\n\njulia> read(io, Char)\n'L': ASCII/Unicode U+004C (category Lu: Letter, uppercase)\n\n\n\n\n\n","category":"function"},{"location":"base/io-network/#Base.seekstart","page":"I/O 与网络","title":"Base.seekstart","text":"seekstart(s)\n\nSeek a stream to its beginning.\n\nExamples\n\njulia> io = IOBuffer(\"JuliaLang is a GitHub organization.\");\n\njulia> seek(io, 5);\n\njulia> read(io, Char)\n'L': ASCII/Unicode U+004C (category Lu: Letter, uppercase)\n\njulia> seekstart(io);\n\njulia> read(io, Char)\n'J': ASCII/Unicode U+004A (category Lu: Letter, uppercase)\n\n\n\n\n\n","category":"function"},{"location":"base/io-network/#Base.seekend","page":"I/O 与网络","title":"Base.seekend","text":"seekend(s)\n\nSeek a stream to its end.\n\n\n\n\n\n","category":"function"},{"location":"base/io-network/#Base.skip","page":"I/O 与网络","title":"Base.skip","text":"skip(s, offset)\n\nSeek a stream relative to the current position.\n\nExamples\n\njulia> io = IOBuffer(\"JuliaLang is a GitHub organization.\");\n\njulia> seek(io, 5);\n\njulia> skip(io, 10);\n\njulia> read(io, Char)\n'G': ASCII/Unicode U+0047 (category Lu: Letter, uppercase)\n\n\n\n\n\n","category":"function"},{"location":"base/io-network/#Base.mark","page":"I/O 与网络","title":"Base.mark","text":"mark(s::IO)\n\nAdd a mark at the current position of stream s. Return the marked position.\n\nSee also unmark, reset, ismarked.\n\n\n\n\n\n","category":"function"},{"location":"base/io-network/#Base.unmark","page":"I/O 与网络","title":"Base.unmark","text":"unmark(s::IO)\n\nRemove a mark from stream s. Return true if the stream was marked, false otherwise.\n\nSee also mark, reset, ismarked.\n\n\n\n\n\n","category":"function"},{"location":"base/io-network/#Base.reset","page":"I/O 与网络","title":"Base.reset","text":"reset(s::IO)\n\nReset a stream s to a previously marked position, and remove the mark. Return the previously marked position. Throw an error if the stream is not marked.\n\nSee also mark, unmark, ismarked.\n\n\n\n\n\nreset(::Event)\n\nReset an Event back into an un-set state. Then any future calls to wait will block until notify is called again.\n\n\n\n\n\n","category":"function"},{"location":"base/io-network/#Base.ismarked","page":"I/O 与网络","title":"Base.ismarked","text":"ismarked(s::IO)\n\nReturn true if stream s is marked.\n\nSee also mark, unmark, reset.\n\n\n\n\n\n","category":"function"},{"location":"base/io-network/#Base.eof","page":"I/O 与网络","title":"Base.eof","text":"eof(stream) -> Bool\n\nTest whether an I/O stream is at end-of-file. If the stream is not yet exhausted, this function will block to wait for more data if necessary, and then return false. Therefore it is always safe to read one byte after seeing eof return false. eof will return false as long as buffered data is still available, even if the remote end of a connection is closed.\n\n\n\n\n\n","category":"function"},{"location":"base/io-network/#Base.isreadonly","page":"I/O 与网络","title":"Base.isreadonly","text":"isreadonly(io) -> Bool\n\nDetermine whether a stream is read-only.\n\nExamples\n\njulia> io = IOBuffer(\"JuliaLang is a GitHub organization\");\n\njulia> isreadonly(io)\ntrue\n\njulia> io = IOBuffer();\n\njulia> isreadonly(io)\nfalse\n\n\n\n\n\n","category":"function"},{"location":"base/io-network/#Base.iswritable","page":"I/O 与网络","title":"Base.iswritable","text":"iswritable(io) -> Bool\n\nReturn false if the specified IO object is not writable.\n\nExamples\n\njulia> open(\"myfile.txt\", \"w\") do io\n print(io, \"Hello world!\");\n iswritable(io)\n end\ntrue\n\njulia> open(\"myfile.txt\", \"r\") do io\n iswritable(io)\n end\nfalse\n\njulia> rm(\"myfile.txt\")\n\n\n\n\n\n","category":"function"},{"location":"base/io-network/#Base.isreadable","page":"I/O 与网络","title":"Base.isreadable","text":"isreadable(io) -> Bool\n\nReturn false if the specified IO object is not readable.\n\nExamples\n\njulia> open(\"myfile.txt\", \"w\") do io\n print(io, \"Hello world!\");\n isreadable(io)\n end\nfalse\n\njulia> open(\"myfile.txt\", \"r\") do io\n isreadable(io)\n end\ntrue\n\njulia> rm(\"myfile.txt\")\n\n\n\n\n\n","category":"function"},{"location":"base/io-network/#Base.isopen","page":"I/O 与网络","title":"Base.isopen","text":"isopen(object) -> Bool\n\nDetermine whether an object - such as a stream or timer – is not yet closed. Once an object is closed, it will never produce a new event. However, since a closed stream may still have data to read in its buffer, use eof to check for the ability to read data. Use the FileWatching package to be notified when a stream might be writable or readable.\n\nExamples\n\njulia> io = open(\"my_file.txt\", \"w+\");\n\njulia> isopen(io)\ntrue\n\njulia> close(io)\n\njulia> isopen(io)\nfalse\n\n\n\n\n\n","category":"function"},{"location":"base/io-network/#Base.fd","page":"I/O 与网络","title":"Base.fd","text":"fd(stream)\n\nReturn the file descriptor backing the stream or file. Note that this function only applies to synchronous File's and IOStream's not to any of the asynchronous streams.\n\n\n\n\n\n","category":"function"},{"location":"base/io-network/#Base.redirect_stdio","page":"I/O 与网络","title":"Base.redirect_stdio","text":"redirect_stdio(;stdin=stdin, stderr=stderr, stdout=stdout)\n\nRedirect a subset of the streams stdin, stderr, stdout. Each argument must be an IOStream, TTY, Pipe, socket, or devnull.\n\ncompat: Julia 1.7\nredirect_stdio requires Julia 1.7 or later.\n\n\n\n\n\nredirect_stdio(f; stdin=nothing, stderr=nothing, stdout=nothing)\n\nRedirect a subset of the streams stdin, stderr, stdout, call f() and restore each stream.\n\nPossible values for each stream are:\n\nnothing indicating the stream should not be redirected.\npath::AbstractString redirecting the stream to the file at path.\nio an IOStream, TTY, Pipe, socket, or devnull.\n\nExamples\n\njulia> redirect_stdio(stdout=\"stdout.txt\", stderr=\"stderr.txt\") do\n print(\"hello stdout\")\n print(stderr, \"hello stderr\")\n end\n\njulia> read(\"stdout.txt\", String)\n\"hello stdout\"\n\njulia> read(\"stderr.txt\", String)\n\"hello stderr\"\n\nEdge cases\n\nIt is possible to pass the same argument to stdout and stderr:\n\njulia> redirect_stdio(stdout=\"log.txt\", stderr=\"log.txt\", stdin=devnull) do\n ...\nend\n\nHowever it is not supported to pass two distinct descriptors of the same file.\n\njulia> io1 = open(\"same/path\", \"w\")\n\njulia> io2 = open(\"same/path\", \"w\")\n\njulia> redirect_stdio(f, stdout=io1, stderr=io2) # not suppored\n\nAlso the stdin argument may not be the same descriptor as stdout or stderr.\n\njulia> io = open(...)\n\njulia> redirect_stdio(f, stdout=io, stdin=io) # not supported\n\ncompat: Julia 1.7\nredirect_stdio requires Julia 1.7 or later.\n\n\n\n\n\n","category":"function"},{"location":"base/io-network/#Base.redirect_stdout","page":"I/O 与网络","title":"Base.redirect_stdout","text":"redirect_stdout([stream]) -> stream\n\nCreate a pipe to which all C and Julia level stdout output will be redirected. Return a stream representing the pipe ends. Data written to stdout may now be read from the rd end of the pipe.\n\nnote: Note\nstream must be a compatible objects, such as an IOStream, TTY, Pipe, socket, or devnull.\n\nSee also redirect_stdio.\n\n\n\n\n\n","category":"function"},{"location":"base/io-network/#Base.redirect_stdout-Tuple{Function, Any}","page":"I/O 与网络","title":"Base.redirect_stdout","text":"redirect_stdout(f::Function, stream)\n\nRun the function f while redirecting stdout to stream. Upon completion, stdout is restored to its prior setting.\n\n\n\n\n\n","category":"method"},{"location":"base/io-network/#Base.redirect_stderr","page":"I/O 与网络","title":"Base.redirect_stderr","text":"redirect_stderr([stream]) -> stream\n\nLike redirect_stdout, but for stderr.\n\nnote: Note\nstream must be a compatible objects, such as an IOStream, TTY, Pipe, socket, or devnull.\n\nSee also redirect_stdio.\n\n\n\n\n\n","category":"function"},{"location":"base/io-network/#Base.redirect_stderr-Tuple{Function, Any}","page":"I/O 与网络","title":"Base.redirect_stderr","text":"redirect_stderr(f::Function, stream)\n\nRun the function f while redirecting stderr to stream. Upon completion, stderr is restored to its prior setting.\n\n\n\n\n\n","category":"method"},{"location":"base/io-network/#Base.redirect_stdin","page":"I/O 与网络","title":"Base.redirect_stdin","text":"redirect_stdin([stream]) -> stream\n\nLike redirect_stdout, but for stdin. Note that the direction of the stream is reversed.\n\nnote: Note\nstream must be a compatible objects, such as an IOStream, TTY, Pipe, socket, or devnull.\n\nSee also redirect_stdio.\n\n\n\n\n\n","category":"function"},{"location":"base/io-network/#Base.redirect_stdin-Tuple{Function, Any}","page":"I/O 与网络","title":"Base.redirect_stdin","text":"redirect_stdin(f::Function, stream)\n\nRun the function f while redirecting stdin to stream. Upon completion, stdin is restored to its prior setting.\n\n\n\n\n\n","category":"method"},{"location":"base/io-network/#Base.readchomp","page":"I/O 与网络","title":"Base.readchomp","text":"readchomp(x)\n\nRead the entirety of x as a string and remove a single trailing newline if there is one. Equivalent to chomp(read(x, String)).\n\nExamples\n\njulia> open(\"my_file.txt\", \"w\") do io\n write(io, \"JuliaLang is a GitHub organization.\\nIt has many members.\\n\");\n end;\n\njulia> readchomp(\"my_file.txt\")\n\"JuliaLang is a GitHub organization.\\nIt has many members.\"\n\njulia> rm(\"my_file.txt\");\n\n\n\n\n\n","category":"function"},{"location":"base/io-network/#Base.truncate","page":"I/O 与网络","title":"Base.truncate","text":"truncate(file, n)\n\nResize the file or buffer given by the first argument to exactly n bytes, filling previously unallocated space with '\\0' if the file or buffer is grown.\n\nExamples\n\njulia> io = IOBuffer();\n\njulia> write(io, \"JuliaLang is a GitHub organization.\")\n35\n\njulia> truncate(io, 15)\nIOBuffer(data=UInt8[...], readable=true, writable=true, seekable=true, append=false, size=15, maxsize=Inf, ptr=16, mark=-1)\n\njulia> String(take!(io))\n\"JuliaLang is a \"\n\njulia> io = IOBuffer();\n\njulia> write(io, \"JuliaLang is a GitHub organization.\");\n\njulia> truncate(io, 40);\n\njulia> String(take!(io))\n\"JuliaLang is a GitHub organization.\\0\\0\\0\\0\\0\"\n\n\n\n\n\n","category":"function"},{"location":"base/io-network/#Base.skipchars","page":"I/O 与网络","title":"Base.skipchars","text":"skipchars(predicate, io::IO; linecomment=nothing)\n\nAdvance the stream io such that the next-read character will be the first remaining for which predicate returns false. If the keyword argument linecomment is specified, all characters from that character until the start of the next line are ignored.\n\nExamples\n\njulia> buf = IOBuffer(\" text\")\nIOBuffer(data=UInt8[...], readable=true, writable=false, seekable=true, append=false, size=8, maxsize=Inf, ptr=1, mark=-1)\n\njulia> skipchars(isspace, buf)\nIOBuffer(data=UInt8[...], readable=true, writable=false, seekable=true, append=false, size=8, maxsize=Inf, ptr=5, mark=-1)\n\njulia> String(readavailable(buf))\n\"text\"\n\n\n\n\n\n","category":"function"},{"location":"base/io-network/#Base.countlines","page":"I/O 与网络","title":"Base.countlines","text":"countlines(io::IO; eol::AbstractChar = '\\n')\n\nRead io until the end of the stream/file and count the number of lines. To specify a file pass the filename as the first argument. EOL markers other than '\\n' are supported by passing them as the second argument. The last non-empty line of io is counted even if it does not end with the EOL, matching the length returned by eachline and readlines.\n\nTo count lines of a String, countlines(IOBuffer(str)) can be used.\n\nExamples\n\njulia> io = IOBuffer(\"JuliaLang is a GitHub organization.\\n\");\n\njulia> countlines(io)\n1\n\njulia> io = IOBuffer(\"JuliaLang is a GitHub organization.\");\n\njulia> countlines(io)\n1\n\njulia> eof(io) # counting lines moves the file pointer\ntrue\n\njulia> io = IOBuffer(\"JuliaLang is a GitHub organization.\");\n\njulia> countlines(io, eol = '.')\n1\n\n\n\n\n\n","category":"function"},{"location":"base/io-network/#Base.PipeBuffer","page":"I/O 与网络","title":"Base.PipeBuffer","text":"PipeBuffer(data::Vector{UInt8}=UInt8[]; maxsize::Integer = typemax(Int))\n\nAn IOBuffer that allows reading and performs writes by appending. Seeking and truncating are not supported. See IOBuffer for the available constructors. If data is given, creates a PipeBuffer to operate on a data vector, optionally specifying a size beyond which the underlying Array may not be grown.\n\n\n\n\n\n","category":"function"},{"location":"base/io-network/#Base.readavailable","page":"I/O 与网络","title":"Base.readavailable","text":"readavailable(stream)\n\nRead available buffered data from a stream. Actual I/O is performed only if no data has already been buffered. The result is a Vector{UInt8}.\n\nwarning: Warning\nThe amount of data returned is implementation-dependent; for example it can depend on the internal choice of buffer size. Other functions such as read should generally be used instead.\n\n\n\n\n\n","category":"function"},{"location":"base/io-network/#Base.IOContext","page":"I/O 与网络","title":"Base.IOContext","text":"IOContext\n\nIOContext provides a mechanism for passing output configuration settings among show methods.\n\nIn short, it is an immutable dictionary that is a subclass of IO. It supports standard dictionary operations such as getindex, and can also be used as an I/O stream.\n\n\n\n\n\n","category":"type"},{"location":"base/io-network/#Base.IOContext-Tuple{IO, Pair}","page":"I/O 与网络","title":"Base.IOContext","text":"IOContext(io::IO, KV::Pair...)\n\nCreate an IOContext that wraps a given stream, adding the specified key=>value pairs to the properties of that stream (note that io can itself be an IOContext).\n\nuse (key => value) in io to see if this particular combination is in the properties set\nuse get(io, key, default) to retrieve the most recent value for a particular key\n\nThe following properties are in common use:\n\n:compact: Boolean specifying that values should be printed more compactly, e.g. that numbers should be printed with fewer digits. This is set when printing array elements. :compact output should not contain line breaks.\n:limit: Boolean specifying that containers should be truncated, e.g. showing … in place of most elements.\n:displaysize: A Tuple{Int,Int} giving the size in rows and columns to use for text output. This can be used to override the display size for called functions, but to get the size of the screen use the displaysize function.\n:typeinfo: a Type characterizing the information already printed concerning the type of the object about to be displayed. This is mainly useful when displaying a collection of objects of the same type, so that redundant type information can be avoided (e.g. [Float16(0)] can be shown as \"Float16[0.0]\" instead of \"Float16[Float16(0.0)]\" : while displaying the elements of the array, the :typeinfo property will be set to Float16).\n:color: Boolean specifying whether ANSI color/escape codes are supported/expected. By default, this is determined by whether io is a compatible terminal and by any --color command-line flag when julia was launched.\n\nExamples\n\njulia> io = IOBuffer();\n\njulia> printstyled(IOContext(io, :color => true), \"string\", color=:red)\n\njulia> String(take!(io))\n\"\\e[31mstring\\e[39m\"\n\njulia> printstyled(io, \"string\", color=:red)\n\njulia> String(take!(io))\n\"string\"\n\njulia> print(IOContext(stdout, :compact => false), 1.12341234)\n1.12341234\njulia> print(IOContext(stdout, :compact => true), 1.12341234)\n1.12341\n\njulia> function f(io::IO)\n if get(io, :short, false)\n print(io, \"short\")\n else\n print(io, \"loooooong\")\n end\n end\nf (generic function with 1 method)\n\njulia> f(stdout)\nloooooong\njulia> f(IOContext(stdout, :short => true))\nshort\n\n\n\n\n\n","category":"method"},{"location":"base/io-network/#Base.IOContext-Tuple{IO, IOContext}","page":"I/O 与网络","title":"Base.IOContext","text":"IOContext(io::IO, context::IOContext)\n\nCreate an IOContext that wraps an alternate IO but inherits the properties of context.\n\n\n\n\n\n","category":"method"},{"location":"base/io-network/#文本-I/O","page":"I/O 与网络","title":"文本 I/O","text":"","category":"section"},{"location":"base/io-network/","page":"I/O 与网络","title":"I/O 与网络","text":"Base.show(::IO, ::Any)\nBase.summary\nBase.print\nBase.println\nBase.printstyled\nBase.sprint\nBase.showerror\nBase.dump\nMeta.@dump\nBase.readline\nBase.readuntil\nBase.readlines\nBase.eachline\nBase.displaysize","category":"page"},{"location":"base/io-network/#Base.show-Tuple{IO, Any}","page":"I/O 与网络","title":"Base.show","text":"show([io::IO = stdout], x)\n\nWrite a text representation of a value x to the output stream io. New types T should overload show(io::IO, x::T). The representation used by show generally includes Julia-specific formatting and type information, and should be parseable Julia code when possible.\n\nrepr returns the output of show as a string.\n\nTo customize human-readable text output for objects of type T, define show(io::IO, ::MIME\"text/plain\", ::T) instead. Checking the :compact IOContext property of io in such methods is recommended, since some containers show their elements by calling this method with :compact => true.\n\nSee also print, which writes un-decorated representations.\n\nExamples\n\njulia> show(\"Hello World!\")\n\"Hello World!\"\njulia> print(\"Hello World!\")\nHello World!\n\n\n\n\n\n","category":"method"},{"location":"base/io-network/#Base.summary","page":"I/O 与网络","title":"Base.summary","text":"summary(io::IO, x)\nstr = summary(x)\n\nPrint to a stream io, or return a string str, giving a brief description of a value. By default returns string(typeof(x)), e.g. Int64.\n\nFor arrays, returns a string of size and type info, e.g. 10-element Array{Int64,1}.\n\nExamples\n\njulia> summary(1)\n\"Int64\"\n\njulia> summary(zeros(2))\n\"2-element Vector{Float64}\"\n\n\n\n\n\n","category":"function"},{"location":"base/io-network/#Base.print","page":"I/O 与网络","title":"Base.print","text":"print([io::IO], xs...)\n\nWrite to io (or to the default output stream stdout if io is not given) a canonical (un-decorated) text representation. The representation used by print includes minimal formatting and tries to avoid Julia-specific details.\n\nprint falls back to calling show, so most types should just define show. Define print if your type has a separate \"plain\" representation. For example, show displays strings with quotes, and print displays strings without quotes.\n\nSee also println, string, printstyled.\n\nExamples\n\njulia> print(\"Hello World!\")\nHello World!\njulia> io = IOBuffer();\n\njulia> print(io, \"Hello\", ' ', :World!)\n\njulia> String(take!(io))\n\"Hello World!\"\n\n\n\n\n\n","category":"function"},{"location":"base/io-network/#Base.println","page":"I/O 与网络","title":"Base.println","text":"println([io::IO], xs...)\n\nPrint (using print) xs to io followed by a newline. If io is not supplied, prints to the default output stream stdout.\n\nSee also printstyled to add colors etc.\n\nExamples\n\njulia> println(\"Hello, world\")\nHello, world\n\njulia> io = IOBuffer();\n\njulia> println(io, \"Hello\", ',', \" world.\")\n\njulia> String(take!(io))\n\"Hello, world.\\n\"\n\n\n\n\n\n","category":"function"},{"location":"base/io-network/#Base.printstyled","page":"I/O 与网络","title":"Base.printstyled","text":"printstyled([io], xs...; bold::Bool=false, underline::Bool=false, blink::Bool=false, reverse::Bool=false, hidden::Bool=false, color::Union{Symbol,Int}=:normal)\n\nPrint xs in a color specified as a symbol or integer, optionally in bold.\n\nKeyword color may take any of the values :normal, :default, :bold, :black, :blink, :blue, :cyan, :green, :hidden, :light_black, :light_blue, :light_cyan, :light_green, :light_magenta, :light_red, :light_white, :light_yellow, :magenta, :nothing, :red, :reverse, :underline, :white, or :yellow or an integer between 0 and 255 inclusive. Note that not all terminals support 256 colors.\n\nKeywords bold=true, underline=true, blink=true are self-explanatory. Keyword reverse=true prints with foreground and background colors exchanged, and hidden=true should be invisibe in the terminal but can still be copied. These properties can be used in any combination.\n\nSee also print, println, show.\n\ncompat: Julia 1.7\nKeywords except color and bold were added in Julia 1.7.\n\n\n\n\n\n","category":"function"},{"location":"base/io-network/#Base.sprint","page":"I/O 与网络","title":"Base.sprint","text":"sprint(f::Function, args...; context=nothing, sizehint=0)\n\nCall the given function with an I/O stream and the supplied extra arguments. Everything written to this I/O stream is returned as a string. context can be an IOContext whose properties will be used, a Pair specifying a property and its value, or a tuple of Pair specifying multiple properties and their values. sizehint suggests the capacity of the buffer (in bytes).\n\nThe optional keyword argument context can be set to a :key=>value pair, a tuple of :key=>value pairs, or an IO or IOContext object whose attributes are used for the I/O stream passed to f. The optional sizehint is a suggested size (in bytes) to allocate for the buffer used to write the string.\n\ncompat: Julia 1.7\nPassing a tuple to keyword context requires Julia 1.7 or later.\n\nExamples\n\njulia> sprint(show, 66.66666; context=:compact => true)\n\"66.6667\"\n\njulia> sprint(showerror, BoundsError([1], 100))\n\"BoundsError: attempt to access 1-element Vector{Int64} at index [100]\"\n\n\n\n\n\n","category":"function"},{"location":"base/io-network/#Base.showerror","page":"I/O 与网络","title":"Base.showerror","text":"showerror(io, e)\n\nShow a descriptive representation of an exception object e. This method is used to display the exception after a call to throw.\n\nExamples\n\njulia> struct MyException <: Exception\n msg::String\n end\n\njulia> function Base.showerror(io::IO, err::MyException)\n print(io, \"MyException: \")\n print(io, err.msg)\n end\n\njulia> err = MyException(\"test exception\")\nMyException(\"test exception\")\n\njulia> sprint(showerror, err)\n\"MyException: test exception\"\n\njulia> throw(MyException(\"test exception\"))\nERROR: MyException: test exception\n\n\n\n\n\n","category":"function"},{"location":"base/io-network/#Base.dump","page":"I/O 与网络","title":"Base.dump","text":"dump(x; maxdepth=8)\n\nShow every part of the representation of a value. The depth of the output is truncated at maxdepth.\n\nExamples\n\njulia> struct MyStruct\n x\n y\n end\n\njulia> x = MyStruct(1, (2,3));\n\njulia> dump(x)\nMyStruct\n x: Int64 1\n y: Tuple{Int64, Int64}\n 1: Int64 2\n 2: Int64 3\n\njulia> dump(x; maxdepth = 1)\nMyStruct\n x: Int64 1\n y: Tuple{Int64, Int64}\n\n\n\n\n\n","category":"function"},{"location":"base/io-network/#Base.Meta.@dump","page":"I/O 与网络","title":"Base.Meta.@dump","text":"@dump expr\n\nShow every part of the representation of the given expression. Equivalent to dump(:(expr)).\n\n\n\n\n\n","category":"macro"},{"location":"base/io-network/#Base.readline","page":"I/O 与网络","title":"Base.readline","text":"readline(io::IO=stdin; keep::Bool=false)\nreadline(filename::AbstractString; keep::Bool=false)\n\nRead a single line of text from the given I/O stream or file (defaults to stdin). When reading from a file, the text is assumed to be encoded in UTF-8. Lines in the input end with '\\n' or \"\\r\\n\" or the end of an input stream. When keep is false (as it is by default), these trailing newline characters are removed from the line before it is returned. When keep is true, they are returned as part of the line.\n\nExamples\n\njulia> open(\"my_file.txt\", \"w\") do io\n write(io, \"JuliaLang is a GitHub organization.\\nIt has many members.\\n\");\n end\n57\n\njulia> readline(\"my_file.txt\")\n\"JuliaLang is a GitHub organization.\"\n\njulia> readline(\"my_file.txt\", keep=true)\n\"JuliaLang is a GitHub organization.\\n\"\n\njulia> rm(\"my_file.txt\")\n\njulia> print(\"Enter your name: \")\nEnter your name:\n\njulia> your_name = readline()\nLogan\n\"Logan\"\n\n\n\n\n\n","category":"function"},{"location":"base/io-network/#Base.readuntil","page":"I/O 与网络","title":"Base.readuntil","text":"readuntil(stream::IO, delim; keep::Bool = false)\nreaduntil(filename::AbstractString, delim; keep::Bool = false)\n\nRead a string from an I/O stream or a file, up to the given delimiter. The delimiter can be a UInt8, AbstractChar, string, or vector. Keyword argument keep controls whether the delimiter is included in the result. The text is assumed to be encoded in UTF-8.\n\nExamples\n\njulia> open(\"my_file.txt\", \"w\") do io\n write(io, \"JuliaLang is a GitHub organization.\\nIt has many members.\\n\");\n end\n57\n\njulia> readuntil(\"my_file.txt\", 'L')\n\"Julia\"\n\njulia> readuntil(\"my_file.txt\", '.', keep = true)\n\"JuliaLang is a GitHub organization.\"\n\njulia> rm(\"my_file.txt\")\n\n\n\n\n\n","category":"function"},{"location":"base/io-network/#Base.readlines","page":"I/O 与网络","title":"Base.readlines","text":"readlines(io::IO=stdin; keep::Bool=false)\nreadlines(filename::AbstractString; keep::Bool=false)\n\nRead all lines of an I/O stream or a file as a vector of strings. Behavior is equivalent to saving the result of reading readline repeatedly with the same arguments and saving the resulting lines as a vector of strings. See also eachline to iterate over the lines without reading them all at once.\n\nExamples\n\njulia> open(\"my_file.txt\", \"w\") do io\n write(io, \"JuliaLang is a GitHub organization.\\nIt has many members.\\n\");\n end\n57\n\njulia> readlines(\"my_file.txt\")\n2-element Vector{String}:\n \"JuliaLang is a GitHub organization.\"\n \"It has many members.\"\n\njulia> readlines(\"my_file.txt\", keep=true)\n2-element Vector{String}:\n \"JuliaLang is a GitHub organization.\\n\"\n \"It has many members.\\n\"\n\njulia> rm(\"my_file.txt\")\n\n\n\n\n\n","category":"function"},{"location":"base/io-network/#Base.eachline","page":"I/O 与网络","title":"Base.eachline","text":"eachline(io::IO=stdin; keep::Bool=false)\neachline(filename::AbstractString; keep::Bool=false)\n\nCreate an iterable EachLine object that will yield each line from an I/O stream or a file. Iteration calls readline on the stream argument repeatedly with keep passed through, determining whether trailing end-of-line characters are retained. When called with a file name, the file is opened once at the beginning of iteration and closed at the end. If iteration is interrupted, the file will be closed when the EachLine object is garbage collected.\n\nTo iterate over each line of a String, eachline(IOBuffer(str)) can be used.\n\nIterators.reverse can be used on an EachLine object to read the lines in reverse order (for files, buffers, and other I/O streams supporting seek), and first or last can be used to extract the initial or final lines, respectively.\n\nExamples\n\njulia> open(\"my_file.txt\", \"w\") do io\n write(io, \"JuliaLang is a GitHub organization.\\n It has many members.\\n\");\n end;\n\njulia> for line in eachline(\"my_file.txt\")\n print(line)\n end\nJuliaLang is a GitHub organization. It has many members.\n\njulia> rm(\"my_file.txt\");\n\ncompat: Julia 1.8\nJulia 1.8 is required to use Iterators.reverse or last with eachline iterators.\n\n\n\n\n\n","category":"function"},{"location":"base/io-network/#Base.displaysize","page":"I/O 与网络","title":"Base.displaysize","text":"displaysize([io::IO]) -> (lines, columns)\n\nReturn the nominal size of the screen that may be used for rendering output to this IO object. If no input is provided, the environment variables LINES and COLUMNS are read. If those are not set, a default size of (24, 80) is returned.\n\nExamples\n\njulia> withenv(\"LINES\" => 30, \"COLUMNS\" => 100) do\n displaysize()\n end\n(30, 100)\n\nTo get your TTY size,\n\njulia> displaysize(stdout)\n(34, 147)\n\n\n\n\n\n","category":"function"},{"location":"base/io-network/#多媒体-I/O","page":"I/O 与网络","title":"多媒体 I/O","text":"","category":"section"},{"location":"base/io-network/","page":"I/O 与网络","title":"I/O 与网络","text":"就像文本输出用 print 实现,用户自定义类型可以通过重载 show 来指定其文本化表示, Julia 提供了一个应用于富多媒体输出的标准化机制 (例如图片、格式化文本、甚至音频和视频),由以下三部分组成:","category":"page"},{"location":"base/io-network/","page":"I/O 与网络","title":"I/O 与网络","text":"函数 display(x) 来请求一个 Julia 对象 x 最丰富的多媒体展示,并以纯文本作为后备模式。\n重载 show 允许指定用户自定义类型的任意多媒体表现形式(以标准MIME类型为键值)。\nMultimedia-capable display backends may be registered by subclassing a generic AbstractDisplay type 并通过 pushdisplay 将其压进显示后端的栈中。","category":"page"},{"location":"base/io-network/","page":"I/O 与网络","title":"I/O 与网络","text":"基础 Julia 运行环境只提供纯文本显示, 但是更富的显示可以通过加载外部模块或者使用图形化 Julia 环境 (比如基于 IPython 的 IJulia notebook)来实现。","category":"page"},{"location":"base/io-network/","page":"I/O 与网络","title":"I/O 与网络","text":"Base.AbstractDisplay\nBase.Multimedia.display\nBase.Multimedia.redisplay\nBase.Multimedia.displayable\nBase.show(::IO, ::Any, ::Any)\nBase.Multimedia.showable\nBase.repr(::MIME, ::Any)\nBase.MIME\nBase.@MIME_str","category":"page"},{"location":"base/io-network/#Base.Multimedia.AbstractDisplay","page":"I/O 与网络","title":"Base.Multimedia.AbstractDisplay","text":"AbstractDisplay\n\nAbstract supertype for rich display output devices. TextDisplay is a subtype of this.\n\n\n\n\n\n","category":"type"},{"location":"base/io-network/#Base.Multimedia.display","page":"I/O 与网络","title":"Base.Multimedia.display","text":"display(x)\ndisplay(d::AbstractDisplay, x)\ndisplay(mime, x)\ndisplay(d::AbstractDisplay, mime, x)\n\nDisplay x using the topmost applicable display in the display stack, typically using the richest supported multimedia output for x, with plain-text stdout output as a fallback. The display(d, x) variant attempts to display x on the given display d only, throwing a MethodError if d cannot display objects of this type.\n\nIn general, you cannot assume that display output goes to stdout (unlike print(x) or show(x)). For example, display(x) may open up a separate window with an image. display(x) means \"show x in the best way you can for the current output device(s).\" If you want REPL-like text output that is guaranteed to go to stdout, use show(stdout, \"text/plain\", x) instead.\n\nThere are also two variants with a mime argument (a MIME type string, such as \"image/png\"), which attempt to display x using the requested MIME type only, throwing a MethodError if this type is not supported by either the display(s) or by x. With these variants, one can also supply the \"raw\" data in the requested MIME type by passing x::AbstractString (for MIME types with text-based storage, such as text/html or application/postscript) or x::Vector{UInt8} (for binary MIME types).\n\nTo customize how instances of a type are displayed, overload show rather than display, as explained in the manual section on custom pretty-printing.\n\n\n\n\n\n","category":"function"},{"location":"base/io-network/#Base.Multimedia.redisplay","page":"I/O 与网络","title":"Base.Multimedia.redisplay","text":"redisplay(x)\nredisplay(d::AbstractDisplay, x)\nredisplay(mime, x)\nredisplay(d::AbstractDisplay, mime, x)\n\nBy default, the redisplay functions simply call display. However, some display backends may override redisplay to modify an existing display of x (if any). Using redisplay is also a hint to the backend that x may be redisplayed several times, and the backend may choose to defer the display until (for example) the next interactive prompt.\n\n\n\n\n\n","category":"function"},{"location":"base/io-network/#Base.Multimedia.displayable","page":"I/O 与网络","title":"Base.Multimedia.displayable","text":"displayable(mime) -> Bool\ndisplayable(d::AbstractDisplay, mime) -> Bool\n\nReturns a boolean value indicating whether the given mime type (string) is displayable by any of the displays in the current display stack, or specifically by the display d in the second variant.\n\n\n\n\n\n","category":"function"},{"location":"base/io-network/#Base.show-Tuple{IO, Any, Any}","page":"I/O 与网络","title":"Base.show","text":"show(io::IO, mime, x)\n\nThe display functions ultimately call show in order to write an object x as a given mime type to a given I/O stream io (usually a memory buffer), if possible. In order to provide a rich multimedia representation of a user-defined type T, it is only necessary to define a new show method for T, via: show(io, ::MIME\"mime\", x::T) = ..., where mime is a MIME-type string and the function body calls write (or similar) to write that representation of x to io. (Note that the MIME\"\" notation only supports literal strings; to construct MIME types in a more flexible manner use MIME{Symbol(\"\")}.)\n\nFor example, if you define a MyImage type and know how to write it to a PNG file, you could define a function show(io, ::MIME\"image/png\", x::MyImage) = ... to allow your images to be displayed on any PNG-capable AbstractDisplay (such as IJulia). As usual, be sure to import Base.show in order to add new methods to the built-in Julia function show.\n\nTechnically, the MIME\"mime\" macro defines a singleton type for the given mime string, which allows us to exploit Julia's dispatch mechanisms in determining how to display objects of any given type.\n\nThe default MIME type is MIME\"text/plain\". There is a fallback definition for text/plain output that calls show with 2 arguments, so it is not always necessary to add a method for that case. If a type benefits from custom human-readable output though, show(::IO, ::MIME\"text/plain\", ::T) should be defined. For example, the Day type uses 1 day as the output for the text/plain MIME type, and Day(1) as the output of 2-argument show.\n\nContainer types generally implement 3-argument show by calling show(io, MIME\"text/plain\"(), x) for elements x, with :compact => true set in an IOContext passed as the first argument.\n\n\n\n\n\n","category":"method"},{"location":"base/io-network/#Base.Multimedia.showable","page":"I/O 与网络","title":"Base.Multimedia.showable","text":"showable(mime, x)\n\nReturns a boolean value indicating whether or not the object x can be written as the given mime type.\n\n(By default, this is determined automatically by the existence of the corresponding show method for typeof(x). Some types provide custom showable methods; for example, if the available MIME formats depend on the value of x.)\n\nExamples\n\njulia> showable(MIME(\"text/plain\"), rand(5))\ntrue\n\njulia> showable(\"image/png\", rand(5))\nfalse\n\n\n\n\n\n","category":"function"},{"location":"base/io-network/#Base.repr-Tuple{MIME, Any}","page":"I/O 与网络","title":"Base.repr","text":"repr(mime, x; context=nothing)\n\nReturns an AbstractString or Vector{UInt8} containing the representation of x in the requested mime type, as written by show(io, mime, x) (throwing a MethodError if no appropriate show is available). An AbstractString is returned for MIME types with textual representations (such as \"text/html\" or \"application/postscript\"), whereas binary data is returned as Vector{UInt8}. (The function istextmime(mime) returns whether or not Julia treats a given mime type as text.)\n\nThe optional keyword argument context can be set to :key=>value pair or an IO or IOContext object whose attributes are used for the I/O stream passed to show.\n\nAs a special case, if x is an AbstractString (for textual MIME types) or a Vector{UInt8} (for binary MIME types), the repr function assumes that x is already in the requested mime format and simply returns x. This special case does not apply to the \"text/plain\" MIME type. This is useful so that raw data can be passed to display(m::MIME, x).\n\nIn particular, repr(\"text/plain\", x) is typically a \"pretty-printed\" version of x designed for human consumption. See also repr(x) to instead return a string corresponding to show(x) that may be closer to how the value of x would be entered in Julia.\n\nExamples\n\njulia> A = [1 2; 3 4];\n\njulia> repr(\"text/plain\", A)\n\"2×2 Matrix{Int64}:\\n 1 2\\n 3 4\"\n\n\n\n\n\n","category":"method"},{"location":"base/io-network/#Base.Multimedia.MIME","page":"I/O 与网络","title":"Base.Multimedia.MIME","text":"MIME\n\nA type representing a standard internet data format. \"MIME\" stands for \"Multipurpose Internet Mail Extensions\", since the standard was originally used to describe multimedia attachments to email messages.\n\nA MIME object can be passed as the second argument to show to request output in that format.\n\nExamples\n\njulia> show(stdout, MIME(\"text/plain\"), \"hi\")\n\"hi\"\n\n\n\n\n\n","category":"type"},{"location":"base/io-network/#Base.Multimedia.@MIME_str","page":"I/O 与网络","title":"Base.Multimedia.@MIME_str","text":"@MIME_str\n\nA convenience macro for writing MIME types, typically used when adding methods to show. For example the syntax show(io::IO, ::MIME\"text/html\", x::MyType) = ... could be used to define how to write an HTML representation of MyType.\n\n\n\n\n\n","category":"macro"},{"location":"base/io-network/","page":"I/O 与网络","title":"I/O 与网络","text":"如上面提到的,用户可以定义新的显示后端。 例如,可以在窗口显示 PNG 图片的模块可以在 Julia 中注册这个能力, 以便为有 PNG 表示的类型调用 display(x) 时可以在模块窗口中自动显示图片。","category":"page"},{"location":"base/io-network/","page":"I/O 与网络","title":"I/O 与网络","text":"In order to define a new display backend, one should first create a subtype D of the abstract class AbstractDisplay. Then, for each MIME type (mime string) that can be displayed on D, one should define a function display(d::D, ::MIME\"mime\", x) = ... that displays x as that MIME type, usually by calling show(io, mime, x) or repr(io, mime, x). A MethodError should be thrown if x cannot be displayed as that MIME type; this is automatic if one calls show or repr. Finally, one should define a function display(d::D, x) that queries showable(mime, x) for the mime types supported by D and displays the \"best\" one; a MethodError should be thrown if no supported MIME types are found for x. Similarly, some subtypes may wish to override redisplay(d::D, ...). (Again, one should import Base.display to add new methods to display.) The return values of these functions are up to the implementation (since in some cases it may be useful to return a display \"handle\" of some type). The display functions for D can then be called directly, but they can also be invoked automatically from display(x) simply by pushing a new display onto the display-backend stack with:","category":"page"},{"location":"base/io-network/","page":"I/O 与网络","title":"I/O 与网络","text":"Base.Multimedia.pushdisplay\nBase.Multimedia.popdisplay\nBase.Multimedia.TextDisplay\nBase.Multimedia.istextmime","category":"page"},{"location":"base/io-network/#Base.Multimedia.pushdisplay","page":"I/O 与网络","title":"Base.Multimedia.pushdisplay","text":"pushdisplay(d::AbstractDisplay)\n\nPushes a new display d on top of the global display-backend stack. Calling display(x) or display(mime, x) will display x on the topmost compatible backend in the stack (i.e., the topmost backend that does not throw a MethodError).\n\n\n\n\n\n","category":"function"},{"location":"base/io-network/#Base.Multimedia.popdisplay","page":"I/O 与网络","title":"Base.Multimedia.popdisplay","text":"popdisplay()\npopdisplay(d::AbstractDisplay)\n\nPop the topmost backend off of the display-backend stack, or the topmost copy of d in the second variant.\n\n\n\n\n\n","category":"function"},{"location":"base/io-network/#Base.Multimedia.TextDisplay","page":"I/O 与网络","title":"Base.Multimedia.TextDisplay","text":"TextDisplay(io::IO)\n\nReturns a TextDisplay <: AbstractDisplay, which displays any object as the text/plain MIME type (by default), writing the text representation to the given I/O stream. (This is how objects are printed in the Julia REPL.)\n\n\n\n\n\n","category":"type"},{"location":"base/io-network/#Base.Multimedia.istextmime","page":"I/O 与网络","title":"Base.Multimedia.istextmime","text":"istextmime(m::MIME)\n\nDetermine whether a MIME type is text data. MIME types are assumed to be binary data except for a set of types known to be text data (possibly Unicode).\n\nExamples\n\njulia> istextmime(MIME(\"text/plain\"))\ntrue\n\njulia> istextmime(MIME(\"image/png\"))\nfalse\n\n\n\n\n\n","category":"function"},{"location":"base/io-network/#网络-I/O","page":"I/O 与网络","title":"网络 I/O","text":"","category":"section"},{"location":"base/io-network/","page":"I/O 与网络","title":"I/O 与网络","text":"Base.bytesavailable\nBase.ntoh\nBase.hton\nBase.ltoh\nBase.htol\nBase.ENDIAN_BOM","category":"page"},{"location":"base/io-network/#Base.bytesavailable","page":"I/O 与网络","title":"Base.bytesavailable","text":"bytesavailable(io)\n\nReturn the number of bytes available for reading before a read from this stream or buffer will block.\n\nExamples\n\njulia> io = IOBuffer(\"JuliaLang is a GitHub organization\");\n\njulia> bytesavailable(io)\n34\n\n\n\n\n\n","category":"function"},{"location":"base/io-network/#Base.ntoh","page":"I/O 与网络","title":"Base.ntoh","text":"ntoh(x)\n\nConvert the endianness of a value from Network byte order (big-endian) to that used by the Host.\n\n\n\n\n\n","category":"function"},{"location":"base/io-network/#Base.hton","page":"I/O 与网络","title":"Base.hton","text":"hton(x)\n\nConvert the endianness of a value from that used by the Host to Network byte order (big-endian).\n\n\n\n\n\n","category":"function"},{"location":"base/io-network/#Base.ltoh","page":"I/O 与网络","title":"Base.ltoh","text":"ltoh(x)\n\nConvert the endianness of a value from Little-endian to that used by the Host.\n\n\n\n\n\n","category":"function"},{"location":"base/io-network/#Base.htol","page":"I/O 与网络","title":"Base.htol","text":"htol(x)\n\nConvert the endianness of a value from that used by the Host to Little-endian.\n\n\n\n\n\n","category":"function"},{"location":"base/io-network/#Base.ENDIAN_BOM","page":"I/O 与网络","title":"Base.ENDIAN_BOM","text":"ENDIAN_BOM\n\nThe 32-bit byte-order-mark indicates the native byte order of the host machine. Little-endian machines will contain the value 0x04030201. Big-endian machines will contain the value 0x01020304.\n\n\n\n\n\n","category":"constant"},{"location":"base/c/#C-接口","page":"C 接口","title":"C 接口","text":"","category":"section"},{"location":"base/c/","page":"C 接口","title":"C 接口","text":"@ccall\nccall\nCore.Intrinsics.cglobal\nBase.@cfunction\nBase.CFunction\nBase.unsafe_convert\nBase.cconvert\nBase.unsafe_load\nBase.unsafe_store!\nBase.unsafe_copyto!{T}(::Ptr{T}, ::Ptr{T}, ::Any)\nBase.unsafe_copyto!{T}(::Array{T}, ::Any, ::Array{T}, ::Any, ::Any)\nBase.copyto!\nBase.pointer\nBase.unsafe_wrap{T,N}(::Union{Type{Array},Type{Array{T}},Type{Array{T,N}}}, ::Ptr{T}, ::NTuple{N,Int})\nBase.pointer_from_objref\nBase.unsafe_pointer_to_objref\nBase.disable_sigint\nBase.reenable_sigint\nBase.exit_on_sigint\nBase.systemerror\nBase.windowserror\nCore.Ptr\nCore.Ref\nBase.isassigned(::Base.RefValue)\nBase.Cchar\nBase.Cuchar\nBase.Cshort\nBase.Cstring\nBase.Cushort\nBase.Cint\nBase.Cuint\nBase.Clong\nBase.Culong\nBase.Clonglong\nBase.Culonglong\nBase.Cintmax_t\nBase.Cuintmax_t\nBase.Csize_t\nBase.Cssize_t\nBase.Cptrdiff_t\nBase.Cwchar_t\nBase.Cwstring\nBase.Cfloat\nBase.Cdouble","category":"page"},{"location":"base/c/#Base.@ccall","page":"C 接口","title":"Base.@ccall","text":"@ccall library.function_name(argvalue1::argtype1, ...)::returntype\n@ccall function_name(argvalue1::argtype1, ...)::returntype\n@ccall $function_pointer(argvalue1::argtype1, ...)::returntype\n\nCall a function in a C-exported shared library, specified by library.function_name, where library is a string constant or literal. The library may be omitted, in which case the function_name is resolved in the current process. Alternatively, @ccall may also be used to call a function pointer $function_pointer, such as one returned by dlsym.\n\nEach argvalue to @ccall is converted to the corresponding argtype, by automatic insertion of calls to unsafe_convert(argtype, cconvert(argtype, argvalue)). (See also the documentation for unsafe_convert and cconvert for further details.) In most cases, this simply results in a call to convert(argtype, argvalue).\n\nExamples\n\n@ccall strlen(s::Cstring)::Csize_t\n\nThis calls the C standard library function:\n\nsize_t strlen(char *)\n\nwith a Julia variable named s. See also ccall.\n\nVarargs are supported with the following convention:\n\n@ccall printf(\"%s = %d\"::Cstring ; \"foo\"::Cstring, foo::Cint)::Cint\n\nThe semicolon is used to separate required arguments (of which there must be at least one) from variadic arguments.\n\nExample using an external library:\n\n# C signature of g_uri_escape_string:\n# char *g_uri_escape_string(const char *unescaped, const char *reserved_chars_allowed, gboolean allow_utf8);\n\nconst glib = \"libglib-2.0\"\n@ccall glib.g_uri_escape_string(my_uri::Cstring, \":/\"::Cstring, true::Cint)::Cstring\n\nThe string literal could also be used directly before the function name, if desired \"libglib-2.0\".g_uri_escape_string(...\n\n\n\n\n\n","category":"macro"},{"location":"base/c/#ccall","page":"C 接口","title":"ccall","text":"ccall((function_name, library), returntype, (argtype1, ...), argvalue1, ...)\nccall(function_name, returntype, (argtype1, ...), argvalue1, ...)\nccall(function_pointer, returntype, (argtype1, ...), argvalue1, ...)\n\nCall a function in a C-exported shared library, specified by the tuple (function_name, library), where each component is either a string or symbol. Instead of specifying a library, one can also use a function_name symbol or string, which is resolved in the current process. Alternatively, ccall may also be used to call a function pointer function_pointer, such as one returned by dlsym.\n\nNote that the argument type tuple must be a literal tuple, and not a tuple-valued variable or expression.\n\nEach argvalue to the ccall will be converted to the corresponding argtype, by automatic insertion of calls to unsafe_convert(argtype, cconvert(argtype, argvalue)). (See also the documentation for unsafe_convert and cconvert for further details.) In most cases, this simply results in a call to convert(argtype, argvalue).\n\n\n\n\n\n","category":"keyword"},{"location":"base/c/#Core.Intrinsics.cglobal","page":"C 接口","title":"Core.Intrinsics.cglobal","text":"cglobal((symbol, library) [, type=Cvoid])\n\nObtain a pointer to a global variable in a C-exported shared library, specified exactly as in ccall. Returns a Ptr{Type}, defaulting to Ptr{Cvoid} if no Type argument is supplied. The values can be read or written by unsafe_load or unsafe_store!, respectively.\n\n\n\n\n\n","category":"function"},{"location":"base/c/#Base.@cfunction","page":"C 接口","title":"Base.@cfunction","text":"@cfunction(callable, ReturnType, (ArgumentTypes...,)) -> Ptr{Cvoid}\n@cfunction($callable, ReturnType, (ArgumentTypes...,)) -> CFunction\n\nGenerate a C-callable function pointer from the Julia function callable for the given type signature. To pass the return value to a ccall, use the argument type Ptr{Cvoid} in the signature.\n\nNote that the argument type tuple must be a literal tuple, and not a tuple-valued variable or expression (although it can include a splat expression). And that these arguments will be evaluated in global scope during compile-time (not deferred until runtime). Adding a '$' in front of the function argument changes this to instead create a runtime closure over the local variable callable (this is not supported on all architectures).\n\nSee manual section on ccall and cfunction usage.\n\nExamples\n\njulia> function foo(x::Int, y::Int)\n return x + y\n end\n\njulia> @cfunction(foo, Int, (Int, Int))\nPtr{Cvoid} @0x000000001b82fcd0\n\n\n\n\n\n","category":"macro"},{"location":"base/c/#Base.CFunction","page":"C 接口","title":"Base.CFunction","text":"CFunction struct\n\nGarbage-collection handle for the return value from @cfunction when the first argument is annotated with '$'. Like all cfunction handles, it should be passed to ccall as a Ptr{Cvoid}, and will be converted automatically at the call site to the appropriate type.\n\nSee @cfunction.\n\n\n\n\n\n","category":"type"},{"location":"base/c/#Base.unsafe_convert","page":"C 接口","title":"Base.unsafe_convert","text":"unsafe_convert(T, x)\n\nConvert x to a C argument of type T where the input x must be the return value of cconvert(T, ...).\n\nIn cases where convert would need to take a Julia object and turn it into a Ptr, this function should be used to define and perform that conversion.\n\nBe careful to ensure that a Julia reference to x exists as long as the result of this function will be used. Accordingly, the argument x to this function should never be an expression, only a variable name or field reference. For example, x=a.b.c is acceptable, but x=[a,b,c] is not.\n\nThe unsafe prefix on this function indicates that using the result of this function after the x argument to this function is no longer accessible to the program may cause undefined behavior, including program corruption or segfaults, at any later time.\n\nSee also cconvert\n\n\n\n\n\n","category":"function"},{"location":"base/c/#Base.cconvert","page":"C 接口","title":"Base.cconvert","text":"cconvert(T,x)\n\nConvert x to a value to be passed to C code as type T, typically by calling convert(T, x).\n\nIn cases where x cannot be safely converted to T, unlike convert, cconvert may return an object of a type different from T, which however is suitable for unsafe_convert to handle. The result of this function should be kept valid (for the GC) until the result of unsafe_convert is not needed anymore. This can be used to allocate memory that will be accessed by the ccall. If multiple objects need to be allocated, a tuple of the objects can be used as return value.\n\nNeither convert nor cconvert should take a Julia object and turn it into a Ptr.\n\n\n\n\n\n","category":"function"},{"location":"base/c/#Base.unsafe_load","page":"C 接口","title":"Base.unsafe_load","text":"unsafe_load(p::Ptr{T}, i::Integer=1)\n\nLoad a value of type T from the address of the ith element (1-indexed) starting at p. This is equivalent to the C expression p[i-1].\n\nThe unsafe prefix on this function indicates that no validation is performed on the pointer p to ensure that it is valid. Incorrect usage may segfault your program or return garbage answers, in the same manner as C.\n\n\n\n\n\n","category":"function"},{"location":"base/c/#Base.unsafe_store!","page":"C 接口","title":"Base.unsafe_store!","text":"unsafe_store!(p::Ptr{T}, x, i::Integer=1)\n\nStore a value of type T to the address of the ith element (1-indexed) starting at p. This is equivalent to the C expression p[i-1] = x.\n\nThe unsafe prefix on this function indicates that no validation is performed on the pointer p to ensure that it is valid. Incorrect usage may corrupt or segfault your program, in the same manner as C.\n\n\n\n\n\n","category":"function"},{"location":"base/c/#Base.unsafe_copyto!-Union{Tuple{T}, Tuple{Ptr{T}, Ptr{T}, Any}} where T","page":"C 接口","title":"Base.unsafe_copyto!","text":"unsafe_copyto!(dest::Ptr{T}, src::Ptr{T}, N)\n\nCopy N elements from a source pointer to a destination, with no checking. The size of an element is determined by the type of the pointers.\n\nThe unsafe prefix on this function indicates that no validation is performed on the pointers dest and src to ensure that they are valid. Incorrect usage may corrupt or segfault your program, in the same manner as C.\n\n\n\n\n\n","category":"method"},{"location":"base/c/#Base.unsafe_copyto!-Union{Tuple{T}, Tuple{Array{T}, Any, Array{T}, Any, Any}} where T","page":"C 接口","title":"Base.unsafe_copyto!","text":"unsafe_copyto!(dest::Array, do, src::Array, so, N)\n\nCopy N elements from a source array to a destination, starting at offset so in the source and do in the destination (1-indexed).\n\nThe unsafe prefix on this function indicates that no validation is performed to ensure that N is inbounds on either array. Incorrect usage may corrupt or segfault your program, in the same manner as C.\n\n\n\n\n\n","category":"method"},{"location":"base/c/#Base.copyto!","page":"C 接口","title":"Base.copyto!","text":"copyto!(dest, do, src, so, N)\n\nCopy N elements from collection src starting at offset so, to array dest starting at offset do. Return dest.\n\n\n\n\n\ncopyto!(dest::AbstractArray, src) -> dest\n\nCopy all elements from collection src to array dest, whose length must be greater than or equal to the length n of src. The first n elements of dest are overwritten, the other elements are left untouched.\n\nSee also copy!, copy.\n\nExamples\n\njulia> x = [1., 0., 3., 0., 5.];\n\njulia> y = zeros(7);\n\njulia> copyto!(y, x);\n\njulia> y\n7-element Vector{Float64}:\n 1.0\n 0.0\n 3.0\n 0.0\n 5.0\n 0.0\n 0.0\n\n\n\n\n\ncopyto!(dest, Rdest::CartesianIndices, src, Rsrc::CartesianIndices) -> dest\n\nCopy the block of src in the range of Rsrc to the block of dest in the range of Rdest. The sizes of the two regions must match.\n\nExamples\n\njulia> A = zeros(5, 5);\n\njulia> B = [1 2; 3 4];\n\njulia> Ainds = CartesianIndices((2:3, 2:3));\n\njulia> Binds = CartesianIndices(B);\n\njulia> copyto!(A, Ainds, B, Binds)\n5×5 Matrix{Float64}:\n 0.0 0.0 0.0 0.0 0.0\n 0.0 1.0 2.0 0.0 0.0\n 0.0 3.0 4.0 0.0 0.0\n 0.0 0.0 0.0 0.0 0.0\n 0.0 0.0 0.0 0.0 0.0\n\n\n\n\n\ncopyto!(dest::AbstractMatrix, src::UniformScaling)\n\nCopies a UniformScaling onto a matrix.\n\ncompat: Julia 1.1\nIn Julia 1.0 this method only supported a square destination matrix. Julia 1.1. added support for a rectangular matrix.\n\n\n\n\n\n","category":"function"},{"location":"base/c/#Base.pointer","page":"C 接口","title":"Base.pointer","text":"pointer(array [, index])\n\nGet the native address of an array or string, optionally at a given location index.\n\nThis function is \"unsafe\". Be careful to ensure that a Julia reference to array exists as long as this pointer will be used. The GC.@preserve macro should be used to protect the array argument from garbage collection within a given block of code.\n\nCalling Ref(array[, index]) is generally preferable to this function as it guarantees validity.\n\n\n\n\n\n","category":"function"},{"location":"base/c/#Base.unsafe_wrap-Union{Tuple{N}, Tuple{T}, Tuple{Union{Type{Array}, Type{Array{T}}, Type{Array{T, N}}}, Ptr{T}, Tuple{Vararg{Int64, N}}}} where {T, N}","page":"C 接口","title":"Base.unsafe_wrap","text":"unsafe_wrap(Array, pointer::Ptr{T}, dims; own = false)\n\nWrap a Julia Array object around the data at the address given by pointer, without making a copy. The pointer element type T determines the array element type. dims is either an integer (for a 1d array) or a tuple of the array dimensions. own optionally specifies whether Julia should take ownership of the memory, calling free on the pointer when the array is no longer referenced.\n\nThis function is labeled \"unsafe\" because it will crash if pointer is not a valid memory address to data of the requested length.\n\n\n\n\n\n","category":"method"},{"location":"base/c/#Base.pointer_from_objref","page":"C 接口","title":"Base.pointer_from_objref","text":"pointer_from_objref(x)\n\nGet the memory address of a Julia object as a Ptr. The existence of the resulting Ptr will not protect the object from garbage collection, so you must ensure that the object remains referenced for the whole time that the Ptr will be used.\n\nThis function may not be called on immutable objects, since they do not have stable memory addresses.\n\nSee also unsafe_pointer_to_objref.\n\n\n\n\n\n","category":"function"},{"location":"base/c/#Base.unsafe_pointer_to_objref","page":"C 接口","title":"Base.unsafe_pointer_to_objref","text":"unsafe_pointer_to_objref(p::Ptr)\n\nConvert a Ptr to an object reference. Assumes the pointer refers to a valid heap-allocated Julia object. If this is not the case, undefined behavior results, hence this function is considered \"unsafe\" and should be used with care.\n\nSee also pointer_from_objref.\n\n\n\n\n\n","category":"function"},{"location":"base/c/#Base.disable_sigint","page":"C 接口","title":"Base.disable_sigint","text":"disable_sigint(f::Function)\n\nDisable Ctrl-C handler during execution of a function on the current task, for calling external code that may call julia code that is not interrupt safe. Intended to be called using do block syntax as follows:\n\ndisable_sigint() do\n # interrupt-unsafe code\n ...\nend\n\nThis is not needed on worker threads (Threads.threadid() != 1) since the InterruptException will only be delivered to the master thread. External functions that do not call julia code or julia runtime automatically disable sigint during their execution.\n\n\n\n\n\n","category":"function"},{"location":"base/c/#Base.reenable_sigint","page":"C 接口","title":"Base.reenable_sigint","text":"reenable_sigint(f::Function)\n\nRe-enable Ctrl-C handler during execution of a function. Temporarily reverses the effect of disable_sigint.\n\n\n\n\n\n","category":"function"},{"location":"base/c/#Base.exit_on_sigint","page":"C 接口","title":"Base.exit_on_sigint","text":"exit_on_sigint(on::Bool)\n\nSet exit_on_sigint flag of the julia runtime. If false, Ctrl-C (SIGINT) is capturable as InterruptException in try block. This is the default behavior in REPL, any code run via -e and -E and in Julia script run with -i option.\n\nIf true, InterruptException is not thrown by Ctrl-C. Running code upon such event requires atexit. This is the default behavior in Julia script run without -i option.\n\ncompat: Julia 1.5\nFunction exit_on_sigint requires at least Julia 1.5.\n\n\n\n\n\n","category":"function"},{"location":"base/c/#Base.systemerror","page":"C 接口","title":"Base.systemerror","text":"systemerror(sysfunc[, errno::Cint=Libc.errno()])\nsystemerror(sysfunc, iftrue::Bool)\n\nRaises a SystemError for errno with the descriptive string sysfunc if iftrue is true\n\n\n\n\n\n","category":"function"},{"location":"base/c/#Base.windowserror","page":"C 接口","title":"Base.windowserror","text":"windowserror(sysfunc[, code::UInt32=Libc.GetLastError()])\nwindowserror(sysfunc, iftrue::Bool)\n\nLike systemerror, but for Windows API functions that use GetLastError to return an error code instead of setting errno.\n\n\n\n\n\n","category":"function"},{"location":"base/c/#Core.Ptr","page":"C 接口","title":"Core.Ptr","text":"Ptr{T}\n\nA memory address referring to data of type T. However, there is no guarantee that the memory is actually valid, or that it actually represents data of the specified type.\n\n\n\n\n\n","category":"type"},{"location":"base/c/#Core.Ref","page":"C 接口","title":"Core.Ref","text":"Ref{T}\n\nAn object that safely references data of type T. This type is guaranteed to point to valid, Julia-allocated memory of the correct type. The underlying data is protected from freeing by the garbage collector as long as the Ref itself is referenced.\n\nIn Julia, Ref objects are dereferenced (loaded or stored) with [].\n\nCreation of a Ref to a value x of type T is usually written Ref(x). Additionally, for creating interior pointers to containers (such as Array or Ptr), it can be written Ref(a, i) for creating a reference to the i-th element of a.\n\nRef{T}() creates a reference to a value of type T without initialization. For a bitstype T, the value will be whatever currently resides in the memory allocated. For a non-bitstype T, the reference will be undefined and attempting to dereference it will result in an error, \"UndefRefError: access to undefined reference\".\n\nTo check if a Ref is an undefined reference, use isassigned(ref::RefValue). For example, isassigned(Ref{T}()) is false if T is not a bitstype. If T is a bitstype, isassigned(Ref{T}()) will always be true.\n\nWhen passed as a ccall argument (either as a Ptr or Ref type), a Ref object will be converted to a native pointer to the data it references. For most T, or when converted to a Ptr{Cvoid}, this is a pointer to the object data. When T is an isbits type, this value may be safely mutated, otherwise mutation is strictly undefined behavior.\n\nAs a special case, setting T = Any will instead cause the creation of a pointer to the reference itself when converted to a Ptr{Any} (a jl_value_t const* const* if T is immutable, else a jl_value_t *const *). When converted to a Ptr{Cvoid}, it will still return a pointer to the data region as for any other T.\n\nA C_NULL instance of Ptr can be passed to a ccall Ref argument to initialize it.\n\nUse in broadcasting\n\nRef is sometimes used in broadcasting in order to treat the referenced values as a scalar.\n\nExamples\n\njulia> Ref(5)\nBase.RefValue{Int64}(5)\n\njulia> isa.(Ref([1,2,3]), [Array, Dict, Int]) # Treat reference values as scalar during broadcasting\n3-element BitVector:\n 1\n 0\n 0\n\njulia> Ref{Function}() # Undefined reference to a non-bitstype, Function\nBase.RefValue{Function}(#undef)\n\njulia> try\n Ref{Function}()[] # Dereferencing an undefined reference will result in an error\n catch e\n println(e)\n end\nUndefRefError()\n\njulia> Ref{Int64}()[]; # A reference to a bitstype refers to an undetermined value if not given\n\njulia> isassigned(Ref{Int64}()) # A reference to a bitstype is always assigned\ntrue\n\njulia> Ref{Int64}(0)[] == 0 # Explicitly give a value for a bitstype reference\ntrue\n\n\n\n\n\n","category":"type"},{"location":"base/c/#Base.isassigned-Tuple{Base.RefValue}","page":"C 接口","title":"Base.isassigned","text":"isassigned(ref::RefValue) -> Bool\n\nTest whether the given Ref is associated with a value. This is always true for a Ref of a bitstype object. Return false if the reference is undefined.\n\nExamples\n\njulia> ref = Ref{Function}()\nBase.RefValue{Function}(#undef)\n\njulia> isassigned(ref)\nfalse\n\njulia> ref[] = (foobar(x) = x)\nfoobar (generic function with 1 method)\n\njulia> isassigned(ref)\ntrue\n\njulia> isassigned(Ref{Int}())\ntrue\n\n\n\n\n\n","category":"method"},{"location":"base/c/#Base.Cchar","page":"C 接口","title":"Base.Cchar","text":"Cchar\n\nEquivalent to the native char c-type.\n\n\n\n\n\n","category":"type"},{"location":"base/c/#Base.Cuchar","page":"C 接口","title":"Base.Cuchar","text":"Cuchar\n\nEquivalent to the native unsigned char c-type (UInt8).\n\n\n\n\n\n","category":"type"},{"location":"base/c/#Base.Cshort","page":"C 接口","title":"Base.Cshort","text":"Cshort\n\nEquivalent to the native signed short c-type (Int16).\n\n\n\n\n\n","category":"type"},{"location":"base/c/#Base.Cstring","page":"C 接口","title":"Base.Cstring","text":"Cstring\n\nA C-style string composed of the native character type Cchars. Cstrings are NUL-terminated. For C-style strings composed of the native wide character type, see Cwstring. For more information about string interopability with C, see the manual.\n\n\n\n\n\n","category":"type"},{"location":"base/c/#Base.Cushort","page":"C 接口","title":"Base.Cushort","text":"Cushort\n\nEquivalent to the native unsigned short c-type (UInt16).\n\n\n\n\n\n","category":"type"},{"location":"base/c/#Base.Cint","page":"C 接口","title":"Base.Cint","text":"Cint\n\nEquivalent to the native signed int c-type (Int32).\n\n\n\n\n\n","category":"type"},{"location":"base/c/#Base.Cuint","page":"C 接口","title":"Base.Cuint","text":"Cuint\n\nEquivalent to the native unsigned int c-type (UInt32).\n\n\n\n\n\n","category":"type"},{"location":"base/c/#Base.Clong","page":"C 接口","title":"Base.Clong","text":"Clong\n\nEquivalent to the native signed long c-type.\n\n\n\n\n\n","category":"type"},{"location":"base/c/#Base.Culong","page":"C 接口","title":"Base.Culong","text":"Culong\n\nEquivalent to the native unsigned long c-type.\n\n\n\n\n\n","category":"type"},{"location":"base/c/#Base.Clonglong","page":"C 接口","title":"Base.Clonglong","text":"Clonglong\n\nEquivalent to the native signed long long c-type (Int64).\n\n\n\n\n\n","category":"type"},{"location":"base/c/#Base.Culonglong","page":"C 接口","title":"Base.Culonglong","text":"Culonglong\n\nEquivalent to the native unsigned long long c-type (UInt64).\n\n\n\n\n\n","category":"type"},{"location":"base/c/#Base.Cintmax_t","page":"C 接口","title":"Base.Cintmax_t","text":"Cintmax_t\n\nEquivalent to the native intmax_t c-type (Int64).\n\n\n\n\n\n","category":"type"},{"location":"base/c/#Base.Cuintmax_t","page":"C 接口","title":"Base.Cuintmax_t","text":"Cuintmax_t\n\nEquivalent to the native uintmax_t c-type (UInt64).\n\n\n\n\n\n","category":"type"},{"location":"base/c/#Base.Csize_t","page":"C 接口","title":"Base.Csize_t","text":"Csize_t\n\nEquivalent to the native size_t c-type (UInt).\n\n\n\n\n\n","category":"type"},{"location":"base/c/#Base.Cssize_t","page":"C 接口","title":"Base.Cssize_t","text":"Cssize_t\n\nEquivalent to the native ssize_t c-type.\n\n\n\n\n\n","category":"type"},{"location":"base/c/#Base.Cptrdiff_t","page":"C 接口","title":"Base.Cptrdiff_t","text":"Cptrdiff_t\n\nEquivalent to the native ptrdiff_t c-type (Int).\n\n\n\n\n\n","category":"type"},{"location":"base/c/#Base.Cwchar_t","page":"C 接口","title":"Base.Cwchar_t","text":"Cwchar_t\n\nEquivalent to the native wchar_t c-type (Int32).\n\n\n\n\n\n","category":"type"},{"location":"base/c/#Base.Cwstring","page":"C 接口","title":"Base.Cwstring","text":"Cwstring\n\nA C-style string composed of the native wide character type Cwchar_ts. Cwstrings are NUL-terminated. For C-style strings composed of the native character type, see Cstring. For more information about string interopability with C, see the manual.\n\n\n\n\n\n","category":"type"},{"location":"base/c/#Base.Cfloat","page":"C 接口","title":"Base.Cfloat","text":"Cfloat\n\nEquivalent to the native float c-type (Float32).\n\n\n\n\n\n","category":"type"},{"location":"base/c/#Base.Cdouble","page":"C 接口","title":"Base.Cdouble","text":"Cdouble\n\nEquivalent to the native double c-type (Float64).\n\n\n\n\n\n","category":"type"},{"location":"base/c/#LLVM-接口","page":"C 接口","title":"LLVM 接口","text":"","category":"section"},{"location":"base/c/","page":"C 接口","title":"C 接口","text":"Core.Intrinsics.llvmcall","category":"page"},{"location":"base/c/#Core.Intrinsics.llvmcall","page":"C 接口","title":"Core.Intrinsics.llvmcall","text":"llvmcall(fun_ir::String, returntype, Tuple{argtype1, ...}, argvalue1, ...)\nllvmcall((mod_ir::String, entry_fn::String), returntype, Tuple{argtype1, ...}, argvalue1, ...)\nllvmcall((mod_bc::Vector{UInt8}, entry_fn::String), returntype, Tuple{argtype1, ...}, argvalue1, ...)\n\nCall the LLVM code provided in the first argument. There are several ways to specify this first argument:\n\nas a literal string, representing function-level IR (similar to an LLVM define block), with arguments are available as consecutive unnamed SSA variables (%0, %1, etc.);\nas a 2-element tuple, containing a string of module IR and a string representing the name of the entry-point function to call;\nas a 2-element tuple, but with the module provided as an Vector{UINt8} with bitcode.\n\nNote that contrary to ccall, the argument types must be specified as a tuple type, and not a tuple of types. All types, as well as the LLVM code, should be specified as literals, and not as variables or expressions (it may be necessary to use @eval to generate these literals).\n\nSee test/llvmcall.jl for usage examples.\n\n\n\n\n\n","category":"function"},{"location":"manual/mathematical-operations/#数学运算和初等函数","page":"数学运算和初等函数","title":"数学运算和初等函数","text":"","category":"section"},{"location":"manual/mathematical-operations/","page":"数学运算和初等函数","title":"数学运算和初等函数","text":"Julia 为它所有的基础数值类型,提供了整套的基础算术和位运算,也提供了一套高效、可移植的标准数学函数。","category":"page"},{"location":"manual/mathematical-operations/#算术运算符","page":"数学运算和初等函数","title":"算术运算符","text":"","category":"section"},{"location":"manual/mathematical-operations/","page":"数学运算和初等函数","title":"数学运算和初等函数","text":"以下算术运算符支持所有的原始数值类型:","category":"page"},{"location":"manual/mathematical-operations/","page":"数学运算和初等函数","title":"数学运算和初等函数","text":"表达式 名称 描述\n+x 一元加法运算符 全等操作\n-x 一元减法运算符 将值变为其相反数\nx + y 二元加法运算符 执行加法\nx - y 二元减法运算符 执行减法\nx * y 乘法运算符 执行乘法\nx / y 除法运算符 执行除法\nx ÷ y 整除 取 x / y 的整数部分\nx \\ y 反向除法 等价于 y / x\nx ^ y 幂操作符 x 的 y 次幂\nx % y 取余 等价于 rem(x,y)","category":"page"},{"location":"manual/mathematical-operations/","page":"数学运算和初等函数","title":"数学运算和初等函数","text":"除了优先级比二元操作符高以外,直接放在标识符或括号前的数字,如 2x 或 2(x+y) 还会被视为乘法。详见数值字面量系数。","category":"page"},{"location":"manual/mathematical-operations/","page":"数学运算和初等函数","title":"数学运算和初等函数","text":"Julia 的类型提升系统使得混合参数类型上的代数运算也能顺其自然的工作,请参考类型提升系统来了解更多内容。","category":"page"},{"location":"manual/mathematical-operations/","page":"数学运算和初等函数","title":"数学运算和初等函数","text":"符号 ÷ 可以通过输入 \\div 到 REPL 或 Julia IDE 的方式来打出. 更多信息参见 Unicode 输入表。","category":"page"},{"location":"manual/mathematical-operations/","page":"数学运算和初等函数","title":"数学运算和初等函数","text":"这里是使用算术运算符的一些简单例子:","category":"page"},{"location":"manual/mathematical-operations/","page":"数学运算和初等函数","title":"数学运算和初等函数","text":"julia> 1 + 2 + 3\n6\n\njulia> 1 - 2\n-1\n\njulia> 3*2/12\n0.5","category":"page"},{"location":"manual/mathematical-operations/","page":"数学运算和初等函数","title":"数学运算和初等函数","text":"习惯上我们会把优先运算的操作符紧邻操作数,比如 -x + 2 表示先要给 x 取反,然后再加 2 。","category":"page"},{"location":"manual/mathematical-operations/","page":"数学运算和初等函数","title":"数学运算和初等函数","text":"在乘法操作中,false 被视作 零。","category":"page"},{"location":"manual/mathematical-operations/","page":"数学运算和初等函数","title":"数学运算和初等函数","text":"julia> NaN * false\n0.0\n\njulia> false * Inf\n0.0","category":"page"},{"location":"manual/mathematical-operations/","page":"数学运算和初等函数","title":"数学运算和初等函数","text":"这在已知某些量为零时,可以避免 NaN 的传播。详细的动机参见:Knuth (1992)。","category":"page"},{"location":"manual/mathematical-operations/#布尔运算符","page":"数学运算和初等函数","title":"布尔运算符","text":"","category":"section"},{"location":"manual/mathematical-operations/","page":"数学运算和初等函数","title":"数学运算和初等函数","text":"Bool 类型支持以下布尔运算符:","category":"page"},{"location":"manual/mathematical-operations/","page":"数学运算和初等函数","title":"数学运算和初等函数","text":"表达式 名称\n!x 否定\nx && y 短路与\nx || y 短路或","category":"page"},{"location":"manual/mathematical-operations/","page":"数学运算和初等函数","title":"数学运算和初等函数","text":"否定将 true 更改为 false,反之亦然。链接页面上解释了逻辑短路。","category":"page"},{"location":"manual/mathematical-operations/","page":"数学运算和初等函数","title":"数学运算和初等函数","text":"请注意,Bool 是一个整数类型,所有常用的类型提升规则和数字运算符仍然对它适用。","category":"page"},{"location":"manual/mathematical-operations/#位运算符","page":"数学运算和初等函数","title":"位运算符","text":"","category":"section"},{"location":"manual/mathematical-operations/","page":"数学运算和初等函数","title":"数学运算和初等函数","text":"所有原始整数类型都支持以下位运算符:","category":"page"},{"location":"manual/mathematical-operations/","page":"数学运算和初等函数","title":"数学运算和初等函数","text":"表达式 名称\n~x 按位取反\nx & y 按位与\nx | y 按位或\nx ⊻ y 按位异或(逻辑异或)\nx ⊼ y 按位与(非与)\nx ⊽ y 按位或(非或)\nx >>> y 逻辑右移\nx >> y 算术右移\nx << y 逻辑/算术左移","category":"page"},{"location":"manual/mathematical-operations/","page":"数学运算和初等函数","title":"数学运算和初等函数","text":"以下是位运算符的一些示例:","category":"page"},{"location":"manual/mathematical-operations/","page":"数学运算和初等函数","title":"数学运算和初等函数","text":"julia> ~123\n-124\n\njulia> 123 & 234\n106\n\njulia> 123 | 234\n251\n\njulia> 123 ⊻ 234\n145\n\njulia> xor(123, 234)\n145\n\njulia> nand(123, 123)\n-124\n\njulia> 123 ⊼ 123\n-124\n\njulia> nor(123, 124)\n-128\n\njulia> 123 ⊽ 124\n-128\n\njulia> ~UInt32(123)\n0xffffff84\n\njulia> ~UInt8(123)\n0x84","category":"page"},{"location":"manual/mathematical-operations/#复合赋值运算符","page":"数学运算和初等函数","title":"复合赋值运算符","text":"","category":"section"},{"location":"manual/mathematical-operations/","page":"数学运算和初等函数","title":"数学运算和初等函数","text":"每一个二元运算符和位运算符都可以给左操作数复合赋值:方法是把 = 直接放在二元运算符后面。比如,x += 3 等价于 x = x + 3 。","category":"page"},{"location":"manual/mathematical-operations/","page":"数学运算和初等函数","title":"数学运算和初等函数","text":"julia> x = 1\n1\n\njulia> x += 3\n4\n\njulia> x\n4","category":"page"},{"location":"manual/mathematical-operations/","page":"数学运算和初等函数","title":"数学运算和初等函数","text":"二元运算符和位运算符的复合赋值操作符有下面几种:","category":"page"},{"location":"manual/mathematical-operations/","page":"数学运算和初等函数","title":"数学运算和初等函数","text":"+= -= *= /= \\= ÷= %= ^= &= |= ⊻= >>>= >>= <<=","category":"page"},{"location":"manual/mathematical-operations/","page":"数学运算和初等函数","title":"数学运算和初等函数","text":"note: Note\n复合赋值后会把变量重新绑定到左操作数上,所以变量的类型可能会改变。julia> x = 0x01; typeof(x)\nUInt8\n\njulia> x *= 2 # 与 x = x * 2 相同\n2\n\njulia> typeof(x)\nInt64","category":"page"},{"location":"manual/mathematical-operations/#man-dot-operators","page":"数学运算和初等函数","title":"向量化 “点” 运算符","text":"","category":"section"},{"location":"manual/mathematical-operations/","page":"数学运算和初等函数","title":"数学运算和初等函数","text":"Julia 中,每个二元运算符都有一个 “点” 运算符与之对应,例如 ^ 就有对应的 .^ 存在。这个对应的 .^ 被 Julia 自动地定义为逐元素地执行 ^ 运算。比如 [1,2,3] ^ 3 是非法的,因为数学上没有给(长宽不一样的)数组的立方下过定义。但是 [1,2,3] .^ 3 在 Julia 里是合法的,它会逐元素地执行 ^ 运算(或称向量化运算),得到 [1^3, 2^3, 3^3]。类似地,! 或 √ 这样的一元运算符,也都有一个对应的 .√ 用于执行逐元素运算。","category":"page"},{"location":"manual/mathematical-operations/","page":"数学运算和初等函数","title":"数学运算和初等函数","text":"julia> [1,2,3] .^ 3\n3-element Vector{Int64}:\n 1\n 8\n 27","category":"page"},{"location":"manual/mathematical-operations/","page":"数学运算和初等函数","title":"数学运算和初等函数","text":"更确切地说,a .^b 被解析为 “点运算” 调用 (^).(a,b),这会执行 广播 操作:该操作能结合数组和标量、相同大小的数组(进行元素之间的运算),甚至不同形状的数组(例如行、列向量结合生成矩阵)。此外,就像所有向量化的点运算调用一样,这些点运算符是融合的。例如,在计算关于数组 A 的表达式 2 .* A.^2 .+ sin.(A)(或者等价地,使用@. 宏,@. 2A^2 + sin(A)),Julia 只对 A 进行做一次循环,遍历 A 中的每个元素 a 并计算 2a^2 + sin(a)。特别的,类似 f.(g.(x)) 的嵌套点运算调用也是融合的,并且“相邻的”二元运算符表达式 x .+ 3 .* x.^2 可以等价转换为嵌套 dot 调用:(+).(x, (*).(3, (^).(x, 2)))。","category":"page"},{"location":"manual/mathematical-operations/","page":"数学运算和初等函数","title":"数学运算和初等函数","text":"除了点运算符,我们还有逐点赋值运算符,类似 a .+= b(或者 @. a += b)会被解析成 a .= a .+ b,这里的 .= 是一个融合的 in-place 运算,更多信息请查看 dot 文档)。","category":"page"},{"location":"manual/mathematical-operations/","page":"数学运算和初等函数","title":"数学运算和初等函数","text":"这个点语法,也能用在用户自定义的运算符上。例如,通过定义 ⊗(A,B) = kron(A,B) 可以为 Kronecker 积(kron)提供一个方便的中缀语法 A ⊗ B,那么配合点语法 [A,B] .⊗ [C,D] 就等价于 [A⊗C, B⊗D]。","category":"page"},{"location":"manual/mathematical-operations/","page":"数学运算和初等函数","title":"数学运算和初等函数","text":"将点运算符用于数值字面量可能会导致歧义。例如,1.+x 到底是表示 1. + x 还是 1 .+ x?这会令人疑惑。因此不允许使用这种语法,遇到这种情况时,必须明确地用空格消除歧义。","category":"page"},{"location":"manual/mathematical-operations/#数值比较","page":"数学运算和初等函数","title":"数值比较","text":"","category":"section"},{"location":"manual/mathematical-operations/","page":"数学运算和初等函数","title":"数学运算和初等函数","text":"标准的比较操作对所有原始数值类型有定义:","category":"page"},{"location":"manual/mathematical-operations/","page":"数学运算和初等函数","title":"数学运算和初等函数","text":"操作符 名称\n== 相等\n!=, ≠ 不等\n< 小于\n<=, ≤ 小于等于\n> 大于\n>=, ≥ 大于等于","category":"page"},{"location":"manual/mathematical-operations/","page":"数学运算和初等函数","title":"数学运算和初等函数","text":"下面是一些简单的例子:","category":"page"},{"location":"manual/mathematical-operations/","page":"数学运算和初等函数","title":"数学运算和初等函数","text":"julia> 1 == 1\ntrue\n\njulia> 1 == 2\nfalse\n\njulia> 1 != 2\ntrue\n\njulia> 1 == 1.0\ntrue\n\njulia> 1 < 2\ntrue\n\njulia> 1.0 > 3\nfalse\n\njulia> 1 >= 1.0\ntrue\n\njulia> -1 <= 1\ntrue\n\njulia> -1 <= -1\ntrue\n\njulia> -1 <= -2\nfalse\n\njulia> 3 < -0.5\nfalse","category":"page"},{"location":"manual/mathematical-operations/","page":"数学运算和初等函数","title":"数学运算和初等函数","text":"整数的比较方式是标准的按位比较,而浮点数的比较方式则遵循 IEEE 754 标准。","category":"page"},{"location":"manual/mathematical-operations/","page":"数学运算和初等函数","title":"数学运算和初等函数","text":"有限数的大小顺序,和我们所熟知的相同。\n+0 等于但不大于 -0.\nInf 等于自身,并且大于除了 NaN 外的所有数。\n-Inf 等于自身,并且小于除了 NaN 外的所有数。\nNaN 不等于、不小于且不大于任何数值,包括它自己。","category":"page"},{"location":"manual/mathematical-operations/","page":"数学运算和初等函数","title":"数学运算和初等函数","text":"NaN 不等于它自己这一点可能会令人感到惊奇,所以需要注意:","category":"page"},{"location":"manual/mathematical-operations/","page":"数学运算和初等函数","title":"数学运算和初等函数","text":"julia> NaN == NaN\nfalse\n\njulia> NaN != NaN\ntrue\n\njulia> NaN < NaN\nfalse\n\njulia> NaN > NaN\nfalse","category":"page"},{"location":"manual/mathematical-operations/","page":"数学运算和初等函数","title":"数学运算和初等函数","text":"当你将 NaN 和 数组 一起连用时,你就会感到头疼:","category":"page"},{"location":"manual/mathematical-operations/","page":"数学运算和初等函数","title":"数学运算和初等函数","text":"julia> [1 NaN] == [1 NaN]\nfalse","category":"page"},{"location":"manual/mathematical-operations/","page":"数学运算和初等函数","title":"数学运算和初等函数","text":"为此,Julia 给这些特别的数提供了下面几个额外的测试函数。这些函数在某些情况下很有用处,比如在做 hash 比较时。","category":"page"},{"location":"manual/mathematical-operations/","page":"数学运算和初等函数","title":"数学运算和初等函数","text":"函数 测试是否满足如下性质\nisequal(x, y) x 与 y 是完全相同的\nisfinite(x) x 是有限大的数字\nisinf(x) x 是(正/负)无穷大\nisnan(x) x 是 NaN","category":"page"},{"location":"manual/mathematical-operations/","page":"数学运算和初等函数","title":"数学运算和初等函数","text":"isequal 认为 NaN 之间是相等的:","category":"page"},{"location":"manual/mathematical-operations/","page":"数学运算和初等函数","title":"数学运算和初等函数","text":"julia> isequal(NaN, NaN)\ntrue\n\njulia> isequal([1 NaN], [1 NaN])\ntrue\n\njulia> isequal(NaN, NaN32)\ntrue","category":"page"},{"location":"manual/mathematical-operations/","page":"数学运算和初等函数","title":"数学运算和初等函数","text":"isequal 也能用来区分带符号的零:","category":"page"},{"location":"manual/mathematical-operations/","page":"数学运算和初等函数","title":"数学运算和初等函数","text":"julia> -0.0 == 0.0\ntrue\n\njulia> isequal(-0.0, 0.0)\nfalse","category":"page"},{"location":"manual/mathematical-operations/","page":"数学运算和初等函数","title":"数学运算和初等函数","text":"有符号整数、无符号整数以及浮点数之间的混合类型比较是很棘手的。开发者费了很大精力来确保 Julia 在这个问题上做的是正确的。","category":"page"},{"location":"manual/mathematical-operations/","page":"数学运算和初等函数","title":"数学运算和初等函数","text":"对于其它类型,isequal 会默认调用 ==,所以如果你想给自己的类型定义相等,那么就只需要为 == 增加一个方法。如果你想定义一个你自己的相等函数,你可能需要定义一个对应的 hash 方法,用于确保 isequal(x,y) 隐含着 hash(x) == hash(y)。","category":"page"},{"location":"manual/mathematical-operations/#链式比较","page":"数学运算和初等函数","title":"链式比较","text":"","category":"section"},{"location":"manual/mathematical-operations/","page":"数学运算和初等函数","title":"数学运算和初等函数","text":"与其他多数语言不同,就像 notable exception of Python 一样,Julia 允许链式比较:","category":"page"},{"location":"manual/mathematical-operations/","page":"数学运算和初等函数","title":"数学运算和初等函数","text":"julia> 1 < 2 <= 2 < 3 == 3 > 2 >= 1 == 1 < 3 != 5\ntrue","category":"page"},{"location":"manual/mathematical-operations/","page":"数学运算和初等函数","title":"数学运算和初等函数","text":"链式比较在写数值代码时特别方便,它使用 && 运算符比较标量,数组则用 & 进行按元素比较。比如,0 .< A .< 1 会得到一个 boolean 数组,如果 A 的元素都在 0 和 1 之间则数组元素就都是 true。","category":"page"},{"location":"manual/mathematical-operations/","page":"数学运算和初等函数","title":"数学运算和初等函数","text":"注意链式比较的执行顺序:","category":"page"},{"location":"manual/mathematical-operations/","page":"数学运算和初等函数","title":"数学运算和初等函数","text":"julia> v(x) = (println(x); x)\nv (generic function with 1 method)\n\njulia> v(1) < v(2) <= v(3)\n2\n1\n3\ntrue\n\njulia> v(1) > v(2) <= v(3)\n2\n1\nfalse","category":"page"},{"location":"manual/mathematical-operations/","page":"数学运算和初等函数","title":"数学运算和初等函数","text":"中间的表达式只会计算一次,而如果写成 v(1) < v(2) && v(2) <= v(3) 是计算了两次的。然而,链式比较中的顺序是不确定的。强烈建议不要在表达式中使用有副作用(比如 printing)的函数。如果的确需要,请使用短路运算符 &&(请参考短路求值)。","category":"page"},{"location":"manual/mathematical-operations/#初等函数","page":"数学运算和初等函数","title":"初等函数","text":"","category":"section"},{"location":"manual/mathematical-operations/","page":"数学运算和初等函数","title":"数学运算和初等函数","text":"Julia 提供了强大的数学函数和运算符集合。这些数学运算定义在各种合理的数值上,包括整型、浮点数、分数和复数,只要这些定义有数学意义就行。","category":"page"},{"location":"manual/mathematical-operations/","page":"数学运算和初等函数","title":"数学运算和初等函数","text":"而且,和其它 Julia 函数一样,这些函数也能通过 点语法 f.(A) 以“向量化”的方式作用于数组和其它集合上。 比如,sin.(A) 会计算 A 中每个元素的 sin 值。","category":"page"},{"location":"manual/mathematical-operations/#运算符的优先级与结合性","page":"数学运算和初等函数","title":"运算符的优先级与结合性","text":"","category":"section"},{"location":"manual/mathematical-operations/","page":"数学运算和初等函数","title":"数学运算和初等函数","text":"从高到低,Julia 运算符的优先级与结合性为:","category":"page"},{"location":"manual/mathematical-operations/","page":"数学运算和初等函数","title":"数学运算和初等函数","text":"分类 运算符 结合性\n语法 . followed by :: 左结合\n幂运算 ^ 右结合\n一元运算符 + - √ 右结合[1]\n移位运算 << >> >>> 左结合\n除法 // 左结合\n乘法 * / % & \\ ÷ 左结合[2]\n加法 + - | ⊻ 左结合[2]\n语法 : .. 左结合\n语法 |> 左结合\n语法 <| 右结合\n比较 > < >= <= == === != !== <: 无结合性\n流程控制 && followed by || followed by ? 右结合\nPair 操作 => 右结合\n赋值 = += -= *= /= //= \\= ^= ÷= %= |= &= ⊻= <<= >>= >>>= 右结合","category":"page"},{"location":"manual/mathematical-operations/","page":"数学运算和初等函数","title":"数学运算和初等函数","text":"[1]: 一元运算符 + 和 - 需要显式调用,即给它们的参数加上括号,以免和 ++ 等运算符混淆。其它一元运算符的混合使用都被解析为右结合的,比如 √√-a 解析为 √(√(-a))。","category":"page"},{"location":"manual/mathematical-operations/","page":"数学运算和初等函数","title":"数学运算和初等函数","text":"[2]: The operators +, ++ and * are non-associative. a + b + c is parsed as +(a, b, c) not +(+(a, b), c). However, the fallback methods for +(a, b, c, d...) and *(a, b, c, d...) both default to left-associative evaluation.","category":"page"},{"location":"manual/mathematical-operations/","page":"数学运算和初等函数","title":"数学运算和初等函数","text":"想查看 每个 Julia 运算符的优先级,可以参考这个文件:src/julia-parser.scm。注意到有一些运算符在 Base 模块中没有定义但是可能是在标准库、包或者用户代码中定义的。","category":"page"},{"location":"manual/mathematical-operations/","page":"数学运算和初等函数","title":"数学运算和初等函数","text":"你也可以通过内置函数 Base.operator_precedence 查看任何给定运算符的优先级数值,数值越大优先级越高:","category":"page"},{"location":"manual/mathematical-operations/","page":"数学运算和初等函数","title":"数学运算和初等函数","text":"julia> Base.operator_precedence(:+), Base.operator_precedence(:*), Base.operator_precedence(:.)\n(11, 12, 17)\n\njulia> Base.operator_precedence(:sin), Base.operator_precedence(:+=), Base.operator_precedence(:(=)) # (注意:等号前后必须有括号 `:(=)`)\n(0, 1, 1)","category":"page"},{"location":"manual/mathematical-operations/","page":"数学运算和初等函数","title":"数学运算和初等函数","text":"另外,内置函数 Base.operator_associativity 可以返回运算符结合性的符号表示:","category":"page"},{"location":"manual/mathematical-operations/","page":"数学运算和初等函数","title":"数学运算和初等函数","text":"julia> Base.operator_associativity(:-), Base.operator_associativity(:+), Base.operator_associativity(:^)\n(:left, :none, :right)\n\njulia> Base.operator_associativity(:⊗), Base.operator_associativity(:sin), Base.operator_associativity(:→)\n(:left, :none, :right)","category":"page"},{"location":"manual/mathematical-operations/","page":"数学运算和初等函数","title":"数学运算和初等函数","text":"注意诸如 :sin 这样的符号返回优先级 0,此值代表无效的运算符或非最低优先级运算符。类似地,它们的结合性被认为是 :none。","category":"page"},{"location":"manual/mathematical-operations/","page":"数学运算和初等函数","title":"数学运算和初等函数","text":"数字字面量系数,例如 2x 被视为比任何其他二元运算具有更高优先级的乘法,除了^,指数计算具有更高的优先级。","category":"page"},{"location":"manual/mathematical-operations/","page":"数学运算和初等函数","title":"数学运算和初等函数","text":"julia> x = 3; 2x^2\n18\n\njulia> x = 3; 2^2x\n64","category":"page"},{"location":"manual/mathematical-operations/","page":"数学运算和初等函数","title":"数学运算和初等函数","text":"并列解析就像一元运算符,它在指数周围具有相同的自然不对称性:-x^y 和 2x^y解析为 -(x^y) 和 2(x^y) 而 x^-y 和 x^2y 解析为x^(-y) 和 x^(2y)。","category":"page"},{"location":"manual/mathematical-operations/#数值转换","page":"数学运算和初等函数","title":"数值转换","text":"","category":"section"},{"location":"manual/mathematical-operations/","page":"数学运算和初等函数","title":"数学运算和初等函数","text":"Julia 支持三种数值转换,它们在处理不精确转换上有所不同。","category":"page"},{"location":"manual/mathematical-operations/","page":"数学运算和初等函数","title":"数学运算和初等函数","text":"T(x) 和 convert(T,x) 都会把 x 转换为 T类型。\n如果 T 是浮点类型,转换的结果就是最近的可表示值, 可能会是正负无穷大。\n如果 T 为整数类型,当 x 不能由 T 类型表示时,会抛出 InexactError。\nx % T 将整数 x 转换为整型 T,与 x 模 2^n 的结果一致,其中 n 是 T 的位数。换句话说,在二进制表示下被截掉了一部分。\n舍入函数 接收一个 T 类型的可选参数。比如,round(Int,x) 是 Int(round(x)) 的简写版。","category":"page"},{"location":"manual/mathematical-operations/","page":"数学运算和初等函数","title":"数学运算和初等函数","text":"下面的例子展示了不同的形式","category":"page"},{"location":"manual/mathematical-operations/","page":"数学运算和初等函数","title":"数学运算和初等函数","text":"julia> Int8(127)\n127\n\njulia> Int8(128)\nERROR: InexactError: trunc(Int8, 128)\nStacktrace:\n[...]\n\njulia> Int8(127.0)\n127\n\njulia> Int8(3.14)\nERROR: InexactError: Int8(3.14)\nStacktrace:\n[...]\n\njulia> Int8(128.0)\nERROR: InexactError: Int8(128.0)\nStacktrace:\n[...]\n\njulia> 127 % Int8\n127\n\njulia> 128 % Int8\n-128\n\njulia> round(Int8,127.4)\n127\n\njulia> round(Int8,127.6)\nERROR: InexactError: trunc(Int8, 128.0)\nStacktrace:\n[...]","category":"page"},{"location":"manual/mathematical-operations/","page":"数学运算和初等函数","title":"数学运算和初等函数","text":"请参考类型转换与类型提升一节来定义你自己的类型转换和提升规则。","category":"page"},{"location":"manual/mathematical-operations/#舍入函数","page":"数学运算和初等函数","title":"舍入函数","text":"","category":"section"},{"location":"manual/mathematical-operations/","page":"数学运算和初等函数","title":"数学运算和初等函数","text":"函数 描述 返回类型\nround(x) x 舍到最接近的整数 typeof(x)\nround(T, x) x 舍到最接近的整数 T\nfloor(x) x 向 -Inf 舍入 typeof(x)\nfloor(T, x) x 向 -Inf 舍入 T\nceil(x) x 向 +Inf 方向取整 typeof(x)\nceil(T, x) x 向 +Inf 方向取整 T\ntrunc(x) x 向 0 取整 typeof(x)\ntrunc(T, x) x 向 0 取整 T","category":"page"},{"location":"manual/mathematical-operations/#除法函数","page":"数学运算和初等函数","title":"除法函数","text":"","category":"section"},{"location":"manual/mathematical-operations/","page":"数学运算和初等函数","title":"数学运算和初等函数","text":"函数 描述\ndiv(x,y), x÷y 截断除法;商向零近似\nfld(x,y) 向下取整除法;商向 -Inf 近似\ncld(x,y) 向上取整除法;商向 +Inf 近似\nrem(x,y) 取余;满足 x == div(x,y)*y + rem(x,y);符号与 x 一致\nmod(x,y) 取模;满足 x == fld(x,y)*y + mod(x,y);符号与 y 一致\nmod1(x,y) 偏移 1 的 mod;若 y>0,则返回 r∈(0,y],若 y<0,则 r∈[y,0) 且满足 mod(r, y) == mod(x, y)\nmod2pi(x) 对 2pi 取模;0 <= mod2pi(x) < 2pi\ndivrem(x,y) 返回 (div(x,y),rem(x,y))\nfldmod(x,y) 返回 (fld(x,y),mod(x,y))\ngcd(x,y...) x, y,... 的最大公约数\nlcm(x,y...) x, y,... 的最小公倍数","category":"page"},{"location":"manual/mathematical-operations/#符号和绝对值函数","page":"数学运算和初等函数","title":"符号和绝对值函数","text":"","category":"section"},{"location":"manual/mathematical-operations/","page":"数学运算和初等函数","title":"数学运算和初等函数","text":"函数 描述\nabs(x) x 的模\nabs2(x) x 的模的平方\nsign(x) 表示 x 的符号,返回 -1,0,或 +1\nsignbit(x) 表示符号位是 true 或 false\ncopysign(x,y) 返回一个数,其值等于 x 的模,符号与 y 一致\nflipsign(x,y) 返回一个数,其值等于 x 的模,符号与 x*y 一致","category":"page"},{"location":"manual/mathematical-operations/#幂、对数与平方根","page":"数学运算和初等函数","title":"幂、对数与平方根","text":"","category":"section"},{"location":"manual/mathematical-operations/","page":"数学运算和初等函数","title":"数学运算和初等函数","text":"函数 描述\nsqrt(x), √x x 的平方根\ncbrt(x), ∛x x 的立方根\nhypot(x,y) 当直角边的长度为 x 和 y时,直角三角形斜边的长度\nexp(x) 自然指数函数在 x 处的值\nexpm1(x) 当 x 接近 0 时的 exp(x)-1 的精确值\nldexp(x,n) x*2^n 的高效算法,n 为整数\nlog(x) x 的自然对数\nlog(b,x) 以 b 为底 x 的对数\nlog2(x) 以 2 为底 x 的对数\nlog10(x) 以 10 为底 x 的对数\nlog1p(x) 当 x接近 0 时的 log(1+x) 的精确值\nexponent(x) x 的二进制指数\nsignificand(x) 浮点数 x 的二进制有效数(也就是尾数)","category":"page"},{"location":"manual/mathematical-operations/","page":"数学运算和初等函数","title":"数学运算和初等函数","text":"想大概了解一下为什么诸如 hypot、expm1和 log1p 函数是必要和有用的,可以看一下 John D. Cook 关于这些主题的两篇优秀博文:expm1, log1p, erfc, 和 hypot。","category":"page"},{"location":"manual/mathematical-operations/#三角和双曲函数","page":"数学运算和初等函数","title":"三角和双曲函数","text":"","category":"section"},{"location":"manual/mathematical-operations/","page":"数学运算和初等函数","title":"数学运算和初等函数","text":"所有标准的三角和双曲函数也都已经定义了:","category":"page"},{"location":"manual/mathematical-operations/","page":"数学运算和初等函数","title":"数学运算和初等函数","text":"sin cos tan cot sec csc\nsinh cosh tanh coth sech csch\nasin acos atan acot asec acsc\nasinh acosh atanh acoth asech acsch\nsinc cosc","category":"page"},{"location":"manual/mathematical-operations/","page":"数学运算和初等函数","title":"数学运算和初等函数","text":"所有这些函数都是单参数函数,不过 atan 也可以接收两个参数 来表示传统的 atan2 函数。","category":"page"},{"location":"manual/mathematical-operations/","page":"数学运算和初等函数","title":"数学运算和初等函数","text":"另外,sinpi(x) 和 cospi(x) 分别用来对 sin(pi*x) 和 cos(pi*x) 进行更精确的计算。","category":"page"},{"location":"manual/mathematical-operations/","page":"数学运算和初等函数","title":"数学运算和初等函数","text":"要计算角度而非弧度的三角函数,以 d 做后缀。 比如,sind(x) 计算 x 的 sine 值,其中 x 是一个角度值。 下面是角度变量的三角函数完整列表:","category":"page"},{"location":"manual/mathematical-operations/","page":"数学运算和初等函数","title":"数学运算和初等函数","text":"sind cosd tand cotd secd cscd\nasind acosd atand acotd asecd acscd","category":"page"},{"location":"manual/mathematical-operations/#特殊函数","page":"数学运算和初等函数","title":"特殊函数","text":"","category":"section"},{"location":"manual/mathematical-operations/","page":"数学运算和初等函数","title":"数学运算和初等函数","text":"SpecialFunctions.jl 提供了许多其他的特殊数学函数。","category":"page"},{"location":"stdlib/DelimitedFiles/#分隔符文件","page":"分隔符文件","title":"分隔符文件","text":"","category":"section"},{"location":"stdlib/DelimitedFiles/","page":"分隔符文件","title":"分隔符文件","text":"DelimitedFiles.readdlm(::Any, ::AbstractChar, ::Type, ::AbstractChar)\nDelimitedFiles.readdlm(::Any, ::AbstractChar, ::AbstractChar)\nDelimitedFiles.readdlm(::Any, ::AbstractChar, ::Type)\nDelimitedFiles.readdlm(::Any, ::AbstractChar)\nDelimitedFiles.readdlm(::Any, ::Type)\nDelimitedFiles.readdlm(::Any)\nDelimitedFiles.writedlm","category":"page"},{"location":"stdlib/DelimitedFiles/#DelimitedFiles.readdlm-Tuple{Any, AbstractChar, Type, AbstractChar}","page":"分隔符文件","title":"DelimitedFiles.readdlm","text":"readdlm(source, delim::AbstractChar, T::Type, eol::AbstractChar; header=false, skipstart=0, skipblanks=true, use_mmap, quotes=true, dims, comments=false, comment_char='#')\n\nRead a matrix from the source where each line (separated by eol) gives one row, with elements separated by the given delimiter. The source can be a text file, stream or byte array. Memory mapped files can be used by passing the byte array representation of the mapped segment as source.\n\nIf T is a numeric type, the result is an array of that type, with any non-numeric elements as NaN for floating-point types, or zero. Other useful values of T include String, AbstractString, and Any.\n\nIf header is true, the first row of data will be read as header and the tuple (data_cells, header_cells) is returned instead of only data_cells.\n\nSpecifying skipstart will ignore the corresponding number of initial lines from the input.\n\nIf skipblanks is true, blank lines in the input will be ignored.\n\nIf use_mmap is true, the file specified by source is memory mapped for potential speedups if the file is large. Default is false. On a Windows filesystem, use_mmap should not be set to true unless the file is only read once and is also not written to. Some edge cases exist where an OS is Unix-like but the filesystem is Windows-like.\n\nIf quotes is true, columns enclosed within double-quote (\") characters are allowed to contain new lines and column delimiters. Double-quote characters within a quoted field must be escaped with another double-quote. Specifying dims as a tuple of the expected rows and columns (including header, if any) may speed up reading of large files. If comments is true, lines beginning with comment_char and text following comment_char in any line are ignored.\n\nExamples\n\njulia> using DelimitedFiles\n\njulia> x = [1; 2; 3; 4];\n\njulia> y = [5; 6; 7; 8];\n\njulia> open(\"delim_file.txt\", \"w\") do io\n writedlm(io, [x y])\n end\n\njulia> readdlm(\"delim_file.txt\", '\\t', Int, '\\n')\n4×2 Matrix{Int64}:\n 1 5\n 2 6\n 3 7\n 4 8\n\njulia> rm(\"delim_file.txt\")\n\n\n\n\n\n","category":"method"},{"location":"stdlib/DelimitedFiles/#DelimitedFiles.readdlm-Tuple{Any, AbstractChar, AbstractChar}","page":"分隔符文件","title":"DelimitedFiles.readdlm","text":"readdlm(source, delim::AbstractChar, eol::AbstractChar; options...)\n\nIf all data is numeric, the result will be a numeric array. If some elements cannot be parsed as numbers, a heterogeneous array of numbers and strings is returned.\n\n\n\n\n\n","category":"method"},{"location":"stdlib/DelimitedFiles/#DelimitedFiles.readdlm-Tuple{Any, AbstractChar, Type}","page":"分隔符文件","title":"DelimitedFiles.readdlm","text":"readdlm(source, delim::AbstractChar, T::Type; options...)\n\nThe end of line delimiter is taken as \\n.\n\nExamples\n\njulia> using DelimitedFiles\n\njulia> x = [1; 2; 3; 4];\n\njulia> y = [1.1; 2.2; 3.3; 4.4];\n\njulia> open(\"delim_file.txt\", \"w\") do io\n writedlm(io, [x y], ',')\n end;\n\njulia> readdlm(\"delim_file.txt\", ',', Float64)\n4×2 Matrix{Float64}:\n 1.0 1.1\n 2.0 2.2\n 3.0 3.3\n 4.0 4.4\n\njulia> rm(\"delim_file.txt\")\n\n\n\n\n\n","category":"method"},{"location":"stdlib/DelimitedFiles/#DelimitedFiles.readdlm-Tuple{Any, AbstractChar}","page":"分隔符文件","title":"DelimitedFiles.readdlm","text":"readdlm(source, delim::AbstractChar; options...)\n\nThe end of line delimiter is taken as \\n. If all data is numeric, the result will be a numeric array. If some elements cannot be parsed as numbers, a heterogeneous array of numbers and strings is returned.\n\nExamples\n\njulia> using DelimitedFiles\n\njulia> x = [1; 2; 3; 4];\n\njulia> y = [1.1; 2.2; 3.3; 4.4];\n\njulia> open(\"delim_file.txt\", \"w\") do io\n writedlm(io, [x y], ',')\n end;\n\njulia> readdlm(\"delim_file.txt\", ',')\n4×2 Matrix{Float64}:\n 1.0 1.1\n 2.0 2.2\n 3.0 3.3\n 4.0 4.4\n\njulia> z = [\"a\"; \"b\"; \"c\"; \"d\"];\n\njulia> open(\"delim_file.txt\", \"w\") do io\n writedlm(io, [x z], ',')\n end;\n\njulia> readdlm(\"delim_file.txt\", ',')\n4×2 Matrix{Any}:\n 1 \"a\"\n 2 \"b\"\n 3 \"c\"\n 4 \"d\"\n\njulia> rm(\"delim_file.txt\")\n\n\n\n\n\n","category":"method"},{"location":"stdlib/DelimitedFiles/#DelimitedFiles.readdlm-Tuple{Any, Type}","page":"分隔符文件","title":"DelimitedFiles.readdlm","text":"readdlm(source, T::Type; options...)\n\nThe columns are assumed to be separated by one or more whitespaces. The end of line delimiter is taken as \\n.\n\nExamples\n\njulia> using DelimitedFiles\n\njulia> x = [1; 2; 3; 4];\n\njulia> y = [5; 6; 7; 8];\n\njulia> open(\"delim_file.txt\", \"w\") do io\n writedlm(io, [x y])\n end;\n\njulia> readdlm(\"delim_file.txt\", Int64)\n4×2 Matrix{Int64}:\n 1 5\n 2 6\n 3 7\n 4 8\n\njulia> readdlm(\"delim_file.txt\", Float64)\n4×2 Matrix{Float64}:\n 1.0 5.0\n 2.0 6.0\n 3.0 7.0\n 4.0 8.0\n\njulia> rm(\"delim_file.txt\")\n\n\n\n\n\n","category":"method"},{"location":"stdlib/DelimitedFiles/#DelimitedFiles.readdlm-Tuple{Any}","page":"分隔符文件","title":"DelimitedFiles.readdlm","text":"readdlm(source; options...)\n\nThe columns are assumed to be separated by one or more whitespaces. The end of line delimiter is taken as \\n. If all data is numeric, the result will be a numeric array. If some elements cannot be parsed as numbers, a heterogeneous array of numbers and strings is returned.\n\nExamples\n\njulia> using DelimitedFiles\n\njulia> x = [1; 2; 3; 4];\n\njulia> y = [\"a\"; \"b\"; \"c\"; \"d\"];\n\njulia> open(\"delim_file.txt\", \"w\") do io\n writedlm(io, [x y])\n end;\n\njulia> readdlm(\"delim_file.txt\")\n4×2 Matrix{Any}:\n 1 \"a\"\n 2 \"b\"\n 3 \"c\"\n 4 \"d\"\n\njulia> rm(\"delim_file.txt\")\n\n\n\n\n\n","category":"method"},{"location":"stdlib/DelimitedFiles/#DelimitedFiles.writedlm","page":"分隔符文件","title":"DelimitedFiles.writedlm","text":"writedlm(f, A, delim='\\t'; opts)\n\nWrite A (a vector, matrix, or an iterable collection of iterable rows) as text to f (either a filename string or an IO stream) using the given delimiter delim (which defaults to tab, but can be any printable Julia object, typically a Char or AbstractString).\n\nFor example, two vectors x and y of the same length can be written as two columns of tab-delimited text to f by either writedlm(f, [x y]) or by writedlm(f, zip(x, y)).\n\nExamples\n\njulia> using DelimitedFiles\n\njulia> x = [1; 2; 3; 4];\n\njulia> y = [5; 6; 7; 8];\n\njulia> open(\"delim_file.txt\", \"w\") do io\n writedlm(io, [x y])\n end\n\njulia> readdlm(\"delim_file.txt\", '\\t', Int, '\\n')\n4×2 Matrix{Int64}:\n 1 5\n 2 6\n 3 7\n 4 8\n\njulia> rm(\"delim_file.txt\")\n\n\n\n\n\n","category":"function"},{"location":"manual/calling-c-and-fortran-code/#Calling-C-and-Fortran-Code","page":"调用 C 和 Fortran 代码","title":"调用 C 和 Fortran 代码","text":"","category":"section"},{"location":"manual/calling-c-and-fortran-code/","page":"调用 C 和 Fortran 代码","title":"调用 C 和 Fortran 代码","text":"在数值计算领域,尽管有很多用 C 语言或 Fortran 写的高质量且成熟的库都可以用 Julia 重写,但为了便捷利用现有的 C 或 Fortran 代码,Julia 提供简洁且高效的调用方式。Julia 的哲学是 no boilerplate: Julia 可以直接调用 C/Fortran 的函数,不需要任何\"胶水\"代码,代码生成或其它编译过程 – 即使在交互式会话 (REPL/Jupyter notebook) 中使用也一样. 在 Julia 中,上述特性可以仅仅通过调用 ccall 实现,它的语法看起来就像是普通的函数调用。","category":"page"},{"location":"manual/calling-c-and-fortran-code/","page":"调用 C 和 Fortran 代码","title":"调用 C 和 Fortran 代码","text":"被调用的代码必须是一个共享库(.so, .dylib, .dll)。大多数 C 和 Fortran 库都已经是以共享库的形式发布的,但在用 GCC 或 Clang 编译自己的代码时,需要添加 -shared 和 -fPIC 编译器选项。由于 Julia 的 JIT 生成的机器码跟原生 C 代码的调用是一样,所以在 Julia 里调用 C/Fortran 库的额外开销与直接从 C 里调用是一样的。[1]","category":"page"},{"location":"manual/calling-c-and-fortran-code/","page":"调用 C 和 Fortran 代码","title":"调用 C 和 Fortran 代码","text":"可以通过元组 (:function, \"library\") 或 (\"function\", \"library\") 这两种形式来索引库中的函数,其中 function 是函数名,library 是库名。(特定平台/操作系统的)加载路径中可用的共享库将按名称解析。 也可以指定库的完整路径。","category":"page"},{"location":"manual/calling-c-and-fortran-code/","page":"调用 C 和 Fortran 代码","title":"调用 C 和 Fortran 代码","text":"可以单独使用函数名来代替元组(只用 :function 或 \"function\")。在这种情况下,函数名在当前进程中进行解析。这一调用形式可用于调用 C 库函数、Julia 运行时中的函数或链接到 Julia 的应用程序中的函数。","category":"page"},{"location":"manual/calling-c-and-fortran-code/","page":"调用 C 和 Fortran 代码","title":"调用 C 和 Fortran 代码","text":"默认情况下,Fortran 编译器会进行名称修饰(例如,将函数名转换为小写或大写,通常会添加下划线),要通过 ccall 调用 Fortran 函数,传递的标识符必须与 Fortran 编译器名称修饰之后的一致。此外,在调用 Fortran 函数时,所有输入必须以指针形式传递,并已在堆或栈上分配内存。这不仅适用于通常是堆分配的数组及可变对象,而且适用于整数和浮点数等标量值,尽管这些值通常是栈分配的,且在使用 C 或 Julia 调用约定时通常是通过寄存器传递的。","category":"page"},{"location":"manual/calling-c-and-fortran-code/","page":"调用 C 和 Fortran 代码","title":"调用 C 和 Fortran 代码","text":"最终,你能使用 ccall 来实际生成一个对库函数的调用。ccall 的参数是:","category":"page"},{"location":"manual/calling-c-and-fortran-code/","page":"调用 C 和 Fortran 代码","title":"调用 C 和 Fortran 代码","text":"一对 (:function, \"library\") (最常见)\n或\n一个名称符号 :function 或名称字符串 \"function\"(用于当前进程或 libc 中的符号),\n或\n一个函数指针(例如,从 dlsym 获得的指针)。\n函数的返回值类型\n输入类型的元组,对应于函数签名\n要传递给函数的实际参数值,如果有的话; 每个都是一个单独的参数。","category":"page"},{"location":"manual/calling-c-and-fortran-code/","page":"调用 C 和 Fortran 代码","title":"调用 C 和 Fortran 代码","text":"note: Note\n(:function, \"library\") 对、返回类型和输入类型必须是字面量(即,它们不能是变量,但请参阅下面的 非常量函数规范)。当定义包含方法时,将在编译时评估其余参数。","category":"page"},{"location":"manual/calling-c-and-fortran-code/","page":"调用 C 和 Fortran 代码","title":"调用 C 和 Fortran 代码","text":"note: Note\n请参阅下文了解如何 将 C 类型映射到 Julia 类型。","category":"page"},{"location":"manual/calling-c-and-fortran-code/","page":"调用 C 和 Fortran 代码","title":"调用 C 和 Fortran 代码","text":"作为一个完整但简单的例子,下面从大多数 Unix 派生系统上的标准 C 库中调用 clock 函数:","category":"page"},{"location":"manual/calling-c-and-fortran-code/","page":"调用 C 和 Fortran 代码","title":"调用 C 和 Fortran 代码","text":"julia> t = ccall(:clock, Int32, ())\n2292761\n\njulia> t\n2292761\n\njulia> typeof(t)\nInt32","category":"page"},{"location":"manual/calling-c-and-fortran-code/","page":"调用 C 和 Fortran 代码","title":"调用 C 和 Fortran 代码","text":"clock 不接受任何参数并返回一个 Int32。 一个常见的错误是忘记了参数类型的单元组必须用逗号结尾。 例如,要调用 getenv 函数来获取指向环境变量值的指针,可以这样调用:","category":"page"},{"location":"manual/calling-c-and-fortran-code/","page":"调用 C 和 Fortran 代码","title":"调用 C 和 Fortran 代码","text":"julia> path = ccall(:getenv, Cstring, (Cstring,), \"SHELL\")\nCstring(@0x00007fff5fbffc45)\n\njulia> unsafe_string(path)\n\"/bin/bash\"","category":"page"},{"location":"manual/calling-c-and-fortran-code/","page":"调用 C 和 Fortran 代码","title":"调用 C 和 Fortran 代码","text":"请注意,参数类型元组必须是 (Cstring,),而不是 (Cstring) 。这是因为 (Cstring) 只是括号括起来的表达式 Cstring,而不是包含 Cstring 的单元组:","category":"page"},{"location":"manual/calling-c-and-fortran-code/","page":"调用 C 和 Fortran 代码","title":"调用 C 和 Fortran 代码","text":"julia> (Cstring)\nCstring\n\njulia> (Cstring,)\n(Cstring,)","category":"page"},{"location":"manual/calling-c-and-fortran-code/","page":"调用 C 和 Fortran 代码","title":"调用 C 和 Fortran 代码","text":"在实践中,尤其是在提供可重用功能时,通常会在 Julia 函数中包装 ccall 使用,这些函数设置参数,然后以 C 或 Fortran 函数指定的任何方式检查错误。 如果发生错误,它会作为普通的 Julia 异常抛出。 这一点尤其重要,因为 C 和 Fortran API 在它们指示错误条件的方式上是出了名的不一致。 例如,getenv C 库函数被包裹在下面的 Julia 函数中,它是 env.jl 实际定义的简化版本:","category":"page"},{"location":"manual/calling-c-and-fortran-code/","page":"调用 C 和 Fortran 代码","title":"调用 C 和 Fortran 代码","text":"function getenv(var::AbstractString)\n val = ccall(:getenv, Cstring, (Cstring,), var)\n if val == C_NULL\n error(\"getenv: undefined variable: \", var)\n end\n return unsafe_string(val)\nend","category":"page"},{"location":"manual/calling-c-and-fortran-code/","page":"调用 C 和 Fortran 代码","title":"调用 C 和 Fortran 代码","text":"C 函数 getenv 通过返回 NULL 的方式进行报错,但是其他 C 标准库函数也会通过多种不同的方式来报错,这包括返回 -1,0,1 以及其它特殊值。此封装能够明确地抛出异常信息,即是否调用者在尝试获取一个不存在的环境变量:","category":"page"},{"location":"manual/calling-c-and-fortran-code/","page":"调用 C 和 Fortran 代码","title":"调用 C 和 Fortran 代码","text":"julia> getenv(\"SHELL\")\n\"/bin/bash\"\n\njulia> getenv(\"FOOBAR\")\ngetenv: undefined variable: FOOBAR","category":"page"},{"location":"manual/calling-c-and-fortran-code/","page":"调用 C 和 Fortran 代码","title":"调用 C 和 Fortran 代码","text":"这是一个稍微复杂的示例,用于发现本地计算机的主机名。 在此示例中,假设网络库代码位于名为“libc”的共享库中。 在实践中,这个函数通常是 C 标准库的一部分,因此“libc”部分应该被省略,但我们希望在这里展示这个语法的用法。","category":"page"},{"location":"manual/calling-c-and-fortran-code/","page":"调用 C 和 Fortran 代码","title":"调用 C 和 Fortran 代码","text":"function gethostname()\n hostname = Vector{UInt8}(undef, 256) # MAXHOSTNAMELEN\n err = ccall((:gethostname, \"libc\"), Int32,\n (Ptr{UInt8}, Csize_t),\n hostname, sizeof(hostname))\n Base.systemerror(\"gethostname\", err != 0)\n hostname[end] = 0 # ensure null-termination\n return GC.@preserve hostname unsafe_string(pointer(hostname))\nend","category":"page"},{"location":"manual/calling-c-and-fortran-code/","page":"调用 C 和 Fortran 代码","title":"调用 C 和 Fortran 代码","text":"此示例首先分配一个字节数组。 然后它调用 C 库函数 gethostname 以使用主机名填充数组。 最后,它接受一个指向主机名缓冲区的指针,并将该指针转换为一个 Julia 字符串,假设它是一个以 NUL 结尾的 C 字符串。","category":"page"},{"location":"manual/calling-c-and-fortran-code/","page":"调用 C 和 Fortran 代码","title":"调用 C 和 Fortran 代码","text":"C 库通常使用这种模式,要求调用者分配要传递给被调用者并填充的内存。 像这样从 Julia 分配内存通常是通过创建一个未初始化的数组并将指向其数据的指针传递给 C 函数来完成的。 这就是我们在这里不使用 Cstring 类型的原因:由于数组未初始化,它可能包含 NUL 字节。 作为 ccall 的一部分,转换为 Cstring 会检查包含的 NUL 字节,因此可能会引发类型转换错误。","category":"page"},{"location":"manual/calling-c-and-fortran-code/","page":"调用 C 和 Fortran 代码","title":"调用 C 和 Fortran 代码","text":"用 unsafe_string 取消引用 pointer(hostname) 是一种不安全的操作,因为它需要访问为 hostname 分配的内存,而这些内存可能在同时被垃圾收集。 宏 GC.@preserve 防止这种情况发生,从而防止访问无效的内存位置。","category":"page"},{"location":"manual/calling-c-and-fortran-code/#创建和C兼容的Julia函数指针","page":"调用 C 和 Fortran 代码","title":"创建和C兼容的Julia函数指针","text":"","category":"section"},{"location":"manual/calling-c-and-fortran-code/","page":"调用 C 和 Fortran 代码","title":"调用 C 和 Fortran 代码","text":"可以将Julia函数传递给接受函数指针参数的原生C函数。例如,要匹配满足下面的C原型:","category":"page"},{"location":"manual/calling-c-and-fortran-code/","page":"调用 C 和 Fortran 代码","title":"调用 C 和 Fortran 代码","text":"typedef returntype (*functiontype)(argumenttype, ...)","category":"page"},{"location":"manual/calling-c-and-fortran-code/","page":"调用 C 和 Fortran 代码","title":"调用 C 和 Fortran 代码","text":"宏 @cfunction 为调用 Julia 函数生成 C 兼容函数指针。 @cfunction 的参数是:","category":"page"},{"location":"manual/calling-c-and-fortran-code/","page":"调用 C 和 Fortran 代码","title":"调用 C 和 Fortran 代码","text":"一个Julia函数\n函数的返回值类型\n输入类型的元组,对应于函数签名","category":"page"},{"location":"manual/calling-c-and-fortran-code/","page":"调用 C 和 Fortran 代码","title":"调用 C 和 Fortran 代码","text":"note: Note\n与 ccall 一样,返回类型和输入类型的元组必须是字面量常量。","category":"page"},{"location":"manual/calling-c-and-fortran-code/","page":"调用 C 和 Fortran 代码","title":"调用 C 和 Fortran 代码","text":"note: Note\n目前,仅支持平台默认的C调用约定。这意味着,@cfunction生成的指针不能用于WINAPI要求在32位Windows上使用stdcall函数的调用中,但可以在WIN64上使用(其中stdcall与C调用约定统一)。","category":"page"},{"location":"manual/calling-c-and-fortran-code/","page":"调用 C 和 Fortran 代码","title":"调用 C 和 Fortran 代码","text":"一个典型的例子就是标准C库函数qsort,定义为:","category":"page"},{"location":"manual/calling-c-and-fortran-code/","page":"调用 C 和 Fortran 代码","title":"调用 C 和 Fortran 代码","text":"void qsort(void *base, size_t nmemb, size_t size,\n int (*compare)(const void*, const void*));","category":"page"},{"location":"manual/calling-c-and-fortran-code/","page":"调用 C 和 Fortran 代码","title":"调用 C 和 Fortran 代码","text":"base 参数是一个指向长度为 nmemb 的数组的指针,每个元素都有 size 字节。 compare 是一个回调函数,它采用指向两个元素 a 和 b 的指针,如果 a 出现在 b 之前/之后,则返回小于/大于零的整数(如果允许任何顺序,则返回零) 。","category":"page"},{"location":"manual/calling-c-and-fortran-code/","page":"调用 C 和 Fortran 代码","title":"调用 C 和 Fortran 代码","text":"现在,假设我们在 Julia 中有一个 1 维数组 A,我们希望使用qsort函数(而不是 Julia 的内置sort函数)对其进行排序。 在我们考虑调用 qsort 并传递参数之前,我们需要编写一个比较函数:","category":"page"},{"location":"manual/calling-c-and-fortran-code/","page":"调用 C 和 Fortran 代码","title":"调用 C 和 Fortran 代码","text":"julia> function mycompare(a, b)::Cint\n return (a < b) ? -1 : ((a > b) ? +1 : 0)\n end\nmycompare (generic function with 1 method)","category":"page"},{"location":"manual/calling-c-and-fortran-code/","page":"调用 C 和 Fortran 代码","title":"调用 C 和 Fortran 代码","text":"qsort 需要一个返回 C int 的比较函数,因此我们将返回类型注释为 Cint。","category":"page"},{"location":"manual/calling-c-and-fortran-code/","page":"调用 C 和 Fortran 代码","title":"调用 C 和 Fortran 代码","text":"为了将此函数传递给 C,我们使用宏@cfunction 获取它的地址:","category":"page"},{"location":"manual/calling-c-and-fortran-code/","page":"调用 C 和 Fortran 代码","title":"调用 C 和 Fortran 代码","text":"julia> mycompare_c = @cfunction(mycompare, Cint, (Ref{Cdouble}, Ref{Cdouble}));","category":"page"},{"location":"manual/calling-c-and-fortran-code/","page":"调用 C 和 Fortran 代码","title":"调用 C 和 Fortran 代码","text":"@cfunction 需要三个参数: Julia函数 (mycompare), 返回值类型(Cint), 和一个输入参数类型的字面量元组, 此处是要排序的Cdouble(Float64) 元素的数组.","category":"page"},{"location":"manual/calling-c-and-fortran-code/","page":"调用 C 和 Fortran 代码","title":"调用 C 和 Fortran 代码","text":"qsort的最终调用看起来是这样的:","category":"page"},{"location":"manual/calling-c-and-fortran-code/","page":"调用 C 和 Fortran 代码","title":"调用 C 和 Fortran 代码","text":"julia> A = [1.3, -2.7, 4.4, 3.1]\n4-element Vector{Float64}:\n 1.3\n -2.7\n 4.4\n 3.1\n\njulia> ccall(:qsort, Cvoid, (Ptr{Cdouble}, Csize_t, Csize_t, Ptr{Cvoid}),\n A, length(A), sizeof(eltype(A)), mycompare_c)\n\njulia> A\n4-element Vector{Float64}:\n -2.7\n 1.3\n 3.1\n 4.4","category":"page"},{"location":"manual/calling-c-and-fortran-code/","page":"调用 C 和 Fortran 代码","title":"调用 C 和 Fortran 代码","text":"如示例所示,原始 Julia 数组 A 现在已排序:[-2.7, 1.3, 3.1, 4.4]。 请注意,Julia 负责将数组转换为Ptr{Cdouble}),计算元素类型的大小(以字节为单位),等等。","category":"page"},{"location":"manual/calling-c-and-fortran-code/","page":"调用 C 和 Fortran 代码","title":"调用 C 和 Fortran 代码","text":"为了好玩,尝试在 mycompare 中插入一行 println(\"mycompare($a, $b)\"),这将允许你查看 qsort 正在执行的比较(并验证它是否真的在调用你传递给它的 Julia 函数)。","category":"page"},{"location":"manual/calling-c-and-fortran-code/#mapping-c-types-to-julia","page":"调用 C 和 Fortran 代码","title":"将 C 类型映射到 Julia","text":"","category":"section"},{"location":"manual/calling-c-and-fortran-code/","page":"调用 C 和 Fortran 代码","title":"调用 C 和 Fortran 代码","text":"将声明的 C 类型与其在 Julia 中的声明完全匹配至关重要。 不一致会导致在一个系统上正常工作的代码在另一个系统上失败或产生不确定的结果。","category":"page"},{"location":"manual/calling-c-and-fortran-code/","page":"调用 C 和 Fortran 代码","title":"调用 C 和 Fortran 代码","text":"请注意,在调用 C 函数的过程中没有任何地方使用 C 头文件:您有责任确保您的 Julia 类型和调用签名准确反映 C 头文件中的那些。[2]","category":"page"},{"location":"manual/calling-c-and-fortran-code/#automatic-type-conversion","page":"调用 C 和 Fortran 代码","title":"自动类型转换","text":"","category":"section"},{"location":"manual/calling-c-and-fortran-code/","page":"调用 C 和 Fortran 代码","title":"调用 C 和 Fortran 代码","text":"Julia 会自动插入对 Base.cconvert 函数的调用,以将每个参数转换为指定的类型。 例如,以下调用:","category":"page"},{"location":"manual/calling-c-and-fortran-code/","page":"调用 C 和 Fortran 代码","title":"调用 C 和 Fortran 代码","text":"ccall((:foo, \"libfoo\"), Cvoid, (Int32, Float64), x, y)","category":"page"},{"location":"manual/calling-c-and-fortran-code/","page":"调用 C 和 Fortran 代码","title":"调用 C 和 Fortran 代码","text":"将表现得好像它是这样写的:","category":"page"},{"location":"manual/calling-c-and-fortran-code/","page":"调用 C 和 Fortran 代码","title":"调用 C 和 Fortran 代码","text":"ccall((:foo, \"libfoo\"), Cvoid, (Int32, Float64),\n Base.unsafe_convert(Int32, Base.cconvert(Int32, x)),\n Base.unsafe_convert(Float64, Base.cconvert(Float64, y)))","category":"page"},{"location":"manual/calling-c-and-fortran-code/","page":"调用 C 和 Fortran 代码","title":"调用 C 和 Fortran 代码","text":"Base.cconvert 通常只调用 convert,但可以定义为返回一个更适合传递给 C 的任意新对象。这应该用于执行 C 代码将访问的内存。 例如,这用于将对象(例如字符串)的 Array 转换为指针数组。","category":"page"},{"location":"manual/calling-c-and-fortran-code/","page":"调用 C 和 Fortran 代码","title":"调用 C 和 Fortran 代码","text":"Base.unsafe_convert 处理到 Ptr 类型转换。 它被认为是不安全的,因为将对象转换为本地指针会隐藏垃圾收集器中的对象,导致它过早地被释放。","category":"page"},{"location":"manual/calling-c-and-fortran-code/#类型对应","page":"调用 C 和 Fortran 代码","title":"类型对应","text":"","category":"section"},{"location":"manual/calling-c-and-fortran-code/","page":"调用 C 和 Fortran 代码","title":"调用 C 和 Fortran 代码","text":"首先,让我们回顾一些相关的 Julia 类型术语:","category":"page"},{"location":"manual/calling-c-and-fortran-code/","page":"调用 C 和 Fortran 代码","title":"调用 C 和 Fortran 代码","text":"语法 / 关键字 例子 描述\nmutable struct BitSet Leaf Type:包含 type-tag 的一组相关数据,由 Julia GC 管理,通过 object-identity 来定义。为了保证实例可以被构造,Leaf Type 必须是完整定义的,即不允许使用 TypeVars。\nabstract type Any, AbstractArray{T, N}, Complex{T} Super Type:用于描述一组类型,它不是 Leaf-Type,也无法被实例化。\nT{A} Vector{Int} Type Parameter:某种类型的一种具体化,通常用于分派或存储优化。\n TypeVar:Type parameter 声明中的 T 是一个 TypeVar,它是类型变量的简称。\nprimitive type Int, Float64 Primitive Type:一种没有成员变量的类型,但是它有大小。它是按值存储和定义的。\nstruct Pair{Int, Int} \"Struct\" :: 所有字段都定义为常量的类型。 它是按值定义的,并且可以与类型标签一起存储。\n ComplexF64 (isbits) \"Is-Bits\" :: 一个 primitive type,或者一个 struct 类型,其中所有字段都是其他 isbits 类型。 它是按值定义的,并且在没有类型标签的情况下存储。\nstruct ...; end nothing Singleton:没有成员变量的 Leaf Type 或 Struct。\n(...) or tuple(...) (1, 2, 3) “元组” :: 类似于匿名结构类型或常量数组的不可变数据结构。 表示为数组或结构。","category":"page"},{"location":"manual/calling-c-and-fortran-code/#man-bits-types","page":"调用 C 和 Fortran 代码","title":"Bits Types","text":"","category":"section"},{"location":"manual/calling-c-and-fortran-code/","page":"调用 C 和 Fortran 代码","title":"调用 C 和 Fortran 代码","text":"有几种特殊类型需要注意,因为没有其他类型可以定义为具有相同的行为:","category":"page"},{"location":"manual/calling-c-and-fortran-code/","page":"调用 C 和 Fortran 代码","title":"调用 C 和 Fortran 代码","text":"Float32\n和C语言中的 float 类型完全对应(以及Fortran中的 REAL*4 )\nFloat64\n和C语言中的 double 类型完全对应(以及Fortran中的 REAL*8 )\nComplexF32\n和C语言中的 complex float 类型完全对应(以及Fortran中的 COMPLEX*8 )\nComplexF64\n和C语言中的 complex double 类型完全对应(以及Fortran中的 COMPLEX*16 )\nSigned\n和C语言中的 signed 类型标识完全对应(以及Fortran中的任意 INTEGER 类型) Julia中任何不是Signed 的子类型的类型,都会被认为是unsigned类型。","category":"page"},{"location":"manual/calling-c-and-fortran-code/","page":"调用 C 和 Fortran 代码","title":"调用 C 和 Fortran 代码","text":"Ref{T}\n和 Ptr{T} 行为相同,能通过Julia的GC管理其内存。","category":"page"},{"location":"manual/calling-c-and-fortran-code/","page":"调用 C 和 Fortran 代码","title":"调用 C 和 Fortran 代码","text":"Array{T,N}\n当数组作为 Ptr{T} 参数传递给 C 时,它不是重新解释转换:Julia 要求数组的元素类型与 T 匹配,并传递第一个元素的地址。\n因此,如果一个 Array 中的数据格式不正确,它必须被显式地转换 ,通过类似 trunc(Int32, a) 的函数。\n若要将一个数组 A 以不同类型的指针传递,而不提前转换数据, (比如,将一个 Float64 数组传给一个处理原生字节的函数时),你 可以将这一参数声明为 Ptr{Cvoid} 。\n如果一个元素类型为 Ptr{T} 的数组作为 Ptr{Ptr{T}} 类型的参数传递, Base.cconvert 将会首先尝试进行 null-terminated copy(即直到下一个元素为null才停止复制),并将每一个元素使用其通过 Base.cconvert 转换后的版本替换。 这允许,比如,将一个 argv 的指针数组,其类型为 Vector{String} ,传递给一个类型为 Ptr{Ptr{Cchar}} 的参数。","category":"page"},{"location":"manual/calling-c-and-fortran-code/","page":"调用 C 和 Fortran 代码","title":"调用 C 和 Fortran 代码","text":"在我们目前支持的所有系统上,基本的 C/C++ 值类型可以转换为 Julia 类型,如下所示。 每个 C 类型还有一个对应的同名 Julia 类型,以 C 为前缀。这在编写可移植代码时很有帮助(记住 C 中的 int 与 Julia 中的 Int 不同)。","category":"page"},{"location":"manual/calling-c-and-fortran-code/","page":"调用 C 和 Fortran 代码","title":"调用 C 和 Fortran 代码","text":"独立于系统的类型","category":"page"},{"location":"manual/calling-c-and-fortran-code/","page":"调用 C 和 Fortran 代码","title":"调用 C 和 Fortran 代码","text":"C 类型 Fortran 类型 标准 Julia 别名 Julia 基本类型\nunsigned char CHARACTER Cuchar UInt8\nbool (_Bool in C99+) Cuchar UInt8\nshort INTEGER*2, LOGICAL*2 Cshort Int16\nunsigned short Cushort UInt16\nint, BOOL (C, typical) INTEGER*4, LOGICAL*4 Cint Int32\nunsigned int Cuint UInt32\nlong long INTEGER*8, LOGICAL*8 Clonglong Int64\nunsigned long long Culonglong UInt64\nintmax_t Cintmax_t Int64\nuintmax_t Cuintmax_t UInt64\nfloat REAL*4i Cfloat Float32\ndouble REAL*8 Cdouble Float64\ncomplex float COMPLEX*8 ComplexF32 Complex{Float32}\ncomplex double COMPLEX*16 ComplexF64 Complex{Float64}\nptrdiff_t Cptrdiff_t Int\nssize_t Cssize_t Int\nsize_t Csize_t UInt\nvoid Cvoid\nvoid and [[noreturn]] or _Noreturn Union{}\nvoid* Ptr{Cvoid} (或类似的 Ref{Cvoid})\nT* (where T represents an appropriately defined type) Ref{T} (只有当 T 是 isbits 类型时,T 才可以安全地转变)\nchar* (or char[], e.g. a string) CHARACTER*N Cstring if NUL-terminated, or Ptr{UInt8} if not\nchar** (or *char[]) Ptr{Ptr{UInt8}}\njl_value_t* (any Julia Type) Any\njl_value_t* const* (一个 Julia 值的引用) Ref{Any}(常量,因为转变需要写屏障,不可能正确插入)\nva_arg Not supported\n... (variadic function specification) T...(其中 T 是上述类型之一,当使用 ccall 函数时)\n... (variadic function specification) ; va_arg1::T、va_arg2::S 等(仅支持@ccall 宏)","category":"page"},{"location":"manual/calling-c-and-fortran-code/","page":"调用 C 和 Fortran 代码","title":"调用 C 和 Fortran 代码","text":"Cstring 类型本质上是Ptr{UInt8}的同义词,但如果Julia字符串包含任何嵌入的NUL字符,则类型转换为Cstring会引发错误(如果C例程将NUL视为终止符,则会导致字符串被静默截断)。如果要将char*传递给不采用NUL终止的C例程(例如,因为传递的是显式字符串长度),或者如果确定Julia字符串不包含NUL并希望跳过检查,则可以使用Ptr{UInt8}作为参数类型。Cstring也可以用作 ccall 返回类型,但在这种情况下,它显然不会引入任何额外的检查,只是为了提高调用的可读性。","category":"page"},{"location":"manual/calling-c-and-fortran-code/","page":"调用 C 和 Fortran 代码","title":"调用 C 和 Fortran 代码","text":"系统独立类型","category":"page"},{"location":"manual/calling-c-and-fortran-code/","page":"调用 C 和 Fortran 代码","title":"调用 C 和 Fortran 代码","text":"C 类型 标准 Julia 别名 Julia 基本类型\nchar Cchar Int8 (x86, x86_64), UInt8 (powerpc, arm)\nlong Clong Int (UNIX), Int32 (Windows)\nunsigned long Culong UInt (UNIX), UInt32 (Windows)\nwchar_t Cwchar_t Int32 (UNIX), UInt16 (Windows)","category":"page"},{"location":"manual/calling-c-and-fortran-code/","page":"调用 C 和 Fortran 代码","title":"调用 C 和 Fortran 代码","text":"note: Note\n调用 Fortran 时,所有输入都必须通过指向堆分配或堆栈分配值的指针传递,因此上述所有类型对应都应在其类型规范周围包含一个额外的 Ptr{..} 或 Ref{..} 包装器。","category":"page"},{"location":"manual/calling-c-and-fortran-code/","page":"调用 C 和 Fortran 代码","title":"调用 C 和 Fortran 代码","text":"warning: Warning\n对于字符串参数 (char*),Julia 类型应该是 Cstring(如果需要以 NUL 结尾的数据),否则为 Ptr{Cchar} 或 Ptr{UInt8}(这两种指针类型具有相同的效果),如上所述,而不是 String。 类似地,对于数组参数(T[] 或 T*),Julia 类型应该还是 Ptr{T},而不是 Vector{T}。","category":"page"},{"location":"manual/calling-c-and-fortran-code/","page":"调用 C 和 Fortran 代码","title":"调用 C 和 Fortran 代码","text":"warning: Warning\nJulia 的 Char 类型是 32 位,这与所有平台上的宽字符类型(wchar_t 或 wint_t)不同。","category":"page"},{"location":"manual/calling-c-and-fortran-code/","page":"调用 C 和 Fortran 代码","title":"调用 C 和 Fortran 代码","text":"warning: Warning\nUnion{} 的返回类型意味着函数不会返回,即 C++11 [[noreturn]] 或 C11 _Noreturn(例如 jl_throw 或 longjmp)。 不要将此用于不返回值(void)但返回的函数,而是使用Cvoid。","category":"page"},{"location":"manual/calling-c-and-fortran-code/","page":"调用 C 和 Fortran 代码","title":"调用 C 和 Fortran 代码","text":"note: Note\n对于 wchar_t* 参数,Julia 类型应为 Cwstring(如果 C 例程需要以 NUL 结尾的字符串),否则为 Ptr{Cwchar_t}。 另请注意,Julia 中的 UTF-8 字符串数据在内部以 NUL 结尾,因此可以将其传递给需要以 NUL 结尾的数据的 C 函数,而无需进行复制(但使用 Cwstring 类型将导致抛出错误,如果字符串本身包含 NUL 字符)。","category":"page"},{"location":"manual/calling-c-and-fortran-code/","page":"调用 C 和 Fortran 代码","title":"调用 C 和 Fortran 代码","text":"note: Note\n可以在 Julia 中使用 Ptr{Ptr{UInt8}} 类型调用采用 char** 类型参数的 C 函数。 例如,以下形式的 C 函数:int main(int argc, char **argv);可以通过以下 Julia 代码调用:argv = [ \"a.out\", \"arg1\", \"arg2\" ]\nccall(:main, Int32, (Int32, Ptr{Ptr{UInt8}}), length(argv), argv)","category":"page"},{"location":"manual/calling-c-and-fortran-code/","page":"调用 C 和 Fortran 代码","title":"调用 C 和 Fortran 代码","text":"note: Note\n对于采用 character(len=*) 类型的可变长度字符串的 Fortran 函数,字符串长度作为隐藏参数提供。 这些参数在列表中的类型和位置是特定于编译器的,编译器供应商通常默认使用 Csize_t 作为类型并将隐藏的参数附加到参数列表的末尾。 虽然此行为对于某些编译器 (GNU) 是固定的,但其他编译器可选 允许将隐藏参数直接放置在字符参数(Intel、PGI)之后。 例如,如下的 Fortran 子程序subroutine test(str1, str2)\ncharacter(len=*) :: str1,str2can be called via the following Julia code, where the lengths are appendedstr1 = \"foo\"\nstr2 = \"bar\"\nccall(:test, Cvoid, (Ptr{UInt8}, Ptr{UInt8}, Csize_t, Csize_t),\n str1, str2, sizeof(str1), sizeof(str2))","category":"page"},{"location":"manual/calling-c-and-fortran-code/","page":"调用 C 和 Fortran 代码","title":"调用 C 和 Fortran 代码","text":"warning: Warning\nFortran 编译器还可以为指针、假定形状(:)和假定大小(*)数组添加其他隐藏参数。 这种行为可以通过使用ISO_C_BINDING并在子例程的定义中包含bind(c)来避免,强烈推荐用于可互操作的代码。 在这种情况下,将没有隐藏的参数,代价是一些语言特性(例如,只允许 character(len=1) 传递字符串)。","category":"page"},{"location":"manual/calling-c-and-fortran-code/","page":"调用 C 和 Fortran 代码","title":"调用 C 和 Fortran 代码","text":"note: Note\n声明为返回 Cvoid 的 C 函数将在 Julia 中返回值 nothing。","category":"page"},{"location":"manual/calling-c-and-fortran-code/#结构类型对应","page":"调用 C 和 Fortran 代码","title":"结构类型对应","text":"","category":"section"},{"location":"manual/calling-c-and-fortran-code/","page":"调用 C 和 Fortran 代码","title":"调用 C 和 Fortran 代码","text":"复合类型,例如 C 中的struct或 Fortran90 中的TYPE(或 F77 的某些变体中的STRUCTURE/RECORD),可以通过创建具有相同字段布局的struct定义在 Julia 中进行镜像复制。","category":"page"},{"location":"manual/calling-c-and-fortran-code/","page":"调用 C 和 Fortran 代码","title":"调用 C 和 Fortran 代码","text":"当递归使用时,isbits 类型被内联存储。 所有其他类型都存储为指向数据的指针。 在 C 中的另一个结构中镜像复制按值使用的结构时,不要尝试手动复制字段,因为这不会保留正确的字段对齐。 相反,建议声明一个 isbits 结构类型并使用它。 未命名的结构在翻译为 Julia 时是不可能的。","category":"page"},{"location":"manual/calling-c-and-fortran-code/","page":"调用 C 和 Fortran 代码","title":"调用 C 和 Fortran 代码","text":"Julia不支持压缩结构和联合声明。","category":"page"},{"location":"manual/calling-c-and-fortran-code/","page":"调用 C 和 Fortran 代码","title":"调用 C 和 Fortran 代码","text":"如果你事先地知道将具有最大大小(可能包括填充)的字段,则可以获得 union 的近似。 将你的字段转换为 Julia 时,将 Julia 字段声明为仅属于该类型。","category":"page"},{"location":"manual/calling-c-and-fortran-code/","page":"调用 C 和 Fortran 代码","title":"调用 C 和 Fortran 代码","text":"参数数组可以用 NTuple 表示。例如,C 符号中的 struct 写成","category":"page"},{"location":"manual/calling-c-and-fortran-code/","page":"调用 C 和 Fortran 代码","title":"调用 C 和 Fortran 代码","text":"struct B {\n int A[3];\n};\n\nb_a_2 = B.A[2];","category":"page"},{"location":"manual/calling-c-and-fortran-code/","page":"调用 C 和 Fortran 代码","title":"调用 C 和 Fortran 代码","text":"可以用 Julia 写成","category":"page"},{"location":"manual/calling-c-and-fortran-code/","page":"调用 C 和 Fortran 代码","title":"调用 C 和 Fortran 代码","text":"struct B\n A::NTuple{3, Cint}\nend\n\nb_a_2 = B.A[3] # note the difference in indexing (1-based in Julia, 0-based in C)","category":"page"},{"location":"manual/calling-c-and-fortran-code/","page":"调用 C 和 Fortran 代码","title":"调用 C 和 Fortran 代码","text":"不直接支持未知大小的数组(由[] 或[0] 指定的符合C99 的可变长度结构)。 通常处理这些的最好方法是直接处理字节偏移量。 例如,如果一个 C 库声明了一个正确的字符串类型并返回一个指向它的指针:","category":"page"},{"location":"manual/calling-c-and-fortran-code/","page":"调用 C 和 Fortran 代码","title":"调用 C 和 Fortran 代码","text":"struct String {\n int strlen;\n char data[];\n};","category":"page"},{"location":"manual/calling-c-and-fortran-code/","page":"调用 C 和 Fortran 代码","title":"调用 C 和 Fortran 代码","text":"在 Julia 中,我们可以独立访问这些部分以制作该字符串的副本:","category":"page"},{"location":"manual/calling-c-and-fortran-code/","page":"调用 C 和 Fortran 代码","title":"调用 C 和 Fortran 代码","text":"str = from_c::Ptr{Cvoid}\nlen = unsafe_load(Ptr{Cint}(str))\nunsafe_string(str + Core.sizeof(Cint), len)","category":"page"},{"location":"manual/calling-c-and-fortran-code/#类型参数","page":"调用 C 和 Fortran 代码","title":"类型参数","text":"","category":"section"},{"location":"manual/calling-c-and-fortran-code/","page":"调用 C 和 Fortran 代码","title":"调用 C 和 Fortran 代码","text":"当定义了方法时,ccall 和 @cfunction 的类型参数被静态地评估。 因此,它们必须采用字面量元组的形式,而不是变量,并且不能引用局部变量。","category":"page"},{"location":"manual/calling-c-and-fortran-code/","page":"调用 C 和 Fortran 代码","title":"调用 C 和 Fortran 代码","text":"这听起来像是一个奇怪的限制,但请记住,由于 C 不是像 Julia 那样的动态语言,它的函数只能接受具有静态已知的固定签名的参数类型。","category":"page"},{"location":"manual/calling-c-and-fortran-code/","page":"调用 C 和 Fortran 代码","title":"调用 C 和 Fortran 代码","text":"然而,虽然必须静态地知道类型布局才能计算预期的 C ABI,但函数的静态参数被视为此静态环境的一部分。函数的静态参数可以用作调用签名中的类型参数,只要它们不影响类型的布局即可。例如, f(x::T) where {T} = ccall(:valid, Ptr{T}, (Ptr{T},), x) 是有效的,因为 Ptr 始终是字大小的原始类型。但是, g(x::T) where {T} = ccall(:notvalid, T, (T,), x) 是无效的,因为 T 的类型布局不是静态已知的。","category":"page"},{"location":"manual/calling-c-and-fortran-code/#SIMD-值","page":"调用 C 和 Fortran 代码","title":"SIMD 值","text":"","category":"section"},{"location":"manual/calling-c-and-fortran-code/","page":"调用 C 和 Fortran 代码","title":"调用 C 和 Fortran 代码","text":"注意:此功能目前仅在 64 位 x86 和 AArch64 平台上实现。","category":"page"},{"location":"manual/calling-c-and-fortran-code/","page":"调用 C 和 Fortran 代码","title":"调用 C 和 Fortran 代码","text":"如果 C/C++ 例程具有本机 SIMD 类型的参数或返回值,则相应的 Julia 类型是自然映射到 SIMD 类型的VecElement 的同构元组。 具体来说:","category":"page"},{"location":"manual/calling-c-and-fortran-code/","page":"调用 C 和 Fortran 代码","title":"调用 C 和 Fortran 代码","text":"元组的大小必须与 SIMD 类型相同。 例如,一个表示 __m128 的元组在 x86 上必须有 16 字节的大小。元组的元素类型必须是 VecElement{T} 的一个实例,其中 T 是一个原始类型是 1、2、4 或 8 个字节。","category":"page"},{"location":"manual/calling-c-and-fortran-code/","page":"调用 C 和 Fortran 代码","title":"调用 C 和 Fortran 代码","text":"例如,考虑这个使用 AVX 内在函数的 C 例程:","category":"page"},{"location":"manual/calling-c-and-fortran-code/","page":"调用 C 和 Fortran 代码","title":"调用 C 和 Fortran 代码","text":"#include \n\n__m256 dist( __m256 a, __m256 b ) {\n return _mm256_sqrt_ps(_mm256_add_ps(_mm256_mul_ps(a, a),\n _mm256_mul_ps(b, b)));\n}","category":"page"},{"location":"manual/calling-c-and-fortran-code/","page":"调用 C 和 Fortran 代码","title":"调用 C 和 Fortran 代码","text":"以下 Julia 代码使用 ccall 调用 dist:","category":"page"},{"location":"manual/calling-c-and-fortran-code/","page":"调用 C 和 Fortran 代码","title":"调用 C 和 Fortran 代码","text":"const m256 = NTuple{8, VecElement{Float32}}\n\na = m256(ntuple(i -> VecElement(sin(Float32(i))), 8))\nb = m256(ntuple(i -> VecElement(cos(Float32(i))), 8))\n\nfunction call_dist(a::m256, b::m256)\n ccall((:dist, \"libdist\"), m256, (m256, m256), a, b)\nend\n\nprintln(call_dist(a,b))","category":"page"},{"location":"manual/calling-c-and-fortran-code/","page":"调用 C 和 Fortran 代码","title":"调用 C 和 Fortran 代码","text":"主机必须具有必要的 SIMD 寄存器。 例如,上面的代码将无法在没有 AVX 支持的主机上运行。","category":"page"},{"location":"manual/calling-c-and-fortran-code/#内存所有权","page":"调用 C 和 Fortran 代码","title":"内存所有权","text":"","category":"section"},{"location":"manual/calling-c-and-fortran-code/","page":"调用 C 和 Fortran 代码","title":"调用 C 和 Fortran 代码","text":"malloc/free","category":"page"},{"location":"manual/calling-c-and-fortran-code/","page":"调用 C 和 Fortran 代码","title":"调用 C 和 Fortran 代码","text":"此类对象的内存分配和释放必须通过调用正在使用的库中的适当清理例程来处理,就像在任何 C 程序中一样。 不要尝试在 Julia 中使用 Libc.free 释放从 C 库接收的对象,因为这可能会导致通过错误的库调用 free 函数并导致进程中止。 反过来(传递在 Julia 中分配的对象以供外部库释放)同样无效。","category":"page"},{"location":"manual/calling-c-and-fortran-code/#何时使用-T、Ptr{T}-以及-Ref{T}","page":"调用 C 和 Fortran 代码","title":"何时使用 T、Ptr{T} 以及 Ref{T}","text":"","category":"section"},{"location":"manual/calling-c-and-fortran-code/","page":"调用 C 和 Fortran 代码","title":"调用 C 和 Fortran 代码","text":"在对外部C例程的Julia代码包装调用中,普通(非指针)数据应该在ccall 中声明为T类型,因为它们是通过值传递的。对于接受指针的C代码,Ref{T} 通常应用于输入参数的类型,允许通过对Base.cconvert 的隐式调用使用指向Julia或C管理的内存的指针。相反,被调用的C函数返回的指针应该声明为输出类型Ptr{T},这反映了指向的内存仅由C管理。C结构中包含的指针应在相应的Julia结构类型中表示为Ptr{T}类型的字段,这些结构类型旨在模拟相应C结构的内部结构。","category":"page"},{"location":"manual/calling-c-and-fortran-code/","page":"调用 C 和 Fortran 代码","title":"调用 C 和 Fortran 代码","text":"在 Julia 代码包装对外部 Fortran 例程的调用中,所有输入参数都应声明为Ref{T}类型,因为 Fortran 通过指向内存位置的指针传递所有变量。 Fortran 子程序的返回类型应该是 Cvoid,或者 Fortran 函数的返回类型应该是 T,返回类型是 T。","category":"page"},{"location":"manual/calling-c-and-fortran-code/#将-C-函数映射到-Julia","page":"调用 C 和 Fortran 代码","title":"将 C 函数映射到 Julia","text":"","category":"section"},{"location":"manual/calling-c-and-fortran-code/#ccall-/-@cfunction-参数翻译指南","page":"调用 C 和 Fortran 代码","title":"ccall / @cfunction 参数翻译指南","text":"","category":"section"},{"location":"manual/calling-c-and-fortran-code/","page":"调用 C 和 Fortran 代码","title":"调用 C 和 Fortran 代码","text":"将 C 参数列表翻译为 Julia:","category":"page"},{"location":"manual/calling-c-and-fortran-code/","page":"调用 C 和 Fortran 代码","title":"调用 C 和 Fortran 代码","text":"T,其中 T 取值为:char、int、long、short、float、double、complex、enum 或其等价的 typedef 类型\nT,其中 T 是等价的 Julia Bits 类型(参见上表)\n如果 T 是 enum,则参数类型应等价于 Cint 或 Cuint\n参数值将被复制(按值传递)\nstruct T (包括 struct 的 typedef)\nT,其中 T 是 Julia 叶类型\n参数值将被复制(按值传递)\nvoid*","category":"page"},{"location":"manual/calling-c-and-fortran-code/","page":"调用 C 和 Fortran 代码","title":"调用 C 和 Fortran 代码","text":" * 取决于如何使用此参数,首先将其翻译为所需的指针类型,然后使用此列表中的其余规则确定 Julia 等价项\n * 这个参数可以声明为 `Ptr{Cvoid}`,如果它真的只是一个未知的指针","category":"page"},{"location":"manual/calling-c-and-fortran-code/","page":"调用 C 和 Fortran 代码","title":"调用 C 和 Fortran 代码","text":"jl_value_t*\nAny\n参数值必须是有效的 Julia 对象\njl_value_t* const*\nRef{Any}\n参数列表必须是有效的 Julia 对象(或 C_NULL)\n不能用于输出参数,除非用户能够单独安排要GC保留的对象\nT* \nRef{T},其中 T 是与 T 对应的 Julia 类型\n如果它是 inlinealloc 类型,则将复制参数值(包括 isbits,否则,值必须是有效的 Julia 对象)\nT (*)(...) (例如,指向函数的指针)\nPtr{Cvoid}(您可能需要显式使用 @cfunction 来创建此指针)\n... (例如,可变参数)\n[对于 ccall]:T...,其中 T 是所有剩余参数的单个 Julia 类型\n[对于 @ccall]:; va_arg1::T, va_arg2::S, etc,其中 T 和 S 是 Julia 类型(即,使用 ; 将常规参数与可变参数分开)\n目前不支持 @cfunction\nva_arg\nccall 或 @cfunction 不支持","category":"page"},{"location":"manual/calling-c-and-fortran-code/#ccall-/-@cfunction-返回类型翻译指南","page":"调用 C 和 Fortran 代码","title":"ccall / @cfunction 返回类型翻译指南","text":"","category":"section"},{"location":"manual/calling-c-and-fortran-code/","page":"调用 C 和 Fortran 代码","title":"调用 C 和 Fortran 代码","text":"将 C 返回类型翻译为 Julia:","category":"page"},{"location":"manual/calling-c-and-fortran-code/","page":"调用 C 和 Fortran 代码","title":"调用 C 和 Fortran 代码","text":"void\nCvoid(这将返回单例实例 nothing::Cvoid)\nT,其中 T 是原始类型之一:char,int,long,short,float,double,complex,enum 或任何等效的 typedef\nT, 其中 T 是等效的 Julia Bits 类型(请参阅上表)\n如果 T 是 enum,则参数类型应等效于 Cint 或 Cuint\n参数值将被复制(按值返回)\nstruct T (包括 typedef 到结构体)\nT,其中 T 是 Julia 叶类型\n参数值将被复制(按值返回)\nvoid*\n* 取决于如何使用此参数,首先将其翻译为所需的指针类型,然后使用此列表中的其余规则确定 Julia 等效项\n* 如果它确实只是一个未知指针,则可以将此参数声明为 `Ptr{Cvoid}`\njl_value_t*\nAny\n参数值必须是有效的 Julia 对象\njl_value_t**\nPtr{Any}(Ref{Any} 是无效的返回类型)\nT*\n如果内存已由 Julia 拥有,或者是 isbits 类型,并且已知为非空:\nRef{T},其中 T 是对应于 T 的 Julia 类型\n返回类型 Ref{Any} 无效,它应该是 Any(对应于 jl_value_t*)或 Ptr{Any}(对应于 jl_value_t**)\nC 不得 修改通过 Ref{T} 返回的内存,如果 T 是 isbits 类型\n如果内存由 C 拥有:\nPtr{T},其中 T 是对应于 T 的 Julia 类型\nT (*)(...)(例如,指向函数的指针)\nPtr{Cvoid},以便从 Julia 直接调用此函数,你需要将此作为 ccall 的第一个参数传递。 请参阅 间接调用。","category":"page"},{"location":"manual/calling-c-and-fortran-code/#传递修改输入的指针","page":"调用 C 和 Fortran 代码","title":"传递修改输入的指针","text":"","category":"section"},{"location":"manual/calling-c-and-fortran-code/","page":"调用 C 和 Fortran 代码","title":"调用 C 和 Fortran 代码","text":"因为 C 不支持多个返回值,所以 C 函数通常会使用指向函数将修改的数据的指针。 要在 ccall 中完成此操作,你需要首先将值封装在适当类型的 Ref{T} 中。 当你将这个 Ref 对象作为参数传递时,Julia 会自动传递一个指向封装数据的 C 指针:","category":"page"},{"location":"manual/calling-c-and-fortran-code/","page":"调用 C 和 Fortran 代码","title":"调用 C 和 Fortran 代码","text":"width = Ref{Cint}(0)\nrange = Ref{Cfloat}(0)\nccall(:foo, Cvoid, (Ref{Cint}, Ref{Cfloat}), width, range)","category":"page"},{"location":"manual/calling-c-and-fortran-code/","page":"调用 C 和 Fortran 代码","title":"调用 C 和 Fortran 代码","text":"返回时,可以通过width[]和range[]检索width和range的内容(如果它们被foo改变的话); 也就是说,它们就像零维数组。","category":"page"},{"location":"manual/calling-c-and-fortran-code/#C-包装器示例","page":"调用 C 和 Fortran 代码","title":"C 包装器示例","text":"","category":"section"},{"location":"manual/calling-c-and-fortran-code/","page":"调用 C 和 Fortran 代码","title":"调用 C 和 Fortran 代码","text":"让我们从一个返回 Ptr 类型的 C 包装器的简单示例开始:","category":"page"},{"location":"manual/calling-c-and-fortran-code/","page":"调用 C 和 Fortran 代码","title":"调用 C 和 Fortran 代码","text":"mutable struct gsl_permutation\nend\n\n# The corresponding C signature is\n# gsl_permutation * gsl_permutation_alloc (size_t n);\nfunction permutation_alloc(n::Integer)\n output_ptr = ccall(\n (:gsl_permutation_alloc, :libgsl), # name of C function and library\n Ptr{gsl_permutation}, # output type\n (Csize_t,), # tuple of input types\n n # name of Julia variable to pass in\n )\n if output_ptr == C_NULL # Could not allocate memory\n throw(OutOfMemoryError())\n end\n return output_ptr\nend","category":"page"},{"location":"manual/calling-c-and-fortran-code/","page":"调用 C 和 Fortran 代码","title":"调用 C 和 Fortran 代码","text":"GNU 科学图书馆(这里假设可以通过:libgsl 访问)定义了一个不透明的指针,gsl_permutation *,作为 C 函数gsl_permutation_alloc 的返回类型。 由于用户代码永远不必查看 gsl_permutation 结构内部,相应的 Julia 包装器只需要一个新的类型声明 gsl_permutation,它没有内部字段,其唯一目的是放置在 Ptr类型的类型参数中。 ccall 的返回类型声明为 Ptr{gsl_permutation},因为 output_ptr 分配和指向的内存由 C 控制。","category":"page"},{"location":"manual/calling-c-and-fortran-code/","page":"调用 C 和 Fortran 代码","title":"调用 C 和 Fortran 代码","text":"输入 n 是按值传递的,因此函数的输入签名被简单地声明为 (Csize_t,),不需要任何 Ref 或 Ptr。 (如果包装器改为调用 Fortran 函数,则相应的函数输入签名将改为 (Ref{Csize_t},),因为 Fortran 变量是通过指针传递的。)此外,n 可以是任何可转换的类型 到一个 Csize_t 整数; ccall 隐式调用 Base.cconvert(Csize_t, n)。","category":"page"},{"location":"manual/calling-c-and-fortran-code/","page":"调用 C 和 Fortran 代码","title":"调用 C 和 Fortran 代码","text":"这是包装相应析构函数的第二个示例:","category":"page"},{"location":"manual/calling-c-and-fortran-code/","page":"调用 C 和 Fortran 代码","title":"调用 C 和 Fortran 代码","text":"# The corresponding C signature is\n# void gsl_permutation_free (gsl_permutation * p);\nfunction permutation_free(p::Ref{gsl_permutation})\n ccall(\n (:gsl_permutation_free, :libgsl), # name of C function and library\n Cvoid, # output type\n (Ref{gsl_permutation},), # tuple of input types\n p # name of Julia variable to pass in\n )\nend","category":"page"},{"location":"manual/calling-c-and-fortran-code/","page":"调用 C 和 Fortran 代码","title":"调用 C 和 Fortran 代码","text":"这里,输入p被声明为Ref{gsl_permutation}类型,这意味着p指向的内存可以由Julia或C管理。由C分配的内存指针应该是类型 Ptr{gsl_permutation},但它可以使用 Base.cconvert 进行转换,因此","category":"page"},{"location":"manual/calling-c-and-fortran-code/","page":"调用 C 和 Fortran 代码","title":"调用 C 和 Fortran 代码","text":"现在,如果你仔细观察这个例子,你可能会注意到它是不正确的,因为我们上面对首选声明类型的解释。 你看到了吗? 我们正在调用的函数将释放内存。 这种类型的操作不能被赋予 Julia 对象(它会崩溃或导致内存损坏)。因此,将 p 类型声明为 Ptr{gsl_permutation } 可能更可取,这样用户就更难错误地传递另一种对象,而不是通过 gsl_permutation_alloc 获得的对象。","category":"page"},{"location":"manual/calling-c-and-fortran-code/","page":"调用 C 和 Fortran 代码","title":"调用 C 和 Fortran 代码","text":"如果 C 包装器从不希望用户将指针传递给 Julia 管理的内存,那么使用 p::Ptr{gsl_permutation} 作为包装器的方法签名,类似地在 ccall 中也是可以接受。","category":"page"},{"location":"manual/calling-c-and-fortran-code/","page":"调用 C 和 Fortran 代码","title":"调用 C 和 Fortran 代码","text":"这是传递 Julia 数组的第三个示例:","category":"page"},{"location":"manual/calling-c-and-fortran-code/","page":"调用 C 和 Fortran 代码","title":"调用 C 和 Fortran 代码","text":"# The corresponding C signature is\n# int gsl_sf_bessel_Jn_array (int nmin, int nmax, double x,\n# double result_array[])\nfunction sf_bessel_Jn_array(nmin::Integer, nmax::Integer, x::Real)\n if nmax < nmin\n throw(DomainError())\n end\n result_array = Vector{Cdouble}(undef, nmax - nmin + 1)\n errorcode = ccall(\n (:gsl_sf_bessel_Jn_array, :libgsl), # name of C function and library\n Cint, # output type\n (Cint, Cint, Cdouble, Ref{Cdouble}),# tuple of input types\n nmin, nmax, x, result_array # names of Julia variables to pass in\n )\n if errorcode != 0\n error(\"GSL error code $errorcode\")\n end\n return result_array\nend","category":"page"},{"location":"manual/calling-c-and-fortran-code/","page":"调用 C 和 Fortran 代码","title":"调用 C 和 Fortran 代码","text":"包装的 C 函数返回一个整数错误代码; Bessel J 函数的实际评估结果填充 Julia 数组 result_array。 这个变量被声明为一个 Ref{Cdouble},因为它的内存是由 Julia 分配和管理的。 对 Base.cconvert(Ref{Cdouble}, result_array) 的隐式调用将指向 Julia 数组数据结构的 Julia 指针解包为 C 可以理解的形式。","category":"page"},{"location":"manual/calling-c-and-fortran-code/#Fortran-包装器示例","page":"调用 C 和 Fortran 代码","title":"Fortran 包装器示例","text":"","category":"section"},{"location":"manual/calling-c-and-fortran-code/","page":"调用 C 和 Fortran 代码","title":"调用 C 和 Fortran 代码","text":"以下示例利用 ccall 调用通用 Fortran 库 (libBLAS) 中的函数来计算点积。 请注意,这里的参数映射与上面的有点不同,因为我们需要从 Julia 映射到 Fortran。 在每个参数类型上,我们指定 Ref 或 Ptr。 此修改约定可能特定于你的 Fortran 编译器和操作系统,并且可能未记录在案。 但是,将每个包装在一个 Ref(或 Ptr,等效地)中是 Fortran 编译器实现的一个常见要求:","category":"page"},{"location":"manual/calling-c-and-fortran-code/","page":"调用 C 和 Fortran 代码","title":"调用 C 和 Fortran 代码","text":"function compute_dot(DX::Vector{Float64}, DY::Vector{Float64})\n @assert length(DX) == length(DY)\n n = length(DX)\n incx = incy = 1\n product = ccall((:ddot_, \"libLAPACK\"),\n Float64,\n (Ref{Int32}, Ptr{Float64}, Ref{Int32}, Ptr{Float64}, Ref{Int32}),\n n, DX, incx, DY, incy)\n return product\nend","category":"page"},{"location":"manual/calling-c-and-fortran-code/#垃圾回收安全","page":"调用 C 和 Fortran 代码","title":"垃圾回收安全","text":"","category":"section"},{"location":"manual/calling-c-and-fortran-code/","page":"调用 C 和 Fortran 代码","title":"调用 C 和 Fortran 代码","text":"将数据传递给 ccall 时,最好避免使用 pointer 函数。 而是定义一个转换方法并将变量直接传递给 ccall。 ccall 自动安排它的所有参数都将从垃圾收集中保留,直到调用返回。 如果 C API 将存储对 Julia 分配的内存的引用,则在 ccall 返回后,你必须确保该对象对垃圾收集器保持可见。 建议的方法是创建一个类型为 Array{Ref,1} 的全局变量来保存这些值,直到 C 库通知你它已完成使用它们。","category":"page"},{"location":"manual/calling-c-and-fortran-code/","page":"调用 C 和 Fortran 代码","title":"调用 C 和 Fortran 代码","text":"每当你创建了一个指向 Julia 数据的指针时,你必须确保原始数据存在,直到你完成使用该指针。 Julia 中的许多方法,例如 unsafe_load 和 String 复制数据而不是获取缓冲区的所有权,因此可以安全地释放(或更改)原始数而不影响 Julia。 一个值得注意的例外是 unsafe_wrap,出于性能原因,它共享(或可以被告知拥有)底层缓冲区。","category":"page"},{"location":"manual/calling-c-and-fortran-code/","page":"调用 C 和 Fortran 代码","title":"调用 C 和 Fortran 代码","text":"垃圾收集器不保证任何终结顺序。 也就是说,如果 a 包含对 b 的引用,并且 a 和 b 都需要进行垃圾回收,则不能保证 b 会在 a 之后完成。 如果 a 的正确终结取决于 b 是否有效,则必须以其他方式处理。","category":"page"},{"location":"manual/calling-c-and-fortran-code/#Non-constant-Function-Specifications","page":"调用 C 和 Fortran 代码","title":"非常数函数规范","text":"","category":"section"},{"location":"manual/calling-c-and-fortran-code/","page":"调用 C 和 Fortran 代码","title":"调用 C 和 Fortran 代码","text":"在某些情况下,所需库的确切名称或路径是事先未知的,必须在运行时计算。 为了处理这种情况,(name, library) 规范的库组件可以是一个函数调用,例如 (:dgemm_, find_blas())。 调用表达式将在执行 ccall 本身时执行。 但是,假设库位置一旦确定就不会改变,因此调用的结果可以被缓存和重用。 因此,表达式执行的次数是未指定的,多次调用返回不同的值会导致未指定的行为。","category":"page"},{"location":"manual/calling-c-and-fortran-code/","page":"调用 C 和 Fortran 代码","title":"调用 C 和 Fortran 代码","text":"如果需要更大的灵活性,可以通过 eval 分段使用计算值作为函数名称,如下所示:","category":"page"},{"location":"manual/calling-c-and-fortran-code/","page":"调用 C 和 Fortran 代码","title":"调用 C 和 Fortran 代码","text":"@eval ccall(($(string(\"a\", \"b\")), \"lib\"), ...","category":"page"},{"location":"manual/calling-c-and-fortran-code/","page":"调用 C 和 Fortran 代码","title":"调用 C 和 Fortran 代码","text":"此表达式使用 string 构造一个名称,然后将此名称替换为一个新的 ccall 表达式,然后对其进行评估。 请记住,eval 仅在顶层运行,因此在此表达式中局部变量将不可用(除非它们的值被替换为 $)。 出于这个原因,eval 通常仅用于形成顶级定义,例如在包装包含许多类似函数的库时。 可以为 @cfunction 构造一个类似的示例。","category":"page"},{"location":"manual/calling-c-and-fortran-code/","page":"调用 C 和 Fortran 代码","title":"调用 C 和 Fortran 代码","text":"但是,这样做也会很慢并且会泄漏内存,因此你通常应该避免这种情况,而是继续阅读。 下一节讨论如何使用间接调用来有效地实现类似的效果。","category":"page"},{"location":"manual/calling-c-and-fortran-code/#非直接调用","page":"调用 C 和 Fortran 代码","title":"非直接调用","text":"","category":"section"},{"location":"manual/calling-c-and-fortran-code/","page":"调用 C 和 Fortran 代码","title":"调用 C 和 Fortran 代码","text":"ccall 的第一个参数也可以是在运行时计算的表达式。 在这种情况下,表达式的计算结果必须为 Ptr,它将用作要调用的本地函数的地址。 当第一个 ccall 参数包含对非常量(例如局部变量、函数参数或非常量全局变量)的引用时,会发生此行为。","category":"page"},{"location":"manual/calling-c-and-fortran-code/","page":"调用 C 和 Fortran 代码","title":"调用 C 和 Fortran 代码","text":"例如,你可以通过 dlsym 查找函数,然后将其缓存在该会话的共享引用中。 例如:","category":"page"},{"location":"manual/calling-c-and-fortran-code/","page":"调用 C 和 Fortran 代码","title":"调用 C 和 Fortran 代码","text":"macro dlsym(func, lib)\n z = Ref{Ptr{Cvoid}}(C_NULL)\n quote\n let zlocal = $z[]\n if zlocal == C_NULL\n zlocal = dlsym($(esc(lib))::Ptr{Cvoid}, $(esc(func)))::Ptr{Cvoid}\n $z[] = zlocal\n end\n zlocal\n end\n end\nend\n\nmylibvar = Libdl.dlopen(\"mylib\")\nccall(@dlsym(\"myfunc\", mylibvar), Cvoid, ())","category":"page"},{"location":"manual/calling-c-and-fortran-code/#cfunction-闭包","page":"调用 C 和 Fortran 代码","title":"cfunction 闭包","text":"","category":"section"},{"location":"manual/calling-c-and-fortran-code/","page":"调用 C 和 Fortran 代码","title":"调用 C 和 Fortran 代码","text":"@cfunction 的第一个参数可以用 $ 标记,在这种情况下,返回值将改为结束参数的 struct CFunction。 你必须确保此返回对象保持活动状态,直到完成对它的所有使用。 当这个引用被删除和 atexit 时,cfunction 指针处的内容和代码将通过 finalizer 删除。 这通常不是必需的,因为此功能在 C 中不存在,但对于处理不提供单独的闭包环境参数的设计不良的 API 很有用。","category":"page"},{"location":"manual/calling-c-and-fortran-code/","page":"调用 C 和 Fortran 代码","title":"调用 C 和 Fortran 代码","text":"function qsort(a::Vector{T}, cmp) where T\n isbits(T) || throw(ArgumentError(\"this method can only qsort isbits arrays\"))\n callback = @cfunction $cmp Cint (Ref{T}, Ref{T})\n # Here, `callback` isa Base.CFunction, which will be converted to Ptr{Cvoid}\n # (and protected against finalization) by the ccall\n ccall(:qsort, Cvoid, (Ptr{T}, Csize_t, Csize_t, Ptr{Cvoid}),\n a, length(a), Base.elsize(a), callback)\n # We could instead use:\n # GC.@preserve callback begin\n # use(Base.unsafe_convert(Ptr{Cvoid}, callback))\n # end\n # if we needed to use it outside of a `ccall`\n return a\nend","category":"page"},{"location":"manual/calling-c-and-fortran-code/","page":"调用 C 和 Fortran 代码","title":"调用 C 和 Fortran 代码","text":"note: Note\n闭包 @cfunction 依赖于 LLVM Trampolines,并非在所有平台(例如 ARM 和 PowerPC)上都可用。","category":"page"},{"location":"manual/calling-c-and-fortran-code/#关闭库","page":"调用 C 和 Fortran 代码","title":"关闭库","text":"","category":"section"},{"location":"manual/calling-c-and-fortran-code/","page":"调用 C 和 Fortran 代码","title":"调用 C 和 Fortran 代码","text":"关闭(卸载)库以便重新加载有时很有用。 例如,在开发与 Julia 一起使用的 C 代码时,可能需要编译、从 Julia 调用 C 代码,然后关闭库、进行编辑、重新编译并加载新的更改。 可以重新启动 Julia 或使用 Libdl 函数来显式管理库,例如:","category":"page"},{"location":"manual/calling-c-and-fortran-code/","page":"调用 C 和 Fortran 代码","title":"调用 C 和 Fortran 代码","text":"lib = Libdl.dlopen(\"./my_lib.so\") # 显式打开库\nsym = Libdl.dlsym(lib, :my_fcn) # 获得用于调用函数的符号\nccall(sym, ...) # 直接用指针 `sym` 而不是 (symbol, library) 元组,其余参数保持不变\nLibdl.dlclose(lib) # 显式关闭库","category":"page"},{"location":"manual/calling-c-and-fortran-code/","page":"调用 C 和 Fortran 代码","title":"调用 C 和 Fortran 代码","text":"请注意,当将 ccall 与输入元组(例如,ccall((:my_fcn, \"./my_lib.so\"), ...))一起使用时,库会隐式打开,并且可能不会显式关闭。","category":"page"},{"location":"manual/calling-c-and-fortran-code/#调用规约","page":"调用 C 和 Fortran 代码","title":"调用规约","text":"","category":"section"},{"location":"manual/calling-c-and-fortran-code/","page":"调用 C 和 Fortran 代码","title":"调用 C 和 Fortran 代码","text":"ccall 的第二个参数可以选择是调用约定说明符(直接在返回类型之前)。 没有任何说明符,使用平台默认的 C 调用约定。 其他支持的约定是:stdcall、cdecl、fastcall 和thiscall(64 位Windows 上无操作)。 例如(来自base/libc.jl)我们看到与上面相同的gethostnameccall,但具有正确的Windows签名:","category":"page"},{"location":"manual/calling-c-and-fortran-code/","page":"调用 C 和 Fortran 代码","title":"调用 C 和 Fortran 代码","text":"hn = Vector{UInt8}(undef, 256)\nerr = ccall(:gethostname, stdcall, Int32, (Ptr{UInt8}, UInt32), hn, length(hn))","category":"page"},{"location":"manual/calling-c-and-fortran-code/","page":"调用 C 和 Fortran 代码","title":"调用 C 和 Fortran 代码","text":"请参阅 LLVM Language Reference 来获得更多信息。","category":"page"},{"location":"manual/calling-c-and-fortran-code/","page":"调用 C 和 Fortran 代码","title":"调用 C 和 Fortran 代码","text":"还有一个额外的特殊调用约定 llvmcall,它允许直接插入对 LLVM 内部函数的调用。 这在针对不常见的平台(例如 GPGPU)时特别有用。 例如,对于CUDA,我们需要能够读取线程索引:","category":"page"},{"location":"manual/calling-c-and-fortran-code/","page":"调用 C 和 Fortran 代码","title":"调用 C 和 Fortran 代码","text":"ccall(\"llvm.nvvm.read.ptx.sreg.tid.x\", llvmcall, Int32, ())","category":"page"},{"location":"manual/calling-c-and-fortran-code/","page":"调用 C 和 Fortran 代码","title":"调用 C 和 Fortran 代码","text":"与任何 ccall 一样,参数签名必须完全正确。另外,请注意,与Core.Intrinsics开放的等效Julia函数不同,没有兼容层级可以确保内在函数有意义并在当前目标上工作。","category":"page"},{"location":"manual/calling-c-and-fortran-code/#访问全局变量","page":"调用 C 和 Fortran 代码","title":"访问全局变量","text":"","category":"section"},{"location":"manual/calling-c-and-fortran-code/","page":"调用 C 和 Fortran 代码","title":"调用 C 和 Fortran 代码","text":"可以使用 cglobal 函数按名称访问本地库导出的全局变量。 cglobal 的参数与 ccall 使用相同的符号规范,以及描述存储在变量中的值的类型:","category":"page"},{"location":"manual/calling-c-and-fortran-code/","page":"调用 C 和 Fortran 代码","title":"调用 C 和 Fortran 代码","text":"julia> cglobal((:errno, :libc), Int32)\nPtr{Int32} @0x00007f418d0816b8","category":"page"},{"location":"manual/calling-c-and-fortran-code/","page":"调用 C 和 Fortran 代码","title":"调用 C 和 Fortran 代码","text":"结果是一个给出值地址的指针。 可以使用 unsafe_load 和 unsafe_store! 通过这个指针来操作该值。","category":"page"},{"location":"manual/calling-c-and-fortran-code/","page":"调用 C 和 Fortran 代码","title":"调用 C 和 Fortran 代码","text":"note: Note\n在名为“libc”的库中可能找不到此 errno 符号,因为这是系统编译器的实现细节。 通常标准库符号应该只通过名称访问,允许编译器填写正确的符号。 然而,这个例子中显示的 errno 符号在大多数编译器中都是特殊的,所以这里看到的值可能不是你所期望或想要的。 在任何支持多线程的系统上用 C 编译等效代码通常实际上会调用不同的函数(通过宏预处理器重载),并且可能给出与此处打印的遗留值不同的结果。","category":"page"},{"location":"manual/calling-c-and-fortran-code/#通过指针来访问数据","page":"调用 C 和 Fortran 代码","title":"通过指针来访问数据","text":"","category":"section"},{"location":"manual/calling-c-and-fortran-code/","page":"调用 C 和 Fortran 代码","title":"调用 C 和 Fortran 代码","text":"以下方法被描述为“不安全”,因为错误的指针或类型声明会导致 Julia 突然终止。","category":"page"},{"location":"manual/calling-c-and-fortran-code/","page":"调用 C 和 Fortran 代码","title":"调用 C 和 Fortran 代码","text":"给定一个 Ptr{T},通常可以使用 unsafe_load(ptr, [index]) 将 T 类型的内容从引用的内存复制到 Julia 对象中。 index 参数是可选的(默认为 1),并遵循基于 1 的索引的 Julia 惯例。 此函数类似于 getindex 和 setindex! 的行为(例如[] 访问语法)。","category":"page"},{"location":"manual/calling-c-and-fortran-code/","page":"调用 C 和 Fortran 代码","title":"调用 C 和 Fortran 代码","text":"返回值将是一个初始化为包含引用内存内容副本的新对象。 引用的内存可以安全地释放或释放。","category":"page"},{"location":"manual/calling-c-and-fortran-code/","page":"调用 C 和 Fortran 代码","title":"调用 C 和 Fortran 代码","text":"如果 T 是 Any,则假定内存包含对 Julia 对象的引用(jl_value_t*),结果将是对该对象的引用,并且不会复制该对象。 在这种情况下,你必须小心确保对象始终对垃圾收集器可见(指针不计数,但新引用计数)以确保内存不会过早释放。 请注意,如果对象最初不是由 Julia 分配的,则新对象将永远不会被 Julia 的垃圾收集器终结。 如果 Ptr 本身实际上是一个 jl_value_t*,它可以通过 unsafe_pointer_to_objref(ptr) 转换回 Julia 对象引用。 (Julia 值 v 可以通过调用 pointer_from_objref(v) 转换为 jl_value_t* 指针,如 Ptr{Cvoid}。)","category":"page"},{"location":"manual/calling-c-and-fortran-code/","page":"调用 C 和 Fortran 代码","title":"调用 C 和 Fortran 代码","text":"可以使用 unsafe_store!(ptr, value, [index]) 执行反向操作(将数据写入 Ptr{T})。 目前,这仅支持原始类型或其他无指针(isbits)不可变结构类型。","category":"page"},{"location":"manual/calling-c-and-fortran-code/","page":"调用 C 和 Fortran 代码","title":"调用 C 和 Fortran 代码","text":"任何引发错误的操作目前可能尚未实现,应作为错误发布,以便解决。","category":"page"},{"location":"manual/calling-c-and-fortran-code/","page":"调用 C 和 Fortran 代码","title":"调用 C 和 Fortran 代码","text":"如果感兴趣的指针是纯数据数组(原始类型或不可变结构),则函数 unsafe_wrap(Array, ptr,dims, own = false) 可能更有用。 如果 Julia 应该“获得”底层缓冲区的所有权并在返回的 Array 对象最终确定时调用 free(ptr),则最后一个参数应该为 true。 如果省略了 own 参数或为 false,则调用者必须确保缓冲区一直存在,直到所有访问完成。","category":"page"},{"location":"manual/calling-c-and-fortran-code/","page":"调用 C 和 Fortran 代码","title":"调用 C 和 Fortran 代码","text":"Julia 中 Ptr 类型的算术(例如使用 +)与 C 的指针算术的行为不同。 将整数添加到 Julia 中的 Ptr 总是将指针移动一定数量的 bytes,而不是元素。 这样,通过指针运算获得的地址值不依赖于指针的元素类型。","category":"page"},{"location":"manual/calling-c-and-fortran-code/#线程安全","page":"调用 C 和 Fortran 代码","title":"线程安全","text":"","category":"section"},{"location":"manual/calling-c-and-fortran-code/","page":"调用 C 和 Fortran 代码","title":"调用 C 和 Fortran 代码","text":"一些 C 库从不同的线程执行它们的回调,并且由于 Julia 不是线程安全的,因此你需要采取一些额外的预防措施。 特别是,你需要设置一个两层系统:C 回调应该只 安排(通过 Julia 的事件循环)执行“真实”回调。 为此,创建一个 AsyncCondition 对象并在其上创建 wait:","category":"page"},{"location":"manual/calling-c-and-fortran-code/","page":"调用 C 和 Fortran 代码","title":"调用 C 和 Fortran 代码","text":"cond = Base.AsyncCondition()\nwait(cond)","category":"page"},{"location":"manual/calling-c-and-fortran-code/","page":"调用 C 和 Fortran 代码","title":"调用 C 和 Fortran 代码","text":"传递给 C 的回调应该只通过 ccall 将 cond.handle 作为参数传递给 :uv_async_send 并调用,注意避免任何内存分配操作或与 Julia 运行时的其他交互。","category":"page"},{"location":"manual/calling-c-and-fortran-code/","page":"调用 C 和 Fortran 代码","title":"调用 C 和 Fortran 代码","text":"注意,事件可能会合并,因此对 uv_async_send 的多个调用可能会导致对该条件的单个唤醒通知。","category":"page"},{"location":"manual/calling-c-and-fortran-code/#关于-Callbacks-的更多内容","page":"调用 C 和 Fortran 代码","title":"关于 Callbacks 的更多内容","text":"","category":"section"},{"location":"manual/calling-c-and-fortran-code/","page":"调用 C 和 Fortran 代码","title":"调用 C 和 Fortran 代码","text":"关于如何传递 callback 到 C 库的更多细节,请参考此博客。","category":"page"},{"location":"manual/calling-c-and-fortran-code/#C","page":"调用 C 和 Fortran 代码","title":"C++","text":"","category":"section"},{"location":"manual/calling-c-and-fortran-code/","page":"调用 C 和 Fortran 代码","title":"调用 C 和 Fortran 代码","text":"如需要直接易用的C++接口,即直接用Julia写封装代码,请参考 Cxx。如需封装C++库的工具,即用C++写封装/胶水代码,请参考CxxWrap。","category":"page"},{"location":"manual/calling-c-and-fortran-code/","page":"调用 C 和 Fortran 代码","title":"调用 C 和 Fortran 代码","text":"[1]: Non-library function calls in both C and Julia can be inlined and thus may have even less overhead than calls to shared library functions. The point above is that the cost of actually doing foreign function call is about the same as doing a call in either native language.","category":"page"},{"location":"manual/calling-c-and-fortran-code/","page":"调用 C 和 Fortran 代码","title":"调用 C 和 Fortran 代码","text":"[2]: The Clang package can be used to auto-generate Julia code from a C header file.","category":"page"},{"location":"base/libc/#C-标准库","page":"C 标准库","title":"C 标准库","text":"","category":"section"},{"location":"base/libc/","page":"C 标准库","title":"C 标准库","text":"Base.Libc.malloc\nBase.Libc.calloc\nBase.Libc.realloc\nBase.Libc.free\nBase.Libc.errno\nBase.Libc.strerror\nBase.Libc.GetLastError\nBase.Libc.FormatMessage\nBase.Libc.time(::Base.Libc.TmStruct)\nBase.Libc.strftime\nBase.Libc.strptime\nBase.Libc.TmStruct\nBase.Libc.flush_cstdio\nBase.Libc.systemsleep","category":"page"},{"location":"base/libc/#Base.Libc.malloc","page":"C 标准库","title":"Base.Libc.malloc","text":"malloc(size::Integer) -> Ptr{Cvoid}\n\nCall malloc from the C standard library.\n\n\n\n\n\n","category":"function"},{"location":"base/libc/#Base.Libc.calloc","page":"C 标准库","title":"Base.Libc.calloc","text":"calloc(num::Integer, size::Integer) -> Ptr{Cvoid}\n\nCall calloc from the C standard library.\n\n\n\n\n\n","category":"function"},{"location":"base/libc/#Base.Libc.realloc","page":"C 标准库","title":"Base.Libc.realloc","text":"realloc(addr::Ptr, size::Integer) -> Ptr{Cvoid}\n\nCall realloc from the C standard library.\n\nSee warning in the documentation for free regarding only using this on memory originally obtained from malloc.\n\n\n\n\n\n","category":"function"},{"location":"base/libc/#Base.Libc.free","page":"C 标准库","title":"Base.Libc.free","text":"free(addr::Ptr)\n\nCall free from the C standard library. Only use this on memory obtained from malloc, not on pointers retrieved from other C libraries. Ptr objects obtained from C libraries should be freed by the free functions defined in that library, to avoid assertion failures if multiple libc libraries exist on the system.\n\n\n\n\n\n","category":"function"},{"location":"base/libc/#Base.Libc.errno","page":"C 标准库","title":"Base.Libc.errno","text":"errno([code])\n\nGet the value of the C library's errno. If an argument is specified, it is used to set the value of errno.\n\nThe value of errno is only valid immediately after a ccall to a C library routine that sets it. Specifically, you cannot call errno at the next prompt in a REPL, because lots of code is executed between prompts.\n\n\n\n\n\n","category":"function"},{"location":"base/libc/#Base.Libc.strerror","page":"C 标准库","title":"Base.Libc.strerror","text":"strerror(n=errno())\n\nConvert a system call error code to a descriptive string\n\n\n\n\n\n","category":"function"},{"location":"base/libc/#Base.Libc.GetLastError","page":"C 标准库","title":"Base.Libc.GetLastError","text":"GetLastError()\n\nCall the Win32 GetLastError function [only available on Windows].\n\n\n\n\n\n","category":"function"},{"location":"base/libc/#Base.Libc.FormatMessage","page":"C 标准库","title":"Base.Libc.FormatMessage","text":"FormatMessage(n=GetLastError())\n\nConvert a Win32 system call error code to a descriptive string [only available on Windows].\n\n\n\n\n\n","category":"function"},{"location":"base/libc/#Base.Libc.time-Tuple{Base.Libc.TmStruct}","page":"C 标准库","title":"Base.Libc.time","text":"time(t::TmStruct)\n\nConverts a TmStruct struct to a number of seconds since the epoch.\n\n\n\n\n\n","category":"method"},{"location":"base/libc/#Base.Libc.strftime","page":"C 标准库","title":"Base.Libc.strftime","text":"strftime([format], time)\n\nConvert time, given as a number of seconds since the epoch or a TmStruct, to a formatted string using the given format. Supported formats are the same as those in the standard C library.\n\n\n\n\n\n","category":"function"},{"location":"base/libc/#Base.Libc.strptime","page":"C 标准库","title":"Base.Libc.strptime","text":"strptime([format], timestr)\n\nParse a formatted time string into a TmStruct giving the seconds, minute, hour, date, etc. Supported formats are the same as those in the standard C library. On some platforms, timezones will not be parsed correctly. If the result of this function will be passed to time to convert it to seconds since the epoch, the isdst field should be filled in manually. Setting it to -1 will tell the C library to use the current system settings to determine the timezone.\n\n\n\n\n\n","category":"function"},{"location":"base/libc/#Base.Libc.TmStruct","page":"C 标准库","title":"Base.Libc.TmStruct","text":"TmStruct([seconds])\n\nConvert a number of seconds since the epoch to broken-down format, with fields sec, min, hour, mday, month, year, wday, yday, and isdst.\n\n\n\n\n\n","category":"type"},{"location":"base/libc/#Base.Libc.flush_cstdio","page":"C 标准库","title":"Base.Libc.flush_cstdio","text":"flush_cstdio()\n\nFlushes the C stdout and stderr streams (which may have been written to by external C code).\n\n\n\n\n\n","category":"function"},{"location":"base/libc/#Base.Libc.systemsleep","page":"C 标准库","title":"Base.Libc.systemsleep","text":"systemsleep(s::Real)\n\nSuspends execution for s seconds. This function does not yield to Julia's scheduler and therefore blocks the Julia thread that it is running on for the duration of the sleep time.\n\nSee also sleep.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LinearAlgebra/#man-linalg","page":"Linear Algebra","title":"Linear Algebra","text":"","category":"section"},{"location":"stdlib/LinearAlgebra/","page":"Linear Algebra","title":"Linear Algebra","text":"DocTestSetup = :(using LinearAlgebra, SparseArrays, SuiteSparse)","category":"page"},{"location":"stdlib/LinearAlgebra/","page":"Linear Algebra","title":"Linear Algebra","text":"除了(且作为一部分)对多维数组的支持,Julia 还提供了许多常见和实用的线性代数运算的本地实现,可通过 using LinearAlgebra 加载。 基本的运算,比如 tr,det 和 inv 都是支持的:","category":"page"},{"location":"stdlib/LinearAlgebra/","page":"Linear Algebra","title":"Linear Algebra","text":"julia> A = [1 2 3; 4 1 6; 7 8 1]\n3×3 Matrix{Int64}:\n 1 2 3\n 4 1 6\n 7 8 1\n\njulia> tr(A)\n3\n\njulia> det(A)\n104.0\n\njulia> inv(A)\n3×3 Matrix{Float64}:\n -0.451923 0.211538 0.0865385\n 0.365385 -0.192308 0.0576923\n 0.240385 0.0576923 -0.0673077","category":"page"},{"location":"stdlib/LinearAlgebra/","page":"Linear Algebra","title":"Linear Algebra","text":"还有其它实用的运算,比如寻找特征值或特征向量:","category":"page"},{"location":"stdlib/LinearAlgebra/","page":"Linear Algebra","title":"Linear Algebra","text":"julia> A = [-4. -17.; 2. 2.]\n2×2 Matrix{Float64}:\n -4.0 -17.0\n 2.0 2.0\n\njulia> eigvals(A)\n2-element Vector{ComplexF64}:\n -1.0 - 5.0im\n -1.0 + 5.0im\n\njulia> eigvecs(A)\n2×2 Matrix{ComplexF64}:\n 0.945905-0.0im 0.945905+0.0im\n -0.166924+0.278207im -0.166924-0.278207im","category":"page"},{"location":"stdlib/LinearAlgebra/","page":"Linear Algebra","title":"Linear Algebra","text":"此外,Julia 提供了多种矩阵分解,通过将矩阵预先分解成更适合问题的形式(出于性能或内存上的原因),它们可用于加快问题的求解,如线性求解或矩阵求幂。更多有关信息请参阅文档 factorize。举个例子:","category":"page"},{"location":"stdlib/LinearAlgebra/","page":"Linear Algebra","title":"Linear Algebra","text":"julia> A = [1.5 2 -4; 3 -1 -6; -10 2.3 4]\n3×3 Matrix{Float64}:\n 1.5 2.0 -4.0\n 3.0 -1.0 -6.0\n -10.0 2.3 4.0\n\njulia> factorize(A)\nLU{Float64, Matrix{Float64}}\nL factor:\n3×3 Matrix{Float64}:\n 1.0 0.0 0.0\n -0.15 1.0 0.0\n -0.3 -0.132196 1.0\nU factor:\n3×3 Matrix{Float64}:\n -10.0 2.3 4.0\n 0.0 2.345 -3.4\n 0.0 0.0 -5.24947","category":"page"},{"location":"stdlib/LinearAlgebra/","page":"Linear Algebra","title":"Linear Algebra","text":"因为 A 不是埃尔米特、对称、三角、三对角或双对角矩阵,LU 分解也许是我们能做的最好分解。与之相比:","category":"page"},{"location":"stdlib/LinearAlgebra/","page":"Linear Algebra","title":"Linear Algebra","text":"julia> B = [1.5 2 -4; 2 -1 -3; -4 -3 5]\n3×3 Matrix{Float64}:\n 1.5 2.0 -4.0\n 2.0 -1.0 -3.0\n -4.0 -3.0 5.0\n\njulia> factorize(B)\nBunchKaufman{Float64, Matrix{Float64}}\nD factor:\n3×3 Tridiagonal{Float64, Vector{Float64}}:\n -1.64286 0.0 ⋅\n 0.0 -2.8 0.0\n ⋅ 0.0 5.0\nU factor:\n3×3 UnitUpperTriangular{Float64, Matrix{Float64}}:\n 1.0 0.142857 -0.8\n ⋅ 1.0 -0.6\n ⋅ ⋅ 1.0\npermutation:\n3-element Vector{Int64}:\n 1\n 2\n 3","category":"page"},{"location":"stdlib/LinearAlgebra/","page":"Linear Algebra","title":"Linear Algebra","text":"在这里,Julia 能够发现 B 确实是对称矩阵,并且使用一种更适当的分解。针对一个具有某些属性的矩阵,比如一个对称或三对角矩阵,往往有可能写出更高效的代码。Julia 提供了一些特殊的类型好让你可以根据矩阵所具有的属性「标记」它们。例如:","category":"page"},{"location":"stdlib/LinearAlgebra/","page":"Linear Algebra","title":"Linear Algebra","text":"julia> B = [1.5 2 -4; 2 -1 -3; -4 -3 5]\n3×3 Matrix{Float64}:\n 1.5 2.0 -4.0\n 2.0 -1.0 -3.0\n -4.0 -3.0 5.0\n\njulia> sB = Symmetric(B)\n3×3 Symmetric{Float64, Matrix{Float64}}:\n 1.5 2.0 -4.0\n 2.0 -1.0 -3.0\n -4.0 -3.0 5.0","category":"page"},{"location":"stdlib/LinearAlgebra/","page":"Linear Algebra","title":"Linear Algebra","text":"sB 已经被标记成(实)对称矩阵,所以对于之后可能在它上面执行的操作,例如特征因子化或矩阵-向量乘积,只引用矩阵的一半可以提高效率。举个例子:","category":"page"},{"location":"stdlib/LinearAlgebra/","page":"Linear Algebra","title":"Linear Algebra","text":"julia> B = [1.5 2 -4; 2 -1 -3; -4 -3 5]\n3×3 Matrix{Float64}:\n 1.5 2.0 -4.0\n 2.0 -1.0 -3.0\n -4.0 -3.0 5.0\n\njulia> sB = Symmetric(B)\n3×3 Symmetric{Float64, Matrix{Float64}}:\n 1.5 2.0 -4.0\n 2.0 -1.0 -3.0\n -4.0 -3.0 5.0\n\njulia> x = [1; 2; 3]\n3-element Vector{Int64}:\n 1\n 2\n 3\n\njulia> sB\\x\n3-element Vector{Float64}:\n -1.7391304347826084\n -1.1086956521739126\n -1.4565217391304346","category":"page"},{"location":"stdlib/LinearAlgebra/","page":"Linear Algebra","title":"Linear Algebra","text":"\\ 运算在这里执行线性求解。左除运算符相当强大,很容易写出紧凑、可读的代码,它足够灵活,可以求解各种线性方程组。","category":"page"},{"location":"stdlib/LinearAlgebra/#特殊矩阵","page":"Linear Algebra","title":"特殊矩阵","text":"","category":"section"},{"location":"stdlib/LinearAlgebra/","page":"Linear Algebra","title":"Linear Algebra","text":"具有特殊对称性和结构的矩阵经常在线性代数中出现并且与各种矩阵分解相关。 Julia 具有丰富的特殊矩阵类型,可以快速计算专门为特定矩阵类型开发的专用例程。","category":"page"},{"location":"stdlib/LinearAlgebra/","page":"Linear Algebra","title":"Linear Algebra","text":"下表总结了在 Julia 中已经实现的特殊矩阵类型,以及为它们提供各种优化方法的钩子在 LAPACK 中是否可用。","category":"page"},{"location":"stdlib/LinearAlgebra/","page":"Linear Algebra","title":"Linear Algebra","text":"类型 描述\nSymmetric Symmetric matrix\nHermitian Hermitian matrix\nUpperTriangular 上三角矩阵\nUnitUpperTriangular 单位上三角矩阵 with unit diagonal\nLowerTriangular 下三角矩阵\nUnitLowerTriangular 单位下三角矩阵\nUpperHessenberg Upper Hessenberg matrix\nTridiagonal Tridiagonal matrix\nSymTridiagonal 对称三对角矩阵\nBidiagonal 上/下双对角矩阵\nDiagonal Diagonal matrix\nUniformScaling Uniform scaling operator","category":"page"},{"location":"stdlib/LinearAlgebra/#基本运算","page":"Linear Algebra","title":"基本运算","text":"","category":"section"},{"location":"stdlib/LinearAlgebra/","page":"Linear Algebra","title":"Linear Algebra","text":"矩阵类型 + - * \\ 具有优化方法的其它函数\nSymmetric MV inv, sqrt, exp\nHermitian MV inv, sqrt, exp\nUpperTriangular MV MV inv, det\nUnitUpperTriangular MV MV inv, det\nLowerTriangular MV MV inv, det\nUnitLowerTriangular MV MV inv, det\nUpperHessenberg MM inv, det\nSymTridiagonal M M MS MV eigmax, eigmin\nTridiagonal M M MS MV \nBidiagonal M M MS MV \nDiagonal M M MV MV inv, det, logdet, /\nUniformScaling M M MVS MVS /","category":"page"},{"location":"stdlib/LinearAlgebra/","page":"Linear Algebra","title":"Linear Algebra","text":"Legend:","category":"page"},{"location":"stdlib/LinearAlgebra/","page":"Linear Algebra","title":"Linear Algebra","text":"Key 说明\nM(矩阵) 针对矩阵与矩阵运算的优化方法可用\nV(向量) 针对矩阵与向量运算的优化方法可用\nS(标量) 针对矩阵与标量运算的优化方法可用","category":"page"},{"location":"stdlib/LinearAlgebra/#矩阵分解","page":"Linear Algebra","title":"矩阵分解","text":"","category":"section"},{"location":"stdlib/LinearAlgebra/","page":"Linear Algebra","title":"Linear Algebra","text":"矩阵类型 LAPACK eigen eigvals eigvecs svd svdvals\nSymmetric SY ARI \nHermitian HE ARI \nUpperTriangular TR A A A \nUnitUpperTriangular TR A A A \nLowerTriangular TR A A A \nUnitLowerTriangular TR A A A \nSymTridiagonal ST A ARI AV \nTridiagonal GT \nBidiagonal BD A A\nDiagonal DI A ","category":"page"},{"location":"stdlib/LinearAlgebra/","page":"Linear Algebra","title":"Linear Algebra","text":"图例:","category":"page"},{"location":"stdlib/LinearAlgebra/","page":"Linear Algebra","title":"Linear Algebra","text":"键名 说明 例子\nA (all) 找到所有特征值和/或特征向量的优化方法可用 e.g. eigvals(M)\nR (range) 通过第 ih 个特征值寻找第 il 个特征值的优化方法可用 eigvals(M, il, ih)\nI (interval) 寻找在区间 [vl, vh] 内的特征值的优化方法可用 eigvals(M, vl, vh)\nV (vectors) 寻找对应于特征值 x=[x1, x2,...] 的特征向量的优化方法可用 eigvecs(M, x)","category":"page"},{"location":"stdlib/LinearAlgebra/#均匀缩放运算符","page":"Linear Algebra","title":"均匀缩放运算符","text":"","category":"section"},{"location":"stdlib/LinearAlgebra/","page":"Linear Algebra","title":"Linear Algebra","text":"UniformScaling 运算符代表一个标量乘以单位运算符,λ*I。 单位运算符 I 被定义为常量,是 UniformScaling 的实例。 这些运算符的大小是通用的,并且会在二元运算符 +,-,* 和 \\ 中与另一个矩阵相匹配。 对于 A+I 和 A-I ,这意味着 A 必须是个方阵。 与单位运算符 I 相乘是一个空操作(除了检查比例因子是一),因此几乎没有开销。","category":"page"},{"location":"stdlib/LinearAlgebra/","page":"Linear Algebra","title":"Linear Algebra","text":"来查看 UniformScaling 运算符的运行结果:","category":"page"},{"location":"stdlib/LinearAlgebra/","page":"Linear Algebra","title":"Linear Algebra","text":"julia> U = UniformScaling(2);\n\njulia> a = [1 2; 3 4]\n2×2 Matrix{Int64}:\n 1 2\n 3 4\n\njulia> a + U\n2×2 Matrix{Int64}:\n 3 2\n 3 6\n\njulia> a * U\n2×2 Matrix{Int64}:\n 2 4\n 6 8\n\njulia> [a U]\n2×4 Matrix{Int64}:\n 1 2 2 0\n 3 4 0 2\n\njulia> b = [1 2 3; 4 5 6]\n2×3 Matrix{Int64}:\n 1 2 3\n 4 5 6\n\njulia> b - U\nERROR: DimensionMismatch(\"matrix is not square: dimensions are (2, 3)\")\nStacktrace:\n[...]","category":"page"},{"location":"stdlib/LinearAlgebra/","page":"Linear Algebra","title":"Linear Algebra","text":"If you need to solve many systems of the form (A+μI)x = b for the same A and different μ, it might be beneficial to first compute the Hessenberg factorization F of A via the hessenberg function. Given F, Julia employs an efficient algorithm for (F+μ*I) \\ b (equivalent to (A+μ*I)x \\ b) and related operations like determinants.","category":"page"},{"location":"stdlib/LinearAlgebra/#man-linalg-factorizations","page":"Linear Algebra","title":"Matrix factorizations","text":"","category":"section"},{"location":"stdlib/LinearAlgebra/","page":"Linear Algebra","title":"Linear Algebra","text":"Matrix factorizations (a.k.a. matrix decompositions) compute the factorization of a matrix into a product of matrices, and are one of the central concepts in linear algebra.","category":"page"},{"location":"stdlib/LinearAlgebra/","page":"Linear Algebra","title":"Linear Algebra","text":"The following table summarizes the types of matrix factorizations that have been implemented in Julia. Details of their associated methods can be found in the Standard functions section of the Linear Algebra documentation.","category":"page"},{"location":"stdlib/LinearAlgebra/","page":"Linear Algebra","title":"Linear Algebra","text":"Type Description\nBunchKaufman Bunch-Kaufman factorization\nCholesky Cholesky factorization\nCholeskyPivoted Pivoted Cholesky factorization\nLDLt LDL(T) factorization\nLU LU factorization\nQR QR factorization\nQRCompactWY Compact WY form of the QR factorization\nQRPivoted Pivoted QR factorization\nLQ QR factorization of transpose(A)\nHessenberg Hessenberg decomposition\nEigen Spectral decomposition\nGeneralizedEigen Generalized spectral decomposition\nSVD Singular value decomposition\nGeneralizedSVD Generalized SVD\nSchur Schur decomposition\nGeneralizedSchur Generalized Schur decomposition","category":"page"},{"location":"stdlib/LinearAlgebra/#Standard-functions","page":"Linear Algebra","title":"Standard functions","text":"","category":"section"},{"location":"stdlib/LinearAlgebra/","page":"Linear Algebra","title":"Linear Algebra","text":"Linear algebra functions in Julia are largely implemented by calling functions from LAPACK. Sparse matrix factorizations call functions from SuiteSparse. Other sparse solvers are available as Julia packages.","category":"page"},{"location":"stdlib/LinearAlgebra/","page":"Linear Algebra","title":"Linear Algebra","text":"Base.:*(::AbstractMatrix, ::AbstractMatrix)\nBase.:\\(::AbstractMatrix, ::AbstractVecOrMat)\nLinearAlgebra.SingularException\nLinearAlgebra.PosDefException\nLinearAlgebra.ZeroPivotException\nLinearAlgebra.dot\nLinearAlgebra.dot(::Any, ::Any, ::Any)\nLinearAlgebra.cross\nLinearAlgebra.factorize\nLinearAlgebra.Diagonal\nLinearAlgebra.Bidiagonal\nLinearAlgebra.SymTridiagonal\nLinearAlgebra.Tridiagonal\nLinearAlgebra.Symmetric\nLinearAlgebra.Hermitian\nLinearAlgebra.LowerTriangular\nLinearAlgebra.UpperTriangular\nLinearAlgebra.UnitLowerTriangular\nLinearAlgebra.UnitUpperTriangular\nLinearAlgebra.UpperHessenberg\nLinearAlgebra.UniformScaling\nLinearAlgebra.I\nLinearAlgebra.UniformScaling(::Integer)\nLinearAlgebra.Factorization\nLinearAlgebra.LU\nLinearAlgebra.lu\nLinearAlgebra.lu!\nLinearAlgebra.Cholesky\nLinearAlgebra.CholeskyPivoted\nLinearAlgebra.cholesky\nLinearAlgebra.cholesky!\nLinearAlgebra.lowrankupdate\nLinearAlgebra.lowrankdowndate\nLinearAlgebra.lowrankupdate!\nLinearAlgebra.lowrankdowndate!\nLinearAlgebra.LDLt\nLinearAlgebra.ldlt\nLinearAlgebra.ldlt!\nLinearAlgebra.QR\nLinearAlgebra.QRCompactWY\nLinearAlgebra.QRPivoted\nLinearAlgebra.qr\nLinearAlgebra.qr!\nLinearAlgebra.LQ\nLinearAlgebra.lq\nLinearAlgebra.lq!\nLinearAlgebra.BunchKaufman\nLinearAlgebra.bunchkaufman\nLinearAlgebra.bunchkaufman!\nLinearAlgebra.Eigen\nLinearAlgebra.GeneralizedEigen\nLinearAlgebra.eigvals\nLinearAlgebra.eigvals!\nLinearAlgebra.eigmax\nLinearAlgebra.eigmin\nLinearAlgebra.eigvecs\nLinearAlgebra.eigen\nLinearAlgebra.eigen!\nLinearAlgebra.Hessenberg\nLinearAlgebra.hessenberg\nLinearAlgebra.hessenberg!\nLinearAlgebra.Schur\nLinearAlgebra.GeneralizedSchur\nLinearAlgebra.schur\nLinearAlgebra.schur!\nLinearAlgebra.ordschur\nLinearAlgebra.ordschur!\nLinearAlgebra.SVD\nLinearAlgebra.GeneralizedSVD\nLinearAlgebra.svd\nLinearAlgebra.svd!\nLinearAlgebra.svdvals\nLinearAlgebra.svdvals!\nLinearAlgebra.Givens\nLinearAlgebra.givens\nLinearAlgebra.triu\nLinearAlgebra.triu!\nLinearAlgebra.tril\nLinearAlgebra.tril!\nLinearAlgebra.diagind\nLinearAlgebra.diag\nLinearAlgebra.diagm\nLinearAlgebra.rank\nLinearAlgebra.norm\nLinearAlgebra.opnorm\nLinearAlgebra.normalize!\nLinearAlgebra.normalize\nLinearAlgebra.cond\nLinearAlgebra.condskeel\nLinearAlgebra.tr\nLinearAlgebra.det\nLinearAlgebra.logdet\nLinearAlgebra.logabsdet\nBase.inv(::AbstractMatrix)\nLinearAlgebra.pinv\nLinearAlgebra.nullspace\nBase.kron\nBase.kron!\nLinearAlgebra.exp(::StridedMatrix{<:LinearAlgebra.BlasFloat})\nBase.cis(::AbstractMatrix)\nBase.:^(::AbstractMatrix, ::Number)\nBase.:^(::Number, ::AbstractMatrix)\nLinearAlgebra.log(::StridedMatrix)\nLinearAlgebra.sqrt(::StridedMatrix{<:Real})\nLinearAlgebra.cos(::StridedMatrix{<:Real})\nLinearAlgebra.sin(::StridedMatrix{<:Real})\nLinearAlgebra.sincos(::StridedMatrix{<:Real})\nLinearAlgebra.tan(::StridedMatrix{<:Real})\nLinearAlgebra.sec(::StridedMatrix)\nLinearAlgebra.csc(::StridedMatrix)\nLinearAlgebra.cot(::StridedMatrix)\nLinearAlgebra.cosh(::StridedMatrix)\nLinearAlgebra.sinh(::StridedMatrix)\nLinearAlgebra.tanh(::StridedMatrix)\nLinearAlgebra.sech(::StridedMatrix)\nLinearAlgebra.csch(::StridedMatrix)\nLinearAlgebra.coth(::StridedMatrix)\nLinearAlgebra.acos(::StridedMatrix)\nLinearAlgebra.asin(::StridedMatrix)\nLinearAlgebra.atan(::StridedMatrix)\nLinearAlgebra.asec(::StridedMatrix)\nLinearAlgebra.acsc(::StridedMatrix)\nLinearAlgebra.acot(::StridedMatrix)\nLinearAlgebra.acosh(::StridedMatrix)\nLinearAlgebra.asinh(::StridedMatrix)\nLinearAlgebra.atanh(::StridedMatrix)\nLinearAlgebra.asech(::StridedMatrix)\nLinearAlgebra.acsch(::StridedMatrix)\nLinearAlgebra.acoth(::StridedMatrix)\nLinearAlgebra.lyap\nLinearAlgebra.sylvester\nLinearAlgebra.issuccess\nLinearAlgebra.issymmetric\nLinearAlgebra.isposdef\nLinearAlgebra.isposdef!\nLinearAlgebra.istril\nLinearAlgebra.istriu\nLinearAlgebra.isdiag\nLinearAlgebra.ishermitian\nBase.transpose\nLinearAlgebra.transpose!\nLinearAlgebra.Transpose\nBase.adjoint\nLinearAlgebra.adjoint!\nLinearAlgebra.Adjoint\nBase.copy(::Union{Transpose,Adjoint})\nLinearAlgebra.stride1\nLinearAlgebra.checksquare\nLinearAlgebra.peakflops","category":"page"},{"location":"stdlib/LinearAlgebra/#Base.:*-Tuple{AbstractMatrix, AbstractMatrix}","page":"Linear Algebra","title":"Base.:*","text":"*(A::AbstractMatrix, B::AbstractMatrix)\n\nMatrix multiplication.\n\nExamples\n\njulia> [1 1; 0 1] * [1 0; 1 1]\n2×2 Matrix{Int64}:\n 2 1\n 1 1\n\n\n\n\n\n","category":"method"},{"location":"stdlib/LinearAlgebra/#Base.:\\-Tuple{AbstractMatrix, AbstractVecOrMat}","page":"Linear Algebra","title":"Base.:\\","text":"\\(A, B)\n\nMatrix division using a polyalgorithm. For input matrices A and B, the result X is such that A*X == B when A is square. The solver that is used depends upon the structure of A. If A is upper or lower triangular (or diagonal), no factorization of A is required and the system is solved with either forward or backward substitution. For non-triangular square matrices, an LU factorization is used.\n\nFor rectangular A the result is the minimum-norm least squares solution computed by a pivoted QR factorization of A and a rank estimate of A based on the R factor.\n\nWhen A is sparse, a similar polyalgorithm is used. For indefinite matrices, the LDLt factorization does not use pivoting during the numerical factorization and therefore the procedure can fail even for invertible matrices.\n\nSee also: factorize, pinv.\n\nExamples\n\njulia> A = [1 0; 1 -2]; B = [32; -4];\n\njulia> X = A \\ B\n2-element Vector{Float64}:\n 32.0\n 18.0\n\njulia> A * X == B\ntrue\n\n\n\n\n\n","category":"method"},{"location":"stdlib/LinearAlgebra/#LinearAlgebra.SingularException","page":"Linear Algebra","title":"LinearAlgebra.SingularException","text":"SingularException\n\nException thrown when the input matrix has one or more zero-valued eigenvalues, and is not invertible. A linear solve involving such a matrix cannot be computed. The info field indicates the location of (one of) the singular value(s).\n\n\n\n\n\n","category":"type"},{"location":"stdlib/LinearAlgebra/#LinearAlgebra.PosDefException","page":"Linear Algebra","title":"LinearAlgebra.PosDefException","text":"PosDefException\n\nException thrown when the input matrix was not positive definite. Some linear algebra functions and factorizations are only applicable to positive definite matrices. The info field indicates the location of (one of) the eigenvalue(s) which is (are) less than/equal to 0.\n\n\n\n\n\n","category":"type"},{"location":"stdlib/LinearAlgebra/#LinearAlgebra.ZeroPivotException","page":"Linear Algebra","title":"LinearAlgebra.ZeroPivotException","text":"ZeroPivotException <: Exception\n\nException thrown when a matrix factorization/solve encounters a zero in a pivot (diagonal) position and cannot proceed. This may not mean that the matrix is singular: it may be fruitful to switch to a diffent factorization such as pivoted LU that can re-order variables to eliminate spurious zero pivots. The info field indicates the location of (one of) the zero pivot(s).\n\n\n\n\n\n","category":"type"},{"location":"stdlib/LinearAlgebra/#LinearAlgebra.dot","page":"Linear Algebra","title":"LinearAlgebra.dot","text":"dot(x, y)\nx ⋅ y\n\nCompute the dot product between two vectors. For complex vectors, the first vector is conjugated.\n\ndot also works on arbitrary iterable objects, including arrays of any dimension, as long as dot is defined on the elements.\n\ndot is semantically equivalent to sum(dot(vx,vy) for (vx,vy) in zip(x, y)), with the added restriction that the arguments must have equal lengths.\n\nx ⋅ y (where ⋅ can be typed by tab-completing \\cdot in the REPL) is a synonym for dot(x, y).\n\nExamples\n\njulia> dot([1; 1], [2; 3])\n5\n\njulia> dot([im; im], [1; 1])\n0 - 2im\n\njulia> dot(1:5, 2:6)\n70\n\njulia> x = fill(2., (5,5));\n\njulia> y = fill(3., (5,5));\n\njulia> dot(x, y)\n150.0\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LinearAlgebra/#LinearAlgebra.dot-Tuple{Any, Any, Any}","page":"Linear Algebra","title":"LinearAlgebra.dot","text":"dot(x, A, y)\n\nCompute the generalized dot product dot(x, A*y) between two vectors x and y, without storing the intermediate result of A*y. As for the two-argument dot(_,_), this acts recursively. Moreover, for complex vectors, the first vector is conjugated.\n\ncompat: Julia 1.4\nThree-argument dot requires at least Julia 1.4.\n\nExamples\n\njulia> dot([1; 1], [1 2; 3 4], [2; 3])\n26\n\njulia> dot(1:5, reshape(1:25, 5, 5), 2:6)\n4850\n\njulia> ⋅(1:5, reshape(1:25, 5, 5), 2:6) == dot(1:5, reshape(1:25, 5, 5), 2:6)\ntrue\n\n\n\n\n\n","category":"method"},{"location":"stdlib/LinearAlgebra/#LinearAlgebra.cross","page":"Linear Algebra","title":"LinearAlgebra.cross","text":"cross(x, y)\n×(x,y)\n\nCompute the cross product of two 3-vectors.\n\nExamples\n\njulia> a = [0;1;0]\n3-element Vector{Int64}:\n 0\n 1\n 0\n\njulia> b = [0;0;1]\n3-element Vector{Int64}:\n 0\n 0\n 1\n\njulia> cross(a,b)\n3-element Vector{Int64}:\n 1\n 0\n 0\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LinearAlgebra/#LinearAlgebra.factorize","page":"Linear Algebra","title":"LinearAlgebra.factorize","text":"factorize(A)\n\nCompute a convenient factorization of A, based upon the type of the input matrix. factorize checks A to see if it is symmetric/triangular/etc. if A is passed as a generic matrix. factorize checks every element of A to verify/rule out each property. It will short-circuit as soon as it can rule out symmetry/triangular structure. The return value can be reused for efficient solving of multiple systems. For example: A=factorize(A); x=A\\b; y=A\\C.\n\nProperties of A type of factorization\nPositive-definite Cholesky (see cholesky)\nDense Symmetric/Hermitian Bunch-Kaufman (see bunchkaufman)\nSparse Symmetric/Hermitian LDLt (see ldlt)\nTriangular Triangular\nDiagonal Diagonal\nBidiagonal Bidiagonal\nTridiagonal LU (see lu)\nSymmetric real tridiagonal LDLt (see ldlt)\nGeneral square LU (see lu)\nGeneral non-square QR (see qr)\n\nIf factorize is called on a Hermitian positive-definite matrix, for instance, then factorize will return a Cholesky factorization.\n\nExamples\n\njulia> A = Array(Bidiagonal(fill(1.0, (5, 5)), :U))\n5×5 Matrix{Float64}:\n 1.0 1.0 0.0 0.0 0.0\n 0.0 1.0 1.0 0.0 0.0\n 0.0 0.0 1.0 1.0 0.0\n 0.0 0.0 0.0 1.0 1.0\n 0.0 0.0 0.0 0.0 1.0\n\njulia> factorize(A) # factorize will check to see that A is already factorized\n5×5 Bidiagonal{Float64, Vector{Float64}}:\n 1.0 1.0 ⋅ ⋅ ⋅\n ⋅ 1.0 1.0 ⋅ ⋅\n ⋅ ⋅ 1.0 1.0 ⋅\n ⋅ ⋅ ⋅ 1.0 1.0\n ⋅ ⋅ ⋅ ⋅ 1.0\n\nThis returns a 5×5 Bidiagonal{Float64}, which can now be passed to other linear algebra functions (e.g. eigensolvers) which will use specialized methods for Bidiagonal types.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LinearAlgebra/#LinearAlgebra.Diagonal","page":"Linear Algebra","title":"LinearAlgebra.Diagonal","text":"Diagonal(V::AbstractVector)\n\nConstruct a matrix with V as its diagonal.\n\nSee also diag, diagm.\n\nExamples\n\njulia> Diagonal([1, 10, 100])\n3×3 Diagonal{Int64, Vector{Int64}}:\n 1 ⋅ ⋅\n ⋅ 10 ⋅\n ⋅ ⋅ 100\n\njulia> diagm([7, 13])\n2×2 Matrix{Int64}:\n 7 0\n 0 13\n\n\n\n\n\nDiagonal(A::AbstractMatrix)\n\nConstruct a matrix from the diagonal of A.\n\nExamples\n\njulia> A = permutedims(reshape(1:15, 5, 3))\n3×5 Matrix{Int64}:\n 1 2 3 4 5\n 6 7 8 9 10\n 11 12 13 14 15\n\njulia> Diagonal(A)\n3×3 Diagonal{Int64, Vector{Int64}}:\n 1 ⋅ ⋅\n ⋅ 7 ⋅\n ⋅ ⋅ 13\n\njulia> diag(A, 2)\n3-element Vector{Int64}:\n 3\n 9\n 15\n\n\n\n\n\nDiagonal{T}(undef, n)\n\nConstruct an uninitialized Diagonal{T} of length n. See undef.\n\n\n\n\n\n","category":"type"},{"location":"stdlib/LinearAlgebra/#LinearAlgebra.Bidiagonal","page":"Linear Algebra","title":"LinearAlgebra.Bidiagonal","text":"Bidiagonal(dv::V, ev::V, uplo::Symbol) where V <: AbstractVector\n\nConstructs an upper (uplo=:U) or lower (uplo=:L) bidiagonal matrix using the given diagonal (dv) and off-diagonal (ev) vectors. The result is of type Bidiagonal and provides efficient specialized linear solvers, but may be converted into a regular matrix with convert(Array, _) (or Array(_) for short). The length of ev must be one less than the length of dv.\n\nExamples\n\njulia> dv = [1, 2, 3, 4]\n4-element Vector{Int64}:\n 1\n 2\n 3\n 4\n\njulia> ev = [7, 8, 9]\n3-element Vector{Int64}:\n 7\n 8\n 9\n\njulia> Bu = Bidiagonal(dv, ev, :U) # ev is on the first superdiagonal\n4×4 Bidiagonal{Int64, Vector{Int64}}:\n 1 7 ⋅ ⋅\n ⋅ 2 8 ⋅\n ⋅ ⋅ 3 9\n ⋅ ⋅ ⋅ 4\n\njulia> Bl = Bidiagonal(dv, ev, :L) # ev is on the first subdiagonal\n4×4 Bidiagonal{Int64, Vector{Int64}}:\n 1 ⋅ ⋅ ⋅\n 7 2 ⋅ ⋅\n ⋅ 8 3 ⋅\n ⋅ ⋅ 9 4\n\n\n\n\n\nBidiagonal(A, uplo::Symbol)\n\nConstruct a Bidiagonal matrix from the main diagonal of A and its first super- (if uplo=:U) or sub-diagonal (if uplo=:L).\n\nExamples\n\njulia> A = [1 1 1 1; 2 2 2 2; 3 3 3 3; 4 4 4 4]\n4×4 Matrix{Int64}:\n 1 1 1 1\n 2 2 2 2\n 3 3 3 3\n 4 4 4 4\n\njulia> Bidiagonal(A, :U) # contains the main diagonal and first superdiagonal of A\n4×4 Bidiagonal{Int64, Vector{Int64}}:\n 1 1 ⋅ ⋅\n ⋅ 2 2 ⋅\n ⋅ ⋅ 3 3\n ⋅ ⋅ ⋅ 4\n\njulia> Bidiagonal(A, :L) # contains the main diagonal and first subdiagonal of A\n4×4 Bidiagonal{Int64, Vector{Int64}}:\n 1 ⋅ ⋅ ⋅\n 2 2 ⋅ ⋅\n ⋅ 3 3 ⋅\n ⋅ ⋅ 4 4\n\n\n\n\n\n","category":"type"},{"location":"stdlib/LinearAlgebra/#LinearAlgebra.SymTridiagonal","page":"Linear Algebra","title":"LinearAlgebra.SymTridiagonal","text":"SymTridiagonal(dv::V, ev::V) where V <: AbstractVector\n\nConstruct a symmetric tridiagonal matrix from the diagonal (dv) and first sub/super-diagonal (ev), respectively. The result is of type SymTridiagonal and provides efficient specialized eigensolvers, but may be converted into a regular matrix with convert(Array, _) (or Array(_) for short).\n\nFor SymTridiagonal block matrices, the elements of dv are symmetrized. The argument ev is interpreted as the superdiagonal. Blocks from the subdiagonal are (materialized) transpose of the corresponding superdiagonal blocks.\n\nExamples\n\njulia> dv = [1, 2, 3, 4]\n4-element Vector{Int64}:\n 1\n 2\n 3\n 4\n\njulia> ev = [7, 8, 9]\n3-element Vector{Int64}:\n 7\n 8\n 9\n\njulia> SymTridiagonal(dv, ev)\n4×4 SymTridiagonal{Int64, Vector{Int64}}:\n 1 7 ⋅ ⋅\n 7 2 8 ⋅\n ⋅ 8 3 9\n ⋅ ⋅ 9 4\n\njulia> A = SymTridiagonal(fill([1 2; 3 4], 3), fill([1 2; 3 4], 2));\n\njulia> A[1,1]\n2×2 Symmetric{Int64, Matrix{Int64}}:\n 1 2\n 2 4\n\njulia> A[1,2]\n2×2 Matrix{Int64}:\n 1 2\n 3 4\n\njulia> A[2,1]\n2×2 Matrix{Int64}:\n 1 3\n 2 4\n\n\n\n\n\nSymTridiagonal(A::AbstractMatrix)\n\nConstruct a symmetric tridiagonal matrix from the diagonal and first superdiagonal of the symmetric matrix A.\n\nExamples\n\njulia> A = [1 2 3; 2 4 5; 3 5 6]\n3×3 Matrix{Int64}:\n 1 2 3\n 2 4 5\n 3 5 6\n\njulia> SymTridiagonal(A)\n3×3 SymTridiagonal{Int64, Vector{Int64}}:\n 1 2 ⋅\n 2 4 5\n ⋅ 5 6\n\njulia> B = reshape([[1 2; 2 3], [1 2; 3 4], [1 3; 2 4], [1 2; 2 3]], 2, 2);\n\njulia> SymTridiagonal(B)\n2×2 SymTridiagonal{Matrix{Int64}, Vector{Matrix{Int64}}}:\n [1 2; 2 3] [1 3; 2 4]\n [1 2; 3 4] [1 2; 2 3]\n\n\n\n\n\n","category":"type"},{"location":"stdlib/LinearAlgebra/#LinearAlgebra.Tridiagonal","page":"Linear Algebra","title":"LinearAlgebra.Tridiagonal","text":"Tridiagonal(dl::V, d::V, du::V) where V <: AbstractVector\n\nConstruct a tridiagonal matrix from the first subdiagonal, diagonal, and first superdiagonal, respectively. The result is of type Tridiagonal and provides efficient specialized linear solvers, but may be converted into a regular matrix with convert(Array, _) (or Array(_) for short). The lengths of dl and du must be one less than the length of d.\n\nExamples\n\njulia> dl = [1, 2, 3];\n\njulia> du = [4, 5, 6];\n\njulia> d = [7, 8, 9, 0];\n\njulia> Tridiagonal(dl, d, du)\n4×4 Tridiagonal{Int64, Vector{Int64}}:\n 7 4 ⋅ ⋅\n 1 8 5 ⋅\n ⋅ 2 9 6\n ⋅ ⋅ 3 0\n\n\n\n\n\nTridiagonal(A)\n\nConstruct a tridiagonal matrix from the first sub-diagonal, diagonal and first super-diagonal of the matrix A.\n\nExamples\n\njulia> A = [1 2 3 4; 1 2 3 4; 1 2 3 4; 1 2 3 4]\n4×4 Matrix{Int64}:\n 1 2 3 4\n 1 2 3 4\n 1 2 3 4\n 1 2 3 4\n\njulia> Tridiagonal(A)\n4×4 Tridiagonal{Int64, Vector{Int64}}:\n 1 2 ⋅ ⋅\n 1 2 3 ⋅\n ⋅ 2 3 4\n ⋅ ⋅ 3 4\n\n\n\n\n\n","category":"type"},{"location":"stdlib/LinearAlgebra/#LinearAlgebra.Symmetric","page":"Linear Algebra","title":"LinearAlgebra.Symmetric","text":"Symmetric(A, uplo=:U)\n\nConstruct a Symmetric view of the upper (if uplo = :U) or lower (if uplo = :L) triangle of the matrix A.\n\nExamples\n\njulia> A = [1 0 2 0 3; 0 4 0 5 0; 6 0 7 0 8; 0 9 0 1 0; 2 0 3 0 4]\n5×5 Matrix{Int64}:\n 1 0 2 0 3\n 0 4 0 5 0\n 6 0 7 0 8\n 0 9 0 1 0\n 2 0 3 0 4\n\njulia> Supper = Symmetric(A)\n5×5 Symmetric{Int64, Matrix{Int64}}:\n 1 0 2 0 3\n 0 4 0 5 0\n 2 0 7 0 8\n 0 5 0 1 0\n 3 0 8 0 4\n\njulia> Slower = Symmetric(A, :L)\n5×5 Symmetric{Int64, Matrix{Int64}}:\n 1 0 6 0 2\n 0 4 0 9 0\n 6 0 7 0 3\n 0 9 0 1 0\n 2 0 3 0 4\n\nNote that Supper will not be equal to Slower unless A is itself symmetric (e.g. if A == transpose(A)).\n\n\n\n\n\n","category":"type"},{"location":"stdlib/LinearAlgebra/#LinearAlgebra.Hermitian","page":"Linear Algebra","title":"LinearAlgebra.Hermitian","text":"Hermitian(A, uplo=:U)\n\nConstruct a Hermitian view of the upper (if uplo = :U) or lower (if uplo = :L) triangle of the matrix A.\n\nExamples\n\njulia> A = [1 0 2+2im 0 3-3im; 0 4 0 5 0; 6-6im 0 7 0 8+8im; 0 9 0 1 0; 2+2im 0 3-3im 0 4];\n\njulia> Hupper = Hermitian(A)\n5×5 Hermitian{Complex{Int64}, Matrix{Complex{Int64}}}:\n 1+0im 0+0im 2+2im 0+0im 3-3im\n 0+0im 4+0im 0+0im 5+0im 0+0im\n 2-2im 0+0im 7+0im 0+0im 8+8im\n 0+0im 5+0im 0+0im 1+0im 0+0im\n 3+3im 0+0im 8-8im 0+0im 4+0im\n\njulia> Hlower = Hermitian(A, :L)\n5×5 Hermitian{Complex{Int64}, Matrix{Complex{Int64}}}:\n 1+0im 0+0im 6+6im 0+0im 2-2im\n 0+0im 4+0im 0+0im 9+0im 0+0im\n 6-6im 0+0im 7+0im 0+0im 3+3im\n 0+0im 9+0im 0+0im 1+0im 0+0im\n 2+2im 0+0im 3-3im 0+0im 4+0im\n\nNote that Hupper will not be equal to Hlower unless A is itself Hermitian (e.g. if A == adjoint(A)).\n\nAll non-real parts of the diagonal will be ignored.\n\nHermitian(fill(complex(1,1), 1, 1)) == fill(1, 1, 1)\n\n\n\n\n\n","category":"type"},{"location":"stdlib/LinearAlgebra/#LinearAlgebra.LowerTriangular","page":"Linear Algebra","title":"LinearAlgebra.LowerTriangular","text":"LowerTriangular(A::AbstractMatrix)\n\nConstruct a LowerTriangular view of the matrix A.\n\nExamples\n\njulia> A = [1.0 2.0 3.0; 4.0 5.0 6.0; 7.0 8.0 9.0]\n3×3 Matrix{Float64}:\n 1.0 2.0 3.0\n 4.0 5.0 6.0\n 7.0 8.0 9.0\n\njulia> LowerTriangular(A)\n3×3 LowerTriangular{Float64, Matrix{Float64}}:\n 1.0 ⋅ ⋅\n 4.0 5.0 ⋅\n 7.0 8.0 9.0\n\n\n\n\n\n","category":"type"},{"location":"stdlib/LinearAlgebra/#LinearAlgebra.UpperTriangular","page":"Linear Algebra","title":"LinearAlgebra.UpperTriangular","text":"UpperTriangular(A::AbstractMatrix)\n\nConstruct an UpperTriangular view of the matrix A.\n\nExamples\n\njulia> A = [1.0 2.0 3.0; 4.0 5.0 6.0; 7.0 8.0 9.0]\n3×3 Matrix{Float64}:\n 1.0 2.0 3.0\n 4.0 5.0 6.0\n 7.0 8.0 9.0\n\njulia> UpperTriangular(A)\n3×3 UpperTriangular{Float64, Matrix{Float64}}:\n 1.0 2.0 3.0\n ⋅ 5.0 6.0\n ⋅ ⋅ 9.0\n\n\n\n\n\n","category":"type"},{"location":"stdlib/LinearAlgebra/#LinearAlgebra.UnitLowerTriangular","page":"Linear Algebra","title":"LinearAlgebra.UnitLowerTriangular","text":"UnitLowerTriangular(A::AbstractMatrix)\n\nConstruct a UnitLowerTriangular view of the matrix A. Such a view has the oneunit of the eltype of A on its diagonal.\n\nExamples\n\njulia> A = [1.0 2.0 3.0; 4.0 5.0 6.0; 7.0 8.0 9.0]\n3×3 Matrix{Float64}:\n 1.0 2.0 3.0\n 4.0 5.0 6.0\n 7.0 8.0 9.0\n\njulia> UnitLowerTriangular(A)\n3×3 UnitLowerTriangular{Float64, Matrix{Float64}}:\n 1.0 ⋅ ⋅\n 4.0 1.0 ⋅\n 7.0 8.0 1.0\n\n\n\n\n\n","category":"type"},{"location":"stdlib/LinearAlgebra/#LinearAlgebra.UnitUpperTriangular","page":"Linear Algebra","title":"LinearAlgebra.UnitUpperTriangular","text":"UnitUpperTriangular(A::AbstractMatrix)\n\nConstruct an UnitUpperTriangular view of the matrix A. Such a view has the oneunit of the eltype of A on its diagonal.\n\nExamples\n\njulia> A = [1.0 2.0 3.0; 4.0 5.0 6.0; 7.0 8.0 9.0]\n3×3 Matrix{Float64}:\n 1.0 2.0 3.0\n 4.0 5.0 6.0\n 7.0 8.0 9.0\n\njulia> UnitUpperTriangular(A)\n3×3 UnitUpperTriangular{Float64, Matrix{Float64}}:\n 1.0 2.0 3.0\n ⋅ 1.0 6.0\n ⋅ ⋅ 1.0\n\n\n\n\n\n","category":"type"},{"location":"stdlib/LinearAlgebra/#LinearAlgebra.UpperHessenberg","page":"Linear Algebra","title":"LinearAlgebra.UpperHessenberg","text":"UpperHessenberg(A::AbstractMatrix)\n\nConstruct an UpperHessenberg view of the matrix A. Entries of A below the first subdiagonal are ignored.\n\nEfficient algorithms are implemented for H \\ b, det(H), and similar.\n\nSee also the hessenberg function to factor any matrix into a similar upper-Hessenberg matrix.\n\nIf F::Hessenberg is the factorization object, the unitary matrix can be accessed with F.Q and the Hessenberg matrix with F.H. When Q is extracted, the resulting type is the HessenbergQ object, and may be converted to a regular matrix with convert(Array, _) (or Array(_) for short).\n\nIterating the decomposition produces the factors F.Q and F.H.\n\nExamples\n\njulia> A = [1 2 3 4; 5 6 7 8; 9 10 11 12; 13 14 15 16]\n4×4 Matrix{Int64}:\n 1 2 3 4\n 5 6 7 8\n 9 10 11 12\n 13 14 15 16\n\njulia> UpperHessenberg(A)\n4×4 UpperHessenberg{Int64, Matrix{Int64}}:\n 1 2 3 4\n 5 6 7 8\n ⋅ 10 11 12\n ⋅ ⋅ 15 16\n\n\n\n\n\n","category":"type"},{"location":"stdlib/LinearAlgebra/#LinearAlgebra.UniformScaling","page":"Linear Algebra","title":"LinearAlgebra.UniformScaling","text":"UniformScaling{T<:Number}\n\nGenerically sized uniform scaling operator defined as a scalar times the identity operator, λ*I. Although without an explicit size, it acts similarly to a matrix in many cases and includes support for some indexing. See also I.\n\ncompat: Julia 1.6\nIndexing using ranges is available as of Julia 1.6.\n\nExamples\n\njulia> J = UniformScaling(2.)\nUniformScaling{Float64}\n2.0*I\n\njulia> A = [1. 2.; 3. 4.]\n2×2 Matrix{Float64}:\n 1.0 2.0\n 3.0 4.0\n\njulia> J*A\n2×2 Matrix{Float64}:\n 2.0 4.0\n 6.0 8.0\n\njulia> J[1:2, 1:2]\n2×2 Matrix{Float64}:\n 2.0 0.0\n 0.0 2.0\n\n\n\n\n\n","category":"type"},{"location":"stdlib/LinearAlgebra/#LinearAlgebra.I","page":"Linear Algebra","title":"LinearAlgebra.I","text":"I\n\nAn object of type UniformScaling, representing an identity matrix of any size.\n\nExamples\n\njulia> fill(1, (5,6)) * I == fill(1, (5,6))\ntrue\n\njulia> [1 2im 3; 1im 2 3] * I\n2×3 Matrix{Complex{Int64}}:\n 1+0im 0+2im 3+0im\n 0+1im 2+0im 3+0im\n\n\n\n\n\n","category":"constant"},{"location":"stdlib/LinearAlgebra/#LinearAlgebra.UniformScaling-Tuple{Integer}","page":"Linear Algebra","title":"LinearAlgebra.UniformScaling","text":"(I::UniformScaling)(n::Integer)\n\nConstruct a Diagonal matrix from a UniformScaling.\n\ncompat: Julia 1.2\nThis method is available as of Julia 1.2.\n\nExamples\n\njulia> I(3)\n3×3 Diagonal{Bool, Vector{Bool}}:\n 1 ⋅ ⋅\n ⋅ 1 ⋅\n ⋅ ⋅ 1\n\njulia> (0.7*I)(3)\n3×3 Diagonal{Float64, Vector{Float64}}:\n 0.7 ⋅ ⋅\n ⋅ 0.7 ⋅\n ⋅ ⋅ 0.7\n\n\n\n\n\n","category":"method"},{"location":"stdlib/LinearAlgebra/#LinearAlgebra.Factorization","page":"Linear Algebra","title":"LinearAlgebra.Factorization","text":"LinearAlgebra.Factorization\n\nAbstract type for matrix factorizations a.k.a. matrix decompositions. See online documentation for a list of available matrix factorizations.\n\n\n\n\n\n","category":"type"},{"location":"stdlib/LinearAlgebra/#LinearAlgebra.LU","page":"Linear Algebra","title":"LinearAlgebra.LU","text":"LU <: Factorization\n\nMatrix factorization type of the LU factorization of a square matrix A. This is the return type of lu, the corresponding matrix factorization function.\n\nThe individual components of the factorization F::LU can be accessed via getproperty:\n\nComponent Description\nF.L L (unit lower triangular) part of LU\nF.U U (upper triangular) part of LU\nF.p (right) permutation Vector\nF.P (right) permutation Matrix\n\nIterating the factorization produces the components F.L, F.U, and F.p.\n\nExamples\n\njulia> A = [4 3; 6 3]\n2×2 Matrix{Int64}:\n 4 3\n 6 3\n\njulia> F = lu(A)\nLU{Float64, Matrix{Float64}, Vector{Int64}}\nL factor:\n2×2 Matrix{Float64}:\n 1.0 0.0\n 0.666667 1.0\nU factor:\n2×2 Matrix{Float64}:\n 6.0 3.0\n 0.0 1.0\n\njulia> F.L * F.U == A[F.p, :]\ntrue\n\njulia> l, u, p = lu(A); # destructuring via iteration\n\njulia> l == F.L && u == F.U && p == F.p\ntrue\n\n\n\n\n\n","category":"type"},{"location":"stdlib/LinearAlgebra/#LinearAlgebra.lu","page":"Linear Algebra","title":"LinearAlgebra.lu","text":"lu(A, pivot = RowMaximum(); check = true) -> F::LU\n\nCompute the LU factorization of A.\n\nWhen check = true, an error is thrown if the decomposition fails. When check = false, responsibility for checking the decomposition's validity (via issuccess) lies with the user.\n\nIn most cases, if A is a subtype S of AbstractMatrix{T} with an element type T supporting +, -, * and /, the return type is LU{T,S{T}}. If pivoting is chosen (default) the element type should also support abs and <. Pivoting can be turned off by passing pivot = NoPivot().\n\nThe individual components of the factorization F can be accessed via getproperty:\n\nComponent Description\nF.L L (lower triangular) part of LU\nF.U U (upper triangular) part of LU\nF.p (right) permutation Vector\nF.P (right) permutation Matrix\n\nIterating the factorization produces the components F.L, F.U, and F.p.\n\nThe relationship between F and A is\n\nF.L*F.U == A[F.p, :]\n\nF further supports the following functions:\n\nSupported function LU LU{T,Tridiagonal{T}}\n/ ✓ \n\\ ✓ ✓\ninv ✓ ✓\ndet ✓ ✓\nlogdet ✓ ✓\nlogabsdet ✓ ✓\nsize ✓ ✓\n\nExamples\n\njulia> A = [4 3; 6 3]\n2×2 Matrix{Int64}:\n 4 3\n 6 3\n\njulia> F = lu(A)\nLU{Float64, Matrix{Float64}, Vector{Int64}}\nL factor:\n2×2 Matrix{Float64}:\n 1.0 0.0\n 0.666667 1.0\nU factor:\n2×2 Matrix{Float64}:\n 6.0 3.0\n 0.0 1.0\n\njulia> F.L * F.U == A[F.p, :]\ntrue\n\njulia> l, u, p = lu(A); # destructuring via iteration\n\njulia> l == F.L && u == F.U && p == F.p\ntrue\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LinearAlgebra/#LinearAlgebra.lu!","page":"Linear Algebra","title":"LinearAlgebra.lu!","text":"lu!(A, pivot = RowMaximum(); check = true) -> LU\n\nlu! is the same as lu, but saves space by overwriting the input A, instead of creating a copy. An InexactError exception is thrown if the factorization produces a number not representable by the element type of A, e.g. for integer types.\n\nExamples\n\njulia> A = [4. 3.; 6. 3.]\n2×2 Matrix{Float64}:\n 4.0 3.0\n 6.0 3.0\n\njulia> F = lu!(A)\nLU{Float64, Matrix{Float64}, Vector{Int64}}\nL factor:\n2×2 Matrix{Float64}:\n 1.0 0.0\n 0.666667 1.0\nU factor:\n2×2 Matrix{Float64}:\n 6.0 3.0\n 0.0 1.0\n\njulia> iA = [4 3; 6 3]\n2×2 Matrix{Int64}:\n 4 3\n 6 3\n\njulia> lu!(iA)\nERROR: InexactError: Int64(0.6666666666666666)\nStacktrace:\n[...]\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LinearAlgebra/#LinearAlgebra.Cholesky","page":"Linear Algebra","title":"LinearAlgebra.Cholesky","text":"Cholesky <: Factorization\n\nMatrix factorization type of the Cholesky factorization of a dense symmetric/Hermitian positive definite matrix A. This is the return type of cholesky, the corresponding matrix factorization function.\n\nThe triangular Cholesky factor can be obtained from the factorization F::Cholesky via F.L and F.U, where A ≈ F.U' * F.U ≈ F.L * F.L'.\n\nThe following functions are available for Cholesky objects: size, \\, inv, det, logdet and isposdef.\n\nIterating the decomposition produces the components L and U.\n\nExamples\n\njulia> A = [4. 12. -16.; 12. 37. -43.; -16. -43. 98.]\n3×3 Matrix{Float64}:\n 4.0 12.0 -16.0\n 12.0 37.0 -43.0\n -16.0 -43.0 98.0\n\njulia> C = cholesky(A)\nCholesky{Float64, Matrix{Float64}}\nU factor:\n3×3 UpperTriangular{Float64, Matrix{Float64}}:\n 2.0 6.0 -8.0\n ⋅ 1.0 5.0\n ⋅ ⋅ 3.0\n\njulia> C.U\n3×3 UpperTriangular{Float64, Matrix{Float64}}:\n 2.0 6.0 -8.0\n ⋅ 1.0 5.0\n ⋅ ⋅ 3.0\n\njulia> C.L\n3×3 LowerTriangular{Float64, Matrix{Float64}}:\n 2.0 ⋅ ⋅\n 6.0 1.0 ⋅\n -8.0 5.0 3.0\n\njulia> C.L * C.U == A\ntrue\n\njulia> l, u = C; # destructuring via iteration\n\njulia> l == C.L && u == C.U\ntrue\n\n\n\n\n\n","category":"type"},{"location":"stdlib/LinearAlgebra/#LinearAlgebra.CholeskyPivoted","page":"Linear Algebra","title":"LinearAlgebra.CholeskyPivoted","text":"CholeskyPivoted\n\nMatrix factorization type of the pivoted Cholesky factorization of a dense symmetric/Hermitian positive semi-definite matrix A. This is the return type of cholesky(_, ::RowMaximum), the corresponding matrix factorization function.\n\nThe triangular Cholesky factor can be obtained from the factorization F::CholeskyPivoted via F.L and F.U, and the permutation via F.p, where A[F.p, F.p] ≈ Ur' * Ur ≈ Lr * Lr' with Ur = F.U[1:F.rank, :] and Lr = F.L[:, 1:F.rank], or alternatively A ≈ Up' * Up ≈ Lp * Lp' with Up = F.U[1:F.rank, invperm(F.p)] and Lp = F.L[invperm(F.p), 1:F.rank].\n\nThe following functions are available for CholeskyPivoted objects: size, \\, inv, det, and rank.\n\nIterating the decomposition produces the components L and U.\n\nExamples\n\njulia> X = [1.0, 2.0, 3.0, 4.0];\n\njulia> A = X * X';\n\njulia> C = cholesky(A, RowMaximum(), check = false)\nCholeskyPivoted{Float64, Matrix{Float64}, Vector{Int64}}\nU factor with rank 1:\n4×4 UpperTriangular{Float64, Matrix{Float64}}:\n 4.0 2.0 3.0 1.0\n ⋅ 0.0 6.0 2.0\n ⋅ ⋅ 9.0 3.0\n ⋅ ⋅ ⋅ 1.0\npermutation:\n4-element Vector{Int64}:\n 4\n 2\n 3\n 1\n\njulia> C.U[1:C.rank, :]' * C.U[1:C.rank, :] ≈ A[C.p, C.p]\ntrue\n\njulia> l, u = C; # destructuring via iteration\n\njulia> l == C.L && u == C.U\ntrue\n\n\n\n\n\n","category":"type"},{"location":"stdlib/LinearAlgebra/#LinearAlgebra.cholesky","page":"Linear Algebra","title":"LinearAlgebra.cholesky","text":"cholesky(A, NoPivot(); check = true) -> Cholesky\n\nCompute the Cholesky factorization of a dense symmetric positive definite matrix A and return a Cholesky factorization. The matrix A can either be a Symmetric or Hermitian AbstractMatrix or a perfectly symmetric or Hermitian AbstractMatrix.\n\nThe triangular Cholesky factor can be obtained from the factorization F via F.L and F.U, where A ≈ F.U' * F.U ≈ F.L * F.L'.\n\nThe following functions are available for Cholesky objects: size, \\, inv, det, logdet and isposdef.\n\nIf you have a matrix A that is slightly non-Hermitian due to roundoff errors in its construction, wrap it in Hermitian(A) before passing it to cholesky in order to treat it as perfectly Hermitian.\n\nWhen check = true, an error is thrown if the decomposition fails. When check = false, responsibility for checking the decomposition's validity (via issuccess) lies with the user.\n\nExamples\n\njulia> A = [4. 12. -16.; 12. 37. -43.; -16. -43. 98.]\n3×3 Matrix{Float64}:\n 4.0 12.0 -16.0\n 12.0 37.0 -43.0\n -16.0 -43.0 98.0\n\njulia> C = cholesky(A)\nCholesky{Float64, Matrix{Float64}}\nU factor:\n3×3 UpperTriangular{Float64, Matrix{Float64}}:\n 2.0 6.0 -8.0\n ⋅ 1.0 5.0\n ⋅ ⋅ 3.0\n\njulia> C.U\n3×3 UpperTriangular{Float64, Matrix{Float64}}:\n 2.0 6.0 -8.0\n ⋅ 1.0 5.0\n ⋅ ⋅ 3.0\n\njulia> C.L\n3×3 LowerTriangular{Float64, Matrix{Float64}}:\n 2.0 ⋅ ⋅\n 6.0 1.0 ⋅\n -8.0 5.0 3.0\n\njulia> C.L * C.U == A\ntrue\n\n\n\n\n\ncholesky(A, RowMaximum(); tol = 0.0, check = true) -> CholeskyPivoted\n\nCompute the pivoted Cholesky factorization of a dense symmetric positive semi-definite matrix A and return a CholeskyPivoted factorization. The matrix A can either be a Symmetric or Hermitian AbstractMatrix or a perfectly symmetric or Hermitian AbstractMatrix.\n\nThe triangular Cholesky factor can be obtained from the factorization F via F.L and F.U, and the permutation via F.p, where A[F.p, F.p] ≈ Ur' * Ur ≈ Lr * Lr' with Ur = F.U[1:F.rank, :] and Lr = F.L[:, 1:F.rank], or alternatively A ≈ Up' * Up ≈ Lp * Lp' with Up = F.U[1:F.rank, invperm(F.p)] and Lp = F.L[invperm(F.p), 1:F.rank].\n\nThe following functions are available for CholeskyPivoted objects: size, \\, inv, det, and rank.\n\nThe argument tol determines the tolerance for determining the rank. For negative values, the tolerance is the machine precision.\n\nIf you have a matrix A that is slightly non-Hermitian due to roundoff errors in its construction, wrap it in Hermitian(A) before passing it to cholesky in order to treat it as perfectly Hermitian.\n\nWhen check = true, an error is thrown if the decomposition fails. When check = false, responsibility for checking the decomposition's validity (via issuccess) lies with the user.\n\nExamples\n\njulia> X = [1.0, 2.0, 3.0, 4.0];\n\njulia> A = X * X';\n\njulia> C = cholesky(A, RowMaximum(), check = false)\nCholeskyPivoted{Float64, Matrix{Float64}, Vector{Int64}}\nU factor with rank 1:\n4×4 UpperTriangular{Float64, Matrix{Float64}}:\n 4.0 2.0 3.0 1.0\n ⋅ 0.0 6.0 2.0\n ⋅ ⋅ 9.0 3.0\n ⋅ ⋅ ⋅ 1.0\npermutation:\n4-element Vector{Int64}:\n 4\n 2\n 3\n 1\n\njulia> C.U[1:C.rank, :]' * C.U[1:C.rank, :] ≈ A[C.p, C.p]\ntrue\n\njulia> l, u = C; # destructuring via iteration\n\njulia> l == C.L && u == C.U\ntrue\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LinearAlgebra/#LinearAlgebra.cholesky!","page":"Linear Algebra","title":"LinearAlgebra.cholesky!","text":"cholesky!(A::AbstractMatrix, NoPivot(); check = true) -> Cholesky\n\nThe same as cholesky, but saves space by overwriting the input A, instead of creating a copy. An InexactError exception is thrown if the factorization produces a number not representable by the element type of A, e.g. for integer types.\n\nExamples\n\njulia> A = [1 2; 2 50]\n2×2 Matrix{Int64}:\n 1 2\n 2 50\n\njulia> cholesky!(A)\nERROR: InexactError: Int64(6.782329983125268)\nStacktrace:\n[...]\n\n\n\n\n\ncholesky!(A::AbstractMatrix, RowMaximum(); tol = 0.0, check = true) -> CholeskyPivoted\n\nThe same as cholesky, but saves space by overwriting the input A, instead of creating a copy. An InexactError exception is thrown if the factorization produces a number not representable by the element type of A, e.g. for integer types.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LinearAlgebra/#LinearAlgebra.lowrankupdate","page":"Linear Algebra","title":"LinearAlgebra.lowrankupdate","text":"lowrankupdate(C::Cholesky, v::AbstractVector) -> CC::Cholesky\n\nUpdate a Cholesky factorization C with the vector v. If A = C.U'C.U then CC = cholesky(C.U'C.U + v*v') but the computation of CC only uses O(n^2) operations.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LinearAlgebra/#LinearAlgebra.lowrankdowndate","page":"Linear Algebra","title":"LinearAlgebra.lowrankdowndate","text":"lowrankdowndate(C::Cholesky, v::AbstractVector) -> CC::Cholesky\n\nDowndate a Cholesky factorization C with the vector v. If A = C.U'C.U then CC = cholesky(C.U'C.U - v*v') but the computation of CC only uses O(n^2) operations.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LinearAlgebra/#LinearAlgebra.lowrankupdate!","page":"Linear Algebra","title":"LinearAlgebra.lowrankupdate!","text":"lowrankupdate!(C::Cholesky, v::AbstractVector) -> CC::Cholesky\n\nUpdate a Cholesky factorization C with the vector v. If A = C.U'C.U then CC = cholesky(C.U'C.U + v*v') but the computation of CC only uses O(n^2) operations. The input factorization C is updated in place such that on exit C == CC. The vector v is destroyed during the computation.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LinearAlgebra/#LinearAlgebra.lowrankdowndate!","page":"Linear Algebra","title":"LinearAlgebra.lowrankdowndate!","text":"lowrankdowndate!(C::Cholesky, v::AbstractVector) -> CC::Cholesky\n\nDowndate a Cholesky factorization C with the vector v. If A = C.U'C.U then CC = cholesky(C.U'C.U - v*v') but the computation of CC only uses O(n^2) operations. The input factorization C is updated in place such that on exit C == CC. The vector v is destroyed during the computation.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LinearAlgebra/#LinearAlgebra.LDLt","page":"Linear Algebra","title":"LinearAlgebra.LDLt","text":"LDLt <: Factorization\n\nMatrix factorization type of the LDLt factorization of a real SymTridiagonal matrix S such that S = L*Diagonal(d)*L', where L is a UnitLowerTriangular matrix and d is a vector. The main use of an LDLt factorization F = ldlt(S) is to solve the linear system of equations Sx = b with F\\b. This is the return type of ldlt, the corresponding matrix factorization function.\n\nThe individual components of the factorization F::LDLt can be accessed via getproperty:\n\nComponent Description\nF.L L (unit lower triangular) part of LDLt\nF.D D (diagonal) part of LDLt\nF.Lt Lt (unit upper triangular) part of LDLt\nF.d diagonal values of D as a Vector\n\nExamples\n\njulia> S = SymTridiagonal([3., 4., 5.], [1., 2.])\n3×3 SymTridiagonal{Float64, Vector{Float64}}:\n 3.0 1.0 ⋅\n 1.0 4.0 2.0\n ⋅ 2.0 5.0\n\njulia> F = ldlt(S)\nLDLt{Float64, SymTridiagonal{Float64, Vector{Float64}}}\nL factor:\n3×3 UnitLowerTriangular{Float64, SymTridiagonal{Float64, Vector{Float64}}}:\n 1.0 ⋅ ⋅\n 0.333333 1.0 ⋅\n 0.0 0.545455 1.0\nD factor:\n3×3 Diagonal{Float64, Vector{Float64}}:\n 3.0 ⋅ ⋅\n ⋅ 3.66667 ⋅\n ⋅ ⋅ 3.90909\n\n\n\n\n\n","category":"type"},{"location":"stdlib/LinearAlgebra/#LinearAlgebra.ldlt","page":"Linear Algebra","title":"LinearAlgebra.ldlt","text":"ldlt(S::SymTridiagonal) -> LDLt\n\nCompute an LDLt (i.e., LDL^T) factorization of the real symmetric tridiagonal matrix S such that S = L*Diagonal(d)*L' where L is a unit lower triangular matrix and d is a vector. The main use of an LDLt factorization F = ldlt(S) is to solve the linear system of equations Sx = b with F\\b.\n\nSee also bunchkaufman for a similar, but pivoted, factorization of arbitrary symmetric or Hermitian matrices.\n\nExamples\n\njulia> S = SymTridiagonal([3., 4., 5.], [1., 2.])\n3×3 SymTridiagonal{Float64, Vector{Float64}}:\n 3.0 1.0 ⋅\n 1.0 4.0 2.0\n ⋅ 2.0 5.0\n\njulia> ldltS = ldlt(S);\n\njulia> b = [6., 7., 8.];\n\njulia> ldltS \\ b\n3-element Vector{Float64}:\n 1.7906976744186047\n 0.627906976744186\n 1.3488372093023255\n\njulia> S \\ b\n3-element Vector{Float64}:\n 1.7906976744186047\n 0.627906976744186\n 1.3488372093023255\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LinearAlgebra/#LinearAlgebra.ldlt!","page":"Linear Algebra","title":"LinearAlgebra.ldlt!","text":"ldlt!(S::SymTridiagonal) -> LDLt\n\nSame as ldlt, but saves space by overwriting the input S, instead of creating a copy.\n\nExamples\n\njulia> S = SymTridiagonal([3., 4., 5.], [1., 2.])\n3×3 SymTridiagonal{Float64, Vector{Float64}}:\n 3.0 1.0 ⋅\n 1.0 4.0 2.0\n ⋅ 2.0 5.0\n\njulia> ldltS = ldlt!(S);\n\njulia> ldltS === S\nfalse\n\njulia> S\n3×3 SymTridiagonal{Float64, Vector{Float64}}:\n 3.0 0.333333 ⋅\n 0.333333 3.66667 0.545455\n ⋅ 0.545455 3.90909\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LinearAlgebra/#LinearAlgebra.QR","page":"Linear Algebra","title":"LinearAlgebra.QR","text":"QR <: Factorization\n\nA QR matrix factorization stored in a packed format, typically obtained from qr. If A is an m×n matrix, then\n\nA = Q R\n\nwhere Q is an orthogonal/unitary matrix and R is upper triangular. The matrix Q is stored as a sequence of Householder reflectors v_i and coefficients tau_i where:\n\nQ = prod_i=1^min(mn) (I - tau_i v_i v_i^T)\n\nIterating the decomposition produces the components Q and R.\n\nThe object has two fields:\n\nfactors is an m×n matrix.\nThe upper triangular part contains the elements of R, that is R = triu(F.factors) for a QR object F.\nThe subdiagonal part contains the reflectors v_i stored in a packed format where v_i is the ith column of the matrix V = I + tril(F.factors, -1).\nτ is a vector of length min(m,n) containing the coefficients au_i.\n\n\n\n\n\n","category":"type"},{"location":"stdlib/LinearAlgebra/#LinearAlgebra.QRCompactWY","page":"Linear Algebra","title":"LinearAlgebra.QRCompactWY","text":"QRCompactWY <: Factorization\n\nA QR matrix factorization stored in a compact blocked format, typically obtained from qr. If A is an m×n matrix, then\n\nA = Q R\n\nwhere Q is an orthogonal/unitary matrix and R is upper triangular. It is similar to the QR format except that the orthogonal/unitary matrix Q is stored in Compact WY format [Schreiber1989]. For the block size n_b, it is stored as a m×n lower trapezoidal matrix V and a matrix T = (T_1 T_2 T_b-1 T_b) composed of b = lceil min(mn) n_b rceil upper triangular matrices T_j of size n_b×n_b (j = 1 b-1) and an upper trapezoidal n_b×min(mn) - (b-1) n_b matrix T_b (j=b) whose upper square part denoted with T_b satisfying\n\nQ = prod_i=1^min(mn) (I - tau_i v_i v_i^T)\n= prod_j=1^b (I - V_j T_j V_j^T)\n\nsuch that v_i is the ith column of V, tau_i is the ith element of [diag(T_1); diag(T_2); …; diag(T_b)], and (V_1 V_2 V_b) is the left m×min(m, n) block of V. When constructed using qr, the block size is given by n_b = min(m n 36).\n\nIterating the decomposition produces the components Q and R.\n\nThe object has two fields:\n\nfactors, as in the QR type, is an m×n matrix.\nThe upper triangular part contains the elements of R, that is R = triu(F.factors) for a QR object F.\nThe subdiagonal part contains the reflectors v_i stored in a packed format such that V = I + tril(F.factors, -1).\nT is a n_b-by-min(mn) matrix as described above. The subdiagonal elements for each triangular matrix T_j are ignored.\n\nnote: Note\nThis format should not to be confused with the older WY representation [Bischof1987].\n\n[Bischof1987]: C Bischof and C Van Loan, \"The WY representation for products of Householder matrices\", SIAM J Sci Stat Comput 8 (1987), s2-s13. doi:10.1137/0908009\n\n[Schreiber1989]: R Schreiber and C Van Loan, \"A storage-efficient WY representation for products of Householder transformations\", SIAM J Sci Stat Comput 10 (1989), 53-57. doi:10.1137/0910005\n\n\n\n\n\n","category":"type"},{"location":"stdlib/LinearAlgebra/#LinearAlgebra.QRPivoted","page":"Linear Algebra","title":"LinearAlgebra.QRPivoted","text":"QRPivoted <: Factorization\n\nA QR matrix factorization with column pivoting in a packed format, typically obtained from qr. If A is an m×n matrix, then\n\nA P = Q R\n\nwhere P is a permutation matrix, Q is an orthogonal/unitary matrix and R is upper triangular. The matrix Q is stored as a sequence of Householder reflectors:\n\nQ = prod_i=1^min(mn) (I - tau_i v_i v_i^T)\n\nIterating the decomposition produces the components Q, R, and p.\n\nThe object has three fields:\n\nfactors is an m×n matrix.\nThe upper triangular part contains the elements of R, that is R = triu(F.factors) for a QR object F.\nThe subdiagonal part contains the reflectors v_i stored in a packed format where v_i is the ith column of the matrix V = I + tril(F.factors, -1).\nτ is a vector of length min(m,n) containing the coefficients au_i.\njpvt is an integer vector of length n corresponding to the permutation P.\n\n\n\n\n\n","category":"type"},{"location":"stdlib/LinearAlgebra/#LinearAlgebra.qr","page":"Linear Algebra","title":"LinearAlgebra.qr","text":"qr(A, pivot = NoPivot(); blocksize) -> F\n\nCompute the QR factorization of the matrix A: an orthogonal (or unitary if A is complex-valued) matrix Q, and an upper triangular matrix R such that\n\nA = Q R\n\nThe returned object F stores the factorization in a packed format:\n\nif pivot == ColumnNorm() then F is a QRPivoted object,\notherwise if the element type of A is a BLAS type (Float32, Float64, ComplexF32 or ComplexF64), then F is a QRCompactWY object,\notherwise F is a QR object.\n\nThe individual components of the decomposition F can be retrieved via property accessors:\n\nF.Q: the orthogonal/unitary matrix Q\nF.R: the upper triangular matrix R\nF.p: the permutation vector of the pivot (QRPivoted only)\nF.P: the permutation matrix of the pivot (QRPivoted only)\n\nIterating the decomposition produces the components Q, R, and if extant p.\n\nThe following functions are available for the QR objects: inv, size, and \\. When A is rectangular, \\ will return a least squares solution and if the solution is not unique, the one with smallest norm is returned. When A is not full rank, factorization with (column) pivoting is required to obtain a minimum norm solution.\n\nMultiplication with respect to either full/square or non-full/square Q is allowed, i.e. both F.Q*F.R and F.Q*A are supported. A Q matrix can be converted into a regular matrix with Matrix. This operation returns the \"thin\" Q factor, i.e., if A is m×n with m>=n, then Matrix(F.Q) yields an m×n matrix with orthonormal columns. To retrieve the \"full\" Q factor, an m×m orthogonal matrix, use F.Q*I. If m<=n, then Matrix(F.Q) yields an m×m orthogonal matrix.\n\nThe block size for QR decomposition can be specified by keyword argument blocksize :: Integer when pivot == NoPivot() and A isa StridedMatrix{<:BlasFloat}. It is ignored when blocksize > minimum(size(A)). See QRCompactWY.\n\ncompat: Julia 1.4\nThe blocksize keyword argument requires Julia 1.4 or later.\n\nExamples\n\njulia> A = [3.0 -6.0; 4.0 -8.0; 0.0 1.0]\n3×2 Matrix{Float64}:\n 3.0 -6.0\n 4.0 -8.0\n 0.0 1.0\n\njulia> F = qr(A)\nLinearAlgebra.QRCompactWY{Float64, Matrix{Float64}, Matrix{Float64}}\nQ factor:\n3×3 LinearAlgebra.QRCompactWYQ{Float64, Matrix{Float64}, Matrix{Float64}}:\n -0.6 0.0 0.8\n -0.8 0.0 -0.6\n 0.0 -1.0 0.0\nR factor:\n2×2 Matrix{Float64}:\n -5.0 10.0\n 0.0 -1.0\n\njulia> F.Q * F.R == A\ntrue\n\nnote: Note\nqr returns multiple types because LAPACK uses several representations that minimize the memory storage requirements of products of Householder elementary reflectors, so that the Q and R matrices can be stored compactly rather as two separate dense matrices.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LinearAlgebra/#LinearAlgebra.qr!","page":"Linear Algebra","title":"LinearAlgebra.qr!","text":"qr!(A, pivot = NoPivot(); blocksize)\n\nqr! is the same as qr when A is a subtype of StridedMatrix, but saves space by overwriting the input A, instead of creating a copy. An InexactError exception is thrown if the factorization produces a number not representable by the element type of A, e.g. for integer types.\n\ncompat: Julia 1.4\nThe blocksize keyword argument requires Julia 1.4 or later.\n\nExamples\n\njulia> a = [1. 2.; 3. 4.]\n2×2 Matrix{Float64}:\n 1.0 2.0\n 3.0 4.0\n\njulia> qr!(a)\nLinearAlgebra.QRCompactWY{Float64, Matrix{Float64}, Matrix{Float64}}\nQ factor:\n2×2 LinearAlgebra.QRCompactWYQ{Float64, Matrix{Float64}, Matrix{Float64}}:\n -0.316228 -0.948683\n -0.948683 0.316228\nR factor:\n2×2 Matrix{Float64}:\n -3.16228 -4.42719\n 0.0 -0.632456\n\njulia> a = [1 2; 3 4]\n2×2 Matrix{Int64}:\n 1 2\n 3 4\n\njulia> qr!(a)\nERROR: InexactError: Int64(3.1622776601683795)\nStacktrace:\n[...]\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LinearAlgebra/#LinearAlgebra.LQ","page":"Linear Algebra","title":"LinearAlgebra.LQ","text":"LQ <: Factorization\n\nMatrix factorization type of the LQ factorization of a matrix A. The LQ decomposition is the QR decomposition of transpose(A). This is the return type of lq, the corresponding matrix factorization function.\n\nIf S::LQ is the factorization object, the lower triangular component can be obtained via S.L, and the orthogonal/unitary component via S.Q, such that A ≈ S.L*S.Q.\n\nIterating the decomposition produces the components S.L and S.Q.\n\nExamples\n\njulia> A = [5. 7.; -2. -4.]\n2×2 Matrix{Float64}:\n 5.0 7.0\n -2.0 -4.0\n\njulia> S = lq(A)\nLQ{Float64, Matrix{Float64}, Vector{Float64}}\nL factor:\n2×2 Matrix{Float64}:\n -8.60233 0.0\n 4.41741 -0.697486\nQ factor:\n2×2 LinearAlgebra.LQPackedQ{Float64, Matrix{Float64}, Vector{Float64}}:\n -0.581238 -0.813733\n -0.813733 0.581238\n\njulia> S.L * S.Q\n2×2 Matrix{Float64}:\n 5.0 7.0\n -2.0 -4.0\n\njulia> l, q = S; # destructuring via iteration\n\njulia> l == S.L && q == S.Q\ntrue\n\n\n\n\n\n","category":"type"},{"location":"stdlib/LinearAlgebra/#LinearAlgebra.lq","page":"Linear Algebra","title":"LinearAlgebra.lq","text":"lq(A) -> S::LQ\n\nCompute the LQ decomposition of A. The decomposition's lower triangular component can be obtained from the LQ object S via S.L, and the orthogonal/unitary component via S.Q, such that A ≈ S.L*S.Q.\n\nIterating the decomposition produces the components S.L and S.Q.\n\nThe LQ decomposition is the QR decomposition of transpose(A), and it is useful in order to compute the minimum-norm solution lq(A) \\ b to an underdetermined system of equations (A has more columns than rows, but has full row rank).\n\nExamples\n\njulia> A = [5. 7.; -2. -4.]\n2×2 Matrix{Float64}:\n 5.0 7.0\n -2.0 -4.0\n\njulia> S = lq(A)\nLQ{Float64, Matrix{Float64}, Vector{Float64}}\nL factor:\n2×2 Matrix{Float64}:\n -8.60233 0.0\n 4.41741 -0.697486\nQ factor:\n2×2 LinearAlgebra.LQPackedQ{Float64, Matrix{Float64}, Vector{Float64}}:\n -0.581238 -0.813733\n -0.813733 0.581238\n\njulia> S.L * S.Q\n2×2 Matrix{Float64}:\n 5.0 7.0\n -2.0 -4.0\n\njulia> l, q = S; # destructuring via iteration\n\njulia> l == S.L && q == S.Q\ntrue\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LinearAlgebra/#LinearAlgebra.lq!","page":"Linear Algebra","title":"LinearAlgebra.lq!","text":"lq!(A) -> LQ\n\nCompute the LQ factorization of A, using the input matrix as a workspace. See also lq.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LinearAlgebra/#LinearAlgebra.BunchKaufman","page":"Linear Algebra","title":"LinearAlgebra.BunchKaufman","text":"BunchKaufman <: Factorization\n\nMatrix factorization type of the Bunch-Kaufman factorization of a symmetric or Hermitian matrix A as P'UDU'P or P'LDL'P, depending on whether the upper (the default) or the lower triangle is stored in A. If A is complex symmetric then U' and L' denote the unconjugated transposes, i.e. transpose(U) and transpose(L), respectively. This is the return type of bunchkaufman, the corresponding matrix factorization function.\n\nIf S::BunchKaufman is the factorization object, the components can be obtained via S.D, S.U or S.L as appropriate given S.uplo, and S.p.\n\nIterating the decomposition produces the components S.D, S.U or S.L as appropriate given S.uplo, and S.p.\n\nExamples\n\njulia> A = [1 2; 2 3]\n2×2 Matrix{Int64}:\n 1 2\n 2 3\n\njulia> S = bunchkaufman(A) # A gets wrapped internally by Symmetric(A)\nBunchKaufman{Float64, Matrix{Float64}, Vector{Int64}}\nD factor:\n2×2 Tridiagonal{Float64, Vector{Float64}}:\n -0.333333 0.0\n 0.0 3.0\nU factor:\n2×2 UnitUpperTriangular{Float64, Matrix{Float64}}:\n 1.0 0.666667\n ⋅ 1.0\npermutation:\n2-element Vector{Int64}:\n 1\n 2\n\njulia> d, u, p = S; # destructuring via iteration\n\njulia> d == S.D && u == S.U && p == S.p\ntrue\n\njulia> S = bunchkaufman(Symmetric(A, :L))\nBunchKaufman{Float64, Matrix{Float64}, Vector{Int64}}\nD factor:\n2×2 Tridiagonal{Float64, Vector{Float64}}:\n 3.0 0.0\n 0.0 -0.333333\nL factor:\n2×2 UnitLowerTriangular{Float64, Matrix{Float64}}:\n 1.0 ⋅\n 0.666667 1.0\npermutation:\n2-element Vector{Int64}:\n 2\n 1\n\n\n\n\n\n","category":"type"},{"location":"stdlib/LinearAlgebra/#LinearAlgebra.bunchkaufman","page":"Linear Algebra","title":"LinearAlgebra.bunchkaufman","text":"bunchkaufman(A, rook::Bool=false; check = true) -> S::BunchKaufman\n\nCompute the Bunch-Kaufman [Bunch1977] factorization of a symmetric or Hermitian matrix A as P'*U*D*U'*P or P'*L*D*L'*P, depending on which triangle is stored in A, and return a BunchKaufman object. Note that if A is complex symmetric then U' and L' denote the unconjugated transposes, i.e. transpose(U) and transpose(L).\n\nIterating the decomposition produces the components S.D, S.U or S.L as appropriate given S.uplo, and S.p.\n\nIf rook is true, rook pivoting is used. If rook is false, rook pivoting is not used.\n\nWhen check = true, an error is thrown if the decomposition fails. When check = false, responsibility for checking the decomposition's validity (via issuccess) lies with the user.\n\nThe following functions are available for BunchKaufman objects: size, \\, inv, issymmetric, ishermitian, getindex.\n\n[Bunch1977]: J R Bunch and L Kaufman, Some stable methods for calculating inertia and solving symmetric linear systems, Mathematics of Computation 31:137 (1977), 163-179. url.\n\nExamples\n\njulia> A = [1 2; 2 3]\n2×2 Matrix{Int64}:\n 1 2\n 2 3\n\njulia> S = bunchkaufman(A) # A gets wrapped internally by Symmetric(A)\nBunchKaufman{Float64, Matrix{Float64}, Vector{Int64}}\nD factor:\n2×2 Tridiagonal{Float64, Vector{Float64}}:\n -0.333333 0.0\n 0.0 3.0\nU factor:\n2×2 UnitUpperTriangular{Float64, Matrix{Float64}}:\n 1.0 0.666667\n ⋅ 1.0\npermutation:\n2-element Vector{Int64}:\n 1\n 2\n\njulia> d, u, p = S; # destructuring via iteration\n\njulia> d == S.D && u == S.U && p == S.p\ntrue\n\njulia> S.U*S.D*S.U' - S.P*A*S.P'\n2×2 Matrix{Float64}:\n 0.0 0.0\n 0.0 0.0\n\njulia> S = bunchkaufman(Symmetric(A, :L))\nBunchKaufman{Float64, Matrix{Float64}, Vector{Int64}}\nD factor:\n2×2 Tridiagonal{Float64, Vector{Float64}}:\n 3.0 0.0\n 0.0 -0.333333\nL factor:\n2×2 UnitLowerTriangular{Float64, Matrix{Float64}}:\n 1.0 ⋅\n 0.666667 1.0\npermutation:\n2-element Vector{Int64}:\n 2\n 1\n\njulia> S.L*S.D*S.L' - A[S.p, S.p]\n2×2 Matrix{Float64}:\n 0.0 0.0\n 0.0 0.0\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LinearAlgebra/#LinearAlgebra.bunchkaufman!","page":"Linear Algebra","title":"LinearAlgebra.bunchkaufman!","text":"bunchkaufman!(A, rook::Bool=false; check = true) -> BunchKaufman\n\nbunchkaufman! is the same as bunchkaufman, but saves space by overwriting the input A, instead of creating a copy.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LinearAlgebra/#LinearAlgebra.Eigen","page":"Linear Algebra","title":"LinearAlgebra.Eigen","text":"Eigen <: Factorization\n\nMatrix factorization type of the eigenvalue/spectral decomposition of a square matrix A. This is the return type of eigen, the corresponding matrix factorization function.\n\nIf F::Eigen is the factorization object, the eigenvalues can be obtained via F.values and the eigenvectors as the columns of the matrix F.vectors. (The kth eigenvector can be obtained from the slice F.vectors[:, k].)\n\nIterating the decomposition produces the components F.values and F.vectors.\n\nExamples\n\njulia> F = eigen([1.0 0.0 0.0; 0.0 3.0 0.0; 0.0 0.0 18.0])\nEigen{Float64, Float64, Matrix{Float64}, Vector{Float64}}\nvalues:\n3-element Vector{Float64}:\n 1.0\n 3.0\n 18.0\nvectors:\n3×3 Matrix{Float64}:\n 1.0 0.0 0.0\n 0.0 1.0 0.0\n 0.0 0.0 1.0\n\njulia> F.values\n3-element Vector{Float64}:\n 1.0\n 3.0\n 18.0\n\njulia> F.vectors\n3×3 Matrix{Float64}:\n 1.0 0.0 0.0\n 0.0 1.0 0.0\n 0.0 0.0 1.0\n\njulia> vals, vecs = F; # destructuring via iteration\n\njulia> vals == F.values && vecs == F.vectors\ntrue\n\n\n\n\n\n","category":"type"},{"location":"stdlib/LinearAlgebra/#LinearAlgebra.GeneralizedEigen","page":"Linear Algebra","title":"LinearAlgebra.GeneralizedEigen","text":"GeneralizedEigen <: Factorization\n\nMatrix factorization type of the generalized eigenvalue/spectral decomposition of A and B. This is the return type of eigen, the corresponding matrix factorization function, when called with two matrix arguments.\n\nIf F::GeneralizedEigen is the factorization object, the eigenvalues can be obtained via F.values and the eigenvectors as the columns of the matrix F.vectors. (The kth eigenvector can be obtained from the slice F.vectors[:, k].)\n\nIterating the decomposition produces the components F.values and F.vectors.\n\nExamples\n\njulia> A = [1 0; 0 -1]\n2×2 Matrix{Int64}:\n 1 0\n 0 -1\n\njulia> B = [0 1; 1 0]\n2×2 Matrix{Int64}:\n 0 1\n 1 0\n\njulia> F = eigen(A, B)\nGeneralizedEigen{ComplexF64, ComplexF64, Matrix{ComplexF64}, Vector{ComplexF64}}\nvalues:\n2-element Vector{ComplexF64}:\n 0.0 - 1.0im\n 0.0 + 1.0im\nvectors:\n2×2 Matrix{ComplexF64}:\n 0.0+1.0im 0.0-1.0im\n -1.0+0.0im -1.0-0.0im\n\njulia> F.values\n2-element Vector{ComplexF64}:\n 0.0 - 1.0im\n 0.0 + 1.0im\n\njulia> F.vectors\n2×2 Matrix{ComplexF64}:\n 0.0+1.0im 0.0-1.0im\n -1.0+0.0im -1.0-0.0im\n\njulia> vals, vecs = F; # destructuring via iteration\n\njulia> vals == F.values && vecs == F.vectors\ntrue\n\n\n\n\n\n","category":"type"},{"location":"stdlib/LinearAlgebra/#LinearAlgebra.eigvals","page":"Linear Algebra","title":"LinearAlgebra.eigvals","text":"eigvals(A; permute::Bool=true, scale::Bool=true, sortby) -> values\n\nReturn the eigenvalues of A.\n\nFor general non-symmetric matrices it is possible to specify how the matrix is balanced before the eigenvalue calculation. The permute, scale, and sortby keywords are the same as for eigen.\n\nExamples\n\njulia> diag_matrix = [1 0; 0 4]\n2×2 Matrix{Int64}:\n 1 0\n 0 4\n\njulia> eigvals(diag_matrix)\n2-element Vector{Float64}:\n 1.0\n 4.0\n\n\n\n\n\nFor a scalar input, eigvals will return a scalar.\n\nExample\n\njulia> eigvals(-2)\n-2\n\n\n\n\n\neigvals(A, B) -> values\n\nCompute the generalized eigenvalues of A and B.\n\nExamples\n\njulia> A = [1 0; 0 -1]\n2×2 Matrix{Int64}:\n 1 0\n 0 -1\n\njulia> B = [0 1; 1 0]\n2×2 Matrix{Int64}:\n 0 1\n 1 0\n\njulia> eigvals(A,B)\n2-element Vector{ComplexF64}:\n 0.0 - 1.0im\n 0.0 + 1.0im\n\n\n\n\n\neigvals(A::Union{SymTridiagonal, Hermitian, Symmetric}, irange::UnitRange) -> values\n\nReturn the eigenvalues of A. It is possible to calculate only a subset of the eigenvalues by specifying a UnitRange irange covering indices of the sorted eigenvalues, e.g. the 2nd to 8th eigenvalues.\n\nExamples\n\njulia> A = SymTridiagonal([1.; 2.; 1.], [2.; 3.])\n3×3 SymTridiagonal{Float64, Vector{Float64}}:\n 1.0 2.0 ⋅\n 2.0 2.0 3.0\n ⋅ 3.0 1.0\n\njulia> eigvals(A, 2:2)\n1-element Vector{Float64}:\n 0.9999999999999996\n\njulia> eigvals(A)\n3-element Vector{Float64}:\n -2.1400549446402604\n 1.0000000000000002\n 5.140054944640259\n\n\n\n\n\neigvals(A::Union{SymTridiagonal, Hermitian, Symmetric}, vl::Real, vu::Real) -> values\n\nReturn the eigenvalues of A. It is possible to calculate only a subset of the eigenvalues by specifying a pair vl and vu for the lower and upper boundaries of the eigenvalues.\n\nExamples\n\njulia> A = SymTridiagonal([1.; 2.; 1.], [2.; 3.])\n3×3 SymTridiagonal{Float64, Vector{Float64}}:\n 1.0 2.0 ⋅\n 2.0 2.0 3.0\n ⋅ 3.0 1.0\n\njulia> eigvals(A, -1, 2)\n1-element Vector{Float64}:\n 1.0000000000000009\n\njulia> eigvals(A)\n3-element Vector{Float64}:\n -2.1400549446402604\n 1.0000000000000002\n 5.140054944640259\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LinearAlgebra/#LinearAlgebra.eigvals!","page":"Linear Algebra","title":"LinearAlgebra.eigvals!","text":"eigvals!(A; permute::Bool=true, scale::Bool=true, sortby) -> values\n\nSame as eigvals, but saves space by overwriting the input A, instead of creating a copy. The permute, scale, and sortby keywords are the same as for eigen.\n\nnote: Note\nThe input matrix A will not contain its eigenvalues after eigvals! is called on it - A is used as a workspace.\n\nExamples\n\njulia> A = [1. 2.; 3. 4.]\n2×2 Matrix{Float64}:\n 1.0 2.0\n 3.0 4.0\n\njulia> eigvals!(A)\n2-element Vector{Float64}:\n -0.3722813232690143\n 5.372281323269014\n\njulia> A\n2×2 Matrix{Float64}:\n -0.372281 -1.0\n 0.0 5.37228\n\n\n\n\n\neigvals!(A, B; sortby) -> values\n\nSame as eigvals, but saves space by overwriting the input A (and B), instead of creating copies.\n\nnote: Note\nThe input matrices A and B will not contain their eigenvalues after eigvals! is called. They are used as workspaces.\n\nExamples\n\njulia> A = [1. 0.; 0. -1.]\n2×2 Matrix{Float64}:\n 1.0 0.0\n 0.0 -1.0\n\njulia> B = [0. 1.; 1. 0.]\n2×2 Matrix{Float64}:\n 0.0 1.0\n 1.0 0.0\n\njulia> eigvals!(A, B)\n2-element Vector{ComplexF64}:\n 0.0 - 1.0im\n 0.0 + 1.0im\n\njulia> A\n2×2 Matrix{Float64}:\n -0.0 -1.0\n 1.0 -0.0\n\njulia> B\n2×2 Matrix{Float64}:\n 1.0 0.0\n 0.0 1.0\n\n\n\n\n\neigvals!(A::Union{SymTridiagonal, Hermitian, Symmetric}, irange::UnitRange) -> values\n\nSame as eigvals, but saves space by overwriting the input A, instead of creating a copy. irange is a range of eigenvalue indices to search for - for instance, the 2nd to 8th eigenvalues.\n\n\n\n\n\neigvals!(A::Union{SymTridiagonal, Hermitian, Symmetric}, vl::Real, vu::Real) -> values\n\nSame as eigvals, but saves space by overwriting the input A, instead of creating a copy. vl is the lower bound of the interval to search for eigenvalues, and vu is the upper bound.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LinearAlgebra/#LinearAlgebra.eigmax","page":"Linear Algebra","title":"LinearAlgebra.eigmax","text":"eigmax(A; permute::Bool=true, scale::Bool=true)\n\nReturn the largest eigenvalue of A. The option permute=true permutes the matrix to become closer to upper triangular, and scale=true scales the matrix by its diagonal elements to make rows and columns more equal in norm. Note that if the eigenvalues of A are complex, this method will fail, since complex numbers cannot be sorted.\n\nExamples\n\njulia> A = [0 im; -im 0]\n2×2 Matrix{Complex{Int64}}:\n 0+0im 0+1im\n 0-1im 0+0im\n\njulia> eigmax(A)\n1.0\n\njulia> A = [0 im; -1 0]\n2×2 Matrix{Complex{Int64}}:\n 0+0im 0+1im\n -1+0im 0+0im\n\njulia> eigmax(A)\nERROR: DomainError with Complex{Int64}[0+0im 0+1im; -1+0im 0+0im]:\n`A` cannot have complex eigenvalues.\nStacktrace:\n[...]\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LinearAlgebra/#LinearAlgebra.eigmin","page":"Linear Algebra","title":"LinearAlgebra.eigmin","text":"eigmin(A; permute::Bool=true, scale::Bool=true)\n\nReturn the smallest eigenvalue of A. The option permute=true permutes the matrix to become closer to upper triangular, and scale=true scales the matrix by its diagonal elements to make rows and columns more equal in norm. Note that if the eigenvalues of A are complex, this method will fail, since complex numbers cannot be sorted.\n\nExamples\n\njulia> A = [0 im; -im 0]\n2×2 Matrix{Complex{Int64}}:\n 0+0im 0+1im\n 0-1im 0+0im\n\njulia> eigmin(A)\n-1.0\n\njulia> A = [0 im; -1 0]\n2×2 Matrix{Complex{Int64}}:\n 0+0im 0+1im\n -1+0im 0+0im\n\njulia> eigmin(A)\nERROR: DomainError with Complex{Int64}[0+0im 0+1im; -1+0im 0+0im]:\n`A` cannot have complex eigenvalues.\nStacktrace:\n[...]\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LinearAlgebra/#LinearAlgebra.eigvecs","page":"Linear Algebra","title":"LinearAlgebra.eigvecs","text":"eigvecs(A::SymTridiagonal[, eigvals]) -> Matrix\n\nReturn a matrix M whose columns are the eigenvectors of A. (The kth eigenvector can be obtained from the slice M[:, k].)\n\nIf the optional vector of eigenvalues eigvals is specified, eigvecs returns the specific corresponding eigenvectors.\n\nExamples\n\njulia> A = SymTridiagonal([1.; 2.; 1.], [2.; 3.])\n3×3 SymTridiagonal{Float64, Vector{Float64}}:\n 1.0 2.0 ⋅\n 2.0 2.0 3.0\n ⋅ 3.0 1.0\n\njulia> eigvals(A)\n3-element Vector{Float64}:\n -2.1400549446402604\n 1.0000000000000002\n 5.140054944640259\n\njulia> eigvecs(A)\n3×3 Matrix{Float64}:\n 0.418304 -0.83205 0.364299\n -0.656749 -7.39009e-16 0.754109\n 0.627457 0.5547 0.546448\n\njulia> eigvecs(A, [1.])\n3×1 Matrix{Float64}:\n 0.8320502943378438\n 4.263514128092366e-17\n -0.5547001962252291\n\n\n\n\n\neigvecs(A; permute::Bool=true, scale::Bool=true, `sortby`) -> Matrix\n\nReturn a matrix M whose columns are the eigenvectors of A. (The kth eigenvector can be obtained from the slice M[:, k].) The permute, scale, and sortby keywords are the same as for eigen.\n\nExamples\n\njulia> eigvecs([1.0 0.0 0.0; 0.0 3.0 0.0; 0.0 0.0 18.0])\n3×3 Matrix{Float64}:\n 1.0 0.0 0.0\n 0.0 1.0 0.0\n 0.0 0.0 1.0\n\n\n\n\n\neigvecs(A, B) -> Matrix\n\nReturn a matrix M whose columns are the generalized eigenvectors of A and B. (The kth eigenvector can be obtained from the slice M[:, k].)\n\nExamples\n\njulia> A = [1 0; 0 -1]\n2×2 Matrix{Int64}:\n 1 0\n 0 -1\n\njulia> B = [0 1; 1 0]\n2×2 Matrix{Int64}:\n 0 1\n 1 0\n\njulia> eigvecs(A, B)\n2×2 Matrix{ComplexF64}:\n 0.0+1.0im 0.0-1.0im\n -1.0+0.0im -1.0-0.0im\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LinearAlgebra/#LinearAlgebra.eigen","page":"Linear Algebra","title":"LinearAlgebra.eigen","text":"eigen(A; permute::Bool=true, scale::Bool=true, sortby) -> Eigen\n\nCompute the eigenvalue decomposition of A, returning an Eigen factorization object F which contains the eigenvalues in F.values and the eigenvectors in the columns of the matrix F.vectors. (The kth eigenvector can be obtained from the slice F.vectors[:, k].)\n\nIterating the decomposition produces the components F.values and F.vectors.\n\nThe following functions are available for Eigen objects: inv, det, and isposdef.\n\nFor general nonsymmetric matrices it is possible to specify how the matrix is balanced before the eigenvector calculation. The option permute=true permutes the matrix to become closer to upper triangular, and scale=true scales the matrix by its diagonal elements to make rows and columns more equal in norm. The default is true for both options.\n\nBy default, the eigenvalues and vectors are sorted lexicographically by (real(λ),imag(λ)). A different comparison function by(λ) can be passed to sortby, or you can pass sortby=nothing to leave the eigenvalues in an arbitrary order. Some special matrix types (e.g. Diagonal or SymTridiagonal) may implement their own sorting convention and not accept a sortby keyword.\n\nExamples\n\njulia> F = eigen([1.0 0.0 0.0; 0.0 3.0 0.0; 0.0 0.0 18.0])\nEigen{Float64, Float64, Matrix{Float64}, Vector{Float64}}\nvalues:\n3-element Vector{Float64}:\n 1.0\n 3.0\n 18.0\nvectors:\n3×3 Matrix{Float64}:\n 1.0 0.0 0.0\n 0.0 1.0 0.0\n 0.0 0.0 1.0\n\njulia> F.values\n3-element Vector{Float64}:\n 1.0\n 3.0\n 18.0\n\njulia> F.vectors\n3×3 Matrix{Float64}:\n 1.0 0.0 0.0\n 0.0 1.0 0.0\n 0.0 0.0 1.0\n\njulia> vals, vecs = F; # destructuring via iteration\n\njulia> vals == F.values && vecs == F.vectors\ntrue\n\n\n\n\n\neigen(A, B; sortby) -> GeneralizedEigen\n\nCompute the generalized eigenvalue decomposition of A and B, returning a GeneralizedEigen factorization object F which contains the generalized eigenvalues in F.values and the generalized eigenvectors in the columns of the matrix F.vectors. (The kth generalized eigenvector can be obtained from the slice F.vectors[:, k].)\n\nIterating the decomposition produces the components F.values and F.vectors.\n\nBy default, the eigenvalues and vectors are sorted lexicographically by (real(λ),imag(λ)). A different comparison function by(λ) can be passed to sortby, or you can pass sortby=nothing to leave the eigenvalues in an arbitrary order.\n\nExamples\n\njulia> A = [1 0; 0 -1]\n2×2 Matrix{Int64}:\n 1 0\n 0 -1\n\njulia> B = [0 1; 1 0]\n2×2 Matrix{Int64}:\n 0 1\n 1 0\n\njulia> F = eigen(A, B);\n\njulia> F.values\n2-element Vector{ComplexF64}:\n 0.0 - 1.0im\n 0.0 + 1.0im\n\njulia> F.vectors\n2×2 Matrix{ComplexF64}:\n 0.0+1.0im 0.0-1.0im\n -1.0+0.0im -1.0-0.0im\n\njulia> vals, vecs = F; # destructuring via iteration\n\njulia> vals == F.values && vecs == F.vectors\ntrue\n\n\n\n\n\neigen(A::Union{SymTridiagonal, Hermitian, Symmetric}, irange::UnitRange) -> Eigen\n\nCompute the eigenvalue decomposition of A, returning an Eigen factorization object F which contains the eigenvalues in F.values and the eigenvectors in the columns of the matrix F.vectors. (The kth eigenvector can be obtained from the slice F.vectors[:, k].)\n\nIterating the decomposition produces the components F.values and F.vectors.\n\nThe following functions are available for Eigen objects: inv, det, and isposdef.\n\nThe UnitRange irange specifies indices of the sorted eigenvalues to search for.\n\nnote: Note\nIf irange is not 1:n, where n is the dimension of A, then the returned factorization will be a truncated factorization.\n\n\n\n\n\neigen(A::Union{SymTridiagonal, Hermitian, Symmetric}, vl::Real, vu::Real) -> Eigen\n\nCompute the eigenvalue decomposition of A, returning an Eigen factorization object F which contains the eigenvalues in F.values and the eigenvectors in the columns of the matrix F.vectors. (The kth eigenvector can be obtained from the slice F.vectors[:, k].)\n\nIterating the decomposition produces the components F.values and F.vectors.\n\nThe following functions are available for Eigen objects: inv, det, and isposdef.\n\nvl is the lower bound of the window of eigenvalues to search for, and vu is the upper bound.\n\nnote: Note\nIf [vl, vu] does not contain all eigenvalues of A, then the returned factorization will be a truncated factorization.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LinearAlgebra/#LinearAlgebra.eigen!","page":"Linear Algebra","title":"LinearAlgebra.eigen!","text":"eigen!(A; permute, scale, sortby)\neigen!(A, B; sortby)\n\nSame as eigen, but saves space by overwriting the input A (and B), instead of creating a copy.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LinearAlgebra/#LinearAlgebra.Hessenberg","page":"Linear Algebra","title":"LinearAlgebra.Hessenberg","text":"Hessenberg <: Factorization\n\nA Hessenberg object represents the Hessenberg factorization QHQ' of a square matrix, or a shift Q(H+μI)Q' thereof, which is produced by the hessenberg function.\n\n\n\n\n\n","category":"type"},{"location":"stdlib/LinearAlgebra/#LinearAlgebra.hessenberg","page":"Linear Algebra","title":"LinearAlgebra.hessenberg","text":"hessenberg(A) -> Hessenberg\n\nCompute the Hessenberg decomposition of A and return a Hessenberg object. If F is the factorization object, the unitary matrix can be accessed with F.Q (of type LinearAlgebra.HessenbergQ) and the Hessenberg matrix with F.H (of type UpperHessenberg), either of which may be converted to a regular matrix with Matrix(F.H) or Matrix(F.Q).\n\nIf A is Hermitian or real-Symmetric, then the Hessenberg decomposition produces a real-symmetric tridiagonal matrix and F.H is of type SymTridiagonal.\n\nNote that the shifted factorization A+μI = Q (H+μI) Q' can be constructed efficiently by F + μ*I using the UniformScaling object I, which creates a new Hessenberg object with shared storage and a modified shift. The shift of a given F is obtained by F.μ. This is useful because multiple shifted solves (F + μ*I) \\ b (for different μ and/or b) can be performed efficiently once F is created.\n\nIterating the decomposition produces the factors F.Q, F.H, F.μ.\n\nExamples\n\njulia> A = [4. 9. 7.; 4. 4. 1.; 4. 3. 2.]\n3×3 Matrix{Float64}:\n 4.0 9.0 7.0\n 4.0 4.0 1.0\n 4.0 3.0 2.0\n\njulia> F = hessenberg(A)\nHessenberg{Float64, UpperHessenberg{Float64, Matrix{Float64}}, Matrix{Float64}, Vector{Float64}, Bool}\nQ factor:\n3×3 LinearAlgebra.HessenbergQ{Float64, Matrix{Float64}, Vector{Float64}, false}:\n 1.0 0.0 0.0\n 0.0 -0.707107 -0.707107\n 0.0 -0.707107 0.707107\nH factor:\n3×3 UpperHessenberg{Float64, Matrix{Float64}}:\n 4.0 -11.3137 -1.41421\n -5.65685 5.0 2.0\n ⋅ -8.88178e-16 1.0\n\njulia> F.Q * F.H * F.Q'\n3×3 Matrix{Float64}:\n 4.0 9.0 7.0\n 4.0 4.0 1.0\n 4.0 3.0 2.0\n\njulia> q, h = F; # destructuring via iteration\n\njulia> q == F.Q && h == F.H\ntrue\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LinearAlgebra/#LinearAlgebra.hessenberg!","page":"Linear Algebra","title":"LinearAlgebra.hessenberg!","text":"hessenberg!(A) -> Hessenberg\n\nhessenberg! is the same as hessenberg, but saves space by overwriting the input A, instead of creating a copy.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LinearAlgebra/#LinearAlgebra.Schur","page":"Linear Algebra","title":"LinearAlgebra.Schur","text":"Schur <: Factorization\n\nMatrix factorization type of the Schur factorization of a matrix A. This is the return type of schur(_), the corresponding matrix factorization function.\n\nIf F::Schur is the factorization object, the (quasi) triangular Schur factor can be obtained via either F.Schur or F.T and the orthogonal/unitary Schur vectors via F.vectors or F.Z such that A = F.vectors * F.Schur * F.vectors'. The eigenvalues of A can be obtained with F.values.\n\nIterating the decomposition produces the components F.T, F.Z, and F.values.\n\nExamples\n\njulia> A = [5. 7.; -2. -4.]\n2×2 Matrix{Float64}:\n 5.0 7.0\n -2.0 -4.0\n\njulia> F = schur(A)\nSchur{Float64, Matrix{Float64}, Vector{Float64}}\nT factor:\n2×2 Matrix{Float64}:\n 3.0 9.0\n 0.0 -2.0\nZ factor:\n2×2 Matrix{Float64}:\n 0.961524 0.274721\n -0.274721 0.961524\neigenvalues:\n2-element Vector{Float64}:\n 3.0\n -2.0\n\njulia> F.vectors * F.Schur * F.vectors'\n2×2 Matrix{Float64}:\n 5.0 7.0\n -2.0 -4.0\n\njulia> t, z, vals = F; # destructuring via iteration\n\njulia> t == F.T && z == F.Z && vals == F.values\ntrue\n\n\n\n\n\n","category":"type"},{"location":"stdlib/LinearAlgebra/#LinearAlgebra.GeneralizedSchur","page":"Linear Algebra","title":"LinearAlgebra.GeneralizedSchur","text":"GeneralizedSchur <: Factorization\n\nMatrix factorization type of the generalized Schur factorization of two matrices A and B. This is the return type of schur(_, _), the corresponding matrix factorization function.\n\nIf F::GeneralizedSchur is the factorization object, the (quasi) triangular Schur factors can be obtained via F.S and F.T, the left unitary/orthogonal Schur vectors via F.left or F.Q, and the right unitary/orthogonal Schur vectors can be obtained with F.right or F.Z such that A=F.left*F.S*F.right' and B=F.left*F.T*F.right'. The generalized eigenvalues of A and B can be obtained with F.α./F.β.\n\nIterating the decomposition produces the components F.S, F.T, F.Q, F.Z, F.α, and F.β.\n\n\n\n\n\n","category":"type"},{"location":"stdlib/LinearAlgebra/#LinearAlgebra.schur","page":"Linear Algebra","title":"LinearAlgebra.schur","text":"schur(A) -> F::Schur\n\nComputes the Schur factorization of the matrix A. The (quasi) triangular Schur factor can be obtained from the Schur object F with either F.Schur or F.T and the orthogonal/unitary Schur vectors can be obtained with F.vectors or F.Z such that A = F.vectors * F.Schur * F.vectors'. The eigenvalues of A can be obtained with F.values.\n\nFor real A, the Schur factorization is \"quasitriangular\", which means that it is upper-triangular except with 2×2 diagonal blocks for any conjugate pair of complex eigenvalues; this allows the factorization to be purely real even when there are complex eigenvalues. To obtain the (complex) purely upper-triangular Schur factorization from a real quasitriangular factorization, you can use Schur{Complex}(schur(A)).\n\nIterating the decomposition produces the components F.T, F.Z, and F.values.\n\nExamples\n\njulia> A = [5. 7.; -2. -4.]\n2×2 Matrix{Float64}:\n 5.0 7.0\n -2.0 -4.0\n\njulia> F = schur(A)\nSchur{Float64, Matrix{Float64}, Vector{Float64}}\nT factor:\n2×2 Matrix{Float64}:\n 3.0 9.0\n 0.0 -2.0\nZ factor:\n2×2 Matrix{Float64}:\n 0.961524 0.274721\n -0.274721 0.961524\neigenvalues:\n2-element Vector{Float64}:\n 3.0\n -2.0\n\njulia> F.vectors * F.Schur * F.vectors'\n2×2 Matrix{Float64}:\n 5.0 7.0\n -2.0 -4.0\n\njulia> t, z, vals = F; # destructuring via iteration\n\njulia> t == F.T && z == F.Z && vals == F.values\ntrue\n\n\n\n\n\nschur(A, B) -> F::GeneralizedSchur\n\nComputes the Generalized Schur (or QZ) factorization of the matrices A and B. The (quasi) triangular Schur factors can be obtained from the Schur object F with F.S and F.T, the left unitary/orthogonal Schur vectors can be obtained with F.left or F.Q and the right unitary/orthogonal Schur vectors can be obtained with F.right or F.Z such that A=F.left*F.S*F.right' and B=F.left*F.T*F.right'. The generalized eigenvalues of A and B can be obtained with F.α./F.β.\n\nIterating the decomposition produces the components F.S, F.T, F.Q, F.Z, F.α, and F.β.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LinearAlgebra/#LinearAlgebra.schur!","page":"Linear Algebra","title":"LinearAlgebra.schur!","text":"schur!(A::StridedMatrix) -> F::Schur\n\nSame as schur but uses the input argument A as workspace.\n\nExamples\n\njulia> A = [5. 7.; -2. -4.]\n2×2 Matrix{Float64}:\n 5.0 7.0\n -2.0 -4.0\n\njulia> F = schur!(A)\nSchur{Float64, Matrix{Float64}, Vector{Float64}}\nT factor:\n2×2 Matrix{Float64}:\n 3.0 9.0\n 0.0 -2.0\nZ factor:\n2×2 Matrix{Float64}:\n 0.961524 0.274721\n -0.274721 0.961524\neigenvalues:\n2-element Vector{Float64}:\n 3.0\n -2.0\n\njulia> A\n2×2 Matrix{Float64}:\n 3.0 9.0\n 0.0 -2.0\n\n\n\n\n\nschur!(A::StridedMatrix, B::StridedMatrix) -> F::GeneralizedSchur\n\nSame as schur but uses the input matrices A and B as workspace.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LinearAlgebra/#LinearAlgebra.ordschur","page":"Linear Algebra","title":"LinearAlgebra.ordschur","text":"ordschur(F::Schur, select::Union{Vector{Bool},BitVector}) -> F::Schur\n\nReorders the Schur factorization F of a matrix A = Z*T*Z' according to the logical array select returning the reordered factorization F object. The selected eigenvalues appear in the leading diagonal of F.Schur and the corresponding leading columns of F.vectors form an orthogonal/unitary basis of the corresponding right invariant subspace. In the real case, a complex conjugate pair of eigenvalues must be either both included or both excluded via select.\n\n\n\n\n\nordschur(F::GeneralizedSchur, select::Union{Vector{Bool},BitVector}) -> F::GeneralizedSchur\n\nReorders the Generalized Schur factorization F of a matrix pair (A, B) = (Q*S*Z', Q*T*Z') according to the logical array select and returns a GeneralizedSchur object F. The selected eigenvalues appear in the leading diagonal of both F.S and F.T, and the left and right orthogonal/unitary Schur vectors are also reordered such that (A, B) = F.Q*(F.S, F.T)*F.Z' still holds and the generalized eigenvalues of A and B can still be obtained with F.α./F.β.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LinearAlgebra/#LinearAlgebra.ordschur!","page":"Linear Algebra","title":"LinearAlgebra.ordschur!","text":"ordschur!(F::Schur, select::Union{Vector{Bool},BitVector}) -> F::Schur\n\nSame as ordschur but overwrites the factorization F.\n\n\n\n\n\nordschur!(F::GeneralizedSchur, select::Union{Vector{Bool},BitVector}) -> F::GeneralizedSchur\n\nSame as ordschur but overwrites the factorization F.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LinearAlgebra/#LinearAlgebra.SVD","page":"Linear Algebra","title":"LinearAlgebra.SVD","text":"SVD <: Factorization\n\nMatrix factorization type of the singular value decomposition (SVD) of a matrix A. This is the return type of svd(_), the corresponding matrix factorization function.\n\nIf F::SVD is the factorization object, U, S, V and Vt can be obtained via F.U, F.S, F.V and F.Vt, such that A = U * Diagonal(S) * Vt. The singular values in S are sorted in descending order.\n\nIterating the decomposition produces the components U, S, and V.\n\nExamples\n\njulia> A = [1. 0. 0. 0. 2.; 0. 0. 3. 0. 0.; 0. 0. 0. 0. 0.; 0. 2. 0. 0. 0.]\n4×5 Matrix{Float64}:\n 1.0 0.0 0.0 0.0 2.0\n 0.0 0.0 3.0 0.0 0.0\n 0.0 0.0 0.0 0.0 0.0\n 0.0 2.0 0.0 0.0 0.0\n\njulia> F = svd(A)\nSVD{Float64, Float64, Matrix{Float64}, Vector{Float64}}\nU factor:\n4×4 Matrix{Float64}:\n 0.0 1.0 0.0 0.0\n 1.0 0.0 0.0 0.0\n 0.0 0.0 0.0 -1.0\n 0.0 0.0 1.0 0.0\nsingular values:\n4-element Vector{Float64}:\n 3.0\n 2.23606797749979\n 2.0\n 0.0\nVt factor:\n4×5 Matrix{Float64}:\n -0.0 0.0 1.0 -0.0 0.0\n 0.447214 0.0 0.0 0.0 0.894427\n -0.0 1.0 0.0 -0.0 0.0\n 0.0 0.0 0.0 1.0 0.0\n\njulia> F.U * Diagonal(F.S) * F.Vt\n4×5 Matrix{Float64}:\n 1.0 0.0 0.0 0.0 2.0\n 0.0 0.0 3.0 0.0 0.0\n 0.0 0.0 0.0 0.0 0.0\n 0.0 2.0 0.0 0.0 0.0\n\njulia> u, s, v = F; # destructuring via iteration\n\njulia> u == F.U && s == F.S && v == F.V\ntrue\n\n\n\n\n\n","category":"type"},{"location":"stdlib/LinearAlgebra/#LinearAlgebra.GeneralizedSVD","page":"Linear Algebra","title":"LinearAlgebra.GeneralizedSVD","text":"GeneralizedSVD <: Factorization\n\nMatrix factorization type of the generalized singular value decomposition (SVD) of two matrices A and B, such that A = F.U*F.D1*F.R0*F.Q' and B = F.V*F.D2*F.R0*F.Q'. This is the return type of svd(_, _), the corresponding matrix factorization function.\n\nFor an M-by-N matrix A and P-by-N matrix B,\n\nU is a M-by-M orthogonal matrix,\nV is a P-by-P orthogonal matrix,\nQ is a N-by-N orthogonal matrix,\nD1 is a M-by-(K+L) diagonal matrix with 1s in the first K entries,\nD2 is a P-by-(K+L) matrix whose top right L-by-L block is diagonal,\nR0 is a (K+L)-by-N matrix whose rightmost (K+L)-by-(K+L) block is nonsingular upper block triangular,\n\nK+L is the effective numerical rank of the matrix [A; B].\n\nIterating the decomposition produces the components U, V, Q, D1, D2, and R0.\n\nThe entries of F.D1 and F.D2 are related, as explained in the LAPACK documentation for the generalized SVD and the xGGSVD3 routine which is called underneath (in LAPACK 3.6.0 and newer).\n\nExamples\n\njulia> A = [1. 0.; 0. -1.]\n2×2 Matrix{Float64}:\n 1.0 0.0\n 0.0 -1.0\n\njulia> B = [0. 1.; 1. 0.]\n2×2 Matrix{Float64}:\n 0.0 1.0\n 1.0 0.0\n\njulia> F = svd(A, B)\nGeneralizedSVD{Float64, Matrix{Float64}, Float64, Vector{Float64}}\nU factor:\n2×2 Matrix{Float64}:\n 1.0 0.0\n 0.0 1.0\nV factor:\n2×2 Matrix{Float64}:\n -0.0 -1.0\n 1.0 0.0\nQ factor:\n2×2 Matrix{Float64}:\n 1.0 0.0\n 0.0 1.0\nD1 factor:\n2×2 Matrix{Float64}:\n 0.707107 0.0\n 0.0 0.707107\nD2 factor:\n2×2 Matrix{Float64}:\n 0.707107 0.0\n 0.0 0.707107\nR0 factor:\n2×2 Matrix{Float64}:\n 1.41421 0.0\n 0.0 -1.41421\n\njulia> F.U*F.D1*F.R0*F.Q'\n2×2 Matrix{Float64}:\n 1.0 0.0\n 0.0 -1.0\n\njulia> F.V*F.D2*F.R0*F.Q'\n2×2 Matrix{Float64}:\n -0.0 1.0\n 1.0 0.0\n\n\n\n\n\n","category":"type"},{"location":"stdlib/LinearAlgebra/#LinearAlgebra.svd","page":"Linear Algebra","title":"LinearAlgebra.svd","text":"svd(A; full::Bool = false, alg::Algorithm = default_svd_alg(A)) -> SVD\n\nCompute the singular value decomposition (SVD) of A and return an SVD object.\n\nU, S, V and Vt can be obtained from the factorization F with F.U, F.S, F.V and F.Vt, such that A = U * Diagonal(S) * Vt. The algorithm produces Vt and hence Vt is more efficient to extract than V. The singular values in S are sorted in descending order.\n\nIterating the decomposition produces the components U, S, and V.\n\nIf full = false (default), a \"thin\" SVD is returned. For an M times N matrix A, in the full factorization U is M times M and V is N times N, while in the thin factorization U is M times K and V is N times K, where K = min(MN) is the number of singular values.\n\nIf alg = DivideAndConquer() a divide-and-conquer algorithm is used to calculate the SVD. Another (typically slower but more accurate) option is alg = QRIteration().\n\ncompat: Julia 1.3\nThe alg keyword argument requires Julia 1.3 or later.\n\nExamples\n\njulia> A = rand(4,3);\n\njulia> F = svd(A); # Store the Factorization Object\n\njulia> A ≈ F.U * Diagonal(F.S) * F.Vt\ntrue\n\njulia> U, S, V = F; # destructuring via iteration\n\njulia> A ≈ U * Diagonal(S) * V'\ntrue\n\njulia> Uonly, = svd(A); # Store U only\n\njulia> Uonly == U\ntrue\n\n\n\n\n\nsvd(A, B) -> GeneralizedSVD\n\nCompute the generalized SVD of A and B, returning a GeneralizedSVD factorization object F such that [A;B] = [F.U * F.D1; F.V * F.D2] * F.R0 * F.Q'\n\nU is a M-by-M orthogonal matrix,\nV is a P-by-P orthogonal matrix,\nQ is a N-by-N orthogonal matrix,\nD1 is a M-by-(K+L) diagonal matrix with 1s in the first K entries,\nD2 is a P-by-(K+L) matrix whose top right L-by-L block is diagonal,\nR0 is a (K+L)-by-N matrix whose rightmost (K+L)-by-(K+L) block is nonsingular upper block triangular,\n\nK+L is the effective numerical rank of the matrix [A; B].\n\nIterating the decomposition produces the components U, V, Q, D1, D2, and R0.\n\nThe generalized SVD is used in applications such as when one wants to compare how much belongs to A vs. how much belongs to B, as in human vs yeast genome, or signal vs noise, or between clusters vs within clusters. (See Edelman and Wang for discussion: https://arxiv.org/abs/1901.00485)\n\nIt decomposes [A; B] into [UC; VS]H, where [UC; VS] is a natural orthogonal basis for the column space of [A; B], and H = RQ' is a natural non-orthogonal basis for the rowspace of [A;B], where the top rows are most closely attributed to the A matrix, and the bottom to the B matrix. The multi-cosine/sine matrices C and S provide a multi-measure of how much A vs how much B, and U and V provide directions in which these are measured.\n\nExamples\n\njulia> A = randn(3,2); B=randn(4,2);\n\njulia> F = svd(A, B);\n\njulia> U,V,Q,C,S,R = F;\n\njulia> H = R*Q';\n\njulia> [A; B] ≈ [U*C; V*S]*H\ntrue\n\njulia> [A; B] ≈ [F.U*F.D1; F.V*F.D2]*F.R0*F.Q'\ntrue\n\njulia> Uonly, = svd(A,B);\n\njulia> U == Uonly\ntrue\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LinearAlgebra/#LinearAlgebra.svd!","page":"Linear Algebra","title":"LinearAlgebra.svd!","text":"svd!(A; full::Bool = false, alg::Algorithm = default_svd_alg(A)) -> SVD\n\nsvd! is the same as svd, but saves space by overwriting the input A, instead of creating a copy. See documentation of svd for details.\n\n\n\n\n\nsvd!(A, B) -> GeneralizedSVD\n\nsvd! is the same as svd, but modifies the arguments A and B in-place, instead of making copies. See documentation of svd for details.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LinearAlgebra/#LinearAlgebra.svdvals","page":"Linear Algebra","title":"LinearAlgebra.svdvals","text":"svdvals(A)\n\nReturn the singular values of A in descending order.\n\nExamples\n\njulia> A = [1. 0. 0. 0. 2.; 0. 0. 3. 0. 0.; 0. 0. 0. 0. 0.; 0. 2. 0. 0. 0.]\n4×5 Matrix{Float64}:\n 1.0 0.0 0.0 0.0 2.0\n 0.0 0.0 3.0 0.0 0.0\n 0.0 0.0 0.0 0.0 0.0\n 0.0 2.0 0.0 0.0 0.0\n\njulia> svdvals(A)\n4-element Vector{Float64}:\n 3.0\n 2.23606797749979\n 2.0\n 0.0\n\n\n\n\n\nsvdvals(A, B)\n\nReturn the generalized singular values from the generalized singular value decomposition of A and B. See also svd.\n\nExamples\n\njulia> A = [1. 0.; 0. -1.]\n2×2 Matrix{Float64}:\n 1.0 0.0\n 0.0 -1.0\n\njulia> B = [0. 1.; 1. 0.]\n2×2 Matrix{Float64}:\n 0.0 1.0\n 1.0 0.0\n\njulia> svdvals(A, B)\n2-element Vector{Float64}:\n 1.0\n 1.0\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LinearAlgebra/#LinearAlgebra.svdvals!","page":"Linear Algebra","title":"LinearAlgebra.svdvals!","text":"svdvals!(A)\n\nReturn the singular values of A, saving space by overwriting the input. See also svdvals and svd. ```\n\n\n\n\n\nsvdvals!(A, B)\n\nReturn the generalized singular values from the generalized singular value decomposition of A and B, saving space by overwriting A and B. See also svd and svdvals.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LinearAlgebra/#LinearAlgebra.Givens","page":"Linear Algebra","title":"LinearAlgebra.Givens","text":"LinearAlgebra.Givens(i1,i2,c,s) -> G\n\nA Givens rotation linear operator. The fields c and s represent the cosine and sine of the rotation angle, respectively. The Givens type supports left multiplication G*A and conjugated transpose right multiplication A*G'. The type doesn't have a size and can therefore be multiplied with matrices of arbitrary size as long as i2<=size(A,2) for G*A or i2<=size(A,1) for A*G'.\n\nSee also givens.\n\n\n\n\n\n","category":"type"},{"location":"stdlib/LinearAlgebra/#LinearAlgebra.givens","page":"Linear Algebra","title":"LinearAlgebra.givens","text":"givens(f::T, g::T, i1::Integer, i2::Integer) where {T} -> (G::Givens, r::T)\n\nComputes the Givens rotation G and scalar r such that for any vector x where\n\nx[i1] = f\nx[i2] = g\n\nthe result of the multiplication\n\ny = G*x\n\nhas the property that\n\ny[i1] = r\ny[i2] = 0\n\nSee also LinearAlgebra.Givens.\n\n\n\n\n\ngivens(A::AbstractArray, i1::Integer, i2::Integer, j::Integer) -> (G::Givens, r)\n\nComputes the Givens rotation G and scalar r such that the result of the multiplication\n\nB = G*A\n\nhas the property that\n\nB[i1,j] = r\nB[i2,j] = 0\n\nSee also LinearAlgebra.Givens.\n\n\n\n\n\ngivens(x::AbstractVector, i1::Integer, i2::Integer) -> (G::Givens, r)\n\nComputes the Givens rotation G and scalar r such that the result of the multiplication\n\nB = G*x\n\nhas the property that\n\nB[i1] = r\nB[i2] = 0\n\nSee also LinearAlgebra.Givens.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LinearAlgebra/#LinearAlgebra.triu","page":"Linear Algebra","title":"LinearAlgebra.triu","text":"triu(M)\n\nUpper triangle of a matrix.\n\nExamples\n\njulia> a = fill(1.0, (4,4))\n4×4 Matrix{Float64}:\n 1.0 1.0 1.0 1.0\n 1.0 1.0 1.0 1.0\n 1.0 1.0 1.0 1.0\n 1.0 1.0 1.0 1.0\n\njulia> triu(a)\n4×4 Matrix{Float64}:\n 1.0 1.0 1.0 1.0\n 0.0 1.0 1.0 1.0\n 0.0 0.0 1.0 1.0\n 0.0 0.0 0.0 1.0\n\n\n\n\n\ntriu(M, k::Integer)\n\nReturns the upper triangle of M starting from the kth superdiagonal.\n\nExamples\n\njulia> a = fill(1.0, (4,4))\n4×4 Matrix{Float64}:\n 1.0 1.0 1.0 1.0\n 1.0 1.0 1.0 1.0\n 1.0 1.0 1.0 1.0\n 1.0 1.0 1.0 1.0\n\njulia> triu(a,3)\n4×4 Matrix{Float64}:\n 0.0 0.0 0.0 1.0\n 0.0 0.0 0.0 0.0\n 0.0 0.0 0.0 0.0\n 0.0 0.0 0.0 0.0\n\njulia> triu(a,-3)\n4×4 Matrix{Float64}:\n 1.0 1.0 1.0 1.0\n 1.0 1.0 1.0 1.0\n 1.0 1.0 1.0 1.0\n 1.0 1.0 1.0 1.0\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LinearAlgebra/#LinearAlgebra.triu!","page":"Linear Algebra","title":"LinearAlgebra.triu!","text":"triu!(M)\n\nUpper triangle of a matrix, overwriting M in the process. See also triu.\n\n\n\n\n\ntriu!(M, k::Integer)\n\nReturn the upper triangle of M starting from the kth superdiagonal, overwriting M in the process.\n\nExamples\n\njulia> M = [1 2 3 4 5; 1 2 3 4 5; 1 2 3 4 5; 1 2 3 4 5; 1 2 3 4 5]\n5×5 Matrix{Int64}:\n 1 2 3 4 5\n 1 2 3 4 5\n 1 2 3 4 5\n 1 2 3 4 5\n 1 2 3 4 5\n\njulia> triu!(M, 1)\n5×5 Matrix{Int64}:\n 0 2 3 4 5\n 0 0 3 4 5\n 0 0 0 4 5\n 0 0 0 0 5\n 0 0 0 0 0\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LinearAlgebra/#LinearAlgebra.tril","page":"Linear Algebra","title":"LinearAlgebra.tril","text":"tril(M)\n\nLower triangle of a matrix.\n\nExamples\n\njulia> a = fill(1.0, (4,4))\n4×4 Matrix{Float64}:\n 1.0 1.0 1.0 1.0\n 1.0 1.0 1.0 1.0\n 1.0 1.0 1.0 1.0\n 1.0 1.0 1.0 1.0\n\njulia> tril(a)\n4×4 Matrix{Float64}:\n 1.0 0.0 0.0 0.0\n 1.0 1.0 0.0 0.0\n 1.0 1.0 1.0 0.0\n 1.0 1.0 1.0 1.0\n\n\n\n\n\ntril(M, k::Integer)\n\nReturns the lower triangle of M starting from the kth superdiagonal.\n\nExamples\n\njulia> a = fill(1.0, (4,4))\n4×4 Matrix{Float64}:\n 1.0 1.0 1.0 1.0\n 1.0 1.0 1.0 1.0\n 1.0 1.0 1.0 1.0\n 1.0 1.0 1.0 1.0\n\njulia> tril(a,3)\n4×4 Matrix{Float64}:\n 1.0 1.0 1.0 1.0\n 1.0 1.0 1.0 1.0\n 1.0 1.0 1.0 1.0\n 1.0 1.0 1.0 1.0\n\njulia> tril(a,-3)\n4×4 Matrix{Float64}:\n 0.0 0.0 0.0 0.0\n 0.0 0.0 0.0 0.0\n 0.0 0.0 0.0 0.0\n 1.0 0.0 0.0 0.0\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LinearAlgebra/#LinearAlgebra.tril!","page":"Linear Algebra","title":"LinearAlgebra.tril!","text":"tril!(M)\n\nLower triangle of a matrix, overwriting M in the process. See also tril.\n\n\n\n\n\ntril!(M, k::Integer)\n\nReturn the lower triangle of M starting from the kth superdiagonal, overwriting M in the process.\n\nExamples\n\njulia> M = [1 2 3 4 5; 1 2 3 4 5; 1 2 3 4 5; 1 2 3 4 5; 1 2 3 4 5]\n5×5 Matrix{Int64}:\n 1 2 3 4 5\n 1 2 3 4 5\n 1 2 3 4 5\n 1 2 3 4 5\n 1 2 3 4 5\n\njulia> tril!(M, 2)\n5×5 Matrix{Int64}:\n 1 2 3 0 0\n 1 2 3 4 0\n 1 2 3 4 5\n 1 2 3 4 5\n 1 2 3 4 5\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LinearAlgebra/#LinearAlgebra.diagind","page":"Linear Algebra","title":"LinearAlgebra.diagind","text":"diagind(M, k::Integer=0)\n\nAn AbstractRange giving the indices of the kth diagonal of the matrix M.\n\nSee also: diag, diagm, Diagonal.\n\nExamples\n\njulia> A = [1 2 3; 4 5 6; 7 8 9]\n3×3 Matrix{Int64}:\n 1 2 3\n 4 5 6\n 7 8 9\n\njulia> diagind(A,-1)\n2:4:6\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LinearAlgebra/#LinearAlgebra.diag","page":"Linear Algebra","title":"LinearAlgebra.diag","text":"diag(M, k::Integer=0)\n\nThe kth diagonal of a matrix, as a vector.\n\nSee also diagm, diagind, Diagonal, isdiag.\n\nExamples\n\njulia> A = [1 2 3; 4 5 6; 7 8 9]\n3×3 Matrix{Int64}:\n 1 2 3\n 4 5 6\n 7 8 9\n\njulia> diag(A,1)\n2-element Vector{Int64}:\n 2\n 6\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LinearAlgebra/#LinearAlgebra.diagm","page":"Linear Algebra","title":"LinearAlgebra.diagm","text":"diagm(kv::Pair{<:Integer,<:AbstractVector}...)\ndiagm(m::Integer, n::Integer, kv::Pair{<:Integer,<:AbstractVector}...)\n\nConstruct a matrix from Pairs of diagonals and vectors. Vector kv.second will be placed on the kv.first diagonal. By default the matrix is square and its size is inferred from kv, but a non-square size m×n (padded with zeros as needed) can be specified by passing m,n as the first arguments. For repeated diagonal indices kv.first the values in the corresponding vectors kv.second will be added.\n\ndiagm constructs a full matrix; if you want storage-efficient versions with fast arithmetic, see Diagonal, Bidiagonal Tridiagonal and SymTridiagonal.\n\nExamples\n\njulia> diagm(1 => [1,2,3])\n4×4 Matrix{Int64}:\n 0 1 0 0\n 0 0 2 0\n 0 0 0 3\n 0 0 0 0\n\njulia> diagm(1 => [1,2,3], -1 => [4,5])\n4×4 Matrix{Int64}:\n 0 1 0 0\n 4 0 2 0\n 0 5 0 3\n 0 0 0 0\n\njulia> diagm(1 => [1,2,3], 1 => [1,2,3])\n4×4 Matrix{Int64}:\n 0 2 0 0\n 0 0 4 0\n 0 0 0 6\n 0 0 0 0\n\n\n\n\n\ndiagm(v::AbstractVector)\ndiagm(m::Integer, n::Integer, v::AbstractVector)\n\nConstruct a matrix with elements of the vector as diagonal elements. By default, the matrix is square and its size is given by length(v), but a non-square size m×n can be specified by passing m,n as the first arguments.\n\nExamples\n\njulia> diagm([1,2,3])\n3×3 Matrix{Int64}:\n 1 0 0\n 0 2 0\n 0 0 3\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LinearAlgebra/#LinearAlgebra.rank","page":"Linear Algebra","title":"LinearAlgebra.rank","text":"rank(A::AbstractMatrix; atol::Real=0, rtol::Real=atol>0 ? 0 : n*ϵ)\nrank(A::AbstractMatrix, rtol::Real)\n\nCompute the rank of a matrix by counting how many singular values of A have magnitude greater than max(atol, rtol*σ₁) where σ₁ is A's largest singular value. atol and rtol are the absolute and relative tolerances, respectively. The default relative tolerance is n*ϵ, where n is the size of the smallest dimension of A, and ϵ is the eps of the element type of A.\n\ncompat: Julia 1.1\nThe atol and rtol keyword arguments requires at least Julia 1.1. In Julia 1.0 rtol is available as a positional argument, but this will be deprecated in Julia 2.0.\n\nExamples\n\njulia> rank(Matrix(I, 3, 3))\n3\n\njulia> rank(diagm(0 => [1, 0, 2]))\n2\n\njulia> rank(diagm(0 => [1, 0.001, 2]), rtol=0.1)\n2\n\njulia> rank(diagm(0 => [1, 0.001, 2]), rtol=0.00001)\n3\n\njulia> rank(diagm(0 => [1, 0.001, 2]), atol=1.5)\n1\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LinearAlgebra/#LinearAlgebra.norm","page":"Linear Algebra","title":"LinearAlgebra.norm","text":"norm(A, p::Real=2)\n\nFor any iterable container A (including arrays of any dimension) of numbers (or any element type for which norm is defined), compute the p-norm (defaulting to p=2) as if A were a vector of the corresponding length.\n\nThe p-norm is defined as\n\nA_p = left( sum_i=1^n a_i ^p right)^1p\n\nwith a_i the entries of A, a_i the norm of a_i, and n the length of A. Since the p-norm is computed using the norms of the entries of A, the p-norm of a vector of vectors is not compatible with the interpretation of it as a block vector in general if p != 2.\n\np can assume any numeric value (even though not all values produce a mathematically valid vector norm). In particular, norm(A, Inf) returns the largest value in abs.(A), whereas norm(A, -Inf) returns the smallest. If A is a matrix and p=2, then this is equivalent to the Frobenius norm.\n\nThe second argument p is not necessarily a part of the interface for norm, i.e. a custom type may only implement norm(A) without second argument.\n\nUse opnorm to compute the operator norm of a matrix.\n\nExamples\n\njulia> v = [3, -2, 6]\n3-element Vector{Int64}:\n 3\n -2\n 6\n\njulia> norm(v)\n7.0\n\njulia> norm(v, 1)\n11.0\n\njulia> norm(v, Inf)\n6.0\n\njulia> norm([1 2 3; 4 5 6; 7 8 9])\n16.881943016134134\n\njulia> norm([1 2 3 4 5 6 7 8 9])\n16.881943016134134\n\njulia> norm(1:9)\n16.881943016134134\n\njulia> norm(hcat(v,v), 1) == norm(vcat(v,v), 1) != norm([v,v], 1)\ntrue\n\njulia> norm(hcat(v,v), 2) == norm(vcat(v,v), 2) == norm([v,v], 2)\ntrue\n\njulia> norm(hcat(v,v), Inf) == norm(vcat(v,v), Inf) != norm([v,v], Inf)\ntrue\n\n\n\n\n\nnorm(x::Number, p::Real=2)\n\nFor numbers, return left( x^p right)^1p.\n\nExamples\n\njulia> norm(2, 1)\n2.0\n\njulia> norm(-2, 1)\n2.0\n\njulia> norm(2, 2)\n2.0\n\njulia> norm(-2, 2)\n2.0\n\njulia> norm(2, Inf)\n2.0\n\njulia> norm(-2, Inf)\n2.0\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LinearAlgebra/#LinearAlgebra.opnorm","page":"Linear Algebra","title":"LinearAlgebra.opnorm","text":"opnorm(A::AbstractMatrix, p::Real=2)\n\nCompute the operator norm (or matrix norm) induced by the vector p-norm, where valid values of p are 1, 2, or Inf. (Note that for sparse matrices, p=2 is currently not implemented.) Use norm to compute the Frobenius norm.\n\nWhen p=1, the operator norm is the maximum absolute column sum of A:\n\nA_1 = max_1 j n sum_i=1^m a_ij \n\nwith a_ij the entries of A, and m and n its dimensions.\n\nWhen p=2, the operator norm is the spectral norm, equal to the largest singular value of A.\n\nWhen p=Inf, the operator norm is the maximum absolute row sum of A:\n\nA_infty = max_1 i m sum _j=1^n a_ij \n\nExamples\n\njulia> A = [1 -2 -3; 2 3 -1]\n2×3 Matrix{Int64}:\n 1 -2 -3\n 2 3 -1\n\njulia> opnorm(A, Inf)\n6.0\n\njulia> opnorm(A, 1)\n5.0\n\n\n\n\n\nopnorm(x::Number, p::Real=2)\n\nFor numbers, return left( x^p right)^1p. This is equivalent to norm.\n\n\n\n\n\nopnorm(A::Adjoint{<:Any,<:AbstracVector}, q::Real=2)\nopnorm(A::Transpose{<:Any,<:AbstracVector}, q::Real=2)\n\nFor Adjoint/Transpose-wrapped vectors, return the operator q-norm of A, which is equivalent to the p-norm with value p = q/(q-1). They coincide at p = q = 2. Use norm to compute the p norm of A as a vector.\n\nThe difference in norm between a vector space and its dual arises to preserve the relationship between duality and the dot product, and the result is consistent with the operator p-norm of a 1 × n matrix.\n\nExamples\n\njulia> v = [1; im];\n\njulia> vc = v';\n\njulia> opnorm(vc, 1)\n1.0\n\njulia> norm(vc, 1)\n2.0\n\njulia> norm(v, 1)\n2.0\n\njulia> opnorm(vc, 2)\n1.4142135623730951\n\njulia> norm(vc, 2)\n1.4142135623730951\n\njulia> norm(v, 2)\n1.4142135623730951\n\njulia> opnorm(vc, Inf)\n2.0\n\njulia> norm(vc, Inf)\n1.0\n\njulia> norm(v, Inf)\n1.0\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LinearAlgebra/#LinearAlgebra.normalize!","page":"Linear Algebra","title":"LinearAlgebra.normalize!","text":"normalize!(a::AbstractArray, p::Real=2)\n\nNormalize the array a in-place so that its p-norm equals unity, i.e. norm(a, p) == 1. See also normalize and norm.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LinearAlgebra/#LinearAlgebra.normalize","page":"Linear Algebra","title":"LinearAlgebra.normalize","text":"normalize(a::AbstractArray, p::Real=2)\n\nNormalize the array a so that its p-norm equals unity, i.e. norm(a, p) == 1. See also normalize! and norm.\n\nExamples\n\njulia> a = [1,2,4];\n\njulia> b = normalize(a)\n3-element Vector{Float64}:\n 0.2182178902359924\n 0.4364357804719848\n 0.8728715609439696\n\njulia> norm(b)\n1.0\n\njulia> c = normalize(a, 1)\n3-element Vector{Float64}:\n 0.14285714285714285\n 0.2857142857142857\n 0.5714285714285714\n\njulia> norm(c, 1)\n1.0\n\njulia> a = [1 2 4 ; 1 2 4]\n2×3 Matrix{Int64}:\n 1 2 4\n 1 2 4\n\njulia> norm(a)\n6.48074069840786\n\njulia> normalize(a)\n2×3 Matrix{Float64}:\n 0.154303 0.308607 0.617213\n 0.154303 0.308607 0.617213\n\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LinearAlgebra/#LinearAlgebra.cond","page":"Linear Algebra","title":"LinearAlgebra.cond","text":"cond(M, p::Real=2)\n\nCondition number of the matrix M, computed using the operator p-norm. Valid values for p are 1, 2 (default), or Inf.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LinearAlgebra/#LinearAlgebra.condskeel","page":"Linear Algebra","title":"LinearAlgebra.condskeel","text":"condskeel(M, [x, p::Real=Inf])\n\nkappa_S(M p) = leftVert leftvert M rightvert leftvert M^-1 rightvert rightVert_p \nkappa_S(M x p) = fracleftVert leftvert M rightvert leftvert M^-1 rightvert leftvert x rightvert rightVert_pleft Vert x right Vert_p\n\nSkeel condition number kappa_S of the matrix M, optionally with respect to the vector x, as computed using the operator p-norm. leftvert M rightvert denotes the matrix of (entry wise) absolute values of M; leftvert M rightvert_ij = leftvert M_ij rightvert. Valid values for p are 1, 2 and Inf (default).\n\nThis quantity is also known in the literature as the Bauer condition number, relative condition number, or componentwise relative condition number.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LinearAlgebra/#LinearAlgebra.tr","page":"Linear Algebra","title":"LinearAlgebra.tr","text":"tr(M)\n\nMatrix trace. Sums the diagonal elements of M.\n\nExamples\n\njulia> A = [1 2; 3 4]\n2×2 Matrix{Int64}:\n 1 2\n 3 4\n\njulia> tr(A)\n5\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LinearAlgebra/#LinearAlgebra.det","page":"Linear Algebra","title":"LinearAlgebra.det","text":"det(M)\n\nMatrix determinant.\n\nSee also: logdet and logabsdet.\n\nExamples\n\njulia> M = [1 0; 2 2]\n2×2 Matrix{Int64}:\n 1 0\n 2 2\n\njulia> det(M)\n2.0\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LinearAlgebra/#LinearAlgebra.logdet","page":"Linear Algebra","title":"LinearAlgebra.logdet","text":"logdet(M)\n\nLog of matrix determinant. Equivalent to log(det(M)), but may provide increased accuracy and/or speed.\n\nExamples\n\njulia> M = [1 0; 2 2]\n2×2 Matrix{Int64}:\n 1 0\n 2 2\n\njulia> logdet(M)\n0.6931471805599453\n\njulia> logdet(Matrix(I, 3, 3))\n0.0\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LinearAlgebra/#LinearAlgebra.logabsdet","page":"Linear Algebra","title":"LinearAlgebra.logabsdet","text":"logabsdet(M)\n\nLog of absolute value of matrix determinant. Equivalent to (log(abs(det(M))), sign(det(M))), but may provide increased accuracy and/or speed.\n\nExamples\n\njulia> A = [-1. 0.; 0. 1.]\n2×2 Matrix{Float64}:\n -1.0 0.0\n 0.0 1.0\n\njulia> det(A)\n-1.0\n\njulia> logabsdet(A)\n(0.0, -1.0)\n\njulia> B = [2. 0.; 0. 1.]\n2×2 Matrix{Float64}:\n 2.0 0.0\n 0.0 1.0\n\njulia> det(B)\n2.0\n\njulia> logabsdet(B)\n(0.6931471805599453, 1.0)\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LinearAlgebra/#Base.inv-Tuple{AbstractMatrix}","page":"Linear Algebra","title":"Base.inv","text":"inv(M)\n\nMatrix inverse. Computes matrix N such that M * N = I, where I is the identity matrix. Computed by solving the left-division N = M \\ I.\n\nExamples\n\njulia> M = [2 5; 1 3]\n2×2 Matrix{Int64}:\n 2 5\n 1 3\n\njulia> N = inv(M)\n2×2 Matrix{Float64}:\n 3.0 -5.0\n -1.0 2.0\n\njulia> M*N == N*M == Matrix(I, 2, 2)\ntrue\n\n\n\n\n\n","category":"method"},{"location":"stdlib/LinearAlgebra/#LinearAlgebra.pinv","page":"Linear Algebra","title":"LinearAlgebra.pinv","text":"pinv(M; atol::Real=0, rtol::Real=atol>0 ? 0 : n*ϵ)\npinv(M, rtol::Real) = pinv(M; rtol=rtol) # to be deprecated in Julia 2.0\n\nComputes the Moore-Penrose pseudoinverse.\n\nFor matrices M with floating point elements, it is convenient to compute the pseudoinverse by inverting only singular values greater than max(atol, rtol*σ₁) where σ₁ is the largest singular value of M.\n\nThe optimal choice of absolute (atol) and relative tolerance (rtol) varies both with the value of M and the intended application of the pseudoinverse. The default relative tolerance is n*ϵ, where n is the size of the smallest dimension of M, and ϵ is the eps of the element type of M.\n\nFor inverting dense ill-conditioned matrices in a least-squares sense, rtol = sqrt(eps(real(float(one(eltype(M)))))) is recommended.\n\nFor more information, see [issue8859], [B96], [S84], [KY88].\n\nExamples\n\njulia> M = [1.5 1.3; 1.2 1.9]\n2×2 Matrix{Float64}:\n 1.5 1.3\n 1.2 1.9\n\njulia> N = pinv(M)\n2×2 Matrix{Float64}:\n 1.47287 -1.00775\n -0.930233 1.16279\n\njulia> M * N\n2×2 Matrix{Float64}:\n 1.0 -2.22045e-16\n 4.44089e-16 1.0\n\n[issue8859]: Issue 8859, \"Fix least squares\", https://github.com/JuliaLang/julia/pull/8859\n\n[B96]: Åke Björck, \"Numerical Methods for Least Squares Problems\", SIAM Press, Philadelphia, 1996, \"Other Titles in Applied Mathematics\", Vol. 51. doi:10.1137/1.9781611971484\n\n[S84]: G. W. Stewart, \"Rank Degeneracy\", SIAM Journal on Scientific and Statistical Computing, 5(2), 1984, 403-413. doi:10.1137/0905030\n\n[KY88]: Konstantinos Konstantinides and Kung Yao, \"Statistical analysis of effective singular values in matrix rank determination\", IEEE Transactions on Acoustics, Speech and Signal Processing, 36(5), 1988, 757-763. doi:10.1109/29.1585\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LinearAlgebra/#LinearAlgebra.nullspace","page":"Linear Algebra","title":"LinearAlgebra.nullspace","text":"nullspace(M; atol::Real=0, rtol::Real=atol>0 ? 0 : n*ϵ)\nnullspace(M, rtol::Real) = nullspace(M; rtol=rtol) # to be deprecated in Julia 2.0\n\nComputes a basis for the nullspace of M by including the singular vectors of M whose singular values have magnitudes smaller than max(atol, rtol*σ₁), where σ₁ is M's largest singular value.\n\nBy default, the relative tolerance rtol is n*ϵ, where n is the size of the smallest dimension of M, and ϵ is the eps of the element type of M.\n\nExamples\n\njulia> M = [1 0 0; 0 1 0; 0 0 0]\n3×3 Matrix{Int64}:\n 1 0 0\n 0 1 0\n 0 0 0\n\njulia> nullspace(M)\n3×1 Matrix{Float64}:\n 0.0\n 0.0\n 1.0\n\njulia> nullspace(M, rtol=3)\n3×3 Matrix{Float64}:\n 0.0 1.0 0.0\n 1.0 0.0 0.0\n 0.0 0.0 1.0\n\njulia> nullspace(M, atol=0.95)\n3×1 Matrix{Float64}:\n 0.0\n 0.0\n 1.0\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LinearAlgebra/#Base.kron","page":"Linear Algebra","title":"Base.kron","text":"kron(A, B)\n\nKronecker tensor product of two vectors or two matrices.\n\nFor real vectors v and w, the Kronecker product is related to the outer product by kron(v,w) == vec(w * transpose(v)) or w * transpose(v) == reshape(kron(v,w), (length(w), length(v))). Note how the ordering of v and w differs on the left and right of these expressions (due to column-major storage). For complex vectors, the outer product w * v' also differs by conjugation of v.\n\nExamples\n\njulia> A = [1 2; 3 4]\n2×2 Matrix{Int64}:\n 1 2\n 3 4\n\njulia> B = [im 1; 1 -im]\n2×2 Matrix{Complex{Int64}}:\n 0+1im 1+0im\n 1+0im 0-1im\n\njulia> kron(A, B)\n4×4 Matrix{Complex{Int64}}:\n 0+1im 1+0im 0+2im 2+0im\n 1+0im 0-1im 2+0im 0-2im\n 0+3im 3+0im 0+4im 4+0im\n 3+0im 0-3im 4+0im 0-4im\n\njulia> v = [1, 2]; w = [3, 4, 5];\n\njulia> w*transpose(v)\n3×2 Matrix{Int64}:\n 3 6\n 4 8\n 5 10\n\njulia> reshape(kron(v,w), (length(w), length(v)))\n3×2 Matrix{Int64}:\n 3 6\n 4 8\n 5 10\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LinearAlgebra/#Base.kron!","page":"Linear Algebra","title":"Base.kron!","text":"kron!(C, A, B)\n\nkron! is the in-place version of kron. Computes kron(A, B) and stores the result in C overwriting the existing value of C.\n\ntip: Tip\nBounds checking can be disabled by @inbounds, but you need to take care of the shape of C, A, B yourself.\n\ncompat: Julia 1.6\nThis function requires Julia 1.6 or later.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LinearAlgebra/#Base.exp-Tuple{StridedMatrix{var\"#s387\"} where var\"#s387\"<:Union{Float32, Float64, ComplexF32, ComplexF64}}","page":"Linear Algebra","title":"Base.exp","text":"exp(A::AbstractMatrix)\n\nCompute the matrix exponential of A, defined by\n\ne^A = sum_n=0^infty fracA^nn\n\nFor symmetric or Hermitian A, an eigendecomposition (eigen) is used, otherwise the scaling and squaring algorithm (see [H05]) is chosen.\n\n[H05]: Nicholas J. Higham, \"The squaring and scaling method for the matrix exponential revisited\", SIAM Journal on Matrix Analysis and Applications, 26(4), 2005, 1179-1193. doi:10.1137/090768539\n\nExamples\n\njulia> A = Matrix(1.0I, 2, 2)\n2×2 Matrix{Float64}:\n 1.0 0.0\n 0.0 1.0\n\njulia> exp(A)\n2×2 Matrix{Float64}:\n 2.71828 0.0\n 0.0 2.71828\n\n\n\n\n\n","category":"method"},{"location":"stdlib/LinearAlgebra/#Base.cis-Tuple{AbstractMatrix}","page":"Linear Algebra","title":"Base.cis","text":"cis(A::AbstractMatrix)\n\nMore efficient method for exp(im*A) of square matrix A (especially if A is Hermitian or real-Symmetric).\n\nSee also cispi, sincos, exp.\n\ncompat: Julia 1.7\nSupport for using cis with matrices was added in Julia 1.7.\n\nExamples\n\njulia> cis([π 0; 0 π]) ≈ -I\ntrue\n\n\n\n\n\n","category":"method"},{"location":"stdlib/LinearAlgebra/#Base.:^-Tuple{AbstractMatrix, Number}","page":"Linear Algebra","title":"Base.:^","text":"^(A::AbstractMatrix, p::Number)\n\nMatrix power, equivalent to exp(plog(A))\n\nExamples\n\njulia> [1 2; 0 3]^3\n2×2 Matrix{Int64}:\n 1 26\n 0 27\n\n\n\n\n\n","category":"method"},{"location":"stdlib/LinearAlgebra/#Base.:^-Tuple{Number, AbstractMatrix}","page":"Linear Algebra","title":"Base.:^","text":"^(b::Number, A::AbstractMatrix)\n\nMatrix exponential, equivalent to exp(log(b)A).\n\ncompat: Julia 1.1\nSupport for raising Irrational numbers (like ℯ) to a matrix was added in Julia 1.1.\n\nExamples\n\njulia> 2^[1 2; 0 3]\n2×2 Matrix{Float64}:\n 2.0 6.0\n 0.0 8.0\n\njulia> ℯ^[1 2; 0 3]\n2×2 Matrix{Float64}:\n 2.71828 17.3673\n 0.0 20.0855\n\n\n\n\n\n","category":"method"},{"location":"stdlib/LinearAlgebra/#Base.log-Tuple{StridedMatrix{T} where T}","page":"Linear Algebra","title":"Base.log","text":"log(A::StridedMatrix)\n\nIf A has no negative real eigenvalue, compute the principal matrix logarithm of A, i.e. the unique matrix X such that e^X = A and -pi Im(lambda) pi for all the eigenvalues lambda of X. If A has nonpositive eigenvalues, a nonprincipal matrix function is returned whenever possible.\n\nIf A is symmetric or Hermitian, its eigendecomposition (eigen) is used, if A is triangular an improved version of the inverse scaling and squaring method is employed (see [AH12] and [AHR13]). If A is real with no negative eigenvalues, then the real Schur form is computed. Otherwise, the complex Schur form is computed. Then the upper (quasi-)triangular algorithm in [AHR13] is used on the upper (quasi-)triangular factor.\n\n[AH12]: Awad H. Al-Mohy and Nicholas J. Higham, \"Improved inverse scaling and squaring algorithms for the matrix logarithm\", SIAM Journal on Scientific Computing, 34(4), 2012, C153-C169. doi:10.1137/110852553\n\n[AHR13]: Awad H. Al-Mohy, Nicholas J. Higham and Samuel D. Relton, \"Computing the Fréchet derivative of the matrix logarithm and estimating the condition number\", SIAM Journal on Scientific Computing, 35(4), 2013, C394-C410. doi:10.1137/120885991\n\nExamples\n\njulia> A = Matrix(2.7182818*I, 2, 2)\n2×2 Matrix{Float64}:\n 2.71828 0.0\n 0.0 2.71828\n\njulia> log(A)\n2×2 Matrix{Float64}:\n 1.0 0.0\n 0.0 1.0\n\n\n\n\n\n","category":"method"},{"location":"stdlib/LinearAlgebra/#Base.sqrt-Tuple{StridedMatrix{var\"#s387\"} where var\"#s387\"<:Real}","page":"Linear Algebra","title":"Base.sqrt","text":"sqrt(x)\n\nReturn sqrtx. Throws DomainError for negative Real arguments. Use complex negative arguments instead. The prefix operator √ is equivalent to sqrt.\n\nSee also: hypot.\n\nExamples\n\njulia> sqrt(big(81))\n9.0\n\njulia> sqrt(big(-81))\nERROR: DomainError with -81.0:\nNaN result for non-NaN input.\nStacktrace:\n [1] sqrt(::BigFloat) at ./mpfr.jl:501\n[...]\n\njulia> sqrt(big(complex(-81)))\n0.0 + 9.0im\n\njulia> .√(1:4)\n4-element Vector{Float64}:\n 1.0\n 1.4142135623730951\n 1.7320508075688772\n 2.0\n\n\n\n\n\nsqrt(A::AbstractMatrix)\n\nIf A has no negative real eigenvalues, compute the principal matrix square root of A, that is the unique matrix X with eigenvalues having positive real part such that X^2 = A. Otherwise, a nonprincipal square root is returned.\n\nIf A is real-symmetric or Hermitian, its eigendecomposition (eigen) is used to compute the square root. For such matrices, eigenvalues λ that appear to be slightly negative due to roundoff errors are treated as if they were zero. More precisely, matrices with all eigenvalues ≥ -rtol*(max |λ|) are treated as semidefinite (yielding a Hermitian square root), with negative eigenvalues taken to be zero. rtol is a keyword argument to sqrt (in the Hermitian/real-symmetric case only) that defaults to machine precision scaled by size(A,1).\n\nOtherwise, the square root is determined by means of the Björck-Hammarling method [BH83], which computes the complex Schur form (schur) and then the complex square root of the triangular factor. If a real square root exists, then an extension of this method [H87] that computes the real Schur form and then the real square root of the quasi-triangular factor is instead used.\n\n[BH83]: Åke Björck and Sven Hammarling, \"A Schur method for the square root of a matrix\", Linear Algebra and its Applications, 52-53, 1983, 127-140. doi:10.1016/0024-3795(83)80010-X\n\n[H87]: Nicholas J. Higham, \"Computing real square roots of a real matrix\", Linear Algebra and its Applications, 88-89, 1987, 405-430. doi:10.1016/0024-3795(87)90118-2\n\nExamples\n\njulia> A = [4 0; 0 4]\n2×2 Matrix{Int64}:\n 4 0\n 0 4\n\njulia> sqrt(A)\n2×2 Matrix{Float64}:\n 2.0 0.0\n 0.0 2.0\n\n\n\n\n\n","category":"method"},{"location":"stdlib/LinearAlgebra/#Base.cos-Tuple{StridedMatrix{var\"#s387\"} where var\"#s387\"<:Real}","page":"Linear Algebra","title":"Base.cos","text":"cos(A::AbstractMatrix)\n\nCompute the matrix cosine of a square matrix A.\n\nIf A is symmetric or Hermitian, its eigendecomposition (eigen) is used to compute the cosine. Otherwise, the cosine is determined by calling exp.\n\nExamples\n\njulia> cos(fill(1.0, (2,2)))\n2×2 Matrix{Float64}:\n 0.291927 -0.708073\n -0.708073 0.291927\n\n\n\n\n\n","category":"method"},{"location":"stdlib/LinearAlgebra/#Base.sin-Tuple{StridedMatrix{var\"#s387\"} where var\"#s387\"<:Real}","page":"Linear Algebra","title":"Base.sin","text":"sin(A::AbstractMatrix)\n\nCompute the matrix sine of a square matrix A.\n\nIf A is symmetric or Hermitian, its eigendecomposition (eigen) is used to compute the sine. Otherwise, the sine is determined by calling exp.\n\nExamples\n\njulia> sin(fill(1.0, (2,2)))\n2×2 Matrix{Float64}:\n 0.454649 0.454649\n 0.454649 0.454649\n\n\n\n\n\n","category":"method"},{"location":"stdlib/LinearAlgebra/#Base.Math.sincos-Tuple{StridedMatrix{var\"#s387\"} where var\"#s387\"<:Real}","page":"Linear Algebra","title":"Base.Math.sincos","text":"sincos(A::AbstractMatrix)\n\nCompute the matrix sine and cosine of a square matrix A.\n\nExamples\n\njulia> S, C = sincos(fill(1.0, (2,2)));\n\njulia> S\n2×2 Matrix{Float64}:\n 0.454649 0.454649\n 0.454649 0.454649\n\njulia> C\n2×2 Matrix{Float64}:\n 0.291927 -0.708073\n -0.708073 0.291927\n\n\n\n\n\n","category":"method"},{"location":"stdlib/LinearAlgebra/#Base.tan-Tuple{StridedMatrix{var\"#s387\"} where var\"#s387\"<:Real}","page":"Linear Algebra","title":"Base.tan","text":"tan(A::AbstractMatrix)\n\nCompute the matrix tangent of a square matrix A.\n\nIf A is symmetric or Hermitian, its eigendecomposition (eigen) is used to compute the tangent. Otherwise, the tangent is determined by calling exp.\n\nExamples\n\njulia> tan(fill(1.0, (2,2)))\n2×2 Matrix{Float64}:\n -1.09252 -1.09252\n -1.09252 -1.09252\n\n\n\n\n\n","category":"method"},{"location":"stdlib/LinearAlgebra/#Base.Math.sec-Tuple{StridedMatrix{T} where T}","page":"Linear Algebra","title":"Base.Math.sec","text":"sec(A::AbstractMatrix)\n\nCompute the matrix secant of a square matrix A.\n\n\n\n\n\n","category":"method"},{"location":"stdlib/LinearAlgebra/#Base.Math.csc-Tuple{StridedMatrix{T} where T}","page":"Linear Algebra","title":"Base.Math.csc","text":"csc(A::AbstractMatrix)\n\nCompute the matrix cosecant of a square matrix A.\n\n\n\n\n\n","category":"method"},{"location":"stdlib/LinearAlgebra/#Base.Math.cot-Tuple{StridedMatrix{T} where T}","page":"Linear Algebra","title":"Base.Math.cot","text":"cot(A::AbstractMatrix)\n\nCompute the matrix cotangent of a square matrix A.\n\n\n\n\n\n","category":"method"},{"location":"stdlib/LinearAlgebra/#Base.cosh-Tuple{StridedMatrix{T} where T}","page":"Linear Algebra","title":"Base.cosh","text":"cosh(A::AbstractMatrix)\n\nCompute the matrix hyperbolic cosine of a square matrix A.\n\n\n\n\n\n","category":"method"},{"location":"stdlib/LinearAlgebra/#Base.sinh-Tuple{StridedMatrix{T} where T}","page":"Linear Algebra","title":"Base.sinh","text":"sinh(A::AbstractMatrix)\n\nCompute the matrix hyperbolic sine of a square matrix A.\n\n\n\n\n\n","category":"method"},{"location":"stdlib/LinearAlgebra/#Base.tanh-Tuple{StridedMatrix{T} where T}","page":"Linear Algebra","title":"Base.tanh","text":"tanh(A::AbstractMatrix)\n\nCompute the matrix hyperbolic tangent of a square matrix A.\n\n\n\n\n\n","category":"method"},{"location":"stdlib/LinearAlgebra/#Base.Math.sech-Tuple{StridedMatrix{T} where T}","page":"Linear Algebra","title":"Base.Math.sech","text":"sech(A::AbstractMatrix)\n\nCompute the matrix hyperbolic secant of square matrix A.\n\n\n\n\n\n","category":"method"},{"location":"stdlib/LinearAlgebra/#Base.Math.csch-Tuple{StridedMatrix{T} where T}","page":"Linear Algebra","title":"Base.Math.csch","text":"csch(A::AbstractMatrix)\n\nCompute the matrix hyperbolic cosecant of square matrix A.\n\n\n\n\n\n","category":"method"},{"location":"stdlib/LinearAlgebra/#Base.Math.coth-Tuple{StridedMatrix{T} where T}","page":"Linear Algebra","title":"Base.Math.coth","text":"coth(A::AbstractMatrix)\n\nCompute the matrix hyperbolic cotangent of square matrix A.\n\n\n\n\n\n","category":"method"},{"location":"stdlib/LinearAlgebra/#Base.acos-Tuple{StridedMatrix{T} where T}","page":"Linear Algebra","title":"Base.acos","text":"acos(A::AbstractMatrix)\n\nCompute the inverse matrix cosine of a square matrix A.\n\nIf A is symmetric or Hermitian, its eigendecomposition (eigen) is used to compute the inverse cosine. Otherwise, the inverse cosine is determined by using log and sqrt. For the theory and logarithmic formulas used to compute this function, see [AH16_1].\n\n[AH16_1]: Mary Aprahamian and Nicholas J. Higham, \"Matrix Inverse Trigonometric and Inverse Hyperbolic Functions: Theory and Algorithms\", MIMS EPrint: 2016.4. https://doi.org/10.1137/16M1057577\n\nExamples\n\njulia> acos(cos([0.5 0.1; -0.2 0.3]))\n2×2 Matrix{ComplexF64}:\n 0.5-8.32667e-17im 0.1+0.0im\n -0.2+2.63678e-16im 0.3-3.46945e-16im\n\n\n\n\n\n","category":"method"},{"location":"stdlib/LinearAlgebra/#Base.asin-Tuple{StridedMatrix{T} where T}","page":"Linear Algebra","title":"Base.asin","text":"asin(A::AbstractMatrix)\n\nCompute the inverse matrix sine of a square matrix A.\n\nIf A is symmetric or Hermitian, its eigendecomposition (eigen) is used to compute the inverse sine. Otherwise, the inverse sine is determined by using log and sqrt. For the theory and logarithmic formulas used to compute this function, see [AH16_2].\n\n[AH16_2]: Mary Aprahamian and Nicholas J. Higham, \"Matrix Inverse Trigonometric and Inverse Hyperbolic Functions: Theory and Algorithms\", MIMS EPrint: 2016.4. https://doi.org/10.1137/16M1057577\n\nExamples\n\njulia> asin(sin([0.5 0.1; -0.2 0.3]))\n2×2 Matrix{ComplexF64}:\n 0.5-4.16334e-17im 0.1-5.55112e-17im\n -0.2+9.71445e-17im 0.3-1.249e-16im\n\n\n\n\n\n","category":"method"},{"location":"stdlib/LinearAlgebra/#Base.atan-Tuple{StridedMatrix{T} where T}","page":"Linear Algebra","title":"Base.atan","text":"atan(A::AbstractMatrix)\n\nCompute the inverse matrix tangent of a square matrix A.\n\nIf A is symmetric or Hermitian, its eigendecomposition (eigen) is used to compute the inverse tangent. Otherwise, the inverse tangent is determined by using log. For the theory and logarithmic formulas used to compute this function, see [AH16_3].\n\n[AH16_3]: Mary Aprahamian and Nicholas J. Higham, \"Matrix Inverse Trigonometric and Inverse Hyperbolic Functions: Theory and Algorithms\", MIMS EPrint: 2016.4. https://doi.org/10.1137/16M1057577\n\nExamples\n\njulia> atan(tan([0.5 0.1; -0.2 0.3]))\n2×2 Matrix{ComplexF64}:\n 0.5+1.38778e-17im 0.1-2.77556e-17im\n -0.2+6.93889e-17im 0.3-4.16334e-17im\n\n\n\n\n\n","category":"method"},{"location":"stdlib/LinearAlgebra/#Base.Math.asec-Tuple{StridedMatrix{T} where T}","page":"Linear Algebra","title":"Base.Math.asec","text":"asec(A::AbstractMatrix)\n\nCompute the inverse matrix secant of A. \n\n\n\n\n\n","category":"method"},{"location":"stdlib/LinearAlgebra/#Base.Math.acsc-Tuple{StridedMatrix{T} where T}","page":"Linear Algebra","title":"Base.Math.acsc","text":"acsc(A::AbstractMatrix)\n\nCompute the inverse matrix cosecant of A. \n\n\n\n\n\n","category":"method"},{"location":"stdlib/LinearAlgebra/#Base.Math.acot-Tuple{StridedMatrix{T} where T}","page":"Linear Algebra","title":"Base.Math.acot","text":"acot(A::AbstractMatrix)\n\nCompute the inverse matrix cotangent of A. \n\n\n\n\n\n","category":"method"},{"location":"stdlib/LinearAlgebra/#Base.acosh-Tuple{StridedMatrix{T} where T}","page":"Linear Algebra","title":"Base.acosh","text":"acosh(A::AbstractMatrix)\n\nCompute the inverse hyperbolic matrix cosine of a square matrix A. For the theory and logarithmic formulas used to compute this function, see [AH16_4].\n\n[AH16_4]: Mary Aprahamian and Nicholas J. Higham, \"Matrix Inverse Trigonometric and Inverse Hyperbolic Functions: Theory and Algorithms\", MIMS EPrint: 2016.4. https://doi.org/10.1137/16M1057577\n\n\n\n\n\n","category":"method"},{"location":"stdlib/LinearAlgebra/#Base.asinh-Tuple{StridedMatrix{T} where T}","page":"Linear Algebra","title":"Base.asinh","text":"asinh(A::AbstractMatrix)\n\nCompute the inverse hyperbolic matrix sine of a square matrix A. For the theory and logarithmic formulas used to compute this function, see [AH16_5].\n\n[AH16_5]: Mary Aprahamian and Nicholas J. Higham, \"Matrix Inverse Trigonometric and Inverse Hyperbolic Functions: Theory and Algorithms\", MIMS EPrint: 2016.4. https://doi.org/10.1137/16M1057577\n\n\n\n\n\n","category":"method"},{"location":"stdlib/LinearAlgebra/#Base.atanh-Tuple{StridedMatrix{T} where T}","page":"Linear Algebra","title":"Base.atanh","text":"atanh(A::AbstractMatrix)\n\nCompute the inverse hyperbolic matrix tangent of a square matrix A. For the theory and logarithmic formulas used to compute this function, see [AH16_6].\n\n[AH16_6]: Mary Aprahamian and Nicholas J. Higham, \"Matrix Inverse Trigonometric and Inverse Hyperbolic Functions: Theory and Algorithms\", MIMS EPrint: 2016.4. https://doi.org/10.1137/16M1057577\n\n\n\n\n\n","category":"method"},{"location":"stdlib/LinearAlgebra/#Base.Math.asech-Tuple{StridedMatrix{T} where T}","page":"Linear Algebra","title":"Base.Math.asech","text":"asech(A::AbstractMatrix)\n\nCompute the inverse matrix hyperbolic secant of A. \n\n\n\n\n\n","category":"method"},{"location":"stdlib/LinearAlgebra/#Base.Math.acsch-Tuple{StridedMatrix{T} where T}","page":"Linear Algebra","title":"Base.Math.acsch","text":"acsch(A::AbstractMatrix)\n\nCompute the inverse matrix hyperbolic cosecant of A. \n\n\n\n\n\n","category":"method"},{"location":"stdlib/LinearAlgebra/#Base.Math.acoth-Tuple{StridedMatrix{T} where T}","page":"Linear Algebra","title":"Base.Math.acoth","text":"acoth(A::AbstractMatrix)\n\nCompute the inverse matrix hyperbolic cotangent of A. \n\n\n\n\n\n","category":"method"},{"location":"stdlib/LinearAlgebra/#LinearAlgebra.lyap","page":"Linear Algebra","title":"LinearAlgebra.lyap","text":"lyap(A, C)\n\nComputes the solution X to the continuous Lyapunov equation AX + XA' + C = 0, where no eigenvalue of A has a zero real part and no two eigenvalues are negative complex conjugates of each other.\n\nExamples\n\njulia> A = [3. 4.; 5. 6]\n2×2 Matrix{Float64}:\n 3.0 4.0\n 5.0 6.0\n\njulia> B = [1. 1.; 1. 2.]\n2×2 Matrix{Float64}:\n 1.0 1.0\n 1.0 2.0\n\njulia> X = lyap(A, B)\n2×2 Matrix{Float64}:\n 0.5 -0.5\n -0.5 0.25\n\njulia> A*X + X*A' + B\n2×2 Matrix{Float64}:\n 0.0 6.66134e-16\n 6.66134e-16 8.88178e-16\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LinearAlgebra/#LinearAlgebra.sylvester","page":"Linear Algebra","title":"LinearAlgebra.sylvester","text":"sylvester(A, B, C)\n\nComputes the solution X to the Sylvester equation AX + XB + C = 0, where A, B and C have compatible dimensions and A and -B have no eigenvalues with equal real part.\n\nExamples\n\njulia> A = [3. 4.; 5. 6]\n2×2 Matrix{Float64}:\n 3.0 4.0\n 5.0 6.0\n\njulia> B = [1. 1.; 1. 2.]\n2×2 Matrix{Float64}:\n 1.0 1.0\n 1.0 2.0\n\njulia> C = [1. 2.; -2. 1]\n2×2 Matrix{Float64}:\n 1.0 2.0\n -2.0 1.0\n\njulia> X = sylvester(A, B, C)\n2×2 Matrix{Float64}:\n -4.46667 1.93333\n 3.73333 -1.8\n\njulia> A*X + X*B + C\n2×2 Matrix{Float64}:\n 2.66454e-15 1.77636e-15\n -3.77476e-15 4.44089e-16\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LinearAlgebra/#LinearAlgebra.issuccess","page":"Linear Algebra","title":"LinearAlgebra.issuccess","text":"issuccess(F::Factorization)\n\nTest that a factorization of a matrix succeeded.\n\ncompat: Julia 1.6\nissuccess(::CholeskyPivoted) requires Julia 1.6 or later.\n\njulia> F = cholesky([1 0; 0 1]);\n\njulia> LinearAlgebra.issuccess(F)\ntrue\n\njulia> F = lu([1 0; 0 0]; check = false);\n\njulia> LinearAlgebra.issuccess(F)\nfalse\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LinearAlgebra/#LinearAlgebra.issymmetric","page":"Linear Algebra","title":"LinearAlgebra.issymmetric","text":"issymmetric(A) -> Bool\n\nTest whether a matrix is symmetric.\n\nExamples\n\njulia> a = [1 2; 2 -1]\n2×2 Matrix{Int64}:\n 1 2\n 2 -1\n\njulia> issymmetric(a)\ntrue\n\njulia> b = [1 im; -im 1]\n2×2 Matrix{Complex{Int64}}:\n 1+0im 0+1im\n 0-1im 1+0im\n\njulia> issymmetric(b)\nfalse\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LinearAlgebra/#LinearAlgebra.isposdef","page":"Linear Algebra","title":"LinearAlgebra.isposdef","text":"isposdef(A) -> Bool\n\nTest whether a matrix is positive definite (and Hermitian) by trying to perform a Cholesky factorization of A.\n\nSee also isposdef!, cholesky.\n\nExamples\n\njulia> A = [1 2; 2 50]\n2×2 Matrix{Int64}:\n 1 2\n 2 50\n\njulia> isposdef(A)\ntrue\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LinearAlgebra/#LinearAlgebra.isposdef!","page":"Linear Algebra","title":"LinearAlgebra.isposdef!","text":"isposdef!(A) -> Bool\n\nTest whether a matrix is positive definite (and Hermitian) by trying to perform a Cholesky factorization of A, overwriting A in the process. See also isposdef.\n\nExamples\n\njulia> A = [1. 2.; 2. 50.];\n\njulia> isposdef!(A)\ntrue\n\njulia> A\n2×2 Matrix{Float64}:\n 1.0 2.0\n 2.0 6.78233\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LinearAlgebra/#LinearAlgebra.istril","page":"Linear Algebra","title":"LinearAlgebra.istril","text":"istril(A::AbstractMatrix, k::Integer = 0) -> Bool\n\nTest whether A is lower triangular starting from the kth superdiagonal.\n\nExamples\n\njulia> a = [1 2; 2 -1]\n2×2 Matrix{Int64}:\n 1 2\n 2 -1\n\njulia> istril(a)\nfalse\n\njulia> istril(a, 1)\ntrue\n\njulia> b = [1 0; -im -1]\n2×2 Matrix{Complex{Int64}}:\n 1+0im 0+0im\n 0-1im -1+0im\n\njulia> istril(b)\ntrue\n\njulia> istril(b, -1)\nfalse\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LinearAlgebra/#LinearAlgebra.istriu","page":"Linear Algebra","title":"LinearAlgebra.istriu","text":"istriu(A::AbstractMatrix, k::Integer = 0) -> Bool\n\nTest whether A is upper triangular starting from the kth superdiagonal.\n\nExamples\n\njulia> a = [1 2; 2 -1]\n2×2 Matrix{Int64}:\n 1 2\n 2 -1\n\njulia> istriu(a)\nfalse\n\njulia> istriu(a, -1)\ntrue\n\njulia> b = [1 im; 0 -1]\n2×2 Matrix{Complex{Int64}}:\n 1+0im 0+1im\n 0+0im -1+0im\n\njulia> istriu(b)\ntrue\n\njulia> istriu(b, 1)\nfalse\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LinearAlgebra/#LinearAlgebra.isdiag","page":"Linear Algebra","title":"LinearAlgebra.isdiag","text":"isdiag(A) -> Bool\n\nTest whether a matrix is diagonal.\n\nExamples\n\njulia> a = [1 2; 2 -1]\n2×2 Matrix{Int64}:\n 1 2\n 2 -1\n\njulia> isdiag(a)\nfalse\n\njulia> b = [im 0; 0 -im]\n2×2 Matrix{Complex{Int64}}:\n 0+1im 0+0im\n 0+0im 0-1im\n\njulia> isdiag(b)\ntrue\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LinearAlgebra/#LinearAlgebra.ishermitian","page":"Linear Algebra","title":"LinearAlgebra.ishermitian","text":"ishermitian(A) -> Bool\n\nTest whether a matrix is Hermitian.\n\nExamples\n\njulia> a = [1 2; 2 -1]\n2×2 Matrix{Int64}:\n 1 2\n 2 -1\n\njulia> ishermitian(a)\ntrue\n\njulia> b = [1 im; -im 1]\n2×2 Matrix{Complex{Int64}}:\n 1+0im 0+1im\n 0-1im 1+0im\n\njulia> ishermitian(b)\ntrue\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LinearAlgebra/#Base.transpose","page":"Linear Algebra","title":"Base.transpose","text":"transpose(A)\n\nLazy transpose. Mutating the returned object should appropriately mutate A. Often, but not always, yields Transpose(A), where Transpose is a lazy transpose wrapper. Note that this operation is recursive.\n\nThis operation is intended for linear algebra usage - for general data manipulation see permutedims, which is non-recursive.\n\nExamples\n\njulia> A = [3+2im 9+2im; 8+7im 4+6im]\n2×2 Matrix{Complex{Int64}}:\n 3+2im 9+2im\n 8+7im 4+6im\n\njulia> transpose(A)\n2×2 transpose(::Matrix{Complex{Int64}}) with eltype Complex{Int64}:\n 3+2im 8+7im\n 9+2im 4+6im\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LinearAlgebra/#LinearAlgebra.transpose!","page":"Linear Algebra","title":"LinearAlgebra.transpose!","text":"transpose!(dest,src)\n\nTranspose array src and store the result in the preallocated array dest, which should have a size corresponding to (size(src,2),size(src,1)). No in-place transposition is supported and unexpected results will happen if src and dest have overlapping memory regions.\n\nExamples\n\njulia> A = [3+2im 9+2im; 8+7im 4+6im]\n2×2 Matrix{Complex{Int64}}:\n 3+2im 9+2im\n 8+7im 4+6im\n\njulia> B = zeros(Complex{Int64}, 2, 2)\n2×2 Matrix{Complex{Int64}}:\n 0+0im 0+0im\n 0+0im 0+0im\n\njulia> transpose!(B, A);\n\njulia> B\n2×2 Matrix{Complex{Int64}}:\n 3+2im 8+7im\n 9+2im 4+6im\n\njulia> A\n2×2 Matrix{Complex{Int64}}:\n 3+2im 9+2im\n 8+7im 4+6im\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LinearAlgebra/#LinearAlgebra.Transpose","page":"Linear Algebra","title":"LinearAlgebra.Transpose","text":"Transpose\n\nLazy wrapper type for a transpose view of the underlying linear algebra object, usually an AbstractVector/AbstractMatrix, but also some Factorization, for instance. Usually, the Transpose constructor should not be called directly, use transpose instead. To materialize the view use copy.\n\nThis type is intended for linear algebra usage - for general data manipulation see permutedims.\n\nExamples\n\njulia> A = [3+2im 9+2im; 8+7im 4+6im]\n2×2 Matrix{Complex{Int64}}:\n 3+2im 9+2im\n 8+7im 4+6im\n\njulia> transpose(A)\n2×2 transpose(::Matrix{Complex{Int64}}) with eltype Complex{Int64}:\n 3+2im 8+7im\n 9+2im 4+6im\n\n\n\n\n\n","category":"type"},{"location":"stdlib/LinearAlgebra/#Base.adjoint","page":"Linear Algebra","title":"Base.adjoint","text":"A'\nadjoint(A)\n\nLazy adjoint (conjugate transposition). Note that adjoint is applied recursively to elements.\n\nFor number types, adjoint returns the complex conjugate, and therefore it is equivalent to the identity function for real numbers.\n\nThis operation is intended for linear algebra usage - for general data manipulation see permutedims.\n\nExamples\n\njulia> A = [3+2im 9+2im; 8+7im 4+6im]\n2×2 Matrix{Complex{Int64}}:\n 3+2im 9+2im\n 8+7im 4+6im\n\njulia> adjoint(A)\n2×2 adjoint(::Matrix{Complex{Int64}}) with eltype Complex{Int64}:\n 3-2im 8-7im\n 9-2im 4-6im\n\njulia> x = [3, 4im]\n2-element Vector{Complex{Int64}}:\n 3 + 0im\n 0 + 4im\n\njulia> x'x\n25 + 0im\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LinearAlgebra/#LinearAlgebra.adjoint!","page":"Linear Algebra","title":"LinearAlgebra.adjoint!","text":"adjoint!(dest,src)\n\nConjugate transpose array src and store the result in the preallocated array dest, which should have a size corresponding to (size(src,2),size(src,1)). No in-place transposition is supported and unexpected results will happen if src and dest have overlapping memory regions.\n\nExamples\n\njulia> A = [3+2im 9+2im; 8+7im 4+6im]\n2×2 Matrix{Complex{Int64}}:\n 3+2im 9+2im\n 8+7im 4+6im\n\njulia> B = zeros(Complex{Int64}, 2, 2)\n2×2 Matrix{Complex{Int64}}:\n 0+0im 0+0im\n 0+0im 0+0im\n\njulia> adjoint!(B, A);\n\njulia> B\n2×2 Matrix{Complex{Int64}}:\n 3-2im 8-7im\n 9-2im 4-6im\n\njulia> A\n2×2 Matrix{Complex{Int64}}:\n 3+2im 9+2im\n 8+7im 4+6im\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LinearAlgebra/#LinearAlgebra.Adjoint","page":"Linear Algebra","title":"LinearAlgebra.Adjoint","text":"Adjoint\n\nLazy wrapper type for an adjoint view of the underlying linear algebra object, usually an AbstractVector/AbstractMatrix, but also some Factorization, for instance. Usually, the Adjoint constructor should not be called directly, use adjoint instead. To materialize the view use copy.\n\nThis type is intended for linear algebra usage - for general data manipulation see permutedims.\n\nExamples\n\njulia> A = [3+2im 9+2im; 8+7im 4+6im]\n2×2 Matrix{Complex{Int64}}:\n 3+2im 9+2im\n 8+7im 4+6im\n\njulia> adjoint(A)\n2×2 adjoint(::Matrix{Complex{Int64}}) with eltype Complex{Int64}:\n 3-2im 8-7im\n 9-2im 4-6im\n\n\n\n\n\n","category":"type"},{"location":"stdlib/LinearAlgebra/#Base.copy-Tuple{Union{Adjoint, Transpose}}","page":"Linear Algebra","title":"Base.copy","text":"copy(A::Transpose)\ncopy(A::Adjoint)\n\nEagerly evaluate the lazy matrix transpose/adjoint. Note that the transposition is applied recursively to elements.\n\nThis operation is intended for linear algebra usage - for general data manipulation see permutedims, which is non-recursive.\n\nExamples\n\njulia> A = [1 2im; -3im 4]\n2×2 Matrix{Complex{Int64}}:\n 1+0im 0+2im\n 0-3im 4+0im\n\njulia> T = transpose(A)\n2×2 transpose(::Matrix{Complex{Int64}}) with eltype Complex{Int64}:\n 1+0im 0-3im\n 0+2im 4+0im\n\njulia> copy(T)\n2×2 Matrix{Complex{Int64}}:\n 1+0im 0-3im\n 0+2im 4+0im\n\n\n\n\n\n","category":"method"},{"location":"stdlib/LinearAlgebra/#LinearAlgebra.stride1","page":"Linear Algebra","title":"LinearAlgebra.stride1","text":"stride1(A) -> Int\n\nReturn the distance between successive array elements in dimension 1 in units of element size.\n\nExamples\n\njulia> A = [1,2,3,4]\n4-element Vector{Int64}:\n 1\n 2\n 3\n 4\n\njulia> LinearAlgebra.stride1(A)\n1\n\njulia> B = view(A, 2:2:4)\n2-element view(::Vector{Int64}, 2:2:4) with eltype Int64:\n 2\n 4\n\njulia> LinearAlgebra.stride1(B)\n2\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LinearAlgebra/#LinearAlgebra.checksquare","page":"Linear Algebra","title":"LinearAlgebra.checksquare","text":"LinearAlgebra.checksquare(A)\n\nCheck that a matrix is square, then return its common dimension. For multiple arguments, return a vector.\n\nExamples\n\njulia> A = fill(1, (4,4)); B = fill(1, (5,5));\n\njulia> LinearAlgebra.checksquare(A, B)\n2-element Vector{Int64}:\n 4\n 5\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LinearAlgebra/#LinearAlgebra.peakflops","page":"Linear Algebra","title":"LinearAlgebra.peakflops","text":"LinearAlgebra.peakflops(n::Integer=2000; parallel::Bool=false)\n\npeakflops computes the peak flop rate of the computer by using double precision gemm!. By default, if no arguments are specified, it multiplies a matrix of size n x n, where n = 2000. If the underlying BLAS is using multiple threads, higher flop rates are realized. The number of BLAS threads can be set with BLAS.set_num_threads(n).\n\nIf the keyword argument parallel is set to true, peakflops is run in parallel on all the worker processors. The flop rate of the entire parallel computer is returned. When running in parallel, only 1 BLAS thread is used. The argument n still refers to the size of the problem that is solved on each processor.\n\ncompat: Julia 1.1\nThis function requires at least Julia 1.1. In Julia 1.0 it is available from the standard library InteractiveUtils.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LinearAlgebra/#Low-level-matrix-operations","page":"Linear Algebra","title":"Low-level matrix operations","text":"","category":"section"},{"location":"stdlib/LinearAlgebra/","page":"Linear Algebra","title":"Linear Algebra","text":"In many cases there are in-place versions of matrix operations that allow you to supply a pre-allocated output vector or matrix. This is useful when optimizing critical code in order to avoid the overhead of repeated allocations. These in-place operations are suffixed with ! below (e.g. mul!) according to the usual Julia convention.","category":"page"},{"location":"stdlib/LinearAlgebra/","page":"Linear Algebra","title":"Linear Algebra","text":"LinearAlgebra.mul!\nLinearAlgebra.lmul!\nLinearAlgebra.rmul!\nLinearAlgebra.ldiv!\nLinearAlgebra.rdiv!","category":"page"},{"location":"stdlib/LinearAlgebra/#LinearAlgebra.mul!","page":"Linear Algebra","title":"LinearAlgebra.mul!","text":"mul!(Y, A, B) -> Y\n\nCalculates the matrix-matrix or matrix-vector product AB and stores the result in Y, overwriting the existing value of Y. Note that Y must not be aliased with either A or B.\n\nExamples\n\njulia> A=[1.0 2.0; 3.0 4.0]; B=[1.0 1.0; 1.0 1.0]; Y = similar(B); mul!(Y, A, B);\n\njulia> Y\n2×2 Matrix{Float64}:\n 3.0 3.0\n 7.0 7.0\n\nImplementation\n\nFor custom matrix and vector types, it is recommended to implement 5-argument mul! rather than implementing 3-argument mul! directly if possible.\n\n\n\n\n\nmul!(C, A, B, α, β) -> C\n\nCombined inplace matrix-matrix or matrix-vector multiply-add A B α + C β. The result is stored in C by overwriting it. Note that C must not be aliased with either A or B.\n\ncompat: Julia 1.3\nFive-argument mul! requires at least Julia 1.3.\n\nExamples\n\njulia> A=[1.0 2.0; 3.0 4.0]; B=[1.0 1.0; 1.0 1.0]; C=[1.0 2.0; 3.0 4.0];\n\njulia> mul!(C, A, B, 100.0, 10.0) === C\ntrue\n\njulia> C\n2×2 Matrix{Float64}:\n 310.0 320.0\n 730.0 740.0\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LinearAlgebra/#LinearAlgebra.lmul!","page":"Linear Algebra","title":"LinearAlgebra.lmul!","text":"lmul!(a::Number, B::AbstractArray)\n\nScale an array B by a scalar a overwriting B in-place. Use rmul! to multiply scalar from right. The scaling operation respects the semantics of the multiplication * between a and an element of B. In particular, this also applies to multiplication involving non-finite numbers such as NaN and ±Inf.\n\ncompat: Julia 1.1\nPrior to Julia 1.1, NaN and ±Inf entries in B were treated inconsistently.\n\nExamples\n\njulia> B = [1 2; 3 4]\n2×2 Matrix{Int64}:\n 1 2\n 3 4\n\njulia> lmul!(2, B)\n2×2 Matrix{Int64}:\n 2 4\n 6 8\n\njulia> lmul!(0.0, [Inf])\n1-element Vector{Float64}:\n NaN\n\n\n\n\n\nlmul!(A, B)\n\nCalculate the matrix-matrix product AB, overwriting B, and return the result. Here, A must be of special matrix type, like, e.g., Diagonal, UpperTriangular or LowerTriangular, or of some orthogonal type, see QR.\n\nExamples\n\njulia> B = [0 1; 1 0];\n\njulia> A = LinearAlgebra.UpperTriangular([1 2; 0 3]);\n\njulia> LinearAlgebra.lmul!(A, B);\n\njulia> B\n2×2 Matrix{Int64}:\n 2 1\n 3 0\n\njulia> B = [1.0 2.0; 3.0 4.0];\n\njulia> F = qr([0 1; -1 0]);\n\njulia> lmul!(F.Q, B)\n2×2 Matrix{Float64}:\n 3.0 4.0\n 1.0 2.0\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LinearAlgebra/#LinearAlgebra.rmul!","page":"Linear Algebra","title":"LinearAlgebra.rmul!","text":"rmul!(A::AbstractArray, b::Number)\n\nScale an array A by a scalar b overwriting A in-place. Use lmul! to multiply scalar from left. The scaling operation respects the semantics of the multiplication * between an element of A and b. In particular, this also applies to multiplication involving non-finite numbers such as NaN and ±Inf.\n\ncompat: Julia 1.1\nPrior to Julia 1.1, NaN and ±Inf entries in A were treated inconsistently.\n\nExamples\n\njulia> A = [1 2; 3 4]\n2×2 Matrix{Int64}:\n 1 2\n 3 4\n\njulia> rmul!(A, 2)\n2×2 Matrix{Int64}:\n 2 4\n 6 8\n\njulia> rmul!([NaN], 0.0)\n1-element Vector{Float64}:\n NaN\n\n\n\n\n\nrmul!(A, B)\n\nCalculate the matrix-matrix product AB, overwriting A, and return the result. Here, B must be of special matrix type, like, e.g., Diagonal, UpperTriangular or LowerTriangular, or of some orthogonal type, see QR.\n\nExamples\n\njulia> A = [0 1; 1 0];\n\njulia> B = LinearAlgebra.UpperTriangular([1 2; 0 3]);\n\njulia> LinearAlgebra.rmul!(A, B);\n\njulia> A\n2×2 Matrix{Int64}:\n 0 3\n 1 2\n\njulia> A = [1.0 2.0; 3.0 4.0];\n\njulia> F = qr([0 1; -1 0]);\n\njulia> rmul!(A, F.Q)\n2×2 Matrix{Float64}:\n 2.0 1.0\n 4.0 3.0\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LinearAlgebra/#LinearAlgebra.ldiv!","page":"Linear Algebra","title":"LinearAlgebra.ldiv!","text":"ldiv!(Y, A, B) -> Y\n\nCompute A \\ B in-place and store the result in Y, returning the result.\n\nThe argument A should not be a matrix. Rather, instead of matrices it should be a factorization object (e.g. produced by factorize or cholesky). The reason for this is that factorization itself is both expensive and typically allocates memory (although it can also be done in-place via, e.g., lu!), and performance-critical situations requiring ldiv! usually also require fine-grained control over the factorization of A.\n\nExamples\n\njulia> A = [1 2.2 4; 3.1 0.2 3; 4 1 2];\n\njulia> X = [1; 2.5; 3];\n\njulia> Y = zero(X);\n\njulia> ldiv!(Y, qr(A), X);\n\njulia> Y\n3-element Vector{Float64}:\n 0.7128099173553719\n -0.051652892561983674\n 0.10020661157024757\n\njulia> A\\X\n3-element Vector{Float64}:\n 0.7128099173553719\n -0.05165289256198333\n 0.10020661157024785\n\n\n\n\n\nldiv!(A, B)\n\nCompute A \\ B in-place and overwriting B to store the result.\n\nThe argument A should not be a matrix. Rather, instead of matrices it should be a factorization object (e.g. produced by factorize or cholesky). The reason for this is that factorization itself is both expensive and typically allocates memory (although it can also be done in-place via, e.g., lu!), and performance-critical situations requiring ldiv! usually also require fine-grained control over the factorization of A.\n\nExamples\n\njulia> A = [1 2.2 4; 3.1 0.2 3; 4 1 2];\n\njulia> X = [1; 2.5; 3];\n\njulia> Y = copy(X);\n\njulia> ldiv!(qr(A), X);\n\njulia> X\n3-element Vector{Float64}:\n 0.7128099173553719\n -0.051652892561983674\n 0.10020661157024757\n\njulia> A\\Y\n3-element Vector{Float64}:\n 0.7128099173553719\n -0.05165289256198333\n 0.10020661157024785\n\n\n\n\n\nldiv!(a::Number, B::AbstractArray)\n\nDivide each entry in an array B by a scalar a overwriting B in-place. Use rdiv! to divide scalar from right.\n\nExamples\n\njulia> B = [1.0 2.0; 3.0 4.0]\n2×2 Matrix{Float64}:\n 1.0 2.0\n 3.0 4.0\n\njulia> ldiv!(2.0, B)\n2×2 Matrix{Float64}:\n 0.5 1.0\n 1.5 2.0\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LinearAlgebra/#LinearAlgebra.rdiv!","page":"Linear Algebra","title":"LinearAlgebra.rdiv!","text":"rdiv!(A, B)\n\nCompute A / B in-place and overwriting A to store the result.\n\nThe argument B should not be a matrix. Rather, instead of matrices it should be a factorization object (e.g. produced by factorize or cholesky). The reason for this is that factorization itself is both expensive and typically allocates memory (although it can also be done in-place via, e.g., lu!), and performance-critical situations requiring rdiv! usually also require fine-grained control over the factorization of B.\n\n\n\n\n\nrdiv!(A::AbstractArray, b::Number)\n\nDivide each entry in an array A by a scalar b overwriting A in-place. Use ldiv! to divide scalar from left.\n\nExamples\n\njulia> A = [1.0 2.0; 3.0 4.0]\n2×2 Matrix{Float64}:\n 1.0 2.0\n 3.0 4.0\n\njulia> rdiv!(A, 2.0)\n2×2 Matrix{Float64}:\n 0.5 1.0\n 1.5 2.0\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LinearAlgebra/#BLAS-functions","page":"Linear Algebra","title":"BLAS functions","text":"","category":"section"},{"location":"stdlib/LinearAlgebra/","page":"Linear Algebra","title":"Linear Algebra","text":"In Julia (as in much of scientific computation), dense linear-algebra operations are based on the LAPACK library, which in turn is built on top of basic linear-algebra building-blocks known as the BLAS. There are highly optimized implementations of BLAS available for every computer architecture, and sometimes in high-performance linear algebra routines it is useful to call the BLAS functions directly.","category":"page"},{"location":"stdlib/LinearAlgebra/","page":"Linear Algebra","title":"Linear Algebra","text":"LinearAlgebra.BLAS provides wrappers for some of the BLAS functions. Those BLAS functions that overwrite one of the input arrays have names ending in '!'. Usually, a BLAS function has four methods defined, for Float64, Float32, ComplexF64, and ComplexF32 arrays.","category":"page"},{"location":"stdlib/LinearAlgebra/#stdlib-blas-chars","page":"Linear Algebra","title":"BLAS character arguments","text":"","category":"section"},{"location":"stdlib/LinearAlgebra/","page":"Linear Algebra","title":"Linear Algebra","text":"Many BLAS functions accept arguments that determine whether to transpose an argument (trans), which triangle of a matrix to reference (uplo or ul), whether the diagonal of a triangular matrix can be assumed to be all ones (dA) or which side of a matrix multiplication the input argument belongs on (side). The possibilities are:","category":"page"},{"location":"stdlib/LinearAlgebra/#stdlib-blas-side","page":"Linear Algebra","title":"Multiplication order","text":"","category":"section"},{"location":"stdlib/LinearAlgebra/","page":"Linear Algebra","title":"Linear Algebra","text":"side Meaning\n'L' The argument goes on the left side of a matrix-matrix operation.\n'R' The argument goes on the right side of a matrix-matrix operation.","category":"page"},{"location":"stdlib/LinearAlgebra/#stdlib-blas-uplo","page":"Linear Algebra","title":"Triangle referencing","text":"","category":"section"},{"location":"stdlib/LinearAlgebra/","page":"Linear Algebra","title":"Linear Algebra","text":"uplo/ul Meaning\n'U' Only the upper triangle of the matrix will be used.\n'L' Only the lower triangle of the matrix will be used.","category":"page"},{"location":"stdlib/LinearAlgebra/#stdlib-blas-trans","page":"Linear Algebra","title":"Transposition operation","text":"","category":"section"},{"location":"stdlib/LinearAlgebra/","page":"Linear Algebra","title":"Linear Algebra","text":"trans/tX Meaning\n'N' The input matrix X is not transposed or conjugated.\n'T' The input matrix X will be transposed.\n'C' The input matrix X will be conjugated and transposed.","category":"page"},{"location":"stdlib/LinearAlgebra/#stdlib-blas-diag","page":"Linear Algebra","title":"Unit diagonal","text":"","category":"section"},{"location":"stdlib/LinearAlgebra/","page":"Linear Algebra","title":"Linear Algebra","text":"diag/dX Meaning\n'N' The diagonal values of the matrix X will be read.\n'U' The diagonal of the matrix X is assumed to be all ones.","category":"page"},{"location":"stdlib/LinearAlgebra/","page":"Linear Algebra","title":"Linear Algebra","text":"LinearAlgebra.BLAS\nLinearAlgebra.BLAS.dot\nLinearAlgebra.BLAS.dotu\nLinearAlgebra.BLAS.dotc\nLinearAlgebra.BLAS.blascopy!\nLinearAlgebra.BLAS.nrm2\nLinearAlgebra.BLAS.asum\nLinearAlgebra.axpy!\nLinearAlgebra.axpby!\nLinearAlgebra.BLAS.scal!\nLinearAlgebra.BLAS.scal\nLinearAlgebra.BLAS.iamax\nLinearAlgebra.BLAS.ger!\nLinearAlgebra.BLAS.syr!\nLinearAlgebra.BLAS.syrk!\nLinearAlgebra.BLAS.syrk\nLinearAlgebra.BLAS.syr2k!\nLinearAlgebra.BLAS.syr2k\nLinearAlgebra.BLAS.her!\nLinearAlgebra.BLAS.herk!\nLinearAlgebra.BLAS.herk\nLinearAlgebra.BLAS.her2k!\nLinearAlgebra.BLAS.her2k\nLinearAlgebra.BLAS.gbmv!\nLinearAlgebra.BLAS.gbmv\nLinearAlgebra.BLAS.sbmv!\nLinearAlgebra.BLAS.sbmv(::Any, ::Any, ::Any, ::Any, ::Any)\nLinearAlgebra.BLAS.sbmv(::Any, ::Any, ::Any, ::Any)\nLinearAlgebra.BLAS.gemm!\nLinearAlgebra.BLAS.gemm(::Any, ::Any, ::Any, ::Any, ::Any)\nLinearAlgebra.BLAS.gemm(::Any, ::Any, ::Any, ::Any)\nLinearAlgebra.BLAS.gemv!\nLinearAlgebra.BLAS.gemv(::Any, ::Any, ::Any, ::Any)\nLinearAlgebra.BLAS.gemv(::Any, ::Any, ::Any)\nLinearAlgebra.BLAS.symm!\nLinearAlgebra.BLAS.symm(::Any, ::Any, ::Any, ::Any, ::Any)\nLinearAlgebra.BLAS.symm(::Any, ::Any, ::Any, ::Any)\nLinearAlgebra.BLAS.symv!\nLinearAlgebra.BLAS.symv(::Any, ::Any, ::Any, ::Any)\nLinearAlgebra.BLAS.symv(::Any, ::Any, ::Any)\nLinearAlgebra.BLAS.hemm!\nLinearAlgebra.BLAS.hemm(::Any, ::Any, ::Any, ::Any, ::Any)\nLinearAlgebra.BLAS.hemm(::Any, ::Any, ::Any, ::Any)\nLinearAlgebra.BLAS.hemv!\nLinearAlgebra.BLAS.hemv(::Any, ::Any, ::Any, ::Any)\nLinearAlgebra.BLAS.hemv(::Any, ::Any, ::Any)\nLinearAlgebra.BLAS.trmm!\nLinearAlgebra.BLAS.trmm\nLinearAlgebra.BLAS.trsm!\nLinearAlgebra.BLAS.trsm\nLinearAlgebra.BLAS.trmv!\nLinearAlgebra.BLAS.trmv\nLinearAlgebra.BLAS.trsv!\nLinearAlgebra.BLAS.trsv\nLinearAlgebra.BLAS.set_num_threads\nLinearAlgebra.BLAS.get_num_threads","category":"page"},{"location":"stdlib/LinearAlgebra/#LinearAlgebra.BLAS","page":"Linear Algebra","title":"LinearAlgebra.BLAS","text":"Interface to BLAS subroutines.\n\n\n\n\n\n","category":"module"},{"location":"stdlib/LinearAlgebra/#LinearAlgebra.BLAS.dot","page":"Linear Algebra","title":"LinearAlgebra.BLAS.dot","text":"dot(n, X, incx, Y, incy)\n\nDot product of two vectors consisting of n elements of array X with stride incx and n elements of array Y with stride incy.\n\nExamples\n\njulia> BLAS.dot(10, fill(1.0, 10), 1, fill(1.0, 20), 2)\n10.0\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LinearAlgebra/#LinearAlgebra.BLAS.dotu","page":"Linear Algebra","title":"LinearAlgebra.BLAS.dotu","text":"dotu(n, X, incx, Y, incy)\n\nDot function for two complex vectors consisting of n elements of array X with stride incx and n elements of array Y with stride incy.\n\nExamples\n\njulia> BLAS.dotu(10, fill(1.0im, 10), 1, fill(1.0+im, 20), 2)\n-10.0 + 10.0im\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LinearAlgebra/#LinearAlgebra.BLAS.dotc","page":"Linear Algebra","title":"LinearAlgebra.BLAS.dotc","text":"dotc(n, X, incx, U, incy)\n\nDot function for two complex vectors, consisting of n elements of array X with stride incx and n elements of array U with stride incy, conjugating the first vector.\n\nExamples\n\njulia> BLAS.dotc(10, fill(1.0im, 10), 1, fill(1.0+im, 20), 2)\n10.0 - 10.0im\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LinearAlgebra/#LinearAlgebra.BLAS.blascopy!","page":"Linear Algebra","title":"LinearAlgebra.BLAS.blascopy!","text":"blascopy!(n, X, incx, Y, incy)\n\nCopy n elements of array X with stride incx to array Y with stride incy. Returns Y.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LinearAlgebra/#LinearAlgebra.BLAS.nrm2","page":"Linear Algebra","title":"LinearAlgebra.BLAS.nrm2","text":"nrm2(n, X, incx)\n\n2-norm of a vector consisting of n elements of array X with stride incx.\n\nExamples\n\njulia> BLAS.nrm2(4, fill(1.0, 8), 2)\n2.0\n\njulia> BLAS.nrm2(1, fill(1.0, 8), 2)\n1.0\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LinearAlgebra/#LinearAlgebra.BLAS.asum","page":"Linear Algebra","title":"LinearAlgebra.BLAS.asum","text":"asum(n, X, incx)\n\nSum of the magnitudes of the first n elements of array X with stride incx.\n\nFor a real array, the magnitude is the absolute value. For a complex array, the magnitude is the sum of the absolute value of the real part and the absolute value of the imaginary part.\n\nExamples\n\njulia> BLAS.asum(5, fill(1.0im, 10), 2)\n5.0\n\njulia> BLAS.asum(2, fill(1.0im, 10), 5)\n2.0\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LinearAlgebra/#LinearAlgebra.axpy!","page":"Linear Algebra","title":"LinearAlgebra.axpy!","text":"axpy!(a, X, Y)\n\nOverwrite Y with X*a + Y, where a is a scalar. Return Y.\n\nExamples\n\njulia> x = [1; 2; 3];\n\njulia> y = [4; 5; 6];\n\njulia> BLAS.axpy!(2, x, y)\n3-element Vector{Int64}:\n 6\n 9\n 12\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LinearAlgebra/#LinearAlgebra.axpby!","page":"Linear Algebra","title":"LinearAlgebra.axpby!","text":"axpby!(a, X, b, Y)\n\nOverwrite Y with X*a + Y*b, where a and b are scalars. Return Y.\n\nExamples\n\njulia> x = [1., 2, 3];\n\njulia> y = [4., 5, 6];\n\njulia> BLAS.axpby!(2., x, 3., y)\n3-element Vector{Float64}:\n 14.0\n 19.0\n 24.0\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LinearAlgebra/#LinearAlgebra.BLAS.scal!","page":"Linear Algebra","title":"LinearAlgebra.BLAS.scal!","text":"scal!(n, a, X, incx)\nscal!(a, X)\n\nOverwrite X with a*X for the first n elements of array X with stride incx. Returns X.\n\nIf n and incx are not provided, length(X) and stride(X,1) are used.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LinearAlgebra/#LinearAlgebra.BLAS.scal","page":"Linear Algebra","title":"LinearAlgebra.BLAS.scal","text":"scal(n, a, X, incx)\nscal(a, X)\n\nReturn X scaled by a for the first n elements of array X with stride incx.\n\nIf n and incx are not provided, length(X) and stride(X,1) are used.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LinearAlgebra/#LinearAlgebra.BLAS.iamax","page":"Linear Algebra","title":"LinearAlgebra.BLAS.iamax","text":"iamax(n, dx, incx)\niamax(dx)\n\nFind the index of the element of dx with the maximum absolute value. n is the length of dx, and incx is the stride. If n and incx are not provided, they assume default values of n=length(dx) and incx=stride1(dx).\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LinearAlgebra/#LinearAlgebra.BLAS.ger!","page":"Linear Algebra","title":"LinearAlgebra.BLAS.ger!","text":"ger!(alpha, x, y, A)\n\nRank-1 update of the matrix A with vectors x and y as alpha*x*y' + A.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LinearAlgebra/#LinearAlgebra.BLAS.syr!","page":"Linear Algebra","title":"LinearAlgebra.BLAS.syr!","text":"syr!(uplo, alpha, x, A)\n\nRank-1 update of the symmetric matrix A with vector x as alpha*x*transpose(x) + A. uplo controls which triangle of A is updated. Returns A.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LinearAlgebra/#LinearAlgebra.BLAS.syrk!","page":"Linear Algebra","title":"LinearAlgebra.BLAS.syrk!","text":"syrk!(uplo, trans, alpha, A, beta, C)\n\nRank-k update of the symmetric matrix C as alpha*A*transpose(A) + beta*C or alpha*transpose(A)*A + beta*C according to trans. Only the uplo triangle of C is used. Returns C.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LinearAlgebra/#LinearAlgebra.BLAS.syrk","page":"Linear Algebra","title":"LinearAlgebra.BLAS.syrk","text":"syrk(uplo, trans, alpha, A)\n\nReturns either the upper triangle or the lower triangle of A, according to uplo, of alpha*A*transpose(A) or alpha*transpose(A)*A, according to trans.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LinearAlgebra/#LinearAlgebra.BLAS.syr2k!","page":"Linear Algebra","title":"LinearAlgebra.BLAS.syr2k!","text":"syr2k!(uplo, trans, alpha, A, B, beta, C)\n\nRank-2k update of the symmetric matrix C as alpha*A*transpose(B) + alpha*B*transpose(A) + beta*C or alpha*transpose(A)*B + alpha*transpose(B)*A + beta*C according to trans. Only the uplo triangle of C is used. Returns C.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LinearAlgebra/#LinearAlgebra.BLAS.syr2k","page":"Linear Algebra","title":"LinearAlgebra.BLAS.syr2k","text":"syr2k(uplo, trans, alpha, A, B)\n\nReturns the uplo triangle of alpha*A*transpose(B) + alpha*B*transpose(A) or alpha*transpose(A)*B + alpha*transpose(B)*A, according to trans.\n\n\n\n\n\nsyr2k(uplo, trans, A, B)\n\nReturns the uplo triangle of A*transpose(B) + B*transpose(A) or transpose(A)*B + transpose(B)*A, according to trans.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LinearAlgebra/#LinearAlgebra.BLAS.her!","page":"Linear Algebra","title":"LinearAlgebra.BLAS.her!","text":"her!(uplo, alpha, x, A)\n\nMethods for complex arrays only. Rank-1 update of the Hermitian matrix A with vector x as alpha*x*x' + A. uplo controls which triangle of A is updated. Returns A.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LinearAlgebra/#LinearAlgebra.BLAS.herk!","page":"Linear Algebra","title":"LinearAlgebra.BLAS.herk!","text":"herk!(uplo, trans, alpha, A, beta, C)\n\nMethods for complex arrays only. Rank-k update of the Hermitian matrix C as alpha*A*A' + beta*C or alpha*A'*A + beta*C according to trans. Only the uplo triangle of C is updated. Returns C.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LinearAlgebra/#LinearAlgebra.BLAS.herk","page":"Linear Algebra","title":"LinearAlgebra.BLAS.herk","text":"herk(uplo, trans, alpha, A)\n\nMethods for complex arrays only. Returns the uplo triangle of alpha*A*A' or alpha*A'*A, according to trans.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LinearAlgebra/#LinearAlgebra.BLAS.her2k!","page":"Linear Algebra","title":"LinearAlgebra.BLAS.her2k!","text":"her2k!(uplo, trans, alpha, A, B, beta, C)\n\nRank-2k update of the Hermitian matrix C as alpha*A*B' + alpha*B*A' + beta*C or alpha*A'*B + alpha*B'*A + beta*C according to trans. The scalar beta has to be real. Only the uplo triangle of C is used. Returns C.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LinearAlgebra/#LinearAlgebra.BLAS.her2k","page":"Linear Algebra","title":"LinearAlgebra.BLAS.her2k","text":"her2k(uplo, trans, alpha, A, B)\n\nReturns the uplo triangle of alpha*A*B' + alpha*B*A' or alpha*A'*B + alpha*B'*A, according to trans.\n\n\n\n\n\nher2k(uplo, trans, A, B)\n\nReturns the uplo triangle of A*B' + B*A' or A'*B + B'*A, according to trans.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LinearAlgebra/#LinearAlgebra.BLAS.gbmv!","page":"Linear Algebra","title":"LinearAlgebra.BLAS.gbmv!","text":"gbmv!(trans, m, kl, ku, alpha, A, x, beta, y)\n\nUpdate vector y as alpha*A*x + beta*y or alpha*A'*x + beta*y according to trans. The matrix A is a general band matrix of dimension m by size(A,2) with kl sub-diagonals and ku super-diagonals. alpha and beta are scalars. Return the updated y.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LinearAlgebra/#LinearAlgebra.BLAS.gbmv","page":"Linear Algebra","title":"LinearAlgebra.BLAS.gbmv","text":"gbmv(trans, m, kl, ku, alpha, A, x)\n\nReturn alpha*A*x or alpha*A'*x according to trans. The matrix A is a general band matrix of dimension m by size(A,2) with kl sub-diagonals and ku super-diagonals, and alpha is a scalar.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LinearAlgebra/#LinearAlgebra.BLAS.sbmv!","page":"Linear Algebra","title":"LinearAlgebra.BLAS.sbmv!","text":"sbmv!(uplo, k, alpha, A, x, beta, y)\n\nUpdate vector y as alpha*A*x + beta*y where A is a symmetric band matrix of order size(A,2) with k super-diagonals stored in the argument A. The storage layout for A is described the reference BLAS module, level-2 BLAS at http://www.netlib.org/lapack/explore-html/. Only the uplo triangle of A is used.\n\nReturn the updated y.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LinearAlgebra/#LinearAlgebra.BLAS.sbmv-NTuple{5, Any}","page":"Linear Algebra","title":"LinearAlgebra.BLAS.sbmv","text":"sbmv(uplo, k, alpha, A, x)\n\nReturn alpha*A*x where A is a symmetric band matrix of order size(A,2) with k super-diagonals stored in the argument A. Only the uplo triangle of A is used.\n\n\n\n\n\n","category":"method"},{"location":"stdlib/LinearAlgebra/#LinearAlgebra.BLAS.sbmv-NTuple{4, Any}","page":"Linear Algebra","title":"LinearAlgebra.BLAS.sbmv","text":"sbmv(uplo, k, A, x)\n\nReturn A*x where A is a symmetric band matrix of order size(A,2) with k super-diagonals stored in the argument A. Only the uplo triangle of A is used.\n\n\n\n\n\n","category":"method"},{"location":"stdlib/LinearAlgebra/#LinearAlgebra.BLAS.gemm!","page":"Linear Algebra","title":"LinearAlgebra.BLAS.gemm!","text":"gemm!(tA, tB, alpha, A, B, beta, C)\n\nUpdate C as alpha*A*B + beta*C or the other three variants according to tA and tB. Return the updated C.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LinearAlgebra/#LinearAlgebra.BLAS.gemm-NTuple{5, Any}","page":"Linear Algebra","title":"LinearAlgebra.BLAS.gemm","text":"gemm(tA, tB, alpha, A, B)\n\nReturn alpha*A*B or the other three variants according to tA and tB.\n\n\n\n\n\n","category":"method"},{"location":"stdlib/LinearAlgebra/#LinearAlgebra.BLAS.gemm-NTuple{4, Any}","page":"Linear Algebra","title":"LinearAlgebra.BLAS.gemm","text":"gemm(tA, tB, A, B)\n\nReturn A*B or the other three variants according to tA and tB.\n\n\n\n\n\n","category":"method"},{"location":"stdlib/LinearAlgebra/#LinearAlgebra.BLAS.gemv!","page":"Linear Algebra","title":"LinearAlgebra.BLAS.gemv!","text":"gemv!(tA, alpha, A, x, beta, y)\n\nUpdate the vector y as alpha*A*x + beta*y or alpha*A'x + beta*y according to tA. alpha and beta are scalars. Return the updated y.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LinearAlgebra/#LinearAlgebra.BLAS.gemv-NTuple{4, Any}","page":"Linear Algebra","title":"LinearAlgebra.BLAS.gemv","text":"gemv(tA, alpha, A, x)\n\nReturn alpha*A*x or alpha*A'x according to tA. alpha is a scalar.\n\n\n\n\n\n","category":"method"},{"location":"stdlib/LinearAlgebra/#LinearAlgebra.BLAS.gemv-Tuple{Any, Any, Any}","page":"Linear Algebra","title":"LinearAlgebra.BLAS.gemv","text":"gemv(tA, A, x)\n\nReturn A*x or A'x according to tA.\n\n\n\n\n\n","category":"method"},{"location":"stdlib/LinearAlgebra/#LinearAlgebra.BLAS.symm!","page":"Linear Algebra","title":"LinearAlgebra.BLAS.symm!","text":"symm!(side, ul, alpha, A, B, beta, C)\n\nUpdate C as alpha*A*B + beta*C or alpha*B*A + beta*C according to side. A is assumed to be symmetric. Only the ul triangle of A is used. Return the updated C.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LinearAlgebra/#LinearAlgebra.BLAS.symm-NTuple{5, Any}","page":"Linear Algebra","title":"LinearAlgebra.BLAS.symm","text":"symm(side, ul, alpha, A, B)\n\nReturn alpha*A*B or alpha*B*A according to side. A is assumed to be symmetric. Only the ul triangle of A is used.\n\n\n\n\n\n","category":"method"},{"location":"stdlib/LinearAlgebra/#LinearAlgebra.BLAS.symm-NTuple{4, Any}","page":"Linear Algebra","title":"LinearAlgebra.BLAS.symm","text":"symm(side, ul, A, B)\n\nReturn A*B or B*A according to side. A is assumed to be symmetric. Only the ul triangle of A is used.\n\n\n\n\n\n","category":"method"},{"location":"stdlib/LinearAlgebra/#LinearAlgebra.BLAS.symv!","page":"Linear Algebra","title":"LinearAlgebra.BLAS.symv!","text":"symv!(ul, alpha, A, x, beta, y)\n\nUpdate the vector y as alpha*A*x + beta*y. A is assumed to be symmetric. Only the ul triangle of A is used. alpha and beta are scalars. Return the updated y.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LinearAlgebra/#LinearAlgebra.BLAS.symv-NTuple{4, Any}","page":"Linear Algebra","title":"LinearAlgebra.BLAS.symv","text":"symv(ul, alpha, A, x)\n\nReturn alpha*A*x. A is assumed to be symmetric. Only the ul triangle of A is used. alpha is a scalar.\n\n\n\n\n\n","category":"method"},{"location":"stdlib/LinearAlgebra/#LinearAlgebra.BLAS.symv-Tuple{Any, Any, Any}","page":"Linear Algebra","title":"LinearAlgebra.BLAS.symv","text":"symv(ul, A, x)\n\nReturn A*x. A is assumed to be symmetric. Only the ul triangle of A is used.\n\n\n\n\n\n","category":"method"},{"location":"stdlib/LinearAlgebra/#LinearAlgebra.BLAS.hemm!","page":"Linear Algebra","title":"LinearAlgebra.BLAS.hemm!","text":"hemm!(side, ul, alpha, A, B, beta, C)\n\nUpdate C as alpha*A*B + beta*C or alpha*B*A + beta*C according to side. A is assumed to be Hermitian. Only the ul triangle of A is used. Return the updated C.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LinearAlgebra/#LinearAlgebra.BLAS.hemm-NTuple{5, Any}","page":"Linear Algebra","title":"LinearAlgebra.BLAS.hemm","text":"hemm(side, ul, alpha, A, B)\n\nReturn alpha*A*B or alpha*B*A according to side. A is assumed to be Hermitian. Only the ul triangle of A is used.\n\n\n\n\n\n","category":"method"},{"location":"stdlib/LinearAlgebra/#LinearAlgebra.BLAS.hemm-NTuple{4, Any}","page":"Linear Algebra","title":"LinearAlgebra.BLAS.hemm","text":"hemm(side, ul, A, B)\n\nReturn A*B or B*A according to side. A is assumed to be Hermitian. Only the ul triangle of A is used.\n\n\n\n\n\n","category":"method"},{"location":"stdlib/LinearAlgebra/#LinearAlgebra.BLAS.hemv!","page":"Linear Algebra","title":"LinearAlgebra.BLAS.hemv!","text":"hemv!(ul, alpha, A, x, beta, y)\n\nUpdate the vector y as alpha*A*x + beta*y. A is assumed to be Hermitian. Only the ul triangle of A is used. alpha and beta are scalars. Return the updated y.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LinearAlgebra/#LinearAlgebra.BLAS.hemv-NTuple{4, Any}","page":"Linear Algebra","title":"LinearAlgebra.BLAS.hemv","text":"hemv(ul, alpha, A, x)\n\nReturn alpha*A*x. A is assumed to be Hermitian. Only the ul triangle of A is used. alpha is a scalar.\n\n\n\n\n\n","category":"method"},{"location":"stdlib/LinearAlgebra/#LinearAlgebra.BLAS.hemv-Tuple{Any, Any, Any}","page":"Linear Algebra","title":"LinearAlgebra.BLAS.hemv","text":"hemv(ul, A, x)\n\nReturn A*x. A is assumed to be Hermitian. Only the ul triangle of A is used.\n\n\n\n\n\n","category":"method"},{"location":"stdlib/LinearAlgebra/#LinearAlgebra.BLAS.trmm!","page":"Linear Algebra","title":"LinearAlgebra.BLAS.trmm!","text":"trmm!(side, ul, tA, dA, alpha, A, B)\n\nUpdate B as alpha*A*B or one of the other three variants determined by side and tA. Only the ul triangle of A is used. dA determines if the diagonal values are read or are assumed to be all ones. Returns the updated B.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LinearAlgebra/#LinearAlgebra.BLAS.trmm","page":"Linear Algebra","title":"LinearAlgebra.BLAS.trmm","text":"trmm(side, ul, tA, dA, alpha, A, B)\n\nReturns alpha*A*B or one of the other three variants determined by side and tA. Only the ul triangle of A is used. dA determines if the diagonal values are read or are assumed to be all ones.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LinearAlgebra/#LinearAlgebra.BLAS.trsm!","page":"Linear Algebra","title":"LinearAlgebra.BLAS.trsm!","text":"trsm!(side, ul, tA, dA, alpha, A, B)\n\nOverwrite B with the solution to A*X = alpha*B or one of the other three variants determined by side and tA. Only the ul triangle of A is used. dA determines if the diagonal values are read or are assumed to be all ones. Returns the updated B.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LinearAlgebra/#LinearAlgebra.BLAS.trsm","page":"Linear Algebra","title":"LinearAlgebra.BLAS.trsm","text":"trsm(side, ul, tA, dA, alpha, A, B)\n\nReturn the solution to A*X = alpha*B or one of the other three variants determined by determined by side and tA. Only the ul triangle of A is used. dA determines if the diagonal values are read or are assumed to be all ones.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LinearAlgebra/#LinearAlgebra.BLAS.trmv!","page":"Linear Algebra","title":"LinearAlgebra.BLAS.trmv!","text":"trmv!(ul, tA, dA, A, b)\n\nReturn op(A)*b, where op is determined by tA. Only the ul triangle of A is used. dA determines if the diagonal values are read or are assumed to be all ones. The multiplication occurs in-place on b.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LinearAlgebra/#LinearAlgebra.BLAS.trmv","page":"Linear Algebra","title":"LinearAlgebra.BLAS.trmv","text":"trmv(ul, tA, dA, A, b)\n\nReturn op(A)*b, where op is determined by tA. Only the ul triangle of A is used. dA determines if the diagonal values are read or are assumed to be all ones.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LinearAlgebra/#LinearAlgebra.BLAS.trsv!","page":"Linear Algebra","title":"LinearAlgebra.BLAS.trsv!","text":"trsv!(ul, tA, dA, A, b)\n\nOverwrite b with the solution to A*x = b or one of the other two variants determined by tA and ul. dA determines if the diagonal values are read or are assumed to be all ones. Return the updated b.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LinearAlgebra/#LinearAlgebra.BLAS.trsv","page":"Linear Algebra","title":"LinearAlgebra.BLAS.trsv","text":"trsv(ul, tA, dA, A, b)\n\nReturn the solution to A*x = b or one of the other two variants determined by tA and ul. dA determines if the diagonal values are read or are assumed to be all ones.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LinearAlgebra/#LinearAlgebra.BLAS.set_num_threads","page":"Linear Algebra","title":"LinearAlgebra.BLAS.set_num_threads","text":"set_num_threads(n::Integer)\nset_num_threads(::Nothing)\n\nSet the number of threads the BLAS library should use equal to n::Integer.\n\nAlso accepts nothing, in which case julia tries to guess the default number of threads. Passing nothing is discouraged and mainly exists for historical reasons.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LinearAlgebra/#LinearAlgebra.BLAS.get_num_threads","page":"Linear Algebra","title":"LinearAlgebra.BLAS.get_num_threads","text":"get_num_threads()\n\nGet the number of threads the BLAS library is using.\n\ncompat: Julia 1.6\nget_num_threads requires at least Julia 1.6.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LinearAlgebra/#LAPACK-functions","page":"Linear Algebra","title":"LAPACK functions","text":"","category":"section"},{"location":"stdlib/LinearAlgebra/","page":"Linear Algebra","title":"Linear Algebra","text":"LinearAlgebra.LAPACK provides wrappers for some of the LAPACK functions for linear algebra. Those functions that overwrite one of the input arrays have names ending in '!'.","category":"page"},{"location":"stdlib/LinearAlgebra/","page":"Linear Algebra","title":"Linear Algebra","text":"Usually a function has 4 methods defined, one each for Float64, Float32, ComplexF64 and ComplexF32 arrays.","category":"page"},{"location":"stdlib/LinearAlgebra/","page":"Linear Algebra","title":"Linear Algebra","text":"Note that the LAPACK API provided by Julia can and will change in the future. Since this API is not user-facing, there is no commitment to support/deprecate this specific set of functions in future releases.","category":"page"},{"location":"stdlib/LinearAlgebra/","page":"Linear Algebra","title":"Linear Algebra","text":"LinearAlgebra.LAPACK\nLinearAlgebra.LAPACK.gbtrf!\nLinearAlgebra.LAPACK.gbtrs!\nLinearAlgebra.LAPACK.gebal!\nLinearAlgebra.LAPACK.gebak!\nLinearAlgebra.LAPACK.gebrd!\nLinearAlgebra.LAPACK.gelqf!\nLinearAlgebra.LAPACK.geqlf!\nLinearAlgebra.LAPACK.geqrf!\nLinearAlgebra.LAPACK.geqp3!\nLinearAlgebra.LAPACK.gerqf!\nLinearAlgebra.LAPACK.geqrt!\nLinearAlgebra.LAPACK.geqrt3!\nLinearAlgebra.LAPACK.getrf!\nLinearAlgebra.LAPACK.tzrzf!\nLinearAlgebra.LAPACK.ormrz!\nLinearAlgebra.LAPACK.gels!\nLinearAlgebra.LAPACK.gesv!\nLinearAlgebra.LAPACK.getrs!\nLinearAlgebra.LAPACK.getri!\nLinearAlgebra.LAPACK.gesvx!\nLinearAlgebra.LAPACK.gelsd!\nLinearAlgebra.LAPACK.gelsy!\nLinearAlgebra.LAPACK.gglse!\nLinearAlgebra.LAPACK.geev!\nLinearAlgebra.LAPACK.gesdd!\nLinearAlgebra.LAPACK.gesvd!\nLinearAlgebra.LAPACK.ggsvd!\nLinearAlgebra.LAPACK.ggsvd3!\nLinearAlgebra.LAPACK.geevx!\nLinearAlgebra.LAPACK.ggev!\nLinearAlgebra.LAPACK.gtsv!\nLinearAlgebra.LAPACK.gttrf!\nLinearAlgebra.LAPACK.gttrs!\nLinearAlgebra.LAPACK.orglq!\nLinearAlgebra.LAPACK.orgqr!\nLinearAlgebra.LAPACK.orgql!\nLinearAlgebra.LAPACK.orgrq!\nLinearAlgebra.LAPACK.ormlq!\nLinearAlgebra.LAPACK.ormqr!\nLinearAlgebra.LAPACK.ormql!\nLinearAlgebra.LAPACK.ormrq!\nLinearAlgebra.LAPACK.gemqrt!\nLinearAlgebra.LAPACK.posv!\nLinearAlgebra.LAPACK.potrf!\nLinearAlgebra.LAPACK.potri!\nLinearAlgebra.LAPACK.potrs!\nLinearAlgebra.LAPACK.pstrf!\nLinearAlgebra.LAPACK.ptsv!\nLinearAlgebra.LAPACK.pttrf!\nLinearAlgebra.LAPACK.pttrs!\nLinearAlgebra.LAPACK.trtri!\nLinearAlgebra.LAPACK.trtrs!\nLinearAlgebra.LAPACK.trcon!\nLinearAlgebra.LAPACK.trevc!\nLinearAlgebra.LAPACK.trrfs!\nLinearAlgebra.LAPACK.stev!\nLinearAlgebra.LAPACK.stebz!\nLinearAlgebra.LAPACK.stegr!\nLinearAlgebra.LAPACK.stein!\nLinearAlgebra.LAPACK.syconv!\nLinearAlgebra.LAPACK.sysv!\nLinearAlgebra.LAPACK.sytrf!\nLinearAlgebra.LAPACK.sytri!\nLinearAlgebra.LAPACK.sytrs!\nLinearAlgebra.LAPACK.hesv!\nLinearAlgebra.LAPACK.hetrf!\nLinearAlgebra.LAPACK.hetri!\nLinearAlgebra.LAPACK.hetrs!\nLinearAlgebra.LAPACK.syev!\nLinearAlgebra.LAPACK.syevr!\nLinearAlgebra.LAPACK.sygvd!\nLinearAlgebra.LAPACK.bdsqr!\nLinearAlgebra.LAPACK.bdsdc!\nLinearAlgebra.LAPACK.gecon!\nLinearAlgebra.LAPACK.gehrd!\nLinearAlgebra.LAPACK.orghr!\nLinearAlgebra.LAPACK.gees!\nLinearAlgebra.LAPACK.gges!\nLinearAlgebra.LAPACK.trexc!\nLinearAlgebra.LAPACK.trsen!\nLinearAlgebra.LAPACK.tgsen!\nLinearAlgebra.LAPACK.trsyl!","category":"page"},{"location":"stdlib/LinearAlgebra/#LinearAlgebra.LAPACK","page":"Linear Algebra","title":"LinearAlgebra.LAPACK","text":"Interfaces to LAPACK subroutines.\n\n\n\n\n\n","category":"module"},{"location":"stdlib/LinearAlgebra/#LinearAlgebra.LAPACK.gbtrf!","page":"Linear Algebra","title":"LinearAlgebra.LAPACK.gbtrf!","text":"gbtrf!(kl, ku, m, AB) -> (AB, ipiv)\n\nCompute the LU factorization of a banded matrix AB. kl is the first subdiagonal containing a nonzero band, ku is the last superdiagonal containing one, and m is the first dimension of the matrix AB. Returns the LU factorization in-place and ipiv, the vector of pivots used.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LinearAlgebra/#LinearAlgebra.LAPACK.gbtrs!","page":"Linear Algebra","title":"LinearAlgebra.LAPACK.gbtrs!","text":"gbtrs!(trans, kl, ku, m, AB, ipiv, B)\n\nSolve the equation AB * X = B. trans determines the orientation of AB. It may be N (no transpose), T (transpose), or C (conjugate transpose). kl is the first subdiagonal containing a nonzero band, ku is the last superdiagonal containing one, and m is the first dimension of the matrix AB. ipiv is the vector of pivots returned from gbtrf!. Returns the vector or matrix X, overwriting B in-place.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LinearAlgebra/#LinearAlgebra.LAPACK.gebal!","page":"Linear Algebra","title":"LinearAlgebra.LAPACK.gebal!","text":"gebal!(job, A) -> (ilo, ihi, scale)\n\nBalance the matrix A before computing its eigensystem or Schur factorization. job can be one of N (A will not be permuted or scaled), P (A will only be permuted), S (A will only be scaled), or B (A will be both permuted and scaled). Modifies A in-place and returns ilo, ihi, and scale. If permuting was turned on, A[i,j] = 0 if j > i and 1 < j < ilo or j > ihi. scale contains information about the scaling/permutations performed.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LinearAlgebra/#LinearAlgebra.LAPACK.gebak!","page":"Linear Algebra","title":"LinearAlgebra.LAPACK.gebak!","text":"gebak!(job, side, ilo, ihi, scale, V)\n\nTransform the eigenvectors V of a matrix balanced using gebal! to the unscaled/unpermuted eigenvectors of the original matrix. Modifies V in-place. side can be L (left eigenvectors are transformed) or R (right eigenvectors are transformed).\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LinearAlgebra/#LinearAlgebra.LAPACK.gebrd!","page":"Linear Algebra","title":"LinearAlgebra.LAPACK.gebrd!","text":"gebrd!(A) -> (A, d, e, tauq, taup)\n\nReduce A in-place to bidiagonal form A = QBP'. Returns A, containing the bidiagonal matrix B; d, containing the diagonal elements of B; e, containing the off-diagonal elements of B; tauq, containing the elementary reflectors representing Q; and taup, containing the elementary reflectors representing P.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LinearAlgebra/#LinearAlgebra.LAPACK.gelqf!","page":"Linear Algebra","title":"LinearAlgebra.LAPACK.gelqf!","text":"gelqf!(A, tau)\n\nCompute the LQ factorization of A, A = LQ. tau contains scalars which parameterize the elementary reflectors of the factorization. tau must have length greater than or equal to the smallest dimension of A.\n\nReturns A and tau modified in-place.\n\n\n\n\n\ngelqf!(A) -> (A, tau)\n\nCompute the LQ factorization of A, A = LQ.\n\nReturns A, modified in-place, and tau, which contains scalars which parameterize the elementary reflectors of the factorization.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LinearAlgebra/#LinearAlgebra.LAPACK.geqlf!","page":"Linear Algebra","title":"LinearAlgebra.LAPACK.geqlf!","text":"geqlf!(A, tau)\n\nCompute the QL factorization of A, A = QL. tau contains scalars which parameterize the elementary reflectors of the factorization. tau must have length greater than or equal to the smallest dimension of A.\n\nReturns A and tau modified in-place.\n\n\n\n\n\ngeqlf!(A) -> (A, tau)\n\nCompute the QL factorization of A, A = QL.\n\nReturns A, modified in-place, and tau, which contains scalars which parameterize the elementary reflectors of the factorization.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LinearAlgebra/#LinearAlgebra.LAPACK.geqrf!","page":"Linear Algebra","title":"LinearAlgebra.LAPACK.geqrf!","text":"geqrf!(A, tau)\n\nCompute the QR factorization of A, A = QR. tau contains scalars which parameterize the elementary reflectors of the factorization. tau must have length greater than or equal to the smallest dimension of A.\n\nReturns A and tau modified in-place.\n\n\n\n\n\ngeqrf!(A) -> (A, tau)\n\nCompute the QR factorization of A, A = QR.\n\nReturns A, modified in-place, and tau, which contains scalars which parameterize the elementary reflectors of the factorization.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LinearAlgebra/#LinearAlgebra.LAPACK.geqp3!","page":"Linear Algebra","title":"LinearAlgebra.LAPACK.geqp3!","text":"geqp3!(A, [jpvt, tau]) -> (A, tau, jpvt)\n\nCompute the pivoted QR factorization of A, AP = QR using BLAS level 3. P is a pivoting matrix, represented by jpvt. tau stores the elementary reflectors. The arguments jpvt and tau are optional and allow for passing preallocated arrays. When passed, jpvt must have length greater than or equal to n if A is an (m x n) matrix and tau must have length greater than or equal to the smallest dimension of A.\n\nA, jpvt, and tau are modified in-place.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LinearAlgebra/#LinearAlgebra.LAPACK.gerqf!","page":"Linear Algebra","title":"LinearAlgebra.LAPACK.gerqf!","text":"gerqf!(A, tau)\n\nCompute the RQ factorization of A, A = RQ. tau contains scalars which parameterize the elementary reflectors of the factorization. tau must have length greater than or equal to the smallest dimension of A.\n\nReturns A and tau modified in-place.\n\n\n\n\n\ngerqf!(A) -> (A, tau)\n\nCompute the RQ factorization of A, A = RQ.\n\nReturns A, modified in-place, and tau, which contains scalars which parameterize the elementary reflectors of the factorization.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LinearAlgebra/#LinearAlgebra.LAPACK.geqrt!","page":"Linear Algebra","title":"LinearAlgebra.LAPACK.geqrt!","text":"geqrt!(A, T)\n\nCompute the blocked QR factorization of A, A = QR. T contains upper triangular block reflectors which parameterize the elementary reflectors of the factorization. The first dimension of T sets the block size and it must be between 1 and n. The second dimension of T must equal the smallest dimension of A.\n\nReturns A and T modified in-place.\n\n\n\n\n\ngeqrt!(A, nb) -> (A, T)\n\nCompute the blocked QR factorization of A, A = QR. nb sets the block size and it must be between 1 and n, the second dimension of A.\n\nReturns A, modified in-place, and T, which contains upper triangular block reflectors which parameterize the elementary reflectors of the factorization.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LinearAlgebra/#LinearAlgebra.LAPACK.geqrt3!","page":"Linear Algebra","title":"LinearAlgebra.LAPACK.geqrt3!","text":"geqrt3!(A, T)\n\nRecursively computes the blocked QR factorization of A, A = QR. T contains upper triangular block reflectors which parameterize the elementary reflectors of the factorization. The first dimension of T sets the block size and it must be between 1 and n. The second dimension of T must equal the smallest dimension of A.\n\nReturns A and T modified in-place.\n\n\n\n\n\ngeqrt3!(A) -> (A, T)\n\nRecursively computes the blocked QR factorization of A, A = QR.\n\nReturns A, modified in-place, and T, which contains upper triangular block reflectors which parameterize the elementary reflectors of the factorization.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LinearAlgebra/#LinearAlgebra.LAPACK.getrf!","page":"Linear Algebra","title":"LinearAlgebra.LAPACK.getrf!","text":"getrf!(A) -> (A, ipiv, info)\n\nCompute the pivoted LU factorization of A, A = LU.\n\nReturns A, modified in-place, ipiv, the pivoting information, and an info code which indicates success (info = 0), a singular value in U (info = i, in which case U[i,i] is singular), or an error code (info < 0).\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LinearAlgebra/#LinearAlgebra.LAPACK.tzrzf!","page":"Linear Algebra","title":"LinearAlgebra.LAPACK.tzrzf!","text":"tzrzf!(A) -> (A, tau)\n\nTransforms the upper trapezoidal matrix A to upper triangular form in-place. Returns A and tau, the scalar parameters for the elementary reflectors of the transformation.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LinearAlgebra/#LinearAlgebra.LAPACK.ormrz!","page":"Linear Algebra","title":"LinearAlgebra.LAPACK.ormrz!","text":"ormrz!(side, trans, A, tau, C)\n\nMultiplies the matrix C by Q from the transformation supplied by tzrzf!. Depending on side or trans the multiplication can be left-sided (side = L, Q*C) or right-sided (side = R, C*Q) and Q can be unmodified (trans = N), transposed (trans = T), or conjugate transposed (trans = C). Returns matrix C which is modified in-place with the result of the multiplication.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LinearAlgebra/#LinearAlgebra.LAPACK.gels!","page":"Linear Algebra","title":"LinearAlgebra.LAPACK.gels!","text":"gels!(trans, A, B) -> (F, B, ssr)\n\nSolves the linear equation A * X = B, transpose(A) * X = B, or adjoint(A) * X = B using a QR or LQ factorization. Modifies the matrix/vector B in place with the solution. A is overwritten with its QR or LQ factorization. trans may be one of N (no modification), T (transpose), or C (conjugate transpose). gels! searches for the minimum norm/least squares solution. A may be under or over determined. The solution is returned in B.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LinearAlgebra/#LinearAlgebra.LAPACK.gesv!","page":"Linear Algebra","title":"LinearAlgebra.LAPACK.gesv!","text":"gesv!(A, B) -> (B, A, ipiv)\n\nSolves the linear equation A * X = B where A is a square matrix using the LU factorization of A. A is overwritten with its LU factorization and B is overwritten with the solution X. ipiv contains the pivoting information for the LU factorization of A.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LinearAlgebra/#LinearAlgebra.LAPACK.getrs!","page":"Linear Algebra","title":"LinearAlgebra.LAPACK.getrs!","text":"getrs!(trans, A, ipiv, B)\n\nSolves the linear equation A * X = B, transpose(A) * X = B, or adjoint(A) * X = B for square A. Modifies the matrix/vector B in place with the solution. A is the LU factorization from getrf!, with ipiv the pivoting information. trans may be one of N (no modification), T (transpose), or C (conjugate transpose).\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LinearAlgebra/#LinearAlgebra.LAPACK.getri!","page":"Linear Algebra","title":"LinearAlgebra.LAPACK.getri!","text":"getri!(A, ipiv)\n\nComputes the inverse of A, using its LU factorization found by getrf!. ipiv is the pivot information output and A contains the LU factorization of getrf!. A is overwritten with its inverse.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LinearAlgebra/#LinearAlgebra.LAPACK.gesvx!","page":"Linear Algebra","title":"LinearAlgebra.LAPACK.gesvx!","text":"gesvx!(fact, trans, A, AF, ipiv, equed, R, C, B) -> (X, equed, R, C, B, rcond, ferr, berr, work)\n\nSolves the linear equation A * X = B (trans = N), transpose(A) * X = B (trans = T), or adjoint(A) * X = B (trans = C) using the LU factorization of A. fact may be E, in which case A will be equilibrated and copied to AF; F, in which case AF and ipiv from a previous LU factorization are inputs; or N, in which case A will be copied to AF and then factored. If fact = F, equed may be N, meaning A has not been equilibrated; R, meaning A was multiplied by Diagonal(R) from the left; C, meaning A was multiplied by Diagonal(C) from the right; or B, meaning A was multiplied by Diagonal(R) from the left and Diagonal(C) from the right. If fact = F and equed = R or B the elements of R must all be positive. If fact = F and equed = C or B the elements of C must all be positive.\n\nReturns the solution X; equed, which is an output if fact is not N, and describes the equilibration that was performed; R, the row equilibration diagonal; C, the column equilibration diagonal; B, which may be overwritten with its equilibrated form Diagonal(R)*B (if trans = N and equed = R,B) or Diagonal(C)*B (if trans = T,C and equed = C,B); rcond, the reciprocal condition number of A after equilbrating; ferr, the forward error bound for each solution vector in X; berr, the forward error bound for each solution vector in X; and work, the reciprocal pivot growth factor.\n\n\n\n\n\ngesvx!(A, B)\n\nThe no-equilibration, no-transpose simplification of gesvx!.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LinearAlgebra/#LinearAlgebra.LAPACK.gelsd!","page":"Linear Algebra","title":"LinearAlgebra.LAPACK.gelsd!","text":"gelsd!(A, B, rcond) -> (B, rnk)\n\nComputes the least norm solution of A * X = B by finding the SVD factorization of A, then dividing-and-conquering the problem. B is overwritten with the solution X. Singular values below rcond will be treated as zero. Returns the solution in B and the effective rank of A in rnk.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LinearAlgebra/#LinearAlgebra.LAPACK.gelsy!","page":"Linear Algebra","title":"LinearAlgebra.LAPACK.gelsy!","text":"gelsy!(A, B, rcond) -> (B, rnk)\n\nComputes the least norm solution of A * X = B by finding the full QR factorization of A, then dividing-and-conquering the problem. B is overwritten with the solution X. Singular values below rcond will be treated as zero. Returns the solution in B and the effective rank of A in rnk.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LinearAlgebra/#LinearAlgebra.LAPACK.gglse!","page":"Linear Algebra","title":"LinearAlgebra.LAPACK.gglse!","text":"gglse!(A, c, B, d) -> (X,res)\n\nSolves the equation A * x = c where x is subject to the equality constraint B * x = d. Uses the formula ||c - A*x||^2 = 0 to solve. Returns X and the residual sum-of-squares.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LinearAlgebra/#LinearAlgebra.LAPACK.geev!","page":"Linear Algebra","title":"LinearAlgebra.LAPACK.geev!","text":"geev!(jobvl, jobvr, A) -> (W, VL, VR)\n\nFinds the eigensystem of A. If jobvl = N, the left eigenvectors of A aren't computed. If jobvr = N, the right eigenvectors of A aren't computed. If jobvl = V or jobvr = V, the corresponding eigenvectors are computed. Returns the eigenvalues in W, the right eigenvectors in VR, and the left eigenvectors in VL.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LinearAlgebra/#LinearAlgebra.LAPACK.gesdd!","page":"Linear Algebra","title":"LinearAlgebra.LAPACK.gesdd!","text":"gesdd!(job, A) -> (U, S, VT)\n\nFinds the singular value decomposition of A, A = U * S * V', using a divide and conquer approach. If job = A, all the columns of U and the rows of V' are computed. If job = N, no columns of U or rows of V' are computed. If job = O, A is overwritten with the columns of (thin) U and the rows of (thin) V'. If job = S, the columns of (thin) U and the rows of (thin) V' are computed and returned separately.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LinearAlgebra/#LinearAlgebra.LAPACK.gesvd!","page":"Linear Algebra","title":"LinearAlgebra.LAPACK.gesvd!","text":"gesvd!(jobu, jobvt, A) -> (U, S, VT)\n\nFinds the singular value decomposition of A, A = U * S * V'. If jobu = A, all the columns of U are computed. If jobvt = A all the rows of V' are computed. If jobu = N, no columns of U are computed. If jobvt = N no rows of V' are computed. If jobu = O, A is overwritten with the columns of (thin) U. If jobvt = O, A is overwritten with the rows of (thin) V'. If jobu = S, the columns of (thin) U are computed and returned separately. If jobvt = S the rows of (thin) V' are computed and returned separately. jobu and jobvt can't both be O.\n\nReturns U, S, and Vt, where S are the singular values of A.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LinearAlgebra/#LinearAlgebra.LAPACK.ggsvd!","page":"Linear Algebra","title":"LinearAlgebra.LAPACK.ggsvd!","text":"ggsvd!(jobu, jobv, jobq, A, B) -> (U, V, Q, alpha, beta, k, l, R)\n\nFinds the generalized singular value decomposition of A and B, U'*A*Q = D1*R and V'*B*Q = D2*R. D1 has alpha on its diagonal and D2 has beta on its diagonal. If jobu = U, the orthogonal/unitary matrix U is computed. If jobv = V the orthogonal/unitary matrix V is computed. If jobq = Q, the orthogonal/unitary matrix Q is computed. If jobu, jobv or jobq is N, that matrix is not computed. This function is only available in LAPACK versions prior to 3.6.0.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LinearAlgebra/#LinearAlgebra.LAPACK.ggsvd3!","page":"Linear Algebra","title":"LinearAlgebra.LAPACK.ggsvd3!","text":"ggsvd3!(jobu, jobv, jobq, A, B) -> (U, V, Q, alpha, beta, k, l, R)\n\nFinds the generalized singular value decomposition of A and B, U'*A*Q = D1*R and V'*B*Q = D2*R. D1 has alpha on its diagonal and D2 has beta on its diagonal. If jobu = U, the orthogonal/unitary matrix U is computed. If jobv = V the orthogonal/unitary matrix V is computed. If jobq = Q, the orthogonal/unitary matrix Q is computed. If jobu, jobv, or jobq is N, that matrix is not computed. This function requires LAPACK 3.6.0.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LinearAlgebra/#LinearAlgebra.LAPACK.geevx!","page":"Linear Algebra","title":"LinearAlgebra.LAPACK.geevx!","text":"geevx!(balanc, jobvl, jobvr, sense, A) -> (A, w, VL, VR, ilo, ihi, scale, abnrm, rconde, rcondv)\n\nFinds the eigensystem of A with matrix balancing. If jobvl = N, the left eigenvectors of A aren't computed. If jobvr = N, the right eigenvectors of A aren't computed. If jobvl = V or jobvr = V, the corresponding eigenvectors are computed. If balanc = N, no balancing is performed. If balanc = P, A is permuted but not scaled. If balanc = S, A is scaled but not permuted. If balanc = B, A is permuted and scaled. If sense = N, no reciprocal condition numbers are computed. If sense = E, reciprocal condition numbers are computed for the eigenvalues only. If sense = V, reciprocal condition numbers are computed for the right eigenvectors only. If sense = B, reciprocal condition numbers are computed for the right eigenvectors and the eigenvectors. If sense = E,B, the right and left eigenvectors must be computed.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LinearAlgebra/#LinearAlgebra.LAPACK.ggev!","page":"Linear Algebra","title":"LinearAlgebra.LAPACK.ggev!","text":"ggev!(jobvl, jobvr, A, B) -> (alpha, beta, vl, vr)\n\nFinds the generalized eigendecomposition of A and B. If jobvl = N, the left eigenvectors aren't computed. If jobvr = N, the right eigenvectors aren't computed. If jobvl = V or jobvr = V, the corresponding eigenvectors are computed.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LinearAlgebra/#LinearAlgebra.LAPACK.gtsv!","page":"Linear Algebra","title":"LinearAlgebra.LAPACK.gtsv!","text":"gtsv!(dl, d, du, B)\n\nSolves the equation A * X = B where A is a tridiagonal matrix with dl on the subdiagonal, d on the diagonal, and du on the superdiagonal.\n\nOverwrites B with the solution X and returns it.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LinearAlgebra/#LinearAlgebra.LAPACK.gttrf!","page":"Linear Algebra","title":"LinearAlgebra.LAPACK.gttrf!","text":"gttrf!(dl, d, du) -> (dl, d, du, du2, ipiv)\n\nFinds the LU factorization of a tridiagonal matrix with dl on the subdiagonal, d on the diagonal, and du on the superdiagonal.\n\nModifies dl, d, and du in-place and returns them and the second superdiagonal du2 and the pivoting vector ipiv.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LinearAlgebra/#LinearAlgebra.LAPACK.gttrs!","page":"Linear Algebra","title":"LinearAlgebra.LAPACK.gttrs!","text":"gttrs!(trans, dl, d, du, du2, ipiv, B)\n\nSolves the equation A * X = B (trans = N), transpose(A) * X = B (trans = T), or adjoint(A) * X = B (trans = C) using the LU factorization computed by gttrf!. B is overwritten with the solution X.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LinearAlgebra/#LinearAlgebra.LAPACK.orglq!","page":"Linear Algebra","title":"LinearAlgebra.LAPACK.orglq!","text":"orglq!(A, tau, k = length(tau))\n\nExplicitly finds the matrix Q of a LQ factorization after calling gelqf! on A. Uses the output of gelqf!. A is overwritten by Q.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LinearAlgebra/#LinearAlgebra.LAPACK.orgqr!","page":"Linear Algebra","title":"LinearAlgebra.LAPACK.orgqr!","text":"orgqr!(A, tau, k = length(tau))\n\nExplicitly finds the matrix Q of a QR factorization after calling geqrf! on A. Uses the output of geqrf!. A is overwritten by Q.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LinearAlgebra/#LinearAlgebra.LAPACK.orgql!","page":"Linear Algebra","title":"LinearAlgebra.LAPACK.orgql!","text":"orgql!(A, tau, k = length(tau))\n\nExplicitly finds the matrix Q of a QL factorization after calling geqlf! on A. Uses the output of geqlf!. A is overwritten by Q.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LinearAlgebra/#LinearAlgebra.LAPACK.orgrq!","page":"Linear Algebra","title":"LinearAlgebra.LAPACK.orgrq!","text":"orgrq!(A, tau, k = length(tau))\n\nExplicitly finds the matrix Q of a RQ factorization after calling gerqf! on A. Uses the output of gerqf!. A is overwritten by Q.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LinearAlgebra/#LinearAlgebra.LAPACK.ormlq!","page":"Linear Algebra","title":"LinearAlgebra.LAPACK.ormlq!","text":"ormlq!(side, trans, A, tau, C)\n\nComputes Q * C (trans = N), transpose(Q) * C (trans = T), adjoint(Q) * C (trans = C) for side = L or the equivalent right-sided multiplication for side = R using Q from a LQ factorization of A computed using gelqf!. C is overwritten.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LinearAlgebra/#LinearAlgebra.LAPACK.ormqr!","page":"Linear Algebra","title":"LinearAlgebra.LAPACK.ormqr!","text":"ormqr!(side, trans, A, tau, C)\n\nComputes Q * C (trans = N), transpose(Q) * C (trans = T), adjoint(Q) * C (trans = C) for side = L or the equivalent right-sided multiplication for side = R using Q from a QR factorization of A computed using geqrf!. C is overwritten.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LinearAlgebra/#LinearAlgebra.LAPACK.ormql!","page":"Linear Algebra","title":"LinearAlgebra.LAPACK.ormql!","text":"ormql!(side, trans, A, tau, C)\n\nComputes Q * C (trans = N), transpose(Q) * C (trans = T), adjoint(Q) * C (trans = C) for side = L or the equivalent right-sided multiplication for side = R using Q from a QL factorization of A computed using geqlf!. C is overwritten.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LinearAlgebra/#LinearAlgebra.LAPACK.ormrq!","page":"Linear Algebra","title":"LinearAlgebra.LAPACK.ormrq!","text":"ormrq!(side, trans, A, tau, C)\n\nComputes Q * C (trans = N), transpose(Q) * C (trans = T), adjoint(Q) * C (trans = C) for side = L or the equivalent right-sided multiplication for side = R using Q from a RQ factorization of A computed using gerqf!. C is overwritten.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LinearAlgebra/#LinearAlgebra.LAPACK.gemqrt!","page":"Linear Algebra","title":"LinearAlgebra.LAPACK.gemqrt!","text":"gemqrt!(side, trans, V, T, C)\n\nComputes Q * C (trans = N), transpose(Q) * C (trans = T), adjoint(Q) * C (trans = C) for side = L or the equivalent right-sided multiplication for side = R using Q from a QR factorization of A computed using geqrt!. C is overwritten.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LinearAlgebra/#LinearAlgebra.LAPACK.posv!","page":"Linear Algebra","title":"LinearAlgebra.LAPACK.posv!","text":"posv!(uplo, A, B) -> (A, B)\n\nFinds the solution to A * X = B where A is a symmetric or Hermitian positive definite matrix. If uplo = U the upper Cholesky decomposition of A is computed. If uplo = L the lower Cholesky decomposition of A is computed. A is overwritten by its Cholesky decomposition. B is overwritten with the solution X.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LinearAlgebra/#LinearAlgebra.LAPACK.potrf!","page":"Linear Algebra","title":"LinearAlgebra.LAPACK.potrf!","text":"potrf!(uplo, A)\n\nComputes the Cholesky (upper if uplo = U, lower if uplo = L) decomposition of positive-definite matrix A. A is overwritten and returned with an info code.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LinearAlgebra/#LinearAlgebra.LAPACK.potri!","page":"Linear Algebra","title":"LinearAlgebra.LAPACK.potri!","text":"potri!(uplo, A)\n\nComputes the inverse of positive-definite matrix A after calling potrf! to find its (upper if uplo = U, lower if uplo = L) Cholesky decomposition.\n\nA is overwritten by its inverse and returned.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LinearAlgebra/#LinearAlgebra.LAPACK.potrs!","page":"Linear Algebra","title":"LinearAlgebra.LAPACK.potrs!","text":"potrs!(uplo, A, B)\n\nFinds the solution to A * X = B where A is a symmetric or Hermitian positive definite matrix whose Cholesky decomposition was computed by potrf!. If uplo = U the upper Cholesky decomposition of A was computed. If uplo = L the lower Cholesky decomposition of A was computed. B is overwritten with the solution X.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LinearAlgebra/#LinearAlgebra.LAPACK.pstrf!","page":"Linear Algebra","title":"LinearAlgebra.LAPACK.pstrf!","text":"pstrf!(uplo, A, tol) -> (A, piv, rank, info)\n\nComputes the (upper if uplo = U, lower if uplo = L) pivoted Cholesky decomposition of positive-definite matrix A with a user-set tolerance tol. A is overwritten by its Cholesky decomposition.\n\nReturns A, the pivots piv, the rank of A, and an info code. If info = 0, the factorization succeeded. If info = i > 0, then A is indefinite or rank-deficient.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LinearAlgebra/#LinearAlgebra.LAPACK.ptsv!","page":"Linear Algebra","title":"LinearAlgebra.LAPACK.ptsv!","text":"ptsv!(D, E, B)\n\nSolves A * X = B for positive-definite tridiagonal A. D is the diagonal of A and E is the off-diagonal. B is overwritten with the solution X and returned.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LinearAlgebra/#LinearAlgebra.LAPACK.pttrf!","page":"Linear Algebra","title":"LinearAlgebra.LAPACK.pttrf!","text":"pttrf!(D, E)\n\nComputes the LDLt factorization of a positive-definite tridiagonal matrix with D as diagonal and E as off-diagonal. D and E are overwritten and returned.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LinearAlgebra/#LinearAlgebra.LAPACK.pttrs!","page":"Linear Algebra","title":"LinearAlgebra.LAPACK.pttrs!","text":"pttrs!(D, E, B)\n\nSolves A * X = B for positive-definite tridiagonal A with diagonal D and off-diagonal E after computing A's LDLt factorization using pttrf!. B is overwritten with the solution X.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LinearAlgebra/#LinearAlgebra.LAPACK.trtri!","page":"Linear Algebra","title":"LinearAlgebra.LAPACK.trtri!","text":"trtri!(uplo, diag, A)\n\nFinds the inverse of (upper if uplo = U, lower if uplo = L) triangular matrix A. If diag = N, A has non-unit diagonal elements. If diag = U, all diagonal elements of A are one. A is overwritten with its inverse.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LinearAlgebra/#LinearAlgebra.LAPACK.trtrs!","page":"Linear Algebra","title":"LinearAlgebra.LAPACK.trtrs!","text":"trtrs!(uplo, trans, diag, A, B)\n\nSolves A * X = B (trans = N), transpose(A) * X = B (trans = T), or adjoint(A) * X = B (trans = C) for (upper if uplo = U, lower if uplo = L) triangular matrix A. If diag = N, A has non-unit diagonal elements. If diag = U, all diagonal elements of A are one. B is overwritten with the solution X.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LinearAlgebra/#LinearAlgebra.LAPACK.trcon!","page":"Linear Algebra","title":"LinearAlgebra.LAPACK.trcon!","text":"trcon!(norm, uplo, diag, A)\n\nFinds the reciprocal condition number of (upper if uplo = U, lower if uplo = L) triangular matrix A. If diag = N, A has non-unit diagonal elements. If diag = U, all diagonal elements of A are one. If norm = I, the condition number is found in the infinity norm. If norm = O or 1, the condition number is found in the one norm.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LinearAlgebra/#LinearAlgebra.LAPACK.trevc!","page":"Linear Algebra","title":"LinearAlgebra.LAPACK.trevc!","text":"trevc!(side, howmny, select, T, VL = similar(T), VR = similar(T))\n\nFinds the eigensystem of an upper triangular matrix T. If side = R, the right eigenvectors are computed. If side = L, the left eigenvectors are computed. If side = B, both sets are computed. If howmny = A, all eigenvectors are found. If howmny = B, all eigenvectors are found and backtransformed using VL and VR. If howmny = S, only the eigenvectors corresponding to the values in select are computed.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LinearAlgebra/#LinearAlgebra.LAPACK.trrfs!","page":"Linear Algebra","title":"LinearAlgebra.LAPACK.trrfs!","text":"trrfs!(uplo, trans, diag, A, B, X, Ferr, Berr) -> (Ferr, Berr)\n\nEstimates the error in the solution to A * X = B (trans = N), transpose(A) * X = B (trans = T), adjoint(A) * X = B (trans = C) for side = L, or the equivalent equations a right-handed side = R X * A after computing X using trtrs!. If uplo = U, A is upper triangular. If uplo = L, A is lower triangular. If diag = N, A has non-unit diagonal elements. If diag = U, all diagonal elements of A are one. Ferr and Berr are optional inputs. Ferr is the forward error and Berr is the backward error, each component-wise.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LinearAlgebra/#LinearAlgebra.LAPACK.stev!","page":"Linear Algebra","title":"LinearAlgebra.LAPACK.stev!","text":"stev!(job, dv, ev) -> (dv, Zmat)\n\nComputes the eigensystem for a symmetric tridiagonal matrix with dv as diagonal and ev as off-diagonal. If job = N only the eigenvalues are found and returned in dv. If job = V then the eigenvectors are also found and returned in Zmat.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LinearAlgebra/#LinearAlgebra.LAPACK.stebz!","page":"Linear Algebra","title":"LinearAlgebra.LAPACK.stebz!","text":"stebz!(range, order, vl, vu, il, iu, abstol, dv, ev) -> (dv, iblock, isplit)\n\nComputes the eigenvalues for a symmetric tridiagonal matrix with dv as diagonal and ev as off-diagonal. If range = A, all the eigenvalues are found. If range = V, the eigenvalues in the half-open interval (vl, vu] are found. If range = I, the eigenvalues with indices between il and iu are found. If order = B, eigvalues are ordered within a block. If order = E, they are ordered across all the blocks. abstol can be set as a tolerance for convergence.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LinearAlgebra/#LinearAlgebra.LAPACK.stegr!","page":"Linear Algebra","title":"LinearAlgebra.LAPACK.stegr!","text":"stegr!(jobz, range, dv, ev, vl, vu, il, iu) -> (w, Z)\n\nComputes the eigenvalues (jobz = N) or eigenvalues and eigenvectors (jobz = V) for a symmetric tridiagonal matrix with dv as diagonal and ev as off-diagonal. If range = A, all the eigenvalues are found. If range = V, the eigenvalues in the half-open interval (vl, vu] are found. If range = I, the eigenvalues with indices between il and iu are found. The eigenvalues are returned in w and the eigenvectors in Z.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LinearAlgebra/#LinearAlgebra.LAPACK.stein!","page":"Linear Algebra","title":"LinearAlgebra.LAPACK.stein!","text":"stein!(dv, ev_in, w_in, iblock_in, isplit_in)\n\nComputes the eigenvectors for a symmetric tridiagonal matrix with dv as diagonal and ev_in as off-diagonal. w_in specifies the input eigenvalues for which to find corresponding eigenvectors. iblock_in specifies the submatrices corresponding to the eigenvalues in w_in. isplit_in specifies the splitting points between the submatrix blocks.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LinearAlgebra/#LinearAlgebra.LAPACK.syconv!","page":"Linear Algebra","title":"LinearAlgebra.LAPACK.syconv!","text":"syconv!(uplo, A, ipiv) -> (A, work)\n\nConverts a symmetric matrix A (which has been factorized into a triangular matrix) into two matrices L and D. If uplo = U, A is upper triangular. If uplo = L, it is lower triangular. ipiv is the pivot vector from the triangular factorization. A is overwritten by L and D.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LinearAlgebra/#LinearAlgebra.LAPACK.sysv!","page":"Linear Algebra","title":"LinearAlgebra.LAPACK.sysv!","text":"sysv!(uplo, A, B) -> (B, A, ipiv)\n\nFinds the solution to A * X = B for symmetric matrix A. If uplo = U, the upper half of A is stored. If uplo = L, the lower half is stored. B is overwritten by the solution X. A is overwritten by its Bunch-Kaufman factorization. ipiv contains pivoting information about the factorization.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LinearAlgebra/#LinearAlgebra.LAPACK.sytrf!","page":"Linear Algebra","title":"LinearAlgebra.LAPACK.sytrf!","text":"sytrf!(uplo, A) -> (A, ipiv, info)\n\nComputes the Bunch-Kaufman factorization of a symmetric matrix A. If uplo = U, the upper half of A is stored. If uplo = L, the lower half is stored.\n\nReturns A, overwritten by the factorization, a pivot vector ipiv, and the error code info which is a non-negative integer. If info is positive the matrix is singular and the diagonal part of the factorization is exactly zero at position info.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LinearAlgebra/#LinearAlgebra.LAPACK.sytri!","page":"Linear Algebra","title":"LinearAlgebra.LAPACK.sytri!","text":"sytri!(uplo, A, ipiv)\n\nComputes the inverse of a symmetric matrix A using the results of sytrf!. If uplo = U, the upper half of A is stored. If uplo = L, the lower half is stored. A is overwritten by its inverse.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LinearAlgebra/#LinearAlgebra.LAPACK.sytrs!","page":"Linear Algebra","title":"LinearAlgebra.LAPACK.sytrs!","text":"sytrs!(uplo, A, ipiv, B)\n\nSolves the equation A * X = B for a symmetric matrix A using the results of sytrf!. If uplo = U, the upper half of A is stored. If uplo = L, the lower half is stored. B is overwritten by the solution X.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LinearAlgebra/#LinearAlgebra.LAPACK.hesv!","page":"Linear Algebra","title":"LinearAlgebra.LAPACK.hesv!","text":"hesv!(uplo, A, B) -> (B, A, ipiv)\n\nFinds the solution to A * X = B for Hermitian matrix A. If uplo = U, the upper half of A is stored. If uplo = L, the lower half is stored. B is overwritten by the solution X. A is overwritten by its Bunch-Kaufman factorization. ipiv contains pivoting information about the factorization.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LinearAlgebra/#LinearAlgebra.LAPACK.hetrf!","page":"Linear Algebra","title":"LinearAlgebra.LAPACK.hetrf!","text":"hetrf!(uplo, A) -> (A, ipiv, info)\n\nComputes the Bunch-Kaufman factorization of a Hermitian matrix A. If uplo = U, the upper half of A is stored. If uplo = L, the lower half is stored.\n\nReturns A, overwritten by the factorization, a pivot vector ipiv, and the error code info which is a non-negative integer. If info is positive the matrix is singular and the diagonal part of the factorization is exactly zero at position info.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LinearAlgebra/#LinearAlgebra.LAPACK.hetri!","page":"Linear Algebra","title":"LinearAlgebra.LAPACK.hetri!","text":"hetri!(uplo, A, ipiv)\n\nComputes the inverse of a Hermitian matrix A using the results of sytrf!. If uplo = U, the upper half of A is stored. If uplo = L, the lower half is stored. A is overwritten by its inverse.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LinearAlgebra/#LinearAlgebra.LAPACK.hetrs!","page":"Linear Algebra","title":"LinearAlgebra.LAPACK.hetrs!","text":"hetrs!(uplo, A, ipiv, B)\n\nSolves the equation A * X = B for a Hermitian matrix A using the results of sytrf!. If uplo = U, the upper half of A is stored. If uplo = L, the lower half is stored. B is overwritten by the solution X.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LinearAlgebra/#LinearAlgebra.LAPACK.syev!","page":"Linear Algebra","title":"LinearAlgebra.LAPACK.syev!","text":"syev!(jobz, uplo, A)\n\nFinds the eigenvalues (jobz = N) or eigenvalues and eigenvectors (jobz = V) of a symmetric matrix A. If uplo = U, the upper triangle of A is used. If uplo = L, the lower triangle of A is used.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LinearAlgebra/#LinearAlgebra.LAPACK.syevr!","page":"Linear Algebra","title":"LinearAlgebra.LAPACK.syevr!","text":"syevr!(jobz, range, uplo, A, vl, vu, il, iu, abstol) -> (W, Z)\n\nFinds the eigenvalues (jobz = N) or eigenvalues and eigenvectors (jobz = V) of a symmetric matrix A. If uplo = U, the upper triangle of A is used. If uplo = L, the lower triangle of A is used. If range = A, all the eigenvalues are found. If range = V, the eigenvalues in the half-open interval (vl, vu] are found. If range = I, the eigenvalues with indices between il and iu are found. abstol can be set as a tolerance for convergence.\n\nThe eigenvalues are returned in W and the eigenvectors in Z.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LinearAlgebra/#LinearAlgebra.LAPACK.sygvd!","page":"Linear Algebra","title":"LinearAlgebra.LAPACK.sygvd!","text":"sygvd!(itype, jobz, uplo, A, B) -> (w, A, B)\n\nFinds the generalized eigenvalues (jobz = N) or eigenvalues and eigenvectors (jobz = V) of a symmetric matrix A and symmetric positive-definite matrix B. If uplo = U, the upper triangles of A and B are used. If uplo = L, the lower triangles of A and B are used. If itype = 1, the problem to solve is A * x = lambda * B * x. If itype = 2, the problem to solve is A * B * x = lambda * x. If itype = 3, the problem to solve is B * A * x = lambda * x.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LinearAlgebra/#LinearAlgebra.LAPACK.bdsqr!","page":"Linear Algebra","title":"LinearAlgebra.LAPACK.bdsqr!","text":"bdsqr!(uplo, d, e_, Vt, U, C) -> (d, Vt, U, C)\n\nComputes the singular value decomposition of a bidiagonal matrix with d on the diagonal and e_ on the off-diagonal. If uplo = U, e_ is the superdiagonal. If uplo = L, e_ is the subdiagonal. Can optionally also compute the product Q' * C.\n\nReturns the singular values in d, and the matrix C overwritten with Q' * C.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LinearAlgebra/#LinearAlgebra.LAPACK.bdsdc!","page":"Linear Algebra","title":"LinearAlgebra.LAPACK.bdsdc!","text":"bdsdc!(uplo, compq, d, e_) -> (d, e, u, vt, q, iq)\n\nComputes the singular value decomposition of a bidiagonal matrix with d on the diagonal and e_ on the off-diagonal using a divide and conqueq method. If uplo = U, e_ is the superdiagonal. If uplo = L, e_ is the subdiagonal. If compq = N, only the singular values are found. If compq = I, the singular values and vectors are found. If compq = P, the singular values and vectors are found in compact form. Only works for real types.\n\nReturns the singular values in d, and if compq = P, the compact singular vectors in iq.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LinearAlgebra/#LinearAlgebra.LAPACK.gecon!","page":"Linear Algebra","title":"LinearAlgebra.LAPACK.gecon!","text":"gecon!(normtype, A, anorm)\n\nFinds the reciprocal condition number of matrix A. If normtype = I, the condition number is found in the infinity norm. If normtype = O or 1, the condition number is found in the one norm. A must be the result of getrf! and anorm is the norm of A in the relevant norm.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LinearAlgebra/#LinearAlgebra.LAPACK.gehrd!","page":"Linear Algebra","title":"LinearAlgebra.LAPACK.gehrd!","text":"gehrd!(ilo, ihi, A) -> (A, tau)\n\nConverts a matrix A to Hessenberg form. If A is balanced with gebal! then ilo and ihi are the outputs of gebal!. Otherwise they should be ilo = 1 and ihi = size(A,2). tau contains the elementary reflectors of the factorization.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LinearAlgebra/#LinearAlgebra.LAPACK.orghr!","page":"Linear Algebra","title":"LinearAlgebra.LAPACK.orghr!","text":"orghr!(ilo, ihi, A, tau)\n\nExplicitly finds Q, the orthogonal/unitary matrix from gehrd!. ilo, ihi, A, and tau must correspond to the input/output to gehrd!.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LinearAlgebra/#LinearAlgebra.LAPACK.gees!","page":"Linear Algebra","title":"LinearAlgebra.LAPACK.gees!","text":"gees!(jobvs, A) -> (A, vs, w)\n\nComputes the eigenvalues (jobvs = N) or the eigenvalues and Schur vectors (jobvs = V) of matrix A. A is overwritten by its Schur form.\n\nReturns A, vs containing the Schur vectors, and w, containing the eigenvalues.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LinearAlgebra/#LinearAlgebra.LAPACK.gges!","page":"Linear Algebra","title":"LinearAlgebra.LAPACK.gges!","text":"gges!(jobvsl, jobvsr, A, B) -> (A, B, alpha, beta, vsl, vsr)\n\nComputes the generalized eigenvalues, generalized Schur form, left Schur vectors (jobsvl = V), or right Schur vectors (jobvsr = V) of A and B.\n\nThe generalized eigenvalues are returned in alpha and beta. The left Schur vectors are returned in vsl and the right Schur vectors are returned in vsr.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LinearAlgebra/#LinearAlgebra.LAPACK.trexc!","page":"Linear Algebra","title":"LinearAlgebra.LAPACK.trexc!","text":"trexc!(compq, ifst, ilst, T, Q) -> (T, Q)\ntrexc!(ifst, ilst, T, Q) -> (T, Q)\n\nReorder the Schur factorization T of a matrix, such that the diagonal block of T with row index ifst is moved to row index ilst. If compq = V, the Schur vectors Q are reordered. If compq = N they are not modified. The 4-arg method calls the 5-arg method with compq = V.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LinearAlgebra/#LinearAlgebra.LAPACK.trsen!","page":"Linear Algebra","title":"LinearAlgebra.LAPACK.trsen!","text":"trsen!(job, compq, select, T, Q) -> (T, Q, w, s, sep)\ntrsen!(select, T, Q) -> (T, Q, w, s, sep)\n\nReorder the Schur factorization of a matrix and optionally finds reciprocal condition numbers. If job = N, no condition numbers are found. If job = E, only the condition number for this cluster of eigenvalues is found. If job = V, only the condition number for the invariant subspace is found. If job = B then the condition numbers for the cluster and subspace are found. If compq = V the Schur vectors Q are updated. If compq = N the Schur vectors are not modified. select determines which eigenvalues are in the cluster. The 3-arg method calls the 5-arg method with job = N and compq = V.\n\nReturns T, Q, reordered eigenvalues in w, the condition number of the cluster of eigenvalues s, and the condition number of the invariant subspace sep.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LinearAlgebra/#LinearAlgebra.LAPACK.tgsen!","page":"Linear Algebra","title":"LinearAlgebra.LAPACK.tgsen!","text":"tgsen!(select, S, T, Q, Z) -> (S, T, alpha, beta, Q, Z)\n\nReorders the vectors of a generalized Schur decomposition. select specifies the eigenvalues in each cluster.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LinearAlgebra/#LinearAlgebra.LAPACK.trsyl!","page":"Linear Algebra","title":"LinearAlgebra.LAPACK.trsyl!","text":"trsyl!(transa, transb, A, B, C, isgn=1) -> (C, scale)\n\nSolves the Sylvester matrix equation A * X +/- X * B = scale*C where A and B are both quasi-upper triangular. If transa = N, A is not modified. If transa = T, A is transposed. If transa = C, A is conjugate transposed. Similarly for transb and B. If isgn = 1, the equation A * X + X * B = scale * C is solved. If isgn = -1, the equation A * X - X * B = scale * C is solved.\n\nReturns X (overwriting C) and scale.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/LinearAlgebra/","page":"Linear Algebra","title":"Linear Algebra","text":"DocTestSetup = nothing","category":"page"},{"location":"stdlib/Sockets/#套接字","page":"套接字","title":"套接字","text":"","category":"section"},{"location":"stdlib/Sockets/","page":"套接字","title":"套接字","text":"Sockets.Sockets\nSockets.connect(::TCPSocket, ::Integer)\nSockets.connect(::AbstractString)\nSockets.listen(::Any)\nSockets.listen(::AbstractString)\nSockets.getaddrinfo\nSockets.getipaddr\nSockets.getipaddrs\nSockets.islinklocaladdr\nSockets.getalladdrinfo\nSockets.DNSError\nSockets.getnameinfo\nSockets.getsockname\nSockets.getpeername\nSockets.IPAddr\nSockets.IPv4\nSockets.IPv6\nSockets.@ip_str\nSockets.TCPSocket\nSockets.UDPSocket\nSockets.accept\nSockets.listenany\nSockets.bind\nSockets.send\nSockets.recv\nSockets.recvfrom\nSockets.setopt\nSockets.nagle\nSockets.quickack","category":"page"},{"location":"stdlib/Sockets/#Sockets.Sockets","page":"套接字","title":"Sockets.Sockets","text":"Support for sockets. Provides IPAddr and subtypes, TCPSocket, and UDPSocket.\n\n\n\n\n\n","category":"module"},{"location":"stdlib/Sockets/#Sockets.connect-Tuple{TCPSocket, Integer}","page":"套接字","title":"Sockets.connect","text":"connect([host], port::Integer) -> TCPSocket\n\nConnect to the host host on port port.\n\n\n\n\n\n","category":"method"},{"location":"stdlib/Sockets/#Sockets.connect-Tuple{AbstractString}","page":"套接字","title":"Sockets.connect","text":"connect(path::AbstractString) -> PipeEndpoint\n\nConnect to the named pipe / UNIX domain socket at path.\n\nnote: Note\nPath length on Unix is limited to somewhere between 92 and 108 bytes (cf. man unix).\n\n\n\n\n\n","category":"method"},{"location":"stdlib/Sockets/#Sockets.listen-Tuple{Any}","page":"套接字","title":"Sockets.listen","text":"listen([addr, ]port::Integer; backlog::Integer=BACKLOG_DEFAULT) -> TCPServer\n\nListen on port on the address specified by addr. By default this listens on localhost only. To listen on all interfaces pass IPv4(0) or IPv6(0) as appropriate. backlog determines how many connections can be pending (not having called accept) before the server will begin to reject them. The default value of backlog is 511.\n\n\n\n\n\n","category":"method"},{"location":"stdlib/Sockets/#Sockets.listen-Tuple{AbstractString}","page":"套接字","title":"Sockets.listen","text":"listen(path::AbstractString) -> PipeServer\n\nCreate and listen on a named pipe / UNIX domain socket.\n\nnote: Note\nPath length on Unix is limited to somewhere between 92 and 108 bytes (cf. man unix).\n\n\n\n\n\n","category":"method"},{"location":"stdlib/Sockets/#Sockets.getaddrinfo","page":"套接字","title":"Sockets.getaddrinfo","text":"getaddrinfo(host::AbstractString, IPAddr=IPv4) -> IPAddr\n\nGets the first IP address of the host of the specified IPAddr type. Uses the operating system's underlying getaddrinfo implementation, which may do a DNS lookup.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/Sockets/#Sockets.getipaddr","page":"套接字","title":"Sockets.getipaddr","text":"getipaddr() -> IPAddr\n\nGet an IP address of the local machine, preferring IPv4 over IPv6. Throws if no addresses are available.\n\ngetipaddr(addr_type::Type{T}) where T<:IPAddr -> T\n\nGet an IP address of the local machine of the specified type. Throws if no addresses of the specified type are available.\n\nThis function is a backwards-compatibility wrapper around getipaddrs. New applications should use getipaddrs instead.\n\nExamples\n\njulia> getipaddr()\nip\"192.168.1.28\"\n\njulia> getipaddr(IPv6)\nip\"fe80::9731:35af:e1c5:6e49\"\n\nSee also getipaddrs.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/Sockets/#Sockets.getipaddrs","page":"套接字","title":"Sockets.getipaddrs","text":"getipaddrs(addr_type::Type{T}=IPAddr; loopback::Bool=false) where T<:IPAddr -> Vector{T}\n\nGet the IP addresses of the local machine.\n\nSetting the optional addr_type parameter to IPv4 or IPv6 causes only addresses of that type to be returned.\n\nThe loopback keyword argument dictates whether loopback addresses (e.g. ip\"127.0.0.1\", ip\"::1\") are included.\n\ncompat: Julia 1.2\nThis function is available as of Julia 1.2.\n\nExamples\n\njulia> getipaddrs()\n5-element Array{IPAddr,1}:\n ip\"198.51.100.17\"\n ip\"203.0.113.2\"\n ip\"2001:db8:8:4:445e:5fff:fe5d:5500\"\n ip\"2001:db8:8:4:c164:402e:7e3c:3668\"\n ip\"fe80::445e:5fff:fe5d:5500\"\n\njulia> getipaddrs(IPv6)\n3-element Array{IPv6,1}:\n ip\"2001:db8:8:4:445e:5fff:fe5d:5500\"\n ip\"2001:db8:8:4:c164:402e:7e3c:3668\"\n ip\"fe80::445e:5fff:fe5d:5500\"\n\nSee also islinklocaladdr.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/Sockets/#Sockets.islinklocaladdr","page":"套接字","title":"Sockets.islinklocaladdr","text":"islinklocaladdr(addr::IPAddr)\n\nTests if an IP address is a link-local address. Link-local addresses are not guaranteed to be unique beyond their network segment, therefore routers do not forward them. Link-local addresses are from the address blocks 169.254.0.0/16 or fe80::/10.\n\nExample\n\nfilter(!islinklocaladdr, getipaddrs())\n\n\n\n\n\n","category":"function"},{"location":"stdlib/Sockets/#Sockets.getalladdrinfo","page":"套接字","title":"Sockets.getalladdrinfo","text":"getalladdrinfo(host::AbstractString) -> Vector{IPAddr}\n\nGets all of the IP addresses of the host. Uses the operating system's underlying getaddrinfo implementation, which may do a DNS lookup.\n\nExample\n\njulia> getalladdrinfo(\"google.com\")\n2-element Array{IPAddr,1}:\n ip\"172.217.6.174\"\n ip\"2607:f8b0:4000:804::200e\"\n\n\n\n\n\n","category":"function"},{"location":"stdlib/Sockets/#Sockets.DNSError","page":"套接字","title":"Sockets.DNSError","text":"DNSError\n\nThe type of exception thrown when an error occurs in DNS lookup. The host field indicates the host URL string. The code field indicates the error code based on libuv.\n\n\n\n\n\n","category":"type"},{"location":"stdlib/Sockets/#Sockets.getnameinfo","page":"套接字","title":"Sockets.getnameinfo","text":"getnameinfo(host::IPAddr) -> String\n\nPerforms a reverse-lookup for IP address to return a hostname and service using the operating system's underlying getnameinfo implementation.\n\nExamples\n\njulia> getnameinfo(Sockets.IPv4(\"8.8.8.8\"))\n\"google-public-dns-a.google.com\"\n\n\n\n\n\n","category":"function"},{"location":"stdlib/Sockets/#Sockets.getsockname","page":"套接字","title":"Sockets.getsockname","text":"getsockname(sock::Union{TCPServer, TCPSocket}) -> (IPAddr, UInt16)\n\nGet the IP address and port that the given socket is bound to.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/Sockets/#Sockets.getpeername","page":"套接字","title":"Sockets.getpeername","text":"getpeername(sock::TCPSocket) -> (IPAddr, UInt16)\n\nGet the IP address and port of the remote endpoint that the given socket is connected to. Valid only for connected TCP sockets.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/Sockets/#Sockets.IPAddr","page":"套接字","title":"Sockets.IPAddr","text":"IPAddr\n\nAbstract supertype for IP addresses. IPv4 and IPv6 are subtypes of this.\n\n\n\n\n\n","category":"type"},{"location":"stdlib/Sockets/#Sockets.IPv4","page":"套接字","title":"Sockets.IPv4","text":"IPv4(host::Integer) -> IPv4\n\nReturns an IPv4 object from ip address host formatted as an Integer.\n\nExamples\n\njulia> IPv4(3223256218)\nip\"192.30.252.154\"\n\n\n\n\n\n","category":"type"},{"location":"stdlib/Sockets/#Sockets.IPv6","page":"套接字","title":"Sockets.IPv6","text":"IPv6(host::Integer) -> IPv6\n\nReturns an IPv6 object from ip address host formatted as an Integer.\n\nExamples\n\njulia> IPv6(3223256218)\nip\"::c01e:fc9a\"\n\n\n\n\n\n","category":"type"},{"location":"stdlib/Sockets/#Sockets.@ip_str","page":"套接字","title":"Sockets.@ip_str","text":"@ip_str str -> IPAddr\n\nParse str as an IP address.\n\nExamples\n\njulia> ip\"127.0.0.1\"\nip\"127.0.0.1\"\n\njulia> @ip_str \"2001:db8:0:0:0:0:2:1\"\nip\"2001:db8::2:1\"\n\n\n\n\n\n","category":"macro"},{"location":"stdlib/Sockets/#Sockets.TCPSocket","page":"套接字","title":"Sockets.TCPSocket","text":"TCPSocket(; delay=true)\n\nOpen a TCP socket using libuv. If delay is true, libuv delays creation of the socket's file descriptor till the first bind call. TCPSocket has various fields to denote the state of the socket as well as its send/receive buffers.\n\n\n\n\n\n","category":"type"},{"location":"stdlib/Sockets/#Sockets.UDPSocket","page":"套接字","title":"Sockets.UDPSocket","text":"UDPSocket()\n\nOpen a UDP socket using libuv. UDPSocket has various fields to denote the state of the socket.\n\n\n\n\n\n","category":"type"},{"location":"stdlib/Sockets/#Sockets.accept","page":"套接字","title":"Sockets.accept","text":"accept(server[, client])\n\nAccepts a connection on the given server and returns a connection to the client. An uninitialized client stream may be provided, in which case it will be used instead of creating a new stream.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/Sockets/#Sockets.listenany","page":"套接字","title":"Sockets.listenany","text":"listenany([host::IPAddr,] port_hint) -> (UInt16, TCPServer)\n\nCreate a TCPServer on any port, using hint as a starting point. Returns a tuple of the actual port that the server was created on and the server itself.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/Sockets/#Base.bind","page":"套接字","title":"Base.bind","text":"bind(chnl::Channel, task::Task)\n\nAssociate the lifetime of chnl with a task. Channel chnl is automatically closed when the task terminates. Any uncaught exception in the task is propagated to all waiters on chnl.\n\nThe chnl object can be explicitly closed independent of task termination. Terminating tasks have no effect on already closed Channel objects.\n\nWhen a channel is bound to multiple tasks, the first task to terminate will close the channel. When multiple channels are bound to the same task, termination of the task will close all of the bound channels.\n\nExamples\n\njulia> c = Channel(0);\n\njulia> task = @async foreach(i->put!(c, i), 1:4);\n\njulia> bind(c,task);\n\njulia> for i in c\n @show i\n end;\ni = 1\ni = 2\ni = 3\ni = 4\n\njulia> isopen(c)\nfalse\n\njulia> c = Channel(0);\n\njulia> task = @async (put!(c, 1); error(\"foo\"));\n\njulia> bind(c, task);\n\njulia> take!(c)\n1\n\njulia> put!(c, 1);\nERROR: TaskFailedException\nStacktrace:\n[...]\n nested task error: foo\n[...]\n\n\n\n\n\nbind(socket::Union{TCPServer, UDPSocket, TCPSocket}, host::IPAddr, port::Integer; ipv6only=false, reuseaddr=false, kws...)\n\nBind socket to the given host:port. Note that 0.0.0.0 will listen on all devices.\n\nThe ipv6only parameter disables dual stack mode. If ipv6only=true, only an IPv6 stack is created.\nIf reuseaddr=true, multiple threads or processes can bind to the same address without error if they all set reuseaddr=true, but only the last to bind will receive any traffic.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/Sockets/#Sockets.send","page":"套接字","title":"Sockets.send","text":"send(socket::UDPSocket, host::IPAddr, port::Integer, msg)\n\nSend msg over socket to host:port.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/Sockets/#Sockets.recv","page":"套接字","title":"Sockets.recv","text":"recv(socket::UDPSocket)\n\nRead a UDP packet from the specified socket, and return the bytes received. This call blocks.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/Sockets/#Sockets.recvfrom","page":"套接字","title":"Sockets.recvfrom","text":"recvfrom(socket::UDPSocket) -> (host_port, data)\n\nRead a UDP packet from the specified socket, returning a tuple of (host_port, data), where host_port will be an InetAddr{IPv4} or InetAddr{IPv6}, as appropriate.\n\ncompat: Julia 1.3\nPrior to Julia version 1.3, the first returned value was an address (IPAddr). In version 1.3 it was changed to an InetAddr.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/Sockets/#Sockets.setopt","page":"套接字","title":"Sockets.setopt","text":"setopt(sock::UDPSocket; multicast_loop=nothing, multicast_ttl=nothing, enable_broadcast=nothing, ttl=nothing)\n\nSet UDP socket options.\n\nmulticast_loop: loopback for multicast packets (default: true).\nmulticast_ttl: TTL for multicast packets (default: nothing).\nenable_broadcast: flag must be set to true if socket will be used for broadcast messages, or else the UDP system will return an access error (default: false).\nttl: Time-to-live of packets sent on the socket (default: nothing).\n\n\n\n\n\n","category":"function"},{"location":"stdlib/Sockets/#Sockets.nagle","page":"套接字","title":"Sockets.nagle","text":"nagle(socket::Union{TCPServer, TCPSocket}, enable::Bool)\n\nEnables or disables Nagle's algorithm on a given TCP server or socket.\n\ncompat: Julia 1.3\nThis function requires Julia 1.3 or later.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/Sockets/#Sockets.quickack","page":"套接字","title":"Sockets.quickack","text":"quickack(socket::Union{TCPServer, TCPSocket}, enable::Bool)\n\nOn Linux systems, the TCP_QUICKACK is disabled or enabled on socket.\n\n\n\n\n\n","category":"function"},{"location":"manual/distributed-computing/#多进程和分布式计算","page":"多进程和分布式计算","title":"多进程和分布式计算","text":"","category":"section"},{"location":"manual/distributed-computing/","page":"多进程和分布式计算","title":"多进程和分布式计算","text":"分布式内存并行计算的实现由模块 Distributed 作为 Julia 附带的标准库的一部分提供。","category":"page"},{"location":"manual/distributed-computing/","page":"多进程和分布式计算","title":"多进程和分布式计算","text":"大多数现代计算机都拥有不止一个 CPU,而且多台计算机可以组织在一起形成一个集群。借助多个 CPU 的计算能力,许多计算过程能够更快地完成,这其中影响性能的两个主要因素分别是:CPU 自身的速度以及它们访问内存的速度。显然,在一个集群中,一个 CPU 访问同一个节点的 RAM 速度是最快的,不过令人吃惊的是,在一台典型的多核笔记本电脑上,由于访问主存和缓存的速度存在差别,类似的现象也会存在。因此,一个良好的多进程环境应该能够管理好某一片内存区域“所属”的CPU。Julia提供的多进程环境是基于消息传递来实现的,可以做到同时让程序在多个进程的不同内存区域中运行。","category":"page"},{"location":"manual/distributed-computing/","page":"多进程和分布式计算","title":"多进程和分布式计算","text":"Julia 的消息传递实现不同于其他环境,例如 MPI[1]。 Julia 中的通信通常是“单方面的”,这意味着程序员只需在双进程操作中显式管理一个进程。 此外,这些操作通常看起来不像“消息发送”和“消息接收”,而是类似于更高级别的操作,例如调用用户函数。","category":"page"},{"location":"manual/distributed-computing/","page":"多进程和分布式计算","title":"多进程和分布式计算","text":"Julia 中的分布式编程基于两个基本概念:远程引用(remote references)和远程调用(remote calls)。远程引用是一个对象,任意一个进程可以通过它访问存储在某个特定进程上的对象。远程调用指是某个进程发起的执行函数的请求,该函数会在另一个(也可能是同一个)进程中执行。","category":"page"},{"location":"manual/distributed-computing/","page":"多进程和分布式计算","title":"多进程和分布式计算","text":"远程引用有两种形式:Future 和 RemoteChannel。","category":"page"},{"location":"manual/distributed-computing/","page":"多进程和分布式计算","title":"多进程和分布式计算","text":"远程调用返回 Future 作为其结果。 远程调用立即返回;当远程调用发生在其他地方后,发出调用的进程继续执行下一个操作。你可以通过在返回的 Future 上调用 wait 来等待远程调用完成,并且可以使用 fetch。","category":"page"},{"location":"manual/distributed-computing/","page":"多进程和分布式计算","title":"多进程和分布式计算","text":"对于 RemoteChannel 而言,它可以被反复写入。例如,多个进程可以通过引用同一个远程 Channel 来协调相互之间的操作。","category":"page"},{"location":"manual/distributed-computing/","page":"多进程和分布式计算","title":"多进程和分布式计算","text":"每个进程都有一个关联的标识符。 提供交互式 Julia 提示符的进程的 id 总是等于 1。默认情况下用于并行操作的进程被称为“workers”。 当只有一个进程时,进程 1 被认为是一个worker。 否则,workers 被认为是进程 1 之外的所有进程。因此,需要添加 2 个或更多进程才能从 pmap 等并行处理方法中获益。 如果你只想在主进程中做其他事情,同时在工作进程上运行长时间的计算,那么添加单个进程是有益的。","category":"page"},{"location":"manual/distributed-computing/","page":"多进程和分布式计算","title":"多进程和分布式计算","text":"让我们开始尝试。 以 julia -p n 开始,在本地机器上提供 n 个工作进程。 通常,n 等于机器上的 CPU 线程(逻辑核心)的数量是有意义的。 请注意,-p 参数隐式加载模块 Distributed。","category":"page"},{"location":"manual/distributed-computing/","page":"多进程和分布式计算","title":"多进程和分布式计算","text":"$ julia -p 2\n\njulia> r = remotecall(rand, 2, 2, 2)\nFuture(2, 1, 4, nothing)\n\njulia> s = @spawnat 2 1 .+ fetch(r)\nFuture(2, 1, 5, nothing)\n\njulia> fetch(s)\n2×2 Array{Float64,2}:\n 1.18526 1.50912\n 1.16296 1.60607","category":"page"},{"location":"manual/distributed-computing/","page":"多进程和分布式计算","title":"多进程和分布式计算","text":"remotecall 的第一个参数是想要调用的函数,第二个参数是执行函数的进程 id,其余的参数会喂给将要被调用的函数。在 Julia 中进行并行编程时,一般不需要显示地指明具体在哪个进程上执行,不过 remotecall 是一个相对底层的接口用来提供细粒度的管理。","category":"page"},{"location":"manual/distributed-computing/","page":"多进程和分布式计算","title":"多进程和分布式计算","text":"可以看到,第一行代码请求进程2构建一个随机矩阵,第二行代码对该矩阵执行加一操作。每次执行的结果存在对应的 Future 中,即 r 和 s。这里 @spawnat 宏会在第一个参数所指定的进程中执行后面第二个参数中的表达式。","category":"page"},{"location":"manual/distributed-computing/","page":"多进程和分布式计算","title":"多进程和分布式计算","text":"有时候,你可能会希望立即获取远程计算的结果,比如,在接下来的操作中就需要读取远程调用的结果,这时候你可以使用 remotecall_fetch 函数,其效果相当于 fetch(remotecall(...)),不过更高效些。","category":"page"},{"location":"manual/distributed-computing/","page":"多进程和分布式计算","title":"多进程和分布式计算","text":"julia> remotecall_fetch(r-> fetch(r)[1, 1], 2, r)\n0.18526337335308085","category":"page"},{"location":"manual/distributed-computing/","page":"多进程和分布式计算","title":"多进程和分布式计算","text":"这将获取 worker 2 上的数组并返回第一个值。 请注意,在这种情况下,fetch 不会移动任何数据,因为它是在拥有该数组的 worker 上执行的。 还可以这样写:","category":"page"},{"location":"manual/distributed-computing/","page":"多进程和分布式计算","title":"多进程和分布式计算","text":"julia> remotecall_fetch(getindex, 2, r, 1, 1)\n0.10824216411304866","category":"page"},{"location":"manual/distributed-computing/","page":"多进程和分布式计算","title":"多进程和分布式计算","text":"回忆下,这里 getindex(r,1,1) 相当于 r[1,1],因此,上面的调用相当于获取 r 的第一个元素。","category":"page"},{"location":"manual/distributed-computing/","page":"多进程和分布式计算","title":"多进程和分布式计算","text":"为方便起见,可以将符号 :any 传递给 @spawnat,它会为你选择执行操作的位置:","category":"page"},{"location":"manual/distributed-computing/","page":"多进程和分布式计算","title":"多进程和分布式计算","text":"julia> r = @spawnat :any rand(2,2)\nFuture(2, 1, 4, nothing)\n\njulia> s = @spawnat :any 1 .+ fetch(r)\nFuture(3, 1, 5, nothing)\n\njulia> fetch(s)\n2×2 Array{Float64,2}:\n 1.38854 1.9098\n 1.20939 1.57158","category":"page"},{"location":"manual/distributed-computing/","page":"多进程和分布式计算","title":"多进程和分布式计算","text":"请注意,我们使用了 1 .+ fetch(r) 而不是 1 .+ r。 这是因为我们不知道代码将在哪里运行,因此通常可能需要一个 fetch 将 r 移动到执行添加的进程。 在这种情况下,@spawnat 足够聪明,可以在拥有 r 的进程上执行计算,因此 fetch 将是一个空操作(没有工作被完成)。","category":"page"},{"location":"manual/distributed-computing/","page":"多进程和分布式计算","title":"多进程和分布式计算","text":"(值得注意的是, @spawnat 不是内置的,而是在 Julia 中定义的 [宏](@ref man-macros)。你也可以自己定义此类构造。)","category":"page"},{"location":"manual/distributed-computing/","page":"多进程和分布式计算","title":"多进程和分布式计算","text":"需要记住的重要一点是,一旦 fetch,Future 将在本地缓存其值。 进一步的 fetch 调用不需要网络跃点。 一旦所有引用 Future 都已获取,远程存储的值将被删除。","category":"page"},{"location":"manual/distributed-computing/","page":"多进程和分布式计算","title":"多进程和分布式计算","text":"@async 类似于 @spawnat,但只在本地进程上运行任务。我们使用它为每个进程创建一个“feeder”任务。每个任务选择需要计算的下一个索引,然后等待其进程完成,然后重复直到我们用完索引。请注意,feeder任务直到主任务到达 @sync 块的末尾才开始执行,此时它放弃控制并等待所有本地任务完成,然后从主任务返回功能。对于 v0.7 及更高版本,feeder 任务能够通过 nextidx 共享状态,因为它们都运行在同一个进程上。即使Tasks 是协作调度的,在某些上下文中可能仍然需要锁定,例如在 asynchronous I/O 中。这意味着上下文切换只发生在明确定义的点:在这种情况下,当 remotecall_fetch 被调用时。这是当前的实现状态,它可能会在未来的 Julia 版本中发生变化,因为它旨在使在 M个 Process 上运行最多 N 个 Tasks 成为可能,也就是 M:N Threading。然后,需要为 nextidx 提供锁获取/释放模型,因为让多个进程同时读写一个资源是不安全的。","category":"page"},{"location":"manual/distributed-computing/#code-availability","page":"多进程和分布式计算","title":"访问代码以及加载库","text":"","category":"section"},{"location":"manual/distributed-computing/","page":"多进程和分布式计算","title":"多进程和分布式计算","text":"对于想要并行执行的代码,需要所有对所有进程都可见。例如,在 Julia 命令行中输入以下命令:","category":"page"},{"location":"manual/distributed-computing/","page":"多进程和分布式计算","title":"多进程和分布式计算","text":"julia> function rand2(dims...)\n return 2*rand(dims...)\n end\n\njulia> rand2(2,2)\n2×2 Array{Float64,2}:\n 0.153756 0.368514\n 1.15119 0.918912\n\njulia> fetch(@spawnat :any rand2(2,2))\nERROR: RemoteException(2, CapturedException(UndefVarError(Symbol(\"#rand2\"))\nStacktrace:\n[...]","category":"page"},{"location":"manual/distributed-computing/","page":"多进程和分布式计算","title":"多进程和分布式计算","text":"进程1知道函数 rand2 的存在,但进程2并不知道。","category":"page"},{"location":"manual/distributed-computing/","page":"多进程和分布式计算","title":"多进程和分布式计算","text":"大多数情况下,你会从文件或者库中加载代码,在此过程中你可以灵活地控制哪个进程加载哪部分代码。假设有这样一个文件,DummyModule.jl,其代码如下:","category":"page"},{"location":"manual/distributed-computing/","page":"多进程和分布式计算","title":"多进程和分布式计算","text":"module DummyModule\n\nexport MyType, f\n\nmutable struct MyType\n a::Int\nend\n\nf(x) = x^2+1\n\nprintln(\"loaded\")\n\nend","category":"page"},{"location":"manual/distributed-computing/","page":"多进程和分布式计算","title":"多进程和分布式计算","text":"为了在所有进程中引用 MyType,DummyModule.jl 需要在每个进程中载入。单独执行 include(\"DummyModule.jl\") 只会在一个进程中将其载入。为了让每个进程都载入它,可以用 @everywhere 宏来实现(启动 Julia 的时候,执行 julia -p 2)。","category":"page"},{"location":"manual/distributed-computing/","page":"多进程和分布式计算","title":"多进程和分布式计算","text":"julia> @everywhere include(\"DummyModule.jl\")\nloaded\n From worker 3: loaded\n From worker 2: loaded","category":"page"},{"location":"manual/distributed-computing/","page":"多进程和分布式计算","title":"多进程和分布式计算","text":"像往常一样,这不会将 DummyModule 引入任何进程的作用域,这需要 using 或 import。 此外,当 DummyModule 被带入一个进程的作用域时,它不在任何其他进程中:","category":"page"},{"location":"manual/distributed-computing/","page":"多进程和分布式计算","title":"多进程和分布式计算","text":"julia> using .DummyModule\n\njulia> MyType(7)\nMyType(7)\n\njulia> fetch(@spawnat 2 MyType(7))\nERROR: On worker 2:\nUndefVarError: MyType not defined\n⋮\n\njulia> fetch(@spawnat 2 DummyModule.MyType(7))\nMyType(7)","category":"page"},{"location":"manual/distributed-computing/","page":"多进程和分布式计算","title":"多进程和分布式计算","text":"不过,我们仍然可以在已经包含(include)过 DummyModule 的进程中,发送 MyType 类型的实例,尽管此时该进程的命名空间中并没有 MyType 变量:","category":"page"},{"location":"manual/distributed-computing/","page":"多进程和分布式计算","title":"多进程和分布式计算","text":"julia> put!(RemoteChannel(2), MyType(7))\nRemoteChannel{Channel{Any}}(2, 1, 13)","category":"page"},{"location":"manual/distributed-computing/","page":"多进程和分布式计算","title":"多进程和分布式计算","text":"文件代码还可以在启动的时候,通过 -L 参数指定,从而提前在多个进程中载入,然后通过一个 driver.jl 文件控制执行逻辑:","category":"page"},{"location":"manual/distributed-computing/","page":"多进程和分布式计算","title":"多进程和分布式计算","text":"julia -p -L file1.jl -L file2.jl driver.jl","category":"page"},{"location":"manual/distributed-computing/","page":"多进程和分布式计算","title":"多进程和分布式计算","text":"上面执行 driver.jl 的进程 id 为1,就跟提供交互式命令行的 Julia 进程一样。","category":"page"},{"location":"manual/distributed-computing/","page":"多进程和分布式计算","title":"多进程和分布式计算","text":"最后,如果DummyModule.jl不是一个独立的文件,而是一个包,那么using DummyModule将在所有进程上加载 DummyModule.jl,但只在调用[using](@ref)的进程上将其纳入作用域。","category":"page"},{"location":"manual/distributed-computing/#启动和管理-worker-进程","page":"多进程和分布式计算","title":"启动和管理 worker 进程","text":"","category":"section"},{"location":"manual/distributed-computing/","page":"多进程和分布式计算","title":"多进程和分布式计算","text":"Julia 自带两种集群管理模式:","category":"page"},{"location":"manual/distributed-computing/","page":"多进程和分布式计算","title":"多进程和分布式计算","text":"本地集群,前面通过启动时指定 -p 参数就是这种模式\n跨机器的集群,通过 --machine-file 指定。这种模式采用没有密码的 ssh 登陆并对应的机器上(与 host 相同的路径下)启动 Julia 的 worker 进程。每个机器定义都采用 [count*][user@]host[:port] [bind_addr[:port]] 的形式。 user 默认为当前用户,port 为标准 ssh 端口。count 是在节点上生成的 worker 数量,默认为 1。可选的 bind-to bind_addr[:port] 指定其他 worker 应该用来连接到这个 worker 的 IP 地址和端口。","category":"page"},{"location":"manual/distributed-computing/","page":"多进程和分布式计算","title":"多进程和分布式计算","text":"addprocs, rmprocs, workers 这些函数可以分别用来对集群中的进程进行增加,删除和修改。","category":"page"},{"location":"manual/distributed-computing/","page":"多进程和分布式计算","title":"多进程和分布式计算","text":"julia> using Distributed\n\njulia> addprocs(2)\n2-element Array{Int64,1}:\n 2\n 3","category":"page"},{"location":"manual/distributed-computing/","page":"多进程和分布式计算","title":"多进程和分布式计算","text":"模块 Distributed 必须在调用 addprocs 之前显式加载到主进程上。 它在工作进程上自动可用。","category":"page"},{"location":"manual/distributed-computing/","page":"多进程和分布式计算","title":"多进程和分布式计算","text":"请注意,worker 不会运行 ~/.julia/config/startup.jl 启动脚本,也不会将其全局状态(例如全局变量、新方法定义和加载的模块)与任何其他正在运行的进程同步 。你可以使用 addprocs(exeflags=\"--project\") 来初始化具有特定环境的 worker,然后使用 @everywhere using 或 @everywhere include(\"file.jl\")。","category":"page"},{"location":"manual/distributed-computing/","page":"多进程和分布式计算","title":"多进程和分布式计算","text":"其它类型的集群可以通过自己写一个 ClusterManager 来实现,下面 集群管理器 部分会介绍。","category":"page"},{"location":"manual/distributed-computing/#数据转移","page":"多进程和分布式计算","title":"数据转移","text":"","category":"section"},{"location":"manual/distributed-computing/","page":"多进程和分布式计算","title":"多进程和分布式计算","text":"分布式程序的性能瓶颈主要是由发送消息和数据转移造成的,减少发送消息和转移数据的数量对于获取高性能和可扩展性至关重要,因此,深入了解 Julia 分布式程序是如何转移数据的非常有必要。","category":"page"},{"location":"manual/distributed-computing/","page":"多进程和分布式计算","title":"多进程和分布式计算","text":"fetch 可以被认为是一个显式的数据转移操作,因为它直接要求将一个对象移动到本地机器。 @spawnat(以及一些相关的结构体)也移动数据,但这并不明显,因此可以称为隐式数据转移操作。 考虑这两种构造和平方一个随机矩阵的方法:","category":"page"},{"location":"manual/distributed-computing/","page":"多进程和分布式计算","title":"多进程和分布式计算","text":"方法一:","category":"page"},{"location":"manual/distributed-computing/","page":"多进程和分布式计算","title":"多进程和分布式计算","text":"julia> A = rand(1000,1000);\n\njulia> Bref = @spawnat :any A^2;\n\n[...]\n\njulia> fetch(Bref);","category":"page"},{"location":"manual/distributed-computing/","page":"多进程和分布式计算","title":"多进程和分布式计算","text":"方法二:","category":"page"},{"location":"manual/distributed-computing/","page":"多进程和分布式计算","title":"多进程和分布式计算","text":"julia> Bref = @spawnat :any rand(1000,1000)^2;\n\n[...]\n\njulia> fetch(Bref);","category":"page"},{"location":"manual/distributed-computing/","page":"多进程和分布式计算","title":"多进程和分布式计算","text":"这种差异看起来微不足道,但实际上由于 @spawnat 的行为而非常显着。 在第一种方法中,在本地构造一个随机矩阵,然后将其发送到另一个进程进行平方。 在第二种方法中,随机矩阵在另一个进程中被构造和平方。 因此,第二种方法发送的数据比第一种方法少得多。","category":"page"},{"location":"manual/distributed-computing/","page":"多进程和分布式计算","title":"多进程和分布式计算","text":"在这个简单示例中,这两种方法很容易区分和选择。 然而,在一个真正的程序设计数据转移可能需要更多的思考和一些测量。 例如,如果第一个进程需要矩阵A,那么第一种方法可能更好。 或者,如果计算 A 很昂贵并且只有当前进程拥有它,那么将它移到另一个进程可能是不可避免的。 或者,如果当前进程在 @spawnat 和 fetch(Bref) 之间几乎没有什么关系,最好完全消除并行性。 或者想象一下 rand(1000,1000) 被更昂贵的操作取代。 那么为这一步添加另一个 @spawnat 语句可能是有意义的。","category":"page"},{"location":"manual/distributed-computing/#全局变量","page":"多进程和分布式计算","title":"全局变量","text":"","category":"section"},{"location":"manual/distributed-computing/","page":"多进程和分布式计算","title":"多进程和分布式计算","text":"通过 @spawnat 远程执行的表达式,或使用 remotecall 为远程执行指定的闭包可能会引用全局变量。 与其他模块中的全局绑定相比,模块 Main 下的全局绑定的处理方式略有不同。 考虑以下代码片段:","category":"page"},{"location":"manual/distributed-computing/","page":"多进程和分布式计算","title":"多进程和分布式计算","text":"A = rand(10,10)\nremotecall_fetch(()->sum(A), 2)","category":"page"},{"location":"manual/distributed-computing/","page":"多进程和分布式计算","title":"多进程和分布式计算","text":"在这种情况下,sum 必须在远程进程中定义。请注意,A 是在本地工作区中定义的全局变量。 worker 2 在 Main 下没有名为 A 的变量。 将闭包 ()->sum(A) 传送到 worker 2 的行为导致 Main.A 被定义在 2 上。即使在调用 remotecall_fetch 返回之后, Main.A 仍然存在于 worker 2 上。带有嵌入式全局引用的远程调用(仅在Main 模块下)以如下的方式管理全局变量:","category":"page"},{"location":"manual/distributed-computing/","page":"多进程和分布式计算","title":"多进程和分布式计算","text":"在全局调用中引用的全局绑定会在将要执行该调用的 worker 中被创建。\n全局常量仍然在远端结点定义为常量。\n全局绑定会在下一次远程调用中引用到的时候,当其值发生改变时,再次发送给目标 worker。此外,集群并不会所有结点的全局绑定。例如:\nA = rand(10,10)\nremotecall_fetch(()->sum(A), 2) # worker 2\nA = rand(10,10)\nremotecall_fetch(()->sum(A), 3) # worker 3\nA = nothing\n可以看到,A 作为全局变量在 worker 2中有定义,而 B 是一个局部变量,因而最后在 worker 2 中并没有 B 的绑定。 执行以上代码之后,worker 2 和 worker 3中的 Main.A 的值是不同的,同时,节点1上的值则为 nothing。","category":"page"},{"location":"manual/distributed-computing/","page":"多进程和分布式计算","title":"多进程和分布式计算","text":"也许你也注意到了,在 master 主节点上被赋值为 nothing 之后,全局变量的内存会被回收,但在 worker 节点上的全局变量并没有被回收掉。执行 clear 可以手动将远端结点上的特定全局变量置为 nothing,然后对应的内存会被周期性的垃圾回收机制回收。","category":"page"},{"location":"manual/distributed-computing/","page":"多进程和分布式计算","title":"多进程和分布式计算","text":"因此,在远程调用中,需要非常小心地引用全局变量。事实上,应当尽量避免引用全局变量,如果必须引用,那么可以考虑用let代码块将全局变量局部化:","category":"page"},{"location":"manual/distributed-computing/","page":"多进程和分布式计算","title":"多进程和分布式计算","text":"julia> A = rand(10,10);\n\njulia> remotecall_fetch(()->A, 2);\n\njulia> B = rand(10,10);\n\njulia> let B = B\n remotecall_fetch(()->B, 2)\n end;\n\njulia> @fetchfrom 2 InteractiveUtils.varinfo()\nname size summary\n––––––––– ––––––––– ––––––––––––––––––––––\nA 800 bytes 10×10 Array{Float64,2}\nBase Module\nCore Module\nMain Module","category":"page"},{"location":"manual/distributed-computing/","page":"多进程和分布式计算","title":"多进程和分布式计算","text":"可以看到,A 作为全局变量在 worker 2中有定义,而 B 是一个局部变量,因而最后在 worker 2 中并没有 B 的绑定。","category":"page"},{"location":"manual/distributed-computing/#并行的Map和Loop","page":"多进程和分布式计算","title":"并行的Map和Loop","text":"","category":"section"},{"location":"manual/distributed-computing/","page":"多进程和分布式计算","title":"多进程和分布式计算","text":"幸运的是,许多有用的并行计算不需要数据转移。 一个常见的例子是蒙特卡罗模拟,其中多个进程可以同时处理独立的模拟试验。 我们可以使用 @spawnat 在两个进程上抛硬币。 首先,在 count_heads.jl 中编写以下函数:","category":"page"},{"location":"manual/distributed-computing/","page":"多进程和分布式计算","title":"多进程和分布式计算","text":"function count_heads(n)\n c::Int = 0\n for i = 1:n\n c += rand(Bool)\n end\n c\nend","category":"page"},{"location":"manual/distributed-computing/","page":"多进程和分布式计算","title":"多进程和分布式计算","text":"函数 count_heads 只是简单地将 n 个随机 0-1 值累加,下面在两个机器上进行试验,并将结果叠加:","category":"page"},{"location":"manual/distributed-computing/","page":"多进程和分布式计算","title":"多进程和分布式计算","text":"julia> @everywhere include_string(Main, $(read(\"count_heads.jl\", String)), \"count_heads.jl\")\n\njulia> a = @spawnat :any count_heads(100000000)\nFuture(2, 1, 6, nothing)\n\njulia> b = @spawnat :any count_heads(100000000)\nFuture(3, 1, 7, nothing)\n\njulia> fetch(a)+fetch(b)\n100001564","category":"page"},{"location":"manual/distributed-computing/","page":"多进程和分布式计算","title":"多进程和分布式计算","text":"上面的例子展示了一种非常常见而且有用的并行编程模式,在一些进程中执行多次独立的迭代,然后将它们的结果通过某个函数合并到一起,这个合并操作通常称作聚合(reduction),也就是一般意义上的张量降维(tensor-rank-reducing),比如将一个向量降维成一个数,或者是将一个 tensor 降维到某一行或者某一列等。在代码中,通常具有 x = f(x, v[i]) 这种形式,其中 x 是一个叠加器,f 是一个聚合函数,而 v[i] 则是将要被聚合的值。一般来说,f 要求满足结合律,这样不管执行的顺序如何,都不会影响计算结果。","category":"page"},{"location":"manual/distributed-computing/","page":"多进程和分布式计算","title":"多进程和分布式计算","text":"请注意,我们可以将这种count_heads 模式推广。 我们使用了两个显式的 @spawnat 语句,将并行性限制为两个进程。 要在任意数量的进程上运行,我们可以使用 并行for循环,在分布式内存中运行,可以在 Julia 中使用 @distributed 编写,如下所示:","category":"page"},{"location":"manual/distributed-computing/","page":"多进程和分布式计算","title":"多进程和分布式计算","text":"nheads = @distributed (+) for i = 1:200000000\n Int(rand(Bool))\nend","category":"page"},{"location":"manual/distributed-computing/","page":"多进程和分布式计算","title":"多进程和分布式计算","text":"上面的写法将多次迭代分配到了不同的进程,然后通过一个聚合函数(这里是 (+))合并计算结果,其中,每次迭代的结果作为 for 循环中的表达式的结果,最后整个循环的结果聚合后得到最终的结果。","category":"page"},{"location":"manual/distributed-computing/","page":"多进程和分布式计算","title":"多进程和分布式计算","text":"注意,尽管这里 for 循环看起来跟串行的 for 循环差不多,实际表现完全不同。这里的迭代并没有特定的执行顺序,而且由于所有的迭代都在不同的进程中进行,其中变量的写入对全局来说不可见。所有并行的 for 循环中的变量都会复制并广播到每个进程。","category":"page"},{"location":"manual/distributed-computing/","page":"多进程和分布式计算","title":"多进程和分布式计算","text":"比如,下面这段代码并不会像你想要的那样执行:","category":"page"},{"location":"manual/distributed-computing/","page":"多进程和分布式计算","title":"多进程和分布式计算","text":"a = zeros(100000)\n@distributed for i = 1:100000\n a[i] = i\nend","category":"page"},{"location":"manual/distributed-computing/","page":"多进程和分布式计算","title":"多进程和分布式计算","text":"这段代码并不会把 a 的所有元素初始化,因为每个进程都会有一份 a 的拷贝,因此类似的 for 循环一定要避免。幸运的是,共享数组 可以用来突破这种限制:","category":"page"},{"location":"manual/distributed-computing/","page":"多进程和分布式计算","title":"多进程和分布式计算","text":"using SharedArrays\n\na = SharedArray{Float64}(10)\n@distributed for i = 1:10\n a[i] = i\nend","category":"page"},{"location":"manual/distributed-computing/","page":"多进程和分布式计算","title":"多进程和分布式计算","text":"当然,对于 for 循环外面的变量来说,如果是只读的话,使用起来完全没问题:","category":"page"},{"location":"manual/distributed-computing/","page":"多进程和分布式计算","title":"多进程和分布式计算","text":"a = randn(1000)\n@distributed (+) for i = 1:100000\n f(a[rand(1:end)])\nend","category":"page"},{"location":"manual/distributed-computing/","page":"多进程和分布式计算","title":"多进程和分布式计算","text":"这里每次迭代都会从共享给每个进程的向量 a 中随机选一个样本,然后用来计算 f。","category":"page"},{"location":"manual/distributed-computing/","page":"多进程和分布式计算","title":"多进程和分布式计算","text":"如你所见,如果不需要,可以省略归约运算符。 在这种情况下,循环异步执行,即它在所有可用的 worker 上产生独立的任务,并立即返回一个 Future 数组,而无需等待完成。 调用者可以稍后通过调用 fetch 来等待 Future 完成,或者通过添加前缀 @sync,比如 @sync @distributed for,来等待循环结束。","category":"page"},{"location":"manual/distributed-computing/","page":"多进程和分布式计算","title":"多进程和分布式计算","text":"在一些不需要聚合函数的情况下,我们可能只是像对某个范围内的整数应用一个函数(或者,更一般地,某个序列中的所有元素),这种操作称作并行的 map,在 Julia 中有一个对应的函数 pmap。例如,可以像下面这样计算一些随机大矩阵的奇异值:","category":"page"},{"location":"manual/distributed-computing/","page":"多进程和分布式计算","title":"多进程和分布式计算","text":"julia> M = Matrix{Float64}[rand(1000,1000) for i = 1:10];\n\njulia> pmap(svdvals, M);","category":"page"},{"location":"manual/distributed-computing/","page":"多进程和分布式计算","title":"多进程和分布式计算","text":"Julia 中的 pmap 是被设计用来处理一些计算量比较复杂的函数的并行化的。与之对比的是,@distributed for 是用来处理一些每次迭代计算都很轻量的计算,比如简单地对两个数求和。pmap 和 @distributed for 都只会用到 worker 的进程。对于 @distributed for 而言,最后的聚合计算由发起者的进程完成。","category":"page"},{"location":"manual/distributed-computing/#远程引用和-AbstractChannel","page":"多进程和分布式计算","title":"远程引用和 AbstractChannel","text":"","category":"section"},{"location":"manual/distributed-computing/","page":"多进程和分布式计算","title":"多进程和分布式计算","text":"远程引用通常指某种 AbstractChannel 的实现。","category":"page"},{"location":"manual/distributed-computing/","page":"多进程和分布式计算","title":"多进程和分布式计算","text":"AbstractChannel(如Channel)的具体实现,需要实现 put!, take!, fetch , isready 和 wait。 Future 所引用的远程对象存储在Channel{Any}(1) 中,即大小为 1 的、能够容纳 Any 类型对象的 Channel 。","category":"page"},{"location":"manual/distributed-computing/","page":"多进程和分布式计算","title":"多进程和分布式计算","text":"RemoteChannel 可以被反复写入,可以指向任意大小和类型的 channel(或者是任意 AbstractChannel 的实现)。","category":"page"},{"location":"manual/distributed-computing/","page":"多进程和分布式计算","title":"多进程和分布式计算","text":"RemoteChannel(f::Function, pid)() 构造器可以构造一些引用,而这些引用指向的 channel 可以容纳多个某种具体类型的数据。其中 f 是将要在 pid 上执行的函数,其返回值必须是 AbstractChannel 类型。","category":"page"},{"location":"manual/distributed-computing/","page":"多进程和分布式计算","title":"多进程和分布式计算","text":"例如,RemoteChannel(()->Channel{Int}(10), pid) 会创建一个 channel,其类型是 Int,容量是 10,这个 channel 存在于 pid 进程中。","category":"page"},{"location":"manual/distributed-computing/","page":"多进程和分布式计算","title":"多进程和分布式计算","text":"针对 RemoteChannel 的 put!, take!, fetch, isready 和 wait 方法会被重定向到其底层存储着 channel 的进程。","category":"page"},{"location":"manual/distributed-computing/","page":"多进程和分布式计算","title":"多进程和分布式计算","text":"因此,RemoteChannel 可以用来引用用户自定义的 AbstractChannel 对象。在 Examples repository 中的 dictchannel.jl 文件中有一个简单的例子,其中使用了一个字典用于远端存储。","category":"page"},{"location":"manual/distributed-computing/#Channel-和-RemoteChannel","page":"多进程和分布式计算","title":"Channel 和 RemoteChannel","text":"","category":"section"},{"location":"manual/distributed-computing/","page":"多进程和分布式计算","title":"多进程和分布式计算","text":"一个 Channel 仅对局部的进程可见,worker 2 无法直接访问 worker 3 上的 Channel,反之亦如此。不过 RemoteChannel 可以跨 worker 获取和写入数据。\nRemoteChannel 可以看作是对 Channel 的封装。\nRemoteChannel 的 pid 就是其封装的 channel 所在的进程 id。\n任意拥有 RemoteChannel 引用的进程都可以对其进行读写,数据会自动发送到 RemoteChannel 底层 channel 的进程(或从中获取数据)\n序列化 Channel 会将其中的所有数据也都序列化,因此反序列化的时候也就可以得到一个原始数据的拷贝。\n不过,对 RemoteChannel 的序列化则只会序列化其底层指向的 channel 的 id,因此反序列化之后得到的对象仍然会指向之前存储的对象。","category":"page"},{"location":"manual/distributed-computing/","page":"多进程和分布式计算","title":"多进程和分布式计算","text":"如上的通道示例可以修改为进程间通信,如下所示","category":"page"},{"location":"manual/distributed-computing/","page":"多进程和分布式计算","title":"多进程和分布式计算","text":"首先,起 4 个 worker 进程处理同一个 remote channel jobs,其中的每个 job 都有一个对应的 job_id,然后每个 task 读取一个 job_id,然后模拟随机等待一段时间,然后往存储结果的 RemoteChannel 中写入一个 Tuple 对象,其中包含 job_id 和等待的时间。最后将结果打印出来。","category":"page"},{"location":"manual/distributed-computing/","page":"多进程和分布式计算","title":"多进程和分布式计算","text":"julia> addprocs(4); # add worker processes\n\njulia> const jobs = RemoteChannel(()->Channel{Int}(32));\n\njulia> const results = RemoteChannel(()->Channel{Tuple}(32));\n\njulia> @everywhere function do_work(jobs, results) # define work function everywhere\n while true\n job_id = take!(jobs)\n exec_time = rand()\n sleep(exec_time) # simulates elapsed time doing actual work\n put!(results, (job_id, exec_time, myid()))\n end\n end\n\njulia> function make_jobs(n)\n for i in 1:n\n put!(jobs, i)\n end\n end;\n\njulia> n = 12;\n\njulia> errormonitor(@async make_jobs(n)); # feed the jobs channel with \"n\" jobs\n\njulia> for p in workers() # start tasks on the workers to process requests in parallel\n remote_do(do_work, p, jobs, results)\n end\n\njulia> @elapsed while n > 0 # print out results\n job_id, exec_time, where = take!(results)\n println(\"$job_id finished in $(round(exec_time; digits=2)) seconds on worker $where\")\n global n = n - 1\n end\n1 finished in 0.18 seconds on worker 4\n2 finished in 0.26 seconds on worker 5\n6 finished in 0.12 seconds on worker 4\n7 finished in 0.18 seconds on worker 4\n5 finished in 0.35 seconds on worker 5\n4 finished in 0.68 seconds on worker 2\n3 finished in 0.73 seconds on worker 3\n11 finished in 0.01 seconds on worker 3\n12 finished in 0.02 seconds on worker 3\n9 finished in 0.26 seconds on worker 5\n8 finished in 0.57 seconds on worker 4\n10 finished in 0.58 seconds on worker 2\n0.055971741","category":"page"},{"location":"manual/distributed-computing/#远程调用和分布式垃圾回收","page":"多进程和分布式计算","title":"远程调用和分布式垃圾回收","text":"","category":"section"},{"location":"manual/distributed-computing/","page":"多进程和分布式计算","title":"多进程和分布式计算","text":"远程引用所指向的对象可以在其所有引用都被集群删除之后被释放掉。","category":"page"},{"location":"manual/distributed-computing/","page":"多进程和分布式计算","title":"多进程和分布式计算","text":"存储值的节点会跟踪哪些 worker 引用了它。 每次将 RemoteChannel 或(未获取的)Future 序列化为 worker 时,都会通知引用指向的节点。 并且每次在本地对 RemoteChannel 或(未获取的)Future 进行垃圾回收时,都会再次通知拥有该值的节点。 这是在内部集群感知序列化程序中实现的。 远程引用仅在正在运行的集群的上下文中有效。 不支持对常规IO对象的引用进行序列化和反序列化。","category":"page"},{"location":"manual/distributed-computing/","page":"多进程和分布式计算","title":"多进程和分布式计算","text":"上面说到的通知都是通过发送\"跟踪\"信息来实现的,当一个引用被序列化的时候,就会发送\"添加引用\"的信息,而一个引用被本地的垃圾回收器回收的时候,就会发送一个\"删除引用\"的信息。","category":"page"},{"location":"manual/distributed-computing/","page":"多进程和分布式计算","title":"多进程和分布式计算","text":"由于 Future 是一次性写入并在本地缓存,因此 fetching 一个 Future 的行为也会更新拥有该值的节点上的引用跟踪信息。","category":"page"},{"location":"manual/distributed-computing/","page":"多进程和分布式计算","title":"多进程和分布式计算","text":"一旦指向某个值的引用都被删除了,对应的节点会将其释放。","category":"page"},{"location":"manual/distributed-computing/","page":"多进程和分布式计算","title":"多进程和分布式计算","text":"使用 [Future](@ref Distributed.Future),将已获取的[Future](@ref Distributed.Future)序列化到其他节点也会发送该值,因为此时原始远程存储可能已收集该值了。","category":"page"},{"location":"manual/distributed-computing/","page":"多进程和分布式计算","title":"多进程和分布式计算","text":"此外需要注意的是,本地的垃圾回收到底发生在什么时候取决于具体对象的大小以及当时系统的内存压力。","category":"page"},{"location":"manual/distributed-computing/","page":"多进程和分布式计算","title":"多进程和分布式计算","text":"在远程引用的情况下,本地引用对象的大小非常小,而存储在远程节点上的值可能非常大。 由于可能不会立即收集本地对象,因此在 RemoteChannel 的本地实例或未获取的 Future 上显式调用 finalize 是一个好习惯 。 由于在 Future 上调用 fetch 也会从远程存储中删除其引用,因此在获取的 Future 上不需要这样做。 显式调用 finalize 会导致立即向远程节点发送消息以继续并删除其对该值的引用。","category":"page"},{"location":"manual/distributed-computing/","page":"多进程和分布式计算","title":"多进程和分布式计算","text":"一旦执行了 finalize 之后,引用就不可用了。","category":"page"},{"location":"manual/distributed-computing/#本地调用","page":"多进程和分布式计算","title":"本地调用","text":"","category":"section"},{"location":"manual/distributed-computing/","page":"多进程和分布式计算","title":"多进程和分布式计算","text":"数据必须复制到远程节点以供执行。 远程调用和数据存储到不同节点上的 RemoteChannel / Future 时都是这种情况。 正如预期的那样,这会在远程节点上生成序列化对象的副本。 但是,当目的节点是本地节点时,即调用进程id与远程节点id相同,则作为本地调用执行。 它通常(并非总是)在不同的 Task 中执行 - 但没有数据的序列化/反序列化。 因此,该调用引用了与传递相同的对象实例 - 没有创建副本。 这种行为在下面突出显示:","category":"page"},{"location":"manual/distributed-computing/","page":"多进程和分布式计算","title":"多进程和分布式计算","text":"julia> using Distributed;\n\njulia> rc = RemoteChannel(()->Channel(3)); # RemoteChannel created on local node\n\njulia> v = [0];\n\njulia> for i in 1:3\n v[1] = i # Reusing `v`\n put!(rc, v)\n end;\n\njulia> result = [take!(rc) for _ in 1:3];\n\njulia> println(result);\nArray{Int64,1}[[3], [3], [3]]\n\njulia> println(\"Num Unique objects : \", length(unique(map(objectid, result))));\nNum Unique objects : 1\n\njulia> addprocs(1);\n\njulia> rc = RemoteChannel(()->Channel(3), workers()[1]); # RemoteChannel created on remote node\n\njulia> v = [0];\n\njulia> for i in 1:3\n v[1] = i\n put!(rc, v)\n end;\n\njulia> result = [take!(rc) for _ in 1:3];\n\njulia> println(result);\nArray{Int64,1}[[1], [2], [3]]\n\njulia> println(\"Num Unique objects : \", length(unique(map(objectid, result))));\nNum Unique objects : 3","category":"page"},{"location":"manual/distributed-computing/","page":"多进程和分布式计算","title":"多进程和分布式计算","text":"可以看出,本地拥有的 RemoteChannel 上的 put! 在调用之间修改了相同的对象 v 会导致存储相同的单个对象实例。 与当拥有 rc 的节点是不同节点时创建的 v 副本相反。","category":"page"},{"location":"manual/distributed-computing/","page":"多进程和分布式计算","title":"多进程和分布式计算","text":"需要注意的是,这通常不是问题。 只有当对象既存储在本地又在调用后被修改时,才需要考虑这一点。 在这种情况下,存储对象的 deepcopy 可能是合适的。","category":"page"},{"location":"manual/distributed-computing/","page":"多进程和分布式计算","title":"多进程和分布式计算","text":"对于本地节点上的远程调用也是如此,如下例所示:","category":"page"},{"location":"manual/distributed-computing/","page":"多进程和分布式计算","title":"多进程和分布式计算","text":"julia> using Distributed; addprocs(1);\n\njulia> v = [0];\n\njulia> v2 = remotecall_fetch(x->(x[1] = 1; x), myid(), v); # Executed on local node\n\njulia> println(\"v=$v, v2=$v2, \", v === v2);\nv=[1], v2=[1], true\n\njulia> v = [0];\n\njulia> v2 = remotecall_fetch(x->(x[1] = 1; x), workers()[1], v); # Executed on remote node\n\njulia> println(\"v=$v, v2=$v2, \", v === v2);\nv=[0], v2=[1], false","category":"page"},{"location":"manual/distributed-computing/","page":"多进程和分布式计算","title":"多进程和分布式计算","text":"再次可以看出,对本地节点的远程调用就像直接调用一样。调用修改作为参数传递的本地对象。 在远程调用中,它对参数的副本进行操作。","category":"page"},{"location":"manual/distributed-computing/","page":"多进程和分布式计算","title":"多进程和分布式计算","text":"重复一遍,一般来说这不是问题。 如果本地节点也被用作计算节点,并且在调用后使用的参数,则需要考虑此行为,并且如果需要,必须将参数的深拷贝传递给在本地节点上唤起的调用。 对远程节点的调用将始终对参数的副本进行操作。","category":"page"},{"location":"manual/distributed-computing/#man-shared-arrays","page":"多进程和分布式计算","title":"共享数组","text":"","category":"section"},{"location":"manual/distributed-computing/","page":"多进程和分布式计算","title":"多进程和分布式计算","text":"共享数组使用系统共享内存将数组映射到多个进程上,尽管和 DArray 有点像,但其实际表现有很大不同。在 DArray 中,每个进程可以访问数据中的一块,但任意两个进程都不能共享同一块数据,而对于 SharedArray,每个进程都可以访问整个数组。如果你想在一台机器上,让一大块数据能够被多个进程访问到,那么 SharedArray 是个不错的选择。","category":"page"},{"location":"manual/distributed-computing/","page":"多进程和分布式计算","title":"多进程和分布式计算","text":"共享数组由 SharedArray 提供,必须在所有相关的 worker 中都显式地加载。","category":"page"},{"location":"manual/distributed-computing/","page":"多进程和分布式计算","title":"多进程和分布式计算","text":"对 SharedArray 索引(访问和复制)操作就跟普通的数组一样,由于底层的内存对本地的进程是可见的,索引的效率很高,因此大多数单进程上的算法对 SharedArray 来说都是适用的,除非某些算法必须使用 Array 类型(此时可以通过调用 sdata 来获取 SharedArray 数组)。对于其它类型的 AbstractArray 类型数组来说,sdata 仅仅会返回数组本身,因此,可以放心地使用 sdata 对任意类型的 Array 进行操作。","category":"page"},{"location":"manual/distributed-computing/","page":"多进程和分布式计算","title":"多进程和分布式计算","text":"共享数组可以通过以下形式构造:","category":"page"},{"location":"manual/distributed-computing/","page":"多进程和分布式计算","title":"多进程和分布式计算","text":"SharedArray{T,N}(dims::NTuple; init=false, pids=Int[])","category":"page"},{"location":"manual/distributed-computing/","page":"多进程和分布式计算","title":"多进程和分布式计算","text":"它在由 pids 指定的进程中创建了一个位类型为 T 和形状为 dims 的 N 维共享数组。 与分布式数组不同,共享数组只能从由pids 命名参数指定的那些参与 worker 访问(如果创建过程在同一主机上,也是如此)。 请注意,SharedArray 中仅支持 isbits 元素。","category":"page"},{"location":"manual/distributed-computing/","page":"多进程和分布式计算","title":"多进程和分布式计算","text":"如果提供了一个类型为 initfn(S::SharedArray) 的 init 函数,那么所有相关的 worker 都会调用它。你可以让每个 worker 都在共享数组不同的地方执行 init 函数,从而实现并行初始化。","category":"page"},{"location":"manual/distributed-computing/","page":"多进程和分布式计算","title":"多进程和分布式计算","text":"下面是个例子:","category":"page"},{"location":"manual/distributed-computing/","page":"多进程和分布式计算","title":"多进程和分布式计算","text":"julia> using Distributed\n\njulia> addprocs(3)\n3-element Array{Int64,1}:\n 2\n 3\n 4\n\njulia> @everywhere using SharedArrays\n\njulia> S = SharedArray{Int,2}((3,4), init = S -> S[localindices(S)] = repeat([myid()], length(localindices(S))))\n3×4 SharedArray{Int64,2}:\n 2 2 3 4\n 2 3 3 4\n 2 3 4 4\n\njulia> S[3,2] = 7\n7\n\njulia> S\n3×4 SharedArray{Int64,2}:\n 2 2 3 4\n 2 3 3 4\n 2 7 4 4","category":"page"},{"location":"manual/distributed-computing/","page":"多进程和分布式计算","title":"多进程和分布式计算","text":"SharedArrays.localindices 提供了一个以为的切片,可以很方便地用来将 task 分配到各个进程上。当然你可以按你想要的方式做区分:","category":"page"},{"location":"manual/distributed-computing/","page":"多进程和分布式计算","title":"多进程和分布式计算","text":"julia> S = SharedArray{Int,2}((3,4), init = S -> S[indexpids(S):length(procs(S)):length(S)] = repeat([myid()], length( indexpids(S):length(procs(S)):length(S))))\n3×4 SharedArray{Int64,2}:\n 2 2 2 2\n 3 3 3 3\n 4 4 4 4","category":"page"},{"location":"manual/distributed-computing/","page":"多进程和分布式计算","title":"多进程和分布式计算","text":"由于所有的进程都能够访问底层的数据,因此一定要小心避免出现冲突:","category":"page"},{"location":"manual/distributed-computing/","page":"多进程和分布式计算","title":"多进程和分布式计算","text":"@sync begin\n for p in procs(S)\n @async begin\n remotecall_wait(fill!, p, S, p)\n end\n end\nend","category":"page"},{"location":"manual/distributed-computing/","page":"多进程和分布式计算","title":"多进程和分布式计算","text":"上面的代码会导致不确定的结果,因为每个进程都将整个数组赋值为其 pid,从而导致最后一个执行完成的进程会保留其 pid。","category":"page"},{"location":"manual/distributed-computing/","page":"多进程和分布式计算","title":"多进程和分布式计算","text":"考虑更复杂的一种情况:","category":"page"},{"location":"manual/distributed-computing/","page":"多进程和分布式计算","title":"多进程和分布式计算","text":"q[i,j,t+1] = q[i,j,t] + u[i,j,t]","category":"page"},{"location":"manual/distributed-computing/","page":"多进程和分布式计算","title":"多进程和分布式计算","text":"这个例子中,如果首先将任务用按照一维的索引作区分,那么就会出问题:如果 q[i,j,t] 位于分配给某个 worker 的最后一个位置,而 q[i,j,t+1] 位于下一个 worker 的开始位置,那么后面这个 worker 开始计算的时候,可能 q[i,j,t] 还没有准备好,这时候,更好的做法是,手动分区,比如可以定义一个函数,按照 (irange,jrange) 给每个 worker 分配任务。","category":"page"},{"location":"manual/distributed-computing/","page":"多进程和分布式计算","title":"多进程和分布式计算","text":"julia> @everywhere function myrange(q::SharedArray)\n idx = indexpids(q)\n if idx == 0 # This worker is not assigned a piece\n return 1:0, 1:0\n end\n nchunks = length(procs(q))\n splits = [round(Int, s) for s in range(0, stop=size(q,2), length=nchunks+1)]\n 1:size(q,1), splits[idx]+1:splits[idx+1]\n end","category":"page"},{"location":"manual/distributed-computing/","page":"多进程和分布式计算","title":"多进程和分布式计算","text":"然后定义计算内核:","category":"page"},{"location":"manual/distributed-computing/","page":"多进程和分布式计算","title":"多进程和分布式计算","text":"julia> @everywhere function advection_chunk!(q, u, irange, jrange, trange)\n @show (irange, jrange, trange) # display so we can see what's happening\n for t in trange, j in jrange, i in irange\n q[i,j,t+1] = q[i,j,t] + u[i,j,t]\n end\n q\n end","category":"page"},{"location":"manual/distributed-computing/","page":"多进程和分布式计算","title":"多进程和分布式计算","text":"然后定义一个 wrapper:","category":"page"},{"location":"manual/distributed-computing/","page":"多进程和分布式计算","title":"多进程和分布式计算","text":"julia> @everywhere advection_shared_chunk!(q, u) =\n advection_chunk!(q, u, myrange(q)..., 1:size(q,3)-1)","category":"page"},{"location":"manual/distributed-computing/","page":"多进程和分布式计算","title":"多进程和分布式计算","text":"接下来,比较三个不同的版本,第一个是单进程版本:","category":"page"},{"location":"manual/distributed-computing/","page":"多进程和分布式计算","title":"多进程和分布式计算","text":"julia> advection_serial!(q, u) = advection_chunk!(q, u, 1:size(q,1), 1:size(q,2), 1:size(q,3)-1);","category":"page"},{"location":"manual/distributed-computing/","page":"多进程和分布式计算","title":"多进程和分布式计算","text":"然后是使用 @distributed:","category":"page"},{"location":"manual/distributed-computing/","page":"多进程和分布式计算","title":"多进程和分布式计算","text":"julia> function advection_parallel!(q, u)\n for t = 1:size(q,3)-1\n @sync @distributed for j = 1:size(q,2)\n for i = 1:size(q,1)\n q[i,j,t+1]= q[i,j,t] + u[i,j,t]\n end\n end\n end\n q\n end;","category":"page"},{"location":"manual/distributed-computing/","page":"多进程和分布式计算","title":"多进程和分布式计算","text":"最后是使用分区:","category":"page"},{"location":"manual/distributed-computing/","page":"多进程和分布式计算","title":"多进程和分布式计算","text":"julia> function advection_shared!(q, u)\n @sync begin\n for p in procs(q)\n @async remotecall_wait(advection_shared_chunk!, p, q, u)\n end\n end\n q\n end;","category":"page"},{"location":"manual/distributed-computing/","page":"多进程和分布式计算","title":"多进程和分布式计算","text":"如果创建好了 SharedArray 之后,计算这些函数的执行时间,那么可以得到以下结果(用 julia -p 4 启动):","category":"page"},{"location":"manual/distributed-computing/","page":"多进程和分布式计算","title":"多进程和分布式计算","text":"julia> q = SharedArray{Float64,3}((500,500,500));\n\njulia> u = SharedArray{Float64,3}((500,500,500));","category":"page"},{"location":"manual/distributed-computing/","page":"多进程和分布式计算","title":"多进程和分布式计算","text":"先执行一次以便 JIT 编译,然后用 @time 宏测试其第二次执行的时间:","category":"page"},{"location":"manual/distributed-computing/","page":"多进程和分布式计算","title":"多进程和分布式计算","text":"julia> @time advection_serial!(q, u);\n(irange,jrange,trange) = (1:500,1:500,1:499)\n 830.220 milliseconds (216 allocations: 13820 bytes)\n\njulia> @time advection_parallel!(q, u);\n 2.495 seconds (3999 k allocations: 289 MB, 2.09% gc time)\n\njulia> @time advection_shared!(q,u);\n From worker 2: (irange,jrange,trange) = (1:500,1:125,1:499)\n From worker 4: (irange,jrange,trange) = (1:500,251:375,1:499)\n From worker 3: (irange,jrange,trange) = (1:500,126:250,1:499)\n From worker 5: (irange,jrange,trange) = (1:500,376:500,1:499)\n 238.119 milliseconds (2264 allocations: 169 KB)","category":"page"},{"location":"manual/distributed-computing/","page":"多进程和分布式计算","title":"多进程和分布式计算","text":"这里 advection_shared! 最大的优势在于,最小程度地降低了 woker 之间的通信,从而让每个 worker 能针对被分配的部分持续地计算一段时间。","category":"page"},{"location":"manual/distributed-computing/#共享数组与分布式垃圾回收","page":"多进程和分布式计算","title":"共享数组与分布式垃圾回收","text":"","category":"section"},{"location":"manual/distributed-computing/","page":"多进程和分布式计算","title":"多进程和分布式计算","text":"和远程引用一样,共享数组也依赖于创建节点上的垃圾回收来释放所有参与的 worker 上的引用。因此,创建大量生命周期比较短的数组,并尽可能快地显式 finilize 这些对象,代码会更高效,这样与之对用的内存和文件句柄都会更快地释放。","category":"page"},{"location":"manual/distributed-computing/#集群管理器","page":"多进程和分布式计算","title":"集群管理器","text":"","category":"section"},{"location":"manual/distributed-computing/","page":"多进程和分布式计算","title":"多进程和分布式计算","text":"Julia 通过集群管理器实现对多个进程(所构成的逻辑上的集群)的启动,管理以及网络通信。一个 ClusterManager 负责:","category":"page"},{"location":"manual/distributed-computing/","page":"多进程和分布式计算","title":"多进程和分布式计算","text":"在一个集群环境中启动 worker 进程 \n管理每个 worker 生命周期内的事件\n(可选),提供数据传输","category":"page"},{"location":"manual/distributed-computing/","page":"多进程和分布式计算","title":"多进程和分布式计算","text":"一个 Julia 集群由以下特点:","category":"page"},{"location":"manual/distributed-computing/","page":"多进程和分布式计算","title":"多进程和分布式计算","text":"初始进程,称为 master,其 id 为 1\n只有 master 进程可以增加或删除 worker 进程\n所有进程之间都可以直接通信","category":"page"},{"location":"manual/distributed-computing/","page":"多进程和分布式计算","title":"多进程和分布式计算","text":"worker 之间的连接(用的是内置的 TCP/IP 传输)按照以下方式进行:","category":"page"},{"location":"manual/distributed-computing/","page":"多进程和分布式计算","title":"多进程和分布式计算","text":"master 进程对一个 ClusterManager 对象调用 addprocs\naddprocs 调用对应的 launch 方法,然后在对应的机器上启动相应数量的 worker 进程\n每个 worker 监听一个端口,然后将其 host 和 port 信息传给 stdout\n集群管理器捕获 stdout 中每个 worker 的信息,并提供给 master 进程\nmaster 进程解析信息并与相应的 worker 建立 TCP/IP 连接\n每个 worker 都会被通知集群中的其它 worker\n每个 worker 与 id 小于自己的 worker 连接\n这样,一个网络就建立了,从而,每个 worker 都可以与其它 worker 建立连接","category":"page"},{"location":"manual/distributed-computing/","page":"多进程和分布式计算","title":"多进程和分布式计算","text":"尽管默认的传输层使用的是 TCPSocket,对于一个自定义的集群管理器来说,完全可以使用其它传输方式。","category":"page"},{"location":"manual/distributed-computing/","page":"多进程和分布式计算","title":"多进程和分布式计算","text":"Julia 提供了两种内置的集群管理器:","category":"page"},{"location":"manual/distributed-computing/","page":"多进程和分布式计算","title":"多进程和分布式计算","text":"LocalManager,调用 addprocs() 或 addprocs(np::Integer) 时会用到。\nSSHManager,调用 addprocs(hostnames::Array) 时,传递一个 hostnames 的列表。","category":"page"},{"location":"manual/distributed-computing/","page":"多进程和分布式计算","title":"多进程和分布式计算","text":"LocalManager 用来在同一个 host 上启动多个 worker,从而利用多核/多处理器硬件。","category":"page"},{"location":"manual/distributed-computing/","page":"多进程和分布式计算","title":"多进程和分布式计算","text":"因此,一个最小的集群管理器需要:","category":"page"},{"location":"manual/distributed-computing/","page":"多进程和分布式计算","title":"多进程和分布式计算","text":"是一个 ClusterManager 抽象类的一个子类\n实现 launch 接口,用来启动新的 worker\n实现 manage,在一个 worker 的生命周期中多次被调用(例如,发送中断信号)","category":"page"},{"location":"manual/distributed-computing/","page":"多进程和分布式计算","title":"多进程和分布式计算","text":"addprocs(manager::FooManager) 需要 FooManager 实现:","category":"page"},{"location":"manual/distributed-computing/","page":"多进程和分布式计算","title":"多进程和分布式计算","text":"function launch(manager::FooManager, params::Dict, launched::Array, c::Condition)\n [...]\nend\n\nfunction manage(manager::FooManager, id::Integer, config::WorkerConfig, op::Symbol)\n [...]\nend","category":"page"},{"location":"manual/distributed-computing/","page":"多进程和分布式计算","title":"多进程和分布式计算","text":"作为一个例子,我们来看下 LocalManager 是怎么实现的:","category":"page"},{"location":"manual/distributed-computing/","page":"多进程和分布式计算","title":"多进程和分布式计算","text":"struct LocalManager <: ClusterManager\n np::Integer\nend\n\nfunction launch(manager::LocalManager, params::Dict, launched::Array, c::Condition)\n [...]\nend\n\nfunction manage(manager::LocalManager, id::Integer, config::WorkerConfig, op::Symbol)\n [...]\nend","category":"page"},{"location":"manual/distributed-computing/","page":"多进程和分布式计算","title":"多进程和分布式计算","text":"launch 方法接收以下参数:","category":"page"},{"location":"manual/distributed-computing/","page":"多进程和分布式计算","title":"多进程和分布式计算","text":"manager::ClusterManager: 调用 addprocs 时所用到的集群管理器\nparams::Dict: 所有的关键字参数都会传递到 addprocs 中\nlaunched::Array: 用来存储一个或多个 WorkerConfig\nc::Condition: 在 workers 启动后被通知的条件变量","category":"page"},{"location":"manual/distributed-computing/","page":"多进程和分布式计算","title":"多进程和分布式计算","text":"launch 会在一个异步的task中调用,该 task 结束之后,意味着所有请求的 worker 都已经启动好了。因此,launch 函数必须在所有 worker 启动之后,尽快退出。","category":"page"},{"location":"manual/distributed-computing/","page":"多进程和分布式计算","title":"多进程和分布式计算","text":"新启动的 worker 之间采用的是多对多的连接方式。在命令行中指定参数 --worker[=] 会让所有启动的进程把自己当作 worker,然后通过 TCP/IP 构建连接。","category":"page"},{"location":"manual/distributed-computing/","page":"多进程和分布式计算","title":"多进程和分布式计算","text":"集群中所有的 worker 默认使用同一个 master 的 cookie。如果 cookie 没有指定,(比如没有通过 --worker 指定),那么 worker 会尝试从它的标准输入中读取。LocalManager 和 SSHManager 都是通过标准输入来将 cookie 传递给新启动的 worker。","category":"page"},{"location":"manual/distributed-computing/","page":"多进程和分布式计算","title":"多进程和分布式计算","text":"默认情况下,一个 worker 会监听从 getipaddr() 函数返回的地址上的一个开放端口。若要指定监听的地址,可以通过额外的参数 --bind-to bind_addr[:port] 指定,这对于多 host 的情况来说很方便。","category":"page"},{"location":"manual/distributed-computing/","page":"多进程和分布式计算","title":"多进程和分布式计算","text":"对于非 TCP/IP 传输,可以选择 MPI 作为一种实现,此时一定不要指定 --worker 参数,另外,新启动的 worker 必须调用 init_worker(cookie) 之后再使用并行的结构体。","category":"page"},{"location":"manual/distributed-computing/","page":"多进程和分布式计算","title":"多进程和分布式计算","text":"对于每个已经启动的 worker,launch 方法必须往 launched 中添加一个 WorkerConfig 对象(相应的值已经初始化)。","category":"page"},{"location":"manual/distributed-computing/","page":"多进程和分布式计算","title":"多进程和分布式计算","text":"mutable struct WorkerConfig\n # Common fields relevant to all cluster managers\n io::Union{IO, Nothing}\n host::Union{AbstractString, Nothing}\n port::Union{Integer, Nothing}\n\n # Used when launching additional workers at a host\n count::Union{Int, Symbol, Nothing}\n exename::Union{AbstractString, Cmd, Nothing}\n exeflags::Union{Cmd, Nothing}\n\n # External cluster managers can use this to store information at a per-worker level\n # Can be a dict if multiple fields need to be stored.\n userdata::Any\n\n # SSHManager / SSH tunnel connections to workers\n tunnel::Union{Bool, Nothing}\n bind_addr::Union{AbstractString, Nothing}\n sshflags::Union{Cmd, Nothing}\n max_parallel::Union{Integer, Nothing}\n\n # Used by Local/SSH managers\n connect_at::Any\n\n [...]\nend","category":"page"},{"location":"manual/distributed-computing/","page":"多进程和分布式计算","title":"多进程和分布式计算","text":"WorkerConfig 中的大多数字段都是内置的集群管理器会用到,对于自定义的管理器,通常只需要指定 io 或 host/port:","category":"page"},{"location":"manual/distributed-computing/","page":"多进程和分布式计算","title":"多进程和分布式计算","text":"如果指定了 io,那么就会用来读取 host/port 信息。每个 worker 会在启动时打印地址和端口,这样 worker 就可以自由监听可用的端口,而不必手动配置 worker 的端口。\n如果 io 没有指定,那么 host 和 port 就会用来连接。\ncount,exename 和 exeflags 用于从一个 worker 上启动额外的 worker。例如,一个集群管理器可能对每个节点都只启动一个 worker,然后再用它来启动额外的 worker。\ncount 可以是一个整数 n,用来指定启动 n 个 worker\ncount 还可以是 :auto,用来启动跟那台机器上 CPU 个数(逻辑上的核的个数)相同的 worker\nexename 是 julia 可执行文件的全路径\nexeflags 应该设置成传递给将要启动的 worker 命令行参数\ntunnel, bind_addr, sshflags 和 max_parallel 会在从 worker 与 master 进程建立 ssh 隧道时用到\nuserdata 用来提供给自定义集群管理器存储自己的 worker 相关的信息","category":"page"},{"location":"manual/distributed-computing/","page":"多进程和分布式计算","title":"多进程和分布式计算","text":"manage(manager::FooManager, id::Integer, config::WorkerConfig, op::Symbol) 会在一个 worker 生命周期中的不同时刻被调用,其中 op 的值可能是:","category":"page"},{"location":"manual/distributed-computing/","page":"多进程和分布式计算","title":"多进程和分布式计算","text":":register/:deregister,从 Julia 的 worker 池子中添加/删除一个 worker\n:interrupt,当 interrupt(workers) 被调用是,此时,ClusterManager 应该给相应的 worker 发送终端信号\n:finalize,用于清理操作。","category":"page"},{"location":"manual/distributed-computing/#自定义集群管理器的传输方式","page":"多进程和分布式计算","title":"自定义集群管理器的传输方式","text":"","category":"section"},{"location":"manual/distributed-computing/","page":"多进程和分布式计算","title":"多进程和分布式计算","text":"将默认的 TCP/IP 多对多 socket 连接替换成一个自定义的传输层需要做很多工作。每个 Julia 进程都有与其连接的 worker 数量相同的通信 task。例如,在一个有 32 个进程的多对多集群中:","category":"page"},{"location":"manual/distributed-computing/","page":"多进程和分布式计算","title":"多进程和分布式计算","text":"每个进程都有31个通信task\n每个 task 在一个消息处理循环中从一个远端 worker 读取所有的输入信息\n每个消息处理循环等待一个 IO 对象(比如,在默认实现中是一个 TCPSocket),然后读取整个信息,处理,等待下一个\n发送消息则可以直接在任意 Julia task 中完成,而不只是通信 task,同样,也是通过相应的 IO 对象","category":"page"},{"location":"manual/distributed-computing/","page":"多进程和分布式计算","title":"多进程和分布式计算","text":"要替换默认的传输方式,需要新的实现能够在远程 worker 之间建立连接,同时提供一个可以用来被消息处理循环等待的 IO 对象。集群管理器的回调函数需要实现如下函数:","category":"page"},{"location":"manual/distributed-computing/","page":"多进程和分布式计算","title":"多进程和分布式计算","text":"connect(manager::FooManager, pid::Integer, config::WorkerConfig)\nkill(manager::FooManager, pid::Int, config::WorkerConfig)","category":"page"},{"location":"manual/distributed-computing/","page":"多进程和分布式计算","title":"多进程和分布式计算","text":"默认的实现(使用的是 TCP/IP socket)是 connect(manager::ClusterManager, pid::Integer, config::WorkerConfig)。","category":"page"},{"location":"manual/distributed-computing/","page":"多进程和分布式计算","title":"多进程和分布式计算","text":"connect 需要返回一对 IO 对象,一个用于从 pid worker 读取数据,另一个用于往 pid 写数据。自定义的集群管理器可以用内存中的 BUfferStream 作为一个管道将自定义的(很可能是非 IO 的)传输与 Julia 内置的并行基础设施衔接起来。","category":"page"},{"location":"manual/distributed-computing/","page":"多进程和分布式计算","title":"多进程和分布式计算","text":"BufferStream 是一个内存中的 IOBuffer,其表现很像 IO,就是一个流(stream),可以异步地处理。","category":"page"},{"location":"manual/distributed-computing/","page":"多进程和分布式计算","title":"多进程和分布式计算","text":"在 Examples repository 的 clustermanager/0mq 目录中,包含一个使用 ZeroMQ 连接 Julia worker 的例子,用的是星型拓补结构。需要注意的是:Julia 的进程仍然是逻辑上相互连接的,任意 worker 都可以与其它 worker 直接相连而无需感知到 0MQ 作为传输层的存在。","category":"page"},{"location":"manual/distributed-computing/","page":"多进程和分布式计算","title":"多进程和分布式计算","text":"在使用自定义传输的时候:","category":"page"},{"location":"manual/distributed-computing/","page":"多进程和分布式计算","title":"多进程和分布式计算","text":"Julia 的 workers 必须不能通过 --worker 启动。如果启动的时候使用了 --worker,那么新启动的 worker 会默认使用基于 TCP/IP socket 的实现\n对于每个 worker 逻辑上的输入连接,必须调用 Base.process_messages(rd::IO, wr::IO)(),这会创建一个新的 task 来处理 worker 消息的读写\ninit_worker(cookie, manager::FooManager) 必须作为 worker 进程初始化的一部分呢被调用\nWorkerConfig中的 connect_at::Any 字段可以被集群管理器在调用 launch 的时候设置,该字段的值会发送到所有的 connect 回调中。通常,其中包含的是如何连接到一个 worker 的信息。例如,在 TCP/IP socket 传输中,用这个字段存储 (host, port) 来声明如何连接到一个 worker。","category":"page"},{"location":"manual/distributed-computing/","page":"多进程和分布式计算","title":"多进程和分布式计算","text":"kill(manager, pid, config) 用来从一个集群中删除一个 worker,在 master 进程中,对应的 IO 对象必须通过对应的实现来关闭,从而保证正确地释放资源。默认的实现简单地对指定的远端 worker 执行 exit() 即可。","category":"page"},{"location":"manual/distributed-computing/","page":"多进程和分布式计算","title":"多进程和分布式计算","text":"在例子目录中,clustermanager/simple 展示了一个简单地实现,使用的是 UNIX 下的 socket。","category":"page"},{"location":"manual/distributed-computing/#LocalManager-和-SSHManager-的网络要求","page":"多进程和分布式计算","title":"LocalManager 和 SSHManager 的网络要求","text":"","category":"section"},{"location":"manual/distributed-computing/","page":"多进程和分布式计算","title":"多进程和分布式计算","text":"Julia 集群设计的时候,默认是在一个安全的环境中执行,比如本地的笔记本,部门的集群,甚至是云端。这部分将介绍 LocalManager 和 SSHManager 的网络安全要点:","category":"page"},{"location":"manual/distributed-computing/","page":"多进程和分布式计算","title":"多进程和分布式计算","text":"master 进程不监听任何端口,它只负责向外连接 worker\n每个 worker 都只绑定一个本地的接口,同时监听一个操作系统分配的临时端口。\naddprocs(N) 使用的 LocalManager,默认只会绑定到回环接口(loopback interface),这就意味着,之后在远程主机上(恶意)启动的 worker 无法连接到集群中,在执行 addprocs(4) 之后,又跟一个 addprocs([\"remote_host\"]) 会失败。有些用户可能希望创建一个集群同时管理本地系统和几个远端系统,这可以通过在绑定 LocalManager 到外部网络接口的时候,指定一个 restrict 参数:addprocs(4; restrict=false)\naddprocs(list_of_remote_hosts) 使用的 SSHManager 会通过 SSH 启动远程机上的 worker。","category":"page"},{"location":"manual/distributed-computing/","page":"多进程和分布式计算","title":"多进程和分布式计算","text":"默认 SSH 只会用来启动 Julia 的 worker。随后的 master-worker 和 worker-worker 连接使用的是普通的、未加密的 TCP/IP 通信。 远程机必须开启免密登陆。 额外的 SSH 标记或认证信息会通过关键字参数 sshflags 指定。","category":"page"},{"location":"manual/distributed-computing/","page":"多进程和分布式计算","title":"多进程和分布式计算","text":"addprocs(list_of_remote_hosts; tunnel=true, sshflags=) 在我们希望给 master-worker 也使用 SSH 连接的时候很有用。 一个典型的场景是本地的笔记本 运行 Julia ERPL (做为 master)和云上的其他机器,比如 Amazon EC2,构成集群。 这时候远程机器只要开启 22 端口就可以,然后要有 SSH 客户端 通过公约基础设施(PKI)认证过。授权信息可以通过 sshflags 生效,比如 sshflags=`-i `。\n在一个所有节点联通的拓扑网中(默认情况下是这样的),所有的 worker 节点都通过普通 TCP socket 通信互相连接。 这样集群的安全策略就必须允许 worker 节点间 通过操作系统分配的临时端口范围自由连接。\n所有 worker-worker 间(都是 SSH)的安全和加密或者信息的加密 都可以通过自定义 ClusterManager 完成。\n如果将 multiplex=true 指定为 addprocs 的选项,则 SSH 多路复用用于在 master 和 worker 之间创建隧道。 如果你自己配置了 SSH 多路复用并且已经建立了连接,则无论 multiplex 选项如何,都会使用 SSH 多路复用。 如果启用了多路复用,则使用现有连接(ssh 中的 -O forward 选项)设置转发。 如果你的服务器需要密码验证,那么这就很有用了;\n你可以通过在 addprocs 之前登录服务器来避免在 Julia 中进行身份验证。 除非使用现有的多路复用连接,否则在会话期间控制套接字将位于 ~/.ssh/julia-%r@%h:%p。 请注意,如果你在一个节点上创建多个进程并启用多路复用,带宽可能会受到限制,因为在这种情况下,进程共享一个多路复用 TCP 连接。","category":"page"},{"location":"manual/distributed-computing/#man-cluster-cookie","page":"多进程和分布式计算","title":"集群 Cookie","text":"","category":"section"},{"location":"manual/distributed-computing/","page":"多进程和分布式计算","title":"多进程和分布式计算","text":"集群上所有的进程都共享同一个 cookie,默认是 master 进程随机生成的字符串。","category":"page"},{"location":"manual/distributed-computing/","page":"多进程和分布式计算","title":"多进程和分布式计算","text":"cluster_cookie() 返回 cookie,而 cluster_cookie(cookie)() 设置并返回新的 cookie。\n所有的连接都进行双向认证,从而保证只有 master 启动的 worker 才能相互连接。\ncookie 可以在 worker 启动的时候,通过参数 --worker= 指定,如果参数 --worker 没有指定 cookie,那么 worker 会从它的标准输入中 (stdin) 读取, stdin 会在 cookie 获取之后立即关闭。\nClusterManager 可以通过 cluster_cookie() 从 master 中过去 cookie,不适用默认 TCP/IP 传输的集群管理器(即没有指定 --worker)必须用于 master 相同的 cookie 调用 init_worker(cookie, manager)。","category":"page"},{"location":"manual/distributed-computing/","page":"多进程和分布式计算","title":"多进程和分布式计算","text":"注意,在对安全性要求很高的环境中,可以通过自定义 ClusterManager 实现。例如,cookie 可以提前共享,然后不必再启动参数中指定。","category":"page"},{"location":"manual/distributed-computing/#指定网络拓补结构(实验性功能)","page":"多进程和分布式计算","title":"指定网络拓补结构(实验性功能)","text":"","category":"section"},{"location":"manual/distributed-computing/","page":"多进程和分布式计算","title":"多进程和分布式计算","text":"传递给 addprocs 的关键字参数 topology 用于指定 workers 必须如何相互连接:","category":"page"},{"location":"manual/distributed-computing/","page":"多进程和分布式计算","title":"多进程和分布式计算","text":":all_to_all,默认的,所有 worker 之间相互都连接\n:master_worker,只有主进程,即 pid 为 1 的进程能够与 worker 建立连接\n:custom: 集群管理器的 launch 方法通过 WorkerConfig 中的 ident 和 connect_idents 指定连接的拓补结构。一个 worker 通过集群管理器提供的 ident 来连接到所有 connect_idents 指定的 worker。","category":"page"},{"location":"manual/distributed-computing/","page":"多进程和分布式计算","title":"多进程和分布式计算","text":"关键字参数 lazy=true|false 只会影响 topology 选项中的 :all_to_all。如果是 true,那么集群启动的时候 master 会连接所有的 worker,然后 worker 之间的特定连接会在初次唤醒的是建立连接,这有利于降低集群初始化的时候对资源的分配。lazy 的默认值是 true。","category":"page"},{"location":"manual/distributed-computing/","page":"多进程和分布式计算","title":"多进程和分布式计算","text":"目前,在没有建立连接的两个 worker 之间传递消息会出错,目前该行为是实验性的,未来的版本中可能会改变。","category":"page"},{"location":"manual/distributed-computing/#一些值得关注的外部库","page":"多进程和分布式计算","title":"一些值得关注的外部库","text":"","category":"section"},{"location":"manual/distributed-computing/","page":"多进程和分布式计算","title":"多进程和分布式计算","text":"除了 Julia 自带的并行机制之外,还有许多外部的库值得一提。例如 MPI.jl 提供了一个 MPI 协议的 Julia 的封装,或者是在 共享数组 提到的 DistributedArrays.jl,此外尤其值得一提的是 Julia 的 GPU 编程生态,其包括:","category":"page"},{"location":"manual/distributed-computing/","page":"多进程和分布式计算","title":"多进程和分布式计算","text":"底层(C内核)的 OpenCL.jl 和 CUDAdrv.jl,分别提供了 OpenCL 和 CUDA 的封装。\n底层(Julia 内核)的接口,如 CUDAnative.jl,提供了 Julia 原生的 CUDA 实现。\n高层的特定抽象,如 CuArrays.jl 和 CLArrays.jl。\n高层的库,如 ArrayFire.jl 和 GPUArrays.jl。","category":"page"},{"location":"manual/distributed-computing/","page":"多进程和分布式计算","title":"多进程和分布式计算","text":"下面的例子将介绍如何用 DistributedArrays.jl 和 CuArrays.jl 通过 distribute() 和 CuArray() 将数组分配到多个进程。","category":"page"},{"location":"manual/distributed-computing/","page":"多进程和分布式计算","title":"多进程和分布式计算","text":"记住在载入 DistributedArrays.jl 时,需要用 @everywhere 将其载入到多个进程中。","category":"page"},{"location":"manual/distributed-computing/","page":"多进程和分布式计算","title":"多进程和分布式计算","text":"$ ./julia -p 4\n\njulia> addprocs()\n\njulia> @everywhere using DistributedArrays\n\njulia> using CuArrays\n\njulia> B = ones(10_000) ./ 2;\n\njulia> A = ones(10_000) .* π;\n\njulia> C = 2 .* A ./ B;\n\njulia> all(C .≈ 4*π)\ntrue\n\njulia> typeof(C)\nArray{Float64,1}\n\njulia> dB = distribute(B);\n\njulia> dA = distribute(A);\n\njulia> dC = 2 .* dA ./ dB;\n\njulia> all(dC .≈ 4*π)\ntrue\n\njulia> typeof(dC)\nDistributedArrays.DArray{Float64,1,Array{Float64,1}}\n\njulia> cuB = CuArray(B);\n\njulia> cuA = CuArray(A);\n\njulia> cuC = 2 .* cuA ./ cuB;\n\njulia> all(cuC .≈ 4*π);\ntrue\n\njulia> typeof(cuC)\nCuArray{Float64,1}","category":"page"},{"location":"manual/distributed-computing/","page":"多进程和分布式计算","title":"多进程和分布式计算","text":"请记住,CUDAnative.jl[2] 目前不支持某些 Julia 功能,尤其是像 sin 这样的一些函数需要替换为 CUDAnative.sin(cc:@maleadt)。","category":"page"},{"location":"manual/distributed-computing/","page":"多进程和分布式计算","title":"多进程和分布式计算","text":"下面的例子中,通过 DistributedArrays.jl 和 CuArrays.jl 将一个数组分配到多个进程,然后调用一个函数。","category":"page"},{"location":"manual/distributed-computing/","page":"多进程和分布式计算","title":"多进程和分布式计算","text":"function power_method(M, v)\n for i in 1:100\n v = M*v\n v /= norm(v)\n end\n\n return v, norm(M*v) / norm(v) # or (M*v) ./ v\nend","category":"page"},{"location":"manual/distributed-computing/","page":"多进程和分布式计算","title":"多进程和分布式计算","text":"power_method 重复创建一个新的向量然后对其归一化,这里并没有在函数中指定类型信息,来看看是否对前面提到的类型适用:","category":"page"},{"location":"manual/distributed-computing/","page":"多进程和分布式计算","title":"多进程和分布式计算","text":"julia> M = [2. 1; 1 1];\n\njulia> v = rand(2)\n2-element Array{Float64,1}:\n0.40395\n0.445877\n\njulia> power_method(M,v)\n([0.850651, 0.525731], 2.618033988749895)\n\njulia> cuM = CuArray(M);\n\njulia> cuv = CuArray(v);\n\njulia> curesult = power_method(cuM, cuv);\n\njulia> typeof(curesult)\nCuArray{Float64,1}\n\njulia> dM = distribute(M);\n\njulia> dv = distribute(v);\n\njulia> dC = power_method(dM, dv);\n\njulia> typeof(dC)\nTuple{DistributedArrays.DArray{Float64,1,Array{Float64,1}},Float64}","category":"page"},{"location":"manual/distributed-computing/","page":"多进程和分布式计算","title":"多进程和分布式计算","text":"最后,我们来看看 MPI.jl,这个库时 Julia 对 MPI 协议的封装。一一介绍其中的每个函数太累赘了,这里领会其实现协议的方法就够了。","category":"page"},{"location":"manual/distributed-computing/","page":"多进程和分布式计算","title":"多进程和分布式计算","text":"考虑下面这个简单的脚本,它做的只是调用每个子进程,然后初始化其 rank,然后在 master 访问时,对 rank 求和。","category":"page"},{"location":"manual/distributed-computing/","page":"多进程和分布式计算","title":"多进程和分布式计算","text":"import MPI\n\nMPI.Init()\n\ncomm = MPI.COMM_WORLD\nMPI.Barrier(comm)\n\nroot = 0\nr = MPI.Comm_rank(comm)\n\nsr = MPI.Reduce(r, MPI.SUM, root, comm)\n\nif(MPI.Comm_rank(comm) == root)\n @printf(\"sum of ranks: %s\\n\", sr)\nend\n\nMPI.Finalize()","category":"page"},{"location":"manual/distributed-computing/","page":"多进程和分布式计算","title":"多进程和分布式计算","text":"mpirun -np 4 ./julia example.jl","category":"page"},{"location":"manual/distributed-computing/","page":"多进程和分布式计算","title":"多进程和分布式计算","text":"[1]: In this context, MPI refers to the MPI-1 standard. Beginning with MPI-2, the MPI standards committee introduced a new set of communication mechanisms, collectively referred to as Remote Memory Access (RMA). The motivation for adding rma to the MPI standard was to facilitate one-sided communication patterns. For additional information on the latest MPI standard, see https://mpi-forum.org/docs.","category":"page"},{"location":"manual/distributed-computing/","page":"多进程和分布式计算","title":"多进程和分布式计算","text":"[2]: Julia GPU man pages","category":"page"},{"location":"manual/running-external-programs/#运行外部程序","page":"运行外部程序","title":"运行外部程序","text":"","category":"section"},{"location":"manual/running-external-programs/","page":"运行外部程序","title":"运行外部程序","text":"Julia 中命令的反引号记法借鉴于 shell、Perl 和 Ruby。然而,在 Julia 中编写","category":"page"},{"location":"manual/running-external-programs/","page":"运行外部程序","title":"运行外部程序","text":"julia> `echo hello`\n`echo hello`","category":"page"},{"location":"manual/running-external-programs/","page":"运行外部程序","title":"运行外部程序","text":"在多个方面上与 shell、Perl 和 Ruby 中的行为有所不同:","category":"page"},{"location":"manual/running-external-programs/","page":"运行外部程序","title":"运行外部程序","text":"反引号创建一个 Cmd 对象来表示命令,而不是立即运行命令。 你可以使用此对象将命令通过管道连接到其它命令、run 它以及对它进行 read 或 write。\n在命令运行时,Julia 不会捕获命令的输出结果,除非你对它专门安排。相反,在默认情况下,命令的输出会被定向到 stdout,因为它将使用 libc 的 system 调用。\n命令从不会在 shell 中运行。相反地,Julia 会直接解析命令语法,适当地插入变量并像 shell 那样拆分单词,同时遵从 shell 的引用语法。命令会作为 julia 的直接子进程运行,使用 fork 和 exec 调用。","category":"page"},{"location":"manual/running-external-programs/","page":"运行外部程序","title":"运行外部程序","text":"note: Note\n下面假设在 Linux 或 MacOS 上使用 Posix 环境。 在 Windows 上,许多类似的命令,例如 echo 和 dir,不是外部程序,而是内置在 shell cmd.exe 本身中。 运行这些命令的一种选择是调用 cmd.exe,例如 cmd /C echo hello。 或者,Julia 可以在 Posix 环境中运行,例如 Cygwin。","category":"page"},{"location":"manual/running-external-programs/","page":"运行外部程序","title":"运行外部程序","text":"这是运行外部程序的简单示例:","category":"page"},{"location":"manual/running-external-programs/","page":"运行外部程序","title":"运行外部程序","text":"julia> mycommand = `echo hello`\n`echo hello`\n\njulia> typeof(mycommand)\nCmd\n\njulia> run(mycommand);\nhello","category":"page"},{"location":"manual/running-external-programs/","page":"运行外部程序","title":"运行外部程序","text":"hello 是 echo 命令的输出,发送到 stdout。 如果外部命令无法成功运行,则 run 方法会抛出 ErrorException。","category":"page"},{"location":"manual/running-external-programs/","page":"运行外部程序","title":"运行外部程序","text":"如果要读取外部命令的输出,可以使用 read 或 readchomp 代替:","category":"page"},{"location":"manual/running-external-programs/","page":"运行外部程序","title":"运行外部程序","text":"julia> read(`echo hello`, String)\n\"hello\\n\"\n\njulia> readchomp(`echo hello`)\n\"hello\"","category":"page"},{"location":"manual/running-external-programs/","page":"运行外部程序","title":"运行外部程序","text":"更一般地,你可以使用 open 来读取或写入外部命令。","category":"page"},{"location":"manual/running-external-programs/","page":"运行外部程序","title":"运行外部程序","text":"julia> open(`less`, \"w\", stdout) do io\n for i = 1:3\n println(io, i)\n end\n end\n1\n2\n3","category":"page"},{"location":"manual/running-external-programs/","page":"运行外部程序","title":"运行外部程序","text":"命令中的程序名称和各个参数可以访问和迭代,这就好像命令也是一个字符串数组:","category":"page"},{"location":"manual/running-external-programs/","page":"运行外部程序","title":"运行外部程序","text":"julia> collect(`echo \"foo bar\"`)\n2-element Vector{String}:\n \"echo\"\n \"foo bar\"\n\njulia> `echo \"foo bar\"`[2]\n\"foo bar\"","category":"page"},{"location":"manual/running-external-programs/#command-interpolation","page":"运行外部程序","title":"插值","text":"","category":"section"},{"location":"manual/running-external-programs/","page":"运行外部程序","title":"运行外部程序","text":"假设你想要做的事情更复杂,并使用以变量 file 表示的文件名作为命令的参数。那你可以像在字符串字面量中那样使用 $ 进行插值:","category":"page"},{"location":"manual/running-external-programs/","page":"运行外部程序","title":"运行外部程序","text":"julia> file = \"/etc/passwd\"\n\"/etc/passwd\"\n\njulia> `sort $file`\n`sort /etc/passwd`","category":"page"},{"location":"manual/running-external-programs/","page":"运行外部程序","title":"运行外部程序","text":"通过 shell 运行外部程序的一个常见陷阱是,如果文件名中包含 shell 中的特殊字符,那么可能会导致不希望出现的行为。例如,假设我们想要对其内容进行排序的文件是 /Volumes/External HD/data.csv,而不是 /etc/passwd。让我们来试试:","category":"page"},{"location":"manual/running-external-programs/","page":"运行外部程序","title":"运行外部程序","text":"julia> file = \"/Volumes/External HD/data.csv\"\n\"/Volumes/External HD/data.csv\"\n\njulia> `sort $file`\n`sort '/Volumes/External HD/data.csv'`","category":"page"},{"location":"manual/running-external-programs/","page":"运行外部程序","title":"运行外部程序","text":"文件名是如何被引用的?Julia 知道 file 是作为单个参数插入的,因此它替你引用了此单词。事实上,这不太准确:file 的值始终不会被 shell 解释,因此并不需要实际引用;插入引号只是为了展现给用户。就算你把值作为 shell 单词的一部分插入,这也可以工作:","category":"page"},{"location":"manual/running-external-programs/","page":"运行外部程序","title":"运行外部程序","text":"julia> path = \"/Volumes/External HD\"\n\"/Volumes/External HD\"\n\njulia> name = \"data\"\n\"data\"\n\njulia> ext = \"csv\"\n\"csv\"\n\njulia> `sort $path/$name.$ext`\n`sort '/Volumes/External HD/data.csv'`","category":"page"},{"location":"manual/running-external-programs/","page":"运行外部程序","title":"运行外部程序","text":"如你所见,path 变量中的空格被恰当地转义了。但是,如果你想插入多个单词怎么办?在此情况下,只需使用数组(或其它可迭代容器):","category":"page"},{"location":"manual/running-external-programs/","page":"运行外部程序","title":"运行外部程序","text":"julia> files = [\"/etc/passwd\",\"/Volumes/External HD/data.csv\"]\n2-element Vector{String}:\n \"/etc/passwd\"\n \"/Volumes/External HD/data.csv\"\n\njulia> `grep foo $files`\n`grep foo /etc/passwd '/Volumes/External HD/data.csv'`","category":"page"},{"location":"manual/running-external-programs/","page":"运行外部程序","title":"运行外部程序","text":"如果将数组作为 shell 单词的一部分插入,Julia 将模拟 shell 的 {a,b,c} 参数生成:","category":"page"},{"location":"manual/running-external-programs/","page":"运行外部程序","title":"运行外部程序","text":"julia> names = [\"foo\",\"bar\",\"baz\"]\n3-element Vector{String}:\n \"foo\"\n \"bar\"\n \"baz\"\n\njulia> `grep xylophone $names.txt`\n`grep xylophone foo.txt bar.txt baz.txt`","category":"page"},{"location":"manual/running-external-programs/","page":"运行外部程序","title":"运行外部程序","text":"此外,若在同一单词中插入多个数组,则将模拟 shell 的笛卡尔积生成行为:","category":"page"},{"location":"manual/running-external-programs/","page":"运行外部程序","title":"运行外部程序","text":"julia> names = [\"foo\",\"bar\",\"baz\"]\n3-element Vector{String}:\n \"foo\"\n \"bar\"\n \"baz\"\n\njulia> exts = [\"aux\",\"log\"]\n2-element Vector{String}:\n \"aux\"\n \"log\"\n\njulia> `rm -f $names.$exts`\n`rm -f foo.aux foo.log bar.aux bar.log baz.aux baz.log`","category":"page"},{"location":"manual/running-external-programs/","page":"运行外部程序","title":"运行外部程序","text":"因为可以插入字面量数组,所以你可以使用此生成功能,而无需先创建临时数组对象:","category":"page"},{"location":"manual/running-external-programs/","page":"运行外部程序","title":"运行外部程序","text":"julia> `rm -rf $[\"foo\",\"bar\",\"baz\",\"qux\"].$[\"aux\",\"log\",\"pdf\"]`\n`rm -rf foo.aux foo.log foo.pdf bar.aux bar.log bar.pdf baz.aux baz.log baz.pdf qux.aux qux.log qux.pdf`","category":"page"},{"location":"manual/running-external-programs/#引用","page":"运行外部程序","title":"引用","text":"","category":"section"},{"location":"manual/running-external-programs/","page":"运行外部程序","title":"运行外部程序","text":"不可避免地,我们会想要编写不那么简单的命令,且有必要使用引号。下面是 shell 提示符下单行 Perl 程序的简单示例:","category":"page"},{"location":"manual/running-external-programs/","page":"运行外部程序","title":"运行外部程序","text":"sh$ perl -le '$|=1; for (0..3) { print }'\n0\n1\n2\n3","category":"page"},{"location":"manual/running-external-programs/","page":"运行外部程序","title":"运行外部程序","text":"该 Perl 表达式需要使用单引号有两个原因:一是为了避免空格将表达式分解为多个 shell 单词,二是为了在使用像 $|(是的,这在 Perl 中是变量名)这样的 Perl 变量时避免发生插值。在其它情况下,你可能想要使用双引号来真的进行插值:","category":"page"},{"location":"manual/running-external-programs/","page":"运行外部程序","title":"运行外部程序","text":"sh$ first=\"A\"\nsh$ second=\"B\"\nsh$ perl -le '$|=1; print for @ARGV' \"1: $first\" \"2: $second\"\n1: A\n2: B","category":"page"},{"location":"manual/running-external-programs/","page":"运行外部程序","title":"运行外部程序","text":"总之,Julia 反引号语法是经过精心设计的,因此你可以只是将 shell 命令剪切并粘贴到反引号中,接着它们将会工作:转义、引用和插值行为与 shell 相同。唯一的不同是,插值是集成的并且知道在 Julia 的概念中什么是单个字符串值、什么是多个值的容器。让我们在 Julia 中尝试上面的两个例子:","category":"page"},{"location":"manual/running-external-programs/","page":"运行外部程序","title":"运行外部程序","text":"julia> A = `perl -le '$|=1; for (0..3) { print }'`\n`perl -le '$|=1; for (0..3) { print }'`\n\njulia> run(A);\n0\n1\n2\n3\n\njulia> first = \"A\"; second = \"B\";\n\njulia> B = `perl -le 'print for @ARGV' \"1: $first\" \"2: $second\"`\n`perl -le 'print for @ARGV' '1: A' '2: B'`\n\njulia> run(B);\n1: A\n2: B","category":"page"},{"location":"manual/running-external-programs/","page":"运行外部程序","title":"运行外部程序","text":"结果是相同的,且 Julia 的插值行为模仿了 shell 的并对其做了一些改进,因为 Julia 支持头等的可迭代对象,但大多数 shell 通过使用空格分隔字符串来实现这一点,而这又引入了歧义。在尝试将 shell 命令移植到 Julia 中时,请先试着剪切并粘贴它。因为 Julia 会在运行命令前向你显示命令,所以你可以在不造成任何破坏的前提下轻松并安全地检查命令的解释。","category":"page"},{"location":"manual/running-external-programs/#管道","page":"运行外部程序","title":"管道","text":"","category":"section"},{"location":"manual/running-external-programs/","page":"运行外部程序","title":"运行外部程序","text":"Shell 元字符,如 |、& 和 >,在 Julia 的反引号中需被引用(或转义):","category":"page"},{"location":"manual/running-external-programs/","page":"运行外部程序","title":"运行外部程序","text":"julia> run(`echo hello '|' sort`);\nhello | sort\n\njulia> run(`echo hello \\| sort`);\nhello | sort","category":"page"},{"location":"manual/running-external-programs/","page":"运行外部程序","title":"运行外部程序","text":"此表达式调用 echo 命令并以三个单词作为其参数:hello、| 和 sort。结果是只打印了一行:hello | sort。那么,如何构造管道呢?为此,请使用 pipeline,而不是在反引号内使用 '|':","category":"page"},{"location":"manual/running-external-programs/","page":"运行外部程序","title":"运行外部程序","text":"julia> run(pipeline(`echo hello`, `sort`));\nhello","category":"page"},{"location":"manual/running-external-programs/","page":"运行外部程序","title":"运行外部程序","text":"这将 echo 命令的输出传输到 sort 命令中。当然,这不是很有趣,因为只有一行要排序,但是我们的当然可以做更多、更有趣的事:","category":"page"},{"location":"manual/running-external-programs/","page":"运行外部程序","title":"运行外部程序","text":"julia> run(pipeline(`cut -d: -f3 /etc/passwd`, `sort -n`, `tail -n5`))\n210\n211\n212\n213\n214","category":"page"},{"location":"manual/running-external-programs/","page":"运行外部程序","title":"运行外部程序","text":"这将打印在 UNIX 系统上最高的五个用户 ID。cut、sort 和 tail 命令都是当前 julia 进程的直接子进程,这中间没有 shell 进程的干预。Julia 自己负责设置管道和连接文件描述符,而这通常由 shell 完成。因为 Julia 自己做了这些事,所以它能更好的控制并做 shell 做不到的一些事情。","category":"page"},{"location":"manual/running-external-programs/","page":"运行外部程序","title":"运行外部程序","text":"Julia 可以并行地运行多个命令:","category":"page"},{"location":"manual/running-external-programs/","page":"运行外部程序","title":"运行外部程序","text":"julia> run(`echo hello` & `echo world`);\nworld\nhello","category":"page"},{"location":"manual/running-external-programs/","page":"运行外部程序","title":"运行外部程序","text":"这里的输出顺序是不确定的,因为两个 echo 进程几乎同时启动,并且争着先写入 stdout 描述符和 julia 父进程。Julia 允许你将这两个进程的输出通过管道传输到另一个程序:","category":"page"},{"location":"manual/running-external-programs/","page":"运行外部程序","title":"运行外部程序","text":"julia> run(pipeline(`echo world` & `echo hello`, `sort`));\nhello\nworld","category":"page"},{"location":"manual/running-external-programs/","page":"运行外部程序","title":"运行外部程序","text":"在 UNIX 管道方面,这里发生的是,一个 UNIX 管道对象由两个 echo 进程创建和写入,管道的另一端由 sort 命令读取。","category":"page"},{"location":"manual/running-external-programs/","page":"运行外部程序","title":"运行外部程序","text":"IO 重定向可以通过向 pipeline 函数传递关键字参数 stdin、stdout 和 stderr 来实现:","category":"page"},{"location":"manual/running-external-programs/","page":"运行外部程序","title":"运行外部程序","text":"pipeline(`do_work`, stdout=pipeline(`sort`, \"out.txt\"), stderr=\"errs.txt\")","category":"page"},{"location":"manual/running-external-programs/#避免管道中的死锁","page":"运行外部程序","title":"避免管道中的死锁","text":"","category":"section"},{"location":"manual/running-external-programs/","page":"运行外部程序","title":"运行外部程序","text":"在单个进程中读取和写入管道的两端时,避免强制内核缓冲所有数据是很重要的。","category":"page"},{"location":"manual/running-external-programs/","page":"运行外部程序","title":"运行外部程序","text":"例如,在读取命令的所有输出时,请调用 read(out, String),而非 wait(process),因为前者会积极地消耗由该进程写入的所有数据,而后者在等待读取者连接时会尝试将数据存储内核的缓冲区中。","category":"page"},{"location":"manual/running-external-programs/","page":"运行外部程序","title":"运行外部程序","text":"另一个常见的解决方案是将读取者和写入者分离到单独的 Task 中:","category":"page"},{"location":"manual/running-external-programs/","page":"运行外部程序","title":"运行外部程序","text":"writer = @async write(process, \"data\")\nreader = @async do_compute(read(process, String))\nwait(writer)\nfetch(reader)","category":"page"},{"location":"manual/running-external-programs/","page":"运行外部程序","title":"运行外部程序","text":"(通常,reader 不是一个单独的任务,因为无论如何我们都会立即fetch它)。","category":"page"},{"location":"manual/running-external-programs/#复杂示例","page":"运行外部程序","title":"复杂示例","text":"","category":"section"},{"location":"manual/running-external-programs/","page":"运行外部程序","title":"运行外部程序","text":"高级编程语言、头等的命令抽象以及进程间管道的自动设置,三者组合起来非常强大。为了更好地理解可被轻松创建的复杂管道,这里有一些更复杂的例子,以避免对单行 Perl 程序的滥用。","category":"page"},{"location":"manual/running-external-programs/","page":"运行外部程序","title":"运行外部程序","text":"julia> prefixer(prefix, sleep) = `perl -nle '$|=1; print \"'$prefix' \", $_; sleep '$sleep';'`;\n\njulia> run(pipeline(`perl -le '$|=1; for(0..5){ print; sleep 1 }'`, prefixer(\"A\",2) & prefixer(\"B\",2)));\nB 0\nA 1\nB 2\nA 3\nB 4\nA 5","category":"page"},{"location":"manual/running-external-programs/","page":"运行外部程序","title":"运行外部程序","text":"这是一个经典的例子,一个生产者为两个并发的消费者提供内容:一个 perl 进程生成从数字 0 到 5 的行,而两个并行进程则使用该输出,一个行首加字母「A」,另一个行首加字母「B」。哪个进程使用第一行是不确定的,但是一旦赢得了竞争,这些行会先后被其中一个进程及另一个进程交替使用。(在 Perl 中设置 $|=1 会导致每个 print 语句刷新 stdout 句柄,这是本例工作所必需的。此外,所有输出将被缓存并一次性打印到管道中,以便只由一个消费者进程读取。)","category":"page"},{"location":"manual/running-external-programs/","page":"运行外部程序","title":"运行外部程序","text":"这是一个更加复杂的多阶段生产者——消费者示例:","category":"page"},{"location":"manual/running-external-programs/","page":"运行外部程序","title":"运行外部程序","text":"julia> run(pipeline(`perl -le '$|=1; for(0..5){ print; sleep 1 }'`,\n prefixer(\"X\",3) & prefixer(\"Y\",3) & prefixer(\"Z\",3),\n prefixer(\"A\",2) & prefixer(\"B\",2)));\nA X 0\nB Y 1\nA Z 2\nB X 3\nA Y 4\nB Z 5","category":"page"},{"location":"manual/running-external-programs/","page":"运行外部程序","title":"运行外部程序","text":"此示例与前一个类似,不同之处在于本例中的消费者有两个阶段,并且阶段间有不同的延迟,因此它们使用不同数量的并行 worker 来维持饱和的吞吐量。","category":"page"},{"location":"manual/running-external-programs/","page":"运行外部程序","title":"运行外部程序","text":"我们强烈建议你尝试所有这些例子,以便了解它们的工作原理。","category":"page"},{"location":"manual/running-external-programs/#Cmd对象","page":"运行外部程序","title":"Cmd对象","text":"","category":"section"},{"location":"manual/running-external-programs/","page":"运行外部程序","title":"运行外部程序","text":"反引号语法创建一个 Cmd 类型的对象。 此类对象也可以直接从现有的 Cmd 或参数列表构造:","category":"page"},{"location":"manual/running-external-programs/","page":"运行外部程序","title":"运行外部程序","text":"run(Cmd(`pwd`, dir=\"..\"))\nrun(Cmd([\"pwd\"], detach=true, ignorestatus=true))","category":"page"},{"location":"manual/running-external-programs/","page":"运行外部程序","title":"运行外部程序","text":"这允许你通过关键字参数指定 Cmd 的执行环境的几个方面。 例如,dir 关键字提供对 Cmd 工作目录的控制:","category":"page"},{"location":"manual/running-external-programs/","page":"运行外部程序","title":"运行外部程序","text":"julia> run(Cmd(`pwd`, dir=\"/\"));\n/","category":"page"},{"location":"manual/running-external-programs/","page":"运行外部程序","title":"运行外部程序","text":"并且 env 关键字允许您设置执行环境变量:","category":"page"},{"location":"manual/running-external-programs/","page":"运行外部程序","title":"运行外部程序","text":"julia> run(Cmd(`sh -c \"echo foo \\$HOWLONG\"`, env=(\"HOWLONG\" => \"ever!\",)));\nfoo ever!","category":"page"},{"location":"manual/running-external-programs/","page":"运行外部程序","title":"运行外部程序","text":"有关其它关键字参数,请参阅 Cmd。 setenv 和 addenv 命令分别提供了另一种替换或添加到 Cmd 执行环境变量的方法:","category":"page"},{"location":"manual/running-external-programs/","page":"运行外部程序","title":"运行外部程序","text":"julia> run(setenv(`sh -c \"echo foo \\$HOWLONG\"`, (\"HOWLONG\" => \"ever!\",)));\nfoo ever!\n\njulia> run(addenv(`sh -c \"echo foo \\$HOWLONG\"`, \"HOWLONG\" => \"ever!\"));\nfoo ever!","category":"page"},{"location":"manual/networking-and-streams/#网络和流","page":"网络和流","title":"网络和流","text":"","category":"section"},{"location":"manual/networking-and-streams/","page":"网络和流","title":"网络和流","text":"Julia 提供了一个功能丰富的接口来处理流式 I/O 对象,如终端、管道和 TCP 套接字。此接口虽然在系统级是异步的,但是其以同步的方式展现给程序员,通常也不需要考虑底层的异步操作。这是通过大量使用 Julia 协作线程(协程)功能实现的。","category":"page"},{"location":"manual/networking-and-streams/#基础流-I/O","page":"网络和流","title":"基础流 I/O","text":"","category":"section"},{"location":"manual/networking-and-streams/","page":"网络和流","title":"网络和流","text":"所有 Julia stream 都暴露了 read 和 write 方法,将 stream 作为它们的第一个参数,如:","category":"page"},{"location":"manual/networking-and-streams/","page":"网络和流","title":"网络和流","text":"julia> write(stdout, \"Hello World\"); # suppress return value 11 with ;\nHello World\njulia> read(stdin, Char)\n\n'\\n': ASCII/Unicode U+000a (category Cc: Other, control)","category":"page"},{"location":"manual/networking-and-streams/","page":"网络和流","title":"网络和流","text":"注意,write 返回 11,字节数(\"Hello World\")写入 stdout,但是返回值使用 ; 抑制。","category":"page"},{"location":"manual/networking-and-streams/","page":"网络和流","title":"网络和流","text":"这里按了两次回车,以便 Julia 能够读取到换行符。正如你在这个例子中所看到的,write 以待写入的数据作为其第二个参数,而 read 以待读取的数据的类型作为其第二个参数。","category":"page"},{"location":"manual/networking-and-streams/","page":"网络和流","title":"网络和流","text":"例如,为了读取一个简单的字节数组,我们可以这样做:","category":"page"},{"location":"manual/networking-and-streams/","page":"网络和流","title":"网络和流","text":"julia> x = zeros(UInt8, 4)\n4-element Array{UInt8,1}:\n 0x00\n 0x00\n 0x00\n 0x00\n\njulia> read!(stdin, x)\nabcd\n4-element Array{UInt8,1}:\n 0x61\n 0x62\n 0x63\n 0x64","category":"page"},{"location":"manual/networking-and-streams/","page":"网络和流","title":"网络和流","text":"但是,因为这有些繁琐,所以提供了几个方便的方法。例如,我们可以把上面的代码编写为:","category":"page"},{"location":"manual/networking-and-streams/","page":"网络和流","title":"网络和流","text":"julia> read(stdin, 4)\nabcd\n4-element Array{UInt8,1}:\n 0x61\n 0x62\n 0x63\n 0x64","category":"page"},{"location":"manual/networking-and-streams/","page":"网络和流","title":"网络和流","text":"或者如果我们想要读取一整行:","category":"page"},{"location":"manual/networking-and-streams/","page":"网络和流","title":"网络和流","text":"julia> readline(stdin)\nabcd\n\"abcd\"","category":"page"},{"location":"manual/networking-and-streams/","page":"网络和流","title":"网络和流","text":"请注意,根据你的终端设置,你的 TTY 可能是行缓冲的,因此在数据发送给 Julia 前可能需要额外的回车。","category":"page"},{"location":"manual/networking-and-streams/","page":"网络和流","title":"网络和流","text":"若要读取 stdin 的每一行,可以使用 eachline:","category":"page"},{"location":"manual/networking-and-streams/","page":"网络和流","title":"网络和流","text":"for line in eachline(stdin)\n print(\"Found $line\")\nend","category":"page"},{"location":"manual/networking-and-streams/","page":"网络和流","title":"网络和流","text":"或者如果你想要按字符读取的话,使用 read :","category":"page"},{"location":"manual/networking-and-streams/","page":"网络和流","title":"网络和流","text":"while !eof(stdin)\n x = read(stdin, Char)\n println(\"Found: $x\")\nend","category":"page"},{"location":"manual/networking-and-streams/#文本-I/O","page":"网络和流","title":"文本 I/O","text":"","category":"section"},{"location":"manual/networking-and-streams/","page":"网络和流","title":"网络和流","text":"请注意,上面提到的 write 方法对二进制流进行操作。具体来说,值不会转换为任何规范的文本表示形式,而是按原样输出:","category":"page"},{"location":"manual/networking-and-streams/","page":"网络和流","title":"网络和流","text":"julia> write(stdout, 0x61); # suppress return value 1 with ;\na","category":"page"},{"location":"manual/networking-and-streams/","page":"网络和流","title":"网络和流","text":"请注意,a 被 write 函数写入到 stdout 并且返回值为 1(因为 0x61 为一个字节)。","category":"page"},{"location":"manual/networking-and-streams/","page":"网络和流","title":"网络和流","text":"对于文本 I/O,请根据需要使用 print 或 show 方法(有关这两个方法之间的差异的详细讨论,请参阅它们的文档):","category":"page"},{"location":"manual/networking-and-streams/","page":"网络和流","title":"网络和流","text":"julia> print(stdout, 0x61)\n97","category":"page"},{"location":"manual/networking-and-streams/","page":"网络和流","title":"网络和流","text":"有关如何实现自定义类型的显示方法的更多信息,请参阅 自定义 pretty-printing。","category":"page"},{"location":"manual/networking-and-streams/#IO-输出的上下文信息","page":"网络和流","title":"IO 输出的上下文信息","text":"","category":"section"},{"location":"manual/networking-and-streams/","page":"网络和流","title":"网络和流","text":"有时,IO 输出可受益于将上下文信息传递到 show 方法的能力。IOContext 对象提供了将任意元数据与 IO 对象相关联的框架。例如,:compact => true 向 IO 对象添加一个参数来提示调用的 show 方法应该打印一个较短的输出(如果适用)。有关常用属性的列表,请参阅 IOContext 文档。","category":"page"},{"location":"manual/networking-and-streams/#使用文件","page":"网络和流","title":"使用文件","text":"","category":"section"},{"location":"manual/networking-and-streams/","page":"网络和流","title":"网络和流","text":"和其他环境一样,Julia 有 open 函数,它接收文件名并返回一个 IOStream 对象,你可以用该对象来对文件进行读取和写入。例如,如果我们有文件 hello.txt,其内容为 Hello, World!:","category":"page"},{"location":"manual/networking-and-streams/","page":"网络和流","title":"网络和流","text":"julia> f = open(\"hello.txt\")\nIOStream()\n\njulia> readlines(f)\n1-element Array{String,1}:\n \"Hello, World!\"","category":"page"},{"location":"manual/networking-and-streams/","page":"网络和流","title":"网络和流","text":"若要写入文件,则可以带着 write(\"w\")标志来打开它:","category":"page"},{"location":"manual/networking-and-streams/","page":"网络和流","title":"网络和流","text":"julia> f = open(\"hello.txt\",\"w\")\nIOStream()\n\njulia> write(f,\"Hello again.\")\n12","category":"page"},{"location":"manual/networking-and-streams/","page":"网络和流","title":"网络和流","text":"你如果在此刻检查 hello.txt 的内容,会注意到它是空的;改动实际上还没有写入到磁盘中。这是因为 IOStream 必须在写入实际刷新到磁盘前关闭:","category":"page"},{"location":"manual/networking-and-streams/","page":"网络和流","title":"网络和流","text":"julia> close(f)","category":"page"},{"location":"manual/networking-and-streams/","page":"网络和流","title":"网络和流","text":"再次检查 hello.txt 将显示其内容已被更改。","category":"page"},{"location":"manual/networking-and-streams/","page":"网络和流","title":"网络和流","text":"打开文件,对其内容执行一些操作,并再次关闭它是一种非常常见的模式。为了使这更容易,open 还有另一种调用方式,它以一个函数作为其第一个参数,以文件名作为其第二个参数,以该文件为参数调用该函数,然后再次关闭它。例如,给定函数:","category":"page"},{"location":"manual/networking-and-streams/","page":"网络和流","title":"网络和流","text":"function read_and_capitalize(f::IOStream)\n return uppercase(read(f, String))\nend","category":"page"},{"location":"manual/networking-and-streams/","page":"网络和流","title":"网络和流","text":"可以调用:","category":"page"},{"location":"manual/networking-and-streams/","page":"网络和流","title":"网络和流","text":"julia> open(read_and_capitalize, \"hello.txt\")\n\"HELLO AGAIN.\"","category":"page"},{"location":"manual/networking-and-streams/","page":"网络和流","title":"网络和流","text":"来打开 hello.txt,对它调用 read_and_capitalize,关闭 hello.txt 并返回大写的内容。","category":"page"},{"location":"manual/networking-and-streams/","page":"网络和流","title":"网络和流","text":"为了避免被迫定义一个命名函数,你可以使用 do 语法,它可以动态地创建匿名函数:","category":"page"},{"location":"manual/networking-and-streams/","page":"网络和流","title":"网络和流","text":"julia> open(\"hello.txt\") do f\n uppercase(read(f, String))\n end\n\"HELLO AGAIN.\"","category":"page"},{"location":"manual/networking-and-streams/#一个简单的-TCP-示例","page":"网络和流","title":"一个简单的 TCP 示例","text":"","category":"section"},{"location":"manual/networking-and-streams/","page":"网络和流","title":"网络和流","text":"让我们直接进入一个 TCP 套接字相关的简单示例。此功能位于名为 Sockets 的标准库中。让我们先创建一个简单的服务器:","category":"page"},{"location":"manual/networking-and-streams/","page":"网络和流","title":"网络和流","text":"julia> using Sockets\n\njulia> errormonitor(@async begin\n server = listen(2000)\n while true\n sock = accept(server)\n println(\"Hello World\\n\")\n end\n end)\nTask (runnable) @0x00007fd31dc11ae0","category":"page"},{"location":"manual/networking-and-streams/","page":"网络和流","title":"网络和流","text":"对于那些熟悉 Unix 套接字 API 的人,这些方法名称会让人感觉很熟悉,可是它们的用法比原始的 Unix 套接字 API 要简单些。在本例中,首次调用 listen 会创建一个服务器,等待传入指定端口(2000)的连接。","category":"page"},{"location":"manual/networking-and-streams/","page":"网络和流","title":"网络和流","text":"julia> listen(2000) # 监听(IPv4 下的)localhost:2000\nSockets.TCPServer(active)\n\njulia> listen(ip\"127.0.0.1\",2000) # 等价于第一个\nSockets.TCPServer(active)\n\njulia> listen(ip\"::1\",2000) # 监听(IPv6 下的)localhost:2000\nSockets.TCPServer(active)\n\njulia> listen(IPv4(0),2001) # 监听所有 IPv4 接口的端口 2001\nSockets.TCPServer(active)\n\njulia> listen(IPv6(0),2001) # 监听所有 IPv6 接口的端口 2001\nSockets.TCPServer(active)\n\njulia> listen(\"testsocket\") # 监听 UNIX 域套接字\nSockets.PipeServer(active)\n\njulia> listen(\"\\\\\\\\.\\\\pipe\\\\testsocket\") # 监听 Windows 命名管道\nSockets.PipeServer(active)","category":"page"},{"location":"manual/networking-and-streams/","page":"网络和流","title":"网络和流","text":"请注意,最后一次调用返回的类型是不同的。这是因为此服务器不监听 TCP,而是监听命名管道(Windows)或 UNIX 域套接字。还请注意 Windows 命名管道格式必须具有特定的模式,即名称前缀(\\\\.\\pipe\\),以便唯一标识文件类型。TCP 和命名管道或 UNIX 域套接字之间的区别是微妙的,这与 accept 和 connect 方法有关。accept 方法检索到连接到我们刚创建的服务器的客户端的连接,而 connect 函数使用指定的方法连接到服务器。connect 函数接收与 listen 相同的参数,因此,假设环境(即 host、cwd 等)相同,你应该能够将相同的参数传递给 connect,就像你在监听建立连接时所做的那样。那么让我们尝试一下(在创建上面的服务器之后):","category":"page"},{"location":"manual/networking-and-streams/","page":"网络和流","title":"网络和流","text":"julia> connect(2000)\nTCPSocket(open, 0 bytes waiting)\n\njulia> Hello World","category":"page"},{"location":"manual/networking-and-streams/","page":"网络和流","title":"网络和流","text":"不出所料,我们看到「Hello World」被打印出来。那么,让我们分析一下幕后发生的事情。在我们调用 connect 时,我们连接到刚刚创建的服务器。与此同时,accept 函数返回到新创建的套接字的服务器端连接,并打印「Hello World」来表明连接成功。","category":"page"},{"location":"manual/networking-and-streams/","page":"网络和流","title":"网络和流","text":"Julia 的强大优势在于,即使 I/O 实际上是异步发生的,API 也以同步方式暴露,我们不必担心回调,甚至不必确保服务器能够运行。在我们调用 connect 时,当前任务等待建立连接,并在这之后才继续执行。在此暂停中,服务器任务恢复执行(因为现在有一个连接请求是可用的),接受该连接,打印信息并等待下一个客户端。读取和写入以同样的方式运行。为了理解这一点,请考虑以下简单的 echo 服务器:","category":"page"},{"location":"manual/networking-and-streams/","page":"网络和流","title":"网络和流","text":"julia> errormonitor(@async begin\n server = listen(2001)\n while true\n sock = accept(server)\n @async while isopen(sock)\n write(sock, readline(sock, keep=true))\n end\n end\n end)\nTask (runnable) @0x00007fd31dc12e60\n\njulia> clientside = connect(2001)\nTCPSocket(RawFD(28) open, 0 bytes waiting)\n\njulia> errormonitor(@async while isopen(clientside)\n write(stdout, readline(clientside, keep=true))\n end)\nTask (runnable) @0x00007fd31dc11870\n\njulia> println(clientside,\"Hello World from the Echo Server\")\nHello World from the Echo Server","category":"page"},{"location":"manual/networking-and-streams/","page":"网络和流","title":"网络和流","text":"与其他流一样,使用 close 即可断开该套接字:","category":"page"},{"location":"manual/networking-and-streams/","page":"网络和流","title":"网络和流","text":"julia> close(clientside)","category":"page"},{"location":"manual/networking-and-streams/#解析-IP-地址","page":"网络和流","title":"解析 IP 地址","text":"","category":"section"},{"location":"manual/networking-and-streams/","page":"网络和流","title":"网络和流","text":"与 listen 方法不一致的 connect 方法之一是 connect(host::String,port),它将尝试连接到由 host 参数给定的主机上的由 port 参数给定的端口。它允许你执行以下操作:","category":"page"},{"location":"manual/networking-and-streams/","page":"网络和流","title":"网络和流","text":"julia> connect(\"google.com\", 80)\nTCPSocket(RawFD(30) open, 0 bytes waiting)","category":"page"},{"location":"manual/networking-and-streams/","page":"网络和流","title":"网络和流","text":"此功能的基础是 getaddrinfo,它将执行适当的地址解析:","category":"page"},{"location":"manual/networking-and-streams/","page":"网络和流","title":"网络和流","text":"julia> getaddrinfo(\"google.com\")\nip\"74.125.226.225\"","category":"page"},{"location":"manual/networking-and-streams/#异步-I/O","page":"网络和流","title":"异步 I/O","text":"","category":"section"},{"location":"manual/networking-and-streams/","page":"网络和流","title":"网络和流","text":"Base.read 和 Base.write 的所有 I/O 操作都可以通过使用 coroutines 异步执行。 你可以使用 @async 宏创建一个新的协程来读取或写入流:","category":"page"},{"location":"manual/networking-and-streams/","page":"网络和流","title":"网络和流","text":"julia> task = @async open(\"foo.txt\", \"w\") do io\n write(io, \"Hello, World!\")\n end;\n\njulia> wait(task)\n\njulia> readlines(\"foo.txt\")\n1-element Array{String,1}:\n \"Hello, World!\"","category":"page"},{"location":"manual/networking-and-streams/","page":"网络和流","title":"网络和流","text":"通常会遇到您想要同时执行多个异步操作并等待它们全部完成的情况。你可以使用@ sync宏,这会阻塞你的程序直到它所包裹的所有协程运行完毕。","category":"page"},{"location":"manual/networking-and-streams/","page":"网络和流","title":"网络和流","text":"julia> using Sockets\n\njulia> @sync for hostname in (\"google.com\", \"github.com\", \"julialang.org\")\n @async begin\n conn = connect(hostname, 80)\n write(conn, \"GET / HTTP/1.1\\r\\nHost:$(hostname)\\r\\n\\r\\n\")\n readline(conn, keep=true)\n println(\"Finished connection to $(hostname)\")\n end\n end\nFinished connection to google.com\nFinished connection to julialang.org\nFinished connection to github.com","category":"page"},{"location":"stdlib/REPL/#Julia-REPL","page":"Julia REPL","title":"Julia REPL","text":"","category":"section"},{"location":"stdlib/REPL/","page":"Julia REPL","title":"Julia REPL","text":"Julia 附带了一个全功能的交互式命令行 REPL(read-eval-print loop),其内置于 julia 可执行文件中。它除了允许快速简便地执行 Julia 语句外,还具有可搜索的历史记录,tab 补全,许多有用的按键绑定以及专用的 help 和 shell 模式。只需不附带任何参数地调用 julia 或双击可执行文件即可启动 REPL:","category":"page"},{"location":"stdlib/REPL/","page":"Julia REPL","title":"Julia REPL","text":"io = IOBuffer()\nBase.banner(io)\nbanner = String(take!(io))\nimport Markdown\nMarkdown.parse(\"```\\n\\$ julia\\n\\n$(banner)\\njulia>\\n```\")","category":"page"},{"location":"stdlib/REPL/","page":"Julia REPL","title":"Julia REPL","text":"要退出交互式会话,在空白行上键入 ^D——control 键和 d 键,或者先键入 quit(),然后键入 return 或 enter 键。REPL 用横幅和 julia> 提示符欢迎你。","category":"page"},{"location":"stdlib/REPL/#不同的提示符模式","page":"Julia REPL","title":"不同的提示符模式","text":"","category":"section"},{"location":"stdlib/REPL/#Julian-模式","page":"Julia REPL","title":"Julian 模式","text":"","category":"section"},{"location":"stdlib/REPL/","page":"Julia REPL","title":"Julia REPL","text":"The REPL has five main modes of operation. The first and most common is the Julian prompt. It is the default mode of operation; each new line initially starts with julia>. It is here that you can enter Julia expressions. Hitting return or enter after a complete expression has been entered will evaluate the entry and show the result of the last expression.","category":"page"},{"location":"stdlib/REPL/","page":"Julia REPL","title":"Julia REPL","text":"julia> string(1 + 2)\n\"3\"","category":"page"},{"location":"stdlib/REPL/","page":"Julia REPL","title":"Julia REPL","text":"交互式运行有许多独特的实用功能。除了显示结果外,REPL 还将结果绑定到变量 ans 上。一行的尾随分号可用作禁止显示结果的标志。","category":"page"},{"location":"stdlib/REPL/","page":"Julia REPL","title":"Julia REPL","text":"julia> string(3 * 4);\n\njulia> ans\n\"12\"","category":"page"},{"location":"stdlib/REPL/","page":"Julia REPL","title":"Julia REPL","text":"In Julia mode, the REPL supports something called prompt pasting. This activates when pasting text that starts with julia> into the REPL. In that case, only expressions starting with julia> are parsed, others are removed. This makes it possible to paste a chunk of code that has been copied from a REPL session without having to scrub away prompts and outputs. This feature is enabled by default but can be disabled or enabled at will with REPL.enable_promptpaste(::Bool). If it is enabled, you can try it out by pasting the code block above this paragraph straight into the REPL. This feature does not work on the standard Windows command prompt due to its limitation at detecting when a paste occurs.","category":"page"},{"location":"stdlib/REPL/","page":"Julia REPL","title":"Julia REPL","text":"Objects are printed at the REPL using the show function with a specific IOContext. In particular, the :limit attribute is set to true. Other attributes can receive in certain show methods a default value if it's not already set, like :compact. It's possible, as an experimental feature, to specify the attributes used by the REPL via the Base.active_repl.options.iocontext dictionary (associating values to attributes). For example:","category":"page"},{"location":"stdlib/REPL/","page":"Julia REPL","title":"Julia REPL","text":"julia> rand(2, 2)\n2×2 Array{Float64,2}:\n 0.8833 0.329197\n 0.719708 0.59114\n\njulia> show(IOContext(stdout, :compact => false), \"text/plain\", rand(2, 2))\n 0.43540323669187075 0.15759787870609387\n 0.2540832269192739 0.4597637838786053\njulia> Base.active_repl.options.iocontext[:compact] = false;\n\njulia> rand(2, 2)\n2×2 Array{Float64,2}:\n 0.2083967319174056 0.13330606013126012\n 0.6244375177790158 0.9777957560761545","category":"page"},{"location":"stdlib/REPL/","page":"Julia REPL","title":"Julia REPL","text":"In order to define automatically the values of this dictionary at startup time, one can use the atreplinit function in the ~/.julia/config/startup.jl file, for example:","category":"page"},{"location":"stdlib/REPL/","page":"Julia REPL","title":"Julia REPL","text":"atreplinit() do repl\n repl.options.iocontext[:compact] = false\nend","category":"page"},{"location":"stdlib/REPL/#帮助模式","page":"Julia REPL","title":"帮助模式","text":"","category":"section"},{"location":"stdlib/REPL/","page":"Julia REPL","title":"Julia REPL","text":"When the cursor is at the beginning of the line, the prompt can be changed to a help mode by typing ?. Julia will attempt to print help or documentation for anything entered in help mode:","category":"page"},{"location":"stdlib/REPL/","page":"Julia REPL","title":"Julia REPL","text":"julia> ? # upon typing ?, the prompt changes (in place) to: help?>\n\nhelp?> string\nsearch: string String Cstring Cwstring RevString randstring bytestring SubString\n\n string(xs...)\n\n Create a string from any values using the print function.","category":"page"},{"location":"stdlib/REPL/","page":"Julia REPL","title":"Julia REPL","text":"Macros, types and variables can also be queried:","category":"page"},{"location":"stdlib/REPL/","page":"Julia REPL","title":"Julia REPL","text":"help?> @time\n @time\n\n A macro to execute an expression, printing the time it took to execute, the number of allocations,\n and the total number of bytes its execution caused to be allocated, before returning the value of the\n expression.\n\n See also @timev, @timed, @elapsed, and @allocated.\n\nhelp?> Int32\nsearch: Int32 UInt32\n\n Int32 <: Signed\n\n 32-bit signed integer type.","category":"page"},{"location":"stdlib/REPL/","page":"Julia REPL","title":"Julia REPL","text":"A string or regex literal searches all docstrings using apropos:","category":"page"},{"location":"stdlib/REPL/","page":"Julia REPL","title":"Julia REPL","text":"help?> \"aprop\"\nREPL.stripmd\nBase.Docs.apropos\n\nhelp?> r\"ap..p\"\nBase.:∘\nBase.shell_escape_posixly\nDistributed.CachingPool\nREPL.stripmd\nBase.Docs.apropos","category":"page"},{"location":"stdlib/REPL/","page":"Julia REPL","title":"Julia REPL","text":"Help mode can be exited by pressing backspace at the beginning of the line.","category":"page"},{"location":"stdlib/REPL/#man-shell-mode","page":"Julia REPL","title":"Shell mode","text":"","category":"section"},{"location":"stdlib/REPL/","page":"Julia REPL","title":"Julia REPL","text":"Just as help mode is useful for quick access to documentation, another common task is to use the system shell to execute system commands. Just as ? entered help mode when at the beginning of the line, a semicolon (;) will enter the shell mode. And it can be exited by pressing backspace at the beginning of the line.","category":"page"},{"location":"stdlib/REPL/","page":"Julia REPL","title":"Julia REPL","text":"julia> ; # upon typing ;, the prompt changes (in place) to: shell>\n\nshell> echo hello\nhello","category":"page"},{"location":"stdlib/REPL/","page":"Julia REPL","title":"Julia REPL","text":"note: Note\nFor Windows users, Julia's shell mode does not expose windows shell commands. Hence, this will fail:","category":"page"},{"location":"stdlib/REPL/","page":"Julia REPL","title":"Julia REPL","text":"julia> ; # upon typing ;, the prompt changes (in place) to: shell>\n\nshell> dir\nERROR: IOError: could not spawn `dir`: no such file or directory (ENOENT)\nStacktrace!\n.......","category":"page"},{"location":"stdlib/REPL/","page":"Julia REPL","title":"Julia REPL","text":"However, you can get access to PowerShell like this:","category":"page"},{"location":"stdlib/REPL/","page":"Julia REPL","title":"Julia REPL","text":"julia> ; # upon typing ;, the prompt changes (in place) to: shell>\n\nshell> powershell\nWindows PowerShell\nCopyright (C) Microsoft Corporation. All rights reserved.\nPS C:\\Users\\elm>","category":"page"},{"location":"stdlib/REPL/","page":"Julia REPL","title":"Julia REPL","text":"... and to cmd.exe like that (see the dir command):","category":"page"},{"location":"stdlib/REPL/","page":"Julia REPL","title":"Julia REPL","text":"julia> ; # upon typing ;, the prompt changes (in place) to: shell>\n\nshell> cmd\nMicrosoft Windows [version 10.0.17763.973]\n(c) 2018 Microsoft Corporation. All rights reserved.\nC:\\Users\\elm>dir\n Volume in drive C has no label\n Volume Serial Number is 1643-0CD7\n Directory of C:\\Users\\elm\n\n29/01/2020 22:15 .\n29/01/2020 22:15 ..\n02/02/2020 08:06 .atom","category":"page"},{"location":"stdlib/REPL/#Pkg-mode","page":"Julia REPL","title":"Pkg mode","text":"","category":"section"},{"location":"stdlib/REPL/","page":"Julia REPL","title":"Julia REPL","text":"The Package manager mode accepts specialized commands for loading and updating packages. It is entered by pressing the ] key at the Julian REPL prompt and exited by pressing CTRL-C or pressing the backspace key at the beginning of the line. The prompt for this mode is pkg>. It supports its own help-mode, which is entered by pressing ? at the beginning of the line of the pkg> prompt. The Package manager mode is documented in the Pkg manual, available at https://julialang.github.io/Pkg.jl/v1/.","category":"page"},{"location":"stdlib/REPL/#Search-modes","page":"Julia REPL","title":"Search modes","text":"","category":"section"},{"location":"stdlib/REPL/","page":"Julia REPL","title":"Julia REPL","text":"In all of the above modes, the executed lines get saved to a history file, which can be searched. To initiate an incremental search through the previous history, type ^R – the control key together with the r key. The prompt will change to (reverse-i-search)`':, and as you type the search query will appear in the quotes. The most recent result that matches the query will dynamically update to the right of the colon as more is typed. To find an older result using the same query, simply type ^R again.","category":"page"},{"location":"stdlib/REPL/","page":"Julia REPL","title":"Julia REPL","text":"Just as ^R is a reverse search, ^S is a forward search, with the prompt (i-search)`':. The two may be used in conjunction with each other to move through the previous or next matching results, respectively.","category":"page"},{"location":"stdlib/REPL/#Key-bindings","page":"Julia REPL","title":"Key bindings","text":"","category":"section"},{"location":"stdlib/REPL/","page":"Julia REPL","title":"Julia REPL","text":"The Julia REPL makes great use of key bindings. Several control-key bindings were already introduced above (^D to exit, ^R and ^S for searching), but there are many more. In addition to the control-key, there are also meta-key bindings. These vary more by platform, but most terminals default to using alt- or option- held down with a key to send the meta-key (or can be configured to do so), or pressing Esc and then the key.","category":"page"},{"location":"stdlib/REPL/","page":"Julia REPL","title":"Julia REPL","text":"Keybinding Description\nProgram control \n^D Exit (when buffer is empty)\n^C Interrupt or cancel\n^L Clear console screen\nReturn/Enter, ^J New line, executing if it is complete\nmeta-Return/Enter Insert new line without executing it\n? or ; Enter help or shell mode (when at start of a line)\n^R, ^S Incremental history search, described above\nCursor movement \nRight arrow, ^F Move right one character\nLeft arrow, ^B Move left one character\nctrl-Right, meta-F Move right one word\nctrl-Left, meta-B Move left one word\nHome, ^A Move to beginning of line\nEnd, ^E Move to end of line\nUp arrow, ^P Move up one line (or change to the previous history entry that matches the text before the cursor)\nDown arrow, ^N Move down one line (or change to the next history entry that matches the text before the cursor)\nShift-Arrow Key Move cursor according to the direction of the Arrow key, while activating the region (\"shift selection\")\nPage-up, meta-P Change to the previous history entry\nPage-down, meta-N Change to the next history entry\nmeta-< Change to the first history entry (of the current session if it is before the current position in history)\nmeta-> Change to the last history entry\n^-Space Set the \"mark\" in the editing region (and de-activate the region if it's active)\n^-Space ^-Space Set the \"mark\" in the editing region and make the region \"active\", i.e. highlighted\n^G De-activate the region (i.e. make it not highlighted)\n^X^X Exchange the current position with the mark\nEditing \nBackspace, ^H Delete the previous character, or the whole region when it's active\nDelete, ^D Forward delete one character (when buffer has text)\nmeta-Backspace Delete the previous word\nmeta-d Forward delete the next word\n^W Delete previous text up to the nearest whitespace\nmeta-w Copy the current region in the kill ring\nmeta-W \"Kill\" the current region, placing the text in the kill ring\n^K \"Kill\" to end of line, placing the text in the kill ring\n^Y \"Yank\" insert the text from the kill ring\nmeta-y Replace a previously yanked text with an older entry from the kill ring\n^T Transpose the characters about the cursor\nmeta-Up arrow Transpose current line with line above\nmeta-Down arrow Transpose current line with line below\nmeta-u Change the next word to uppercase\nmeta-c Change the next word to titlecase\nmeta-l Change the next word to lowercase\n^/, ^_ Undo previous editing action\n^Q Write a number in REPL and press ^Q to open editor at corresponding stackframe or method\nmeta-Left Arrow indent the current line on the left\nmeta-Right Arrow indent the current line on the right\nmeta-. insert last word from previous history entry","category":"page"},{"location":"stdlib/REPL/#Customizing-keybindings","page":"Julia REPL","title":"Customizing keybindings","text":"","category":"section"},{"location":"stdlib/REPL/","page":"Julia REPL","title":"Julia REPL","text":"Julia's REPL keybindings may be fully customized to a user's preferences by passing a dictionary to REPL.setup_interface. The keys of this dictionary may be characters or strings. The key '*' refers to the default action. Control plus character x bindings are indicated with \"^x\". Meta plus x can be written \"\\\\M-x\" or \"\\ex\", and Control plus x can be written \"\\\\C-x\" or \"^x\". The values of the custom keymap must be nothing (indicating that the input should be ignored) or functions that accept the signature (PromptState, AbstractREPL, Char). The REPL.setup_interface function must be called before the REPL is initialized, by registering the operation with atreplinit . For example, to bind the up and down arrow keys to move through history without prefix search, one could put the following code in ~/.julia/config/startup.jl:","category":"page"},{"location":"stdlib/REPL/","page":"Julia REPL","title":"Julia REPL","text":"import REPL\nimport REPL.LineEdit\n\nconst mykeys = Dict{Any,Any}(\n # Up Arrow\n \"\\e[A\" => (s,o...)->(LineEdit.edit_move_up(s) || LineEdit.history_prev(s, LineEdit.mode(s).hist)),\n # Down Arrow\n \"\\e[B\" => (s,o...)->(LineEdit.edit_move_down(s) || LineEdit.history_next(s, LineEdit.mode(s).hist))\n)\n\nfunction customize_keys(repl)\n repl.interface = REPL.setup_interface(repl; extra_repl_keymap = mykeys)\nend\n\natreplinit(customize_keys)","category":"page"},{"location":"stdlib/REPL/","page":"Julia REPL","title":"Julia REPL","text":"Users should refer to LineEdit.jl to discover the available actions on key input.","category":"page"},{"location":"stdlib/REPL/#Tab-completion","page":"Julia REPL","title":"Tab completion","text":"","category":"section"},{"location":"stdlib/REPL/","page":"Julia REPL","title":"Julia REPL","text":"In both the Julian and help modes of the REPL, one can enter the first few characters of a function or type and then press the tab key to get a list all matches:","category":"page"},{"location":"stdlib/REPL/","page":"Julia REPL","title":"Julia REPL","text":"julia> stri[TAB]\nstride strides string strip\n\njulia> Stri[TAB]\nStridedArray StridedMatrix StridedVecOrMat StridedVector String","category":"page"},{"location":"stdlib/REPL/","page":"Julia REPL","title":"Julia REPL","text":"The tab key can also be used to substitute LaTeX math symbols with their Unicode equivalents, and get a list of LaTeX matches as well:","category":"page"},{"location":"stdlib/REPL/","page":"Julia REPL","title":"Julia REPL","text":"julia> \\pi[TAB]\njulia> π\nπ = 3.1415926535897...\n\njulia> e\\_1[TAB] = [1,0]\njulia> e₁ = [1,0]\n2-element Array{Int64,1}:\n 1\n 0\n\njulia> e\\^1[TAB] = [1 0]\njulia> e¹ = [1 0]\n1×2 Array{Int64,2}:\n 1 0\n\njulia> \\sqrt[TAB]2 # √ is equivalent to the sqrt function\njulia> √2\n1.4142135623730951\n\njulia> \\hbar[TAB](h) = h / 2\\pi[TAB]\njulia> ħ(h) = h / 2π\nħ (generic function with 1 method)\n\njulia> \\h[TAB]\n\\hat \\hermitconjmatrix \\hkswarow \\hrectangle\n\\hatapprox \\hexagon \\hookleftarrow \\hrectangleblack\n\\hbar \\hexagonblack \\hookrightarrow \\hslash\n\\heartsuit \\hksearow \\house \\hspace\n\njulia> α=\"\\alpha[TAB]\" # LaTeX completion also works in strings\njulia> α=\"α\"","category":"page"},{"location":"stdlib/REPL/","page":"Julia REPL","title":"Julia REPL","text":"A full list of tab-completions can be found in the Unicode Input section of the manual.","category":"page"},{"location":"stdlib/REPL/","page":"Julia REPL","title":"Julia REPL","text":"Completion of paths works for strings and julia's shell mode:","category":"page"},{"location":"stdlib/REPL/","page":"Julia REPL","title":"Julia REPL","text":"julia> path=\"/[TAB]\"\n.dockerenv .juliabox/ boot/ etc/ lib/ media/ opt/ root/ sbin/ sys/ usr/\n.dockerinit bin/ dev/ home/ lib64/ mnt/ proc/ run/ srv/ tmp/ var/\nshell> /[TAB]\n.dockerenv .juliabox/ boot/ etc/ lib/ media/ opt/ root/ sbin/ sys/ usr/\n.dockerinit bin/ dev/ home/ lib64/ mnt/ proc/ run/ srv/ tmp/ var/","category":"page"},{"location":"stdlib/REPL/","page":"Julia REPL","title":"Julia REPL","text":"Tab completion can help with investigation of the available methods matching the input arguments:","category":"page"},{"location":"stdlib/REPL/","page":"Julia REPL","title":"Julia REPL","text":"julia> max([TAB] # All methods are displayed, not shown here due to size of the list\n\njulia> max([1, 2], [TAB] # All methods where `Vector{Int}` matches as first argument\nmax(x, y) in Base at operators.jl:215\nmax(a, b, c, xs...) in Base at operators.jl:281\n\njulia> max([1, 2], max(1, 2), [TAB] # All methods matching the arguments.\nmax(x, y) in Base at operators.jl:215\nmax(a, b, c, xs...) in Base at operators.jl:281","category":"page"},{"location":"stdlib/REPL/","page":"Julia REPL","title":"Julia REPL","text":"Keywords are also displayed in the suggested methods after ;, see below line where limit and keepempty are keyword arguments:","category":"page"},{"location":"stdlib/REPL/","page":"Julia REPL","title":"Julia REPL","text":"julia> split(\"1 1 1\", [TAB]\nsplit(str::AbstractString; limit, keepempty) in Base at strings/util.jl:302\nsplit(str::T, splitter; limit, keepempty) where T<:AbstractString in Base at strings/util.jl:277","category":"page"},{"location":"stdlib/REPL/","page":"Julia REPL","title":"Julia REPL","text":"The completion of the methods uses type inference and can therefore see if the arguments match even if the arguments are output from functions. The function needs to be type stable for the completion to be able to remove non-matching methods.","category":"page"},{"location":"stdlib/REPL/","page":"Julia REPL","title":"Julia REPL","text":"Tab completion can also help completing fields:","category":"page"},{"location":"stdlib/REPL/","page":"Julia REPL","title":"Julia REPL","text":"julia> import UUIDs\n\njulia> UUIDs.uuid[TAB]\nuuid1 uuid4 uuid_version","category":"page"},{"location":"stdlib/REPL/","page":"Julia REPL","title":"Julia REPL","text":"Fields for output from functions can also be completed:","category":"page"},{"location":"stdlib/REPL/","page":"Julia REPL","title":"Julia REPL","text":"julia> split(\"\",\"\")[1].[TAB]\nlastindex offset string","category":"page"},{"location":"stdlib/REPL/","page":"Julia REPL","title":"Julia REPL","text":"The completion of fields for output from functions uses type inference, and it can only suggest fields if the function is type stable.","category":"page"},{"location":"stdlib/REPL/","page":"Julia REPL","title":"Julia REPL","text":"Dictionary keys can also be tab completed:","category":"page"},{"location":"stdlib/REPL/","page":"Julia REPL","title":"Julia REPL","text":"julia> foo = Dict(\"qwer1\"=>1, \"qwer2\"=>2, \"asdf\"=>3)\nDict{String,Int64} with 3 entries:\n \"qwer2\" => 2\n \"asdf\" => 3\n \"qwer1\" => 1\n\njulia> foo[\"q[TAB]\n\n\"qwer1\" \"qwer2\"\njulia> foo[\"qwer","category":"page"},{"location":"stdlib/REPL/#Customizing-Colors","page":"Julia REPL","title":"Customizing Colors","text":"","category":"section"},{"location":"stdlib/REPL/","page":"Julia REPL","title":"Julia REPL","text":"The colors used by Julia and the REPL can be customized, as well. To change the color of the Julia prompt you can add something like the following to your ~/.julia/config/startup.jl file, which is to be placed inside your home directory:","category":"page"},{"location":"stdlib/REPL/","page":"Julia REPL","title":"Julia REPL","text":"function customize_colors(repl)\n repl.prompt_color = Base.text_colors[:cyan]\nend\n\natreplinit(customize_colors)","category":"page"},{"location":"stdlib/REPL/","page":"Julia REPL","title":"Julia REPL","text":"The available color keys can be seen by typing Base.text_colors in the help mode of the REPL. In addition, the integers 0 to 255 can be used as color keys for terminals with 256 color support.","category":"page"},{"location":"stdlib/REPL/","page":"Julia REPL","title":"Julia REPL","text":"You can also change the colors for the help and shell prompts and input and answer text by setting the appropriate field of repl in the customize_colors function above (respectively, help_color, shell_color, input_color, and answer_color). For the latter two, be sure that the envcolors field is also set to false.","category":"page"},{"location":"stdlib/REPL/","page":"Julia REPL","title":"Julia REPL","text":"It is also possible to apply boldface formatting by using Base.text_colors[:bold] as a color. For instance, to print answers in boldface font, one can use the following as a ~/.julia/config/startup.jl:","category":"page"},{"location":"stdlib/REPL/","page":"Julia REPL","title":"Julia REPL","text":"function customize_colors(repl)\n repl.envcolors = false\n repl.answer_color = Base.text_colors[:bold]\nend\n\natreplinit(customize_colors)","category":"page"},{"location":"stdlib/REPL/","page":"Julia REPL","title":"Julia REPL","text":"You can also customize the color used to render warning and informational messages by setting the appropriate environment variables. For instance, to render error, warning, and informational messages respectively in magenta, yellow, and cyan you can add the following to your ~/.julia/config/startup.jl file:","category":"page"},{"location":"stdlib/REPL/","page":"Julia REPL","title":"Julia REPL","text":"ENV[\"JULIA_ERROR_COLOR\"] = :magenta\nENV[\"JULIA_WARN_COLOR\"] = :yellow\nENV[\"JULIA_INFO_COLOR\"] = :cyan","category":"page"},{"location":"stdlib/REPL/#TerminalMenus","page":"Julia REPL","title":"TerminalMenus","text":"","category":"section"},{"location":"stdlib/REPL/","page":"Julia REPL","title":"Julia REPL","text":"TerminalMenus is a submodule of the Julia REPL and enables small, low-profile interactive menus in the terminal.","category":"page"},{"location":"stdlib/REPL/#Examples","page":"Julia REPL","title":"Examples","text":"","category":"section"},{"location":"stdlib/REPL/","page":"Julia REPL","title":"Julia REPL","text":"import REPL\nusing REPL.TerminalMenus\n\noptions = [\"apple\", \"orange\", \"grape\", \"strawberry\",\n \"blueberry\", \"peach\", \"lemon\", \"lime\"]\n","category":"page"},{"location":"stdlib/REPL/#RadioMenu","page":"Julia REPL","title":"RadioMenu","text":"","category":"section"},{"location":"stdlib/REPL/","page":"Julia REPL","title":"Julia REPL","text":"The RadioMenu allows the user to select one option from the list. The request function displays the interactive menu and returns the index of the selected choice. If a user presses 'q' or ctrl-c, request will return a -1.","category":"page"},{"location":"stdlib/REPL/","page":"Julia REPL","title":"Julia REPL","text":"# `pagesize` is the number of items to be displayed at a time.\n# The UI will scroll if the number of options is greater\n# than the `pagesize`\nmenu = RadioMenu(options, pagesize=4)\n\n# `request` displays the menu and returns the index after the\n# user has selected a choice\nchoice = request(\"Choose your favorite fruit:\", menu)\n\nif choice != -1\n println(\"Your favorite fruit is \", options[choice], \"!\")\nelse\n println(\"Menu canceled.\")\nend\n","category":"page"},{"location":"stdlib/REPL/","page":"Julia REPL","title":"Julia REPL","text":"Output:","category":"page"},{"location":"stdlib/REPL/","page":"Julia REPL","title":"Julia REPL","text":"Choose your favorite fruit:\n^ grape\n strawberry\n > blueberry\nv peach\nYour favorite fruit is blueberry!","category":"page"},{"location":"stdlib/REPL/#MultiSelectMenu","page":"Julia REPL","title":"MultiSelectMenu","text":"","category":"section"},{"location":"stdlib/REPL/","page":"Julia REPL","title":"Julia REPL","text":"The MultiSelectMenu allows users to select many choices from a list.","category":"page"},{"location":"stdlib/REPL/","page":"Julia REPL","title":"Julia REPL","text":"# here we use the default `pagesize` 10\nmenu = MultiSelectMenu(options)\n\n# `request` returns a `Set` of selected indices\n# if the menu us canceled (ctrl-c or q), return an empty set\nchoices = request(\"Select the fruits you like:\", menu)\n\nif length(choices) > 0\n println(\"You like the following fruits:\")\n for i in choices\n println(\" - \", options[i])\n end\nelse\n println(\"Menu canceled.\")\nend","category":"page"},{"location":"stdlib/REPL/","page":"Julia REPL","title":"Julia REPL","text":"Output:","category":"page"},{"location":"stdlib/REPL/","page":"Julia REPL","title":"Julia REPL","text":"Select the fruits you like:\n[press: d=done, a=all, n=none]\n [ ] apple\n > [X] orange\n [X] grape\n [ ] strawberry\n [ ] blueberry\n [X] peach\n [ ] lemon\n [ ] lime\nYou like the following fruits:\n - orange\n - grape\n - peach","category":"page"},{"location":"stdlib/REPL/#Customization-/-Configuration","page":"Julia REPL","title":"Customization / Configuration","text":"","category":"section"},{"location":"stdlib/REPL/#ConfiguredMenu-subtypes","page":"Julia REPL","title":"ConfiguredMenu subtypes","text":"","category":"section"},{"location":"stdlib/REPL/","page":"Julia REPL","title":"Julia REPL","text":"Starting with Julia 1.6, the recommended way to configure menus is via the constructor. For instance, the default multiple-selection menu","category":"page"},{"location":"stdlib/REPL/","page":"Julia REPL","title":"Julia REPL","text":"julia> menu = MultiSelectMenu(options, pagesize=5);\n\njulia> request(menu) # ASCII is used by default\n[press: d=done, a=all, n=none]\n [ ] apple\n [X] orange\n [ ] grape\n > [X] strawberry\nv [ ] blueberry","category":"page"},{"location":"stdlib/REPL/","page":"Julia REPL","title":"Julia REPL","text":"can instead be rendered with Unicode selection and navigation characters with","category":"page"},{"location":"stdlib/REPL/","page":"Julia REPL","title":"Julia REPL","text":"julia> menu = MultiSelectMenu(options, pagesize=5, charset=:unicode);\n\njulia> request(menu)\n[press: d=done, a=all, n=none]\n ⬚ apple\n ✓ orange\n ⬚ grape\n → ✓ strawberry\n↓ ⬚ blueberry","category":"page"},{"location":"stdlib/REPL/","page":"Julia REPL","title":"Julia REPL","text":"More fine-grained configuration is also possible:","category":"page"},{"location":"stdlib/REPL/","page":"Julia REPL","title":"Julia REPL","text":"julia> menu = MultiSelectMenu(options, pagesize=5, charset=:unicode, checked=\"YEP!\", unchecked=\"NOPE\", cursor='⧐');\n\njulia> request(menu)\njulia> request(menu)\n[press: d=done, a=all, n=none]\n NOPE apple\n YEP! orange\n NOPE grape\n ⧐ YEP! strawberry\n↓ NOPE blueberry","category":"page"},{"location":"stdlib/REPL/","page":"Julia REPL","title":"Julia REPL","text":"Aside from the overall charset option, for RadioMenu the configurable options are:","category":"page"},{"location":"stdlib/REPL/","page":"Julia REPL","title":"Julia REPL","text":"cursor::Char='>'|'→': character to use for cursor\nup_arrow::Char='^'|'↑': character to use for up arrow\ndown_arrow::Char='v'|'↓': character to use for down arrow\nupdown_arrow::Char='I'|'↕': character to use for up/down arrow in one-line page\nscroll_wrap::Bool=false: optionally wrap-around at the beginning/end of a menu\nctrl_c_interrupt::Bool=true: If false, return empty on ^C, if true throw InterruptException() on ^C","category":"page"},{"location":"stdlib/REPL/","page":"Julia REPL","title":"Julia REPL","text":"MultiSelectMenu adds:","category":"page"},{"location":"stdlib/REPL/","page":"Julia REPL","title":"Julia REPL","text":"checked::String=\"[X]\"|\"✓\": string to use for checked\nunchecked::String=\"[ ]\"|\"⬚\"): string to use for unchecked","category":"page"},{"location":"stdlib/REPL/","page":"Julia REPL","title":"Julia REPL","text":"You can create new menu types of your own. Types that are derived from TerminalMenus.ConfiguredMenu configure the menu options at construction time.","category":"page"},{"location":"stdlib/REPL/#Legacy-interface","page":"Julia REPL","title":"Legacy interface","text":"","category":"section"},{"location":"stdlib/REPL/","page":"Julia REPL","title":"Julia REPL","text":"Prior to Julia 1.6, and still supported throughout Julia 1.x, one can also configure menus by calling TerminalMenus.config().","category":"page"},{"location":"stdlib/REPL/#References","page":"Julia REPL","title":"References","text":"","category":"section"},{"location":"stdlib/REPL/#REPL","page":"Julia REPL","title":"REPL","text":"","category":"section"},{"location":"stdlib/REPL/","page":"Julia REPL","title":"Julia REPL","text":"Base.atreplinit","category":"page"},{"location":"stdlib/REPL/#Base.atreplinit","page":"Julia REPL","title":"Base.atreplinit","text":"atreplinit(f)\n\nRegister a one-argument function to be called before the REPL interface is initialized in interactive sessions; this is useful to customize the interface. The argument of f is the REPL object. This function should be called from within the .julia/config/startup.jl initialization file.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/REPL/#TerminalMenus-2","page":"Julia REPL","title":"TerminalMenus","text":"","category":"section"},{"location":"stdlib/REPL/#Configuration","page":"Julia REPL","title":"Configuration","text":"","category":"section"},{"location":"stdlib/REPL/","page":"Julia REPL","title":"Julia REPL","text":"REPL.TerminalMenus.Config\nREPL.TerminalMenus.MultiSelectConfig\nREPL.TerminalMenus.config","category":"page"},{"location":"stdlib/REPL/#REPL.TerminalMenus.Config","page":"Julia REPL","title":"REPL.TerminalMenus.Config","text":"Config(; scroll_wrap=false, ctrl_c_interrupt=true, charset=:ascii, cursor::Char, up_arrow::Char, down_arrow::Char)\n\nConfigure behavior for selection menus via keyword arguments:\n\nscroll_wrap, if true, causes the menu to wrap around when scrolling above the first or below the last entry\nctrl_c_interrupt, if true, throws an InterruptException if the user hits Ctrl-C during menu selection. If false, TerminalMenus.request will return the default result from TerminalMenus.selected.\ncharset affects the default values for cursor, up_arrow, and down_arrow, and can be :ascii or :unicode\ncursor is the character printed to indicate the option that will be chosen by hitting \"Enter.\" Defaults are '>' or '→', depending on charset.\nup_arrow is the character printed when the display does not include the first entry. Defaults are '^' or '↑', depending on charset.\ndown_arrow is the character printed when the display does not include the last entry. Defaults are 'v' or '↓', depending on charset.\n\nSubtypes of ConfiguredMenu will print cursor, up_arrow, and down_arrow automatically as needed, your writeline method should not print them.\n\ncompat: Julia 1.6\nConfig is available as of Julia 1.6. On older releases use the global CONFIG.\n\n\n\n\n\n","category":"type"},{"location":"stdlib/REPL/#REPL.TerminalMenus.MultiSelectConfig","page":"Julia REPL","title":"REPL.TerminalMenus.MultiSelectConfig","text":"MultiSelectConfig(; charset=:ascii, checked::String, unchecked::String, kwargs...)\n\nConfigure behavior for a multiple-selection menu via keyword arguments:\n\nchecked is the string to print when an option has been selected. Defaults are \"[X]\" or \"✓\", depending on charset.\nunchecked is the string to print when an option has not been selected. Defaults are \"[ ]\" or \"⬚\", depending on charset.\n\nAll other keyword arguments are as described for TerminalMenus.Config. checked and unchecked are not printed automatically, and should be printed by your writeline method.\n\ncompat: Julia 1.6\nMultiSelectConfig is available as of Julia 1.6. On older releases use the global CONFIG.\n\n\n\n\n\n","category":"type"},{"location":"stdlib/REPL/#REPL.TerminalMenus.config","page":"Julia REPL","title":"REPL.TerminalMenus.config","text":"config( )\n\nKeyword-only function to configure global menu parameters\n\nArguments\n\ncharset::Symbol=:na: ui characters to use (:ascii or :unicode); overridden by other arguments\ncursor::Char='>'|'→': character to use for cursor\nup_arrow::Char='^'|'↑': character to use for up arrow\ndown_arrow::Char='v'|'↓': character to use for down arrow\nchecked::String=\"[X]\"|\"✓\": string to use for checked\nunchecked::String=\"[ ]\"|\"⬚\"): string to use for unchecked\nscroll::Symbol=:nowrap: If :wrap wrap cursor around top and bottom, if :nowrap do not wrap cursor\nsupress_output::Bool=false: Ignored legacy argument, pass suppress_output as a keyword argument to request instead.\nctrl_c_interrupt::Bool=true: If false, return empty on ^C, if true throw InterruptException() on ^C\n\ncompat: Julia 1.6\nAs of Julia 1.6, config is deprecated. Use Config or MultiSelectConfig instead.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/REPL/#User-interaction","page":"Julia REPL","title":"User interaction","text":"","category":"section"},{"location":"stdlib/REPL/","page":"Julia REPL","title":"Julia REPL","text":"REPL.TerminalMenus.request","category":"page"},{"location":"stdlib/REPL/#REPL.TerminalMenus.request","page":"Julia REPL","title":"REPL.TerminalMenus.request","text":"request(m::AbstractMenu; cursor=1)\n\nDisplay the menu and enter interactive mode. cursor indicates the item number used for the initial cursor position. cursor can be either an Int or a RefValue{Int}. The latter is useful for observation and control of the cursor position from the outside.\n\nReturns selected(m).\n\ncompat: Julia 1.6\nThe cursor argument requires Julia 1.6 or later.\n\n\n\n\n\nrequest([term,] msg::AbstractString, m::AbstractMenu)\n\nShorthand for println(msg); request(m).\n\n\n\n\n\n","category":"function"},{"location":"stdlib/REPL/#AbstractMenu-extension-interface","page":"Julia REPL","title":"AbstractMenu extension interface","text":"","category":"section"},{"location":"stdlib/REPL/","page":"Julia REPL","title":"Julia REPL","text":"Any subtype of AbstractMenu must be mutable, and must contain the fields pagesize::Int and pageoffset::Int. Any subtype must also implement the following functions:","category":"page"},{"location":"stdlib/REPL/","page":"Julia REPL","title":"Julia REPL","text":"REPL.TerminalMenus.pick\nREPL.TerminalMenus.cancel\nREPL.TerminalMenus.writeline","category":"page"},{"location":"stdlib/REPL/#REPL.TerminalMenus.pick","page":"Julia REPL","title":"REPL.TerminalMenus.pick","text":"pick(m::AbstractMenu, cursor::Int)\n\nDefines what happens when a user presses the Enter key while the menu is open. If true is returned, request() will exit. cursor indexes the position of the selection.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/REPL/#REPL.TerminalMenus.cancel","page":"Julia REPL","title":"REPL.TerminalMenus.cancel","text":"cancel(m::AbstractMenu)\n\nDefine what happens when a user cancels ('q' or ctrl-c) a menu. request() will always exit after calling this function.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/REPL/#REPL.TerminalMenus.writeline","page":"Julia REPL","title":"REPL.TerminalMenus.writeline","text":"writeline(buf::IO, m::AbstractMenu, idx::Int, iscursor::Bool)\n\nWrite the option at index idx to buf. iscursor, if true, indicates that this item is at the current cursor position (the one that will be selected by hitting \"Enter\").\n\nIf m is a ConfiguredMenu, TerminalMenus will print the cursor indicator. Otherwise the callee is expected to handle such printing.\n\ncompat: Julia 1.6\nwriteline requires Julia 1.6 or higher.On older versions of Julia, this was writeLine(buf::IO, m::AbstractMenu, idx, iscursor::Bool) and m is assumed to be unconfigured. The selection and cursor indicators can be obtained from TerminalMenus.CONFIG.This older function is supported on all Julia 1.x versions but will be dropped in Julia 2.0.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/REPL/","page":"Julia REPL","title":"Julia REPL","text":"It must also implement either options or numoptions:","category":"page"},{"location":"stdlib/REPL/","page":"Julia REPL","title":"Julia REPL","text":"REPL.TerminalMenus.options\nREPL.TerminalMenus.numoptions","category":"page"},{"location":"stdlib/REPL/#REPL.TerminalMenus.options","page":"Julia REPL","title":"REPL.TerminalMenus.options","text":"options(m::AbstractMenu)\n\nReturn a list of strings to be displayed as options in the current page.\n\nAlternatively, implement numoptions, in which case options is not needed.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/REPL/#REPL.TerminalMenus.numoptions","page":"Julia REPL","title":"REPL.TerminalMenus.numoptions","text":"numoptions(m::AbstractMenu) -> Int\n\nReturn the number of options in menu m. Defaults to length(options(m)).\n\ncompat: Julia 1.6\nThis function requires Julia 1.6 or later.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/REPL/","page":"Julia REPL","title":"Julia REPL","text":"If the subtype does not have a field named selected, it must also implement","category":"page"},{"location":"stdlib/REPL/","page":"Julia REPL","title":"Julia REPL","text":"REPL.TerminalMenus.selected","category":"page"},{"location":"stdlib/REPL/#REPL.TerminalMenus.selected","page":"Julia REPL","title":"REPL.TerminalMenus.selected","text":"selected(m::AbstractMenu)\n\nReturn information about the user-selected option. By default it returns m.selected.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/REPL/","page":"Julia REPL","title":"Julia REPL","text":"The following are optional but can allow additional customization:","category":"page"},{"location":"stdlib/REPL/","page":"Julia REPL","title":"Julia REPL","text":"REPL.TerminalMenus.header\nREPL.TerminalMenus.keypress","category":"page"},{"location":"stdlib/REPL/#REPL.TerminalMenus.header","page":"Julia REPL","title":"REPL.TerminalMenus.header","text":"header(m::AbstractMenu) -> String\n\nReturns a header string to be printed above the menu. Defaults to \"\".\n\n\n\n\n\n","category":"function"},{"location":"stdlib/REPL/#REPL.TerminalMenus.keypress","page":"Julia REPL","title":"REPL.TerminalMenus.keypress","text":"keypress(m::AbstractMenu, i::UInt32) -> Bool\n\nHandle any non-standard keypress event. If true is returned, TerminalMenus.request will exit. Defaults to false.\n\n\n\n\n\n","category":"function"},{"location":"base/stacktraces/#堆栈跟踪","page":"堆栈跟踪","title":"堆栈跟踪","text":"","category":"section"},{"location":"base/stacktraces/","page":"堆栈跟踪","title":"堆栈跟踪","text":"Base.StackTraces.StackFrame\nBase.StackTraces.StackTrace\nBase.StackTraces.stacktrace","category":"page"},{"location":"base/stacktraces/#Base.StackTraces.StackFrame","page":"堆栈跟踪","title":"Base.StackTraces.StackFrame","text":"StackFrame\n\nStack information representing execution context, with the following fields:\n\nfunc::Symbol\nThe name of the function containing the execution context.\nlinfo::Union{Core.MethodInstance, CodeInfo, Nothing}\nThe MethodInstance containing the execution context (if it could be found).\nfile::Symbol\nThe path to the file containing the execution context.\nline::Int\nThe line number in the file containing the execution context.\nfrom_c::Bool\nTrue if the code is from C.\ninlined::Bool\nTrue if the code is from an inlined frame.\npointer::UInt64\nRepresentation of the pointer to the execution context as returned by backtrace.\n\n\n\n\n\n","category":"type"},{"location":"base/stacktraces/#Base.StackTraces.StackTrace","page":"堆栈跟踪","title":"Base.StackTraces.StackTrace","text":"StackTrace\n\nAn alias for Vector{StackFrame} provided for convenience; returned by calls to stacktrace.\n\n\n\n\n\n","category":"type"},{"location":"base/stacktraces/#Base.StackTraces.stacktrace","page":"堆栈跟踪","title":"Base.StackTraces.stacktrace","text":"stacktrace([trace::Vector{Ptr{Cvoid}},] [c_funcs::Bool=false]) -> StackTrace\n\nReturns a stack trace in the form of a vector of StackFrames. (By default stacktrace doesn't return C functions, but this can be enabled.) When called without specifying a trace, stacktrace first calls backtrace.\n\n\n\n\n\n","category":"function"},{"location":"base/stacktraces/","page":"堆栈跟踪","title":"堆栈跟踪","text":"Base.StackTraces 中以下方法和类型不会被导出,需要显式调用,例如 StackTraces.lookup(ptr)。","category":"page"},{"location":"base/stacktraces/","page":"堆栈跟踪","title":"堆栈跟踪","text":"Base.StackTraces.lookup\nBase.StackTraces.remove_frames!","category":"page"},{"location":"base/stacktraces/#Base.StackTraces.lookup","page":"堆栈跟踪","title":"Base.StackTraces.lookup","text":"lookup(pointer::Ptr{Cvoid}) -> Vector{StackFrame}\n\nGiven a pointer to an execution context (usually generated by a call to backtrace), looks up stack frame context information. Returns an array of frame information for all functions inlined at that point, innermost function first.\n\n\n\n\n\n","category":"function"},{"location":"base/stacktraces/#Base.StackTraces.remove_frames!","page":"堆栈跟踪","title":"Base.StackTraces.remove_frames!","text":"remove_frames!(stack::StackTrace, name::Symbol)\n\nTakes a StackTrace (a vector of StackFrames) and a function name (a Symbol) and removes the StackFrame specified by the function name from the StackTrace (also removing all frames above the specified function). Primarily used to remove StackTraces functions from the StackTrace prior to returning it.\n\n\n\n\n\nremove_frames!(stack::StackTrace, m::Module)\n\nReturns the StackTrace with all StackFrames from the provided Module removed.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/SparseArrays/#稀疏数组","page":"稀疏数组","title":"稀疏数组","text":"","category":"section"},{"location":"stdlib/SparseArrays/","page":"稀疏数组","title":"稀疏数组","text":"DocTestSetup = :(using SparseArrays, LinearAlgebra)","category":"page"},{"location":"stdlib/SparseArrays/","page":"稀疏数组","title":"稀疏数组","text":"Julia 在 SparseArrays 标准库模块中提供了对稀疏向量和稀疏矩阵的支持。与稠密数组相比,包含足够多零值的稀疏数组在以特殊的数据结构存储时可以节省大量的空间和运算时间。","category":"page"},{"location":"stdlib/SparseArrays/#man-csc","page":"稀疏数组","title":"压缩稀疏列(CSC)稀疏矩阵存储","text":"","category":"section"},{"location":"stdlib/SparseArrays/","page":"稀疏数组","title":"稀疏数组","text":"在 Julia 中,稀疏矩阵是按照压缩稀疏列(CSC)格式存储的。Julia 稀疏矩阵具有 SparseMatrixCSC{Tv,Ti} 类型,其中 Tv 是存储值的类型,Ti 是存储列指针和行索引的整型类型。SparseMatrixCSC 的内部表示如下所示:","category":"page"},{"location":"stdlib/SparseArrays/","page":"稀疏数组","title":"稀疏数组","text":"struct SparseMatrixCSC{Tv,Ti<:Integer} <: AbstractSparseMatrixCSC{Tv,Ti}\n m::Int # Number of rows\n n::Int # Number of columns\n colptr::Vector{Ti} # Column j is in colptr[j]:(colptr[j+1]-1)\n rowval::Vector{Ti} # Row indices of stored values\n nzval::Vector{Tv} # Stored values, typically nonzeros\nend","category":"page"},{"location":"stdlib/SparseArrays/","page":"稀疏数组","title":"稀疏数组","text":"压缩稀疏列存储格式使得访问稀疏矩阵的列元素非常简单快速,而访问稀疏矩阵的行会非常缓慢。在 CSC 稀疏矩阵中执行类似插入新元素的操作也会非常慢。这是由于在稀疏矩阵中插入新元素时,在插入点之后的所有元素都要向后移动一位。","category":"page"},{"location":"stdlib/SparseArrays/","page":"稀疏数组","title":"稀疏数组","text":"All operations on sparse matrices are carefully implemented to exploit the CSC data structure for performance, and to avoid expensive operations.","category":"page"},{"location":"stdlib/SparseArrays/","page":"稀疏数组","title":"稀疏数组","text":"如果你有来自不同应用或库的 CSC 格式数据,并且想要将它导入 Julia,确保使用基于 1 的索引。每个列中的行索引都要是有序的。如果你的 SparseMatrixCSC 对象包含无序的行索引,一个快速将它们排序的方法是做一次二重转置。","category":"page"},{"location":"stdlib/SparseArrays/","page":"稀疏数组","title":"稀疏数组","text":"In some applications, it is convenient to store explicit zero values in a SparseMatrixCSC. These are accepted by functions in Base (but there is no guarantee that they will be preserved in mutating operations). Such explicitly stored zeros are treated as structural nonzeros by many routines. The nnz function returns the number of elements explicitly stored in the sparse data structure, including non-structural zeros. In order to count the exact number of numerical nonzeros, use count(!iszero, x), which inspects every stored element of a sparse matrix. dropzeros, and the in-place dropzeros!, can be used to remove stored zeros from the sparse matrix.","category":"page"},{"location":"stdlib/SparseArrays/","page":"稀疏数组","title":"稀疏数组","text":"julia> A = sparse([1, 1, 2, 3], [1, 3, 2, 3], [0, 1, 2, 0])\n3×3 SparseMatrixCSC{Int64, Int64} with 4 stored entries:\n 0 ⋅ 1\n ⋅ 2 ⋅\n ⋅ ⋅ 0\n\njulia> dropzeros(A)\n3×3 SparseMatrixCSC{Int64, Int64} with 2 stored entries:\n ⋅ ⋅ 1\n ⋅ 2 ⋅\n ⋅ ⋅ ⋅","category":"page"},{"location":"stdlib/SparseArrays/#稀疏向量储存","page":"稀疏数组","title":"稀疏向量储存","text":"","category":"section"},{"location":"stdlib/SparseArrays/","page":"稀疏数组","title":"稀疏数组","text":"Sparse vectors are stored in a close analog to compressed sparse column format for sparse matrices. In Julia, sparse vectors have the type SparseVector{Tv,Ti} where Tv is the type of the stored values and Ti the integer type for the indices. The internal representation is as follows:","category":"page"},{"location":"stdlib/SparseArrays/","page":"稀疏数组","title":"稀疏数组","text":"struct SparseVector{Tv,Ti<:Integer} <: AbstractSparseVector{Tv,Ti}\n n::Int # Length of the sparse vector\n nzind::Vector{Ti} # Indices of stored values\n nzval::Vector{Tv} # Stored values, typically nonzeros\nend","category":"page"},{"location":"stdlib/SparseArrays/","page":"稀疏数组","title":"稀疏数组","text":"对于 SparseMatrixCSC, SparseVector 类型也能包含显示存储的,零值。(见 稀疏矩阵存储。)","category":"page"},{"location":"stdlib/SparseArrays/#稀疏向量与矩阵构造函数","page":"稀疏数组","title":"稀疏向量与矩阵构造函数","text":"","category":"section"},{"location":"stdlib/SparseArrays/","page":"稀疏数组","title":"稀疏数组","text":"创建一个稀疏矩阵的最简单的方法是使用一个与 Julia 提供的用来处理稠密矩阵的zeros 等价的函数。要产生一个稀疏矩阵,你可以用同样的名字加上 sp 前缀:","category":"page"},{"location":"stdlib/SparseArrays/","page":"稀疏数组","title":"稀疏数组","text":"julia> spzeros(3)\n3-element SparseVector{Float64, Int64} with 0 stored entries","category":"page"},{"location":"stdlib/SparseArrays/","page":"稀疏数组","title":"稀疏数组","text":"sparse 函数通常是一个构建稀疏矩阵的便捷方法。例如,要构建一个稀疏矩阵,我们可以输入一个列索引向量 I,一个行索引向量 J,一个储存值的向量 V(这也叫作 COO(坐标) 格式)。 然后 sparse(I,J,V) 创建一个满足 S[I[k], J[k]] = V[k] 的稀疏矩阵。等价的稀疏向量构建函数是 sparsevec,它接受(行)索引向量 I 和储存值的向量 V 并创建一个满足 R[I[k]] = V[k] 的向量 R。","category":"page"},{"location":"stdlib/SparseArrays/","page":"稀疏数组","title":"稀疏数组","text":"julia> I = [1, 4, 3, 5]; J = [4, 7, 18, 9]; V = [1, 2, -5, 3];\n\njulia> S = sparse(I,J,V)\n5×18 SparseMatrixCSC{Int64, Int64} with 4 stored entries:\n⠀⠈⠀⡀⠀⠀⠀⠀⠠\n⠀⠀⠀⠀⠁⠀⠀⠀⠀\n\njulia> R = sparsevec(I,V)\n5-element SparseVector{Int64, Int64} with 4 stored entries:\n [1] = 1\n [3] = -5\n [4] = 2\n [5] = 3","category":"page"},{"location":"stdlib/SparseArrays/","page":"稀疏数组","title":"稀疏数组","text":"The inverse of the sparse and sparsevec functions is findnz, which retrieves the inputs used to create the sparse array. findall(!iszero, x) returns the cartesian indices of non-zero entries in x (including stored entries equal to zero).","category":"page"},{"location":"stdlib/SparseArrays/","page":"稀疏数组","title":"稀疏数组","text":"julia> findnz(S)\n([1, 4, 5, 3], [4, 7, 9, 18], [1, 2, 3, -5])\n\njulia> findall(!iszero, S)\n4-element Vector{CartesianIndex{2}}:\n CartesianIndex(1, 4)\n CartesianIndex(4, 7)\n CartesianIndex(5, 9)\n CartesianIndex(3, 18)\n\njulia> findnz(R)\n([1, 3, 4, 5], [1, -5, 2, 3])\n\njulia> findall(!iszero, R)\n4-element Vector{Int64}:\n 1\n 3\n 4\n 5","category":"page"},{"location":"stdlib/SparseArrays/","page":"稀疏数组","title":"稀疏数组","text":"另一个创建稀疏数组的方法是使用 sparse 函数将一个稠密数组转化为稀疏数组:","category":"page"},{"location":"stdlib/SparseArrays/","page":"稀疏数组","title":"稀疏数组","text":"julia> sparse(Matrix(1.0I, 5, 5))\n5×5 SparseMatrixCSC{Float64, Int64} with 5 stored entries:\n 1.0 ⋅ ⋅ ⋅ ⋅\n ⋅ 1.0 ⋅ ⋅ ⋅\n ⋅ ⋅ 1.0 ⋅ ⋅\n ⋅ ⋅ ⋅ 1.0 ⋅\n ⋅ ⋅ ⋅ ⋅ 1.0\n\njulia> sparse([1.0, 0.0, 1.0])\n3-element SparseVector{Float64, Int64} with 2 stored entries:\n [1] = 1.0\n [3] = 1.0","category":"page"},{"location":"stdlib/SparseArrays/","page":"稀疏数组","title":"稀疏数组","text":"You can go in the other direction using the Array constructor. The issparse function can be used to query if a matrix is sparse.","category":"page"},{"location":"stdlib/SparseArrays/","page":"稀疏数组","title":"稀疏数组","text":"julia> issparse(spzeros(5))\ntrue","category":"page"},{"location":"stdlib/SparseArrays/#稀疏矩阵的操作","page":"稀疏数组","title":"稀疏矩阵的操作","text":"","category":"section"},{"location":"stdlib/SparseArrays/","page":"稀疏数组","title":"稀疏数组","text":"Arithmetic operations on sparse matrices also work as they do on dense matrices. Indexing of, assignment into, and concatenation of sparse matrices work in the same way as dense matrices. Indexing operations, especially assignment, are expensive, when carried out one element at a time. In many cases it may be better to convert the sparse matrix into (I,J,V) format using findnz, manipulate the values or the structure in the dense vectors (I,J,V), and then reconstruct the sparse matrix.","category":"page"},{"location":"stdlib/SparseArrays/#Correspondence-of-dense-and-sparse-methods","page":"稀疏数组","title":"Correspondence of dense and sparse methods","text":"","category":"section"},{"location":"stdlib/SparseArrays/","page":"稀疏数组","title":"稀疏数组","text":"The following table gives a correspondence between built-in methods on sparse matrices and their corresponding methods on dense matrix types. In general, methods that generate sparse matrices differ from their dense counterparts in that the resulting matrix follows the same sparsity pattern as a given sparse matrix S, or that the resulting sparse matrix has density d, i.e. each matrix element has a probability d of being non-zero.","category":"page"},{"location":"stdlib/SparseArrays/","page":"稀疏数组","title":"稀疏数组","text":"Details can be found in the Sparse Vectors and Matrices section of the standard library reference.","category":"page"},{"location":"stdlib/SparseArrays/","page":"稀疏数组","title":"稀疏数组","text":"构造函数 密度 说明\nspzeros(m,n) zeros(m,n) Creates a m-by-n matrix of zeros. (spzeros(m,n) is empty.)\nsparse(I,n,n) Matrix(I,n,n) Creates a n-by-n identity matrix.\nsparse(A) Array(S) Interconverts between dense and sparse formats.\nsprand(m,n,d) rand(m,n) Creates a m-by-n random matrix (of density d) with iid non-zero elements distributed uniformly on the half-open interval 0 1).\nsprandn(m,n,d) randn(m,n) Creates a m-by-n random matrix (of density d) with iid non-zero elements distributed according to the standard normal (Gaussian) distribution.\nsprandn(rng,m,n,d) randn(rng,m,n) Creates a m-by-n random matrix (of density d) with iid non-zero elements generated with the rng random number generator","category":"page"},{"location":"stdlib/SparseArrays/#stdlib-sparse-arrays","page":"稀疏数组","title":"Sparse Arrays","text":"","category":"section"},{"location":"stdlib/SparseArrays/","page":"稀疏数组","title":"稀疏数组","text":"SparseArrays.AbstractSparseArray\nSparseArrays.AbstractSparseVector\nSparseArrays.AbstractSparseMatrix\nSparseArrays.SparseVector\nSparseArrays.SparseMatrixCSC\nSparseArrays.sparse\nSparseArrays.sparsevec\nSparseArrays.issparse\nSparseArrays.nnz\nSparseArrays.findnz\nSparseArrays.spzeros\nSparseArrays.spdiagm\nSparseArrays.blockdiag\nSparseArrays.sprand\nSparseArrays.sprandn\nSparseArrays.nonzeros\nSparseArrays.rowvals\nSparseArrays.nzrange\nSparseArrays.droptol!\nSparseArrays.dropzeros!\nSparseArrays.dropzeros\nSparseArrays.permute\npermute!{Tv, Ti, Tp <: Integer, Tq <: Integer}(::SparseMatrixCSC{Tv,Ti}, ::SparseMatrixCSC{Tv,Ti}, ::AbstractArray{Tp,1}, ::AbstractArray{Tq,1})","category":"page"},{"location":"stdlib/SparseArrays/#SparseArrays.AbstractSparseArray","page":"稀疏数组","title":"SparseArrays.AbstractSparseArray","text":"AbstractSparseArray{Tv,Ti,N}\n\nSupertype for N-dimensional sparse arrays (or array-like types) with elements of type Tv and index type Ti. SparseMatrixCSC, SparseVector and SuiteSparse.CHOLMOD.Sparse are subtypes of this.\n\n\n\n\n\n","category":"type"},{"location":"stdlib/SparseArrays/#SparseArrays.AbstractSparseVector","page":"稀疏数组","title":"SparseArrays.AbstractSparseVector","text":"AbstractSparseVector{Tv,Ti}\n\nSupertype for one-dimensional sparse arrays (or array-like types) with elements of type Tv and index type Ti. Alias for AbstractSparseArray{Tv,Ti,1}.\n\n\n\n\n\n","category":"type"},{"location":"stdlib/SparseArrays/#SparseArrays.AbstractSparseMatrix","page":"稀疏数组","title":"SparseArrays.AbstractSparseMatrix","text":"AbstractSparseMatrix{Tv,Ti}\n\nSupertype for two-dimensional sparse arrays (or array-like types) with elements of type Tv and index type Ti. Alias for AbstractSparseArray{Tv,Ti,2}.\n\n\n\n\n\n","category":"type"},{"location":"stdlib/SparseArrays/#SparseArrays.SparseVector","page":"稀疏数组","title":"SparseArrays.SparseVector","text":"SparseVector{Tv,Ti<:Integer} <: AbstractSparseVector{Tv,Ti}\n\nVector type for storing sparse vectors.\n\n\n\n\n\n","category":"type"},{"location":"stdlib/SparseArrays/#SparseArrays.SparseMatrixCSC","page":"稀疏数组","title":"SparseArrays.SparseMatrixCSC","text":"SparseMatrixCSC{Tv,Ti<:Integer} <: AbstractSparseMatrixCSC{Tv,Ti}\n\nMatrix type for storing sparse matrices in the Compressed Sparse Column format. The standard way of constructing SparseMatrixCSC is through the sparse function. See also spzeros, spdiagm and sprand.\n\n\n\n\n\n","category":"type"},{"location":"stdlib/SparseArrays/#SparseArrays.sparse","page":"稀疏数组","title":"SparseArrays.sparse","text":"sparse(A)\n\nConvert an AbstractMatrix A into a sparse matrix.\n\nExamples\n\njulia> A = Matrix(1.0I, 3, 3)\n3×3 Matrix{Float64}:\n 1.0 0.0 0.0\n 0.0 1.0 0.0\n 0.0 0.0 1.0\n\njulia> sparse(A)\n3×3 SparseMatrixCSC{Float64, Int64} with 3 stored entries:\n 1.0 ⋅ ⋅\n ⋅ 1.0 ⋅\n ⋅ ⋅ 1.0\n\n\n\n\n\nsparse(I, J, V,[ m, n, combine])\n\nCreate a sparse matrix S of dimensions m x n such that S[I[k], J[k]] = V[k]. The combine function is used to combine duplicates. If m and n are not specified, they are set to maximum(I) and maximum(J) respectively. If the combine function is not supplied, combine defaults to + unless the elements of V are Booleans in which case combine defaults to |. All elements of I must satisfy 1 <= I[k] <= m, and all elements of J must satisfy 1 <= J[k] <= n. Numerical zeros in (I, J, V) are retained as structural nonzeros; to drop numerical zeros, use dropzeros!.\n\nFor additional documentation and an expert driver, see SparseArrays.sparse!.\n\nExamples\n\njulia> Is = [1; 2; 3];\n\njulia> Js = [1; 2; 3];\n\njulia> Vs = [1; 2; 3];\n\njulia> sparse(Is, Js, Vs)\n3×3 SparseMatrixCSC{Int64, Int64} with 3 stored entries:\n 1 ⋅ ⋅\n ⋅ 2 ⋅\n ⋅ ⋅ 3\n\n\n\n\n\n","category":"function"},{"location":"stdlib/SparseArrays/#SparseArrays.sparsevec","page":"稀疏数组","title":"SparseArrays.sparsevec","text":"sparsevec(I, V, [m, combine])\n\nCreate a sparse vector S of length m such that S[I[k]] = V[k]. Duplicates are combined using the combine function, which defaults to + if no combine argument is provided, unless the elements of V are Booleans in which case combine defaults to |.\n\nExamples\n\njulia> II = [1, 3, 3, 5]; V = [0.1, 0.2, 0.3, 0.2];\n\njulia> sparsevec(II, V)\n5-element SparseVector{Float64, Int64} with 3 stored entries:\n [1] = 0.1\n [3] = 0.5\n [5] = 0.2\n\njulia> sparsevec(II, V, 8, -)\n8-element SparseVector{Float64, Int64} with 3 stored entries:\n [1] = 0.1\n [3] = -0.1\n [5] = 0.2\n\njulia> sparsevec([1, 3, 1, 2, 2], [true, true, false, false, false])\n3-element SparseVector{Bool, Int64} with 3 stored entries:\n [1] = 1\n [2] = 0\n [3] = 1\n\n\n\n\n\nsparsevec(d::Dict, [m])\n\nCreate a sparse vector of length m where the nonzero indices are keys from the dictionary, and the nonzero values are the values from the dictionary.\n\nExamples\n\njulia> sparsevec(Dict(1 => 3, 2 => 2))\n2-element SparseVector{Int64, Int64} with 2 stored entries:\n [1] = 3\n [2] = 2\n\n\n\n\n\nsparsevec(A)\n\nConvert a vector A into a sparse vector of length m.\n\nExamples\n\njulia> sparsevec([1.0, 2.0, 0.0, 0.0, 3.0, 0.0])\n6-element SparseVector{Float64, Int64} with 3 stored entries:\n [1] = 1.0\n [2] = 2.0\n [5] = 3.0\n\n\n\n\n\n","category":"function"},{"location":"stdlib/SparseArrays/#SparseArrays.issparse","page":"稀疏数组","title":"SparseArrays.issparse","text":"issparse(S)\n\nReturns true if S is sparse, and false otherwise.\n\nExamples\n\njulia> sv = sparsevec([1, 4], [2.3, 2.2], 10)\n10-element SparseVector{Float64, Int64} with 2 stored entries:\n [1 ] = 2.3\n [4 ] = 2.2\n\njulia> issparse(sv)\ntrue\n\njulia> issparse(Array(sv))\nfalse\n\n\n\n\n\n","category":"function"},{"location":"stdlib/SparseArrays/#SparseArrays.nnz","page":"稀疏数组","title":"SparseArrays.nnz","text":"nnz(A)\n\nReturns the number of stored (filled) elements in a sparse array.\n\nExamples\n\njulia> A = sparse(2I, 3, 3)\n3×3 SparseMatrixCSC{Int64, Int64} with 3 stored entries:\n 2 ⋅ ⋅\n ⋅ 2 ⋅\n ⋅ ⋅ 2\n\njulia> nnz(A)\n3\n\n\n\n\n\n","category":"function"},{"location":"stdlib/SparseArrays/#SparseArrays.findnz","page":"稀疏数组","title":"SparseArrays.findnz","text":"findnz(A::SparseMatrixCSC)\n\nReturn a tuple (I, J, V) where I and J are the row and column indices of the stored (\"structurally non-zero\") values in sparse matrix A, and V is a vector of the values.\n\nExamples\n\njulia> A = sparse([1 2 0; 0 0 3; 0 4 0])\n3×3 SparseMatrixCSC{Int64, Int64} with 4 stored entries:\n 1 2 ⋅\n ⋅ ⋅ 3\n ⋅ 4 ⋅\n\njulia> findnz(A)\n([1, 1, 3, 2], [1, 2, 2, 3], [1, 2, 4, 3])\n\n\n\n\n\n","category":"function"},{"location":"stdlib/SparseArrays/#SparseArrays.spzeros","page":"稀疏数组","title":"SparseArrays.spzeros","text":"spzeros([type,]m[,n])\n\nCreate a sparse vector of length m or sparse matrix of size m x n. This sparse array will not contain any nonzero values. No storage will be allocated for nonzero values during construction. The type defaults to Float64 if not specified.\n\nExamples\n\njulia> spzeros(3, 3)\n3×3 SparseMatrixCSC{Float64, Int64} with 0 stored entries:\n ⋅ ⋅ ⋅\n ⋅ ⋅ ⋅\n ⋅ ⋅ ⋅\n\njulia> spzeros(Float32, 4)\n4-element SparseVector{Float32, Int64} with 0 stored entries\n\n\n\n\n\n","category":"function"},{"location":"stdlib/SparseArrays/#SparseArrays.spdiagm","page":"稀疏数组","title":"SparseArrays.spdiagm","text":"spdiagm(kv::Pair{<:Integer,<:AbstractVector}...)\nspdiagm(m::Integer, n::Integer, kv::Pair{<:Integer,<:AbstractVector}...)\n\nConstruct a sparse diagonal matrix from Pairs of vectors and diagonals. Each vector kv.second will be placed on the kv.first diagonal. By default, the matrix is square and its size is inferred from kv, but a non-square size m×n (padded with zeros as needed) can be specified by passing m,n as the first arguments.\n\nExamples\n\njulia> spdiagm(-1 => [1,2,3,4], 1 => [4,3,2,1])\n5×5 SparseMatrixCSC{Int64, Int64} with 8 stored entries:\n ⋅ 4 ⋅ ⋅ ⋅\n 1 ⋅ 3 ⋅ ⋅\n ⋅ 2 ⋅ 2 ⋅\n ⋅ ⋅ 3 ⋅ 1\n ⋅ ⋅ ⋅ 4 ⋅\n\n\n\n\n\nspdiagm(v::AbstractVector)\nspdiagm(m::Integer, n::Integer, v::AbstractVector)\n\nConstruct a sparse matrix with elements of the vector as diagonal elements. By default (no given m and n), the matrix is square and its size is given by length(v), but a non-square size m×n can be specified by passing m and n as the first arguments.\n\ncompat: Julia 1.6\nThese functions require at least Julia 1.6.\n\nExamples\n\njulia> spdiagm([1,2,3])\n3×3 SparseMatrixCSC{Int64, Int64} with 3 stored entries:\n 1 ⋅ ⋅\n ⋅ 2 ⋅\n ⋅ ⋅ 3\n\njulia> spdiagm(sparse([1,0,3]))\n3×3 SparseMatrixCSC{Int64, Int64} with 2 stored entries:\n 1 ⋅ ⋅\n ⋅ ⋅ ⋅\n ⋅ ⋅ 3\n\n\n\n\n\n","category":"function"},{"location":"stdlib/SparseArrays/#SparseArrays.blockdiag","page":"稀疏数组","title":"SparseArrays.blockdiag","text":"blockdiag(A...)\n\nConcatenate matrices block-diagonally. Currently only implemented for sparse matrices.\n\nExamples\n\njulia> blockdiag(sparse(2I, 3, 3), sparse(4I, 2, 2))\n5×5 SparseMatrixCSC{Int64, Int64} with 5 stored entries:\n 2 ⋅ ⋅ ⋅ ⋅\n ⋅ 2 ⋅ ⋅ ⋅\n ⋅ ⋅ 2 ⋅ ⋅\n ⋅ ⋅ ⋅ 4 ⋅\n ⋅ ⋅ ⋅ ⋅ 4\n\n\n\n\n\n","category":"function"},{"location":"stdlib/SparseArrays/#SparseArrays.sprand","page":"稀疏数组","title":"SparseArrays.sprand","text":"sprand([rng],[type],m,[n],p::AbstractFloat,[rfn])\n\nCreate a random length m sparse vector or m by n sparse matrix, in which the probability of any element being nonzero is independently given by p (and hence the mean density of nonzeros is also exactly p). Nonzero values are sampled from the distribution specified by rfn and have the type type. The uniform distribution is used in case rfn is not specified. The optional rng argument specifies a random number generator, see Random Numbers.\n\nExamples\n\njulia> sprand(Bool, 2, 2, 0.5)\n2×2 SparseMatrixCSC{Bool, Int64} with 2 stored entries:\n 1 1\n ⋅ ⋅\n\njulia> sprand(Float64, 3, 0.75)\n3-element SparseVector{Float64, Int64} with 2 stored entries:\n [1] = 0.795547\n [2] = 0.49425\n\n\n\n\n\n","category":"function"},{"location":"stdlib/SparseArrays/#SparseArrays.sprandn","page":"稀疏数组","title":"SparseArrays.sprandn","text":"sprandn([rng][,Type],m[,n],p::AbstractFloat)\n\nCreate a random sparse vector of length m or sparse matrix of size m by n with the specified (independent) probability p of any entry being nonzero, where nonzero values are sampled from the normal distribution. The optional rng argument specifies a random number generator, see Random Numbers.\n\ncompat: Julia 1.1\nSpecifying the output element type Type requires at least Julia 1.1.\n\nExamples\n\njulia> sprandn(2, 2, 0.75)\n2×2 SparseMatrixCSC{Float64, Int64} with 3 stored entries:\n -1.20577 ⋅\n 0.311817 -0.234641\n\n\n\n\n\n","category":"function"},{"location":"stdlib/SparseArrays/#SparseArrays.nonzeros","page":"稀疏数组","title":"SparseArrays.nonzeros","text":"nonzeros(A)\n\nReturn a vector of the structural nonzero values in sparse array A. This includes zeros that are explicitly stored in the sparse array. The returned vector points directly to the internal nonzero storage of A, and any modifications to the returned vector will mutate A as well. See rowvals and nzrange.\n\nExamples\n\njulia> A = sparse(2I, 3, 3)\n3×3 SparseMatrixCSC{Int64, Int64} with 3 stored entries:\n 2 ⋅ ⋅\n ⋅ 2 ⋅\n ⋅ ⋅ 2\n\njulia> nonzeros(A)\n3-element Vector{Int64}:\n 2\n 2\n 2\n\n\n\n\n\n","category":"function"},{"location":"stdlib/SparseArrays/#SparseArrays.rowvals","page":"稀疏数组","title":"SparseArrays.rowvals","text":"rowvals(A::AbstractSparseMatrixCSC)\n\nReturn a vector of the row indices of A. Any modifications to the returned vector will mutate A as well. Providing access to how the row indices are stored internally can be useful in conjunction with iterating over structural nonzero values. See also nonzeros and nzrange.\n\nExamples\n\njulia> A = sparse(2I, 3, 3)\n3×3 SparseMatrixCSC{Int64, Int64} with 3 stored entries:\n 2 ⋅ ⋅\n ⋅ 2 ⋅\n ⋅ ⋅ 2\n\njulia> rowvals(A)\n3-element Vector{Int64}:\n 1\n 2\n 3\n\n\n\n\n\n","category":"function"},{"location":"stdlib/SparseArrays/#SparseArrays.nzrange","page":"稀疏数组","title":"SparseArrays.nzrange","text":"nzrange(A::AbstractSparseMatrixCSC, col::Integer)\n\nReturn the range of indices to the structural nonzero values of a sparse matrix column. In conjunction with nonzeros and rowvals, this allows for convenient iterating over a sparse matrix :\n\nA = sparse(I,J,V)\nrows = rowvals(A)\nvals = nonzeros(A)\nm, n = size(A)\nfor j = 1:n\n for i in nzrange(A, j)\n row = rows[i]\n val = vals[i]\n # perform sparse wizardry...\n end\nend\n\n\n\n\n\nnzrange(x::SparseVectorUnion, col)\n\nGive the range of indices to the structural nonzero values of a sparse vector. The column index col is ignored (assumed to be 1).\n\n\n\n\n\n","category":"function"},{"location":"stdlib/SparseArrays/#SparseArrays.droptol!","page":"稀疏数组","title":"SparseArrays.droptol!","text":"droptol!(A::AbstractSparseMatrixCSC, tol)\n\nRemoves stored values from A whose absolute value is less than or equal to tol.\n\n\n\n\n\ndroptol!(x::SparseVector, tol)\n\nRemoves stored values from x whose absolute value is less than or equal to tol.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/SparseArrays/#SparseArrays.dropzeros!","page":"稀疏数组","title":"SparseArrays.dropzeros!","text":"dropzeros!(A::AbstractSparseMatrixCSC;)\n\nRemoves stored numerical zeros from A.\n\nFor an out-of-place version, see dropzeros. For algorithmic information, see fkeep!.\n\n\n\n\n\ndropzeros!(x::SparseVector)\n\nRemoves stored numerical zeros from x.\n\nFor an out-of-place version, see dropzeros. For algorithmic information, see fkeep!.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/SparseArrays/#SparseArrays.dropzeros","page":"稀疏数组","title":"SparseArrays.dropzeros","text":"dropzeros(A::AbstractSparseMatrixCSC;)\n\nGenerates a copy of A and removes stored numerical zeros from that copy.\n\nFor an in-place version and algorithmic information, see dropzeros!.\n\nExamples\n\njulia> A = sparse([1, 2, 3], [1, 2, 3], [1.0, 0.0, 1.0])\n3×3 SparseMatrixCSC{Float64, Int64} with 3 stored entries:\n 1.0 ⋅ ⋅\n ⋅ 0.0 ⋅\n ⋅ ⋅ 1.0\n\njulia> dropzeros(A)\n3×3 SparseMatrixCSC{Float64, Int64} with 2 stored entries:\n 1.0 ⋅ ⋅\n ⋅ ⋅ ⋅\n ⋅ ⋅ 1.0\n\n\n\n\n\ndropzeros(x::SparseVector)\n\nGenerates a copy of x and removes numerical zeros from that copy.\n\nFor an in-place version and algorithmic information, see dropzeros!.\n\nExamples\n\njulia> A = sparsevec([1, 2, 3], [1.0, 0.0, 1.0])\n3-element SparseVector{Float64, Int64} with 3 stored entries:\n [1] = 1.0\n [2] = 0.0\n [3] = 1.0\n\njulia> dropzeros(A)\n3-element SparseVector{Float64, Int64} with 2 stored entries:\n [1] = 1.0\n [3] = 1.0\n\n\n\n\n\n","category":"function"},{"location":"stdlib/SparseArrays/#SparseArrays.permute","page":"稀疏数组","title":"SparseArrays.permute","text":"permute(A::AbstractSparseMatrixCSC{Tv,Ti}, p::AbstractVector{<:Integer},\n q::AbstractVector{<:Integer}) where {Tv,Ti}\n\nBilaterally permute A, returning PAQ (A[p,q]). Column-permutation q's length must match A's column count (length(q) == size(A, 2)). Row-permutation p's length must match A's row count (length(p) == size(A, 1)).\n\nFor expert drivers and additional information, see permute!.\n\nExamples\n\njulia> A = spdiagm(0 => [1, 2, 3, 4], 1 => [5, 6, 7])\n4×4 SparseMatrixCSC{Int64, Int64} with 7 stored entries:\n 1 5 ⋅ ⋅\n ⋅ 2 6 ⋅\n ⋅ ⋅ 3 7\n ⋅ ⋅ ⋅ 4\n\njulia> permute(A, [4, 3, 2, 1], [1, 2, 3, 4])\n4×4 SparseMatrixCSC{Int64, Int64} with 7 stored entries:\n ⋅ ⋅ ⋅ 4\n ⋅ ⋅ 3 7\n ⋅ 2 6 ⋅\n 1 5 ⋅ ⋅\n\njulia> permute(A, [1, 2, 3, 4], [4, 3, 2, 1])\n4×4 SparseMatrixCSC{Int64, Int64} with 7 stored entries:\n ⋅ ⋅ 5 1\n ⋅ 6 2 ⋅\n 7 3 ⋅ ⋅\n 4 ⋅ ⋅ ⋅\n\n\n\n\n\n","category":"function"},{"location":"stdlib/SparseArrays/#Base.permute!-Union{Tuple{Tq}, Tuple{Tp}, Tuple{Ti}, Tuple{Tv}, Tuple{SparseMatrixCSC{Tv, Ti}, SparseMatrixCSC{Tv, Ti}, AbstractVector{Tp}, AbstractVector{Tq}}} where {Tv, Ti, Tp<:Integer, Tq<:Integer}","page":"稀疏数组","title":"Base.permute!","text":"permute!(X::AbstractSparseMatrixCSC{Tv,Ti}, A::AbstractSparseMatrixCSC{Tv,Ti},\n p::AbstractVector{<:Integer}, q::AbstractVector{<:Integer},\n [C::AbstractSparseMatrixCSC{Tv,Ti}]) where {Tv,Ti}\n\nBilaterally permute A, storing result PAQ (A[p,q]) in X. Stores intermediate result (AQ)^T (transpose(A[:,q])) in optional argument C if present. Requires that none of X, A, and, if present, C alias each other; to store result PAQ back into A, use the following method lacking X:\n\npermute!(A::AbstractSparseMatrixCSC{Tv,Ti}, p::AbstractVector{<:Integer},\n q::AbstractVector{<:Integer}[, C::AbstractSparseMatrixCSC{Tv,Ti},\n [workcolptr::Vector{Ti}]]) where {Tv,Ti}\n\nX's dimensions must match those of A (size(X, 1) == size(A, 1) and size(X, 2) == size(A, 2)), and X must have enough storage to accommodate all allocated entries in A (length(rowvals(X)) >= nnz(A) and length(nonzeros(X)) >= nnz(A)). Column-permutation q's length must match A's column count (length(q) == size(A, 2)). Row-permutation p's length must match A's row count (length(p) == size(A, 1)).\n\nC's dimensions must match those of transpose(A) (size(C, 1) == size(A, 2) and size(C, 2) == size(A, 1)), and C must have enough storage to accommodate all allocated entries in A (length(rowvals(C)) >= nnz(A) and length(nonzeros(C)) >= nnz(A)).\n\nFor additional (algorithmic) information, and for versions of these methods that forgo argument checking, see (unexported) parent methods unchecked_noalias_permute! and unchecked_aliasing_permute!.\n\nSee also permute.\n\n\n\n\n\n","category":"method"},{"location":"stdlib/SparseArrays/","page":"稀疏数组","title":"稀疏数组","text":"DocTestSetup = nothing","category":"page"},{"location":"manual/constructors/#man-constructors","page":"构造函数","title":"构造函数","text":"","category":"section"},{"location":"manual/constructors/","page":"构造函数","title":"构造函数","text":"构造函数 [1] 是用来创建新对象的函数 – 确切地说,它创建的是复合类型的实例。在 Julia 中,类型对象也同时充当构造函数的角色:可以用类名加参数元组的方式像函数调用一样来创建新实例。这一点在介绍复合类型(Composite Types)时已经大致谈过了。例如:","category":"page"},{"location":"manual/constructors/","page":"构造函数","title":"构造函数","text":"julia> struct Foo\n bar\n baz\n end\n\njulia> foo = Foo(1, 2)\nFoo(1, 2)\n\njulia> foo.bar\n1\n\njulia> foo.baz\n2","category":"page"},{"location":"manual/constructors/","page":"构造函数","title":"构造函数","text":"对很多类型来说,通过给所有字段赋值来创建新对象的这种方式就足以用于产生新实例了。然而,在某些情形下,创建复合对象需要更多的功能。有时必须通过检查或转化参数来确保固有属性不变。递归数据结构,特别是那些可能引用自身的数据结构,它们通常不能被干净地构造,而是需要首先被不完整地构造,然后再通过编程的方式完成补全。为了方便,有时需要用较少的参数或者不同类型的参数来创建对象,Julia 的对象构造系统解决了所有这些问题。","category":"page"},{"location":"manual/constructors/","page":"构造函数","title":"构造函数","text":"[1]: 命名法:虽然术语「构造函数」通常是指用于构造类型对象的函数全体,但通常会略微滥用术语将特定的构造方法称为「构造函数」。在这种情况下,通常可以从上下文中清楚地辨别出术语表示的是「构造方法」而不是「构造函数」,尤其是在讨论某个特别的「构造方法」的时候。","category":"page"},{"location":"manual/constructors/#man-outer-constructor-methods","page":"构造函数","title":"外部构造方法","text":"","category":"section"},{"location":"manual/constructors/","page":"构造函数","title":"构造函数","text":"构造函数与 Julia 中的其他任何函数一样,其整体行为由其各个方法的组合行为定义。因此,只要定义新方法就可以向构造函数添加功能。例如,假设你想为 Foo 对象添加一个构造方法,该方法只接受一个参数并其作为 bar 和 baz 的值。这很简单:","category":"page"},{"location":"manual/constructors/","page":"构造函数","title":"构造函数","text":"julia> Foo(x) = Foo(x,x)\nFoo\n\njulia> Foo(1)\nFoo(1, 1)","category":"page"},{"location":"manual/constructors/","page":"构造函数","title":"构造函数","text":"你也可以为 Foo 添加新的零参数构造方法,它为 bar 和 baz 提供默认值:","category":"page"},{"location":"manual/constructors/","page":"构造函数","title":"构造函数","text":"julia> Foo() = Foo(0)\nFoo\n\njulia> Foo()\nFoo(0, 0)","category":"page"},{"location":"manual/constructors/","page":"构造函数","title":"构造函数","text":"这里零参数构造方法会调用单参数构造方法,单参数构造方法又调用了自动提供默认值的双参数构造方法。上面附加的这类构造方法,它们的声明方式与普通的方法一样,像这样的构造方法被称为外部构造方法,下文很快就会揭示这样称呼的原因。外部构造方法只能通过调用其他构造方法来创建新实例,比如自动提供默认值的构造方法。","category":"page"},{"location":"manual/constructors/#man-inner-constructor-methods","page":"构造函数","title":"内部构造方法","text":"","category":"section"},{"location":"manual/constructors/","page":"构造函数","title":"构造函数","text":"尽管外部构造方法可以成功地为构造对象提供了额外的便利,但它无法解决另外两个在本章导言里提到的问题:确保固有属性不变和允许创建自引用对象。因此,我们需要内部构造方法。内部构造方法和外部构造方法很相像,但有两点不同:","category":"page"},{"location":"manual/constructors/","page":"构造函数","title":"构造函数","text":"内部构造方法在类型声明代码块的内部,而不是和普通方法一样在外部。\n内部构造方法能够访问一个特殊的局部函数 new,此函数能够创建该类型的对象。","category":"page"},{"location":"manual/constructors/","page":"构造函数","title":"构造函数","text":"例如,假设你要声明一个保存一对实数的类型,但要约束第一个数不大于第二个数。你可以像这样声明它:","category":"page"},{"location":"manual/constructors/","page":"构造函数","title":"构造函数","text":"julia> struct OrderedPair\n x::Real\n y::Real\n OrderedPair(x,y) = x > y ? error(\"out of order\") : new(x,y)\n end","category":"page"},{"location":"manual/constructors/","page":"构造函数","title":"构造函数","text":"现在 OrderedPair 对象只能在 x <= y 时被成功构造:","category":"page"},{"location":"manual/constructors/","page":"构造函数","title":"构造函数","text":"julia> OrderedPair(1, 2)\nOrderedPair(1, 2)\n\njulia> OrderedPair(2,1)\nERROR: out of order\nStacktrace:\n [1] error at ./error.jl:33 [inlined]\n [2] OrderedPair(::Int64, ::Int64) at ./none:4\n [3] top-level scope","category":"page"},{"location":"manual/constructors/","page":"构造函数","title":"构造函数","text":"如果类型被声明为 mutable,你可以直接更改字段值来打破这个固有属性,然而,在未经允许的情况下,随意摆弄对象的内核一般都是不好的行为。你(或者其他人)可以在以后任何时候提供额外的外部构造方法,但一旦类型被声明了,就没有办法来添加更多的内部构造方法了。由于外部构造方法只能通过调用其它的构造方法来创建对象,所以最终构造对象的一定是某个内部构造函数。这保证了已声明类型的对象必须通过调用该类型的内部构造方法才得已存在,从而在某种程度上保证了类型的固有属性。","category":"page"},{"location":"manual/constructors/","page":"构造函数","title":"构造函数","text":"只要定义了任何一个内部构造方法,Julia 就不会再提供默认的构造方法:它会假定你已经为自己提供了所需的所有内部构造方法。默认构造方法等效于一个你自己编写的内部构造函数,该函数将所有成员作为参数(如果相应的字段具有类型,则约束为正确的类型),并将它们传递给 new,最后返回结果对象:","category":"page"},{"location":"manual/constructors/","page":"构造函数","title":"构造函数","text":"julia> struct Foo\n bar\n baz\n Foo(bar,baz) = new(bar,baz)\n end\n","category":"page"},{"location":"manual/constructors/","page":"构造函数","title":"构造函数","text":"这个声明与前面没有显式内部构造方法的 Foo 类型的定义效果相同。 以下两个类型是等价的 – 一个具有默认构造方法,另一个具有显式构造方法:","category":"page"},{"location":"manual/constructors/","page":"构造函数","title":"构造函数","text":"julia> struct T1\n x::Int64\n end\n\njulia> struct T2\n x::Int64\n T2(x) = new(x)\n end\n\njulia> T1(1)\nT1(1)\n\njulia> T2(1)\nT2(1)\n\njulia> T1(1.0)\nT1(1)\n\njulia> T2(1.0)\nT2(1)","category":"page"},{"location":"manual/constructors/","page":"构造函数","title":"构造函数","text":"提供尽可能少的内部构造方法是一种良好的形式:仅在需要显式地处理所有参数,以及强制执行必要的错误检查和转换时候才使用内部构造。其它用于提供便利的构造方法,比如提供默认值或辅助转换,应该定义为外部构造函数,然后再通过调用内部构造函数来执行繁重的工作。这种解耦是很自然的。","category":"page"},{"location":"manual/constructors/#不完整初始化","page":"构造函数","title":"不完整初始化","text":"","category":"section"},{"location":"manual/constructors/","page":"构造函数","title":"构造函数","text":"最后一个还没提到的问题是,如何构造具有自引用的对象,更广义地来说是构造递归数据结构。由于这其中的困难并不是那么显而易见,这里我们来简单解释一下,考虑如下的递归类型声明:","category":"page"},{"location":"manual/constructors/","page":"构造函数","title":"构造函数","text":"julia> mutable struct SelfReferential\n obj::SelfReferential\n end\n","category":"page"},{"location":"manual/constructors/","page":"构造函数","title":"构造函数","text":"这种类型可能看起来没什么大不了,直到我们考虑如何来构造它的实例。 如果 a 是 SelfReferential 的一个实例,则第二个实例可以用如下的调用来创建:","category":"page"},{"location":"manual/constructors/","page":"构造函数","title":"构造函数","text":"julia> b = SelfReferential(a)","category":"page"},{"location":"manual/constructors/","page":"构造函数","title":"构造函数","text":"但是,当没有实例存在的情况下,即没有可以传递给 obj 成员变量的有效值时,如何构造第一个实例?唯一的解决方案是允许使用未初始化的 obj 成员来创建一个未完全初始化的 SelfReferential 实例,并使用该不完整的实例作为另一个实例的 obj 成员的有效值,例如,它本身。","category":"page"},{"location":"manual/constructors/","page":"构造函数","title":"构造函数","text":"为了允许创建未完全初始化的对象,Julia 允许使用少于该类型成员数的参数来调用 new 函数,并返回一个具有某个未初始化成员的对象。然后,内部构造函数可以使用不完整的对象,在返回之前完成初始化。例如,我们在定义 SelfReferential 类型时采用了另一个方法,使用零参数内部构造函数来返回一个实例,此实例的 obj 成员指向其自身:","category":"page"},{"location":"manual/constructors/","page":"构造函数","title":"构造函数","text":"julia> mutable struct SelfReferential\n obj::SelfReferential\n SelfReferential() = (x = new(); x.obj = x)\n end\n","category":"page"},{"location":"manual/constructors/","page":"构造函数","title":"构造函数","text":"我们可以验证这一构造函数有效性,且由其构造的对象确实是自引用的:","category":"page"},{"location":"manual/constructors/","page":"构造函数","title":"构造函数","text":"julia> x = SelfReferential();\n\njulia> x === x\ntrue\n\njulia> x === x.obj\ntrue\n\njulia> x === x.obj.obj\ntrue","category":"page"},{"location":"manual/constructors/","page":"构造函数","title":"构造函数","text":"虽然从一个内部构造函数中返回一个完全初始化的对象是很好的,但是也可以返回未完全初始化的对象:","category":"page"},{"location":"manual/constructors/","page":"构造函数","title":"构造函数","text":"julia> mutable struct Incomplete\n data\n Incomplete() = new()\n end\n\njulia> z = Incomplete();","category":"page"},{"location":"manual/constructors/","page":"构造函数","title":"构造函数","text":"尽管允许创建含有未初始化成员的对象,然而任何对未初始化引用的访问都会立即报错:","category":"page"},{"location":"manual/constructors/","page":"构造函数","title":"构造函数","text":"julia> z.data\nERROR: UndefRefError: access to undefined reference","category":"page"},{"location":"manual/constructors/","page":"构造函数","title":"构造函数","text":"这避免了不断地检测 null 值的需要。然而,并不是所有的对象成员都是引用。Julia 会将一些类型当作纯数据(\"plain data\"),这意味着它们的数据是自包含的,并且没有引用其它对象。这些纯数据包括原始类型(比如 Int )和由其它纯数据类型构成的不可变结构体。纯数据类型的初始值是未定义的:","category":"page"},{"location":"manual/constructors/","page":"构造函数","title":"构造函数","text":"julia> struct HasPlain\n n::Int\n HasPlain() = new()\n end\n\njulia> HasPlain()\nHasPlain(438103441441)","category":"page"},{"location":"manual/constructors/","page":"构造函数","title":"构造函数","text":"由纯数据组成的数组也具有一样的行为。","category":"page"},{"location":"manual/constructors/","page":"构造函数","title":"构造函数","text":"在内部构造函数中,你可以将不完整的对象传递给其它函数来委托其补全构造:","category":"page"},{"location":"manual/constructors/","page":"构造函数","title":"构造函数","text":"julia> mutable struct Lazy\n data\n Lazy(v) = complete_me(new(), v)\n end","category":"page"},{"location":"manual/constructors/","page":"构造函数","title":"构造函数","text":"与构造函数返回的不完整对象一样,如果 complete_me 或其任何被调用者尝试在初始化之前访问 Lazy 对象的 data 字段,就会立刻报错。","category":"page"},{"location":"manual/constructors/#参数类型的构造函数","page":"构造函数","title":"参数类型的构造函数","text":"","category":"section"},{"location":"manual/constructors/","page":"构造函数","title":"构造函数","text":"参数类型的存在为构造函数增加了更多的复杂性。首先,让我们回顾一下参数类型。在默认情况下,我们可以用两种方法来实例化参数复合类型,一种是显式地提供类型参数,另一种是让 Julia 根据构造函数输入参数的类型来隐式地推导类型参数。这里有一些例子:","category":"page"},{"location":"manual/constructors/","page":"构造函数","title":"构造函数","text":"julia> struct Point{T<:Real}\n x::T\n y::T\n end\n\njulia> Point(1,2) ## 隐式的 T ##\nPoint{Int64}(1, 2)\n\njulia> Point(1.0,2.5) ## 隐式的 T ##\nPoint{Float64}(1.0, 2.5)\n\njulia> Point(1,2.5) ## 隐式的 T ##\nERROR: MethodError: no method matching Point(::Int64, ::Float64)\nClosest candidates are:\n Point(::T, ::T) where T<:Real at none:2\n\njulia> Point{Int64}(1, 2) ## 显式的 T ##\nPoint{Int64}(1, 2)\n\njulia> Point{Int64}(1.0,2.5) ## 显式的 T ##\nERROR: InexactError: Int64(2.5)\nStacktrace:\n[...]\n\njulia> Point{Float64}(1.0, 2.5) ## 显式的 T ##\nPoint{Float64}(1.0, 2.5)\n\njulia> Point{Float64}(1,2) ## 显式的 T ##\nPoint{Float64}(1.0, 2.0)","category":"page"},{"location":"manual/constructors/","page":"构造函数","title":"构造函数","text":"就像你看到的那样,用类型参数显式地调用构造函数,其参数会被转换为指定的类型:Point{Int64}(1,2) 可以正常工作,但是 Point{Int64}(1.0,2.5) 则会在将 2.5 转换为 Int64 的时候报一个 InexactError。当类型是从构造函数的参数隐式推导出来的时候,比如在例子 Point(1,2) 中,输入参数的类型必须一致,否则就无法确定 T 是什么,但 Point 的构造函数仍可以适配任意同类型的实数对。","category":"page"},{"location":"manual/constructors/","page":"构造函数","title":"构造函数","text":"实际上,这里的 Point,Point{Float64} 以及 Point{Int64} 是不同的构造函数。Point{T} 表示对于每个类型 T 都存在一个不同的构造函数。如果不显式提供内部构造函数,在声明复合类型 Point{T<:Real} 的时候,Julia 会对每个满足 T<:Real 条件的类型都提供一个默认的内部构造函数 Point{T},它们的行为与非参数类型的默认内部构造函数一致。Julia 同时也会提供了一个通用的外部构造函数 Point,用于适配任意同类型的实数对。Julia 默认提供的构造函数等价于下面这种显式的声明:","category":"page"},{"location":"manual/constructors/","page":"构造函数","title":"构造函数","text":"julia> struct Point{T<:Real}\n x::T\n y::T\n Point{T}(x,y) where {T<:Real} = new(x,y)\n end\n\njulia> Point(x::T, y::T) where {T<:Real} = Point{T}(x,y);","category":"page"},{"location":"manual/constructors/","page":"构造函数","title":"构造函数","text":"注意,每个构造函数定义的方式与调用它们的方式是一样的。调用 Point{Int64}(1,2) 会触发 struct 块内部的 Point{T}(x,y)。另一方面,外部构造函数声明的 Point 构造函数只会被同类型的实数对触发,它使得我们可以直接以 Point(1,2) 和 Point(1.0,2.5) 这种方式来创建实例,而不需要显示地使用类型参数。由于此方法的声明方式已经对输入参数的类型施加了约束,像 Point(1,2.5) 这种调用自然会导致 \"no method\" 错误。","category":"page"},{"location":"manual/constructors/","page":"构造函数","title":"构造函数","text":"假如我们想让 Point(1,2.5) 这种调用方式正常工作,比如,通过将整数 1 自动「提升」为浮点数 1.0,最简单的方法是像下面这样定义一个额外的外部构造函数:","category":"page"},{"location":"manual/constructors/","page":"构造函数","title":"构造函数","text":"julia> Point(x::Int64, y::Float64) = Point(convert(Float64,x),y);","category":"page"},{"location":"manual/constructors/","page":"构造函数","title":"构造函数","text":"此方法使用 convert 函数将 x 显式转换为 Float64,然后在两个参数都是 Float64 的情况下使用通用的构造函数。通过这个方法定义,以前的报MethodError的代码现在可以成功地创建一个类型为 Point{Float64} 的点:","category":"page"},{"location":"manual/constructors/","page":"构造函数","title":"构造函数","text":"julia> p = Point(1,2.5)\nPoint{Float64}(1.0, 2.5)\n\njulia> typeof(p)\nPoint{Float64}","category":"page"},{"location":"manual/constructors/","page":"构造函数","title":"构造函数","text":"然而,其它类似的调用依然有问题:","category":"page"},{"location":"manual/constructors/","page":"构造函数","title":"构造函数","text":"julia> Point(1.5,2)\nERROR: MethodError: no method matching Point(::Float64, ::Int64)\nClosest candidates are:\n Point(::T, !Matched::T) where T<:Real at none:1","category":"page"},{"location":"manual/constructors/","page":"构造函数","title":"构造函数","text":"如果你想要找到一种方法可以使类似的调用都可以正常工作,请参阅类型转换与类型提升。这里稍稍“剧透”一下,我们可以利用下面的这个外部构造函数来满足需求,无论输入参数的类型如何,它都可以触发通用的 Point 构造函数:","category":"page"},{"location":"manual/constructors/","page":"构造函数","title":"构造函数","text":"julia> Point(x::Real, y::Real) = Point(promote(x,y)...);","category":"page"},{"location":"manual/constructors/","page":"构造函数","title":"构造函数","text":"这里的 promote 函数会将它的输入转化为同一类型,在此例中是 Float64。定义了这个方法,Point 构造函数会自动提升输入参数的类型,且提升机制与算术运算符相同,比如 +,因此对所有的实数输入参数都适用:","category":"page"},{"location":"manual/constructors/","page":"构造函数","title":"构造函数","text":"julia> Point(1.5,2)\nPoint{Float64}(1.5, 2.0)\n\njulia> Point(1,1//2)\nPoint{Rational{Int64}}(1//1, 1//2)\n\njulia> Point(1.0,1//2)\nPoint{Float64}(1.0, 0.5)","category":"page"},{"location":"manual/constructors/","page":"构造函数","title":"构造函数","text":"因此,虽然 Julia 中默认提供的隐式类型参数构造函数相当严格,但可以很容易地使它们以更轻松且明智的方式运行。 此外,由于构造函数可以利用类型系统、方法和多重派发的所有功能,因此定义复杂的行为通常非常简单。","category":"page"},{"location":"manual/constructors/#示例学习:有理数","page":"构造函数","title":"示例学习:有理数","text":"","category":"section"},{"location":"manual/constructors/","page":"构造函数","title":"构造函数","text":"也许将所有这些部分联系在一起的最佳方法是展示参数复合类型及其构造方法的真实示例。 为此,我们实现了自己的有理数类型 OurRational,类似于 Julia 的内置 Rational 类型,定义在 [rational.jl](https://github.com/JuliaLang /julia/blob/master/base/rational.jl):","category":"page"},{"location":"manual/constructors/","page":"构造函数","title":"构造函数","text":"julia> struct OurRational{T<:Integer} <: Real\n num::T\n den::T\n function OurRational{T}(num::T, den::T) where T<:Integer\n if num == 0 && den == 0\n error(\"invalid rational: 0//0\")\n end\n num = flipsign(num, den)\n den = flipsign(den, den)\n g = gcd(num, den)\n num = div(num, g)\n den = div(den, g)\n new(num, den)\n end\n end\n\njulia> OurRational(n::T, d::T) where {T<:Integer} = OurRational{T}(n,d)\nOurRational\n\njulia> OurRational(n::Integer, d::Integer) = OurRational(promote(n,d)...)\nOurRational\n\njulia> OurRational(n::Integer) = OurRational(n,one(n))\nOurRational\n\njulia> ⊘(n::Integer, d::Integer) = OurRational(n,d)\n⊘ (generic function with 1 method)\n\njulia> ⊘(x::OurRational, y::Integer) = x.num ⊘ (x.den*y)\n⊘ (generic function with 2 methods)\n\njulia> ⊘(x::Integer, y::OurRational) = (x*y.den) ⊘ y.num\n⊘ (generic function with 3 methods)\n\njulia> ⊘(x::Complex, y::Real) = complex(real(x) ⊘ y, imag(x) ⊘ y)\n⊘ (generic function with 4 methods)\n\njulia> ⊘(x::Real, y::Complex) = (x*y') ⊘ real(y*y')\n⊘ (generic function with 5 methods)\n\njulia> function ⊘(x::Complex, y::Complex)\n xy = x*y'\n yy = real(y*y')\n complex(real(xy) ⊘ yy, imag(xy) ⊘ yy)\n end\n⊘ (generic function with 6 methods)","category":"page"},{"location":"manual/constructors/","page":"构造函数","title":"构造函数","text":"第一行 – struct OurRational{T<:Integer} <: Real – 声明了 OurRational 会接收一个整数类型的类型参数,且它自己属于实数类型。它声明了两个成员:num::T 和 den::T。这表明一个 OurRational{T} 的实例中会包含一对整数,且类型为 T,其中一个表示分子,另一个表示分母。","category":"page"},{"location":"manual/constructors/","page":"构造函数","title":"构造函数","text":"现在事情变得有趣了。 OurRational 有一个内部构造器方法,它检查 num 和 den 不都为零,并确保每个有理数都是以非负分母的“最低项”构造的。 这是通过首先翻转分子和分母的符号(如果分母为负)来实现的。 然后,两者都除以它们的最大公约数(gcd 总是返回一个非负数,无论其参数的符号如何)。 因为这是 OurRational 唯一的内部构造函数,我们可以确定 OurRational 对象总是以这种规范化形式构造的。","category":"page"},{"location":"manual/constructors/","page":"构造函数","title":"构造函数","text":"为了方便,OurRational 也提供了一些其它的外部构造函数。第一个外部构造函数是“标准的”通用构造函数,当分子和分母的类型一致时,它就可以推导出类型参数 T。第二个外部构造函数可以用于分子和分母的类型不一致的情景,它会将分子和分母的类型提升至一个共同的类型,然后再委托第一个外部构造函数进行构造。第三个构造函数会将一个整数转化为分数,方法是将 1 当作分母。","category":"page"},{"location":"manual/constructors/","page":"构造函数","title":"构造函数","text":"在定义了外部构造函数之后,我们为 ⊘ 算符定义了一系列的方法,之后就可以使用 ⊘ 算符来写分数,(比如 1 ⊘ 2)。Julia 的 Rational 类型采用的是 // 算符。在做上述定义之前,⊘ 是一个无意的且未被定义的算符。定义之后,它的行为与在 有理数 一节中描述的一致——注意它的所有行为都是那短短几行定义的。第一个也是最基础的定义只是将 a ⊘ b 中的 a 和 b 当作参数传递给 OurRational 的构造函数来实例化 OurRational,这要求 a 和 b 分别都是整数。在 ⊘ 的某个操作数已经是分数的情况下,我们采用了一个有点不一样的方法来构建新的分数,这实际上等价于用分数除以一个整数。最后,我们也可以让 ⊘ 作用于复数,用来创建一个类型为 Complex{<:OurRational} 的对象——即一个实部和虚部都是分数的复数:","category":"page"},{"location":"manual/constructors/","page":"构造函数","title":"构造函数","text":"julia> z = (1 + 2im) ⊘ (1 - 2im);\n\njulia> typeof(z)\nComplex{OurRational{Int64}}\n\njulia> typeof(z) <: Complex{<:OurRational}\ntrue","category":"page"},{"location":"manual/constructors/","page":"构造函数","title":"构造函数","text":"因此,尽管 ⊘ 算符通常会返回一个 OurRational 的实例,但倘若其中一个操作数是复整数,那么就会返回 Complex{<:OurRational}。感兴趣的话可以读一读 rational.jl:它实现了一个完整的 Julia 基本类型,但却非常的简短,而且是自恰的。","category":"page"},{"location":"manual/constructors/#仅外部的构造函数","page":"构造函数","title":"仅外部的构造函数","text":"","category":"section"},{"location":"manual/constructors/","page":"构造函数","title":"构造函数","text":"正如我们所看到的,典型的参数类型都有一个内部构造函数,它仅在全部的类型参数都已知的情况下才会被调用。例如,可以用 Point{Int}调用,但Point 就不行。我们可以选择性的添加外部构造函数来自动推导并添加类型参数,比如,调用 Point(1,2) 来构造 Point{Int}。外部构造函数调用内部构造函数来实际创建实例。然而,在某些情况下,我们可能并不想要内部构造函数,从而达到禁止手动指定类型参数的目的。","category":"page"},{"location":"manual/constructors/","page":"构造函数","title":"构造函数","text":"例如,假设我们要定义一个类型用于存储向量以及其累加和:","category":"page"},{"location":"manual/constructors/","page":"构造函数","title":"构造函数","text":"julia> struct SummedArray{T<:Number,S<:Number}\n data::Vector{T}\n sum::S\n end\n\njulia> SummedArray(Int32[1; 2; 3], Int32(6))\nSummedArray{Int32, Int32}(Int32[1, 2, 3], 6)","category":"page"},{"location":"manual/constructors/","page":"构造函数","title":"构造函数","text":"问题在于我们想让 S 的类型始终比 T 大,这样做是为了确保累加过程不会丢失信息。例如,当 T 是 Int32 时,我们想让 S 是 Int64。所以我们想要一种接口来禁止用户创建像 SummedArray{Int32,Int32} 这种类型的实例。一种实现方式是只提供一个 SummedArray 构造函数,当需要将其放入 struct-block 中,从而不让 Julia 提供默认的构造函数:","category":"page"},{"location":"manual/constructors/","page":"构造函数","title":"构造函数","text":"julia> struct SummedArray{T<:Number,S<:Number}\n data::Vector{T}\n sum::S\n function SummedArray(a::Vector{T}) where T\n S = widen(T)\n new{T,S}(a, sum(S, a))\n end\n end\n\njulia> SummedArray(Int32[1; 2; 3], Int32(6))\nERROR: MethodError: no method matching SummedArray(::Vector{Int32}, ::Int32)\nClosest candidates are:\n SummedArray(::Vector{T}) where T at none:4\nStacktrace:\n[...]","category":"page"},{"location":"manual/constructors/","page":"构造函数","title":"构造函数","text":"此构造函数将会被 SummedArray(a) 这种写法触发。new{T,S} 的这种写法允许指定待构建类型的参数,也就是说调用它会返回一个 SummedArray{T,S} 的实例。new{T,S} 也可以用于其它构造函数的定义中,但为了方便,Julia 会根据正在构造的类型自动推导出 new{} 花括号里的参数(如果可行的话)。","category":"page"},{"location":"stdlib/SHA/#SHA","page":"SHA","title":"SHA","text":"","category":"section"},{"location":"stdlib/SHA/","page":"SHA","title":"SHA","text":"用法非常直接:","category":"page"},{"location":"stdlib/SHA/","page":"SHA","title":"SHA","text":"julia> using SHA\n\njulia> bytes2hex(sha256(\"test\"))\n\"9f86d081884c7d659a2feaa0c55ad015a3bf4f1b2b0b822cd15d6c15b0f00a08\"","category":"page"},{"location":"stdlib/SHA/","page":"SHA","title":"SHA","text":"Each exported function (at the time of this writing, SHA-1, SHA-2 224, 256, 384 and 512, and SHA-3 224, 256, 384 and 512 functions are implemented) takes in either an AbstractVector{UInt8}, an AbstractString or an IO object. This makes it trivial to checksum a file:","category":"page"},{"location":"stdlib/SHA/","page":"SHA","title":"SHA","text":"shell> cat /tmp/test.txt\ntest\njulia> using SHA\n\njulia> open(\"/tmp/test.txt\") do f\n sha2_256(f)\n end\n32-element Array{UInt8,1}:\n 0x9f\n 0x86\n 0xd0\n 0x81\n 0x88\n 0x4c\n 0x7d\n 0x65\n ⋮\n 0x5d\n 0x6c\n 0x15\n 0xb0\n 0xf0\n 0x0a\n 0x08","category":"page"},{"location":"stdlib/SHA/","page":"SHA","title":"SHA","text":"Due to the colloquial usage of sha256 to refer to sha2_256, convenience functions are provided, mapping shaxxx() function calls to sha2_xxx(). For SHA-3, no such colloquialisms exist and the user must use the full sha3_xxx() names.","category":"page"},{"location":"stdlib/SHA/","page":"SHA","title":"SHA","text":"shaxxx() takes AbstractString and array-like objects (NTuple and Array) with elements of type UInt8.","category":"page"},{"location":"stdlib/SHA/","page":"SHA","title":"SHA","text":"To create a hash from multiple items the SHAX_XXX_CTX() types can be used to create a stateful hash object that is updated with update! and finalized with digest!","category":"page"},{"location":"stdlib/SHA/","page":"SHA","title":"SHA","text":"julia> ctx = SHA2_256_CTX()\nSHA2 256-bit hash state\n\njulia> update!(ctx, b\"some data\")\n0x0000000000000009\n\njulia> update!(ctx, b\"some more data\")\n0x0000000000000017\n\njulia> digest!(ctx)\n32-element Vector{UInt8}:\n 0xbe\n 0xcf\n 0x23\n 0xda\n 0xaf\n 0x02\n ⋮\n 0x25\n 0x52\n 0x19\n 0xa0\n 0x8b\n 0xc5","category":"page"},{"location":"stdlib/SHA/","page":"SHA","title":"SHA","text":"Note that, at the time of this writing, the SHA3 code is not optimized, and as such is roughly an order of magnitude slower than SHA2.","category":"page"},{"location":"devdocs/ssair/#Julia-SSA-form-IR","page":"Julia SSA-form IR","title":"Julia SSA-form IR","text":"","category":"section"},{"location":"devdocs/ssair/#Background","page":"Julia SSA-form IR","title":"Background","text":"","category":"section"},{"location":"devdocs/ssair/","page":"Julia SSA-form IR","title":"Julia SSA-form IR","text":"Beginning in Julia 0.7, parts of the compiler use a new SSA-form intermediate representation. Historically, the compiler used to directly generate LLVM IR, from a lowered form of the Julia AST. This form had most syntactic abstractions removed, but still looked a lot like an abstract syntax tree. Over time, in order to facilitate optimizations, SSA values were introduced to this IR and the IR was linearized (i.e. a form where function arguments may only be SSA values or constants). However, non-SSA values (slots) remained in the IR due to the lack of Phi nodes in the IR (necessary for back-edges and re-merging of conditional control flow), negating much of the usefulness of the SSA form representation to perform middle end optimizations. Some heroic effort was put into making these optimizations work without a complete SSA form representation, but the lack of such a representation ultimately proved prohibitive.","category":"page"},{"location":"devdocs/ssair/#New-IR-nodes","page":"Julia SSA-form IR","title":"New IR nodes","text":"","category":"section"},{"location":"devdocs/ssair/","page":"Julia SSA-form IR","title":"Julia SSA-form IR","text":"With the new IR representation, the compiler learned to handle four new IR nodes, Phi nodes, Pi nodes as well as PhiC nodes and Upsilon nodes (the latter two are only used for exception handling).","category":"page"},{"location":"devdocs/ssair/#Phi-nodes-and-Pi-nodes","page":"Julia SSA-form IR","title":"Phi nodes and Pi nodes","text":"","category":"section"},{"location":"devdocs/ssair/","page":"Julia SSA-form IR","title":"Julia SSA-form IR","text":"Phi nodes are part of generic SSA abstraction (see the link above if you're not familiar with the concept). In the Julia IR, these nodes are represented as:","category":"page"},{"location":"devdocs/ssair/","page":"Julia SSA-form IR","title":"Julia SSA-form IR","text":"struct PhiNode\n edges::Vector{Int}\n values::Vector{Any}\nend","category":"page"},{"location":"devdocs/ssair/","page":"Julia SSA-form IR","title":"Julia SSA-form IR","text":"where we ensure that both vectors always have the same length. In the canonical representation (the one handled by codegen and the interpreter), the edge values indicate come-from statement numbers (i.e. if edge has an entry of 15, there must be a goto, gotoifnot or implicit fall through from statement 15 that targets this phi node). Values are either SSA values or constants. It is also possible for a value to be unassigned if the variable was not defined on this path. However, undefinedness checks get explicitly inserted and represented as booleans after middle end optimizations, so code generators may assume that any use of a Phi node will have an assigned value in the corresponding slot. It is also legal for the mapping to be incomplete, i.e. for a Phi node to have missing incoming edges. In that case, it must be dynamically guaranteed that the corresponding value will not be used.","category":"page"},{"location":"devdocs/ssair/","page":"Julia SSA-form IR","title":"Julia SSA-form IR","text":"PiNodes encode statically proven information that may be implicitly assumed in basic blocks dominated by a given pi node. They are conceptually equivalent to the technique introduced in the paper ABCD: Eliminating Array Bounds Checks on Demand or the predicate info nodes in LLVM. To see how they work, consider, e.g.","category":"page"},{"location":"devdocs/ssair/","page":"Julia SSA-form IR","title":"Julia SSA-form IR","text":"%x::Union{Int, Float64} # %x is some Union{Int, Float64} typed ssa value\nif isa(x, Int)\n # use x\nelse\n # use x\nend","category":"page"},{"location":"devdocs/ssair/","page":"Julia SSA-form IR","title":"Julia SSA-form IR","text":"We can perform predicate insertion and turn this into:","category":"page"},{"location":"devdocs/ssair/","page":"Julia SSA-form IR","title":"Julia SSA-form IR","text":"%x::Union{Int, Float64} # %x is some Union{Int, Float64} typed ssa value\nif isa(x, Int)\n %x_int = PiNode(x, Int)\n # use %x_int\nelse\n %x_float = PiNode(x, Float64)\n # use %x_float\nend","category":"page"},{"location":"devdocs/ssair/","page":"Julia SSA-form IR","title":"Julia SSA-form IR","text":"Pi nodes are generally ignored in the interpreter, since they don't have any effect on the values, but they may sometimes lead to code generation in the compiler (e.g. to change from an implicitly union split representation to a plain unboxed representation). The main usefulness of PiNodes stems from the fact that path conditions of the values can be accumulated simply by def-use chain walking that is generally done for most optimizations that care about these conditions anyway.","category":"page"},{"location":"devdocs/ssair/#PhiC-nodes-and-Upsilon-nodes","page":"Julia SSA-form IR","title":"PhiC nodes and Upsilon nodes","text":"","category":"section"},{"location":"devdocs/ssair/","page":"Julia SSA-form IR","title":"Julia SSA-form IR","text":"Exception handling complicates the SSA story moderately, because exception handling introduces additional control flow edges into the IR across which values must be tracked. One approach to do so, which is followed by LLVM is to make calls which may throw exceptions into basic block terminators and add an explicit control flow edge to the catch handler:","category":"page"},{"location":"devdocs/ssair/","page":"Julia SSA-form IR","title":"Julia SSA-form IR","text":"invoke @function_that_may_throw() to label %regular unwind to %catch\n\nregular:\n# Control flow continues here\n\ncatch:\n# Exceptions go here","category":"page"},{"location":"devdocs/ssair/","page":"Julia SSA-form IR","title":"Julia SSA-form IR","text":"However, this is problematic in a language like julia where at the start of the optimization pipeline, we do not know which calls throw. We would have to conservatively assume that every call (which in julia is every statement) throws. This would have several negative effects. On the one hand, it would essentially reduce the scope of every basic block to a single call, defeating the purpose of having operations be performed at the basic block level. On the other hand, every catch basic block would have n*m phi node arguments (n, the number of statements in the critical region, m the number of live values through the catch block). To work around this, we use a combination of Upsilon and PhiC (the C standing for catch, written φᶜ in the IR pretty printer, because unicode subscript c is not available) nodes. There are several ways to think of these nodes, but perhaps the easiest is to think of each PhiC as a load from a unique store-many, read-once slot, with Upsilon being the corresponding store operation. The PhiC has an operand list of all the upsilon nodes that store to its implicit slot. The Upsilon nodes however, do not record which PhiC node they store to. This is done for more natural integration with the rest of the SSA IR. E.g. if there are no more uses of a PhiC node, it is safe to delete it, and the same is true of an Upsilon node. In most IR passes, PhiC nodes can be treated like Phi nodes. One can follow use-def chains through them, and they can be lifted to new PhiC nodes and new Upsilon nodes (in the same places as the original Upsilon nodes). The result of this scheme is that the number of Upsilon nodes (and PhiC arguments) is proportional to the number of assigned values to a particular variable (before SSA conversion), rather than the number of statements in the critical region.","category":"page"},{"location":"devdocs/ssair/","page":"Julia SSA-form IR","title":"Julia SSA-form IR","text":"To see this scheme in action, consider the function","category":"page"},{"location":"devdocs/ssair/","page":"Julia SSA-form IR","title":"Julia SSA-form IR","text":"@noinline opaque() = invokelatest(identity, nothing) # Something opaque\nfunction foo()\n local y\n x = 1\n try\n y = 2\n opaque()\n y = 3\n error()\n catch\n end\n (x, y)\nend","category":"page"},{"location":"devdocs/ssair/","page":"Julia SSA-form IR","title":"Julia SSA-form IR","text":"The corresponding IR (with irrelevant types stripped) is:","category":"page"},{"location":"devdocs/ssair/","page":"Julia SSA-form IR","title":"Julia SSA-form IR","text":"1 ─ nothing::Nothing\n2 ─ %2 = $(Expr(:enter, #4))\n3 ─ %3 = ϒ (false)\n│ %4 = ϒ (#undef)\n│ %5 = ϒ (1)\n│ %6 = ϒ (true)\n│ %7 = ϒ (2)\n│ invoke Main.opaque()::Any\n│ %9 = ϒ (true)\n│ %10 = ϒ (3)\n│ invoke Main.error()::Union{}\n└── $(Expr(:unreachable))::Union{}\n4 ┄ %13 = φᶜ (%3, %6, %9)::Bool\n│ %14 = φᶜ (%4, %7, %10)::Core.Compiler.MaybeUndef(Int64)\n│ %15 = φᶜ (%5)::Core.Const(1)\n└── $(Expr(:leave, 1))\n5 ─ $(Expr(:pop_exception, :(%2)))::Any\n│ $(Expr(:throw_undef_if_not, :y, :(%13)))::Any\n│ %19 = Core.tuple(%15, %14)\n└── return %19","category":"page"},{"location":"devdocs/ssair/","page":"Julia SSA-form IR","title":"Julia SSA-form IR","text":"Note in particular that every value live into the critical region gets an upsilon node at the top of the critical region. This is because catch blocks are considered to have an invisible control flow edge from outside the function. As a result, no SSA value dominates the catch blocks, and all incoming values have to come through a φᶜ node.","category":"page"},{"location":"devdocs/ssair/#Main-SSA-data-structure","page":"Julia SSA-form IR","title":"Main SSA data structure","text":"","category":"section"},{"location":"devdocs/ssair/","page":"Julia SSA-form IR","title":"Julia SSA-form IR","text":"The main SSAIR data structure is worthy of discussion. It draws inspiration from LLVM and Webkit's B3 IR. The core of the data structure is a flat vector of statements. Each statement is implicitly assigned an SSA value based on its position in the vector (i.e. the result of the statement at idx 1 can be accessed using SSAValue(1) etc). For each SSA value, we additionally maintain its type. Since, SSA values are definitionally assigned only once, this type is also the result type of the expression at the corresponding index. However, while this representation is rather efficient (since the assignments don't need to be explicitly encoded), it of course carries the drawback that order is semantically significant, so reorderings and insertions change statement numbers. Additionally, we do not keep use lists (i.e. it is impossible to walk from a def to all its uses without explicitly computing this map–def lists however are trivial since you can look up the corresponding statement from the index), so the LLVM-style RAUW (replace-all-uses-with) operation is unavailable.","category":"page"},{"location":"devdocs/ssair/","page":"Julia SSA-form IR","title":"Julia SSA-form IR","text":"Instead, we do the following:","category":"page"},{"location":"devdocs/ssair/","page":"Julia SSA-form IR","title":"Julia SSA-form IR","text":"We keep a separate buffer of nodes to insert (including the position to insert them at, the type of the corresponding value and the node itself). These nodes are numbered by their occurrence in the insertion buffer, allowing their values to be immediately used elsewhere in the IR (i.e. if there are 12 statements in the original statement list, the first new statement will be accessible as SSAValue(13)).\nRAUW style operations are performed by setting the corresponding statement index to the replacement value.\nStatements are erased by setting the corresponding statement to nothing (this is essentially just a special-case convention of the above.\nIf there are any uses of the statement being erased, they will be set to nothing.","category":"page"},{"location":"devdocs/ssair/","page":"Julia SSA-form IR","title":"Julia SSA-form IR","text":"There is a compact! function that compacts the above data structure by performing the insertion of nodes in the appropriate place, trivial copy propagation, and renaming of uses to any changed SSA values. However, the clever part of this scheme is that this compaction can be done lazily as part of the subsequent pass. Most optimization passes need to walk over the entire list of statements, performing analysis or modifications along the way. We provide an IncrementalCompact iterator that can be used to iterate over the statement list. It will perform any necessary compaction and return the new index of the node, as well as the node itself. It is legal at this point to walk def-use chains, as well as make any modifications or deletions to the IR (insertions are disallowed however).","category":"page"},{"location":"devdocs/ssair/","page":"Julia SSA-form IR","title":"Julia SSA-form IR","text":"The idea behind this arrangement is that, since the optimization passes need to touch the corresponding memory anyway and incur the corresponding memory access penalty, performing the extra housekeeping should have comparatively little overhead (and save the overhead of maintaining these data structures during IR modification).","category":"page"},{"location":"manual/","page":"-","title":"-","text":"io = IOBuffer()\nrelease = isempty(VERSION.prerelease)\nv = \"$(VERSION.major).$(VERSION.minor)\"\n!release && (v = v*\"-$(first(VERSION.prerelease))\")\nprint(io, \"\"\"\n # Julia $(v) Documentation\n\n Welcome to the documentation for Julia $(v).\n\n \"\"\")\nif !release\n print(io,\"\"\"\n !!! warning \"Work in progress!\"\n This documentation is for an unreleased, in-development, version of Julia.\n \"\"\")\nend\nimport Markdown\nMarkdown.parse(String(take!(io)))","category":"page"},{"location":"manual/","page":"-","title":"-","text":"请阅读 release notes 以了解自上次发行以来发生了什么变化。","category":"page"},{"location":"manual/","page":"-","title":"-","text":"release = isempty(VERSION.prerelease)\nfile = release ? \"julia-$(VERSION).pdf\" :\n \"julia-$(VERSION.major).$(VERSION.minor).$(VERSION.patch)-$(first(VERSION.prerelease)).pdf\"\nurl = \"https://raw.githubusercontent.com/JuliaLang/docs.julialang.org/assets/$(file)\"\nimport Markdown\nMarkdown.parse(\"\"\"\n!!! note\n The documentation is also available in PDF format: [$file]($url).\n\"\"\")","category":"page"},{"location":"manual/#man-introduction","page":"-","title":"简介","text":"","category":"section"},{"location":"manual/","page":"-","title":"-","text":"科学计算对性能一直有着最高的需求,但目前各领域的专家却大量使用较慢的动态语言来开展他们的日常工作。 偏爱动态语言有很多很好的理由,因此我们不会舍弃动态的特性。 幸运的是,现代编程语言设计与编译器技术可以大大消除性能折衷(trade-off),并提供有足够生产力的单一环境进行原型设计,而且能高效地部署性能密集型应用程序。 Julia 语言在这其中扮演了这样一个角色:它是一门灵活的动态语言,适合用于科学计算和数值计算,并且性能可与传统的静态类型语言媲美。","category":"page"},{"location":"manual/","page":"-","title":"-","text":"由于 Julia 的编译器和其它语言比如 Python 或 R 的解释器有所不同,一开始你可能发现 Julia 的性能并不是很突出。 如果你觉得速度有点慢,我们强烈建议在尝试其他功能前,先读一读文档中的提高性能的窍门部分。 一旦你理解了 Julia 的运作方式后,写出和 C 一样快的代码就是小菜一碟。","category":"page"},{"location":"manual/","page":"-","title":"-","text":"Julia features optional typing, multiple dispatch, and good performance, achieved using type inference and just-in-time (JIT) compilation, implemented using LLVM. It is multi-paradigm, combining features of imperative, functional, and object-oriented programming. Julia provides ease and expressiveness for high-level numerical computing, in the same way as languages such as R, MATLAB, and Python, but also supports general programming. To achieve this, Julia builds upon the lineage of mathematical programming languages, but also borrows much from popular dynamic languages, including Lisp, Perl, Python, Lua, and Ruby.","category":"page"},{"location":"manual/","page":"-","title":"-","text":"Julia 与传统动态语言最重要的区别是:","category":"page"},{"location":"manual/","page":"-","title":"-","text":"The core language imposes very little; Julia Base and the standard library are written in Julia itself, including primitive operations like integer arithmetic\nA rich language of types for constructing and describing objects, that can also optionally be used to make type declarations\nThe ability to define function behavior across many combinations of argument types via multiple dispatch\nAutomatic generation of efficient, specialized code for different argument types\nGood performance, approaching that of statically-compiled languages like C","category":"page"},{"location":"manual/","page":"-","title":"-","text":"Although one sometimes speaks of dynamic languages as being \"typeless\", they are definitely not: every object, whether primitive or user-defined, has a type. The lack of type declarations in most dynamic languages, however, means that one cannot instruct the compiler about the types of values, and often cannot explicitly talk about types at all. In static languages, on the other hand, while one can – and usually must – annotate types for the compiler, types exist only at compile time and cannot be manipulated or expressed at run time. In Julia, types are themselves run-time objects, and can also be used to convey information to the compiler.","category":"page"},{"location":"manual/","page":"-","title":"-","text":"While the casual programmer need not explicitly use types or multiple dispatch, they are the core unifying features of Julia: functions are defined on different combinations of argument types, and applied by dispatching to the most specific matching definition. This model is a good fit for mathematical programming, where it is unnatural for the first argument to \"own\" an operation as in traditional object-oriented dispatch. Operators are just functions with special notation – to extend addition to new user-defined data types, you define new methods for the + function. Existing code then seamlessly applies to the new data types.","category":"page"},{"location":"manual/","page":"-","title":"-","text":"Partly because of run-time type inference (augmented by optional type annotations), and partly because of a strong focus on performance from the inception of the project, Julia's computational efficiency exceeds that of other dynamic languages, and even rivals that of statically-compiled languages. For large scale numerical problems, speed always has been, continues to be, and probably always will be crucial: the amount of data being processed has easily kept pace with Moore's Law over the past decades.","category":"page"},{"location":"manual/","page":"-","title":"-","text":"Julia aims to create an unprecedented combination of ease-of-use, power, and efficiency in a single language. In addition to the above, some advantages of Julia over comparable systems include:","category":"page"},{"location":"manual/","page":"-","title":"-","text":"Free and open source (MIT licensed)\nUser-defined types are as fast and compact as built-ins\nNo need to vectorize code for performance; devectorized code is fast\nDesigned for parallelism and distributed computation\nLightweight \"green\" threading (coroutines)\nUnobtrusive yet powerful type system\nElegant and extensible conversions and promotions for numeric and other types\nEfficient support for Unicode, including but not limited to UTF-8\nCall C functions directly (no wrappers or special APIs needed)\nPowerful shell-like capabilities for managing other processes\nLisp-like macros and other metaprogramming facilities","category":"page"},{"location":"manual/control-flow/#流程控制","page":"流程控制","title":"流程控制","text":"","category":"section"},{"location":"manual/control-flow/","page":"流程控制","title":"流程控制","text":"Julia 提供了大量的流程控制构件:","category":"page"},{"location":"manual/control-flow/","page":"流程控制","title":"流程控制","text":"复合表达式:begin 和 ;。\n条件表达式:if-elseif-else 和 ?: (三元运算符)。\n短路求值:逻辑运算符 &&(与)和 ||(或),以及链式比较。\n重复执行:循环:while 和 for。\n异常处理:try-catch、error 和 throw。\nTask(协程):yieldto。","category":"page"},{"location":"manual/control-flow/","page":"流程控制","title":"流程控制","text":"前五个流程控制机制是高级编程语言的标准。Task 不是那么的标准:它提供了非局部的流程控制,这使得在暂时挂起的计算任务之间进行切换成为可能。这是一个功能强大的构件:Julia 中的异常处理和协同多任务都是通过 Task 实现的。虽然日常编程并不需要直接使用 Task,但某些问题用 Task 处理会更加简单。","category":"page"},{"location":"manual/control-flow/#man-compound-expressions","page":"流程控制","title":"复合表达式","text":"","category":"section"},{"location":"manual/control-flow/","page":"流程控制","title":"流程控制","text":"有时一个表达式能够有序地计算若干子表达式,并返回最后一个子表达式的值作为它的值是很方便的。Julia 有两个组件来完成这个: begin 代码块 和 ; 链。这两个复合表达式组件的值都是最后一个子表达式的值。下面是一个 begin 代码块的例子:","category":"page"},{"location":"manual/control-flow/","page":"流程控制","title":"流程控制","text":"julia> z = begin\n x = 1\n y = 2\n x + y\n end\n3","category":"page"},{"location":"manual/control-flow/","page":"流程控制","title":"流程控制","text":"因为这些是非常简短的表达式,它们可以简单地被放到一行里,这也是 ; 链的由来:","category":"page"},{"location":"manual/control-flow/","page":"流程控制","title":"流程控制","text":"julia> z = (x = 1; y = 2; x + y)\n3","category":"page"},{"location":"manual/control-flow/","page":"流程控制","title":"流程控制","text":"这个语法在定义简洁的单行函数的时候特别有用,参见函数。尽管很典型,但是并不要求 begin 代码块是多行的,或者 ; 链是单行的:","category":"page"},{"location":"manual/control-flow/","page":"流程控制","title":"流程控制","text":"julia> begin x = 1; y = 2; x + y end\n3\n\njulia> (x = 1;\n y = 2;\n x + y)\n3","category":"page"},{"location":"manual/control-flow/#man-conditional-evaluation","page":"流程控制","title":"条件表达式","text":"","category":"section"},{"location":"manual/control-flow/","page":"流程控制","title":"流程控制","text":"条件表达式(Conditional evaluation)可以根据布尔表达式的值,让部分代码被执行或者不被执行。下面是对 if-elseif-else 条件语法的分析:","category":"page"},{"location":"manual/control-flow/","page":"流程控制","title":"流程控制","text":"if x < y\n println(\"x is less than y\")\nelseif x > y\n println(\"x is greater than y\")\nelse\n println(\"x is equal to y\")\nend","category":"page"},{"location":"manual/control-flow/","page":"流程控制","title":"流程控制","text":"如果表达式 x < y 是 true,那么对应的代码块会被执行;否则判断条件表达式 x > y,如果它是 true,则执行对应的代码块;如果没有表达式是 true,则执行 else 代码块。下面是一个例子:","category":"page"},{"location":"manual/control-flow/","page":"流程控制","title":"流程控制","text":"julia> function test(x, y)\n if x < y\n println(\"x is less than y\")\n elseif x > y\n println(\"x is greater than y\")\n else\n println(\"x is equal to y\")\n end\n end\ntest (generic function with 1 method)\n\njulia> test(1, 2)\nx is less than y\n\njulia> test(2, 1)\nx is greater than y\n\njulia> test(1, 1)\nx is equal to y","category":"page"},{"location":"manual/control-flow/","page":"流程控制","title":"流程控制","text":"elseif 和 else 代码块是可选的,并且可以使用任意多个 elseif 代码块。 if-elseif-else 组件中的第一个条件表达式为 true 时,其他条件表达式才会被执行,当对应的代码块被执行后,其余的表达式或者代码块将不会被执行。","category":"page"},{"location":"manual/control-flow/","page":"流程控制","title":"流程控制","text":"if 代码块是\"有渗漏的\",也就是说它们不会引入局部作用域。这意味着在 if 语句中新定义的变量依然可以在 if 代码块之后使用,尽管这些变量没有在 if 语句之前定义过。所以,我们可以将上面的 test 函数定义为","category":"page"},{"location":"manual/control-flow/","page":"流程控制","title":"流程控制","text":"julia> function test(x,y)\n if x < y\n relation = \"less than\"\n elseif x == y\n relation = \"equal to\"\n else\n relation = \"greater than\"\n end\n println(\"x is \", relation, \" y.\")\n end\ntest (generic function with 1 method)\n\njulia> test(2, 1)\nx is greater than y.","category":"page"},{"location":"manual/control-flow/","page":"流程控制","title":"流程控制","text":"变量 relation 是在 if 代码块内部声明的,但可以在外部使用。然而,在利用这种行为的时候,要保证变量在所有的分支下都进行了定义。对上述函数做如下修改会导致运行时错误","category":"page"},{"location":"manual/control-flow/","page":"流程控制","title":"流程控制","text":"julia> function test(x,y)\n if x < y\n relation = \"less than\"\n elseif x == y\n relation = \"equal to\"\n end\n println(\"x is \", relation, \" y.\")\n end\ntest (generic function with 1 method)\n\njulia> test(1,2)\nx is less than y.\n\njulia> test(2,1)\nERROR: UndefVarError: relation not defined\nStacktrace:\n [1] test(::Int64, ::Int64) at ./none:7","category":"page"},{"location":"manual/control-flow/","page":"流程控制","title":"流程控制","text":"if 代码块也会返回一个值,这可能对于一些从其他语言转过来的用户来说不是很直观。 这个返回值就是被执行的分支中最后一个被执行的语句的返回值。 所以","category":"page"},{"location":"manual/control-flow/","page":"流程控制","title":"流程控制","text":"julia> x = 3\n3\n\njulia> if x > 0\n \"positive!\"\n else\n \"negative...\"\n end\n\"positive!\"","category":"page"},{"location":"manual/control-flow/","page":"流程控制","title":"流程控制","text":"需要注意的是,在 Julia 中,经常会用短路求值来表示非常短的条件表达式(单行),这会在下一节中介绍。","category":"page"},{"location":"manual/control-flow/","page":"流程控制","title":"流程控制","text":"与 C, MATLAB, Perl, Python,以及 Ruby 不同,但跟 Java,还有一些别的严谨的类型语言类似:一个条件表达式的值如果不是 true 或者 false 的话,会返回错误:","category":"page"},{"location":"manual/control-flow/","page":"流程控制","title":"流程控制","text":"julia> if 1\n println(\"true\")\n end\nERROR: TypeError: non-boolean (Int64) used in boolean context","category":"page"},{"location":"manual/control-flow/","page":"流程控制","title":"流程控制","text":"这个错误是说,条件判断结果的类型:Int64 是错的,而不是期望的 Bool。","category":"page"},{"location":"manual/control-flow/","page":"流程控制","title":"流程控制","text":"所谓的 \"三元运算符\", ?:,很类似 if-elseif-else 语法,它用于选择性获取单个表达式的值,而不是选择性执行大段的代码块。它因在很多语言中是唯一一个有三个操作数的运算符而得名:","category":"page"},{"location":"manual/control-flow/","page":"流程控制","title":"流程控制","text":"a ? b : c","category":"page"},{"location":"manual/control-flow/","page":"流程控制","title":"流程控制","text":"在 ? 之前的表达式 a, 是一个条件表达式,如果条件 a 是 true,三元运算符计算在 : 之前的表达式 b;如果条件 a 是 false,则执行 : 后面的表达式 c。注意,? 和 : 旁边的空格是强制的,像 a?b:c 这种表达式不是一个有效的三元表达式(但在? 和 : 之后的换行是允许的)。","category":"page"},{"location":"manual/control-flow/","page":"流程控制","title":"流程控制","text":"理解这种行为的最简单方式是看一个实际的例子。在前一个例子中,虽然在三个分支中都有调用 println,但实质上是选择打印哪一个字符串。在这种情况下,我们可以用三元运算符更紧凑地改写。为了简明,我们先尝试只有两个分支的版本:","category":"page"},{"location":"manual/control-flow/","page":"流程控制","title":"流程控制","text":"julia> x = 1; y = 2;\n\njulia> println(x < y ? \"less than\" : \"not less than\")\nless than\n\njulia> x = 1; y = 0;\n\njulia> println(x < y ? \"less than\" : \"not less than\")\nnot less than","category":"page"},{"location":"manual/control-flow/","page":"流程控制","title":"流程控制","text":"如果表达式 x < y 为真,整个三元运算符会执行字符串 \"less than\",否则执行字符串 \"not less than\"。原本的三个分支的例子需要链式嵌套使用三元运算符:","category":"page"},{"location":"manual/control-flow/","page":"流程控制","title":"流程控制","text":"julia> test(x, y) = println(x < y ? \"x is less than y\" :\n x > y ? \"x is greater than y\" : \"x is equal to y\")\ntest (generic function with 1 method)\n\njulia> test(1, 2)\nx is less than y\n\njulia> test(2, 1)\nx is greater than y\n\njulia> test(1, 1)\nx is equal to y","category":"page"},{"location":"manual/control-flow/","page":"流程控制","title":"流程控制","text":"为了方便链式传值,运算符从右到左连接到一起。","category":"page"},{"location":"manual/control-flow/","page":"流程控制","title":"流程控制","text":"重要地是,与 if-elseif-else 类似,: 之前和之后的表达式只有在条件表达式为 true 或者 false 时才会被相应地执行:","category":"page"},{"location":"manual/control-flow/","page":"流程控制","title":"流程控制","text":"julia> v(x) = (println(x); x)\nv (generic function with 1 method)\n\njulia> 1 < 2 ? v(\"yes\") : v(\"no\")\nyes\n\"yes\"\n\njulia> 1 > 2 ? v(\"yes\") : v(\"no\")\nno\n\"no\"","category":"page"},{"location":"manual/control-flow/#短路求值","page":"流程控制","title":"短路求值","text":"","category":"section"},{"location":"manual/control-flow/","page":"流程控制","title":"流程控制","text":"Julia 中的 && 和 || 运算符分别对应于逻辑“与”和“或”操作,并通常都这样使用。 但是,它们具有 逻辑短路 的特殊性质:不一定评估其第二个参数,下面会详细介绍。 (也有按位 & 和 | 运算符可用作逻辑“与”和“或”的无短路行为,但要注意 & 和 | 的评估时的优先级高于 && 和 || 。)","category":"page"},{"location":"manual/control-flow/","page":"流程控制","title":"流程控制","text":"短路求值与条件求值非常相似。 这种行为在大多数具有 && 和 || 布尔运算符的命令式编程语言中都可以找到:在一系列由这些运算符连接的布尔表达式中,为了得到整个链的最终布尔值,仅仅只有最小数量的表达式被计算。 一些语言(如 Python)将它们称为and(&&)和or(||)。 更准确地说,这意味着:","category":"page"},{"location":"manual/control-flow/","page":"流程控制","title":"流程控制","text":"在表达式 a && b 中,子表达式 b 仅当 a 为 true 的时候才会被执行。\n在表达式 a || b 中,子表达式 b 仅在 a 为 false 的时候才会被执行。","category":"page"},{"location":"manual/control-flow/","page":"流程控制","title":"流程控制","text":"这里的原因是:如果 a 是 false,那么无论 b 的值是多少,a && b 一定是 false。同理,如果 a 是 true,那么无论 b 的值是多少,a || b 的值一定是 true。&& 和 || 都依赖于右边,但是 && 比 || 有更高的优先级。我们可以简单地测试一下这个行为:","category":"page"},{"location":"manual/control-flow/","page":"流程控制","title":"流程控制","text":"julia> t(x) = (println(x); true)\nt (generic function with 1 method)\n\njulia> f(x) = (println(x); false)\nf (generic function with 1 method)\n\njulia> t(1) && t(2)\n1\n2\ntrue\n\njulia> t(1) && f(2)\n1\n2\nfalse\n\njulia> f(1) && t(2)\n1\nfalse\n\njulia> f(1) && f(2)\n1\nfalse\n\njulia> t(1) || t(2)\n1\ntrue\n\njulia> t(1) || f(2)\n1\ntrue\n\njulia> f(1) || t(2)\n1\n2\ntrue\n\njulia> f(1) || f(2)\n1\n2\nfalse","category":"page"},{"location":"manual/control-flow/","page":"流程控制","title":"流程控制","text":"你可以用同样的方式测试不同 && 和 || 运算符的组合条件下的关联和优先级。","category":"page"},{"location":"manual/control-flow/","page":"流程控制","title":"流程控制","text":"这种行为在 Julia 中经常被用来作为简短 if 语句的替代。 可以用 && (可读为: and then )来替换 if end。 类似的, 可以用 || (可读为: or else )来替换 if ! end.","category":"page"},{"location":"manual/control-flow/","page":"流程控制","title":"流程控制","text":"例如,可以像这样定义递归阶乘:","category":"page"},{"location":"manual/control-flow/","page":"流程控制","title":"流程控制","text":"julia> function fact(n::Int)\n n >= 0 || error(\"n must be non-negative\")\n n == 0 && return 1\n n * fact(n-1)\n end\nfact (generic function with 1 method)\n\njulia> fact(5)\n120\n\njulia> fact(0)\n1\n\njulia> fact(-1)\nERROR: n must be non-negative\nStacktrace:\n [1] error at ./error.jl:33 [inlined]\n [2] fact(::Int64) at ./none:2\n [3] top-level scope","category":"page"},{"location":"manual/control-flow/","page":"流程控制","title":"流程控制","text":"无短路求值的布尔运算可以用位布尔运算符来完成,见数学运算和初等函数:& 和 |。这些是普通的函数,同时也刚好支持中缀运算符语法,但总是会计算它们的所有参数:","category":"page"},{"location":"manual/control-flow/","page":"流程控制","title":"流程控制","text":"julia> f(1) & t(2)\n1\n2\nfalse\n\njulia> t(1) | t(2)\n1\n2\ntrue","category":"page"},{"location":"manual/control-flow/","page":"流程控制","title":"流程控制","text":"与 if, elseif 或者三元运算符中的条件表达式相同,&& 或者 || 的操作数必须是布尔值(true 或者 false)。在链式嵌套的条件表达式中, 除最后一项外,使用非布尔值会导致错误:","category":"page"},{"location":"manual/control-flow/","page":"流程控制","title":"流程控制","text":"julia> 1 && true\nERROR: TypeError: non-boolean (Int64) used in boolean context","category":"page"},{"location":"manual/control-flow/","page":"流程控制","title":"流程控制","text":"但在链的末尾允许使用任意类型的表达式,此表达式会根据前面的条件被执行并返回:","category":"page"},{"location":"manual/control-flow/","page":"流程控制","title":"流程控制","text":"julia> true && (x = (1, 2, 3))\n(1, 2, 3)\n\njulia> false && (x = (1, 2, 3))\nfalse","category":"page"},{"location":"manual/control-flow/#man-loops","page":"流程控制","title":"重复执行:循环","text":"","category":"section"},{"location":"manual/control-flow/","page":"流程控制","title":"流程控制","text":"有两个用于重复执行表达式的组件:while 循环和 for 循环。下面是一个 while 循环的例子:","category":"page"},{"location":"manual/control-flow/","page":"流程控制","title":"流程控制","text":"julia> i = 1;\n\njulia> while i <= 5\n println(i)\n global i += 1\n end\n1\n2\n3\n4\n5","category":"page"},{"location":"manual/control-flow/","page":"流程控制","title":"流程控制","text":"while 循环会执行条件表达式(例子中为 i <= 5),只要它为 true,就一直执行while 循环的主体部分。当 while 循环第一次执行时,如果条件表达式为 false,那么主体代码就一次也不会被执行。","category":"page"},{"location":"manual/control-flow/","page":"流程控制","title":"流程控制","text":"for 循环使得常见的重复执行代码写起来更容易。 像之前 while 循环中用到的向上和向下计数是可以用 for 循环更简明地表达:","category":"page"},{"location":"manual/control-flow/","page":"流程控制","title":"流程控制","text":"julia> for i = 1:5\n println(i)\n end\n1\n2\n3\n4\n5","category":"page"},{"location":"manual/control-flow/","page":"流程控制","title":"流程控制","text":"这里的 1:5 是一个范围对象,代表数字 1, 2, 3, 4, 5 的序列。for 循环在这些值之中迭代,对每一个变量 i 进行赋值。for 循环与之前 while 循环的一个非常重要区别是作用域,即变量的可见性。如果变量 i 没有在另一个作用域里引入,在 for 循环内,它就只在 for 循环内部可见,在外部和后面均不可见。你需要一个新的交互式会话实例或者一个新的变量名来测试这个特性:","category":"page"},{"location":"manual/control-flow/","page":"流程控制","title":"流程控制","text":"julia> for j = 1:5\n println(j)\n end\n1\n2\n3\n4\n5\n\njulia> j\nERROR: UndefVarError: j not defined","category":"page"},{"location":"manual/control-flow/","page":"流程控制","title":"流程控制","text":"参见变量作用域中对变量作用域的详细解释以及它在 Julia 中是如何工作的。","category":"page"},{"location":"manual/control-flow/","page":"流程控制","title":"流程控制","text":"一般来说,for 循环组件可以用于迭代任一个容器。在这种情况下,相比 =,另外的(但完全相同)关键字 in 或者 ∈ 则更常用,因为它使得代码更清晰:","category":"page"},{"location":"manual/control-flow/","page":"流程控制","title":"流程控制","text":"julia> for i in [1,4,0]\n println(i)\n end\n1\n4\n0\n\njulia> for s ∈ [\"foo\",\"bar\",\"baz\"]\n println(s)\n end\nfoo\nbar\nbaz","category":"page"},{"location":"manual/control-flow/","page":"流程控制","title":"流程控制","text":"在手册后面的章节中会介绍和讨论各种不同的迭代容器(比如,多维数组)。","category":"page"},{"location":"manual/control-flow/","page":"流程控制","title":"流程控制","text":"为了方便,我们可能会在测试条件不成立之前终止一个 while 循环,或者在访问到迭代对象的结尾之前停止一个 for 循环,这可以用关键字 break 来完成:","category":"page"},{"location":"manual/control-flow/","page":"流程控制","title":"流程控制","text":"julia> i = 1;\n\njulia> while true\n println(i)\n if i >= 5\n break\n end\n global i += 1\n end\n1\n2\n3\n4\n5\n\njulia> for j = 1:1000\n println(j)\n if j >= 5\n break\n end\n end\n1\n2\n3\n4\n5","category":"page"},{"location":"manual/control-flow/","page":"流程控制","title":"流程控制","text":"没有关键字 break 的话,上面的 while 循环永远不会自己结束,而 for 循环会迭代到 1000,这些循环都可以使用 break 来提前结束。","category":"page"},{"location":"manual/control-flow/","page":"流程控制","title":"流程控制","text":"在某些场景下,需要直接结束此次迭代,并立刻进入下次迭代,continue 关键字可以用来完成此功能:","category":"page"},{"location":"manual/control-flow/","page":"流程控制","title":"流程控制","text":"julia> for i = 1:10\n if i % 3 != 0\n continue\n end\n println(i)\n end\n3\n6\n9","category":"page"},{"location":"manual/control-flow/","page":"流程控制","title":"流程控制","text":"这是一个有点做作的例子,因为我们可以通过否定这个条件,把 println 调用放到 if 代码块里来更简洁的实现同样的功能。在实际应用中,在 continue 后面还会有更多的代码要运行,并且调用 continue 的地方可能会有多个。","category":"page"},{"location":"manual/control-flow/","page":"流程控制","title":"流程控制","text":"多个嵌套的 for 循环可以合并到一个外部循环,可以用来创建其迭代对象的笛卡尔积:","category":"page"},{"location":"manual/control-flow/","page":"流程控制","title":"流程控制","text":"julia> for i = 1:2, j = 3:4\n println((i, j))\n end\n(1, 3)\n(1, 4)\n(2, 3)\n(2, 4)","category":"page"},{"location":"manual/control-flow/","page":"流程控制","title":"流程控制","text":"有了这个语法,迭代变量依然可以正常使用循环变量来进行索引,例如 for i = 1:n, j = 1:i 是合法的,但是在一个循环里面使用 break 语句则会跳出整个嵌套循环,不仅仅是内层循环。每次内层循环运行的时候,变量(i 和 j)会被赋值为他们当前的迭代变量值。所以对 i 的赋值对于接下来的迭代是不可见的:","category":"page"},{"location":"manual/control-flow/","page":"流程控制","title":"流程控制","text":"julia> for i = 1:2, j = 3:4\n println((i, j))\n i = 0\n end\n(1, 3)\n(1, 4)\n(2, 3)\n(2, 4)","category":"page"},{"location":"manual/control-flow/","page":"流程控制","title":"流程控制","text":"如果这个例子给每个变量一个关键字 for 来重写,那么输出会不一样:第二个和第四个变量包含 0。","category":"page"},{"location":"manual/control-flow/","page":"流程控制","title":"流程控制","text":"可以使用 zip 在单个 for 循环中同时迭代多个容器:","category":"page"},{"location":"manual/control-flow/","page":"流程控制","title":"流程控制","text":"julia> for (j, k) in zip([1 2 3], [4 5 6 7])\n println((j,k))\n end\n(1, 4)\n(2, 5)\n(3, 6)","category":"page"},{"location":"manual/control-flow/","page":"流程控制","title":"流程控制","text":"使用 zip 将创建一个迭代器,它是一个包含传递给它的容器的子迭代器的元组。 zip 迭代器将按顺序迭代所有子迭代器,在 for 循环的第 i 次迭代中选择每个子迭代器的第 i 个元素。 一旦任何子迭代器用完,for 循环就会停止。","category":"page"},{"location":"manual/control-flow/#异常处理","page":"流程控制","title":"异常处理","text":"","category":"section"},{"location":"manual/control-flow/","page":"流程控制","title":"流程控制","text":"当一个意外条件发生时,一个函数可能无法向调用者返回一个合理的值。在这种情况下,最好让意外条件终止程序并打印出调试的错误信息,或者根据程序员预先提供的异常处理代码来采取恰当的措施。","category":"page"},{"location":"manual/control-flow/#内置的-Exception","page":"流程控制","title":"内置的 Exception","text":"","category":"section"},{"location":"manual/control-flow/","page":"流程控制","title":"流程控制","text":"当一个意外的情况发生时,会抛出 Exception。下面列出的内置 Exception 都会中断正常的控制流程。","category":"page"},{"location":"manual/control-flow/","page":"流程控制","title":"流程控制","text":"Exception\nArgumentError\nBoundsError\nCompositeException\nDimensionMismatch\nDivideError\nDomainError\nEOFError\nErrorException\nInexactError\nInitError\nInterruptException\nInvalidStateException\nKeyError\nLoadError\nOutOfMemoryError\nReadOnlyMemoryError\nRemoteException\nMethodError\nOverflowError\nMeta.ParseError\nSystemError\nTypeError\nUndefRefError\nUndefVarError\nStringIndexError","category":"page"},{"location":"manual/control-flow/","page":"流程控制","title":"流程控制","text":"例如,当输入参数为负实数时,sqrt 函数会抛出一个 DomainError :","category":"page"},{"location":"manual/control-flow/","page":"流程控制","title":"流程控制","text":"julia> sqrt(-1)\nERROR: DomainError with -1.0:\nsqrt will only return a complex result if called with a complex argument. Try sqrt(Complex(x)).\nStacktrace:\n[...]","category":"page"},{"location":"manual/control-flow/","page":"流程控制","title":"流程控制","text":"你可能需要根据下面的方式来定义你自己的异常:","category":"page"},{"location":"manual/control-flow/","page":"流程控制","title":"流程控制","text":"julia> struct MyCustomException <: Exception end","category":"page"},{"location":"manual/control-flow/#[throw](@ref)-函数","page":"流程控制","title":"throw 函数","text":"","category":"section"},{"location":"manual/control-flow/","page":"流程控制","title":"流程控制","text":"我们可以用 throw 显式地创建异常。例如,若一个函数只对非负数有定义,当输入参数是负数的时候,可以用 throw 抛出一个 DomainError。","category":"page"},{"location":"manual/control-flow/","page":"流程控制","title":"流程控制","text":"julia> f(x) = x>=0 ? exp(-x) : throw(DomainError(x, \"argument must be nonnegative\"))\nf (generic function with 1 method)\n\njulia> f(1)\n0.36787944117144233\n\njulia> f(-1)\nERROR: DomainError with -1:\nargument must be nonnegative\nStacktrace:\n [1] f(::Int64) at ./none:1","category":"page"},{"location":"manual/control-flow/","page":"流程控制","title":"流程控制","text":"注意 DomainError 后面不接括号的话不是一个异常,而是一个异常类型。我们需要调用它来获得一个 Exception 对象:","category":"page"},{"location":"manual/control-flow/","page":"流程控制","title":"流程控制","text":"julia> typeof(DomainError(nothing)) <: Exception\ntrue\n\njulia> typeof(DomainError) <: Exception\nfalse","category":"page"},{"location":"manual/control-flow/","page":"流程控制","title":"流程控制","text":"另外,一些异常类型会接受一个或多个参数来进行错误报告:","category":"page"},{"location":"manual/control-flow/","page":"流程控制","title":"流程控制","text":"julia> throw(UndefVarError(:x))\nERROR: UndefVarError: x not defined","category":"page"},{"location":"manual/control-flow/","page":"流程控制","title":"流程控制","text":"我们可以仿照 UndefVarError 的写法,用自定义异常类型来轻松实现这个机制:","category":"page"},{"location":"manual/control-flow/","page":"流程控制","title":"流程控制","text":"julia> struct MyUndefVarError <: Exception\n var::Symbol\n end\n\njulia> Base.showerror(io::IO, e::MyUndefVarError) = print(io, e.var, \" not defined\")","category":"page"},{"location":"manual/control-flow/","page":"流程控制","title":"流程控制","text":"note: Note\n错误信息的第一个单词最好用小写。例如:size(A) == size(B) || throw(DimensionMismatch(\"size of A not equal to size of B\"))就比size(A) == size(B) || throw(DimensionMismatch(\"Size of A not equal to size of B\")).更好。但是,有时保留大写首字母是有意义的,例如函数的参数就是大写字母时:size(A,1) == size(B,2) || throw(DimensionMismatch(\"A has first dimension...\")).","category":"page"},{"location":"manual/control-flow/#错误","page":"流程控制","title":"错误","text":"","category":"section"},{"location":"manual/control-flow/","page":"流程控制","title":"流程控制","text":"我们可以用 error 函数生成一个 ErrorException 来中断正常的控制流程。","category":"page"},{"location":"manual/control-flow/","page":"流程控制","title":"流程控制","text":"假设我们希望在计算负数的平方根时让程序立即停止执行。为了实现它,我们可以定义一个挑剔的 sqrt 函数,当它的参数是负数时,产生一个错误:","category":"page"},{"location":"manual/control-flow/","page":"流程控制","title":"流程控制","text":"julia> fussy_sqrt(x) = x >= 0 ? sqrt(x) : error(\"negative x not allowed\")\nfussy_sqrt (generic function with 1 method)\n\njulia> fussy_sqrt(2)\n1.4142135623730951\n\njulia> fussy_sqrt(-1)\nERROR: negative x not allowed\nStacktrace:\n [1] error at ./error.jl:33 [inlined]\n [2] fussy_sqrt(::Int64) at ./none:1\n [3] top-level scope","category":"page"},{"location":"manual/control-flow/","page":"流程控制","title":"流程控制","text":"如果另一个函数调用 fussy_sqrt 和一个负数, 它会立马返回, 在交互会话中显示错误信息,而不会继续执行调用的函数:","category":"page"},{"location":"manual/control-flow/","page":"流程控制","title":"流程控制","text":"julia> function verbose_fussy_sqrt(x)\n println(\"before fussy_sqrt\")\n r = fussy_sqrt(x)\n println(\"after fussy_sqrt\")\n return r\n end\nverbose_fussy_sqrt (generic function with 1 method)\n\njulia> verbose_fussy_sqrt(2)\nbefore fussy_sqrt\nafter fussy_sqrt\n1.4142135623730951\n\njulia> verbose_fussy_sqrt(-1)\nbefore fussy_sqrt\nERROR: negative x not allowed\nStacktrace:\n [1] error at ./error.jl:33 [inlined]\n [2] fussy_sqrt at ./none:1 [inlined]\n [3] verbose_fussy_sqrt(::Int64) at ./none:3\n [4] top-level scope","category":"page"},{"location":"manual/control-flow/#try/catch-语句","page":"流程控制","title":"try/catch 语句","text":"","category":"section"},{"location":"manual/control-flow/","page":"流程控制","title":"流程控制","text":"通过 try / catch 语句,可以测试 Exception 并 优雅处理可能会破坏应用程序的事情。 例如, 在下面的代码中,平方根函数会引发异常。 通过 在其周围放置 try / catch 块可以缓解。 您可以选择如何 处理此异常,无论是记录它,返回占位符值还是 就像下面仅打印一句话。 要注意的是 在决定如何处理异常时,使用try / catch 块 比使用条件分支处理要慢得多。 以下是使用try / catch 块处理异常的更多示例:","category":"page"},{"location":"manual/control-flow/","page":"流程控制","title":"流程控制","text":"julia> try\nsqrt(\"ten\")\ncatch e\nprintln(\"You should have entered a numeric value\")\nend\nYou should have entered a numeric value","category":"page"},{"location":"manual/control-flow/","page":"流程控制","title":"流程控制","text":"try/catch 语句允许保存 Exception 到一个变量中。在下面这个做作的例子中,如果 x 是可索引的,则计算 x 的第二项的平方根,否则就假设 x 是一个实数,并返回它的平方根:","category":"page"},{"location":"manual/control-flow/","page":"流程控制","title":"流程控制","text":"julia> sqrt_second(x) = try\n sqrt(x[2])\n catch y\n if isa(y, DomainError)\n sqrt(complex(x[2], 0))\n elseif isa(y, BoundsError)\n sqrt(x)\n end\n end\nsqrt_second (generic function with 1 method)\n\njulia> sqrt_second([1 4])\n2.0\n\njulia> sqrt_second([1 -4])\n0.0 + 2.0im\n\njulia> sqrt_second(9)\n3.0\n\njulia> sqrt_second(-9)\nERROR: DomainError with -9.0:\nsqrt will only return a complex result if called with a complex argument. Try sqrt(Complex(x)).\nStacktrace:\n[...]","category":"page"},{"location":"manual/control-flow/","page":"流程控制","title":"流程控制","text":"注意 catch 后面的字符会被一直认为是异常的名字,所以在写 try/catch 单行表达式时,需要特别小心。下面的代码不会在错误的情况下返回 x 的值:","category":"page"},{"location":"manual/control-flow/","page":"流程控制","title":"流程控制","text":"try bad() catch x end","category":"page"},{"location":"manual/control-flow/","page":"流程控制","title":"流程控制","text":"正确的做法是在 catch 后添加一个分号或者直接换行:","category":"page"},{"location":"manual/control-flow/","page":"流程控制","title":"流程控制","text":"try bad() catch; x end\n\ntry bad()\ncatch\n x\nend","category":"page"},{"location":"manual/control-flow/","page":"流程控制","title":"流程控制","text":"try/catch 结构的强大之处在于能够立即将深度嵌套的计算展开到调用函数堆栈中的更高级别。 在某些情况下,没有发生错误,但需要能够展开堆栈并将值传递到更高级别。 Julia 提供了 rethrow、backtrace、catch_backtrace 和 current_exceptions 函数来进行更高级的错误处理。","category":"page"},{"location":"manual/control-flow/#finally-子句","page":"流程控制","title":"finally 子句","text":"","category":"section"},{"location":"manual/control-flow/","page":"流程控制","title":"流程控制","text":"在进行状态改变或者使用类似文件的资源的编程时,经常需要在代码结束的时候进行必要的清理工作(比如关闭文件)。由于异常会使得部分代码块在正常结束之前退出,所以可能会让上述工作变得复杂。finally 关键字提供了一种方式,无论代码块是如何退出的,都能够让代码块在退出时运行某段代码。","category":"page"},{"location":"manual/control-flow/","page":"流程控制","title":"流程控制","text":"这里是一个确保一个打开的文件被关闭的例子:","category":"page"},{"location":"manual/control-flow/","page":"流程控制","title":"流程控制","text":"f = open(\"file\")\ntry\n # operate on file f\nfinally\n close(f)\nend","category":"page"},{"location":"manual/control-flow/","page":"流程控制","title":"流程控制","text":"当控制流离开 try 代码块(例如,遇到 return,或者正常结束),close(f) 就会被执行。如果 try 代码块由于异常退出,这个异常会继续传递。catch 代码块可以和 try 还有 finally 配合使用。这时 finally 代码块会在 catch 处理错误之后才运行。","category":"page"},{"location":"manual/control-flow/#man-tasks","page":"流程控制","title":" Tasks 任务(或协程)","text":"","category":"section"},{"location":"manual/control-flow/","page":"流程控制","title":"流程控制","text":"Task 是一种允许计算以更灵活的方式被中断或者恢复的流程控制特性。 我们提及它只是为了说明的完整性;详细的介绍参见:异步编程。","category":"page"},{"location":"devdocs/meta/#Talking-to-the-compiler-(the-:meta-mechanism)","page":"Talking to the compiler (the :meta mechanism)","title":"Talking to the compiler (the :meta mechanism)","text":"","category":"section"},{"location":"devdocs/meta/","page":"Talking to the compiler (the :meta mechanism)","title":"Talking to the compiler (the :meta mechanism)","text":"In some circumstances, one might wish to provide hints or instructions that a given block of code has special properties: you might always want to inline it, or you might want to turn on special compiler optimization passes. Starting with version 0.4, Julia has a convention that these instructions can be placed inside a :meta expression, which is typically (but not necessarily) the first expression in the body of a function.","category":"page"},{"location":"devdocs/meta/","page":"Talking to the compiler (the :meta mechanism)","title":"Talking to the compiler (the :meta mechanism)","text":":meta expressions are created with macros. As an example, consider the implementation of the @inline macro:","category":"page"},{"location":"devdocs/meta/","page":"Talking to the compiler (the :meta mechanism)","title":"Talking to the compiler (the :meta mechanism)","text":"macro inline(ex)\n esc(isa(ex, Expr) ? pushmeta!(ex, :inline) : ex)\nend","category":"page"},{"location":"devdocs/meta/","page":"Talking to the compiler (the :meta mechanism)","title":"Talking to the compiler (the :meta mechanism)","text":"Here, ex is expected to be an expression defining a function. A statement like this:","category":"page"},{"location":"devdocs/meta/","page":"Talking to the compiler (the :meta mechanism)","title":"Talking to the compiler (the :meta mechanism)","text":"@inline function myfunction(x)\n x*(x+3)\nend","category":"page"},{"location":"devdocs/meta/","page":"Talking to the compiler (the :meta mechanism)","title":"Talking to the compiler (the :meta mechanism)","text":"gets turned into an expression like this:","category":"page"},{"location":"devdocs/meta/","page":"Talking to the compiler (the :meta mechanism)","title":"Talking to the compiler (the :meta mechanism)","text":"quote\n function myfunction(x)\n Expr(:meta, :inline)\n x*(x+3)\n end\nend","category":"page"},{"location":"devdocs/meta/","page":"Talking to the compiler (the :meta mechanism)","title":"Talking to the compiler (the :meta mechanism)","text":"Base.pushmeta!(ex, :symbol, args...) appends :symbol to the end of the :meta expression, creating a new :meta expression if necessary. If args is specified, a nested expression containing :symbol and these arguments is appended instead, which can be used to specify additional information.","category":"page"},{"location":"devdocs/meta/","page":"Talking to the compiler (the :meta mechanism)","title":"Talking to the compiler (the :meta mechanism)","text":"To use the metadata, you have to parse these :meta expressions. If your implementation can be performed within Julia, Base.popmeta! is very handy: Base.popmeta!(body, :symbol) will scan a function body expression (one without the function signature) for the first :meta expression containing :symbol, extract any arguments, and return a tuple (found::Bool, args::Array{Any}). If the metadata did not have any arguments, or :symbol was not found, the args array will be empty.","category":"page"},{"location":"devdocs/meta/","page":"Talking to the compiler (the :meta mechanism)","title":"Talking to the compiler (the :meta mechanism)","text":"Not yet provided is a convenient infrastructure for parsing :meta expressions from C++.","category":"page"},{"location":"devdocs/stdio/#printf()-and-stdio-in-the-Julia-runtime","page":"printf() and stdio in the Julia runtime","title":"printf() and stdio in the Julia runtime","text":"","category":"section"},{"location":"devdocs/stdio/#Libuv-wrappers-for-stdio","page":"printf() and stdio in the Julia runtime","title":"Libuv wrappers for stdio","text":"","category":"section"},{"location":"devdocs/stdio/","page":"printf() and stdio in the Julia runtime","title":"printf() and stdio in the Julia runtime","text":"julia.h defines libuv wrappers for the stdio.h streams:","category":"page"},{"location":"devdocs/stdio/","page":"printf() and stdio in the Julia runtime","title":"printf() and stdio in the Julia runtime","text":"uv_stream_t *JL_STDIN;\nuv_stream_t *JL_STDOUT;\nuv_stream_t *JL_STDERR;","category":"page"},{"location":"devdocs/stdio/","page":"printf() and stdio in the Julia runtime","title":"printf() and stdio in the Julia runtime","text":"... and corresponding output functions:","category":"page"},{"location":"devdocs/stdio/","page":"printf() and stdio in the Julia runtime","title":"printf() and stdio in the Julia runtime","text":"int jl_printf(uv_stream_t *s, const char *format, ...);\nint jl_vprintf(uv_stream_t *s, const char *format, va_list args);","category":"page"},{"location":"devdocs/stdio/","page":"printf() and stdio in the Julia runtime","title":"printf() and stdio in the Julia runtime","text":"These printf functions are used by the .c files in the src/ and cli/ directories wherever stdio is needed to ensure that output buffering is handled in a unified way.","category":"page"},{"location":"devdocs/stdio/","page":"printf() and stdio in the Julia runtime","title":"printf() and stdio in the Julia runtime","text":"In special cases, like signal handlers, where the full libuv infrastructure is too heavy, jl_safe_printf() can be used to write(2) directly to STDERR_FILENO:","category":"page"},{"location":"devdocs/stdio/","page":"printf() and stdio in the Julia runtime","title":"printf() and stdio in the Julia runtime","text":"void jl_safe_printf(const char *str, ...);","category":"page"},{"location":"devdocs/stdio/#Interface-between-JL_STD*-and-Julia-code","page":"printf() and stdio in the Julia runtime","title":"Interface between JL_STD* and Julia code","text":"","category":"section"},{"location":"devdocs/stdio/","page":"printf() and stdio in the Julia runtime","title":"printf() and stdio in the Julia runtime","text":"Base.stdin, Base.stdout and Base.stderr are bound to the JL_STD* libuv streams defined in the runtime.","category":"page"},{"location":"devdocs/stdio/","page":"printf() and stdio in the Julia runtime","title":"printf() and stdio in the Julia runtime","text":"Julia's __init__() function (in base/sysimg.jl) calls reinit_stdio() (in base/stream.jl) to create Julia objects for Base.stdin, Base.stdout and Base.stderr.","category":"page"},{"location":"devdocs/stdio/","page":"printf() and stdio in the Julia runtime","title":"printf() and stdio in the Julia runtime","text":"reinit_stdio() uses ccall to retrieve pointers to JL_STD* and calls jl_uv_handle_type() to inspect the type of each stream. It then creates a Julia Base.IOStream, Base.TTY or Base.PipeEndpoint object to represent each stream, e.g.:","category":"page"},{"location":"devdocs/stdio/","page":"printf() and stdio in the Julia runtime","title":"printf() and stdio in the Julia runtime","text":"$ julia -e 'println(typeof((stdin, stdout, stderr)))'\nTuple{Base.TTY,Base.TTY,Base.TTY}\n\n$ julia -e 'println(typeof((stdin, stdout, stderr)))' < /dev/null 2>/dev/null\nTuple{IOStream,Base.TTY,IOStream}\n\n$ echo hello | julia -e 'println(typeof((stdin, stdout, stderr)))' | cat\nTuple{Base.PipeEndpoint,Base.PipeEndpoint,Base.TTY}","category":"page"},{"location":"devdocs/stdio/","page":"printf() and stdio in the Julia runtime","title":"printf() and stdio in the Julia runtime","text":"The Base.read and Base.write methods for these streams use ccall to call libuv wrappers in src/jl_uv.c, e.g.:","category":"page"},{"location":"devdocs/stdio/","page":"printf() and stdio in the Julia runtime","title":"printf() and stdio in the Julia runtime","text":"stream.jl: function write(s::IO, p::Ptr, nb::Integer)\n -> ccall(:jl_uv_write, ...)\n jl_uv.c: -> int jl_uv_write(uv_stream_t *stream, ...)\n -> uv_write(uvw, stream, buf, ...)","category":"page"},{"location":"devdocs/stdio/#printf()-during-initialization","page":"printf() and stdio in the Julia runtime","title":"printf() during initialization","text":"","category":"section"},{"location":"devdocs/stdio/","page":"printf() and stdio in the Julia runtime","title":"printf() and stdio in the Julia runtime","text":"The libuv streams relied upon by jl_printf() etc., are not available until midway through initialization of the runtime (see init.c, init_stdio()). Error messages or warnings that need to be printed before this are routed to the standard C library fwrite() function by the following mechanism:","category":"page"},{"location":"devdocs/stdio/","page":"printf() and stdio in the Julia runtime","title":"printf() and stdio in the Julia runtime","text":"In sys.c, the JL_STD* stream pointers are statically initialized to integer constants: STD*_FILENO (0, 1 and 2). In jl_uv.c the jl_uv_puts() function checks its uv_stream_t* stream argument and calls fwrite() if stream is set to STDOUT_FILENO or STDERR_FILENO.","category":"page"},{"location":"devdocs/stdio/","page":"printf() and stdio in the Julia runtime","title":"printf() and stdio in the Julia runtime","text":"This allows for uniform use of jl_printf() throughout the runtime regardless of whether or not any particular piece of code is reachable before initialization is complete.","category":"page"},{"location":"devdocs/stdio/#Legacy-ios.c-library","page":"printf() and stdio in the Julia runtime","title":"Legacy ios.c library","text":"","category":"section"},{"location":"devdocs/stdio/","page":"printf() and stdio in the Julia runtime","title":"printf() and stdio in the Julia runtime","text":"The src/support/ios.c library is inherited from femtolisp. It provides cross-platform buffered file IO and in-memory temporary buffers.","category":"page"},{"location":"devdocs/stdio/","page":"printf() and stdio in the Julia runtime","title":"printf() and stdio in the Julia runtime","text":"ios.c is still used by:","category":"page"},{"location":"devdocs/stdio/","page":"printf() and stdio in the Julia runtime","title":"printf() and stdio in the Julia runtime","text":"src/flisp/*.c\nsrc/dump.c – for serialization file IO and for memory buffers.\nsrc/staticdata.c – for serialization file IO and for memory buffers.\nbase/iostream.jl – for file IO (see base/fs.jl for libuv equivalent).","category":"page"},{"location":"devdocs/stdio/","page":"printf() and stdio in the Julia runtime","title":"printf() and stdio in the Julia runtime","text":"Use of ios.c in these modules is mostly self-contained and separated from the libuv I/O system. However, there is one place where femtolisp calls through to jl_printf() with a legacy ios_t stream.","category":"page"},{"location":"devdocs/stdio/","page":"printf() and stdio in the Julia runtime","title":"printf() and stdio in the Julia runtime","text":"There is a hack in ios.h that makes the ios_t.bm field line up with the uv_stream_t.type and ensures that the values used for ios_t.bm to not overlap with valid UV_HANDLE_TYPE values. This allows uv_stream_t pointers to point to ios_t streams.","category":"page"},{"location":"devdocs/stdio/","page":"printf() and stdio in the Julia runtime","title":"printf() and stdio in the Julia runtime","text":"This is needed because jl_printf() caller jl_static_show() is passed an ios_t stream by femtolisp's fl_print() function. Julia's jl_uv_puts() function has special handling for this:","category":"page"},{"location":"devdocs/stdio/","page":"printf() and stdio in the Julia runtime","title":"printf() and stdio in the Julia runtime","text":"if (stream->type > UV_HANDLE_TYPE_MAX) {\n return ios_write((ios_t*)stream, str, n);\n}","category":"page"},{"location":"manual/getting-started/#man-getting-started","page":"入门","title":"入门","text":"","category":"section"},{"location":"manual/getting-started/","page":"入门","title":"入门","text":"无论是使用预编译好的二进制程序,还是自己从源码编译,安装 Julia 都是一件很简单的事情。 请按照 https://julialang.org/downloads/ 的提示来下载并安装 Julia。","category":"page"},{"location":"manual/getting-started/","page":"入门","title":"入门","text":"如果你是从下面的某一种语言切换到 Julia 的话,那么你应该首先阅读与这些语言有显著差异的那一部分 MATLAB, R, Python, C/C++ or Common Lisp. 这将帮助你避免一些常见的编程陷阱,因为 Julia 在许多微妙的方面与这些语言不同。","category":"page"},{"location":"manual/getting-started/","page":"入门","title":"入门","text":"启动一个交互式会话(也叫 REPL)是学习和尝试 Julia 最简单的方法。双击 Julia 的可执行文件或是从命令行运行 julia 就可以启动:","category":"page"},{"location":"manual/getting-started/","page":"入门","title":"入门","text":"io = IOBuffer()\nBase.banner(io)\nbanner = String(take!(io))\nimport Markdown\nMarkdown.parse(\"```\\n\\$ julia\\n\\n$(banner)\\njulia> 1 + 2\\n3\\n\\njulia> ans\\n3\\n```\")","category":"page"},{"location":"manual/getting-started/","page":"入门","title":"入门","text":"输入 CTRL-D(同时按 Ctrl 键和 d 键)或 exit() 便可以退出交互式会话。在交互式模式中,julia 会显示一条横幅并提示用户输入。一旦用户输入了一段完整的代码(表达式),例如 1 + 2,然后按回车,交互式会话就会执行这段代码,并将结果显示出来。如果输入的代码以分号结尾,那么结果将不会显示出来。然而不管结果显示与否,变量 ans 总会存储上一次执行代码的结果,需要注意的是,变量 ans 只在交互式会话中才有。","category":"page"},{"location":"manual/getting-started/","page":"入门","title":"入门","text":"在交互式会话中,要运行写在源文件 file.jl 中的代码,只需输入 include(\"file.jl\")。","category":"page"},{"location":"manual/getting-started/","page":"入门","title":"入门","text":"如果想以非交互的方式执行文件中的代码,可以把文件名作为 julia 命令的第一个参数:","category":"page"},{"location":"manual/getting-started/","page":"入门","title":"入门","text":"$ julia script.jl arg1 arg2...","category":"page"},{"location":"manual/getting-started/","page":"入门","title":"入门","text":"如这个例子所示,julia 后跟着的命令行参数会被作为程序 script.jl 的命令行参数。这些参数使用全局常量 ARGS 来传递,脚本自身的名字会以全局变量 PROGRAM_FILE 传入。注意当脚本以命令行里的 -e 选项输入时,ARGS 也会被设定(详见此页末尾列表)但是 PROGRAM_FILE 会是空的。例如,要把一个脚本的输入参数显示出来,你可以:","category":"page"},{"location":"manual/getting-started/","page":"入门","title":"入门","text":"$ julia -e 'println(PROGRAM_FILE); for x in ARGS; println(x); end' foo bar\n\nfoo\nbar","category":"page"},{"location":"manual/getting-started/","page":"入门","title":"入门","text":"或者你可以把代码写到一个脚本文件中再执行它:","category":"page"},{"location":"manual/getting-started/","page":"入门","title":"入门","text":"$ echo 'println(PROGRAM_FILE); for x in ARGS; println(x); end' > script.jl\n$ julia script.jl foo bar\nscript.jl\nfoo\nbar","category":"page"},{"location":"manual/getting-started/","page":"入门","title":"入门","text":"可以使用 -- 分隔符来将传给脚本文件的参数和 Julia 本身的命令行参数区分开:","category":"page"},{"location":"manual/getting-started/","page":"入门","title":"入门","text":"$ julia --color=yes -O -- script.jl arg1 arg2..","category":"page"},{"location":"manual/getting-started/","page":"入门","title":"入门","text":"有关编写 Julia 脚本的更多信息,请参阅 脚本。","category":"page"},{"location":"manual/getting-started/","page":"入门","title":"入门","text":"使用选项 -p 或者 --machine-file 可以在并行模式下启动 Julia。 -p n 会启动额外的 n 个 worker,使用 --machine-file file 会为 file 文件中的每一行启动一个 worker。 定义在 file 中的机器必须能够通过一个不需要密码的 ssh 登陆访问到,且 Julia 的安装位置需要和当前主机相同。 定义机器的格式为 [count*][user@]host[:port] [bind_addr[:port]]。 user 默认值是当前用户; port 默认值是标准 ssh 端口; count 是在这个节点上的 worker 的数量,默认是 1; 可选的 bind-to bind_addr[:port] 指定了其它 worker 访问当前 worker 应当使用的 IP 地址与端口。","category":"page"},{"location":"manual/getting-started/","page":"入门","title":"入门","text":"要让 Julia 每次启动都自动执行一些代码,你可以把它们放在 ~/.julia/config/startup.jl 中:","category":"page"},{"location":"manual/getting-started/","page":"入门","title":"入门","text":"$ echo 'println(\"Greetings! 你好! 안녕하세요?\")' > ~/.julia/config/startup.jl\n$ julia\nGreetings! 你好! 안녕하세요?\n\n...","category":"page"},{"location":"manual/getting-started/","page":"入门","title":"入门","text":"在你第一次运行 Julia 后,你应该多了一个 ~/.julia 文件夹。 你还可以新建 ~/.julia/config 文件夹和 ~/.julia/config/startup.jl 文件来配置 Julia。","category":"page"},{"location":"manual/getting-started/","page":"入门","title":"入门","text":"和 perl 和 ruby 程序类似,还有很多种运行 Julia 代码的方式,运行代码时也有很多选项:","category":"page"},{"location":"manual/getting-started/","page":"入门","title":"入门","text":"julia [switches] -- [programfile] [args...]","category":"page"},{"location":"manual/getting-started/","page":"入门","title":"入门","text":"详细的命令选项可以在这里找到 Command-line Options.","category":"page"},{"location":"manual/getting-started/#资源","page":"入门","title":"资源","text":"","category":"section"},{"location":"manual/getting-started/","page":"入门","title":"入门","text":"除了本手册以外,官方网站还提供了一个有用的学习资源列表来帮助新用户学习 Julia。","category":"page"},{"location":"manual/getting-started/","page":"入门","title":"入门","text":"如果已经对 Julia 有所了解,你可以先看 Performance Tips 和 Workflow Tips。","category":"page"},{"location":"manual/types/#man-types","page":"类型","title":"类型","text":"","category":"section"},{"location":"manual/types/","page":"类型","title":"类型","text":"通常,我们把程序语言中的类型系统划分成两类:静态类型和动态类型。对于静态类型系统,在程序运行之前,我们就可计算每一个表达式的类型。而对于动态类型系统,我们只有通过运行那个程序,得到表达式具体的值,才能确定其具体的类型。通过让编写的代码无需在编译时知道值的确切类型,面向对象允许静态类型语言具有一定的灵活性。可以编写在不同类型上都能运行的代码的能力被称为多态。在经典的动态类型语言中,所有的代码都是多态的,这意味着这些代码对于其中值的类型没有约束,除非在代码中去具体的判断一个值的类型,或者对对象做一些它不支持的操作。","category":"page"},{"location":"manual/types/","page":"类型","title":"类型","text":"Julia 类型系统是动态的,但由于允许指出某些变量具有特定类型,因此占有静态类型系统的一些优势。这对于生成高效的代码非常有帮助,但更重要的是,它允许针对函数参数类型的方法派发与语言深度集成。方法派发将在方法中详细探讨,但它根植于此处提供的类型系统。","category":"page"},{"location":"manual/types/","page":"类型","title":"类型","text":"在类型被省略时,Julia 的默认行为是允许值为任何类型。因此,可以编写许多有用的 Julia 函数,而无需显式使用类型。然而,当需要额外的表达力时,很容易逐渐将显式的类型注释引入先前的「无类型」代码中。添加类型注释主要有三个目的:利用 Julia 强大的多重派发机制、提高代码可读性以及捕获程序错误。","category":"page"},{"location":"manual/types/","page":"类型","title":"类型","text":"用类型系统的术语描述,Julia是动态(dynamic)、主格(nominative)和参数(parametric)的。泛型可以被参数化,并且类型之间的层次关系可以被显式地声明,而不是隐含地通过兼容的结构。Julia 类型系统的一个特别显著的特征是具体类型相互之间不能是子类型:所有具体类型都是最终的,并且超类只能是抽象类型。虽然这乍一看可能过于严格,但它有许多益处,且缺点却少得出奇。事实证明,能够继承行为比继承结构更重要,同时继承两者在传统的面向对象语言中导致了重大困难。Julia 类型系统的其它高级方面应当在先言明:","category":"page"},{"location":"manual/types/","page":"类型","title":"类型","text":"对象值和非对象值之间没有分别:Julia 中的所有值都是具有类型的真实对象且其类型属于一个单独的、完全连通的类型图,该类型图的所有节点作为类型一样都是头等的。\n「编译期类型」是没有任何意义的概念:变量所具有的唯一类型是程序运行时的实际类型。这在面向对象被称为「运行时类型」,其中静态编译和多态的组合使得这种区别变得显著。\n只有值,而不是变量,有类型——变量只是绑定到值的名称,尽管为了简单起见,我们可以说“变量的类型”作为“变量所引用的值的类型”的简写。\n抽象类型和具体类型都可以通过其它类型进行参数化。它们的参数化还可通过符号、使得 isbits 返回 true 的任意类型的值(实质上,也就是像数字或布尔变量这样的东西,存储方式像 C 类型或不包含指向其它对象的指针的 struct)和其元组。类型参数在不需要被引用或限制时可以省略。","category":"page"},{"location":"manual/types/","page":"类型","title":"类型","text":"Julia 的类型系统设计得强大而富有表现力,却清晰、直观且不引人注目。许多 Julia 程序员可能从未感觉需要编写明确使用类型的代码。但是,某些场景的编程可通过声明类型变得更加清晰、简单、快速和稳健。","category":"page"},{"location":"manual/types/#类型声明","page":"类型","title":"类型声明","text":"","category":"section"},{"location":"manual/types/","page":"类型","title":"类型","text":":: 运算符可以用来在程序中给表达式和变量附加类型注释。这有两个主要原因:","category":"page"},{"location":"manual/types/","page":"类型","title":"类型","text":"作为断言,帮助程序确认能是否正常运行,\n给编译器提供额外的类型信息,在一些情况下这可以提升程序性能。","category":"page"},{"location":"manual/types/","page":"类型","title":"类型","text":"置于到计算值的表达式后面时,:: 操作符读作「是······的实例(is an instance of)」。在任何地方都可以用它来断言左侧表达式的值是右侧类型的实例。当右侧类型是具体类型时,左侧的值必须能够以该类型作为其实现——回想一下,所有具体类型都是最终的,因此没有任何实现是任何其它具体类型的子类型。当右侧类型是抽象类型时,值是由该抽象类型子类型中的某个具体类型实现的才能满足该断言。如果类型断言非真,抛出一个异常,否则返回左侧的值:","category":"page"},{"location":"manual/types/","page":"类型","title":"类型","text":"julia> (1+2)::AbstractFloat\nERROR: TypeError: in typeassert, expected AbstractFloat, got a value of type Int64\n\njulia> (1+2)::Int\n3","category":"page"},{"location":"manual/types/","page":"类型","title":"类型","text":"这将允许类型断言作用在任意表达式上。","category":"page"},{"location":"manual/types/","page":"类型","title":"类型","text":"置于赋值语句左侧的变量之后,或作为 local 声明的一部分时,:: 操作符的意义有所不同:它声明变量始终具有指定的类型,就像静态类型语言(如 C)中的类型声明。每个被赋给该变量的值都将使用 convert 转换为被声明的类型:","category":"page"},{"location":"manual/types/","page":"类型","title":"类型","text":"julia> function foo()\n x::Int8 = 100\n x\n end\nfoo (generic function with 1 method)\n\njulia> x = foo()\n100\n\njulia> typeof(x)\nInt8","category":"page"},{"location":"manual/types/","page":"类型","title":"类型","text":"这个特性对避免特定的性能「陷阱」很有帮助,比如给一个变量赋值时意外地更改了其类型。","category":"page"},{"location":"manual/types/","page":"类型","title":"类型","text":"此「声明」行为仅发生在特定上下文中:","category":"page"},{"location":"manual/types/","page":"类型","title":"类型","text":"local x::Int8 # in a local declaration\nx::Int8 = 10 # as the left-hand side of an assignment","category":"page"},{"location":"manual/types/","page":"类型","title":"类型","text":"并应用于整个当前作用域,甚至在该声明之前。目前,类型声明不能在全局作用域中使用,例如在 REPL 中就不可以,因为 Julia 还没有常量类型的全局变量。","category":"page"},{"location":"manual/types/","page":"类型","title":"类型","text":"声明也可以附加到函数定义:","category":"page"},{"location":"manual/types/","page":"类型","title":"类型","text":"function sinc(x)::Float64\n if x == 0\n return 1\n end\n return sin(pi*x)/(pi*x)\nend","category":"page"},{"location":"manual/types/","page":"类型","title":"类型","text":"从函数返回时就如同给一个已被声明类型的变量赋值:返回值始终会被转换为Float64。","category":"page"},{"location":"manual/types/#man-abstract-types","page":"类型","title":"抽象类型","text":"","category":"section"},{"location":"manual/types/","page":"类型","title":"类型","text":"抽象类型不能实例化,只能作为类型图中的节点使用,从而描述相关具体类型的集,即那些作为其后代的具体类型。即便抽象类型没有实例, 由于它们是类型系统的主干,故我们首先从抽象类型谈起:抽象类型形成了概念的层次结构,这使得 Julia 的类型系统不只是对象实现的集合。","category":"page"},{"location":"manual/types/","page":"类型","title":"类型","text":"回想一下,在整数和浮点数中,我们介绍了各种数值的具体类型:Int8、UInt8、Int16、UInt16、Int32、UInt32、Int64、UInt64、Int128、UInt128、Float16、Float32 和 Float64。尽管 Int8、Int16、Int32、Int64 和 Int128 具有不同的表示大小,但都具有共同的特征,即它们都是带符号的整数类型。类似地,UInt8、UInt16、UInt32、UInt64 和 UInt128 都是无符号整数类型,而 Float16、Float32 和 Float64 是不同的浮点数类型而非整数类型。一段代码只对某些类型有意义是很常见的,比如,只在其参数是某种类型的整数,而不真正取决于特定类型的整数时有意义。例如,最大公分母算法适用于所有类型的整数,但不适用于浮点数。抽象类型允许构造类型的层次结构,这给具体类型提供了可以适应的环境。例如,你可以轻松地为任何类型的整数编程,而不用将算法限制为某种特殊类型的整数。","category":"page"},{"location":"manual/types/","page":"类型","title":"类型","text":"抽象类型可以由 abstract type 关键字来声明。声明抽象类型的一般语法是:","category":"page"},{"location":"manual/types/","page":"类型","title":"类型","text":"abstract type «name» end\nabstract type «name» <: «supertype» end","category":"page"},{"location":"manual/types/","page":"类型","title":"类型","text":"该 abstract type 关键字引入了一个新的抽象类型,«name» 为其名称。此名称后面可以跟 <: 和一个已存在的类型,表示新声明的抽象类型是此「父」类型的子类型。","category":"page"},{"location":"manual/types/","page":"类型","title":"类型","text":"如果没有给出超类型,则默认超类型为 Any——一个已经定义好的抽象类型,所有对象都是 Any 的实例并且所有类型都是 Any 的子类型。在类型理论中,Any 通常称为「top」,因为它位于类型图的顶点。Julia 还有一个预定义了的抽象「bottom」类型,在类型图的最低点,写成 Union{}。这与 Any 完全相反:任何对象都不是 Union{} 的实例,所有的类型都是 Union{} 的超类型。","category":"page"},{"location":"manual/types/","page":"类型","title":"类型","text":"让我们考虑一些构成 Julia 数值类型层次结构的抽象类型:","category":"page"},{"location":"manual/types/","page":"类型","title":"类型","text":"abstract type Number end\nabstract type Real <: Number end\nabstract type AbstractFloat <: Real end\nabstract type Integer <: Real end\nabstract type Signed <: Integer end\nabstract type Unsigned <: Integer end","category":"page"},{"location":"manual/types/","page":"类型","title":"类型","text":"Number 类型为 Any 类型的直接子类型,并且 Real 为它的子类型。接下来,Real 有两个子类型(它还有更多的子类型,但这里只展示了两个,稍后将会看到其它的子类型): Integer 和 AbstractFloat,将世界分为整数的表示和实数的表示。实数的表示当然包括浮点类型,但也包括其他类型,例如有理数。因此,AbstractFloat 是一个 Real 的子类型,仅包括实数的浮点表示。整数被进一步细分为 Signed 和 Unsigned 两类。","category":"page"},{"location":"manual/types/","page":"类型","title":"类型","text":"<: 运算符的通常意义为「是······的子类型(is a subtype of)」,可以用在声明中,声明右侧类型是新声明类型的直接超类型;也可以在表达式中用作子类型运算符,在其左操作数为其右操作数的子类型时返回 true:","category":"page"},{"location":"manual/types/","page":"类型","title":"类型","text":"julia> Integer <: Number\ntrue\n\njulia> Integer <: AbstractFloat\nfalse","category":"page"},{"location":"manual/types/","page":"类型","title":"类型","text":"抽象类型的一个重要用途是为具体类型提供默认实现。举个简单的例子,考虑:","category":"page"},{"location":"manual/types/","page":"类型","title":"类型","text":"function myplus(x,y)\n x+y\nend","category":"page"},{"location":"manual/types/","page":"类型","title":"类型","text":"首先需要注意的是上述的参数声明等价于 x::Any 和 y::Any。当函数被调用时,例如 myplus(2,5),派发器会选择与给定参数相匹配的名称为 myplus 的最具体方法。(有关多重派发的更多信息,请参阅方法。)","category":"page"},{"location":"manual/types/","page":"类型","title":"类型","text":"假设没有找到比上述方法更具体的方法,Julia 则会基于上面给出的泛型函数,在内部定义并编译一个名为 myplus 的方法,专门用于处理两个 Int 参数,即它隐式地定义并编译:","category":"page"},{"location":"manual/types/","page":"类型","title":"类型","text":"function myplus(x::Int,y::Int)\n x+y\nend","category":"page"},{"location":"manual/types/","page":"类型","title":"类型","text":"最后,调用这个具体的方法。","category":"page"},{"location":"manual/types/","page":"类型","title":"类型","text":"因此,抽象类型允许程序员编写泛型函数,泛型函数可以通过许多具体类型的组合用作默认方法。多重派发使得程序员可以完全控制是使用默认方法还是更具体的方法。","category":"page"},{"location":"manual/types/","page":"类型","title":"类型","text":"需要注意的重点是,即使程序员依赖参数为抽象类型的函数,性能也不会有任何损失,因为它会针对每个调用它的参数元组的具体类型重新编译。(但在函数参数是抽象类型的容器的情况下,可能存在性能问题;请参阅性能建议。)","category":"page"},{"location":"manual/types/#原始类型","page":"类型","title":"原始类型","text":"","category":"section"},{"location":"manual/types/","page":"类型","title":"类型","text":"warning: Warning\n通常情况下更建议在新的复合类型中封装现有的原始类型,而不是重新定义自己的原始类型。这个功能的存在是为了允许 Julia 能引导受 LLVM 支持的标准基本类型。一旦一些标准类型被定义,就不需要再定义更多了。","category":"page"},{"location":"manual/types/","page":"类型","title":"类型","text":"原始类型是具体类型,其数据是由简单的位组成。原始类型的经典示例是整数和浮点数。与大多数语言不同,Julia 允许你声明自己的原始类型,而不是只提供一组固定的内置原始类型。实际上,标准原始类型都是在语言本身中定义的:","category":"page"},{"location":"manual/types/","page":"类型","title":"类型","text":"primitive type Float16 <: AbstractFloat 16 end\nprimitive type Float32 <: AbstractFloat 32 end\nprimitive type Float64 <: AbstractFloat 64 end\n\nprimitive type Bool <: Integer 8 end\nprimitive type Char <: AbstractChar 32 end\n\nprimitive type Int8 <: Signed 8 end\nprimitive type UInt8 <: Unsigned 8 end\nprimitive type Int16 <: Signed 16 end\nprimitive type UInt16 <: Unsigned 16 end\nprimitive type Int32 <: Signed 32 end\nprimitive type UInt32 <: Unsigned 32 end\nprimitive type Int64 <: Signed 64 end\nprimitive type UInt64 <: Unsigned 64 end\nprimitive type Int128 <: Signed 128 end\nprimitive type UInt128 <: Unsigned 128 end","category":"page"},{"location":"manual/types/","page":"类型","title":"类型","text":"声明原始类型的一般语法是:","category":"page"},{"location":"manual/types/","page":"类型","title":"类型","text":"primitive type «name» «bits» end\nprimitive type «name» <: «supertype» «bits» end","category":"page"},{"location":"manual/types/","page":"类型","title":"类型","text":"bits 的数值表示该类型需要多少存储空间,name 为新类型指定名称。可以选择将一个原始类型声明为某个超类型的子类型。如果省略超类型,则默认 Any 为其直接超类型。上述声明中意味着 Bool 类型需要 8 位来储存,并且直接超类型为 Integer。目前支持的大小只能是 8 位的倍数,不然你就会遇到 LLVM 的 bug。因此,布尔值虽然确实只需要一位,但不能声明为小于 8 位的值。","category":"page"},{"location":"manual/types/","page":"类型","title":"类型","text":"Bool,Int8 和 UInt8 类型都具有相同的表现形式:它们都是 8 位内存块。然而,由于 Julia 的类型系统是主格的,它们尽管具有相同的结构,但不是通用的。它们之间的一个根本区别是它们具有不同的超类型:Bool 的直接超类型是 Integer、Int8 的是 Signed 而 UInt8 的是 Unsigned。Bool,Int8 和 UInt8 的所有其它差异是行为上的——定义函数的方式在这些类型的对象作为参数给定时起作用。这也是为什么主格的类型系统是必须的:如果结构确定类型,类型决定行为,就不可能使 Bool 的行为与 Int8 或 UInt8 有任何不同。","category":"page"},{"location":"manual/types/#复合类型","page":"类型","title":"复合类型","text":"","category":"section"},{"location":"manual/types/","page":"类型","title":"类型","text":"复合类型在各种语言中被称为 record、struct 和 object。复合类型是命名字段的集合,其实例可以视为单个值。复合类型在许多语言中是唯一一种用户可定义的类型,也是 Julia 中最常用的用户定义类型。","category":"page"},{"location":"manual/types/","page":"类型","title":"类型","text":"在主流的面向对象语言中,比如 C++、Java、Python 和 Ruby,复合类型也具有与它们相关的命名函数,并且该组合称为「对象」。在纯粹的面向对象语言中,例如 Ruby 或 Smalltalk,所有值都是对象,无论它们是否为复合类型。在不太纯粹的面向对象语言中,包括 C++ 和 Java,一些值,比如整数和浮点值,不是对象,而用户定义的复合类型是具有相关方法的真实对象。在 Julia 中,所有值都是对象,但函数不与它们操作的对象捆绑在一起。这是必要的,因为 Julia 通过多重派发选择函数使用的方法,这意味着在选择方法时考虑所有函数参数的类型,而不仅仅是第一个(有关方法和派发的更多信息,请参阅方法)。因此,函数仅仅「属于」它们的第一个参数是不合适的。将方法组织到函数对象中而不是在每个对象「内部」命名方法最终成为语言设计中一个非常有益的方面。","category":"page"},{"location":"manual/types/","page":"类型","title":"类型","text":"struct 关键字与复合类型一起引入,后跟一个字段名称的块,可选择使用 :: 运算符注释类型:","category":"page"},{"location":"manual/types/","page":"类型","title":"类型","text":"julia> struct Foo\n bar\n baz::Int\n qux::Float64\n end","category":"page"},{"location":"manual/types/","page":"类型","title":"类型","text":"没有类型注释的字段默认为 Any 类型,所以可以包含任何类型的值。","category":"page"},{"location":"manual/types/","page":"类型","title":"类型","text":"类型为 Foo 的新对象通过将 Foo 类型对象像函数一样应用于其字段的值来创建:","category":"page"},{"location":"manual/types/","page":"类型","title":"类型","text":"julia> foo = Foo(\"Hello, world.\", 23, 1.5)\nFoo(\"Hello, world.\", 23, 1.5)\n\njulia> typeof(foo)\nFoo","category":"page"},{"location":"manual/types/","page":"类型","title":"类型","text":"像函数一样使用的类型称为构造函数。有两个构造函数已被自动生成(这些构造函数称为默认构造函数)。其中一个接受任何参数并调用 convert 函数将它其转换为字段的类型,另一个接受与字段类型完全匹配的参数。两者都生成的原因是,这使得更容易添加新定义而不会在无意中替换默认构造函数。","category":"page"},{"location":"manual/types/","page":"类型","title":"类型","text":"由于 bar 字段在类型上不受限制,因此任何值都可以。但是 baz 的值必须可转换为 Int 类型:","category":"page"},{"location":"manual/types/","page":"类型","title":"类型","text":"julia> Foo((), 23.5, 1)\nERROR: InexactError: Int64(23.5)\nStacktrace:\n[...]","category":"page"},{"location":"manual/types/","page":"类型","title":"类型","text":"可以使用 fieldnames 函数找到字段名称列表。","category":"page"},{"location":"manual/types/","page":"类型","title":"类型","text":"julia> fieldnames(Foo)\n(:bar, :baz, :qux)","category":"page"},{"location":"manual/types/","page":"类型","title":"类型","text":"可以使用传统的 foo.bar 表示法访问复合对象的字段值:","category":"page"},{"location":"manual/types/","page":"类型","title":"类型","text":"julia> foo.bar\n\"Hello, world.\"\n\njulia> foo.baz\n23\n\njulia> foo.qux\n1.5","category":"page"},{"location":"manual/types/","page":"类型","title":"类型","text":"用 struct 声明的复合对象是不可变的;创建后不能修改。乍一看这似乎很奇怪,但它有几个优点:","category":"page"},{"location":"manual/types/","page":"类型","title":"类型","text":"它可以更高效。某些 struct 可以被高效地打包到数组中,并且在某些情况下,编译器可以避免完全分配不可变对象。\n不可能违反类型构造函数提供的不变性。\n使用不可变对象的代码更容易推理。","category":"page"},{"location":"manual/types/","page":"类型","title":"类型","text":"不可变对象可以包含可变对象(比如数组)作为字段。那些被包含的对象将保持可变;只是不可变对象本身的字段不能更改为指向不同的对象。","category":"page"},{"location":"manual/types/","page":"类型","title":"类型","text":"如果需要,可以使用关键字 mutable struct 声明可变复合对象,这将在下一节中讨论。","category":"page"},{"location":"manual/types/","page":"类型","title":"类型","text":"如果一个不可变结构的所有字段都是不可区分的(===),那么包含这些字段的两个不可变值也是不可区分的:","category":"page"},{"location":"manual/types/","page":"类型","title":"类型","text":"julia> struct X\n a::Int\n b::Float64\n end\n\njulia> X(1, 2) === X(1, 2)\ntrue","category":"page"},{"location":"manual/types/","page":"类型","title":"类型","text":"关于如何构造复合类型的实例还有很多要说的,但这种讨论依赖于参数类型和方法,并且这是非常重要的,应该在专门的章节中讨论:构造函数。","category":"page"},{"location":"manual/types/#可变复合类型","page":"类型","title":"可变复合类型","text":"","category":"section"},{"location":"manual/types/","page":"类型","title":"类型","text":"如果使用 mutable struct 而不是 struct 声明复合类型,则它的实例可以被修改:","category":"page"},{"location":"manual/types/","page":"类型","title":"类型","text":"julia> mutable struct Bar\n baz\n qux::Float64\n end\n\njulia> bar = Bar(\"Hello\", 1.5);\n\njulia> bar.qux = 2.0\n2.0\n\njulia> bar.baz = 1//2\n1//2","category":"page"},{"location":"manual/types/","page":"类型","title":"类型","text":"为了支持修改,这种对象通常分配在堆上,并且具有稳定的内存地址。可变对象就像一个小容器,随着时间的推移,可能保持不同的值,因此只能通过其地址可靠地识别。相反地,不可变类型的实例与特定字段值相关——仅字段值就告诉你该对象的所有内容。在决定是否使类型为可变类型时,请询问具有相同字段值的两个实例是否被视为相同,或者它们是否可能需要随时间独立更改。如果它们被认为是相同的,该类型就应该是不可变的。","category":"page"},{"location":"manual/types/","page":"类型","title":"类型","text":"总结一下,Julia 的两个基本属性定义了不变性:","category":"page"},{"location":"manual/types/","page":"类型","title":"类型","text":"不允许修改不可变类型的值。\n对于位类型,这意味着值的位模式一旦设置将不再改变,并且该值是位类型的标识。\n对于复合类型,这意味着其字段值的标识将不再改变。当字段是位类型时,这意味着它们的位将不再改变,对于其值是可变类型(如数组)的字段,这意味着字段将始终引用相同的可变值,尽管该可变值的内容本身可能被修改。\n具有不可变类型的对象可以被编译器自由复制,因为其不可变性使得不可能以编程方式区分原始对象和副本。\n特别地,这意味着足够小的不可变值(如整数和浮点数)通常在寄存器(或栈分配)中传递给函数。\n另一方面,可变值是堆分配的,并作为指向堆分配值的指针传递给函数,除非编译器确定没有办法知道这不是正在发生的事情。","category":"page"},{"location":"manual/types/#man-declared-types","page":"类型","title":"已声明的类型","text":"","category":"section"},{"location":"manual/types/","page":"类型","title":"类型","text":"前面章节中讨论的三种类型(抽象、原始、复合)实际上都是密切相关的。它们共有相同的关键属性:","category":"page"},{"location":"manual/types/","page":"类型","title":"类型","text":"它们都是显式声明的。\n它们都具有名称。\n它们都已经显式声明超类型。\n它们可以有参数。","category":"page"},{"location":"manual/types/","page":"类型","title":"类型","text":"由于这些共有属性,它们在内部表现为相同概念 DataType 的实例,其是任何这些类型的类型:","category":"page"},{"location":"manual/types/","page":"类型","title":"类型","text":"julia> typeof(Real)\nDataType\n\njulia> typeof(Int)\nDataType","category":"page"},{"location":"manual/types/","page":"类型","title":"类型","text":"DataType 可以是抽象的或具体的。它如果是具体的,就具有指定的大小、存储布局和字段名称(可选)。因此,原始类型是具有非零大小的 DataType,但没有字段名称。复合类型是具有字段名称或者为空(大小为零)的 DataType。","category":"page"},{"location":"manual/types/","page":"类型","title":"类型","text":"每一个具体的值在系统里都是某个 DataType 的实例。","category":"page"},{"location":"manual/types/#类型共用体","page":"类型","title":"类型共用体","text":"","category":"section"},{"location":"manual/types/","page":"类型","title":"类型","text":"类型共用体是一种特殊的抽象类型,它包含作为对象的任何参数类型的所有实例,使用特殊Union关键字构造:","category":"page"},{"location":"manual/types/","page":"类型","title":"类型","text":"julia> IntOrString = Union{Int,AbstractString}\nUnion{Int64, AbstractString}\n\njulia> 1 :: IntOrString\n1\n\njulia> \"Hello!\" :: IntOrString\n\"Hello!\"\n\njulia> 1.0 :: IntOrString\nERROR: TypeError: in typeassert, expected Union{Int64, AbstractString}, got a value of type Float64","category":"page"},{"location":"manual/types/","page":"类型","title":"类型","text":"许多语言都有内建的共用体结构来推导类型;Julia 简单地将它暴露给程序员。Julia 编译器能在 Union 类型只具有少量类型[1]的情况下生成高效的代码,方法是为每个可能类型的不同分支都生成专用代码。","category":"page"},{"location":"manual/types/","page":"类型","title":"类型","text":"Union 类型的一种特别有用的情况是 Union{T, Nothing},其中 T 可以是任何类型,Nothing 是单态类型,其唯一实例是对象 nothing。此模式是其它语言中 Nullable、Option 或 Maybe 类型在 Julia 的等价。通过将函数参数或字段声明为 Union{T, Nothing},可以将其设置为类型为 T 的值,或者 nothing 来表示没有值。有关详细信息,请参阅常见问题的此条目。","category":"page"},{"location":"manual/types/#Parametric-Types","page":"类型","title":"参数类型","text":"","category":"section"},{"location":"manual/types/","page":"类型","title":"类型","text":"Julia 类型系统的一个重要和强大的特征是它是参数的:类型可以接受参数,因此类型声明实际上引入了一整套新类型——每一个参数值的可能组合引入一个新类型。许多语言支持某种版本的泛型编程,其中,可以指定操作泛型的数据结构和算法,而无需指定所涉及的确切类型。例如,某些形式的泛型编程存在于 ML、Haskell、Ada、Eiffel、C++、Java、C#、F#、和 Scala 中,这只是其中的一些例子。这些语言中的一些支持真正的参数多态(例如 ML、Haskell、Scala),而其它语言基于模板的泛型编程风格(例如 C++、Java)。由于在不同语言中有多种不同种类的泛型编程和参数类型,我们甚至不会尝试将 Julia 的参数类型与其它语言的进行比较,而是专注于解释 Julia 系统本身。然而,我们将注意到,因为 Julia 是动态类型语言并且不需要在编译时做出所有类型决定,所以许多在静态参数类型系统中遇到的传统困难可以被相对容易地处理。","category":"page"},{"location":"manual/types/","page":"类型","title":"类型","text":"所有已声明的类型(DataType 类型)都可被参数化,在每种情况下都使用一样的语法。我们将按一下顺序讨论它们:首先是参数复合类型,接着是参数抽象类型,最后是参数原始类型。","category":"page"},{"location":"manual/types/#man-parametric-composite-types","page":"类型","title":"参数复合类型","text":"","category":"section"},{"location":"manual/types/","page":"类型","title":"类型","text":"类型参数在类型名称后引入,用大括号扩起来:","category":"page"},{"location":"manual/types/","page":"类型","title":"类型","text":"julia> struct Point{T}\n x::T\n y::T\n end","category":"page"},{"location":"manual/types/","page":"类型","title":"类型","text":"此声明定义了一个新的参数类型,Point{T},拥有类型为 T 的两个「坐标」。有人可能会问 T 是什么?嗯,这恰恰是参数类型的重点:它可以是任何类型(或者任何位类型值,虽然它实际上在这里显然用作类型)。Point{Float64} 是一个具体类型,该类型等价于通过用 Float64 替换 Point 的定义中的 T 所定义的类型。因此,单独这一个声明实际上声明了无限个类型:Point{Float64},Point{AbstractString},Point{Int64},等等。这些类型中的每一个类型现在都是可用的具体类型:","category":"page"},{"location":"manual/types/","page":"类型","title":"类型","text":"julia> Point{Float64}\nPoint{Float64}\n\njulia> Point{AbstractString}\nPoint{AbstractString}","category":"page"},{"location":"manual/types/","page":"类型","title":"类型","text":"Point{Float64} 类型是坐标为 64 位浮点值的点,而 Point{AbstractString} 类型是「坐标」为字符串对象(请参阅 Strings)的「点」。","category":"page"},{"location":"manual/types/","page":"类型","title":"类型","text":"Point 本身也是一个有效的类型对象,包括所有实例 Point{Float64}、Point{AbstractString} 等作为子类型:","category":"page"},{"location":"manual/types/","page":"类型","title":"类型","text":"julia> Point{Float64} <: Point\ntrue\n\njulia> Point{AbstractString} <: Point\ntrue","category":"page"},{"location":"manual/types/","page":"类型","title":"类型","text":"当然,其他类型不是它的子类型:","category":"page"},{"location":"manual/types/","page":"类型","title":"类型","text":"julia> Float64 <: Point\nfalse\n\njulia> AbstractString <: Point\nfalse","category":"page"},{"location":"manual/types/","page":"类型","title":"类型","text":"Point 不同 T 值所声明的具体类型之间,不能互相作为子类型:","category":"page"},{"location":"manual/types/","page":"类型","title":"类型","text":"julia> Point{Float64} <: Point{Int64}\nfalse\n\njulia> Point{Float64} <: Point{Real}\nfalse","category":"page"},{"location":"manual/types/","page":"类型","title":"类型","text":"warning: Warning\n最后一点非常重要:即使 Float64 <: Real 也没有 Point{Float64} <: Point{Real}。","category":"page"},{"location":"manual/types/","page":"类型","title":"类型","text":"换成类型理论说法,Julia 的类型参数是不变的,而不是协变的(或甚至是逆变的)。这是出于实际原因:虽然任何 Point{Float64} 的实例在概念上也可能像是 Point{Real} 的实例,但这两种类型在内存中有不同的表示:","category":"page"},{"location":"manual/types/","page":"类型","title":"类型","text":"Point{Float64} 的实例可以紧凑而高效地表示为一对 64 位立即数;\nPoint{Real} 的实例必须能够保存任何一对 Real 的实例。由于 Real 实例的对象可以具有任意的大小和结构,Point{Real} 的实例实际上必须表示为一对指向单独分配的 Real 对象的指针。","category":"page"},{"location":"manual/types/","page":"类型","title":"类型","text":"在数组的情况下,能够以立即数存储 Point{Float64} 对象会极大地提高效率:Array{Float64} 可以存储为一段 64 位浮点值组成的连续内存块,而 Array{Real} 必须是一个由指向单独分配的 Real 的指针组成的数组——这可能是 boxed 64 位浮点值,但也可能是任意庞大和复杂的对象,且其被声明为 Real 抽象类型的表示。","category":"page"},{"location":"manual/types/","page":"类型","title":"类型","text":"由于 Point{Float64} 不是 Point{Real} 的子类型,下面的方法不适用于类型为 Point{Float64} 的参数:","category":"page"},{"location":"manual/types/","page":"类型","title":"类型","text":"function norm(p::Point{Real})\n sqrt(p.x^2 + p.y^2)\nend","category":"page"},{"location":"manual/types/","page":"类型","title":"类型","text":"一种正确的方法来定义一个接受类型的所有参数的方法,Point{T}其中T是一个子类型Real:","category":"page"},{"location":"manual/types/","page":"类型","title":"类型","text":"function norm(p::Point{<:Real})\n sqrt(p.x^2 + p.y^2)\nend","category":"page"},{"location":"manual/types/","page":"类型","title":"类型","text":"(等效地,另一种定义方法 function norm(p::Point{T} where T<:Real) 或 function norm(p::Point{T}) where T<:Real;查看 UnionAll 类型。)","category":"page"},{"location":"manual/types/","page":"类型","title":"类型","text":"稍后将在方法中讨论更多示例。","category":"page"},{"location":"manual/types/","page":"类型","title":"类型","text":"如何构造一个 Point 对象?可以为复合类型定义自定义的构造函数,这将在构造函数中详细讨论,但在没有任何特别的构造函数声明的情况下,有两种默认方式可以创建新的复合对象,一种是显式地给出类型参数,另一种是通过传给对象构造函数的参数隐式地推断出。","category":"page"},{"location":"manual/types/","page":"类型","title":"类型","text":"由于 Point{Float64} 类型等价于在 Point 声明时用 Float64 替换 T 得到的具体类型,它可以相应地作为构造函数使用:","category":"page"},{"location":"manual/types/","page":"类型","title":"类型","text":"julia> p = Point{Float64}(1.0, 2.0)\nPoint{Float64}(1.0, 2.0)\n\njulia> typeof(p)\nPoint{Float64}","category":"page"},{"location":"manual/types/","page":"类型","title":"类型","text":"对于默认的构造函数,必须为每个字段提供一个参数:","category":"page"},{"location":"manual/types/","page":"类型","title":"类型","text":"julia> Point{Float64}(1.0)\nERROR: MethodError: no method matching Point{Float64}(::Float64)\n[...]\n\njulia> Point{Float64}(1.0,2.0,3.0)\nERROR: MethodError: no method matching Point{Float64}(::Float64, ::Float64, ::Float64)\n[...]","category":"page"},{"location":"manual/types/","page":"类型","title":"类型","text":"参数类型只生成一个默认的构造函数,因为它无法覆盖。这个构造函数接受任何参数并将它们转换为字段的类型。","category":"page"},{"location":"manual/types/","page":"类型","title":"类型","text":"许多情况下,没有必要提供想要构造的 Point 对象的类型,因为构造函数调用参数的类型已经隐式地提供了类型信息。因此,你也可以将 Point 本身用作构造函数,前提是参数类型 T 的隐含值是明确的:","category":"page"},{"location":"manual/types/","page":"类型","title":"类型","text":"julia> p1 = Point(1.0,2.0)\nPoint{Float64}(1.0, 2.0)\n\njulia> typeof(p1)\nPoint{Float64}\n\njulia> p2 = Point(1,2)\nPoint{Int64}(1, 2)\n\njulia> typeof(p2)\nPoint{Int64}","category":"page"},{"location":"manual/types/","page":"类型","title":"类型","text":"在 Point 的例子中,当且仅当 Point 的两个参数类型相同时,T 的类型才确实是隐含的。如果不是这种情况,构造函数将失败并出现 MethodError:","category":"page"},{"location":"manual/types/","page":"类型","title":"类型","text":"julia> Point(1,2.5)\nERROR: MethodError: no method matching Point(::Int64, ::Float64)\nClosest candidates are:\n Point(::T, !Matched::T) where T at none:2","category":"page"},{"location":"manual/types/","page":"类型","title":"类型","text":"可以定义适当处理此类混合情况的函数构造方法,将在后面的构造函数中讨论。","category":"page"},{"location":"manual/types/#参数抽象类型","page":"类型","title":"参数抽象类型","text":"","category":"section"},{"location":"manual/types/","page":"类型","title":"类型","text":"参数抽象类型声明以非常相似的方式声明了一族抽象类型:","category":"page"},{"location":"manual/types/","page":"类型","title":"类型","text":"julia> abstract type Pointy{T} end","category":"page"},{"location":"manual/types/","page":"类型","title":"类型","text":"在此声明中,对于每个类型或整数值 T,Pointy{T} 都是不同的抽象类型。与参数复合类型一样,每个此类型的实例都是 Pointy 的子类型:","category":"page"},{"location":"manual/types/","page":"类型","title":"类型","text":"julia> Pointy{Int64} <: Pointy\ntrue\n\njulia> Pointy{1} <: Pointy\ntrue","category":"page"},{"location":"manual/types/","page":"类型","title":"类型","text":"参数抽象类型是不变的,就像参数复合类型:","category":"page"},{"location":"manual/types/","page":"类型","title":"类型","text":"julia> Pointy{Float64} <: Pointy{Real}\nfalse\n\njulia> Pointy{Real} <: Pointy{Float64}\nfalse","category":"page"},{"location":"manual/types/","page":"类型","title":"类型","text":"符号 Pointy{<:Real} 可用于表示协变类型的 Julia 类似物,而 Pointy{>:Int} 类似于逆变类型,但从技术上讲,它们都代表了类型的集合(参见 UnionAll 类型)。","category":"page"},{"location":"manual/types/","page":"类型","title":"类型","text":"julia> Pointy{Float64} <: Pointy{<:Real}\ntrue\n\njulia> Pointy{Real} <: Pointy{>:Int}\ntrue","category":"page"},{"location":"manual/types/","page":"类型","title":"类型","text":"正如之前的普通抽象类型用于在具体类型上创建实用的类型层次结构一样,参数抽象类型在参数复合类型上具有相同的用途。例如,我们可以将 Point{T} 声明为 Pointy{T} 的子类型,如下所示:","category":"page"},{"location":"manual/types/","page":"类型","title":"类型","text":"julia> struct Point{T} <: Pointy{T}\n x::T\n y::T\n end","category":"page"},{"location":"manual/types/","page":"类型","title":"类型","text":"鉴于此类声明,对每个 T,都有 Point{T} 是 Pointy{T} 的子类型:","category":"page"},{"location":"manual/types/","page":"类型","title":"类型","text":"julia> Point{Float64} <: Pointy{Float64}\ntrue\n\njulia> Point{Real} <: Pointy{Real}\ntrue\n\njulia> Point{AbstractString} <: Pointy{AbstractString}\ntrue","category":"page"},{"location":"manual/types/","page":"类型","title":"类型","text":"下面的关系依然不变:","category":"page"},{"location":"manual/types/","page":"类型","title":"类型","text":"julia> Point{Float64} <: Pointy{Real}\nfalse\n\njulia> Point{Float64} <: Pointy{<:Real}\ntrue","category":"page"},{"location":"manual/types/","page":"类型","title":"类型","text":"参数抽象类型(比如 Pointy)的用途是什么?考虑一下如果点都在对角线 x = y 上,那我们创建的点的实现可以只有一个坐标:","category":"page"},{"location":"manual/types/","page":"类型","title":"类型","text":"julia> struct DiagPoint{T} <: Pointy{T}\n x::T\n end","category":"page"},{"location":"manual/types/","page":"类型","title":"类型","text":"现在,Point{Float64} 和 DiagPoint{Float64} 都是抽象 Pointy{Float64} 的实现,每个类型 T 的其它可能选择与之类似。这允许对被所有 Pointy 对象共享的公共接口进行编程,接口都由 Point 和 DiagPoint 实现。但是,直到我们在下一节方法中引入方法和分派前,这无法完全证明。","category":"page"},{"location":"manual/types/","page":"类型","title":"类型","text":"有时,类型参数取遍所有可能类型也许是无意义的。在这种情况下,可以像这样约束 T 的范围:","category":"page"},{"location":"manual/types/","page":"类型","title":"类型","text":"julia> abstract type Pointy{T<:Real} end","category":"page"},{"location":"manual/types/","page":"类型","title":"类型","text":"在这样的声明中,可以使用任何 Real 的子类型替换 T,但不能使用不是 Real 子类型的类型:","category":"page"},{"location":"manual/types/","page":"类型","title":"类型","text":"julia> Pointy{Float64}\nPointy{Float64}\n\njulia> Pointy{Real}\nPointy{Real}\n\njulia> Pointy{AbstractString}\nERROR: TypeError: in Pointy, in T, expected T<:Real, got Type{AbstractString}\n\njulia> Pointy{1}\nERROR: TypeError: in Pointy, in T, expected T<:Real, got a value of type Int64","category":"page"},{"location":"manual/types/","page":"类型","title":"类型","text":"参数化复合类型的类型参数可用相同的方式限制:","category":"page"},{"location":"manual/types/","page":"类型","title":"类型","text":"struct Point{T<:Real} <: Pointy{T}\n x::T\n y::T\nend","category":"page"},{"location":"manual/types/","page":"类型","title":"类型","text":"这里给出了一个真实示例,展示了所有这些参数类型机制如何发挥作用,下面是 Julia 的不可变类型 Rational 的实际定义(除了我们为了简单起见省略了的构造函数),用来表示准确的整数比例:","category":"page"},{"location":"manual/types/","page":"类型","title":"类型","text":"struct Rational{T<:Integer} <: Real\n num::T\n den::T\nend","category":"page"},{"location":"manual/types/","page":"类型","title":"类型","text":"只有接受整数值的比例才是有意义的,因此参数类型 T 被限制为 Integer 的子类型,又整数的比例代表实数轴上的值,因此任何 Rational 都是抽象 Real 的实现。","category":"page"},{"location":"manual/types/#元组类型","page":"类型","title":"元组类型","text":"","category":"section"},{"location":"manual/types/","page":"类型","title":"类型","text":"元组类型是函数参数的抽象化——不带函数本身。函数参数的突出特征是它们的顺序和类型。因此,元组类型类似于参数化的不可变类型,其中每个参数都是一个字段的类型。例如,二元元组类型类似于以下不可变类型:","category":"page"},{"location":"manual/types/","page":"类型","title":"类型","text":"struct Tuple2{A,B}\n a::A\n b::B\nend","category":"page"},{"location":"manual/types/","page":"类型","title":"类型","text":"然而,有三个主要差异:","category":"page"},{"location":"manual/types/","page":"类型","title":"类型","text":"元组类型可以具有任意数量的参数。\n元组类型的参数是协变的(covariant):Tuple{Int} 是 Tuple{Any} 的子类型。因此,Tuple{Any} 被认为是一种抽象类型,且元组类型只有在它们的参数都是具体类型时才是具体类型。 \n元组没有字段名称; 字段只能通过索引访问。","category":"page"},{"location":"manual/types/","page":"类型","title":"类型","text":"元组值用括号和逗号书写。构造元组时,会根据需要生成适当的元组类型:","category":"page"},{"location":"manual/types/","page":"类型","title":"类型","text":"julia> typeof((1,\"foo\",2.5))\nTuple{Int64, String, Float64}","category":"page"},{"location":"manual/types/","page":"类型","title":"类型","text":"请注意协变性的含义:","category":"page"},{"location":"manual/types/","page":"类型","title":"类型","text":"julia> Tuple{Int,AbstractString} <: Tuple{Real,Any}\ntrue\n\njulia> Tuple{Int,AbstractString} <: Tuple{Real,Real}\nfalse\n\njulia> Tuple{Int,AbstractString} <: Tuple{Real,}\nfalse","category":"page"},{"location":"manual/types/","page":"类型","title":"类型","text":"直观地,这对应于函数参数的类型是函数签名(当函数签名匹配时)的子类型。","category":"page"},{"location":"manual/types/#变参元组类型","page":"类型","title":"变参元组类型","text":"","category":"section"},{"location":"manual/types/","page":"类型","title":"类型","text":"元组类型的最后一个参数可以是特殊值Vararg,它表示任意数量的尾随参数:  ","category":"page"},{"location":"manual/types/","page":"类型","title":"类型","text":"julia> mytupletype = Tuple{AbstractString,Vararg{Int}}\nTuple{AbstractString, Vararg{Int64}}\n\njulia> isa((\"1\",), mytupletype)\ntrue\n\njulia> isa((\"1\",1), mytupletype)\ntrue\n\njulia> isa((\"1\",1,2), mytupletype)\ntrue\n\njulia> isa((\"1\",1,2,3.0), mytupletype)\nfalse","category":"page"},{"location":"manual/types/","page":"类型","title":"类型","text":"此外,Vararg{T} 对应于零个或更多的类型为 T 的元素。变参元组类型被用来表示变参方法接受的参数(请参阅变参函数)。  ","category":"page"},{"location":"manual/types/","page":"类型","title":"类型","text":"特殊值 Vararg{T,N}(当用作元组类型的最后一个参数时)正好对应于类型为 T 的 N 个元素。 NTuple{N,T} 是 Tuple{Vararg{T,N}} 的一个方便的别名,即一个包含正好包含 T 类型的 N 个元素的元组类型。","category":"page"},{"location":"manual/types/#具名元组类型","page":"类型","title":"具名元组类型","text":"","category":"section"},{"location":"manual/types/","page":"类型","title":"类型","text":"具名元组是 NamedTuple 类型的实例,该类型有两个参数:一个给出字段名称的符号元组,和一个给出字段类型的元组类型。","category":"page"},{"location":"manual/types/","page":"类型","title":"类型","text":"julia> typeof((a=1,b=\"hello\"))\nNamedTuple{(:a, :b), Tuple{Int64, String}}","category":"page"},{"location":"manual/types/","page":"类型","title":"类型","text":"@NamedTuple 宏提供了类结构体(struct)的具名元组(NamedTuple)声明,使用 key::Type 的语法,如果省略 ::Type 则默认为 ::Any。","category":"page"},{"location":"manual/types/","page":"类型","title":"类型","text":"julia> @NamedTuple{a::Int, b::String}\nNamedTuple{(:a, :b), Tuple{Int64, String}}\n\njulia> @NamedTuple begin\n a::Int\n b::String\n end\nNamedTuple{(:a, :b), Tuple{Int64, String}}","category":"page"},{"location":"manual/types/","page":"类型","title":"类型","text":"NamedTuple 类型可以用作构造函数,接受一个单独的元组作为参数。构造出来的 NamedTuple 类型可以是具体类型,如果参数都被指定,也可以是只由字段名称所指定的类型:","category":"page"},{"location":"manual/types/","page":"类型","title":"类型","text":"julia> @NamedTuple{a::Float32,b::String}((1,\"\"))\n(a = 1.0f0, b = \"\")\n\njulia> NamedTuple{(:a, :b)}((1,\"\"))\n(a = 1, b = \"\")","category":"page"},{"location":"manual/types/","page":"类型","title":"类型","text":"如果指定了字段类型,参数会被转换。否则,就直接使用参数的类型。","category":"page"},{"location":"manual/types/#参数原始类型","page":"类型","title":"参数原始类型","text":"","category":"section"},{"location":"manual/types/","page":"类型","title":"类型","text":"原始类型也可以参数化声明,例如,指针都能表示为原始类型,其在 Julia 中以如下方式声明:","category":"page"},{"location":"manual/types/","page":"类型","title":"类型","text":"# 32-bit system:\nprimitive type Ptr{T} 32 end\n\n# 64-bit system:\nprimitive type Ptr{T} 64 end","category":"page"},{"location":"manual/types/","page":"类型","title":"类型","text":"与典型的参数复合类型相比,此声明中略显奇怪的特点是类型参数 T 并未在类型本身的定义里使用——它实际上只是一个抽象的标记,定义了一整族具有相同结构的类型,类型间仅由它们的类型参数来区分。因此,Ptr{Float64} 和 Ptr{Int64} 是不同的类型,就算它们具有相同的表示。当然,所有特定的指针类型都是总类型 Ptr 的子类型:","category":"page"},{"location":"manual/types/","page":"类型","title":"类型","text":"julia> Ptr{Float64} <: Ptr\ntrue\n\njulia> Ptr{Int64} <: Ptr\ntrue","category":"page"},{"location":"manual/types/#UnionAll-类型","page":"类型","title":"UnionAll 类型","text":"","category":"section"},{"location":"manual/types/","page":"类型","title":"类型","text":"我们已经说过,像 Ptr 这样的参数类型可充当它所有实例(Ptr{Int64} 等)的超类型。这是如何办到的?Ptr 本身不能是普通的数据类型,因为在不知道引用数据的类型时,该类型显然不能用于存储器操作。答案是 Ptr(或其它参数类型像 Array)是一种不同种类的类型,称为 UnionAll 类型。这种类型表示某些参数的所有值的类型的迭代并集。","category":"page"},{"location":"manual/types/","page":"类型","title":"类型","text":"UnionAll 类型通常使用关键字 where 编写。例如,Ptr 可以更精确地写为 Ptr{T} where T,也就是对于 T 的某些值,所有类型为 Ptr{T} 的值。在这种情况下,参数 T 也常被称为「类型变量」,因为它就像一个取值范围为类型的变量。每个 where 只引入一个类型变量,因此在具有多个参数的类型中这些表达式会被嵌套,例如 Array{T,N} where N where T。","category":"page"},{"location":"manual/types/","page":"类型","title":"类型","text":"类型应用语法 A{B,C} 要求 A 是个 UnionAll 类型,并先代入 B 作为 A 中最外层的类型变量。结果应该是另一个 UnionAll 类型,然后再将 C 代入。所以 A{B,C} 等价于 A{B}{C}。这解释了为什么可以部分实例化一个类型,比如 Array{Float64}:第一个参数已经被固定,但第二个参数仍取遍所有可能值。通过使用 where 语法,任何参数子集都能被固定。例如,所有一维数组的类型可以写为 Array{T,1} where T。","category":"page"},{"location":"manual/types/","page":"类型","title":"类型","text":"类型变量可以用子类型关系来加以限制。Array{T} where T<:Integer 指的是元素类型是某种 Integer 的所有数组。语法 Array{<:Integer} 是 Array{T} where T<:Integer 的便捷的缩写。类型变量可同时具有上下界。Array{T} where Int<:T<:Number 指的是元素类型为能够包含 Int 的 Number 的所有数组(因为 T 至少和 Int 一样大)。语法 where T>:Int 也能用来只指定类型变量的下界,且 Array{>:Int} 等价于 Array{T} where T>:Int。","category":"page"},{"location":"manual/types/","page":"类型","title":"类型","text":"由于 where 表达式可以嵌套,类型变量界可以引用更外层的类型变量。比如 Tuple{T,Array{S}} where S<:AbstractArray{T} where T<:Real 指的是二元元组,其第一个元素是某个 Real,而第二个元素是数组的数组 Array,其包含的内部数组的元素类型由元组的第一个元素类型决定。","category":"page"},{"location":"manual/types/","page":"类型","title":"类型","text":"where 关键字本身可以嵌套在更复杂的声明里。例如,考虑由以下声明创建的两个类型:","category":"page"},{"location":"manual/types/","page":"类型","title":"类型","text":"julia> const T1 = Array{Array{T, 1} where T, 1}\nVector{Vector} (alias for Array{Array{T, 1} where T, 1})\n\njulia> const T2 = Array{Array{T, 1}, 1} where T\nArray{Vector{T}, 1} where T","category":"page"},{"location":"manual/types/","page":"类型","title":"类型","text":"类型 T1 定义了由一维数组组成的一维数组;每个内部数组由相同类型的对象组成,但此类型对于不同内部数组可以不同。另一方面,类型 T2 定义了由一维数组组成的一维数组,其中的每个内部数组必须具有相同的类型。请注意,T2 是个抽象类型,比如 Array{Array{Int,1},1} <: T2,而 T1 是个具体类型。因此,T1 可由零参数构造函数 a=T1() 构造,但 T2 不行。","category":"page"},{"location":"manual/types/","page":"类型","title":"类型","text":"命名此类型有一种方便的语法,类似于函数定义语法的简短形式:","category":"page"},{"location":"manual/types/","page":"类型","title":"类型","text":"Vector{T} = Array{T, 1}","category":"page"},{"location":"manual/types/","page":"类型","title":"类型","text":"这等价于 const Vector = Array{T,1} where T。编写 Vector{Float64} 等价于编写 Array{Float64,1},总类型 Vector 具有所有 Array 对象的实例,其中 Array 对象的第二个参数——数组维数——是 1,而不考虑元素类型是什么。在参数类型必须总被完整指定的语言中,这不是特别有用,但在 Julia 中,这允许只编写 Vector 来表示包含任何元素类型的所有一维密集数组的抽象类型。","category":"page"},{"location":"manual/types/#man-singleton-types","page":"类型","title":"单例类型","text":"","category":"section"},{"location":"manual/types/","page":"类型","title":"类型","text":"没有字段的不可变复合类型称为 单例类型。正式地,如果","category":"page"},{"location":"manual/types/","page":"类型","title":"类型","text":"T 是一个不可变的复合类型(即用 struct 定义),\na isa T && b isa T 暗含 a === b,","category":"page"},{"location":"manual/types/","page":"类型","title":"类型","text":"那么T是单例类型。[2] Base.issingletontype 可以用来检查一个类型是否是单例类型。 抽象类型 不能通过构造成为单例类型。","category":"page"},{"location":"manual/types/","page":"类型","title":"类型","text":"根据定义,此类类型只能有一个实例:","category":"page"},{"location":"manual/types/","page":"类型","title":"类型","text":"julia> struct NoFields\n end\n\njulia> NoFields() === NoFields()\ntrue\n\njulia> Base.issingletontype(NoFields)\ntrue","category":"page"},{"location":"manual/types/","page":"类型","title":"类型","text":"=== 函数确认NoFields 的构造实例实际上是一个且相同的。","category":"page"},{"location":"manual/types/","page":"类型","title":"类型","text":"当上述条件成立时,参数类型可以是单例类型。例如,","category":"page"},{"location":"manual/types/","page":"类型","title":"类型","text":"julia> struct NoFieldsParam{T}\n end\n\njulia> Base.issingletontype(NoFieldsParam) # can't be a singleton type ...\nfalse\n\njulia> NoFieldsParam{Int}() isa NoFieldsParam # ... because it has ...\ntrue\n\njulia> NoFieldsParam{Bool}() isa NoFieldsParam # ... multiple instances\ntrue\n\njulia> Base.issingletontype(NoFieldsParam{Int}) # parametrized, it is a singleton\ntrue\n\njulia> NoFieldsParam{Int}() === NoFieldsParam{Int}()\ntrue","category":"page"},{"location":"manual/types/#man-typet-type","page":"类型","title":"Type{T} 类型选择器","text":"","category":"section"},{"location":"manual/types/","page":"类型","title":"类型","text":"对于每个类型T,Type{T} 是一个抽象的参数类型,它的唯一实例是对象T。 在我们讨论 参数方法 和 类型转换 之前,很难解释这个构造的效用,但简而言之,它允许人们专门针对特定类型的函数行为 作为值。 这对于编写其行为取决于作为显式参数给出的类型而不是由其参数之一的类型隐含的类型的方法(尤其是参数方法)很有用。","category":"page"},{"location":"manual/types/","page":"类型","title":"类型","text":"由于定义有点难理解,我们来看一些例子:","category":"page"},{"location":"manual/types/","page":"类型","title":"类型","text":"julia> isa(Float64, Type{Float64})\ntrue\n\njulia> isa(Real, Type{Float64})\nfalse\n\njulia> isa(Real, Type{Real})\ntrue\n\njulia> isa(Float64, Type{Real})\nfalse","category":"page"},{"location":"manual/types/","page":"类型","title":"类型","text":"换句话说,is(A, Type{B}) 当且仅当 A 和 B 是同一个对象并且该对象是一个类型时才为真。","category":"page"},{"location":"manual/types/","page":"类型","title":"类型","text":"特别的,由于参数类型是 不变量,我们有","category":"page"},{"location":"manual/types/","page":"类型","title":"类型","text":"julia> struct TypeParamExample{T}\n x::T\n end\n\njulia> TypeParamExample isa Type{TypeParamExample}\ntrue\n\njulia> TypeParamExample{Int} isa Type{TypeParamExample}\nfalse\n\njulia> TypeParamExample{Int} isa Type{TypeParamExample{Int}}\ntrue","category":"page"},{"location":"manual/types/","page":"类型","title":"类型","text":"如果没有参数,Type 只是一个抽象类型,所有类型对象都是其实例:","category":"page"},{"location":"manual/types/","page":"类型","title":"类型","text":"julia> isa(Type{Float64}, Type)\ntrue\n\njulia> isa(Float64, Type)\ntrue\n\njulia> isa(Real, Type)\ntrue","category":"page"},{"location":"manual/types/","page":"类型","title":"类型","text":"不是类型的对象不是 Type 的实例:","category":"page"},{"location":"manual/types/","page":"类型","title":"类型","text":"julia> isa(1, Type)\nfalse\n\njulia> isa(\"foo\", Type)\nfalse","category":"page"},{"location":"manual/types/","page":"类型","title":"类型","text":"虽然 Type 与任何其他抽象参数类型一样是 Julia 类型层次结构的一部分,但它并不常用在方法签名之外,除非在某些特殊情况下。 Type 的另一个重要用法是使不太精确的字段类型更加清晰,例如DataType 在下面的示例中,默认构造函数可能会导致依赖精确包装类型的代码出现性能问题(类似于 [抽象类型参数](@ref man-performance-abstract-container))。","category":"page"},{"location":"manual/types/","page":"类型","title":"类型","text":"julia> struct WrapType{T}\n value::T\n end\n\njulia> WrapType(Float64) # default constructor, note DataType\nWrapType{DataType}(Float64)\n\njulia> WrapType(::Type{T}) where T = WrapType{Type{T}}(T)\nWrapType\n\njulia> WrapType(Float64) # sharpened constructor, note more precise Type{Float64}\nWrapType{Type{Float64}}(Float64)","category":"page"},{"location":"manual/types/#类型别名","page":"类型","title":"类型别名","text":"","category":"section"},{"location":"manual/types/","page":"类型","title":"类型","text":"有时为一个已经可表达的类型引入新名称是很方便的。这可通过一个简单的赋值语句完成。例如,UInt 是 UInt32 或 UInt64 的别名,因为它的大小与系统上的指针大小是相适应的。","category":"page"},{"location":"manual/types/","page":"类型","title":"类型","text":"# 32-bit system:\njulia> UInt\nUInt32\n\n# 64-bit system:\njulia> UInt\nUInt64","category":"page"},{"location":"manual/types/","page":"类型","title":"类型","text":"这是由 base/boot.jl 中以下代码实现的:","category":"page"},{"location":"manual/types/","page":"类型","title":"类型","text":"if Int === Int64\n const UInt = UInt64\nelse\n const UInt = UInt32\nend","category":"page"},{"location":"manual/types/","page":"类型","title":"类型","text":"当然,这依赖于 Int 的别名,但它被预定义成正确的类型—— Int32 或 Int64。","category":"page"},{"location":"manual/types/","page":"类型","title":"类型","text":"(注意,与 Int 不同,Float 不作为特定大小的 AbstractFloat 类型的别名而存在。与整数寄存器不同,浮点数寄存器大小由 IEEE-754 标准指定,而 Int 的大小反映了该机器上本地指针的大小。)","category":"page"},{"location":"manual/types/#类型操作","page":"类型","title":"类型操作","text":"","category":"section"},{"location":"manual/types/","page":"类型","title":"类型","text":"因为 Julia 中的类型本身就是对象,所以一般的函数可以对它们进行操作。已经引入了一些对于使用或探索类型特别有用的函数,例如 <: 运算符,它表示其左操作数是否为其右操作数的子类型。","category":"page"},{"location":"manual/types/","page":"类型","title":"类型","text":"isa 函数测试对象是否具有给定类型并返回 true 或 false:","category":"page"},{"location":"manual/types/","page":"类型","title":"类型","text":"julia> isa(1, Int)\ntrue\n\njulia> isa(1, AbstractFloat)\nfalse","category":"page"},{"location":"manual/types/","page":"类型","title":"类型","text":"在文档示例中随处可见的 typeof 函数返回其参数的类型。如上所述,因为类型都是对象,所以它们也有类型,我们可以询问它们的类型:","category":"page"},{"location":"manual/types/","page":"类型","title":"类型","text":"julia> typeof(Rational{Int})\nDataType\n\njulia> typeof(Union{Real,String})\nUnion","category":"page"},{"location":"manual/types/","page":"类型","title":"类型","text":"如果我们重复这个过程会怎样?一个类型的类型是什么?碰巧,每个类型都是复合值,因此都具有 DataType 类型:","category":"page"},{"location":"manual/types/","page":"类型","title":"类型","text":"julia> typeof(DataType)\nDataType\n\njulia> typeof(Union)\nDataType","category":"page"},{"location":"manual/types/","page":"类型","title":"类型","text":"DataType 是它自己的类型。","category":"page"},{"location":"manual/types/","page":"类型","title":"类型","text":"另一个适用于某些类型的操作是 supertype,它显示了类型的超类型。只有已声明的类型(DataType)才有明确的超类型:","category":"page"},{"location":"manual/types/","page":"类型","title":"类型","text":"julia> supertype(Float64)\nAbstractFloat\n\njulia> supertype(Number)\nAny\n\njulia> supertype(AbstractString)\nAny\n\njulia> supertype(Any)\nAny","category":"page"},{"location":"manual/types/","page":"类型","title":"类型","text":"如果将 supertype 应用于其它类型对象(或非类型对象),则会引发 MethodError:","category":"page"},{"location":"manual/types/","page":"类型","title":"类型","text":"julia> supertype(Union{Float64,Int64})\nERROR: MethodError: no method matching supertype(::Type{Union{Float64, Int64}})\nClosest candidates are:\n[...]","category":"page"},{"location":"manual/types/#man-custom-pretty-printing","page":"类型","title":"自定义 pretty-printing","text":"","category":"section"},{"location":"manual/types/","page":"类型","title":"类型","text":"通常,人们会想要自定义显示类型实例的方式。这可通过重载 show 函数来完成。举个例子,假设我们定义一个类型来表示极坐标形式的复数:","category":"page"},{"location":"manual/types/","page":"类型","title":"类型","text":"julia> struct Polar{T<:Real} <: Number\n r::T\n Θ::T\n end\n\njulia> Polar(r::Real,Θ::Real) = Polar(promote(r,Θ)...)\nPolar","category":"page"},{"location":"manual/types/","page":"类型","title":"类型","text":"在这里,我们添加了一个自定义的构造函数,这样就可以接受不同 Real 类型的参数并将它们类型提升为共同类型(请参阅构造函数和类型转换和类型提升)。(当然,为了让它表现地像个 Number,我们需要定义许多其它方法,例如 +、*、one、zero 及类型提升规则等。)默认情况下,此类型的实例只是相当简单地显示有关类型名称和字段值的信息,比如,Polar{Float64}(3.0,4.0)。","category":"page"},{"location":"manual/types/","page":"类型","title":"类型","text":"如果我们希望它显示为 3.0 * exp(4.0im),我们可定义以下方法来将对象打印到给定的输出对象 io(其代表文件、终端、及缓冲区等;请参阅网络和流):","category":"page"},{"location":"manual/types/","page":"类型","title":"类型","text":"julia> Base.show(io::IO, z::Polar) = print(io, z.r, \" * exp(\", z.Θ, \"im)\")","category":"page"},{"location":"manual/types/","page":"类型","title":"类型","text":"Polar 对象的输出可以被更精细地控制。特别是,人们有时想要啰嗦的多行打印格式,用于在 REPL 和其它交互式环境中显示单个对象,以及一个更紧凑的单行格式,用于 print 函数或在作为其它对象(比如一个数组)的部分是显示该对象。虽然在两种情况下默认都会调用 show(io, z) 函数,你仍可以定义一个不同的多行格式来显示单个对象,这通过重载三参数形式的 show 函数,该函数接收 text/plain MIME 类型(请参阅 多媒体 I/O)作为它的第二个参数,举个例子:","category":"page"},{"location":"manual/types/","page":"类型","title":"类型","text":"julia> Base.show(io::IO, ::MIME\"text/plain\", z::Polar{T}) where{T} =\n print(io, \"Polar{$T} complex number:\\n \", z)","category":"page"},{"location":"manual/types/","page":"类型","title":"类型","text":"(请注意 print(..., z) 在这里调用的是双参数的 show(io, z) 方法。)这导致:","category":"page"},{"location":"manual/types/","page":"类型","title":"类型","text":"julia> Polar(3, 4.0)\nPolar{Float64} complex number:\n 3.0 * exp(4.0im)\n\njulia> [Polar(3, 4.0), Polar(4.0,5.3)]\n2-element Vector{Polar{Float64}}:\n 3.0 * exp(4.0im)\n 4.0 * exp(5.3im)","category":"page"},{"location":"manual/types/","page":"类型","title":"类型","text":"其中单行格式的 show(io, z) 仍用于由 Polar 值组成的数组。从技术上讲,REPL 调用 display(z) 来显示单行的执行结果,其默认为 show(stdout, MIME(\"text/plain\"), z),而后者又默认为 show(stdout, z),但是你不应该定义新的 display 方法,除非你正在定义新的多媒体显示管理器(请参阅多媒体 I/O)。","category":"page"},{"location":"manual/types/","page":"类型","title":"类型","text":"此外,你还可以为其它 MIME 类型定义 show 方法,以便在支持的环境(比如 IJulia)中实现更丰富的对象显示(HTML、图像等)。例如,我们可以定义 Polar 对象的 HTML 显示格式,使其带有上标和斜体:","category":"page"},{"location":"manual/types/","page":"类型","title":"类型","text":"julia> Base.show(io::IO, ::MIME\"text/html\", z::Polar{T}) where {T} =\n println(io, \"Polar{$T} complex number: \",\n z.r, \" e\", z.Θ, \" i\")","category":"page"},{"location":"manual/types/","page":"类型","title":"类型","text":"之后会在支持 HTML 显示的环境中自动使用 HTML 显示 Polar 对象,但你也可以手动调用 show 来获取 HTML 输出:","category":"page"},{"location":"manual/types/","page":"类型","title":"类型","text":"julia> show(stdout, \"text/html\", Polar(3.0,4.0))\nPolar{Float64} complex number: 3.0 e4.0 i","category":"page"},{"location":"manual/types/","page":"类型","title":"类型","text":"

        An HTML renderer would display this as: Polar{Float64} complex number: 3.0 e4.0 i

        ","category":"page"},{"location":"manual/types/","page":"类型","title":"类型","text":"根据经验,单行 show 方法应为创建的显示对象打印有效的 Julia 表达式。当这个 show 方法包含中缀运算符时,比如上面的 Polar 的单行 show 方法里的乘法运算符(*),在作为另一个对象的部分打印时,它可能无法被正确解析。要查看此问题,请考虑下面的表达式对象(请参阅程序表示),它代表 Polar 类型的特定实例的平方:","category":"page"},{"location":"manual/types/","page":"类型","title":"类型","text":"julia> a = Polar(3, 4.0)\nPolar{Float64} complex number:\n 3.0 * exp(4.0im)\n\njulia> print(:($a^2))\n3.0 * exp(4.0im) ^ 2","category":"page"},{"location":"manual/types/","page":"类型","title":"类型","text":"因为运算符 ^ 的优先级高于 *(请参阅运算符的优先级与结合性),所以此输出错误地表示了表达式 a ^ 2,而该表达式等价于 (3.0 * exp(4.0im)) ^ 2。为了解决这个问题,我们必须为 Base.show_unquoted(io::IO, z::Polar, indent::Int, precedence::Int) 创建一个自定义方法,在打印时,表达式对象会在内部调用它:","category":"page"},{"location":"manual/types/","page":"类型","title":"类型","text":"julia> function Base.show_unquoted(io::IO, z::Polar, ::Int, precedence::Int)\n if Base.operator_precedence(:*) <= precedence\n print(io, \"(\")\n show(io, z)\n print(io, \")\")\n else\n show(io, z)\n end\n end\n\njulia> :($a^2)\n:((3.0 * exp(4.0im)) ^ 2)","category":"page"},{"location":"manual/types/","page":"类型","title":"类型","text":"当正在调用的运算符的优先级大于等于乘法的优先级时,上面定义的方法会在 show 调用的两侧加上括号。这个检查允许,在没有括号时也可被正确解析的表达式(例如 :($a + 2) 和 :($a == 2)),在打印时省略括号:","category":"page"},{"location":"manual/types/","page":"类型","title":"类型","text":"julia> :($a + 2)\n:(3.0 * exp(4.0im) + 2)\n\njulia> :($a == 2)\n:(3.0 * exp(4.0im) == 2)","category":"page"},{"location":"manual/types/","page":"类型","title":"类型","text":"在某些情况下,根据上下文调整 show 方法的行为是很有用的。这可通过 IOContext 类型实现,它允许同时传递上下文属性和封装后的 IO 流。例如,我们可以在 :compact 属性设置为 true 时创建一个更短的表示,而在该属性为 false 或不存在时返回长的表示:","category":"page"},{"location":"manual/types/","page":"类型","title":"类型","text":"julia> function Base.show(io::IO, z::Polar)\n if get(io, :compact, false)\n print(io, z.r, \"ℯ\", z.Θ, \"im\")\n else\n print(io, z.r, \" * exp(\", z.Θ, \"im)\")\n end\n end","category":"page"},{"location":"manual/types/","page":"类型","title":"类型","text":"当传入的 IO 流是设置了 :compact(译注:该属性还应当设置为 true)属性的 IOContext 对象时,新的紧凑表示将被使用。特别地,当打印具有多列的数组(由于水平空间有限)时就是这种情况:","category":"page"},{"location":"manual/types/","page":"类型","title":"类型","text":"julia> show(IOContext(stdout, :compact=>true), Polar(3, 4.0))\n3.0ℯ4.0im\n\njulia> [Polar(3, 4.0) Polar(4.0,5.3)]\n1×2 Matrix{Polar{Float64}}:\n 3.0ℯ4.0im 4.0ℯ5.3im","category":"page"},{"location":"manual/types/","page":"类型","title":"类型","text":"有关调整打印效果的常用属性列表,请参阅文档 IOContext。","category":"page"},{"location":"manual/types/#值类型","page":"类型","title":"值类型","text":"","category":"section"},{"location":"manual/types/","page":"类型","title":"类型","text":"在 Julia 中,你无法根据诸如 true 或 false 之类的值进行分派。然而,你可以根据参数类型进行分派,Julia 允许你包含「plain bits」值(类型、符号、整数、浮点数和元组等)作为类型参数。Array{T,N} 里的维度参数就是一个常见的例子,在这里 T 是类型(比如 Float64),而 N 只是个 Int。","category":"page"},{"location":"manual/types/","page":"类型","title":"类型","text":"你可以创建把值作为参数的自定义类型,并使用它们控制自定义类型的分派。为了说明这个想法,让我们引入参数类型 Val{x} 和构造函数 Val(x) = Val{x}(),在不需要更精细的层次结构时,这是利用此技巧的一种习惯的方式。","category":"page"},{"location":"manual/types/","page":"类型","title":"类型","text":"Val 的定义为:","category":"page"},{"location":"manual/types/","page":"类型","title":"类型","text":"julia> struct Val{x}\n end\n\njulia> Val(x) = Val{x}()\nVal","category":"page"},{"location":"manual/types/","page":"类型","title":"类型","text":"Val 的实现就只需要这些。一些 Julia 标准库里的函数接收 Val 的实例作为参数,你也可以使用它来编写你自己的函数,例如:","category":"page"},{"location":"manual/types/","page":"类型","title":"类型","text":"julia> firstlast(::Val{true}) = \"First\"\nfirstlast (generic function with 1 method)\n\njulia> firstlast(::Val{false}) = \"Last\"\nfirstlast (generic function with 2 methods)\n\njulia> firstlast(Val(true))\n\"First\"\n\njulia> firstlast(Val(false))\n\"Last\"","category":"page"},{"location":"manual/types/","page":"类型","title":"类型","text":"为了保证 Julia 的一致性,调用处应当始终传递 Val 实例 而不是 类型,也就是使用 foo(Val(:bar)) 而不是 foo(Val{:bar})。","category":"page"},{"location":"manual/types/","page":"类型","title":"类型","text":"值得注意的是,参数「值」类型非常容易被误用,包括 Val;在不适用的情形下,你很容易使代码性能变得更糟糕。特别是,你可能永远都不会想要写出如上所示的代码。有关 Val 的正确(和不正确)使用的更多信息,请阅读性能建议中更广泛的讨论。","category":"page"},{"location":"manual/types/","page":"类型","title":"类型","text":"[1]: 「少数」由常数 MAX_UNION_SPLITTING 定义,目前设置为 4。","category":"page"},{"location":"manual/types/","page":"类型","title":"类型","text":"[2]: 一些流行的编程语言具有单例类型,包括 Haskell、Scala 和 Ruby。","category":"page"},{"location":"stdlib/Unicode/#Unicode","page":"Unicode","title":"Unicode","text":"","category":"section"},{"location":"stdlib/Unicode/","page":"Unicode","title":"Unicode","text":"Unicode.isassigned\nUnicode.normalize\nUnicode.graphemes","category":"page"},{"location":"stdlib/Unicode/#Unicode.isassigned","page":"Unicode","title":"Unicode.isassigned","text":"Unicode.isassigned(c) -> Bool\n\nReturns true if the given char or integer is an assigned Unicode code point.\n\nExamples\n\njulia> Unicode.isassigned(101)\ntrue\n\njulia> Unicode.isassigned('\\x01')\ntrue\n\n\n\n\n\n","category":"function"},{"location":"stdlib/Unicode/#Unicode.normalize","page":"Unicode","title":"Unicode.normalize","text":"Unicode.normalize(s::AbstractString; keywords...)\nUnicode.normalize(s::AbstractString, normalform::Symbol)\n\nNormalize the string s. By default, canonical composition (compose=true) is performed without ensuring Unicode versioning stability (compat=false), which produces the shortest possible equivalent string but may introduce composition characters not present in earlier Unicode versions.\n\nAlternatively, one of the four \"normal forms\" of the Unicode standard can be specified: normalform can be :NFC, :NFD, :NFKC, or :NFKD. Normal forms C (canonical composition) and D (canonical decomposition) convert different visually identical representations of the same abstract string into a single canonical form, with form C being more compact. Normal forms KC and KD additionally canonicalize \"compatibility equivalents\": they convert characters that are abstractly similar but visually distinct into a single canonical choice (e.g. they expand ligatures into the individual characters), with form KC being more compact.\n\nAlternatively, finer control and additional transformations may be obtained by calling Unicode.normalize(s; keywords...), where any number of the following boolean keywords options (which all default to false except for compose) are specified:\n\ncompose=false: do not perform canonical composition\ndecompose=true: do canonical decomposition instead of canonical composition (compose=true is ignored if present)\ncompat=true: compatibility equivalents are canonicalized\ncasefold=true: perform Unicode case folding, e.g. for case-insensitive string comparison\nnewline2lf=true, newline2ls=true, or newline2ps=true: convert various newline sequences (LF, CRLF, CR, NEL) into a linefeed (LF), line-separation (LS), or paragraph-separation (PS) character, respectively\nstripmark=true: strip diacritical marks (e.g. accents)\nstripignore=true: strip Unicode's \"default ignorable\" characters (e.g. the soft hyphen or the left-to-right marker)\nstripcc=true: strip control characters; horizontal tabs and form feeds are converted to spaces; newlines are also converted to spaces unless a newline-conversion flag was specified\nrejectna=true: throw an error if unassigned code points are found\nstable=true: enforce Unicode versioning stability (never introduce characters missing from earlier Unicode versions)\n\nYou can also use the chartransform keyword (which defaults to identity) to pass an arbitrary function mapping Integer codepoints to codepoints, which is is called on each character in s as it is processed, in order to perform arbitrary additional normalizations. For example, by passing chartransform=Unicode.julia_chartransform, you can apply a few Julia-specific character normalizations that are performed by Julia when parsing identifiers (in addition to NFC normalization: compose=true, stable=true).\n\nFor example, NFKC corresponds to the options compose=true, compat=true, stable=true.\n\nExamples\n\njulia> \"é\" == Unicode.normalize(\"é\") #LHS: Unicode U+00e9, RHS: U+0065 & U+0301\ntrue\n\njulia> \"μ\" == Unicode.normalize(\"µ\", compat=true) #LHS: Unicode U+03bc, RHS: Unicode U+00b5\ntrue\n\njulia> Unicode.normalize(\"JuLiA\", casefold=true)\n\"julia\"\n\njulia> Unicode.normalize(\"JúLiA\", stripmark=true)\n\"JuLiA\"\n\ncompat: Julia 1.8\nThe chartransform keyword argument requires Julia 1.8.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/Unicode/#Unicode.graphemes","page":"Unicode","title":"Unicode.graphemes","text":"graphemes(s::AbstractString) -> GraphemeIterator\n\nReturns an iterator over substrings of s that correspond to the extended graphemes in the string, as defined by Unicode UAX #29. (Roughly, these are what users would perceive as single characters, even though they may contain more than one codepoint; for example a letter combined with an accent mark is a single grapheme.)\n\n\n\n\n\n","category":"function"},{"location":"base/constants/#lib-constants","page":"常量","title":"常量","text":"","category":"section"},{"location":"base/constants/","page":"常量","title":"常量","text":"Core.nothing\nBase.PROGRAM_FILE\nBase.ARGS\nBase.C_NULL\nBase.VERSION\nBase.DEPOT_PATH\nBase.LOAD_PATH\nBase.Sys.BINDIR\nBase.Sys.CPU_THREADS\nBase.Sys.WORD_SIZE\nBase.Sys.KERNEL\nBase.Sys.ARCH\nBase.Sys.MACHINE","category":"page"},{"location":"base/constants/#Core.nothing","page":"常量","title":"Core.nothing","text":"nothing\n\nThe singleton instance of type Nothing, used by convention when there is no value to return (as in a C void function) or when a variable or field holds no value.\n\nSee also: isnothing, something, missing.\n\n\n\n\n\n","category":"constant"},{"location":"base/constants/#Base.PROGRAM_FILE","page":"常量","title":"Base.PROGRAM_FILE","text":"PROGRAM_FILE\n\nA string containing the script name passed to Julia from the command line. Note that the script name remains unchanged from within included files. Alternatively see @__FILE__.\n\n\n\n\n\n","category":"constant"},{"location":"base/constants/#Base.ARGS","page":"常量","title":"Base.ARGS","text":"ARGS\n\nAn array of the command line arguments passed to Julia, as strings.\n\n\n\n\n\n","category":"constant"},{"location":"base/constants/#Base.C_NULL","page":"常量","title":"Base.C_NULL","text":"C_NULL\n\nThe C null pointer constant, sometimes used when calling external code.\n\n\n\n\n\n","category":"constant"},{"location":"base/constants/#Base.VERSION","page":"常量","title":"Base.VERSION","text":"VERSION\n\nA VersionNumber object describing which version of Julia is in use. See also Version Number Literals.\n\n\n\n\n\n","category":"constant"},{"location":"base/constants/#Base.DEPOT_PATH","page":"常量","title":"Base.DEPOT_PATH","text":"DEPOT_PATH\n\nA stack of \"depot\" locations where the package manager, as well as Julia's code loading mechanisms, look for package registries, installed packages, named environments, repo clones, cached compiled package images, and configuration files. By default it includes:\n\n~/.julia where ~ is the user home as appropriate on the system;\nan architecture-specific shared system directory, e.g. /usr/local/share/julia;\nan architecture-independent shared system directory, e.g. /usr/share/julia.\n\nSo DEPOT_PATH might be:\n\n[joinpath(homedir(), \".julia\"), \"/usr/local/share/julia\", \"/usr/share/julia\"]\n\nThe first entry is the \"user depot\" and should be writable by and owned by the current user. The user depot is where: registries are cloned, new package versions are installed, named environments are created and updated, package repos are cloned, newly compiled package image files are saved, log files are written, development packages are checked out by default, and global configuration data is saved. Later entries in the depot path are treated as read-only and are appropriate for registries, packages, etc. installed and managed by system administrators.\n\nDEPOT_PATH is populated based on the JULIA_DEPOT_PATH environment variable if set.\n\nDEPOT_PATH contents\n\nEach entry in DEPOT_PATH is a path to a directory which contains subdirectories used by Julia for various purposes. Here is an overview of some of the subdirectories that may exist in a depot:\n\nclones: Contains full clones of package repos. Maintained by Pkg.jl and used as a cache.\ncompiled: Contains precompiled *.ji files for packages. Maintained by Julia.\ndev: Default directory for Pkg.develop. Maintained by Pkg.jl and the user.\nenvironments: Default package environments. For instance the global environment for a specific julia version. Maintained by Pkg.jl.\nlogs: Contains logs of Pkg and REPL operations. Maintained by Pkg.jl and Julia.\npackages: Contains packages, some of which were explicitly installed and some which are implicit dependencies. Maintained by Pkg.jl.\nregistries: Contains package registries. By default only General. Maintained by Pkg.jl.\n\nSee also JULIA_DEPOT_PATH, and Code Loading.\n\n\n\n\n\n","category":"constant"},{"location":"base/constants/#Base.LOAD_PATH","page":"常量","title":"Base.LOAD_PATH","text":"LOAD_PATH\n\nAn array of paths for using and import statements to consider as project environments or package directories when loading code. It is populated based on the JULIA_LOAD_PATH environment variable if set; otherwise it defaults to [\"@\", \"@v#.#\", \"@stdlib\"]. Entries starting with @ have special meanings:\n\n@ refers to the \"current active environment\", the initial value of which is initially determined by the JULIA_PROJECT environment variable or the --project command-line option.\n@stdlib expands to the absolute path of the current Julia installation's standard library directory.\n@name refers to a named environment, which are stored in depots (see JULIA_DEPOT_PATH) under the environments subdirectory. The user's named environments are stored in ~/.julia/environments so @name would refer to the environment in ~/.julia/environments/name if it exists and contains a Project.toml file. If name contains # characters, then they are replaced with the major, minor and patch components of the Julia version number. For example, if you are running Julia 1.2 then @v#.# expands to @v1.2 and will look for an environment by that name, typically at ~/.julia/environments/v1.2.\n\nThe fully expanded value of LOAD_PATH that is searched for projects and packages can be seen by calling the Base.load_path() function.\n\nSee also JULIA_LOAD_PATH, JULIA_PROJECT, JULIA_DEPOT_PATH, and Code Loading.\n\n\n\n\n\n","category":"constant"},{"location":"base/constants/#Base.Sys.BINDIR","page":"常量","title":"Base.Sys.BINDIR","text":"Sys.BINDIR::String\n\nA string containing the full path to the directory containing the julia executable.\n\n\n\n\n\n","category":"constant"},{"location":"base/constants/#Base.Sys.CPU_THREADS","page":"常量","title":"Base.Sys.CPU_THREADS","text":"Sys.CPU_THREADS::Int\n\nThe number of logical CPU cores available in the system, i.e. the number of threads that the CPU can run concurrently. Note that this is not necessarily the number of CPU cores, for example, in the presence of hyper-threading.\n\nSee Hwloc.jl or CpuId.jl for extended information, including number of physical cores.\n\n\n\n\n\n","category":"constant"},{"location":"base/constants/#Base.Sys.WORD_SIZE","page":"常量","title":"Base.Sys.WORD_SIZE","text":"Sys.WORD_SIZE::Int\n\nStandard word size on the current machine, in bits.\n\n\n\n\n\n","category":"constant"},{"location":"base/constants/#Base.Sys.KERNEL","page":"常量","title":"Base.Sys.KERNEL","text":"Sys.KERNEL::Symbol\n\nA symbol representing the name of the operating system, as returned by uname of the build configuration.\n\n\n\n\n\n","category":"constant"},{"location":"base/constants/#Base.Sys.ARCH","page":"常量","title":"Base.Sys.ARCH","text":"Sys.ARCH::Symbol\n\nA symbol representing the architecture of the build configuration.\n\n\n\n\n\n","category":"constant"},{"location":"base/constants/#Base.Sys.MACHINE","page":"常量","title":"Base.Sys.MACHINE","text":"Sys.MACHINE::String\n\nA string containing the build triple.\n\n\n\n\n\n","category":"constant"},{"location":"base/constants/","page":"常量","title":"常量","text":"参见:","category":"page"},{"location":"base/constants/","page":"常量","title":"常量","text":"stdin\nstdout\nstderr\nENV\nENDIAN_BOM\nLibc.MS_ASYNC\nLibc.MS_INVALIDATE\nLibc.MS_SYNC","category":"page"},{"location":"devdocs/cartesian/#笛卡尔","page":"笛卡尔","title":"笛卡尔","text":"","category":"section"},{"location":"devdocs/cartesian/","page":"笛卡尔","title":"笛卡尔","text":"The (non-exported) Cartesian module provides macros that facilitate writing multidimensional algorithms. Most often you can write such algorithms with straightforward techniques; however, there are a few cases where Base.Cartesian is still useful or necessary.","category":"page"},{"location":"devdocs/cartesian/#Principles-of-usage","page":"笛卡尔","title":"Principles of usage","text":"","category":"section"},{"location":"devdocs/cartesian/","page":"笛卡尔","title":"笛卡尔","text":"A simple example of usage is:","category":"page"},{"location":"devdocs/cartesian/","page":"笛卡尔","title":"笛卡尔","text":"@nloops 3 i A begin\n s += @nref 3 A i\nend","category":"page"},{"location":"devdocs/cartesian/","page":"笛卡尔","title":"笛卡尔","text":"which generates the following code:","category":"page"},{"location":"devdocs/cartesian/","page":"笛卡尔","title":"笛卡尔","text":"for i_3 = axes(A, 3)\n for i_2 = axes(A, 2)\n for i_1 = axes(A, 1)\n s += A[i_1, i_2, i_3]\n end\n end\nend","category":"page"},{"location":"devdocs/cartesian/","page":"笛卡尔","title":"笛卡尔","text":"In general, Cartesian allows you to write generic code that contains repetitive elements, like the nested loops in this example. Other applications include repeated expressions (e.g., loop unwinding) or creating function calls with variable numbers of arguments without using the \"splat\" construct (i...).","category":"page"},{"location":"devdocs/cartesian/#基本语法","page":"笛卡尔","title":"基本语法","text":"","category":"section"},{"location":"devdocs/cartesian/","page":"笛卡尔","title":"笛卡尔","text":"The (basic) syntax of @nloops is as follows:","category":"page"},{"location":"devdocs/cartesian/","page":"笛卡尔","title":"笛卡尔","text":"The first argument must be an integer (not a variable) specifying the number of loops.\nThe second argument is the symbol-prefix used for the iterator variable. Here we used i, and variables i_1, i_2, i_3 were generated.\nThe third argument specifies the range for each iterator variable. If you use a variable (symbol) here, it's taken as axes(A, dim). More flexibly, you can use the anonymous-function expression syntax described below.\nThe last argument is the body of the loop. Here, that's what appears between the begin...end.","category":"page"},{"location":"devdocs/cartesian/","page":"笛卡尔","title":"笛卡尔","text":"There are some additional features of @nloops described in the reference section.","category":"page"},{"location":"devdocs/cartesian/","page":"笛卡尔","title":"笛卡尔","text":"@nref follows a similar pattern, generating A[i_1,i_2,i_3] from @nref 3 A i. The general practice is to read from left to right, which is why @nloops is @nloops 3 i A expr (as in for i_2 = axes(A, 2), where i_2 is to the left and the range is to the right) whereas @nref is @nref 3 A i (as in A[i_1,i_2,i_3], where the array comes first).","category":"page"},{"location":"devdocs/cartesian/","page":"笛卡尔","title":"笛卡尔","text":"If you're developing code with Cartesian, you may find that debugging is easier when you examine the generated code, using @macroexpand:","category":"page"},{"location":"devdocs/cartesian/","page":"笛卡尔","title":"笛卡尔","text":"DocTestSetup = quote\n import Base.Cartesian: @nref\nend","category":"page"},{"location":"devdocs/cartesian/","page":"笛卡尔","title":"笛卡尔","text":"julia> @macroexpand @nref 2 A i\n:(A[i_1, i_2])","category":"page"},{"location":"devdocs/cartesian/","page":"笛卡尔","title":"笛卡尔","text":"DocTestSetup = nothing","category":"page"},{"location":"devdocs/cartesian/#Supplying-the-number-of-expressions","page":"笛卡尔","title":"Supplying the number of expressions","text":"","category":"section"},{"location":"devdocs/cartesian/","page":"笛卡尔","title":"笛卡尔","text":"The first argument to both of these macros is the number of expressions, which must be an integer. When you're writing a function that you intend to work in multiple dimensions, this may not be something you want to hard-code. The recommended approach is to use a @generated function. Here's an example:","category":"page"},{"location":"devdocs/cartesian/","page":"笛卡尔","title":"笛卡尔","text":"@generated function mysum(A::Array{T,N}) where {T,N}\n quote\n s = zero(T)\n @nloops $N i A begin\n s += @nref $N A i\n end\n s\n end\nend","category":"page"},{"location":"devdocs/cartesian/","page":"笛卡尔","title":"笛卡尔","text":"Naturally, you can also prepare expressions or perform calculations before the quote block.","category":"page"},{"location":"devdocs/cartesian/#Anonymous-function-expressions-as-macro-arguments","page":"笛卡尔","title":"Anonymous-function expressions as macro arguments","text":"","category":"section"},{"location":"devdocs/cartesian/","page":"笛卡尔","title":"笛卡尔","text":"Perhaps the single most powerful feature in Cartesian is the ability to supply anonymous-function expressions that get evaluated at parsing time. Let's consider a simple example:","category":"page"},{"location":"devdocs/cartesian/","page":"笛卡尔","title":"笛卡尔","text":"@nexprs 2 j->(i_j = 1)","category":"page"},{"location":"devdocs/cartesian/","page":"笛卡尔","title":"笛卡尔","text":"@nexprs generates n expressions that follow a pattern. This code would generate the following statements:","category":"page"},{"location":"devdocs/cartesian/","page":"笛卡尔","title":"笛卡尔","text":"i_1 = 1\ni_2 = 1","category":"page"},{"location":"devdocs/cartesian/","page":"笛卡尔","title":"笛卡尔","text":"In each generated statement, an \"isolated\" j (the variable of the anonymous function) gets replaced by values in the range 1:2. Generally speaking, Cartesian employs a LaTeX-like syntax. This allows you to do math on the index j. Here's an example computing the strides of an array:","category":"page"},{"location":"devdocs/cartesian/","page":"笛卡尔","title":"笛卡尔","text":"s_1 = 1\n@nexprs 3 j->(s_{j+1} = s_j * size(A, j))","category":"page"},{"location":"devdocs/cartesian/","page":"笛卡尔","title":"笛卡尔","text":"would generate expressions","category":"page"},{"location":"devdocs/cartesian/","page":"笛卡尔","title":"笛卡尔","text":"s_1 = 1\ns_2 = s_1 * size(A, 1)\ns_3 = s_2 * size(A, 2)\ns_4 = s_3 * size(A, 3)","category":"page"},{"location":"devdocs/cartesian/","page":"笛卡尔","title":"笛卡尔","text":"Anonymous-function expressions have many uses in practice.","category":"page"},{"location":"devdocs/cartesian/#dev-cartesian-reference","page":"笛卡尔","title":"Macro reference","text":"","category":"section"},{"location":"devdocs/cartesian/","page":"笛卡尔","title":"笛卡尔","text":"Base.Cartesian.@nloops\nBase.Cartesian.@nref\nBase.Cartesian.@nextract\nBase.Cartesian.@nexprs\nBase.Cartesian.@ncall\nBase.Cartesian.@ntuple\nBase.Cartesian.@nall\nBase.Cartesian.@nany\nBase.Cartesian.@nif","category":"page"},{"location":"devdocs/cartesian/#Base.Cartesian.@nloops","page":"笛卡尔","title":"Base.Cartesian.@nloops","text":"@nloops N itersym rangeexpr bodyexpr\n@nloops N itersym rangeexpr preexpr bodyexpr\n@nloops N itersym rangeexpr preexpr postexpr bodyexpr\n\nGenerate N nested loops, using itersym as the prefix for the iteration variables. rangeexpr may be an anonymous-function expression, or a simple symbol var in which case the range is axes(var, d) for dimension d.\n\nOptionally, you can provide \"pre\" and \"post\" expressions. These get executed first and last, respectively, in the body of each loop. For example:\n\n@nloops 2 i A d -> j_d = min(i_d, 5) begin\n s += @nref 2 A j\nend\n\nwould generate:\n\nfor i_2 = axes(A, 2)\n j_2 = min(i_2, 5)\n for i_1 = axes(A, 1)\n j_1 = min(i_1, 5)\n s += A[j_1, j_2]\n end\nend\n\nIf you want just a post-expression, supply nothing for the pre-expression. Using parentheses and semicolons, you can supply multi-statement expressions.\n\n\n\n\n\n","category":"macro"},{"location":"devdocs/cartesian/#Base.Cartesian.@nref","page":"笛卡尔","title":"Base.Cartesian.@nref","text":"@nref N A indexexpr\n\nGenerate expressions like A[i_1, i_2, ...]. indexexpr can either be an iteration-symbol prefix, or an anonymous-function expression.\n\nExamples\n\njulia> @macroexpand Base.Cartesian.@nref 3 A i\n:(A[i_1, i_2, i_3])\n\n\n\n\n\n","category":"macro"},{"location":"devdocs/cartesian/#Base.Cartesian.@nextract","page":"笛卡尔","title":"Base.Cartesian.@nextract","text":"@nextract N esym isym\n\nGenerate N variables esym_1, esym_2, ..., esym_N to extract values from isym. isym can be either a Symbol or anonymous-function expression.\n\n@nextract 2 x y would generate\n\nx_1 = y[1]\nx_2 = y[2]\n\nwhile @nextract 3 x d->y[2d-1] yields\n\nx_1 = y[1]\nx_2 = y[3]\nx_3 = y[5]\n\n\n\n\n\n","category":"macro"},{"location":"devdocs/cartesian/#Base.Cartesian.@nexprs","page":"笛卡尔","title":"Base.Cartesian.@nexprs","text":"@nexprs N expr\n\nGenerate N expressions. expr should be an anonymous-function expression.\n\nExamples\n\njulia> @macroexpand Base.Cartesian.@nexprs 4 i -> y[i] = A[i+j]\nquote\n y[1] = A[1 + j]\n y[2] = A[2 + j]\n y[3] = A[3 + j]\n y[4] = A[4 + j]\nend\n\n\n\n\n\n","category":"macro"},{"location":"devdocs/cartesian/#Base.Cartesian.@ncall","page":"笛卡尔","title":"Base.Cartesian.@ncall","text":"@ncall N f sym...\n\nGenerate a function call expression. sym represents any number of function arguments, the last of which may be an anonymous-function expression and is expanded into N arguments.\n\nFor example, @ncall 3 func a generates\n\nfunc(a_1, a_2, a_3)\n\nwhile @ncall 2 func a b i->c[i] yields\n\nfunc(a, b, c[1], c[2])\n\n\n\n\n\n","category":"macro"},{"location":"devdocs/cartesian/#Base.Cartesian.@ntuple","page":"笛卡尔","title":"Base.Cartesian.@ntuple","text":"@ntuple N expr\n\nGenerates an N-tuple. @ntuple 2 i would generate (i_1, i_2), and @ntuple 2 k->k+1 would generate (2,3).\n\n\n\n\n\n","category":"macro"},{"location":"devdocs/cartesian/#Base.Cartesian.@nall","page":"笛卡尔","title":"Base.Cartesian.@nall","text":"@nall N expr\n\nCheck whether all of the expressions generated by the anonymous-function expression expr evaluate to true.\n\n@nall 3 d->(i_d > 1) would generate the expression (i_1 > 1 && i_2 > 1 && i_3 > 1). This can be convenient for bounds-checking.\n\n\n\n\n\n","category":"macro"},{"location":"devdocs/cartesian/#Base.Cartesian.@nany","page":"笛卡尔","title":"Base.Cartesian.@nany","text":"@nany N expr\n\nCheck whether any of the expressions generated by the anonymous-function expression expr evaluate to true.\n\n@nany 3 d->(i_d > 1) would generate the expression (i_1 > 1 || i_2 > 1 || i_3 > 1).\n\n\n\n\n\n","category":"macro"},{"location":"devdocs/cartesian/#Base.Cartesian.@nif","page":"笛卡尔","title":"Base.Cartesian.@nif","text":"@nif N conditionexpr expr\n@nif N conditionexpr expr elseexpr\n\nGenerates a sequence of if ... elseif ... else ... end statements. For example:\n\n@nif 3 d->(i_d >= size(A,d)) d->(error(\"Dimension \", d, \" too big\")) d->println(\"All OK\")\n\nwould generate:\n\nif i_1 > size(A, 1)\n error(\"Dimension \", 1, \" too big\")\nelseif i_2 > size(A, 2)\n error(\"Dimension \", 2, \" too big\")\nelse\n println(\"All OK\")\nend\n\n\n\n\n\n","category":"macro"},{"location":"stdlib/SharedArrays/#共享数组","page":"共享数组","title":"共享数组","text":"","category":"section"},{"location":"stdlib/SharedArrays/","page":"共享数组","title":"共享数组","text":"SharedArrays.SharedArray\nSharedArrays.SharedVector\nSharedArrays.SharedMatrix\nSharedArrays.procs(::SharedArray)\nSharedArrays.sdata\nSharedArrays.indexpids\nSharedArrays.localindices","category":"page"},{"location":"stdlib/SharedArrays/#SharedArrays.SharedArray","page":"共享数组","title":"SharedArrays.SharedArray","text":"SharedArray{T}(dims::NTuple; init=false, pids=Int[])\nSharedArray{T,N}(...)\n\nConstruct a SharedArray of a bits type T and size dims across the processes specified by pids - all of which have to be on the same host. If N is specified by calling SharedArray{T,N}(dims), then N must match the length of dims.\n\nIf pids is left unspecified, the shared array will be mapped across all processes on the current host, including the master. But, localindices and indexpids will only refer to worker processes. This facilitates work distribution code to use workers for actual computation with the master process acting as a driver.\n\nIf an init function of the type initfn(S::SharedArray) is specified, it is called on all the participating workers.\n\nThe shared array is valid as long as a reference to the SharedArray object exists on the node which created the mapping.\n\nSharedArray{T}(filename::AbstractString, dims::NTuple, [offset=0]; mode=nothing, init=false, pids=Int[])\nSharedArray{T,N}(...)\n\nConstruct a SharedArray backed by the file filename, with element type T (must be a bits type) and size dims, across the processes specified by pids - all of which have to be on the same host. This file is mmapped into the host memory, with the following consequences:\n\nThe array data must be represented in binary format (e.g., an ASCII format like CSV cannot be supported)\nAny changes you make to the array values (e.g., A[3] = 0) will also change the values on disk\n\nIf pids is left unspecified, the shared array will be mapped across all processes on the current host, including the master. But, localindices and indexpids will only refer to worker processes. This facilitates work distribution code to use workers for actual computation with the master process acting as a driver.\n\nmode must be one of \"r\", \"r+\", \"w+\", or \"a+\", and defaults to \"r+\" if the file specified by filename already exists, or \"w+\" if not. If an init function of the type initfn(S::SharedArray) is specified, it is called on all the participating workers. You cannot specify an init function if the file is not writable.\n\noffset allows you to skip the specified number of bytes at the beginning of the file.\n\n\n\n\n\n","category":"type"},{"location":"stdlib/SharedArrays/#SharedArrays.SharedVector","page":"共享数组","title":"SharedArrays.SharedVector","text":"SharedVector\n\nA one-dimensional SharedArray.\n\n\n\n\n\n","category":"type"},{"location":"stdlib/SharedArrays/#SharedArrays.SharedMatrix","page":"共享数组","title":"SharedArrays.SharedMatrix","text":"SharedMatrix\n\nA two-dimensional SharedArray.\n\n\n\n\n\n","category":"type"},{"location":"stdlib/SharedArrays/#Distributed.procs-Tuple{SharedArray}","page":"共享数组","title":"Distributed.procs","text":"procs(S::SharedArray)\n\nGet the vector of processes mapping the shared array.\n\n\n\n\n\n","category":"method"},{"location":"stdlib/SharedArrays/#SharedArrays.sdata","page":"共享数组","title":"SharedArrays.sdata","text":"sdata(S::SharedArray)\n\nReturns the actual Array object backing S.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/SharedArrays/#SharedArrays.indexpids","page":"共享数组","title":"SharedArrays.indexpids","text":"indexpids(S::SharedArray)\n\nReturns the current worker's index in the list of workers mapping the SharedArray (i.e. in the same list returned by procs(S)), or 0 if the SharedArray is not mapped locally.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/SharedArrays/#SharedArrays.localindices","page":"共享数组","title":"SharedArrays.localindices","text":"localindices(S::SharedArray)\n\nReturns a range describing the \"default\" indices to be handled by the current process. This range should be interpreted in the sense of linear indexing, i.e., as a sub-range of 1:length(S). In multi-process contexts, returns an empty range in the parent process (or any process for which indexpids returns 0).\n\nIt's worth emphasizing that localindices exists purely as a convenience, and you can partition work on the array among workers any way you wish. For a SharedArray, all indices should be equally fast for each worker process.\n\n\n\n\n\n","category":"function"},{"location":"manual/modules/#modules","page":"模块","title":"模块","text":"","category":"section"},{"location":"manual/modules/","page":"模块","title":"模块","text":"Julia 中的模块有助于将代码组织成连贯的部分。 它们在语法上以 module Name ... end 界定,并具有以下特点:","category":"page"},{"location":"manual/modules/","page":"模块","title":"模块","text":"模块是独立的命名空间,每个都引入了一个新的全局作用域。 这很有用,因为它允许对不同的函数或全局变量使用相同的名称而不会发生冲突,只要它们在不同的模块中即可。\n模块具有用于命名空间管理的工具:每个模块定义一组它export的名称,并且可以使用 using 和 import 从其他模块导入名称(我们将在下面解释这些)。\n模块可以预编译以加快加载速度,并包含用于运行时初始化的代码。","category":"page"},{"location":"manual/modules/","page":"模块","title":"模块","text":"通常,在较大的 Julia 包中,你会看到模块的代码组织成文件,例如","category":"page"},{"location":"manual/modules/","page":"模块","title":"模块","text":"module SomeModule\n\n# export, using, import statements are usually here; we discuss these below\n\ninclude(\"file1.jl\")\ninclude(\"file2.jl\")\n\nend","category":"page"},{"location":"manual/modules/","page":"模块","title":"模块","text":"文件和文件名大多与模块无关; 模块仅与模块表达式相关联。 每个模块可以有多个文件,每个文件可以有多个模块。 include 的行为就像在包含模块的全局作用域内执行源文件的内容一样。 在本章中,我们使用简短和简化的示例,因此我们不会使用include。","category":"page"},{"location":"manual/modules/","page":"模块","title":"模块","text":"我们推荐不要缩进模块的主体,因为这通常会导致整个文件被缩进。 此外,通常使用 UpperCamelCase 作为模块名称(就像类型一样),并在适用时使用复数形式,特别是如果模块包含类似命名的标识符,以避免名称冲突。 例如,","category":"page"},{"location":"manual/modules/","page":"模块","title":"模块","text":"module FastThings\n\nstruct FastThing\n ...\nend\n\nend","category":"page"},{"location":"manual/modules/#namespace-management","page":"模块","title":"命名空间管理","text":"","category":"section"},{"location":"manual/modules/","page":"模块","title":"模块","text":"命名空间管理是指语言提供的设施,用于使模块中的名称在其他模块中可用。 我们在下面详细讨论相关的概念和功能。","category":"page"},{"location":"manual/modules/#合格的名称","page":"模块","title":"合格的名称","text":"","category":"section"},{"location":"manual/modules/","page":"模块","title":"模块","text":"全局作用域内的函数、变量和类型的名称,如sin、ARGS和UnitRange始终属于一个模块,称为母模块,例如,可以与parentmodule交互来找到该模块","category":"page"},{"location":"manual/modules/","page":"模块","title":"模块","text":"julia> parentmodule(UnitRange)\nBase","category":"page"},{"location":"manual/modules/","page":"模块","title":"模块","text":"也可以通过在它们的模块前面加上前缀来引用它们的父模块之外的这些名称,例如Base.UnitRange。 这称为限定名称。 父模块可以使用像Base.Math.sin这样的子模块链来访问,其中Base.Math被称为模块路径。 由于句法歧义,限定只包含符号的名称,例如运算符,需要插入冒号,例如 Base.:+。 少数运算符还需要括号,例如 Base.:(==)。","category":"page"},{"location":"manual/modules/","page":"模块","title":"模块","text":"如果一个名称是限定的,那么它总是可访问的,在函数的情况下,它也可以通过使用限定的名称作为函数名称来添加方法。","category":"page"},{"location":"manual/modules/","page":"模块","title":"模块","text":"在一个模块中,一个变量名可以通过将其声明 global x 不赋值而“保留”。 这可以防止在加载时间后初始化的全局变量的名称冲突。 语法M.x = y 不适用于在另一个模块中分配一个全局变量; 全局分配需要在模块本地进行操作。","category":"page"},{"location":"manual/modules/#导出列表","page":"模块","title":"导出列表","text":"","category":"section"},{"location":"manual/modules/","page":"模块","title":"模块","text":"名称(指函数、类型、全局变量和常量)可以通过 export 添加到模块的 *导出列表 *。 通常,它们位于或靠近模块定义的顶部,以便源代码的读者可以轻松找到它们,如","category":"page"},{"location":"manual/modules/","page":"模块","title":"模块","text":"module NiceStuff\n\nexport nice, DOG\n\nstruct Dog end # singleton type, not exported\n\nconst DOG = Dog() # named instance, exported\n\nnice(x) = \"nice $x\" # function, exported\n\nend","category":"page"},{"location":"manual/modules/","page":"模块","title":"模块","text":"但这只是一个风格建议——一个模块可以在任意位置有多个 export 语句。","category":"page"},{"location":"manual/modules/","page":"模块","title":"模块","text":"导出构成 API(应用程序接口)一部分的名称是很常见的。 在上面的代码中,导出列表建议用户应该使用nice和DOG。 然而,由于限定名称总是使标识符可访问,这只是组织 API 的一个选项:与其他语言不同,Julia 没有真正隐藏模块内部的功能。","category":"page"},{"location":"manual/modules/","page":"模块","title":"模块","text":"此外,某些模块根本不导出名称。 这通常是因为他们的 API 中使用常用词(例如derivative),这很容易与其他模块的导出列表发生冲突。 我们将在下面看到如何管理名称冲突。","category":"page"},{"location":"manual/modules/#单独使用using和import","page":"模块","title":"单独使用using和import","text":"","category":"section"},{"location":"manual/modules/","page":"模块","title":"模块","text":"加载模块最常见的方式可能是using ModuleName。 这 加载 与 ModuleName 关联的代码,并引入","category":"page"},{"location":"manual/modules/","page":"模块","title":"模块","text":"模块名称\n和导出列表的元素到周围的全局命名空间中。","category":"page"},{"location":"manual/modules/","page":"模块","title":"模块","text":"严格来说,声明 using ModuleName 意味着一个名为 ModuleName 的模块可用于根据需要解析名称。 当遇到当前模块中没有定义的全局变量时,系统会在ModuleName导出的变量中查找,找到就使用。 这意味着当前模块中该全局变量的所有使用都将解析为ModuleName中该变量的定义。","category":"page"},{"location":"manual/modules/","page":"模块","title":"模块","text":"继续我们的例子,","category":"page"},{"location":"manual/modules/","page":"模块","title":"模块","text":"using NiceStuff","category":"page"},{"location":"manual/modules/","page":"模块","title":"模块","text":"将加载上面的代码,使 NiceStuff(模块名称)、DOG 和 nice 可用。 Dog 不在导出列表中,但如果名称被模块路径(这里只是模块名称)限定为 NiceStuff.Dog,则可以访问它。","category":"page"},{"location":"manual/modules/","page":"模块","title":"模块","text":"重要的是,导出列表只在using ModuleName 的形式下起作用。","category":"page"},{"location":"manual/modules/","page":"模块","title":"模块","text":"相反,","category":"page"},{"location":"manual/modules/","page":"模块","title":"模块","text":"import NiceStuff","category":"page"},{"location":"manual/modules/","page":"模块","title":"模块","text":"仅将模块名称带入作用域。 用户需要使用 NiceStuff.DOG、NiceStuff.Dog 和 NiceStuff.nice 来访问其内容。 通常,当用户想要保持命名空间干净时,在上下文中使用 import ModuleName。 正如我们将在下一节中看到的,import NiceStuff 等同于 using NiceStuff: NiceStuff。","category":"page"},{"location":"manual/modules/","page":"模块","title":"模块","text":"你可以用逗号分隔符来组合相同类型的多个using和import语句,例如:","category":"page"},{"location":"manual/modules/","page":"模块","title":"模块","text":"using LinearAlgebra, Statistics","category":"page"},{"location":"manual/modules/#具有特定标识符的using-和-import-,并添加方法","page":"模块","title":"具有特定标识符的using 和 import ,并添加方法","text":"","category":"section"},{"location":"manual/modules/","page":"模块","title":"模块","text":"当 using ModuleName: 或 import ModuleName: 后跟以逗号分隔的名称列表时,模块会被加载,但 只有那些特定的名称才会被语句带入命名空间。 例如,","category":"page"},{"location":"manual/modules/","page":"模块","title":"模块","text":"using NiceStuff: nice, DOG","category":"page"},{"location":"manual/modules/","page":"模块","title":"模块","text":"将导入名称nice和DOG。","category":"page"},{"location":"manual/modules/","page":"模块","title":"模块","text":"重要的是,模块名称NiceStuff 不会出现在命名空间中。 如果要使其可访问,则必须明确列出它,如","category":"page"},{"location":"manual/modules/","page":"模块","title":"模块","text":"using NiceStuff: nice, DOG, NiceStuff","category":"page"},{"location":"manual/modules/","page":"模块","title":"模块","text":"Julia有两种形式来表示似乎相同的内容,因为只有 import ModuleName:f 允许在 没有模块路径的情况下向 f 添加方法。也就是说,以下示例将给出一个错误:","category":"page"},{"location":"manual/modules/","page":"模块","title":"模块","text":"using NiceStuff: nice\nstruct Cat end\nnice(::Cat) = \"nice 😸\"","category":"page"},{"location":"manual/modules/","page":"模块","title":"模块","text":"此错误可防止意外将方法添加到你仅打算使用的其他模块中的函数。","category":"page"},{"location":"manual/modules/","page":"模块","title":"模块","text":"有两种方法可以解决这个问题。 你始终可以使用模块路径限定函数名称:","category":"page"},{"location":"manual/modules/","page":"模块","title":"模块","text":"using NiceStuff\nstruct Cat end\nNiceStuff.nice(::Cat) = \"nice 😸\"","category":"page"},{"location":"manual/modules/","page":"模块","title":"模块","text":"或者,你可以import特定的函数名称:","category":"page"},{"location":"manual/modules/","page":"模块","title":"模块","text":"import NiceStuff: nice\nstruct Cat end\nnice(::Cat) = \"nice 😸\"","category":"page"},{"location":"manual/modules/","page":"模块","title":"模块","text":"你选择哪一个取决于你的代码风格。第一种形式表明你正在向另一个模块中的函数添加一个方法(请记住,导入和方法定义可能在单独的文件中),而第二种形式较短,如果你定义了多个方法,这一点尤其方便。","category":"page"},{"location":"manual/modules/","page":"模块","title":"模块","text":"一旦一个变量通过 using 或 import 引入,当前模块就不能创建同名的变量了。而且导入的变量是只读的,给全局变量赋值只能影响到由当前模块拥有的变量,否则会报错。","category":"page"},{"location":"manual/modules/#用as来重命名","page":"模块","title":"用as来重命名","text":"","category":"section"},{"location":"manual/modules/","page":"模块","title":"模块","text":"由import 或using 引入作用域的标识符可以用关键字as 重命名。 这对于解决名称冲突以及缩短名称很有用。 例如,Base 导出函数名read,但CSV.jl 包也提供了CSV.read。 如果我们要多次调用 CSV 读取,删除 CSV. 限定符会很方便。 但是,我们指的是Base.read还是CSV.read是模棱两可的:","category":"page"},{"location":"manual/modules/","page":"模块","title":"模块","text":"julia> read;\n\njulia> import CSV: read\nWARNING: ignoring conflicting import of CSV.read into Main","category":"page"},{"location":"manual/modules/","page":"模块","title":"模块","text":"重命名提供了一个解决方案:","category":"page"},{"location":"manual/modules/","page":"模块","title":"模块","text":"julia> import CSV: read as rd","category":"page"},{"location":"manual/modules/","page":"模块","title":"模块","text":"导入的包本身也可以重命名:","category":"page"},{"location":"manual/modules/","page":"模块","title":"模块","text":"import BenchmarkTools as BT","category":"page"},{"location":"manual/modules/","page":"模块","title":"模块","text":"as 仅在将单个标识符引入作用域时才与 using 一起使用。 例如,using CSV: read as rd 有效,但using CSV as C 无效,因为它对 CSV 中的所有导出名称进行操作。","category":"page"},{"location":"manual/modules/#混合使用多个-using-和-import-语句","page":"模块","title":"混合使用多个 using 和 import 语句","text":"","category":"section"},{"location":"manual/modules/","page":"模块","title":"模块","text":"当使用上述任何形式的多个 using 或 import 语句时,它们的效果将按照它们出现的顺序组合。 例如,","category":"page"},{"location":"manual/modules/","page":"模块","title":"模块","text":"using NiceStuff # exported names and the module name\nimport NiceStuff: nice # allows adding methods to unqualified functions","category":"page"},{"location":"manual/modules/","page":"模块","title":"模块","text":"会将 NiceStuff 的所有导出名称和模块名称本身带入作用域,并且还允许向 nice 添加方法而不用模块名称作为前缀。","category":"page"},{"location":"manual/modules/#处理名称冲突","page":"模块","title":"处理名称冲突","text":"","category":"section"},{"location":"manual/modules/","page":"模块","title":"模块","text":"考虑两个(或更多)包导出相同名称的情况,如","category":"page"},{"location":"manual/modules/","page":"模块","title":"模块","text":"module A\nexport f\nf() = 1\nend\n\nmodule B\nexport f\nf() = 2\nend","category":"page"},{"location":"manual/modules/","page":"模块","title":"模块","text":"using A, B 语句有效,但是当你尝试调用 f 时,你会收到警告","category":"page"},{"location":"manual/modules/","page":"模块","title":"模块","text":"WARNING: both B and A export \"f\"; uses of it in module Main must be qualified\nERROR: LoadError: UndefVarError: f not defined","category":"page"},{"location":"manual/modules/","page":"模块","title":"模块","text":"在这里,Julia 无法确定您指的是哪个 f,因此你必须做出选择。 常用的解决方法有以下几种:","category":"page"},{"location":"manual/modules/","page":"模块","title":"模块","text":"只需继续使用限定名称,如A.f 和B.f。 这使代码的读者可以清楚地了解上下文,特别是如果 f 恰好重合但在不同的包中具有不同的含义。 例如,degree在数学、自然科学和日常生活中有多种用途,这些含义应该分开。\n使用上面的 as 关键字重命名一个或两个标识符,例如\nusing A: f as f\nusing B: f as g\n会使B.f 可用作g。 在这里,我们假设您之前没有使用 using A, 这会把f代入命名空间。\n当问题中的多个名称确实有相同的含义时,通常一个模块会从另一个模块导入它,或者有一个轻量级的“基础”包,它的唯一功能是定义这样的接口,可以被其他包使用。按照惯例,这些包名以 ...Base 结尾(这与 Julia 的 Base 模块无关)","category":"page"},{"location":"manual/modules/#默认顶层定义以及裸模块","page":"模块","title":"默认顶层定义以及裸模块","text":"","category":"section"},{"location":"manual/modules/","page":"模块","title":"模块","text":"模块自动包含 using Core、using Base 以及 eval 和 include 函数的定义,这些函数在该模块的全局作用域内计算表达式/文件 .","category":"page"},{"location":"manual/modules/","page":"模块","title":"模块","text":"如果不需要这些默认定义,可以使用关键字 baremodule 来定义模块(注意:Core 仍然是导入的)。 就 baremodule 而言,一个标准的 module 看起来像这样:","category":"page"},{"location":"manual/modules/","page":"模块","title":"模块","text":"baremodule Mod\n\nusing Base\n\neval(x) = Core.eval(Mod, x)\ninclude(p) = Base.include(Mod, p)\n\n...\n\nend","category":"page"},{"location":"manual/modules/#标准模块","page":"模块","title":"标准模块","text":"","category":"section"},{"location":"manual/modules/","page":"模块","title":"模块","text":"有三个重要的标准模块:","category":"page"},{"location":"manual/modules/","page":"模块","title":"模块","text":"Core 包含了语言“内置”的所有功能。\nBase 包含了绝大多数情况下都会用到的基本功能。\nMain 是顶层模块,当 julia 启动时,也是当前模块。","category":"page"},{"location":"manual/modules/","page":"模块","title":"模块","text":"note: Standard library modules\n默认情况下,Julia 附带了一些标准库模块。 除了你不需要显式安装它们之外,它们的行为与常规 Julia 包类似。 例如,如果您想执行一些单元测试,你可以按如下方式加载 Test 标准库:using Test","category":"page"},{"location":"manual/modules/#子模块和相对路径","page":"模块","title":"子模块和相对路径","text":"","category":"section"},{"location":"manual/modules/","page":"模块","title":"模块","text":"模块可以包含 子模块,嵌套相同的语法module ... end。 它们可用于引入单独的命名空间,这有助于组织复杂的代码库。 请注意,每个 module 都引入了自己的 作用域,因此子模块不会自动从其父模块“继承”名称。","category":"page"},{"location":"manual/modules/","page":"模块","title":"模块","text":"建议子模块在 using 和 import 语句中使用 相对模块限定符 来引用封闭父模块中的其他模块(包括后者)。 相对模块限定符以句点 (.) 开头,它对应于当前模块,每个连续的 . 都指向当前模块的父级。 如有必要,这应该跟在模块之后,最后是要访问的实际名称,所有名称都以.分隔。","category":"page"},{"location":"manual/modules/","page":"模块","title":"模块","text":"考虑以下示例,其中子模块SubA定义了一个函数,然后在其“兄弟”模块中进行扩展:","category":"page"},{"location":"manual/modules/","page":"模块","title":"模块","text":"module ParentModule\n\nmodule SubA\nexport add_D # exported interface\nconst D = 3\nadd_D(x) = x + D\nend\n\nusing .SubA # brings `add_D` into the namespace\n\nexport add_D # export it from ParentModule too\n\nmodule SubB\nimport ..SubA: add_D # relative path for a “sibling” module\nstruct Infinity end\nadd_D(x::Infinity) = x\nend\n\nend","category":"page"},{"location":"manual/modules/","page":"模块","title":"模块","text":"你可能会在包中看到代码,在类似的情况下,它使用","category":"page"},{"location":"manual/modules/","page":"模块","title":"模块","text":"import ParentModule.SubA: add_D","category":"page"},{"location":"manual/modules/","page":"模块","title":"模块","text":"然而,这是通过 代码加载 操作的,因此仅当 ParentModule 在包中时才有效。 最好使用相对路径。","category":"page"},{"location":"manual/modules/","page":"模块","title":"模块","text":"请注意,如果你正在评估值,定义的顺序也很重要。 考虑","category":"page"},{"location":"manual/modules/","page":"模块","title":"模块","text":"module TestPackage\n\nexport x, y\n\nx = 0\n\nmodule Sub\nusing ..TestPackage\nz = y # ERROR: UndefVarError: y not defined\nend\n\ny = 1\n\nend","category":"page"},{"location":"manual/modules/","page":"模块","title":"模块","text":"其中 Sub 在定义之前尝试使用 TestPackage.y,因此它没有值。","category":"page"},{"location":"manual/modules/","page":"模块","title":"模块","text":"出于类似的原因,你不能使用循环顺序:","category":"page"},{"location":"manual/modules/","page":"模块","title":"模块","text":"module A\n\nmodule B\nusing ..C # ERROR: UndefVarError: C not defined\nend\n\nmodule C\nusing ..B\nend\n\nend","category":"page"},{"location":"manual/modules/#模块初始化和预编译","page":"模块","title":"模块初始化和预编译","text":"","category":"section"},{"location":"manual/modules/","page":"模块","title":"模块","text":"因为执行模块中的所有语句通常需要编译大量代码,大型模块可能需要几秒钟才能加载。Julia 会创建模块的预编译缓存以减少这个时间。","category":"page"},{"location":"manual/modules/","page":"模块","title":"模块","text":"当用 import 或 using 加载一个模块时,模块增量预编译文件会自动创建并使用。这会让模块在第一次加载时自动编译。 另外,你也可以手工调用 Base.compilecache(modulename),产生的缓存文件会放在 DEPOT_PATH[1]/compiled/ 目录下。 之后,当该模块的任何一个依赖发生变更时,该模块会在 using 或 import 时自动重新编译; 模块的依赖指的是:任何它导入的模块、Julia 自身、include 的文件或由 include_dependency(path) 显式声明的依赖。","category":"page"},{"location":"manual/modules/","page":"模块","title":"模块","text":"对于文件依赖项,通过检查由 include 加载或由 include_dependency 显式添加的每个文件的修改时间(mtime)是否保持不变,或是否等于截断到最接近秒的修改时间(以适应无法以亚秒精度复制 mtime的系统),来确定更改。它还考虑由 require 中的搜索逻辑选择的文件路径是否与创建预编译文件的路径匹配。它还考虑了已加载到当前进程中的依赖项集,并且不会重新编译这些模块,即使它们的文件更改或消失,以避免在正在运行的系统和预编译缓存之间创建不兼容。","category":"page"},{"location":"manual/modules/","page":"模块","title":"模块","text":"如果你知道一个模块预编译不安全(例如,由于下面描述的原因之一),你应该把__precompile__(false)放在模块文件中(通常放在顶部)。 这会导致Base.compilecache 抛出错误,并且会导致using / import 将其直接加载到当前进程中并跳过预编译和缓存。 这也因此防止了模块被任何其他预编译模块导入。","category":"page"},{"location":"manual/modules/","page":"模块","title":"模块","text":"在开发模块的时候,你可能需要了解一些与增量编译相关的固有行为。例如,外部状态不会被保留。为了解决这个问题,需要显式分离运行时与编译期的部分。Julia 允许你定义一个 __init__() 函数来执行任何需要在运行时发生的初始化。在编译期(--output-*),此函数将不会被调用。你可以假设在代码的生存周期中,此函数只会被运行一次。当然,如果有必要,你也可以手动调用它,但在默认的情况下,请假定此函数是为了处理与本机状态相关的信息,注意这些信息不需要,更不应该存入预编译镜像。此函数会在模块被导入到当前进程之后被调用,这包括在一个增量编译中导入该模块的时候(--output-incremental=yes),但在完整编译时该函数不会被调用。","category":"page"},{"location":"manual/modules/","page":"模块","title":"模块","text":"特别的,如果你在模块里定义了一个名为 __init__() 的函数,那么 Julia 在加载这个模块之后会在第一次运行时(runtime)立刻调用这个函数(例如,通过 import,using,或者 require 加载时),也就是说 __init__ 只会在模块中所有其它命令都执行完以后被调用一次。因为这个函数将在模块完全载入后被调用,任何子模块或者已经载入的模块都将在当前模块调用 __init__ 之前 调用自己的 __init__ 函数。","category":"page"},{"location":"manual/modules/","page":"模块","title":"模块","text":"__init__的典型用法有二,一是用于调用外部 C 库的运行时初始化函数,二是用于初始化涉及到外部库所返回的指针的全局常量。例如,假设我们正在调用一个 C 库 libfoo,它要求我们在运行时调用foo_init() 这个初始化函数。假设我们还想定义一个全局常量 foo_data_ptr,它保存 libfoo 所定义的 void *foo_data() 函数的返回值——必须在运行时(而非编译时)初始化这个常量,因为指针地址不是固定的。可以通过在模块中定义 __init__ 函数来完成这个操作。","category":"page"},{"location":"manual/modules/","page":"模块","title":"模块","text":"const foo_data_ptr = Ref{Ptr{Cvoid}}(0)\nfunction __init__()\n ccall((:foo_init, :libfoo), Cvoid, ())\n foo_data_ptr[] = ccall((:foo_data, :libfoo), Ptr{Cvoid}, ())\n nothing\nend","category":"page"},{"location":"manual/modules/","page":"模块","title":"模块","text":"注意,在像 __init__ 这样的函数里定义一个全局变量是完全可以的,这是动态语言的优点之一。但是把全局作用域的值定义成常量,可以让编译器能确定该值的类型,并且能让编译器生成更好的优化过的代码。显然,你的模块(Module)中,任何其他依赖于 foo_data_ptr 的全局量也必须在 __init__ 中被初始化。","category":"page"},{"location":"manual/modules/","page":"模块","title":"模块","text":"涉及大多数不是由 ccall 生成的 Julia 对象的常量不需要放在 __init__ 中:它们的定义可以从缓存的模块映像中预编译和加载。 这包括复杂的堆分配对象,如数组。 但是,任何返回原始指针值的例程都必须在运行时调用才能使预编译工作(Ptr 对象将变成空指针,除非它们隐藏在 isbits 目的)。 这包括 Julia 函数 @cfunction 和 pointer 的返回值。","category":"page"},{"location":"manual/modules/","page":"模块","title":"模块","text":"字典和集合类型,或者通常任何依赖于 hash(key) 方法的类型,都是比较棘手的情况。 通常当键是数字、字符串、符号、范围、Expr 或这些类型的组合(通过数组、元组、集合、映射对等)时,可以安全地预编译它们。但是,对于一些其它的键类型,例如 Function 或 DataType、以及还没有定义散列方法的通用用户定义类型,回退(fallback)的散列(hash)方法依赖于对象的内存地址(通过 objectid),因此可能会在每次运行时发生变化。 如果您有这些关键类型中的一种,或者您不确定,为了安全起见,您可以在您的 __init__ 函数中初始化这个字典。或者,您可以使用 IdDict 字典类型,它是由预编译专门处理的,因此在编译时初始化是安全的。","category":"page"},{"location":"manual/modules/","page":"模块","title":"模块","text":"当使用预编译时,我们必须要清楚地区分代码的编译阶段和运行阶段。在此模式下,我们会更清楚发现 Julia 的编译器可以执行任何 Julia 代码,而不是一个用于生成编译后代码的独立的解释器。","category":"page"},{"location":"manual/modules/","page":"模块","title":"模块","text":"其它已知的潜在失败场景包括:","category":"page"},{"location":"manual/modules/","page":"模块","title":"模块","text":"全局计数器,例如:为了试图唯一的标识对象。考虑以下代码片段:\nmutable struct UniquedById\n myid::Int\n let counter = 0\n UniquedById() = new(counter += 1)\n end\nend\n尽管这段代码的目标是给每个实例赋一个唯一的 ID,但计数器的值会在代码编译结束时被记录。任何对此增量编译模块的后续使用,计数器都将从同一个值开始计数。\n注意 objectid (工作原理是取内存指针的 hash)也有类似的问题,请查阅下面关于 Dict 的用法。\n一种解决方案是用宏捕捉 @__MODULE__,并将它与目前的 counter 值一起保存。然而,更好的方案是对代码进行重新设计,不要依赖这种全局状态变量。\n像 Dict 和 Set 这种关联集合需要在 __init__ 中 re-hash。Julia 在未来很可能会提供一个机制来注册初始化函数。\n依赖编译期的副作用会在加载时蔓延。例子包括:更改其它 Julia 模块里的数组或变量,操作文件或设备的句柄,保存指向其它系统资源(包括内存)的指针。\n无意中从其它模块中“拷贝”了全局状态:通过直接引用的方式而不是通过查找的方式。例如,在全局作用域下:\n#mystdout = Base.stdout #= will not work correctly, since this will copy Base.stdout into this module =#\n# instead use accessor functions:\ngetstdout() = Base.stdout #= best option =#\n# or move the assignment into the runtime:\n__init__() = global mystdout = Base.stdout #= also works =#","category":"page"},{"location":"manual/modules/","page":"模块","title":"模块","text":"此处为预编译中的操作附加了若干限制,以帮助用户避免其他误操作:","category":"page"},{"location":"manual/modules/","page":"模块","title":"模块","text":"调用 eval 来在另一个模块中引发副作用。当增量预编译被标记时,该操作同时会导致抛出一个警告。\n当 __init__() 已经开始执行后,在局部作用域中声明 global const(见 issue #12010,计划为此情况添加一个错误提示)\n在增量预编译时替换模块是一个运行时错误。","category":"page"},{"location":"manual/modules/","page":"模块","title":"模块","text":"一些其他需要注意的点:","category":"page"},{"location":"manual/modules/","page":"模块","title":"模块","text":"在源代码文件本身被修改之后,不会执行代码重载或缓存失效化处理(包括由 Pkg.update 执行的修改,此外在 Pkg.rm 执行后也没有清理操作)\n变形数组的内存共享特性会被预编译忽略(每个数组样貌都会获得一个拷贝)\n文件系统在编译期间和运行期间被假设为不变的,比如使用 @__FILE__/source_path() 在运行期间寻找资源、或使用 BinDeps 宏 @checked_lib。有时这是不可避免的。但是可能的话,在编译期将资源复制到模块里面是个好做法,这样在运行期间,就不需要去寻找它们了。\nWeakRef 对象和完成器目前在序列化器中无法被恰当地处理(在接下来的发行版中将修复)。\n通常,最好避免去捕捉内部元数据对象的引用,如 Method、MethodInstance、TypeMapLevel、TypeMapEntry 及这些对象的字段,因为这会迷惑序列化器,且可能会引发你不想要的结果。此操作不足以成为一个错误,但你需做好准备:系统会尝试拷贝一部分,然后创建其余部分的单个独立实例。","category":"page"},{"location":"manual/modules/","page":"模块","title":"模块","text":"在开发模块时,关闭增量预编译可能会有所帮助。命令行标记 --compiled-modules={yes|no} 可以让你切换预编译的开启和关闭。当 Julia 附加 --compiled-modules=no 启动,在载入模块和模块依赖时,编译缓存中的序列化模块会被忽略。Base.compilecache 仍可以被手动调用。此命令行标记的状态会被传递给 Pkg.build,禁止其在安装、更新、显式构建包时触发自动预编译。","category":"page"},{"location":"devdocs/debuggingtips/#gdb-调试提示","page":"gdb 调试提示","title":"gdb 调试提示","text":"","category":"section"},{"location":"devdocs/debuggingtips/#显示-Julia-变量","page":"gdb 调试提示","title":"显示 Julia 变量","text":"","category":"section"},{"location":"devdocs/debuggingtips/","page":"gdb 调试提示","title":"gdb 调试提示","text":"在 gdb 中, 任何 jl_value_t* 类型的变量 obj 的展示可以通过使用:","category":"page"},{"location":"devdocs/debuggingtips/","page":"gdb 调试提示","title":"gdb 调试提示","text":"(gdb) call jl_(obj)","category":"page"},{"location":"devdocs/debuggingtips/","page":"gdb 调试提示","title":"gdb 调试提示","text":"这个对象会在 julia 会话中展示,而不是在 gdb 会话中。这是一种行之有效的方式来发现由 Julia 的 C 代码操控的对象的类型和值。","category":"page"},{"location":"devdocs/debuggingtips/","page":"gdb 调试提示","title":"gdb 调试提示","text":"同样,如果你在调试一些 Julia 内部的东西 (比如 compiler.jl ),你可以通过使用这些来打印 obj :","category":"page"},{"location":"devdocs/debuggingtips/","page":"gdb 调试提示","title":"gdb 调试提示","text":"ccall(:jl_, Cvoid, (Any,), obj)","category":"page"},{"location":"devdocs/debuggingtips/","page":"gdb 调试提示","title":"gdb 调试提示","text":"这是一种很好的方法,可以避免 Julia 的输出流初始化顺序引起的问题。","category":"page"},{"location":"devdocs/debuggingtips/","page":"gdb 调试提示","title":"gdb 调试提示","text":"Julia的 flisp 解释器使用 value_t 对象;能够通过 call fl_print(fl_ctx, ios_stdout, obj) 来展示。","category":"page"},{"location":"devdocs/debuggingtips/#有用的用于检查的-Julia-变量","page":"gdb 调试提示","title":"有用的用于检查的 Julia 变量","text":"","category":"section"},{"location":"devdocs/debuggingtips/","page":"gdb 调试提示","title":"gdb 调试提示","text":"While the addresses of many variables, like singletons, can be useful to print for many failures, there are a number of additional variables (see julia.h for a complete list) that are even more useful.","category":"page"},{"location":"devdocs/debuggingtips/","page":"gdb 调试提示","title":"gdb 调试提示","text":"(when in jl_apply_generic) mfunc and jl_uncompress_ast(mfunc->def, mfunc->code) :: for figuring out a bit about the call-stack\njl_lineno and jl_filename :: for figuring out what line in a test to go start debugging from (or figure out how far into a file has been parsed)\n$1 :: not really a variable, but still a useful shorthand for referring to the result of the last gdb command (such as print)\njl_options :: sometimes useful, since it lists all of the command line options that were successfully parsed\njl_uv_stderr :: because who doesn't like to be able to interact with stdio","category":"page"},{"location":"devdocs/debuggingtips/#Useful-Julia-functions-for-Inspecting-those-variables","page":"gdb 调试提示","title":"Useful Julia functions for Inspecting those variables","text":"","category":"section"},{"location":"devdocs/debuggingtips/","page":"gdb 调试提示","title":"gdb 调试提示","text":"jl_gdblookup($rip) :: For looking up the current function and line. (use $eip on i686 platforms)\njlbacktrace() :: For dumping the current Julia backtrace stack to stderr. Only usable after record_backtrace() has been called.\njl_dump_llvm_value(Value*) :: For invoking Value->dump() in gdb, where it doesn't work natively. For example, f->linfo->functionObject, f->linfo->specFunctionObject, and to_function(f->linfo).\nType->dump() :: only works in lldb. Note: add something like ;1 to prevent lldb from printing its prompt over the output\njl_eval_string(\"expr\") :: for invoking side-effects to modify the current state or to lookup symbols\njl_typeof(jl_value_t*) :: for extracting the type tag of a Julia value (in gdb, call macro define jl_typeof jl_typeof first, or pick something short like ty for the first arg to define a shorthand)","category":"page"},{"location":"devdocs/debuggingtips/#Inserting-breakpoints-for-inspection-from-gdb","page":"gdb 调试提示","title":"Inserting breakpoints for inspection from gdb","text":"","category":"section"},{"location":"devdocs/debuggingtips/","page":"gdb 调试提示","title":"gdb 调试提示","text":"In your gdb session, set a breakpoint in jl_breakpoint like so:","category":"page"},{"location":"devdocs/debuggingtips/","page":"gdb 调试提示","title":"gdb 调试提示","text":"(gdb) break jl_breakpoint","category":"page"},{"location":"devdocs/debuggingtips/","page":"gdb 调试提示","title":"gdb 调试提示","text":"Then within your Julia code, insert a call to jl_breakpoint by adding","category":"page"},{"location":"devdocs/debuggingtips/","page":"gdb 调试提示","title":"gdb 调试提示","text":"ccall(:jl_breakpoint, Cvoid, (Any,), obj)","category":"page"},{"location":"devdocs/debuggingtips/","page":"gdb 调试提示","title":"gdb 调试提示","text":"where obj can be any variable or tuple you want to be accessible in the breakpoint.","category":"page"},{"location":"devdocs/debuggingtips/","page":"gdb 调试提示","title":"gdb 调试提示","text":"It's particularly helpful to back up to the jl_apply frame, from which you can display the arguments to a function using, e.g.,","category":"page"},{"location":"devdocs/debuggingtips/","page":"gdb 调试提示","title":"gdb 调试提示","text":"(gdb) call jl_(args[0])","category":"page"},{"location":"devdocs/debuggingtips/","page":"gdb 调试提示","title":"gdb 调试提示","text":"Another useful frame is to_function(jl_method_instance_t *li, bool cstyle). The jl_method_instance_t* argument is a struct with a reference to the final AST sent into the compiler. However, the AST at this point will usually be compressed; to view the AST, call jl_uncompress_ast and then pass the result to jl_:","category":"page"},{"location":"devdocs/debuggingtips/","page":"gdb 调试提示","title":"gdb 调试提示","text":"#2 0x00007ffff7928bf7 in to_function (li=0x2812060, cstyle=false) at codegen.cpp:584\n584 abort();\n(gdb) p jl_(jl_uncompress_ast(li, li->ast))","category":"page"},{"location":"devdocs/debuggingtips/#Inserting-breakpoints-upon-certain-conditions","page":"gdb 调试提示","title":"Inserting breakpoints upon certain conditions","text":"","category":"section"},{"location":"devdocs/debuggingtips/#Loading-a-particular-file","page":"gdb 调试提示","title":"Loading a particular file","text":"","category":"section"},{"location":"devdocs/debuggingtips/","page":"gdb 调试提示","title":"gdb 调试提示","text":"Let's say the file is sysimg.jl:","category":"page"},{"location":"devdocs/debuggingtips/","page":"gdb 调试提示","title":"gdb 调试提示","text":"(gdb) break jl_load if strcmp(fname, \"sysimg.jl\")==0","category":"page"},{"location":"devdocs/debuggingtips/#Calling-a-particular-method","page":"gdb 调试提示","title":"Calling a particular method","text":"","category":"section"},{"location":"devdocs/debuggingtips/","page":"gdb 调试提示","title":"gdb 调试提示","text":"(gdb) break jl_apply_generic if strcmp((char*)(jl_symbol_name)(jl_gf_mtable(F)->name), \"method_to_break\")==0","category":"page"},{"location":"devdocs/debuggingtips/","page":"gdb 调试提示","title":"gdb 调试提示","text":"Since this function is used for every call, you will make everything 1000x slower if you do this.","category":"page"},{"location":"devdocs/debuggingtips/#Dealing-with-signals","page":"gdb 调试提示","title":"Dealing with signals","text":"","category":"section"},{"location":"devdocs/debuggingtips/","page":"gdb 调试提示","title":"gdb 调试提示","text":"Julia requires a few signal to function property. The profiler uses SIGUSR2 for sampling and the garbage collector uses SIGSEGV for threads synchronization. If you are debugging some code that uses the profiler or multiple threads, you may want to let the debugger ignore these signals since they can be triggered very often during normal operations. The command to do this in GDB is (replace SIGSEGV with SIGUSRS or other signals you want to ignore):","category":"page"},{"location":"devdocs/debuggingtips/","page":"gdb 调试提示","title":"gdb 调试提示","text":"(gdb) handle SIGSEGV noprint nostop pass","category":"page"},{"location":"devdocs/debuggingtips/","page":"gdb 调试提示","title":"gdb 调试提示","text":"The corresponding LLDB command is (after the process is started):","category":"page"},{"location":"devdocs/debuggingtips/","page":"gdb 调试提示","title":"gdb 调试提示","text":"(lldb) pro hand -p true -s false -n false SIGSEGV","category":"page"},{"location":"devdocs/debuggingtips/","page":"gdb 调试提示","title":"gdb 调试提示","text":"If you are debugging a segfault with threaded code, you can set a breakpoint on jl_critical_error (sigdie_handler should also work on Linux and BSD) in order to only catch the actual segfault rather than the GC synchronization points.","category":"page"},{"location":"devdocs/debuggingtips/#Debugging-during-Julia's-build-process-(bootstrap)","page":"gdb 调试提示","title":"Debugging during Julia's build process (bootstrap)","text":"","category":"section"},{"location":"devdocs/debuggingtips/","page":"gdb 调试提示","title":"gdb 调试提示","text":"Errors that occur during make need special handling. Julia is built in two stages, constructing sys0 and sys.ji. To see what commands are running at the time of failure, use make VERBOSE=1.","category":"page"},{"location":"devdocs/debuggingtips/","page":"gdb 调试提示","title":"gdb 调试提示","text":"At the time of this writing, you can debug build errors during the sys0 phase from the base directory using:","category":"page"},{"location":"devdocs/debuggingtips/","page":"gdb 调试提示","title":"gdb 调试提示","text":"julia/base$ gdb --args ../usr/bin/julia-debug -C native --build ../usr/lib/julia/sys0 sysimg.jl","category":"page"},{"location":"devdocs/debuggingtips/","page":"gdb 调试提示","title":"gdb 调试提示","text":"You might need to delete all the files in usr/lib/julia/ to get this to work.","category":"page"},{"location":"devdocs/debuggingtips/","page":"gdb 调试提示","title":"gdb 调试提示","text":"You can debug the sys.ji phase using:","category":"page"},{"location":"devdocs/debuggingtips/","page":"gdb 调试提示","title":"gdb 调试提示","text":"julia/base$ gdb --args ../usr/bin/julia-debug -C native --build ../usr/lib/julia/sys -J ../usr/lib/julia/sys0.ji sysimg.jl","category":"page"},{"location":"devdocs/debuggingtips/","page":"gdb 调试提示","title":"gdb 调试提示","text":"By default, any errors will cause Julia to exit, even under gdb. To catch an error \"in the act\", set a breakpoint in jl_error (there are several other useful spots, for specific kinds of failures, including: jl_too_few_args, jl_too_many_args, and jl_throw).","category":"page"},{"location":"devdocs/debuggingtips/","page":"gdb 调试提示","title":"gdb 调试提示","text":"Once an error is caught, a useful technique is to walk up the stack and examine the function by inspecting the related call to jl_apply. To take a real-world example:","category":"page"},{"location":"devdocs/debuggingtips/","page":"gdb 调试提示","title":"gdb 调试提示","text":"Breakpoint 1, jl_throw (e=0x7ffdf42de400) at task.c:802\n802 {\n(gdb) p jl_(e)\nErrorException(\"auto_unbox: unable to determine argument type\")\n$2 = void\n(gdb) bt 10\n#0 jl_throw (e=0x7ffdf42de400) at task.c:802\n#1 0x00007ffff65412fe in jl_error (str=0x7ffde56be000 <_j_str267> \"auto_unbox:\n unable to determine argument type\")\n at builtins.c:39\n#2 0x00007ffde56bd01a in julia_convert_16886 ()\n#3 0x00007ffff6541154 in jl_apply (f=0x7ffdf367f630, args=0x7fffffffc2b0, nargs=2) at julia.h:1281\n...","category":"page"},{"location":"devdocs/debuggingtips/","page":"gdb 调试提示","title":"gdb 调试提示","text":"The most recent jl_apply is at frame #3, so we can go back there and look at the AST for the function julia_convert_16886. This is the uniqued name for some method of convert. f in this frame is a jl_function_t*, so we can look at the type signature, if any, from the specTypes field:","category":"page"},{"location":"devdocs/debuggingtips/","page":"gdb 调试提示","title":"gdb 调试提示","text":"(gdb) f 3\n#3 0x00007ffff6541154 in jl_apply (f=0x7ffdf367f630, args=0x7fffffffc2b0, nargs=2) at julia.h:1281\n1281 return f->fptr((jl_value_t*)f, args, nargs);\n(gdb) p f->linfo->specTypes\n$4 = (jl_tupletype_t *) 0x7ffdf39b1030\n(gdb) p jl_( f->linfo->specTypes )\nTuple{Type{Float32}, Float64} # <-- type signature for julia_convert_16886","category":"page"},{"location":"devdocs/debuggingtips/","page":"gdb 调试提示","title":"gdb 调试提示","text":"Then, we can look at the AST for this function:","category":"page"},{"location":"devdocs/debuggingtips/","page":"gdb 调试提示","title":"gdb 调试提示","text":"(gdb) p jl_( jl_uncompress_ast(f->linfo, f->linfo->ast) )\nExpr(:lambda, Array{Any, 1}[:#s29, :x], Array{Any, 1}[Array{Any, 1}[], Array{Any, 1}[Array{Any, 1}[:#s29, :Any, 0], Array{Any, 1}[:x, :Any, 0]], Array{Any, 1}[], 0], Expr(:body,\nExpr(:line, 90, :float.jl)::Any,\nExpr(:return, Expr(:call, :box, :Float32, Expr(:call, :fptrunc, :Float32, :x)::Any)::Any)::Any)::Any)::Any","category":"page"},{"location":"devdocs/debuggingtips/","page":"gdb 调试提示","title":"gdb 调试提示","text":"Finally, and perhaps most usefully, we can force the function to be recompiled in order to step through the codegen process. To do this, clear the cached functionObject from the jl_lamdbda_info_t*:","category":"page"},{"location":"devdocs/debuggingtips/","page":"gdb 调试提示","title":"gdb 调试提示","text":"(gdb) p f->linfo->functionObject\n$8 = (void *) 0x1289d070\n(gdb) set f->linfo->functionObject = NULL","category":"page"},{"location":"devdocs/debuggingtips/","page":"gdb 调试提示","title":"gdb 调试提示","text":"Then, set a breakpoint somewhere useful (e.g. emit_function, emit_expr, emit_call, etc.), and run codegen:","category":"page"},{"location":"devdocs/debuggingtips/","page":"gdb 调试提示","title":"gdb 调试提示","text":"(gdb) p jl_compile(f)\n... # your breakpoint here","category":"page"},{"location":"devdocs/debuggingtips/#Debugging-precompilation-errors","page":"gdb 调试提示","title":"Debugging precompilation errors","text":"","category":"section"},{"location":"devdocs/debuggingtips/","page":"gdb 调试提示","title":"gdb 调试提示","text":"Module precompilation spawns a separate Julia process to precompile each module. Setting a breakpoint or catching failures in a precompile worker requires attaching a debugger to the worker. The easiest approach is to set the debugger watch for new process launches matching a given name. For example:","category":"page"},{"location":"devdocs/debuggingtips/","page":"gdb 调试提示","title":"gdb 调试提示","text":"(gdb) attach -w -n julia-debug","category":"page"},{"location":"devdocs/debuggingtips/","page":"gdb 调试提示","title":"gdb 调试提示","text":"or:","category":"page"},{"location":"devdocs/debuggingtips/","page":"gdb 调试提示","title":"gdb 调试提示","text":"(lldb) process attach -w -n julia-debug","category":"page"},{"location":"devdocs/debuggingtips/","page":"gdb 调试提示","title":"gdb 调试提示","text":"Then run a script/command to start precompilation. As described earlier, use conditional breakpoints in the parent process to catch specific file-loading events and narrow the debugging window. (some operating systems may require alternative approaches, such as following each fork from the parent process)","category":"page"},{"location":"devdocs/debuggingtips/#Mozilla's-Record-and-Replay-Framework-(rr)","page":"gdb 调试提示","title":"Mozilla's Record and Replay Framework (rr)","text":"","category":"section"},{"location":"devdocs/debuggingtips/","page":"gdb 调试提示","title":"gdb 调试提示","text":"Julia now works out of the box with rr, the lightweight recording and deterministic debugging framework from Mozilla. This allows you to replay the trace of an execution deterministically. The replayed execution's address spaces, register contents, syscall data etc are exactly the same in every run.","category":"page"},{"location":"devdocs/debuggingtips/","page":"gdb 调试提示","title":"gdb 调试提示","text":"A recent version of rr (3.1.0 or higher) is required.","category":"page"},{"location":"devdocs/debuggingtips/#Reproducing-concurrency-bugs-with-rr","page":"gdb 调试提示","title":"Reproducing concurrency bugs with rr","text":"","category":"section"},{"location":"devdocs/debuggingtips/","page":"gdb 调试提示","title":"gdb 调试提示","text":"rr simulates a single-threaded machine by default. In order to debug concurrent code you can use rr record --chaos which will cause rr to simulate between one to eight cores, chosen randomly. You might therefore want to set JULIA_NUM_THREADS=8 and rerun your code under rr until you have caught your bug.","category":"page"},{"location":"manual/stacktraces/#栈跟踪","page":"栈跟踪","title":"栈跟踪","text":"","category":"section"},{"location":"manual/stacktraces/","page":"栈跟踪","title":"栈跟踪","text":"StackTraces 模块提供了简单的栈跟踪功能,这些栈跟踪信息既可读又易于编程使用。","category":"page"},{"location":"manual/stacktraces/#查看栈跟踪","page":"栈跟踪","title":"查看栈跟踪","text":"","category":"section"},{"location":"manual/stacktraces/","page":"栈跟踪","title":"栈跟踪","text":"获取栈跟踪信息的主要函数是 stacktrace:","category":"page"},{"location":"manual/stacktraces/","page":"栈跟踪","title":"栈跟踪","text":"6-element Array{Base.StackTraces.StackFrame,1}:\n top-level scope\n eval at boot.jl:317 [inlined]\n eval(::Module, ::Expr) at REPL.jl:5\n eval_user_input(::Any, ::REPL.REPLBackend) at REPL.jl:85\n macro expansion at REPL.jl:116 [inlined]\n (::getfield(REPL, Symbol(\"##28#29\")){REPL.REPLBackend})() at event.jl:92","category":"page"},{"location":"manual/stacktraces/","page":"栈跟踪","title":"栈跟踪","text":"调用 stacktrace() 会返回一个 StackTraces.StackFrame 数组。为了使用方便,可以用 StackTraces.StackTrace 来代替 Vector{StackFrame}。下面例子中 [...] 的意思是这部分输出的内容可能会根据代码的实际执行情况而定。","category":"page"},{"location":"manual/stacktraces/","page":"栈跟踪","title":"栈跟踪","text":"julia> example() = stacktrace()\nexample (generic function with 1 method)\n\njulia> example()\n7-element Array{Base.StackTraces.StackFrame,1}:\n example() at REPL[1]:1\n top-level scope\n eval at boot.jl:317 [inlined]\n[...]\n\njulia> @noinline child() = stacktrace()\nchild (generic function with 1 method)\n\njulia> @noinline parent() = child()\nparent (generic function with 1 method)\n\njulia> grandparent() = parent()\ngrandparent (generic function with 1 method)\n\njulia> grandparent()\n9-element Array{Base.StackTraces.StackFrame,1}:\n child() at REPL[3]:1\n parent() at REPL[4]:1\n grandparent() at REPL[5]:1\n[...]","category":"page"},{"location":"manual/stacktraces/","page":"栈跟踪","title":"栈跟踪","text":"注意,在调用 stacktrace() 的时,通常会出现 eval at boot.jl 这帧。 当从 REPL 里调用 stacktrace() 的时候,还会显示 REPL.jl 里的一些额外帧,就像下面一样:","category":"page"},{"location":"manual/stacktraces/","page":"栈跟踪","title":"栈跟踪","text":"julia> example() = stacktrace()\nexample (generic function with 1 method)\n\njulia> example()\n7-element Array{Base.StackTraces.StackFrame,1}:\n example() at REPL[1]:1\n top-level scope\n eval at boot.jl:317 [inlined]\n eval(::Module, ::Expr) at REPL.jl:5\n eval_user_input(::Any, ::REPL.REPLBackend) at REPL.jl:85\n macro expansion at REPL.jl:116 [inlined]\n (::getfield(REPL, Symbol(\"##28#29\")){REPL.REPLBackend})() at event.jl:92","category":"page"},{"location":"manual/stacktraces/#抽取有用信息","page":"栈跟踪","title":"抽取有用信息","text":"","category":"section"},{"location":"manual/stacktraces/","page":"栈跟踪","title":"栈跟踪","text":"每个 StackTraces.StackFrame 都会包含函数名,文件名,代码行数,lambda 信息,一个用于确认此帧是否被内联的标帜,一个用于确认函数是否为 C 函数的标帜(在默认的情况下 C 函数不会出现在栈跟踪信息中)以及一个用整数表示的指针,它是由 backtrace 返回的:","category":"page"},{"location":"manual/stacktraces/","page":"栈跟踪","title":"栈跟踪","text":"julia> frame = stacktrace()[3]\neval(::Module, ::Expr) at REPL.jl:5\n\njulia> frame.func\n:eval\n\njulia> frame.file\nSymbol(\"~/julia/usr/share/julia/stdlib/v0.7/REPL/src/REPL.jl\")\n\njulia> frame.line\n5\n\njulia> frame.linfo\nMethodInstance for eval(::Module, ::Expr)\n\njulia> frame.inlined\nfalse\n\njulia> frame.from_c\nfalse\n\njulia> frame.pointer\n0x00007f92d6293171","category":"page"},{"location":"manual/stacktraces/","page":"栈跟踪","title":"栈跟踪","text":"这使得我们可以通过编程的方式将栈跟踪信息用于打印日志,处理错误以及其它更多用途。","category":"page"},{"location":"manual/stacktraces/#错误处理","page":"栈跟踪","title":"错误处理","text":"","category":"section"},{"location":"manual/stacktraces/","page":"栈跟踪","title":"栈跟踪","text":"能够轻松地获取当前调用栈的状态信息在许多场景下都很有用,但最直接的应用是错误处理和调试。","category":"page"},{"location":"manual/stacktraces/","page":"栈跟踪","title":"栈跟踪","text":"julia> @noinline bad_function() = undeclared_variable\nbad_function (generic function with 1 method)\n\njulia> @noinline example() = try\n bad_function()\n catch\n stacktrace()\n end\nexample (generic function with 1 method)\n\njulia> example()\n7-element Array{Base.StackTraces.StackFrame,1}:\n example() at REPL[2]:4\n top-level scope\n eval at boot.jl:317 [inlined]\n[...]","category":"page"},{"location":"manual/stacktraces/","page":"栈跟踪","title":"栈跟踪","text":"你可能已经注意到了,上述例子中第一个栈帧指向了stacktrace被调用的第 4 行,而不是 bad_function 被调用的第 2 行,且完全没有出现 bad_function 的栈帧。这是也是可以理解的,因为 stacktrace 是在 catch 的上下文中被调用的。虽然在这个例子中很容易查找到错误的真正源头,但在复杂的情况下查找错误源并不是一件容易的事。","category":"page"},{"location":"manual/stacktraces/","page":"栈跟踪","title":"栈跟踪","text":"为了补救,我们可以将 catch_backtrace 的输出传递给 stacktrace。catch_backtrace 会返回最近发生异常的上下文中的栈信息,而不是返回当前上下文中的调用栈信息。","category":"page"},{"location":"manual/stacktraces/","page":"栈跟踪","title":"栈跟踪","text":"julia> @noinline bad_function() = undeclared_variable\nbad_function (generic function with 1 method)\n\njulia> @noinline example() = try\n bad_function()\n catch\n stacktrace(catch_backtrace())\n end\nexample (generic function with 1 method)\n\njulia> example()\n8-element Array{Base.StackTraces.StackFrame,1}:\n bad_function() at REPL[1]:1\n example() at REPL[2]:2\n[...]","category":"page"},{"location":"manual/stacktraces/","page":"栈跟踪","title":"栈跟踪","text":"可以看到,现在栈跟踪会显示正确的行号以及之前缺失的栈帧。","category":"page"},{"location":"manual/stacktraces/","page":"栈跟踪","title":"栈跟踪","text":"julia> @noinline child() = error(\"Whoops!\")\nchild (generic function with 1 method)\n\njulia> @noinline parent() = child()\nparent (generic function with 1 method)\n\njulia> @noinline function grandparent()\n try\n parent()\n catch err\n println(\"ERROR: \", err.msg)\n stacktrace(catch_backtrace())\n end\n end\ngrandparent (generic function with 1 method)\n\njulia> grandparent()\nERROR: Whoops!\n10-element Array{Base.StackTraces.StackFrame,1}:\n error at error.jl:33 [inlined]\n child() at REPL[1]:1\n parent() at REPL[2]:1\n grandparent() at REPL[3]:3\n[...]","category":"page"},{"location":"manual/stacktraces/#异常栈与[current_exceptions](@ref)","page":"栈跟踪","title":"异常栈与current_exceptions","text":"","category":"section"},{"location":"manual/stacktraces/","page":"栈跟踪","title":"栈跟踪","text":"compat: Julia 1.1\n异常栈需要 Julia 1.1 及以上版本。","category":"page"},{"location":"manual/stacktraces/","page":"栈跟踪","title":"栈跟踪","text":"在处理一个异常时,后续的异常同样可能被抛出。观察这些异常对定位问题的源头极有帮助。Julia runtime 支持将每个异常发生后推入一个内部的异常栈。当代码正常退出一个catch语句,可认为所有被推入栈中的异常在相应的try语句中被成功处理并已从栈中移除。","category":"page"},{"location":"manual/stacktraces/","page":"栈跟踪","title":"栈跟踪","text":"存放当前异常的栈可通过测试函数 current_exceptions 获取,例如","category":"page"},{"location":"manual/stacktraces/","page":"栈跟踪","title":"栈跟踪","text":"julia> try\n error(\"(A) The root cause\")\n catch\n try\n error(\"(B) An exception while handling the exception\")\n catch\n for (exc, bt) in current_exceptions()\n showerror(stdout, exc, bt)\n println(stdout)\n end\n end\n end\n(A) The root cause\nStacktrace:\n [1] error(::String) at error.jl:33\n [2] top-level scope at REPL[7]:2\n [3] eval(::Module, ::Any) at boot.jl:319\n [4] eval_user_input(::Any, ::REPL.REPLBackend) at REPL.jl:85\n [5] macro expansion at REPL.jl:117 [inlined]\n [6] (::getfield(REPL, Symbol(\"##26#27\")){REPL.REPLBackend})() at task.jl:259\n(B) An exception while handling the exception\nStacktrace:\n [1] error(::String) at error.jl:33\n [2] top-level scope at REPL[7]:5\n [3] eval(::Module, ::Any) at boot.jl:319\n [4] eval_user_input(::Any, ::REPL.REPLBackend) at REPL.jl:85\n [5] macro expansion at REPL.jl:117 [inlined]\n [6] (::getfield(REPL, Symbol(\"##26#27\")){REPL.REPLBackend})() at task.jl:259","category":"page"},{"location":"manual/stacktraces/","page":"栈跟踪","title":"栈跟踪","text":"在本例中,根源异常(A)排在栈头,其后放置着延伸异常(B)。 在正常退出(例如,不抛出新异常)两个 catch 块后,所有异常都被移除出栈,无法访问。","category":"page"},{"location":"manual/stacktraces/","page":"栈跟踪","title":"栈跟踪","text":"异常栈被存放于发生异常的 Task 处。当某个任务失败,出现意料外的异常时,current_exceptions(task) 可被用于观察该任务的异常栈。","category":"page"},{"location":"manual/stacktraces/#[stacktrace](@ref)-与-[backtrace](@ref)-的比较","page":"栈跟踪","title":"stacktrace 与 backtrace 的比较","text":"","category":"section"},{"location":"manual/stacktraces/","page":"栈跟踪","title":"栈跟踪","text":"调用 backtrace 会返回一个 Union{Ptr{Nothing}, Base.InterpreterIP} 的数组,可以将其传给 stacktrace 函数进行转化:","category":"page"},{"location":"manual/stacktraces/","page":"栈跟踪","title":"栈跟踪","text":"julia> trace = backtrace()\n18-element Array{Union{Ptr{Nothing}, Base.InterpreterIP},1}:\n Ptr{Nothing} @0x00007fd8734c6209\n Ptr{Nothing} @0x00007fd87362b342\n Ptr{Nothing} @0x00007fd87362c136\n Ptr{Nothing} @0x00007fd87362c986\n Ptr{Nothing} @0x00007fd87362d089\n Base.InterpreterIP(CodeInfo(:(begin\n Core.SSAValue(0) = backtrace()\n trace = Core.SSAValue(0)\n return Core.SSAValue(0)\n end)), 0x0000000000000000)\n Ptr{Nothing} @0x00007fd87362e4cf\n[...]\n\njulia> stacktrace(trace)\n6-element Array{Base.StackTraces.StackFrame,1}:\n top-level scope\n eval at boot.jl:317 [inlined]\n eval(::Module, ::Expr) at REPL.jl:5\n eval_user_input(::Any, ::REPL.REPLBackend) at REPL.jl:85\n macro expansion at REPL.jl:116 [inlined]\n (::getfield(REPL, Symbol(\"##28#29\")){REPL.REPLBackend})() at event.jl:92","category":"page"},{"location":"manual/stacktraces/","page":"栈跟踪","title":"栈跟踪","text":"需要注意的是,backtrace 返回的向量有 18 个元素,而 stacktrace 返回的向量只包含6 个元素。这是因为 stacktrace 在默认情况下会移除所有底层 C 函数的栈信息。如果你想显示 C 函数调用的栈帧,可以这样做:","category":"page"},{"location":"manual/stacktraces/","page":"栈跟踪","title":"栈跟踪","text":"julia> stacktrace(trace, true)\n21-element Array{Base.StackTraces.StackFrame,1}:\n jl_apply_generic at gf.c:2167\n do_call at interpreter.c:324\n eval_value at interpreter.c:416\n eval_body at interpreter.c:559\n jl_interpret_toplevel_thunk_callback at interpreter.c:798\n top-level scope\n jl_interpret_toplevel_thunk at interpreter.c:807\n jl_toplevel_eval_flex at toplevel.c:856\n jl_toplevel_eval_in at builtins.c:624\n eval at boot.jl:317 [inlined]\n eval(::Module, ::Expr) at REPL.jl:5\n jl_apply_generic at gf.c:2167\n eval_user_input(::Any, ::REPL.REPLBackend) at REPL.jl:85\n jl_apply_generic at gf.c:2167\n macro expansion at REPL.jl:116 [inlined]\n (::getfield(REPL, Symbol(\"##28#29\")){REPL.REPLBackend})() at event.jl:92\n jl_fptr_trampoline at gf.c:1838\n jl_apply_generic at gf.c:2167\n jl_apply at julia.h:1540 [inlined]\n start_task at task.c:268\n ip:0xffffffffffffffff","category":"page"},{"location":"manual/stacktraces/","page":"栈跟踪","title":"栈跟踪","text":"backtrace 返回的单个指针可以通过 StackTraces.lookup 来转化成一组 StackTraces.StackFrame:","category":"page"},{"location":"manual/stacktraces/","page":"栈跟踪","title":"栈跟踪","text":"julia> pointer = backtrace()[1];\n\njulia> frame = StackTraces.lookup(pointer)\n1-element Array{Base.StackTraces.StackFrame,1}:\n jl_apply_generic at gf.c:2167\n\njulia> println(\"The top frame is from $(frame[1].func)!\")\nThe top frame is from jl_apply_generic!","category":"page"},{"location":"base/collections/#集合和数据结构","page":"集合和数据结构","title":"集合和数据结构","text":"","category":"section"},{"location":"base/collections/#lib-collections-iteration","page":"集合和数据结构","title":"迭代","text":"","category":"section"},{"location":"base/collections/","page":"集合和数据结构","title":"集合和数据结构","text":"序列迭代由 iterate 实现 广义的 for 循环","category":"page"},{"location":"base/collections/","page":"集合和数据结构","title":"集合和数据结构","text":"for i in iter # or \"for i = iter\"\n # body\nend","category":"page"},{"location":"base/collections/","page":"集合和数据结构","title":"集合和数据结构","text":"被转换成","category":"page"},{"location":"base/collections/","page":"集合和数据结构","title":"集合和数据结构","text":"next = iterate(iter)\nwhile next !== nothing\n (i, state) = next\n # body\n next = iterate(iter, state)\nend","category":"page"},{"location":"base/collections/","page":"集合和数据结构","title":"集合和数据结构","text":"state 对象可以是任何对象,并且对于每个可迭代类型应该选择合适的 state 对象。 请参照 帮助文档接口的迭代小节 来获取关于定义一个常见迭代类型的更多细节。","category":"page"},{"location":"base/collections/","page":"集合和数据结构","title":"集合和数据结构","text":"Base.iterate\nBase.IteratorSize\nBase.IteratorEltype","category":"page"},{"location":"base/collections/#Base.iterate","page":"集合和数据结构","title":"Base.iterate","text":"iterate(iter [, state]) -> Union{Nothing, Tuple{Any, Any}}\n\nAdvance the iterator to obtain the next element. If no elements remain, nothing should be returned. Otherwise, a 2-tuple of the next element and the new iteration state should be returned.\n\n\n\n\n\n","category":"function"},{"location":"base/collections/#Base.IteratorSize","page":"集合和数据结构","title":"Base.IteratorSize","text":"IteratorSize(itertype::Type) -> IteratorSize\n\nGiven the type of an iterator, return one of the following values:\n\nSizeUnknown() if the length (number of elements) cannot be determined in advance.\nHasLength() if there is a fixed, finite length.\nHasShape{N}() if there is a known length plus a notion of multidimensional shape (as for an array). In this case N should give the number of dimensions, and the axes function is valid for the iterator.\nIsInfinite() if the iterator yields values forever.\n\nThe default value (for iterators that do not define this function) is HasLength(). This means that most iterators are assumed to implement length.\n\nThis trait is generally used to select between algorithms that pre-allocate space for their result, and algorithms that resize their result incrementally.\n\njulia> Base.IteratorSize(1:5)\nBase.HasShape{1}()\n\njulia> Base.IteratorSize((2,3))\nBase.HasLength()\n\n\n\n\n\n","category":"type"},{"location":"base/collections/#Base.IteratorEltype","page":"集合和数据结构","title":"Base.IteratorEltype","text":"IteratorEltype(itertype::Type) -> IteratorEltype\n\nGiven the type of an iterator, return one of the following values:\n\nEltypeUnknown() if the type of elements yielded by the iterator is not known in advance.\nHasEltype() if the element type is known, and eltype would return a meaningful value.\n\nHasEltype() is the default, since iterators are assumed to implement eltype.\n\nThis trait is generally used to select between algorithms that pre-allocate a specific type of result, and algorithms that pick a result type based on the types of yielded values.\n\njulia> Base.IteratorEltype(1:5)\nBase.HasEltype()\n\n\n\n\n\n","category":"type"},{"location":"base/collections/","page":"集合和数据结构","title":"集合和数据结构","text":"以下类型均完全实现了上述函数:","category":"page"},{"location":"base/collections/","page":"集合和数据结构","title":"集合和数据结构","text":"AbstractRange\nUnitRange\nTuple\nNumber\nAbstractArray\nBitSet\nIdDict\nDict\nWeakKeyDict\nEachLine\nAbstractString\nSet\nPair\nNamedTuple","category":"page"},{"location":"base/collections/#构造函数和类型","page":"集合和数据结构","title":"构造函数和类型","text":"","category":"section"},{"location":"base/collections/","page":"集合和数据结构","title":"集合和数据结构","text":"Base.AbstractRange\nBase.OrdinalRange\nBase.AbstractUnitRange\nBase.StepRange\nBase.UnitRange\nBase.LinRange","category":"page"},{"location":"base/collections/#Base.AbstractRange","page":"集合和数据结构","title":"Base.AbstractRange","text":"AbstractRange{T}\n\nSupertype for ranges with elements of type T. UnitRange and other types are subtypes of this.\n\n\n\n\n\n","category":"type"},{"location":"base/collections/#Base.OrdinalRange","page":"集合和数据结构","title":"Base.OrdinalRange","text":"OrdinalRange{T, S} <: AbstractRange{T}\n\nSupertype for ordinal ranges with elements of type T with spacing(s) of type S. The steps should be always-exact multiples of oneunit, and T should be a \"discrete\" type, which cannot have values smaller than oneunit. For example, Integer or Date types would qualify, whereas Float64 would not (since this type can represent values smaller than oneunit(Float64). UnitRange, StepRange, and other types are subtypes of this.\n\n\n\n\n\n","category":"type"},{"location":"base/collections/#Base.AbstractUnitRange","page":"集合和数据结构","title":"Base.AbstractUnitRange","text":"AbstractUnitRange{T} <: OrdinalRange{T, T}\n\nSupertype for ranges with a step size of oneunit(T) with elements of type T. UnitRange and other types are subtypes of this.\n\n\n\n\n\n","category":"type"},{"location":"base/collections/#Base.StepRange","page":"集合和数据结构","title":"Base.StepRange","text":"StepRange{T, S} <: OrdinalRange{T, S}\n\nRanges with elements of type T with spacing of type S. The step between each element is constant, and the range is defined in terms of a start and stop of type T and a step of type S. Neither T nor S should be floating point types. The syntax a:b:c with b > 1 and a, b, and c all integers creates a StepRange.\n\nExamples\n\njulia> collect(StepRange(1, Int8(2), 10))\n5-element Vector{Int64}:\n 1\n 3\n 5\n 7\n 9\n\njulia> typeof(StepRange(1, Int8(2), 10))\nStepRange{Int64, Int8}\n\njulia> typeof(1:3:6)\nStepRange{Int64, Int64}\n\n\n\n\n\n","category":"type"},{"location":"base/collections/#Base.UnitRange","page":"集合和数据结构","title":"Base.UnitRange","text":"UnitRange{T<:Real}\n\nA range parameterized by a start and stop of type T, filled with elements spaced by 1 from start until stop is exceeded. The syntax a:b with a and b both Integers creates a UnitRange.\n\nExamples\n\njulia> collect(UnitRange(2.3, 5.2))\n3-element Vector{Float64}:\n 2.3\n 3.3\n 4.3\n\njulia> typeof(1:10)\nUnitRange{Int64}\n\n\n\n\n\n","category":"type"},{"location":"base/collections/#Base.LinRange","page":"集合和数据结构","title":"Base.LinRange","text":"LinRange{T,L}\n\nA range with len linearly spaced elements between its start and stop. The size of the spacing is controlled by len, which must be an Integer.\n\nExamples\n\njulia> LinRange(1.5, 5.5, 9)\n9-element LinRange{Float64, Int64}:\n 1.5,2.0,2.5,3.0,3.5,4.0,4.5,5.0,5.5\n\nCompared to using range, directly constructing a LinRange should have less overhead but won't try to correct for floating point errors:\n\njulia> collect(range(-0.1, 0.3, length=5))\n5-element Vector{Float64}:\n -0.1\n 0.0\n 0.1\n 0.2\n 0.3\n\njulia> collect(LinRange(-0.1, 0.3, 5))\n5-element Vector{Float64}:\n -0.1\n -1.3877787807814457e-17\n 0.09999999999999999\n 0.19999999999999998\n 0.3\n\n\n\n\n\n","category":"type"},{"location":"base/collections/#通用集合","page":"集合和数据结构","title":"通用集合","text":"","category":"section"},{"location":"base/collections/","page":"集合和数据结构","title":"集合和数据结构","text":"Base.isempty\nBase.empty!\nBase.length\nBase.checked_length","category":"page"},{"location":"base/collections/#Base.isempty","page":"集合和数据结构","title":"Base.isempty","text":"isempty(collection) -> Bool\n\nDetermine whether a collection is empty (has no elements).\n\nExamples\n\njulia> isempty([])\ntrue\n\njulia> isempty([1 2 3])\nfalse\n\n\n\n\n\nisempty(condition)\n\nReturn true if no tasks are waiting on the condition, false otherwise.\n\n\n\n\n\n","category":"function"},{"location":"base/collections/#Base.empty!","page":"集合和数据结构","title":"Base.empty!","text":"empty!(collection) -> collection\n\nRemove all elements from a collection.\n\nExamples\n\njulia> A = Dict(\"a\" => 1, \"b\" => 2)\nDict{String, Int64} with 2 entries:\n \"b\" => 2\n \"a\" => 1\n\njulia> empty!(A);\n\njulia> A\nDict{String, Int64}()\n\n\n\n\n\n","category":"function"},{"location":"base/collections/#Base.length","page":"集合和数据结构","title":"Base.length","text":"length(collection) -> Integer\n\nReturn the number of elements in the collection.\n\nUse lastindex to get the last valid index of an indexable collection.\n\nSee also: size, ndims, eachindex.\n\nExamples\n\njulia> length(1:5)\n5\n\njulia> length([1, 2, 3, 4])\n4\n\njulia> length([1 2; 3 4])\n4\n\n\n\n\n\n","category":"function"},{"location":"base/collections/#Base.checked_length","page":"集合和数据结构","title":"Base.checked_length","text":"Base.checked_length(r)\n\nCalculates length(r), but may check for overflow errors where applicable when the result doesn't fit into Union{Integer(eltype(r)),Int}.\n\n\n\n\n\n","category":"function"},{"location":"base/collections/","page":"集合和数据结构","title":"集合和数据结构","text":"以下类型均完全实现了上述函数:","category":"page"},{"location":"base/collections/","page":"集合和数据结构","title":"集合和数据结构","text":"AbstractRange\nUnitRange\nTuple\nNumber\nAbstractArray\nBitSet\nIdDict\nDict\nWeakKeyDict\nAbstractString\nSet\nNamedTuple","category":"page"},{"location":"base/collections/#可迭代集合","page":"集合和数据结构","title":"可迭代集合","text":"","category":"section"},{"location":"base/collections/","page":"集合和数据结构","title":"集合和数据结构","text":"Base.in\nBase.:∉\nBase.eltype\nBase.indexin\nBase.unique\nBase.unique!\nBase.allunique\nBase.reduce(::Any, ::Any)\nBase.foldl(::Any, ::Any)\nBase.foldr(::Any, ::Any)\nBase.maximum\nBase.maximum!\nBase.minimum\nBase.minimum!\nBase.extrema\nBase.argmax\nBase.argmin\nBase.findmax\nBase.findmin\nBase.findmax!\nBase.findmin!\nBase.sum\nBase.sum!\nBase.prod\nBase.prod!\nBase.any(::Any)\nBase.any(::AbstractArray, ::Any)\nBase.any!\nBase.all(::Any)\nBase.all(::AbstractArray, ::Any)\nBase.all!\nBase.count\nBase.any(::Any, ::Any)\nBase.all(::Any, ::Any)\nBase.foreach\nBase.map\nBase.map!\nBase.mapreduce(::Any, ::Any, ::Any)\nBase.mapfoldl(::Any, ::Any, ::Any)\nBase.mapfoldr(::Any, ::Any, ::Any)\nBase.first\nBase.last\nBase.front\nBase.tail\nBase.step\nBase.collect(::Any)\nBase.collect(::Type, ::Any)\nBase.filter\nBase.filter!\nBase.replace(::Any, ::Pair...)\nBase.replace(::Base.Callable, ::Any)\nBase.replace!\nBase.rest","category":"page"},{"location":"base/collections/#Base.in","page":"集合和数据结构","title":"Base.in","text":"in(item, collection) -> Bool\n∈(item, collection) -> Bool\n\nDetermine whether an item is in the given collection, in the sense that it is == to one of the values generated by iterating over the collection. Returns a Bool value, except if item is missing or collection contains missing but not item, in which case missing is returned (three-valued logic, matching the behavior of any and ==).\n\nSome collections follow a slightly different definition. For example, Sets check whether the item isequal to one of the elements. Dicts look for key=>value pairs, and the key is compared using isequal. To test for the presence of a key in a dictionary, use haskey or k in keys(dict). For these collections, the result is always a Bool and never missing.\n\nTo determine whether an item is not in a given collection, see :∉. You may also negate the in by doing !(a in b) which is logically similar to \"not in\".\n\nWhen broadcasting with in.(items, collection) or items .∈ collection, both item and collection are broadcasted over, which is often not what is intended. For example, if both arguments are vectors (and the dimensions match), the result is a vector indicating whether each value in collection items is in the value at the corresponding position in collection. To get a vector indicating whether each value in items is in collection, wrap collection in a tuple or a Ref like this: in.(items, Ref(collection)) or items .∈ Ref(collection).\n\nExamples\n\njulia> a = 1:3:20\n1:3:19\n\njulia> 4 in a\ntrue\n\njulia> 5 in a\nfalse\n\njulia> missing in [1, 2]\nmissing\n\njulia> 1 in [2, missing]\nmissing\n\njulia> 1 in [1, missing]\ntrue\n\njulia> missing in Set([1, 2])\nfalse\n\njulia> !(21 in a)\ntrue\n\njulia> !(19 in a)\nfalse\n\njulia> [1, 2] .∈ [2, 3]\n2-element BitVector:\n 0\n 0\n\njulia> [1, 2] .∈ ([2, 3],)\n2-element BitVector:\n 0\n 1\n\nSee also: insorted, contains, occursin, issubset.\n\n\n\n\n\n","category":"function"},{"location":"base/collections/#Base.:∉","page":"集合和数据结构","title":"Base.:∉","text":"∉(item, collection) -> Bool\n∌(collection, item) -> Bool\n\nNegation of ∈ and ∋, i.e. checks that item is not in collection.\n\nWhen broadcasting with items .∉ collection, both item and collection are broadcasted over, which is often not what is intended. For example, if both arguments are vectors (and the dimensions match), the result is a vector indicating whether each value in collection items is not in the value at the corresponding position in collection. To get a vector indicating whether each value in items is not in collection, wrap collection in a tuple or a Ref like this: items .∉ Ref(collection).\n\nExamples\n\njulia> 1 ∉ 2:4\ntrue\n\njulia> 1 ∉ 1:3\nfalse\n\njulia> [1, 2] .∉ [2, 3]\n2-element BitVector:\n 1\n 1\n\njulia> [1, 2] .∉ ([2, 3],)\n2-element BitVector:\n 1\n 0\n\n\n\n\n\n","category":"function"},{"location":"base/collections/#Base.eltype","page":"集合和数据结构","title":"Base.eltype","text":"eltype(type)\n\nDetermine the type of the elements generated by iterating a collection of the given type. For dictionary types, this will be a Pair{KeyType,ValType}. The definition eltype(x) = eltype(typeof(x)) is provided for convenience so that instances can be passed instead of types. However the form that accepts a type argument should be defined for new types.\n\nSee also: keytype, typeof.\n\nExamples\n\njulia> eltype(fill(1f0, (2,2)))\nFloat32\n\njulia> eltype(fill(0x1, (2,2)))\nUInt8\n\n\n\n\n\n","category":"function"},{"location":"base/collections/#Base.indexin","page":"集合和数据结构","title":"Base.indexin","text":"indexin(a, b)\n\nReturn an array containing the first index in b for each value in a that is a member of b. The output array contains nothing wherever a is not a member of b.\n\nSee also: sortperm, findfirst.\n\nExamples\n\njulia> a = ['a', 'b', 'c', 'b', 'd', 'a'];\n\njulia> b = ['a', 'b', 'c'];\n\njulia> indexin(a, b)\n6-element Vector{Union{Nothing, Int64}}:\n 1\n 2\n 3\n 2\n nothing\n 1\n\njulia> indexin(b, a)\n3-element Vector{Union{Nothing, Int64}}:\n 1\n 2\n 3\n\n\n\n\n\n","category":"function"},{"location":"base/collections/#Base.unique","page":"集合和数据结构","title":"Base.unique","text":"unique(itr)\n\nReturn an array containing only the unique elements of collection itr, as determined by isequal, in the order that the first of each set of equivalent elements originally appears. The element type of the input is preserved.\n\nSee also: unique!, allunique, allequal.\n\nExamples\n\njulia> unique([1, 2, 6, 2])\n3-element Vector{Int64}:\n 1\n 2\n 6\n\njulia> unique(Real[1, 1.0, 2])\n2-element Vector{Real}:\n 1\n 2\n\n\n\n\n\nunique(f, itr)\n\nReturns an array containing one value from itr for each unique value produced by f applied to elements of itr.\n\nExamples\n\njulia> unique(x -> x^2, [1, -1, 3, -3, 4])\n3-element Vector{Int64}:\n 1\n 3\n 4\n\n\n\n\n\nunique(A::AbstractArray; dims::Int)\n\nReturn unique regions of A along dimension dims.\n\nExamples\n\njulia> A = map(isodd, reshape(Vector(1:8), (2,2,2)))\n2×2×2 Array{Bool, 3}:\n[:, :, 1] =\n 1 1\n 0 0\n\n[:, :, 2] =\n 1 1\n 0 0\n\njulia> unique(A)\n2-element Vector{Bool}:\n 1\n 0\n\njulia> unique(A, dims=2)\n2×1×2 Array{Bool, 3}:\n[:, :, 1] =\n 1\n 0\n\n[:, :, 2] =\n 1\n 0\n\njulia> unique(A, dims=3)\n2×2×1 Array{Bool, 3}:\n[:, :, 1] =\n 1 1\n 0 0\n\n\n\n\n\n","category":"function"},{"location":"base/collections/#Base.unique!","page":"集合和数据结构","title":"Base.unique!","text":"unique!(f, A::AbstractVector)\n\nSelects one value from A for each unique value produced by f applied to elements of A, then return the modified A.\n\ncompat: Julia 1.1\nThis method is available as of Julia 1.1.\n\nExamples\n\njulia> unique!(x -> x^2, [1, -1, 3, -3, 4])\n3-element Vector{Int64}:\n 1\n 3\n 4\n\njulia> unique!(n -> n%3, [5, 1, 8, 9, 3, 4, 10, 7, 2, 6])\n3-element Vector{Int64}:\n 5\n 1\n 9\n\njulia> unique!(iseven, [2, 3, 5, 7, 9])\n2-element Vector{Int64}:\n 2\n 3\n\n\n\n\n\nunique!(A::AbstractVector)\n\nRemove duplicate items as determined by isequal, then return the modified A. unique! will return the elements of A in the order that they occur. If you do not care about the order of the returned data, then calling (sort!(A); unique!(A)) will be much more efficient as long as the elements of A can be sorted.\n\nExamples\n\njulia> unique!([1, 1, 1])\n1-element Vector{Int64}:\n 1\n\njulia> A = [7, 3, 2, 3, 7, 5];\n\njulia> unique!(A)\n4-element Vector{Int64}:\n 7\n 3\n 2\n 5\n\njulia> B = [7, 6, 42, 6, 7, 42];\n\njulia> sort!(B); # unique! is able to process sorted data much more efficiently.\n\njulia> unique!(B)\n3-element Vector{Int64}:\n 6\n 7\n 42\n\n\n\n\n\n","category":"function"},{"location":"base/collections/#Base.allunique","page":"集合和数据结构","title":"Base.allunique","text":"allunique(itr) -> Bool\n\nReturn true if all values from itr are distinct when compared with isequal.\n\nSee also: unique, issorted, allequal.\n\nExamples\n\njulia> a = [1; 2; 3]\n3-element Vector{Int64}:\n 1\n 2\n 3\n\njulia> allunique(a)\ntrue\n\njulia> allunique([a, a])\nfalse\n\n\n\n\n\n","category":"function"},{"location":"base/collections/#Base.reduce-Tuple{Any, Any}","page":"集合和数据结构","title":"Base.reduce","text":"reduce(op, itr; [init])\n\nReduce the given collection itr with the given binary operator op. If provided, the initial value init must be a neutral element for op that will be returned for empty collections. It is unspecified whether init is used for non-empty collections.\n\nFor empty collections, providing init will be necessary, except for some special cases (e.g. when op is one of +, *, max, min, &, |) when Julia can determine the neutral element of op.\n\nReductions for certain commonly-used operators may have special implementations, and should be used instead: maximum(itr), minimum(itr), sum(itr), prod(itr), any(itr), all(itr).\n\nThe associativity of the reduction is implementation dependent. This means that you can't use non-associative operations like - because it is undefined whether reduce(-,[1,2,3]) should be evaluated as (1-2)-3 or 1-(2-3). Use foldl or foldr instead for guaranteed left or right associativity.\n\nSome operations accumulate error. Parallelism will be easier if the reduction can be executed in groups. Future versions of Julia might change the algorithm. Note that the elements are not reordered if you use an ordered collection.\n\nExamples\n\njulia> reduce(*, [2; 3; 4])\n24\n\njulia> reduce(*, [2; 3; 4]; init=-1)\n-24\n\n\n\n\n\n","category":"method"},{"location":"base/collections/#Base.foldl-Tuple{Any, Any}","page":"集合和数据结构","title":"Base.foldl","text":"foldl(op, itr; [init])\n\nLike reduce, but with guaranteed left associativity. If provided, the keyword argument init will be used exactly once. In general, it will be necessary to provide init to work with empty collections.\n\nSee also mapfoldl, foldr, accumulate.\n\nExamples\n\njulia> foldl(=>, 1:4)\n((1 => 2) => 3) => 4\n\njulia> foldl(=>, 1:4; init=0)\n(((0 => 1) => 2) => 3) => 4\n\njulia> accumulate(=>, (1,2,3,4))\n(1, 1 => 2, (1 => 2) => 3, ((1 => 2) => 3) => 4)\n\n\n\n\n\n","category":"method"},{"location":"base/collections/#Base.foldr-Tuple{Any, Any}","page":"集合和数据结构","title":"Base.foldr","text":"foldr(op, itr; [init])\n\nLike reduce, but with guaranteed right associativity. If provided, the keyword argument init will be used exactly once. In general, it will be necessary to provide init to work with empty collections.\n\nExamples\n\njulia> foldr(=>, 1:4)\n1 => (2 => (3 => 4))\n\njulia> foldr(=>, 1:4; init=0)\n1 => (2 => (3 => (4 => 0)))\n\n\n\n\n\n","category":"method"},{"location":"base/collections/#Base.maximum","page":"集合和数据结构","title":"Base.maximum","text":"maximum(f, itr; [init])\n\nReturns the largest result of calling function f on each element of itr.\n\nThe value returned for empty itr can be specified by init. It must be a neutral element for max (i.e. which is less than or equal to any other element) as it is unspecified whether init is used for non-empty collections.\n\ncompat: Julia 1.6\nKeyword argument init requires Julia 1.6 or later.\n\nExamples\n\njulia> maximum(length, [\"Julion\", \"Julia\", \"Jule\"])\n6\n\njulia> maximum(length, []; init=-1)\n-1\n\njulia> maximum(sin, Real[]; init=-1.0) # good, since output of sin is >= -1\n-1.0\n\n\n\n\n\nmaximum(itr; [init])\n\nReturns the largest element in a collection.\n\nThe value returned for empty itr can be specified by init. It must be a neutral element for max (i.e. which is less than or equal to any other element) as it is unspecified whether init is used for non-empty collections.\n\ncompat: Julia 1.6\nKeyword argument init requires Julia 1.6 or later.\n\nExamples\n\njulia> maximum(-20.5:10)\n9.5\n\njulia> maximum([1,2,3])\n3\n\njulia> maximum(())\nERROR: MethodError: reducing over an empty collection is not allowed; consider supplying `init` to the reducer\nStacktrace:\n[...]\n\njulia> maximum((); init=-Inf)\n-Inf\n\n\n\n\n\nmaximum(A::AbstractArray; dims)\n\nCompute the maximum value of an array over the given dimensions. See also the max(a,b) function to take the maximum of two or more arguments, which can be applied elementwise to arrays via max.(a,b).\n\nSee also: maximum!, extrema, findmax, argmax.\n\nExamples\n\njulia> A = [1 2; 3 4]\n2×2 Matrix{Int64}:\n 1 2\n 3 4\n\njulia> maximum(A, dims=1)\n1×2 Matrix{Int64}:\n 3 4\n\njulia> maximum(A, dims=2)\n2×1 Matrix{Int64}:\n 2\n 4\n\n\n\n\n\nmaximum(f, A::AbstractArray; dims)\n\nCompute the maximum value by calling the function f on each element of an array over the given dimensions.\n\nExamples\n\njulia> A = [1 2; 3 4]\n2×2 Matrix{Int64}:\n 1 2\n 3 4\n\njulia> maximum(abs2, A, dims=1)\n1×2 Matrix{Int64}:\n 9 16\n\njulia> maximum(abs2, A, dims=2)\n2×1 Matrix{Int64}:\n 4\n 16\n\n\n\n\n\n","category":"function"},{"location":"base/collections/#Base.maximum!","page":"集合和数据结构","title":"Base.maximum!","text":"maximum!(r, A)\n\nCompute the maximum value of A over the singleton dimensions of r, and write results to r.\n\nExamples\n\njulia> A = [1 2; 3 4]\n2×2 Matrix{Int64}:\n 1 2\n 3 4\n\njulia> maximum!([1; 1], A)\n2-element Vector{Int64}:\n 2\n 4\n\njulia> maximum!([1 1], A)\n1×2 Matrix{Int64}:\n 3 4\n\n\n\n\n\n","category":"function"},{"location":"base/collections/#Base.minimum","page":"集合和数据结构","title":"Base.minimum","text":"minimum(f, itr; [init])\n\nReturns the smallest result of calling function f on each element of itr.\n\nThe value returned for empty itr can be specified by init. It must be a neutral element for min (i.e. which is greater than or equal to any other element) as it is unspecified whether init is used for non-empty collections.\n\ncompat: Julia 1.6\nKeyword argument init requires Julia 1.6 or later.\n\nExamples\n\njulia> minimum(length, [\"Julion\", \"Julia\", \"Jule\"])\n4\n\njulia> minimum(length, []; init=typemax(Int64))\n9223372036854775807\n\njulia> minimum(sin, Real[]; init=1.0) # good, since output of sin is <= 1\n1.0\n\n\n\n\n\nminimum(itr; [init])\n\nReturns the smallest element in a collection.\n\nThe value returned for empty itr can be specified by init. It must be a neutral element for min (i.e. which is greater than or equal to any other element) as it is unspecified whether init is used for non-empty collections.\n\ncompat: Julia 1.6\nKeyword argument init requires Julia 1.6 or later.\n\nExamples\n\njulia> minimum(-20.5:10)\n-20.5\n\njulia> minimum([1,2,3])\n1\n\njulia> minimum([])\nERROR: MethodError: reducing over an empty collection is not allowed; consider supplying `init` to the reducer\nStacktrace:\n[...]\n\njulia> minimum([]; init=Inf)\nInf\n\n\n\n\n\nminimum(A::AbstractArray; dims)\n\nCompute the minimum value of an array over the given dimensions. See also the min(a,b) function to take the minimum of two or more arguments, which can be applied elementwise to arrays via min.(a,b).\n\nSee also: minimum!, extrema, findmin, argmin.\n\nExamples\n\njulia> A = [1 2; 3 4]\n2×2 Matrix{Int64}:\n 1 2\n 3 4\n\njulia> minimum(A, dims=1)\n1×2 Matrix{Int64}:\n 1 2\n\njulia> minimum(A, dims=2)\n2×1 Matrix{Int64}:\n 1\n 3\n\n\n\n\n\nminimum(f, A::AbstractArray; dims)\n\nCompute the minimum value by calling the function f on each element of an array over the given dimensions.\n\nExamples\n\njulia> A = [1 2; 3 4]\n2×2 Matrix{Int64}:\n 1 2\n 3 4\n\njulia> minimum(abs2, A, dims=1)\n1×2 Matrix{Int64}:\n 1 4\n\njulia> minimum(abs2, A, dims=2)\n2×1 Matrix{Int64}:\n 1\n 9\n\n\n\n\n\n","category":"function"},{"location":"base/collections/#Base.minimum!","page":"集合和数据结构","title":"Base.minimum!","text":"minimum!(r, A)\n\nCompute the minimum value of A over the singleton dimensions of r, and write results to r.\n\nExamples\n\njulia> A = [1 2; 3 4]\n2×2 Matrix{Int64}:\n 1 2\n 3 4\n\njulia> minimum!([1; 1], A)\n2-element Vector{Int64}:\n 1\n 3\n\njulia> minimum!([1 1], A)\n1×2 Matrix{Int64}:\n 1 2\n\n\n\n\n\n","category":"function"},{"location":"base/collections/#Base.extrema","page":"集合和数据结构","title":"Base.extrema","text":"extrema(itr; [init]) -> (mn, mx)\n\nCompute both the minimum mn and maximum mx element in a single pass, and return them as a 2-tuple.\n\nThe value returned for empty itr can be specified by init. It must be a 2-tuple whose first and second elements are neutral elements for min and max respectively (i.e. which are greater/less than or equal to any other element). As a consequence, when itr is empty the returned (mn, mx) tuple will satisfy mn ≥ mx. When init is specified it may be used even for non-empty itr.\n\ncompat: Julia 1.8\nKeyword argument init requires Julia 1.8 or later.\n\nExamples\n\njulia> extrema(2:10)\n(2, 10)\n\njulia> extrema([9,pi,4.5])\n(3.141592653589793, 9.0)\n\njulia> extrema([]; init = (Inf, -Inf))\n(Inf, -Inf)\n\n\n\n\n\nextrema(f, itr; [init]) -> (mn, mx)\n\nCompute both the minimum mn and maximum mx of f applied to each element in itr and return them as a 2-tuple. Only one pass is made over itr.\n\nThe value returned for empty itr can be specified by init. It must be a 2-tuple whose first and second elements are neutral elements for min and max respectively (i.e. which are greater/less than or equal to any other element). It is used for non-empty collections. Note: it implies that, for empty itr, the returned value (mn, mx) satisfies mn ≥ mx even though for non-empty itr it satisfies mn ≤ mx. This is a \"paradoxical\" but yet expected result.\n\ncompat: Julia 1.2\nThis method requires Julia 1.2 or later.\n\ncompat: Julia 1.8\nKeyword argument init requires Julia 1.8 or later.\n\nExamples\n\njulia> extrema(sin, 0:π)\n(0.0, 0.9092974268256817)\n\njulia> extrema(sin, Real[]; init = (1.0, -1.0)) # good, since -1 ≤ sin(::Real) ≤ 1\n(1.0, -1.0)\n\n\n\n\n\nextrema(A::AbstractArray; dims) -> Array{Tuple}\n\nCompute the minimum and maximum elements of an array over the given dimensions.\n\nSee also: minimum, maximum, extrema!.\n\nExamples\n\njulia> A = reshape(Vector(1:2:16), (2,2,2))\n2×2×2 Array{Int64, 3}:\n[:, :, 1] =\n 1 5\n 3 7\n\n[:, :, 2] =\n 9 13\n 11 15\n\njulia> extrema(A, dims = (1,2))\n1×1×2 Array{Tuple{Int64, Int64}, 3}:\n[:, :, 1] =\n (1, 7)\n\n[:, :, 2] =\n (9, 15)\n\n\n\n\n\nextrema(f, A::AbstractArray; dims) -> Array{Tuple}\n\nCompute the minimum and maximum of f applied to each element in the given dimensions of A.\n\ncompat: Julia 1.2\nThis method requires Julia 1.2 or later.\n\n\n\n\n\n","category":"function"},{"location":"base/collections/#Base.argmax","page":"集合和数据结构","title":"Base.argmax","text":"argmax(r::AbstractRange)\n\nRanges can have multiple maximal elements. In that case argmax will return a maximal index, but not necessarily the first one.\n\n\n\n\n\nargmax(f, domain)\n\nReturn a value x in the domain of f for which f(x) is maximised. If there are multiple maximal values for f(x) then the first one will be found.\n\ndomain must be a non-empty iterable.\n\nValues are compared with isless.\n\ncompat: Julia 1.7\nThis method requires Julia 1.7 or later.\n\nSee also argmin, findmax.\n\nExamples\n\njulia> argmax(abs, -10:5)\n-10\n\njulia> argmax(cos, 0:π/2:2π)\n0.0\n\n\n\n\n\nargmax(itr)\n\nReturn the index or key of the maximal element in a collection. If there are multiple maximal elements, then the first one will be returned.\n\nThe collection must not be empty.\n\nValues are compared with isless.\n\nSee also: argmin, findmax.\n\nExamples\n\njulia> argmax([8, 0.1, -9, pi])\n1\n\njulia> argmax([1, 7, 7, 6])\n2\n\njulia> argmax([1, 7, 7, NaN])\n4\n\n\n\n\n\nargmax(A; dims) -> indices\n\nFor an array input, return the indices of the maximum elements over the given dimensions. NaN is treated as greater than all other values except missing.\n\nExamples\n\njulia> A = [1.0 2; 3 4]\n2×2 Matrix{Float64}:\n 1.0 2.0\n 3.0 4.0\n\njulia> argmax(A, dims=1)\n1×2 Matrix{CartesianIndex{2}}:\n CartesianIndex(2, 1) CartesianIndex(2, 2)\n\njulia> argmax(A, dims=2)\n2×1 Matrix{CartesianIndex{2}}:\n CartesianIndex(1, 2)\n CartesianIndex(2, 2)\n\n\n\n\n\n","category":"function"},{"location":"base/collections/#Base.argmin","page":"集合和数据结构","title":"Base.argmin","text":"argmin(r::AbstractRange)\n\nRanges can have multiple minimal elements. In that case argmin will return a minimal index, but not necessarily the first one.\n\n\n\n\n\nargmin(f, domain)\n\nReturn a value x in the domain of f for which f(x) is minimised. If there are multiple minimal values for f(x) then the first one will be found.\n\ndomain must be a non-empty iterable.\n\nNaN is treated as less than all other values except missing.\n\ncompat: Julia 1.7\nThis method requires Julia 1.7 or later.\n\nSee also argmax, findmin.\n\nExamples\n\njulia> argmin(sign, -10:5)\n-10\n\njulia> argmin(x -> -x^3 + x^2 - 10, -5:5)\n5\n\njulia> argmin(acos, 0:0.1:1)\n1.0\n\n\n\n\n\nargmin(itr)\n\nReturn the index or key of the minimal element in a collection. If there are multiple minimal elements, then the first one will be returned.\n\nThe collection must not be empty.\n\nNaN is treated as less than all other values except missing.\n\nSee also: argmax, findmin.\n\nExamples\n\njulia> argmin([8, 0.1, -9, pi])\n3\n\njulia> argmin([7, 1, 1, 6])\n2\n\njulia> argmin([7, 1, 1, NaN])\n4\n\n\n\n\n\nargmin(A; dims) -> indices\n\nFor an array input, return the indices of the minimum elements over the given dimensions. NaN is treated as less than all other values except missing.\n\nExamples\n\njulia> A = [1.0 2; 3 4]\n2×2 Matrix{Float64}:\n 1.0 2.0\n 3.0 4.0\n\njulia> argmin(A, dims=1)\n1×2 Matrix{CartesianIndex{2}}:\n CartesianIndex(1, 1) CartesianIndex(1, 2)\n\njulia> argmin(A, dims=2)\n2×1 Matrix{CartesianIndex{2}}:\n CartesianIndex(1, 1)\n CartesianIndex(2, 1)\n\n\n\n\n\n","category":"function"},{"location":"base/collections/#Base.findmax","page":"集合和数据结构","title":"Base.findmax","text":"findmax(f, domain) -> (f(x), index)\n\nReturns a pair of a value in the codomain (outputs of f) and the index of the corresponding value in the domain (inputs to f) such that f(x) is maximised. If there are multiple maximal points, then the first one will be returned.\n\ndomain must be a non-empty iterable.\n\nValues are compared with isless.\n\ncompat: Julia 1.7\nThis method requires Julia 1.7 or later.\n\nExamples\n\njulia> findmax(identity, 5:9)\n(9, 5)\n\njulia> findmax(-, 1:10)\n(-1, 1)\n\njulia> findmax(first, [(1, :a), (3, :b), (3, :c)])\n(3, 2)\n\njulia> findmax(cos, 0:π/2:2π)\n(1.0, 1)\n\n\n\n\n\nfindmax(itr) -> (x, index)\n\nReturn the maximal element of the collection itr and its index or key. If there are multiple maximal elements, then the first one will be returned. Values are compared with isless.\n\nSee also: findmin, argmax, maximum.\n\nExamples\n\njulia> findmax([8, 0.1, -9, pi])\n(8.0, 1)\n\njulia> findmax([1, 7, 7, 6])\n(7, 2)\n\njulia> findmax([1, 7, 7, NaN])\n(NaN, 4)\n\n\n\n\n\nfindmax(A; dims) -> (maxval, index)\n\nFor an array input, returns the value and index of the maximum over the given dimensions. NaN is treated as greater than all other values except missing.\n\nExamples\n\njulia> A = [1.0 2; 3 4]\n2×2 Matrix{Float64}:\n 1.0 2.0\n 3.0 4.0\n\njulia> findmax(A, dims=1)\n([3.0 4.0], CartesianIndex{2}[CartesianIndex(2, 1) CartesianIndex(2, 2)])\n\njulia> findmax(A, dims=2)\n([2.0; 4.0;;], CartesianIndex{2}[CartesianIndex(1, 2); CartesianIndex(2, 2);;])\n\n\n\n\n\n","category":"function"},{"location":"base/collections/#Base.findmin","page":"集合和数据结构","title":"Base.findmin","text":"findmin(f, domain) -> (f(x), index)\n\nReturns a pair of a value in the codomain (outputs of f) and the index of the corresponding value in the domain (inputs to f) such that f(x) is minimised. If there are multiple minimal points, then the first one will be returned.\n\ndomain must be a non-empty iterable.\n\nNaN is treated as less than all other values except missing.\n\ncompat: Julia 1.7\nThis method requires Julia 1.7 or later.\n\nExamples\n\njulia> findmin(identity, 5:9)\n(5, 1)\n\njulia> findmin(-, 1:10)\n(-10, 10)\n\njulia> findmin(first, [(2, :a), (2, :b), (3, :c)])\n(2, 1)\n\njulia> findmin(cos, 0:π/2:2π)\n(-1.0, 3)\n\n\n\n\n\nfindmin(itr) -> (x, index)\n\nReturn the minimal element of the collection itr and its index or key. If there are multiple minimal elements, then the first one will be returned. NaN is treated as less than all other values except missing.\n\nSee also: findmax, argmin, minimum.\n\nExamples\n\njulia> findmin([8, 0.1, -9, pi])\n(-9.0, 3)\n\njulia> findmin([1, 7, 7, 6])\n(1, 1)\n\njulia> findmin([1, 7, 7, NaN])\n(NaN, 4)\n\n\n\n\n\nfindmin(A; dims) -> (minval, index)\n\nFor an array input, returns the value and index of the minimum over the given dimensions. NaN is treated as less than all other values except missing.\n\nExamples\n\njulia> A = [1.0 2; 3 4]\n2×2 Matrix{Float64}:\n 1.0 2.0\n 3.0 4.0\n\njulia> findmin(A, dims=1)\n([1.0 2.0], CartesianIndex{2}[CartesianIndex(1, 1) CartesianIndex(1, 2)])\n\njulia> findmin(A, dims=2)\n([1.0; 3.0;;], CartesianIndex{2}[CartesianIndex(1, 1); CartesianIndex(2, 1);;])\n\n\n\n\n\n","category":"function"},{"location":"base/collections/#Base.findmax!","page":"集合和数据结构","title":"Base.findmax!","text":"findmax!(rval, rind, A) -> (maxval, index)\n\nFind the maximum of A and the corresponding linear index along singleton dimensions of rval and rind, and store the results in rval and rind. NaN is treated as greater than all other values except missing.\n\n\n\n\n\n","category":"function"},{"location":"base/collections/#Base.findmin!","page":"集合和数据结构","title":"Base.findmin!","text":"findmin!(rval, rind, A) -> (minval, index)\n\nFind the minimum of A and the corresponding linear index along singleton dimensions of rval and rind, and store the results in rval and rind. NaN is treated as less than all other values except missing.\n\n\n\n\n\n","category":"function"},{"location":"base/collections/#Base.sum","page":"集合和数据结构","title":"Base.sum","text":"sum(f, itr; [init])\n\nSum the results of calling function f on each element of itr.\n\nThe return type is Int for signed integers of less than system word size, and UInt for unsigned integers of less than system word size. For all other arguments, a common return type is found to which all arguments are promoted.\n\nThe value returned for empty itr can be specified by init. It must be the additive identity (i.e. zero) as it is unspecified whether init is used for non-empty collections.\n\ncompat: Julia 1.6\nKeyword argument init requires Julia 1.6 or later.\n\nExamples\n\njulia> sum(abs2, [2; 3; 4])\n29\n\nNote the important difference between sum(A) and reduce(+, A) for arrays with small integer eltype:\n\njulia> sum(Int8[100, 28])\n128\n\njulia> reduce(+, Int8[100, 28])\n-128\n\nIn the former case, the integers are widened to system word size and therefore the result is 128. In the latter case, no such widening happens and integer overflow results in -128.\n\n\n\n\n\nsum(itr; [init])\n\nReturns the sum of all elements in a collection.\n\nThe return type is Int for signed integers of less than system word size, and UInt for unsigned integers of less than system word size. For all other arguments, a common return type is found to which all arguments are promoted.\n\nThe value returned for empty itr can be specified by init. It must be the additive identity (i.e. zero) as it is unspecified whether init is used for non-empty collections.\n\ncompat: Julia 1.6\nKeyword argument init requires Julia 1.6 or later.\n\nSee also: reduce, mapreduce, count, union.\n\nExamples\n\njulia> sum(1:20)\n210\n\njulia> sum(1:20; init = 0.0)\n210.0\n\n\n\n\n\nsum(A::AbstractArray; dims)\n\nSum elements of an array over the given dimensions.\n\nExamples\n\njulia> A = [1 2; 3 4]\n2×2 Matrix{Int64}:\n 1 2\n 3 4\n\njulia> sum(A, dims=1)\n1×2 Matrix{Int64}:\n 4 6\n\njulia> sum(A, dims=2)\n2×1 Matrix{Int64}:\n 3\n 7\n\n\n\n\n\nsum(f, A::AbstractArray; dims)\n\nSum the results of calling function f on each element of an array over the given dimensions.\n\nExamples\n\njulia> A = [1 2; 3 4]\n2×2 Matrix{Int64}:\n 1 2\n 3 4\n\njulia> sum(abs2, A, dims=1)\n1×2 Matrix{Int64}:\n 10 20\n\njulia> sum(abs2, A, dims=2)\n2×1 Matrix{Int64}:\n 5\n 25\n\n\n\n\n\n","category":"function"},{"location":"base/collections/#Base.sum!","page":"集合和数据结构","title":"Base.sum!","text":"sum!(r, A)\n\nSum elements of A over the singleton dimensions of r, and write results to r.\n\nExamples\n\njulia> A = [1 2; 3 4]\n2×2 Matrix{Int64}:\n 1 2\n 3 4\n\njulia> sum!([1; 1], A)\n2-element Vector{Int64}:\n 3\n 7\n\njulia> sum!([1 1], A)\n1×2 Matrix{Int64}:\n 4 6\n\n\n\n\n\n","category":"function"},{"location":"base/collections/#Base.prod","page":"集合和数据结构","title":"Base.prod","text":"prod(f, itr; [init])\n\nReturns the product of f applied to each element of itr.\n\nThe return type is Int for signed integers of less than system word size, and UInt for unsigned integers of less than system word size. For all other arguments, a common return type is found to which all arguments are promoted.\n\nThe value returned for empty itr can be specified by init. It must be the multiplicative identity (i.e. one) as it is unspecified whether init is used for non-empty collections.\n\ncompat: Julia 1.6\nKeyword argument init requires Julia 1.6 or later.\n\nExamples\n\njulia> prod(abs2, [2; 3; 4])\n576\n\n\n\n\n\nprod(itr; [init])\n\nReturns the product of all elements of a collection.\n\nThe return type is Int for signed integers of less than system word size, and UInt for unsigned integers of less than system word size. For all other arguments, a common return type is found to which all arguments are promoted.\n\nThe value returned for empty itr can be specified by init. It must be the multiplicative identity (i.e. one) as it is unspecified whether init is used for non-empty collections.\n\ncompat: Julia 1.6\nKeyword argument init requires Julia 1.6 or later.\n\nSee also: reduce, cumprod, any.\n\nExamples\n\njulia> prod(1:5)\n120\n\njulia> prod(1:5; init = 1.0)\n120.0\n\n\n\n\n\nprod(A::AbstractArray; dims)\n\nMultiply elements of an array over the given dimensions.\n\nExamples\n\njulia> A = [1 2; 3 4]\n2×2 Matrix{Int64}:\n 1 2\n 3 4\n\njulia> prod(A, dims=1)\n1×2 Matrix{Int64}:\n 3 8\n\njulia> prod(A, dims=2)\n2×1 Matrix{Int64}:\n 2\n 12\n\n\n\n\n\nprod(f, A::AbstractArray; dims)\n\nMultiply the results of calling the function f on each element of an array over the given dimensions.\n\nExamples\n\njulia> A = [1 2; 3 4]\n2×2 Matrix{Int64}:\n 1 2\n 3 4\n\njulia> prod(abs2, A, dims=1)\n1×2 Matrix{Int64}:\n 9 64\n\njulia> prod(abs2, A, dims=2)\n2×1 Matrix{Int64}:\n 4\n 144\n\n\n\n\n\n","category":"function"},{"location":"base/collections/#Base.prod!","page":"集合和数据结构","title":"Base.prod!","text":"prod!(r, A)\n\nMultiply elements of A over the singleton dimensions of r, and write results to r.\n\nExamples\n\njulia> A = [1 2; 3 4]\n2×2 Matrix{Int64}:\n 1 2\n 3 4\n\njulia> prod!([1; 1], A)\n2-element Vector{Int64}:\n 2\n 12\n\njulia> prod!([1 1], A)\n1×2 Matrix{Int64}:\n 3 8\n\n\n\n\n\n","category":"function"},{"location":"base/collections/#Base.any-Tuple{Any}","page":"集合和数据结构","title":"Base.any","text":"any(itr) -> Bool\n\nTest whether any elements of a boolean collection are true, returning true as soon as the first true value in itr is encountered (short-circuiting). To short-circuit on false, use all.\n\nIf the input contains missing values, return missing if all non-missing values are false (or equivalently, if the input contains no true value), following three-valued logic.\n\nSee also: all, count, sum, |, , ||.\n\nExamples\n\njulia> a = [true,false,false,true]\n4-element Vector{Bool}:\n 1\n 0\n 0\n 1\n\njulia> any(a)\ntrue\n\njulia> any((println(i); v) for (i, v) in enumerate(a))\n1\ntrue\n\njulia> any([missing, true])\ntrue\n\njulia> any([false, missing])\nmissing\n\n\n\n\n\n","category":"method"},{"location":"base/collections/#Base.any-Tuple{AbstractArray, Any}","page":"集合和数据结构","title":"Base.any","text":"any(p, itr) -> Bool\n\nDetermine whether predicate p returns true for any elements of itr, returning true as soon as the first item in itr for which p returns true is encountered (short-circuiting). To short-circuit on false, use all.\n\nIf the input contains missing values, return missing if all non-missing values are false (or equivalently, if the input contains no true value), following three-valued logic.\n\nExamples\n\njulia> any(i->(4<=i<=6), [3,5,7])\ntrue\n\njulia> any(i -> (println(i); i > 3), 1:10)\n1\n2\n3\n4\ntrue\n\njulia> any(i -> i > 0, [1, missing])\ntrue\n\njulia> any(i -> i > 0, [-1, missing])\nmissing\n\njulia> any(i -> i > 0, [-1, 0])\nfalse\n\n\n\n\n\n","category":"method"},{"location":"base/collections/#Base.any!","page":"集合和数据结构","title":"Base.any!","text":"any!(r, A)\n\nTest whether any values in A along the singleton dimensions of r are true, and write results to r.\n\nExamples\n\njulia> A = [true false; true false]\n2×2 Matrix{Bool}:\n 1 0\n 1 0\n\njulia> any!([1; 1], A)\n2-element Vector{Int64}:\n 1\n 1\n\njulia> any!([1 1], A)\n1×2 Matrix{Int64}:\n 1 0\n\n\n\n\n\n","category":"function"},{"location":"base/collections/#Base.all-Tuple{Any}","page":"集合和数据结构","title":"Base.all","text":"all(itr) -> Bool\n\nTest whether all elements of a boolean collection are true, returning false as soon as the first false value in itr is encountered (short-circuiting). To short-circuit on true, use any.\n\nIf the input contains missing values, return missing if all non-missing values are true (or equivalently, if the input contains no false value), following three-valued logic.\n\nSee also: all!, any, count, &, , &&, allunique.\n\nExamples\n\njulia> a = [true,false,false,true]\n4-element Vector{Bool}:\n 1\n 0\n 0\n 1\n\njulia> all(a)\nfalse\n\njulia> all((println(i); v) for (i, v) in enumerate(a))\n1\n2\nfalse\n\njulia> all([missing, false])\nfalse\n\njulia> all([true, missing])\nmissing\n\n\n\n\n\n","category":"method"},{"location":"base/collections/#Base.all-Tuple{AbstractArray, Any}","page":"集合和数据结构","title":"Base.all","text":"all(p, itr) -> Bool\n\nDetermine whether predicate p returns true for all elements of itr, returning false as soon as the first item in itr for which p returns false is encountered (short-circuiting). To short-circuit on true, use any.\n\nIf the input contains missing values, return missing if all non-missing values are true (or equivalently, if the input contains no false value), following three-valued logic.\n\nExamples\n\njulia> all(i->(4<=i<=6), [4,5,6])\ntrue\n\njulia> all(i -> (println(i); i < 3), 1:10)\n1\n2\n3\nfalse\n\njulia> all(i -> i > 0, [1, missing])\nmissing\n\njulia> all(i -> i > 0, [-1, missing])\nfalse\n\njulia> all(i -> i > 0, [1, 2])\ntrue\n\n\n\n\n\n","category":"method"},{"location":"base/collections/#Base.all!","page":"集合和数据结构","title":"Base.all!","text":"all!(r, A)\n\nTest whether all values in A along the singleton dimensions of r are true, and write results to r.\n\nExamples\n\njulia> A = [true false; true false]\n2×2 Matrix{Bool}:\n 1 0\n 1 0\n\njulia> all!([1; 1], A)\n2-element Vector{Int64}:\n 0\n 0\n\njulia> all!([1 1], A)\n1×2 Matrix{Int64}:\n 1 0\n\n\n\n\n\n","category":"function"},{"location":"base/collections/#Base.count","page":"集合和数据结构","title":"Base.count","text":"count([f=identity,] itr; init=0) -> Integer\n\nCount the number of elements in itr for which the function f returns true. If f is omitted, count the number of true elements in itr (which should be a collection of boolean values). init optionally specifies the value to start counting from and therefore also determines the output type.\n\ncompat: Julia 1.6\ninit keyword was added in Julia 1.6.\n\nSee also: any, sum.\n\nExamples\n\njulia> count(i->(4<=i<=6), [2,3,4,5,6])\n3\n\njulia> count([true, false, true, true])\n3\n\njulia> count(>(3), 1:7, init=0x03)\n0x07\n\n\n\n\n\ncount(\n pattern::Union{AbstractChar,AbstractString,AbstractPattern},\n string::AbstractString;\n overlap::Bool = false,\n)\n\nReturn the number of matches for pattern in string. This is equivalent to calling length(findall(pattern, string)) but more efficient.\n\nIf overlap=true, the matching sequences are allowed to overlap indices in the original string, otherwise they must be from disjoint character ranges.\n\ncompat: Julia 1.3\nThis method requires at least Julia 1.3.\n\ncompat: Julia 1.7\nUsing a character as the pattern requires at least Julia 1.7.\n\n\n\n\n\ncount([f=identity,] A::AbstractArray; dims=:)\n\nCount the number of elements in A for which f returns true over the given dimensions.\n\ncompat: Julia 1.5\ndims keyword was added in Julia 1.5.\n\ncompat: Julia 1.6\ninit keyword was added in Julia 1.6.\n\nExamples\n\njulia> A = [1 2; 3 4]\n2×2 Matrix{Int64}:\n 1 2\n 3 4\n\njulia> count(<=(2), A, dims=1)\n1×2 Matrix{Int64}:\n 1 1\n\njulia> count(<=(2), A, dims=2)\n2×1 Matrix{Int64}:\n 2\n 0\n\n\n\n\n\n","category":"function"},{"location":"base/collections/#Base.any-Tuple{Any, Any}","page":"集合和数据结构","title":"Base.any","text":"any(p, itr) -> Bool\n\nDetermine whether predicate p returns true for any elements of itr, returning true as soon as the first item in itr for which p returns true is encountered (short-circuiting). To short-circuit on false, use all.\n\nIf the input contains missing values, return missing if all non-missing values are false (or equivalently, if the input contains no true value), following three-valued logic.\n\nExamples\n\njulia> any(i->(4<=i<=6), [3,5,7])\ntrue\n\njulia> any(i -> (println(i); i > 3), 1:10)\n1\n2\n3\n4\ntrue\n\njulia> any(i -> i > 0, [1, missing])\ntrue\n\njulia> any(i -> i > 0, [-1, missing])\nmissing\n\njulia> any(i -> i > 0, [-1, 0])\nfalse\n\n\n\n\n\n","category":"method"},{"location":"base/collections/#Base.all-Tuple{Any, Any}","page":"集合和数据结构","title":"Base.all","text":"all(p, itr) -> Bool\n\nDetermine whether predicate p returns true for all elements of itr, returning false as soon as the first item in itr for which p returns false is encountered (short-circuiting). To short-circuit on true, use any.\n\nIf the input contains missing values, return missing if all non-missing values are true (or equivalently, if the input contains no false value), following three-valued logic.\n\nExamples\n\njulia> all(i->(4<=i<=6), [4,5,6])\ntrue\n\njulia> all(i -> (println(i); i < 3), 1:10)\n1\n2\n3\nfalse\n\njulia> all(i -> i > 0, [1, missing])\nmissing\n\njulia> all(i -> i > 0, [-1, missing])\nfalse\n\njulia> all(i -> i > 0, [1, 2])\ntrue\n\n\n\n\n\n","category":"method"},{"location":"base/collections/#Base.foreach","page":"集合和数据结构","title":"Base.foreach","text":"foreach(f, c...) -> Nothing\n\nCall function f on each element of iterable c. For multiple iterable arguments, f is called elementwise, and iteration stops when any iterator is finished.\n\nforeach should be used instead of map when the results of f are not needed, for example in foreach(println, array).\n\nExamples\n\njulia> tri = 1:3:7; res = Int[];\n\njulia> foreach(x -> push!(res, x^2), tri)\n\njulia> res\n3-element Vector{Int64}:\n 1\n 16\n 49\n\njulia> foreach((x, y) -> println(x, \" with \", y), tri, 'a':'z')\n1 with a\n4 with b\n7 with c\n\n\n\n\n\n","category":"function"},{"location":"base/collections/#Base.map","page":"集合和数据结构","title":"Base.map","text":"map(f, c...) -> collection\n\nTransform collection c by applying f to each element. For multiple collection arguments, apply f elementwise, and stop when when any of them is exhausted.\n\nSee also map!, foreach, mapreduce, mapslices, zip, Iterators.map.\n\nExamples\n\njulia> map(x -> x * 2, [1, 2, 3])\n3-element Vector{Int64}:\n 2\n 4\n 6\n\njulia> map(+, [1, 2, 3], [10, 20, 30, 400, 5000])\n3-element Vector{Int64}:\n 11\n 22\n 33\n\n\n\n\n\nmap(f, A::AbstractArray...) -> N-array\n\nWhen acting on multi-dimensional arrays of the same ndims, they must all have the same axes, and the answer will too.\n\nSee also broadcast, which allows mismatched sizes.\n\nExamples\n\njulia> map(//, [1 2; 3 4], [4 3; 2 1])\n2×2 Matrix{Rational{Int64}}:\n 1//4 2//3\n 3//2 4//1\n\njulia> map(+, [1 2; 3 4], zeros(2,1))\nERROR: DimensionMismatch\n\njulia> map(+, [1 2; 3 4], [1,10,100,1000], zeros(3,1)) # iterates until 3rd is exhausted\n3-element Vector{Float64}:\n 2.0\n 13.0\n 102.0\n\n\n\n\n\n","category":"function"},{"location":"base/collections/#Base.map!","page":"集合和数据结构","title":"Base.map!","text":"map!(function, destination, collection...)\n\nLike map, but stores the result in destination rather than a new collection. destination must be at least as large as the smallest collection.\n\nSee also: map, foreach, zip, copyto!.\n\nExamples\n\njulia> a = zeros(3);\n\njulia> map!(x -> x * 2, a, [1, 2, 3]);\n\njulia> a\n3-element Vector{Float64}:\n 2.0\n 4.0\n 6.0\n\njulia> map!(+, zeros(Int, 5), 100:999, 1:3)\n5-element Vector{Int64}:\n 101\n 103\n 105\n 0\n 0\n\n\n\n\n\nmap!(f, values(dict::AbstractDict))\n\nModifies dict by transforming each value from val to f(val). Note that the type of dict cannot be changed: if f(val) is not an instance of the value type of dict then it will be converted to the value type if possible and otherwise raise an error.\n\ncompat: Julia 1.2\nmap!(f, values(dict::AbstractDict)) requires Julia 1.2 or later.\n\nExamples\n\njulia> d = Dict(:a => 1, :b => 2)\nDict{Symbol, Int64} with 2 entries:\n :a => 1\n :b => 2\n\njulia> map!(v -> v-1, values(d))\nValueIterator for a Dict{Symbol, Int64} with 2 entries. Values:\n 0\n 1\n\n\n\n\n\n","category":"function"},{"location":"base/collections/#Base.mapreduce-Tuple{Any, Any, Any}","page":"集合和数据结构","title":"Base.mapreduce","text":"mapreduce(f, op, itrs...; [init])\n\nApply function f to each element(s) in itrs, and then reduce the result using the binary function op. If provided, init must be a neutral element for op that will be returned for empty collections. It is unspecified whether init is used for non-empty collections. In general, it will be necessary to provide init to work with empty collections.\n\nmapreduce is functionally equivalent to calling reduce(op, map(f, itr); init=init), but will in general execute faster since no intermediate collection needs to be created. See documentation for reduce and map.\n\ncompat: Julia 1.2\nmapreduce with multiple iterators requires Julia 1.2 or later.\n\nExamples\n\njulia> mapreduce(x->x^2, +, [1:3;]) # == 1 + 4 + 9\n14\n\nThe associativity of the reduction is implementation-dependent. Additionally, some implementations may reuse the return value of f for elements that appear multiple times in itr. Use mapfoldl or mapfoldr instead for guaranteed left or right associativity and invocation of f for every value.\n\n\n\n\n\n","category":"method"},{"location":"base/collections/#Base.mapfoldl-Tuple{Any, Any, Any}","page":"集合和数据结构","title":"Base.mapfoldl","text":"mapfoldl(f, op, itr; [init])\n\nLike mapreduce, but with guaranteed left associativity, as in foldl. If provided, the keyword argument init will be used exactly once. In general, it will be necessary to provide init to work with empty collections.\n\n\n\n\n\n","category":"method"},{"location":"base/collections/#Base.mapfoldr-Tuple{Any, Any, Any}","page":"集合和数据结构","title":"Base.mapfoldr","text":"mapfoldr(f, op, itr; [init])\n\nLike mapreduce, but with guaranteed right associativity, as in foldr. If provided, the keyword argument init will be used exactly once. In general, it will be necessary to provide init to work with empty collections.\n\n\n\n\n\n","category":"method"},{"location":"base/collections/#Base.first","page":"集合和数据结构","title":"Base.first","text":"first(coll)\n\nGet the first element of an iterable collection. Return the start point of an AbstractRange even if it is empty.\n\nSee also: only, firstindex, last.\n\nExamples\n\njulia> first(2:2:10)\n2\n\njulia> first([1; 2; 3; 4])\n1\n\n\n\n\n\nfirst(itr, n::Integer)\n\nGet the first n elements of the iterable collection itr, or fewer elements if itr is not long enough.\n\nSee also: startswith, Iterators.take.\n\ncompat: Julia 1.6\nThis method requires at least Julia 1.6.\n\nExamples\n\njulia> first([\"foo\", \"bar\", \"qux\"], 2)\n2-element Vector{String}:\n \"foo\"\n \"bar\"\n\njulia> first(1:6, 10)\n1:6\n\njulia> first(Bool[], 1)\nBool[]\n\n\n\n\n\nfirst(s::AbstractString, n::Integer)\n\nGet a string consisting of the first n characters of s.\n\nExamples\n\njulia> first(\"∀ϵ≠0: ϵ²>0\", 0)\n\"\"\n\njulia> first(\"∀ϵ≠0: ϵ²>0\", 1)\n\"∀\"\n\njulia> first(\"∀ϵ≠0: ϵ²>0\", 3)\n\"∀ϵ≠\"\n\n\n\n\n\n","category":"function"},{"location":"base/collections/#Base.last","page":"集合和数据结构","title":"Base.last","text":"last(coll)\n\nGet the last element of an ordered collection, if it can be computed in O(1) time. This is accomplished by calling lastindex to get the last index. Return the end point of an AbstractRange even if it is empty.\n\nSee also first, endswith.\n\nExamples\n\njulia> last(1:2:10)\n9\n\njulia> last([1; 2; 3; 4])\n4\n\n\n\n\n\nlast(itr, n::Integer)\n\nGet the last n elements of the iterable collection itr, or fewer elements if itr is not long enough.\n\ncompat: Julia 1.6\nThis method requires at least Julia 1.6.\n\nExamples\n\njulia> last([\"foo\", \"bar\", \"qux\"], 2)\n2-element Vector{String}:\n \"bar\"\n \"qux\"\n\njulia> last(1:6, 10)\n1:6\n\njulia> last(Float64[], 1)\nFloat64[]\n\n\n\n\n\nlast(s::AbstractString, n::Integer)\n\nGet a string consisting of the last n characters of s.\n\nExamples\n\njulia> last(\"∀ϵ≠0: ϵ²>0\", 0)\n\"\"\n\njulia> last(\"∀ϵ≠0: ϵ²>0\", 1)\n\"0\"\n\njulia> last(\"∀ϵ≠0: ϵ²>0\", 3)\n\"²>0\"\n\n\n\n\n\n","category":"function"},{"location":"base/collections/#Base.front","page":"集合和数据结构","title":"Base.front","text":"front(x::Tuple)::Tuple\n\nReturn a Tuple consisting of all but the last component of x.\n\nSee also: first, tail.\n\nExamples\n\njulia> Base.front((1,2,3))\n(1, 2)\n\njulia> Base.front(())\nERROR: ArgumentError: Cannot call front on an empty tuple.\n\n\n\n\n\n","category":"function"},{"location":"base/collections/#Base.tail","page":"集合和数据结构","title":"Base.tail","text":"tail(x::Tuple)::Tuple\n\nReturn a Tuple consisting of all but the first component of x.\n\nSee also: front, rest, first, Iterators.peel.\n\nExamples\n\njulia> Base.tail((1,2,3))\n(2, 3)\n\njulia> Base.tail(())\nERROR: ArgumentError: Cannot call tail on an empty tuple.\n\n\n\n\n\n","category":"function"},{"location":"base/collections/#Base.step","page":"集合和数据结构","title":"Base.step","text":"step(r)\n\nGet the step size of an AbstractRange object.\n\nExamples\n\njulia> step(1:10)\n1\n\njulia> step(1:2:10)\n2\n\njulia> step(2.5:0.3:10.9)\n0.3\n\njulia> step(range(2.5, stop=10.9, length=85))\n0.1\n\n\n\n\n\n","category":"function"},{"location":"base/collections/#Base.collect-Tuple{Any}","page":"集合和数据结构","title":"Base.collect","text":"collect(collection)\n\nReturn an Array of all items in a collection or iterator. For dictionaries, returns Pair{KeyType, ValType}. If the argument is array-like or is an iterator with the HasShape trait, the result will have the same shape and number of dimensions as the argument.\n\nUsed by comprehensions to turn a generator into an Array.\n\nExamples\n\njulia> collect(1:2:13)\n7-element Vector{Int64}:\n 1\n 3\n 5\n 7\n 9\n 11\n 13\n\njulia> [x^2 for x in 1:8 if isodd(x)]\n4-element Vector{Int64}:\n 1\n 9\n 25\n 49\n\n\n\n\n\n","category":"method"},{"location":"base/collections/#Base.collect-Tuple{Type, Any}","page":"集合和数据结构","title":"Base.collect","text":"collect(element_type, collection)\n\nReturn an Array with the given element type of all items in a collection or iterable. The result has the same shape and number of dimensions as collection.\n\nExamples\n\njulia> collect(Float64, 1:2:5)\n3-element Vector{Float64}:\n 1.0\n 3.0\n 5.0\n\n\n\n\n\n","category":"method"},{"location":"base/collections/#Base.filter","page":"集合和数据结构","title":"Base.filter","text":"filter(f, a)\n\nReturn a copy of collection a, removing elements for which f is false. The function f is passed one argument.\n\ncompat: Julia 1.4\nSupport for a as a tuple requires at least Julia 1.4.\n\nSee also: filter!, Iterators.filter.\n\nExamples\n\njulia> a = 1:10\n1:10\n\njulia> filter(isodd, a)\n5-element Vector{Int64}:\n 1\n 3\n 5\n 7\n 9\n\n\n\n\n\nfilter(f, d::AbstractDict)\n\nReturn a copy of d, removing elements for which f is false. The function f is passed key=>value pairs.\n\nExamples\n\njulia> d = Dict(1=>\"a\", 2=>\"b\")\nDict{Int64, String} with 2 entries:\n 2 => \"b\"\n 1 => \"a\"\n\njulia> filter(p->isodd(p.first), d)\nDict{Int64, String} with 1 entry:\n 1 => \"a\"\n\n\n\n\n\nfilter(f, itr::SkipMissing{<:AbstractArray})\n\nReturn a vector similar to the array wrapped by the given SkipMissing iterator but with all missing elements and those for which f returns false removed.\n\ncompat: Julia 1.2\nThis method requires Julia 1.2 or later.\n\nExamples\n\njulia> x = [1 2; missing 4]\n2×2 Matrix{Union{Missing, Int64}}:\n 1 2\n missing 4\n\njulia> filter(isodd, skipmissing(x))\n1-element Vector{Int64}:\n 1\n\n\n\n\n\n","category":"function"},{"location":"base/collections/#Base.filter!","page":"集合和数据结构","title":"Base.filter!","text":"filter!(f, a)\n\nUpdate collection a, removing elements for which f is false. The function f is passed one argument.\n\nExamples\n\njulia> filter!(isodd, Vector(1:10))\n5-element Vector{Int64}:\n 1\n 3\n 5\n 7\n 9\n\n\n\n\n\nfilter!(f, d::AbstractDict)\n\nUpdate d, removing elements for which f is false. The function f is passed key=>value pairs.\n\nExample\n\njulia> d = Dict(1=>\"a\", 2=>\"b\", 3=>\"c\")\nDict{Int64, String} with 3 entries:\n 2 => \"b\"\n 3 => \"c\"\n 1 => \"a\"\n\njulia> filter!(p->isodd(p.first), d)\nDict{Int64, String} with 2 entries:\n 3 => \"c\"\n 1 => \"a\"\n\n\n\n\n\n","category":"function"},{"location":"base/collections/#Base.replace-Tuple{Any, Vararg{Pair}}","page":"集合和数据结构","title":"Base.replace","text":"replace(A, old_new::Pair...; [count::Integer])\n\nReturn a copy of collection A where, for each pair old=>new in old_new, all occurrences of old are replaced by new. Equality is determined using isequal. If count is specified, then replace at most count occurrences in total.\n\nThe element type of the result is chosen using promotion (see promote_type) based on the element type of A and on the types of the new values in pairs. If count is omitted and the element type of A is a Union, the element type of the result will not include singleton types which are replaced with values of a different type: for example, Union{T,Missing} will become T if missing is replaced.\n\nSee also replace!, splice!, delete!, insert!.\n\ncompat: Julia 1.7\nVersion 1.7 is required to replace elements of a Tuple.\n\nExamples\n\njulia> replace([1, 2, 1, 3], 1=>0, 2=>4, count=2)\n4-element Vector{Int64}:\n 0\n 4\n 1\n 3\n\njulia> replace([1, missing], missing=>0)\n2-element Vector{Int64}:\n 1\n 0\n\n\n\n\n\n","category":"method"},{"location":"base/collections/#Base.replace-Tuple{Union{Function, Type}, Any}","page":"集合和数据结构","title":"Base.replace","text":"replace(new::Function, A; [count::Integer])\n\nReturn a copy of A where each value x in A is replaced by new(x). If count is specified, then replace at most count values in total (replacements being defined as new(x) !== x).\n\ncompat: Julia 1.7\nVersion 1.7 is required to replace elements of a Tuple.\n\nExamples\n\njulia> replace(x -> isodd(x) ? 2x : x, [1, 2, 3, 4])\n4-element Vector{Int64}:\n 2\n 2\n 6\n 4\n\njulia> replace(Dict(1=>2, 3=>4)) do kv\n first(kv) < 3 ? first(kv)=>3 : kv\n end\nDict{Int64, Int64} with 2 entries:\n 3 => 4\n 1 => 3\n\n\n\n\n\n","category":"method"},{"location":"base/collections/#Base.replace!","page":"集合和数据结构","title":"Base.replace!","text":"replace!(A, old_new::Pair...; [count::Integer])\n\nFor each pair old=>new in old_new, replace all occurrences of old in collection A by new. Equality is determined using isequal. If count is specified, then replace at most count occurrences in total. See also replace.\n\nExamples\n\njulia> replace!([1, 2, 1, 3], 1=>0, 2=>4, count=2)\n4-element Vector{Int64}:\n 0\n 4\n 1\n 3\n\njulia> replace!(Set([1, 2, 3]), 1=>0)\nSet{Int64} with 3 elements:\n 0\n 2\n 3\n\n\n\n\n\nreplace!(new::Function, A; [count::Integer])\n\nReplace each element x in collection A by new(x). If count is specified, then replace at most count values in total (replacements being defined as new(x) !== x).\n\nExamples\n\njulia> replace!(x -> isodd(x) ? 2x : x, [1, 2, 3, 4])\n4-element Vector{Int64}:\n 2\n 2\n 6\n 4\n\njulia> replace!(Dict(1=>2, 3=>4)) do kv\n first(kv) < 3 ? first(kv)=>3 : kv\n end\nDict{Int64, Int64} with 2 entries:\n 3 => 4\n 1 => 3\n\njulia> replace!(x->2x, Set([3, 6]))\nSet{Int64} with 2 elements:\n 6\n 12\n\n\n\n\n\n","category":"function"},{"location":"base/collections/#Base.rest","page":"集合和数据结构","title":"Base.rest","text":"Base.rest(collection[, itr_state])\n\nGeneric function for taking the tail of collection, starting from a specific iteration state itr_state. Return a Tuple, if collection itself is a Tuple, a subtype of AbstractVector, if collection is an AbstractArray, a subtype of AbstractString if collection is an AbstractString, and an arbitrary iterator, falling back to Iterators.rest(collection[, itr_state]), otherwise.\n\nCan be overloaded for user-defined collection types to customize the behavior of slurping in assignments, like a, b... = collection.\n\ncompat: Julia 1.6\nBase.rest requires at least Julia 1.6.\n\nSee also: first, Iterators.rest.\n\nExamples\n\njulia> a = [1 2; 3 4]\n2×2 Matrix{Int64}:\n 1 2\n 3 4\n\njulia> first, state = iterate(a)\n(1, 2)\n\njulia> first, Base.rest(a, state)\n(1, [3, 2, 4])\n\n\n\n\n\n","category":"function"},{"location":"base/collections/#可索引集合","page":"集合和数据结构","title":"可索引集合","text":"","category":"section"},{"location":"base/collections/","page":"集合和数据结构","title":"集合和数据结构","text":"Base.getindex\nBase.setindex!\nBase.firstindex\nBase.lastindex","category":"page"},{"location":"base/collections/#Base.getindex","page":"集合和数据结构","title":"Base.getindex","text":"getindex(collection, key...)\n\nRetrieve the value(s) stored at the given key or index within a collection. The syntax a[i,j,...] is converted by the compiler to getindex(a, i, j, ...).\n\nSee also get, keys, eachindex.\n\nExamples\n\njulia> A = Dict(\"a\" => 1, \"b\" => 2)\nDict{String, Int64} with 2 entries:\n \"b\" => 2\n \"a\" => 1\n\njulia> getindex(A, \"a\")\n1\n\n\n\n\n\n","category":"function"},{"location":"base/collections/#Base.setindex!","page":"集合和数据结构","title":"Base.setindex!","text":"setindex!(collection, value, key...)\n\nStore the given value at the given key or index within a collection. The syntax a[i,j,...] = x is converted by the compiler to (setindex!(a, x, i, j, ...); x).\n\n\n\n\n\n","category":"function"},{"location":"base/collections/#Base.firstindex","page":"集合和数据结构","title":"Base.firstindex","text":"firstindex(collection) -> Integer\nfirstindex(collection, d) -> Integer\n\nReturn the first index of collection. If d is given, return the first index of collection along dimension d.\n\nThe syntaxes A[begin] and A[1, begin] lower to A[firstindex(A)] and A[1, firstindex(A, 2)], respectively.\n\nSee also: first, axes, lastindex, nextind.\n\nExamples\n\njulia> firstindex([1,2,4])\n1\n\njulia> firstindex(rand(3,4,5), 2)\n1\n\n\n\n\n\n","category":"function"},{"location":"base/collections/#Base.lastindex","page":"集合和数据结构","title":"Base.lastindex","text":"lastindex(collection) -> Integer\nlastindex(collection, d) -> Integer\n\nReturn the last index of collection. If d is given, return the last index of collection along dimension d.\n\nThe syntaxes A[end] and A[end, end] lower to A[lastindex(A)] and A[lastindex(A, 1), lastindex(A, 2)], respectively.\n\nSee also: axes, firstindex, eachindex, prevind.\n\nExamples\n\njulia> lastindex([1,2,4])\n3\n\njulia> lastindex(rand(3,4,5), 2)\n4\n\n\n\n\n\n","category":"function"},{"location":"base/collections/","page":"集合和数据结构","title":"集合和数据结构","text":"以下类型均完全实现了上述函数:","category":"page"},{"location":"base/collections/","page":"集合和数据结构","title":"集合和数据结构","text":"Array\nBitArray\nAbstractArray\nSubArray","category":"page"},{"location":"base/collections/","page":"集合和数据结构","title":"集合和数据结构","text":"以下类型仅实现了部分上述函数:","category":"page"},{"location":"base/collections/","page":"集合和数据结构","title":"集合和数据结构","text":"AbstractRange\nUnitRange\nTuple\nAbstractString\nDict\nIdDict\nWeakKeyDict\nNamedTuple","category":"page"},{"location":"base/collections/#字典","page":"集合和数据结构","title":"字典","text":"","category":"section"},{"location":"base/collections/","page":"集合和数据结构","title":"集合和数据结构","text":"Dict 是一个标准字典。其实现利用了 hash 作为键的哈希函数和 isequal 来决定是否相等。对于自定义类型,可以定义这两个函数来重载它们在哈希表内的存储方式。","category":"page"},{"location":"base/collections/","page":"集合和数据结构","title":"集合和数据结构","text":"IdDict 是一种特殊的哈希表,在里面键始终是对象标识符。","category":"page"},{"location":"base/collections/","page":"集合和数据结构","title":"集合和数据结构","text":"WeakKeyDict 是一个哈希表的实现,里面键是对象的弱引用, 所以即使键在哈希表中被引用也有可能被垃圾回收。 它像 Dict 一样使用 hash 来做哈希和 isequal 来做相等判断, 但是它不会在插入时转换键,这点不像 Dict。","category":"page"},{"location":"base/collections/","page":"集合和数据结构","title":"集合和数据结构","text":"Dicts 可以由传递含有 => 的成对对象给 Dict 的构造函数来被创建:Dict(\"A\"=>1, \"B\"=>2)。 这个调用会尝试从键值对中推到类型信息(比如这个例子创造了一个 Dict{String, Int64})。 为了显式指定类型,请使用语法 Dict{KeyType,ValueType}(...)。例如:Dict{String,Int32}(\"A\"=>1, \"B\"=>2)。","category":"page"},{"location":"base/collections/","page":"集合和数据结构","title":"集合和数据结构","text":"字典也可以用生成器创建。例如:Dict(i => f(i) for i = 1:10)。","category":"page"},{"location":"base/collections/","page":"集合和数据结构","title":"集合和数据结构","text":"对于字典 D,若键 x 的值存在,则语法 D[x] 返回 x 的值;否则抛出一个错误。 D[x] = y 存储键值对 x => y 到 D 中,会覆盖键 x 的已有的值。 多个参数传入D[...] 会被转化成元组; 例如:语法 D[x,y] 等于 D[(x,y)],也就是说,它指向键为元组 (x,y) 的值。","category":"page"},{"location":"base/collections/","page":"集合和数据结构","title":"集合和数据结构","text":"Base.AbstractDict\nBase.Dict\nBase.IdDict\nBase.WeakKeyDict\nBase.ImmutableDict\nBase.haskey\nBase.get\nBase.get!\nBase.getkey\nBase.delete!\nBase.pop!(::Any, ::Any, ::Any)\nBase.keys\nBase.values\nBase.pairs\nBase.merge\nBase.mergewith\nBase.merge!\nBase.mergewith!\nBase.sizehint!\nBase.keytype\nBase.valtype","category":"page"},{"location":"base/collections/#Base.AbstractDict","page":"集合和数据结构","title":"Base.AbstractDict","text":"AbstractDict{K, V}\n\nSupertype for dictionary-like types with keys of type K and values of type V. Dict, IdDict and other types are subtypes of this. An AbstractDict{K, V} should be an iterator of Pair{K, V}.\n\n\n\n\n\n","category":"type"},{"location":"base/collections/#Base.Dict","page":"集合和数据结构","title":"Base.Dict","text":"Dict([itr])\n\nDict{K,V}() constructs a hash table with keys of type K and values of type V. Keys are compared with isequal and hashed with hash.\n\nGiven a single iterable argument, constructs a Dict whose key-value pairs are taken from 2-tuples (key,value) generated by the argument.\n\nExamples\n\njulia> Dict([(\"A\", 1), (\"B\", 2)])\nDict{String, Int64} with 2 entries:\n \"B\" => 2\n \"A\" => 1\n\nAlternatively, a sequence of pair arguments may be passed.\n\njulia> Dict(\"A\"=>1, \"B\"=>2)\nDict{String, Int64} with 2 entries:\n \"B\" => 2\n \"A\" => 1\n\n\n\n\n\n","category":"type"},{"location":"base/collections/#Base.IdDict","page":"集合和数据结构","title":"Base.IdDict","text":"IdDict([itr])\n\nIdDict{K,V}() constructs a hash table using objectid as hash and === as equality with keys of type K and values of type V.\n\nSee Dict for further help. In the example below, The Dict keys are all isequal and therefore get hashed the same, so they get overwritten. The IdDict hashes by object-id, and thus preserves the 3 different keys.\n\nExamples\n\njulia> Dict(true => \"yes\", 1 => \"no\", 1.0 => \"maybe\")\nDict{Real, String} with 1 entry:\n 1.0 => \"maybe\"\n\njulia> IdDict(true => \"yes\", 1 => \"no\", 1.0 => \"maybe\")\nIdDict{Any, String} with 3 entries:\n true => \"yes\"\n 1.0 => \"maybe\"\n 1 => \"no\"\n\n\n\n\n\n","category":"type"},{"location":"base/collections/#Base.WeakKeyDict","page":"集合和数据结构","title":"Base.WeakKeyDict","text":"WeakKeyDict([itr])\n\nWeakKeyDict() constructs a hash table where the keys are weak references to objects which may be garbage collected even when referenced in a hash table.\n\nSee Dict for further help. Note, unlike Dict, WeakKeyDict does not convert keys on insertion, as this would imply the key object was unreferenced anywhere before insertion.\n\n\n\n\n\n","category":"type"},{"location":"base/collections/#Base.ImmutableDict","page":"集合和数据结构","title":"Base.ImmutableDict","text":"ImmutableDict\n\nImmutableDict is a dictionary implemented as an immutable linked list, which is optimal for small dictionaries that are constructed over many individual insertions. Note that it is not possible to remove a value, although it can be partially overridden and hidden by inserting a new value with the same key.\n\nImmutableDict(KV::Pair)\n\nCreate a new entry in the ImmutableDict for a key => value pair\n\nuse (key => value) in dict to see if this particular combination is in the properties set\nuse get(dict, key, default) to retrieve the most recent value for a particular key\n\n\n\n\n\n","category":"type"},{"location":"base/collections/#Base.haskey","page":"集合和数据结构","title":"Base.haskey","text":"haskey(collection, key) -> Bool\n\nDetermine whether a collection has a mapping for a given key.\n\nExamples\n\njulia> D = Dict('a'=>2, 'b'=>3)\nDict{Char, Int64} with 2 entries:\n 'a' => 2\n 'b' => 3\n\njulia> haskey(D, 'a')\ntrue\n\njulia> haskey(D, 'c')\nfalse\n\n\n\n\n\n","category":"function"},{"location":"base/collections/#Base.get","page":"集合和数据结构","title":"Base.get","text":"get(collection, key, default)\n\nReturn the value stored for the given key, or the given default value if no mapping for the key is present.\n\ncompat: Julia 1.7\nFor tuples and numbers, this function requires at least Julia 1.7.\n\nExamples\n\njulia> d = Dict(\"a\"=>1, \"b\"=>2);\n\njulia> get(d, \"a\", 3)\n1\n\njulia> get(d, \"c\", 3)\n3\n\n\n\n\n\nget(f::Function, collection, key)\n\nReturn the value stored for the given key, or if no mapping for the key is present, return f(). Use get! to also store the default value in the dictionary.\n\nThis is intended to be called using do block syntax\n\nget(dict, key) do\n # default value calculated here\n time()\nend\n\n\n\n\n\n","category":"function"},{"location":"base/collections/#Base.get!","page":"集合和数据结构","title":"Base.get!","text":"get!(collection, key, default)\n\nReturn the value stored for the given key, or if no mapping for the key is present, store key => default, and return default.\n\nExamples\n\njulia> d = Dict(\"a\"=>1, \"b\"=>2, \"c\"=>3);\n\njulia> get!(d, \"a\", 5)\n1\n\njulia> get!(d, \"d\", 4)\n4\n\njulia> d\nDict{String, Int64} with 4 entries:\n \"c\" => 3\n \"b\" => 2\n \"a\" => 1\n \"d\" => 4\n\n\n\n\n\nget!(f::Function, collection, key)\n\nReturn the value stored for the given key, or if no mapping for the key is present, store key => f(), and return f().\n\nThis is intended to be called using do block syntax.\n\nExamples\n\njulia> squares = Dict{Int, Int}();\n\njulia> function get_square!(d, i)\n get!(d, i) do\n i^2\n end\n end\nget_square! (generic function with 1 method)\n\njulia> get_square!(squares, 2)\n4\n\njulia> squares\nDict{Int64, Int64} with 1 entry:\n 2 => 4\n\n\n\n\n\n","category":"function"},{"location":"base/collections/#Base.getkey","page":"集合和数据结构","title":"Base.getkey","text":"getkey(collection, key, default)\n\nReturn the key matching argument key if one exists in collection, otherwise return default.\n\nExamples\n\njulia> D = Dict('a'=>2, 'b'=>3)\nDict{Char, Int64} with 2 entries:\n 'a' => 2\n 'b' => 3\n\njulia> getkey(D, 'a', 1)\n'a': ASCII/Unicode U+0061 (category Ll: Letter, lowercase)\n\njulia> getkey(D, 'd', 'a')\n'a': ASCII/Unicode U+0061 (category Ll: Letter, lowercase)\n\n\n\n\n\n","category":"function"},{"location":"base/collections/#Base.delete!","page":"集合和数据结构","title":"Base.delete!","text":"delete!(collection, key)\n\nDelete the mapping for the given key in a collection, if any, and return the collection.\n\nExamples\n\njulia> d = Dict(\"a\"=>1, \"b\"=>2)\nDict{String, Int64} with 2 entries:\n \"b\" => 2\n \"a\" => 1\n\njulia> delete!(d, \"b\")\nDict{String, Int64} with 1 entry:\n \"a\" => 1\n\njulia> delete!(d, \"b\") # d is left unchanged\nDict{String, Int64} with 1 entry:\n \"a\" => 1\n\n\n\n\n\n","category":"function"},{"location":"base/collections/#Base.pop!-Tuple{Any, Any, Any}","page":"集合和数据结构","title":"Base.pop!","text":"pop!(collection, key[, default])\n\nDelete and return the mapping for key if it exists in collection, otherwise return default, or throw an error if default is not specified.\n\nExamples\n\njulia> d = Dict(\"a\"=>1, \"b\"=>2, \"c\"=>3);\n\njulia> pop!(d, \"a\")\n1\n\njulia> pop!(d, \"d\")\nERROR: KeyError: key \"d\" not found\nStacktrace:\n[...]\n\njulia> pop!(d, \"e\", 4)\n4\n\n\n\n\n\n","category":"method"},{"location":"base/collections/#Base.keys","page":"集合和数据结构","title":"Base.keys","text":"keys(iterator)\n\nFor an iterator or collection that has keys and values (e.g. arrays and dictionaries), return an iterator over the keys.\n\n\n\n\n\n","category":"function"},{"location":"base/collections/#Base.values","page":"集合和数据结构","title":"Base.values","text":"values(iterator)\n\nFor an iterator or collection that has keys and values, return an iterator over the values. This function simply returns its argument by default, since the elements of a general iterator are normally considered its \"values\".\n\nExamples\n\njulia> d = Dict(\"a\"=>1, \"b\"=>2);\n\njulia> values(d)\nValueIterator for a Dict{String, Int64} with 2 entries. Values:\n 2\n 1\n\njulia> values([2])\n1-element Vector{Int64}:\n 2\n\n\n\n\n\nvalues(a::AbstractDict)\n\nReturn an iterator over all values in a collection. collect(values(a)) returns an array of values. When the values are stored internally in a hash table, as is the case for Dict, the order in which they are returned may vary. But keys(a) and values(a) both iterate a and return the elements in the same order.\n\nExamples\n\njulia> D = Dict('a'=>2, 'b'=>3)\nDict{Char, Int64} with 2 entries:\n 'a' => 2\n 'b' => 3\n\njulia> collect(values(D))\n2-element Vector{Int64}:\n 2\n 3\n\n\n\n\n\n","category":"function"},{"location":"base/collections/#Base.pairs","page":"集合和数据结构","title":"Base.pairs","text":"pairs(IndexLinear(), A)\npairs(IndexCartesian(), A)\npairs(IndexStyle(A), A)\n\nAn iterator that accesses each element of the array A, returning i => x, where i is the index for the element and x = A[i]. Identical to pairs(A), except that the style of index can be selected. Also similar to enumerate(A), except i will be a valid index for A, while enumerate always counts from 1 regardless of the indices of A.\n\nSpecifying IndexLinear() ensures that i will be an integer; specifying IndexCartesian() ensures that i will be a CartesianIndex; specifying IndexStyle(A) chooses whichever has been defined as the native indexing style for array A.\n\nMutation of the bounds of the underlying array will invalidate this iterator.\n\nExamples\n\njulia> A = [\"a\" \"d\"; \"b\" \"e\"; \"c\" \"f\"];\n\njulia> for (index, value) in pairs(IndexStyle(A), A)\n println(\"$index $value\")\n end\n1 a\n2 b\n3 c\n4 d\n5 e\n6 f\n\njulia> S = view(A, 1:2, :);\n\njulia> for (index, value) in pairs(IndexStyle(S), S)\n println(\"$index $value\")\n end\nCartesianIndex(1, 1) a\nCartesianIndex(2, 1) b\nCartesianIndex(1, 2) d\nCartesianIndex(2, 2) e\n\nSee also IndexStyle, axes.\n\n\n\n\n\npairs(collection)\n\nReturn an iterator over key => value pairs for any collection that maps a set of keys to a set of values. This includes arrays, where the keys are the array indices.\n\nExamples\n\njulia> a = Dict(zip([\"a\", \"b\", \"c\"], [1, 2, 3]))\nDict{String, Int64} with 3 entries:\n \"c\" => 3\n \"b\" => 2\n \"a\" => 1\n\njulia> pairs(a)\nDict{String, Int64} with 3 entries:\n \"c\" => 3\n \"b\" => 2\n \"a\" => 1\n\njulia> foreach(println, pairs([\"a\", \"b\", \"c\"]))\n1 => \"a\"\n2 => \"b\"\n3 => \"c\"\n\njulia> (;a=1, b=2, c=3) |> pairs |> collect\n3-element Vector{Pair{Symbol, Int64}}:\n :a => 1\n :b => 2\n :c => 3\n\njulia> (;a=1, b=2, c=3) |> collect\n3-element Vector{Int64}:\n 1\n 2\n 3\n\n\n\n\n\n","category":"function"},{"location":"base/collections/#Base.merge","page":"集合和数据结构","title":"Base.merge","text":"merge(d::AbstractDict, others::AbstractDict...)\n\nConstruct a merged collection from the given collections. If necessary, the types of the resulting collection will be promoted to accommodate the types of the merged collections. If the same key is present in another collection, the value for that key will be the value it has in the last collection listed. See also mergewith for custom handling of values with the same key.\n\nExamples\n\njulia> a = Dict(\"foo\" => 0.0, \"bar\" => 42.0)\nDict{String, Float64} with 2 entries:\n \"bar\" => 42.0\n \"foo\" => 0.0\n\njulia> b = Dict(\"baz\" => 17, \"bar\" => 4711)\nDict{String, Int64} with 2 entries:\n \"bar\" => 4711\n \"baz\" => 17\n\njulia> merge(a, b)\nDict{String, Float64} with 3 entries:\n \"bar\" => 4711.0\n \"baz\" => 17.0\n \"foo\" => 0.0\n\njulia> merge(b, a)\nDict{String, Float64} with 3 entries:\n \"bar\" => 42.0\n \"baz\" => 17.0\n \"foo\" => 0.0\n\n\n\n\n\nmerge(a::NamedTuple, bs::NamedTuple...)\n\nConstruct a new named tuple by merging two or more existing ones, in a left-associative manner. Merging proceeds left-to-right, between pairs of named tuples, and so the order of fields present in both the leftmost and rightmost named tuples take the same position as they are found in the leftmost named tuple. However, values are taken from matching fields in the rightmost named tuple that contains that field. Fields present in only the rightmost named tuple of a pair are appended at the end. A fallback is implemented for when only a single named tuple is supplied, with signature merge(a::NamedTuple).\n\ncompat: Julia 1.1\nMerging 3 or more NamedTuple requires at least Julia 1.1.\n\nExamples\n\njulia> merge((a=1, b=2, c=3), (b=4, d=5))\n(a = 1, b = 4, c = 3, d = 5)\n\njulia> merge((a=1, b=2), (b=3, c=(d=1,)), (c=(d=2,),))\n(a = 1, b = 3, c = (d = 2,))\n\n\n\n\n\nmerge(a::NamedTuple, iterable)\n\nInterpret an iterable of key-value pairs as a named tuple, and perform a merge.\n\njulia> merge((a=1, b=2, c=3), [:b=>4, :d=>5])\n(a = 1, b = 4, c = 3, d = 5)\n\n\n\n\n\n","category":"function"},{"location":"base/collections/#Base.mergewith","page":"集合和数据结构","title":"Base.mergewith","text":"mergewith(combine, d::AbstractDict, others::AbstractDict...)\nmergewith(combine)\nmerge(combine, d::AbstractDict, others::AbstractDict...)\n\nConstruct a merged collection from the given collections. If necessary, the types of the resulting collection will be promoted to accommodate the types of the merged collections. Values with the same key will be combined using the combiner function. The curried form mergewith(combine) returns the function (args...) -> mergewith(combine, args...).\n\nMethod merge(combine::Union{Function,Type}, args...) as an alias of mergewith(combine, args...) is still available for backward compatibility.\n\ncompat: Julia 1.5\nmergewith requires Julia 1.5 or later.\n\nExamples\n\njulia> a = Dict(\"foo\" => 0.0, \"bar\" => 42.0)\nDict{String, Float64} with 2 entries:\n \"bar\" => 42.0\n \"foo\" => 0.0\n\njulia> b = Dict(\"baz\" => 17, \"bar\" => 4711)\nDict{String, Int64} with 2 entries:\n \"bar\" => 4711\n \"baz\" => 17\n\njulia> mergewith(+, a, b)\nDict{String, Float64} with 3 entries:\n \"bar\" => 4753.0\n \"baz\" => 17.0\n \"foo\" => 0.0\n\njulia> ans == mergewith(+)(a, b)\ntrue\n\n\n\n\n\n","category":"function"},{"location":"base/collections/#Base.merge!","page":"集合和数据结构","title":"Base.merge!","text":"merge!(d::AbstractDict, others::AbstractDict...)\n\nUpdate collection with pairs from the other collections. See also merge.\n\nExamples\n\njulia> d1 = Dict(1 => 2, 3 => 4);\n\njulia> d2 = Dict(1 => 4, 4 => 5);\n\njulia> merge!(d1, d2);\n\njulia> d1\nDict{Int64, Int64} with 3 entries:\n 4 => 5\n 3 => 4\n 1 => 4\n\n\n\n\n\n","category":"function"},{"location":"base/collections/#Base.mergewith!","page":"集合和数据结构","title":"Base.mergewith!","text":"mergewith!(combine, d::AbstractDict, others::AbstractDict...) -> d\nmergewith!(combine)\nmerge!(combine, d::AbstractDict, others::AbstractDict...) -> d\n\nUpdate collection with pairs from the other collections. Values with the same key will be combined using the combiner function. The curried form mergewith!(combine) returns the function (args...) -> mergewith!(combine, args...).\n\nMethod merge!(combine::Union{Function,Type}, args...) as an alias of mergewith!(combine, args...) is still available for backward compatibility.\n\ncompat: Julia 1.5\nmergewith! requires Julia 1.5 or later.\n\nExamples\n\njulia> d1 = Dict(1 => 2, 3 => 4);\n\njulia> d2 = Dict(1 => 4, 4 => 5);\n\njulia> mergewith!(+, d1, d2);\n\njulia> d1\nDict{Int64, Int64} with 3 entries:\n 4 => 5\n 3 => 4\n 1 => 6\n\njulia> mergewith!(-, d1, d1);\n\njulia> d1\nDict{Int64, Int64} with 3 entries:\n 4 => 0\n 3 => 0\n 1 => 0\n\njulia> foldl(mergewith!(+), [d1, d2]; init=Dict{Int64, Int64}())\nDict{Int64, Int64} with 3 entries:\n 4 => 5\n 3 => 0\n 1 => 4\n\n\n\n\n\n","category":"function"},{"location":"base/collections/#Base.sizehint!","page":"集合和数据结构","title":"Base.sizehint!","text":"sizehint!(s, n)\n\nSuggest that collection s reserve capacity for at least n elements. This can improve performance.\n\nNotes on the performance model\n\nFor types that support sizehint!,\n\npush! and append! methods generally may (but are not required to) preallocate extra storage. For types implemented in Base, they typically do, using a heuristic optimized for a general use case.\nsizehint! may control this preallocation. Again, it typically does this for types in Base.\nempty! is nearly costless (and O(1)) for types that support this kind of preallocation.\n\n\n\n\n\n","category":"function"},{"location":"base/collections/#Base.keytype","page":"集合和数据结构","title":"Base.keytype","text":"keytype(T::Type{<:AbstractArray})\nkeytype(A::AbstractArray)\n\nReturn the key type of an array. This is equal to the eltype of the result of keys(...), and is provided mainly for compatibility with the dictionary interface.\n\nExamples\n\njulia> keytype([1, 2, 3]) == Int\ntrue\n\njulia> keytype([1 2; 3 4])\nCartesianIndex{2}\n\ncompat: Julia 1.2\nFor arrays, this function requires at least Julia 1.2.\n\n\n\n\n\nkeytype(type)\n\nGet the key type of a dictionary type. Behaves similarly to eltype.\n\nExamples\n\njulia> keytype(Dict(Int32(1) => \"foo\"))\nInt32\n\n\n\n\n\n","category":"function"},{"location":"base/collections/#Base.valtype","page":"集合和数据结构","title":"Base.valtype","text":"valtype(T::Type{<:AbstractArray})\nvaltype(A::AbstractArray)\n\nReturn the value type of an array. This is identical to eltype and is provided mainly for compatibility with the dictionary interface.\n\nExamples\n\njulia> valtype([\"one\", \"two\", \"three\"])\nString\n\ncompat: Julia 1.2\nFor arrays, this function requires at least Julia 1.2.\n\n\n\n\n\nvaltype(type)\n\nGet the value type of a dictionary type. Behaves similarly to eltype.\n\nExamples\n\njulia> valtype(Dict(Int32(1) => \"foo\"))\nString\n\n\n\n\n\n","category":"function"},{"location":"base/collections/","page":"集合和数据结构","title":"集合和数据结构","text":"以下类型均完全实现了上述函数:","category":"page"},{"location":"base/collections/","page":"集合和数据结构","title":"集合和数据结构","text":"IdDict\nDict\nWeakKeyDict","category":"page"},{"location":"base/collections/","page":"集合和数据结构","title":"集合和数据结构","text":"以下类型仅实现了部分上述函数:","category":"page"},{"location":"base/collections/","page":"集合和数据结构","title":"集合和数据结构","text":"BitSet\nSet\nEnvDict\nArray\nBitArray\nImmutableDict\nIterators.Pairs","category":"page"},{"location":"base/collections/#类似-Set-的集合","page":"集合和数据结构","title":"类似 Set 的集合","text":"","category":"section"},{"location":"base/collections/","page":"集合和数据结构","title":"集合和数据结构","text":"Base.AbstractSet\nBase.Set\nBase.BitSet\nBase.union\nBase.union!\nBase.intersect\nBase.setdiff\nBase.setdiff!\nBase.symdiff\nBase.symdiff!\nBase.intersect!\nBase.issubset\nBase.:⊈\nBase.:⊊\nBase.issetequal\nBase.isdisjoint","category":"page"},{"location":"base/collections/#Base.AbstractSet","page":"集合和数据结构","title":"Base.AbstractSet","text":"AbstractSet{T}\n\nSupertype for set-like types whose elements are of type T. Set, BitSet and other types are subtypes of this.\n\n\n\n\n\n","category":"type"},{"location":"base/collections/#Base.Set","page":"集合和数据结构","title":"Base.Set","text":"Set([itr])\n\nConstruct a Set of the values generated by the given iterable object, or an empty set. Should be used instead of BitSet for sparse integer sets, or for sets of arbitrary objects.\n\nSee also: push!, empty!, union!, in.\n\n\n\n\n\n","category":"type"},{"location":"base/collections/#Base.BitSet","page":"集合和数据结构","title":"Base.BitSet","text":"BitSet([itr])\n\nConstruct a sorted set of Ints generated by the given iterable object, or an empty set. Implemented as a bit string, and therefore designed for dense integer sets. If the set will be sparse (for example, holding a few very large integers), use Set instead.\n\n\n\n\n\n","category":"type"},{"location":"base/collections/#Base.union","page":"集合和数据结构","title":"Base.union","text":"union(s, itrs...)\n∪(s, itrs...)\n\nConstruct an object containing all distinct elements from all of the arguments.\n\nThe first argument controls what kind of container is returned. If this is an array, it maintains the order in which elements first appear.\n\nUnicode ∪ can be typed by writing \\cup then pressing tab in the Julia REPL, and in many editors. This is an infix operator, allowing s ∪ itr.\n\nSee also unique, intersect, isdisjoint, vcat, Iterators.flatten.\n\nExamples\n\njulia> union([1, 2], [3])\n3-element Vector{Int64}:\n 1\n 2\n 3\n\njulia> union([4 2 3 4 4], 1:3, 3.0)\n4-element Vector{Float64}:\n 4.0\n 2.0\n 3.0\n 1.0\n\njulia> (0, 0.0) ∪ (-0.0, NaN)\n3-element Vector{Real}:\n 0\n -0.0\n NaN\n\njulia> union(Set([1, 2]), 2:3)\nSet{Int64} with 3 elements:\n 2\n 3\n 1\n\n\n\n\n\n","category":"function"},{"location":"base/collections/#Base.union!","page":"集合和数据结构","title":"Base.union!","text":"union!(s::Union{AbstractSet,AbstractVector}, itrs...)\n\nConstruct the union of passed in sets and overwrite s with the result. Maintain order with arrays.\n\nExamples\n\njulia> a = Set([3, 4, 5]);\n\njulia> union!(a, 1:2:7);\n\njulia> a\nSet{Int64} with 5 elements:\n 5\n 4\n 7\n 3\n 1\n\n\n\n\n\n","category":"function"},{"location":"base/collections/#Base.intersect","page":"集合和数据结构","title":"Base.intersect","text":"intersect(s, itrs...)\n∩(s, itrs...)\n\nConstruct the set containing those elements which appear in all of the arguments.\n\nThe first argument controls what kind of container is returned. If this is an array, it maintains the order in which elements first appear.\n\nUnicode ∩ can be typed by writing \\cap then pressing tab in the Julia REPL, and in many editors. This is an infix operator, allowing s ∩ itr.\n\nSee also setdiff, isdisjoint, issubset, issetequal.\n\ncompat: Julia 1.8\nAs of Julia 1.8 intersect returns a result with the eltype of the type-promoted eltypes of the two inputs\n\nExamples\n\njulia> intersect([1, 2, 3], [3, 4, 5])\n1-element Vector{Int64}:\n 3\n\njulia> intersect([1, 4, 4, 5, 6], [6, 4, 6, 7, 8])\n2-element Vector{Int64}:\n 4\n 6\n\njulia> intersect(1:16, 7:99)\n7:16\n\njulia> (0, 0.0) ∩ (-0.0, 0)\n1-element Vector{Real}:\n 0\n\njulia> intersect(Set([1, 2]), BitSet([2, 3]), 1.0:10.0)\nSet{Float64} with 1 element:\n 2.0\n\n\n\n\n\n","category":"function"},{"location":"base/collections/#Base.setdiff","page":"集合和数据结构","title":"Base.setdiff","text":"setdiff(s, itrs...)\n\nConstruct the set of elements in s but not in any of the iterables in itrs. Maintain order with arrays.\n\nSee also setdiff!, union and intersect.\n\nExamples\n\njulia> setdiff([1,2,3], [3,4,5])\n2-element Vector{Int64}:\n 1\n 2\n\n\n\n\n\n","category":"function"},{"location":"base/collections/#Base.setdiff!","page":"集合和数据结构","title":"Base.setdiff!","text":"setdiff!(s, itrs...)\n\nRemove from set s (in-place) each element of each iterable from itrs. Maintain order with arrays.\n\nExamples\n\njulia> a = Set([1, 3, 4, 5]);\n\njulia> setdiff!(a, 1:2:6);\n\njulia> a\nSet{Int64} with 1 element:\n 4\n\n\n\n\n\n","category":"function"},{"location":"base/collections/#Base.symdiff","page":"集合和数据结构","title":"Base.symdiff","text":"symdiff(s, itrs...)\n\nConstruct the symmetric difference of elements in the passed in sets. When s is not an AbstractSet, the order is maintained. Note that in this case the multiplicity of elements matters.\n\nSee also symdiff!, setdiff, union and intersect.\n\nExamples\n\njulia> symdiff([1,2,3], [3,4,5], [4,5,6])\n3-element Vector{Int64}:\n 1\n 2\n 6\n\njulia> symdiff([1,2,1], [2, 1, 2])\n2-element Vector{Int64}:\n 1\n 2\n\njulia> symdiff(unique([1,2,1]), unique([2, 1, 2]))\nInt64[]\n\n\n\n\n\n","category":"function"},{"location":"base/collections/#Base.symdiff!","page":"集合和数据结构","title":"Base.symdiff!","text":"symdiff!(s::Union{AbstractSet,AbstractVector}, itrs...)\n\nConstruct the symmetric difference of the passed in sets, and overwrite s with the result. When s is an array, the order is maintained. Note that in this case the multiplicity of elements matters.\n\n\n\n\n\n","category":"function"},{"location":"base/collections/#Base.intersect!","page":"集合和数据结构","title":"Base.intersect!","text":"intersect!(s::Union{AbstractSet,AbstractVector}, itrs...)\n\nIntersect all passed in sets and overwrite s with the result. Maintain order with arrays.\n\n\n\n\n\n","category":"function"},{"location":"base/collections/#Base.issubset","page":"集合和数据结构","title":"Base.issubset","text":"issubset(a, b) -> Bool\n⊆(a, b) -> Bool\n⊇(b, a) -> Bool\n\nDetermine whether every element of a is also in b, using in.\n\nSee also ⊊, ⊈, ∩, ∪, contains.\n\nExamples\n\njulia> issubset([1, 2], [1, 2, 3])\ntrue\n\njulia> [1, 2, 3] ⊆ [1, 2]\nfalse\n\njulia> [1, 2, 3] ⊇ [1, 2]\ntrue\n\n\n\n\n\n","category":"function"},{"location":"base/collections/#Base.:⊈","page":"集合和数据结构","title":"Base.:⊈","text":"⊈(a, b) -> Bool\n⊉(b, a) -> Bool\n\nNegation of ⊆ and ⊇, i.e. checks that a is not a subset of b.\n\nSee also issubset (⊆), ⊊.\n\nExamples\n\njulia> (1, 2) ⊈ (2, 3)\ntrue\n\njulia> (1, 2) ⊈ (1, 2, 3)\nfalse\n\n\n\n\n\n","category":"function"},{"location":"base/collections/#Base.:⊊","page":"集合和数据结构","title":"Base.:⊊","text":"⊊(a, b) -> Bool\n⊋(b, a) -> Bool\n\nDetermines if a is a subset of, but not equal to, b.\n\nSee also issubset (⊆), ⊈.\n\nExamples\n\njulia> (1, 2) ⊊ (1, 2, 3)\ntrue\n\njulia> (1, 2) ⊊ (1, 2)\nfalse\n\n\n\n\n\n","category":"function"},{"location":"base/collections/#Base.issetequal","page":"集合和数据结构","title":"Base.issetequal","text":"issetequal(a, b) -> Bool\n\nDetermine whether a and b have the same elements. Equivalent to a ⊆ b && b ⊆ a but more efficient when possible.\n\nSee also: isdisjoint, union.\n\nExamples\n\njulia> issetequal([1, 2], [1, 2, 3])\nfalse\n\njulia> issetequal([1, 2], [2, 1])\ntrue\n\n\n\n\n\n","category":"function"},{"location":"base/collections/#Base.isdisjoint","page":"集合和数据结构","title":"Base.isdisjoint","text":"isdisjoint(a, b) -> Bool\n\nDetermine whether the collections a and b are disjoint. Equivalent to isempty(a ∩ b) but more efficient when possible.\n\nSee also: intersect, isempty, issetequal.\n\ncompat: Julia 1.5\nThis function requires at least Julia 1.5.\n\nExamples\n\njulia> isdisjoint([1, 2], [2, 3, 4])\nfalse\n\njulia> isdisjoint([3, 1], [2, 4])\ntrue\n\n\n\n\n\n","category":"function"},{"location":"base/collections/","page":"集合和数据结构","title":"集合和数据结构","text":"以下类型均完全实现了上述函数:","category":"page"},{"location":"base/collections/","page":"集合和数据结构","title":"集合和数据结构","text":"BitSet\nSet","category":"page"},{"location":"base/collections/","page":"集合和数据结构","title":"集合和数据结构","text":"以下类型仅实现了部分上述函数:","category":"page"},{"location":"base/collections/","page":"集合和数据结构","title":"集合和数据结构","text":"Array","category":"page"},{"location":"base/collections/#双端队列","page":"集合和数据结构","title":"双端队列","text":"","category":"section"},{"location":"base/collections/","page":"集合和数据结构","title":"集合和数据结构","text":"Base.push!\nBase.pop!\nBase.popat!\nBase.pushfirst!\nBase.popfirst!\nBase.insert!\nBase.deleteat!\nBase.keepat!\nBase.splice!\nBase.resize!\nBase.append!\nBase.prepend!","category":"page"},{"location":"base/collections/#Base.push!","page":"集合和数据结构","title":"Base.push!","text":"push!(collection, items...) -> collection\n\nInsert one or more items in collection. If collection is an ordered container, the items are inserted at the end (in the given order).\n\nExamples\n\njulia> push!([1, 2, 3], 4, 5, 6)\n6-element Vector{Int64}:\n 1\n 2\n 3\n 4\n 5\n 6\n\nIf collection is ordered, use append! to add all the elements of another collection to it. The result of the preceding example is equivalent to append!([1, 2, 3], [4, 5, 6]). For AbstractSet objects, union! can be used instead.\n\nSee sizehint! for notes about the performance model.\n\nSee also pushfirst!.\n\n\n\n\n\n","category":"function"},{"location":"base/collections/#Base.pop!","page":"集合和数据结构","title":"Base.pop!","text":"pop!(collection) -> item\n\nRemove an item in collection and return it. If collection is an ordered container, the last item is returned; for unordered containers, an arbitrary element is returned.\n\nSee also: popfirst!, popat!, delete!, deleteat!, splice!, and push!.\n\nExamples\n\njulia> A=[1, 2, 3]\n3-element Vector{Int64}:\n 1\n 2\n 3\n\njulia> pop!(A)\n3\n\njulia> A\n2-element Vector{Int64}:\n 1\n 2\n\njulia> S = Set([1, 2])\nSet{Int64} with 2 elements:\n 2\n 1\n\njulia> pop!(S)\n2\n\njulia> S\nSet{Int64} with 1 element:\n 1\n\njulia> pop!(Dict(1=>2))\n1 => 2\n\n\n\n\n\npop!(collection, key[, default])\n\nDelete and return the mapping for key if it exists in collection, otherwise return default, or throw an error if default is not specified.\n\nExamples\n\njulia> d = Dict(\"a\"=>1, \"b\"=>2, \"c\"=>3);\n\njulia> pop!(d, \"a\")\n1\n\njulia> pop!(d, \"d\")\nERROR: KeyError: key \"d\" not found\nStacktrace:\n[...]\n\njulia> pop!(d, \"e\", 4)\n4\n\n\n\n\n\n","category":"function"},{"location":"base/collections/#Base.popat!","page":"集合和数据结构","title":"Base.popat!","text":"popat!(a::Vector, i::Integer, [default])\n\nRemove the item at the given i and return it. Subsequent items are shifted to fill the resulting gap. When i is not a valid index for a, return default, or throw an error if default is not specified.\n\nSee also: pop!, popfirst!, deleteat!, splice!.\n\ncompat: Julia 1.5\nThis function is available as of Julia 1.5.\n\nExamples\n\njulia> a = [4, 3, 2, 1]; popat!(a, 2)\n3\n\njulia> a\n3-element Vector{Int64}:\n 4\n 2\n 1\n\njulia> popat!(a, 4, missing)\nmissing\n\njulia> popat!(a, 4)\nERROR: BoundsError: attempt to access 3-element Vector{Int64} at index [4]\n[...]\n\n\n\n\n\n","category":"function"},{"location":"base/collections/#Base.pushfirst!","page":"集合和数据结构","title":"Base.pushfirst!","text":"pushfirst!(collection, items...) -> collection\n\nInsert one or more items at the beginning of collection.\n\nThis function is called unshift in many other programming languages.\n\nExamples\n\njulia> pushfirst!([1, 2, 3, 4], 5, 6)\n6-element Vector{Int64}:\n 5\n 6\n 1\n 2\n 3\n 4\n\n\n\n\n\n","category":"function"},{"location":"base/collections/#Base.popfirst!","page":"集合和数据结构","title":"Base.popfirst!","text":"popfirst!(collection) -> item\n\nRemove the first item from collection.\n\nThis function is called shift in many other programming languages.\n\nSee also: pop!, popat!, delete!.\n\nExamples\n\njulia> A = [1, 2, 3, 4, 5, 6]\n6-element Vector{Int64}:\n 1\n 2\n 3\n 4\n 5\n 6\n\njulia> popfirst!(A)\n1\n\njulia> A\n5-element Vector{Int64}:\n 2\n 3\n 4\n 5\n 6\n\n\n\n\n\n","category":"function"},{"location":"base/collections/#Base.insert!","page":"集合和数据结构","title":"Base.insert!","text":"insert!(a::Vector, index::Integer, item)\n\nInsert an item into a at the given index. index is the index of item in the resulting a.\n\nSee also: push!, replace, popat!, splice!.\n\nExamples\n\njulia> insert!(Any[1:6;], 3, \"here\")\n7-element Vector{Any}:\n 1\n 2\n \"here\"\n 3\n 4\n 5\n 6\n\n\n\n\n\n","category":"function"},{"location":"base/collections/#Base.deleteat!","page":"集合和数据结构","title":"Base.deleteat!","text":"deleteat!(a::Vector, i::Integer)\n\nRemove the item at the given i and return the modified a. Subsequent items are shifted to fill the resulting gap.\n\nSee also: delete!, popat!, splice!.\n\nExamples\n\njulia> deleteat!([6, 5, 4, 3, 2, 1], 2)\n5-element Vector{Int64}:\n 6\n 4\n 3\n 2\n 1\n\n\n\n\n\ndeleteat!(a::Vector, inds)\n\nRemove the items at the indices given by inds, and return the modified a. Subsequent items are shifted to fill the resulting gap.\n\ninds can be either an iterator or a collection of sorted and unique integer indices, or a boolean vector of the same length as a with true indicating entries to delete.\n\nExamples\n\njulia> deleteat!([6, 5, 4, 3, 2, 1], 1:2:5)\n3-element Vector{Int64}:\n 5\n 3\n 1\n\njulia> deleteat!([6, 5, 4, 3, 2, 1], [true, false, true, false, true, false])\n3-element Vector{Int64}:\n 5\n 3\n 1\n\njulia> deleteat!([6, 5, 4, 3, 2, 1], (2, 2))\nERROR: ArgumentError: indices must be unique and sorted\nStacktrace:\n[...]\n\n\n\n\n\n","category":"function"},{"location":"base/collections/#Base.keepat!","page":"集合和数据结构","title":"Base.keepat!","text":"keepat!(a::Vector, inds)\nkeepat!(a::BitVector, inds)\n\nRemove the items at all the indices which are not given by inds, and return the modified a. Items which are kept are shifted to fill the resulting gaps.\n\ninds must be an iterator of sorted and unique integer indices. See also deleteat!.\n\ncompat: Julia 1.7\nThis function is available as of Julia 1.7.\n\nExamples\n\njulia> keepat!([6, 5, 4, 3, 2, 1], 1:2:5)\n3-element Vector{Int64}:\n 6\n 4\n 2\n\n\n\n\n\nkeepat!(a::Vector, m::AbstractVector{Bool})\nkeepat!(a::BitVector, m::AbstractVector{Bool})\n\nThe in-place version of logical indexing a = a[m]. That is, keepat!(a, m) on vectors of equal length a and m will remove all elements from a for which m at the corresponding index is false.\n\nExamples\n\njulia> a = [:a, :b, :c];\n\njulia> keepat!(a, [true, false, true])\n2-element Vector{Symbol}:\n :a\n :c\n\njulia> a\n2-element Vector{Symbol}:\n :a\n :c\n\n\n\n\n\n","category":"function"},{"location":"base/collections/#Base.splice!","page":"集合和数据结构","title":"Base.splice!","text":"splice!(a::Vector, index::Integer, [replacement]) -> item\n\nRemove the item at the given index, and return the removed item. Subsequent items are shifted left to fill the resulting gap. If specified, replacement values from an ordered collection will be spliced in place of the removed item.\n\nSee also: replace, delete!, deleteat!, pop!, popat!.\n\nExamples\n\njulia> A = [6, 5, 4, 3, 2, 1]; splice!(A, 5)\n2\n\njulia> A\n5-element Vector{Int64}:\n 6\n 5\n 4\n 3\n 1\n\njulia> splice!(A, 5, -1)\n1\n\njulia> A\n5-element Vector{Int64}:\n 6\n 5\n 4\n 3\n -1\n\njulia> splice!(A, 1, [-1, -2, -3])\n6\n\njulia> A\n7-element Vector{Int64}:\n -1\n -2\n -3\n 5\n 4\n 3\n -1\n\nTo insert replacement before an index n without removing any items, use splice!(collection, n:n-1, replacement).\n\n\n\n\n\nsplice!(a::Vector, indices, [replacement]) -> items\n\nRemove items at specified indices, and return a collection containing the removed items. Subsequent items are shifted left to fill the resulting gaps. If specified, replacement values from an ordered collection will be spliced in place of the removed items; in this case, indices must be a AbstractUnitRange.\n\nTo insert replacement before an index n without removing any items, use splice!(collection, n:n-1, replacement).\n\ncompat: Julia 1.5\nPrior to Julia 1.5, indices must always be a UnitRange.\n\ncompat: Julia 1.8\nPrior to Julia 1.8, indices must be a UnitRange if splicing in replacement values.\n\nExamples\n\njulia> A = [-1, -2, -3, 5, 4, 3, -1]; splice!(A, 4:3, 2)\nInt64[]\n\njulia> A\n8-element Vector{Int64}:\n -1\n -2\n -3\n 2\n 5\n 4\n 3\n -1\n\n\n\n\n\n","category":"function"},{"location":"base/collections/#Base.resize!","page":"集合和数据结构","title":"Base.resize!","text":"resize!(a::Vector, n::Integer) -> Vector\n\nResize a to contain n elements. If n is smaller than the current collection length, the first n elements will be retained. If n is larger, the new elements are not guaranteed to be initialized.\n\nExamples\n\njulia> resize!([6, 5, 4, 3, 2, 1], 3)\n3-element Vector{Int64}:\n 6\n 5\n 4\n\njulia> a = resize!([6, 5, 4, 3, 2, 1], 8);\n\njulia> length(a)\n8\n\njulia> a[1:6]\n6-element Vector{Int64}:\n 6\n 5\n 4\n 3\n 2\n 1\n\n\n\n\n\n","category":"function"},{"location":"base/collections/#Base.append!","page":"集合和数据结构","title":"Base.append!","text":"append!(collection, collections...) -> collection.\n\nFor an ordered container collection, add the elements of each collections to the end of it.\n\ncompat: Julia 1.6\nSpecifying multiple collections to be appended requires at least Julia 1.6.\n\nExamples\n\njulia> append!([1], [2, 3])\n3-element Vector{Int64}:\n 1\n 2\n 3\n\njulia> append!([1, 2, 3], [4, 5], [6])\n6-element Vector{Int64}:\n 1\n 2\n 3\n 4\n 5\n 6\n\nUse push! to add individual items to collection which are not already themselves in another collection. The result of the preceding example is equivalent to push!([1, 2, 3], 4, 5, 6).\n\nSee sizehint! for notes about the performance model.\n\nSee also vcat for vectors, union! for sets, and prepend! and pushfirst! for the opposite order.\n\n\n\n\n\n","category":"function"},{"location":"base/collections/#Base.prepend!","page":"集合和数据结构","title":"Base.prepend!","text":"prepend!(a::Vector, collections...) -> collection\n\nInsert the elements of each collections to the beginning of a.\n\nWhen collections specifies multiple collections, order is maintained: elements of collections[1] will appear leftmost in a, and so on.\n\ncompat: Julia 1.6\nSpecifying multiple collections to be prepended requires at least Julia 1.6.\n\nExamples\n\njulia> prepend!([3], [1, 2])\n3-element Vector{Int64}:\n 1\n 2\n 3\n\njulia> prepend!([6], [1, 2], [3, 4, 5])\n6-element Vector{Int64}:\n 1\n 2\n 3\n 4\n 5\n 6\n\n\n\n\n\n","category":"function"},{"location":"base/collections/","page":"集合和数据结构","title":"集合和数据结构","text":"以下类型均完全实现了上述函数:","category":"page"},{"location":"base/collections/","page":"集合和数据结构","title":"集合和数据结构","text":"Vector (a.k.a. 1-dimensional Array)\nBitVector (a.k.a. 1-dimensional BitArray)","category":"page"},{"location":"base/collections/#集合相关的实用工具","page":"集合和数据结构","title":"集合相关的实用工具","text":"","category":"section"},{"location":"base/collections/","page":"集合和数据结构","title":"集合和数据结构","text":"Base.Pair\nIterators.Pairs","category":"page"},{"location":"base/collections/#Core.Pair","page":"集合和数据结构","title":"Core.Pair","text":"Pair(x, y)\nx => y\n\nConstruct a Pair object with type Pair{typeof(x), typeof(y)}. The elements are stored in the fields first and second. They can also be accessed via iteration (but a Pair is treated as a single \"scalar\" for broadcasting operations).\n\nSee also Dict.\n\nExamples\n\njulia> p = \"foo\" => 7\n\"foo\" => 7\n\njulia> typeof(p)\nPair{String, Int64}\n\njulia> p.first\n\"foo\"\n\njulia> for x in p\n println(x)\n end\nfoo\n7\n\n\n\n\n\n","category":"type"},{"location":"base/collections/#Base.Pairs","page":"集合和数据结构","title":"Base.Pairs","text":"Iterators.Pairs(values, keys) <: AbstractDict{eltype(keys), eltype(values)}\n\nTransforms an indexable container into a Dictionary-view of the same data. Modifying the key-space of the underlying data may invalidate this object.\n\n\n\n\n\n","category":"type"},{"location":"stdlib/Distributed/#man-distributed","page":"Distributed Computing","title":"Distributed Computing","text":"","category":"section"},{"location":"stdlib/Distributed/","page":"Distributed Computing","title":"Distributed Computing","text":"Distributed.addprocs\nDistributed.nprocs\nDistributed.nworkers\nDistributed.procs()\nDistributed.procs(::Integer)\nDistributed.workers\nDistributed.rmprocs\nDistributed.interrupt\nDistributed.myid\nDistributed.pmap\nDistributed.RemoteException\nDistributed.Future\nDistributed.RemoteChannel\nDistributed.fetch(::Distributed.Future)\nDistributed.fetch(::RemoteChannel)\nDistributed.remotecall(::Any, ::Integer, ::Any...)\nDistributed.remotecall_wait(::Any, ::Integer, ::Any...)\nDistributed.remotecall_fetch(::Any, ::Integer, ::Any...)\nDistributed.remote_do(::Any, ::Integer, ::Any...)\nDistributed.put!(::RemoteChannel, ::Any...)\nDistributed.put!(::Distributed.Future, ::Any)\nDistributed.take!(::RemoteChannel, ::Any...)\nDistributed.isready(::RemoteChannel, ::Any...)\nDistributed.isready(::Distributed.Future)\nDistributed.AbstractWorkerPool\nDistributed.WorkerPool\nDistributed.CachingPool\nDistributed.default_worker_pool\nDistributed.clear!(::CachingPool)\nDistributed.remote\nDistributed.remotecall(::Any, ::AbstractWorkerPool, ::Any...)\nDistributed.remotecall_wait(::Any, ::AbstractWorkerPool, ::Any...)\nDistributed.remotecall_fetch(::Any, ::AbstractWorkerPool, ::Any...)\nDistributed.remote_do(::Any, ::AbstractWorkerPool, ::Any...)\nDistributed.@spawnat\nDistributed.@fetch\nDistributed.@fetchfrom\nDistributed.@distributed\nDistributed.@everywhere\nDistributed.clear!(::Any, ::Any; ::Any)\nDistributed.remoteref_id\nDistributed.channel_from_id\nDistributed.worker_id_from_socket\nDistributed.cluster_cookie()\nDistributed.cluster_cookie(::Any)","category":"page"},{"location":"stdlib/Distributed/#Distributed.addprocs","page":"Distributed Computing","title":"Distributed.addprocs","text":"addprocs(manager::ClusterManager; kwargs...) -> List of process identifiers\n\nLaunches worker processes via the specified cluster manager.\n\nFor example, Beowulf clusters are supported via a custom cluster manager implemented in the package ClusterManagers.jl.\n\nThe number of seconds a newly launched worker waits for connection establishment from the master can be specified via variable JULIA_WORKER_TIMEOUT in the worker process's environment. Relevant only when using TCP/IP as transport.\n\nTo launch workers without blocking the REPL, or the containing function if launching workers programmatically, execute addprocs in its own task.\n\nExamples\n\n# On busy clusters, call `addprocs` asynchronously\nt = @async addprocs(...)\n\n# Utilize workers as and when they come online\nif nprocs() > 1 # Ensure at least one new worker is available\n .... # perform distributed execution\nend\n\n# Retrieve newly launched worker IDs, or any error messages\nif istaskdone(t) # Check if `addprocs` has completed to ensure `fetch` doesn't block\n if nworkers() == N\n new_pids = fetch(t)\n else\n fetch(t)\n end\nend\n\n\n\n\n\naddprocs(machines; tunnel=false, sshflags=``, max_parallel=10, kwargs...) -> List of process identifiers\n\nAdd processes on remote machines via SSH. See exename to set the path to the julia installation on remote machines.\n\nmachines is a vector of machine specifications. Workers are started for each specification.\n\nA machine specification is either a string machine_spec or a tuple - (machine_spec, count).\n\nmachine_spec is a string of the form [user@]host[:port] [bind_addr[:port]]. user defaults to current user, port to the standard ssh port. If [bind_addr[:port]] is specified, other workers will connect to this worker at the specified bind_addr and port.\n\ncount is the number of workers to be launched on the specified host. If specified as :auto it will launch as many workers as the number of CPU threads on the specific host.\n\nKeyword arguments:\n\ntunnel: if true then SSH tunneling will be used to connect to the worker from the master process. Default is false.\nmultiplex: if true then SSH multiplexing is used for SSH tunneling. Default is false.\nssh: the name or path of the SSH client executable used to start the workers. Default is \"ssh\".\nsshflags: specifies additional ssh options, e.g. sshflags=`-i /home/foo/bar.pem`\nmax_parallel: specifies the maximum number of workers connected to in parallel at a host. Defaults to 10.\nshell: specifies the type of shell to which ssh connects on the workers.\nshell=:posix: a POSIX-compatible Unix/Linux shell (sh, ksh, bash, dash, zsh, etc.). The default.\nshell=:csh: a Unix C shell (csh, tcsh).\nshell=:wincmd: Microsoft Windows cmd.exe.\ndir: specifies the working directory on the workers. Defaults to the host's current directory (as found by pwd())\nenable_threaded_blas: if true then BLAS will run on multiple threads in added processes. Default is false.\nexename: name of the julia executable. Defaults to \"$(Sys.BINDIR)/julia\" or \"$(Sys.BINDIR)/julia-debug\" as the case may be.\nexeflags: additional flags passed to the worker processes.\ntopology: Specifies how the workers connect to each other. Sending a message between unconnected workers results in an error.\ntopology=:all_to_all: All processes are connected to each other. The default.\ntopology=:master_worker: Only the driver process, i.e. pid 1 connects to the workers. The workers do not connect to each other.\ntopology=:custom: The launch method of the cluster manager specifies the connection topology via fields ident and connect_idents in WorkerConfig. A worker with a cluster manager identity ident will connect to all workers specified in connect_idents.\nlazy: Applicable only with topology=:all_to_all. If true, worker-worker connections are setup lazily, i.e. they are setup at the first instance of a remote call between workers. Default is true.\nenv: provide an array of string pairs such as env=[\"JULIA_DEPOT_PATH\"=>\"/depot\"] to request that environment variables are set on the remote machine. By default only the environment variable JULIA_WORKER_TIMEOUT is passed automatically from the local to the remote environment.\ncmdline_cookie: pass the authentication cookie via the --worker commandline option. The (more secure) default behaviour of passing the cookie via ssh stdio may hang with Windows workers that use older (pre-ConPTY) Julia or Windows versions, in which case cmdline_cookie=true offers a work-around.\n\ncompat: Julia 1.6\nThe keyword arguments ssh, shell, env and cmdline_cookie were added in Julia 1.6.\n\nEnvironment variables:\n\nIf the master process fails to establish a connection with a newly launched worker within 60.0 seconds, the worker treats it as a fatal situation and terminates. This timeout can be controlled via environment variable JULIA_WORKER_TIMEOUT. The value of JULIA_WORKER_TIMEOUT on the master process specifies the number of seconds a newly launched worker waits for connection establishment.\n\n\n\n\n\naddprocs(; kwargs...) -> List of process identifiers\n\nEquivalent to addprocs(Sys.CPU_THREADS; kwargs...)\n\nNote that workers do not run a .julia/config/startup.jl startup script, nor do they synchronize their global state (such as global variables, new method definitions, and loaded modules) with any of the other running processes.\n\n\n\n\n\naddprocs(np::Integer; restrict=true, kwargs...) -> List of process identifiers\n\nLaunches workers using the in-built LocalManager which only launches workers on the local host. This can be used to take advantage of multiple cores. addprocs(4) will add 4 processes on the local machine. If restrict is true, binding is restricted to 127.0.0.1. Keyword args dir, exename, exeflags, topology, lazy and enable_threaded_blas have the same effect as documented for addprocs(machines).\n\n\n\n\n\n","category":"function"},{"location":"stdlib/Distributed/#Distributed.nprocs","page":"Distributed Computing","title":"Distributed.nprocs","text":"nprocs()\n\nGet the number of available processes.\n\nExamples\n\njulia> nprocs()\n3\n\njulia> workers()\n2-element Array{Int64,1}:\n 2\n 3\n\n\n\n\n\n","category":"function"},{"location":"stdlib/Distributed/#Distributed.nworkers","page":"Distributed Computing","title":"Distributed.nworkers","text":"nworkers()\n\nGet the number of available worker processes. This is one less than nprocs(). Equal to nprocs() if nprocs() == 1.\n\nExamples\n\n$ julia -p 2\n\njulia> nprocs()\n3\n\njulia> nworkers()\n2\n\n\n\n\n\n","category":"function"},{"location":"stdlib/Distributed/#Distributed.procs-Tuple{}","page":"Distributed Computing","title":"Distributed.procs","text":"procs()\n\nReturn a list of all process identifiers, including pid 1 (which is not included by workers()).\n\nExamples\n\n$ julia -p 2\n\njulia> procs()\n3-element Array{Int64,1}:\n 1\n 2\n 3\n\n\n\n\n\n","category":"method"},{"location":"stdlib/Distributed/#Distributed.procs-Tuple{Integer}","page":"Distributed Computing","title":"Distributed.procs","text":"procs(pid::Integer)\n\nReturn a list of all process identifiers on the same physical node. Specifically all workers bound to the same ip-address as pid are returned.\n\n\n\n\n\n","category":"method"},{"location":"stdlib/Distributed/#Distributed.workers","page":"Distributed Computing","title":"Distributed.workers","text":"workers()\n\nReturn a list of all worker process identifiers.\n\nExamples\n\n$ julia -p 2\n\njulia> workers()\n2-element Array{Int64,1}:\n 2\n 3\n\n\n\n\n\n","category":"function"},{"location":"stdlib/Distributed/#Distributed.rmprocs","page":"Distributed Computing","title":"Distributed.rmprocs","text":"rmprocs(pids...; waitfor=typemax(Int))\n\nRemove the specified workers. Note that only process 1 can add or remove workers.\n\nArgument waitfor specifies how long to wait for the workers to shut down:\n\nIf unspecified, rmprocs will wait until all requested pids are removed.\nAn ErrorException is raised if all workers cannot be terminated before the requested waitfor seconds.\nWith a waitfor value of 0, the call returns immediately with the workers scheduled for removal in a different task. The scheduled Task object is returned. The user should call wait on the task before invoking any other parallel calls.\n\nExamples\n\n$ julia -p 5\n\njulia> t = rmprocs(2, 3, waitfor=0)\nTask (runnable) @0x0000000107c718d0\n\njulia> wait(t)\n\njulia> workers()\n3-element Array{Int64,1}:\n 4\n 5\n 6\n\n\n\n\n\n","category":"function"},{"location":"stdlib/Distributed/#Distributed.interrupt","page":"Distributed Computing","title":"Distributed.interrupt","text":"interrupt(pids::Integer...)\n\nInterrupt the current executing task on the specified workers. This is equivalent to pressing Ctrl-C on the local machine. If no arguments are given, all workers are interrupted.\n\n\n\n\n\ninterrupt(pids::AbstractVector=workers())\n\nInterrupt the current executing task on the specified workers. This is equivalent to pressing Ctrl-C on the local machine. If no arguments are given, all workers are interrupted.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/Distributed/#Distributed.myid","page":"Distributed Computing","title":"Distributed.myid","text":"myid()\n\nGet the id of the current process.\n\nExamples\n\njulia> myid()\n1\n\njulia> remotecall_fetch(() -> myid(), 4)\n4\n\n\n\n\n\n","category":"function"},{"location":"stdlib/Distributed/#Distributed.pmap","page":"Distributed Computing","title":"Distributed.pmap","text":"pmap(f, [::AbstractWorkerPool], c...; distributed=true, batch_size=1, on_error=nothing, retry_delays=[], retry_check=nothing) -> collection\n\nTransform collection c by applying f to each element using available workers and tasks.\n\nFor multiple collection arguments, apply f elementwise.\n\nNote that f must be made available to all worker processes; see Code Availability and Loading Packages for details.\n\nIf a worker pool is not specified, all available workers, i.e., the default worker pool is used.\n\nBy default, pmap distributes the computation over all specified workers. To use only the local process and distribute over tasks, specify distributed=false. This is equivalent to using asyncmap. For example, pmap(f, c; distributed=false) is equivalent to asyncmap(f,c; ntasks=()->nworkers())\n\npmap can also use a mix of processes and tasks via the batch_size argument. For batch sizes greater than 1, the collection is processed in multiple batches, each of length batch_size or less. A batch is sent as a single request to a free worker, where a local asyncmap processes elements from the batch using multiple concurrent tasks.\n\nAny error stops pmap from processing the remainder of the collection. To override this behavior you can specify an error handling function via argument on_error which takes in a single argument, i.e., the exception. The function can stop the processing by rethrowing the error, or, to continue, return any value which is then returned inline with the results to the caller.\n\nConsider the following two examples. The first one returns the exception object inline, the second a 0 in place of any exception:\n\njulia> pmap(x->iseven(x) ? error(\"foo\") : x, 1:4; on_error=identity)\n4-element Array{Any,1}:\n 1\n ErrorException(\"foo\")\n 3\n ErrorException(\"foo\")\n\njulia> pmap(x->iseven(x) ? error(\"foo\") : x, 1:4; on_error=ex->0)\n4-element Array{Int64,1}:\n 1\n 0\n 3\n 0\n\nErrors can also be handled by retrying failed computations. Keyword arguments retry_delays and retry_check are passed through to retry as keyword arguments delays and check respectively. If batching is specified, and an entire batch fails, all items in the batch are retried.\n\nNote that if both on_error and retry_delays are specified, the on_error hook is called before retrying. If on_error does not throw (or rethrow) an exception, the element will not be retried.\n\nExample: On errors, retry f on an element a maximum of 3 times without any delay between retries.\n\npmap(f, c; retry_delays = zeros(3))\n\nExample: Retry f only if the exception is not of type InexactError, with exponentially increasing delays up to 3 times. Return a NaN in place for all InexactError occurrences.\n\npmap(f, c; on_error = e->(isa(e, InexactError) ? NaN : rethrow()), retry_delays = ExponentialBackOff(n = 3))\n\n\n\n\n\n","category":"function"},{"location":"stdlib/Distributed/#Distributed.RemoteException","page":"Distributed Computing","title":"Distributed.RemoteException","text":"RemoteException(captured)\n\nExceptions on remote computations are captured and rethrown locally. A RemoteException wraps the pid of the worker and a captured exception. A CapturedException captures the remote exception and a serializable form of the call stack when the exception was raised.\n\n\n\n\n\n","category":"type"},{"location":"stdlib/Distributed/#Distributed.Future","page":"Distributed Computing","title":"Distributed.Future","text":"Future(w::Int, rrid::RRID, v::Union{Some, Nothing}=nothing)\n\nA Future is a placeholder for a single computation of unknown termination status and time. For multiple potential computations, see RemoteChannel. See remoteref_id for identifying an AbstractRemoteRef.\n\n\n\n\n\n","category":"type"},{"location":"stdlib/Distributed/#Distributed.RemoteChannel","page":"Distributed Computing","title":"Distributed.RemoteChannel","text":"RemoteChannel(pid::Integer=myid())\n\nMake a reference to a Channel{Any}(1) on process pid. The default pid is the current process.\n\nRemoteChannel(f::Function, pid::Integer=myid())\n\nCreate references to remote channels of a specific size and type. f is a function that when executed on pid must return an implementation of an AbstractChannel.\n\nFor example, RemoteChannel(()->Channel{Int}(10), pid), will return a reference to a channel of type Int and size 10 on pid.\n\nThe default pid is the current process.\n\n\n\n\n\n","category":"type"},{"location":"stdlib/Distributed/#Base.fetch-Tuple{Distributed.Future}","page":"Distributed Computing","title":"Base.fetch","text":"fetch(x::Future)\n\nWait for and get the value of a Future. The fetched value is cached locally. Further calls to fetch on the same reference return the cached value. If the remote value is an exception, throws a RemoteException which captures the remote exception and backtrace.\n\n\n\n\n\n","category":"method"},{"location":"stdlib/Distributed/#Base.fetch-Tuple{RemoteChannel}","page":"Distributed Computing","title":"Base.fetch","text":"fetch(c::RemoteChannel)\n\nWait for and get a value from a RemoteChannel. Exceptions raised are the same as for a Future. Does not remove the item fetched.\n\n\n\n\n\n","category":"method"},{"location":"stdlib/Distributed/#Distributed.remotecall-Tuple{Any, Integer, Vararg{Any}}","page":"Distributed Computing","title":"Distributed.remotecall","text":"remotecall(f, id::Integer, args...; kwargs...) -> Future\n\nCall a function f asynchronously on the given arguments on the specified process. Return a Future. Keyword arguments, if any, are passed through to f.\n\n\n\n\n\n","category":"method"},{"location":"stdlib/Distributed/#Distributed.remotecall_wait-Tuple{Any, Integer, Vararg{Any}}","page":"Distributed Computing","title":"Distributed.remotecall_wait","text":"remotecall_wait(f, id::Integer, args...; kwargs...)\n\nPerform a faster wait(remotecall(...)) in one message on the Worker specified by worker id id. Keyword arguments, if any, are passed through to f.\n\nSee also wait and remotecall.\n\n\n\n\n\n","category":"method"},{"location":"stdlib/Distributed/#Distributed.remotecall_fetch-Tuple{Any, Integer, Vararg{Any}}","page":"Distributed Computing","title":"Distributed.remotecall_fetch","text":"remotecall_fetch(f, id::Integer, args...; kwargs...)\n\nPerform fetch(remotecall(...)) in one message. Keyword arguments, if any, are passed through to f. Any remote exceptions are captured in a RemoteException and thrown.\n\nSee also fetch and remotecall.\n\nExamples\n\n$ julia -p 2\n\njulia> remotecall_fetch(sqrt, 2, 4)\n2.0\n\njulia> remotecall_fetch(sqrt, 2, -4)\nERROR: On worker 2:\nDomainError with -4.0:\nsqrt will only return a complex result if called with a complex argument. Try sqrt(Complex(x)).\n...\n\n\n\n\n\n","category":"method"},{"location":"stdlib/Distributed/#Distributed.remote_do-Tuple{Any, Integer, Vararg{Any}}","page":"Distributed Computing","title":"Distributed.remote_do","text":"remote_do(f, id::Integer, args...; kwargs...) -> nothing\n\nExecutes f on worker id asynchronously. Unlike remotecall, it does not store the result of computation, nor is there a way to wait for its completion.\n\nA successful invocation indicates that the request has been accepted for execution on the remote node.\n\nWhile consecutive remotecalls to the same worker are serialized in the order they are invoked, the order of executions on the remote worker is undetermined. For example, remote_do(f1, 2); remotecall(f2, 2); remote_do(f3, 2) will serialize the call to f1, followed by f2 and f3 in that order. However, it is not guaranteed that f1 is executed before f3 on worker 2.\n\nAny exceptions thrown by f are printed to stderr on the remote worker.\n\nKeyword arguments, if any, are passed through to f.\n\n\n\n\n\n","category":"method"},{"location":"stdlib/Distributed/#Base.put!-Tuple{RemoteChannel, Vararg{Any}}","page":"Distributed Computing","title":"Base.put!","text":"put!(rr::RemoteChannel, args...)\n\nStore a set of values to the RemoteChannel. If the channel is full, blocks until space is available. Return the first argument.\n\n\n\n\n\n","category":"method"},{"location":"stdlib/Distributed/#Base.put!-Tuple{Distributed.Future, Any}","page":"Distributed Computing","title":"Base.put!","text":"put!(rr::Future, v)\n\nStore a value to a Future rr. Futures are write-once remote references. A put! on an already set Future throws an Exception. All asynchronous remote calls return Futures and set the value to the return value of the call upon completion.\n\n\n\n\n\n","category":"method"},{"location":"stdlib/Distributed/#Base.take!-Tuple{RemoteChannel, Vararg{Any}}","page":"Distributed Computing","title":"Base.take!","text":"take!(rr::RemoteChannel, args...)\n\nFetch value(s) from a RemoteChannel rr, removing the value(s) in the process.\n\n\n\n\n\n","category":"method"},{"location":"stdlib/Distributed/#Base.isready-Tuple{RemoteChannel, Vararg{Any}}","page":"Distributed Computing","title":"Base.isready","text":"isready(rr::RemoteChannel, args...)\n\nDetermine whether a RemoteChannel has a value stored to it. Note that this function can cause race conditions, since by the time you receive its result it may no longer be true. However, it can be safely used on a Future since they are assigned only once.\n\n\n\n\n\n","category":"method"},{"location":"stdlib/Distributed/#Base.isready-Tuple{Distributed.Future}","page":"Distributed Computing","title":"Base.isready","text":"isready(rr::Future)\n\nDetermine whether a Future has a value stored to it.\n\nIf the argument Future is owned by a different node, this call will block to wait for the answer. It is recommended to wait for rr in a separate task instead or to use a local Channel as a proxy:\n\np = 1\nf = Future(p)\nerrormonitor(@async put!(f, remotecall_fetch(long_computation, p)))\nisready(f) # will not block\n\n\n\n\n\n","category":"method"},{"location":"stdlib/Distributed/#Distributed.AbstractWorkerPool","page":"Distributed Computing","title":"Distributed.AbstractWorkerPool","text":"AbstractWorkerPool\n\nSupertype for worker pools such as WorkerPool and CachingPool. An AbstractWorkerPool should implement:\n\npush! - add a new worker to the overall pool (available + busy)\nput! - put back a worker to the available pool\ntake! - take a worker from the available pool (to be used for remote function execution)\nlength - number of workers available in the overall pool\nisready - return false if a take! on the pool would block, else true\n\nThe default implementations of the above (on a AbstractWorkerPool) require fields\n\nchannel::Channel{Int}\nworkers::Set{Int}\n\nwhere channel contains free worker pids and workers is the set of all workers associated with this pool.\n\n\n\n\n\n","category":"type"},{"location":"stdlib/Distributed/#Distributed.WorkerPool","page":"Distributed Computing","title":"Distributed.WorkerPool","text":"WorkerPool(workers::Vector{Int})\n\nCreate a WorkerPool from a vector of worker ids.\n\nExamples\n\n$ julia -p 3\n\njulia> WorkerPool([2, 3])\nWorkerPool(Channel{Int64}(sz_max:9223372036854775807,sz_curr:2), Set([2, 3]), RemoteChannel{Channel{Any}}(1, 1, 6))\n\n\n\n\n\n","category":"type"},{"location":"stdlib/Distributed/#Distributed.CachingPool","page":"Distributed Computing","title":"Distributed.CachingPool","text":"CachingPool(workers::Vector{Int})\n\nAn implementation of an AbstractWorkerPool. remote, remotecall_fetch, pmap (and other remote calls which execute functions remotely) benefit from caching the serialized/deserialized functions on the worker nodes, especially closures (which may capture large amounts of data).\n\nThe remote cache is maintained for the lifetime of the returned CachingPool object. To clear the cache earlier, use clear!(pool).\n\nFor global variables, only the bindings are captured in a closure, not the data. let blocks can be used to capture global data.\n\nExamples\n\nconst foo = rand(10^8);\nwp = CachingPool(workers())\nlet foo = foo\n pmap(i -> sum(foo) + i, wp, 1:100);\nend\n\nThe above would transfer foo only once to each worker.\n\n\n\n\n\n","category":"type"},{"location":"stdlib/Distributed/#Distributed.default_worker_pool","page":"Distributed Computing","title":"Distributed.default_worker_pool","text":"default_worker_pool()\n\nWorkerPool containing idle workers - used by remote(f) and pmap (by default).\n\nExamples\n\n$ julia -p 3\n\njulia> default_worker_pool()\nWorkerPool(Channel{Int64}(sz_max:9223372036854775807,sz_curr:3), Set([4, 2, 3]), RemoteChannel{Channel{Any}}(1, 1, 4))\n\n\n\n\n\n","category":"function"},{"location":"stdlib/Distributed/#Distributed.clear!-Tuple{CachingPool}","page":"Distributed Computing","title":"Distributed.clear!","text":"clear!(pool::CachingPool) -> pool\n\nRemoves all cached functions from all participating workers.\n\n\n\n\n\n","category":"method"},{"location":"stdlib/Distributed/#Distributed.remote","page":"Distributed Computing","title":"Distributed.remote","text":"remote([p::AbstractWorkerPool], f) -> Function\n\nReturn an anonymous function that executes function f on an available worker (drawn from WorkerPool p if provided) using remotecall_fetch.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/Distributed/#Distributed.remotecall-Tuple{Any, AbstractWorkerPool, Vararg{Any}}","page":"Distributed Computing","title":"Distributed.remotecall","text":"remotecall(f, pool::AbstractWorkerPool, args...; kwargs...) -> Future\n\nWorkerPool variant of remotecall(f, pid, ....). Wait for and take a free worker from pool and perform a remotecall on it.\n\nExamples\n\n$ julia -p 3\n\njulia> wp = WorkerPool([2, 3]);\n\njulia> A = rand(3000);\n\njulia> f = remotecall(maximum, wp, A)\nFuture(2, 1, 6, nothing)\n\nIn this example, the task ran on pid 2, called from pid 1.\n\n\n\n\n\n","category":"method"},{"location":"stdlib/Distributed/#Distributed.remotecall_wait-Tuple{Any, AbstractWorkerPool, Vararg{Any}}","page":"Distributed Computing","title":"Distributed.remotecall_wait","text":"remotecall_wait(f, pool::AbstractWorkerPool, args...; kwargs...) -> Future\n\nWorkerPool variant of remotecall_wait(f, pid, ....). Wait for and take a free worker from pool and perform a remotecall_wait on it.\n\nExamples\n\n$ julia -p 3\n\njulia> wp = WorkerPool([2, 3]);\n\njulia> A = rand(3000);\n\njulia> f = remotecall_wait(maximum, wp, A)\nFuture(3, 1, 9, nothing)\n\njulia> fetch(f)\n0.9995177101692958\n\n\n\n\n\n","category":"method"},{"location":"stdlib/Distributed/#Distributed.remotecall_fetch-Tuple{Any, AbstractWorkerPool, Vararg{Any}}","page":"Distributed Computing","title":"Distributed.remotecall_fetch","text":"remotecall_fetch(f, pool::AbstractWorkerPool, args...; kwargs...) -> result\n\nWorkerPool variant of remotecall_fetch(f, pid, ....). Waits for and takes a free worker from pool and performs a remotecall_fetch on it.\n\nExamples\n\n$ julia -p 3\n\njulia> wp = WorkerPool([2, 3]);\n\njulia> A = rand(3000);\n\njulia> remotecall_fetch(maximum, wp, A)\n0.9995177101692958\n\n\n\n\n\n","category":"method"},{"location":"stdlib/Distributed/#Distributed.remote_do-Tuple{Any, AbstractWorkerPool, Vararg{Any}}","page":"Distributed Computing","title":"Distributed.remote_do","text":"remote_do(f, pool::AbstractWorkerPool, args...; kwargs...) -> nothing\n\nWorkerPool variant of remote_do(f, pid, ....). Wait for and take a free worker from pool and perform a remote_do on it.\n\n\n\n\n\n","category":"method"},{"location":"stdlib/Distributed/#Distributed.@spawnat","page":"Distributed Computing","title":"Distributed.@spawnat","text":"@spawnat p expr\n\nCreate a closure around an expression and run the closure asynchronously on process p. Return a Future to the result. If p is the quoted literal symbol :any, then the system will pick a processor to use automatically.\n\nExamples\n\njulia> addprocs(3);\n\njulia> f = @spawnat 2 myid()\nFuture(2, 1, 3, nothing)\n\njulia> fetch(f)\n2\n\njulia> f = @spawnat :any myid()\nFuture(3, 1, 7, nothing)\n\njulia> fetch(f)\n3\n\ncompat: Julia 1.3\nThe :any argument is available as of Julia 1.3.\n\n\n\n\n\n","category":"macro"},{"location":"stdlib/Distributed/#Distributed.@fetch","page":"Distributed Computing","title":"Distributed.@fetch","text":"@fetch expr\n\nEquivalent to fetch(@spawnat :any expr). See fetch and @spawnat.\n\nExamples\n\njulia> addprocs(3);\n\njulia> @fetch myid()\n2\n\njulia> @fetch myid()\n3\n\njulia> @fetch myid()\n4\n\njulia> @fetch myid()\n2\n\n\n\n\n\n","category":"macro"},{"location":"stdlib/Distributed/#Distributed.@fetchfrom","page":"Distributed Computing","title":"Distributed.@fetchfrom","text":"@fetchfrom\n\nEquivalent to fetch(@spawnat p expr). See fetch and @spawnat.\n\nExamples\n\njulia> addprocs(3);\n\njulia> @fetchfrom 2 myid()\n2\n\njulia> @fetchfrom 4 myid()\n4\n\n\n\n\n\n","category":"macro"},{"location":"stdlib/Distributed/#Distributed.@distributed","page":"Distributed Computing","title":"Distributed.@distributed","text":"@distributed\n\nA distributed memory, parallel for loop of the form :\n\n@distributed [reducer] for var = range\n body\nend\n\nThe specified range is partitioned and locally executed across all workers. In case an optional reducer function is specified, @distributed performs local reductions on each worker with a final reduction on the calling process.\n\nNote that without a reducer function, @distributed executes asynchronously, i.e. it spawns independent tasks on all available workers and returns immediately without waiting for completion. To wait for completion, prefix the call with @sync, like :\n\n@sync @distributed for var = range\n body\nend\n\n\n\n\n\n","category":"macro"},{"location":"stdlib/Distributed/#Distributed.@everywhere","page":"Distributed Computing","title":"Distributed.@everywhere","text":"@everywhere [procs()] expr\n\nExecute an expression under Main on all procs. Errors on any of the processes are collected into a CompositeException and thrown. For example:\n\n@everywhere bar = 1\n\nwill define Main.bar on all current processes. Any processes added later (say with addprocs()) will not have the expression defined.\n\nUnlike @spawnat, @everywhere does not capture any local variables. Instead, local variables can be broadcast using interpolation:\n\nfoo = 1\n@everywhere bar = $foo\n\nThe optional argument procs allows specifying a subset of all processes to have execute the expression.\n\nSimilar to calling remotecall_eval(Main, procs, expr), but with two extra features:\n\n- `using` and `import` statements run on the calling process first, to ensure\n packages are precompiled.\n- The current source file path used by `include` is propagated to other processes.\n\n\n\n\n\n","category":"macro"},{"location":"stdlib/Distributed/#Distributed.clear!-Tuple{Any, Any}","page":"Distributed Computing","title":"Distributed.clear!","text":"clear!(syms, pids=workers(); mod=Main)\n\nClears global bindings in modules by initializing them to nothing. syms should be of type Symbol or a collection of Symbols . pids and mod identify the processes and the module in which global variables are to be reinitialized. Only those names found to be defined under mod are cleared.\n\nAn exception is raised if a global constant is requested to be cleared.\n\n\n\n\n\n","category":"method"},{"location":"stdlib/Distributed/#Distributed.remoteref_id","page":"Distributed Computing","title":"Distributed.remoteref_id","text":"remoteref_id(r::AbstractRemoteRef) -> RRID\n\nFutures and RemoteChannels are identified by fields:\n\nwhere - refers to the node where the underlying object/storage referred to by the reference actually exists.\nwhence - refers to the node the remote reference was created from. Note that this is different from the node where the underlying object referred to actually exists. For example calling RemoteChannel(2) from the master process would result in a where value of 2 and a whence value of 1.\nid is unique across all references created from the worker specified by whence.\n\nTaken together, whence and id uniquely identify a reference across all workers.\n\nremoteref_id is a low-level API which returns a RRID object that wraps whence and id values of a remote reference.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/Distributed/#Distributed.channel_from_id","page":"Distributed Computing","title":"Distributed.channel_from_id","text":"channel_from_id(id) -> c\n\nA low-level API which returns the backing AbstractChannel for an id returned by remoteref_id. The call is valid only on the node where the backing channel exists.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/Distributed/#Distributed.worker_id_from_socket","page":"Distributed Computing","title":"Distributed.worker_id_from_socket","text":"worker_id_from_socket(s) -> pid\n\nA low-level API which, given a IO connection or a Worker, returns the pid of the worker it is connected to. This is useful when writing custom serialize methods for a type, which optimizes the data written out depending on the receiving process id.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/Distributed/#Distributed.cluster_cookie-Tuple{}","page":"Distributed Computing","title":"Distributed.cluster_cookie","text":"cluster_cookie() -> cookie\n\nReturn the cluster cookie.\n\n\n\n\n\n","category":"method"},{"location":"stdlib/Distributed/#Distributed.cluster_cookie-Tuple{Any}","page":"Distributed Computing","title":"Distributed.cluster_cookie","text":"cluster_cookie(cookie) -> cookie\n\nSet the passed cookie as the cluster cookie, then returns it.\n\n\n\n\n\n","category":"method"},{"location":"stdlib/Distributed/#Cluster-Manager-Interface","page":"Distributed Computing","title":"Cluster Manager Interface","text":"","category":"section"},{"location":"stdlib/Distributed/","page":"Distributed Computing","title":"Distributed Computing","text":"This interface provides a mechanism to launch and manage Julia workers on different cluster environments. There are two types of managers present in Base: LocalManager, for launching additional workers on the same host, and SSHManager, for launching on remote hosts via ssh. TCP/IP sockets are used to connect and transport messages between processes. It is possible for Cluster Managers to provide a different transport.","category":"page"},{"location":"stdlib/Distributed/","page":"Distributed Computing","title":"Distributed Computing","text":"Distributed.ClusterManager\nDistributed.WorkerConfig\nDistributed.launch\nDistributed.manage\nDistributed.kill(::ClusterManager, ::Int, ::WorkerConfig)\nDistributed.connect(::ClusterManager, ::Int, ::WorkerConfig)\nDistributed.init_worker\nDistributed.start_worker\nDistributed.process_messages\nDistributed.default_addprocs_params","category":"page"},{"location":"stdlib/Distributed/#Distributed.ClusterManager","page":"Distributed Computing","title":"Distributed.ClusterManager","text":"ClusterManager\n\nSupertype for cluster managers, which control workers processes as a cluster. Cluster managers implement how workers can be added, removed and communicated with. SSHManager and LocalManager are subtypes of this.\n\n\n\n\n\n","category":"type"},{"location":"stdlib/Distributed/#Distributed.WorkerConfig","page":"Distributed Computing","title":"Distributed.WorkerConfig","text":"WorkerConfig\n\nType used by ClusterManagers to control workers added to their clusters. Some fields are used by all cluster managers to access a host:\n\nio – the connection used to access the worker (a subtype of IO or Nothing)\nhost – the host address (either a String or Nothing)\nport – the port on the host used to connect to the worker (either an Int or Nothing)\n\nSome are used by the cluster manager to add workers to an already-initialized host:\n\ncount – the number of workers to be launched on the host\nexename – the path to the Julia executable on the host, defaults to \"$(Sys.BINDIR)/julia\" or \"$(Sys.BINDIR)/julia-debug\"\nexeflags – flags to use when lauching Julia remotely\n\nThe userdata field is used to store information for each worker by external managers.\n\nSome fields are used by SSHManager and similar managers:\n\ntunnel – true (use tunneling), false (do not use tunneling), or nothing (use default for the manager)\nmultiplex – true (use SSH multiplexing for tunneling) or false\nforward – the forwarding option used for -L option of ssh\nbind_addr – the address on the remote host to bind to\nsshflags – flags to use in establishing the SSH connection\nmax_parallel – the maximum number of workers to connect to in parallel on the host\n\nSome fields are used by both LocalManagers and SSHManagers:\n\nconnect_at – determines whether this is a worker-to-worker or driver-to-worker setup call\nprocess – the process which will be connected (usually the manager will assign this during addprocs)\nospid – the process ID according to the host OS, used to interrupt worker processes\nenviron – private dictionary used to store temporary information by Local/SSH managers\nident – worker as identified by the ClusterManager\nconnect_idents – list of worker ids the worker must connect to if using a custom topology\nenable_threaded_blas – true, false, or nothing, whether to use threaded BLAS or not on the workers\n\n\n\n\n\n","category":"type"},{"location":"stdlib/Distributed/#Distributed.launch","page":"Distributed Computing","title":"Distributed.launch","text":"launch(manager::ClusterManager, params::Dict, launched::Array, launch_ntfy::Condition)\n\nImplemented by cluster managers. For every Julia worker launched by this function, it should append a WorkerConfig entry to launched and notify launch_ntfy. The function MUST exit once all workers, requested by manager have been launched. params is a dictionary of all keyword arguments addprocs was called with.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/Distributed/#Distributed.manage","page":"Distributed Computing","title":"Distributed.manage","text":"manage(manager::ClusterManager, id::Integer, config::WorkerConfig. op::Symbol)\n\nImplemented by cluster managers. It is called on the master process, during a worker's lifetime, with appropriate op values:\n\nwith :register/:deregister when a worker is added / removed from the Julia worker pool.\nwith :interrupt when interrupt(workers) is called. The ClusterManager should signal the appropriate worker with an interrupt signal.\nwith :finalize for cleanup purposes.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/Distributed/#Base.kill-Tuple{ClusterManager, Int64, WorkerConfig}","page":"Distributed Computing","title":"Base.kill","text":"kill(manager::ClusterManager, pid::Int, config::WorkerConfig)\n\nImplemented by cluster managers. It is called on the master process, by rmprocs. It should cause the remote worker specified by pid to exit. kill(manager::ClusterManager.....) executes a remote exit() on pid.\n\n\n\n\n\n","category":"method"},{"location":"stdlib/Distributed/#Sockets.connect-Tuple{ClusterManager, Int64, WorkerConfig}","page":"Distributed Computing","title":"Sockets.connect","text":"connect(manager::ClusterManager, pid::Int, config::WorkerConfig) -> (instrm::IO, outstrm::IO)\n\nImplemented by cluster managers using custom transports. It should establish a logical connection to worker with id pid, specified by config and return a pair of IO objects. Messages from pid to current process will be read off instrm, while messages to be sent to pid will be written to outstrm. The custom transport implementation must ensure that messages are delivered and received completely and in order. connect(manager::ClusterManager.....) sets up TCP/IP socket connections in-between workers.\n\n\n\n\n\n","category":"method"},{"location":"stdlib/Distributed/#Distributed.init_worker","page":"Distributed Computing","title":"Distributed.init_worker","text":"init_worker(cookie::AbstractString, manager::ClusterManager=DefaultClusterManager())\n\nCalled by cluster managers implementing custom transports. It initializes a newly launched process as a worker. Command line argument --worker[=] has the effect of initializing a process as a worker using TCP/IP sockets for transport. cookie is a cluster_cookie.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/Distributed/#Distributed.start_worker","page":"Distributed Computing","title":"Distributed.start_worker","text":"start_worker([out::IO=stdout], cookie::AbstractString=readline(stdin); close_stdin::Bool=true, stderr_to_stdout::Bool=true)\n\nstart_worker is an internal function which is the default entry point for worker processes connecting via TCP/IP. It sets up the process as a Julia cluster worker.\n\nhost:port information is written to stream out (defaults to stdout).\n\nThe function reads the cookie from stdin if required, and listens on a free port (or if specified, the port in the --bind-to command line option) and schedules tasks to process incoming TCP connections and requests. It also (optionally) closes stdin and redirects stderr to stdout.\n\nIt does not return.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/Distributed/#Distributed.process_messages","page":"Distributed Computing","title":"Distributed.process_messages","text":"process_messages(r_stream::IO, w_stream::IO, incoming::Bool=true)\n\nCalled by cluster managers using custom transports. It should be called when the custom transport implementation receives the first message from a remote worker. The custom transport must manage a logical connection to the remote worker and provide two IO objects, one for incoming messages and the other for messages addressed to the remote worker. If incoming is true, the remote peer initiated the connection. Whichever of the pair initiates the connection sends the cluster cookie and its Julia version number to perform the authentication handshake.\n\nSee also cluster_cookie.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/Distributed/#Distributed.default_addprocs_params","page":"Distributed Computing","title":"Distributed.default_addprocs_params","text":"default_addprocs_params(mgr::ClusterManager) -> Dict{Symbol, Any}\n\nImplemented by cluster managers. The default keyword parameters passed when calling addprocs(mgr). The minimal set of options is available by calling default_addprocs_params()\n\n\n\n\n\n","category":"function"},{"location":"manual/conversion-and-promotion/#conversion-and-promotion","page":"类型转换和类型提升","title":"类型转换和类型提升","text":"","category":"section"},{"location":"manual/conversion-and-promotion/","page":"类型转换和类型提升","title":"类型转换和类型提升","text":"Julia 有一个提升系统,可以将数学运算符的参数提升为通用类型,如在前面章节中提到的整数和浮点数、数学运算和初等函数、类型和方法。在本节中,我们将解释类型提升系统如何工作,以及如何将其扩展到新的类型,并将其应用于除内置数学运算符之外的其他函数。传统上,编程语言在参数的类型提升上分为两大阵营:","category":"page"},{"location":"manual/conversion-and-promotion/","page":"类型转换和类型提升","title":"类型转换和类型提升","text":"内置数学类型和运算符的自动类型提升。大多数语言中,内置数值类型,当作为带有中缀语法的算术运算符的操作数时,例如 +、-、* 和 / 将自动提升为通用类型,以产生预期的结果。举例来说,C、Java、Perl 和 Python,都将 1 + 1.5 的和作为浮点值 2.5,即使 + 的一个操作数是整数。这些系统非常方便且设计得足够精细,以至于它对于程序员来讲通常是不可见的:在编写这样的表达式时,几乎没有人有意识地想到这种类型提升,但编译器和解释器必须在相加前执行转换,因为整数和浮点值无法按原样相加。因此,这种自动类型转换的复杂规则不可避免地是这些语言的规范和实现的一部分。\n没有自动类型提升。这个阵营包括 Ada 和 ML——非常「严格的」 静态类型语言。在这些语言中,每个类型转换都必须由程序员明确指定。因此,示例表达式 1 + 1.5 在 Ada 和 ML 中都会导致编译错误。相反地,必须编写 real(1) + 1.5,来在执行加法前将整数 1 显式转换为浮点值。然而,处处都显式转换是如此地不方便,以至于连 Ada 也有一定程度的自动类型转换:整数字面量被类型提升为预期的整数类型,浮点字面量同样被类型提升为适当的浮点类型。","category":"page"},{"location":"manual/conversion-and-promotion/","page":"类型转换和类型提升","title":"类型转换和类型提升","text":"在某种意义上,Julia 属于「无自动类型提升」类别:数学操作符只是具有特殊语法的函数,函数的参数永远不会自动转换。然而,人们可能会发现数学运算能应用于各种混合的参数类型,但这只是多态的多重分派的极端情况——这是 Julia 的分派和类型系统特别适合处理的情况。数学操作数的「自动」类型提升只是作为一个特殊的应用出现:Julia 带有预定义的数学运算符的 catch-all 分派规则,其在某些操作数类型的组合没有特定实现时调用。这些 catch-all 分派规则首先使用用户可定义的类型提升规则将所有操作数提升到一个通用的类型,然后针对结果值(现在已属于相同类型)调用相关运算符的特定实现。用户定义的类型可简单地加入这个类型提升系统,这需要先定义与其它类型进行相互类型转换的方法,接着提供一些类型提升规则来定义与其它类型混合时应该提升到什么类型。","category":"page"},{"location":"manual/conversion-and-promotion/#类型转换","page":"类型转换和类型提升","title":"类型转换","text":"","category":"section"},{"location":"manual/conversion-and-promotion/","page":"类型转换和类型提升","title":"类型转换和类型提升","text":"获取某种类型 T 的值的标准方法是调用该类型的构造函数 T(x)。但是,有些情况下,在程序员没有明确要求时,仍将值从一种类型转换为另一种类型是很方便的。其中一个例子是将值赋给一个数组:假设 A 是个 Vector{Float64},表达式 A[1] = 2 执行时应该自动将 2 从 Int 转换为 Float,并将结果存储在该数组中。这通过 convert 函数完成。","category":"page"},{"location":"manual/conversion-and-promotion/","page":"类型转换和类型提升","title":"类型转换和类型提升","text":"convert 函数通常接受两个参数:第一个是类型对象,第二个是需要转换为该类型的值。返回的是已转换后的值。理解这个函数最简单的办法就是尝试:","category":"page"},{"location":"manual/conversion-and-promotion/","page":"类型转换和类型提升","title":"类型转换和类型提升","text":"julia> x = 12\n12\n\njulia> typeof(x)\nInt64\n\njulia> xu = convert(UInt8, x)\n0x0c\n\njulia> typeof(xu)\nUInt8\n\njulia> xf = convert(AbstractFloat, x)\n12.0\n\njulia> typeof(xf)\nFloat64\n\njulia> a = Any[1 2 3; 4 5 6]\n2×3 Matrix{Any}:\n 1 2 3\n 4 5 6\n\njulia> convert(Array{Float64}, a)\n2×3 Matrix{Float64}:\n 1.0 2.0 3.0\n 4.0 5.0 6.0","category":"page"},{"location":"manual/conversion-and-promotion/","page":"类型转换和类型提升","title":"类型转换和类型提升","text":"类型转换并不总是可行的,有时 convert 函数并不知道该如何执行所请求的类型转换就会抛出 MethodError 错误。例如下例:","category":"page"},{"location":"manual/conversion-and-promotion/","page":"类型转换和类型提升","title":"类型转换和类型提升","text":"julia> convert(AbstractFloat, \"foo\")\nERROR: MethodError: Cannot `convert` an object of type String to an object of type AbstractFloat\n[...]","category":"page"},{"location":"manual/conversion-and-promotion/","page":"类型转换和类型提升","title":"类型转换和类型提升","text":"一些语言考虑将解析字符串为数字或格式化数字为字符串来进行转换(许多动态语言甚至会自动执行转换),但 Julia 不会:尽管某些字符串可以解析为数字,但大多数字符串都不是有效的数字表示形式,只有非常有限的子集才是。因此,在 Julia 中,必须使用专用的 parse 函数来执行此操作,这使其更加明确。","category":"page"},{"location":"manual/conversion-and-promotion/#什么时候使用-convert-函数?","page":"类型转换和类型提升","title":"什么时候使用 convert 函数?","text":"","category":"section"},{"location":"manual/conversion-and-promotion/","page":"类型转换和类型提升","title":"类型转换和类型提升","text":"构造以下语言结构时需要调用 convert 函数:","category":"page"},{"location":"manual/conversion-and-promotion/","page":"类型转换和类型提升","title":"类型转换和类型提升","text":"对一个数组赋值会转换为数组元素的类型。\n对一个对象的字段赋值会转换为已声明的字段类型。\n使用 new 构造对象会转换为该对象已声明的字段类型。\n对已声明类型的变量赋值(例如 local x::T)会转换为该类型。\n已声明返回类型的函数会转换其返回值为该类型。\n把值传递给 ccall 会将其转换为相应参数的类型。","category":"page"},{"location":"manual/conversion-and-promotion/#类型转换与构造","page":"类型转换和类型提升","title":"类型转换与构造","text":"","category":"section"},{"location":"manual/conversion-and-promotion/","page":"类型转换和类型提升","title":"类型转换和类型提升","text":"注意到 convert(T, x) 的行为似乎与 T(x) 几乎相同,它的确通常是这样。但是,有一个关键的语义差别:因为 convert 能被隐式调用,所以它的方法仅限于被认为是「安全」或「意料之内」的情况。convert 只会在表示事物的相同基本种类的类型之间进行转换(例如,不同的数字表示和不同的字符串编码)。它通常也是无损的;将值转换为其它类型并再次转换回去应该产生完全相同的值。","category":"page"},{"location":"manual/conversion-and-promotion/","page":"类型转换和类型提升","title":"类型转换和类型提升","text":"这是四种一般的构造函数与 convert 不同的情况:","category":"page"},{"location":"manual/conversion-and-promotion/#与其参数类型无关的类型的构造函数","page":"类型转换和类型提升","title":"与其参数类型无关的类型的构造函数","text":"","category":"section"},{"location":"manual/conversion-and-promotion/","page":"类型转换和类型提升","title":"类型转换和类型提升","text":"一些构造函数没有体现「转换」的概念。例如,Timer(2) 创建一个时长 2 秒的定时器,它实际上并不是从整数到定时器的「转换」。","category":"page"},{"location":"manual/conversion-and-promotion/#可变的集合","page":"类型转换和类型提升","title":"可变的集合","text":"","category":"section"},{"location":"manual/conversion-and-promotion/","page":"类型转换和类型提升","title":"类型转换和类型提升","text":"如果 x 类型已经为 T,convert(T, x) 应该返回原本的 x。相反地,如果 T 是一个可变的集合类型,那么 T(x) 应该总是创建一个新的集合(从 x 复制元素)。","category":"page"},{"location":"manual/conversion-and-promotion/#封装器类型","page":"类型转换和类型提升","title":"封装器类型","text":"","category":"section"},{"location":"manual/conversion-and-promotion/","page":"类型转换和类型提升","title":"类型转换和类型提升","text":"对于某些「封装」其它值的类型,构造函数可能会将其参数封装在一个新对象中,即使它已经是所请求的类型。例如,用 Some(x) 表示封装了一个 x 值(在上下文中,其结果可能是一个 Some 或 nothing)。但是,x 本身可能是对象 Some(y),在这种情况下,结果为 Some(Some(y)),封装了两层。然而,convert(Some, x) 只会返回 x,因为它已经是 Some 的实例了。","category":"page"},{"location":"manual/conversion-and-promotion/#不返回自身类型的实例的构造函数","page":"类型转换和类型提升","title":"不返回自身类型的实例的构造函数","text":"","category":"section"},{"location":"manual/conversion-and-promotion/","page":"类型转换和类型提升","title":"类型转换和类型提升","text":"在极少见的情况下,构造函数 T(x) 返回一个类型不为 T 的对象是有意义的。如果封装器类型是它自身的反转(例如 Flip(Flip(x)) === x),或者在重构库时为了支持某个旧的调用语法以实现向后兼容,则可能发生这种情况。但是,convert(T, x) 应该总是返回一个类型为 T 的值。","category":"page"},{"location":"manual/conversion-and-promotion/#定义新的类型转换","page":"类型转换和类型提升","title":"定义新的类型转换","text":"","category":"section"},{"location":"manual/conversion-and-promotion/","page":"类型转换和类型提升","title":"类型转换和类型提升","text":"在定义新类型时,最初创建它的所有方法都应定义为构造函数。如果隐式类型转换很明显是有用的,并且某些构造函数满足上面的「安全」标准,那么可以考虑添加 convert 方法。这些方法通常非常简单,因为它们只需要调用适当的构造函数。此类定义可能会像这样:","category":"page"},{"location":"manual/conversion-and-promotion/","page":"类型转换和类型提升","title":"类型转换和类型提升","text":"convert(::Type{MyType}, x) = MyType(x)","category":"page"},{"location":"manual/conversion-and-promotion/","page":"类型转换和类型提升","title":"类型转换和类型提升","text":"这个方法的第一个参数的类型是Type{MyType},它的唯一实例是MyType。 因此,仅当第一个参数是类型值MyType时才会调用此方法。注意第一个参数使用的语法:在::符号之前省略参数名称,只给出类型。 这是 Julia 中指定类型但不需要通过名称引用其值的函数参数的语法。","category":"page"},{"location":"manual/conversion-and-promotion/","page":"类型转换和类型提升","title":"类型转换和类型提升","text":"某些抽象类型的所有实例默认都被认为是「足够相似的」,在 Julia Base 中也提供了通用的 convert 定义。例如,这个定义声明通过调用单参数构造函数将任何 Number 类型 convert 为其它任何 Number 类型是有效的:","category":"page"},{"location":"manual/conversion-and-promotion/","page":"类型转换和类型提升","title":"类型转换和类型提升","text":"convert(::Type{T}, x::Number) where {T<:Number} = T(x)","category":"page"},{"location":"manual/conversion-and-promotion/","page":"类型转换和类型提升","title":"类型转换和类型提升","text":"这意味着新的 Number 类型只需要定义构造函数,因为此定义将为它们处理 convert。在参数已经是所请求的类型的情况下,用恒同变换来处理 convert。","category":"page"},{"location":"manual/conversion-and-promotion/","page":"类型转换和类型提升","title":"类型转换和类型提升","text":"convert(::Type{T}, x::T) where {T<:Number} = x","category":"page"},{"location":"manual/conversion-and-promotion/","page":"类型转换和类型提升","title":"类型转换和类型提升","text":"AbstractString、AbstractArray 和 AbstractDict 也存在类似的定义。","category":"page"},{"location":"manual/conversion-and-promotion/#类型提升","page":"类型转换和类型提升","title":"类型提升","text":"","category":"section"},{"location":"manual/conversion-and-promotion/","page":"类型转换和类型提升","title":"类型转换和类型提升","text":"类型提升是指将一组混合类型的值转换为单个通用类型。尽管不是绝对必要的,但一般暗示被转换的值的通用类型可以忠实地表示所有原始值。此意义下,术语「类型提升」是合适的,因为值被转换为「更大」的类型——即能用一个通用类型表示所有输入值的类型。但重要的是,不要将它与面向对象(结构)超类或 Julia 的抽象超类型混淆:类型提升与类型层次结构无关,而与备选的表示之间的转换有关。例如,尽管每个 Int32 值可以表示为 Float64 值,但 Int32 不是 Float64 的子类型。","category":"page"},{"location":"manual/conversion-and-promotion/","page":"类型转换和类型提升","title":"类型转换和类型提升","text":"在 Julia 中,类型提升到一个通用的「更大」类型的操作是通过 promote 函数执行的,该函数接受任意数量的参数,并返回由相同数量的值组成的元组,值会被转换为一个通用类型,或在无法类型提升时抛出异常。类型提升的最常见用途是将数字参数转换为通用类型:","category":"page"},{"location":"manual/conversion-and-promotion/","page":"类型转换和类型提升","title":"类型转换和类型提升","text":"julia> promote(1, 2.5)\n(1.0, 2.5)\n\njulia> promote(1, 2.5, 3)\n(1.0, 2.5, 3.0)\n\njulia> promote(2, 3//4)\n(2//1, 3//4)\n\njulia> promote(1, 2.5, 3, 3//4)\n(1.0, 2.5, 3.0, 0.75)\n\njulia> promote(1.5, im)\n(1.5 + 0.0im, 0.0 + 1.0im)\n\njulia> promote(1 + 2im, 3//4)\n(1//1 + 2//1*im, 3//4 + 0//1*im)","category":"page"},{"location":"manual/conversion-and-promotion/","page":"类型转换和类型提升","title":"类型转换和类型提升","text":"浮点值被提升为最大的浮点参数类型。整数值会被提升为本机机器字大小或最大的整数参数类型中较大的一个。整数和浮点值的混合会被提升为一个足以包含所有值的浮点类型。与有理数混合的整数会被提升有理数。与浮点数混合的有理数会被提升为浮点数。与实数值混合的复数值会被提升为合适类型的复数值。","category":"page"},{"location":"manual/conversion-and-promotion/","page":"类型转换和类型提升","title":"类型转换和类型提升","text":"这就是使用类型提升的全部内容。剩下的只是聪明的应用,最典型的「聪明」应用是数值操作(如 +、-、* 和 /)的 catch-all 方法的定义。以下是在 promotion.jl 中给出的几个 catch-all 方法的定义:","category":"page"},{"location":"manual/conversion-and-promotion/","page":"类型转换和类型提升","title":"类型转换和类型提升","text":"+(x::Number, y::Number) = +(promote(x,y)...)\n-(x::Number, y::Number) = -(promote(x,y)...)\n*(x::Number, y::Number) = *(promote(x,y)...)\n/(x::Number, y::Number) = /(promote(x,y)...)","category":"page"},{"location":"manual/conversion-and-promotion/","page":"类型转换和类型提升","title":"类型转换和类型提升","text":"这些方法的定义表明,如果没有更特殊的规则来加、减、乘及除一对数值,则将这些值提升为通用类型并再试一次。这就是它的全部内容:在其它任何地方都不需要为数值操作担心到通用数值类型的类型提升——它会自动进行。许多算术和数学函数的 catch-all 类型提升方法的定义在 promotion.jl 中,但除此之外,Julia Base 中几乎不再需要调用 promote。promote 最常用于外部构造方法中,为了更方便,可允许使用混合类型的构造函数调用委托给一个内部构造函数,并将字段提升为适当的通用类型。例如,回想一下,rational.jl 提供了以下外部构造方法:","category":"page"},{"location":"manual/conversion-and-promotion/","page":"类型转换和类型提升","title":"类型转换和类型提升","text":"Rational(n::Integer, d::Integer) = Rational(promote(n,d)...)","category":"page"},{"location":"manual/conversion-and-promotion/","page":"类型转换和类型提升","title":"类型转换和类型提升","text":"这允许像下面这样的调用正常工作:","category":"page"},{"location":"manual/conversion-and-promotion/","page":"类型转换和类型提升","title":"类型转换和类型提升","text":"julia> x = Rational(Int8(15),Int32(-5))\n-3//1\n\njulia> typeof(x)\nRational{Int32}","category":"page"},{"location":"manual/conversion-and-promotion/","page":"类型转换和类型提升","title":"类型转换和类型提升","text":"对于大多数用户定义的类型,最好要求程序员明确地向构造函数提供期待的类型,但有时,尤其是对于数值问题,自动进行类型提升会很方便。","category":"page"},{"location":"manual/conversion-and-promotion/#定义类型提升规则","page":"类型转换和类型提升","title":"定义类型提升规则","text":"","category":"section"},{"location":"manual/conversion-and-promotion/","page":"类型转换和类型提升","title":"类型转换和类型提升","text":"虽然原则上可以直接为 promote 函数定义方法,但这需要为参数类型的所有可能排列下许多冗余的定义。相反地,promote 的行为是根据名为 promote_rule 的辅助函数定义的,该辅助函数可以为其提供方法。promote_rule 函数接受一对类型对象并返回另一个类型对象,这样参数类型的实例会被提升为被返回的类型。 因此,通过定义规则:","category":"page"},{"location":"manual/conversion-and-promotion/","page":"类型转换和类型提升","title":"类型转换和类型提升","text":"promote_rule(::Type{Float64}, ::Type{Float32}) = Float64","category":"page"},{"location":"manual/conversion-and-promotion/","page":"类型转换和类型提升","title":"类型转换和类型提升","text":"声明当同时类型提升 64 位和 32 位浮点值时,它们应该被类型提升为 64 位浮点数。但是,提升类型不需要是参数类型之一;例如,在 Julia Base 中有以下类型提升规则:","category":"page"},{"location":"manual/conversion-and-promotion/","page":"类型转换和类型提升","title":"类型转换和类型提升","text":"promote_rule(::Type{BigInt}, ::Type{Float64}) = BigFloat\npromote_rule(::Type{BigInt}, ::Type{Int8}) = BigInt","category":"page"},{"location":"manual/conversion-and-promotion/","page":"类型转换和类型提升","title":"类型转换和类型提升","text":"在后一种情况下,输出类型是 BigInt,因为 BigInt 是唯一一个足以容纳任意精度整数运算结果的类型。还要注意,不需要同时定义 promote_rule(::Type{A}, ::Type{B}) 和 promote_rule(::Type{B}, ::Type{A})——对称性隐含在类型提升过程中使用 promote_rule 的方式。","category":"page"},{"location":"manual/conversion-and-promotion/","page":"类型转换和类型提升","title":"类型转换和类型提升","text":"以 promote_rule 函数为基础定义了 promote_type 函数,在给定任意数量的类型对象时,它返回这些值作为 promote 的参数应被提升的通用类型。因此,如果想知道在没有实际值情况下,具有确定类型的一些值会被类型提升为什么类型,可以使用 promote_type:","category":"page"},{"location":"manual/conversion-and-promotion/","page":"类型转换和类型提升","title":"类型转换和类型提升","text":"julia> promote_type(Int8, Int64)\nInt64","category":"page"},{"location":"manual/conversion-and-promotion/","page":"类型转换和类型提升","title":"类型转换和类型提升","text":"在内部,promote_type 在 promote 中用于确定参数值应被转换为什么类型以便进行类型提升。但是,它本身可能是有用的。好奇的读者可以阅读 promotion.jl,该文件用大概 35 行定义了完整的类型提升规则。","category":"page"},{"location":"manual/conversion-and-promotion/#案例研究:有理数的类型提升","page":"类型转换和类型提升","title":"案例研究:有理数的类型提升","text":"","category":"section"},{"location":"manual/conversion-and-promotion/","page":"类型转换和类型提升","title":"类型转换和类型提升","text":"最后,我们来完成关于 Julia 的有理数类型的案例研究,该案例通过以下类型提升规则相对复杂地使用了类型提升机制:","category":"page"},{"location":"manual/conversion-and-promotion/","page":"类型转换和类型提升","title":"类型转换和类型提升","text":"promote_rule(::Type{Rational{T}}, ::Type{S}) where {T<:Integer,S<:Integer} = Rational{promote_type(T,S)}\npromote_rule(::Type{Rational{T}}, ::Type{Rational{S}}) where {T<:Integer,S<:Integer} = Rational{promote_type(T,S)}\npromote_rule(::Type{Rational{T}}, ::Type{S}) where {T<:Integer,S<:AbstractFloat} = promote_type(T,S)","category":"page"},{"location":"manual/conversion-and-promotion/","page":"类型转换和类型提升","title":"类型转换和类型提升","text":"第一条规则说,使用其它整数类型类型提升有理数类型会得到个有理数类型,其分子/分母类型是使用其它整数类型提升该有理数分子/分母类型的结果。第二条规则将相同的逻辑应用于两种不同的有理数类型,它们进行类型提升会得到有理数类型,其分子/分母类型是它们各自的分子/分母类型进行提升的结果。第三个也是最后一个规则规定,使用浮点数类型提升有理数类型与使用该浮点数类型提升其分子/分母类型会产生相同的类型。","category":"page"},{"location":"manual/conversion-and-promotion/","page":"类型转换和类型提升","title":"类型转换和类型提升","text":"这一小部分的类型提升规则,连同该类型的构造函数和数字的默认 convert 方法,便足以使有理数与 Julia 的其它数值类型——整数、浮点数和复数——完全自然地互操作。通过以相同的方式提供类型转换方法和类型提升规则,任何用户定义的数值类型都可像 Julia 的预定义数值类型一样自然地进行互操作。","category":"page"},{"location":"devdocs/ast/#Julia-的-AST","page":"Julia 的 AST","title":"Julia 的 AST","text":"","category":"section"},{"location":"devdocs/ast/","page":"Julia 的 AST","title":"Julia 的 AST","text":"Julia 有两种代码的表现形式。 第一种是解析器返回的表面语法 AST (例如 Meta.parse 函数),由宏来操控。是代码编写时的结构化表示,由 julia-parser.scm 用字符流构造而成。 另一种则是底层形式,或者 IR(中间表示),这种形式在进行类型推导和代码生成的时候被使用。在这种底层形式中结点的类型相对更少,所有的宏都会被展开,所有的控制流会被转化成显式的分支和语句的序列。底层的形式由 julia-syntax.scm 构建。","category":"page"},{"location":"devdocs/ast/","page":"Julia 的 AST","title":"Julia 的 AST","text":"首先,我们将关注AST,因为需要它来编写宏。","category":"page"},{"location":"devdocs/ast/#表面语法AST","page":"Julia 的 AST","title":"表面语法AST","text":"","category":"section"},{"location":"devdocs/ast/","page":"Julia 的 AST","title":"Julia 的 AST","text":"前端AST几乎由 Expr 和原子(例如 符号、数字)。 对于视觉上不同的语法形式,通常有不同的表达式头。 示例将在s-expression 语法中给出。 每个圆括号括着的列表都对应着一个 Expr,其中第一个元素是它的头部。 例如(call f x)对应于Julia中的 Expr(:call,:f,:x) 。","category":"page"},{"location":"devdocs/ast/#调用","page":"Julia 的 AST","title":"调用","text":"","category":"section"},{"location":"devdocs/ast/","page":"Julia 的 AST","title":"Julia 的 AST","text":"输入 AST\nf(x) (call f x)\nf(x, y=1, z=2) (call f x (kw y 1) (kw z 2))\nf(x; y=1) (call f (parameters (kw y 1)) x)\nf(x...) (call f (... x))","category":"page"},{"location":"devdocs/ast/","page":"Julia 的 AST","title":"Julia 的 AST","text":"do syntax:","category":"page"},{"location":"devdocs/ast/","page":"Julia 的 AST","title":"Julia 的 AST","text":"f(x) do a,b\n body\nend","category":"page"},{"location":"devdocs/ast/","page":"Julia 的 AST","title":"Julia 的 AST","text":"parses as (do (call f x) (-> (tuple a b) (block body))).","category":"page"},{"location":"devdocs/ast/#运算符","page":"Julia 的 AST","title":"运算符","text":"","category":"section"},{"location":"devdocs/ast/","page":"Julia 的 AST","title":"Julia 的 AST","text":"Most uses of operators are just function calls, so they are parsed with the head call. However some operators are special forms (not necessarily function calls), and in those cases the operator itself is the expression head. In julia-parser.scm these are referred to as \"syntactic operators\". Some operators (+ and *) use N-ary parsing; chained calls are parsed as a single N-argument call. Finally, chains of comparisons have their own special expression structure.","category":"page"},{"location":"devdocs/ast/","page":"Julia 的 AST","title":"Julia 的 AST","text":"Input AST\nx+y (call + x y)\na+b+c+d (call + a b c d)\n2x (call * 2 x)\na&&b (&& a b)\nx += 1 (+= x 1)\na ? 1 : 2 (if a 1 2)\na:b (: a b)\na:b:c (: a b c)\na,b (tuple a b)\na==b (call == a b)\n1 inlinehint,always-inline,noinline\n3 = strict-ieee (strictfp)\n4-6 = \n7 = has out-of-band info\nlinetable\nAn array of source location objects\ncodelocs\nAn array of integer indices into the linetable, giving the location associated with each statement.","category":"page"},{"location":"devdocs/ast/","page":"Julia 的 AST","title":"Julia 的 AST","text":"Optional Fields:","category":"page"},{"location":"devdocs/ast/","page":"Julia 的 AST","title":"Julia 的 AST","text":"slottypes\nAn array of types for the slots.\nrettype\nThe inferred return type of the lowered form (IR). Default value is Any.\nmethod_for_inference_limit_heuristics\nThe method_for_inference_heuristics will expand the given method's generator if necessary during inference.\nparent\nThe MethodInstance that \"owns\" this object (if applicable).\nmin_world/max_world\nThe range of world ages for which this code was valid at the time when it had been inferred.","category":"page"},{"location":"devdocs/ast/","page":"Julia 的 AST","title":"Julia 的 AST","text":"Boolean properties:","category":"page"},{"location":"devdocs/ast/","page":"Julia 的 AST","title":"Julia 的 AST","text":"inferred\nWhether this has been produced by type inference.\ninlineable\nWhether this should be eligible for inlining.\npropagate_inbounds\nWhether this should propagate @inbounds when inlined for the purpose of eliding @boundscheck blocks.\npure\nWhether this is known to be a pure function of its arguments, without respect to the state of the method caches or other mutable global state.","category":"page"},{"location":"stdlib/Printf/#man-printf","page":"Printf","title":"Printf","text":"","category":"section"},{"location":"stdlib/Printf/","page":"Printf","title":"Printf","text":"Printf.@printf\nPrintf.@sprintf","category":"page"},{"location":"stdlib/Printf/#Printf.@printf","page":"Printf","title":"Printf.@printf","text":"@printf([io::IO], \"%Fmt\", args...)\n\nPrint args using C printf style format specification string. Optionally, an IO may be passed as the first argument to redirect output.\n\nExamples\n\njulia> @printf \"Hello %s\" \"world\"\nHello world\n\njulia> @printf \"Scientific notation %e\" 1.234\nScientific notation 1.234000e+00\n\njulia> @printf \"Scientific notation three digits %.3e\" 1.23456\nScientific notation three digits 1.235e+00\n\njulia> @printf \"Decimal two digits %.2f\" 1.23456\nDecimal two digits 1.23\n\njulia> @printf \"Padded to length 5 %5i\" 123\nPadded to length 5 123\n\njulia> @printf \"Padded with zeros to length 6 %06i\" 123\nPadded with zeros to length 6 000123\n\njulia> @printf \"Use shorter of decimal or scientific %g %g\" 1.23 12300000.0\nUse shorter of decimal or scientific 1.23 1.23e+07\n\nFor a systematic specification of the format, see here. See also @sprintf.\n\nCaveats\n\nInf and NaN are printed consistently as Inf and NaN for flags %a, %A, %e, %E, %f, %F, %g, and %G. Furthermore, if a floating point number is equally close to the numeric values of two possible output strings, the output string further away from zero is chosen.\n\nExamples\n\njulia> @printf(\"%f %F %f %F\", Inf, Inf, NaN, NaN)\nInf Inf NaN NaN\n\njulia> @printf \"%.0f %.1f %f\" 0.5 0.025 -0.0078125\n0 0.0 -0.007812\n\ncompat: Julia 1.8\nStarting in Julia 1.8, %s (string) and %c (character) widths are computed using textwidth, which e.g. ignores zero-width characters (such as combining characters for diacritical marks) and treats certain \"wide\" characters (e.g. emoji) as width 2.\n\n\n\n\n\n","category":"macro"},{"location":"stdlib/Printf/#Printf.@sprintf","page":"Printf","title":"Printf.@sprintf","text":"@sprintf(\"%Fmt\", args...)\n\nReturn @printf formatted output as string.\n\nExamples\n\njulia> @sprintf \"this is a %s %15.1f\" \"test\" 34.567\n\"this is a test 34.6\"\n\n\n\n\n\n","category":"macro"},{"location":"stdlib/Test/#单元测试","page":"单元测试","title":"单元测试","text":"","category":"section"},{"location":"stdlib/Test/","page":"单元测试","title":"单元测试","text":"DocTestSetup = :(using Test)","category":"page"},{"location":"stdlib/Test/#测试-Julia-Base-库","page":"单元测试","title":"测试 Julia Base 库","text":"","category":"section"},{"location":"stdlib/Test/","page":"单元测试","title":"单元测试","text":"Julia 处于快速开发中,有着可以扩展的测试套件,用来跨平台测试功能。 如果你是通过源代码构建的 Julia ,你可以通过 make test 来运行这个测试套件。 如果是通过二进制包安装的,你可以通过 Base.runtests() 来运行这个测试套件。","category":"page"},{"location":"stdlib/Test/","page":"单元测试","title":"单元测试","text":"Base.runtests","category":"page"},{"location":"stdlib/Test/#Base.runtests","page":"单元测试","title":"Base.runtests","text":"Base.runtests(tests=[\"all\"]; ncores=ceil(Int, Sys.CPU_THREADS / 2),\n exit_on_error=false, revise=false, [seed])\n\nRun the Julia unit tests listed in tests, which can be either a string or an array of strings, using ncores processors. If exit_on_error is false, when one test fails, all remaining tests in other files will still be run; they are otherwise discarded, when exit_on_error == true. If revise is true, the Revise package is used to load any modifications to Base or to the standard libraries before running the tests. If a seed is provided via the keyword argument, it is used to seed the global RNG in the context where the tests are run; otherwise the seed is chosen randomly.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/Test/#基本的单元测试","page":"单元测试","title":"基本的单元测试","text":"","category":"section"},{"location":"stdlib/Test/","page":"单元测试","title":"单元测试","text":"The Test module provides simple unit testing functionality. Unit testing is a way to see if your code is correct by checking that the results are what you expect. It can be helpful to ensure your code still works after you make changes, and can be used when developing as a way of specifying the behaviors your code should have when complete.","category":"page"},{"location":"stdlib/Test/","page":"单元测试","title":"单元测试","text":"简单的单元测试可以通过 @test 和 @test_throws 宏来完成:","category":"page"},{"location":"stdlib/Test/","page":"单元测试","title":"单元测试","text":"Test.@test\nTest.@test_throws","category":"page"},{"location":"stdlib/Test/#Test.@test","page":"单元测试","title":"Test.@test","text":"@test ex\n@test f(args...) key=val ...\n@test ex broken=true\n@test ex skip=true\n\nTest that the expression ex evaluates to true. If executed inside a @testset, return a Pass Result if it does, a Fail Result if it is false, and an Error Result if it could not be evaluated. If executed outside a @testset, throw an exception instead of returning Fail or Error.\n\nExamples\n\njulia> @test true\nTest Passed\n\njulia> @test [1, 2] + [2, 1] == [3, 3]\nTest Passed\n\nThe @test f(args...) key=val... form is equivalent to writing @test f(args..., key=val...) which can be useful when the expression is a call using infix syntax such as approximate comparisons:\n\njulia> @test π ≈ 3.14 atol=0.01\nTest Passed\n\nThis is equivalent to the uglier test @test ≈(π, 3.14, atol=0.01). It is an error to supply more than one expression unless the first is a call expression and the rest are assignments (k=v).\n\nYou can use any key for the key=val arguments, except for broken and skip, which have special meanings in the context of @test:\n\nbroken=cond indicates a test that should pass but currently consistently fails when cond==true. Tests that the expression ex evaluates to false or causes an exception. Returns a Broken Result if it does, or an Error Result if the expression evaluates to true. Regular @test ex is evaluated when cond==false.\nskip=cond marks a test that should not be executed but should be included in test summary reporting as Broken, when cond==true. This can be useful for tests that intermittently fail, or tests of not-yet-implemented functionality. Regular @test ex is evaluated when cond==false.\n\nExamples\n\njulia> @test 2 + 2 ≈ 6 atol=1 broken=true\nTest Broken\n Expression: ≈(2 + 2, 6, atol = 1)\n\njulia> @test 2 + 2 ≈ 5 atol=1 broken=false\nTest Passed\n\njulia> @test 2 + 2 == 5 skip=true\nTest Broken\n Skipped: 2 + 2 == 5\n\njulia> @test 2 + 2 == 4 skip=false\nTest Passed\n\ncompat: Julia 1.7\nThe broken and skip keyword arguments require at least Julia 1.7.\n\n\n\n\n\n","category":"macro"},{"location":"stdlib/Test/#Test.@test_throws","page":"单元测试","title":"Test.@test_throws","text":"@test_throws exception expr\n\nTests that the expression expr throws exception. The exception may specify either a type, a string, regular expression, or list of strings occurring in the displayed error message, a matching function, or a value (which will be tested for equality by comparing fields). Note that @test_throws does not support a trailing keyword form.\n\ncompat: Julia 1.8\nThe ability to specify anything other than a type or a value as exception requires Julia v1.8 or later.\n\nExamples\n\njulia> @test_throws BoundsError [1, 2, 3][4]\nTest Passed\n Thrown: BoundsError\n\njulia> @test_throws DimensionMismatch [1, 2, 3] + [1, 2]\nTest Passed\n Thrown: DimensionMismatch\n\njulia> @test_throws \"Try sqrt(Complex\" sqrt(-1)\nTest Passed\n Message: \"DomainError with -1.0:\\nsqrt will only return a complex result if called with a complex argument. Try sqrt(Complex(x)).\"\n\nIn the final example, instead of matching a single string it could alternatively have been performed with:\n\n[\"Try\", \"Complex\"] (a list of strings)\nr\"Try sqrt\\([Cc]omplex\" (a regular expression)\nstr -> occursin(\"complex\", str) (a matching function)\n\n\n\n\n\n","category":"macro"},{"location":"stdlib/Test/","page":"单元测试","title":"单元测试","text":"例如,假设我们想要测试新的函数 foo(x) 是否按照期望的方式工作:","category":"page"},{"location":"stdlib/Test/","page":"单元测试","title":"单元测试","text":"julia> using Test\n\njulia> foo(x) = length(x)^2\nfoo (generic function with 1 method)","category":"page"},{"location":"stdlib/Test/","page":"单元测试","title":"单元测试","text":"If the condition is true, a Pass is returned:","category":"page"},{"location":"stdlib/Test/","page":"单元测试","title":"单元测试","text":"julia> @test foo(\"bar\") == 9\nTest Passed\n Expression: foo(\"bar\") == 9\n Evaluated: 9 == 9\n\njulia> @test foo(\"fizz\") >= 10\nTest Passed\n Expression: foo(\"fizz\") >= 10\n Evaluated: 16 >= 10","category":"page"},{"location":"stdlib/Test/","page":"单元测试","title":"单元测试","text":"如果条件为假,则返回 Fail 并抛出异常。","category":"page"},{"location":"stdlib/Test/","page":"单元测试","title":"单元测试","text":"julia> @test foo(\"f\") == 20\nTest Failed at none:1\n Expression: foo(\"f\") == 20\n Evaluated: 1 == 20\nERROR: There was an error during testing","category":"page"},{"location":"stdlib/Test/","page":"单元测试","title":"单元测试","text":"If the condition could not be evaluated because an exception was thrown, which occurs in this case because length is not defined for symbols, an Error object is returned and an exception is thrown:","category":"page"},{"location":"stdlib/Test/","page":"单元测试","title":"单元测试","text":"julia> @test foo(:cat) == 1\nError During Test\n Test threw an exception of type MethodError\n Expression: foo(:cat) == 1\n MethodError: no method matching length(::Symbol)\n Closest candidates are:\n length(::SimpleVector) at essentials.jl:256\n length(::Base.MethodList) at reflection.jl:521\n length(::MethodTable) at reflection.jl:597\n ...\n Stacktrace:\n [...]\nERROR: There was an error during testing","category":"page"},{"location":"stdlib/Test/","page":"单元测试","title":"单元测试","text":"If we expect that evaluating an expression should throw an exception, then we can use @test_throws to check that this occurs:","category":"page"},{"location":"stdlib/Test/","page":"单元测试","title":"单元测试","text":"julia> @test_throws MethodError foo(:cat)\nTest Passed\n Expression: foo(:cat)\n Thrown: MethodError","category":"page"},{"location":"stdlib/Test/#Working-with-Test-Sets","page":"单元测试","title":"Working with Test Sets","text":"","category":"section"},{"location":"stdlib/Test/","page":"单元测试","title":"单元测试","text":"Typically a large number of tests are used to make sure functions work correctly over a range of inputs. In the event a test fails, the default behavior is to throw an exception immediately. However, it is normally preferable to run the rest of the tests first to get a better picture of how many errors there are in the code being tested.","category":"page"},{"location":"stdlib/Test/","page":"单元测试","title":"单元测试","text":"note: Note\nThe @testset will create a local scope of its own when running the tests in it.","category":"page"},{"location":"stdlib/Test/","page":"单元测试","title":"单元测试","text":"The @testset macro can be used to group tests into sets. All the tests in a test set will be run, and at the end of the test set a summary will be printed. If any of the tests failed, or could not be evaluated due to an error, the test set will then throw a TestSetException.","category":"page"},{"location":"stdlib/Test/","page":"单元测试","title":"单元测试","text":"Test.@testset\nTest.TestSetException","category":"page"},{"location":"stdlib/Test/#Test.@testset","page":"单元测试","title":"Test.@testset","text":"@testset [CustomTestSet] [option=val ...] [\"description\"] begin ... end\n@testset [CustomTestSet] [option=val ...] [\"description $v\"] for v in (...) ... end\n@testset [CustomTestSet] [option=val ...] [\"description $v, $w\"] for v in (...), w in (...) ... end\n@testset [CustomTestSet] [option=val ...] [\"description $v, $w\"] foo()\n\nStarts a new test set, or multiple test sets if a for loop is provided.\n\nIf no custom testset type is given it defaults to creating a DefaultTestSet. DefaultTestSet records all the results and, if there are any Fails or Errors, throws an exception at the end of the top-level (non-nested) test set, along with a summary of the test results.\n\nAny custom testset type (subtype of AbstractTestSet) can be given and it will also be used for any nested @testset invocations. The given options are only applied to the test set where they are given. The default test set type accepts two boolean options:\n\nverbose: if true, the result summary of the nested testsets is shown even\n\nwhen they all pass (the default is false).\n\nshowtiming: if true, the duration of each displayed testset is shown\n\n(the default is true).\n\ncompat: Julia 1.8\n@testset foo() requires at least Julia 1.8.\n\nThe description string accepts interpolation from the loop indices. If no description is provided, one is constructed based on the variables. If a function call is provided, its name will be used. Explicit description strings override this behavior.\n\nBy default the @testset macro will return the testset object itself, though this behavior can be customized in other testset types. If a for loop is used then the macro collects and returns a list of the return values of the finish method, which by default will return a list of the testset objects used in each iteration.\n\nBefore the execution of the body of a @testset, there is an implicit call to Random.seed!(seed) where seed is the current seed of the global RNG. Moreover, after the execution of the body, the state of the global RNG is restored to what it was before the @testset. This is meant to ease reproducibility in case of failure, and to allow seamless re-arrangements of @testsets regardless of their side-effect on the global RNG state.\n\nExamples\n\njulia> @testset \"trigonometric identities\" begin\n θ = 2/3*π\n @test sin(-θ) ≈ -sin(θ)\n @test cos(-θ) ≈ cos(θ)\n @test sin(2θ) ≈ 2*sin(θ)*cos(θ)\n @test cos(2θ) ≈ cos(θ)^2 - sin(θ)^2\n end;\nTest Summary: | Pass Total Time\ntrigonometric identities | 4 4 0.2s\n\n\n\n\n\n","category":"macro"},{"location":"stdlib/Test/#Test.TestSetException","page":"单元测试","title":"Test.TestSetException","text":"TestSetException\n\nThrown when a test set finishes and not all tests passed.\n\n\n\n\n\n","category":"type"},{"location":"stdlib/Test/","page":"单元测试","title":"单元测试","text":"We can put our tests for the foo(x) function in a test set:","category":"page"},{"location":"stdlib/Test/","page":"单元测试","title":"单元测试","text":"julia> @testset \"Foo Tests\" begin\n @test foo(\"a\") == 1\n @test foo(\"ab\") == 4\n @test foo(\"abc\") == 9\n end;\nTest Summary: | Pass Total\nFoo Tests | 3 3","category":"page"},{"location":"stdlib/Test/","page":"单元测试","title":"单元测试","text":"测试集可以嵌套:","category":"page"},{"location":"stdlib/Test/","page":"单元测试","title":"单元测试","text":"julia> @testset \"Foo Tests\" begin\n @testset \"Animals\" begin\n @test foo(\"cat\") == 9\n @test foo(\"dog\") == foo(\"cat\")\n end\n @testset \"Arrays $i\" for i in 1:3\n @test foo(zeros(i)) == i^2\n @test foo(fill(1.0, i)) == i^2\n end\n end;\nTest Summary: | Pass Total\nFoo Tests | 8 8","category":"page"},{"location":"stdlib/Test/","page":"单元测试","title":"单元测试","text":"In the event that a nested test set has no failures, as happened here, it will be hidden in the summary, unless the verbose=true option is passed:","category":"page"},{"location":"stdlib/Test/","page":"单元测试","title":"单元测试","text":"julia> @testset verbose = true \"Foo Tests\" begin\n @testset \"Animals\" begin\n @test foo(\"cat\") == 9\n @test foo(\"dog\") == foo(\"cat\")\n end\n @testset \"Arrays $i\" for i in 1:3\n @test foo(zeros(i)) == i^2\n @test foo(fill(1.0, i)) == i^2\n end\n end;\nTest Summary: | Pass Total\nFoo Tests | 8 8\n Animals | 2 2\n Arrays 1 | 2 2\n Arrays 2 | 2 2\n Arrays 3 | 2 2","category":"page"},{"location":"stdlib/Test/","page":"单元测试","title":"单元测试","text":"If we do have a test failure, only the details for the failed test sets will be shown:","category":"page"},{"location":"stdlib/Test/","page":"单元测试","title":"单元测试","text":"julia> @testset \"Foo Tests\" begin\n @testset \"Animals\" begin\n @testset \"Felines\" begin\n @test foo(\"cat\") == 9\n end\n @testset \"Canines\" begin\n @test foo(\"dog\") == 9\n end\n end\n @testset \"Arrays\" begin\n @test foo(zeros(2)) == 4\n @test foo(fill(1.0, 4)) == 15\n end\n end\n\nArrays: Test Failed\n Expression: foo(fill(1.0, 4)) == 15\n Evaluated: 16 == 15\n[...]\nTest Summary: | Pass Fail Total\nFoo Tests | 3 1 4\n Animals | 2 2\n Arrays | 1 1 2\nERROR: Some tests did not pass: 3 passed, 1 failed, 0 errored, 0 broken.","category":"page"},{"location":"stdlib/Test/#Other-Test-Macros","page":"单元测试","title":"Other Test Macros","text":"","category":"section"},{"location":"stdlib/Test/","page":"单元测试","title":"单元测试","text":"As calculations on floating-point values can be imprecise, you can perform approximate equality checks using either @test a ≈ b (where ≈, typed via tab completion of \\approx, is the isapprox function) or use isapprox directly.","category":"page"},{"location":"stdlib/Test/","page":"单元测试","title":"单元测试","text":"julia> @test 1 ≈ 0.999999999\nTest Passed\n Expression: 1 ≈ 0.999999999\n Evaluated: 1 ≈ 0.999999999\n\njulia> @test 1 ≈ 0.999999\nTest Failed at none:1\n Expression: 1 ≈ 0.999999\n Evaluated: 1 ≈ 0.999999\nERROR: There was an error during testing","category":"page"},{"location":"stdlib/Test/","page":"单元测试","title":"单元测试","text":"You can specify relative and absolute tolerances by setting the rtol and atol keyword arguments of isapprox, respectively, after the ≈ comparison:","category":"page"},{"location":"stdlib/Test/","page":"单元测试","title":"单元测试","text":"julia> @test 1 ≈ 0.999999 rtol=1e-5\nTest Passed\n Expression: ≈(1, 0.999999, rtol = 1.0e-5)\n Evaluated: ≈(1, 0.999999; rtol = 1.0e-5)","category":"page"},{"location":"stdlib/Test/","page":"单元测试","title":"单元测试","text":"Note that this is not a specific feature of the ≈ but rather a general feature of the @test macro: @test a b key=val is transformed by the macro into @test op(a, b, key=val). It is, however, particularly useful for ≈ tests.","category":"page"},{"location":"stdlib/Test/","page":"单元测试","title":"单元测试","text":"Test.@inferred\nTest.@test_logs\nTest.@test_deprecated\nTest.@test_warn\nTest.@test_nowarn","category":"page"},{"location":"stdlib/Test/#Test.@inferred","page":"单元测试","title":"Test.@inferred","text":"@inferred [AllowedType] f(x)\n\nTests that the call expression f(x) returns a value of the same type inferred by the compiler. It is useful to check for type stability.\n\nf(x) can be any call expression. Returns the result of f(x) if the types match, and an Error Result if it finds different types.\n\nOptionally, AllowedType relaxes the test, by making it pass when either the type of f(x) matches the inferred type modulo AllowedType, or when the return type is a subtype of AllowedType. This is useful when testing type stability of functions returning a small union such as Union{Nothing, T} or Union{Missing, T}.\n\njulia> f(a) = a > 1 ? 1 : 1.0\nf (generic function with 1 method)\n\njulia> typeof(f(2))\nInt64\n\njulia> @code_warntype f(2)\nMethodInstance for f(::Int64)\n from f(a) in Main at none:1\nArguments\n #self#::Core.Const(f)\n a::Int64\nBody::UNION{FLOAT64, INT64}\n1 ─ %1 = (a > 1)::Bool\n└── goto #3 if not %1\n2 ─ return 1\n3 ─ return 1.0\n\njulia> @inferred f(2)\nERROR: return type Int64 does not match inferred return type Union{Float64, Int64}\n[...]\n\njulia> @inferred max(1, 2)\n2\n\njulia> g(a) = a < 10 ? missing : 1.0\ng (generic function with 1 method)\n\njulia> @inferred g(20)\nERROR: return type Float64 does not match inferred return type Union{Missing, Float64}\n[...]\n\njulia> @inferred Missing g(20)\n1.0\n\njulia> h(a) = a < 10 ? missing : f(a)\nh (generic function with 1 method)\n\njulia> @inferred Missing h(20)\nERROR: return type Int64 does not match inferred return type Union{Missing, Float64, Int64}\n[...]\n\n\n\n\n\n","category":"macro"},{"location":"stdlib/Test/#Test.@test_logs","page":"单元测试","title":"Test.@test_logs","text":"@test_logs [log_patterns...] [keywords] expression\n\nCollect a list of log records generated by expression using collect_test_logs, check that they match the sequence log_patterns, and return the value of expression. The keywords provide some simple filtering of log records: the min_level keyword controls the minimum log level which will be collected for the test, the match_mode keyword defines how matching will be performed (the default :all checks that all logs and patterns match pairwise; use :any to check that the pattern matches at least once somewhere in the sequence.)\n\nThe most useful log pattern is a simple tuple of the form (level,message). A different number of tuple elements may be used to match other log metadata, corresponding to the arguments to passed to AbstractLogger via the handle_message function: (level,message,module,group,id,file,line). Elements which are present will be matched pairwise with the log record fields using == by default, with the special cases that Symbols may be used for the standard log levels, and Regexs in the pattern will match string or Symbol fields using occursin.\n\nExamples\n\nConsider a function which logs a warning, and several debug messages:\n\nfunction foo(n)\n @info \"Doing foo with n=$n\"\n for i=1:n\n @debug \"Iteration $i\"\n end\n 42\nend\n\nWe can test the info message using\n\n@test_logs (:info,\"Doing foo with n=2\") foo(2)\n\nIf we also wanted to test the debug messages, these need to be enabled with the min_level keyword:\n\nusing Logging\n@test_logs (:info,\"Doing foo with n=2\") (:debug,\"Iteration 1\") (:debug,\"Iteration 2\") min_level=Logging.Debug foo(2)\n\nIf you want to test that some particular messages are generated while ignoring the rest, you can set the keyword match_mode=:any:\n\nusing Logging\n@test_logs (:info,) (:debug,\"Iteration 42\") min_level=Logging.Debug match_mode=:any foo(100)\n\nThe macro may be chained with @test to also test the returned value:\n\n@test (@test_logs (:info,\"Doing foo with n=2\") foo(2)) == 42\n\nIf you want to test for the absence of warnings, you can omit specifying log patterns and set the min_level accordingly:\n\n# test that the expression logs no messages when the logger level is warn:\n@test_logs min_level=Logging.Warn @info(\"Some information\") # passes\n@test_logs min_level=Logging.Warn @warn(\"Some information\") # fails\n\nIf you want to test the absence of warnings (or error messages) in stderr which are not generated by @warn, see @test_nowarn.\n\n\n\n\n\n","category":"macro"},{"location":"stdlib/Test/#Test.@test_deprecated","page":"单元测试","title":"Test.@test_deprecated","text":"@test_deprecated [pattern] expression\n\nWhen --depwarn=yes, test that expression emits a deprecation warning and return the value of expression. The log message string will be matched against pattern which defaults to r\"deprecated\"i.\n\nWhen --depwarn=no, simply return the result of executing expression. When --depwarn=error, check that an ErrorException is thrown.\n\nExamples\n\n# Deprecated in julia 0.7\n@test_deprecated num2hex(1)\n\n# The returned value can be tested by chaining with @test:\n@test (@test_deprecated num2hex(1)) == \"0000000000000001\"\n\n\n\n\n\n","category":"macro"},{"location":"stdlib/Test/#Test.@test_warn","page":"单元测试","title":"Test.@test_warn","text":"@test_warn msg expr\n\nTest whether evaluating expr results in stderr output that contains the msg string or matches the msg regular expression. If msg is a boolean function, tests whether msg(output) returns true. If msg is a tuple or array, checks that the error output contains/matches each item in msg. Returns the result of evaluating expr.\n\nSee also @test_nowarn to check for the absence of error output.\n\nNote: Warnings generated by @warn cannot be tested with this macro. Use @test_logs instead.\n\n\n\n\n\n","category":"macro"},{"location":"stdlib/Test/#Test.@test_nowarn","page":"单元测试","title":"Test.@test_nowarn","text":"@test_nowarn expr\n\nTest whether evaluating expr results in empty stderr output (no warnings or other messages). Returns the result of evaluating expr.\n\nNote: The absence of warnings generated by @warn cannot be tested with this macro. Use @test_logs instead.\n\n\n\n\n\n","category":"macro"},{"location":"stdlib/Test/#Broken-Tests","page":"单元测试","title":"Broken Tests","text":"","category":"section"},{"location":"stdlib/Test/","page":"单元测试","title":"单元测试","text":"If a test fails consistently it can be changed to use the @test_broken macro. This will denote the test as Broken if the test continues to fail and alerts the user via an Error if the test succeeds.","category":"page"},{"location":"stdlib/Test/","page":"单元测试","title":"单元测试","text":"Test.@test_broken","category":"page"},{"location":"stdlib/Test/#Test.@test_broken","page":"单元测试","title":"Test.@test_broken","text":"@test_broken ex\n@test_broken f(args...) key=val ...\n\nIndicates a test that should pass but currently consistently fails. Tests that the expression ex evaluates to false or causes an exception. Returns a Broken Result if it does, or an Error Result if the expression evaluates to true. This is equivalent to @test ex broken=true.\n\nThe @test_broken f(args...) key=val... form works as for the @test macro.\n\nExamples\n\njulia> @test_broken 1 == 2\nTest Broken\n Expression: 1 == 2\n\njulia> @test_broken 1 == 2 atol=0.1\nTest Broken\n Expression: ==(1, 2, atol = 0.1)\n\n\n\n\n\n","category":"macro"},{"location":"stdlib/Test/","page":"单元测试","title":"单元测试","text":"@test_skip is also available to skip a test without evaluation, but counting the skipped test in the test set reporting. The test will not run but gives a Broken Result.","category":"page"},{"location":"stdlib/Test/","page":"单元测试","title":"单元测试","text":"Test.@test_skip","category":"page"},{"location":"stdlib/Test/#Test.@test_skip","page":"单元测试","title":"Test.@test_skip","text":"@test_skip ex\n@test_skip f(args...) key=val ...\n\nMarks a test that should not be executed but should be included in test summary reporting as Broken. This can be useful for tests that intermittently fail, or tests of not-yet-implemented functionality. This is equivalent to @test ex skip=true.\n\nThe @test_skip f(args...) key=val... form works as for the @test macro.\n\nExamples\n\njulia> @test_skip 1 == 2\nTest Broken\n Skipped: 1 == 2\n\njulia> @test_skip 1 == 2 atol=0.1\nTest Broken\n Skipped: ==(1, 2, atol = 0.1)\n\n\n\n\n\n","category":"macro"},{"location":"stdlib/Test/#Creating-Custom-AbstractTestSet-Types","page":"单元测试","title":"Creating Custom AbstractTestSet Types","text":"","category":"section"},{"location":"stdlib/Test/","page":"单元测试","title":"单元测试","text":"Packages can create their own AbstractTestSet subtypes by implementing the record and finish methods. The subtype should have a one-argument constructor taking a description string, with any options passed in as keyword arguments.","category":"page"},{"location":"stdlib/Test/","page":"单元测试","title":"单元测试","text":"Test.record\nTest.finish","category":"page"},{"location":"stdlib/Test/#Test.record","page":"单元测试","title":"Test.record","text":"record(ts::AbstractTestSet, res::Result)\n\nRecord a result to a testset. This function is called by the @testset infrastructure each time a contained @test macro completes, and is given the test result (which could be an Error). This will also be called with an Error if an exception is thrown inside the test block but outside of a @test context.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/Test/#Test.finish","page":"单元测试","title":"Test.finish","text":"finish(ts::AbstractTestSet)\n\nDo any final processing necessary for the given testset. This is called by the @testset infrastructure after a test block executes.\n\nCustom AbstractTestSet subtypes should call record on their parent (if there is one) to add themselves to the tree of test results. This might be implemented as:\n\nif get_testset_depth() != 0\n # Attach this test set to the parent test set\n parent_ts = get_testset()\n record(parent_ts, self)\n return self\nend\n\n\n\n\n\n","category":"function"},{"location":"stdlib/Test/","page":"单元测试","title":"单元测试","text":"Test takes responsibility for maintaining a stack of nested testsets as they are executed, but any result accumulation is the responsibility of the AbstractTestSet subtype. You can access this stack with the get_testset and get_testset_depth methods. Note that these functions are not exported.","category":"page"},{"location":"stdlib/Test/","page":"单元测试","title":"单元测试","text":"Test.get_testset\nTest.get_testset_depth","category":"page"},{"location":"stdlib/Test/#Test.get_testset","page":"单元测试","title":"Test.get_testset","text":"get_testset()\n\nRetrieve the active test set from the task's local storage. If no test set is active, use the fallback default test set.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/Test/#Test.get_testset_depth","page":"单元测试","title":"Test.get_testset_depth","text":"get_testset_depth()\n\nReturns the number of active test sets, not including the default test set\n\n\n\n\n\n","category":"function"},{"location":"stdlib/Test/","page":"单元测试","title":"单元测试","text":"Test also makes sure that nested @testset invocations use the same AbstractTestSet subtype as their parent unless it is set explicitly. It does not propagate any properties of the testset. Option inheritance behavior can be implemented by packages using the stack infrastructure that Test provides.","category":"page"},{"location":"stdlib/Test/","page":"单元测试","title":"单元测试","text":"Defining a basic AbstractTestSet subtype might look like:","category":"page"},{"location":"stdlib/Test/","page":"单元测试","title":"单元测试","text":"import Test: Test, record, finish\nusing Test: AbstractTestSet, Result, Pass, Fail, Error\nusing Test: get_testset_depth, get_testset\nstruct CustomTestSet <: Test.AbstractTestSet\n description::AbstractString\n foo::Int\n results::Vector\n # constructor takes a description string and options keyword arguments\n CustomTestSet(desc; foo=1) = new(desc, foo, [])\nend\n\nrecord(ts::CustomTestSet, child::AbstractTestSet) = push!(ts.results, child)\nrecord(ts::CustomTestSet, res::Result) = push!(ts.results, res)\nfunction finish(ts::CustomTestSet)\n # just record if we're not the top-level parent\n if get_testset_depth() > 0\n record(get_testset(), ts)\n end\n ts\nend","category":"page"},{"location":"stdlib/Test/","page":"单元测试","title":"单元测试","text":"And using that testset looks like:","category":"page"},{"location":"stdlib/Test/","page":"单元测试","title":"单元测试","text":"@testset CustomTestSet foo=4 \"custom testset inner 2\" begin\n # this testset should inherit the type, but not the argument.\n @testset \"custom testset inner\" begin\n @test true\n end\nend","category":"page"},{"location":"stdlib/Test/#Test-utilities","page":"单元测试","title":"Test utilities","text":"","category":"section"},{"location":"stdlib/Test/","page":"单元测试","title":"单元测试","text":"Test.GenericArray\nTest.GenericDict\nTest.GenericOrder\nTest.GenericSet\nTest.GenericString\nTest.detect_ambiguities\nTest.detect_unbound_args","category":"page"},{"location":"stdlib/Test/#Test.GenericArray","page":"单元测试","title":"Test.GenericArray","text":"The GenericArray can be used to test generic array APIs that program to the AbstractArray interface, in order to ensure that functions can work with array types besides the standard Array type.\n\n\n\n\n\n","category":"type"},{"location":"stdlib/Test/#Test.GenericDict","page":"单元测试","title":"Test.GenericDict","text":"The GenericDict can be used to test generic dict APIs that program to the AbstractDict interface, in order to ensure that functions can work with associative types besides the standard Dict type.\n\n\n\n\n\n","category":"type"},{"location":"stdlib/Test/#Test.GenericOrder","page":"单元测试","title":"Test.GenericOrder","text":"The GenericOrder can be used to test APIs for their support of generic ordered types.\n\n\n\n\n\n","category":"type"},{"location":"stdlib/Test/#Test.GenericSet","page":"单元测试","title":"Test.GenericSet","text":"The GenericSet can be used to test generic set APIs that program to the AbstractSet interface, in order to ensure that functions can work with set types besides the standard Set and BitSet types.\n\n\n\n\n\n","category":"type"},{"location":"stdlib/Test/#Test.GenericString","page":"单元测试","title":"Test.GenericString","text":"The GenericString can be used to test generic string APIs that program to the AbstractString interface, in order to ensure that functions can work with string types besides the standard String type.\n\n\n\n\n\n","category":"type"},{"location":"stdlib/Test/#Test.detect_ambiguities","page":"单元测试","title":"Test.detect_ambiguities","text":"detect_ambiguities(mod1, mod2...; recursive=false,\n ambiguous_bottom=false,\n allowed_undefineds=nothing)\n\nReturns a vector of (Method,Method) pairs of ambiguous methods defined in the specified modules. Use recursive=true to test in all submodules.\n\nambiguous_bottom controls whether ambiguities triggered only by Union{} type parameters are included; in most cases you probably want to set this to false. See Base.isambiguous.\n\nSee Test.detect_unbound_args for an explanation of allowed_undefineds.\n\ncompat: Julia 1.8\nallowed_undefineds requires at least Julia 1.8.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/Test/#Test.detect_unbound_args","page":"单元测试","title":"Test.detect_unbound_args","text":"detect_unbound_args(mod1, mod2...; recursive=false, allowed_undefineds=nothing)\n\nReturns a vector of Methods which may have unbound type parameters. Use recursive=true to test in all submodules.\n\nBy default, any undefined symbols trigger a warning. This warning can be suppressed by supplying a collection of GlobalRefs for which the warning can be skipped. For example, setting\n\nallow_undefineds = Set([GlobalRef(Base, :active_repl),\n GlobalRef(Base, :active_repl_backend)])\n\nwould suppress warnings about Base.active_repl and Base.active_repl_backend.\n\ncompat: Julia 1.8\nallowed_undefineds requires at least Julia 1.8.\n\n\n\n\n\n","category":"function"},{"location":"stdlib/Test/","page":"单元测试","title":"单元测试","text":"DocTestSetup = nothing","category":"page"},{"location":"manual/interfaces/#接口","page":"接口","title":"接口","text":"","category":"section"},{"location":"manual/interfaces/","page":"接口","title":"接口","text":"Julia 的很多能力和扩展性都来自于一些非正式的接口。通过为自定义的类型扩展一些特定的方法,自定义类型的对象不但获得那些方法的功能,而且也能够用于其它的基于那些行为而定义的通用方法中。","category":"page"},{"location":"manual/interfaces/#man-interface-iteration","page":"接口","title":"迭代","text":"","category":"section"},{"location":"manual/interfaces/","page":"接口","title":"接口","text":"必需方法 简短描述\niterate(iter) 通常返回由第一项及其初始状态组成的元组,但如果为空,则返回 nothing\niterate(iter, state) 通常返回由下一项及其状态组成的元组,或者在没有下一项存在时返回 nothing。\n重要可选方法 默认定义 简短描述\nIteratorSize(IterType) HasLength() HasLength(),HasShape{N}(),IsInfinite() 或者 SizeUnknown() 中合适的一个\nIteratorEltype(IterType) HasEltype() EltypeUnknown() 或 HasEltype() 中合适的一个\neltype(IterType) Any 由 iterate() 返回元组中第一项的类型。\nlength(iter) (未定义) 项数,如果已知\nsize(iter, [dim]) (未定义) 在各个维度上项数,如果已知","category":"page"},{"location":"manual/interfaces/","page":"接口","title":"接口","text":"由 IteratorSize(IterType) 返回的值 必需方法\nHasLength() length(iter)\nHasShape{N}() length(iter) 和 size(iter, [dim])\nIsInfinite() (无)\nSizeUnknown() (无)","category":"page"},{"location":"manual/interfaces/","page":"接口","title":"接口","text":"由 IteratorEltype(IterType) 返回的值 必需方法\nHasEltype() eltype(IterType)\nEltypeUnknown() (none)","category":"page"},{"location":"manual/interfaces/","page":"接口","title":"接口","text":"顺序迭代由 iterate 函数实现。 Julia 的迭代器可以从对象外部跟踪迭代状态,而不是在迭代过程中改变对象本身。 迭代过程中的返回一个包含了当前迭代值及其状态的元组,或者在没有元素存在的情况下返回 nothing。 状态对象将在下一次迭代时传递回 iterate 函数,并且通常被认为是可迭代对象的私有实现细节。","category":"page"},{"location":"manual/interfaces/","page":"接口","title":"接口","text":"任何定义了这个函数的对象都是可迭代的,并且可以被应用到许多依赖迭代的函数上 。 也可以直接被应用到 for 循环中,因为根据语法:","category":"page"},{"location":"manual/interfaces/","page":"接口","title":"接口","text":"for item in iter # or \"for item = iter\"\n # body\nend","category":"page"},{"location":"manual/interfaces/","page":"接口","title":"接口","text":"以上代码被解释为:","category":"page"},{"location":"manual/interfaces/","page":"接口","title":"接口","text":"next = iterate(iter)\nwhile next !== nothing\n (item, state) = next\n # body\n next = iterate(iter, state)\nend","category":"page"},{"location":"manual/interfaces/","page":"接口","title":"接口","text":"举一个简单的例子:一组定长数据的平方数迭代序列:","category":"page"},{"location":"manual/interfaces/","page":"接口","title":"接口","text":"julia> struct Squares\n count::Int\n end\n\njulia> Base.iterate(S::Squares, state=1) = state > S.count ? nothing : (state*state, state+1)","category":"page"},{"location":"manual/interfaces/","page":"接口","title":"接口","text":"仅仅定义了 iterate 函数的 Squares 类型就已经很强大了。 我们现在可以迭代所有的元素了:","category":"page"},{"location":"manual/interfaces/","page":"接口","title":"接口","text":"julia> for item in Squares(7)\n println(item)\n end\n1\n4\n9\n16\n25\n36\n49","category":"page"},{"location":"manual/interfaces/","page":"接口","title":"接口","text":"我们可以利用许多内置方法来处理迭代,比如标准库 Statistics 中的 in,mean 和 std 。","category":"page"},{"location":"manual/interfaces/","page":"接口","title":"接口","text":"julia> 25 in Squares(10)\ntrue\n\njulia> using Statistics\n\njulia> mean(Squares(100))\n3383.5\n\njulia> std(Squares(100))\n3024.355854282583","category":"page"},{"location":"manual/interfaces/","page":"接口","title":"接口","text":"我们可以扩展一些其它的方法,为 Julia 提供有关此可迭代集合的更多信息。我们知道 Squares 序列中的元素总是 Int 型的。通过扩展 eltype 方法,我们可以给 Julia 更多信息来帮助其在更复杂的方法中生成更具体的代码。我们同时也知道该序列中的元素数目,故同样地也可以扩展 length:","category":"page"},{"location":"manual/interfaces/","page":"接口","title":"接口","text":"julia> Base.eltype(::Type{Squares}) = Int # Note that this is defined for the type\n\njulia> Base.length(S::Squares) = S.count","category":"page"},{"location":"manual/interfaces/","page":"接口","title":"接口","text":"现在,当我们让 Julia 去 collect 所有元素到一个数组中时,Julia 可以预分配一个适当大小的 Vector{Int},而不是朴素地 push! 每一个元素到 Vector{Any}:","category":"page"},{"location":"manual/interfaces/","page":"接口","title":"接口","text":"julia> collect(Squares(4))\n4-element Vector{Int64}:\n 1\n 4\n 9\n 16","category":"page"},{"location":"manual/interfaces/","page":"接口","title":"接口","text":"尽管大多时候我们都可以依赖一些通用的实现,但某些时候,如果我们知道一个更简单的算法,可以用其扩展具体方法。例如,计算平方和有公式,因此可以扩展出一个更高效的解法来替代通用方法:","category":"page"},{"location":"manual/interfaces/","page":"接口","title":"接口","text":"julia> Base.sum(S::Squares) = (n = S.count; return n*(n+1)*(2n+1)÷6)\n\njulia> sum(Squares(1803))\n1955361914","category":"page"},{"location":"manual/interfaces/","page":"接口","title":"接口","text":"这种模式在 Julia Base 中很常见,一些必须实现的方法构成了一个小的集合,从而定义出一个非正式的接口,用于实现一些更加炫酷的操作。某些应用场景中,一些类型有更高效的算法,故可以扩展出额外的专用方法。","category":"page"},{"location":"manual/interfaces/","page":"接口","title":"接口","text":"能以逆序迭代集合也很有用,这可由 Iterators.reverse(iterator) 迭代实现。但是,为了实际支持逆序迭代,迭代器类型 T 需要为 Iterators.Reverse{T} 实现 iterate。(给定 r::Iterators.Reverse{T},类型 T 的底层迭代器是 r.itr。)在我们的 Squares 示例中,我们可以实现 Iterators.Reverse{Squares} 方法:","category":"page"},{"location":"manual/interfaces/","page":"接口","title":"接口","text":"julia> Base.iterate(rS::Iterators.Reverse{Squares}, state=rS.itr.count) = state < 1 ? nothing : (state*state, state-1)\n\njulia> collect(Iterators.reverse(Squares(4)))\n4-element Vector{Int64}:\n 16\n 9\n 4\n 1","category":"page"},{"location":"manual/interfaces/#Indexing","page":"接口","title":"Indexing","text":"","category":"section"},{"location":"manual/interfaces/","page":"接口","title":"接口","text":"Methods to implement Brief description\ngetindex(X, i) X[i], indexed element access\nsetindex!(X, v, i) X[i] = v, indexed assignment\nfirstindex(X) The first index, used in X[begin]\nlastindex(X) The last index, used in X[end]","category":"page"},{"location":"manual/interfaces/","page":"接口","title":"接口","text":"For the Squares iterable above, we can easily compute the ith element of the sequence by squaring it. We can expose this as an indexing expression S[i]. To opt into this behavior, Squares simply needs to define getindex:","category":"page"},{"location":"manual/interfaces/","page":"接口","title":"接口","text":"julia> function Base.getindex(S::Squares, i::Int)\n 1 <= i <= S.count || throw(BoundsError(S, i))\n return i*i\n end\n\njulia> Squares(100)[23]\n529","category":"page"},{"location":"manual/interfaces/","page":"接口","title":"接口","text":"另外,为了支持语法 S[begin] 和 S[end],我们必须定义 lastindex 来指定最后一个有效索引。建议也定义 firstindex 来指定第一个有效索引:","category":"page"},{"location":"manual/interfaces/","page":"接口","title":"接口","text":"julia> Base.firstindex(S::Squares) = 1\n\njulia> Base.lastindex(S::Squares) = length(S)\n\njulia> Squares(23)[end]\n529","category":"page"},{"location":"manual/interfaces/","page":"接口","title":"接口","text":"对多维的 begin/end索引,例如,像是 a[3, begin, 7],你应该定义 firstindex(a, dim) 和 lastindex(a, dim)(它们默认各自在 axes(a, dim) 上调用 first和last)","category":"page"},{"location":"manual/interfaces/","page":"接口","title":"接口","text":"注意,上面只定义了一个整数索引的 getindex 方法,用除一个整数之外的其它东西索引会抛出MethodError,因为现在还没有匹配的方法。为了支持 Int 的范围或向量索引,必须另外写一个方法:","category":"page"},{"location":"manual/interfaces/","page":"接口","title":"接口","text":"julia> Base.getindex(S::Squares, i::Number) = S[convert(Int, i)]\n\njulia> Base.getindex(S::Squares, I) = [S[i] for i in I]\n\njulia> Squares(10)[[3,4.,5]]\n3-element Vector{Int64}:\n 9\n 16\n 25","category":"page"},{"location":"manual/interfaces/","page":"接口","title":"接口","text":"虽然这开始支持更多某些内置类型支持的索引操作,但仍然有很多行为不支持。因为我们为 Squares 序列所添加的行为,它开始看起来越来越像向量。我们可以正式定义其为 AbstractArray 的子类型,而不是自己定义所有这些行为。","category":"page"},{"location":"manual/interfaces/#man-interface-array","page":"接口","title":"抽象数组","text":"","category":"section"},{"location":"manual/interfaces/","page":"接口","title":"接口","text":"需要实现的方法 简短描述\nsize(A) 返回包含 A 各维度大小的元组\ngetindex(A, i::Int) (若为 IndexLinear)线性标量索引\ngetindex(A, I::Vararg{Int, N}) (若为 IndexCartesian,其中 N = ndims(A))N 维标量索引\nsetindex!(A, v, i::Int) (若为 IndexLinear)线性索引元素赋值\nsetindex!(A, v, I::Vararg{Int, N}) (若为 IndexCartesian,其中 N = ndims(A))N 维标量索引元素赋值\n可选方法 默认定义 简短描述\nIndexStyle(::Type) IndexCartesian() 返回 IndexLinear() 或 IndexCartesian()。请参阅下文描述。\ngetindex(A, I...) 基于标量 getindex 定义 多维非标量索引\nsetindex!(A, X, I...) 基于标量 setindex! 定义 多维非标量索引元素赋值\niterate 基于标量 getindex 定义 Iteration\nlength(A) prod(size(A)) 元素数\nsimilar(A) similar(A, eltype(A), size(A)) 返回具有相同形状和元素类型的可变数组\nsimilar(A, ::Type{S}) similar(A, S, size(A)) 返回具有相同形状和指定元素类型的可变数组\nsimilar(A, dims::Dims) similar(A, eltype(A), dims) 返回具有相同元素类型和大小为 dims 的可变数组\nsimilar(A, ::Type{S}, dims::Dims) Array{S}(undef, dims) 返回具有指定元素类型及大小的可变数组\n不遵循惯例的索引 默认定义 简短描述\naxes(A) map(OneTo, size(A)) 返回有效索引的 AbstractUnitRange{<:Integer}\nsimilar(A, ::Type{S}, inds) similar(A, S, Base.to_shape(inds)) 返回使用特殊索引 inds 的可变数组(详见下文)\nsimilar(T::Union{Type,Function}, inds) T(Base.to_shape(inds)) 返回类似于 T 的使用特殊索引 inds 的数组(详见下文)","category":"page"},{"location":"manual/interfaces/","page":"接口","title":"接口","text":"如果一个类型被定义为 AbstractArray 的子类型,那它就继承了一大堆丰富的行为,包括构建在单元素访问之上的迭代和多维索引。有关更多支持的方法,请参阅文档 多维数组 及 Julia Base。","category":"page"},{"location":"manual/interfaces/","page":"接口","title":"接口","text":"定义 AbstractArray 子类型的关键部分是 IndexStyle。由于索引是数组的重要部分且经常出现在 hot loops 中,使索引和索引赋值尽可能高效非常重要。数组数据结构通常以两种方式定义:要么仅使用一个索引(即线性索引)来最高效地访问其元素,要么实际上使用由各个维度确定的索引访问其元素。这两种方式被 Julia 标记为 IndexLinear() 和 IndexCartesian()。把线性索引转换为多重索引下标通常代价高昂,因此这提供了基于 traits 机制,以便能为所有矩阵类型提供高效的通用代码。","category":"page"},{"location":"manual/interfaces/","page":"接口","title":"接口","text":"此区别决定了该类型必须定义的标量索引方法。IndexLinear() 很简单:只需定义 getindex(A::ArrayType, i::Int)。当数组后用多维索引集进行索引时,回退 getindex(A::AbstractArray, I...)() 高效地将该索引转换为线性索引,然后调用上述方法。另一方面,IndexCartesian() 数组需要为每个支持的、使用 ndims(A) 个 Int 索引的维度定义方法。例如,SparseArrays 标准库里的 SparseMatrixCSC 只支持二维,所以它只定义了 getindex(A::SparseMatrixCSC, i::Int, j::Int)。setindex! 也是如此。","category":"page"},{"location":"manual/interfaces/","page":"接口","title":"接口","text":"回到上面的平方数序列,我们可以将它定义为 AbstractArray{Int, 1} 的子类型:","category":"page"},{"location":"manual/interfaces/","page":"接口","title":"接口","text":"julia> struct SquaresVector <: AbstractArray{Int, 1}\n count::Int\n end\n\njulia> Base.size(S::SquaresVector) = (S.count,)\n\njulia> Base.IndexStyle(::Type{<:SquaresVector}) = IndexLinear()\n\njulia> Base.getindex(S::SquaresVector, i::Int) = i*i","category":"page"},{"location":"manual/interfaces/","page":"接口","title":"接口","text":"请注意,指定 AbstractArray 的两个参数非常重要;第一个参数定义了 eltype,第二个则定义了 ndims。该超类型和这三个方法就足以使 SquaresVector 变成一个可迭代、可索引且功能齐全的数组:","category":"page"},{"location":"manual/interfaces/","page":"接口","title":"接口","text":"julia> s = SquaresVector(4)\n4-element SquaresVector:\n 1\n 4\n 9\n 16\n\njulia> s[s .> 8]\n2-element Vector{Int64}:\n 9\n 16\n\njulia> s + s\n4-element Vector{Int64}:\n 2\n 8\n 18\n 32\n\njulia> sin.(s)\n4-element Vector{Float64}:\n 0.8414709848078965\n -0.7568024953079282\n 0.4121184852417566\n -0.2879033166650653","category":"page"},{"location":"manual/interfaces/","page":"接口","title":"接口","text":"作为一个更复杂的例子,让我们在 Dict 之上定义自己的玩具性质的 N 维稀疏数组类型。","category":"page"},{"location":"manual/interfaces/","page":"接口","title":"接口","text":"julia> struct SparseArray{T,N} <: AbstractArray{T,N}\n data::Dict{NTuple{N,Int}, T}\n dims::NTuple{N,Int}\n end\n\njulia> SparseArray(::Type{T}, dims::Int...) where {T} = SparseArray(T, dims);\n\njulia> SparseArray(::Type{T}, dims::NTuple{N,Int}) where {T,N} = SparseArray{T,N}(Dict{NTuple{N,Int}, T}(), dims);\n\njulia> Base.size(A::SparseArray) = A.dims\n\njulia> Base.similar(A::SparseArray, ::Type{T}, dims::Dims) where {T} = SparseArray(T, dims)\n\njulia> Base.getindex(A::SparseArray{T,N}, I::Vararg{Int,N}) where {T,N} = get(A.data, I, zero(T))\n\njulia> Base.setindex!(A::SparseArray{T,N}, v, I::Vararg{Int,N}) where {T,N} = (A.data[I] = v)","category":"page"},{"location":"manual/interfaces/","page":"接口","title":"接口","text":"请注意,这是个 IndexCartesian 数组,因此我们必须在数组的维度上手动定义 getindex 和 setindex!。与 SquaresVector 不同,我们可以定义 setindex!,这样便能更改数组:","category":"page"},{"location":"manual/interfaces/","page":"接口","title":"接口","text":"julia> A = SparseArray(Float64, 3, 3)\n3×3 SparseArray{Float64, 2}:\n 0.0 0.0 0.0\n 0.0 0.0 0.0\n 0.0 0.0 0.0\n\njulia> fill!(A, 2)\n3×3 SparseArray{Float64, 2}:\n 2.0 2.0 2.0\n 2.0 2.0 2.0\n 2.0 2.0 2.0\n\njulia> A[:] = 1:length(A); A\n3×3 SparseArray{Float64, 2}:\n 1.0 4.0 7.0\n 2.0 5.0 8.0\n 3.0 6.0 9.0","category":"page"},{"location":"manual/interfaces/","page":"接口","title":"接口","text":"索引 AbstractArray 的结果本身可以是数组(例如,在使用 AbstractRange 时)。AbstractArray 回退方法使用 similar 来分配具有适当大小和元素类型的 Array,该数组使用上述的基本索引方法填充。但是,在实现数组封装器时,你通常希望也封装结果:","category":"page"},{"location":"manual/interfaces/","page":"接口","title":"接口","text":"julia> A[1:2,:]\n2×3 SparseArray{Float64, 2}:\n 1.0 4.0 7.0\n 2.0 5.0 8.0","category":"page"},{"location":"manual/interfaces/","page":"接口","title":"接口","text":"在此例中,创建合适的封装数组通过定义 Base.similar(A::SparseArray, ::Type{T}, dims::Dims) where T 来实现。(请注意,虽然 similar 支持 1 参数和 2 参数形式,但在大多数情况下,你只需要专门定义 3 参数形式。)为此,SparseArray 是可变的(支持 setindex!)便很重要。为 SparseArray 定义 similar、getindex 和 setindex! 也使得该数组能够 copy 。","category":"page"},{"location":"manual/interfaces/","page":"接口","title":"接口","text":"julia> copy(A)\n3×3 SparseArray{Float64,2}:\n 1.0 4.0 7.0\n 2.0 5.0 8.0\n 3.0 6.0 9.0","category":"page"},{"location":"manual/interfaces/","page":"接口","title":"接口","text":"除了上面的所有可迭代和可索引方法之外,这些类型还能相互交互,并使用在 Julia Base 中为 AbstractArray 定义的大多数方法:","category":"page"},{"location":"manual/interfaces/","page":"接口","title":"接口","text":"julia> A[SquaresVector(3)]\n3-element SparseArray{Float64, 1}:\n 1.0\n 4.0\n 9.0\n\njulia> sum(A)\n45.0","category":"page"},{"location":"manual/interfaces/","page":"接口","title":"接口","text":"如果要定义允许非传统索引(索引以 1 之外的数字开始)的数组类型,你应该专门指定 axes。你也应该专门指定 similar,以便 dims 参数(通常是大小为 Dims 的元组)可以接收 AbstractUnitRange 对象,它也许是你自己设计的 range 类型 Ind。有关更多信息,请参阅使用自定义索引的数组。","category":"page"},{"location":"manual/interfaces/#man-interface-strided-arrays","page":"接口","title":"等步长数组","text":"","category":"section"},{"location":"manual/interfaces/","page":"接口","title":"接口","text":"实习方法 简要描述\nstrides(A) 返回每个维度中相邻元素之间的内存距离(以内存元素数量的形式)组成的元组。如果 A 是 AbstractArray{T,0},这应该返回空元组。\nBase.unsafe_convert(::Type{Ptr{T}}, A) 返回数组的本地内存地址\nBase.elsize(::Type{<:A}) 返回数组中连续元素的步长\n可选方法 默认定义 简要描述\nstride(A, i::Int) strides(A)[i] 返回维度 i(译注:原文为 k)上相邻元素之间的内存距离(以内存元素数量的形式)。","category":"page"},{"location":"manual/interfaces/","page":"接口","title":"接口","text":"等步长数组是 AbstractArray 的子类型,其条目以固定步长储存在内存中。如果数组的元素类型与 BLAS 兼容,则 strided 数组可以利用 BLAS 和 LAPACK 例程来实现更高效的线性代数例程。用户定义的 strided 数组的典型示例是把标准 Array 用附加结构进行封装的数组。","category":"page"},{"location":"manual/interfaces/","page":"接口","title":"接口","text":"警告:如果底层存储实际上不是 strided,则不要实现这些方法,因为这可能导致错误的结果或段错误。","category":"page"},{"location":"manual/interfaces/","page":"接口","title":"接口","text":"下面是一些示例,用来演示哪些数组类型是 strided 数组,哪些不是:","category":"page"},{"location":"manual/interfaces/","page":"接口","title":"接口","text":"1:5 # not strided (there is no storage associated with this array.)\nVector(1:5) # is strided with strides (1,)\nA = [1 5; 2 6; 3 7; 4 8] # is strided with strides (1,4)\nV = view(A, 1:2, :) # is strided with strides (1,4)\nV = view(A, 1:2:3, 1:2) # is strided with strides (2,4)\nV = view(A, [1,2,4], :) # is not strided, as the spacing between rows is not fixed.","category":"page"},{"location":"manual/interfaces/#man-interfaces-broadcasting","page":"接口","title":"自定义广播","text":"","category":"section"},{"location":"manual/interfaces/","page":"接口","title":"接口","text":"需要实现的方法 简短描述\nBase.BroadcastStyle(::Type{SrcType}) = SrcStyle() SrcType 的广播行为\nBase.similar(bc::Broadcasted{DestStyle}, ::Type{ElType}) 输出容器的分配\n可选方法 \nBase.BroadcastStyle(::Style1, ::Style2) = Style12() 混合广播风格的优先级规则\nBase.axes(x) 用于广播的 x 的索引的声明(默认为 axes(x))\nBase.broadcastable(x) 将 x 转换为一个具有 axes 且支持索引的对象\n绕过默认机制 \nBase.copy(bc::Broadcasted{DestStyle}) broadcast 的自定义实现\nBase.copyto!(dest, bc::Broadcasted{DestStyle}) 专门针对 DestStyle 的自定义 broadcast! 实现\nBase.copyto!(dest::DestType, bc::Broadcasted{Nothing}) 专门针对 DestStyle 的自定义 broadcast! 实现\nBase.Broadcast.broadcasted(f, args...) 覆盖融合表达式中的默认惰性行为\nBase.Broadcast.instantiate(bc::Broadcasted{DestStyle}) 覆盖惰性广播的 axes 的计算","category":"page"},{"location":"manual/interfaces/","page":"接口","title":"接口","text":"广播可由 broadcast 或 broadcast! 的显式调用、或者像 A .+ b 或 f.(x, y) 这样的「点」操作隐式触发。任何具有 axes 且支持索引的对象都可作为参数参与广播,默认情况下,广播结果储存在 Array 中。这个基本框架可通过三个主要方式扩展:","category":"page"},{"location":"manual/interfaces/","page":"接口","title":"接口","text":"确保所有参数都支持广播\n为给定参数集选择合适的输出数组\n为给定参数集选择高效的实现","category":"page"},{"location":"manual/interfaces/","page":"接口","title":"接口","text":"不是所有类型都支持 axes 和索引,但许多类型便于支持广播。Base.broadcastable 函数会在每个广播参数上调用,它能返回与广播参数不同的支持 axes 和索引的对象。默认情况下,对于所有 AbstractArray 和 Number 来说这是 identity 函数——因为它们已经支持 axes 和索引了。少数其它类型(包括但不限于类型本身、函数、像 missing 和 nothing 这样的特殊单态类型以及日期)为了能被广播,Base.broadcastable 会返回封装在 Ref 的参数来充当 0 维「标量」。自定义类型可以类似地指定 Base.broadcastable 来定义其形状,但是它们应当遵循 collect(Base.broadcastable(x)) == collect(x) 的约定。一个值得注意的例外是 AbstractString;字符串是个特例,为了能被广播其表现为标量,尽管它们是其字符的可迭代集合(详见 字符串)。","category":"page"},{"location":"manual/interfaces/","page":"接口","title":"接口","text":"接下来的两个步骤(选择输出数组和实现)依赖于如何确定给定参数集的唯一解。广播必须接受其参数的所有不同类型,并把它们折叠到一个输出数组和实现。广播称此唯一解为“风格”。每个可广播对象都有自己的首选风格,并使用类似于类型提升的系统将这些风格组合成一个唯一解——“目标风格”。","category":"page"},{"location":"manual/interfaces/#广播风格","page":"接口","title":"广播风格","text":"","category":"section"},{"location":"manual/interfaces/","page":"接口","title":"接口","text":"抽象类型 Base.BroadcastStyle 派生了所有的广播风格。其在用作函数时有两种可能的形式,分别为一元形式(单参数)和二元形式。使用一元形式表明你打算实现特定的广播行为和/或输出类型,并且不希望依赖于默认的回退 Broadcast.DefaultArrayStyle。","category":"page"},{"location":"manual/interfaces/","page":"接口","title":"接口","text":"为了覆盖这些默认值,你可以为对象自定义 BroadcastStyle:","category":"page"},{"location":"manual/interfaces/","page":"接口","title":"接口","text":"struct MyStyle <: Broadcast.BroadcastStyle end\nBase.BroadcastStyle(::Type{<:MyType}) = MyStyle()","category":"page"},{"location":"manual/interfaces/","page":"接口","title":"接口","text":"在某些情况下,无需定义 MyStyle 也许很方便,在这些情况下,你可以利用一个通用的广播封装器:","category":"page"},{"location":"manual/interfaces/","page":"接口","title":"接口","text":"Base.BroadcastStyle(::Type{<:MyType}) = Broadcast.Style{MyType}() 可用于任意类型。\n如果 MyType 是一个 AbstractArray,首选是 Base.BroadcastStyle(::Type{<:MyType}) = Broadcast.ArrayStyle{MyType}()。\n对于只支持某个具体维度的 AbstractArrays,请创建 Broadcast.AbstractArrayStyle{N} 的子类型(请参阅下文)。","category":"page"},{"location":"manual/interfaces/","page":"接口","title":"接口","text":"当你的广播操作涉及多个参数,各个广播风格将合并,来确定唯一一个 DestStyle 以控制输出容器的类型。有关更多详细信息,请参阅下文。","category":"page"},{"location":"manual/interfaces/#选择合适的输出数组","page":"接口","title":"选择合适的输出数组","text":"","category":"section"},{"location":"manual/interfaces/","page":"接口","title":"接口","text":"每个广播操作都会计算广播风格以便支持派发和专门化。结果数组的实际分配由 similar 处理,其使用 Broadcasted 对象作为其第一个参数。","category":"page"},{"location":"manual/interfaces/","page":"接口","title":"接口","text":"Base.similar(bc::Broadcasted{DestStyle}, ::Type{ElType})","category":"page"},{"location":"manual/interfaces/","page":"接口","title":"接口","text":"回退定义是","category":"page"},{"location":"manual/interfaces/","page":"接口","title":"接口","text":"similar(bc::Broadcasted{DefaultArrayStyle{N}}, ::Type{ElType}) where {N,ElType} =\n similar(Array{ElType}, axes(bc))","category":"page"},{"location":"manual/interfaces/","page":"接口","title":"接口","text":"但是,如果需要,你可以专门化任何或所有这些参数。最后的参数 bc 是(还可能是融合的)广播操作的惰性表示,即 Broadcasted 对象。出于这些目的,该封装器中最重要的字段是 f 和 args,分别描述函数和参数列表。请注意,参数列表可以——并且经常——包含其它嵌套的 Broadcasted 封装器。","category":"page"},{"location":"manual/interfaces/","page":"接口","title":"接口","text":"举个完整的例子,假设你创建了类型 ArrayAndChar,该类型存储一个数组和单个字符:","category":"page"},{"location":"manual/interfaces/","page":"接口","title":"接口","text":"struct ArrayAndChar{T,N} <: AbstractArray{T,N}\n data::Array{T,N}\n char::Char\nend\nBase.size(A::ArrayAndChar) = size(A.data)\nBase.getindex(A::ArrayAndChar{T,N}, inds::Vararg{Int,N}) where {T,N} = A.data[inds...]\nBase.setindex!(A::ArrayAndChar{T,N}, val, inds::Vararg{Int,N}) where {T,N} = A.data[inds...] = val\nBase.showarg(io::IO, A::ArrayAndChar, toplevel) = print(io, typeof(A), \" with char '\", A.char, \"'\")","category":"page"},{"location":"manual/interfaces/","page":"接口","title":"接口","text":"你可能想要广播保留“元数据”char。为此,我们首先定义","category":"page"},{"location":"manual/interfaces/","page":"接口","title":"接口","text":"Base.BroadcastStyle(::Type{<:ArrayAndChar}) = Broadcast.ArrayStyle{ArrayAndChar}()","category":"page"},{"location":"manual/interfaces/","page":"接口","title":"接口","text":"这意味着我们还必须定义相应的 similar 方法:","category":"page"},{"location":"manual/interfaces/","page":"接口","title":"接口","text":"function Base.similar(bc::Broadcast.Broadcasted{Broadcast.ArrayStyle{ArrayAndChar}}, ::Type{ElType}) where ElType\n # Scan the inputs for the ArrayAndChar:\n A = find_aac(bc)\n # Use the char field of A to create the output\n ArrayAndChar(similar(Array{ElType}, axes(bc)), A.char)\nend\n\n\"`A = find_aac(As)` returns the first ArrayAndChar among the arguments.\"\nfind_aac(bc::Base.Broadcast.Broadcasted) = find_aac(bc.args)\nfind_aac(args::Tuple) = find_aac(find_aac(args[1]), Base.tail(args))\nfind_aac(x) = x\nfind_aac(::Tuple{}) = nothing\nfind_aac(a::ArrayAndChar, rest) = a\nfind_aac(::Any, rest) = find_aac(rest)","category":"page"},{"location":"manual/interfaces/","page":"接口","title":"接口","text":"在这些定义中,可以得到以下行为:","category":"page"},{"location":"manual/interfaces/","page":"接口","title":"接口","text":"julia> a = ArrayAndChar([1 2; 3 4], 'x')\n2×2 ArrayAndChar{Int64, 2} with char 'x':\n 1 2\n 3 4\n\njulia> a .+ 1\n2×2 ArrayAndChar{Int64, 2} with char 'x':\n 2 3\n 4 5\n\njulia> a .+ [5,10]\n2×2 ArrayAndChar{Int64, 2} with char 'x':\n 6 7\n 13 14","category":"page"},{"location":"manual/interfaces/#extending-in-place-broadcast","page":"接口","title":"使用自定义实现扩展广播","text":"","category":"section"},{"location":"manual/interfaces/","page":"接口","title":"接口","text":"一般来说,广播操作由一个惰性 Broadcasted 容器表示,该容器保存要应用的函数及其参数。这些参数可能本身是嵌套得更深的 Broadcasted 容器,并一起形成了一个待求值的大型表达式树。嵌套的 Broadcasted 容器树可由隐式的点语法直接构造;例如,5 .+ 2.*x 由 Broadcasted(+, 5, Broadcasted(*, 2, x)) 暂时表示。这对于用户是不可见的,因为它是通过调用 copy 立即实现的,但是此容器为自定义类型的作者提供了广播可扩展性的基础。然后,内置的广播机制将根据参数确定结果的类型和大小,为它分配内存,并最终通过默认的 copyto!(::AbstractArray, ::Broadcasted) 方法将 Broadcasted 对象复制到其中。内置的回退 broadcast 和 broadcast! 方法类似地构造操作的暂时 Broadcasted 表示,因此它们共享相同的代码路径。这便允许自定义的数组实现通过提供它们自己的专门化 copyto! 来定义和优化广播。这再次由计算后的广播风格确定。此广播风格在广播操作中非常重要,以至于它被存储为 Broadcasted 类型的第一个类型参数,且允许派发和专门化。","category":"page"},{"location":"manual/interfaces/","page":"接口","title":"接口","text":"对于某些类型,跨越层层嵌套的广播的「融合」操作无法实现,或者无法更高效地逐步完成。在这种情况下,你可能需要或者想要求值 x .* (x .+ 1),就好像该式已被编写成 broadcast(*, x, broadcast(+, x, 1)),其中内部广播操作会在处理外部广播操作前进行求值。这种直接的操作以有点间接的方式得到直接支持;Julia 不会直接构造 Broadcasted 对象,而会将 待融合的表达式 x .* (x .+ 1) 降低为 Broadcast.broadcasted(*, x, Broadcast.broadcasted(+, x, 1))。现在,默认情况下,broadcasted 只会调用 Broadcasted 构造函数来创建待融合表达式树的惰性表示,但是你可以选择为函数和参数的特定组合覆盖它。","category":"page"},{"location":"manual/interfaces/","page":"接口","title":"接口","text":"举个例子,内置的 AbstractRange 对象使用此机制优化广播表达式的片段,这些表达式片段可以只根据 start、step 和 length(或 stop)直接进行求值,而无需计算每个元素。与所有其它机制一样,broadcasted 也会计算并暴露其参数的组合广播风格,所以你可以为广播风格、函数和参数的任意组合专门化 broadcasted(::DestStyle, f, args...),而不是专门化 broadcasted(f, args...)。","category":"page"},{"location":"manual/interfaces/","page":"接口","title":"接口","text":"例如,以下定义支持 range 的负运算:","category":"page"},{"location":"manual/interfaces/","page":"接口","title":"接口","text":"broadcasted(::DefaultArrayStyle{1}, ::typeof(-), r::OrdinalRange) = range(-first(r), step=-step(r), length=length(r))","category":"page"},{"location":"manual/interfaces/#extending-in-place-broadcast-2","page":"接口","title":"扩展 in-place 广播","text":"","category":"section"},{"location":"manual/interfaces/","page":"接口","title":"接口","text":"In-place 广播可通过定义合适的 copyto!(dest, bc::Broadcasted) 方法来支持。由于你可能想要专门化 dest 或 bc 的特定子类型,为了避免包之间的歧义,我们建议采用以下约定。","category":"page"},{"location":"manual/interfaces/","page":"接口","title":"接口","text":"如果你想要专门化特定的广播风格 DestStyle,请为其定义一个方法","category":"page"},{"location":"manual/interfaces/","page":"接口","title":"接口","text":"copyto!(dest, bc::Broadcasted{DestStyle})","category":"page"},{"location":"manual/interfaces/","page":"接口","title":"接口","text":"你可选择使用此形式,如果使用,你还可以专门化 dest 的类型。","category":"page"},{"location":"manual/interfaces/","page":"接口","title":"接口","text":"如果你想专门化目标类型 DestType 而不专门化 DestStyle,那么你应该定义一个带有以下签名的方法:","category":"page"},{"location":"manual/interfaces/","page":"接口","title":"接口","text":"copyto!(dest::DestType, bc::Broadcasted{Nothing})","category":"page"},{"location":"manual/interfaces/","page":"接口","title":"接口","text":"这利用了 copyto! 的回退实现,它将该封装器转换为一个 Broadcasted{Nothing} 对象。因此,专门化 DestType 的方法优先级低于专门化 DestStyle 的方法。","category":"page"},{"location":"manual/interfaces/","page":"接口","title":"接口","text":"同样,你可以使用 copy(::Broadcasted) 方法完全覆盖 out-of-place 广播。","category":"page"},{"location":"manual/interfaces/#使用-Broadcasted-对象","page":"接口","title":"使用 Broadcasted 对象","text":"","category":"section"},{"location":"manual/interfaces/","page":"接口","title":"接口","text":"当然,为了实现这样的 copy 或 copyto! 方法,你必须使用 Broadcasted 封装器来计算每个元素。这主要有两种方式:","category":"page"},{"location":"manual/interfaces/","page":"接口","title":"接口","text":"Broadcast.flatten 将可能的嵌套操作重新计算为单个函数并平铺参数列表。你自己负责实现广播形状规则,但这在有限的情况下可能会有所帮助。\n迭代 axes(::Broadcasted) 的 CartesianIndices 并使用所生成的 CartesianIndex 对象的索引来计算结果。","category":"page"},{"location":"manual/interfaces/#writing-binary-broadcasting-rules","page":"接口","title":"编写二元广播规则","text":"","category":"section"},{"location":"manual/interfaces/","page":"接口","title":"接口","text":"广播风格的优先级规则由二元 BroadcastStyle 调用定义:","category":"page"},{"location":"manual/interfaces/","page":"接口","title":"接口","text":"Base.BroadcastStyle(::Style1, ::Style2) = Style12()","category":"page"},{"location":"manual/interfaces/","page":"接口","title":"接口","text":"其中,Style12 是你要为输出所选择的 BroadcastStyle,所涉及的参数具有 Style1 及 Style2。例如,","category":"page"},{"location":"manual/interfaces/","page":"接口","title":"接口","text":"Base.BroadcastStyle(::Broadcast.Style{Tuple}, ::Broadcast.AbstractArrayStyle{0}) = Broadcast.Style{Tuple}()","category":"page"},{"location":"manual/interfaces/","page":"接口","title":"接口","text":"表示 Tuple「胜过」零维数组(输出容器将是元组)。值得注意的是,你不需要(也不应该)为此调用的两个参数顺序下定义;无论用户提供的以何种顺序提供参数,定义一个就够了。","category":"page"},{"location":"manual/interfaces/","page":"接口","title":"接口","text":"对于 AbstractArray 类型,定义 BroadcastStyle 将取代回退选择 Broadcast.DefaultArrayStyle。DefaultArrayStyle 及其抽象超类型 AbstractArrayStyle 将维度存储为类型参数,以支持具有固定维度需求的特定数组类型。","category":"page"},{"location":"manual/interfaces/","page":"接口","title":"接口","text":"由于以下方法,DefaultArrayStyle「输给」任何其它已定义的 AbstractArrayStyle:","category":"page"},{"location":"manual/interfaces/","page":"接口","title":"接口","text":"BroadcastStyle(a::AbstractArrayStyle{Any}, ::DefaultArrayStyle) = a\nBroadcastStyle(a::AbstractArrayStyle{N}, ::DefaultArrayStyle{N}) where N = a\nBroadcastStyle(a::AbstractArrayStyle{M}, ::DefaultArrayStyle{N}) where {M,N} =\n typeof(a)(Val(max(M, N)))","category":"page"},{"location":"manual/interfaces/","page":"接口","title":"接口","text":"除非你想要为两个或多个非 DefaultArrayStyle 的类型建立优先级,否则不需要编写二元 BroadcastStyle 规则。","category":"page"},{"location":"manual/interfaces/","page":"接口","title":"接口","text":"如果你的数组类型确实有固定的维度需求,那么你应该定义一个 AbstractArrayStyle 的子类型。例如,稀疏数组的代码中有以下定义:","category":"page"},{"location":"manual/interfaces/","page":"接口","title":"接口","text":"struct SparseVecStyle <: Broadcast.AbstractArrayStyle{1} end\nstruct SparseMatStyle <: Broadcast.AbstractArrayStyle{2} end\nBase.BroadcastStyle(::Type{<:SparseVector}) = SparseVecStyle()\nBase.BroadcastStyle(::Type{<:SparseMatrixCSC}) = SparseMatStyle()","category":"page"},{"location":"manual/interfaces/","page":"接口","title":"接口","text":"每当你定义一个 AbstractArrayStyle 的子类型,你还需要定义用于组合维度的规则,这通过为你的广播风格创建带有一个 Val(N) 参数的构造函数。例如:","category":"page"},{"location":"manual/interfaces/","page":"接口","title":"接口","text":"SparseVecStyle(::Val{0}) = SparseVecStyle()\nSparseVecStyle(::Val{1}) = SparseVecStyle()\nSparseVecStyle(::Val{2}) = SparseMatStyle()\nSparseVecStyle(::Val{N}) where N = Broadcast.DefaultArrayStyle{N}()","category":"page"},{"location":"manual/interfaces/","page":"接口","title":"接口","text":"这些规则表明 SparseVecStyle 与 0 维或 1 维数组的组合会产生另一个 SparseVecStyle,与 2 维数组的组合会产生 SparseMatStyle,而与维度更高的数组则回退到任意维密集矩阵的框架中。这些规则允许广播为产生一维或二维输出的操作保持其稀疏表示,但为任何其它维度生成 Array。","category":"page"}] } diff --git a/dev/stdlib/Artifacts/index.html b/dev/stdlib/Artifacts/index.html index f0642bb7..2f904592 100644 --- a/dev/stdlib/Artifacts/index.html +++ b/dev/stdlib/Artifacts/index.html @@ -9,4 +9,4 @@

        Artifacts

        Starting with Julia 1.6, the artifacts support has moved from Pkg.jl to Julia itself. Until proper documentation can be added here, you can learn more about artifacts in the Pkg.jl manual at https://julialang.github.io/Pkg.jl/v1/artifacts/.

        Julia 1.6

        Julia's artifacts API requires at least Julia 1.6. In Julia versions 1.3 to 1.5, you can use Pkg.Artifacts instead.

        Artifacts.artifact_metaFunction
        artifact_meta(name::String, artifacts_toml::String;
                       platform::AbstractPlatform = HostPlatform(),
                       pkg_uuid::Union{Base.UUID,Nothing}=nothing)

        Get metadata about a given artifact (identified by name) stored within the given (Julia)Artifacts.toml file. If the artifact is platform-specific, use platform to choose the most appropriate mapping. If none is found, return nothing.

        Julia 1.3

        This function requires at least Julia 1.3.

        Artifacts.artifact_hashFunction
        artifact_hash(name::String, artifacts_toml::String;
        -              platform::AbstractPlatform = HostPlatform())

        Thin wrapper around artifact_meta() to return the hash of the specified, platform- collapsed artifact. Returns nothing if no mapping can be found.

        Julia 1.3

        This function requires at least Julia 1.3.

        Artifacts.find_artifacts_tomlFunction
        find_artifacts_toml(path::String)

        Given the path to a .jl file, (such as the one returned by __source__.file in a macro context), find the (Julia)Artifacts.toml that is contained within the containing project (if it exists), otherwise return nothing.

        Julia 1.3

        This function requires at least Julia 1.3.

        Artifacts.@artifact_strMacro
        macro artifact_str(name)

        Return the on-disk path to an artifact. Automatically looks the artifact up by name in the project's (Julia)Artifacts.toml file. Throws an error on if the requested artifact is not present. If run in the REPL, searches for the toml file starting in the current directory, see find_artifacts_toml() for more.

        If the artifact is marked "lazy" and the package has using LazyArtifacts defined, the artifact will be downloaded on-demand with Pkg the first time this macro tries to compute the path. The files will then be left installed locally for later.

        If name contains a forward or backward slash, all elements after the first slash will be taken to be path names indexing into the artifact, allowing for an easy one-liner to access a single file/directory within an artifact. Example:

        ffmpeg_path = @artifact"FFMPEG/bin/ffmpeg"
        Julia 1.3

        This macro requires at least Julia 1.3.

        Julia 1.6

        Slash-indexing requires at least Julia 1.6.

        + platform::AbstractPlatform = HostPlatform())

        Thin wrapper around artifact_meta() to return the hash of the specified, platform- collapsed artifact. Returns nothing if no mapping can be found.

        Julia 1.3

        This function requires at least Julia 1.3.

        Artifacts.find_artifacts_tomlFunction
        find_artifacts_toml(path::String)

        Given the path to a .jl file, (such as the one returned by __source__.file in a macro context), find the (Julia)Artifacts.toml that is contained within the containing project (if it exists), otherwise return nothing.

        Julia 1.3

        This function requires at least Julia 1.3.

        Artifacts.@artifact_strMacro
        macro artifact_str(name)

        Return the on-disk path to an artifact. Automatically looks the artifact up by name in the project's (Julia)Artifacts.toml file. Throws an error on if the requested artifact is not present. If run in the REPL, searches for the toml file starting in the current directory, see find_artifacts_toml() for more.

        If the artifact is marked "lazy" and the package has using LazyArtifacts defined, the artifact will be downloaded on-demand with Pkg the first time this macro tries to compute the path. The files will then be left installed locally for later.

        If name contains a forward or backward slash, all elements after the first slash will be taken to be path names indexing into the artifact, allowing for an easy one-liner to access a single file/directory within an artifact. Example:

        ffmpeg_path = @artifact"FFMPEG/bin/ffmpeg"
        Julia 1.3

        This macro requires at least Julia 1.3.

        Julia 1.6

        Slash-indexing requires at least Julia 1.6.

        diff --git a/dev/stdlib/Base64/index.html b/dev/stdlib/Base64/index.html index d0f08e51..35bea6a3 100644 --- a/dev/stdlib/Base64/index.html +++ b/dev/stdlib/Base64/index.html @@ -40,4 +40,4 @@ 0x21 julia> String(b) -"Hello!"
        Base64.stringmimeFunction
        stringmime(mime, x; context=nothing)

        Returns an AbstractString containing the representation of x in the requested mime type. This is similar to repr(mime, x) except that binary data is base64-encoded as an ASCII string.

        The optional keyword argument context can be set to :key=>value pair or an IO or IOContext object whose attributes are used for the I/O stream passed to show.

        +"Hello!"
        Base64.stringmimeFunction
        stringmime(mime, x; context=nothing)

        Returns an AbstractString containing the representation of x in the requested mime type. This is similar to repr(mime, x) except that binary data is base64-encoded as an ASCII string.

        The optional keyword argument context can be set to :key=>value pair or an IO or IOContext object whose attributes are used for the I/O stream passed to show.

        diff --git a/dev/stdlib/CRC32c/index.html b/dev/stdlib/CRC32c/index.html index 3d0c4737..ebd3bf77 100644 --- a/dev/stdlib/CRC32c/index.html +++ b/dev/stdlib/CRC32c/index.html @@ -6,4 +6,4 @@ ga('create', 'UA-28835595-9', 'auto'); ga('send', 'pageview', {'page': location.pathname + location.search + location.hash}); -

        CRC32c

        CRC32c.crc32cFunction
        crc32c(data, crc::UInt32=0x00000000)

        Compute the CRC-32c checksum of the given data, which can be an Array{UInt8}, a contiguous subarray thereof, or a String. Optionally, you can pass a starting crc integer to be mixed in with the checksum. The crc parameter can be used to compute a checksum on data divided into chunks: performing crc32c(data2, crc32c(data1)) is equivalent to the checksum of [data1; data2]. (Technically, a little-endian checksum is computed.)

        There is also a method crc32c(io, nb, crc) to checksum nb bytes from a stream io, or crc32c(io, crc) to checksum all the remaining bytes. Hence you can do open(crc32c, filename) to checksum an entire file, or crc32c(seekstart(buf)) to checksum an IOBuffer without calling take!.

        For a String, note that the result is specific to the UTF-8 encoding (a different checksum would be obtained from a different Unicode encoding). To checksum an a::Array of some other bitstype, you can do crc32c(reinterpret(UInt8,a)), but note that the result may be endian-dependent.

        CRC32c.crc32cMethod
        crc32c(io::IO, [nb::Integer,] crc::UInt32=0x00000000)

        Read up to nb bytes from io and return the CRC-32c checksum, optionally mixed with a starting crc integer. If nb is not supplied, then io will be read until the end of the stream.

        +

        CRC32c

        CRC32c.crc32cFunction
        crc32c(data, crc::UInt32=0x00000000)

        Compute the CRC-32c checksum of the given data, which can be an Array{UInt8}, a contiguous subarray thereof, or a String. Optionally, you can pass a starting crc integer to be mixed in with the checksum. The crc parameter can be used to compute a checksum on data divided into chunks: performing crc32c(data2, crc32c(data1)) is equivalent to the checksum of [data1; data2]. (Technically, a little-endian checksum is computed.)

        There is also a method crc32c(io, nb, crc) to checksum nb bytes from a stream io, or crc32c(io, crc) to checksum all the remaining bytes. Hence you can do open(crc32c, filename) to checksum an entire file, or crc32c(seekstart(buf)) to checksum an IOBuffer without calling take!.

        For a String, note that the result is specific to the UTF-8 encoding (a different checksum would be obtained from a different Unicode encoding). To checksum an a::Array of some other bitstype, you can do crc32c(reinterpret(UInt8,a)), but note that the result may be endian-dependent.

        CRC32c.crc32cMethod
        crc32c(io::IO, [nb::Integer,] crc::UInt32=0x00000000)

        Read up to nb bytes from io and return the CRC-32c checksum, optionally mixed with a starting crc integer. If nb is not supplied, then io will be read until the end of the stream.

        diff --git a/dev/stdlib/Dates/index.html b/dev/stdlib/Dates/index.html index e2d54d1d..7a9bc76c 100644 --- a/dev/stdlib/Dates/index.html +++ b/dev/stdlib/Dates/index.html @@ -489,4 +489,4 @@ "2018-08-08T12:00:43.001"
        Dates.ISODateFormatConstant
        Dates.ISODateFormat

        Describes the ISO8601 formatting for a date. This is the default value for Dates.format of a Date.

        Example

        julia> Dates.format(Date(2018, 8, 8), ISODateFormat)
         "2018-08-08"
        Dates.ISOTimeFormatConstant
        Dates.ISOTimeFormat

        Describes the ISO8601 formatting for a time. This is the default value for Dates.format of a Time.

        Example

        julia> Dates.format(Time(12, 0, 43, 1), ISOTimeFormat)
         "12:00:43.001"
        Dates.RFC1123FormatConstant
        Dates.RFC1123Format

        Describes the RFC1123 formatting for a date and time.

        Example

        julia> Dates.format(DateTime(2018, 8, 8, 12, 0, 43, 1), RFC1123Format)
        -"Wed, 08 Aug 2018 12:00:43"
        • 1The notion of the UT second is actually quite fundamental. There are basically two different notions of time generally accepted, one based on the physical rotation of the earth (one full rotation = 1 day), the other based on the SI second (a fixed, constant value). These are radically different! Think about it, a "UT second", as defined relative to the rotation of the earth, may have a different absolute length depending on the day! Anyway, the fact that Date and DateTime are based on UT seconds is a simplifying, yet honest assumption so that things like leap seconds and all their complexity can be avoided. This basis of time is formally called UT or UT1. Basing types on the UT second basically means that every minute has 60 seconds and every day has 24 hours and leads to more natural calculations when working with calendar dates.
        +"Wed, 08 Aug 2018 12:00:43"
        • 1The notion of the UT second is actually quite fundamental. There are basically two different notions of time generally accepted, one based on the physical rotation of the earth (one full rotation = 1 day), the other based on the SI second (a fixed, constant value). These are radically different! Think about it, a "UT second", as defined relative to the rotation of the earth, may have a different absolute length depending on the day! Anyway, the fact that Date and DateTime are based on UT seconds is a simplifying, yet honest assumption so that things like leap seconds and all their complexity can be avoided. This basis of time is formally called UT or UT1. Basing types on the UT second basically means that every minute has 60 seconds and every day has 24 hours and leads to more natural calculations when working with calendar dates.
        diff --git a/dev/stdlib/DelimitedFiles/index.html b/dev/stdlib/DelimitedFiles/index.html index ff2e5b58..97fa4456 100644 --- a/dev/stdlib/DelimitedFiles/index.html +++ b/dev/stdlib/DelimitedFiles/index.html @@ -128,4 +128,4 @@ 3 7 4 8 -julia> rm("delim_file.txt") +julia> rm("delim_file.txt") diff --git a/dev/stdlib/Distributed/index.html b/dev/stdlib/Distributed/index.html index ccc65291..b5b735dd 100644 --- a/dev/stdlib/Distributed/index.html +++ b/dev/stdlib/Distributed/index.html @@ -150,4 +150,4 @@ end
        Distributed.@everywhereMacro
        @everywhere [procs()] expr

        Execute an expression under Main on all procs. Errors on any of the processes are collected into a CompositeException and thrown. For example:

        @everywhere bar = 1

        will define Main.bar on all current processes. Any processes added later (say with addprocs()) will not have the expression defined.

        Unlike @spawnat, @everywhere does not capture any local variables. Instead, local variables can be broadcast using interpolation:

        foo = 1
         @everywhere bar = $foo

        The optional argument procs allows specifying a subset of all processes to have execute the expression.

        Similar to calling remotecall_eval(Main, procs, expr), but with two extra features:

        - `using` and `import` statements run on the calling process first, to ensure
           packages are precompiled.
        -- The current source file path used by `include` is propagated to other processes.
        Distributed.clear!Method
        clear!(syms, pids=workers(); mod=Main)

        Clears global bindings in modules by initializing them to nothing. syms should be of type Symbol or a collection of Symbols . pids and mod identify the processes and the module in which global variables are to be reinitialized. Only those names found to be defined under mod are cleared.

        An exception is raised if a global constant is requested to be cleared.

        Distributed.remoteref_idFunction
        remoteref_id(r::AbstractRemoteRef) -> RRID

        Futures and RemoteChannels are identified by fields:

        • where - refers to the node where the underlying object/storage referred to by the reference actually exists.

        • whence - refers to the node the remote reference was created from. Note that this is different from the node where the underlying object referred to actually exists. For example calling RemoteChannel(2) from the master process would result in a where value of 2 and a whence value of 1.

        • id is unique across all references created from the worker specified by whence.

        Taken together, whence and id uniquely identify a reference across all workers.

        remoteref_id is a low-level API which returns a RRID object that wraps whence and id values of a remote reference.

        Distributed.channel_from_idFunction
        channel_from_id(id) -> c

        A low-level API which returns the backing AbstractChannel for an id returned by remoteref_id. The call is valid only on the node where the backing channel exists.

        Distributed.worker_id_from_socketFunction
        worker_id_from_socket(s) -> pid

        A low-level API which, given a IO connection or a Worker, returns the pid of the worker it is connected to. This is useful when writing custom serialize methods for a type, which optimizes the data written out depending on the receiving process id.

        Distributed.cluster_cookieMethod
        cluster_cookie(cookie) -> cookie

        Set the passed cookie as the cluster cookie, then returns it.

        Cluster Manager Interface

        This interface provides a mechanism to launch and manage Julia workers on different cluster environments. There are two types of managers present in Base: LocalManager, for launching additional workers on the same host, and SSHManager, for launching on remote hosts via ssh. TCP/IP sockets are used to connect and transport messages between processes. It is possible for Cluster Managers to provide a different transport.

        Distributed.ClusterManagerType
        ClusterManager

        Supertype for cluster managers, which control workers processes as a cluster. Cluster managers implement how workers can be added, removed and communicated with. SSHManager and LocalManager are subtypes of this.

        Distributed.WorkerConfigType
        WorkerConfig

        Type used by ClusterManagers to control workers added to their clusters. Some fields are used by all cluster managers to access a host:

        • io – the connection used to access the worker (a subtype of IO or Nothing)
        • host – the host address (either a String or Nothing)
        • port – the port on the host used to connect to the worker (either an Int or Nothing)

        Some are used by the cluster manager to add workers to an already-initialized host:

        • count – the number of workers to be launched on the host
        • exename – the path to the Julia executable on the host, defaults to "$(Sys.BINDIR)/julia" or "$(Sys.BINDIR)/julia-debug"
        • exeflags – flags to use when lauching Julia remotely

        The userdata field is used to store information for each worker by external managers.

        Some fields are used by SSHManager and similar managers:

        • tunneltrue (use tunneling), false (do not use tunneling), or nothing (use default for the manager)
        • multiplextrue (use SSH multiplexing for tunneling) or false
        • forward – the forwarding option used for -L option of ssh
        • bind_addr – the address on the remote host to bind to
        • sshflags – flags to use in establishing the SSH connection
        • max_parallel – the maximum number of workers to connect to in parallel on the host

        Some fields are used by both LocalManagers and SSHManagers:

        • connect_at – determines whether this is a worker-to-worker or driver-to-worker setup call
        • process – the process which will be connected (usually the manager will assign this during addprocs)
        • ospid – the process ID according to the host OS, used to interrupt worker processes
        • environ – private dictionary used to store temporary information by Local/SSH managers
        • ident – worker as identified by the ClusterManager
        • connect_idents – list of worker ids the worker must connect to if using a custom topology
        • enable_threaded_blastrue, false, or nothing, whether to use threaded BLAS or not on the workers
        Distributed.launchFunction
        launch(manager::ClusterManager, params::Dict, launched::Array, launch_ntfy::Condition)

        Implemented by cluster managers. For every Julia worker launched by this function, it should append a WorkerConfig entry to launched and notify launch_ntfy. The function MUST exit once all workers, requested by manager have been launched. params is a dictionary of all keyword arguments addprocs was called with.

        Distributed.manageFunction
        manage(manager::ClusterManager, id::Integer, config::WorkerConfig. op::Symbol)

        Implemented by cluster managers. It is called on the master process, during a worker's lifetime, with appropriate op values:

        • with :register/:deregister when a worker is added / removed from the Julia worker pool.
        • with :interrupt when interrupt(workers) is called. The ClusterManager should signal the appropriate worker with an interrupt signal.
        • with :finalize for cleanup purposes.
        Base.killMethod
        kill(manager::ClusterManager, pid::Int, config::WorkerConfig)

        Implemented by cluster managers. It is called on the master process, by rmprocs. It should cause the remote worker specified by pid to exit. kill(manager::ClusterManager.....) executes a remote exit() on pid.

        Sockets.connectMethod
        connect(manager::ClusterManager, pid::Int, config::WorkerConfig) -> (instrm::IO, outstrm::IO)

        Implemented by cluster managers using custom transports. It should establish a logical connection to worker with id pid, specified by config and return a pair of IO objects. Messages from pid to current process will be read off instrm, while messages to be sent to pid will be written to outstrm. The custom transport implementation must ensure that messages are delivered and received completely and in order. connect(manager::ClusterManager.....) sets up TCP/IP socket connections in-between workers.

        Distributed.init_workerFunction
        init_worker(cookie::AbstractString, manager::ClusterManager=DefaultClusterManager())

        Called by cluster managers implementing custom transports. It initializes a newly launched process as a worker. Command line argument --worker[=<cookie>] has the effect of initializing a process as a worker using TCP/IP sockets for transport. cookie is a cluster_cookie.

        Distributed.start_workerFunction
        start_worker([out::IO=stdout], cookie::AbstractString=readline(stdin); close_stdin::Bool=true, stderr_to_stdout::Bool=true)

        start_worker is an internal function which is the default entry point for worker processes connecting via TCP/IP. It sets up the process as a Julia cluster worker.

        host:port information is written to stream out (defaults to stdout).

        The function reads the cookie from stdin if required, and listens on a free port (or if specified, the port in the --bind-to command line option) and schedules tasks to process incoming TCP connections and requests. It also (optionally) closes stdin and redirects stderr to stdout.

        It does not return.

        Distributed.process_messagesFunction
        process_messages(r_stream::IO, w_stream::IO, incoming::Bool=true)

        Called by cluster managers using custom transports. It should be called when the custom transport implementation receives the first message from a remote worker. The custom transport must manage a logical connection to the remote worker and provide two IO objects, one for incoming messages and the other for messages addressed to the remote worker. If incoming is true, the remote peer initiated the connection. Whichever of the pair initiates the connection sends the cluster cookie and its Julia version number to perform the authentication handshake.

        See also cluster_cookie.

        Distributed.default_addprocs_paramsFunction
        default_addprocs_params(mgr::ClusterManager) -> Dict{Symbol, Any}

        Implemented by cluster managers. The default keyword parameters passed when calling addprocs(mgr). The minimal set of options is available by calling default_addprocs_params()

        +- The current source file path used by `include` is propagated to other processes.
        Distributed.clear!Method
        clear!(syms, pids=workers(); mod=Main)

        Clears global bindings in modules by initializing them to nothing. syms should be of type Symbol or a collection of Symbols . pids and mod identify the processes and the module in which global variables are to be reinitialized. Only those names found to be defined under mod are cleared.

        An exception is raised if a global constant is requested to be cleared.

        Distributed.remoteref_idFunction
        remoteref_id(r::AbstractRemoteRef) -> RRID

        Futures and RemoteChannels are identified by fields:

        • where - refers to the node where the underlying object/storage referred to by the reference actually exists.

        • whence - refers to the node the remote reference was created from. Note that this is different from the node where the underlying object referred to actually exists. For example calling RemoteChannel(2) from the master process would result in a where value of 2 and a whence value of 1.

        • id is unique across all references created from the worker specified by whence.

        Taken together, whence and id uniquely identify a reference across all workers.

        remoteref_id is a low-level API which returns a RRID object that wraps whence and id values of a remote reference.

        Distributed.channel_from_idFunction
        channel_from_id(id) -> c

        A low-level API which returns the backing AbstractChannel for an id returned by remoteref_id. The call is valid only on the node where the backing channel exists.

        Distributed.worker_id_from_socketFunction
        worker_id_from_socket(s) -> pid

        A low-level API which, given a IO connection or a Worker, returns the pid of the worker it is connected to. This is useful when writing custom serialize methods for a type, which optimizes the data written out depending on the receiving process id.

        Distributed.cluster_cookieMethod
        cluster_cookie(cookie) -> cookie

        Set the passed cookie as the cluster cookie, then returns it.

        Cluster Manager Interface

        This interface provides a mechanism to launch and manage Julia workers on different cluster environments. There are two types of managers present in Base: LocalManager, for launching additional workers on the same host, and SSHManager, for launching on remote hosts via ssh. TCP/IP sockets are used to connect and transport messages between processes. It is possible for Cluster Managers to provide a different transport.

        Distributed.ClusterManagerType
        ClusterManager

        Supertype for cluster managers, which control workers processes as a cluster. Cluster managers implement how workers can be added, removed and communicated with. SSHManager and LocalManager are subtypes of this.

        Distributed.WorkerConfigType
        WorkerConfig

        Type used by ClusterManagers to control workers added to their clusters. Some fields are used by all cluster managers to access a host:

        • io – the connection used to access the worker (a subtype of IO or Nothing)
        • host – the host address (either a String or Nothing)
        • port – the port on the host used to connect to the worker (either an Int or Nothing)

        Some are used by the cluster manager to add workers to an already-initialized host:

        • count – the number of workers to be launched on the host
        • exename – the path to the Julia executable on the host, defaults to "$(Sys.BINDIR)/julia" or "$(Sys.BINDIR)/julia-debug"
        • exeflags – flags to use when lauching Julia remotely

        The userdata field is used to store information for each worker by external managers.

        Some fields are used by SSHManager and similar managers:

        • tunneltrue (use tunneling), false (do not use tunneling), or nothing (use default for the manager)
        • multiplextrue (use SSH multiplexing for tunneling) or false
        • forward – the forwarding option used for -L option of ssh
        • bind_addr – the address on the remote host to bind to
        • sshflags – flags to use in establishing the SSH connection
        • max_parallel – the maximum number of workers to connect to in parallel on the host

        Some fields are used by both LocalManagers and SSHManagers:

        • connect_at – determines whether this is a worker-to-worker or driver-to-worker setup call
        • process – the process which will be connected (usually the manager will assign this during addprocs)
        • ospid – the process ID according to the host OS, used to interrupt worker processes
        • environ – private dictionary used to store temporary information by Local/SSH managers
        • ident – worker as identified by the ClusterManager
        • connect_idents – list of worker ids the worker must connect to if using a custom topology
        • enable_threaded_blastrue, false, or nothing, whether to use threaded BLAS or not on the workers
        Distributed.launchFunction
        launch(manager::ClusterManager, params::Dict, launched::Array, launch_ntfy::Condition)

        Implemented by cluster managers. For every Julia worker launched by this function, it should append a WorkerConfig entry to launched and notify launch_ntfy. The function MUST exit once all workers, requested by manager have been launched. params is a dictionary of all keyword arguments addprocs was called with.

        Distributed.manageFunction
        manage(manager::ClusterManager, id::Integer, config::WorkerConfig. op::Symbol)

        Implemented by cluster managers. It is called on the master process, during a worker's lifetime, with appropriate op values:

        • with :register/:deregister when a worker is added / removed from the Julia worker pool.
        • with :interrupt when interrupt(workers) is called. The ClusterManager should signal the appropriate worker with an interrupt signal.
        • with :finalize for cleanup purposes.
        Base.killMethod
        kill(manager::ClusterManager, pid::Int, config::WorkerConfig)

        Implemented by cluster managers. It is called on the master process, by rmprocs. It should cause the remote worker specified by pid to exit. kill(manager::ClusterManager.....) executes a remote exit() on pid.

        Sockets.connectMethod
        connect(manager::ClusterManager, pid::Int, config::WorkerConfig) -> (instrm::IO, outstrm::IO)

        Implemented by cluster managers using custom transports. It should establish a logical connection to worker with id pid, specified by config and return a pair of IO objects. Messages from pid to current process will be read off instrm, while messages to be sent to pid will be written to outstrm. The custom transport implementation must ensure that messages are delivered and received completely and in order. connect(manager::ClusterManager.....) sets up TCP/IP socket connections in-between workers.

        Distributed.init_workerFunction
        init_worker(cookie::AbstractString, manager::ClusterManager=DefaultClusterManager())

        Called by cluster managers implementing custom transports. It initializes a newly launched process as a worker. Command line argument --worker[=<cookie>] has the effect of initializing a process as a worker using TCP/IP sockets for transport. cookie is a cluster_cookie.

        Distributed.start_workerFunction
        start_worker([out::IO=stdout], cookie::AbstractString=readline(stdin); close_stdin::Bool=true, stderr_to_stdout::Bool=true)

        start_worker is an internal function which is the default entry point for worker processes connecting via TCP/IP. It sets up the process as a Julia cluster worker.

        host:port information is written to stream out (defaults to stdout).

        The function reads the cookie from stdin if required, and listens on a free port (or if specified, the port in the --bind-to command line option) and schedules tasks to process incoming TCP connections and requests. It also (optionally) closes stdin and redirects stderr to stdout.

        It does not return.

        Distributed.process_messagesFunction
        process_messages(r_stream::IO, w_stream::IO, incoming::Bool=true)

        Called by cluster managers using custom transports. It should be called when the custom transport implementation receives the first message from a remote worker. The custom transport must manage a logical connection to the remote worker and provide two IO objects, one for incoming messages and the other for messages addressed to the remote worker. If incoming is true, the remote peer initiated the connection. Whichever of the pair initiates the connection sends the cluster cookie and its Julia version number to perform the authentication handshake.

        See also cluster_cookie.

        Distributed.default_addprocs_paramsFunction
        default_addprocs_params(mgr::ClusterManager) -> Dict{Symbol, Any}

        Implemented by cluster managers. The default keyword parameters passed when calling addprocs(mgr). The minimal set of options is available by calling default_addprocs_params()

        diff --git a/dev/stdlib/FileWatching/index.html b/dev/stdlib/FileWatching/index.html index 16a612c1..5b223853 100644 --- a/dev/stdlib/FileWatching/index.html +++ b/dev/stdlib/FileWatching/index.html @@ -6,4 +6,4 @@ ga('create', 'UA-28835595-9', 'auto'); ga('send', 'pageview', {'page': location.pathname + location.search + location.hash}); -

        文件相关事件

        FileWatching.poll_fdFunction
        poll_fd(fd, timeout_s::Real=-1; readable=false, writable=false)

        Monitor a file descriptor fd for changes in the read or write availability, and with a timeout given by timeout_s seconds.

        The keyword arguments determine which of read and/or write status should be monitored; at least one of them must be set to true.

        The returned value is an object with boolean fields readable, writable, and timedout, giving the result of the polling.

        FileWatching.poll_fileFunction
        poll_file(path::AbstractString, interval_s::Real=5.007, timeout_s::Real=-1) -> (previous::StatStruct, current)

        Monitor a file for changes by polling every interval_s seconds until a change occurs or timeout_s seconds have elapsed. The interval_s should be a long period; the default is 5.007 seconds.

        Returns a pair of status objects (previous, current) when a change is detected. The previous status is always a StatStruct, but it may have all of the fields zeroed (indicating the file didn't previously exist, or wasn't previously accessible).

        The current status object may be a StatStruct, an EOFError (indicating the timeout elapsed), or some other Exception subtype (if the stat operation failed - for example, if the path does not exist).

        To determine when a file was modified, compare current isa StatStruct && mtime(prev) != mtime(current) to detect notification of changes. However, using watch_file for this operation is preferred, since it is more reliable and efficient, although in some situations it may not be available.

        FileWatching.watch_fileFunction
        watch_file(path::AbstractString, timeout_s::Real=-1)

        Watch file or directory path for changes until a change occurs or timeout_s seconds have elapsed.

        The returned value is an object with boolean fields changed, renamed, and timedout, giving the result of watching the file.

        This behavior of this function varies slightly across platforms. See https://nodejs.org/api/fs.html#fs_caveats for more detailed information.

        FileWatching.watch_folderFunction
        watch_folder(path::AbstractString, timeout_s::Real=-1)

        Watches a file or directory path for changes until a change has occurred or timeout_s seconds have elapsed.

        This will continuing tracking changes for path in the background until unwatch_folder is called on the same path.

        The returned value is an pair where the first field is the name of the changed file (if available) and the second field is an object with boolean fields changed, renamed, and timedout, giving the event.

        This behavior of this function varies slightly across platforms. See https://nodejs.org/api/fs.html#fs_caveats for more detailed information.

        FileWatching.unwatch_folderFunction
        unwatch_folder(path::AbstractString)

        Stop background tracking of changes for path. It is not recommended to do this while another task is waiting for watch_folder to return on the same path, as the result may be unpredictable.

        +

        文件相关事件

        FileWatching.poll_fdFunction
        poll_fd(fd, timeout_s::Real=-1; readable=false, writable=false)

        Monitor a file descriptor fd for changes in the read or write availability, and with a timeout given by timeout_s seconds.

        The keyword arguments determine which of read and/or write status should be monitored; at least one of them must be set to true.

        The returned value is an object with boolean fields readable, writable, and timedout, giving the result of the polling.

        FileWatching.poll_fileFunction
        poll_file(path::AbstractString, interval_s::Real=5.007, timeout_s::Real=-1) -> (previous::StatStruct, current)

        Monitor a file for changes by polling every interval_s seconds until a change occurs or timeout_s seconds have elapsed. The interval_s should be a long period; the default is 5.007 seconds.

        Returns a pair of status objects (previous, current) when a change is detected. The previous status is always a StatStruct, but it may have all of the fields zeroed (indicating the file didn't previously exist, or wasn't previously accessible).

        The current status object may be a StatStruct, an EOFError (indicating the timeout elapsed), or some other Exception subtype (if the stat operation failed - for example, if the path does not exist).

        To determine when a file was modified, compare current isa StatStruct && mtime(prev) != mtime(current) to detect notification of changes. However, using watch_file for this operation is preferred, since it is more reliable and efficient, although in some situations it may not be available.

        FileWatching.watch_fileFunction
        watch_file(path::AbstractString, timeout_s::Real=-1)

        Watch file or directory path for changes until a change occurs or timeout_s seconds have elapsed.

        The returned value is an object with boolean fields changed, renamed, and timedout, giving the result of watching the file.

        This behavior of this function varies slightly across platforms. See https://nodejs.org/api/fs.html#fs_caveats for more detailed information.

        FileWatching.watch_folderFunction
        watch_folder(path::AbstractString, timeout_s::Real=-1)

        Watches a file or directory path for changes until a change has occurred or timeout_s seconds have elapsed.

        This will continuing tracking changes for path in the background until unwatch_folder is called on the same path.

        The returned value is an pair where the first field is the name of the changed file (if available) and the second field is an object with boolean fields changed, renamed, and timedout, giving the event.

        This behavior of this function varies slightly across platforms. See https://nodejs.org/api/fs.html#fs_caveats for more detailed information.

        FileWatching.unwatch_folderFunction
        unwatch_folder(path::AbstractString)

        Stop background tracking of changes for path. It is not recommended to do this while another task is waiting for watch_folder to return on the same path, as the result may be unpredictable.

        diff --git a/dev/stdlib/Future/index.html b/dev/stdlib/Future/index.html index 7715ff3a..a1773135 100644 --- a/dev/stdlib/Future/index.html +++ b/dev/stdlib/Future/index.html @@ -6,4 +6,4 @@ ga('create', 'UA-28835595-9', 'auto'); ga('send', 'pageview', {'page': location.pathname + location.search + location.hash}); -

        Future

        The Future module implements future behavior of already existing functions, which will replace the current version in a future release of Julia.

        Future.copy!Function
        Future.copy!(dst, src) -> dst

        Copy src into dst.

        Julia 1.1

        This function has moved to Base with Julia 1.1, consider using copy!(dst, src) instead. Future.copy! will be deprecated in the future.

        Future.randjumpFunction
        randjump(r::MersenneTwister, steps::Integer) -> MersenneTwister

        Create an initialized MersenneTwister object, whose state is moved forward (without generating numbers) from r by steps steps. One such step corresponds to the generation of two Float64 numbers. For each different value of steps, a large polynomial has to be generated internally. One is already pre-computed for steps=big(10)^20.

        +

        Future

        The Future module implements future behavior of already existing functions, which will replace the current version in a future release of Julia.

        Future.copy!Function
        Future.copy!(dst, src) -> dst

        Copy src into dst.

        Julia 1.1

        This function has moved to Base with Julia 1.1, consider using copy!(dst, src) instead. Future.copy! will be deprecated in the future.

        Future.randjumpFunction
        randjump(r::MersenneTwister, steps::Integer) -> MersenneTwister

        Create an initialized MersenneTwister object, whose state is moved forward (without generating numbers) from r by steps steps. One such step corresponds to the generation of two Float64 numbers. For each different value of steps, a large polynomial has to be generated internally. One is already pre-computed for steps=big(10)^20.

        diff --git a/dev/stdlib/InteractiveUtils/index.html b/dev/stdlib/InteractiveUtils/index.html index 9aef6c85..1e3349d3 100644 --- a/dev/stdlib/InteractiveUtils/index.html +++ b/dev/stdlib/InteractiveUtils/index.html @@ -16,4 +16,4 @@ r"\bemacs\b.*\s(-nw|--no-window-system)\b", wait=true) do cmd, path, line `$cmd +$line $path` end
        Julia 1.4

        define_editor was introduced in Julia 1.4.

        InteractiveUtils.lessMethod
        less(file::AbstractString, [line::Integer])

        Show a file using the default pager, optionally providing a starting line number. Returns to the julia prompt when you quit the pager.

        InteractiveUtils.lessMethod
        less(function, [types])

        Show the definition of a function using the default pager, optionally specifying a tuple of types to indicate which method to see.

        InteractiveUtils.@whichMacro
        @which

        Applied to a function or macro call, it evaluates the arguments to the specified call, and returns the Method object for the method that would be called for those arguments. Applied to a variable, it returns the module in which the variable was bound. It calls out to the which function.

        See also: @less, @edit.

        InteractiveUtils.@functionlocMacro
        @functionloc

        Applied to a function or macro call, it evaluates the arguments to the specified call, and returns a tuple (filename,line) giving the location for the method that would be called for those arguments. It calls out to the functionloc function.

        InteractiveUtils.@code_typedMacro
        @code_typed

        Evaluates the arguments to the function or macro call, determines their types, and calls code_typed on the resulting expression. Use the optional argument optimize with

        @code_typed optimize=true foo(x)

        to control whether additional optimizations, such as inlining, are also applied.

        InteractiveUtils.code_warntypeFunction
        code_warntype([io::IO], f, types; debuginfo=:default)

        Prints lowered and type-inferred ASTs for the methods matching the given generic function and type signature to io which defaults to stdout. The ASTs are annotated in such a way as to cause "non-leaf" types to be emphasized (if color is available, displayed in red). This serves as a warning of potential type instability. Not all non-leaf types are particularly problematic for performance, so the results need to be used judiciously. In particular, unions containing either missing or nothing are displayed in yellow, since these are often intentional.

        Keyword argument debuginfo may be one of :source or :none (default), to specify the verbosity of code comments.

        See @code_warntype for more information.

        InteractiveUtils.code_llvmFunction
        code_llvm([io=stdout,], f, types; raw=false, dump_module=false, optimize=true, debuginfo=:default)

        Prints the LLVM bitcodes generated for running the method matching the given generic function and type signature to io.

        If the optimize keyword is unset, the code will be shown before LLVM optimizations. All metadata and dbg.* calls are removed from the printed bitcode. For the full IR, set the raw keyword to true. To dump the entire module that encapsulates the function (with declarations), set the dump_module keyword to true. Keyword argument debuginfo may be one of source (default) or none, to specify the verbosity of code comments.

        InteractiveUtils.@code_llvmMacro
        @code_llvm

        Evaluates the arguments to the function or macro call, determines their types, and calls code_llvm on the resulting expression. Set the optional keyword arguments raw, dump_module, debuginfo, optimize by putting them and their value before the function call, like this:

        @code_llvm raw=true dump_module=true debuginfo=:default f(x)
        -@code_llvm optimize=false f(x)

        optimize controls whether additional optimizations, such as inlining, are also applied. raw makes all metadata and dbg.* calls visible. debuginfo may be one of :source (default) or :none, to specify the verbosity of code comments. dump_module prints the entire module that encapsulates the function.

        InteractiveUtils.code_nativeFunction
        code_native([io=stdout,], f, types; syntax=:att, debuginfo=:default, binary=false, dump_module=true)

        Prints the native assembly instructions generated for running the method matching the given generic function and type signature to io.

        • Set assembly syntax by setting syntax to :att (default) for AT&T syntax or :intel for Intel syntax.
        • Specify verbosity of code comments by setting debuginfo to :source (default) or :none.
        • If binary is true, also print the binary machine code for each instruction precedented by an abbreviated address.
        • If dump_module is false, do not print metadata such as rodata or directives.

        See also: @code_native, code_llvm, code_typed and code_lowered

        InteractiveUtils.@code_nativeMacro
        @code_native

        Evaluates the arguments to the function or macro call, determines their types, and calls code_native on the resulting expression.

        Set any of the optional keyword arguments syntax, debuginfo, binary or dump_module by putting it before the function call, like this:

        @code_native syntax=:intel debuginfo=:default binary=true dump_module=false f(x)
        • Set assembly syntax by setting syntax to :att (default) for AT&T syntax or :intel for Intel syntax.
        • Specify verbosity of code comments by setting debuginfo to :source (default) or :none.
        • If binary is true, also print the binary machine code for each instruction precedented by an abbreviated address.
        • If dump_module is false, do not print metadata such as rodata or directives.

        See also: code_native, @code_llvm, @code_typed and @code_lowered

        InteractiveUtils.clipboardFunction
        clipboard(x)

        Send a printed form of x to the operating system clipboard ("copy").

        clipboard() -> AbstractString

        Return a string with the contents of the operating system clipboard ("paste").

        +@code_llvm optimize=false f(x)

        optimize controls whether additional optimizations, such as inlining, are also applied. raw makes all metadata and dbg.* calls visible. debuginfo may be one of :source (default) or :none, to specify the verbosity of code comments. dump_module prints the entire module that encapsulates the function.

        InteractiveUtils.code_nativeFunction
        code_native([io=stdout,], f, types; syntax=:att, debuginfo=:default, binary=false, dump_module=true)

        Prints the native assembly instructions generated for running the method matching the given generic function and type signature to io.

        • Set assembly syntax by setting syntax to :att (default) for AT&T syntax or :intel for Intel syntax.
        • Specify verbosity of code comments by setting debuginfo to :source (default) or :none.
        • If binary is true, also print the binary machine code for each instruction precedented by an abbreviated address.
        • If dump_module is false, do not print metadata such as rodata or directives.

        See also: @code_native, code_llvm, code_typed and code_lowered

        InteractiveUtils.@code_nativeMacro
        @code_native

        Evaluates the arguments to the function or macro call, determines their types, and calls code_native on the resulting expression.

        Set any of the optional keyword arguments syntax, debuginfo, binary or dump_module by putting it before the function call, like this:

        @code_native syntax=:intel debuginfo=:default binary=true dump_module=false f(x)
        • Set assembly syntax by setting syntax to :att (default) for AT&T syntax or :intel for Intel syntax.
        • Specify verbosity of code comments by setting debuginfo to :source (default) or :none.
        • If binary is true, also print the binary machine code for each instruction precedented by an abbreviated address.
        • If dump_module is false, do not print metadata such as rodata or directives.

        See also: code_native, @code_llvm, @code_typed and @code_lowered

        InteractiveUtils.clipboardFunction
        clipboard(x)

        Send a printed form of x to the operating system clipboard ("copy").

        clipboard() -> AbstractString

        Return a string with the contents of the operating system clipboard ("paste").

        diff --git a/dev/stdlib/LazyArtifacts/index.html b/dev/stdlib/LazyArtifacts/index.html index f43ebbc8..ea150e9a 100644 --- a/dev/stdlib/LazyArtifacts/index.html +++ b/dev/stdlib/LazyArtifacts/index.html @@ -6,4 +6,4 @@ ga('create', 'UA-28835595-9', 'auto'); ga('send', 'pageview', {'page': location.pathname + location.search + location.hash}); -

        Lazy Artifacts

        In order for a package to download artifacts lazily, LazyArtifacts must be explicitly listed as a dependency of that package.

        For further information on artifacts, see Artifacts.

        +

        Lazy Artifacts

        In order for a package to download artifacts lazily, LazyArtifacts must be explicitly listed as a dependency of that package.

        For further information on artifacts, see Artifacts.

        diff --git a/dev/stdlib/LibGit2/index.html b/dev/stdlib/LibGit2/index.html index d95fc0ce..0961f746 100644 --- a/dev/stdlib/LibGit2/index.html +++ b/dev/stdlib/LibGit2/index.html @@ -239,4 +239,4 @@ julia> LibGit2.url(remote) "https://github.com/JuliaLang/Example.jl"
        LibGit2.withFunction
        with(f::Function, obj)

        Resource management helper function. Applies f to obj, making sure to call close on obj after f successfully returns or throws an error. Ensures that allocated git resources are finalized as soon as they are no longer needed.

        LibGit2.with_warnFunction
        with_warn(f::Function, ::Type{T}, args...)

        Resource management helper function. Apply f to args, first constructing an instance of type T from args. Makes sure to call close on the resulting object after f successfully returns or throws an error. Ensures that allocated git resources are finalized as soon as they are no longer needed. If an error is thrown by f, a warning is shown containing the error.

        LibGit2.workdirFunction
        LibGit2.workdir(repo::GitRepo)

        Return the location of the working directory of repo. This will throw an error for bare repositories.

        Note

        This will typically be the parent directory of gitdir(repo), but can be different in some cases: e.g. if either the core.worktree configuration variable or the GIT_WORK_TREE environment variable is set.

        See also gitdir, path.

        LibGit2.GitObjectMethod
        (::Type{T})(te::GitTreeEntry) where T<:GitObject

        Get the git object to which te refers and return it as its actual type (the type entrytype would show), for instance a GitBlob or GitTag.

        Examples

        tree = LibGit2.GitTree(repo, "HEAD^{tree}")
         tree_entry = tree[1]
        -blob = LibGit2.GitBlob(tree_entry)
        LibGit2.isfilledFunction
        isfilled(cred::AbstractCredential) -> Bool

        Verifies that a credential is ready for use in authentication.

        LibGit2.CredentialPayloadType
        LibGit2.CredentialPayload

        Retains the state between multiple calls to the credential callback for the same URL. A CredentialPayload instance is expected to be reset! whenever it will be used with a different URL.

        LibGit2.approveFunction
        approve(payload::CredentialPayload; shred::Bool=true) -> Nothing

        Store the payload credential for re-use in a future authentication. Should only be called when authentication was successful.

        The shred keyword controls whether sensitive information in the payload credential field should be destroyed. Should only be set to false during testing.

        LibGit2.rejectFunction
        reject(payload::CredentialPayload; shred::Bool=true) -> Nothing

        Discard the payload credential from begin re-used in future authentication. Should only be called when authentication was unsuccessful.

        The shred keyword controls whether sensitive information in the payload credential field should be destroyed. Should only be set to false during testing.

        +blob = LibGit2.GitBlob(tree_entry)
        LibGit2.isfilledFunction
        isfilled(cred::AbstractCredential) -> Bool

        Verifies that a credential is ready for use in authentication.

        LibGit2.CredentialPayloadType
        LibGit2.CredentialPayload

        Retains the state between multiple calls to the credential callback for the same URL. A CredentialPayload instance is expected to be reset! whenever it will be used with a different URL.

        LibGit2.approveFunction
        approve(payload::CredentialPayload; shred::Bool=true) -> Nothing

        Store the payload credential for re-use in a future authentication. Should only be called when authentication was successful.

        The shred keyword controls whether sensitive information in the payload credential field should be destroyed. Should only be set to false during testing.

        LibGit2.rejectFunction
        reject(payload::CredentialPayload; shred::Bool=true) -> Nothing

        Discard the payload credential from begin re-used in future authentication. Should only be called when authentication was unsuccessful.

        The shred keyword controls whether sensitive information in the payload credential field should be destroyed. Should only be set to false during testing.

        diff --git a/dev/stdlib/Libdl/index.html b/dev/stdlib/Libdl/index.html index afeae5a2..07e9a2c6 100644 --- a/dev/stdlib/Libdl/index.html +++ b/dev/stdlib/Libdl/index.html @@ -18,4 +18,4 @@ ... do something finally dlclose(hdl) -end

        We define a dlclose() method that accepts a parameter of type Nothing, so that user code does not have to change its behavior for the case that library_name was not found.

        source
        Base.Libc.Libdl.dlpathFunction
        dlpath(handle::Ptr{Cvoid})

        Given a library handle from dlopen, return the full path.

        source
        dlpath(libname::Union{AbstractString, Symbol})

        Get the full path of the library libname.

        Example

        julia> dlpath("libjulia")
        source
        Base.Libc.Libdl.find_libraryFunction
        find_library(names, locations)

        Searches for the first library in names in the paths in the locations list, DL_LOAD_PATH, or system library paths (in that order) which can successfully be dlopen'd. On success, the return value will be one of the names (potentially prefixed by one of the paths in locations). This string can be assigned to a global const and used as the library name in future ccall's. On failure, it returns the empty string.

        source
        Base.DL_LOAD_PATHConstant
        DL_LOAD_PATH

        When calling dlopen, the paths in this list will be searched first, in order, before searching the system locations for a valid library handle.

        source
        +end

        We define a dlclose() method that accepts a parameter of type Nothing, so that user code does not have to change its behavior for the case that library_name was not found.

        source
        Base.Libc.Libdl.dlpathFunction
        dlpath(handle::Ptr{Cvoid})

        Given a library handle from dlopen, return the full path.

        source
        dlpath(libname::Union{AbstractString, Symbol})

        Get the full path of the library libname.

        Example

        julia> dlpath("libjulia")
        source
        Base.Libc.Libdl.find_libraryFunction
        find_library(names, locations)

        Searches for the first library in names in the paths in the locations list, DL_LOAD_PATH, or system library paths (in that order) which can successfully be dlopen'd. On success, the return value will be one of the names (potentially prefixed by one of the paths in locations). This string can be assigned to a global const and used as the library name in future ccall's. On failure, it returns the empty string.

        source
        Base.DL_LOAD_PATHConstant
        DL_LOAD_PATH

        When calling dlopen, the paths in this list will be searched first, in order, before searching the system locations for a valid library handle.

        source
        diff --git a/dev/stdlib/LinearAlgebra/index.html b/dev/stdlib/LinearAlgebra/index.html index ae7f102c..2a0eac83 100644 --- a/dev/stdlib/LinearAlgebra/index.html +++ b/dev/stdlib/LinearAlgebra/index.html @@ -2291,4 +2291,4 @@ iamax(dx)

        Find the index of the element of dx with the maximum absolute value. n is the length of dx, and incx is the stride. If n and incx are not provided, they assume default values of n=length(dx) and incx=stride1(dx).

        LinearAlgebra.BLAS.ger!Function
        ger!(alpha, x, y, A)

        Rank-1 update of the matrix A with vectors x and y as alpha*x*y' + A.

        LinearAlgebra.BLAS.syr!Function
        syr!(uplo, alpha, x, A)

        Rank-1 update of the symmetric matrix A with vector x as alpha*x*transpose(x) + A. uplo controls which triangle of A is updated. Returns A.

        LinearAlgebra.BLAS.syrk!Function
        syrk!(uplo, trans, alpha, A, beta, C)

        Rank-k update of the symmetric matrix C as alpha*A*transpose(A) + beta*C or alpha*transpose(A)*A + beta*C according to trans. Only the uplo triangle of C is used. Returns C.

        LinearAlgebra.BLAS.syrkFunction
        syrk(uplo, trans, alpha, A)

        Returns either the upper triangle or the lower triangle of A, according to uplo, of alpha*A*transpose(A) or alpha*transpose(A)*A, according to trans.

        LinearAlgebra.BLAS.syr2k!Function
        syr2k!(uplo, trans, alpha, A, B, beta, C)

        Rank-2k update of the symmetric matrix C as alpha*A*transpose(B) + alpha*B*transpose(A) + beta*C or alpha*transpose(A)*B + alpha*transpose(B)*A + beta*C according to trans. Only the uplo triangle of C is used. Returns C.

        LinearAlgebra.BLAS.syr2kFunction
        syr2k(uplo, trans, alpha, A, B)

        Returns the uplo triangle of alpha*A*transpose(B) + alpha*B*transpose(A) or alpha*transpose(A)*B + alpha*transpose(B)*A, according to trans.

        syr2k(uplo, trans, A, B)

        Returns the uplo triangle of A*transpose(B) + B*transpose(A) or transpose(A)*B + transpose(B)*A, according to trans.

        LinearAlgebra.BLAS.her!Function
        her!(uplo, alpha, x, A)

        Methods for complex arrays only. Rank-1 update of the Hermitian matrix A with vector x as alpha*x*x' + A. uplo controls which triangle of A is updated. Returns A.

        LinearAlgebra.BLAS.herk!Function
        herk!(uplo, trans, alpha, A, beta, C)

        Methods for complex arrays only. Rank-k update of the Hermitian matrix C as alpha*A*A' + beta*C or alpha*A'*A + beta*C according to trans. Only the uplo triangle of C is updated. Returns C.

        LinearAlgebra.BLAS.herkFunction
        herk(uplo, trans, alpha, A)

        Methods for complex arrays only. Returns the uplo triangle of alpha*A*A' or alpha*A'*A, according to trans.

        LinearAlgebra.BLAS.her2k!Function
        her2k!(uplo, trans, alpha, A, B, beta, C)

        Rank-2k update of the Hermitian matrix C as alpha*A*B' + alpha*B*A' + beta*C or alpha*A'*B + alpha*B'*A + beta*C according to trans. The scalar beta has to be real. Only the uplo triangle of C is used. Returns C.

        LinearAlgebra.BLAS.her2kFunction
        her2k(uplo, trans, alpha, A, B)

        Returns the uplo triangle of alpha*A*B' + alpha*B*A' or alpha*A'*B + alpha*B'*A, according to trans.

        her2k(uplo, trans, A, B)

        Returns the uplo triangle of A*B' + B*A' or A'*B + B'*A, according to trans.

        LinearAlgebra.BLAS.gbmv!Function
        gbmv!(trans, m, kl, ku, alpha, A, x, beta, y)

        Update vector y as alpha*A*x + beta*y or alpha*A'*x + beta*y according to trans. The matrix A is a general band matrix of dimension m by size(A,2) with kl sub-diagonals and ku super-diagonals. alpha and beta are scalars. Return the updated y.

        LinearAlgebra.BLAS.gbmvFunction
        gbmv(trans, m, kl, ku, alpha, A, x)

        Return alpha*A*x or alpha*A'*x according to trans. The matrix A is a general band matrix of dimension m by size(A,2) with kl sub-diagonals and ku super-diagonals, and alpha is a scalar.

        LinearAlgebra.BLAS.sbmv!Function
        sbmv!(uplo, k, alpha, A, x, beta, y)

        Update vector y as alpha*A*x + beta*y where A is a symmetric band matrix of order size(A,2) with k super-diagonals stored in the argument A. The storage layout for A is described the reference BLAS module, level-2 BLAS at http://www.netlib.org/lapack/explore-html/. Only the uplo triangle of A is used.

        Return the updated y.

        LinearAlgebra.BLAS.sbmvMethod
        sbmv(uplo, k, alpha, A, x)

        Return alpha*A*x where A is a symmetric band matrix of order size(A,2) with k super-diagonals stored in the argument A. Only the uplo triangle of A is used.

        LinearAlgebra.BLAS.sbmvMethod
        sbmv(uplo, k, A, x)

        Return A*x where A is a symmetric band matrix of order size(A,2) with k super-diagonals stored in the argument A. Only the uplo triangle of A is used.

        LinearAlgebra.BLAS.gemm!Function
        gemm!(tA, tB, alpha, A, B, beta, C)

        Update C as alpha*A*B + beta*C or the other three variants according to tA and tB. Return the updated C.

        LinearAlgebra.BLAS.gemmMethod
        gemm(tA, tB, alpha, A, B)

        Return alpha*A*B or the other three variants according to tA and tB.

        LinearAlgebra.BLAS.gemv!Function
        gemv!(tA, alpha, A, x, beta, y)

        Update the vector y as alpha*A*x + beta*y or alpha*A'x + beta*y according to tA. alpha and beta are scalars. Return the updated y.

        LinearAlgebra.BLAS.symm!Function
        symm!(side, ul, alpha, A, B, beta, C)

        Update C as alpha*A*B + beta*C or alpha*B*A + beta*C according to side. A is assumed to be symmetric. Only the ul triangle of A is used. Return the updated C.

        LinearAlgebra.BLAS.symmMethod
        symm(side, ul, alpha, A, B)

        Return alpha*A*B or alpha*B*A according to side. A is assumed to be symmetric. Only the ul triangle of A is used.

        LinearAlgebra.BLAS.symmMethod
        symm(side, ul, A, B)

        Return A*B or B*A according to side. A is assumed to be symmetric. Only the ul triangle of A is used.

        LinearAlgebra.BLAS.symv!Function
        symv!(ul, alpha, A, x, beta, y)

        Update the vector y as alpha*A*x + beta*y. A is assumed to be symmetric. Only the ul triangle of A is used. alpha and beta are scalars. Return the updated y.

        LinearAlgebra.BLAS.symvMethod
        symv(ul, alpha, A, x)

        Return alpha*A*x. A is assumed to be symmetric. Only the ul triangle of A is used. alpha is a scalar.

        LinearAlgebra.BLAS.hemm!Function
        hemm!(side, ul, alpha, A, B, beta, C)

        Update C as alpha*A*B + beta*C or alpha*B*A + beta*C according to side. A is assumed to be Hermitian. Only the ul triangle of A is used. Return the updated C.

        LinearAlgebra.BLAS.hemmMethod
        hemm(side, ul, alpha, A, B)

        Return alpha*A*B or alpha*B*A according to side. A is assumed to be Hermitian. Only the ul triangle of A is used.

        LinearAlgebra.BLAS.hemmMethod
        hemm(side, ul, A, B)

        Return A*B or B*A according to side. A is assumed to be Hermitian. Only the ul triangle of A is used.

        LinearAlgebra.BLAS.hemv!Function
        hemv!(ul, alpha, A, x, beta, y)

        Update the vector y as alpha*A*x + beta*y. A is assumed to be Hermitian. Only the ul triangle of A is used. alpha and beta are scalars. Return the updated y.

        LinearAlgebra.BLAS.hemvMethod
        hemv(ul, alpha, A, x)

        Return alpha*A*x. A is assumed to be Hermitian. Only the ul triangle of A is used. alpha is a scalar.

        LinearAlgebra.BLAS.trmm!Function
        trmm!(side, ul, tA, dA, alpha, A, B)

        Update B as alpha*A*B or one of the other three variants determined by side and tA. Only the ul triangle of A is used. dA determines if the diagonal values are read or are assumed to be all ones. Returns the updated B.

        LinearAlgebra.BLAS.trmmFunction
        trmm(side, ul, tA, dA, alpha, A, B)

        Returns alpha*A*B or one of the other three variants determined by side and tA. Only the ul triangle of A is used. dA determines if the diagonal values are read or are assumed to be all ones.

        LinearAlgebra.BLAS.trsm!Function
        trsm!(side, ul, tA, dA, alpha, A, B)

        Overwrite B with the solution to A*X = alpha*B or one of the other three variants determined by side and tA. Only the ul triangle of A is used. dA determines if the diagonal values are read or are assumed to be all ones. Returns the updated B.

        LinearAlgebra.BLAS.trsmFunction
        trsm(side, ul, tA, dA, alpha, A, B)

        Return the solution to A*X = alpha*B or one of the other three variants determined by determined by side and tA. Only the ul triangle of A is used. dA determines if the diagonal values are read or are assumed to be all ones.

        LinearAlgebra.BLAS.trmv!Function
        trmv!(ul, tA, dA, A, b)

        Return op(A)*b, where op is determined by tA. Only the ul triangle of A is used. dA determines if the diagonal values are read or are assumed to be all ones. The multiplication occurs in-place on b.

        LinearAlgebra.BLAS.trmvFunction
        trmv(ul, tA, dA, A, b)

        Return op(A)*b, where op is determined by tA. Only the ul triangle of A is used. dA determines if the diagonal values are read or are assumed to be all ones.

        LinearAlgebra.BLAS.trsv!Function
        trsv!(ul, tA, dA, A, b)

        Overwrite b with the solution to A*x = b or one of the other two variants determined by tA and ul. dA determines if the diagonal values are read or are assumed to be all ones. Return the updated b.

        LinearAlgebra.BLAS.trsvFunction
        trsv(ul, tA, dA, A, b)

        Return the solution to A*x = b or one of the other two variants determined by tA and ul. dA determines if the diagonal values are read or are assumed to be all ones.

        LinearAlgebra.BLAS.set_num_threadsFunction
        set_num_threads(n::Integer)
         set_num_threads(::Nothing)

        Set the number of threads the BLAS library should use equal to n::Integer.

        Also accepts nothing, in which case julia tries to guess the default number of threads. Passing nothing is discouraged and mainly exists for historical reasons.

        LAPACK functions

        LinearAlgebra.LAPACK provides wrappers for some of the LAPACK functions for linear algebra. Those functions that overwrite one of the input arrays have names ending in '!'.

        Usually a function has 4 methods defined, one each for Float64, Float32, ComplexF64 and ComplexF32 arrays.

        Note that the LAPACK API provided by Julia can and will change in the future. Since this API is not user-facing, there is no commitment to support/deprecate this specific set of functions in future releases.

        LinearAlgebra.LAPACK.gbtrf!Function
        gbtrf!(kl, ku, m, AB) -> (AB, ipiv)

        Compute the LU factorization of a banded matrix AB. kl is the first subdiagonal containing a nonzero band, ku is the last superdiagonal containing one, and m is the first dimension of the matrix AB. Returns the LU factorization in-place and ipiv, the vector of pivots used.

        LinearAlgebra.LAPACK.gbtrs!Function
        gbtrs!(trans, kl, ku, m, AB, ipiv, B)

        Solve the equation AB * X = B. trans determines the orientation of AB. It may be N (no transpose), T (transpose), or C (conjugate transpose). kl is the first subdiagonal containing a nonzero band, ku is the last superdiagonal containing one, and m is the first dimension of the matrix AB. ipiv is the vector of pivots returned from gbtrf!. Returns the vector or matrix X, overwriting B in-place.

        LinearAlgebra.LAPACK.gebal!Function
        gebal!(job, A) -> (ilo, ihi, scale)

        Balance the matrix A before computing its eigensystem or Schur factorization. job can be one of N (A will not be permuted or scaled), P (A will only be permuted), S (A will only be scaled), or B (A will be both permuted and scaled). Modifies A in-place and returns ilo, ihi, and scale. If permuting was turned on, A[i,j] = 0 if j > i and 1 < j < ilo or j > ihi. scale contains information about the scaling/permutations performed.

        LinearAlgebra.LAPACK.gebak!Function
        gebak!(job, side, ilo, ihi, scale, V)

        Transform the eigenvectors V of a matrix balanced using gebal! to the unscaled/unpermuted eigenvectors of the original matrix. Modifies V in-place. side can be L (left eigenvectors are transformed) or R (right eigenvectors are transformed).

        LinearAlgebra.LAPACK.gebrd!Function
        gebrd!(A) -> (A, d, e, tauq, taup)

        Reduce A in-place to bidiagonal form A = QBP'. Returns A, containing the bidiagonal matrix B; d, containing the diagonal elements of B; e, containing the off-diagonal elements of B; tauq, containing the elementary reflectors representing Q; and taup, containing the elementary reflectors representing P.

        LinearAlgebra.LAPACK.gelqf!Function
        gelqf!(A, tau)

        Compute the LQ factorization of A, A = LQ. tau contains scalars which parameterize the elementary reflectors of the factorization. tau must have length greater than or equal to the smallest dimension of A.

        Returns A and tau modified in-place.

        gelqf!(A) -> (A, tau)

        Compute the LQ factorization of A, A = LQ.

        Returns A, modified in-place, and tau, which contains scalars which parameterize the elementary reflectors of the factorization.

        LinearAlgebra.LAPACK.geqlf!Function
        geqlf!(A, tau)

        Compute the QL factorization of A, A = QL. tau contains scalars which parameterize the elementary reflectors of the factorization. tau must have length greater than or equal to the smallest dimension of A.

        Returns A and tau modified in-place.

        geqlf!(A) -> (A, tau)

        Compute the QL factorization of A, A = QL.

        Returns A, modified in-place, and tau, which contains scalars which parameterize the elementary reflectors of the factorization.

        LinearAlgebra.LAPACK.geqrf!Function
        geqrf!(A, tau)

        Compute the QR factorization of A, A = QR. tau contains scalars which parameterize the elementary reflectors of the factorization. tau must have length greater than or equal to the smallest dimension of A.

        Returns A and tau modified in-place.

        geqrf!(A) -> (A, tau)

        Compute the QR factorization of A, A = QR.

        Returns A, modified in-place, and tau, which contains scalars which parameterize the elementary reflectors of the factorization.

        LinearAlgebra.LAPACK.geqp3!Function
        geqp3!(A, [jpvt, tau]) -> (A, tau, jpvt)

        Compute the pivoted QR factorization of A, AP = QR using BLAS level 3. P is a pivoting matrix, represented by jpvt. tau stores the elementary reflectors. The arguments jpvt and tau are optional and allow for passing preallocated arrays. When passed, jpvt must have length greater than or equal to n if A is an (m x n) matrix and tau must have length greater than or equal to the smallest dimension of A.

        A, jpvt, and tau are modified in-place.

        LinearAlgebra.LAPACK.gerqf!Function
        gerqf!(A, tau)

        Compute the RQ factorization of A, A = RQ. tau contains scalars which parameterize the elementary reflectors of the factorization. tau must have length greater than or equal to the smallest dimension of A.

        Returns A and tau modified in-place.

        gerqf!(A) -> (A, tau)

        Compute the RQ factorization of A, A = RQ.

        Returns A, modified in-place, and tau, which contains scalars which parameterize the elementary reflectors of the factorization.

        LinearAlgebra.LAPACK.geqrt!Function
        geqrt!(A, T)

        Compute the blocked QR factorization of A, A = QR. T contains upper triangular block reflectors which parameterize the elementary reflectors of the factorization. The first dimension of T sets the block size and it must be between 1 and n. The second dimension of T must equal the smallest dimension of A.

        Returns A and T modified in-place.

        geqrt!(A, nb) -> (A, T)

        Compute the blocked QR factorization of A, A = QR. nb sets the block size and it must be between 1 and n, the second dimension of A.

        Returns A, modified in-place, and T, which contains upper triangular block reflectors which parameterize the elementary reflectors of the factorization.

        LinearAlgebra.LAPACK.geqrt3!Function
        geqrt3!(A, T)

        Recursively computes the blocked QR factorization of A, A = QR. T contains upper triangular block reflectors which parameterize the elementary reflectors of the factorization. The first dimension of T sets the block size and it must be between 1 and n. The second dimension of T must equal the smallest dimension of A.

        Returns A and T modified in-place.

        geqrt3!(A) -> (A, T)

        Recursively computes the blocked QR factorization of A, A = QR.

        Returns A, modified in-place, and T, which contains upper triangular block reflectors which parameterize the elementary reflectors of the factorization.

        LinearAlgebra.LAPACK.getrf!Function
        getrf!(A) -> (A, ipiv, info)

        Compute the pivoted LU factorization of A, A = LU.

        Returns A, modified in-place, ipiv, the pivoting information, and an info code which indicates success (info = 0), a singular value in U (info = i, in which case U[i,i] is singular), or an error code (info < 0).

        LinearAlgebra.LAPACK.tzrzf!Function
        tzrzf!(A) -> (A, tau)

        Transforms the upper trapezoidal matrix A to upper triangular form in-place. Returns A and tau, the scalar parameters for the elementary reflectors of the transformation.

        LinearAlgebra.LAPACK.ormrz!Function
        ormrz!(side, trans, A, tau, C)

        Multiplies the matrix C by Q from the transformation supplied by tzrzf!. Depending on side or trans the multiplication can be left-sided (side = L, Q*C) or right-sided (side = R, C*Q) and Q can be unmodified (trans = N), transposed (trans = T), or conjugate transposed (trans = C). Returns matrix C which is modified in-place with the result of the multiplication.

        LinearAlgebra.LAPACK.gels!Function
        gels!(trans, A, B) -> (F, B, ssr)

        Solves the linear equation A * X = B, transpose(A) * X = B, or adjoint(A) * X = B using a QR or LQ factorization. Modifies the matrix/vector B in place with the solution. A is overwritten with its QR or LQ factorization. trans may be one of N (no modification), T (transpose), or C (conjugate transpose). gels! searches for the minimum norm/least squares solution. A may be under or over determined. The solution is returned in B.

        LinearAlgebra.LAPACK.gesv!Function
        gesv!(A, B) -> (B, A, ipiv)

        Solves the linear equation A * X = B where A is a square matrix using the LU factorization of A. A is overwritten with its LU factorization and B is overwritten with the solution X. ipiv contains the pivoting information for the LU factorization of A.

        LinearAlgebra.LAPACK.getrs!Function
        getrs!(trans, A, ipiv, B)

        Solves the linear equation A * X = B, transpose(A) * X = B, or adjoint(A) * X = B for square A. Modifies the matrix/vector B in place with the solution. A is the LU factorization from getrf!, with ipiv the pivoting information. trans may be one of N (no modification), T (transpose), or C (conjugate transpose).

        LinearAlgebra.LAPACK.getri!Function
        getri!(A, ipiv)

        Computes the inverse of A, using its LU factorization found by getrf!. ipiv is the pivot information output and A contains the LU factorization of getrf!. A is overwritten with its inverse.

        LinearAlgebra.LAPACK.gesvx!Function
        gesvx!(fact, trans, A, AF, ipiv, equed, R, C, B) -> (X, equed, R, C, B, rcond, ferr, berr, work)

        Solves the linear equation A * X = B (trans = N), transpose(A) * X = B (trans = T), or adjoint(A) * X = B (trans = C) using the LU factorization of A. fact may be E, in which case A will be equilibrated and copied to AF; F, in which case AF and ipiv from a previous LU factorization are inputs; or N, in which case A will be copied to AF and then factored. If fact = F, equed may be N, meaning A has not been equilibrated; R, meaning A was multiplied by Diagonal(R) from the left; C, meaning A was multiplied by Diagonal(C) from the right; or B, meaning A was multiplied by Diagonal(R) from the left and Diagonal(C) from the right. If fact = F and equed = R or B the elements of R must all be positive. If fact = F and equed = C or B the elements of C must all be positive.

        Returns the solution X; equed, which is an output if fact is not N, and describes the equilibration that was performed; R, the row equilibration diagonal; C, the column equilibration diagonal; B, which may be overwritten with its equilibrated form Diagonal(R)*B (if trans = N and equed = R,B) or Diagonal(C)*B (if trans = T,C and equed = C,B); rcond, the reciprocal condition number of A after equilbrating; ferr, the forward error bound for each solution vector in X; berr, the forward error bound for each solution vector in X; and work, the reciprocal pivot growth factor.

        gesvx!(A, B)

        The no-equilibration, no-transpose simplification of gesvx!.

        LinearAlgebra.LAPACK.gelsd!Function
        gelsd!(A, B, rcond) -> (B, rnk)

        Computes the least norm solution of A * X = B by finding the SVD factorization of A, then dividing-and-conquering the problem. B is overwritten with the solution X. Singular values below rcond will be treated as zero. Returns the solution in B and the effective rank of A in rnk.

        LinearAlgebra.LAPACK.gelsy!Function
        gelsy!(A, B, rcond) -> (B, rnk)

        Computes the least norm solution of A * X = B by finding the full QR factorization of A, then dividing-and-conquering the problem. B is overwritten with the solution X. Singular values below rcond will be treated as zero. Returns the solution in B and the effective rank of A in rnk.

        LinearAlgebra.LAPACK.gglse!Function
        gglse!(A, c, B, d) -> (X,res)

        Solves the equation A * x = c where x is subject to the equality constraint B * x = d. Uses the formula ||c - A*x||^2 = 0 to solve. Returns X and the residual sum-of-squares.

        LinearAlgebra.LAPACK.geev!Function
        geev!(jobvl, jobvr, A) -> (W, VL, VR)

        Finds the eigensystem of A. If jobvl = N, the left eigenvectors of A aren't computed. If jobvr = N, the right eigenvectors of A aren't computed. If jobvl = V or jobvr = V, the corresponding eigenvectors are computed. Returns the eigenvalues in W, the right eigenvectors in VR, and the left eigenvectors in VL.

        LinearAlgebra.LAPACK.gesdd!Function
        gesdd!(job, A) -> (U, S, VT)

        Finds the singular value decomposition of A, A = U * S * V', using a divide and conquer approach. If job = A, all the columns of U and the rows of V' are computed. If job = N, no columns of U or rows of V' are computed. If job = O, A is overwritten with the columns of (thin) U and the rows of (thin) V'. If job = S, the columns of (thin) U and the rows of (thin) V' are computed and returned separately.

        LinearAlgebra.LAPACK.gesvd!Function
        gesvd!(jobu, jobvt, A) -> (U, S, VT)

        Finds the singular value decomposition of A, A = U * S * V'. If jobu = A, all the columns of U are computed. If jobvt = A all the rows of V' are computed. If jobu = N, no columns of U are computed. If jobvt = N no rows of V' are computed. If jobu = O, A is overwritten with the columns of (thin) U. If jobvt = O, A is overwritten with the rows of (thin) V'. If jobu = S, the columns of (thin) U are computed and returned separately. If jobvt = S the rows of (thin) V' are computed and returned separately. jobu and jobvt can't both be O.

        Returns U, S, and Vt, where S are the singular values of A.

        LinearAlgebra.LAPACK.ggsvd!Function
        ggsvd!(jobu, jobv, jobq, A, B) -> (U, V, Q, alpha, beta, k, l, R)

        Finds the generalized singular value decomposition of A and B, U'*A*Q = D1*R and V'*B*Q = D2*R. D1 has alpha on its diagonal and D2 has beta on its diagonal. If jobu = U, the orthogonal/unitary matrix U is computed. If jobv = V the orthogonal/unitary matrix V is computed. If jobq = Q, the orthogonal/unitary matrix Q is computed. If jobu, jobv or jobq is N, that matrix is not computed. This function is only available in LAPACK versions prior to 3.6.0.

        LinearAlgebra.LAPACK.ggsvd3!Function
        ggsvd3!(jobu, jobv, jobq, A, B) -> (U, V, Q, alpha, beta, k, l, R)

        Finds the generalized singular value decomposition of A and B, U'*A*Q = D1*R and V'*B*Q = D2*R. D1 has alpha on its diagonal and D2 has beta on its diagonal. If jobu = U, the orthogonal/unitary matrix U is computed. If jobv = V the orthogonal/unitary matrix V is computed. If jobq = Q, the orthogonal/unitary matrix Q is computed. If jobu, jobv, or jobq is N, that matrix is not computed. This function requires LAPACK 3.6.0.

        LinearAlgebra.LAPACK.geevx!Function
        geevx!(balanc, jobvl, jobvr, sense, A) -> (A, w, VL, VR, ilo, ihi, scale, abnrm, rconde, rcondv)

        Finds the eigensystem of A with matrix balancing. If jobvl = N, the left eigenvectors of A aren't computed. If jobvr = N, the right eigenvectors of A aren't computed. If jobvl = V or jobvr = V, the corresponding eigenvectors are computed. If balanc = N, no balancing is performed. If balanc = P, A is permuted but not scaled. If balanc = S, A is scaled but not permuted. If balanc = B, A is permuted and scaled. If sense = N, no reciprocal condition numbers are computed. If sense = E, reciprocal condition numbers are computed for the eigenvalues only. If sense = V, reciprocal condition numbers are computed for the right eigenvectors only. If sense = B, reciprocal condition numbers are computed for the right eigenvectors and the eigenvectors. If sense = E,B, the right and left eigenvectors must be computed.

        LinearAlgebra.LAPACK.ggev!Function
        ggev!(jobvl, jobvr, A, B) -> (alpha, beta, vl, vr)

        Finds the generalized eigendecomposition of A and B. If jobvl = N, the left eigenvectors aren't computed. If jobvr = N, the right eigenvectors aren't computed. If jobvl = V or jobvr = V, the corresponding eigenvectors are computed.

        LinearAlgebra.LAPACK.gtsv!Function
        gtsv!(dl, d, du, B)

        Solves the equation A * X = B where A is a tridiagonal matrix with dl on the subdiagonal, d on the diagonal, and du on the superdiagonal.

        Overwrites B with the solution X and returns it.

        LinearAlgebra.LAPACK.gttrf!Function
        gttrf!(dl, d, du) -> (dl, d, du, du2, ipiv)

        Finds the LU factorization of a tridiagonal matrix with dl on the subdiagonal, d on the diagonal, and du on the superdiagonal.

        Modifies dl, d, and du in-place and returns them and the second superdiagonal du2 and the pivoting vector ipiv.

        LinearAlgebra.LAPACK.gttrs!Function
        gttrs!(trans, dl, d, du, du2, ipiv, B)

        Solves the equation A * X = B (trans = N), transpose(A) * X = B (trans = T), or adjoint(A) * X = B (trans = C) using the LU factorization computed by gttrf!. B is overwritten with the solution X.

        LinearAlgebra.LAPACK.orglq!Function
        orglq!(A, tau, k = length(tau))

        Explicitly finds the matrix Q of a LQ factorization after calling gelqf! on A. Uses the output of gelqf!. A is overwritten by Q.

        LinearAlgebra.LAPACK.orgqr!Function
        orgqr!(A, tau, k = length(tau))

        Explicitly finds the matrix Q of a QR factorization after calling geqrf! on A. Uses the output of geqrf!. A is overwritten by Q.

        LinearAlgebra.LAPACK.orgql!Function
        orgql!(A, tau, k = length(tau))

        Explicitly finds the matrix Q of a QL factorization after calling geqlf! on A. Uses the output of geqlf!. A is overwritten by Q.

        LinearAlgebra.LAPACK.orgrq!Function
        orgrq!(A, tau, k = length(tau))

        Explicitly finds the matrix Q of a RQ factorization after calling gerqf! on A. Uses the output of gerqf!. A is overwritten by Q.

        LinearAlgebra.LAPACK.ormlq!Function
        ormlq!(side, trans, A, tau, C)

        Computes Q * C (trans = N), transpose(Q) * C (trans = T), adjoint(Q) * C (trans = C) for side = L or the equivalent right-sided multiplication for side = R using Q from a LQ factorization of A computed using gelqf!. C is overwritten.

        LinearAlgebra.LAPACK.ormqr!Function
        ormqr!(side, trans, A, tau, C)

        Computes Q * C (trans = N), transpose(Q) * C (trans = T), adjoint(Q) * C (trans = C) for side = L or the equivalent right-sided multiplication for side = R using Q from a QR factorization of A computed using geqrf!. C is overwritten.

        LinearAlgebra.LAPACK.ormql!Function
        ormql!(side, trans, A, tau, C)

        Computes Q * C (trans = N), transpose(Q) * C (trans = T), adjoint(Q) * C (trans = C) for side = L or the equivalent right-sided multiplication for side = R using Q from a QL factorization of A computed using geqlf!. C is overwritten.

        LinearAlgebra.LAPACK.ormrq!Function
        ormrq!(side, trans, A, tau, C)

        Computes Q * C (trans = N), transpose(Q) * C (trans = T), adjoint(Q) * C (trans = C) for side = L or the equivalent right-sided multiplication for side = R using Q from a RQ factorization of A computed using gerqf!. C is overwritten.

        LinearAlgebra.LAPACK.gemqrt!Function
        gemqrt!(side, trans, V, T, C)

        Computes Q * C (trans = N), transpose(Q) * C (trans = T), adjoint(Q) * C (trans = C) for side = L or the equivalent right-sided multiplication for side = R using Q from a QR factorization of A computed using geqrt!. C is overwritten.

        LinearAlgebra.LAPACK.posv!Function
        posv!(uplo, A, B) -> (A, B)

        Finds the solution to A * X = B where A is a symmetric or Hermitian positive definite matrix. If uplo = U the upper Cholesky decomposition of A is computed. If uplo = L the lower Cholesky decomposition of A is computed. A is overwritten by its Cholesky decomposition. B is overwritten with the solution X.

        LinearAlgebra.LAPACK.potrf!Function
        potrf!(uplo, A)

        Computes the Cholesky (upper if uplo = U, lower if uplo = L) decomposition of positive-definite matrix A. A is overwritten and returned with an info code.

        LinearAlgebra.LAPACK.potri!Function
        potri!(uplo, A)

        Computes the inverse of positive-definite matrix A after calling potrf! to find its (upper if uplo = U, lower if uplo = L) Cholesky decomposition.

        A is overwritten by its inverse and returned.

        LinearAlgebra.LAPACK.potrs!Function
        potrs!(uplo, A, B)

        Finds the solution to A * X = B where A is a symmetric or Hermitian positive definite matrix whose Cholesky decomposition was computed by potrf!. If uplo = U the upper Cholesky decomposition of A was computed. If uplo = L the lower Cholesky decomposition of A was computed. B is overwritten with the solution X.

        LinearAlgebra.LAPACK.pstrf!Function
        pstrf!(uplo, A, tol) -> (A, piv, rank, info)

        Computes the (upper if uplo = U, lower if uplo = L) pivoted Cholesky decomposition of positive-definite matrix A with a user-set tolerance tol. A is overwritten by its Cholesky decomposition.

        Returns A, the pivots piv, the rank of A, and an info code. If info = 0, the factorization succeeded. If info = i > 0, then A is indefinite or rank-deficient.

        LinearAlgebra.LAPACK.ptsv!Function
        ptsv!(D, E, B)

        Solves A * X = B for positive-definite tridiagonal A. D is the diagonal of A and E is the off-diagonal. B is overwritten with the solution X and returned.

        LinearAlgebra.LAPACK.pttrf!Function
        pttrf!(D, E)

        Computes the LDLt factorization of a positive-definite tridiagonal matrix with D as diagonal and E as off-diagonal. D and E are overwritten and returned.

        LinearAlgebra.LAPACK.pttrs!Function
        pttrs!(D, E, B)

        Solves A * X = B for positive-definite tridiagonal A with diagonal D and off-diagonal E after computing A's LDLt factorization using pttrf!. B is overwritten with the solution X.

        LinearAlgebra.LAPACK.trtri!Function
        trtri!(uplo, diag, A)

        Finds the inverse of (upper if uplo = U, lower if uplo = L) triangular matrix A. If diag = N, A has non-unit diagonal elements. If diag = U, all diagonal elements of A are one. A is overwritten with its inverse.

        LinearAlgebra.LAPACK.trtrs!Function
        trtrs!(uplo, trans, diag, A, B)

        Solves A * X = B (trans = N), transpose(A) * X = B (trans = T), or adjoint(A) * X = B (trans = C) for (upper if uplo = U, lower if uplo = L) triangular matrix A. If diag = N, A has non-unit diagonal elements. If diag = U, all diagonal elements of A are one. B is overwritten with the solution X.

        LinearAlgebra.LAPACK.trcon!Function
        trcon!(norm, uplo, diag, A)

        Finds the reciprocal condition number of (upper if uplo = U, lower if uplo = L) triangular matrix A. If diag = N, A has non-unit diagonal elements. If diag = U, all diagonal elements of A are one. If norm = I, the condition number is found in the infinity norm. If norm = O or 1, the condition number is found in the one norm.

        LinearAlgebra.LAPACK.trevc!Function
        trevc!(side, howmny, select, T, VL = similar(T), VR = similar(T))

        Finds the eigensystem of an upper triangular matrix T. If side = R, the right eigenvectors are computed. If side = L, the left eigenvectors are computed. If side = B, both sets are computed. If howmny = A, all eigenvectors are found. If howmny = B, all eigenvectors are found and backtransformed using VL and VR. If howmny = S, only the eigenvectors corresponding to the values in select are computed.

        LinearAlgebra.LAPACK.trrfs!Function
        trrfs!(uplo, trans, diag, A, B, X, Ferr, Berr) -> (Ferr, Berr)

        Estimates the error in the solution to A * X = B (trans = N), transpose(A) * X = B (trans = T), adjoint(A) * X = B (trans = C) for side = L, or the equivalent equations a right-handed side = R X * A after computing X using trtrs!. If uplo = U, A is upper triangular. If uplo = L, A is lower triangular. If diag = N, A has non-unit diagonal elements. If diag = U, all diagonal elements of A are one. Ferr and Berr are optional inputs. Ferr is the forward error and Berr is the backward error, each component-wise.

        LinearAlgebra.LAPACK.stev!Function
        stev!(job, dv, ev) -> (dv, Zmat)

        Computes the eigensystem for a symmetric tridiagonal matrix with dv as diagonal and ev as off-diagonal. If job = N only the eigenvalues are found and returned in dv. If job = V then the eigenvectors are also found and returned in Zmat.

        LinearAlgebra.LAPACK.stebz!Function
        stebz!(range, order, vl, vu, il, iu, abstol, dv, ev) -> (dv, iblock, isplit)

        Computes the eigenvalues for a symmetric tridiagonal matrix with dv as diagonal and ev as off-diagonal. If range = A, all the eigenvalues are found. If range = V, the eigenvalues in the half-open interval (vl, vu] are found. If range = I, the eigenvalues with indices between il and iu are found. If order = B, eigvalues are ordered within a block. If order = E, they are ordered across all the blocks. abstol can be set as a tolerance for convergence.

        LinearAlgebra.LAPACK.stegr!Function
        stegr!(jobz, range, dv, ev, vl, vu, il, iu) -> (w, Z)

        Computes the eigenvalues (jobz = N) or eigenvalues and eigenvectors (jobz = V) for a symmetric tridiagonal matrix with dv as diagonal and ev as off-diagonal. If range = A, all the eigenvalues are found. If range = V, the eigenvalues in the half-open interval (vl, vu] are found. If range = I, the eigenvalues with indices between il and iu are found. The eigenvalues are returned in w and the eigenvectors in Z.

        LinearAlgebra.LAPACK.stein!Function
        stein!(dv, ev_in, w_in, iblock_in, isplit_in)

        Computes the eigenvectors for a symmetric tridiagonal matrix with dv as diagonal and ev_in as off-diagonal. w_in specifies the input eigenvalues for which to find corresponding eigenvectors. iblock_in specifies the submatrices corresponding to the eigenvalues in w_in. isplit_in specifies the splitting points between the submatrix blocks.

        LinearAlgebra.LAPACK.syconv!Function
        syconv!(uplo, A, ipiv) -> (A, work)

        Converts a symmetric matrix A (which has been factorized into a triangular matrix) into two matrices L and D. If uplo = U, A is upper triangular. If uplo = L, it is lower triangular. ipiv is the pivot vector from the triangular factorization. A is overwritten by L and D.

        LinearAlgebra.LAPACK.sysv!Function
        sysv!(uplo, A, B) -> (B, A, ipiv)

        Finds the solution to A * X = B for symmetric matrix A. If uplo = U, the upper half of A is stored. If uplo = L, the lower half is stored. B is overwritten by the solution X. A is overwritten by its Bunch-Kaufman factorization. ipiv contains pivoting information about the factorization.

        LinearAlgebra.LAPACK.sytrf!Function
        sytrf!(uplo, A) -> (A, ipiv, info)

        Computes the Bunch-Kaufman factorization of a symmetric matrix A. If uplo = U, the upper half of A is stored. If uplo = L, the lower half is stored.

        Returns A, overwritten by the factorization, a pivot vector ipiv, and the error code info which is a non-negative integer. If info is positive the matrix is singular and the diagonal part of the factorization is exactly zero at position info.

        LinearAlgebra.LAPACK.sytri!Function
        sytri!(uplo, A, ipiv)

        Computes the inverse of a symmetric matrix A using the results of sytrf!. If uplo = U, the upper half of A is stored. If uplo = L, the lower half is stored. A is overwritten by its inverse.

        LinearAlgebra.LAPACK.sytrs!Function
        sytrs!(uplo, A, ipiv, B)

        Solves the equation A * X = B for a symmetric matrix A using the results of sytrf!. If uplo = U, the upper half of A is stored. If uplo = L, the lower half is stored. B is overwritten by the solution X.

        LinearAlgebra.LAPACK.hesv!Function
        hesv!(uplo, A, B) -> (B, A, ipiv)

        Finds the solution to A * X = B for Hermitian matrix A. If uplo = U, the upper half of A is stored. If uplo = L, the lower half is stored. B is overwritten by the solution X. A is overwritten by its Bunch-Kaufman factorization. ipiv contains pivoting information about the factorization.

        LinearAlgebra.LAPACK.hetrf!Function
        hetrf!(uplo, A) -> (A, ipiv, info)

        Computes the Bunch-Kaufman factorization of a Hermitian matrix A. If uplo = U, the upper half of A is stored. If uplo = L, the lower half is stored.

        Returns A, overwritten by the factorization, a pivot vector ipiv, and the error code info which is a non-negative integer. If info is positive the matrix is singular and the diagonal part of the factorization is exactly zero at position info.

        LinearAlgebra.LAPACK.hetri!Function
        hetri!(uplo, A, ipiv)

        Computes the inverse of a Hermitian matrix A using the results of sytrf!. If uplo = U, the upper half of A is stored. If uplo = L, the lower half is stored. A is overwritten by its inverse.

        LinearAlgebra.LAPACK.hetrs!Function
        hetrs!(uplo, A, ipiv, B)

        Solves the equation A * X = B for a Hermitian matrix A using the results of sytrf!. If uplo = U, the upper half of A is stored. If uplo = L, the lower half is stored. B is overwritten by the solution X.

        LinearAlgebra.LAPACK.syev!Function
        syev!(jobz, uplo, A)

        Finds the eigenvalues (jobz = N) or eigenvalues and eigenvectors (jobz = V) of a symmetric matrix A. If uplo = U, the upper triangle of A is used. If uplo = L, the lower triangle of A is used.

        LinearAlgebra.LAPACK.syevr!Function
        syevr!(jobz, range, uplo, A, vl, vu, il, iu, abstol) -> (W, Z)

        Finds the eigenvalues (jobz = N) or eigenvalues and eigenvectors (jobz = V) of a symmetric matrix A. If uplo = U, the upper triangle of A is used. If uplo = L, the lower triangle of A is used. If range = A, all the eigenvalues are found. If range = V, the eigenvalues in the half-open interval (vl, vu] are found. If range = I, the eigenvalues with indices between il and iu are found. abstol can be set as a tolerance for convergence.

        The eigenvalues are returned in W and the eigenvectors in Z.

        LinearAlgebra.LAPACK.sygvd!Function
        sygvd!(itype, jobz, uplo, A, B) -> (w, A, B)

        Finds the generalized eigenvalues (jobz = N) or eigenvalues and eigenvectors (jobz = V) of a symmetric matrix A and symmetric positive-definite matrix B. If uplo = U, the upper triangles of A and B are used. If uplo = L, the lower triangles of A and B are used. If itype = 1, the problem to solve is A * x = lambda * B * x. If itype = 2, the problem to solve is A * B * x = lambda * x. If itype = 3, the problem to solve is B * A * x = lambda * x.

        LinearAlgebra.LAPACK.bdsqr!Function
        bdsqr!(uplo, d, e_, Vt, U, C) -> (d, Vt, U, C)

        Computes the singular value decomposition of a bidiagonal matrix with d on the diagonal and e_ on the off-diagonal. If uplo = U, e_ is the superdiagonal. If uplo = L, e_ is the subdiagonal. Can optionally also compute the product Q' * C.

        Returns the singular values in d, and the matrix C overwritten with Q' * C.

        LinearAlgebra.LAPACK.bdsdc!Function
        bdsdc!(uplo, compq, d, e_) -> (d, e, u, vt, q, iq)

        Computes the singular value decomposition of a bidiagonal matrix with d on the diagonal and e_ on the off-diagonal using a divide and conqueq method. If uplo = U, e_ is the superdiagonal. If uplo = L, e_ is the subdiagonal. If compq = N, only the singular values are found. If compq = I, the singular values and vectors are found. If compq = P, the singular values and vectors are found in compact form. Only works for real types.

        Returns the singular values in d, and if compq = P, the compact singular vectors in iq.

        LinearAlgebra.LAPACK.gecon!Function
        gecon!(normtype, A, anorm)

        Finds the reciprocal condition number of matrix A. If normtype = I, the condition number is found in the infinity norm. If normtype = O or 1, the condition number is found in the one norm. A must be the result of getrf! and anorm is the norm of A in the relevant norm.

        LinearAlgebra.LAPACK.gehrd!Function
        gehrd!(ilo, ihi, A) -> (A, tau)

        Converts a matrix A to Hessenberg form. If A is balanced with gebal! then ilo and ihi are the outputs of gebal!. Otherwise they should be ilo = 1 and ihi = size(A,2). tau contains the elementary reflectors of the factorization.

        LinearAlgebra.LAPACK.orghr!Function
        orghr!(ilo, ihi, A, tau)

        Explicitly finds Q, the orthogonal/unitary matrix from gehrd!. ilo, ihi, A, and tau must correspond to the input/output to gehrd!.

        LinearAlgebra.LAPACK.gees!Function
        gees!(jobvs, A) -> (A, vs, w)

        Computes the eigenvalues (jobvs = N) or the eigenvalues and Schur vectors (jobvs = V) of matrix A. A is overwritten by its Schur form.

        Returns A, vs containing the Schur vectors, and w, containing the eigenvalues.

        LinearAlgebra.LAPACK.gges!Function
        gges!(jobvsl, jobvsr, A, B) -> (A, B, alpha, beta, vsl, vsr)

        Computes the generalized eigenvalues, generalized Schur form, left Schur vectors (jobsvl = V), or right Schur vectors (jobvsr = V) of A and B.

        The generalized eigenvalues are returned in alpha and beta. The left Schur vectors are returned in vsl and the right Schur vectors are returned in vsr.

        LinearAlgebra.LAPACK.trexc!Function
        trexc!(compq, ifst, ilst, T, Q) -> (T, Q)
         trexc!(ifst, ilst, T, Q) -> (T, Q)

        Reorder the Schur factorization T of a matrix, such that the diagonal block of T with row index ifst is moved to row index ilst. If compq = V, the Schur vectors Q are reordered. If compq = N they are not modified. The 4-arg method calls the 5-arg method with compq = V.

        LinearAlgebra.LAPACK.trsen!Function
        trsen!(job, compq, select, T, Q) -> (T, Q, w, s, sep)
        -trsen!(select, T, Q) -> (T, Q, w, s, sep)

        Reorder the Schur factorization of a matrix and optionally finds reciprocal condition numbers. If job = N, no condition numbers are found. If job = E, only the condition number for this cluster of eigenvalues is found. If job = V, only the condition number for the invariant subspace is found. If job = B then the condition numbers for the cluster and subspace are found. If compq = V the Schur vectors Q are updated. If compq = N the Schur vectors are not modified. select determines which eigenvalues are in the cluster. The 3-arg method calls the 5-arg method with job = N and compq = V.

        Returns T, Q, reordered eigenvalues in w, the condition number of the cluster of eigenvalues s, and the condition number of the invariant subspace sep.

        LinearAlgebra.LAPACK.tgsen!Function
        tgsen!(select, S, T, Q, Z) -> (S, T, alpha, beta, Q, Z)

        Reorders the vectors of a generalized Schur decomposition. select specifies the eigenvalues in each cluster.

        LinearAlgebra.LAPACK.trsyl!Function
        trsyl!(transa, transb, A, B, C, isgn=1) -> (C, scale)

        Solves the Sylvester matrix equation A * X +/- X * B = scale*C where A and B are both quasi-upper triangular. If transa = N, A is not modified. If transa = T, A is transposed. If transa = C, A is conjugate transposed. Similarly for transb and B. If isgn = 1, the equation A * X + X * B = scale * C is solved. If isgn = -1, the equation A * X - X * B = scale * C is solved.

        Returns X (overwriting C) and scale.

        • Bischof1987C Bischof and C Van Loan, "The WY representation for products of Householder matrices", SIAM J Sci Stat Comput 8 (1987), s2-s13. doi:10.1137/0908009
        • Schreiber1989R Schreiber and C Van Loan, "A storage-efficient WY representation for products of Householder transformations", SIAM J Sci Stat Comput 10 (1989), 53-57. doi:10.1137/0910005
        • Bunch1977J R Bunch and L Kaufman, Some stable methods for calculating inertia and solving symmetric linear systems, Mathematics of Computation 31:137 (1977), 163-179. url.
        • issue8859Issue 8859, "Fix least squares", https://github.com/JuliaLang/julia/pull/8859
        • B96Åke Björck, "Numerical Methods for Least Squares Problems", SIAM Press, Philadelphia, 1996, "Other Titles in Applied Mathematics", Vol. 51. doi:10.1137/1.9781611971484
        • S84G. W. Stewart, "Rank Degeneracy", SIAM Journal on Scientific and Statistical Computing, 5(2), 1984, 403-413. doi:10.1137/0905030
        • KY88Konstantinos Konstantinides and Kung Yao, "Statistical analysis of effective singular values in matrix rank determination", IEEE Transactions on Acoustics, Speech and Signal Processing, 36(5), 1988, 757-763. doi:10.1109/29.1585
        • H05Nicholas J. Higham, "The squaring and scaling method for the matrix exponential revisited", SIAM Journal on Matrix Analysis and Applications, 26(4), 2005, 1179-1193. doi:10.1137/090768539
        • AH12Awad H. Al-Mohy and Nicholas J. Higham, "Improved inverse scaling and squaring algorithms for the matrix logarithm", SIAM Journal on Scientific Computing, 34(4), 2012, C153-C169. doi:10.1137/110852553
        • AHR13Awad H. Al-Mohy, Nicholas J. Higham and Samuel D. Relton, "Computing the Fréchet derivative of the matrix logarithm and estimating the condition number", SIAM Journal on Scientific Computing, 35(4), 2013, C394-C410. doi:10.1137/120885991
        • BH83Åke Björck and Sven Hammarling, "A Schur method for the square root of a matrix", Linear Algebra and its Applications, 52-53, 1983, 127-140. doi:10.1016/0024-3795(83)80010-X
        • H87Nicholas J. Higham, "Computing real square roots of a real matrix", Linear Algebra and its Applications, 88-89, 1987, 405-430. doi:10.1016/0024-3795(87)90118-2
        • AH16_1Mary Aprahamian and Nicholas J. Higham, "Matrix Inverse Trigonometric and Inverse Hyperbolic Functions: Theory and Algorithms", MIMS EPrint: 2016.4. https://doi.org/10.1137/16M1057577
        • AH16_2Mary Aprahamian and Nicholas J. Higham, "Matrix Inverse Trigonometric and Inverse Hyperbolic Functions: Theory and Algorithms", MIMS EPrint: 2016.4. https://doi.org/10.1137/16M1057577
        • AH16_3Mary Aprahamian and Nicholas J. Higham, "Matrix Inverse Trigonometric and Inverse Hyperbolic Functions: Theory and Algorithms", MIMS EPrint: 2016.4. https://doi.org/10.1137/16M1057577
        • AH16_4Mary Aprahamian and Nicholas J. Higham, "Matrix Inverse Trigonometric and Inverse Hyperbolic Functions: Theory and Algorithms", MIMS EPrint: 2016.4. https://doi.org/10.1137/16M1057577
        • AH16_5Mary Aprahamian and Nicholas J. Higham, "Matrix Inverse Trigonometric and Inverse Hyperbolic Functions: Theory and Algorithms", MIMS EPrint: 2016.4. https://doi.org/10.1137/16M1057577
        • AH16_6Mary Aprahamian and Nicholas J. Higham, "Matrix Inverse Trigonometric and Inverse Hyperbolic Functions: Theory and Algorithms", MIMS EPrint: 2016.4. https://doi.org/10.1137/16M1057577
        +trsen!(select, T, Q) -> (T, Q, w, s, sep)

        Reorder the Schur factorization of a matrix and optionally finds reciprocal condition numbers. If job = N, no condition numbers are found. If job = E, only the condition number for this cluster of eigenvalues is found. If job = V, only the condition number for the invariant subspace is found. If job = B then the condition numbers for the cluster and subspace are found. If compq = V the Schur vectors Q are updated. If compq = N the Schur vectors are not modified. select determines which eigenvalues are in the cluster. The 3-arg method calls the 5-arg method with job = N and compq = V.

        Returns T, Q, reordered eigenvalues in w, the condition number of the cluster of eigenvalues s, and the condition number of the invariant subspace sep.

        LinearAlgebra.LAPACK.tgsen!Function
        tgsen!(select, S, T, Q, Z) -> (S, T, alpha, beta, Q, Z)

        Reorders the vectors of a generalized Schur decomposition. select specifies the eigenvalues in each cluster.

        LinearAlgebra.LAPACK.trsyl!Function
        trsyl!(transa, transb, A, B, C, isgn=1) -> (C, scale)

        Solves the Sylvester matrix equation A * X +/- X * B = scale*C where A and B are both quasi-upper triangular. If transa = N, A is not modified. If transa = T, A is transposed. If transa = C, A is conjugate transposed. Similarly for transb and B. If isgn = 1, the equation A * X + X * B = scale * C is solved. If isgn = -1, the equation A * X - X * B = scale * C is solved.

        Returns X (overwriting C) and scale.

        • Bischof1987C Bischof and C Van Loan, "The WY representation for products of Householder matrices", SIAM J Sci Stat Comput 8 (1987), s2-s13. doi:10.1137/0908009
        • Schreiber1989R Schreiber and C Van Loan, "A storage-efficient WY representation for products of Householder transformations", SIAM J Sci Stat Comput 10 (1989), 53-57. doi:10.1137/0910005
        • Bunch1977J R Bunch and L Kaufman, Some stable methods for calculating inertia and solving symmetric linear systems, Mathematics of Computation 31:137 (1977), 163-179. url.
        • issue8859Issue 8859, "Fix least squares", https://github.com/JuliaLang/julia/pull/8859
        • B96Åke Björck, "Numerical Methods for Least Squares Problems", SIAM Press, Philadelphia, 1996, "Other Titles in Applied Mathematics", Vol. 51. doi:10.1137/1.9781611971484
        • S84G. W. Stewart, "Rank Degeneracy", SIAM Journal on Scientific and Statistical Computing, 5(2), 1984, 403-413. doi:10.1137/0905030
        • KY88Konstantinos Konstantinides and Kung Yao, "Statistical analysis of effective singular values in matrix rank determination", IEEE Transactions on Acoustics, Speech and Signal Processing, 36(5), 1988, 757-763. doi:10.1109/29.1585
        • H05Nicholas J. Higham, "The squaring and scaling method for the matrix exponential revisited", SIAM Journal on Matrix Analysis and Applications, 26(4), 2005, 1179-1193. doi:10.1137/090768539
        • AH12Awad H. Al-Mohy and Nicholas J. Higham, "Improved inverse scaling and squaring algorithms for the matrix logarithm", SIAM Journal on Scientific Computing, 34(4), 2012, C153-C169. doi:10.1137/110852553
        • AHR13Awad H. Al-Mohy, Nicholas J. Higham and Samuel D. Relton, "Computing the Fréchet derivative of the matrix logarithm and estimating the condition number", SIAM Journal on Scientific Computing, 35(4), 2013, C394-C410. doi:10.1137/120885991
        • BH83Åke Björck and Sven Hammarling, "A Schur method for the square root of a matrix", Linear Algebra and its Applications, 52-53, 1983, 127-140. doi:10.1016/0024-3795(83)80010-X
        • H87Nicholas J. Higham, "Computing real square roots of a real matrix", Linear Algebra and its Applications, 88-89, 1987, 405-430. doi:10.1016/0024-3795(87)90118-2
        • AH16_1Mary Aprahamian and Nicholas J. Higham, "Matrix Inverse Trigonometric and Inverse Hyperbolic Functions: Theory and Algorithms", MIMS EPrint: 2016.4. https://doi.org/10.1137/16M1057577
        • AH16_2Mary Aprahamian and Nicholas J. Higham, "Matrix Inverse Trigonometric and Inverse Hyperbolic Functions: Theory and Algorithms", MIMS EPrint: 2016.4. https://doi.org/10.1137/16M1057577
        • AH16_3Mary Aprahamian and Nicholas J. Higham, "Matrix Inverse Trigonometric and Inverse Hyperbolic Functions: Theory and Algorithms", MIMS EPrint: 2016.4. https://doi.org/10.1137/16M1057577
        • AH16_4Mary Aprahamian and Nicholas J. Higham, "Matrix Inverse Trigonometric and Inverse Hyperbolic Functions: Theory and Algorithms", MIMS EPrint: 2016.4. https://doi.org/10.1137/16M1057577
        • AH16_5Mary Aprahamian and Nicholas J. Higham, "Matrix Inverse Trigonometric and Inverse Hyperbolic Functions: Theory and Algorithms", MIMS EPrint: 2016.4. https://doi.org/10.1137/16M1057577
        • AH16_6Mary Aprahamian and Nicholas J. Higham, "Matrix Inverse Trigonometric and Inverse Hyperbolic Functions: Theory and Algorithms", MIMS EPrint: 2016.4. https://doi.org/10.1137/16M1057577
        diff --git a/dev/stdlib/Logging/index.html b/dev/stdlib/Logging/index.html index 2943a293..cdc85132 100644 --- a/dev/stdlib/Logging/index.html +++ b/dev/stdlib/Logging/index.html @@ -105,4 +105,4 @@ test(1) test([1,2]) endsource
        Logging.current_loggerFunction
        current_logger()

        Return the logger for the current task, or the global logger if none is attached to the task.

        source

        Loggers that are supplied with the system:

        Logging.NullLoggerType
        NullLogger()

        Logger which disables all messages and produces no output - the logger equivalent of /dev/null.

        source
        Logging.ConsoleLoggerType
        ConsoleLogger([stream,] min_level=Info; meta_formatter=default_metafmt,
        -              show_limited=true, right_justify=0)

        Logger with formatting optimized for readability in a text console, for example interactive work with the Julia REPL.

        Log levels less than min_level are filtered out.

        Message formatting can be controlled by setting keyword arguments:

        • meta_formatter is a function which takes the log event metadata (level, _module, group, id, file, line) and returns a color (as would be passed to printstyled), prefix and suffix for the log message. The default is to prefix with the log level and a suffix containing the module, file and line location.
        • show_limited limits the printing of large data structures to something which can fit on the screen by setting the :limit IOContext key during formatting.
        • right_justify is the integer column which log metadata is right justified at. The default is zero (metadata goes on its own line).
        Logging.SimpleLoggerType
        SimpleLogger([stream,] min_level=Info)

        Simplistic logger for logging all messages with level greater than or equal to min_level to stream. If stream is closed then messages with log level greater or equal to Warn will be logged to stderr and below to stdout.

        source
        + show_limited=true, right_justify=0)

        Logger with formatting optimized for readability in a text console, for example interactive work with the Julia REPL.

        Log levels less than min_level are filtered out.

        Message formatting can be controlled by setting keyword arguments:

        • meta_formatter is a function which takes the log event metadata (level, _module, group, id, file, line) and returns a color (as would be passed to printstyled), prefix and suffix for the log message. The default is to prefix with the log level and a suffix containing the module, file and line location.
        • show_limited limits the printing of large data structures to something which can fit on the screen by setting the :limit IOContext key during formatting.
        • right_justify is the integer column which log metadata is right justified at. The default is zero (metadata goes on its own line).
        Logging.SimpleLoggerType
        SimpleLogger([stream,] min_level=Info)

        Simplistic logger for logging all messages with level greater than or equal to min_level to stream. If stream is closed then messages with log level greater or equal to Warn will be logged to stderr and below to stdout.

        source
        diff --git a/dev/stdlib/Markdown/index.html b/dev/stdlib/Markdown/index.html index fe88e6be..971e1ad8 100644 --- a/dev/stdlib/Markdown/index.html +++ b/dev/stdlib/Markdown/index.html @@ -102,4 +102,4 @@ This warning admonition has a custom title: `"Beware!"`.

        The first word after !!! declares the type of the admonition. There are standard admonition types that should produce special styling. Namely (in order of decreasing severity): danger, warning, info/note, and tip.

        You can also use your own admonition types, as long as the type name only contains lowercase Latin characters (a-z). For example, you could have a terminology block like this:

        !!! terminology "julia vs Julia"
         
             Strictly speaking, "Julia" refers to the language,
        -    and "julia" to the standard implementation.

        However, unless the code rendering the Markdown special-cases that particular admonition type, it will get the default styling.

        A custom title for the box can be provided as a string (in double quotes) after the admonition type. If no title text is specified after the admonition type, then the type name will be used as the title (e.g. "Note" for the note admonition).

        Admonitions, like most other toplevel elements, can contain other toplevel elements (e.g. lists, images).

        Markdown Syntax Extensions

        Julia's markdown supports interpolation in a very similar way to basic string literals, with the difference that it will store the object itself in the Markdown tree (as opposed to converting it to a string). When the Markdown content is rendered the usual show methods will be called, and these can be overridden as usual. This design allows the Markdown to be extended with arbitrarily complex features (such as references) without cluttering the basic syntax.

        In principle, the Markdown parser itself can also be arbitrarily extended by packages, or an entirely custom flavour of Markdown can be used, but this should generally be unnecessary.

        + and "julia" to the standard implementation.

        However, unless the code rendering the Markdown special-cases that particular admonition type, it will get the default styling.

        A custom title for the box can be provided as a string (in double quotes) after the admonition type. If no title text is specified after the admonition type, then the type name will be used as the title (e.g. "Note" for the note admonition).

        Admonitions, like most other toplevel elements, can contain other toplevel elements (e.g. lists, images).

        Markdown Syntax Extensions

        Julia's markdown supports interpolation in a very similar way to basic string literals, with the difference that it will store the object itself in the Markdown tree (as opposed to converting it to a string). When the Markdown content is rendered the usual show methods will be called, and these can be overridden as usual. This design allows the Markdown to be extended with arbitrarily complex features (such as references) without cluttering the basic syntax.

        In principle, the Markdown parser itself can also be arbitrarily extended by packages, or an entirely custom flavour of Markdown can be used, but this should generally be unnecessary.

        diff --git a/dev/stdlib/Mmap/index.html b/dev/stdlib/Mmap/index.html index 35aba500..882ca1e2 100644 --- a/dev/stdlib/Mmap/index.html +++ b/dev/stdlib/Mmap/index.html @@ -58,4 +58,4 @@ julia> close(io) -julia> rm("mmap.bin")

        This creates a 25-by-30000 BitArray, linked to the file associated with stream io.

        Mmap.sync!Function
        Mmap.sync!(array)

        Forces synchronization between the in-memory version of a memory-mapped Array or BitArray and the on-disk version.

        +julia> rm("mmap.bin")

        This creates a 25-by-30000 BitArray, linked to the file associated with stream io.

        Mmap.sync!Function
        Mmap.sync!(array)

        Forces synchronization between the in-memory version of a memory-mapped Array or BitArray and the on-disk version.

        diff --git a/dev/stdlib/Printf/index.html b/dev/stdlib/Printf/index.html index 09d40844..df7e9640 100644 --- a/dev/stdlib/Printf/index.html +++ b/dev/stdlib/Printf/index.html @@ -30,4 +30,4 @@ julia> @printf "%.0f %.1f %f" 0.5 0.025 -0.0078125 0 0.0 -0.007812
        Julia 1.8

        Starting in Julia 1.8, %s (string) and %c (character) widths are computed using textwidth, which e.g. ignores zero-width characters (such as combining characters for diacritical marks) and treats certain "wide" characters (e.g. emoji) as width 2.

        Printf.@sprintfMacro
        @sprintf("%Fmt", args...)

        Return @printf formatted output as string.

        Examples

        julia> @sprintf "this is a %s %15.1f" "test" 34.567
        -"this is a test            34.6"
        +"this is a test 34.6" diff --git a/dev/stdlib/Profile/index.html b/dev/stdlib/Profile/index.html index 330af88d..64e4cf03 100644 --- a/dev/stdlib/Profile/index.html +++ b/dev/stdlib/Profile/index.html @@ -6,4 +6,4 @@ ga('create', 'UA-28835595-9', 'auto'); ga('send', 'pageview', {'page': location.pathname + location.search + location.hash}); -

        性能分析

        Profile.@profileMacro
        @profile

        @profile <expression> runs your expression while taking periodic backtraces. These are appended to an internal buffer of backtraces.

        Profile 里的方法均未导出,需要通过 Profile.print() 的方式调用。

        Profile.clearFunction
        clear()

        Clear any existing backtraces from the internal buffer.

        Profile.printFunction
        print([io::IO = stdout,] [data::Vector = fetch()], [lidict::Union{LineInfoDict, LineInfoFlatDict} = getdict(data)]; kwargs...)

        Prints profiling results to io (by default, stdout). If you do not supply a data vector, the internal buffer of accumulated backtraces will be used.

        The keyword arguments can be any combination of:

        • format – Determines whether backtraces are printed with (default, :tree) or without (:flat) indentation indicating tree structure.

        • C – If true, backtraces from C and Fortran code are shown (normally they are excluded).

        • combine – If true (default), instruction pointers are merged that correspond to the same line of code.

        • maxdepth – Limits the depth higher than maxdepth in the :tree format.

        • sortedby – Controls the order in :flat format. :filefuncline (default) sorts by the source line, :count sorts in order of number of collected samples, and :overhead sorts by the number of samples incurred by each function by itself.

        • groupby – Controls grouping over tasks and threads, or no grouping. Options are :none (default), :thread, :task, [:thread, :task], or [:task, :thread] where the last two provide nested grouping.

        • noisefloor – Limits frames that exceed the heuristic noise floor of the sample (only applies to format :tree). A suggested value to try for this is 2.0 (the default is 0). This parameter hides samples for which n <= noisefloor * √N, where n is the number of samples on this line, and N is the number of samples for the callee.

        • mincount – Limits the printout to only those lines with at least mincount occurrences.

        • recur – Controls the recursion handling in :tree format. :off (default) prints the tree as normal. :flat instead compresses any recursion (by ip), showing the approximate effect of converting any self-recursion into an iterator. :flatc does the same but also includes collapsing of C frames (may do odd things around jl_apply).

        • threads::Union{Int,AbstractVector{Int}} – Specify which threads to include snapshots from in the report. Note that this does not control which threads samples are collected on (which may also have been collected on another machine).

        • tasks::Union{Int,AbstractVector{Int}} – Specify which tasks to include snapshots from in the report. Note that this does not control which tasks samples are collected within.

        print([io::IO = stdout,] data::Vector, lidict::LineInfoDict; kwargs...)

        Prints profiling results to io. This variant is used to examine results exported by a previous call to retrieve. Supply the vector data of backtraces and a dictionary lidict of line information.

        See Profile.print([io], data) for an explanation of the valid keyword arguments.

        Profile.initFunction
        init(; n::Integer, delay::Real)

        Configure the delay between backtraces (measured in seconds), and the number n of instruction pointers that may be stored per thread. Each instruction pointer corresponds to a single line of code; backtraces generally consist of a long list of instruction pointers. Note that 6 spaces for instruction pointers per backtrace are used to store metadata and two NULL end markers. Current settings can be obtained by calling this function with no arguments, and each can be set independently using keywords or in the order (n, delay).

        Julia 1.8

        As of Julia 1.8, this function allocates space for n instruction pointers per thread being profiled. Previously this was n total.

        Profile.fetchFunction
        fetch(;include_meta = true) -> data

        Returns a copy of the buffer of profile backtraces. Note that the values in data have meaning only on this machine in the current session, because it depends on the exact memory addresses used in JIT-compiling. This function is primarily for internal use; retrieve may be a better choice for most users. By default metadata such as threadid and taskid is included. Set include_meta to false to strip metadata.

        Profile.retrieveFunction
        retrieve(; kwargs...) -> data, lidict

        "Exports" profiling results in a portable format, returning the set of all backtraces (data) and a dictionary that maps the (session-specific) instruction pointers in data to LineInfo values that store the file name, function name, and line number. This function allows you to save profiling results for future analysis.

        Profile.callersFunction
        callers(funcname, [data, lidict], [filename=<filename>], [linerange=<start:stop>]) -> Vector{Tuple{count, lineinfo}}

        Given a previous profiling run, determine who called a particular function. Supplying the filename (and optionally, range of line numbers over which the function is defined) allows you to disambiguate an overloaded method. The returned value is a vector containing a count of the number of calls and line information about the caller. One can optionally supply backtrace data obtained from retrieve; otherwise, the current internal profile buffer is used.

        Profile.clear_malloc_dataFunction
        clear_malloc_data()

        Clears any stored memory allocation data when running julia with --track-allocation. Execute the command(s) you want to test (to force JIT-compilation), then call clear_malloc_data. Then execute your command(s) again, quit Julia, and examine the resulting *.mem files.

        +

        性能分析

        Profile.@profileMacro
        @profile

        @profile <expression> runs your expression while taking periodic backtraces. These are appended to an internal buffer of backtraces.

        Profile 里的方法均未导出,需要通过 Profile.print() 的方式调用。

        Profile.clearFunction
        clear()

        Clear any existing backtraces from the internal buffer.

        Profile.printFunction
        print([io::IO = stdout,] [data::Vector = fetch()], [lidict::Union{LineInfoDict, LineInfoFlatDict} = getdict(data)]; kwargs...)

        Prints profiling results to io (by default, stdout). If you do not supply a data vector, the internal buffer of accumulated backtraces will be used.

        The keyword arguments can be any combination of:

        • format – Determines whether backtraces are printed with (default, :tree) or without (:flat) indentation indicating tree structure.

        • C – If true, backtraces from C and Fortran code are shown (normally they are excluded).

        • combine – If true (default), instruction pointers are merged that correspond to the same line of code.

        • maxdepth – Limits the depth higher than maxdepth in the :tree format.

        • sortedby – Controls the order in :flat format. :filefuncline (default) sorts by the source line, :count sorts in order of number of collected samples, and :overhead sorts by the number of samples incurred by each function by itself.

        • groupby – Controls grouping over tasks and threads, or no grouping. Options are :none (default), :thread, :task, [:thread, :task], or [:task, :thread] where the last two provide nested grouping.

        • noisefloor – Limits frames that exceed the heuristic noise floor of the sample (only applies to format :tree). A suggested value to try for this is 2.0 (the default is 0). This parameter hides samples for which n <= noisefloor * √N, where n is the number of samples on this line, and N is the number of samples for the callee.

        • mincount – Limits the printout to only those lines with at least mincount occurrences.

        • recur – Controls the recursion handling in :tree format. :off (default) prints the tree as normal. :flat instead compresses any recursion (by ip), showing the approximate effect of converting any self-recursion into an iterator. :flatc does the same but also includes collapsing of C frames (may do odd things around jl_apply).

        • threads::Union{Int,AbstractVector{Int}} – Specify which threads to include snapshots from in the report. Note that this does not control which threads samples are collected on (which may also have been collected on another machine).

        • tasks::Union{Int,AbstractVector{Int}} – Specify which tasks to include snapshots from in the report. Note that this does not control which tasks samples are collected within.

        print([io::IO = stdout,] data::Vector, lidict::LineInfoDict; kwargs...)

        Prints profiling results to io. This variant is used to examine results exported by a previous call to retrieve. Supply the vector data of backtraces and a dictionary lidict of line information.

        See Profile.print([io], data) for an explanation of the valid keyword arguments.

        Profile.initFunction
        init(; n::Integer, delay::Real)

        Configure the delay between backtraces (measured in seconds), and the number n of instruction pointers that may be stored per thread. Each instruction pointer corresponds to a single line of code; backtraces generally consist of a long list of instruction pointers. Note that 6 spaces for instruction pointers per backtrace are used to store metadata and two NULL end markers. Current settings can be obtained by calling this function with no arguments, and each can be set independently using keywords or in the order (n, delay).

        Julia 1.8

        As of Julia 1.8, this function allocates space for n instruction pointers per thread being profiled. Previously this was n total.

        Profile.fetchFunction
        fetch(;include_meta = true) -> data

        Returns a copy of the buffer of profile backtraces. Note that the values in data have meaning only on this machine in the current session, because it depends on the exact memory addresses used in JIT-compiling. This function is primarily for internal use; retrieve may be a better choice for most users. By default metadata such as threadid and taskid is included. Set include_meta to false to strip metadata.

        Profile.retrieveFunction
        retrieve(; kwargs...) -> data, lidict

        "Exports" profiling results in a portable format, returning the set of all backtraces (data) and a dictionary that maps the (session-specific) instruction pointers in data to LineInfo values that store the file name, function name, and line number. This function allows you to save profiling results for future analysis.

        Profile.callersFunction
        callers(funcname, [data, lidict], [filename=<filename>], [linerange=<start:stop>]) -> Vector{Tuple{count, lineinfo}}

        Given a previous profiling run, determine who called a particular function. Supplying the filename (and optionally, range of line numbers over which the function is defined) allows you to disambiguate an overloaded method. The returned value is a vector containing a count of the number of calls and line information about the caller. One can optionally supply backtrace data obtained from retrieve; otherwise, the current internal profile buffer is used.

        Profile.clear_malloc_dataFunction
        clear_malloc_data()

        Clears any stored memory allocation data when running julia with --track-allocation. Execute the command(s) you want to test (to force JIT-compilation), then call clear_malloc_data. Then execute your command(s) again, quit Julia, and examine the resulting *.mem files.

        diff --git a/dev/stdlib/REPL/index.html b/dev/stdlib/REPL/index.html index a4d76b62..7483d020 100644 --- a/dev/stdlib/REPL/index.html +++ b/dev/stdlib/REPL/index.html @@ -255,4 +255,4 @@ YEP! orange NOPE grape ⧐ YEP! strawberry -↓ NOPE blueberry

        Aside from the overall charset option, for RadioMenu the configurable options are:

        • cursor::Char='>'|'→': character to use for cursor
        • up_arrow::Char='^'|'↑': character to use for up arrow
        • down_arrow::Char='v'|'↓': character to use for down arrow
        • updown_arrow::Char='I'|'↕': character to use for up/down arrow in one-line page
        • scroll_wrap::Bool=false: optionally wrap-around at the beginning/end of a menu
        • ctrl_c_interrupt::Bool=true: If false, return empty on ^C, if true throw InterruptException() on ^C

        MultiSelectMenu adds:

        • checked::String="[X]"|"✓": string to use for checked
        • unchecked::String="[ ]"|"⬚"): string to use for unchecked

        You can create new menu types of your own. Types that are derived from TerminalMenus.ConfiguredMenu configure the menu options at construction time.

        Legacy interface

        Prior to Julia 1.6, and still supported throughout Julia 1.x, one can also configure menus by calling TerminalMenus.config().

        References

        REPL

        Base.atreplinitFunction
        atreplinit(f)

        Register a one-argument function to be called before the REPL interface is initialized in interactive sessions; this is useful to customize the interface. The argument of f is the REPL object. This function should be called from within the .julia/config/startup.jl initialization file.

        source

        TerminalMenus

        Configuration

        REPL.TerminalMenus.ConfigType
        Config(; scroll_wrap=false, ctrl_c_interrupt=true, charset=:ascii, cursor::Char, up_arrow::Char, down_arrow::Char)

        Configure behavior for selection menus via keyword arguments:

        • scroll_wrap, if true, causes the menu to wrap around when scrolling above the first or below the last entry
        • ctrl_c_interrupt, if true, throws an InterruptException if the user hits Ctrl-C during menu selection. If false, TerminalMenus.request will return the default result from TerminalMenus.selected.
        • charset affects the default values for cursor, up_arrow, and down_arrow, and can be :ascii or :unicode
        • cursor is the character printed to indicate the option that will be chosen by hitting "Enter." Defaults are '>' or '→', depending on charset.
        • up_arrow is the character printed when the display does not include the first entry. Defaults are '^' or '↑', depending on charset.
        • down_arrow is the character printed when the display does not include the last entry. Defaults are 'v' or '↓', depending on charset.

        Subtypes of ConfiguredMenu will print cursor, up_arrow, and down_arrow automatically as needed, your writeline method should not print them.

        Julia 1.6

        Config is available as of Julia 1.6. On older releases use the global CONFIG.

        REPL.TerminalMenus.MultiSelectConfigType
        MultiSelectConfig(; charset=:ascii, checked::String, unchecked::String, kwargs...)

        Configure behavior for a multiple-selection menu via keyword arguments:

        • checked is the string to print when an option has been selected. Defaults are "[X]" or "✓", depending on charset.
        • unchecked is the string to print when an option has not been selected. Defaults are "[ ]" or "⬚", depending on charset.

        All other keyword arguments are as described for TerminalMenus.Config. checked and unchecked are not printed automatically, and should be printed by your writeline method.

        Julia 1.6

        MultiSelectConfig is available as of Julia 1.6. On older releases use the global CONFIG.

        REPL.TerminalMenus.configFunction
        config( <see arguments> )

        Keyword-only function to configure global menu parameters

        Arguments

        • charset::Symbol=:na: ui characters to use (:ascii or :unicode); overridden by other arguments
        • cursor::Char='>'|'→': character to use for cursor
        • up_arrow::Char='^'|'↑': character to use for up arrow
        • down_arrow::Char='v'|'↓': character to use for down arrow
        • checked::String="[X]"|"✓": string to use for checked
        • unchecked::String="[ ]"|"⬚"): string to use for unchecked
        • scroll::Symbol=:nowrap: If :wrap wrap cursor around top and bottom, if :nowrap do not wrap cursor
        • supress_output::Bool=false: Ignored legacy argument, pass suppress_output as a keyword argument to request instead.
        • ctrl_c_interrupt::Bool=true: If false, return empty on ^C, if true throw InterruptException() on ^C
        Julia 1.6

        As of Julia 1.6, config is deprecated. Use Config or MultiSelectConfig instead.

        User interaction

        REPL.TerminalMenus.requestFunction
        request(m::AbstractMenu; cursor=1)

        Display the menu and enter interactive mode. cursor indicates the item number used for the initial cursor position. cursor can be either an Int or a RefValue{Int}. The latter is useful for observation and control of the cursor position from the outside.

        Returns selected(m).

        Julia 1.6

        The cursor argument requires Julia 1.6 or later.

        request([term,] msg::AbstractString, m::AbstractMenu)

        Shorthand for println(msg); request(m).

        AbstractMenu extension interface

        Any subtype of AbstractMenu must be mutable, and must contain the fields pagesize::Int and pageoffset::Int. Any subtype must also implement the following functions:

        REPL.TerminalMenus.pickFunction
        pick(m::AbstractMenu, cursor::Int)

        Defines what happens when a user presses the Enter key while the menu is open. If true is returned, request() will exit. cursor indexes the position of the selection.

        REPL.TerminalMenus.cancelFunction
        cancel(m::AbstractMenu)

        Define what happens when a user cancels ('q' or ctrl-c) a menu. request() will always exit after calling this function.

        REPL.TerminalMenus.writelineFunction
        writeline(buf::IO, m::AbstractMenu, idx::Int, iscursor::Bool)

        Write the option at index idx to buf. iscursor, if true, indicates that this item is at the current cursor position (the one that will be selected by hitting "Enter").

        If m is a ConfiguredMenu, TerminalMenus will print the cursor indicator. Otherwise the callee is expected to handle such printing.

        Julia 1.6

        writeline requires Julia 1.6 or higher.

        On older versions of Julia, this was writeLine(buf::IO, m::AbstractMenu, idx, iscursor::Bool) and m is assumed to be unconfigured. The selection and cursor indicators can be obtained from TerminalMenus.CONFIG.

        This older function is supported on all Julia 1.x versions but will be dropped in Julia 2.0.

        It must also implement either options or numoptions:

        REPL.TerminalMenus.optionsFunction
        options(m::AbstractMenu)

        Return a list of strings to be displayed as options in the current page.

        Alternatively, implement numoptions, in which case options is not needed.

        REPL.TerminalMenus.numoptionsFunction
        numoptions(m::AbstractMenu) -> Int

        Return the number of options in menu m. Defaults to length(options(m)).

        Julia 1.6

        This function requires Julia 1.6 or later.

        If the subtype does not have a field named selected, it must also implement

        REPL.TerminalMenus.selectedFunction
        selected(m::AbstractMenu)

        Return information about the user-selected option. By default it returns m.selected.

        The following are optional but can allow additional customization:

        REPL.TerminalMenus.headerFunction
        header(m::AbstractMenu) -> String

        Returns a header string to be printed above the menu. Defaults to "".

        +↓ NOPE blueberry

        Aside from the overall charset option, for RadioMenu the configurable options are:

        • cursor::Char='>'|'→': character to use for cursor
        • up_arrow::Char='^'|'↑': character to use for up arrow
        • down_arrow::Char='v'|'↓': character to use for down arrow
        • updown_arrow::Char='I'|'↕': character to use for up/down arrow in one-line page
        • scroll_wrap::Bool=false: optionally wrap-around at the beginning/end of a menu
        • ctrl_c_interrupt::Bool=true: If false, return empty on ^C, if true throw InterruptException() on ^C

        MultiSelectMenu adds:

        • checked::String="[X]"|"✓": string to use for checked
        • unchecked::String="[ ]"|"⬚"): string to use for unchecked

        You can create new menu types of your own. Types that are derived from TerminalMenus.ConfiguredMenu configure the menu options at construction time.

        Legacy interface

        Prior to Julia 1.6, and still supported throughout Julia 1.x, one can also configure menus by calling TerminalMenus.config().

        References

        REPL

        Base.atreplinitFunction
        atreplinit(f)

        Register a one-argument function to be called before the REPL interface is initialized in interactive sessions; this is useful to customize the interface. The argument of f is the REPL object. This function should be called from within the .julia/config/startup.jl initialization file.

        source

        TerminalMenus

        Configuration

        REPL.TerminalMenus.ConfigType
        Config(; scroll_wrap=false, ctrl_c_interrupt=true, charset=:ascii, cursor::Char, up_arrow::Char, down_arrow::Char)

        Configure behavior for selection menus via keyword arguments:

        • scroll_wrap, if true, causes the menu to wrap around when scrolling above the first or below the last entry
        • ctrl_c_interrupt, if true, throws an InterruptException if the user hits Ctrl-C during menu selection. If false, TerminalMenus.request will return the default result from TerminalMenus.selected.
        • charset affects the default values for cursor, up_arrow, and down_arrow, and can be :ascii or :unicode
        • cursor is the character printed to indicate the option that will be chosen by hitting "Enter." Defaults are '>' or '→', depending on charset.
        • up_arrow is the character printed when the display does not include the first entry. Defaults are '^' or '↑', depending on charset.
        • down_arrow is the character printed when the display does not include the last entry. Defaults are 'v' or '↓', depending on charset.

        Subtypes of ConfiguredMenu will print cursor, up_arrow, and down_arrow automatically as needed, your writeline method should not print them.

        Julia 1.6

        Config is available as of Julia 1.6. On older releases use the global CONFIG.

        REPL.TerminalMenus.MultiSelectConfigType
        MultiSelectConfig(; charset=:ascii, checked::String, unchecked::String, kwargs...)

        Configure behavior for a multiple-selection menu via keyword arguments:

        • checked is the string to print when an option has been selected. Defaults are "[X]" or "✓", depending on charset.
        • unchecked is the string to print when an option has not been selected. Defaults are "[ ]" or "⬚", depending on charset.

        All other keyword arguments are as described for TerminalMenus.Config. checked and unchecked are not printed automatically, and should be printed by your writeline method.

        Julia 1.6

        MultiSelectConfig is available as of Julia 1.6. On older releases use the global CONFIG.

        REPL.TerminalMenus.configFunction
        config( <see arguments> )

        Keyword-only function to configure global menu parameters

        Arguments

        • charset::Symbol=:na: ui characters to use (:ascii or :unicode); overridden by other arguments
        • cursor::Char='>'|'→': character to use for cursor
        • up_arrow::Char='^'|'↑': character to use for up arrow
        • down_arrow::Char='v'|'↓': character to use for down arrow
        • checked::String="[X]"|"✓": string to use for checked
        • unchecked::String="[ ]"|"⬚"): string to use for unchecked
        • scroll::Symbol=:nowrap: If :wrap wrap cursor around top and bottom, if :nowrap do not wrap cursor
        • supress_output::Bool=false: Ignored legacy argument, pass suppress_output as a keyword argument to request instead.
        • ctrl_c_interrupt::Bool=true: If false, return empty on ^C, if true throw InterruptException() on ^C
        Julia 1.6

        As of Julia 1.6, config is deprecated. Use Config or MultiSelectConfig instead.

        User interaction

        REPL.TerminalMenus.requestFunction
        request(m::AbstractMenu; cursor=1)

        Display the menu and enter interactive mode. cursor indicates the item number used for the initial cursor position. cursor can be either an Int or a RefValue{Int}. The latter is useful for observation and control of the cursor position from the outside.

        Returns selected(m).

        Julia 1.6

        The cursor argument requires Julia 1.6 or later.

        request([term,] msg::AbstractString, m::AbstractMenu)

        Shorthand for println(msg); request(m).

        AbstractMenu extension interface

        Any subtype of AbstractMenu must be mutable, and must contain the fields pagesize::Int and pageoffset::Int. Any subtype must also implement the following functions:

        REPL.TerminalMenus.pickFunction
        pick(m::AbstractMenu, cursor::Int)

        Defines what happens when a user presses the Enter key while the menu is open. If true is returned, request() will exit. cursor indexes the position of the selection.

        REPL.TerminalMenus.cancelFunction
        cancel(m::AbstractMenu)

        Define what happens when a user cancels ('q' or ctrl-c) a menu. request() will always exit after calling this function.

        REPL.TerminalMenus.writelineFunction
        writeline(buf::IO, m::AbstractMenu, idx::Int, iscursor::Bool)

        Write the option at index idx to buf. iscursor, if true, indicates that this item is at the current cursor position (the one that will be selected by hitting "Enter").

        If m is a ConfiguredMenu, TerminalMenus will print the cursor indicator. Otherwise the callee is expected to handle such printing.

        Julia 1.6

        writeline requires Julia 1.6 or higher.

        On older versions of Julia, this was writeLine(buf::IO, m::AbstractMenu, idx, iscursor::Bool) and m is assumed to be unconfigured. The selection and cursor indicators can be obtained from TerminalMenus.CONFIG.

        This older function is supported on all Julia 1.x versions but will be dropped in Julia 2.0.

        It must also implement either options or numoptions:

        REPL.TerminalMenus.optionsFunction
        options(m::AbstractMenu)

        Return a list of strings to be displayed as options in the current page.

        Alternatively, implement numoptions, in which case options is not needed.

        REPL.TerminalMenus.numoptionsFunction
        numoptions(m::AbstractMenu) -> Int

        Return the number of options in menu m. Defaults to length(options(m)).

        Julia 1.6

        This function requires Julia 1.6 or later.

        If the subtype does not have a field named selected, it must also implement

        REPL.TerminalMenus.selectedFunction
        selected(m::AbstractMenu)

        Return information about the user-selected option. By default it returns m.selected.

        The following are optional but can allow additional customization:

        REPL.TerminalMenus.headerFunction
        header(m::AbstractMenu) -> String

        Returns a header string to be printed above the menu. Defaults to "".

        diff --git a/dev/stdlib/Random/index.html b/dev/stdlib/Random/index.html index abb9fc81..7645b39c 100644 --- a/dev/stdlib/Random/index.html +++ b/dev/stdlib/Random/index.html @@ -283,4 +283,4 @@ SamplerSimple(die, Sampler(RNG, 1:die.nsides, r)) rand(rng::AbstractRNG, sp::SamplerSimple{Die}) = rand(rng, sp.data)

        Here, sp.data refers to the second parameter in the call to the SamplerSimple constructor (in this case equal to Sampler(rng, 1:die.nsides, r)), while the Die object can be accessed via sp[].

        Like SamplerDie, any custom sampler must be a subtype of Sampler{T} where T is the type of the generated values. Note that SamplerSimple(x, data) isa Sampler{eltype(x)}, so this constrains what the first argument to SamplerSimple can be (it's recommended to use SamplerSimple like in the Die example, where x is simply forwarded while defining a Sampler method). Similarly, SamplerTrivial(x) isa Sampler{eltype(x)}.

        Another helper type is currently available for other cases, Random.SamplerTag, but is considered as internal API, and can break at any time without proper deprecations.

        Using distinct algorithms for scalar or array generation

        In some cases, whether one wants to generate only a handful of values or a large number of values will have an impact on the choice of algorithm. This is handled with the third parameter of the Sampler constructor. Let's assume we defined two helper types for Die, say SamplerDie1 which should be used to generate only few random values, and SamplerDieMany for many values. We can use those types as follows:

        Sampler(RNG::Type{<:AbstractRNG}, die::Die, ::Val{1}) = SamplerDie1(...)
        -Sampler(RNG::Type{<:AbstractRNG}, die::Die, ::Val{Inf}) = SamplerDieMany(...)

        Of course, rand must also be defined on those types (i.e. rand(::AbstractRNG, ::SamplerDie1) and rand(::AbstractRNG, ::SamplerDieMany)). Note that, as usual, SamplerTrivial and SamplerSimple can be used if custom types are not necessary.

        Note: Sampler(rng, x) is simply a shorthand for Sampler(rng, x, Val(Inf)), and Random.Repetition is an alias for Union{Val{1}, Val{Inf}}.

        Creating new generators

        The API is not clearly defined yet, but as a rule of thumb:

        1. any rand method producing "basic" types (isbitstype integer and floating types in Base) should be defined for this specific RNG, if they are needed;
        2. other documented rand methods accepting an AbstractRNG should work out of the box, (provided the methods from 1) what are relied on are implemented), but can of course be specialized for this RNG if there is room for optimization;
        3. copy for pseudo-RNGs should return an independent copy that generates the exact same random sequence as the original from that point when called in the same way. When this is not feasible (e.g. hardware-based RNGs), copy must not be implemented.

        Concerning 1), a rand method may happen to work automatically, but it's not officially supported and may break without warnings in a subsequent release.

        To define a new rand method for an hypothetical MyRNG generator, and a value specification s (e.g. s == Int, or s == 1:10) of type S==typeof(s) or S==Type{s} if s is a type, the same two methods as we saw before must be defined:

        1. Sampler(::Type{MyRNG}, ::S, ::Repetition), which returns an object of type say SamplerS
        2. rand(rng::MyRNG, sp::SamplerS)

        It can happen that Sampler(rng::AbstractRNG, ::S, ::Repetition) is already defined in the Random module. It would then be possible to skip step 1) in practice (if one wants to specialize generation for this particular RNG type), but the corresponding SamplerS type is considered as internal detail, and may be changed without warning.

        Specializing array generation

        In some cases, for a given RNG type, generating an array of random values can be more efficient with a specialized method than by merely using the decoupling technique explained before. This is for example the case for MersenneTwister, which natively writes random values in an array.

        To implement this specialization for MyRNG and for a specification s, producing elements of type S, the following method can be defined: rand!(rng::MyRNG, a::AbstractArray{S}, ::SamplerS), where SamplerS is the type of the sampler returned by Sampler(MyRNG, s, Val(Inf)). Instead of AbstractArray, it's possible to implement the functionality only for a subtype, e.g. Array{S}. The non-mutating array method of rand will automatically call this specialization internally.

        Reproducibility

        By using an RNG parameter initialized with a given seed, you can reproduce the same pseudorandom number sequence when running your program multiple times. However, a minor release of Julia (e.g. 1.3 to 1.4) may change the sequence of pseudorandom numbers generated from a specific seed, in particular if MersenneTwister is used. (Even if the sequence produced by a low-level function like rand does not change, the output of higher-level functions like randsubseq may change due to algorithm updates.) Rationale: guaranteeing that pseudorandom streams never change prohibits many algorithmic improvements.

        If you need to guarantee exact reproducibility of random data, it is advisable to simply save the data (e.g. as a supplementary attachment in a scientific publication). (You can also, of course, specify a particular Julia version and package manifest, especially if you require bit reproducibility.)

        Software tests that rely on specific "random" data should also generally either save the data, embed it into the test code, or use third-party packages like StableRNGs.jl. On the other hand, tests that should pass for most random data (e.g. testing A \ (A*x) ≈ x for a random matrix A = randn(n,n)) can use an RNG with a fixed seed to ensure that simply running the test many times does not encounter a failure due to very improbable data (e.g. an extremely ill-conditioned matrix).

        The statistical distribution from which random samples are drawn is guaranteed to be the same across any minor Julia releases.

        +Sampler(RNG::Type{<:AbstractRNG}, die::Die, ::Val{Inf}) = SamplerDieMany(...)

        Of course, rand must also be defined on those types (i.e. rand(::AbstractRNG, ::SamplerDie1) and rand(::AbstractRNG, ::SamplerDieMany)). Note that, as usual, SamplerTrivial and SamplerSimple can be used if custom types are not necessary.

        Note: Sampler(rng, x) is simply a shorthand for Sampler(rng, x, Val(Inf)), and Random.Repetition is an alias for Union{Val{1}, Val{Inf}}.

        Creating new generators

        The API is not clearly defined yet, but as a rule of thumb:

        1. any rand method producing "basic" types (isbitstype integer and floating types in Base) should be defined for this specific RNG, if they are needed;
        2. other documented rand methods accepting an AbstractRNG should work out of the box, (provided the methods from 1) what are relied on are implemented), but can of course be specialized for this RNG if there is room for optimization;
        3. copy for pseudo-RNGs should return an independent copy that generates the exact same random sequence as the original from that point when called in the same way. When this is not feasible (e.g. hardware-based RNGs), copy must not be implemented.

        Concerning 1), a rand method may happen to work automatically, but it's not officially supported and may break without warnings in a subsequent release.

        To define a new rand method for an hypothetical MyRNG generator, and a value specification s (e.g. s == Int, or s == 1:10) of type S==typeof(s) or S==Type{s} if s is a type, the same two methods as we saw before must be defined:

        1. Sampler(::Type{MyRNG}, ::S, ::Repetition), which returns an object of type say SamplerS
        2. rand(rng::MyRNG, sp::SamplerS)

        It can happen that Sampler(rng::AbstractRNG, ::S, ::Repetition) is already defined in the Random module. It would then be possible to skip step 1) in practice (if one wants to specialize generation for this particular RNG type), but the corresponding SamplerS type is considered as internal detail, and may be changed without warning.

        Specializing array generation

        In some cases, for a given RNG type, generating an array of random values can be more efficient with a specialized method than by merely using the decoupling technique explained before. This is for example the case for MersenneTwister, which natively writes random values in an array.

        To implement this specialization for MyRNG and for a specification s, producing elements of type S, the following method can be defined: rand!(rng::MyRNG, a::AbstractArray{S}, ::SamplerS), where SamplerS is the type of the sampler returned by Sampler(MyRNG, s, Val(Inf)). Instead of AbstractArray, it's possible to implement the functionality only for a subtype, e.g. Array{S}. The non-mutating array method of rand will automatically call this specialization internally.

        Reproducibility

        By using an RNG parameter initialized with a given seed, you can reproduce the same pseudorandom number sequence when running your program multiple times. However, a minor release of Julia (e.g. 1.3 to 1.4) may change the sequence of pseudorandom numbers generated from a specific seed, in particular if MersenneTwister is used. (Even if the sequence produced by a low-level function like rand does not change, the output of higher-level functions like randsubseq may change due to algorithm updates.) Rationale: guaranteeing that pseudorandom streams never change prohibits many algorithmic improvements.

        If you need to guarantee exact reproducibility of random data, it is advisable to simply save the data (e.g. as a supplementary attachment in a scientific publication). (You can also, of course, specify a particular Julia version and package manifest, especially if you require bit reproducibility.)

        Software tests that rely on specific "random" data should also generally either save the data, embed it into the test code, or use third-party packages like StableRNGs.jl. On the other hand, tests that should pass for most random data (e.g. testing A \ (A*x) ≈ x for a random matrix A = randn(n,n)) can use an RNG with a fixed seed to ensure that simply running the test many times does not encounter a failure due to very improbable data (e.g. an extremely ill-conditioned matrix).

        The statistical distribution from which random samples are drawn is guaranteed to be the same across any minor Julia releases.

        diff --git a/dev/stdlib/SHA/index.html b/dev/stdlib/SHA/index.html index 766b7c57..5cde19be 100644 --- a/dev/stdlib/SHA/index.html +++ b/dev/stdlib/SHA/index.html @@ -55,4 +55,4 @@ 0x19 0xa0 0x8b - 0xc5

        Note that, at the time of this writing, the SHA3 code is not optimized, and as such is roughly an order of magnitude slower than SHA2.

        + 0xc5

        Note that, at the time of this writing, the SHA3 code is not optimized, and as such is roughly an order of magnitude slower than SHA2.

        diff --git a/dev/stdlib/Serialization/index.html b/dev/stdlib/Serialization/index.html index 83e5e553..3d01fcd3 100644 --- a/dev/stdlib/Serialization/index.html +++ b/dev/stdlib/Serialization/index.html @@ -6,4 +6,4 @@ ga('create', 'UA-28835595-9', 'auto'); ga('send', 'pageview', {'page': location.pathname + location.search + location.hash}); -

        序列化

        Serialization.serializeFunction
        serialize(stream::IO, value)

        Write an arbitrary value to a stream in an opaque format, such that it can be read back by deserialize. The read-back value will be as identical as possible to the original, but note that Ptr values are serialized as all-zero bit patterns (NULL).

        An 8-byte identifying header is written to the stream first. To avoid writing the header, construct a Serializer and use it as the first argument to serialize instead. See also Serialization.writeheader.

        The data format can change in minor (1.x) Julia releases, but files written by prior 1.x versions will remain readable. The main exception to this is when the definition of a type in an external package changes. If that occurs, it may be necessary to specify an explicit compatible version of the affected package in your environment. Renaming functions, even private functions, inside packages can also put existing files out of sync. Anonymous functions require special care: because their names are automatically generated, minor code changes can cause them to be renamed. Serializing anonymous functions should be avoided in files intended for long-term storage.

        In some cases, the word size (32- or 64-bit) of the reading and writing machines must match. In rarer cases the OS or architecture must also match, for example when using packages that contain platform-dependent code.

        serialize(filename::AbstractString, value)

        Open a file and serialize the given value to it.

        Julia 1.1

        This method is available as of Julia 1.1.

        Serialization.deserializeFunction
        deserialize(stream)

        Read a value written by serialize. deserialize assumes the binary data read from stream is correct and has been serialized by a compatible implementation of serialize. deserialize is designed for simplicity and performance, and so does not validate the data read. Malformed data can result in process termination. The caller must ensure the integrity and correctness of data read from stream.

        deserialize(filename::AbstractString)

        Open a file and deserialize its contents.

        Julia 1.1

        This method is available as of Julia 1.1.

        Serialization.writeheaderFunction
        Serialization.writeheader(s::AbstractSerializer)

        Write an identifying header to the specified serializer. The header consists of 8 bytes as follows:

        OffsetDescription
        0tag byte (0x37)
        1-2signature bytes "JL"
        3protocol version
        4bits 0-1: endianness: 0 = little, 1 = big
        4bits 2-3: platform: 0 = 32-bit, 1 = 64-bit
        5-7reserved
        +

        序列化

        Serialization.serializeFunction
        serialize(stream::IO, value)

        Write an arbitrary value to a stream in an opaque format, such that it can be read back by deserialize. The read-back value will be as identical as possible to the original, but note that Ptr values are serialized as all-zero bit patterns (NULL).

        An 8-byte identifying header is written to the stream first. To avoid writing the header, construct a Serializer and use it as the first argument to serialize instead. See also Serialization.writeheader.

        The data format can change in minor (1.x) Julia releases, but files written by prior 1.x versions will remain readable. The main exception to this is when the definition of a type in an external package changes. If that occurs, it may be necessary to specify an explicit compatible version of the affected package in your environment. Renaming functions, even private functions, inside packages can also put existing files out of sync. Anonymous functions require special care: because their names are automatically generated, minor code changes can cause them to be renamed. Serializing anonymous functions should be avoided in files intended for long-term storage.

        In some cases, the word size (32- or 64-bit) of the reading and writing machines must match. In rarer cases the OS or architecture must also match, for example when using packages that contain platform-dependent code.

        serialize(filename::AbstractString, value)

        Open a file and serialize the given value to it.

        Julia 1.1

        This method is available as of Julia 1.1.

        Serialization.deserializeFunction
        deserialize(stream)

        Read a value written by serialize. deserialize assumes the binary data read from stream is correct and has been serialized by a compatible implementation of serialize. deserialize is designed for simplicity and performance, and so does not validate the data read. Malformed data can result in process termination. The caller must ensure the integrity and correctness of data read from stream.

        deserialize(filename::AbstractString)

        Open a file and deserialize its contents.

        Julia 1.1

        This method is available as of Julia 1.1.

        Serialization.writeheaderFunction
        Serialization.writeheader(s::AbstractSerializer)

        Write an identifying header to the specified serializer. The header consists of 8 bytes as follows:

        OffsetDescription
        0tag byte (0x37)
        1-2signature bytes "JL"
        3protocol version
        4bits 0-1: endianness: 0 = little, 1 = big
        4bits 2-3: platform: 0 = 32-bit, 1 = 64-bit
        5-7reserved
        diff --git a/dev/stdlib/SharedArrays/index.html b/dev/stdlib/SharedArrays/index.html index 286203b2..6e4359ca 100644 --- a/dev/stdlib/SharedArrays/index.html +++ b/dev/stdlib/SharedArrays/index.html @@ -8,4 +8,4 @@ ga('send', 'pageview', {'page': location.pathname + location.search + location.hash});

        共享数组

        SharedArrays.SharedArrayType
        SharedArray{T}(dims::NTuple; init=false, pids=Int[])
         SharedArray{T,N}(...)

        Construct a SharedArray of a bits type T and size dims across the processes specified by pids - all of which have to be on the same host. If N is specified by calling SharedArray{T,N}(dims), then N must match the length of dims.

        If pids is left unspecified, the shared array will be mapped across all processes on the current host, including the master. But, localindices and indexpids will only refer to worker processes. This facilitates work distribution code to use workers for actual computation with the master process acting as a driver.

        If an init function of the type initfn(S::SharedArray) is specified, it is called on all the participating workers.

        The shared array is valid as long as a reference to the SharedArray object exists on the node which created the mapping.

        SharedArray{T}(filename::AbstractString, dims::NTuple, [offset=0]; mode=nothing, init=false, pids=Int[])
        -SharedArray{T,N}(...)

        Construct a SharedArray backed by the file filename, with element type T (must be a bits type) and size dims, across the processes specified by pids - all of which have to be on the same host. This file is mmapped into the host memory, with the following consequences:

        • The array data must be represented in binary format (e.g., an ASCII format like CSV cannot be supported)

        • Any changes you make to the array values (e.g., A[3] = 0) will also change the values on disk

        If pids is left unspecified, the shared array will be mapped across all processes on the current host, including the master. But, localindices and indexpids will only refer to worker processes. This facilitates work distribution code to use workers for actual computation with the master process acting as a driver.

        mode must be one of "r", "r+", "w+", or "a+", and defaults to "r+" if the file specified by filename already exists, or "w+" if not. If an init function of the type initfn(S::SharedArray) is specified, it is called on all the participating workers. You cannot specify an init function if the file is not writable.

        offset allows you to skip the specified number of bytes at the beginning of the file.

        Distributed.procsMethod
        procs(S::SharedArray)

        Get the vector of processes mapping the shared array.

        SharedArrays.sdataFunction
        sdata(S::SharedArray)

        Returns the actual Array object backing S.

        SharedArrays.indexpidsFunction
        indexpids(S::SharedArray)

        Returns the current worker's index in the list of workers mapping the SharedArray (i.e. in the same list returned by procs(S)), or 0 if the SharedArray is not mapped locally.

        SharedArrays.localindicesFunction
        localindices(S::SharedArray)

        Returns a range describing the "default" indices to be handled by the current process. This range should be interpreted in the sense of linear indexing, i.e., as a sub-range of 1:length(S). In multi-process contexts, returns an empty range in the parent process (or any process for which indexpids returns 0).

        It's worth emphasizing that localindices exists purely as a convenience, and you can partition work on the array among workers any way you wish. For a SharedArray, all indices should be equally fast for each worker process.

        +SharedArray{T,N}(...)

        Construct a SharedArray backed by the file filename, with element type T (must be a bits type) and size dims, across the processes specified by pids - all of which have to be on the same host. This file is mmapped into the host memory, with the following consequences:

        • The array data must be represented in binary format (e.g., an ASCII format like CSV cannot be supported)

        • Any changes you make to the array values (e.g., A[3] = 0) will also change the values on disk

        If pids is left unspecified, the shared array will be mapped across all processes on the current host, including the master. But, localindices and indexpids will only refer to worker processes. This facilitates work distribution code to use workers for actual computation with the master process acting as a driver.

        mode must be one of "r", "r+", "w+", or "a+", and defaults to "r+" if the file specified by filename already exists, or "w+" if not. If an init function of the type initfn(S::SharedArray) is specified, it is called on all the participating workers. You cannot specify an init function if the file is not writable.

        offset allows you to skip the specified number of bytes at the beginning of the file.

        Distributed.procsMethod
        procs(S::SharedArray)

        Get the vector of processes mapping the shared array.

        SharedArrays.sdataFunction
        sdata(S::SharedArray)

        Returns the actual Array object backing S.

        SharedArrays.indexpidsFunction
        indexpids(S::SharedArray)

        Returns the current worker's index in the list of workers mapping the SharedArray (i.e. in the same list returned by procs(S)), or 0 if the SharedArray is not mapped locally.

        SharedArrays.localindicesFunction
        localindices(S::SharedArray)

        Returns a range describing the "default" indices to be handled by the current process. This range should be interpreted in the sense of linear indexing, i.e., as a sub-range of 1:length(S). In multi-process contexts, returns an empty range in the parent process (or any process for which indexpids returns 0).

        It's worth emphasizing that localindices exists purely as a convenience, and you can partition work on the array among workers any way you wish. For a SharedArray, all indices should be equally fast for each worker process.

        diff --git a/dev/stdlib/Sockets/index.html b/dev/stdlib/Sockets/index.html index f72a0291..7037fe35 100644 --- a/dev/stdlib/Sockets/index.html +++ b/dev/stdlib/Sockets/index.html @@ -61,4 +61,4 @@ Stacktrace: [...] nested task error: foo -[...]source
        bind(socket::Union{TCPServer, UDPSocket, TCPSocket}, host::IPAddr, port::Integer; ipv6only=false, reuseaddr=false, kws...)

        Bind socket to the given host:port. Note that 0.0.0.0 will listen on all devices.

        • The ipv6only parameter disables dual stack mode. If ipv6only=true, only an IPv6 stack is created.
        • If reuseaddr=true, multiple threads or processes can bind to the same address without error if they all set reuseaddr=true, but only the last to bind will receive any traffic.
        Sockets.sendFunction
        send(socket::UDPSocket, host::IPAddr, port::Integer, msg)

        Send msg over socket to host:port.

        Sockets.recvFunction
        recv(socket::UDPSocket)

        Read a UDP packet from the specified socket, and return the bytes received. This call blocks.

        Sockets.recvfromFunction
        recvfrom(socket::UDPSocket) -> (host_port, data)

        Read a UDP packet from the specified socket, returning a tuple of (host_port, data), where host_port will be an InetAddr{IPv4} or InetAddr{IPv6}, as appropriate.

        Julia 1.3

        Prior to Julia version 1.3, the first returned value was an address (IPAddr). In version 1.3 it was changed to an InetAddr.

        Sockets.setoptFunction
        setopt(sock::UDPSocket; multicast_loop=nothing, multicast_ttl=nothing, enable_broadcast=nothing, ttl=nothing)

        Set UDP socket options.

        • multicast_loop: loopback for multicast packets (default: true).
        • multicast_ttl: TTL for multicast packets (default: nothing).
        • enable_broadcast: flag must be set to true if socket will be used for broadcast messages, or else the UDP system will return an access error (default: false).
        • ttl: Time-to-live of packets sent on the socket (default: nothing).
        Sockets.nagleFunction
        nagle(socket::Union{TCPServer, TCPSocket}, enable::Bool)

        Enables or disables Nagle's algorithm on a given TCP server or socket.

        Julia 1.3

        This function requires Julia 1.3 or later.

        Sockets.quickackFunction
        quickack(socket::Union{TCPServer, TCPSocket}, enable::Bool)

        On Linux systems, the TCP_QUICKACK is disabled or enabled on socket.

        +[...]source
        bind(socket::Union{TCPServer, UDPSocket, TCPSocket}, host::IPAddr, port::Integer; ipv6only=false, reuseaddr=false, kws...)

        Bind socket to the given host:port. Note that 0.0.0.0 will listen on all devices.

        • The ipv6only parameter disables dual stack mode. If ipv6only=true, only an IPv6 stack is created.
        • If reuseaddr=true, multiple threads or processes can bind to the same address without error if they all set reuseaddr=true, but only the last to bind will receive any traffic.
        Sockets.sendFunction
        send(socket::UDPSocket, host::IPAddr, port::Integer, msg)

        Send msg over socket to host:port.

        Sockets.recvFunction
        recv(socket::UDPSocket)

        Read a UDP packet from the specified socket, and return the bytes received. This call blocks.

        Sockets.recvfromFunction
        recvfrom(socket::UDPSocket) -> (host_port, data)

        Read a UDP packet from the specified socket, returning a tuple of (host_port, data), where host_port will be an InetAddr{IPv4} or InetAddr{IPv6}, as appropriate.

        Julia 1.3

        Prior to Julia version 1.3, the first returned value was an address (IPAddr). In version 1.3 it was changed to an InetAddr.

        Sockets.setoptFunction
        setopt(sock::UDPSocket; multicast_loop=nothing, multicast_ttl=nothing, enable_broadcast=nothing, ttl=nothing)

        Set UDP socket options.

        • multicast_loop: loopback for multicast packets (default: true).
        • multicast_ttl: TTL for multicast packets (default: nothing).
        • enable_broadcast: flag must be set to true if socket will be used for broadcast messages, or else the UDP system will return an access error (default: false).
        • ttl: Time-to-live of packets sent on the socket (default: nothing).
        Sockets.nagleFunction
        nagle(socket::Union{TCPServer, TCPSocket}, enable::Bool)

        Enables or disables Nagle's algorithm on a given TCP server or socket.

        Julia 1.3

        This function requires Julia 1.3 or later.

        Sockets.quickackFunction
        quickack(socket::Union{TCPServer, TCPSocket}, enable::Bool)

        On Linux systems, the TCP_QUICKACK is disabled or enabled on socket.

        diff --git a/dev/stdlib/SparseArrays/index.html b/dev/stdlib/SparseArrays/index.html index 5fe37495..0d7da311 100644 --- a/dev/stdlib/SparseArrays/index.html +++ b/dev/stdlib/SparseArrays/index.html @@ -252,4 +252,4 @@ p::AbstractVector{<:Integer}, q::AbstractVector{<:Integer}, [C::AbstractSparseMatrixCSC{Tv,Ti}]) where {Tv,Ti}

        Bilaterally permute A, storing result PAQ (A[p,q]) in X. Stores intermediate result (AQ)^T (transpose(A[:,q])) in optional argument C if present. Requires that none of X, A, and, if present, C alias each other; to store result PAQ back into A, use the following method lacking X:

        permute!(A::AbstractSparseMatrixCSC{Tv,Ti}, p::AbstractVector{<:Integer},
                  q::AbstractVector{<:Integer}[, C::AbstractSparseMatrixCSC{Tv,Ti},
        -         [workcolptr::Vector{Ti}]]) where {Tv,Ti}

        X's dimensions must match those of A (size(X, 1) == size(A, 1) and size(X, 2) == size(A, 2)), and X must have enough storage to accommodate all allocated entries in A (length(rowvals(X)) >= nnz(A) and length(nonzeros(X)) >= nnz(A)). Column-permutation q's length must match A's column count (length(q) == size(A, 2)). Row-permutation p's length must match A's row count (length(p) == size(A, 1)).

        C's dimensions must match those of transpose(A) (size(C, 1) == size(A, 2) and size(C, 2) == size(A, 1)), and C must have enough storage to accommodate all allocated entries in A (length(rowvals(C)) >= nnz(A) and length(nonzeros(C)) >= nnz(A)).

        For additional (algorithmic) information, and for versions of these methods that forgo argument checking, see (unexported) parent methods unchecked_noalias_permute! and unchecked_aliasing_permute!.

        See also permute.

        + [workcolptr::Vector{Ti}]]) where {Tv,Ti}

        X's dimensions must match those of A (size(X, 1) == size(A, 1) and size(X, 2) == size(A, 2)), and X must have enough storage to accommodate all allocated entries in A (length(rowvals(X)) >= nnz(A) and length(nonzeros(X)) >= nnz(A)). Column-permutation q's length must match A's column count (length(q) == size(A, 2)). Row-permutation p's length must match A's row count (length(p) == size(A, 1)).

        C's dimensions must match those of transpose(A) (size(C, 1) == size(A, 2) and size(C, 2) == size(A, 1)), and C must have enough storage to accommodate all allocated entries in A (length(rowvals(C)) >= nnz(A) and length(nonzeros(C)) >= nnz(A)).

        For additional (algorithmic) information, and for versions of these methods that forgo argument checking, see (unexported) parent methods unchecked_noalias_permute! and unchecked_aliasing_permute!.

        See also permute.

        diff --git a/dev/stdlib/Statistics/index.html b/dev/stdlib/Statistics/index.html index eb240242..3363bae3 100644 --- a/dev/stdlib/Statistics/index.html +++ b/dev/stdlib/Statistics/index.html @@ -123,4 +123,4 @@ 18.000000000000004 julia> quantile(skipmissing([1, 10, missing]), 0.5) -5.5 +5.5 diff --git a/dev/stdlib/TOML/index.html b/dev/stdlib/TOML/index.html index e95ed3f7..12abcb60 100644 --- a/dev/stdlib/TOML/index.html +++ b/dev/stdlib/TOML/index.html @@ -82,4 +82,4 @@ parse(p::Parser, x::Union{AbstractString, IO})

        Parse the string or stream x, and return the resulting table (dictionary). Throw a ParserError upon failure.

        See also TOML.tryparse.

        TOML.parsefileFunction
        parsefile(f::AbstractString)
         parsefile(p::Parser, f::AbstractString)

        Parse file f and return the resulting table (dictionary). Throw a ParserError upon failure.

        See also TOML.tryparsefile.

        TOML.tryparseFunction
        tryparse(x::Union{AbstractString, IO})
         tryparse(p::Parser, x::Union{AbstractString, IO})

        Parse the string or stream x, and return the resulting table (dictionary). Return a ParserError upon failure.

        See also TOML.parse.

        TOML.tryparsefileFunction
        tryparsefile(f::AbstractString)
        -tryparsefile(p::Parser, f::AbstractString)

        Parse file f and return the resulting table (dictionary). Return a ParserError upon failure.

        See also TOML.parsefile.

        TOML.printFunction
        print([to_toml::Function], io::IO [=stdout], data::AbstractDict; sorted=false, by=identity)

        Write data as TOML syntax to the stream io. If the keyword argument sorted is set to true, sort tables according to the function given by the keyword argument by.

        The following data types are supported: AbstractDict, Integer, AbstractFloat, Bool, Dates.DateTime, Dates.Time, Dates.Date. Note that the integers and floats need to be convertible to Float64 and Int64 respectively. For other data types, pass the function to_toml that takes the data types and returns a value of a supported type.

        TOML.ParserType
        Parser()

        Constructor for a TOML Parser. Note that in most cases one does not need to explicitly create a Parser but instead one directly use use TOML.parsefile or TOML.parse. Using an explicit parser will however reuse some internal data structures which can be beneficial for performance if a larger number of small files are parsed.

        TOML.ParserErrorType
        ParserError

        Type that is returned from tryparse and tryparsefile when parsing fails. It contains (among others) the following fields:

        • pos, the position in the string when the error happened
        • table, the result that so far was successfully parsed
        • type, an error type, different for different types of errors
        +tryparsefile(p::Parser, f::AbstractString)

        Parse file f and return the resulting table (dictionary). Return a ParserError upon failure.

        See also TOML.parsefile.

        TOML.printFunction
        print([to_toml::Function], io::IO [=stdout], data::AbstractDict; sorted=false, by=identity)

        Write data as TOML syntax to the stream io. If the keyword argument sorted is set to true, sort tables according to the function given by the keyword argument by.

        The following data types are supported: AbstractDict, Integer, AbstractFloat, Bool, Dates.DateTime, Dates.Time, Dates.Date. Note that the integers and floats need to be convertible to Float64 and Int64 respectively. For other data types, pass the function to_toml that takes the data types and returns a value of a supported type.

        TOML.ParserType
        Parser()

        Constructor for a TOML Parser. Note that in most cases one does not need to explicitly create a Parser but instead one directly use use TOML.parsefile or TOML.parse. Using an explicit parser will however reuse some internal data structures which can be beneficial for performance if a larger number of small files are parsed.

        TOML.ParserErrorType
        ParserError

        Type that is returned from tryparse and tryparsefile when parsing fails. It contains (among others) the following fields:

        • pos, the position in the string when the error happened
        • table, the result that so far was successfully parsed
        • type, an error type, different for different types of errors
        diff --git a/dev/stdlib/Test/index.html b/dev/stdlib/Test/index.html index 874d8d36..1980d77a 100644 --- a/dev/stdlib/Test/index.html +++ b/dev/stdlib/Test/index.html @@ -245,4 +245,4 @@ end

        Test utilities

        Test.GenericArrayType

        The GenericArray can be used to test generic array APIs that program to the AbstractArray interface, in order to ensure that functions can work with array types besides the standard Array type.

        Test.GenericDictType

        The GenericDict can be used to test generic dict APIs that program to the AbstractDict interface, in order to ensure that functions can work with associative types besides the standard Dict type.

        Test.GenericOrderType

        The GenericOrder can be used to test APIs for their support of generic ordered types.

        Test.GenericSetType

        The GenericSet can be used to test generic set APIs that program to the AbstractSet interface, in order to ensure that functions can work with set types besides the standard Set and BitSet types.

        Test.GenericStringType

        The GenericString can be used to test generic string APIs that program to the AbstractString interface, in order to ensure that functions can work with string types besides the standard String type.

        Test.detect_ambiguitiesFunction
        detect_ambiguities(mod1, mod2...; recursive=false,
                                           ambiguous_bottom=false,
                                           allowed_undefineds=nothing)

        Returns a vector of (Method,Method) pairs of ambiguous methods defined in the specified modules. Use recursive=true to test in all submodules.

        ambiguous_bottom controls whether ambiguities triggered only by Union{} type parameters are included; in most cases you probably want to set this to false. See Base.isambiguous.

        See Test.detect_unbound_args for an explanation of allowed_undefineds.

        Julia 1.8

        allowed_undefineds requires at least Julia 1.8.

        Test.detect_unbound_argsFunction
        detect_unbound_args(mod1, mod2...; recursive=false, allowed_undefineds=nothing)

        Returns a vector of Methods which may have unbound type parameters. Use recursive=true to test in all submodules.

        By default, any undefined symbols trigger a warning. This warning can be suppressed by supplying a collection of GlobalRefs for which the warning can be skipped. For example, setting

        allow_undefineds = Set([GlobalRef(Base, :active_repl),
        -                        GlobalRef(Base, :active_repl_backend)])

        would suppress warnings about Base.active_repl and Base.active_repl_backend.

        Julia 1.8

        allowed_undefineds requires at least Julia 1.8.

        + GlobalRef(Base, :active_repl_backend)])

        would suppress warnings about Base.active_repl and Base.active_repl_backend.

        Julia 1.8

        allowed_undefineds requires at least Julia 1.8.

        diff --git a/dev/stdlib/UUIDs/index.html b/dev/stdlib/UUIDs/index.html index f21193ac..655e6781 100644 --- a/dev/stdlib/UUIDs/index.html +++ b/dev/stdlib/UUIDs/index.html @@ -19,4 +19,4 @@ julia> u5 = uuid5(u4, "julia") UUID("086cc5bb-2461-57d8-8068-0aed7f5b5cd1")
        UUIDs.uuid_versionFunction
        uuid_version(u::UUID) -> Int

        Inspects the given UUID and returns its version (see RFC 4122).

        Examples

        julia> uuid_version(uuid4())
        -4
        +4 diff --git a/dev/stdlib/Unicode/index.html b/dev/stdlib/Unicode/index.html index 54627a14..40d38829 100644 --- a/dev/stdlib/Unicode/index.html +++ b/dev/stdlib/Unicode/index.html @@ -21,4 +21,4 @@ "julia" julia> Unicode.normalize("JúLiA", stripmark=true) -"JuLiA"
        Julia 1.8

        The chartransform keyword argument requires Julia 1.8.

        Unicode.graphemesFunction
        graphemes(s::AbstractString) -> GraphemeIterator

        Returns an iterator over substrings of s that correspond to the extended graphemes in the string, as defined by Unicode UAX #29. (Roughly, these are what users would perceive as single characters, even though they may contain more than one codepoint; for example a letter combined with an accent mark is a single grapheme.)

        +"JuLiA"
        Julia 1.8

        The chartransform keyword argument requires Julia 1.8.

        Unicode.graphemesFunction
        graphemes(s::AbstractString) -> GraphemeIterator

        Returns an iterator over substrings of s that correspond to the extended graphemes in the string, as defined by Unicode UAX #29. (Roughly, these are what users would perceive as single characters, even though they may contain more than one codepoint; for example a letter combined with an accent mark is a single grapheme.)