Documentation

Accessing Documentation

Документацию можно получить в REPL или по адресу IJulia, набрав ? и затем имя функции или макроса, и нажав Enter. Например,

?cos
?@time
?r""

покажет документацию для соответствующей функции, макроса или строкового макроса соответственно. Большинство сред Julia предоставляют способ доступа к документации напрямую:

  • VS Code показывает документацию, когда вы наводите курсор на имя функции. Вы также можете использовать панель Julia в боковой панели для поиска документации.
  • В Pluto откройте панель "Live Docs" в правом нижнем углу.
  • В Juno с помощью Ctrl-J, Ctrl-D будет показана документация для объекта под курсором.

Docs.hasdoc(module, name)::Bool говорит о том, имеет ли имя строку документации. Docs.undocumented_names(module; all) возвращает недокументированные имена в модуле.

Writing Documentation

Julia позволяет разработчикам пакетов и пользователям легко документировать функции, типы и другие объекты с помощью встроенной системы документации.

Основной синтаксис прост: любая строка, appearing just before an object (function, macro, type or instance) будет интерпретироваться как документация для него (они называются docstrings). Обратите внимание, что между docstring и документируемым объектом не должно быть пустых строк или комментариев. Вот базовый пример:

"Tell whether there are too foo items in the array."
foo(xs::Array) = ...

Документация интерпретируется как Markdown, поэтому вы можете использовать отступы и кодовые блоки для разделения примеров кода от текста. Технически, любой объект может быть связан с любым другим в качестве метаданных; Markdown является стандартным, но можно создать и другие строковые макросы и передать их в макрос @doc так же хорошо.

Note

Поддержка Markdown реализована в стандартной библиотеке Markdown, а полный список поддерживаемого синтаксиса можно увидеть в documentation.

Пожалуйста, вставьте текст, который вы хотите перевести.

"""
    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) ...

Как в приведенном выше примере, мы рекомендуем следовать некоторым простым соглашениям при написании документации:

  1. Всегда показывайте сигнатуру функции в верхней части документации с отступом в четыре пробела, чтобы она отображалась как код 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 ниже).

  2. Включите одно предложение, описывающее, что делает функция или что представляет объект, после упрощенного блока сигнатуры. При необходимости предоставьте больше деталей во втором абзаце, после пустой строки.

    Однострочное предложение должно использовать повелительное наклонение ("Сделай это", "Верни то") вместо третьего лица (не пишите "Возвращает длину..."). Оно должно заканчиваться точкой. Если смысл функции нельзя легко резюмировать, может быть полезно разделить её на отдельные составные части (это не следует воспринимать как абсолютное требование для каждого отдельного случая).

  3. Не повторяй себя.

    Поскольку имя функции указано в сигнатуре, нет необходимости начинать документацию с "Функция bar...": переходите сразу к сути. Аналогично, если сигнатура указывает типы аргументов, упоминание их в описании является избыточным.

  4. Предоставляйте список аргументов только в действительно необходимых случаях.

    Для простых функций часто яснее упомянуть роль аргументов непосредственно в описании цели функции. Список аргументов только повторял бы информацию, уже предоставленную в другом месте. Однако предоставление списка аргументов может быть хорошей идеей для сложных функций с множеством аргументов (в частности, аргументов с ключевыми словами). В этом случае вставьте его после общего описания функции, под заголовком # Arguments, с одним - маркером для каждого аргумента. Список должен упоминать типы и значения по умолчанию (если таковые имеются) аргументов:

    ```julia """ ...

    Arguments

    • n::Integer: the number of elements to compute.
    • dim::Integer=1: the dimensions along which to perform the computation.

    ... """ ```

  5. Предоставьте подсказки к связанным функциям.

    Иногда существуют функции, связанные с функциональностью. Чтобы увеличить обнаруживаемость, пожалуйста, предоставьте короткий список этих функций в абзаце См. также.

    See also [`bar!`](@ref), [`baz`](@ref), [`baaz`](@ref).

  6. Include any code examples in an # Examples section.

    Примеры должны, когда это возможно, быть написаны в виде doctests. Doctest — это огражденный кодовый блок (см. Code blocks), начинающийся с ```jldoctest и содержащий любое количество подсказок julia> вместе с вводом и ожидаемыми выводами, которые имитируют REPL Julia.

    !!! note Доктесты включены с помощью Documenter.jl. Для более подробной документации смотрите документацию manual.

Например, в следующем документированном строке переменная `a` определяется, и ожидаемый результат, как он отображается в REPL Julia, появляется позже:

````julia
"""
Some nice documentation here.

