--- title: "Documenting Functions and Macros" output: arl::arl_html_vignette pkgdown: as_is: true vignette: > %\VignetteIndexEntry{Documenting Functions and Macros} %\VignetteEngine{knitr::rmarkdown} %\VignetteEncoding{UTF-8} --- ```{r setup, include = FALSE} knitr::opts_chunk$set(collapse = TRUE, comment = "#>") arl::register_knitr_engine() ``` Arl 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. ;;' @examples ;;' (square 3) ; => 9 ;;' (square -2) ; => 4 ;;' @seealso cube, expt ;;' @note Pure function; no side effects. (define square (lambda (x) (* x x))) ``` ```{arl, include=FALSE} (assert-equal 9 (square 3)) (assert-equal 4 (square -2)) ``` The same syntax works for macros: ```{arl} ;;' @description Execute body only when condition is false. ;;' @examples ;;' (unless #f (display "ran\n")) (defmacro unless (condition . body) `(if (not ,condition) (begin ,@body))) ``` ```{arl, include=FALSE} (assert-equal 42 (unless #f 42)) (assert-equal #nil (unless #t 42)) ``` ### 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: ```{arl, eval=FALSE} ;;' @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))) ; Set just the description (doc! double "Double the input value.") ; Set specific fields with keyword arguments (doc! double :examples "(double 3) ; => 6") (doc! double :note "Pure function.") ; Set multiple fields at once (doc! double :description "Double x." :examples "(double 5) ; => 10") ``` ```{arl, include=FALSE} (assert-equal 6 (double 3)) (assert-equal 10 (double 5)) ``` `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) (doc double "examples") ; => "(double 5) ; => 10" (doc double "note") ; => "Pure function." (doc double "all") ; => named list of all fields ``` ```{arl, include=FALSE} (assert-equal "Double x." (doc double)) (assert-equal "(double 5) ; => 10" (doc double "examples")) (assert-equal "Pure function." (doc double "note")) (define all-docs (doc double "all")) (assert-equal #t (is.list all-docs)) (assert-equal "Double x." (r-call "[[" (list all-docs "description"))) (assert-equal "(double 5) ; => 10" (r-call "[[" (list all-docs "examples"))) (assert-equal "Pure function." (r-call "[[" (list all-docs "note"))) ``` ## 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.