X-Git-Url: https://git.distorted.org.uk/~mdw/sod/blobdiff_plain/e8d70b1b4abe17f1425aa7b8d4e582cd02372766..1edb774eed8bea3f6dbde5b02db6ecd209394cf8:/doc/misc.tex diff --git a/doc/misc.tex b/doc/misc.tex index 32e2e75..b7ed6e5 100644 --- a/doc/misc.tex +++ b/doc/misc.tex @@ -39,7 +39,8 @@ of these are standard. \begin{describe}{mac} {with-gensyms (@{ @ @! (@ @[@@]) @}^*) \\ \ind @^* \\ - @
^*} + @^* + \-\nlret @^*} Bind each @ (a symbol, not evaluated) to a freshly made gensym whose name is based on the corresponding @ (a string, evaluated), and evaluate the @s as an implicit @|progn| in the resulting environment. @@ -52,7 +53,7 @@ of these are standard. @{ @ @! (@ @[@@]) @}^*) \\ \ind @^* \\ @^* - \nlret @} + \-\nlret @} This is a helper to ensure that macro expansions evaluate their arguments exactly once each, in the correct order. @@ -163,7 +164,8 @@ refer to the same place; but that doesn't work for these locatives. @{ @ @! (@{ @ @! (@ @[@@]) @}^*) @} \\ \ind @^* \\ - @^*} + @^* + \-\nlret @^*} This is a macro which hides the use of locatives from its caller using symbol-macros. @@ -182,7 +184,7 @@ refer to the same place; but that doesn't work for these locatives. An anaphoric macro implicitly binds a well-known name to a value of interest, in the course of doing something else. The concept was popularized by Paul -Graham \cite[FIXME:OnLisp]. +Graham \cite{graham-1993:on-lisp}. The macros described here all bind the variable @|it|. @@ -190,13 +192,13 @@ The macros described here all bind the variable @|it|. The symbol @|it| is exported by the @|sod-utilities| package. \end{describe} -\begin{describe}{mac}{aif @ @ @[@@]} +\begin{describe}{mac}{aif @ @ @[@@] @> @^*} Evaluate the @. If @ is non-nil, then bind @|it| to the resulting value and evaluate the @, returning all of its values. Otherwise, evaluate @, returning all of its values. \end{describe} -\begin{describe}{mac}{aand @^*} +\begin{describe}{mac}{aand @^* @> @^*} Evaluate each @ in turn. If any @ evaluates to nil, then stop and return nil. Each form except the first is evaluated with @|it| bound to the (necessarily non-nil) value of the previous form. If all but the @@ -205,12 +207,12 @@ The macros described here all bind the variable @|it|. (No @|aor| is provided, since @|it| would necessarily be bound to nil.) -\begin{describe}{mac}{awhen @ @^*} +\begin{describe}{mac}{awhen @ @^* @> nil} If @ evaluates to a non-nil value, bind @|it| to that value, and evaluate the @s as an implicit @|progn|. Otherwise, return nil. \end{describe} -\begin{describe}{mac}{acond @{ (@ @^*) @}^*} +\begin{describe}{mac}{acond @{ (@ @^*) @}^* @> @^*} Evaluate each @ in turn, until one of them produces a non-nil value. If the @ is followed by one or more @s, then bind @|it| to the non-nil value of the @ and evaluate the @s as @@ -219,21 +221,27 @@ The macros described here all bind the variable @|it|. \end{describe} \begin{describe*} - {\dhead{mac} - {acase @ @{ (@{ @ @! (@^*) @} @^*) @}^*} - \dhead{mac} - {aecase @ @{ (@{ @ @! (@^*) @} @^*) @}^*} - \dhead{mac}{atypecase @ @{ (@ @^*) @}^*} - \dhead{mac}{aetypecase @ @{ (@ @^*) @}^*}} + {\dhead{mac}{acase @ + @{ (@{ @ @! (@^*) @} @^*) @}^* + @> @^*} + \dhead{mac}{aecase @ + @{ (@{ @ @! (@^*) @} @^*) @}^* + @> @^*} + \dhead{mac}{atypecase @ @{ (@ @^*) @}^* + @> @^*} + \dhead{mac}{aetypecase @ @{ (@ @^*) @}^* + @> @^*}} These are like the Common Lisp macros @|case|, @|ecase|, @|typecase|, and @|etypecase|, except that @|it| is bound to the value of the @ while evaluating the matching @s. \end{describe*} -\begin{describe}{mac}{asetf @{ @ @ @}^*} +\begin{describe}{mac}{asetf @{ @ @ @}^* @> @^*} For each @ and @ in turn: bind @|it| to the current value of the @, evaluate the @ expression, and store the resulting - value back in the @. + value back in the @. Return the @(s) stored by the final + pair: there may be more than one value, e.g., if @ is a @|values| + form. For example, @|(asetf @ (1+ it))| is almost equivalent to @|(incf @)|, even if evaluating @ has side-effects. @@ -245,7 +253,7 @@ The macros described here all bind the variable @|it|. The following utilities make use of the introspection features of the CLOS metaobject protocol. -\begin{describe}{gf}{instance-initargs @} +\begin{describe}{gf}{instance-initargs @ @> @} Return a fresh list of plausible initargs for the given @. This is done by digging through the instance's class's slot definitions and @@ -497,6 +505,15 @@ be implemented fairly easily using @|merge-lists| below. the partial order. \end{describe} +\begin{describe}{fun}{cross-product \&rest @} + Return the cross product of the @. + + Each arguments may be a list, or a (non-nil) atom, which is equivalent to a + singleton list containing just that atom. Return a list of all possible + lists which can be constructed by taking one item from each argument list + in turn, in an arbitrary order. +\end{describe} + \begin{describe}{fun} {find-duplicates @ @ \&key :key :test} Call @ on each pair of duplicate items in a @. @@ -505,9 +522,14 @@ be implemented fairly easily using @|merge-lists| below. and $y$ are considered equal if and only if @|(funcall @ (funcall @ $x$) (funcall @ $y$))| returns non-nil. + The @ function is called as @|(funcall @ @ + @)|. Duplicates are reported in order; the @ item is + always the first matching item in the sequence. + This function will work for arbitrary @ functions, but it will run - much more efficiently if @ is @|eq|, @|eql|, @|equal|, or @|equalp| - (because it can use hash-tables). + much more efficiently if @ is @|eq|, @|eql|, @|equal|, or @|equalp|, + because it can use hash-tables. (The generic implementation for lists is + especially inefficient.) \end{describe} @@ -725,37 +747,157 @@ The following definitions are useful when working with conditions. \begin{describe}{fun} {frob-identifier @ \&key :swap-case :swap-hyphen @> @} + Return a `frobbed' version of the identifier @. Two different + transformations can be applied. + + \begin{itemize} + + \item If @ is non-nil (the default), and the letters in + @ are either all uppercase or all lowercase, then switch the case + of all of the letters. + + \item If @ is non-nil (the default), and @ contains + either hyphens @`--' or underscores @`_', but not both, then replace the + hyphens by underscores or \emph{vice-versa}. + + \end{itemize} + + (These are the `obvious' transformations to convert a C identifier into a + Lisp symbol.) + + Some examples: + \begin{itemize} + \item @|(frob-identifier "foo")| $\Longrightarrow$ @|"FOO"| + \item @|(frob-identifier "FOO")| $\Longrightarrow$ @|"foo"| + \item @|(frob-identifier "FooBar")| $\Longrightarrow$ @|"FooBar"| + \item @|(frob-identifier "Foo-Bar")| $\Longrightarrow$ @|"Foo_Bar"| + \item @|(frob-identifier "Foo_Bar")| $\Longrightarrow$ @|"Foo-Bar"| + \item @|(frob-identifier "foo_bar")| $\Longrightarrow$ @|"FOO-BAR"| + \item @|(frob-identifier "foo_bar" :swap-hyphen nil)| $\Longrightarrow$ + @|"FOO_BAR"| + \item @|(frob-identifier "foo_bar" :swap-case nil)| $\Longrightarrow$ + @|"foo-bar"| + \item @|(frob-identifier "foo_bar" :swap-case nil :swap-hyphen nil)| + $\Longrightarrow$ @|"foo_bar"| + \end{itemize} \end{describe} \begin{describe}{fun} - {compose @ \&rest @ @> @} + {compose @ @> @} + Return the left-to-right composition zero or more @. + + Let $f_1$, $f_2$, \ldots, $f_n$ be functions, and let $g = @|(compose $f_1$ + $f_2$ $\cdots$ $f_n$)|$ is their composition. If $g$ is applied to + arguments, the effect is as follows: first, $f_1$ is applied to the + arguments, yielding some value; $f_2$ is applied to this value, yielding a + second value; and so on, until finally the value yielded by $f_n$ is + returned as the result of $g$. Note that this is the reverse of the usual + mathematician's convention, but the author finds this ordering + significantly easier to work with: + \[ g = f_n \circ \cdots \circ f_2 \circ f_1 \] + + If any of the input functions return multiple values then \emph{all} of the + values are passed on to the next function in the list. (If the last + function returns multiple values then all of the values are returned from + the composition. + + The result of composing no functions is a function which simply returns all + of its arguments as values; essentially, $@|(compose)| \equiv + @|\#'values|$. \end{describe} \begin{describe}{mac}{defvar-unbound @ @ @> @} + Define a variable called @, with a @ string. + + The Common Lisp @|defvar| macro accepts both an initial value and a + doc-string as optional arguments, in that order, with the result that it's + not possible to define a variable and establish a documentation string for + it without also giving it an initial value. The @|defvar-unbound| macro, + on the other hand, never changes the symbol's variable-value. \end{describe} \begin{describe}{mac} {dosequence (@ @ @[[ :start @ @! :end @ @! - :indexvar @ @]]) \\ \ind + :indexvar @ @]]) \\ \ind @^* \\ @{ @ @! @ @}^*} + Iterate over a @. Common Lisp has a rich collection of iteration + primitives, and a rich collection of functions for working with sequences, + but no macro for iterating over the items of a sequence. + + First, the @ is evaluated. If @ and/or @ are + provided, they are also evaluated (in that order), which should produce + integers; @ may be also be nil. If not provided, or nil (in the case + of @), @ and @ default respectively to zero and the length + of the @. For each item in the sequence between the @ and + @ positions (i.e., each item in @|(subseq @ @ + @)|, in order, the body is evaluated as an implicit @|tagbody|, with + @ bound to the item and, if provided, @ bound to the item's + index. It is not specified whether the @ and @ are + let-bound or mutated in each iteration. + + Unlike other Common Lisp @|do|\dots\ forms, there is no `result' form. \end{describe} \begin{describe}{mac} {define-access-wrapper @ @ @[[ :read-only @ @]]} + Define @ as a function of one argument, so that @|(@ @)| + is equivalent to @|(@ @)|. If @ is nil (the + default), then also define @|(setf @)| so that @|(setf (@ + @) @)| is equivalent to @|(setf (@ @) @)|. + + In a @|defstruct| form, the accessor function names are constructed based + on the structure name and slot names. The structure name and accessor + names are part of the exported interface, but the slot names ideally + shouldn't be. This causes a problem when the slot name which will lead to + the right accessor is already an external symbol in some package. You can + solve this problem by choosing an internal name for the symbol, and then + using this macro to define an accessor function with the name that you + want, in terms of the accessor that @|defstruct| made. \end{describe} \begin{describe}{fun} {distinguished-point-shortest-paths @ @ @> @} + Calculate the shortest path from the @ to each node reachable from it + in a directed graph. The nodes of the graph can be any kind of object; + they will be compared using @|eql|. + + The @ should be a function which, given a node~$v$ as its + only argument, returns a list of cons cells @|($v'$ . $c'$)|, one for each + node~$v'$ adjacent to $v$, indicating the cost $c'$ of traversing the arc + from $v$ to $v'$. + + The return value is a list of cons cells @|($c$ . $p$)|, where $p$ is list + of nodes, in reverse order, along a path from the @ to some other + node, and $c$ is the total cost of traversing this path. (Therefore @|(car + $p$)| is the destination node, and @|(car (last $p$))| is always the + @ itself.) + + The function runs in $O(n^2)$ time, where $n$ is the number of nodes + reachable from the @. Currently, it uses an algorithm due to Edsger + Dijkstra. +\end{describe} + + +\subsection{Other exported symbols} + +\begin{describe}{sym}{int} + The symbol @|int| is exported by the @|sod-utilities| package, without + giving it any particular meaning. This is done because it's given + non-conflicting meanings by two different packages, and it's more + convenient for user code not to have to deal with an unnecessary symbol + conflict. Specifically, the @|sod| package wants to define it as a C type + specifier, see \descref{cls}{simple-c-type}; and @|optparse| wants to + define it as an option handler, see \descref{opt}{int}. \end{describe} %%%-------------------------------------------------------------------------- \section{Option parser} \label{sec:misc.optparse} -These symbols are defined in the @|optparse| package. +Most of these symbols are defined in the @|optparse| package. \begin{describe}{fun}{exit \&optional (@ 0) \&key :abrupt} \end{describe} @@ -803,8 +945,8 @@ These symbols are defined in the @|optparse| package. \dhead{fun}{setf (opt-negated-tag @