Documenting Functions and Macros
Source:vignettes/documenting-functions-macros.Rmd
documenting-functions-macros.RmdArl has two ways to attach documentation to functions and macros:
;;' annotation comments (used at definition time) and the
doc! builtin (used at runtime). Both produce the same
arl_doc attribute, which help and
doc read.
Annotation comments (;;')
Annotation comments use the ;;' prefix and support
roxygen-like tags. Place them immediately before a define
or defmacro:
arl> ;;' @description Compute the square of x.
arl> ;;' @examples
arl> ;;' (square 3) ; => 9
arl> ;;' (square -2) ; => 4
arl> ;;' @seealso cube, expt
arl> ;;' @note Pure function; no side effects.
arl> (define square
arl> (lambda (x) (* x x)))
#> <function>
The same syntax works for macros:
arl> ;;' @description Execute body only when condition is false.
arl> ;;' @examples
arl> ;;' (unless #f (display "ran\n"))
arl> (defmacro unless (condition . body)
arl> `(if (not ,condition) (begin ,@body)))
Supported tags
| Tag | Purpose |
|---|---|
@description |
One-line or multi-line description. |
@examples |
One or more example expressions (one per continuation line). |
@seealso |
Comma-separated list of related function names. |
@note |
Additional notes (caveats, performance, history). |
@signature |
Override the auto-detected call signature. |
@section |
Section heading for grouping functions in generated docs. |
Multi-line content is written with continuation ;;'
lines:
;;' @description Concatenate strings with a separator.
;;' Accepts any number of string arguments.
;;' @examples
;;' (string-join ", " '("a" "b" "c")) ; => "a, b, c"
;;' (string-join "" '("x" "y")) ; => "xy"
(define string-join ...)The compiler reads ;;' blocks at compile time and bakes
the resulting documentation into the definition, so no runtime overhead
is incurred. This is the recommended way to document functions, macros,
and module exports.
Runtime documentation with doc!
doc! attaches documentation fields to an already-defined
function or macro. It is useful for interactive work, dynamically
generated definitions, or adding fields incrementally:
arl> (define double (lambda (x) (* x 2)))
#> <function>
arl> ; Set just the description
arl> (doc! double "Double the input value.")
#> <function>
arl> ; Set specific fields with keyword arguments
arl> (doc! double :examples "(double 3) ; => 6")
#> <function>
arl> (doc! double :note "Pure function.")
#> <function>
arl> ; Set multiple fields at once
arl> (doc! double :description "Double x." :examples "(double 5) ; => 10")
#> <function>
doc! merges with existing documentation
— setting :examples does not erase a previously set
:description.
Retrieving documentation with doc
doc reads fields from a function’s documentation:
arl> (doc double) ; => "Double x." (description, the default)
#> "Double x."
arl> (doc double "examples") ; => "(double 5) ; => 10"
#> "(double 5) ; => 10"
arl> (doc double "note") ; => "Pure function."
#> "Pure function."
arl> (doc double "all") ; => named list of all fields
#> (:description "Double x." :examples "(double 5) ; => 10" :note "Pure function.")
Which mechanism to use
| Situation | Use |
|---|---|
Defining a function or macro in a .arl source file |
;;' annotations |
| Attaching docs interactively in the REPL |
doc! or ;;'
|
| Building docs dynamically from data |
doc! with keyword args |
| Reading docs programmatically | doc |
| Looking up docs as a user | help |
Both ;;' and doc! produce the same
arl_doc attribute, so help and
doc work identically regardless of how the documentation
was attached.