文件
存取文件
可在 REPL 或 IJulia 中輸入 ?
後接函數或巨集名稱,並按下 Enter
來存取文件。例如,
?cos
?@time
?r""
將分別顯示相關函數、巨集或字串巨集的文件。大多數 Julia 環境提供直接存取文件的方法
- VS Code 在您將滑鼠游標移到函數名稱上時會顯示文件。您也可以使用側邊欄中的 Julia 面板來搜尋文件。
- 在 Pluto 中,開啟右下角的「Live Docs」面板。
- 在 Juno 中使用
Ctrl-J, Ctrl-D
將顯示游標下的物件文件。
撰寫文件
Julia 讓套件開發人員和使用者可以透過內建文件系統輕鬆地記錄函數、類型和其他物件。
基本語法很簡單:任何出現在物件(函數、巨集、類型或實例)之前的字串都會被解釋為記錄它(這些稱為文件字串)。請注意,文件字串和所記錄的物件之間不能有空白行或註解。以下是一個基本範例
"Tell whether there are too foo items in the array."
foo(xs::Array) = ...
文件被解釋為 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`.
# Examples
```julia-repl
julia> bar([1, 2], [1, 2])
1
```
"""
function bar(x, y) ...
如同上面的範例,我們建議在撰寫文件時遵循一些簡單的慣例
請務必在文件最上方顯示函數簽章,並使用四個空格縮排,以便列印為 Julia 程式碼。
此簽章可以與 Julia 程式碼中的簽章相同(例如
mean(x::AbstractArray)
),或為簡化形式。如果可行,應以其預設值表示選用參數(例如f(x, y=1)
),遵循實際 Julia 語法。沒有預設值的選用參數應置於括弧中(例如f(x[, y])
和f(x[, y[, z]])
)。另一種解決方案是使用多行:一行不含選用參數,其他行則包含選用參數。此解決方案也可用於記錄給定函數的數個相關方法。當函數接受多個關鍵字參數時,請僅在簽章中包含<keyword arguments>
佔位符(例如f(x; <keyword arguments>)
),並在# Arguments
區段下方提供完整清單(請參閱下方的第 4 點)。在簡化簽章區塊後,請包含一個單行句子,說明函數的作用或物件的表示方式。如果需要,請在空白行後,於第二段提供更多詳細資訊。
記錄函數時,單行句子應使用命令式(「執行此操作」、「傳回那個」),而非第三人稱(請勿撰寫「傳回長度...」)。句子應以句號結尾。如果無法輕易總結函數的意義,將其拆分成可組合的個別部分可能有所幫助(但這不應視為每個案例的絕對要求)。
請勿重複說明。
由於函數名稱是由簽章給出的,因此無需以「函數
bar
...」開始文件說明:直接切入重點。類似地,如果簽章指定參數的類型,在說明中提到它們是多餘的。僅在確實需要時提供參數清單。
對於簡單的函數,通常在函數目的說明中直接提到參數的角色會更清楚。參數清單只會重複其他地方已經提供的資訊。但是,對於具有許多參數(特別是關鍵字參數)的複雜函數,提供參數清單會是個好主意。在這種情況下,在函數的一般說明之後,在
# Arguments
標題下插入它,每個參數有一個-
項目符號。清單應提到參數的類型和預設值(如果有)。""" ... # Arguments - `n::Integer`: the number of elements to compute. - `dim::Integer=1`: the dimensions along which to perform the computation. ... """
提供與相關函數的提示。
有時會有相關功能的函數。為了增加可發現性,請在
See also
段落中提供這些函數的簡短清單。See also [`bar!`](@ref), [`baz`](@ref), [`baaz`](@ref).
在
# Examples
區段中包含任何程式碼範例。範例應盡可能寫成 doctests。doctest 是以
```jldoctest
開頭的圍欄式程式碼區塊(請參閱 程式碼區塊),包含任意數量的julia>
提示,以及輸入和預期的輸出,模擬 Julia REPL。注意 Doctests 由
Documenter.jl
啟用。有關更詳細的文件說明,請參閱 Documenter 的 手冊。例如,在以下文件字串中,定義了一個變數
a
,然後出現預期的結果,就像在 Julia REPL 中列印的一樣""" Some nice documentation here. # Examples ```jldoctest julia> a = [1 2; 3 4] 2×2 Array{Int64,2}: 1 2 3 4 ``` """
警告 然後您可以執行
make -C doc doctest=true
以執行 Julia 手冊和 API 文件中的所有 doctest,這將確保您的範例有效。若要指出輸出結果已截斷,您可以在檢查應停止的行中寫入
[...]
。當 doctest 顯示已引發例外時,這對於隱藏堆疊追蹤(包含對 julia 程式碼行的非永久性參考)很有用,例如```jldoctest julia> div(1, 0) ERROR: DivideError: integer division error [...] ```
不可測試的範例應寫在以
```julia
開頭的圍欄式程式碼區塊中,以便在產生的文件中正確地加以突顯。提示 範例應盡可能自給自足且可執行,以便讀者能夠在不包含任何依賴項的情況下試用它們。
使用反引號來識別程式碼和方程式。
Julia 識別碼和程式碼摘錄應始終出現在反引號
`
之間,以啟用突顯。LaTeX 語法中的方程式可以插入在雙反引號``
之間。使用 Unicode 字元,而不是它們的 LaTeX 逸出序列,即``α = 1``
而不是``\\alpha = 1``
。將開始和結束的
"""
字元放在單獨的行上。也就是說,寫
""" ... ... """ f(x, y) = ...
而不是
"""... ...""" f(x, y) = ...
這使得文件字串的開始和結束位置更清楚。
遵守周圍程式碼使用的行長度限制。
文件字串使用與程式碼相同的工具編輯。因此,應套用相同的慣例。建議每行寬度最多為 92 個字元。
在
# Implementation
區段提供資訊,讓自訂類型可以在函式中實作。這些實作細節是針對開發人員而非使用者,例如說明應覆寫哪些函式,以及哪些函式會自動使用適當的後備。此類細節最好與函式行為的主要說明分開。對於較長的說明文件,請考慮使用
# Extended help
標題分割說明文件。典型的說明模式只會顯示標題上方的資料;您可以在表達式的開頭加上「?」來存取完整說明(也就是「??foo」而不是「?foo」)。
函式與方法
Julia 中的函式可能有多個實作,稱為方法。雖然讓一般函式只有一個目的會是很好的做法,但 Julia 允許在必要時個別說明方法。一般來說,只應說明最一般的函式,甚至函式本身(也就是透過 function bar end
建立的物件,不含任何方法)。只有當特定方法的行為與較一般的方法不同時,才應說明該方法。無論如何,它們不應重複其他地方提供的資訊。例如
"""
*(x, y, z...)
Multiplication operator. `x * y * z *...` calls this function with multiple
arguments, i.e. `*(x, y, z...)`.
"""
function *(x, y, z...)
# ... [implementation sold separately] ...
end
"""
*(x::AbstractString, y::AbstractString, z::AbstractString...)
When applied to strings, concatenates them.
"""
function *(x::AbstractString, y::AbstractString, z::AbstractString...)
# ... [insert secret sauce here] ...
end
help?> *
search: * .*
*(x, y, z...)
Multiplication operator. x * y * z *... calls this function with multiple
arguments, i.e. *(x,y,z...).
*(x::AbstractString, y::AbstractString, z::AbstractString...)
When applied to strings, concatenates them.
在擷取通用函數文件時,每個方法的元資料會與 catdoc
函數串接,當然也可以為自訂類型覆寫此函數。
進階用法
@doc
巨集會將其第一個引數與第二個引數關聯在稱為 META
的每個模組字典中。
為了讓撰寫文件更輕鬆,剖析器會特別處理巨集名稱 @doc
:如果對 @doc
的呼叫只有一個引數,但另一個表達式出現在單行中斷後,則會將該額外表達式新增為巨集的引數。因此,剖析器會將下列語法剖析為對 @doc
的 2 個引數呼叫
@doc raw"""
...
"""
f(x) = x
這樣就能使用除了正常字串文字 (例如 raw""
字串巨集) 以外的表達式作為文件字串。
當用於擷取文件時,@doc
巨集 (或等同的 doc
函數) 會搜尋所有 META
字典,以取得與給定物件相關的元資料並傳回。傳回的物件 (例如一些 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)
所示
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
動態文件
有時,類型實例的適當文件取決於該實例的欄位值,而不仅仅取決於類型本身。在這些情況下,您可以為自訂類型新增一個方法到 Docs.getdoc
,以逐實例傳回文件。例如,
struct MyType
value::Int
end
Docs.getdoc(t::MyType) = "Documentation for MyType with value $(t.value)"
x = MyType(1)
y = MyType(2)
?x
會顯示「值為 1 的 MyType 文件」,而 ?y
會顯示「值為 2 的 MyType 文件」。
語法指南
本指南提供全面的概觀,說明如何將文件附加到所有 Julia 語法結構,這些結構可以提供文件。
在以下範例中,"..."
用於說明任意文件字串。
$
和 \
字元
$
和 \
字元在文件字串中仍解析為字串內插或跳脫序列的開頭。raw""
字串巨集與 @doc
巨集可一同使用,以避免必須跳脫這些字元。當文件字串包含包含內插的 LaTeX 或 Julia 原始碼範例時,這很方便
@doc raw"""
```math
\LaTeX
```
"""
function f end
函式和方法
"..."
function f end
"..."
f
將文件字串 "..."
新增至函式 f
。第一個版本是首選語法,但兩個版本都是等效的。
"..."
f(x) = x
"..."
function f(x)
x
end
"..."
f(x)
將文件字串 "..."
新增至方法 f(::Any)
。
"..."
f(x, y = 1) = x + y
將文件字串 "..."
新增至兩個 Method
,即 f(::Any)
和 f(::Any, ::Any)
。
巨集
"..."
macro m(x) end
將文件字串 "..."
新增至 @m(::Any)
巨集定義。
"..."
:(@m)
將文件字串 "..."
加入名為 @m
的巨集。
類型
"..."
abstract type T1 end
"..."
mutable struct T2
...
end
"..."
struct T3
...
end
將文件字串 "..."
加入類型 T1
、T2
和 T3
。
"..."
struct T
"x"
x
"y"
y
end
將文件字串 "..."
加入類型 T
,將 "x"
加入欄位 T.x
,將 "y"
加入欄位 T.y
。此規則也適用於 mutable struct
類型。
模組
"..."
module M end
module M
"..."
M
end
將文件字串 "..."
加入 Module
M
。建議在 Module
上方加入文件字串,但這兩種語法是等效的。
"..."
baremodule M
# ...
end
baremodule M
import Base: @doc
"..."
f(x) = x
end
透過在表達式上方放置文件字串來記錄 baremodule
,會自動將 @doc
匯入模組。當模組表達式未記錄時,必須手動完成這些匯入。
全域變數
"..."
const a = 1
"..."
b = 2
"..."
global c = 3
將文件字串 "..."
加入 Binding
a
、b
和 c
。
Binding
用於儲存對 Module
中特定 Symbol
的參照,而不會儲存參照值本身。
當 const
定義僅用於定義另一個定義的別名時,例如 Base
中的函式 div
及其別名 ÷
,請勿記錄別名,而應記錄實際函式。
如果記錄別名而非實際定義,則文件系統(?
模式)在搜尋實際定義時,不會傳回附加至別名的文件字串。
例如,您應該撰寫
"..."
f(x) = x + 1
const alias = f
而不是
f(x) = x + 1
"..."
const alias = f
"..."
sym
將文件字串 "..."
新增至與 sym
相關聯的值。不過,建議在定義 sym
的地方記錄文件。
多個物件
"..."
a, b
將文件字串 "..."
新增至 a
和 b
,每個都應該是可以記錄文件運算式。此語法等於
"..."
a
"..."
b
任何數量的運算式都可以用這種方式一起記錄文件。當兩個函數相關聯時,此語法會很有用,例如非變異和變異版本 f
和 f!
。
巨集產生的程式碼
"..."
@m expression
將文件字串 "..."
新增至透過展開 @m expression
產生的運算式。這允許使用 @inline
、@noinline
、@generated
或任何其他巨集裝飾的運算式,以與未裝飾的運算式相同的方式記錄文件。
巨集作者應注意,只有產生單一運算式的巨集才會自動支援文件字串。如果巨集傳回包含多個子運算式的區塊,則必須使用 @__doc__
巨集標記應記錄文件的子運算式。
@enum
巨集利用 @__doc__
來允許記錄文件 Enum
。檢視其定義應作為如何正確使用 @__doc__
的範例。
Core.@__doc__
— 巨集@__doc__(ex)
用於標記巨集所回傳的表達式,並應予以記錄的低階巨集。如果標記了多個表達式,則相同的文件字串會套用至每個表達式。
macro example(f)
quote
$(f)() = 0
@__doc__ $(f)(x) = 1
$(f)(x, y) = 2
end |> esc
end
當使用它的巨集未記錄時,@__doc__
沒有作用。