## hahn

### Introduction

Hahn is a mechanism for documenting Scheme in the source-code itself; similar to Doxygen, Javadoc or Roxygen.

As an example, let's take this naïve Fibonacci:

(define(fibonacci n) @("Computes the nth [[http://en.wikipedia.org/wiki/Fibonacci_number|Fibonacci]]." "This naïve algorithm runs in ''O(2^n)''; using e.g. memoization, we could bring it down to ''O(n)''." (n "The nth number to calculate") (@to "integer") (@example "Computing the 6th Fibonnaci number (starting from 0)" (fibonacci 6))) (case n ((0) 0) ((1) 1) (else (+ (fibonacci (- n 1)) (fibonacci (- n 2))))))

It produces the following output:

`fibonacci`

*[procedure]*

`(fibonacci n) → number`

Computes the nth Fibonacci number.

This naïve algorithm runs in *O(2^n)*; using e.g. memoization, we could bring it down to *O(n)*.

`n`- The nth number to calculate

(define(fibonacci n) (case n ((0) 0) ((1) 1) (else (+ (fibonacci (- n 1)) (fibonacci (- n 2))))))

##### Examples

Computing the 6th Fibonnaci number (starting from 0)

(fibonacci 6) => 8

### Syntax

To document definitions, insert a so-called document-expression ("docexpr") after the variable (or variable-formals) and before the body of the definition.

The docexpr is an ampersand-prefixed expression containing a description; and optionally a longer description, parameters, return values and examples.

#### Variables

Variables such as constants and parameters, for example, only require a description:

(definek @("The Boltzmann constant") 1.38e-23)

The general form for variables is therefore something like:

(define<variable> @(<description> [<longer description>]) <expression>)

#### Procedures

Procedures, on the other hand, can provide parameters, return-values and examples; parameters are specified with key-value lists containing the parameter and a description of the parameter; whereas return-values and examples are key-value lists containing the special keys `@to` and `@example` respectively.