# Examples
```jldoctest
julia> a = [1 2; 3 4]
2×2 Array{Int64,2}:
 1  2
 3  4
```
"""
````

!!! warning
    Вызов `rand` и других функций, связанных с генерацией случайных чисел, следует избегать в doctests, так как они не будут производить последовательные результаты в разных сессиях Julia. Если вы хотите продемонстрировать функциональность, связанную с генерацией случайных чисел, одним из вариантов является явное создание и инициализация вашего собственного объекта RNG (см. [`Random`](@ref Random-Numbers)) и передача его в функции, которые вы тестируете.

    Размер слова операционной системы ([`Int32`](@ref) или [`Int64`](@ref)) а также различия в разделителях путей (`/` или `\`) также повлияют на воспроизводимость некоторых doctests.

    Обратите внимание, что пробелы в вашем doctest имеют значение! Doctest завершится неудачей, если вы неправильно выровняете вывод красивой печати массива, например.


Вы можете затем выполнить `make -C doc doctest=true`, чтобы запустить все doctests в руководстве и документации API Julia, что обеспечит работу вашего примера.

Чтобы указать, что результат вывода обрезан, вы можете написать `[...]` на строке, где следует остановить проверку. Это полезно для скрытия трассировки стека (которая содержит непостоянные ссылки на строки кода julia), когда doctest показывает, что было выброшено исключение, например:

````julia
```jldoctest
julia> div(1, 0)
ERROR: DivideError: integer division error
[...]
```
````

Примеры, которые нельзя протестировать, должны быть написаны в огражденных кодовых блоках, начинающихся с ````` ```julia`````, чтобы они правильно выделялись в сгенерированной документации.

!!! tip
    Где это возможно, примеры должны быть **самодостаточными** и **выполнимыми**, чтобы читатели могли попробовать их без необходимости включать какие-либо зависимости.
  1. Используйте обратные кавычки для обозначения кода и уравнений.

    Идентификаторы Julia и фрагменты кода всегда должны быть заключены в обратные кавычки `, чтобы обеспечить подсветку. Уравнения в синтаксисе LaTeX можно вставлять между двойными обратными кавычками ``. Используйте символы Unicode вместо их последовательности экранирования LaTeX, т.е. ``α = 1`` вместо ``\\alpha = 1``.

  2. Place the starting and ending """ characters on lines by themselves.

    Пишите:

    ```julia """ ...

    ... """ f(x, y) = ... ```

    вместо:

    ```julia """...

    ...""" f(x, y) = ... ```

    Это делает более ясным, где начинаются и заканчиваются строки документации.

  3. Уважайте ограничение длины строки, используемое в окружающем коде.

    Докстринги редактируются с использованием тех же инструментов, что и код. Поэтому должны применяться те же соглашения. Рекомендуется, чтобы строки имели ширину не более 92 символов.

  4. Provide information allowing custom types to implement the function in an # Implementation section. These implementation details are intended for developers rather than users, explaining e.g. which functions should be overridden and which functions automatically use appropriate fallbacks. Such details are best kept separate from the main description of the function's behavior.

  5. Для длинных строк документации рассмотрите возможность разделения документации с помощью заголовка # Расширенная помощь. Обычный режим помощи будет показывать только материал выше заголовка; вы можете получить доступ к полной помощи, добавив '?' в начале выражения (т.е. "??foo", а не "?foo").

Functions & Methods

Функции в 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, которую, конечно, можно переопределить для пользовательских типов.

Advanced Usage

Макрос @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

добавит документацию к f(x), когда condition() будет true. Обратите внимание, что даже если 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

Dynamic documentation

Иногда соответствующая документация для экземпляра типа зависит от значений полей этого экземпляра, а не только от самого типа. В таких случаях вы можете добавить метод к 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 будет отображать "Документация для MyType со значением 1", в то время как ?y будет отображать "Документация для MyType со значением 2".

Syntax Guide

Этот гид предоставляет всесторонний обзор того, как прикрепить документацию ко всем синтаксическим конструкциям Julia, для которых возможно предоставление документации.

В следующих примерах "..." используется для иллюстрации произвольной строки документации.

$ and \ characters

Символы $ и \ по-прежнему интерпретируются как интерполяция строк или начало последовательности экранирования в строках документации. Макрос raw"" вместе с макросом @doc можно использовать, чтобы избежать необходимости экранирования этих символов. Это удобно, когда строки документации содержат примеры исходного кода LaTeX или Julia с интерполяцией:

