文件
查阅文件
访问REPL中的文档或https://github.com/JuliaLang/IJulia.jl [IJulia]进入`?'宏或函数的名称之前,并按’Enter’键。 例子::
?cos
?@time
?r""
将显示相应函数、宏和字符串宏的文档。 在大多数Julia环境中,有一种方法可以直接访问文档。
-
https://www.julia-vscode.org /[VS Code]当鼠标指针悬停在函数名上时显示文档。 您还可以在Julia侧边栏中搜索文档。
-
在环境中https://github.com/fonsp/Pluto.jl [Pluto]您可以打开右下角的Live Docs面板(在线文档)。
-
在环境中https://junolab.org [Juno]键盘快捷键"Ctrl-J,Ctrl-D"允许您显示光标所在对象的文档。
"文档。hasdoc(module,name)::Bool`指定名称是否有docstring。 "文档。undocumented_names(module;all)'返回模块中未记录的名称。
编写文档
Julia的内置文档系统允许用户和包开发人员轻松地记录函数、类型和其他对象。
基本语法非常简单:对象(函数、宏、类型或实例)前面的任何字符串都被解释为记录该对象(此类字符串称为_docstring_)。 请注意,docstring和文档化对象之间不应该有空行或注释。 最简单的例子:
"Tell whether there are too foo items in the array."
foo(xs::Array) = ...
文档被解释为https://en.wikipedia.org/wiki/Markdown [Markdown],所以你可以使用填充和边框(`
) 将示例代码与主文本分开。 严格地说,任何对象都可以作为其元数据与任何其他对象相关联。 Markdown只是默认使用,但您可以创建其他宏字符串并将其传递给'@doc’宏。
Markdown支持是通过标准库’Markdown’实现的。 有关支持的语法的完整列表,请参阅 文件。 |
下面是一个仍然基于Markdown的更复杂的例子:
"""
bar(x[, y])
Compute the Bar index between `x` and `y`.
If `y` is unspecified, compute the Bar index between all pairs of columns of `x`.
# Примеры
```julia-repl
julia> bar([1, 2], [1, 2])
1
```
"""
function bar(x, y) ...
上面的示例演示了一些简单的标准,建议在编写文档时遵循这些标准。
-
始终在文档顶部指出函数签名,用四个空格分隔它,以便它作为Julia代码输出。
它可以与Julia代码中的签名相同(例如,
mean(x::AbstractArray)
)或以简化形式指定。 如果可能的话,可选参数应该根据实际的Julia语法提供默认值(即`f(x,y=1))。 没有默认值的可选参数应放在方括号中(即`f(x[,y])`和`f(x[,y[,z]])
)。 另一种选择是使用多行:一个没有可选参数,另一个有它们的指示。 此解决方案还可用于记录特定功能的几种相关方法。 如果函数接受许多命名参数,则在签名中包含替换文本`<关键字参数>`(即`f(x;<关键字参数>))就足够了,然后在
#Arguments`部分提供完整的参数列表(请参阅下面的第4点)。 -
在简化的签名块之后,在一行中描述函数或对象的目的。 如有必要,请输入包含其他信息的第二段,用空行分隔。
文档中功能的单行描述应该是第三人称单数形式的单个句子,没有主语(")。..","返回。..",等等。). 在描述的末尾放置一个句点。 如果很难简单描述函数的目的,将其分成几个部分可能是有意义的(但是,这不是每种情况都必须的)。
-
不要重复你自己。
由于签名已经包括函数名称,因此不需要以"函数`bar`字样开始文档。..",不如开门见山。 同样,如果签名已经指定了参数的类型,那么在描述中提及这些类型将是多余的。
-
仅在确实必要时提供参数列表。
如果函数很简单,通常在其目的的描述中直接指定参数的作用就足够了。 参数列表只会重复其他地方已经给出的信息。 但是,对于具有多个参数(特别是命名参数)的复杂函数,提供它们的列表会很有用。 在这种情况下,在函数的一般描述后的标题`#Arguments`下插入一个参数的项目符号列表(带有`-'标记)。 列表应指定参数的类型及其默认值(如果有)。
""" ... # Аргументы - `n::Integer`: the number of elements to compute. - `dim::Integer=1`: the dimensions along which to perform the computation. ... """
-
提供相关功能的链接。
有时可能会有类似功能的功能。 为了使它们更容易找到,请在"另见"段落中提供此类功能的简短列表。
See also [`bar!`](@ref), [`baz`](@ref), [`baaz`](@ref).
-
在`#Examples`部分中包含代码示例。
如果可能,应该在_doctest_块中提供代码示例。 _doctest_代码块由边框分隔(请参阅 Code Blocks),以`jldoctest"开头,包含任意数量的命令’julia>',输入和预期输出数据模拟Julia的REPL。
对于doctest块,使用以下内容https://github.com/JuliaDocs/Documenter.jl ['文件。jl']。 有关更详细的文档,请参阅https://juliadocs.github.io/Documenter.jl /[手册]文件。
例如,以下docstring行显示变量`a`的定义以及Julia的REPL中的预期结果输出。
""" Some nice documentation here. # Примеры ```jldoctest julia> a = [1 2; 3 4] 2×2 Array{Int64,2}: 1 2 3 4 ``` """
不建议在doctest块中调用`rand`和其他与随机数生成相关的函数,因为它们的输出会因Julia会话而异。 如果您需要演示与随机数生成相关的一些功能,那么作为其中一个选项,您可以显式创建自己的RNG对象(请参阅 `Random'),生成其值并将其传递给doctest中指定的函数。
空间在doctest中很重要! 例如,doctest可能由于数组的结构打印输出的不正确对齐而失败。
然后,您可以使用’make-C doc doctest=true’来执行Julia手册和API文档中的所有doctest块,并验证您的示例是否有效。
如果要显示输出结果的截断,可以输入'[。..]`在检查应该停止的行上。 这允许您在doctest显示抛出异常时隐藏堆栈跟踪(包含对Julia代码行的非永久性引用),例如:
```jldoctest julia> div(1, 0) ERROR: DivideError: integer division error [...] ```
不受测试的示例应该写成以"julia"开头的分隔代码块,以便它们在创建的文档中正确突出。
如果可能的话,例子应该是*隔离*和*工作*,以便读者可以尝试它们,而不包括任何依赖元素。
-
使用backstroke字符来标识代码和表达式。
要使用高亮显示,请始终将Julia Id和代码片段放在backstroke字符之间。 (
`
). LaTeX语法中的方程可以通过双回击来分隔。 (`
). 为此,请使用Unicode字符而不是LaTeX转义序列,即``α=1`而不是
`\\alpha=1`'。 -
首尾字符'"""`必须放在单独的行上。
也就是说,有必要进入:
""" ... ... """ f(x, y) = ...
不应该使用:
"""... ...""" f(x, y) = ...
这将使docstring行开始和结束的位置更清晰。
-
请记住相邻代码中的字符串长度限制。
Docstring字符串的编辑方式与代码相同,因此必须遵循相同的标准。 建议行宽不应超过92个字符。
-
在'#Implementation’部分,提供在自定义类型中实现函数所需的信息。 这些数据不是针对用户的,而是针对开发人员的,因为它们解释了例如应该重新定义哪些功能以及哪些功能自动使用合适的备份选项。 最好将这样的信息与功能的主要描述分开。
-
对于大型文档,建议使用标题"#扩展帮助"分隔文档。 在正常帮助模式下,仅显示此标题上方的材料。 要访问完整的参考数据,请添加另一个"?"在表达式的开头签名(即,而不是"?foo"进入"??foo")。
功能和方法
Julia中的函数可以有许多称为方法的实现。 虽然,作为一项规则,建议使用具有严格一个目的的通用函数,但Julia允许您在必要时单独记录不同的方法。 通常,应该只记录最通用的方法,甚至是函数本身(即,使用"功能栏结束"创建的没有任何方法的对象)。 只有当它们的行为与更通用的行为不同时,才应该记录具体的方法。 无论如何,文档不应重复其他地方已有的信息。 例如:
"""
*(x, y, z...)
Multiplication operator. `x * y * z *...` calls this function with multiple
arguments, i.e. `*(x, y, z...)`.
"""
function *(x, y, z...)
# ... [реализация приведена в другом месте] ...
end
"""
*(x::AbstractString, y::AbstractString, z::AbstractString...)
When applied to strings, concatenates them.
"""
function *(x::AbstractString, y::AbstractString, z::AbstractString...)
# ... [использует здесь особый код] ...
end
help?> *
search: * .*
*(x, y, z...)
乘法运算符。 x*y*z*。.. 用多个调用此函数
参数,即*(x,y,z...).
*(x::AbstractString,y::AbstractString,z::AbstractString...)
当应用于字符串时,将它们连接起来。
当接收通用函数的文档时,使用`catdoc`函数为每个方法连接元数据,当然,可以为自定义类型重新定义该函数。
延长使用
宏'@doc’将其第一个参数的内容绑定到第二个参数,并将其放置在特定模块的`META`字典中。
为了简化编写文档,分析器以一种特殊的方式处理宏"@doc":如果在调用"@doc"中给出了一个参数,但另一个表达式在换行后跟随它,那么这个表达式被认为是宏的第二个参数。 因此,以下语法将被解析为具有两个参数的`@doc`的调用:
@doc raw"""
...
"""
f(x) = x
这使您不仅可以使用常规字符串文字作为docstring,还可以使用其他表达式(例如,宏`raw'"`的字符串)。
当使用宏'@doc`(以及`doc’函数)获取文档时,在所有元字典中搜索与此对象相关的元数据,并返回相应的元数据。 默认情况下,返回的对象(例如某些Markdown内容)是格式化的。 这种操作原理还通过代码简化了与文档系统的交互。 以下是如何为函数的不同版本重用相同的文档。:
@doc "..." foo!
@doc (@doc foo!) foo
Julia元编程函数的使用示例:
for (f, op) in ((:add, :+), (:subtract, :-), (:multiply, :*), (:divide, :/))
@eval begin
$f(a, b) = $op(a, b)
end
end
@doc "`add(a, b)` adds `a` and `b` together" add
@doc "`subtract(a, b)` subtracts `b` from `a`" subtract
当编写不在顶级块中的文档时,例如,在`begin`,if
,for
,let`和内部构造函数中,它应该通过
@doc`添加到系统中。 例如:
if condition()
@doc "..."
f(x) = x
end
此代码在满足条件`condition()(`true
)时添加了`f(x)`的文档。 与此同时,即使函数’f(x)'超出块后区域的边界,其文档也会被保留。
为了简化文档的创建,您可以使用元编程的功能。 当使用字符串插值时,文档字符串中需要一个额外的字符'$,如
$(name name)`所示:
for func in (:day, :dayofmonth)
name = string(func)
@eval begin
@doc """
$($name)(dt::TimeType) -> Int64
The day of month of a `Date` or `DateTime` as an `Int64`.
""" $func(dt::Dates.TimeType)
end
end
语法指南
本指南提供了如何向所有Julia语法结构添加文档的详细概述。
在下面的实施例中,'"。.."'匹配任意docstring字符串。
字符'$'和'\`
字符'$'和'\'将继续被解析为字符串插值或转义序列的开头,包括在docstring字符串中。 为了避免对它们使用转义码,您可以使用宏字符串`raw""`以及宏`@doc`。 当docstring字符串包含带有插值的LaTeX或Julia源代码示例时,这很有用。:
@doc raw"""
```math
\LaTeX
```
"""
function f end
功能和方法
"..."
function f end
"..."
f
添加docstring字符串'"。.."'为函数’f'。 首选语法的第一个版本,但两者都是等价的。
"..."
f(x) = x
"..."
function f(x)
return x
end
"..."
f(x)
添加docstring字符串'"。.."`为方法`f(::Any)'。
"..."
f(x, y = 1) = x + y
添加docstring字符串'"。.."'用于两个方法’f(::Any)'和’f(::Any,::Any)`。
宏
"..."
macro m(x) end
添加docstring字符串'"。.."'来定义宏'@m(::Any)'。
"..."
:(@m1)
"..."
macro m2 end
添加docstring字符串'"。.."为名为
@m1`和'@m2’的宏。
类别
"..." abstract type T1 end "..." mutable struct T2 ... end "..." struct T3 ... end
添加docstring字符串'"。.."表示类型`T1
,`T2`和`T3'。
"..." T1 "..." T2 "..." T3
添加docstring字符串'"。.."表示类型`T1
,`T2`和`T3'。 以前版本的语法是首选,但两者都是等效的。
"..."
struct T
"x"
x
"y"
y
@doc"内部构造函数"
功能T()
新(。..)
结束
结束
添加docstring字符串'"。.."'用于类型’T`,"x"`用于字段`t.x
,`"y"`用于’T’字段。y’和`"内部构造函数"`为内部构造函数’T()'。 也适用于"可变结构"类型。
模块
"..."
module M end
module M
"..."
M
end
添加docstring字符串'"。.."'为模块’M'。 在"模块"上添加docstring的语法是首选,但这两个选项是等价的。
"..."
baremodule M
# ...
end
baremodule M
import Base: @doc
"..."
f(x) = x
end
当通过在表达式上方放置docstring来记录`baremodule`时,宏`@doc’会自动导入到模块中。 如果未记录模块表达式,则必须手动执行此类导入。
全局变量
"..."
const a = 1
"..."
b = 2
"..."
global c = 3
添加字符串docstring'"。.."'表示`A`,b`和`c`的绑定(`Binding
)。
绑定(Binding
)允许您在模块(Module
)中保存指向特定符号(`Symbol')的链接,而无需保存链接的直接值。
当`const`的定义仅为另一个定义指定别名时,例如,就像`Base`中的函数`div`及其别名`÷`的情况一样,需要记录的不是别名,而是函数本身。 如果记录了别名,而不是实际定义,那么在搜索实际定义时,文档系统(模式`?`)不会返回与别名关联的docstring字符串。 例如,你应该写: "'朱莉娅 "…" f(x)=x+1 const别名=f
|
"..."
sym
添加docstring字符串'"。.."`表示与’sym’相关联的值。 但是,建议记录其定义所在的`sym’对象。
多个对象
"..."
a, b
添加docstring字符串'"。.."`表示元素`a’和’b'。 两者都应该是文档可能的表达式。 此语法等效于以下内容。
"..."
a
"..."
b
可以以这种方式记录任意数量的表达式。 当有两个相关函数时,这种语法很有用,例如`f`和`f’的不可变和可变版本!`.
宏生成的代码
"..."
@m expression
添加docstring字符串'"。.."表示打开
@m表达式`时形成的表达式。 这允许您记录前面有`@inline`,@noinline
,`@generated`或任何其他宏的表达式,就像没有宏的表达式一样。
在编写宏时,请记住,只有形成单个表达式的宏才会自动支持docstring。 如果宏返回包含多个嵌套表达式的块,则要记录嵌套表达式,请使用宏标记它。 '@__doc__`。
#
'核心。@__doc__
*-Macro
@__doc__(ex)
低级宏,用于标记应记录的宏返回的表达式。 如果标记了多个表达式,则对每个表达式应用相同的docstring。
macro example(f) quote $(f)() = 0 @__doc__ $(f)(x) = 1 $(f)(x, y) = 2 end |> esc end
'@__doc__'在没有记录使用它的宏时没有效果。