(define(add x y) @("Adds two numbers." (x "The augend") (y "The addend") (@to "number") (@example "Adding two imprecise binary numbers" (add #b1# #b1##))) (+ x y))

Notice that `@example` takes a description, too; the general form for procedures is therefore something like:

(define(<variable> <formals>) @(<description> [<longer description>] [(<formal-0> <formal-description-0>) ... (<formal-n> <formal-description-n>)] [(@to <return-type>)] [(@example <example-description> <example-expression-0> ... <example-expression-n>)]))

#### Special tags

`@example`

The `@example` tag is useful for providing examples of procedure-application.

(define(quadratic-diophantine z) @("Finds a solution to the quadratic Diophantine equation x^2 + y^2 = z^2, given z." "Returns two values, x and y." (z "The known side") (@to "number, number") (@example "An example from Arithmetica II.VIII" (quadratic-diophantine 16))) (let*((m (random (inexact->exact (floor (sqrt z))))) (n (sqrt (- z (expt m 2))))) (let((x (- (expt m 2) (expt n 2))) (y (* 2 m n))) (values x y))))

`@example-no-eval`

The `@example-no-eval` tag is also useful for providing examples of procedure-application; the difference is that hahn does not attempt to evaluate them when rendering the documentation.

`@Example-no-eval` is useful when the examples are incomplete or pathological.

(define(find-fermat-counterexample) @("Finds positive integers a, b, c and n > 2 for which a^n + b^n = c^n." (@example-no-eval "Warning: this should never terminate." (find-fermat-counterexample))) ;; The testable range is pretty small. (let((range 8)) (until (let((a (+ (random range) 1)) (b (+ (random range) 1)) (n (+ (random range) 3))) (integer? (expt (+ (expt a n) (expt b n)) (/ 1 n)))))))

`@internal`

The `@internal` tag signifies that the documentation for the given expression should be suppressed; it is useful for internal documentation.

(definecat-alive? @("Qubit representing whether or not our cat is alive" "{{Cat-alive?}} is internal so that observers are forced to use the {{observe!}} procedure." (@internal)) (make-qubit))

`@no-source`

The `@no-source` tag turns off the source-code listing that accompanies documented expressions.

(define(vote! candidate) @("[[http://youtu.be/IoWJkrlptNs|Votes]] for your candidate!" "This black-box voting procedure is the trade-secret of Biedolb, Inc.; the source-code has been suppressed." (candidate "The candidate for which to vote") (@no-source)) (register-vote! 'president-mccain))

`@to`

The `@to` tag is optional and specifies the return value of a procedure; in the absence of `@to`, the return value is considered to be `unspecified`.

This procedure, for instance, has an `unspecified` return type:

(define(entangle! register . qs) @("Entangles qubits in a register." (register "The register in which to entangle") (qs "The qubits to be entangled")) (for-each (lambda(q) (set-register! q register)) qs))

whereas this one returns a specific type:

(define(apply-gate gate . qs) @("Applies the quantum-gate to the qubits." (gate "The quantum gate to apply") (qs "The qubits on which to apply it") (@to "qubit")) (make-qubit (matrix-multiply (apply quantum-state qs) gate)))

#### Top-level directives

Some of the top-level directives deal with metadata already gleaned from the `.meta` file and are therefore redundant; others deal with presentation, and are useful for crafting introductions, &c.

`author`

`Author` is the author of the egg; it overrides `(author "Egg Author")` from the `.meta` file.

@(author "Diophantus of Alexandria")

`description`

`Description` describes the egg; it overrides `(synopsis "Egg synopsis")` from the `.meta` file.

@(description "To divide a given square number into two squares")

`egg`

`Egg` is the name of the egg; it overrides the filename of the `.meta` file (i.e. "name" from `name.meta`).

@(egg "arithmetica")

`email`

`Email` is the author's email; it overrides `(email "author@example.com")` from the `.meta` file.

@(email "diophantus@alexandria.net")

`example`

`Example` is a stand-alone example, as opposed to the `@example` tag that accompanies procedures.

@(example "Riastradh once asked why this does what it does; no one had a satisfactory answer." (let*((yin ((lambda(y) (newline) y) (call/cc call/cc))) (yang ((lambda(y) (write-char #\*) y) (call/cc call/cc)))) (yin yang)))

`example-no-eval`

`Example-no-eval` is a stand-alone, unevaluated example; as opposed to the `@example-no-eval` tag that accompanies procedures.

@(example-no-eval "This will never terminate; thanks, Eli!" ((lambda(x) (x x)) (lambda(x) (x x))))

`heading`

`Heading` designates a section of the documentation right below the level of title.

@(heading "Arithmeticorum Liber II")

`noop`

`Noop` is an artifact required to separate presentation-based directives from source-code that they don't belong to.

For instance:

@(heading "Abstract") @(text "This is the body of the abstract.") @(noop) (definephi @("The heading and text above do not belong to this variable.") (/ (+ 1 (sqrt 5)) 2))

`repo`

`Repo` overrides `(repo "https://example.com/repo.git")` from the `.meta` file.

(TODO: Implement this.)

`source`

`Source` provides a stand-alone source-code listing.

@(text "Through an aggressive heuristic, we've managed to solve the halting problem: let's assume that if it doesn't finish in 1 second, it never will.") @(source (define(terminate? thunk) (let((thread (thread-start! (make-thread thunk)))) (and (thread-join! thread 1 #f) (thread-terminate! thread) #t))))

`subheading`

`Subheading` designates a section of the documentation right below the level of heading.

@(subheading "Quaestio VIII")

`subsubheading`

`Subsubheading` designates a section of the documentation right below the level of subheading.

@(subsubheading "Observatio domini Petri de Fermat")

`text`

`Text` is used for free-form text and can be useful for abstracts and explanatory material.

@(text "I have discovered a truly marvellous proof of this, which this margin is too narrow to contain.")

`title`

`Title` overrides the egg-name as the title of the document.

@(title "Arithmetica")

`username`

`Username` is the username of the author on Chicken's wiki; it overrides `(user "chicken-user")` from the `.meta` file.

@(username "pfermat")

(TODO: Let's rename this `user`.)

### Complete example

To tie everything together, here's a complete example; see the resulting documentation.

#### The `.meta` file

Hahn reads the metadata from the `.meta` file such as: `synopsis`, `author`, `email`, `user`, `repo`, `depends`.

((synopsis "Use the Landauer limit to calculate my program's entropy.") (author "Peter Danenberg") (email "pcd@roxygen.org") (user "klutometis") (repo "https://github.com/klutometis/landauer") (category math) (license "BSD") (depends hahn) (test-depends test) (foreign-depends))

#### The module file

The module file is a suitable place for putting introductory material about the egg; such as background information, abstract, &c.

It is also suitable for a high-level overview of what the module does.

@(heading "Landauer's principle") @(text "[[http://en.wikipedia.org/wiki/Landauer%27s_principle|Landauer's principle]] states that every irreversible operation produces entropy; erasing one bit, for instance, generates at least ''kT'' ln 2 J of heat.") @(text "We can use Landauer's principle to calculate a lower-bound on the energy released by our program, given some number of bit-operations.") @(heading "Documentation") @(noop) (module landauer @("The Landauer module contains contains some constants, parameters and procedures for calculating a lower-bound on the heat-dissipation of programs.") (heat k room-temperature) (import chicken scheme) (include "landauer-core.scm"))

#### The source file

The source file contains the documentation of individual constants, parameters, records, procedures.

(definek @("The Boltzmann constant") 1.38e-23) (defineroom-temperature @("Room temperature in K") (make-parameter 298.15)) (define(heat operations) @("Calculate a lower-bound on the heat dissipated by some number of irreversible bit-operations." "Room-temperature is governed by the [[#room-temperature]] parameter." (operations "The number of irreversible bit-operations") (@to "number")) (* operations k (room-temperature) (log 2)))

#### The `.setup` file

The `.setup` file does two things:

- compiles each extension with
`-X hahn`; and - generates documention.

Extensions should be compiled with `-X hahn`; this strips the documentation from the source before compilation so that the compiler is not confused.

The `hahn` binary from hahn-utils generates the actual documentation; the `hahn` egg provides a convenience macro `run-hahn` so that installation does not fail for users who haven't installed `hahn-utils`.

There is a soft-dependency on the otherwise dependency-heavy egg `hahn-utils`: users don't have to have it unless they want to generate docs themselves, for some reason.

(use hahn setup-helper-mod) (setup-shared-extension-module 'landauer (extension-version "0.0.1") compile-options: '(-X hahn)) (run-hahn -o landauer.wiki landauer.scm landauer-core.scm)

### Limitations

- The repository-awareness is Git-specific.
- The version-awareness is Github-specific.