@doc raw"""
```math
\LaTeX
```
"""
function f end

Functions and Methods

"..."
function f end

"..."
f

Добавляет строку документации "..." к функции f. Первая версия является предпочтительным синтаксисом, однако обе эквивалентны.

"..."
f(x) = x

"..."
function f(x)
    return x
end

"..."
f(x)

Добавляет строку документации "..." к методу f(::Any).

"..."
f(x, y = 1) = x + y

Добавляет строку документации "..." к двум методам, а именно f(::Any) и f(::Any, ::Any).

Macros

"..."
macro m(x) end

Добавляет строку документации "..." к определению макроса @m(::Any).

"..."
:(@m1)

"..."
macro m2 end

Добавляет строку документации "..." к макросам с именами @m1 и @m2.

Types

"..."
abstract type T1 end

"..."
mutable struct T2
    ...
end

"..."
struct T3
    ...
end

Добавляет строку документа "..." к типам T1, T2 и T3.

"..."
T1

"..."
T2

"..."
T3

Добавляет строку документа "..." к типам T1, T2 и T3. Предыдущая версия является предпочтительным синтаксисом, однако обе являются эквивалентными.

"..."
struct T
    "x"
    x
    "y"
    y

    @doc "Inner constructor"
    function T()
        new(...)
    end
end

Добавляет строку документации "..." к типу T, "x" к полю T.x, "y" к полю T.y и "Внутренний конструктор" к внутреннему конструктору T(). Также применимо к типам mutable struct.

Modules

"..."
module M end

module M

"..."
M

end

Добавляет строку документации "..." к Module M. Добавление строки документации выше Module является предпочтительным синтаксисом, однако оба варианта эквивалентны.

"..."
baremodule M
# ...
end

baremodule M

import Base: @doc

"..."
f(x) = x

end

Документирование baremodule, помещая строку документации над выражением, автоматически импортирует @doc в модуль. Эти импорты должны выполняться вручную, когда выражение модуля не документировано.

Global Variables

"..."
const a = 1

"..."
b = 2

"..."
global c = 3

Добавляет строку документации "..." к Bindingам a, b и c.

Bindings используются для хранения ссылки на определённый Symbol в Module, не храня при этом само ссылочное значение.

Note

Когда определение const используется только для определения псевдонима другого определения, как это происходит с функцией div и её псевдонимом ÷ в Base, не документируйте псевдоним, а вместо этого документируйте фактическую функцию.

Если псевдоним задокументирован, а не реальное определение, то система документации (? режим) не вернет строку документации, прикрепленную к псевдониму, когда будет осуществлен поиск реального определения.

Например, вы должны написать

"..."
f(x) = x + 1
const alias = f

вместо

f(x) = x + 1
"..."
const alias = f
"..."
sym

Добавляет строку документации "..." к значению, связанному с sym. Однако предпочтительно, чтобы sym был задокументирован там, где он определен.

Multiple Objects

"..."
a, b

Добавляет строку документации "..." к a и b, каждый из которых должен быть документируемым выражением. Этот синтаксис эквивалентен

"..."
a

"..."
b

Любое количество выражений может быть задокументировано вместе таким образом. Этот синтаксис может быть полезен, когда две функции связаны, такие как немутирующие и мутирующие версии f и f!.

Macro-generated code

"..."
@m expression

Добавляет строку документации "..." к выражению, сгенерированному при расширении @m expression. Это позволяет документировать выражения, украшенные @inline, @noinline, @generated или любым другим макросом, таким же образом, как и неукрашенные выражения.

Авторы макросов должны учитывать, что только макросы, которые генерируют одно выражение, автоматически поддерживают документационные строки. Если макрос возвращает блок, содержащий несколько подвыражений, то подвыражение, которое должно быть задокументировано, должно быть отмечено с помощью макроса @__doc__.

Макрос @enum использует @__doc__, чтобы позволить документировать Enums. Изучение его определения должно служить примером того, как правильно использовать @__doc__.

Core.@__doc__Macro
@__doc__(ex)

Низкоуровневый макрос, используемый для пометки выражений, возвращаемых макросом, которые должны быть задокументированы. Если помечено более одного выражения, то одна и та же строка документации применяется к каждому выражению.

macro example(f)
    quote
        $(f)() = 0
        @__doc__ $(f)(x) = 1
        $(f)(x, y) = 2
    end |> esc
end

@__doc__ не имеет эффекта, когда макрос, использующий его, не документирован.

source