%% -*- Mode:TeX; Fonts:(hl12fb) -*- %% *-* File: /usr/local/gbbopen/doc-source/reference.tex *-* %% *-* Last-Edit: Mon Aug 22 12:06:33 2011; Edited-By: cork *-* %% *-* Machine: phoenix *-* %% Copyright (C) 2003-2011, Dan Corkill %% Part of the GBBopen Project. %% Licensed under Apache License 2.0 (see LICENSE for license information). %% %% ======================================================================== %% The LaTeX and hyperlatex code used in producing GBBopen documentation %% is placed under and covered by the GBBopen software license that %% accompanies each GBBopen distribution and is also available at %% http://GBBopen.org/downloads/LICENSE. %% ======================================================================== %% %% Note: To keep both LaTeX and hyperlatex happy with indexing, index %% commands must be positioned with care (including the use of %% % after all entries). Follow the placement used here to %% minimize the creation of anchors by hyperlatex. Indexes %% should only be placed at locations where an inserted   %% anchor does not visibly affect the html layout. %% %% \indexit doesn't play well with @\xxx{} formating, so use %% the basic \index{...|itidx} rather than \indexit shorthand. \documentclass[10pt,twoside,english,pdftex]{article} \usepackage{hyperlatex} \usepackage{color} \usepackage{makeidx} \T\usepackage{atbeginend} \T\usepackage{stringstrings} \T\usepackage{longtable} \T\usepackage{newcent} \T\usepackage[T1]{fontenc} % Use smaller TT font throughout \W\begin{iftex} \makeatletter \DeclareRobustCommand\smallttfamily {\not@math@alphabet\ttfamily\mathtt \fontfamily\ttdefault\small\selectfont} \makeatother \W\end{iftex} \T\usepackage{fancyhdr} \W\usepackage{frames} %% Req'd for pdflatex -- note use epstopdf to convert eps figures; %% ps2pdf won't create correct bounding boxes \T\newcommand{\pdfgraphics}{\DeclareGraphicsExtensions{.pdf}} \T\usepackage{graphicx} \T\pdfgraphics \newcommand{\docname}{Reference} \input{common.tex} %% This should work, but the current-working-directory gets confused when %% running from the same AucTeX session: %% %%\htmldirectory{../hyperdoc} \htmldirectory{/usr/local/gbbopen/hyperdoc} \htmladdress{\xml{a target="_top" class="address" href="http://GBBopen.org/"}The GBBopen Project\xml{/a}} \htmlcss{gbbopen.css} \newcommand{\homepage}{http://GBBopen.org/} \W\setcounter{htmldepth}{4} \T\setcounter{secnumdepth}{2} \W\newcommand{\GoToTopTarget}{\xml{a target="_top" href="reference.html"}} %% ---------------------------------------------------------------------------- %% Titlepage (LaTeX version only) \W\begin{iftex} \makeatletter %% Add logo to article.cls version \def\@maketitle{% \newpage \hfill\includegraphics[scale=0.5]{GBBopen-logo}\\ \null \vskip 2em% \begin{center}% \let \footnote \thanks {\LARGE \@title \par}% \vskip 1.5em% {\large \lineskip .5em% \begin{tabular}[t]{c}% \@author \end{tabular}\par}% \vskip 1em% {\large \@date}% \end{center}% \par \vskip 1.5em} \makeatother \W\end{iftex} %% ---------------------------------------------------------------------------- \title{\vspace{3in}{\LARGE\textbf{GBBopen Reference Manual}}\\[14pt] {\Large\textbf{Version \gbbopenversion}}} \author{\vspace{1in}~\\{\Large\textbf{Dan Corkill}}\\~\\~\\ {\Large\textbf{The GBBopen Project}}\\[4pt] {\large\textbf{\xsitelink{http://GBBopen.org}{http://GBBopen.org}}}} \date{\today\\[4pt] \hhmm~\timezone} \W\renewcommand{\navigationname}{{\Large Reference Manual}} \newcommand{\inprogress}{\vfill\textcolor{darkergray}{\textsf{\textbf{This reference manual is being revised and expanded on a regular basis.}}}} \newcommand{\experimental}{\vfill\textcolor{darkergray}{\textsf{\textbf{The entities in this module are experimental and are subject to change.}}}} \newcommand{\inline}{This function is compiled in-line for top performance.} \W\begin{iftex} \usepackage[bookmarks=true, plainpages=false, linktocpage=true, colorlinks=true, linkcolor=blue, pagecolor=blue, urlcolor=blue, pdfstartview=FitH, pdfpagemode=None]{hyperref} \W\end{iftex} \makeindex \begin{document} \T\pagenumbering{roman} \T\pagestyle{plain} \T\thispagestyle{empty} \T\raggedright \T\sloppy \T\parskip=0.5\baselineskip \T\parindent=0pt \T\maketitle \T\renewcommand{\headrulewidth}{0pt} \T\begin{ifhtml} \xml{p class="tiny" align="right"} \xsitelink{PDF version}{http://gbbopen.org/downloads/reference.pdf} \xml{/p} \xml{img align="left" src="GBBopen-logo.png"} \xml{br clear="both"} {\LARGE\bf Reference Manual}\\ {\large\bf Version \gbbopenversion} \T\end{ifhtml} %\begin{center} %\inprogress\\ %\end{center} \newcommand{\intro}{% GBBopen is a modern, high-performance, open source blackboard-system development environment that is based on the concepts that were explored and refined in the \xsitelink{UMass Generic Blackboard system}{http://dancorkill.home.comcast.net/pubs/aaai87.pdf} and the commercial GBB product. GBBopen is not, however, a clone or updated version of either system. The GBBopen Project is applying the knowledge and experience gained with these earlier tools to create a new generation of blackboard-system capabilities and make them freely available to a wide audience. GBBopen is structured for high-performance and scalability while maintaining flexibility and adaptability to changes in representation, \glref{knowledge-source} (KS) components, and control strategies. Multi-dimensional abstraction of blackboard components (``\glref{space~instances}''), blackboard objects (``\glref{unit~instances}''), and proximity-based retrieval patterns is used to provide a semantically meaningful separation of blackboard-repository storage mechanisms from \glref{KS} and control code. This separation allows storage and search strategies and optimizations to change dynamically as well as to be adapted to a broad range of application areas. GBBopen also provides highly efficient and extensible event primitives that form the foundation for fast, yet effective, opportunistic control reasoning. At the implementation level, GBBopen is designed as a smooth extension of \xsitelink{Common Lisp}{http://www.lispworks.com/documentation/HyperSpec/Front/index.htm}, providing all the advantages of a rich, dynamic, reflective, and extensible programming language to the blackboard-system architects and component writers. These capabilities are crucial in building complex blackboard-based applications where object representations, knowledge sources (\glref{KSs}), and control mechanisms will change during development and over the operational lifetime of the blackboard application. GBBopen is tightly integrated with CLOS (the Common Lisp Object System) and provides additional blackboard-specific object mechanisms via the \xsitelink{Metaobject Protocol}{http://www.lisp.org/mop/index.html}. The open-source licensing of GBBopen provides a number of important benefits: \begin{itemize} \item A modular, open-source reference implementation of blackboard-system infrastructure that serves as a basis for research and development activities. \item The availability of source code and the right to modify it enables unlimited improvement and enhancement of the software. It also makes it possible to port the code to new hardware and software, to adapt it to changing conditions, and to reach a detailed understanding of how GBBopen works. Source code availability also makes it much easier to isolate and fix bugs. \item The right to redistribute improvements and extensions to the GBBopen source code. \item The right to use the software. \item There is no single entity on which the future of the GBBopen software depends. This is particularly important given the highly specialized nature of blackboard-system software and the lack of multiple implementations. \item GBBopen supports alternative and additional GBBopen \glref{modules} for use in research and experimentation. \end{itemize} }% end of intro %% ======================================================================== %% Introduction (HTML version only) \T\begin{ifhtml} \intro % Turn off the auto Navigation menu: \setcounter{htmlautomenu}{0} \T\end{ifhtml} % This should be redundant, given the one above, but it is needed! \T\thispagestyle{empty} %% ======================================================================== %% Copyright page \T\newpage \T~ \T\vfill \W\xname{ref-copyright} \W\section*{Copyright} Copyright \copyright{} 2003--2011 by Daniel D. Corkill for the GBBopen Project. This manual may be reproduced and distributed in whole or in part, subject to the following conditions: \begin{tightitemize} \item The copyright notice above and this permission notice must be preserved complete on all complete or partial copies. \item Any translation or derivative work of this manual must be approved by the copyright holder in writing before distribution. \item If you distribute this manual in part, instructions and a means for obtaining a complete version of this manual must be included. \item Small portions may be reproduced as illustrations for reviews or quotes in other works without this permission notice if proper citation is given. \item Distribution of this work or a derivative of this work in any standard (hard copy) book form is prohibited without prior written permission from the copyright holder. \end{tightitemize} All source code examples in this work are placed under and covered by the GBBopen software license that accompanies each GBBopen distribution and is also available at \xsitelink{\nobr{\code{http://GBBopen.org/svn/GBBopen/trunk/LICENSE}}}% {http://GBBopen.org/svn/GBBopen/trunk/LICENSE}. \T\bigskip % This work is licensed and provided ``as is'' without warranty of any kind, express or implied, including, but not limited to, the implied warranties of merchantability and fitness for a particular purpose or a warranty of non-infringement. GBBopen software and the information in this manual are subject to change without notice. \T\bigskip % Please help improve this manual by reporting any errors, inaccuracies, bugs, misleading or confusing statements, missing or unhelpful index entries, and typographical errors that you find. E-mail bug reports, comments, and suggestions to \xsitelink{\nobr{\code{bugs@GBBopen.org}}}{mailto:bugs@GBBopen.org}. Your help is greatly appreciated and will be acknowledged. \T\bigskip % GBBopen is a trademark of the GBBopen Project.\\ Any other brand or product names are trademarks or registered trademarks of their respective holders. \T\bigskip % \hfill\begin{tabular}{@{}l@{}} \textbf{The GBBopen Project}\\ 181 Pondview Drive\\ Amherst, Massachusetts ~ 01002\\~\\ \xsitelink{\nobr{\code{GBBopen@GBBopen.org}}}{mailto:GBBopen@GBBopen.org}\\ \xsitelink{\nobr{\code{http://GBBopen.org}}}{http://GBBopen.org}\\ \end{tabular} \T\vspace{0.5in} \W\bigskip \W\begin{iftex} This manual was produced using \xsitelink{\LaTeX}{http://www.latex-project.org} and PDF\LaTeX. \W\end{iftex} \T\begin{ifhtml} This manual was produced using \xsitelink{\LaTeX}{http://www.latex-project.org} and \xsitelink{Hyperlatex}{http://hyperlatex.sourceforge.net/} 2.9a. \T\end{ifhtml} \T\cleardoublepage \W\xname{ref-contents} \T\bgroup \T\parskip 0pt \tableofcontents \T\egroup \T\cleardoublepage %% ======================================================================== %% Acknowledgments \T\cleardoublepage \W\xname{ref-acknowledgments} % Turn the auto Navigation menu back on: \W\setcounter{htmlautomenu}{1} \input{acknowledgments.tex} %% ======================================================================== %% NYI notices \newcommand{\instanceevfnsnyi}{Unit-instance-specific event functions are not yet implemented in GBBopen.} \newcommand{\instancemirroringnyi}{Unit-instance-specific mirroring is not yet implemented in GBBopen.} \newcommand{\instancekstriggersnyi}{Unit-instance-specific \glref{KS} triggers are not yet implemented in GBBopen.} %% ======================================================================== %% Global index entries \index{alist|see{association list}}% \index{slot, link|see{link slot}}% \index{KS|see{knowledge source}}% \index{KSA|see{knowledge-source activation}}% % \REPLindexnd{:commands}{Show extended-REPL commands}% \REPLindexnd{:ds}{Describe object} \REPLindexnd{:exit}{Exit Lisp} \REPLindexnd{:pa}{Set current package}% \REPLindexnd{:systems}{Show all systems}% \REPLindexnd{:undefine-system}{Undefine a system} %% ======================================================================== %% Global syntax specifications \newcommand{\compilemoduleoptions}{\T\\[4pt] \begin{tabular}{@{~~~}l@{}p{4.2in}@{}} \code{:create-dirs} & Creates any needed directories that are missing in the compiled-file tree\\[2pt] \code{:noautorun} & Binds \nobr{\textbf{\entlink{*autorun-modules*}}} to \nil{} during compilation and loading\\[2pt] \code{:nopatches} & Do not compile or load any \glref{patches}\\[2pt] \code{:nopropagate} & Cancels (overrides) a specified :propagate option\\[2pt] \nobr{\code{:patches-only}}~~~ & Do not compile or load/reload any non-\glref{patch} files (binds \nobr{\textbf{\entlink{*patches-only*}}} to \code{t} during compilation and loading)\\[2pt] \code{:print} & Incrementally prints information during compilation and loading\\[2pt] \code{:propagate} & Applies the specified options to all \glref{required~modules}\\[2pt] \code{:recompile} & Compiles files even if the existing compiled file is newer than the source file\\[2pt] \code{:reload} & Loads files even if they are already loaded\\[2pt] \code{:source} & Loads from the source file even if the existing compiled file is newer than the source file (implies \code{:reload})\\[2pt] \end{tabular} % \codeindexqual{:create-dirs}{compile/load-module option}% \codeindexqual{:noautorun}{compile/load-module option}% \codeindexqual{:nopatches}{compile/load-module option}% \codeindexqual{:nopropagate}{compile/load-module option}% \codeindexqual{:print}{compile/load-module option}% \codeindexqual{:propagate}{compile/load-module option}% \codeindexsub{:recompile}{compile/load-module option}% \codeindexsub{:reload}{compile/load-module option}% \codeindexsub{:source}{compile/load-module option}% } \newcommand{\loadmoduleoptions}{\T\\[4pt] \begin{tabular}{@{~~~}l@{}p{4.2in}@{}} \code{:noautorun} & Binds \nobr{\textbf{\entlink{*autorun-modules*}}} to \nil{} during loading\\[2pt] \code{:nopatches} & Do not load any \glref{patches}\\[2pt] \code{:nopropagate}~~~ & Cancels (overrides) a specified :propagate option\\[2pt] \nobr{\code{:patches-only}}~~~ & Do not load/reload any non-\glref{patch} files (binds \nobr{\textbf{\entlink{*patches-only*}}} to \code{t} during loading)\\[2pt] \code{:print} & Incrementally prints information during loading\\[2pt] \code{:propagate} & Applies the specified options to all \glref{required~modules}\\[2pt] \code{:reload} & Loads files even if they are already loaded\\[2pt] \code{:source} & Loads from the source file even if the existing compiled file is newer than the source file (implies \code{:reload})\\[2pt] \end{tabular} % \codeindexqual{:noautorun}{compile/load-module option}% \codeindexqual{:nopatches}{compile/load-module option}% \codeindexqual{:nopropagate}{compile/load-module option}% \codeindexqual{:print}{compile/load-module option}% \codeindexqual{:propagate}{compile/load-module option}% \codeindexsub{:reload}{compile/load-module option}% \codeindexsub{:source}{compile/load-module option}% } \newcommand{\loadonefilemoduleoptions}{\T\\[4pt] \begin{tabular}{@{~~~}l@{}p{4.2in}@{}} \code{:noautorun}~~~ & Binds \nobr{\textbf{\entlink{*autorun-modules*}}} to \nil{} during loading\\[2pt] \code{:print} & Incrementally prints information during loading\\[2pt] \code{:source} & Loads from the source file even if the existing compiled file is newer than the source file\\[2pt] \end{tabular} % \codeindexqual{:noautorun}{compile/load-module option}% \codeindexqual{:print}{compile/load-module option}% \codeindexsub{:source}{compile/load-module option}% } \newcommand{\compilemodulefileoptions}{\T\\[4pt] \begin{tabular}{@{~~~}l@{}l@{}} \code{:developing} & If the patch file has changed, recompile and reload it (patch files only) \\[2pt] \code{:forces-recompile}~~~ & If the file has changed, recompile and reload all subsequent files and \glref{modules}\\[2pt] \code{:noload} & Compile, but do not load the file \\[2pt] \code{:recompile} & Always recompile the file \\[2pt] \code{:reload} & Always reload the file \\[2pt] \code{:skip-recompile}~~~ & Skip recompiling the file if it has been loaded already\\ & (takes precedence over other recompilation decisions)\\[2pt] \code{:source} & Do not compile the file (load the source instead) \\ \end{tabular} % \codeindexsub{:developing}{define-module file option (patch files only)}% \codeindexqual{:forces-recompile}{define-module file option}% \codeindexqual{:noload}{define-module file option}% \codeindexsub{:recompile}{define-module file option}% \codeindexsub{:reload}{define-module file option}% \codeindexqual{:skip-recompile}{define-module file option}% \codeindexsub{:source}{define-module file option}% } \newcommand{\loadmodulefileoptions}{\T\\[4pt] \begin{tabular}{@{~~~}l@{}l@{}} \code{:developing} & If the compiled patch file has changed, reload it (patch files only) \\[2pt] \code{:forces-recompile}~~~ & If the file has changed, recompile and reload all subsequent files and \glref{modules}\\[2pt] \code{:noautorun}~~~ & Binds \nobr{\textbf{\entlink{*autorun-modules*}}} to \nil{} during compilation and loading\\[2pt] \code{:print} & Incrementally prints information during compilation and loading\\[2pt] \code{:reload} & Always reload the file \\[2pt] \code{:source} & Do not compile the file (load the source instead) \\ \end{tabular} % \codeindexsub{:developing}{define-module file option (patch files only)}% \codeindexqual{:noautorun}{compile/load-module option}% \codeindexqual{:print}{compile/load-module option}% \codeindexsub{:reload}{define-module file option}% \codeindexsub{:source}{define-module file option}% } %% --------------------------------------------------------------------------- \newcommand{\patternspec}[1]{% \begin{tabular}{@{~}l@{~}l} \nobr{\var{pattern\/} ::=} \index{pattern!specification}% & \var{subpattern\/} \vbar{} \code{t} #1\\ \end{tabular} \T\\ \begin{tabular}{@{~}l@{~}l} \nobr{\var{subpattern\/} ::=} \index{pattern!negation}% \index{pattern!conjunctive}% \index{pattern!disjunctive}% \index{pattern!t@\code{t}}% \index{conjunctive pattern}% \index{disjunctive pattern}% \index{t@\code{t} pattern|itidx}% \index{not@\code{not} ~(pattern-negation operator)|itidx}% \index{and@\code{and} ~(conjunctive-pattern operator)|itidx}% \index{or@\code{or} ~(disjunctive-pattern operator)|itidx}% & \var{pattern-element\/} \vbar{}\\ & \code{(not} \var{subpattern\/}\code{)} \vbar{} \\ & \code{(and} \var{subpattern\/}\superstar\code{)} \vbar{} \\ & \code{(or} \var{subpattern\/}\superstar\code{)}\\ \end{tabular} \T\\ \begin{tabular}{@{~}l@{~}l} \nobr{\var{pattern-element\/} ::=} & \code{(}\var{pattern-op dimension-names\/} \var{pattern-values\/} \var{option\/}\superstar\code{)} \vbar{} \\ & \code{(}\var{boolean-dimension-unary-pattern-op dimension-names\/} \var{option\/}\superstar\code{)} \\ \end{tabular} \T\\ \begin{tabular}{@{~}l@{~}l} \nobr{\var{pattern-op\/} ::=} & \var{ordered-dimension-pattern-op\/} \vbar{} \\ & \var{enumerated-dimension-pattern-op\/} \vbar{} \\ & \var{boolean-dimension-binary-pattern-op\/} \\ \end{tabular} \T\\ \begin{tabular}{@{~}l@{~}l} \nobr{\var{ordered-dimension-pattern-op\/} ::=} \index{ordered dimension!pattern operators}% & \var{ordered-dimension-any-numeric-value-pattern-op\/} \vbar{} \\ & \var{ordered-dimension-explicit-type-pattern-op\/} \\ \end{tabular} \T\\ \begin{tabular}{@{~}l@{~}l} \nobr{\var{ordered-dimension-explicit-type-pattern-op\/} ::=} \index{ordered dimension!pattern operators}% & \var{ordered-dimension-fixnum-pattern-op\/} \vbar{} \\ & \var{ordered-dimension-short-float-pattern-op\/} \vbar{} \\ & \var{ordered-dimension-single-float-pattern-op\/} \vbar{} \\ & \var{ordered-dimension-double-float-pattern-op\/} \vbar{} \\ & \var{ordered-dimension-long-float-pattern-op\/} \vbar{} \\ & \var{ordered-dimension-pseudo-probability-pattern-op\/} \\ \end{tabular} \T\\ \begin{tabular}{@{~}l@{~}l} \nobr{\var{ordered-dimension-any-numeric-value-pattern-op\/} ::=} \index{$<$@\code{$<$} ~(ordered-dimension pattern operator)|itidx}% \index{$<$=@\code{$<$=} ~(ordered-dimension pattern operator)|itidx}% \index{$>$=@\code{$>$=} ~(ordered-dimension pattern operator)|itidx}% \index{$>$@\code{$>$} ~(ordered-dimension pattern operator)|itidx}% \index{=@\code{=} ~(ordered-dimension pattern operator)|itidx}% \index{/=@\code{/=} ~(ordered-dimension pattern operator)|itidx}% \index{within@\code{within} ~(ordered-dimension pattern operator)|itidx}% \index{covers@\code{covers} ~(ordered-dimension pattern operator)|itidx}% \index{overlaps@\code{overlaps} ~(ordered-dimension pattern operator)|itidx}% \index{abuts@\code{abuts} ~(ordered-dimension pattern operator)|itidx}% \index{starts@\code{starts} ~(ordered-dimension pattern operator)|itidx}% \index{ends@\code{ends} ~(ordered-dimension pattern operator)|itidx}% & \code{$<$} \vbar{} \code{$<$=} \vbar{} \code{$>$=} \vbar{} \code{$>$} \vbar{} \code{=} \vbar{} \code{/=} \vbar{} \\ & \code{within} \vbar{} \code{covers} \vbar{} \code{overlaps} \vbar{} \\ & \code{abuts} \vbar{} \code{starts} \vbar{} \code{ends} \\ \end{tabular} \T\\ \begin{tabular}{@{~}l@{~}l} \nobr{\var{ordered-dimension-fixnum-pattern-op\/} ::=} \index{$<$\&@\code{$<$\&} ~(ordered-dimension fixnum pattern operator)|itidx}% \index{$<$\&=@\code{$<$=\&} ~(ordered-dimension fixnum pattern operator)|itidx}% \index{$>$\&=@\code{$>$=\&} ~(ordered-dimension fixnum pattern operator)|itidx}% \index{$>$\&@\code{$>$\&} ~(ordered-dimension fixnum pattern operator)|itidx}% \index{=\&@\code{=\&} ~(ordered-dimension fixnum pattern operator)|itidx}% \index{/=\&@\code{/=\&} ~(ordered-dimension fixnum pattern operator)|itidx}% \index{within\&@\code{within\&} ~(ordered-dimension fixnum pattern operator)|itidx}% \index{covers\&@\code{covers\&} ~(ordered-dimension fixnum pattern operator)|itidx}% \index{overlaps\&@\code{overlaps\&} ~(ordered-dimension fixnum pattern operator)|itidx}% \index{abuts\&@\code{abuts\&} ~(ordered-dimension fixnum pattern operator)|itidx}% \index{starts\&@\code{starts\&} ~(ordered-dimension fixnum pattern operator)|itidx}% \index{ends\&@\code{ends\&} ~(ordered-dimension fixnum pattern operator)|itidx}% & \code{$<$\&} \vbar{} \code{$<$=\&} \vbar{} \code{$>$=\&} \vbar{} \code{$>$\&} \vbar{} \code{=\&} \vbar{} \code{/=\&} \vbar{} \\ & \code{within\&} \vbar{} \code{covers\&} \vbar{} \code{overlaps\&} \vbar{} \\ & \code{abuts\&} \vbar{} \code{starts\&} \vbar{} \code{ends\&} \\ \end{tabular} \T\\ \begin{tabular}{@{~}l@{~}l} \nobr{\var{ordered-dimension-short-float-pattern-op\/} ::=} \index{$<$\$\&@\code{$<$\$\&} ~(ordered-dimension short-float pattern operator)|itidx}% \index{$<$\$\&=@\code{$<$=\$\&} ~(ordered-dimension short-float pattern operator)|itidx}% \index{$>$\$\&=@\code{$>$=\$\&} ~(ordered-dimension short-float pattern operator)|itidx}% \index{$>$\$\&@\code{$>$\$\&} ~(ordered-dimension short-float pattern operator)|itidx}% \index{=\$\&@\code{=\$\&} ~(ordered-dimension short-float pattern operator)|itidx}% \index{/=\$\&@\code{/=\$\&} ~(ordered-dimension short-float pattern operator)|itidx}% \index{within\$\&@\code{within\$\&} ~(ordered-dimension short-float pattern operator)|itidx}% \index{covers\$\&@\code{covers\$\&} ~(ordered-dimension short-float pattern operator)|itidx}% \index{overlaps\$\&@\code{overlaps\$\&} ~(ordered-dimension short-float pattern operator)|itidx}% \index{abuts\$\&@\code{abuts\$\&} ~(ordered-dimension short-float pattern operator)|itidx}% \index{starts\$\&@\code{starts\$\&} ~(ordered-dimension short-float pattern operator)|itidx}% \index{ends\$\&@\code{ends\$\&} ~(ordered-dimension short-float pattern operator)|itidx}% & \code{$<$\$\&} \vbar{} \code{$<$=\$\&} \vbar{} \code{$>$=\$\&} \vbar{} \code{$>$\$\&} \vbar{} \code{=\$\&} \vbar{} \code{/=\$\&} \vbar{} \\ & \code{within\$\&} \vbar{} \code{covers\$\&} \vbar{} \code{overlaps\$\&} \vbar{} \\ & \code{abuts\$\&} \vbar{} \code{starts\$\&} \vbar{} \code{ends\$\&} \\ \end{tabular} \T\\ \begin{tabular}{@{~}l@{~}l} \nobr{\var{ordered-dimension-single-float-pattern-op\/} ::=} \index{$<$\$@\code{$<$\$} ~(ordered-dimension single-float pattern operator)|itidx}% \index{$<$\$=@\code{$<$=\$} ~(ordered-dimension single-float pattern operator)|itidx}% \index{$>$\$=@\code{$>$=\$} ~(ordered-dimension single-float pattern operator)|itidx}% \index{$>$\$@\code{$>$\$} ~(ordered-dimension single-float pattern operator)|itidx}% \index{=\$@\code{=\$} ~(ordered-dimension single-float pattern operator)|itidx}% \index{/=\$@\code{/=\$} ~(ordered-dimension single-float pattern operator)|itidx}% \index{within\$@\code{within\$} ~(ordered-dimension single-float pattern operator)|itidx}% \index{covers\$@\code{covers\$} ~(ordered-dimension single-float pattern operator)|itidx}% \index{overlaps\$@\code{overlaps\$} ~(ordered-dimension single-float pattern operator)|itidx}% \index{abuts\$@\code{abuts\$} ~(ordered-dimension single-float pattern operator)|itidx}% \index{starts\$@\code{starts\$} ~(ordered-dimension single-float pattern operator)|itidx}% \index{ends\$@\code{ends\$} ~(ordered-dimension single-float pattern operator)|itidx}% & \code{$<$\$} \vbar{} \code{$<$=\$} \vbar{} \code{$>$=\$} \vbar{} \code{$>$\$} \vbar{} \code{=\$} \vbar{} \code{/=\$} \vbar{} \\ & \code{within\$} \vbar{} \code{covers\$} \vbar{} \code{overlaps\$} \vbar{} \\ & \code{abuts\$} \vbar{} \code{starts\$} \vbar{} \code{ends\$} \\ \end{tabular} \T\\ \begin{tabular}{@{~}l@{~}l} \nobr{\var{ordered-dimension-double-float-pattern-op\/} ::=} \index{$<$\$\$@\code{$<$\$\$} ~(ordered-dimension double-float pattern operator)|itidx}% \index{$<$\$\$=@\code{$<$=\$\$} ~(ordered-dimension double-float pattern operator)|itidx}% \index{$>$\$\$=@\code{$>$=\$\$} ~(ordered-dimension double-float pattern operator)|itidx}% \index{$>$\$\$@\code{$>$\$\$} ~(ordered-dimension double-float pattern operator)|itidx}% \index{=\$\$@\code{=\$\$} ~(ordered-dimension double-float pattern operator)|itidx}% \index{/=\$\$@\code{/=\$\$} ~(ordered-dimension double-float pattern operator)|itidx}% \index{within\$\$@\code{within\$\$} ~(ordered-dimension double-float pattern operator)|itidx}% \index{covers\$\$@\code{covers\$\$} ~(ordered-dimension double-float pattern operator)|itidx}% \index{overlaps\$\$@\code{overlaps\$\$} ~(ordered-dimension double-float pattern operator)|itidx}% \index{abuts\$\$@\code{abuts\$\$} ~(ordered-dimension double-float pattern operator)|itidx}% \index{starts\$\$@\code{starts\$\$} ~(ordered-dimension double-float pattern operator)|itidx}% \index{ends\$\$@\code{ends\$\$} ~(ordered-dimension double-float pattern operator)|itidx}% & \code{$<$\$\$} \vbar{} \code{$<$=\$\$} \vbar{} \code{$>$=\$\$} \vbar{} \code{$>$\$\$} \vbar{} \code{=\$\$} \vbar{} \code{/=\$\$} \vbar{} \\ & \code{within\$\$} \vbar{} \code{covers\$\$} \vbar{} \code{overlaps\$\$} \vbar{} \\ & \code{abuts\$\$} \vbar{} \code{starts\$\$} \vbar{} \code{ends\$\$} \\ \end{tabular} \T\\ \begin{tabular}{@{~}l@{~}l} \nobr{\var{ordered-dimension-long-float-pattern-op\/} ::=} \index{$<$\$\$\$@\code{$<$\$\$\$} ~(ordered-dimension long-float pattern operator)|itidx}% \index{$<$\$\$\$=@\code{$<$=\$\$\$} ~(ordered-dimension long-float pattern operator)|itidx}% \index{$>$\$\$\$=@\code{$>$=\$\$\$} ~(ordered-dimension long-float pattern operator)|itidx}% \index{$>$\$\$\$@\code{$>$\$\$\$} ~(ordered-dimension long-float pattern operator)|itidx}% \index{=\$\$\$@\code{=\$\$\$} ~(ordered-dimension long-float pattern operator)|itidx}% \index{/=\$\$\$@\code{/=\$\$\$} ~(ordered-dimension long-float pattern operator)|itidx}% \index{within\$\$\$@\code{within\$\$\$} ~(ordered-dimension long-float pattern operator)|itidx}% \index{covers\$\$\$@\code{covers\$\$\$} ~(ordered-dimension long-float pattern operator)|itidx}% \index{overlaps\$\$\$@\code{overlaps\$\$\$} ~(ordered-dimension long-float pattern operator)|itidx}% \index{abuts\$\$\$@\code{abuts\$\$\$} ~(ordered-dimension long-float pattern operator)|itidx}% \index{starts\$\$\$@\code{starts\$\$\$} ~(ordered-dimension long-float pattern operator)|itidx}% \index{ends\$\$\$@\code{ends\$\$\$} ~(ordered-dimension long-float pattern operator)|itidx}% & \code{$<$\$\$\$} \vbar{} \code{$<$=\$\$\$} \vbar{} \code{$>$=\$\$\$} \vbar{} \code{$>$\$\$\$} \vbar{} \code{=\$\$\$} \vbar{} \code{/=\$\$\$} \vbar{} \\ & \code{within\$\$\$} \vbar{} \code{covers\$\$\$} \vbar{} \code{overlaps\$\$\$} \vbar{} \\ & \code{abuts\$\$\$} \vbar{} \code{starts\$\$\$} \vbar{} \code{ends\$\$\$} \\ \end{tabular} \T\\ \begin{tabular}{@{~}l@{~}l} \nobr{\var{ordered-dimension-pseudo-probability-pattern-op\/} ::=} \index{$<$\%@\code{$<$\%} ~(ordered-dimension pseudo-probability pattern operator)|itidx}% \index{$<$\%=@\code{$<$=\%} ~(ordered-dimension pseudo-probability pattern operator)|itidx}% \index{$>$\%=@\code{$>$=\%} ~(ordered-dimension pseudo-probability pattern operator)|itidx}% \index{$>$\%@\code{$>$\%} ~(ordered-dimension pseudo-probability pattern operator)|itidx}% \index{=\%@\code{=\%} ~(ordered-dimension pseudo-probability pattern operator)|itidx}% \index{/=\%@\code{/=\%} ~(ordered-dimension pseudo-probability pattern operator)|itidx}% \index{within\%@\code{within\%} ~(ordered-dimension pseudo-probability pattern operator)|itidx}% \index{covers\%@\code{covers\%} ~(ordered-dimension pseudo-probability pattern operator)|itidx}% \index{overlaps\%@\code{overlaps\%} ~(ordered-dimension pseudo-probability pattern operator)|itidx}% \index{abuts\%@\code{abuts\%} ~(ordered-dimension pseudo-probability pattern operator)|itidx}% \index{starts\%@\code{starts\%} ~(ordered-dimension pseudo-probability pattern operator)|itidx}% \index{ends\%@\code{ends\%} ~(ordered-dimension pseudo-probability pattern operator)|itidx}% & \code{$<$\%} \vbar{} \code{$<$=\%} \vbar{} \code{$>$=\%} \vbar{} \code{$>$\%} \vbar{} \code{=\%} \vbar{} \code{/=\%} \vbar{} \\ & \code{within\%} \vbar{} \code{covers\%} \vbar{} \code{overlaps\%} \vbar{} \\ & \code{abuts\%} \vbar{} \code{starts\%} \vbar{} \code{ends\%} \\ \end{tabular} \T\\ \begin{tabular}{@{~}l@{~}l} \nobr{\var{enumerated-dimension-pattern-op\/} ::=} \index{enumerated dimension!pattern operators}% \index{is@\code{is} ~(enumerated-dimension pattern operator)|itidx}% & \code{is} \vbar{} \var{enumerated-dimension-explicit-test-pattern-op\/} \\ \end{tabular} \T\\ \begin{tabular}{@{~}l@{~}l} \nobr{\var{enumerated-dimension-explicit-test-pattern-op\/} ::=} \index{is-eq@\code{is-eq} ~(enumerated-dimension pattern operator)|itidx}% \index{is-eql@\code{is-eql} ~(enumerated-dimension pattern operator)|itidx}% \index{is-equal@\code{is-equal} ~(enumerated-dimension pattern operator)|itidx}% \index{ie-equalp@\code{ie-equalp} ~(enumerated-dimension pattern operator)|itidx}% & \code{is-eq} \vbar{} \code{is-eql} \vbar{} \code{is-equal} \vbar{} \code{is-equalp} \\ \end{tabular} \T\\ \begin{tabular}{@{~}l@{~}l} \nobr{\var{boolean-dimension-binary-pattern-op\/} ::=} \index{boolean dimension!pattern operators}% \index{eqv@\code{eqv} ~(boolean-dimension pattern operator)|itidx}% & \code{eqv} \\ \end{tabular} \T\\ \begin{tabular}{@{~}l@{~}l} \nobr{\var{boolean-dimension-unary-pattern-op\/} ::=} \index{boolean dimension!unary-pattern operators}% \index{true@\code{true} ~(boolean-dimension pattern operator)|itidx}% \index{false@\code{false} ~(boolean-dimension pattern operator)|itidx}% & \code{true} \vbar{} \code{false} \\ \end{tabular} \T\\ \begin{tabular}{@{~}l@{~}l} \nobr{\var{dimension-names\/} ::=} & \var{dimension-name\/} \vbar{} \code{(}\var{dimension-name\/}\superplus\code{)} \\ \end{tabular} \T\\ \begin{tabular}{@{~}l@{~}l} \nobr{\var{pattern-values\/} ::=} \index{pattern!value}% \index{dotted list!pattern values}% \index{list!pattern values}% \index{vector!pattern values}% & \var{pattern-value\/} \vbar{} \\ & \code{(}\var{pattern-value\/}\superplus\code{)} \vbar{} \\ & \code{(}\var{pattern-value\/}\superplus{} \code{.} \var{pattern-value\/}\code{)} \vbar{} \\ & \code{\#(}\var{pattern-value\/}\superplus\code{)} \\ \end{tabular} \T\\ \begin{tabular}{@{~}l@{~}l} \nobr{\var{pattern-value\/} ::=} \index{point!pattern value}% \index{interval!pattern value}% \index{element!pattern value}% \index{set!pattern value}% & \var{point\/} \vbar{} \var{interval\/} \vbar{} \var{element\/} \vbar{} \var{set\/} \\ \end{tabular} \T\\ \begin{tabular}{@{~}l@{~}l} \nobr{\var{interval\/} ::=} & \code{(}\var{start end\/}\code{)} \vbar{} \code{(}\var{start\/} \code{.} \var{end\/}\code{)} \vbar{} \code{\#(}\var{start end\/}\code{)} \\ \end{tabular} } \newcommand{\patternterms}{% \begin{tabular}{@{}l@{}l@{}l@{}} \var{point\/} \codeindexqualit{-infinity}{interval start value}% \codeindexqualit{infinity}{interval end value}% & & A number, \code{infinity}, or \code{-infinity}\\ \var{start\/} & & A number or \code{-infinity}\\ \var{end\/} & & A number or \code{infinity}\\ \var{element\/} & ~~ & An object\\ \end{tabular} } \newcommand{\patternnote}{% Fixnum \code{overlaps} comparisons can result in bignum computations if the combined intervals of the pattern and a candidate \glref{unit~instance} exceeds \code{most-positive-fixnum}. } %% --------------------------------------------------------------------------- \newcommand{\eventclassspec}{% \begin{tabular}{@{~}l@{~}l} \nobr{\var{event-class-specifier\/} ::=} & \var{atomic-event-class\/} \vbar{} \code{(}\var{atomic-event-class subeventing-specifier\/}\code{)} \vbar{} \code{t}\\ \end{tabular} \T\\ \begin{tabular}{@{~}l@{~}l} \nobr{\var{atomic-event-class\/} ::=} & \var{event-class\/} \vbar{} \var{event-class-name\/} \\ \end{tabular} } %% --------------------------------------------------------------------------- \newcommand{\unitclassinstancespec}{% \begin{tabular}{@{~}l@{~}l} \nobr{\var{unit-class-or-instance-specifier\/} ::=} & \var{unit-instance\/} \vbar{} \code{(}\var{unit-instance\/}\superstar\code{)} \vbar{} \\ & \var{atomic-unit-class\/} \vbar{} \\ & \code{(}\var{atomic-unit-class subclassing-specifier\/}\code{)} \vbar{} \code{t}\\ \end{tabular} \T\\ \begin{tabular}{@{~}l@{~}l} \nobr{\var{atomic-unit-class\/} ::= } & \var{unit-class\/} \vbar{} \var{unit-class-name\/} \\ \end{tabular} } %% --------------------------------------------------------------------------- \newcommand{\unitclassspec}{% \begin{tabular}{@{~}l@{~}l} \nobr{\var{unit-class-specifier\/} ::=} & \var{atomic-unit-class\/} \vbar{} \code{(}\var{atomic-unit-class subclassing-specifier\/}\code{)} \vbar{} \code{t}\\ \end{tabular} \T\\ \begin{tabular}{@{~}l@{~}l} \nobr{\var{atomic-unit-class\/} ::=} & \var{unit-class\/} \vbar{} \var{unit-class-name\/} \\ \end{tabular} } %% --------------------------------------------------------------------------- \newcommand{\unitclassesspec}{% \begin{tabular}{@{~}l@{~}l} \nobr{\var{unit-classes-specifier\/} ::=} & \code{t} \vbar{} \var{single-unit-class-specifier\/} \vbar{} \code{(}\var{single-unit-class-specifier\/}\superplus\code{)}\\ \end{tabular} \T\\ \begin{tabular}{@{~}l@{~}l} \nobr{\var{single-unit-class-specifier\/} ::=} & \var{atomic-unit-class\/} \vbar{} \code{(}\var{atomic-unit-class subclassing-specifier\/}\code{)}\\ \end{tabular} \T\\ \begin{tabular}{@{~}l@{~}l} \nobr{\var{atomic-unit-class\/} ::=} & \var{unit-class\/} \vbar{} \var{unit-class-name\/} \\ \end{tabular} } %% --------------------------------------------------------------------------- \newcommand{\subclassingspec}{% \begin{tabular}{@{~}l@{~}l} \nobr{\var{subclassing-specifier\/} ::=} \codeindexit{:plus-subclasses}% \codeindexit{:no-subclasses}% & \code{:plus-subclasses} \vbar{} \code{:no-subclasses} \vbar{} \code{+} \vbar{} \code{=} \\ \end{tabular} \T\\[4pt] The shorthand \code{+} subclasses specifier is equivalent to \code{:plus-subclasses} and \code{=} to \code{:no-subclasses}. } %% --------------------------------------------------------------------------- \newcommand{\subeventingspec}{% \begin{tabular}{@{~}l@{~}l} \nobr{\var{subeventing-specifier\/} ::=} \codeindexit{:plus-subevents}% \codeindexit{:no-subevents}% & \code{:plus-subevents} \vbar{} \code{:no-subevents} \code{+} \vbar{} \code{=} \\ \end{tabular} \T\\[4pt] The shorthand \code{+} subevents specifier is equivalent to \code{:plus-subevents} and \code{=} to \code{:no-subevents}. } %% --------------------------------------------------------------------------- \newcommand{\storagespec}{% \begin{tabular}{@{~}l@{~}l} \nobr{\var{storage\/} ::=} & \code{(}\var{unit-class-specifier dimension-names storage-specification\/}\code{)\superstar{}}\\ \end{tabular} \T\\ \begin{tabular}{@{~}l@{~}l} \nobr{\var{dimension-names\/} ::=} & \var{dimension-name\/} \vbar{} \code{(}\var{dimension-name\/}\superplus\code{)} \vbar{} \code{t} \\ \end{tabular} \T\\ \begin{tabular}{@{~}l@{~}l} \nobr{\var{storage-specification\/} ::=} \index{unit instance!storage specification!unstructured@\code{unstructured}|itidx}% \index{unit instance!storage specification!boolean@\code{boolean}|itidx}% \index{unit instance!storage specification!uniform-buckets@\code{uniform-buckets}|itidx}% %\index{unit instance!storage specification!quadtree@\code{quadtree}|itidx}% \index{unit instance!storage specification!hashed@\code{hashed}|itidx}% & \code{unstructured} \vbar{}\\ & \code{boolean} \vbar{}\\ & \code{uniform-buckets} \code{:layout} \var{dimension-buckets-specification\/}\superplus{} \vbar{}\\ & \code{hashed} [\code{:size} \var{integer\/}]\\ \end{tabular} \T\\ \begin{tabular}{@{~}l@{~}l} \nobr{\var{dimension-buckets-specification\/} ::=} & \code{(}\var{start-value end-value bucket-width\/}\code{)}\\ \end{tabular} } %% --------------------------------------------------------------------------- \newcommand{\comparisontypespecs}{% \begin{tabular}{@{~}l@{~}l} \nobr{\var{ordered-comparison-type\/} ::=} \codeindexit{number}% \codeindexit{fixnum}% \codeindexit{short-float}% \codeindexit{single-float}% \codeindexit{double-float}% \codeindexit{long-float}% \codeindexit{pseudo-probability}% & \code{number} \vbar{} \code{fixnum} \vbar{} \code{short-float} \vbar{} \code{single-float} \vbar{} \\ & \code{double-float} \vbar{} \code{long-float} \vbar{} \\ & \code{pseudo-probability} \\ \end{tabular} \T\\ \begin{tabular}{@{~}l@{~}l} \nobr{\var{enumerated-comparison-type\/} ::=} \codeindexit{eq}% \codeindexit{eql}% \codeindexit{equal}% \codeindexit{equalp}% & \code{eq} \vbar{} \code{eql} \vbar{} \code{equal} \vbar{} \code{equalp} \\ \end{tabular} \T\\ \begin{tabular}{@{~}l@{~}l} \nobr{\var{boolean-comparison-type\/} ::=} & \code{t} \\ \end{tabular} } \newcommand{\comparisontypenote}{% The default \nobr{\var{ordered-comparison-type}}, if unspecified, is \nobr{\code{number}}. The default \nobr{\var{enumerated-comparison-type}}, if unspecified, is \code{eql}. The default \nobr{\var{boolean-comparison-type\/}} is \code{t}.} %% --------------------------------------------------------------------------- \newcommand{\dimensionvaluesspec}{% \begin{tabular}{@{~}l@{~}l} \nobr{\var{dimension-value-specifier\/} ::=} & \var{incomposite-dv-specifier\/} \vbar{} \var{composite-dv-specifier\/} \\ \end{tabular} \T\\ \begin{tabular}{@{~}l@{~}l} \nobr{\var{incomposite-dv-specifier\/} ::=} & \code{(}\var{dimension-name dimension-value-spec dimension-value-place\/}\code{)} \\ \end{tabular} \T\\ \begin{tabular}{@{~}l@{~}l} \nobr{\var{composite-dv-specifier\/} ::=} & \code{(}\var{dimension-name dimension-value-specifier\/} \\ & ~ \var{composite-type dimension-value-place\/}\code{)} \\ \end{tabular} \T\\ \begin{tabular}{@{~}l@{~}l} \nobr{\var{composite-type\/} ::=} & \code{:set} \vbar{} \textcolor{darkergray}{\code{:sequence}} \vbar{} \\ & \textcolor{darkergray}{\{\code{:ascending-series} \var{ordering-dimension-name\/}\}} \vbar{} \\ & \textcolor{darkergray}{\{\code{:descending-series} \var{ordering-dimension-name\/}\}} \\ \end{tabular} \T\\ \begin{tabular}{@{~}l@{~}l} \nobr{\var{dimension-value-specifier\/} ::=} & \var{dimension-value-type\/} \vbar{} \\ & \code{(}\var{ordered-dimension-value-type\/} [\var{ordered-comparison-type\/}]\code{)} \vbar{} \\ & \code{(}\var{enumerated-dimension-value-type\/} [\var{enumerated-comparison-type\/}]\code{)} \vbar{} \\ & \code{(}\var{boolean-dimension-value-type\/} [\var{boolean-comparison-type\/}]\code{)} \\ \end{tabular} \T\\ \begin{tabular}{@{~}l@{~}l} \nobr{\var{dimension-value-type\/} ::=} & \var{ordered-dimension-value-type\/} \vbar{} \\ & \var{enumerated-dimension-value-type\/} \vbar{} \\ & \var{boolean-dimension-value-type\/} \\ \end{tabular} \T\\ \begin{tabular}{@{~}l@{~}l} \nobr{\var{ordered-dimension-value-type\/} ::=} \codeindexit{:point}% \codeindexit{:range}% \codeindexit{:mixed}% & \code{:point} \vbar{} \code{:interval} \vbar{} \code{:mixed}\\ \end{tabular} \T\\ \begin{tabular}{@{~}l@{~}l} \nobr{\var{enumerated-dimension-value-type\/} ::=} \codeindexit{:element}% & \code{:element} \\ \end{tabular} \T\\ \begin{tabular}{@{~}l@{~}l} \nobr{\var{boolean-dimension-value-type\/} ::=} \codeindexit{:boolean}% & \code{:boolean}\\ \end{tabular} \T\\ \comparisontypespecs \T\\ \begin{tabular}{@{~}l@{~}l} \nobr{\var{dimension-value-place\/} ::=} & \{\var{slot-name\/} [\var{slot-name\/}]\} \vbar{} \{\var{function} [\var{slot-name\/}]\} \\ \end{tabular} } \newcommand{\dimensionspecnote}{% A \var{dimension-value-place\/} with two \nobr{\var{slot-names\/}} is allowed only for an \nobr{\code{:interval}} dimension-value specification.} \newcommand{\classoptioninheritance}{% \index{inheritance!unit-class options}% \index{dimension values!inheritance}% \index{initial space instances!inheritance}% \index{retention, of unit instances!inheritance}% \index{unit instance!retaining, by delete-blackboard-repository!inheritance}% \index{instance-name comparison test!inheritance}% \index{use global instance-name counter!inheritance}% % The set of \nobr{\var{dimensional-values\/}} for a \glref{unit~class} is the union of the sets specified in the \nobr{\var{dimensional-values\/}} options of the class and its superclasses. When more than one dimension-value specification is supplied for a given dimension, the one supplied by the most specific class is used. The effective \nobr{\var{initial-space-instances\/}} value for a \glref{unit~class} is the value specified in the definition of the most specific \glref{unit~class}. (No additive inheritance of \nobr{\var{initial-space-instances\/}} is performed.) If no definitions specify an \nobr{\var{initial-space-instances\/}} value, \nil{} is used. The \nobr{\var{instance-name-comparison-test\/}} value is not inherited. If no value is specified in the \glref{unit-class} definition, the default initialization value associated with the metaclass is used. If a \var{retain\/} value is not specified, a value of \nobr{\code{:propagate}} is used as the default if any parent \glref{unit~classes} have a \nobr{\code{:propagate}} retention value; otherwise \nil{} is used as the default value. The \nobr{\var{use-global-instance-name-counter\/}} value is not inherited. If no value is specified in the \glref{unit-class} definition, the default initialization value associated with the metaclass is used.} %% ======================================================================== %% Errors & notes \newcommand{\modulenotdefined}{Module \var{module-name\/} has not been defined.} \newcommand{\relativedircircularity}{A \glref{relative~directory} specification contains a circularity.} \newcommand{\patchesonlymodulenotloaded}{Module \var{module-name\/} or one of its required modules has not been loaded and \nobr{\textbf{\entlink{*patches-only*}}} is true.} \newcommand{\nothreads}{Threads (multiprocessing) is not supported on the Common Lisp implementation.} \newcommand{\threadsnotstarted}{The idle-loop process has not been started on \xsitelink{CMUCL}{http://www.cons.org/cmucl/}. Multiprocessing has not been started on \xsitelink{LispWorks}{http://www.lispworks.com}.} \newcommand{\nocvlock}{The \glref{lock} (or \glref{recursive~lock}) associated with \nobr{\var{condition-variable}} is not held by the executing process.} \newcommand{\pollingnote}{When a non-\nil{} \nobr{\code{:run-polling-functions}} value is supplied to \nobr{\textbf{\entlink{start-control-shell}}} (the default on Common Lisp implementations without threads), \nobr{\textbf{\entlink{run-polling-functions}}} is called at the beginning of every control-shell-cycle and at one-half-second intervals when the Agenda Shell is hibernating due to \glref{quiescence}.} %% ======================================================================== %% Other global specifications \newcommand{\spaceinstanceregexp}{% \index{=@\code{=} (path-expression match character)}% \index{?@\code{?} (path-expression match character)}% \index{+@\code{+} (path-expression match character)}% \index{*@\code{*} (path-expression match character)}% \index{\^@\code{\^} (path-expression match character)}% \index{path!expression!match characters}% % \begin{tabular}{@{}l@{}c@{}l@{}l@{}} & \code{=} & & matches one occurrence in a \glref{space-instance\/} path \\ & \code{?} & & matches zero or one occurrence in a \glref{space-instance\/} path \\ & \code{+} & & matches one or more occurrences in a \glref{space-instance\/} path \\ & \code{*} & & matches zero or more occurrences in a \glref{space-instance\/} path \\ ~~ & \code{\^} & ~~ & move to parent \\ \end{tabular} } %% ======================================================================== %% Introduction (LaTeX version only) \W\begin{iftex} \markright{}% \cleardoublepage \setcounter{page}{1} \pagenumbering{arabic} \pagestyle{fancy} \thispagestyle{fancybottom} \section*{Introduction} \addcontentsline{toc}{section}{\textbf{Introduction}}% \label{sec:introduction}% \intro \W\end{iftex} %% ======================================================================== %% Starting Up \T\markright{}% \T\pagestyle{plain} \T\cleardoublepage \W\xname{ref-starting-up} \T\pagestyle{fancy} \T\thispagestyle{fancybottom} \T\global\def\fnlastname{ }% \section{Starting Up} \label{sec:startup}% GBBopen is packaged with its own \reflink{module system}{sec:module-manager} that supports compiling and loading GBBopen components. The Module Manager Facility is designed for ease of use and for simplicity in porting to Common Lisp implementations. For example, to compile all GBBopen \glref{modules}, you only need to evaluate the following forms within your Common Lisp environment. First load GBBopen's \nobr{\code{\var{\/}/initiate.lisp}} file: % \W\supp \begin{smallexample} \textcolor{darkergray}{% cl-user> \textcolor{black}{(load "\var{\/}/initiate.lisp")} ;; Loading \var{\/}/initiate.lisp ;; GBBopen is installed in \var{\/} ;; Your "home" directory is \var{\/} ;; Loading \var{\/}/extended-repl.lisp ;; Loading \var{\/}/commands.lisp ;; Loading \var{\/}/gbbopen-modules-directory.lisp ;; No shared module command definitions were found in \var{\/}/gbbopen-modules/. ;; No personal module command definitions were found in \var{\/}/gbbopen-modules/. #P"\var{\/}/initiate.lisp" cl-user>} \end{smallexample} % Notice that some additional GBBopen initialization files have been loaded by this file as well as GBBopen's top level read-eval-print loop (REPL) \glref{command} definitions. \begin{notebox}{Windows users} \index{backslash character, in Windows file specifications}% \index{Windows file specification, backslash characters}% If you are running GBBopen on Windows, note that backslash is the escape character in the standard Common Lisp reader; it causes the next character to treated as a normal character rather than as having any special syntactic characteristics. So, each backslash in a file-name string must be entered as two backslash characters. For example: % \W\supp\notpretop \begin{verbatim} > (load "c:\\GBBopen\\initiate.lisp") \end{verbatim} Many Common Lisp implementations also support Unix-style regular slashes in Windows file names (e.g., \nobr{\code{"c:/GBBopen/initiate.lisp"}}), which can be particularly convenient when typing file names in the REPL. \end{notebox} \ppar{Top-level REPL commands} \index{REPL, top-level (keyword) commands}% \index{SLIME!REPL keyword commands}% % The files loaded by \nobr{\code{\var{\/}/initiate.lisp}} add some handy REPL \glref{keyword~commands} when running % \xsitelink{Allegro CL}{http://franz.com/products/allegrocl/}, \xsitelink{Clozure CL}{http://trac.clozure.com/ccl}, \xsitelink{CMUCL}{http://www.cons.org/cmucl/}, \xsitelink{ECL}{http://common-lisp.net/project/ecl/}, \xsitelink{LispWorks}{http://www.lispworks.com}, \xsitelink{SBCL}{http://sbcl.sourceforge.net}, and \xsitelink{Scieneer CL}{http://www.scieneer.com/scl/} % users. Some interaction interfaces, such as \xsitelink{SLIME}{http://common-lisp.net/project/slime/}, use their own REPL rather than the top-level listener provided by the Common Lisp implementation and, therefore, may not support \glref{keyword} \glref{REPL~command} processing. GBBopen provides a Swank extension to the \xsitelink{SLIME}{http://common-lisp.net/project/slime/} REPL that supports REPL \glref{keyword~commands}. Built-in and GBBopen \glref{REPL~commands} are defined in the file \nobr{\code{\var{\/}/commands.lisp}}. \glref{REPL~commands}, including those that have arguments, are specified using a non-list (``spread'') representation. For example: % \W\supp \begin{example} > :gbbopen-test :propagate :create-dirs \textrm{\ldots{}} > \end{example} Some Common Lisp implementations (\xsitelink{Clozure CL}{http://trac.clozure.com/ccl}, \xsitelink{LispWorks}{http://www.lispworks.com}, and \xsitelink{SBCL}{http://sbcl.sourceforge.net}) and the \xsitelink{SLIME}{http://common-lisp.net/project/slime/} REPL interface, also support REPL commands in non-spread (list) form in addition to the spread notation. For example: % \W\supp\notpretop \begin{example} > (:gbbopen-test :propagate :create-dirs) \textrm{\ldots{}} > \end{example} % Equivalent functions in the \nobr{\code{:common-lisp-user}} package are always defined for each \glref{REPL~command}, and these functions can be used in place of REPL \glref{keyword-command} processing. \ppar{Compiling all GBBopen modules} \index{REPL, top-level (keyword) commands}% \index{SLIME!REPL keyword commands}% % Once \nobr{\code{\var{\/}/initiate.lisp}}, all GBBopen modules can be compiled by entering the following REPL command: % \W\supp\notpretop \begin{smallexample} \textcolor{darkergray}{% cl-user> \textcolor{black}{:compile-gbbopen} ;; Loading \var{\/}/startup.lisp ;; GBBopen is installed in \var{\/} ;; Your "home" directory is \var{\/} ;; Loading \var{\/}/source/module-manager/module-manager-loader.lisp ;; Loading \var{\/}/\var{\/}/module-manager/module-manager.lisp \textrm{\ldots{}} ;; Loading \var{\/}/modules.lisp ;; No shared module definitions were found in \var{\/}/gbbopen-modules/. ;; No personal module definitions were found in \var{\/}/gbbopen-modules/. \textrm{\ldots{}} ;;; GBBopen modules compilation completed. \textrm{[Common Lisp will exit]}} \end{smallexample} % GBBopen should compile all GBBopen modules and then exit Common Lisp without error. As can be seen from the file-loading messages, the \nobr{\code{startup.lisp}} file that is loaded by the \code{:compile-gbbopen} command loads a bootstrap loader file for the \reflink{Module Manager Facility}{sec:module-manager} (the file \nobr{\code{source/module-manager/module-manager-loader.lisp}}). This bootstrap file then loads the Module Manager files (\nobr{\code{source/module-manager/module-manager.lisp}} and \nobr{\code{source/module-manager/module-manager-user.lisp}}) followed by the module definitions for all GBBopen \glref{modules} (contained in the file \nobr{\code{source/modules.lisp}}). Then the Module Manager is used to compile all GBBopen modules. \indexit{clbuild}% \indexit{Quicklisp}% \begin{notebox}{ASDF, clbuild, and Quicklisp users} GBBopen's Module Manager Facility provides an interface that allows \xsitelink{ASDF}{http://common-lisp.net/project/asdf/} (and therefore \xsitelink{clbuild}{http://common-lisp.net/project/clbuild/} and \xsitelink{Quicklisp}{http://quicklisp.org/beta/}) to play nice with Module Manager. If you installed GBBopen using clbuild or Quicklisp, ASDF has been informed of GBBopen's \nobr{\code{\var{\/}/gbbopen.asd}} system-definition file. Otherwise, to use ASDF to set up GBBopen, you must add the \nobr{\code{gbbopen.asd}} file to ASDF's Registry manually. Then, instead of loading the \nobr{\code{\var{\/}/initiate.lisp}} file, the Module Manager and GBBopen module definitions can be loaded using ASDF by entering: % \T\smallskip \W\supp\notpretop \begin{smallexample} \textcolor{darkergray}{% cl-user> \textcolor{black}{(asdf:operate 'asdf:load-op :gbbbopen)} ;; Loading \var{\/}/initiate.lisp ;; GBBopen is installed in \var{\/} ;; Your "home" directory is \var{\/} \textrm{\ldots{}} ;; Loading \var{\/}/startup.lisp ;; GBBopen is installed in \var{\/} ;; Your "home" directory is \var{\/} ;; Loading \var{\/}/source/module-manager/module-manager-loader.lisp ;; Loading \var{\/}/\var{\/}/module-manager/module-manager.lisp \textrm{\ldots{}} ;; Loading \var{\/}/modules.lisp ;; No shared module definitions were found in \var{\/}/gbbopen-modules/. ;; No personal module definitions were found in \var{\/}/gbbopen-modules/. \textrm{\ldots{}} ;; Defining an ASDF defsystem for each Module Manager module... cl-user>} \end{smallexample} % or when ASDF is integrated with Common Lisp's \textbf{require}: % \T\smallskip \W\supp\notpretop \begin{smallexample} \textcolor{darkergray}{% cl-user> \textcolor{black}{(require :gbbopen)} ;; Loading \var{\/}/initiate.lisp ;; GBBopen is installed in \var{\/} ;; Your "home" directory is \var{\/} \textrm{\ldots{}} ;; Loading \var{\/}/startup.lisp ;; GBBopen is installed in \var{\/} ;; Your "home" directory is \var{\/} ;; Loading \var{\/}/source/module-manager/module-manager-loader.lisp ;; Loading \var{\/}/\var{\/}/module-manager/module-manager.lisp \textrm{\ldots{}} ;; Loading \var{\/}/modules.lisp ;; No shared module definitions were found in \var{\/}/gbbopen-modules/. ;; No personal module definitions were found in \var{\/}/gbbopen-modules/. \textrm{\ldots{}} ;; Defining an ASDF defsystem for each Module Manager module... cl-user>} \end{smallexample} Notice that loading the \nobr{\code{\var{\/}/initiate.lisp}} file loaded only GBBopen's REPL command processing extensions, global REPL command definitions, and module-directory processing into Common Lisp--the Module Manager is not loaded until it is needed (such as when we performed the \nobr{\code{:gbbopen-user}} REPL command). The ASDF \code{:gbbopen} ``system'' start up, on the other hand, must also load the Module Manager and module definitions, as they are required in order to define an ASDF system for each Module Manager module. \end{notebox} \ppar{Personal \texttt{gbbopen-init.lisp} file} \index{initialization, personal gbbopen-init.lisp@\code{gbbopen-init.lisp} file}% \index{gbbopen-init.lisp@\code{gbbopen-init.lisp}, personal initializations file}% \index{loading!user-specific module definitions}% \index{module definitions, loading user-specific}% \bfindexit{user-homedir-pathname}% % If a \nobr{\code{gbbopen-init.lisp}} file (source or compiled) is present in the user's ``home'' directory (as defined by \nobr{\textbf{user-homedir-pathname}}), it is loaded by the \nobr{\code{\var{\/}/startup.lisp}} file after the \reflink{Module Manager Facility}{sec:module-manager} and definitions have been loaded. A personal \nobr{\code{\var{\/}/gbbopen-init.lisp}} file is a handy mechanism for defining user-specific modules, application \glref{modules}, GBBopen parameters, and other personalizations. Here is a simple example of a personal \nobr{\code{\var{\/}/gbbopen-init.lisp}} file that defines a root directory named \nobr{\code{:my-app-root}} and the \glref{module} \nobr{\code{:my-app}}: % \W\supp \begin{example} ;;;; -*- Mode:Common-Lisp; Package:CL-USER -*- (in-package :cl-user) (module-manager:\entlink{define-root-directory} :my-app-root (make-pathname :directory "~/my-app")) (module-manager:\entlink{define-module} :my-app (:requires :gbbopen-user) (:directory :my-app-root) (:files "my-file")) ;;; =============================================== ;;; End of File ;;; =============================================== \end{example} For shared or more substantial application \glref{modules}, we recommend a packaging convention that mirrors that of GBBopen. This will be discussed shortly in conjunction with using a \reflink{personal \nobr{\code{gbbopen-modules}} directory}{sec:personal-gbbopen-modules-directory}. \ppar{Personal \texttt{gbbopen-commands.lisp} file} \index{initialization, personal gbbopen-commands.lisp@\code{gbbopen-commands.lisp} file}% \index{gbbopen-commands.lisp@\code{gbbopen-commands.lisp}, personal initializations file}% \index{loading!user-specific, REPL command definitions}% \index{REPL command definitions, loading user-specific}% \bfindexit{user-homedir-pathname}% % You can create your own \glref{REPL~commands} by defining them in a personal \nobr{\code{gbbopen-commands.lisp}} file. If a \nobr{\code{gbbopen-commands}} file (source or compiled) is present in the user's ``homedir'' home directory (as defined by \nobr{\textbf{user-homedir-pathname}}), it is loaded automatically by GBBopen's \nobr{\code{initiate.lisp}} file. For example, the following personal \nobr{\code{gbbopen-commands.lisp}} file defines a \glref{REPL~command} (named \nobr{\code{:my-app}}) and an equivalent \glref{function} \nobr{(\code{cl-user::my-app}}) for compiling and loading the \nobr{\code{:my-app}} \glref{module} that was defined above: % \W\supp\notpretop \begin{example} ;;;; -*- Mode:Common-Lisp; Package:CL-USER -*- (in-package :cl-user) (\entlink{define-repl-command} :my-app (&rest options) "Compile and load my GBBopen application module" (\entlink{startup-module} :my-app options :gbbopen-user)) ;;; =============================================== ;;; End of File ;;; =============================================== \end{example} \ppar{Personal \texttt{gbbopen-modules} directory} \label{sec:personal-gbbopen-modules-directory} \index{initialization, personal gbbopen-modules@\code{gbbopen-modules} directory files}% \index{gbbopen-modules@\code{gbbopen-modules}, personal module definitions}% \index{loading!user-specific module definitions}% \index{module definitions, loading user-specific}% \bfindexit{user-homedir-pathname}% % Although a personal \nobr{\code{gbbopen-init.lisp}} file can be used to define the \glref{module} \nobr{\code{:my-app}}, GBBopen provides an alternative mechanism that is even more convenient if you develop, share, or use a number of \glref{modules} or applications. If a \nobr{\code{gbbopen-modules}} directory is present in the user's home directory (as defined by \nobr{\code{user-homedir-pathname}}), it is expected to consist of directories each containing an individual GBBopen application or library. Although these application directories can be placed directly in the \nobr{\code{gbbopen-modules}} directory, it is generally more convenient to use a symbolic link (or a ``pseudo symbolic-link file'' on Windows) to point to the actual application directory, where ever it is located. For example, an application can be provided to a number of users by creating a symbolic link to the actual application directory in each user's \nobr{\code{gbbopen-modules}} directory. Each application directory contains: % \begin{tightitemize} \item a \code{modules.lisp} file that contains \glref{module} definitions (loaded after the personal \nobr{\code{gbbopen-init.lisp}} file if there is one in the user's ``homedir'') \item a directory named \code{source} containing all the source files for the \glref{module} or application \item an optional \code{commands.lisp} file that specifies \glref{REPL~commands} for the \glref{module} (loaded after the personal \nobr{\code{gbbopen-commands.lisp}} file if there is one in the user's ``homedir'') \item any additional directories or files useful to the application \end{tightitemize} We highly recommend following this packaging convention, which mirrors that of GBBopen itself. It is very easy to create, use, and share \glref{modules} defined in this way by placing symbolic links to the module directories in your personal \nobr{\code{gbbopen-modules}} directory. Windows, unfortunately, is the exception to this as Windows does not provide symbolic links. GBBopen users running on Windows must create a text file with the file extension \code{.sym} (that contains the target directory path as its sole line) as a stand-in for the symbolic link. \ppar{Installation-wide \texttt{shared-gbbopen-modules} directory} \label{sec:shared-gbbopen-modules-directory} \index{initialization, shared-gbbopen-modules@\code{shared-gbbopen-modules} directory files}% \index{shared-gbbopen-modules@\code{shared-gbbopen-modules}, shared module definitions}% \index{loading!installation-wide, shared module definitions}% \index{module definitions, loading installation-wide, shared}% % There is also an \nobr{\code{\var{\/}/shared-gbbopen-modules}} directory. As with a user's \nobr{\code{gbbopen-modules}} directory (discussed above), the \nobr{\code{shared-gbbopen-modules}} directory is assumed to contain symbolic links (or ``pseudo-symbolic-link'' files on Windows) to individual GBBopen module directory trees. This is the recommended mechanism for installation-wide managing and sharing of modules and applications. \ppar{GBBopen Hyperdoc} \label{sec:hyperdoc} \index{GBBopen!Hyperdoc}% \index{GBBopen!Hyperdoc!access from Emacs}% \index{Emacs!GBBopen Hyperdoc access}% \index{Emacs!Meta-?}% \index{Meta-?, Emacs key binding}% \index{Hyperdoc, on line}% \indexit{Common Lisp HyperSpec}% \indexit{SLIME}% \indexit{ILISP}% \codeindex{browse-hyperdoc.el}% \codeindex{hyperspec.el}% Convenient access to a local copy of the GBBopen Hyperdoc manual from Common Lisp is available by using the \nobr{\textbf{\entlink{browse-hyperdoc}}} function; part of the \reflink{\nobr{\code{:os-interface}}}{sec:os-interface} \glref{module}. The browser used by \nobr{\textbf{\entlink{browse-hyperdoc}}} is specified by the value of \nobr{\code{\entlink{*preferred-browser*}}}. A different value can be specified in either your Common Lisp initialization file or, preferably, in your personal \nobr{\code{gbbopen-init.lisp}} file. Changing the default setting in GBBopen's \nobr{\code{startup.lisp}} is not recommended. \xsitelink{Emacs}{http://www.gnu.org/software/emacs/emacs.html} access to the GBBopen Hyperdoc is provided by \nobr{\code{\var{\/}/browse-hyperdoc.el}}. This file defines the interactive Emacs command \nobr{\code{browse-hyperdoc}} and binds it to \nobr{\code{META-?}}. To enable this command, load \nobr{\code{\var{\/}/browse-hyperdoc.el}} from your \code{.emacs} initialization file. If you already use the \xsitelink{\nobr{\code{hyperspec.el}}}{http://cvs.sourceforge.net/viewcvs.py/ilisp/ILISP/extra/hyperspec.el?rev=1.5&view=auto} utility (included with \xsitelink{SLIME}{http://common-lisp.net/project/slime/} and \xsitelink{ILISP}{http://sourceforge.net/projects/ilisp/} distributions, but usable on its own), the Emacs \nobr{\code{browse-hyperdoc}} command will automatically defer to the \xsitelink{Common Lisp HyperSpec}{http://www.lispworks.com/documentation/HyperSpec/} when given a non-GBBopen entity. You can also download and install a local copy of the Common Lisp HyperSpec for use without a network connection. In this case, set the value of \nobr{\code{common-lisp-hyperspec-root}} in your \code{.emacs} initialization file to point to your local copy of the HyperSpec. For example: % \W\supp \begin{example} (setf common-lisp-hyperspec-root "file:/usr/local/CLHS/") \end{example} Highly recommended! \W\entities \T\ppar{Starting-up entities} \T Descriptions of entities related to installing and customizing GBBopen follow. \T\clearpage \T\renewcommand{\headrulewidth}{0.01pt} %% ------------------------------------------------------------------------ \begin{functiondoc}[ignored-gbbopen-modules-directory-subdirectories-var]% {Variable}{*ignored-gbbopen-modules-directory-subdirectories*}{}% \fnsyntax \fnpurpose Specify subdirectory names to be ignored by GBBopen's \code{gbbopen-modules} directory processing. \fnpackage \code{:common-lisp-user} \fnmodule Defined in \code{gbbopen-modules-directory.lisp} \fnvaluetype A list \fninitialvalue \code{(".svn")} \fndescription Subdirectories named in \nobr{\code{*ignored-gbbopen-modules-directory-subdirectories*}} are ignored when processing shared and personal \code{gbbopen-modules} directories for command and module definitions. \fnexample Add \code{"CVS"} to the list of subdirectories that are ignored by GBBopen's \code{gbbopen-modules} directory processing: % \W\supp \begin{example} > (push "CVS" *ignored-gbbopen-modules-directory-subdirectories*) ("CVS" ".svn") > \end{example} \end{functiondoc} %% ------------------------------------------------------------------------ \begin{functiondoc}[gbbopen-modules-directory-verbose-var]% {Variable}{*gbbopen-modules-directory-verbose*}{}% \fnsyntax \fnpurpose Controls whether the processing of individual modules is shown during \nobr{\code{gbbopen-modules}} directory processing. \fnpackage \code{:common-lisp-user} \fnmodule Defined in \code{gbbopen-modules-directory.lisp} \fnvaluetype A \glref{generalized~boolean} \fninitialvalue \code{t} \end{functiondoc} %% ------------------------------------------------------------------------ \begin{functiondoc}[preferred-browser-var]{Variable}{*preferred-browser*}{}% \fnsyntax \fnpurpose Specify the preferred browser program. \fnpackage \code{:common-lisp-user} \fnmodule Defined in \code{startup.lisp} \fnvaluetype A string \fninitialvalue (see the first example below) \fndescription To change the preferred browser, set the value of \nobr{\code{*preferred-browser*}} in either your Common Lisp initialization file or your personal \nobr{\code{gbbopen-init.lisp}} file. Because \nobr{\code{startup.lisp}} is under \xsitelink{Subversion}{http://subversion.tigris.org} source control, changing \nobr{\code{startup.lisp}} directly is not recommended. \begin{alsos}{browse-hyperdoc} \also[browse-hyperdoc] \end{alsos} \fnexamples Here is the setting that is made in \nobr{\code{startup.lisp}}: % \W\supp \begin{example} (defvar *preferred-browser* ;; On Mac OSX we defer to the OS default browser: #+(or macosx darwin) "open" ;; LispWorks (non-Windows) and SBCL do not search PATH for programs, so ;; the path must be explicitly included in the preferred browser setting: #+(or (and lispworks (not win32)) sbcl) "/usr/bin/firefox" #-(or macosx darwin (and lispworks (not win32)) sbcl) "firefox") \end{example} Specify a different browser (in a personal \nobr{\code{gbbopen-init.lisp}} file) on Linux machines: % \W\supp \begin{example} (in-package :common-lisp-user) #+linux (setf *preferred-browser* ;; Lispworks (non-Windows) and SBCL do not search PATH for programs, so ;; the path must be explicitly included in the preferred browser setting: #+(or lispworks sbcl) "/usr/bin/opera" #-(or lispworks sbcl) "opera") \end{example} \fnnote % \xsitelink{LispWorks}{http://www.lispworks.com} (non-Windows platforms) and \xsitelink{SBCL}{http://sbcl.sourceforge.net} do not perform a \code{PATH} search for programs, so the browser-program path must be explicitly included in the preferred browser setting. \end{functiondoc} %% ------------------------------------------------------------------------ \begin{functiondoc}[sym-file-verbose-var]% {Variable}{*sym-file-verbose*}{}% \fnsyntax \fnpurpose Controls whether the mapping from \code{*.sym} pseudo-symbolic-link files to target module directories is shown during \nobr{\code{gbbopen-modules}} directory processing. \fnpackage \code{:common-lisp-user} \fnmodule Defined in \code{gbbopen-modules-directory.lisp} \fnvaluetype A \glref{generalized~boolean} \fninitialvalue \nil \fnexample % Show \code{*.sym} pseudo-symbolic-link file to target module-directory mapping \code{gbbopen-modules} directory processing on startup module loading (after \nobr{\code{\var{\/}/initiate.lisp}} has been loaded): % \W\supp \begin{example} > (setf *sym-file-verbose* 't) t > :startup ;; Loading \var{\/}/startup.lisp ;; GBBopen is installed in \var{\/} ;; Your "home" directory is \var{\/} ;; Loading \var{\/}/source/module-manager/module-manager-loader.lisp ;; Loading \var{\/}/source/module-manager/module-manager.lisp ;; Loading \var{\/}/source/module-manager/module-manager-user.lisp ;; Loading \var{\/}/source/modules.lisp ;; No shared module definitions were found in \var{\/}/shared-gbbopen-modules/. ;; Loading personal module definitions from \var{\/}/gbbopen-modules/... ;; Pseudo (*.sym) link \var{\/}/gbbopen-modules/an-app.sym --> /usr/local/an-app/ ;; Loading /usr/local/an-app/modules.lisp T > > \end{example} \end{functiondoc} %% ------------------------------------------------------------------------ \begin{functiondoc}{Macro}{define-repl-command}{% \var{\nobr{command-name-spec} \nobr{lambda-list\/}} \nobr{[\var{declaration\/}\superstar{} \vbar{} \var{documentation\/}]} \nobr{\var{form\/}\superstar}} \index{startup!defining REPL commands}% \index{command, top-level loop, defining}% \index{defining!a REPL command}% \fnsyntax \fnpurpose Define a top-level REPL (read-eval-print loop) \glref{command}. \fnpackage \code{:common-lisp-user} (also imported into and exported from \nobr{\code{:module-manager}}) \fnmodule Defined in \code{extended-repl.lisp} \fnargs \begin{args}{command-name-spec} \arg[command-name-spec] A \var{command-name\/} or a list \nobr{\code{(}\var{command-name} \var{option\/}\superstar\code{)}} \arg[lambda-list] A lambda-list \arg[declaration] A declare expression (not evaluated) \arg[documentation] A documentation string (not evaluated) \arg[form] A \glref{form} \end{args} \fndsyntax \W\supp\tabletop \begin{tabular}{@{~}l@{~}l} \nobr{\var{option\/} ::=} & \code{:add-to-native-help} \vbar{} \code{:no-help} \vbar{} \nobr{\code{:no-cl-user-function}}\\ \end{tabular} \fnterms \begin{args}{command-name} \arg[command-name] A \glref{keyword~symbol} naming the \glref{command} \end{args} \fndescription The arguments to the \glref{command} are not evaluated before the command is invoked; it is up to the command to perform argument evaluation if needed (see the example, below). If the \nobr{\code{:add-to-native-help}} option is specified, then the \glref{command} and its \nobr{\var{documentation\/}} string are added to the Common Lisp implementation's primary REPL help; otherwise the command is only added to the extended-REPL commands help that is displayed by the \nobr{\code{:commands}} REPL command. (Not all Common Lisp implementations distinguish primary and secondary command-help levels.) If the \code{:no-help} option is specified, then the \glref{command} is not added to either the primary or secondary help displays. An equivalent function in the \nobr{\code{:common-lisp-user}} package is normally defined for the \nobr{\var{command-name\/}} \glref{keyword~command}, and this function can be used when REPL keyword-command processing is not fully supported. However, a \nobr{\code{:common-lisp-user}} functional version of the \glref{command} is not defined if the \nobr{\code{:no-cl-user-function}} option is specified. \var{Documentation\/} is a documentation string to be associated with the \glref{REPL~command} \nobr{\var{command-name}}. \begin{alsos}{startup-module} \also[startup-module] \end{alsos} \fnexamples Define a \glref{REPL~command} named \code{:ds} to be a handy shortcut to the Common Lisp \nobr{\code{describe}} function: % \W\supp \begin{example} (define-repl-command (:ds :add-to-native-help) (obj) "Describe object" (describe (eval obj))) \end{example} Define a \glref{REPL~command} named \nobr{\code{:my-app}} that compiles and loads the \glref{module} \nobr{\code{:my-app}} and sets the current package to the \nobr{\code{:gbbopen-user}} package: % \W\supp \begin{example} (define-repl-command :my-app (&rest options) "Compile and load my GBBopen application module" (\entlink{startup-module} :my-app options :gbbopen-user)) \end{example} \end{functiondoc} %% ------------------------------------------------------------------------ \begin{functiondoc}{Function}{funcall-in-package}% {\var{symbol package-name\/} \nobr{\code{\&rest} \var{args\/}}} \index{calling a function in another package}% \index{startup!calling a function in another package}% \fnsyntax \fnpurpose Apply a function to arguments when the package containing the function may not exist until execution time. \fnpackage \code{:common-lisp-user} (not exported) \fnmodule Defined in \nobr{\code{initiate.lisp}} (or in \nobr{\code{startup.lisp},} if \nobr{\code{initiate.lisp}} is not used to initiate GBBopen) \fnargs \begin{args}{package-name} \arg[symbol] A symbol \arg[package-name] A package name \arg[args] Arguments to the function \end{args} \fndescription This function provides a convenient means of applying a function to arguments, when the package containing the function may not exist until execution time. The function to be applied is determined at runtime by using the name of \var{symbol\/} to find the symbol with the same name in \var{package\/} and using it as the function designator. \fnexample \bfindexit{define-repl-command}% % Define a \glref{REPL~command} named \nobr{\code{:my-app}} that compiles and loads the \glref{module} \nobr{\code{:my-app}}, sets the current package to the \nobr{\code{:gbbopen-user}} package, and then calls the function \nobr{\code{startup}} in the package \nobr{\code{:my-app-package}} that is defined when the \nobr{\code{:my-app}} module is loaded: % \W\supp \begin{example} (\entlink{define-repl-command} :my-app (&rest options) "Compile and load my GBBopen application module" (startup-module :my-app options :gbbopen-user) ;; Call the startup function: (funcall-in-package '#:startup :my-app-package)) \end{example} \end{functiondoc} %% ------------------------------------------------------------------------ \begin{functiondoc}{Function}{startup-module}% {\var{\nobr{module-name} options\/} \nobr{\code{\&optional} \var{package-name\/}}} \index{compiling, a module, and also loading module}% \index{loading!a module}% \index{module!compiling, recompiling, and loading}% \index{module!directory}% \index{recompiling, a module, and also loading module}% \index{startup!compiling a module and also loading}% \index{startup!setting current package}% \fnsyntax \fnpurpose Compile and load a GBBopen \glref{module}, even if the \reflink{Module Manager Facility}{sec:module-manager} is not yet loaded, and optionally set the current package. \fnpackage \code{:common-lisp-user} (not exported) \fnmodule Defined in \code{initiate.lisp} \fnargs \begin{args}{package-name} \arg[module-name] A \glref{keyword~symbol} naming a \glref{module} \arg[option] Any of the following \glref{keywords}: \compilemoduleoptions \arg[package-name] A package name (default is \nil) \end{args} \fnerrors \modulenotdefined\\ \relativedircircularity \fndescription This function bootstraps GBBopen loading, if needed, before calling \nobr{\textbf{\entlinknoex{compile-module}}} on \nobr{\var{module-name\/}} with \nobr{\var{options}}. Then, unless \nobr{\var{package-name\/}} is \nil, the current package is set to the package named by \nobr{\var{package-name}}. The named package does not need to be defined before calling \nobr{\textbf{startup-module}}, but it must be defined at the conclusion of \glref{module} compilation and loading. \codeindexqualit{:nopropagate}{compile/load-module option}% \codeindexqualit{:propagate}{compile/load-module option}% % \textbf{Startup-module} adds the option \nobr{\code{:propagate}} to the supplied \nobr{\var{options}}. If this propagation behavior is not desired, the \nobr{\code{:nopropagate}} option can be specified to override (cancel) propagation. \begin{alsos}{define-repl-command} \also[compile-module] \also[define-module] \also[define-repl-command] \end{alsos} \fnexample % Define a \glref{REPL~command} named \nobr{\code{:my-app}} that compiles and loads the \glref{module} \nobr{\code{:my-app}} and sets the current package to the \nobr{\code{:gbbopen-user}} package: % \W\supp \begin{example} (\entlink{define-repl-command} :my-app (&rest options) "Compile and load my GBBopen application module" (startup-module :my-app options :gbbopen-user)) \end{example} \end{functiondoc} %% ------------------------------------------------------------------------ \begin{functiondoc}{Macro}{with-system-name}{% \nobr{\code{(}\var{system-name\/}\code{)}} \nobr{\var{form\/}\superstar{}} \nobr{\returns{} \var{result\/}\superstar}} \index{compiling, a module, and also loading module}% \index{loading!a module}% \index{module!compiling, recompiling, and loading}% \index{module!directory}% \index{recompiling, a module, and also loading module}% \index{startup!compiling a module and also loading}% \index{startup!setting current package}% \fnsyntax \fnpurpose Associate \nobr{\var{system-name\/}} with \glref{REPL~commands}, directory definitions, and module definitions defined in \var{forms}. \fnpackage \code{:common-lisp-user} (also imported into and exported from \nobr{\code{:module-manager}}) \fnmodule Defined in \code{extended-repl.lisp} \fnargs \begin{args}{system-name} \arg[system-name] A \glref{keyword~symbol} identifying a \glref{system} \arg[form] A \glref{form} \arg[results] The values returned by evaluating the last \var{form} \end{args} \fnreturns The values returned by evaluating the last \var{form}. \begin{alsos}{define-relative-directory} \also[define-relative-directory] \also[define-root-directory] \also[define-module] \also[define-repl-command] \end{alsos} \fnexamples % Define a \glref{REPL~command} named \nobr{\code{:my-app}} associated with system \nobr{\code{:my-app}} that compiles and loads the \glref{module} \nobr{\code{:my-app}} and sets the current package to the \nobr{\code{:gbbopen-user}} package: % \W\supp \begin{example} (with-system-name (:my-app) (\entlink{define-repl-command} :my-app (&rest options) "Compile and load my GBBopen application module" (\entlink{startup-module} :my-app options :gbbopen-user))) \end{example} Now, show the \glref{commands} associated with \glref{system} \nobr{\code{:my-app}}: % \W\supp \begin{example} > :commands :my-app Command Description ------- ----------- :my-app Compile and load my GBBopen application module > \end{example} Now, undefine all the \glref{commands}, directories, and module definitions associated with \glref{system} \nobr{\code{:my-app}}: % \W\supp \begin{example} > :undefine-system :my-app Really undefine commands, directories, & modules of :my-app? y ;; System :my-app undefined. > :commands :my-app ;; System :my-app was not found. > \end{example} \fnnotes % A developer will typically wrap the \nobr{\textbf{\entlink{define-repl-command}}} forms in an application's \nobr{\code{commands.lisp}} file with a single \nobr{\textbf{with-system-name}} macro and the definitions in the application's \nobr{\code{modules.lisp}} file with a second \nobr{\textbf{with-system-name}} macro. \end{functiondoc} %% ======================================================================== %% Module Manager Facility \T\markright{}% \T\pagestyle{plain} \T\cleardoublepage \W\xname{ref-module-manager-entities} \T\pagestyle{fancy} \T\thispagestyle{fancybottom} \T\global\def\fnlastname{ }% \T\renewcommand{\headrulewidth}{0pt} \section{Module Manager Facility} \label{sec:module-manager}% \index{module!:module-manager@\code{:module-manager}}% \index{:module-manager@\code{:module-manager} module}% \index{:module-manager@\code{:module-manager} module!loading}% \index{module!:module-manager@\code{:module-manager}!loading}% \index{loading!:module-manager@\code{:module-manager} module}% \index{module!loading!:module-manager@\code{:module-manager} module}% \index{startup.lisp@\code{startup.lisp} file|itidx}% \index{defsystem packages}% \index{ASDF (Another System Definition Facility)}% % The Module Manager Facility provides a lightweight and easy to use mechanism for compiling and loading \glref{module} files. The facility keeps track of the dependencies between modules and the modules that have been compiled and loaded. The Module Manager Facility was designed to be easy to use, yet it is powerful enough to manage substantial software projects, each operating on multiple hardware platforms and Common Lisp implementations. Other, more complex, \nobr{\textbf{defsystem}} packages, such as (\xsitelink{ASDF}{http://common-lisp.net/project/asdf/}), are available, but their complexity makes defining and maintaining correct system definitions difficult. \index{initialization, personal gbbopen-init.lisp@\code{gbbopen-init.lisp} file}% \index{gbbopen-init.lisp@\code{gbbopen-init.lisp}, personal initializations file}% \index{loading!user-specific module definitions}% \index{module definitions, loading user-specific}% \bfindexit{user-homedir-pathname}% % The \code{:module-manager} \glref{module} is automatically loaded by the GBBopen \nobr{\code{\var{\/}/startup.lisp}} file (by the \nobr{\code{module-manager-loader.lisp}} file located in the \nobr{\code{module-manager}} subdirectory). If a \nobr{\code{gbbopen-init.lisp}} file (source or compiled) is present in the user's ``home'' directory, it is loaded immediately following the loading of the Module Manager Facility. A personal \nobr{\code{\var{\/}/gbbopen-init.lisp}} file is very useful for defining GBBopen parameters and other personalizations % \W\begin{iftex} (see \link{Section~\ref{sec:startup}}{sec:startup}). \W\end{iftex} \T\begin{ifhtml} (see the GBBopen \link{start-up description}{sec:startup}). \T\end{ifhtml} \ppar{Key concepts} The Module Manager Facility incorporates several important concepts: \begin{tightitemize} % \item Dependencies are maintained among modules, rather than among individual files. Defining compilation and loading dependencies at the file level (and maintaining those dependencies as applications and libraries evolve) is both complex and error prone. Instead, each Module Manager module definition specifies a total ordering of any other modules that it requires (directly) as well as a total ordering of the individual files that comprise the module. (It is an error for a file to be associated with more than one module.) % \item A total ordering of all the individual files that are required and used by a module is generated from the module definitions. The Module Manager Facility expands a module's specified required modules recursively to obtain a fully expanded sequence of all the modules that are required (directly or indirectly) by the module. The individual files associated with each module in this fully expanded sequence of required modules define the sequence of all the individual files that must be possibly compiled and/or loaded as part of compiling or loading the module. % \item Recompilation and reloading dependencies are specified as options associated with individual files. For example, if the option \nobr{\code{:forces-recompile}} is specified for a file and that file needs to be recompiled, all files later in the total file sequence need to be recompiled and reloaded. This simple, ``somewhat aggressive'' recompilation mechanism replaces complex definitions of pairwise dependencies between individual files (and the risk of missed and no-longer-appropriate dependencies), but at the cost of some unneeded recompilation. It also simplifies handling dependencies that exist between some files in a requiring module and files in ones of that module's required modules when each module is supported by a different developer/maintainer. A developer only needs to consider whether a file includes forms (such as macro definitions and compiler transforms) that may effect the compilation and/or loading of downstream files (whether or not those files are known to the developer). With today's fast Common Lisp compilers, some unnecessary recompilation is a small price to pay for easier and more likely to be correct dependency specifications. % \item The fully expanded required module sequences of all modules (and therefore the compilation and loading sequence of files for all modules) must be consistent. This requirement is checked by the Module Manager and ensures that the ordering of file compilation and loading will be maintained no matter what module (or modules) is being loaded. Ordering consistency is important in avoiding unnecessary recompilation of unchanged files if different modules were allowed to specify their sequence of overlapping required modules differently. Although required-module ordering consistency is a very strong constraint---especially when independently development modules use common libraries as required modules---in practice, existing required-module orderings quickly eliminate most ``otherwise arbitrary'' required-module orderings. Where two required modules are not constrained as to their pairwise ordering, the convention of specifying the module that is earlier alphabetically first is recommended. % \item Separate compiled-file directory trees are created for each Common Lisp implementation and platform. These compiled-file directories mirror the directory structure of the original source-file directory tree of a system. This separation makes packaging and distributing compiled files for one or more platforms (with or without the source tree) simple by including only the desired directory trees. % \item Freezing a release (and providing patches later, if needed) are important phases of the release life cycle of some applications. Support for freezing and patches that are in keeping with the above concepts is provided explicitly by Module Manager operators. \end{tightitemize} \ppar{Stand-alone usage} To bootstrap the Module Manager Facility stand-alone (separate from the GBBopen Project software tree), do the following: \begin{tightitemize} \item create a ``root'' directory to contain the Module Manager software tree\\ (for example: \nobr{\code{\$ mkdir my-tree}}) \item create the Module Manager portion of the source tree in the newly created ``root'' directory\\ (for example: \nobr{\code{\$ cd my-tree ; mkdir -p source/module-manager}}) \item copy the \xsitelink{\nobr{\code{module-manager-loader.lisp}}}{http://gbbopen.org/svn/GBBopen/trunk/source/module-manager/module-manager-loader.lisp}, \W~ \xsitelink{\nobr{\code{module-manager.lisp}}}{http://gbbopen.org/svn/GBBopen/trunk/source/module-manager/module-manager.lisp}, \W~ and \xsitelink{\nobr{\code{module-manager-user.lisp}}}{http://gbbopen.org/svn/GBBopen/trunk/source/module-manager/module-manager-user.lisp} files into the \nobr{\code{source/module-manager}} directory \item start your Common Lisp implementation and then load the \nobr{\code{module-manager-loader.lisp}} file\\ ~~~\nobr{\code{> (load "my-tree/source/module-manager/module-manager-loader")}} \item compile the \nobr{\code{:module-manager}} and \nobr{\code{:module-manager-user}} modules:\\ ~~~\nobr{\code{> (module-manager:\entlink{compile-module} :module-manager-user :create-dirs :propagate)}} \end{tightitemize} % After performing the above steps, the Module Manager can be used stand-alone by loading \nobr{\code{source/module-manager-loader.lisp}} as part of your Common Lisp initialization. \W\entities \T\ppar{Module Manager entities} \T Descriptions of Module Manager entities follow. \T\clearpage \T\renewcommand{\headrulewidth}{0.01pt} %% ------------------------------------------------------------------------ \begin{functiondoc}[automatically-create-missing-directories-var]{Variable}% {*automatically-create-missing-directories*}{}% \index{compiling, a module, and also loading module!creating missing directories}% \index{module!compiling, recompiling, and loading!creating missing directories}% \index{recompiling, a module, and also loading module!creating missing directories}% \fnsyntax \fnpurpose Controls whether any directories that are missing in the compiled-file tree should be created when needed. \fnpackage \code{:common-lisp-user} (also imported into and exported from \nobr{\code{:module-manager}}) \fnmodule \code{:module-manager} \fnvaluetype A \glref{generalized~boolean} \fninitialvalue \code{t} \fndescription % By default, the Module Manager will create any needed directories in the compiled-file tree automatically during module compilation. For tighter control over new directory creation, \nobr{\textbf{*automatically-create-missing-directories*}} can be set to \nil, causing \nobr{\textbf{\entlink{compile-module}}} to signal a continuable error during compilation if a needed directory is missing in the compiled-file tree. When \nobr{\textbf{*automatically-create-missing-directories*}} has been set to \nil, the \nobr{\textbf{\entlink{compile-module}}} option \nobr{\code{:create-dirs}} provides a convenient way to bind \nobr{\textbf{*automatically-create-missing-directories*}} to true during compilation of a specified \glref{module}. \begin{alsos}{compile-module} \also[compile-module] \end{alsos} \fnexample % Have the Module Manager generate a continuable error during module compilation when a needed directory in the compiled-file tree is missing (and the compile-module option \nobr{\code{:create-dirs}} was not specified when compiling the module needing that missing directory): % \W\supp \begin{example} (setf common-lisp-user::*automatically-create-missing-directories* nil) \end{example} \end{functiondoc} %% ------------------------------------------------------------------------ \begin{functiondoc}[autorun-modules-var]{Variable}{*autorun-modules*}{}% \index{loading!a module!controlling autorun forms}% \fnsyntax \fnpurpose Indicates whether a \glref{module} should evaluate \glref{autorun~forms} when it is loaded. \fnpackage \code{:common-lisp-user} (also imported into and exported from \nobr{\code{:module-manager}}) \fnmodule \code{:module-manager} \fnvaluetype A \glref{generalized~boolean} \fninitialvalue True \fndescription The value of \nobr{\textbf{*autorun-modules*}} can be used to conditionally evaluate forms when \glref{module} files are loaded. By default, the value of \nobr{\textbf{*autorun-modules*}} is set to true, but it can be set or bound to \nil{} to disable conditional \glref{autorun~forms}. The compile-module or load-module option \nobr{\code{:noautorun}} can also be specified to bind \nobr{\textbf{*autorun-modules*}} to \nil{} during module compilation and loading. \begin{alsos}{load-module-file} \also[compile-module] \also[load-module] \also[load-module-file] \end{alsos} \fnexample Conditionally evaluate the \nobr{\code{http-test}} function when the file \nobr{\code{http-test.lisp}} that includes the following form is loaded: % \W\supp \begin{example} (when common-lisp-user::*autorun-modules* (http-test "GBBopen.org" 80)) \end{example} \end{functiondoc} %% ------------------------------------------------------------------------ \begin{functiondoc}[patches-only-var]{Variable}{*patches-only*}{}% \index{compiling, a module, and also loading module!patches only}% \index{loading!a module!patches only}% \index{module!compiling, recompiling, and loading!patches only}% \index{recompiling, a module, and also loading module!patches only}% \fnsyntax \fnpurpose Controls whether regular files (non-\glref{patch} files) in \glref{modules} are compiled and loaded by the Module Manager. \fnpackage \code{:common-lisp-user} (also imported into and exported from \nobr{\code{:module-manager}}) \fnmodule \code{:module-manager} \fnvaluetype A \glref{generalized~boolean} \fninitialvalue \nil \fndescription By default, \nobr{\textbf{*patches-only*}} is set to \nil, but it can be set to true to instruct \nobr{\textbf{\entlink{compile-module}}} and \nobr{\textbf{\entlink{load-module}}} to bypass compiling and loading regular files (non-\glref{patch} files) in \glref{modules}. By setting \nobr{\textbf{*patches-only*}} to true after loading an application, the image is ``frozen'' so that only patches will be applied by subsequent uses of \nobr{\textbf{\entlink{compile-module}}} or \nobr{\textbf{\entlink{load-module}}}. \begin{alsos}{compile-module} \also[compile-module] \also[load-module] \end{alsos} \fnexample \bfindexit{compile-module} % Compile, load, and freeze the GBBopen application defined by \glref{module} \nobr{\code{:my-app}}: % \W\supp \begin{example} > (progn (\entlink{compile-module} :my-app :propagate) (setf *patches-only* 't)) t > \end{example} \end{functiondoc} %% ------------------------------------------------------------------------ \begin{functiondoc}{Function}{compile-module}{% \nobr{\var{module-name\/}} \nobr{\code{\&rest} \var{options\/}}} \index{compiling, a module, and also loading module}% \index{loading!a module}% \index{module!compiling, recompiling, and loading}% \index{module!directory}% \index{recompiling, a module, and also loading module}% \fnsyntax \fnpurpose Compiles and loads the files in a \glref{module}. \fnpackage \code{:module-manager} \fnmodule \code{:module-manager} \fnargs \begin{args}{module-name} \arg[module-name] A \glref{keyword~symbol} naming a \glref{module} \arg[option] Any of the following \glref{keywords}: \compilemoduleoptions \end{args} \fnerrors \modulenotdefined\\ \relativedircircularity\\ \patchesonlymodulenotloaded \fndescription These file options, when specified for individual files in the \glref{module} definition (see \nobr{\textbf{\entlinknoex{define-module}}}), have the following effects (overriding the behavior of \nobr{\var{options\/}} supplied to \nobr{\textbf{compile-module}}): % \W\supp\tabletop \compilemodulefileoptions \begin{alsos}{*automatically-create-missing-directories-modules*} \also[:disable-compiler-macros] \also[:full-safety] \also[*automatically-create-missing-directories*] \also[*autorun-modules*] \also[*patches-only*] \also[define-module] \also[load-module] \also[load-module-file] \also[startup-module] \end{alsos} \fnexample Compile and load the GBBopen User \glref{module} and all its \glref{required~modules}, creating new compilation directories if they do not exist already: % \W\supp \begin{example} (compile-module :gbbopen-user :propagate :create-dirs) \end{example} \replnote \textbf{Compile-module} can be invoked using the \glref{REPL~command}: % \REPLindex{:cm}% % \W\supp \begin{example} :cm \textrm{[}\var{module-name\/} \textrm{[}\var{option\/}\superstar\textrm{]]} \end{example} % which remembers the last specified \nobr{\var{module-name\/}} and \nobr{\var{options\/}} as default values for the command. \end{functiondoc} %% ------------------------------------------------------------------------ \begin{functiondoc}{Macro}{continue-patch}{\var{form\/}\superstar} \index{module!patching}% \index{patching!a module}% \fnsyntax \fnpurpose Continue the definition of a multiple top-level form \glref{patch} to a \glref{module}. \fnpackage \code{:module-manager} \fnmodule \code{:module-manager} \fnargs \begin{args}{description} \arg[form] A \glref{form} \end{args} \fnerrors A patch has not been started with \nobr{\textbf{\entlink{start-patch}}}. \fndescription % The \textbf{continue-patch} macro, along with \nobr{\textbf{\entlink{start-patch}}} and \nobr{\textbf{\entlink{finish-patch}}}, can be used to define a patch as multiple top-level forms in the same patch file if a patch cannot be defined as a single \nobr{\textbf{\entlink{patch}}} form. \begin{alsos}{get-patch-description} \also[allow-redefinition] \also[define-module] \also[describe-module] \also[describe-patches] \also[finish-patch] \also[get-patch-description] \also[parse-date] \also[patch] \also[patch-loaded-p] \also[start-patch] \also[undefmethod] \end{alsos} \fnexample % Define a more complex \glref{patch} (in a file named \nobr{\code{my-app-p002.lisp}} in the \nobr{\code{patches}} subdirectory of the module): % \bfindexit{printv}% \bfindexit{start-patch}% \bfindexit{finish-patch}% % \W\supp \begin{example} (\entlink{start-patch} (2 "06-23-08" :author "Corkill" :description "A more complex patch example") (\entlink{printv} "More complex example patch started!")) (eval-when (:compile-toplevel) (continue-patch (\entlink{printv} "Defining compile-time-only-macro-for-patch...") (defmacro compile-time-only-macro-for-patch (x) `',x))) (eval-when (:compile-toplevel :load-toplevel :execute) (continue-patch (\entlink{printv} "Defining macro-for-patch at compile & load time...") (defmacro macro-for-patch (x) `',x)))\goodpagebreak (continue-patch (\entlink{printv} "Using macro-for-patch at load time...") (macro-for-patch abc)) (eval-when (:compile-toplevel :load-toplevel :execute) (continue-patch (\entlink{printv} "Using macro-for-patch at compile & load time...") (macro-for-patch xyz)))\goodpagebreak (eval-when (:compile-toplevel) (continue-patch (\entlink{printv} "Using compile-time-only-macro-for-patch...") (compile-time-only-macro-for-patch abc))) (\entlink{finish-patch} (\entlink{printv} "More complex example patch finished!")) \end{example} \end{functiondoc} %% ------------------------------------------------------------------------ \begin{functiondoc}{Macro}{define-module}{% \var{\nobr{module-name} \nobr{module-option\/}\superstar}} \index{module!defining or redefining}% \index{defining!a module}% \index{redefining!a module}% \fnsyntax \fnpurpose Defines a \glref{module} to the Module Manager Facility. \fnpackage \code{:module-manager} \fnmodule \code{:module-manager} \fnargs \begin{args}{module-options} \arg[module-name] A \glref{keyword~symbol} naming a \glref{module} \arg[module-options] See below \end{args} \fnerrors The \code{:requires} module option specifies a fully expanded \glref{required-module} order that contains a circularity.\\ % The \code{:requires} module option specifies a fully expanded \glref{required-module} order that conflicts with the fully expanded \glref{required-module} order in a previously defined \glref{module}. \fndsyntax \W\supp\tabletop \begin{tabular}{@{~}l@{~}l} \nobr{\var{module-option\/} ::=} & \code{(:requires} \var{module-name\/}\superstar\code{)} \vbar{} \\ & \code{(:directory} \var{directory-specifier\/}\code{)} \vbar{} \\ & \code{(:files} \var{file-specifier\/}\superstar\code{)} \vbar{} \\ & \code{(:patches} \var{file-specifier\/}\superstar\code{)} \\ \end{tabular} \T\\ \begin{tabular}{@{~}l@{~}l} \nobr{\var{directory-specifier\/} ::=} & \var{root-or-relative-directory subdirectory\/}\superstar{} \\ \end{tabular} \T\\ \begin{tabular}{@{~}l@{~}l} \nobr{\var{file-specifier\/} ::=} & \var{file-name\/} \vbar{} \\ & \code{(}\var{file-name file-option\/}\superstar\code{)} \\ \end{tabular} \T\\ \begin{tabular}{@{~}l@{~}l} \nobr{\var{file-option\/} ::=} & \code{:recompile} \vbar{} \code{:reload} \vbar{} \code{:source} \vbar{} \code{:forces-recompile} \vbar{} \code{:noload} \\ \end{tabular} \fnterms \begin{args}{root-or-relative-directory} \arg[root-or-relative-directory] A \glref{keyword} naming a \glref{root} or \glref{relative~directory}, a \glref{keyword} naming another \glref{module}, or \nil{}, indicating that the module is rooted at the \nobr{\code{*load-truename*}} value in effect when the module definition is loaded \arg[subdirectory] A string naming a subdirectory \arg[file-name] A string naming a file \arg[module-name] A \glref{keyword~symbol} naming a \glref{module} \end{args} \fndescription The \var{module-options\/} \nobr{\code{:requires}}, \nobr{\code{:directory}}, \code{:files}, and \code{:patches} can be specified in any order, but at most one of each is allowed. If a \code{:directory} module option is not specified, an implicit root directory for the \glref{module} (at the \nobr{\code{*load-truename*}} of the file containing the \nobr{\textbf{define-module}} form) is used. If the \nobr{\code{:directory}} module option specifies a \glref{keyword} naming another \glref{module}, the directory specification of the named module is used as the base (root or relative) directory for the module that is being defined. If both a \glref{module} and a \glref{root} or \glref{relative~directory} definition have the same name, the directory definition takes precedence over the module directory specification. The \code{:requires} module option specifies, in order, the \glref{modules} that must be loaded before this \glref{module}. The fully expanded \glref{required-module} order determined from the specified \nobr{\code{:requires}} module option must be consistent with all previously defined modules. The \code{:files} module option specifies, in order, the files that are compiled (when appropriate) and loaded for this \glref{module}. Similarly, the \nobr{\code{:patches}} module option specifies, in order, the \glref{patch} files that are compiled (when appropriate) and loaded for this \glref{module}. The combination of the \nobr{\code{:requires}}, \code{:files}, and \nobr{\code{:patches}} module options specifies a total ordering of all the files that must be compiled and loaded for this \glref{module} (the files associated with each of the \glref{required~modules} followed by the files specified for this \glref{module} followed by the patch files associated with each of the \glref{required~modules} followed by the patch files specified for this \glref{module}).In order to maintain an invariant patch ordering, patches should be added sequentially to the main (last loaded) module of an application. The source files for patches should be placed in a subdirectory named \nobr{\code{patches}} in the module's source-file directory. \var{File-options\/} have the following effects: % \W\supp\tabletop \compilemodulefileoptions \begin{alsos}{define-relative-directory} \also[define-relative-directory] \also[define-root-directory] \also[describe-module] \also[describe-patches] \also[compile-module] \also[continue-patch] \also[get-patch-description] \also[finish-patch] \also[load-module] \also[load-module-file] \also[patch] \also[patch-loaded-p] \also[start-patch] \also[with-system-name] \also[with-module-redefinitions] \end{alsos} \fnexamples \bfindexit{define-root-directory}% Define a \glref{root~directory} and \glref{module} for \nobr{\code{:my-app}}: % \W\supp \begin{example} (\entlink{define-root-directory} :my-app-root (make-pathname :directory "~/my-app")) (define-module :my-app (:requires :gbbopen-user) (:directory :my-app-root) (:files "preamble" ("macros" :forces-recompile) "classes" "my-app" "epilogue")) \end{example} Define a \glref{module} for \nobr{\code{:my-app}} rooted relative to the file containing the \nobr{\textbf{define-module}} form: % \W\supp \begin{example} (define-module :my-app (:requires :gbbopen-user) (:files "preamble" ("macros" :forces-recompile) "classes" "my-app" "epilogue")) \end{example} Add two \glref{patch} files to the \nobr{\code{:my-app}} \glref{module}: % \W\supp \begin{example} (define-module :my-app (:requires :gbbopen-user) (:files "preamble" ("macros" :forces-recompile) "classes" "my-app" "epilogue") (:patches "my-app-p001" "my-app-p002")) \end{example} \end{functiondoc} %% ------------------------------------------------------------------------ \begin{functiondoc}{Function}{define-relative-directory}% {\var{name directory\/} \nobr{\code{\&rest} \var{subdirectories\/}}} \index{directory!defining relative}% \index{relative directory!defining}% \index{defining!a relative directory}% \index{redefining!a relative directory}% \fnsyntax \fnpurpose Defines a directory relative to a \glref{root} or \glref{relative~directory} or to the directory specification of a \glref{module} definition. \fnpackage \code{:module-manager} \fnmodule \code{:module-manager} \fnargs \begin{args}{subdirectories} \arg[name] A \glref{keyword~symbol} naming the \glref{relative~directory} \arg[directory] The \glref{keyword~symbol} name of a \glref{root} or \glref{relative~directory} or the name of a \glref{module} \arg[subdirectories] One or more strings specifying, in order, subdirectories from \nobr{\var{directory\/}} to the relative directory. (The \glref{keyword} \code{:up} or \code{:back} can also be supplied in addition to any of these strings, indicating to go upward one semantic or syntactic level of directory structure, respectively.) \end{args} \fndescription \glref{Root} and \glref{relative~directory} definitions are used to isolate file-system details from \glref{module} definitions. A \glref{relative~directory} is defined in relation to another directory definition, that is either a \glref{root~directory} or another \glref{relative~directory} (which itself is eventually associated with a \glref{root~directory}). If this \glref{root} directory location changes, every \glref{relative~directory} associated with it is adjusted automatically. \begin{alsos}{show-defined-directories} \also[define-root-directory] \also[get-directory] \also[show-defined-directories] \also[with-system-name] \end{alsos} \fnexamples Define a relative directory below \nobr{\code{:my-app-root}} named \nobr{\code{:my-tests}}: % \W\supp \begin{example} (define-relative-directory :my-tests :my-app-root "tests") \end{example} % Define another relative directory named \nobr{\code{:my-performance-tests}} below \nobr{\code{:my-tests}}: % \W\supp\notpretop \begin{example} (define-relative-directory :my-performance-tests :my-tests "performance") \end{example} % Define a data directory sibling to the \nobr{\code{source}} directory of \nobr{\code{:my-app}} \glref{module}: % \W\supp\notpretop \begin{example} (define-relative-directory :app-data :my-app :up "data") \end{example} \end{functiondoc} %% ------------------------------------------------------------------------ \begin{functiondoc}{Function}{define-root-directory}% {\var{name \nobr{directory-specification\/}} \nobr{\code{\&rest} \var{subdirectories\/}}} \index{directory!defining root}% \index{root directory!defining}% \index{defining!a directory}% \index{redefining!a directory}% \fnsyntax \fnpurpose Define a \glref{root~directory}. \fnpackage \code{:module-manager} \fnmodule \code{:module-manager} \fnargs \begin{args}{directory-specification} \arg[name] A \glref{keyword~symbol} naming the \glref{root~directory} or a list containing the keyword-symbol name and, optionally, an application-version-identifier string \arg[directory-specification] One of the following: \begin{tightitemize} \item A string specifying the \glref{root~directory} \item A pathname specifying the \glref{root~directory} \item A \glref{keyword} naming a previously defined \glref{root~directory} \item A symbol whose value is one of the above \end{tightitemize} \arg[subdirectories] One or more strings specifying, in order, subdirectories from \nobr{\var{directory-specification\/}} to the \glref{root~directory}. (The \glref{keyword} \code{:up} or \code{:back} can also be supplied in addition to any of these strings, indicating to go upward one semantic or syntactic level of directory structure, respectively.) \end{args} \fndescription \glref{Root} and \glref{relative~directory} definitions are used to isolate file-system details from \glref{module} definitions. \glref{Root~directories} specify a fixed anchor directory for a tree of \glref{relative~directory} definitions. If the \glref{root~directory} is redefined to a new location, all \glref{relative~directories} beneath it are updated automatically. Note: When a \glref{root~directory} is used as the \nobr{\var{directory-specification\/}} for a new \glref{root~directory}, the new \glref{root-directory} location will not be changed if the location of the source \glref{root~directory} is changed. When an application-version-identifier string is supplied in \nobr{\var{name\/}}, it is concatenated to the standard \nobr{\var{\/}} compiled-directory name for all compiled module files that are defined relative to this \glref{root-directory}. \begin{alsos}{show-defined-directories} \also[define-relative-directory] \also[get-directory] \also[get-root-directory] \also[show-defined-directories] \also[with-system-name] \end{alsos} \fnexamples Define a \glref{root~directory} named \nobr{\code{:my-app-root}}: % \W\supp \begin{example} (define-root-directory :my-app-root (make-pathname :directory "~/my-app")) \end{example} % Define a \glref{root~directory} named \nobr{\code{:my-app-root}} to be the directory containing the file containing the \nobr{\textbf{define-root-directory}} form: % \W\supp\notpretop \begin{example} (define-root-directory :my-app-root *load-truename*) \end{example} % Define a \glref{root~directory} named \nobr{\code{:my-app-root}} to be the directory containing the file containing the \nobr{\textbf{define-root-directory}} form, but if the \nobr{\code{:my-app-preprelease}} feature is present, place the compiled files in a separate ``beta'' compile tree: % \W\supp\notpretop \begin{example} (define-root-directory '(:my-app-root #+my-app-prerelease "beta") *load-truename*) \end{example} \end{functiondoc} %% ------------------------------------------------------------------------ \begin{functiondoc}{Function}{describe-module}{\var{module-name\/}} \index{module!describing}% \index{module!printing information about}% \index{printing!information about!a module}% \fnsyntax \fnpurpose Print information about a \glref{module}. \fnpackage \code{:module-manager} \fnmodule \code{:module-manager} \fnargs \begin{args}{module-name} \arg[module-name] A \glref{keyword~symbol} naming a \glref{module} \end{args} \fnerrors \modulenotdefined\\ \relativedircircularity \fndescription \bfindexit{*standard-output*}% The description is printed to the {\bf *standard-output*} stream. Files and patch files shown with an asterisk following their load time indicate that the source file has been modified since that file was loaded. \begin{alsos}{define-module} \also[define-module] \end{alsos} \fnexamples Describe the \code{:gbbopen-test} \glref{module} before it has been loaded: % \W\supp \begin{example} > (describe-module :gbbopen-test) Module :gbbopen-test (not loaded) Requires: (:gbbopen-user) Fully expanded requires: (:module-manager :module-manager-user :portable-threads :gbbopen-tools :gbbopen-core :os-interface :gbbopen-user) Source directory: \nobr{\var{\/}/source/gbbopen/test/} Compiled directory: \nobr{\var{\/}/\var{\/}/gbbopen/test/} Forces recompile date: None Files: basic-tests (:reload) Patches: basic-tests-p001 basic-tests-p002 (:developing) > \end{example} Describe the \code{:gbbopen-test} \glref{module} after it has been loaded: % \W\supp \begin{example} > (describe-module :gbbopen-test) Module :gbbopen-test (loaded) Requires: (:gbbopen-user) Fully expanded requires: (:module-manager :module-manager-user :portable-threads :gbbopen-tools :gbbopen-core :os-interface :gbbopen-user) Source directory: \nobr{\var{\/}/source/gbbopen/test/} Compiled directory: \nobr{\var{\/}/\var{\/}/gbbopen/test/} Forces recompile date: None Files: Jun 27 05:22 basic-tests (:reload) Patches: Jun 27 05:22 basic-tests-p001 Jun 27 05:22* basic-tests-p002 (:developing) > \end{example} \end{functiondoc} %% ------------------------------------------------------------------------ \begin{functiondoc}{Function}{describe-patches}{\var{module-name\/}} \index{patch!describing}% \fnsyntax \fnpurpose Print information about \glref{patch} \var{id\/} to a \nobr{\var{module}}. \fnpackage \code{:module-manager} \fnmodule \code{:module-manager} \fnargs \begin{args}{module-name} \arg[module-name] A \glref{keyword~symbol} naming a \glref{module} \end{args} \fnerrors \modulenotdefined \begin{alsos}{get-patch-description} \also[continue-patch] \also[define-module] \also[describe-module] \also[finish-patch] \also[get-patch-description] \also[parse-date] \also[patch] \also[patch-loaded-p] \also[start-patch] \end{alsos} \fnexamples % Display the \glref{patches} to \glref{module} \nobr{\code{:my-app}}: % \W\supp \begin{example} > (describe-patches ':my-app) ;; 1 Jun 22, 2008 Corkill (loaded Jun 24 13:08) ;; A simple example patch ;; 2 Jun 23, 2008 Corkill (loaded Jun 24 13:08) ;; A more complex patch example > \end{example} Display the \glref{patches} to \glref{module} \nobr{\code{:gbbopen-test}} (when that module has not been loaded): % \W\supp \begin{example} > (describe-patches ':gbbopen-test) ;; Module :gbbopen-test is not loaded > \end{example} \end{functiondoc} %% ------------------------------------------------------------------------ \begin{functiondoc}{Macro}{finish-patch}{\var{form\/}\superstar} \index{module!patching}% \index{patching!a module}% \fnsyntax \fnpurpose Finish the definition of a multiple top-level form \glref{patch} to a \glref{module}. \fnpackage \code{:module-manager} \fnmodule \code{:module-manager} \fnargs \begin{args}{description} \arg[form] A \glref{form} \end{args} \fnerrors A patch has not been started with \nobr{\textbf{\entlink{start-patch}}}. \fndescription % The \textbf{start-patch} macro, along with \nobr{\textbf{\entlink{continue-patch}}} and \nobr{\textbf{\entlink{finish-patch}}}, can be used to define a patch as multiple top-level forms in the same patch file if a patch cannot be defined as a single \nobr{\textbf{\entlink{patch}}} form. \begin{alsos}{get-patch-description} \also[allow-redefinition] \also[continue-patch] \also[define-module] \also[describe-module] \also[describe-patches] \also[get-patch-description] \also[parse-date] \also[patch] \also[patch-loaded-p] \also[start-patch] \also[undefmethod] \end{alsos} \fnexample % Define a more complex \glref{patch} (in a file named \nobr{\code{my-app-p002.lisp}} in the \nobr{\code{patches}} subdirectory of the module): % \bfindexit{printv}% \bfindexit{start-patch}% \bfindexit{continue-patch}% % \W\supp \begin{example} (\entlink{start-patch} (2 "06-23-08" :author "Corkill" :description "A more complex patch example") (\entlink{printv} "More complex example patch started!")) (eval-when (:compile-toplevel) (\entlink{continue-patch} (\entlink{printv} "Defining compile-time-only-macro-for-patch...") (defmacro compile-time-only-macro-for-patch (x) `',x))) (eval-when (:compile-toplevel :load-toplevel :execute) (\entlink{continue-patch} (\entlink{printv} "Defining macro-for-patch at compile & load time...") (defmacro macro-for-patch (x) `',x)))\goodpagebreak (\entlink{continue-patch} (\entlink{printv} "Using macro-for-patch at load time...") (macro-for-patch abc)) (eval-when (:compile-toplevel :load-toplevel :execute) (\entlink{continue-patch} (\entlink{printv} "Using macro-for-patch at compile & load time...") (macro-for-patch xyz)))\goodpagebreak (eval-when (:compile-toplevel) (\entlink{continue-patch} (\entlink{printv} "Using compile-time-only-macro-for-patch...") (compile-time-only-macro-for-patch abc))) (finish-patch (\entlink{printv} "More complex example patch finished!")) \end{example} \end{functiondoc} %% ------------------------------------------------------------------------ \begin{functiondoc}{Function}{get-directory}{\var{name\/} \nobr{\code{\&rest} \var{subdirectories\/}} \nobr{\returns{} \var{pathname\/}}} \index{directory!getting pathname from name}% \fnsyntax \fnpurpose Return the pathname based on a \glref{root~directory}, a \glref{relative~directory}, or a \glref{module}. \fnpackage \code{:module-manager} \fnmodule \code{:module-manager} \fnargs \begin{args}{directory-specification} \arg[name] A \glref{keyword~symbol} naming a \glref{root~directory}, a \glref{relative~directory}, or a \glref{module}. \arg[subdirectories] One or more strings specifying, in order, subdirectories to be appended to the \glref{root~directory}, \glref{relative~directory}, or \glref{module} directory. (The \glref{keyword} \code{:up} or \code{:back} can also be supplied in addition to any of these strings, indicating to go upward one semantic or syntactic level of directory structure, respectively.) \arg[pathname] A \glref{pathname} \end{args} \fnreturns The pathname. \fnerrors \relativedircircularity \fndescription \glref{Root} and \glref{relative-directory} definitions are searched first. If no \var{name\/} directory definition is found, \glref{module} definitions are searched. \glref{Root~directories} specify a fixed anchor directory for a tree of \glref{relative~directory} definitions. The pathname returned for relative directories is based on the source pathname. \begin{alsos}{show-defined-directories} \also[define-relative-directory] \also[define-root-directory] \also[get-root-directory] \also[show-defined-directories] \end{alsos} \fnexamples Return the pathname of the \nobr{\code{:my-app-root}} \glref{root~directory}: % \W\supp \begin{example} > (get-directory :my-app-root) #P"~/my-app/" > \end{example} % Return the pathname of the \nobr{\code{:gbbopen-tools}} \glref{relative~directory}: % \W\supp\notpretop \begin{example} > (get-directory :gbbopen-tools) #P"\var{\/}/source/tools/" > \end{example} Return this same pathname, this time computed from the \nobr{\code{:gbbopen-root}} \glref{root~directory}: % \W\supp\notpretop \begin{example} > (get-directory :gbbopen-root "tools") #P"\var{\/}/source/tools/" > \end{example} % Return the pathname of the \nobr{\code{:gbbopen-user}} \glref{module}: % \W\supp\notpretop \begin{example} > (get-directory :gbbopen-user) #P"\var{\/}/source/gbbopen/" > \end{example} \end{functiondoc} %% ------------------------------------------------------------------------ \begin{functiondoc}{Function}{get-patch-description}% {\var{id module-name\/} \nobr{\returns{} \var{id, date, author,}} \var{description, \nobr{date-loaded,} \nobr{file-name\/}} or \nil} \index{patch!description, getting}% \fnsyntax \fnpurpose Return the information describing \glref{patch} \var{id\/} to a \nobr{\var{module}}. \fnpackage \code{:module-manager} \fnmodule \code{:module-manager} \fnargs \begin{args}{module-name} \arg[id] An object \arg[module-name] A \glref{keyword~symbol} naming a \glref{module} \arg[date] A \glref{Universal~Time} \arg[author] A string \arg[description] A string or a \glref{proper~list} of strings or \nil \arg[date-loaded] A \glref{Universal~Time} \arg[file-name] A string \end{args} \fnreturns Six values: \var{id}, \var{date}, \nobr{\var{author}}, \nobr{\var{description}}, \nobr{\var{date-loaded}}, and \nobr{\var{file-name}}, or \nil{} if the patch has not been loaded. \fnerrors \modulenotdefined \begin{alsos}{describe-patches} \also[continue-patch] \also[define-module] \also[describe-module] \also[describe-patches] \also[finish-patch] \also[parse-date] \also[patch] \also[patch-loaded-p] \also[start-patch] \end{alsos} \fnexamples % Get the description values for \glref{patch} \code{1} to \glref{module} \nobr{\code{:my-app}}: % \W\supp \begin{example} > (get-patch-description 1 ':my-app) 1 3423139200 "Corkill" "A simple example patch" 3423316130 "my-app-p001" > \end{example} % and for non-existent patch \code{3}: % \W\supp\notpretop \begin{example} > (get-patch-description 3 ':my-app) nil > \end{example} % and for patch \code{1} in \glref{module} \nobr{\code{:gbbopen-test}} (when that module has not been loaded): % \W\supp\notpretop \begin{example} > (get-patch-description 1 ':gbbopen-test) nil > \end{example} \end{functiondoc} %% ------------------------------------------------------------------------ \begin{functiondoc}{Function}{get-root-directory}{\var{name\/} \nobr{\returns{} \var{pathname\/}}} \index{directory!getting root-directory pathname from name}% \fnsyntax \fnpurpose Return the pathname of the \glref{root~directory} of a \glref{root~directory}, a \glref{relative~directory}, or a \glref{module}. \fnpackage \code{:module-manager} \fnmodule \code{:module-manager} \fnargs \begin{args}{pathname} \arg[name] A \glref{keyword~symbol} naming a \glref{root~directory}, a \glref{relative~directory}, or a \glref{module}. \arg[pathname] A \glref{pathname} \end{args} \fnreturns The \glref{root-directory} pathname of the defined directory or module. \fndescription \glref{Root} and \glref{relative-directory} definitions are searched first. If no \var{name\/} directory definition is found, \glref{module} definitions are searched. \glref{Root~directories} specify a fixed anchor directory for a tree of \glref{relative~directory} definitions. \begin{alsos}{show-defined-directories} \also[define-relative-directory] \also[define-root-directory] \also[get-directory] \also[show-defined-directories] \end{alsos} \fnexamples % Return the \glref{root-directory} pathname of the \nobr{\code{:gbbopen-root}} \glref{root~directory}: % \W\supp \begin{example} > (get-root-directory :gbbopen-root) #P"\var{\/}/" > \end{example} % Return the \glref{root-directory} pathname of the \nobr{\code{:gbbopen-tools}} \glref{relative~directory}: % \W\supp\notpretop \begin{example} > (get-root-directory :gbbopen-tools) #P"\var{\/}/" > \end{example} Return the \glref{root-directory} pathname of the \nobr{\code{:gbbopen-user}} \glref{module}: % \W\supp\notpretop \begin{example} > (get-root-directory :gbbopen-user) #P"\var{\/}/" > \end{example} \end{functiondoc} %% ------------------------------------------------------------------------ \begin{functiondoc}{Function}{load-module}{% \nobr{\var{module-name\/}} \nobr{\code{\&rest} \var{options\/}}} \index{module!loading}% \index{loading!a module}% \fnsyntax \fnpurpose Load the files in a \glref{module}. \fnpackage \code{:module-manager} \fnmodule \code{:module-manager} \fnargs \begin{args}{module-name} \arg[module-name] A \glref{keyword~symbol} naming a \glref{module} \arg[option] Any of the following \glref{keywords}: \loadmoduleoptions \end{args} \fnerrors \modulenotdefined\\ \relativedircircularity\\ \patchesonlymodulenotloaded \fndescription These file options, when specified for individual files in the \glref{module} definition (see \nobr{\textbf{\entlinknoex{define-module}}}), have the following effects (overriding the behavior of \nobr{\var{options\/}} supplied to \nobr{\textbf{load-module}}): % \W\supp\tabletop \loadmodulefileoptions \begin{alsos}{*autorun-modules*} \also[*autorun-modules*] \also[*patches-only*] \also[compile-module] \also[define-module] \also[load-module-file] \end{alsos} \fnexample % Load the GBBopen User \glref{module} and all its \glref{required~modules}: % \W\supp \begin{example} (load-module :gbbopen-user) \end{example} \replnote \textbf{Load-module} can be invoked using the \glref{REPL~command}: % \REPLindex{:lm}% % \W\supp \begin{example} :lm \textrm{[}\var{module-name\/} \textrm{[}\var{option\/}\superstar\textrm{]]} \end{example} % which remembers the last specified \nobr{\var{module-name\/}} and \nobr{\var{options}} as default values for the command. \end{functiondoc} %% ------------------------------------------------------------------------ \begin{functiondoc}{Function}{load-module-file}% {\var{\nobr{module-name} \nobr{file-name\/}} \nobr{\code{\&rest} \var{options\/}} \nobr{\returns{} \var{pathname\/}}} \index{module!loading a file of}% \index{loading!a module file}% \fnsyntax \fnpurpose Load a single file from a \glref{module}. \fnpackage \code{:module-manager} \fnmodule \code{:module-manager} \fnargs \begin{args}{module-name} \arg[module-name] A \glref{keyword~symbol} naming a \glref{module} \arg[file-name] A string naming a file in the \glref{module} \arg[option] Any of the following \glref{keywords}: \loadonefilemoduleoptions \arg[pathname] A \glref{pathname} \end{args} \fnreturns The pathname of the loaded file. \fnerrors \modulenotdefined\\ % File \var{file-name\/} is not associated with the module. \relativedircircularity \fndescription File options specified for individual files in the \glref{module} definition (see \nobr{\textbf{\entlinknoex{define-module}}}) are ignored by \nobr{\textbf{load-module-file}}. \begin{alsos}{*autorun-modules*} \also[*autorun-modules*] \also[define-module] \also[load-module] \end{alsos} \fnexample Load the source of the file \code{tools} from the GBBopen Tools \glref{module}: % \W\supp \begin{example} > (load-module-file :gbbopen-tools "tools" :source) ;; Loading \var{\/}/source/tools/tools.lisp #P"\var{\/}/source/tools/tools.lisp" > \end{example} \replnote \textbf{Load-module-file} can be invoked using the \glref{REPL~command}: % \REPLindex{:lmf}% % \W\supp \begin{example} :lmf \textrm{[}\var{module-name\/} \var{file-name\/} \textrm{[}\var{option\/}\superstar\textrm{]]} \end{example} % which remembers the last specified \nobr{\var{module-name\/}}, \nobr{\var{file-name\/}}, and \nobr{\var{options}} as default values for the command. \end{functiondoc} %% ------------------------------------------------------------------------ \begin{functiondoc}{Function}{module-directories}{% \nobr{\var{module-name\/}} \nobr{\returns{} \var{source-directory, compiled-directory\/}}} \index{module!directories}% \index{directories, of a module}% \fnsyntax \fnpurpose Return the source and compiled directories of a \glref{module}. \fnpackage \code{:module-manager} \fnmodule \code{:module-manager} \fnargs \begin{args}{module-name} \arg[module-name] A \glref{keyword~symbol} naming a \glref{module} \arg[source-directory] A \glref{pathname} \arg[compiled-directory] A \glref{pathname} \end{args} \fnreturns Two values: the source directory \glref{pathname} and the compiled directory \glref{pathname}. \fnerrors \modulenotdefined\\ \relativedircircularity \begin{alsos}{load-module-file} \also[define-module] \also[load-module-file] \end{alsos} \fnexample % Return the source and compiled directories of the Agenda Shell \glref{module}: % \W\supp \begin{example} > (module-directories :agenda-shell) \nobr{#P"\var{\/}/source/gbbopen/control-shells"} \nobr{#P"\var{\/}/\var{\/}/gbbopen/control-shells"} > \end{example} \end{functiondoc} %% ------------------------------------------------------------------------ \begin{functiondoc}{Function}{module-loaded-p}{% \nobr{\var{module-name\/}} \nobr{\returns{} \var{boolean\/}}} \index{module!loaded, checking for}% \index{loaded module, checking for}% \fnsyntax \fnpurpose Determine if a \glref{module} has been fully loaded into Common Lisp. \fnpackage \code{:module-manager} \fnmodule \code{:module-manager} \fnargs \begin{args}{module-name} \arg[module-name] A \glref{keyword~symbol} naming a \glref{module} \arg[boolean] A \glref{generalized~boolean} \end{args} \fnreturns True if the \glref{module} has been fully loaded; \nil{} otherwise. \fnerrors \modulenotdefined \begin{alsos}{define-module} \also[define-module] \also[load-module] \end{alsos} \fnexample Check if the Agenda Shell \glref{module} has been loaded: % \begin{example} \W\supp > (module-loaded-p :agenda-shell) t > \end{example} \end{functiondoc} %% ------------------------------------------------------------------------ \begin{functiondoc}{Macro}{patch}% {\code{(}\var{id date\/} \nobr{\code{\&key} \var{author description\/}\code{)}} \nobr{\var{form\/}\superstar}} \index{module!patching}% \index{patching!a module}% \fnsyntax \fnpurpose Define a \glref{patch} to a \glref{module}. \fnpackage \code{:module-manager} \fnmodule \code{:module-manager} \fnargs \begin{args}{description} \arg[id] An object \arg[date] A simple string representing a date (parsed by \nobr{\textbf{\entlink{parse-date}}}) \arg[author] A string (default is \nobr{\code{"Anonymous"}}) \arg[description] A string or a \glref{proper~list} of strings (default is \nil) \arg[form] A \glref{form} \end{args} \fndescription % The source file for a patch should be placed in a subdirectory named \nobr{\code{patches}} in the module's source-files directory. If a patch cannot be defined as a single \nobr{\textbf{patch}} form, the more primitive \nobr{\textbf{\entlink{start-patch}}}, \nobr{\textbf{\entlink{continue-patch}}}, and \nobr{\textbf{\entlink{finish-patch}}} macros can be used to separate the patch into multiple top-level forms in the same patch file. \begin{alsos}{get-patch-description} \also[allow-redefinition] \also[continue-patch] \also[define-module] \also[describe-module] \also[describe-patches] \also[finish-patch] \also[get-patch-description] \also[parse-date] \also[patch-loaded-p] \also[start-patch] \also[undefmethod] \end{alsos} \fnexample % Define a simple \glref{patch} (in a file named \nobr{\code{my-app-p001.lisp}} in the \nobr{\code{patches}} subdirectory of the module): % \bfindexit{printv}% \bfindexit{define-module}% % \W\supp \begin{example} (patch (1 "06-22-08" :author "Corkill" :description "A simple example patch") (\entlink{printv} "Simple example patch loaded!")) \end{example} % and add the patch file to the \nobr{\code{:my-app}} \glref{module}: % \W\supp\notpretop \begin{example} (\entlink{define-module} :my-app (:requires :gbbopen-user) (:files "preamble" ("macros" :forces-recompile) "classes" "my-app" "epilogue") (:patches "my-app-p001")) \end{example} \end{functiondoc} %% ------------------------------------------------------------------------ \begin{functiondoc}{Function}{patch-loaded-p}% {\var{id module-name\/} \nobr{\returns{} \var{boolean\/}}} \index{patch!checking if loaded}% \index{loaded patch, checking for}% \fnsyntax \fnpurpose Determine if \glref{patch} \var{id\/} to \nobr{\var{module\/}} has been loaded. \fnpackage \code{:module-manager} \fnmodule \code{:module-manager} \fnargs \begin{args}{module-name} \arg[id] An object \arg[module-name] A \glref{keyword~symbol} naming a \glref{module} \arg[boolean] A \glref{generalized~boolean} \end{args} \fnreturns True if the \glref{patch} has been loaded; \nil{} otherwise. \fnerrors \modulenotdefined \begin{alsos}{get-patch-description} \also[continue-patch] \also[define-module] \also[describe-module] \also[describe-patches] \also[finish-patch] \also[get-patch-description] \also[parse-date] \also[patch] \also[start-patch] \end{alsos} \fnexamples % Check if \glref{patch} \code{1} to \glref{module} \nobr{\code{:my-app}} has been loaded: % \W\supp \begin{example} > (patch-loaded-p 1 ':my-app) t > \end{example} Check for non-existent patch \code{3}: % \W\supp \begin{example} > (patch-loaded-p 3 ':my-app) nil > \end{example} Check for patch \code{1} in \glref{module} \nobr{\code{:gbbopen-test}} (when that module has not been loaded): % \W\supp \begin{example} > (patch-loaded-p 1 ':gbbopen-test) nil > \end{example} \end{functiondoc} %% ------------------------------------------------------------------------ \begin{functiondoc}{Function}{show-defined-directories}{\noargs} \index{directory!show defined}% \index{relative directory!show defined} \index{root directory!show defined}% \fnsyntax \fnpurpose Show all \glref{root} and \glref{relative-directory} definitions. \fnpackage \code{:module-manager} \fnmodule \code{:module-manager} \begin{alsos}{define-relative-directory} \also[define-relative-directory] \also[define-root-directory] \also[get-directory] \also[get-root-directory] \end{alsos} \fnexample % List the currently defined \glref{root} and \glref{relative~directories}: % \begin{example} % \W\supp > (show-defined-directories) :gbbopen Relative to :gbbopen-root Subdirectories: ("gbbopen") :gbbopen-root Root: \var{\/} :gbbopen-tools Relative to :gbbopen-root Subdirectories: ("tools") :module-manager-root Root: \var{\/} > \end{example} \end{functiondoc} %% ------------------------------------------------------------------------ \begin{functiondoc}{Macro}{start-patch}% {\nobr{\code{(}\var{id date\/}} \nobr{\code{\&key} \var{author description\/}\code{)}} \nobr{\var{form\/}\superstar}} \index{module!patching}% \index{patching!a module}% \fnsyntax \fnpurpose Start the definition of a multiple top-level form \glref{patch} to a \glref{module}. \fnpackage \code{:module-manager} \fnmodule \code{:module-manager} \fnargs \begin{args}{description} \arg[id] An object \arg[date] A simple string representing a date (parsed by \nobr{\textbf{\entlink{parse-date}}}) \arg[author] A string (default is \nobr{\code{"Anonymous"}}) \arg[description] A string or a \glref{proper~list} of strings (default is \nil) \arg[form] A \glref{form} \end{args} \fndescription % The source file for a patch should be placed in a subdirectory named \nobr{\code{patches}} in the module's source-files directory. The \textbf{start-patch} macro, along with \nobr{\textbf{\entlink{continue-patch}}} and \nobr{\textbf{\entlink{finish-patch}}}, can be used to define a patch as multiple top-level forms in the same patch file if a patch cannot be defined as a single \nobr{\textbf{\entlink{patch}}} form. \begin{alsos}{get-patch-description} \also[allow-redefinition] \also[continue-patch] \also[define-module] \also[describe-module] \also[describe-patches] \also[finish-patch] \also[get-patch-description] \also[parse-date] \also[patch] \also[patch-loaded-p] \also[undefmethod] \end{alsos} \fnexample % Define a more complex \glref{patch} (in a file named \nobr{\code{my-app-p002.lisp}} in the \nobr{\code{patches}} subdirectory of the module): % \bfindexit{printv}% \bfindexit{continue-patch}% \bfindexit{finish-patch}% % \W\supp \begin{example} (start-patch (2 "06-23-08" :author "Corkill" :description "A more complex patch example") (\entlink{printv} "More complex example patch started!")) (eval-when (:compile-toplevel) (\entlink{continue-patch} (\entlink{printv} "Defining compile-time-only-macro-for-patch...") (defmacro compile-time-only-macro-for-patch (x) `',x))) (eval-when (:compile-toplevel :load-toplevel :execute) (\entlink{continue-patch} (\entlink{printv} "Defining macro-for-patch at compile & load time...") (defmacro macro-for-patch (x) `',x)))\goodpagebreak (\entlink{continue-patch} (\entlink{printv} "Using macro-for-patch at load time...") (macro-for-patch abc)) (eval-when (:compile-toplevel :load-toplevel :execute) (\entlink{continue-patch} (\entlink{printv} "Using macro-for-patch at compile & load time...") (macro-for-patch xyz)))\goodpagebreak (eval-when (:compile-toplevel) (\entlink{continue-patch} (\entlink{printv} "Using compile-time-only-macro-for-patch...") (compile-time-only-macro-for-patch abc))) (\entlink{finish-patch} (\entlink{printv} "More complex example patch finished!")) \end{example} \end{functiondoc} %% ------------------------------------------------------------------------ \begin{functiondoc}{Macro}{with-module-redefinitions}% {\var{form\/}\superstar} \index{module!defining or redefining}% \index{defining!a module}% \index{redefining!a module}% \fnsyntax \fnpurpose Defer \glref{required-module} order checking of \glref{module} definitions in \var{forms} until all \var{forms} have been processed. \fnpackage \code{:module-manager} \fnmodule \code{:module-manager} \fnargs \begin{args}{form} \arg[form] A \glref{form} \end{args} \fnerrors The fully expanded \glref{required-module} order of a module redefined in \var{forms} conflicts with the fully expanded \glref{required-module} order of another \glref{module}. \fndescription Normally, the fully expanded \glref{required-module} order specified by the \nobr{\code{:requires}} option is checked immediately for conflicts with previously defined \glref{modules} by \nobr{\textbf{\entlink{define-module}}}. Wrapping several \nobr{\textbf{\entlink{define-module}}} forms with \nobr{\textbf{with-module-redefinitions}} allows the definitions to be conflicting temporarily, until all the \var{forms} have been processed. \begin{alsos}{define-module} \also[define-module] \end{alsos} \fnexample \bfindexit{define-module}% Redefine several modules with deferred conflict checking: % \W\supp \begin{example} (with-module-redefinitions (\entlink{define-module} :alpha \textrm{...}) (\entlink{define-module} :beta \textrm{...})) \textbf{...} (\entlink{define-module} :omega \textrm{...}))) \end{example} \end{functiondoc} %% ======================================================================== %% Tools \T\markright{}% \T\pagestyle{plain} \T\cleardoublepage \W\xname{ref-tools-entities} \T\pagestyle{fancy} \T\thispagestyle{fancybottom} \T\global\def\fnlastname{ }% \T\renewcommand{\headrulewidth}{0pt} \section{GBBopen Tools} \index{module!:gbbopen-tools@\code{:gbbopen-tools}}% \index{:gbbopen-tools@\code{:gbbopen-tools} module}% % The GBBopen Tools \glref{module}, \nobr{\code{:gbbopen-tools}}, contains useful Common Lisp additions and utilities. Convenient (\reflink{shorthand operators}{sec:declared-numerics} for declared \nobr{\code{\glref{fixnum}}}, \nobr{\code{short-float}}, \nobr{\code{single-float}}, \nobr{\code{double-float}}, and \nobr{\code{long-float}} numeric operators are provided, as are efficient \reflink{pseudo probability}{sec:pprob} operators. Uniform access to \reflink{commonly used CLOS and MOP symbols}{sec:CLOS} is provided by the module's \nobr{\code{:gbbopen-tools}} package. Date and time \reflink{parsing and formatting entities}{sec:dateandtime}, \nobr{\code{\glref{fixnum}}}-based \reflink{offset-universal-time functions}{sec:offsettime}, and \reflink{left-leaning red-black (\glref{LLRB}) trees}{sec:trees} are also included in GBBopen Tools. Additional GBBopen Tools entities that are not loaded as part of the \nobr{\code{:gbbopen-tools}} module are documented in the \reflink{Additional GBBopen Tools section}{sec:additional-tools} of this Reference. These additional-tool entities are grouped into separate modules that can be loaded as appropriate. Several entities in the \nobr{\code{:gbbopen-tools}} module that are extended by additional methods in the \nobr{\code{:gbbopen-core}} module are documented in the \reflink{GBBopen Core section}{sec:gbbopen-core} of this Reference. These entities are: % \T\\[3pt] \W\supp\tabletop \begin{tabular}{@{}l@{}l@{}} ~~~~~ & \code{\entlink{*print-object-for-sending*}} \\ & \code{\entlink{*save/send-references-only*}} \\ & \code{\entlink{initialize-saved/sent-instance}} \\ & \code{\entlink{make-duplicate-instance}} \\ & \code{\entlink{make-duplicate-instance-changing-class}} \\ & \code{\entlink{omitted-slots-for-saving/sending}} \\ & \code{\entlink{print-object-for-saving/sending}} \\ & \code{\entlink{print-slot-for-saving/sending}} \\ & \code{\entlink{with-reading-saved/sent-objects-block}} \\ & \code{\entlink{with-saving/sending-block}} \\ \end{tabular} \W\entities \T\ppar{GBBopen Tools entities} \T Descriptions of GBBopen Tools entities follow. \T\clearpage \T\renewcommand{\headrulewidth}{0.01pt} %% ------------------------------------------------------------------------ \begin{functiondoc}[disable-compiler-macros]{Feature}% {:disable-compiler-macros}{}% \index{compiler macros!disabling}% \index{disabling!compiler macros}% \index{compiler, disabling compiler macros}% \fnsyntax \fnpurpose Disable GBBopen compiler macros. \begin{alsos}{:full-safety} \also[:full-safety] \also[defcm] \end{alsos} \fnexample \bfindexit{compile-module}% \codeindexsubit{:recompile}{compile/load-module option}% \codeindexqualit{:propagate}{compile/load-module option}% Recompile a GBBopen application (and GBBopen itself) with all GBBopen compiler macros disabled: % \W\supp \begin{example} (pushnew :disable-compiler-macros *features*) (\entlink{compile-module} :my-app :recompile :propagate) \end{example} \end{functiondoc} %% ------------------------------------------------------------------------ \begin{functiondoc}[full-safety]{Feature}{:full-safety}{}% \index{optimizations!disabling}% \index{disabling!optimizations}% \index{safety, disabling optimizations}% \fnsyntax \fnpurpose Disable GBBopen compile-time optimizations. \fndescription % The \textbf{:full-safety} feature disables all compile-time optimizations, including the use of compiler macros. Compiler macros can be disabled without disabling other compile-time optimizations with the feature \nobr{\textbf{\entlinknoex{:disable-compiler-macros}}}. \begin{alsos}{:disable-compiler-macros} \also[defcm] \also[:disable-compiler-macros] \end{alsos} \fnexample \bfindexit{compile-module}% \codeindexsubit{:recompile}{compile/load-module option}% \codeindexqualit{:propagate}{compile/load-module option}% Recompile a GBBopen application (and GBBopen itself) with all GBBopen optimizations disabled: % \W\supp \begin{example} (pushnew :full-safety *features*) (\entlink{compile-module} :my-app :recompile :propagate) \end{example} \end{functiondoc} %% ------------------------------------------------------------------------ \begin{functiondoc}[disable-with-error-handling-var]{Variable}% {*disable-with-error-handling*}{}% \fnsyntax \fnpurpose Controls whether \nobr{\textbf{\entlink{with-error-handling}}} is in effect. \fnpackage \code{:gbbopen-tools} \fnmodule \code{:gbbopen-tools} \fnvaluetype A \glref{generalized~boolean} \fninitialvalue \nil \fndescription Setting \nobr{\textbf{*disable-with-error-handling*}} to true causes \nobr{\textbf{\entlink{with-error-handling}}} to evaluate its \var{forms\/} without any error handling in place. Any \nobr{\var{handler-form\/}} or \nobr{\var{error-form\/}} in the \nobr{\textbf{\entlink{with-error-handling}}} is ignored. Setting \nobr{\textbf{*disable-with-error-handling*}} to true is very handy for debugging an unexpected error in a \nobr{\textbf{\entlink{with-error-handling}}} \var{form}. \begin{alsos}{with-error-handling} \also[with-error-handling] \end{alsos} \fnexample \bfindexit{with-error-handling}% \bfindexit{printv}% Use \nobr{\textbf{*disable-with-error-handling*}} to debug a handled form: % \W\supp \begin{example} > (with-error-handling (/ 10 0) (\entlink{printv} (error-message)) nil) ;; (error-message) => "Attempt to divide 10 by zero." nil > (setf *disable-with-error-handling* 't) t > (with-error-handling (/ 10 0) (\entlink{printv} (error-message)) nil) Error: Attempt to divide 10 by zero. >> \end{example} \end{functiondoc} %% ------------------------------------------------------------------------ \begin{functiondoc}{Macro}{allow-redefinition}{% \nobr{\var{form\/}\superstar{}} \nobr{\returns{} \var{result\/}\superstar}} \index{redefining!functions without warnings}% \index{redefining!classes without warnings}% \fnsyntax \fnpurpose Suppress redefinition warnings associated with processing \var{forms} when possible. \fnpackage \code{:gbbopen-tools} (home package is \nobr{\code{:module-manager}}) \fnmodule \code{:module-manager} \fnargs \begin{args}{form} \arg[form] A \glref{form} \arg[results] The values returned by evaluating the last \var{form} \end{args} \fnreturns The values returned by evaluating the last \var{form}. \begin{alsos}{continue-patch} \also[continue-patch] \also[finish-patch] \also[patch] \also[start-patch] \end{alsos} \fnexample % \W\supp \begin{example} > (defun redefined-function () "Silly.") silly > (defclass also-silly () ()) also-silly > (allow-redefinition (defun redefined-function "Even more silliness.") (\entlink{define-unit-class} also-silly () ())) also-silly > \end{example} \fnnote \indexit{module!:module-manager@\code{:module-manager}}% \indexit{:module-manager@\code{:module-manager} module}% % This macro is defined in the \nobr{\code{:module-manager}} \glref{module} in order to make it available as early as possible. At present, redefinition warnings are not suppressed on \xsitelink{CMUCL}{http://www.cons.org/cmucl/}, \xsitelink{ECL}{http://common-lisp.net/project/ecl/}, \xsitelink{SBCL}{http://sbcl.sourceforge.net}, and \xsitelink{Scieneer CL}{http://www.scieneer.com/scl/}. \end{functiondoc} %% ------------------------------------------------------------------------ \begin{functiondoc}{Function}{assq}{\var{item alist\/} \nobr{\returns{} \var{entry\/}}} \index{searching!for an entry in an association list}% \index{association list, searching for an entry in}% \fnsyntax \fnpurpose Search for \var{entry\/} in \var{alist\/} using \code{eq} as the comparison function. \fnpackage \code{:gbbopen-tools} \fnmodule \code{:gbbopen-tools} \fnargs \begin{args}{symbol} \arg[item] An object \arg[alist] An \glref{association~list} \arg[entry] A \glref{cons} that is an element of \var{alist} or \nil \end{args} \fnreturns The first \glref{cons} in \var{alist\/} whose car is \code{eq} to \var{item}, or nil if no such cons is found. \fndescription \textbf{Assq} is a convenient shorthand for: % \W\supp \begin{example} (assoc \var{item\/} (the list \var{alist\/}) :test #'eq) \end{example} \begin{alsos}{memq} \also[memq] \end{alsos} \fnexamples % \W\supp \begin{example} > (assq 'b '((a . 1) (b . 2) (c . 3) (b . 4))) (b . 2) > (assq 'x '((a . 1) (b . 2) (c . 3) (b . 4))) nil > \end{example} \end{functiondoc} %% ------------------------------------------------------------------------ \begin{functiondoc}{Function}{bounded-value}{\var{min number max\/} \nobr{\returns{} \var{bounded-number\/}}} \index{numeric value!bounding within a range}% \fnsyntax \fnpurpose Return a numeric value that is bounded between a minimum and maximum value. \fnpackage \code{:gbbopen-tools} \fnmodule \code{:gbbopen-tools} \fnargs \begin{args}{bounded-number} \arg[min] A number (the minimum bound) \arg[number] A number \arg[max] A number (the maximum bound) \arg[bounded-number] A number \end{args} \fnreturns One of the following values: \begin{tightitemize} \item \var{number\/} if it between \var{min\/} and \var{max\/}, inclusive \item \var{min\/} if \nobr{\var{number\/}} is less than \var{min\/} \item \var{max\/} if \nobr{\var{number\/}} is greater than \var{max\/} \end{tightitemize} \fnexamples \begin{example} % \W\supp > (bounded-value 3 pi 4) 3.141592653589793d0 > (bounded-value 3.5 pi 4) 3.5 > (bounded-value 2 pi 3) 3 > \end{example} \fnnote % \bfindex{bounded-value\&}% \bfindex{bounded-value\$\&}% \bfindex{bounded-value\$}% \bfindex{bounded-value\$\$}% \bfindex{bounded-value\$\$\$}% \bfindex{bounded-value\%}% % \reflink{Declared numeric}{sec:declared-numerics} and \reflink{pseudo probability}{sec:pprob} versions of \nobr{\textbf{bounded-value}} are also provided: \nobr{\textbf{bounded-value\&}}, \nobr{\textbf{bounded-value\$\&}}, \nobr{\textbf{bounded-value\$}}, \nobr{\textbf{bounded-value\$\$}}, \nobr{\textbf{bounded-value\$\$\$}}, and \nobr{\textbf{bounded-value\%}}. \end{functiondoc} %% ------------------------------------------------------------------------ \begin{functiondoc}{Macro}{case-using}{% \var{test keyform\/} \nobr{\{\var{normal-clause\/}\}\superstar{}} \nobr{[\var{otherwise-clause\/}]} \nobr{\returns{} \var{result\/}\superstar} or \nil} \fnsyntax \fnpurpose Conditionally execute the forms in a clause that is selected by matching the result of evaluating \nobr{\var{keyform\/}} according to \var{test}. \fnpackage \code{:gbbopen-tools} \fnmodule \code{:gbbopen-tools} \fnargs \begin{args}{keyform} \arg[test] A symbol designating a comparison predicate (not evaluated) \arg[keyform] A \glref{form}; evaluated to produce a \nobr{\var{test-key\/}} (see below) \arg[results] The values returned by evaluating the last \var{form} in the selected clause or \nil{} \end{args} \fnreturns The values returned by the last form in the matching \nobr{\var{normal-clause}}; otherwise the values returned by the last form in the \nobr{\var{otherwise-clause}}, if specified; otherwise \nil. \fndsyntax \W\supp\tabletop \begin{tabular}{@{~}l@{~}l} \nobr{\var{normal-clause\/} ::=} & \code{(}\var{keys form\/}\superstar\code{)} \\ \nobr{\var{otherwise-clause\/} ::=} & \code{(}\{\code{otherwise} \vbar{} \code{t}\} \var{form\/}\superstar\code{)} \\ \end{tabular} \fnterms \begin{args}{test-key} \arg[test-key] An object produced by evaluating \nobr{\var{keyform}} \arg[keys] An object or a \glref{proper~list} of objects. To refer to the symbols \code{t} and \nobr{\code{otherwise}} by themselves as the sole key object for a \nobr{\var{normal-clause}}, \code{(t)} and \nobr{\code{(otherwise)}}, respectively, must be specified as the \var{keys\/} for the clause. \arg[form] A \glref{form} \end{args} \fndescription % The specified \var{test\/} symbol is not evaluated; however the comparison predicate that it designates must be available during expansion of the \nobr{\textbf{case-using}} form. The \var{keyform\/} is first evaluated to produce the \nobr{\var{test-key}}. Each of the \nobr{\var{normal-clauses\/}} is then considered in turn. If the \nobr{\var{test-key\/}} matches that clause according to \var{test}, then the forms in that clause are evaluated as an implicit \nobr{\code{progn}}, and the values it returns are returned as the value of the \nobr{\textbf{case-using}} form. \textbf{Case-using} is a generalization of Common Lisp's \code{case} macro. \begin{alsos}{ecase-using} \also[ccase-using] \also[ecase-using] \end{alsos} \fnexamples % \W\supp \begin{example} > (case-using string= "a" ("a" 1) (("b" "c" "d") 2)) 1 > (case-using string= "d" ("a" 1) (("b" "c" "d") 2)) 2\goodpagebreak > (case-using string= "C" ("a" 1) (("b" "c" "d") 2)) nil\goodpagebreak > (case-using string= "C" ("a" 1) (("b" "c" "d") 2) (otherwise -1)) -1 > (case-using equalp "C" ("a" 1) (("b" "c" "d") 2) (otherwise -1)) 2 > \end{example} \end{functiondoc} %% ------------------------------------------------------------------------ \begin{functiondoc}{Condition}{case-using-failure}{} \index{condition!case-using-failure@\textbf{case-using-failure}}% \fnsyntax \fnpackage \code{:gbbopen-tools} \fnmodule \code{:gbbopen-tools} \codeindexit{type-error}% % \fndescription % The condition \nobr{\textbf{case-using-failure}} is a subclass of \nobr{\code{type-error}}. \begin{alsos}{ecase-using} \also[case-using] \also[ccase-using] \also[ecase-using] \end{alsos} \end{functiondoc} %% ------------------------------------------------------------------------ \begin{functiondoc}{Macro}{ccase-using}{% \var{test keyplace\/} \nobr{\{\var{clause\/}\}\superstar{}} \nobr{\returns{} \var{result\/}\superstar}} \fnsyntax \fnpurpose Conditionally execute the forms in a clause that is selected by matching the result of evaluating \nobr{\var{keyplace\/}} according to \var{test}, generating a correctable error if no clause is selected. \fnpackage \code{:gbbopen-tools} \fnmodule \code{:gbbopen-tools} \fnargs \begin{args}{keyplace} \arg[test] A symbol designating a comparison predicate (not evaluated) \arg[keyplace] A \glref{form}; evaluated to produce a \nobr{\var{test-key\/}} and possibly also used later as a place if no \var{keys\/} match (see below) \arg[results] The values returned by evaluating the last \var{form\/} in the selected \var{clause} \end{args} \fnreturns The values returned by the last form in the selected \var{clause}. \fnerrors No \var{clause\/} was selected. \fndsyntax \W\supp\tabletop \begin{tabular}{@{~}l@{~}l} \nobr{\var{clause\/} ::=} & \code{(}\var{keys form\/}\superstar\code{)} \\ \end{tabular} \fnterms \begin{args}{test-key} \arg[test-key] An object produced by evaluating \nobr{\var{keyplace}} \arg[keys] An object or a \glref{proper~list} of objects. \arg[form] A \glref{form} \end{args} \fndescription % The specified \var{test\/} symbol is not evaluated; however the comparison predicate that it designates must be available during expansion of the \nobr{\textbf{case-using}} form. The \var{keyplace\/} is first evaluated to produce the \nobr{\var{test-key}}. Each of the \var{clauses\/} is then considered in turn. If the \nobr{\var{test-key\/}} matches that clause according to \var{test}, then the forms in that clause are evaluated as an implicit \nobr{\code{progn}}, and the values it returns are returned as the value of the \nobr{\textbf{ccase-using}} form. \codeindexit{store-value}% \codeindexit{type-error}% \bfindexit{case-using-failure}% % If no \var{clause\/} is selected, a correctable error of type \nobr{\code{case-using-failure}} (a subclass of \nobr{\code{type-error}}) is signaled. The offending datum is the \nobr{\var{test-key\/}} and the expected type is type equivalent to \nobr{\code{(member (union} \var{keys\/} \code{:test} \var{test\/}\code{)}}. Common Lisp's \nobr{\code{store-value}} restart can be used to correct the error. \textbf{Ccase-using} is a generalization of Common Lisp's \nobr{\code{ccase}} macro. \begin{alsos}{case-using-failure} \also[case-using-failure] \also[case-using] \also[ecase-using] \end{alsos} \fnexamples % \W\supp \begin{example} > (defparameter *x* "a") *x* > (ccase-using string= *x* ("a" 1) (("b" "c" "d") 2)) 1 > (setf *x* "d") "d" > (ccase-using string= *x* ("a" 1) (("b" "c" "d") 2)) 2\goodpagebreak > (setf *x* "C") "C"\goodpagebreak > (ccase-using string= *x* ("a" 1) (("b" "c" "d") 2)) Error: "C" fell through an ecase-using string= form; the valid keys are "a", "b", "c", and "d". Restart actions (select using :c n): 0: Supply a new value for *x*. >> :c 0 Enter a form to evaluate as the new value for *x*: "a" *x* is now "a" 1 > \end{example} \end{functiondoc} %% ------------------------------------------------------------------------ \begin{functiondoc}{Function}{compiler-macroexpand}{\var{form\/} \nobr{\code{\&optional} \var{env\/}} \nobr{\returns{} \var{expansion, expanded-p\/}}} \index{compiler macro!expanding}% \index{macroexpand!compiler macro}% \fnsyntax \fnpurpose Expand \var{form\/} until it is no longer a compiler-macro form. \fnpackage \code{:gbbopen-tools} \fnmodule \code{:gbbopen-tools} \fnargs \begin{args}{form} \arg[form] A \glref{form} \arg[env] An environment object (default is \nil) \arg[expansion] A \glref{form} \arg[expanded-p] A \glref{generalized~boolean} \end{args} \fnreturns Two values: \begin{tightitemize} \item if \var{form\/} is a compiler-macro form, then return the repeatedly expanded compiler-macro form and true \item otherwise, return the given \var{form\/} and \nil{} \end{tightitemize} \fndescription % \var{Form\/} is expanded repeatedly by calling \nobr{\textbf{\entlink{compiler-macroexpand-1}}} until it is no longer a compiler-macro form. \begin{alsos}{compiler-macroexpand-1} \also[compiler-macroexpand-1] \end{alsos} \fnexamples % \W\supp \begin{example} > (compiler-macroexpand '(ensure-list x)) (let ((#:g7105 x)) (if (listp #:g7105) #:g7105 (list #:g7105))) t > (compiler-macroexpand '(cons x nil)) (cons x nil) nil > \end{example} \end{functiondoc} %% ------------------------------------------------------------------------ \begin{functiondoc}{Function}{compiler-macroexpand-1}{\var{form\/} \nobr{\code{\&optional} \var{env\/}} \nobr{\returns{} \var{expansion, expanded-p\/}}} \index{compiler macro!expanding}% \index{macroexpand!compiler macro}% \fnsyntax \fnpurpose Expand \var{form\/} if it is a compiler-macro form. \fnpackage \code{:gbbopen-tools} \fnmodule \code{:gbbopen-tools} \fnargs \begin{args}{form} \arg[form] A \glref{form} \arg[env] An environment object (default is \nil) \arg[expansion] A \glref{form} \arg[expanded-p] A \glref{generalized~boolean} \end{args} \fnreturns Two values: \begin{tightitemize} \item if \var{form\/} is a compiler-macro form, then return the compiler-macro expansion of \var{form\/} and true \item otherwise, return the given \var{form\/} and \nil{} \end{tightitemize} \fndescription % If \var{form\/} is a compiler-macro form, then \nobr{\textbf{compiler-macroexpand-1}} expands the compiler-macro-form call once. \begin{alsos}{compiler-macroexpand} \also[compiler-macroexpand] \end{alsos} \fnexamples % \W\supp \begin{example} > (compiler-macroexpand-1 '(ensure-list x)) (let ((#:g7105 x)) (if (listp #:g7105) #:g7105 (list #:g7105))) t > (compiler-macroexpand-1 '(cons x nil)) (cons x nil) nil > \end{example} \end{functiondoc} %% ------------------------------------------------------------------------ \begin{functiondoc}{Function}{counted-delete}{\var{item sequence\/} \nobr{\code{\&key} \var{from-end}} \var{test \nobr{test-not} start end count key\/} \nobr{\returns{} \var{result-sequence, count\/}}} \fnsyntax \fnpurpose A version of \nobr{\code{delete}} that returns the number of items that were deleted as a second value. \fnpackage \code{:gbbopen-tools} \fnmodule \code{:gbbopen-tools} \fnargs \begin{args}{from-end} \arg[item] An object \arg[sequence] A proper sequence \arg[from-end] A \glref{generalized~boolean} (default is \nil) \arg[test] A \glref{function~designator} specifying a \glref{function~object} of two arguments that returns a \glref{generalized~boolean} (default is \nobr{\code{\#'eql}}) \arg[test-not] A \glref{function~designator} specifying a \glref{function~object} of two arguments that returns a \glref{generalized~boolean} (use of \nobr{\code{:test-not}} is deprecated) \arg[start] Starting index into \nobr{\var{sequence\/}} (default is \code{0}) \arg[end] Ending index into \nobr{\var{sequence\/}} (default is \nil, meaning end of \nobr{\var{sequence\/}}) \arg[count] An integer or \nil{} (default is \nil) \arg[key] A \glref{function~designator} specifying a \glref{function~object} of one argument, or \nil{} (default is \nil) \arg[result-sequence] A sequence \end{args} \fnreturns Two values: \begin{tightitemize} \item the \var{sequence\/} from which the elements that satisfy the \var{test\/} have been removed \item the number of items that have been removed, or \nil \end{tightitemize} \fndescription Returns a sequence from which elements that satisfy the \var{test\/} have been deleted. The supplied \nobr{\var{sequence\/}} may be modified in constructing the result; however, modification of the supplied \nobr{\var{sequence\/}} itself is not guaranteed. Specifying a \nobr{\var{from-end\/}} value of true matters only when the \var{count\/} is provided, and in that case only the rightmost \var{count\/} elements satisfying the \var{test\/} are deleted. \begin{alsos}{atomic-delete} \also[atomic-delete] \also[delq] \also[delq-one] \end{alsos} \fnexamples \begin{example} % \W\supp > (counted-delete 'a '(a b c a b c)) (b c b c) 2 > (counted-delete #\bkslash{}a "abcabc") "bcbc" 2\goodpagebreak > (counted-delete 'z '(a b c a b c)) (a b c a b c) 0 > (counted-delete #\bkslash{}a "abcabc" :from-end 't :count 1) "abcbc" 1 > \end{example} \fnnote % This is what \nobr{\code{delete}} should have been (and was on the Lisp Machines). \end{functiondoc} %% ------------------------------------------------------------------------ \begin{functiondoc}{Macro}{decf-after}{\var{place\/} \nobr{\code{\&optional} \var{decrement\/}} \nobr{\returns{} \var{original-value\/}}} \index{place!decrementing numeric value of}% \fnsyntax \fnpurpose Decrement the value of \var{place}, returning the original value of \var{place}. \fnpackage \code{:gbbopen-tools} \fnmodule \code{:gbbopen-tools} \fnargs \begin{args}{original-value} \arg[place] A \glref{form} which is suitable for use as a \glref{generalized~reference} \arg[decrement] A number (default is \code{1}) \arg[original-value] A number \end{args} \fnreturns The original value of \var{place}. \begin{alsos}{incf-after} \also[incf-after] \end{alsos} \fnexamples \begin{example} % \W\supp > (defparameter *x* 4) *x* > (decf-after *x*) 4 > *x* 3 > (decf-after *x* 3) 3 > *x* 0 > \end{example} \fnnote % \bfindex{decf-after\&}% \bfindex{decf-after\$\&}% \bfindex{decf-after\$}% \bfindex{decf-after\$\$}% \bfindex{decf-after\$\$\$}% \bfindex{decf-after\%}% % \reflink{Declared numeric}{sec:declared-numerics} and \reflink{pseudo probability}{sec:pprob} versions of \nobr{\textbf{decf-after}} are also provided: \nobr{\textbf{decf-after\&}}, \nobr{\textbf{decf-after\$\&}}, \nobr{\textbf{decf-after\$}}, \nobr{\textbf{decf-after\$\$}}, \nobr{\textbf{decf-after\$\$\$}}, and \nobr{\textbf{decf-after\%}}. \end{functiondoc} %% ------------------------------------------------------------------------ \begin{functiondoc}[decf-delete-acons]{Macro}{decf/delete-acons}{% \var{item decrement place\/} \nobr{\code{\&key} \var{key test test-not\/}} \nobr{\returns{} \var{new-place-value\/}}} \index{pushing!a new pair onto an association list}% \index{decrementing, the value of an association-list pair}% \index{association list!pushing a new pair onto}% \index{association list!decrementing the value of a pair}% \fnsyntax \fnpurpose Decrement by \nobr{\var{decrement\/}} the value associated with \var{item\/} in an \glref{association~list} stored in \var{place}, deleting the \glref{cons} associated with \var{item\/} if the value becomes zero. \fnpackage \code{:gbbopen-tools} \fnmodule \code{:gbbopen-tools} \fnargs \begin{args}{new-place-value} \arg[item] An object \arg[decrement] A number \arg[place] A \glref{form} which is suitable for use as a \glref{generalized~reference} \arg[key] A \glref{function~designator} specifying a \glref{function~object} of one argument, or \nil{} (default is \nil) \arg[test] A \glref{function~designator} specifying a \glref{function~object} of two arguments that returns a \glref{generalized~boolean} (default is \nobr{\code{\#'eql}}) \arg[test-not] A \glref{function~designator} specifying a \glref{function~object} of two arguments that returns a \glref{generalized~boolean} (use of \nobr{\code{:test-not}} is deprecated) \arg[new-place-value] An \glref{association~list} \end{args} \fnreturns An \glref{association~list} (the new value of \var{place\/}). \fnerrors Item \var{item\/} is not present in the \glref{association~list} stored in \var{place}. \fndescription This is the inverse of \nobr{\textbf{\entlink{pushnew/incf-acons}}}. \begin{alsos}{pushnew/incf-acons} \also[pushnew/incf-acons] \end{alsos} \fnexamples % \W\supp \begin{example} > (setf alist '((x . 2)(y . 2)) ((x . 2)(y . 2)) > (decf/delete-acons 'x 1 alist) ((x . 1)(y . 2)) > (decf/delete-acons 'x 1 alist) ((y . 2))\goodpagebreak > (decf/delete-acons 'y 2 alist) nil > \end{example} \fnnote % \bfindex{decf\&/delete-acons}% \bfindex{decf\$\&/delete-acons}% \bfindex{decf\$/delete-acons}% \bfindex{decf\$\$/delete-acons}% \bfindex{decf\$\$\$/delete-acons}% \bfindex{decf\%/delete-acons}% % \reflink{Declared numeric}{sec:declared-numerics} and \reflink{pseudo probability}{sec:pprob} versions of \nobr{\textbf{decf/delete-acons}} are also provided: \nobr{\textbf{decf\&/delete-acons}}, \nobr{\textbf{decf\$\&/delete-acons}}, \nobr{\textbf{decf\$/delete-acons}}, \nobr{\textbf{decf\$\$/delete-acons}}, \nobr{\textbf{decf\$\$\$/delete-acons}}, and \nobr{\textbf{decf\%/delete-acons}}, \end{functiondoc} %% ------------------------------------------------------------------------ \begin{functiondoc}{Function}{delq}{\var{item list\/} \nobr{\returns{} \var{list\/}}} \index{deleting!an item from a list}% \fnsyntax \fnpurpose Destructively delete all \var{item\/} elements from \var{list\/} using \code{eq} as the comparison function. \fnpackage \code{:gbbopen-tools} \fnmodule \code{:gbbopen-tools} \fnargs \begin{args}{symbol} \arg[item] An object \arg[list] A \glref{proper~list} \end{args} \fnreturns A list from which all \var{item\/} elements have been deleted. \fndescription \textbf{Delq} is a convenient shorthand for: % \W\supp \begin{example} (delete \var{item\/} (the list \var{list\/}) :test #'eq) \end{example} % As is the case with \nobr{\code{delete}}, \nobr{\textbf{delq}} may modify the top-level structure of \var{list\/} in constructing the \nobr{\var{result-list}}. \begin{alsos}{counted-delete} \also[atomic-delete] \also[counted-delete] \also[delq-one] \end{alsos} \fnexamples \W\supp \begin{example} > (delq 'b '(a b c b)) (a c) > (delq 'x '(a b c b)) (a b c b) > \end{example} \end{functiondoc} %% ------------------------------------------------------------------------ \begin{functiondoc}{Function}{delq-one}{\var{item list\/} \nobr{\returns{} \var{list\/}}} \index{deleting!an item from a list}% \fnsyntax \fnpurpose Destructively delete the first occurrence of \var{item\/} from \var{list\/} using \code{eq} as the comparison function. \fnpackage \code{:gbbopen-tools} \fnmodule \code{:gbbopen-tools} \fnargs \begin{args}{symbol} \arg[item] An object \arg[list] A \glref{proper~list} \end{args} \fnreturns A list from which the first \var{item\/} element has been deleted. \fndescription \textbf{Delq-one} is a convenient and efficient shorthand for: % \W\supp \begin{example} (delete \var{item\/} (the list \var{list\/}) :test #'eq :count 1) \end{example} % As is the case with \nobr{\code{delete}}, \nobr{\textbf{delq-one}} may modify the top-level structure of \var{list\/} in constructing the \nobr{\var{result-list}}. \begin{alsos}{counted-delete} \also[atomic-delete] \also[counted-delete] \also[delq] \end{alsos} \fnexamples \W\supp \begin{example} > (delq-one 'b '(a b c b)) (a c b) > (delq-one 'x '(a b c b)) (a b c b) > \end{example} \end{functiondoc} %% ------------------------------------------------------------------------ \begin{functiondoc}{Macro}{defcm}{\var{name \nobr{lambda-list\/}} \nobr{[[\var{declaration\/}\superstar{} \vbar{} \var{documentation\/}]]} \nobr{\var{form\/}\superstar} \nobr{\returns{} \var{name\/}}} \index{compiler macro!defining}% \index{defining!a compiler macro}% \fnsyntax \fnpurpose Define a read-time conditional compiler macro. \fnpackage \code{:gbbopen-tools} \fnmodule \code{:gbbopen-tools} \fnargs \begin{args}{documentation} \arg[name] A non-\nil, \glref{non-keyword~symbol} that names a function or macro \arg[lambda-list] A lambda-list \arg[declaration] A declare expression (not evaluated) \arg[documentation] A documentation string (not evaluated) \arg[form] A \glref{form} \end{args} \fnreturns The supplied \var{name}. \fndescription % \textbf{Defcm} is a read-time conditional version of Common Lisp's \nobr{\code{define-compiler-macro}}. As with \nobr{\code{define-compiler-macro}}: % \begin{tightitemize} \item The expander function is installed as a compiler macro function for \var{name}. \item The \code{\&whole} argument is bound to the form argument that is passed to \nobr{\textbf{defcm}}. The remaining \nobr{\var{lambda-list\/}} parameters are specified as if this form contained the function name in the car and the actual arguments in the cdr. However, if the car of the actual form is the symbol \nobr{\code{funcall}}, then the destructuring of the arguments is actually performed using its cddr instead. \item Documentation is attached as a documentation string to name (as kind \nobr{\code{compiler-macro}}) and to the compiler macro function. \item A compiler macro can decline to provide an expansion merely by returning the original form (which can be obtained by using \nobr{\code{\&whole}}). \end{tightitemize} % A compiler macro is not defined if the feature \nobr{\textbf{\entlinknoex{:disable-compiler-macros}}} or the feature \nobr{\textbf{\entlinknoex{:full-safety}}} is present when the expander function is executed on a form. \begin{alsos}{:disable-compiler-macros} \also[:disable-compiler-macros] \also[:full-safety] \end{alsos} \fnexample % \bfindexit{ensure-list}% \bfindexit{with-once-only-bindings}% % Here is the compiler macro defined for \nobr{\textbf{\entlink{ensure-list}}}: % \W\supp \begin{example} > (defcm ensure-list (x) (\entlink{with-once-only-bindings} (x) `(if (listp ,x) ,x (list ,x)))) ensure-list > \end{example} \end{functiondoc} %% ------------------------------------------------------------------------ \begin{functiondoc}{Macro}{define-class}{\var{class-name\/} \nobr{\code{(}\{\var{superclass-name\/}\}\superstar\code{)}} \nobr{[\var{documentation\/}]} \nobr{\code{(}\{\var{slot-specifier\/}\}\superstar\code{)}} \nobr{\{\var{class-option\/}\}\superstar{}} \nobr{\returns{} \var{new-class\/}}} \index{class!defining/redefining}% \index{defining!a class}% \index{redefining!a class}% \fnsyntax \fnpurpose Extended macro for defining or redefining a \glref{class}. \fnpackage \code{:gbbopen-tools} \fnmodule \code{:gbbopen-tools} \fnargs \begin{args}{superclass-name} \arg[class-name] A non-\nil, \glref{non-keyword~symbol} that names the \glref{class} \arg[superclass-name] A non-\nil, \glref{non-keyword~symbol} that specifies a direct superclass of the \glref{class} \nobr{\var{class-name\/}} \arg[documentation] A documentation string (not evaluated) \arg[slot-specifiers] See below \arg[class-options] See below \arg[new-class] A new or modified \glref{class} object \end{args} \fnreturns The newly defined or modified \glref{class} object. \fndsyntax \W\supp\tabletop \begin{tabular}{@{~}l@{~}l} \nobr{\var{slot-specifier\/} ::=} & \var{slot-name\/} \vbar \\ & \code{(}\var{slot-name\/} [[\var{slot-option\/}]]\code{)} \\ \end{tabular} \T\\ \begin{tabular}{@{~}l@{~}l} \nobr{\var{slot-option\/} ::=} & \{\code{:accessor} \var{reader-function-name\/}\}\superstar{} \vbar \\ & \{\code{:allocation} \var{allocation-type\/}\} \vbar \\ & \{\code{:documentation} \var{string\/}\} \vbar \\ & \{\code{:initarg} \var{initarg-name\/}\}\superstar{} \vbar \\ & \{\code{:initform} \var{form\/}\} \vbar \\ & \{\code{:reader} \var{reader-function-name\/}\}\superstar{} \vbar \\ & \{\code{:type} \var{type-specifier\/}\} \vbar \\ & \{\code{:writer} \var{writer-function-name\/}\}\superstar{} \\ \end{tabular} \T\\ \begin{tabular}{@{~}l@{~}l} \nobr{\var{class-option\/} ::=} & \code{(:default-initargs .} \var{initarg-list\/}\code{)} \vbar \\ & \code{(:documentation} \var{string\/}\code{)} \vbar \\ & \code{(:export-accessors} \var{boolean\/}\code{)} \vbar \\ & \code{(:export-class-name} \var{boolean\/}\code{)} \vbar \\ & \code{(:export-slot-names} \var{slots-specifier\/}\code{)} \vbar \\ & \code{(:generate-accessors} \var{slots-specifier\/}\code{)} \vbar \\ & \code{(:generate-accessors-format} \{\code{:prefix} \vbar{} \code{:suffix}\} \vbar \\ & \code{(:generate-accessors-prefix} \{\var{string\/} \vbar{} \var{symbol\/}\}\code{)} \vbar \\ & \code{(:generate-accessors-suffix} \{\var{string\/} \vbar{} \var{symbol\/}\}\code{)} \vbar \\ & \code{(:generate-initargs} \var{slots-specifier\/}\code{)} \vbar \\ & \code{(:metaclass} \var{class-name\/}\code{)} \\ \end{tabular} \T\\ \begin{tabular}{@{~}l@{~}l} \nobr{\var{slots-specifier\/} ::=} & \nil{} \vbar{} \code{t} \vbar{} \var{included-slot-name\/}\superstar{} \vbar \\ & \{\code{t :exclude} \var{excluded-slot-name\/}\superstar{}\} \\ \end{tabular} \fnterms \begin{args}{initarg-list} \arg[class-name] A non-\nil, \glref{non-keyword~symbol} that names a \glref{class} \arg[initarg-list] An \glref{initialization~argument~list} \arg[slot-name] A non-\nil, \glref{non-keyword~symbol} \end{args} \fndescription Each \var{superclass-name\/} argument specifies a direct superclass of the new class. If the superclass list is empty, then the direct superclass defaults to the single class \nobr{\code{standard-object}}. \bfindexit{standard-class}% The \code{:metaclass} class option, if specified, must be a subclass of \nobr{\code{standard-class}}. The default metaclass value is \nobr{\code{standard-class}}. \begin{alsos}{with-generate-accessors-format} \also[define-unit-class] \also[make-instance] \also[with-generate-accessors-format] \end{alsos} \fnexamples Define a class, \nobr{\code{rectangle}}, generating ``\code{-of}'' slot accessors: % \W\supp \begin{example} > (define-class rectangle (point) (length width)) # > \end{example} Define a class, \code{foo}, generating \nobr{``\var{class-name}\code{.}\var{slot-name}''} slot accessors: % \W\supp \begin{example} > (define-class foo () ((slot :initform ':uninitialized)) (:generate-accessors-format :prefix)) # > \end{example} \end{functiondoc} %% ------------------------------------------------------------------------ \begin{functiondoc}{Macro}{do-until}{\var{form \nobr{test-form\/}}} \index{iteration!do-until@\textbf{do-until}}% \fnsyntax \fnpurpose Evaluates \var{form\/} and then \nobr{\var{test-form\/}} repeatedly, as long as \nobr{\var{test-form\/}} evaluates to \nil. \fnpackage \code{:gbbopen-tools} \fnmodule \code{:gbbopen-tools} \fnargs \begin{args}{test-form} \arg[form] A \glref{form} \arg[test-form] A \glref{form} \end{args} \begin{alsos}{do-while} \also[do-while] \also[until] \also[while] \end{alsos} \fnexamples % \W\supp \begin{example} > (let ((i 0)) (do-until (print i) (> (incf i) 3))) 1 2 3 nil\goodpagebreak > (let ((i 10)) (do-until (print i) (> (incf i) 3))) 10 nil > \end{example} \end{functiondoc} %% ------------------------------------------------------------------------ \begin{functiondoc}{Macro}{do-while}{\var{form \nobr{test-form\/}}} \index{iteration!do-while@\textbf{do-while}}% \fnsyntax \fnpurpose Evaluates \var{form\/} and then \nobr{\var{test-form\/}} repeatedly, until \nobr{\var{test-form\/}} evaluates to \nil. \fnpackage \code{:gbbopen-tools} \fnmodule \code{:gbbopen-tools} \fnargs \begin{args}{test-form} \arg[form] A \glref{form} \arg[test-form] A \glref{form} \end{args} \begin{alsos}{do-until} \also[do-until] \also[until] \also[while] \end{alsos} \fnexamples % \W\supp \begin{example} > (let ((i 0)) (do-while (print i) (<= (incf i) 3))) 1 2 3 nil\goodpagebreak > (let ((i 10)) (do-while (print i) (<= (incf i) 3))) 10 nil > \end{example} \end{functiondoc} %% ------------------------------------------------------------------------ \begin{functiondoc}{Macro}{dosequence}{% \nobr{(\var{var sequence-form\/} [\var{result-form\/}])} \nobr{\var{declaration\/}\superstar{}} \nobr{\{\var{tag\/} \vbar{} \var{form\/}\}\superstar} \nobr{\returns{} \var{result\/}\superstar or \nil}} \index{iteration!dosequence@\textbf{dosequence}}% \fnsyntax \fnpurpose A generalized \code{dolist}-style iterator for any sequence. \fnpackage \code{:gbbopen-tools} \fnmodule \code{:gbbopen-tools} \fnargs \begin{args}{sequence-form} \arg[var] A \glref{variable~symbol} \arg[sequence-form] A \glref{form} that evaluates to a sequence \arg[result-form] A \glref{form} \arg[declarations] A declare expression (not evaluated) \arg[tag] A \code{go} tag (not evaluated) \arg[form] A \glref{form} \arg[results] The values returned by evaluating the last \var{form} \end{args} \fnreturns If a \code{return} or \nobr{\code{return-from}} form is executed, then the values passed from that form are returned; otherwise, the values returned by evaluating the \nobr{\var{result-form\/}} are returned, or \nil{} if there is no \nobr{\var{result-form}}. \fndescription The body of \nobr{\textbf{dosequence}} is like a \nobr{\code{tagbody}}. \nobr{\textbf{Dosequence}} evaluates \nobr{\var{sequence-form}}, which should produce a sequence. It then executes the body once for each element in the sequence, with \var{var\/} bound to the element. The scope of the binding of \var{var\/} does not include the \nobr{\var{sequence-form}}, but it does include the \nobr{\var{result-form}}. \begin{alsos}{dosublists} \also[dosublists] \end{alsos} \fnexamples % \W\supp \begin{example} > (dosequence (elt #(1 2 3)) (print elt)) 1 2 3 nil\goodpagebreak > (dosequence (char "abc") (print char)) #\(\backslash\)a #\(\backslash\)b #\(\backslash\)c nil > \end{example} \end{functiondoc} %% ------------------------------------------------------------------------ \begin{functiondoc}{Macro}{dosublists}{% \nobr{(\var{var list-form\/} [\var{result-form\/}])} \nobr{\var{declaration\/}\superstar{}} \nobr{\{\var{tag\/} \vbar{} \var{form\/}\}\superstar} \nobr{\returns{} \var{result\/}\superstar or \nil}} \index{iteration!dosublists@\textbf{dosublists}}% \fnsyntax \fnpurpose A \code{dolist}-style iterator for successive sublists of a list. \fnpackage \code{:gbbopen-tools} \fnmodule \code{:gbbopen-tools} \fnargs \begin{args}{declarations} \arg[var] A \glref{variable~symbol} \arg[list-form] A \glref{form} that evaluates to a \glref{proper~list} \arg[result-form] A \glref{form} \arg[declarations] A declare expression (not evaluated) \arg[tag] A \code{go} tag (not evaluated) \arg[form] A \glref{form} \arg[results] The values returned by evaluating the last \var{form} \end{args} \fnreturns If a \code{return} or \nobr{\code{return-from}} form is executed, then the values passed from that form are returned; otherwise, the values returned by evaluating the \nobr{\var{result-form\/}} are returned, or \nil{} if there is no \nobr{\var{result-form}}. \fndescription The body of \nobr{\textbf{dosublists}} is like a \nobr{\code{tagbody}}. \nobr{\textbf{Dosublists}} evaluates \nobr{\var{list-form}}, which should produce a \glref{proper~list}. It then executes the body once for each successive sublist in the list, with \var{var\/} bound to the sublist. The scope of the binding of \var{var\/} does not include the \nobr{\var{list-form}}, but it does include the \nobr{\var{result-form}}. \begin{alsos}{dosequence} \also[dosequence] \end{alsos} \fnexamples % \W\supp \begin{example} > (dosublists (sublist '(1 2 3)) (print sublist)) (1 2 3) (2 3) (3) nil\goodpagebreak > (dosublists (sublist '(1 2 3) (print "Done")) (print sublist)) (1 2 3) (2 3) (3) "Done" > \end{example} \end{functiondoc} %% ------------------------------------------------------------------------ \begin{functiondoc}{Function}{dotted-length}{\var{list\/} \nobr{\returns{} \var{n\/}}} \index{length!of a dotted list}% \index{dotted list!obtaining the length of}% \fnsyntax \fnpurpose Return the length of a \glref{proper~list} or \glref{dotted~list}. \fnpackage \code{:gbbopen-tools} \fnmodule \code{:gbbopen-tools} \fnargs \begin{args}{list} \arg[list] A \glref{proper~list} or a \glref{dotted~list} \arg[n] An integer \end{args} \fnreturns The length of \var{list}. \fnexamples % \W\supp \begin{example} > (dotted-length '(a b)) 2 > (dotted-length '(a b . c)) 2 > \end{example} \fnnote % This \glref{function} will not work on a \glref{circular~list}. \end{functiondoc} %% ------------------------------------------------------------------------ \begin{functiondoc}{Macro}{ecase-using}{% \var{test keyform\/} \nobr{\{\var{clause\/}\}\superstar{}} \nobr{\returns{} \var{result\/}\superstar}} \fnsyntax \fnpurpose Conditionally execute the forms in a clause that is selected by matching the result of evaluating \nobr{\var{keyform\/}} according to \var{test}, generating an error if no clause is selected. \fnpackage \code{:gbbopen-tools} \fnmodule \code{:gbbopen-tools} \fnargs \begin{args}{keyform} \arg[test] A symbol designating a comparison predicate (not evaluated) \arg[keyform] A \glref{form}; evaluated to produce a \nobr{\var{test-key\/}} (see below) \arg[results] The values returned by evaluating the last \var{form\/} in the selected \var{clause} \end{args} \fnreturns The values returned by the last form in the selected \var{clause}. \fnerrors No \var{clause\/} was selected. \fndsyntax \W\supp\tabletop \begin{tabular}{@{~}l@{~}l} \nobr{\var{clause\/} ::=} & \code{(}\var{keys form\/}\superstar\code{)} \\ \end{tabular} \fnterms \begin{args}{test-key} \arg[test-key] An object produced by evaluating \nobr{\var{keyform}} \arg[keys] An object or a \glref{proper~list} of objects. \arg[form] A \glref{form} \end{args} \fndescription % The specified \var{test\/} symbol is not evaluated; however the comparison predicate that it designates must be available during expansion of the \nobr{\textbf{case-using}} form. The \var{keyform\/} is first evaluated to produce the \nobr{\var{test-key}}. Each of the \var{clauses\/} is then considered in turn. If the \nobr{\var{test-key\/}} matches that clause according to \var{test}, then the forms in that clause are evaluated as an implicit \nobr{\code{progn}}, and the values it returns are returned as the value of the \nobr{\textbf{ecase-using}} form. \codeindexit{type-error}% \bfindexit{case-using-failure}% % If no \var{clause\/} is selected, a non-correctable error of type \nobr{\code{case-using-failure}} (a subclass of \nobr{\code{type-error}}) is signaled. The offending datum is the \nobr{\var{test-key\/}} and the expected type is type equivalent to \nobr{\code{(member (union} \var{keys\/} \code{:test} \var{test\/}\code{)}}. \textbf{Ecase-using} is a generalization of Common Lisp's \nobr{\code{ecase}} macro. \begin{alsos}{case-using-failure} \also[case-using-failure] \also[case-using] \also[ccase-using] \end{alsos} \fnexamples % \W\supp \begin{example} > (ecase-using string= "a" ("a" 1) (("b" "c" "d") 2)) 1 > (ecase-using string= "d" ("a" 1) (("b" "c" "d") 2)) 2\goodpagebreak > (ecase-using string= "C" ("a" 1) (("b" "c" "d") 2)) Error: "C" fell through an ecase-using string= form; the valid keys are "a", "b", "c", and "d". >> \end{example} \end{functiondoc} %% ------------------------------------------------------------------------ \begin{functiondoc}{Function}{ensure-finalized-class}{\var{class\/} \nobr{\returns{} \var{finalized-class\/}}} \index{class!finalization}% \index{finalizing, a class}% \fnsyntax \fnpurpose Finalizes \var{class\/} if it is not already finalized. \fnpackage \code{:gbbopen-tools} \fnmodule \code{:gbbopen-tools} \fnargs \begin{args}{finalized-class} \arg[class] A \glref{class~designator} \arg[finalized-class] A \glref{class} object \end{args} \fnreturns The finalized \var{class\/}. \fnexample % \W\supp \begin{example} > (ensure-finalized-class (find-class 'hyp)) # > \end{example} \fnnote \inline \end{functiondoc} %% ------------------------------------------------------------------------ \begin{functiondoc}{Function}{ensure-list}{\var{object\/} \nobr{\returns{} \var{list\/}}} \index{list!assuring}% \fnsyntax \fnpurpose Construct a list containing an object, if the object is not already a list. \fnpackage \code{:gbbopen-tools} \fnmodule \code{:gbbopen-tools} \fnargs \begin{args}{object} \arg[object] An object \arg[list] A list \end{args} \fnreturns The \var{object\/} if it is a list or, if \var{object\/} is an atom, a newly consed list containing \var{object\/} as its sole element. \fnexamples % \W\supp \begin{example} > (ensure-list 'x) (x) > (ensure-list '(x)) (x) > (ensure-list nil) nil > \end{example} \fnnote \inline \end{functiondoc} %% ------------------------------------------------------------------------ \begin{functiondoc}{Macro}{incf-after}{\var{place\/} \nobr{\code{\&optional} \var{increment\/}} \nobr{\returns{} \var{original-value\/}}} \index{place!incrementing numeric value of}% \fnsyntax \fnpurpose Increment the value of \var{place}, returning the original value of \var{place}. \fnpackage \code{:gbbopen-tools} \fnmodule \code{:gbbopen-tools} \fnargs \begin{args}{original-value} \arg[place] A \glref{form} which is suitable for use as a \glref{generalized~reference} \arg[increment] A number (default is \code{1}) \arg[original-value] A number \end{args} \fnreturns The original value of \var{place}. \begin{alsos}{decf-after} \also[decf-after] \end{alsos} \fnexamples \begin{example} % \W\supp > (defparameter *x* 0) *x* > (incf-after *x*) 0 > *x* 1 > (incf-after *x* 3) 1 > *x* 4 > \end{example} \fnnote % \bfindex{incf-after\&}% \bfindex{incf-after\$\&}% \bfindex{incf-after\$}% \bfindex{incf-after\$\$}% \bfindex{incf-after\$\$\$}% \bfindex{incf-after\%}% % \reflink{Declared numeric}{sec:declared-numerics} and \reflink{pseudo probability}{sec:pprob} versions of \nobr{\textbf{incf-after}} are also provided: \nobr{\textbf{incf-after\&}}, \nobr{\textbf{incf-after\$\&}}, \nobr{\textbf{incf-after\$}}, \nobr{\textbf{incf-after\$\$}}, \nobr{\textbf{incf-after\$\$\$}}, and \nobr{\textbf{incf-after\%}}. \end{functiondoc} %% ------------------------------------------------------------------------ \begin{functiondoc}{Function}{list-length-1-p}{% \var{list\/} \nobr{\returns{} \var{boolean\/}}} \index{length!testing a list for length $=$ 1}% \index{list!testing length $=$ 1}% \fnsyntax \fnpurpose Fast length $=$ 1 test of a list. \fnpackage \code{:gbbopen-tools} \fnmodule \code{:gbbopen-tools} \fnargs \begin{args}{boolean} \arg[list] A \glref{proper~list} or a \glref{dotted~list} \arg[boolean] A \glref{generalized~boolean} \end{args} \fnreturns True if \var{list\/} has length 1; \nil{} otherwise. \begin{alsos}{list-length-2-p} \also[list-length>] \also[list-length>1] \also[list-length>2] \also[list-length-2-p] \end{alsos} \fnexamples % \W\supp \begin{example} > (list-length-1-p '(a)) t > (list-length-1-p '(a b)) nil > (list-length-1-p nil) nil > (list-length-1-p '(a . b)) nil > \end{example} \end{functiondoc} %% ------------------------------------------------------------------------ \begin{functiondoc}{Function}{list-length-2-p}{% \var{list\/} \nobr{\returns{} \var{boolean\/}}} \index{length!testing a list for length $=$ 2}% \index{list!testing length $=$ 2}% \fnsyntax \fnpurpose Fast length $=$ 2 test of a list. \fnpackage \code{:gbbopen-tools} \fnmodule \code{:gbbopen-tools} \fnargs \begin{args}{boolean} \arg[list] A \glref{proper~list} or a \glref{dotted~list} \arg[boolean] A \glref{generalized~boolean} \end{args} \fnreturns True if \var{list\/} has length 2; \nil{} otherwise. \begin{alsos}{list-length-1-p} \also[list-length-1-p] \also[list-length>] \also[list-length>1] \also[list-length>2] \end{alsos} \fnexamples % \W\supp \begin{example} > (list-length-2-p '(a b)) t > (list-length-2-p '(a b c)) nil > (list-length-2-p '(a)) nil > (list-length-2-p '(a b . c)) nil > \end{example} \end{functiondoc} %% ------------------------------------------------------------------------ \begin{functiondoc}[list-length-gt]{Function}{list-length>}{% \var{n list\/} \nobr{\returns{} \var{boolean\/}}} \index{length!testing a list for length $>$ $n$}% \index{list!testing length $>$ $n$}% \fnsyntax \fnpurpose Fast length $>$ $n$ test of a list. \fnpackage \code{:gbbopen-tools} \fnmodule \code{:gbbopen-tools} \fnargs \begin{args}{boolean} \arg[n] A non-negative \code{\glref{fixnum}} \arg[list] A \glref{proper~list} or a \glref{dotted~list} \arg[boolean] A \glref{generalized~boolean} \end{args} \fnreturns True if \var{list\/} has length $>$ $n$; \nil{} otherwise. \begin{alsos}{list-length-2-p} \also[list-length>] \also[list-length-1-p] \also[list-length-2-p] \end{alsos} \fnexamples % \W\supp \begin{example} > (list-length> 1 '(a b)) t > (list-length> 2 '(a b)) nil > (list-length> 1 '(a)) nil\goodpagebreak > (list-length> 1 '(a . b)) nil > (list-length> 1 '(a b . c)) t > \end{example} \end{functiondoc} %% ------------------------------------------------------------------------ \begin{functiondoc}[list-length-gt-1]{Function}{list-length>1}{% \var{list\/} \nobr{\returns{} \var{boolean\/}}} \index{length!testing a list for length $>$ 1}% \index{list!testing length $>$ 1}% \fnsyntax \fnpurpose Fast length $>$ 1 test of a list. \fnpackage \code{:gbbopen-tools} \fnmodule \code{:gbbopen-tools} \fnargs \begin{args}{boolean} \arg[list] A \glref{proper~list} or a \glref{dotted~list} \arg[boolean] A \glref{generalized~boolean} \end{args} \fnreturns True if \var{list\/} has length $>$ 1; \nil{} otherwise. \begin{alsos}{list-length-2-p} \also[list-length>] \also[list-length-1-p] \also[list-length-2-p] \end{alsos} \fnexamples % \W\supp \begin{example} > (list-length>1 '(a b)) t > (list-length>1 '(a)) nil\goodpagebreak > (list-length>1 '(a . b)) nil > (list-length>1 '(a b . c)) t > \end{example} \end{functiondoc} %% ------------------------------------------------------------------------ \begin{functiondoc}[list-length-gt-2]{Function}{list-length>2}{% \var{list\/} \nobr{\returns{} \var{boolean\/}}} \index{length!testing a list for length $>$ 2}% \index{list!testing length $>$ 2}% \fnsyntax \fnpurpose Fast length $>$ 2 test of a list. \fnpackage \code{:gbbopen-tools} \fnmodule \code{:gbbopen-tools} \fnargs \begin{args}{boolean} \arg[list] A \glref{proper~list} or a \glref{dotted~list} \arg[boolean] A \glref{generalized~boolean} \end{args} \fnreturns True if \var{list\/} has length $>$ 2; \nil{} otherwise. \begin{alsos}{list-length-2-p} \also[list-length>] \also[list-length>1] \also[list-length-1-p] \also[list-length-2-p] \end{alsos} \fnexamples % \W\supp \begin{example} > (list-length>2 '(a b c)) t > (list-length>2 '(a b)) nil\goodpagebreak > (list-length>2 '(a b . c)) nil > (list-length>2 '(a b c . d)) t > \end{example} \end{functiondoc} %% ------------------------------------------------------------------------ \begin{functiondoc}{Function}{make-hash-values-vector}{\var{hash-table\/} \nobr{\returns{} \var{vector\/}}} \index{hash-table!coerce values to a vector}% \fnsyntax \fnpurpose Return a vector containing all values in \nobr{\var{hash-table}}. \fnpackage \code{:gbbopen-tools} \fnmodule \code{:gbbopen-tools} \fnargs \begin{args}{hash-table} \arg[hash-table] A hash table \arg[vector] A vector \end{args} \fnreturns The newly allocated \var{vector}. \fnexamples % \W\supp \begin{example} > (defparameter *ht* (make-hash-table)) *ht* > (make-hash-values-vector *ht*) #() > (setf (gethash 'a *ht*) 1) 1 > (setf (gethash 'b *ht*) 2) 2 > (setf (gethash 'c *ht*) 3) 3 > (make-hash-values-vector *ht*) #(3 1 2) > \end{example} \end{functiondoc} %% ------------------------------------------------------------------------ \begin{functiondoc}{Function}{make-keyword}{\var{x\/} \nobr{\returns{} \var{keyword\/}}} \index{creating!a keyword symbol}% \index{making!a keyword symbol}% \fnsyntax \fnpurpose Return a \glref{keyword~symbol} as specified by \var{x}. \fnpackage \code{:gbbopen-tools} \fnmodule \code{:gbbopen-tools} \fnargs \begin{args}{keyword} \arg[x] A string, symbol, or character \arg[keyword] A \glref{keyword~symbol} \end{args} \fnreturns The \glref{keyword~symbol}. \fnexamples % \W\supp \begin{example} > (make-keyword 'gbbopen) :gbbopen > (make-keyword "GBBOPEN") :gbbopen > (make-keyword #\bkslash{}X) :x > \end{example} \fnnote \inline \end{functiondoc} %% ------------------------------------------------------------------------ \begin{functiondoc}{Function}{memq}{\var{item list\/} \nobr{\returns{} \var{tail\/}}} \index{searching!for an item in a list}% \fnsyntax \fnpurpose Search for \var{item\/} in \var{list\/} using \code{eq} as the comparison function. \fnpackage \code{:gbbopen-tools} \fnmodule \code{:gbbopen-tools} \fnargs \begin{args}{symbol} \arg[item] An object \arg[list] A \glref{proper~list} \arg[tail] A \glref{proper~list} \end{args} \fnreturns The tail of \var{list\/} beginning with \var{item\/} if \var{item\/} is present; \nil{} otherwise. \fndescription \textbf{Memq} is a convenient shorthand for: % \W\supp \begin{example} (member \var{item\/} (the list \var{list\/}) :test #'eq) \end{example} \begin{alsos}{counted-delete} \also[counted-delete] \also[assq] \also[delq] \also[delq-one] \end{alsos} \fnexamples % \W\supp \begin{example} > (memq 'b '(a b c b)) (b c b) > (memq 'x '(a b c b)) nil > \end{example} \end{functiondoc} %% ------------------------------------------------------------------------ \begin{functiondoc}{Macro}{multiple-value-setf}{% \nobr{\code{(\var{place\/}\superstar)}} \var{form\/} \nobr{\returns{} \var{primary-value\/}}} \fnsyntax \fnpurpose Assign values to \var{places}. \fnpackage \code{:gbbopen-tools} \fnmodule \code{:gbbopen-tools} \fnargs \begin{args}{test-form} \arg[place] A \glref{form} which is suitable for use as a \glref{generalized~reference} or \nil \arg[form] A \glref{form} \arg[primary-value] The first value returned by evaluating \var{form} \end{args} \fnreturns The primary value returned by \var{form}. \fndescription % The \var{form\/} is evaluated, and each \var{place\/} is assigned to the corresponding value returned by \var{form}. If \nil{} is used one or more \var{places\/}, no assignment is made to the \nil{} ``place,'' but the corresponding value is consumed (ignored). If there are more \var{places\/} than values returned, \nil{} is assigned to the extra \var{places}. If there are more values than \var{places}, the extra values are discarded. \fnexamples % \W\supp \begin{example} > (setf *x* (cons 0 0)) (0 . 0) > (multiple-value-setf ((car *x*) (cdr *x*)) (values 1 2 3)) 1 > *x* (1 . 2)\goodpagebreak > (multiple-value-setf (nil nil (cdr *x*)) (values -1 -2 -3)) -1 > *x* (1 . -3)\goodpagebreak > (multiple-value-setf ((car *x*) (cdr *x*)) 100) 100 > *x* (100)\goodpagebreak > (multiple-value-setf ((car *x*) (cdr *x*)) nil) nil > *x* (nil)\goodpagebreak > \end{example} \end{functiondoc} %% ------------------------------------------------------------------------ \begin{functiondoc}{Function}{nsorted-insert}{\var{item list\/} \nobr{\code{\&optional} \var{predicate key\/}} \nobr{\returns{} \var{result-list\/}}} \index{inserting an item!into a sorted list}% \index{sorted list!inserting an item into}% \fnsyntax \fnpurpose Positionally insert \var{item\/} in \var{list\/} based on \nobr{\var{predicate\/}} and \var{key\/} functions. \fnpackage \code{:gbbopen-tools} \fnmodule \code{:gbbopen-tools} \fnargs \begin{args}{result-list} \arg[item] An object \arg[list] A \glref{proper~list} \arg[predicate] A \glref{function~designator} specifying a \glref{function~object} of two arguments that returns a \glref{generalized~boolean} (default is \nobr{\code{\#'$<$}}) \arg[key] A \glref{function~designator} specifying a \glref{function~object} of one argument, or \nil{} (default is \nil) \arg[result-list] A \glref{proper~list} \end{args} \fnreturns A list into which \var{item\/} has been inserted. \fndescription The supplied \var{list\/} may be modified in constructing the result; however, modification of the supplied \var{list\/} itself is not guaranteed. \fnexample % \W\supp \begin{example} > (nsorted-insert 5 '(2 4 6 8)) (2 4 5 6 8) > \end{example} \end{functiondoc} %% ------------------------------------------------------------------------ \begin{functiondoc}{Function}{object-address}{\var{object\/} \nobr{\code{\&optional} \var{hex-string-p\/}} \nobr{\returns{} \var{address\/}}} \index{searching!for an item in a list}% \fnsyntax \fnpurpose Return the internal address of \var{object}. \fnpackage \code{:gbbopen-tools} \fnmodule \code{:gbbopen-tools} \fnargs \begin{args}{hex-string-p} \arg[object] An object \arg[hex-string-p] A \glref{generalized~boolean} (default is \nil) \arg[address] An integer or a string \end{args} \fnreturns The integer internal address of \var{object\/} or a string containing the hexadecimal representation of the address if \nobr{\var{hex-string-p\/}} is true. \fndescription \textbf{Object-address} can be useful with \nobr{\textbf{\entlink{printv}}}. \begin{alsos}{printv} \also[printv] \end{alsos} \fnexamples % \W\supp \begin{example} > (object-address *package*) 1907568474 > (object-address *package* 't) "71B32F5A" > \end{example} \end{functiondoc} %% ------------------------------------------------------------------------ \begin{functiondoc}{Generic~Function}{print-instance-slot-value}% {\var{instance \nobr{slot-name} stream\/} \nobr{\code{\&key} \var{function no-space\/}}} \fnsyntax \fnpurpose Print the value of the \var{slot-name\/} slot in \var{instance\/} or \code{[Unbound]}, if the slot is unbound. \fnmethods \fnalternate{print-instance-slot-value}{\code{(}\var{instance\/} \code{standard-gbbopen-instance)} slot-name stream\/} \fnpackage \code{:gbbopen-tools} \fnmodule \code{:gbbopen-tools} \fnargs \begin{args}{instance} \arg[instance] A \glref{standard-gbbopen-instance} object \arg[slot-name] A non-\nil, \glref{non-keyword~symbol} \arg[stream] A stream \arg[function] A \glref{function~designator} specifying a \glref{function~object} of one argument \arg[no-space] A \glref{generalized~boolean} (default is \nil) \end{args} \fndescription % Unless \var{no-space} is true, a space character is printed to \var{stream}. Then the slot value in \var{instance\/} specified by \var{slot-name} is printed to \var{stream\/}, unless the slot is unbound, in which case \code{[Unbound]} is printed to \var{stream}. If the slot is bound and \var{function\/} is specifed, \var{function\/} is called with the slot value and the result is printed to \var{stream} rather than the slot value. \begin{alsos}{standard-gbbopen-instance} \also[print-instance-slots] \also[standard-gbbopen-instance] \end{alsos} \fnexample % \bfindexit{print-instance-slots}% Extend the \nobr{\code{print-object}} printing for \code{hyp} \glref{instances} to include \code{location} and \code{belief} slot values: \W\supp \begin{example} (defmethod \entlink{print-instance-slots} ((obj hyp) stream) (call-next-method) (print-instance-slot-value obj 'location stream) (print-instance-slot-value obj 'belief stream)) \end{example} \end{functiondoc} %% ------------------------------------------------------------------------ \begin{functiondoc}{Generic~Function}{print-instance-slots}% {\var{instance stream\/}} \fnsyntax \fnpurpose Extend \glref{standard-gbbopen-instance} printing performed by \nobr{\code{print-object}} to include additional \glref{slot}-value information. \fnmethods \fnalternate{print-instance-slots}{\code{(}\var{instance\/} \code{ksa)} stream\/} \fnalternate{print-instance-slots}{\code{(}\var{instance\/} \code{link/nonlink-slot-event)} stream\/} \fnalternate{print-instance-slots}{\code{(}\var{instance\/} \code{multiple-instances-event)} stream\/} \fnalternate{print-instance-slots}{\code{(}\var{instance\/} \code{single-instance-event)} stream\/} \fnalternate{print-instance-slots}{\code{(}\var{instance\/} \code{space-instance-event)} stream\/} \fnalternate{print-instance-slots}{\code{(}\var{instance\/} \code{standard-event-instance)} stream\/} \fnalternate{print-instance-slots}{\code{(}\var{instance\/} \code{standard-gbbopen-instance)} stream\/} \fnalternate{print-instance-slots}{\code{(}\var{instance\/} \code{standard-unit-instance)} stream\/} \fnalternate{print-instance-slots}{\code{:after (}\var{instance\/} \code{standard-unit-instance)} stream\/} \fnpackage \code{:gbbopen-tools} \fnmodule \code{:gbbopen-tools} \fnargs \begin{args}{instance} \arg[instance] A \glref{standard-gbbopen-instance} object \arg[stream] A stream \end{args} \begin{alsos}{standard-gbbopen-instance} \also[print-instance-slot-value] \also[standard-gbbopen-instance] \end{alsos} \fnexamples % Extend the \nobr{\code{print-object}} printing for \code{hyp} \glref{instances} to include \code{location} and \code{belief} slot values: % \W\supp \begin{example} (defmethod print-instance-slots ((obj hyp) stream) (call-next-method) (when (and (slot-boundp obj 'location) (slot-boundp obj 'belief)) (format stream " ~s ~s" (slot-value obj 'location) (slot-value obj 'belief)))) \end{example} % \bfindexit{print-instance-slot-value}% or if displaying \code{[Unbound]} for unbound slots is desired: % \W\supp\notpretop \begin{example} (defmethod print-instance-slots ((obj hyp) stream) (call-next-method) (\entlink{print-instance-slot-value} obj 'location stream) (\entlink{print-instance-slot-value} obj 'belief stream)) \end{example} \end{functiondoc} %% ------------------------------------------------------------------------ \begin{functiondoc}{Macro}{printv}{% \nobr{\var{form\/}\superstar{}} \nobr{\returns{} \var{result\/}\superstar}} \index{debugging, using printv@using \textbf{printv}}% \fnsyntax \fnpurpose Assist debugging by printing forms and the results of evaluating them to \nobr{\code{*trace-output*}}. \fnpackage \code{:gbbopen-tools} (home package is \nobr{\code{:module-manager}}) \fnmodule \code{:module-manager} \fnargs \begin{args}{results} \arg[forms] An implicit \nobr{\code{progn}} of \glref{forms} to be evaluated and printed \arg[results] The values returned by evaluating the last \var{form} that is not the keyword symbol \code{:hr} \end{args} \fnreturns The values returned by evaluating the last \var{form} that is not the keyword symbol \code{:hr} \fndescription The following is performed for each form in \var{forms}: \begin{tightitemize} \item if the form is the keyword symbol \code{:hr}, a dashed separator line printed to \nobr{\code{*trace-output*}} \item if the form is a string (before evaluation), it is treated as a label and printed to \nobr{\code{*trace-output*}} without enclosing double-quote characters \item if the form is a self-evaluating object, it is printed to \nobr{\code{*trace-output*}} \item otherwise, the form is printed to \nobr{\code{*trace-output*}}, then the form is evaluated and the result values are printed to \nobr{\code{*trace-output*}}. \end{tightitemize} \begin{alsos}{printvot} \also[printvot] \end{alsos} \bfindexit{object-address}% \fnexamples % \W\supp \begin{example} > (printv :hr "PRINTV example" (list 1 2) (list 3 4) '"A quoted string" "Return no values:" (values) "Return multiple values:" (values 5 6) :hr) ;; ------------------------------------------------------------ ;; PRINTV example ;; (list 1 2) => (1 2) ;; (list 3 4) => (3 4) ;; Return no values: ;; (values) => [returned 0 values] ;; '"A quoted string" => "A quoted string" ;; Return multiple values: ;; (values 5 6) => 5; 6 ;; ------------------------------------------------------------ 5 6\goodpagebreak > (printv *package* (\entlink{object-address} *package* 't)) ;; *package* => # ;; (object-address *package* 't) => "71b32f5a" "71b32f5a" > \end{example} \fnnote \indexit{module!:module-manager@\code{:module-manager}}% \indexit{:module-manager@\code{:module-manager} module}% % This macro is defined in the \nobr{\code{:module-manager}} \glref{module} in order to make it available as early as possible. \end{functiondoc} %% ------------------------------------------------------------------------ \begin{functiondoc}{Macro}{push-acons}{\var{item value place\/} \nobr{\returns{} \var{new-place-value\/}}} \index{pushing!a pair onto an association list}% \index{association list!pushing a pair onto}% \fnsyntax \fnpurpose Add a new \var{item value\/} \glref{cons} to an \glref{association~list} stored in \var{place}. \fnpackage \code{:gbbopen-tools} \fnmodule \code{:gbbopen-tools} \fnargs \begin{args}{new-place-value} \arg[item] An object \arg[value] An object \arg[place] A \glref{form} which is suitable for use as a \glref{generalized~reference} \arg[new-place-value] An \glref{association~list} \end{args} \fnreturns An \glref{association~list} (the new value of \var{place}). \begin{alsos}{pushnew/incf-acons} \also[pushnew-acons] \also[pushnew/incf-acons] \end{alsos} \fnexamples % \W\supp \begin{example} > (setf alist nil) nil > (push-acons 'x 1 alist) ((x . 1))\goodpagebreak > (push-acons 'y 2 alist) ((y . 2) (x . 1)) > alist ((y . 2) (x . 1)) > \end{example} \end{functiondoc} %% ------------------------------------------------------------------------ \begin{functiondoc}{Macro}{pushnew-acons}{\var{item value place\/} \nobr{\code{\&key} \var{key test test-not\/}} \nobr{\returns{} \var{new-place-value\/}}} \index{pushing!a new pair onto an association list}% \index{updating, the value of an association-list pair}% \index{association list!pushing a new pair onto}% \index{association list!updating the value of a pair}% \fnsyntax \fnpurpose Replace the \var{value\/} associated with \var{item\/} in an \glref{association~list} stored in \var{place\/} or add a new \nobr{\code{(\var{item\/} . \var{value\/})}} \glref{cons} to the \glref{association~list} if there is no existing association for \var{item}. \fnpackage \code{:gbbopen-tools} \fnmodule \code{:gbbopen-tools} \fnargs \begin{args}{new-place-value} \arg[item] An object \arg[value] An object \arg[place] A \glref{form} which is suitable for use as a \glref{generalized~reference} \arg[key] A \glref{function~designator} specifying a \glref{function~object} of one argument, or \nil{} (default is \nil) \arg[test] A \glref{function~designator} specifying a \glref{function~object} of two arguments that returns a \glref{generalized~boolean} (default is \nobr{\code{\#'eql}}) \arg[test-not] A \glref{function~designator} specifying a \glref{function~object} of two arguments that returns a \glref{generalized~boolean} (use of \code{:test-not} is deprecated) \arg[new-place-value] An \glref{association~list} \end{args} \fnreturns An \glref{association~list} (the new value of \var{place}). \begin{alsos}{pushnew/incf-acons} \also[push-acons] \also[pushnew/incf-acons] \end{alsos} \fnexamples % \W\supp \begin{example} > (setf alist nil) nil > (pushnew-acons 'x 1 alist) ((x . 1)) > (pushnew-acons 'y 2 alist) ((y . 2) (x . 1))\goodpagebreak > (pushnew-acons 'x -1 alist) ((y . 2) (x . -1)) > alist ((y . 2) (x . -1)) > \end{example} \end{functiondoc} %% ------------------------------------------------------------------------ \begin{functiondoc}{Macro}{pushnew-elements}{\var{list place\/} \nobr{\code{\&key} \var{key test test-not\/}} \nobr{\returns{} \var{new-place-value\/}}} \index{pushing!new elements onto a list}% \index{list!pushing new elements onto}% \fnsyntax \fnpurpose Pushes new elements in \var{list\/} onto the list stored in \var{place}. \fnpackage \code{:gbbopen-tools} \fnmodule \code{:gbbopen-tools} \fnargs \begin{args}{new-place-value} \arg[list] A \glref{proper~list} \arg[place] A \glref{form} which is suitable for use as a \glref{generalized~reference} \arg[key] A \glref{function~designator} specifying a \glref{function~object} of one argument, or \nil{} (default is \nil) \arg[test] A \glref{function~designator} specifying a \glref{function~object} of two arguments that returns a \glref{generalized~boolean} (default is \nobr{\code{\#'eql}}) \arg[test-not] A \glref{function~designator} specifying a \glref{function~object} of two arguments that returns a \glref{generalized~boolean} (use of \nobr{\code{:test-not}} is deprecated) \arg[new-place-value] An \glref{association~list} \end{args} \fnreturns The new value of \var{place}. \fndescription Each element in \var{list\/} is checked to see if it is already present in the \glref{proper~list} stored in \var{place}. If the element is not already present, it is prepended to the list stored in \var{place}. \fnexamples % \W\supp \begin{example} > (setf x '(1 3 5)) (1 3 5) > (pushnew-elements '(1 2 3) x) (2 1 3 5) > (pushnew-elements '(3 4 5) x) (4 2 1 3 5) > \end{example} \end{functiondoc} %% ------------------------------------------------------------------------ \begin{functiondoc}[pushnew-incf-acons]{Macro}{pushnew/incf-acons}{% \var{item increment place\/} \nobr{\code{\&key} \var{key test test-not\/}} \nobr{\returns{} \var{new-place-value\/}}} \index{pushing!a new pair onto an association list}% \index{incrementing, the value of an association-list pair}% \index{association list!pushing a new pair onto}% \index{association list!incrementing the value of a pair}% \fnsyntax \fnpurpose Increment by \var{increment\/} the value associated with \var{item\/} in an \glref{association~list} stored in \var{place\/} or add a new \nobr{\code{(\var{item\/} . \var{increment\/})}} \glref{cons} to the \glref{association~list} if there is no existing association for \var{item}. \fnpackage \code{:gbbopen-tools} \fnmodule \code{:gbbopen-tools} \fnargs \begin{args}{new-place-value} \arg[item] An object \arg[increment] A number \arg[place] A \glref{form} which is suitable for use as a \glref{generalized~reference} \arg[key] A \glref{function~designator} specifying a \glref{function~object} of one argument, or \nil{} (default is \nil) \arg[test] A \glref{function~designator} specifying a \glref{function~object} of two arguments that returns a \glref{generalized~boolean} (default is \nobr{\code{\#'eql}}) \arg[test-not] A \glref{function~designator} specifying a \glref{function~object} of two arguments that returns a \glref{generalized~boolean} (use of \nobr{\code{:test-not}} is deprecated) \arg[new-place-value] An \glref{association~list} \end{args} \fnreturns An \glref{association~list} (the new value of \var{place}). \begin{alsos}{decf/delete-acons} \also[push-acons] \also[pushnew-acons] \also[decf/delete-acons] \end{alsos} \fnexamples % \W\supp \begin{example} > (setf alist nil) nil > (pushnew/incf-acons 'x 1 alist) ((x . 1)) > (pushnew/incf-acons 'x 1 alist) ((x . 2))\goodpagebreak > (pushnew/incf-acons 'y 2 alist) ((y . 2) (x . 2)) > (pushnew/incf-acons 'x -1 alist) ((y . 2) (x . 1)) > alist ((y . 2) (x . 1)) > \end{example} \fnnote % \bfindex{pushnew/incf\&-acons}% \bfindex{pushnew/incf\$\&-acons}% \bfindex{pushnew/incf\$-acons}% \bfindex{pushnew/incf\$\$-acons}% \bfindex{pushnew/incf\$\$\$-acons}% \bfindex{pushnew/incf\%-acons}% % \reflink{Declared numeric}{sec:declared-numerics} and \reflink{pseudo probability}{sec:pprob} versions of \nobr{\textbf{pushnew/incf-acons}} are also provided: \nobr{\textbf{pushnew/incf\&-acons}}, \nobr{\textbf{pushnew/incf\$\&-acons}}, \nobr{\textbf{pushnew/incf\$-acons}}, \nobr{\textbf{pushnew/incf\$\$-acons}}, \nobr{\textbf{pushnew/incf\$\$\$-acons}}, and \nobr{\textbf{pushnew/incf\%-acons}}. \end{functiondoc} %% ------------------------------------------------------------------------ \begin{functiondoc}{Function}{remove-properties}{\var{plist indicators\/} \nobr{\returns{} \var{new-plist\/}}} \index{property list!removing property from}% \index{removing property, from a property list}% \fnsyntax \fnpurpose Non-destructively removes \glref{properties} from a \glref{property~list}. \fnpackage \code{:gbbopen-tools} \fnmodule \code{:gbbopen-tools} \fnargs \begin{args}{indicator} \arg[plist] A \glref{property~list} \arg[indicators] A list of objects \arg[new-plist] A \glref{property~list} \end{args} \fnreturns The new \glref{property~list}. \fndescription All instances of each specified \glref{property} in the \glref{property~list} are removed. \begin{alsos}{remove-property} \also[remove-property] \end{alsos} \fnexamples % \W\supp \begin{example} > (remove-properties '(:x 1 :y 2 :z 3) '(:y)) (:x 1 :z 3) > (remove-properties '(:x 1 :y 2 :x 11 :y 12 :z -1) '(:z :y)) (:x 1 :x 11) > (remove-properties '(:x 1 :y 2 :z 3) '(:missing)) (:x 1 :y 2 :z 3) > \end{example} \end{functiondoc} %% ------------------------------------------------------------------------ \begin{functiondoc}{Function}{remove-property}{\var{plist indicator\/} \nobr{\returns{} \var{new-plist\/}}} \index{property list!removing property from}% \index{removing property, from a property list}% \fnsyntax \fnpurpose Non-destructively remove a \glref{property} from a \glref{property~list}. \fnpackage \code{:gbbopen-tools} \fnmodule \code{:gbbopen-tools} \fnargs \begin{args}{indicator} \arg[plist] A \glref{property~list} \arg[indicator] An object \arg[new-plist] A \glref{property~list} \end{args} \fnreturns The new \glref{property~list}. \fndescription If there is more than one instance of \glref{property} in the \glref{property~list}, only the first one is removed. \begin{alsos}{remove-properties} \also[remove-properties] \end{alsos} \fnexamples % \W\supp \begin{example} > (remove-property '(:x 1 :y 2 :z 3) :y) (:x 1 :z 3) > (remove-property '(:x 1 :y 2 :x 11 :y 12) :y) (:x 1 :x 11 :y 12) > (remove-property '(:x 1 :y 2 :z 3) :missing) (:x 1 :y 2 :z 3) > \end{example} \end{functiondoc} %% ------------------------------------------------------------------------ \begin{functiondoc}{Function}{set-equal}{% \nobr{\var{list-1 list-2\/}} \nobr{\code{\&key} \var{test test-not key\/}} \nobr{\returns{} \var{boolean\/}}} \fnsyntax \fnpurpose Determine if all elements in two lists are present in both lists. \fnpackage \code{:gbbopen-tools} \fnmodule \code{:gbbopen-tools} \fnargs \begin{args}{test-not} \arg[list-1] A \glref{proper~list} \arg[list-2] A \glref{proper~list} \arg[test] A \glref{function~designator} specifying a \glref{function~object} of two arguments that returns a \glref{generalized~boolean} (default is \nobr{\code{\#'eql}}) \arg[test-not] A \glref{function~designator} specifying a \glref{function~object} of two arguments that returns a \glref{generalized~boolean} (use of \nobr{\code{:test-not}} is deprecated) \arg[key] A \glref{function~designator} specifying a \glref{function~object} of one argument, or \nil{} (default is \nil) \arg[boolean] A \glref{generalized~boolean} \end{args} \fnreturns True if all elements in \var{\var{list-1\/}} are also in \nobr{\var{list-2\/}} and vice versa; \nil{} otherwise. \fndescription Duplicate elements in either list are permitted, so the lengths of \nobr{\var{list-1\/}} and \nobr{\var{list-2\/}} can differ and still return true. \fnexamples % \W\supp \begin{example} > (set-equal '(1 2 3) '(3 2 1)) t > (set-equal '(1 2) '(3 2 1)) nil\goodpagebreak > (set-equal '(1 2 3) '(3 1)) nil > (set-equal '(1 2 3) '(3 3 3 2 1)) t > (set-equal '(1 2 3) '(4 5 6 7) :test #'/=) t > \end{example} \end{functiondoc} %% ------------------------------------------------------------------------ \begin{functiondoc}{Function}{sets-overlap-p}{% \nobr{\var{list-1 list-2\/}} \nobr{\code{\&key} \var{test test-not key\/}} \nobr{\returns{} \var{boolean\/}}} \fnsyntax \fnpurpose Determine if any element in \nobr{\var{list-1\/}} appears in \nobr{\var{list-2}}. \fnpackage \code{:gbbopen-tools} \fnmodule \code{:gbbopen-tools} \fnargs \begin{args}{test-not} \arg[list-1] A \glref{proper~list} \arg[list-2] A \glref{proper~list} \arg[test] A \glref{function~designator} specifying a \glref{function~object} of two arguments that returns a \glref{generalized~boolean} (default is \nobr{\code{\#'eql}}) \arg[test-not] A \glref{function~designator} specifying a \glref{function~object} of two arguments that returns a \glref{generalized~boolean} (use of \nobr{\code{:test-not}} is deprecated) \arg[key] A \glref{function~designator} specifying a \glref{function~object} of one argument, or \nil{} (default is \nil) \arg[boolean] A \glref{generalized~boolean} \end{args} \fnreturns True if any element in \nobr{\var{list-1\/}} is also in \nobr{\var{list-2\/}}; \nil{} otherwise. \fndescription Duplicate elements in either list are permitted. \fnexamples % \W\supp \begin{example} > (sets-overlap-p '(1 2 3) '(3 4 5)) t > (sets-overlap-p '(1 2) '(3 4 5)) nil > (sets-overlap-p '(1 3 7) '(3 4 5 6) :test #'/=) t > \end{example} \end{functiondoc} %% ------------------------------------------------------------------------ \begin{functiondoc}{Function}{shuffle-list}{\var{list\/} \nobr{\returns{} \var{shuffled-list\/}}} \index{list!shuffling}% \fnsyntax \fnpurpose Return a copy of a list, with the elements in random order. \fnpackage \code{:gbbopen-tools} \fnmodule \code{:gbbopen-tools} \fnargs \begin{args}{shuffled-list} \arg[list] A \glref{proper~list} \arg[shuffled-list] A \glref{proper~list} \end{args} \fnreturns The shuffled copy of \var{list}. \fnexamples % \W\supp \begin{example} > (shuffle-list '(a b c d)) (b a c d) > (shuffle-list '(a b c d)) (c a d b) > \end{example} \end{functiondoc} %% ------------------------------------------------------------------------ \begin{functiondoc}{Function}{shrink-vector}{\var{vector length\/} \nobr{\returns{} \var{vector\/}}} \fnsyntax \fnpurpose Shorten a one-dimensional simple array destructively, if possible. \fnpackage \code{:gbbopen-tools} \fnmodule \code{:gbbopen-tools} \fnargs \begin{args}{list} \arg[vector] A ``simple'' vector that is a one-dimensional simple array \arg[length] A non-negative integer, not greater than the length of \var{vector} \end{args} \fnreturns The truncated \var{vector}, which may not be identical (\code{eq}) to the original \nobr{\var{vector\/}} argument on some Common Lisp implementations. \fndescription This function provides access to the Common Lisp implementation's low-level truncation operation. \fnexample % \W\supp \begin{example} > (shrink-vector "abcdefghijklmnopqrstuvwxyz" 3) "abc" > \end{example} \fnnote \inline \end{functiondoc} %% ------------------------------------------------------------------------ \begin{functiondoc}{Function}{sole-element}{\var{list\/} \nobr{\returns{} \var{element\/} or \nil}} \index{list!returning first element of}% \index{first element! of a list, returning}% \fnsyntax \fnpurpose Return the first element of a list containing, at most, one element. \fnpackage \code{:gbbopen-tools} \fnmodule \code{:gbbopen-tools} \fnargs \begin{args}{object} \arg[list] A \glref{proper~list} \arg[element] An object \end{args} \fnreturns The sole element of \var{list\/} or \nil. \fnerrors \var{List\/} contains more than one element. \fndescription If \var{list\/} is a \glref{cons}, \nobr{\textbf{sole-element}} returns the \glref{car} of that \glref{cons}. If \var{list\/} is \nil, \nobr{\textbf{sole-element}} returns \nil. If \var{list\/} is a \glref{cons} and the \glref{cdr} of that \glref{cons} is not \nil, a continuable error is signaled. If you continue from the error, the first element is returned. \bfindexit{find-instances}% \bfindexit{filter-instances}% This \glref{function} is preferable to \nobr{\textbf{\glref{car}}} when you expect a list of, at most, one element. For example, this \glref{function} is often used on the results of calling \nobr{\textbf{\entlinknoex{find-instances}}} or \nobr{\textbf{\entlinknoex{filter-instances}}} when only a single \glref{unit~instance} is expected in the result list. \fnexamples % \W\supp \begin{example} > (sole-element '(a)) a > (sole-element nil) nil\goodpagebreak > (sole-element '(a b)) Error: The list (a b) contains more than 1 element. If continued - Ignore the remaining elements. >> \end{example} \fnnote \inline \end{functiondoc} %% ------------------------------------------------------------------------ \begin{functiondoc}{Function}{splitting-butlast}{\var{list\/} \nobr{\code{\&optional} \var{n\/}} \nobr{\returns{} \var{result-list, tail\/}}} \index{list!splitting into two sublists}% \index{splitting a list}% \fnsyntax \fnpurpose Return all but the last \var{n\/} elements of \var{list\/} and, as a second value, the tail containing those last \var{n\/} elements. \fnpackage \code{:gbbopen-tools} \fnmodule \code{:gbbopen-tools} \fnargs \begin{args}{result-list} \arg[list] A \glref{proper~list} or a \glref{dotted~list} \arg[n] A non-negative integer (default is \code{1}) \arg[result-list] A \glref{proper~list} \arg[tail] A \glref{proper~list} or a \glref{dotted~list} \end{args} \fnreturns Two values: \begin{tightitemize} \item a copy of \var{list\/} up to, but not including, the last \var{n\/} \glref{conses} \item the unused tail of \var{list} \end{tightitemize} \fnexamples % \W\supp \begin{example} > (splitting-butlast '(a b c d e)) (a b c d) (e) > (splitting-butlast '(a b c d e) 3) (a b) (c d e)\goodpagebreak > (splitting-butlast '(a b . c)) (a) (b . c) > \end{example} \end{functiondoc} %% ------------------------------------------------------------------------ \begin{functiondoc}{Function}{sorted-maphash}% {\var{function \nobr{hash-table} predicate\/} \nobr{\&key \var{key\/}}} \index{maphash!sorted}% \fnsyntax \fnpurpose Apply a \glref{function} once to each of the entries in a hash table according to the entry-key order determined by the \var{predicate\/} function \fnpackage \code{:gbbopen-tools} \fnmodule \code{:gbbopen-tools} \fnargs \begin{args}{hash-table} \arg[function] A \glref{function~designator} specifying a \glref{function~object} of two arguments, the key and value of the hash-table entry \arg[hash-table] A hash table \arg[predicate] A \glref{function~designator} specifying a \glref{function~object} of two arguments that returns a \glref{generalized~boolean} \arg[key] A \glref{function~designator} specifying a \glref{function~object} of one argument, or \nil{} (default is \nil) \end{args} \fndescription % For each entry in the hash table, the \var{function\/} is called with two arguments--the key and the value of that entry. The first argument to the \var{predicate\/} function is the key of one entry in the hash table (or part of that key extracted by the \var{key\/} function, if supplied); the second argument is the key of another entry in the hash table (or part of that key extracted by the \var{key\/} function, if supplied). The \var{predicate\/} function should return true if and only if the first argument is strictly less than the second; otherwise the predicate should return false. \fnexample Print a list of entries in \code{hash-table}, in ascending order of their keys (which are strings): % \W\supp \begin{example} (sorted-maphash #'(lambda (key value) (format t "~&;; key: ~s value: ~s~\%" key value) hash-table #'string<) \end{example} \end{functiondoc} %% ------------------------------------------------------------------------ \begin{functiondoc}{Macro}{sortf}{\var{place predicate\/} \nobr{\code{\&key} \var{key\/}}} \index{place!sorting sequence value of}% \fnsyntax \fnpurpose Sort the sequence value of \var{place}, and change the value of \var{place\/} to the sorted result. \fnpackage \code{:gbbopen-tools} \fnmodule \code{:gbbopen-tools} \fnargs \begin{args}{predicate} \arg[place] A \glref{form} which is suitable for use as a \glref{generalized~reference} \arg[predicate] A \glref{function~designator} specifying a \glref{function~object} of two arguments that returns a \glref{generalized~boolean} \arg[key] A \glref{function~designator} specifying a \glref{function~object} of one argument, or \nil{} (default is \nil) \end{args} \fndescription % The first argument to the \var{predicate\/} function is one element of the sequence value in \var{place\/} (or part of that element extracted by the key function, if supplied); the second argument another element of the sequence (or part of that element extracted by the \var{key\/} function, if supplied). The \var{predicate\/} function should return true if and only if the first argument is strictly less than the second; otherwise the predicate should return false. The sorting operation can be destructive, and it is not guaranteed stable. Elements considered equal by \var{predicate\/} might not stay in their original order. \begin{alsos}{stable-sortf} \also[stable-sortf] \end{alsos} \fnexample \begin{example} % \W\supp > (defparameter *x* '(1 5 3 2 4)) *x* > (sortf *x* '<) (1 2 3 4 5) > *x* (1 2 3 4 5) > \end{example} \end{functiondoc} %% ------------------------------------------------------------------------ \begin{functiondoc}{Macro}{stable-sortf}{\var{place predicate\/} \nobr{\code{\&key} \var{key\/}}} \index{place!sorting sequence value of}% \fnsyntax \fnpurpose Stably sort the sequence value of \var{place}, and change the value of \var{place\/} to the sorted result. \fnpackage \code{:gbbopen-tools} \fnmodule \code{:gbbopen-tools} \fnargs \begin{args}{predicate} \arg[place] A \glref{form} which is suitable for use as a \glref{generalized~reference} \arg[predicate] A \glref{function~designator} specifying a \glref{function~object} of two arguments that returns a \glref{generalized~boolean} \arg[key] A \glref{function~designator} specifying a \glref{function~object} of one argument, or \nil{} (default is \nil) \end{args} \fndescription % The first argument to the \var{predicate\/} function is one element of the sequence value in \var{place\/} (or part of that element extracted by the key function, if supplied); the second argument another element of the sequence (or part of that element extracted by the \var{key\/} function, if supplied). The \var{predicate\/} function should return true if and only if the first argument is strictly less than the second; otherwise the predicate should return false. The sorting operation can be destructive. Elements considered equal by \var{predicate\/} stay in their original order. \begin{alsos}{sortf} \also[sortf] \end{alsos} \fnexample \begin{example} % \W\supp > (defparameter *x* '(1 2 3 6 5 4)) *x* > (stable-sortf *x* #'(lambda (x y) (and (oddp x) (evenp y)))) (1 3 5 2 6 4) > *x* (1 3 5 2 6 4) > \end{example} \end{functiondoc} %% ------------------------------------------------------------------------ \begin{functiondoc}{Class}{standard-gbbopen-instance}{} \index{class!standard-gbbopen-instance@\textbf{standard-gbbopen-instance}}% \fnsyntax \fnpackage \code{:gbbopen-tools} \fnmodule \code{:gbbopen-tools} \fndescription The class \nobr{\textbf{standard-gbbopen-instance}} is a subclass of \nobr{\code{standard-object}}. It is a superclass of \nobr{\textbf{\entlink{deleted-unit-instance}}}, \nobr{\textbf{\entlink{standard-event-instance}}}, \nobr{\textbf{\entlink{standard-link-pointer}}}, and \nobr{\textbf{\entlink{standard-unit-instance}}}. %% and gbbopen-node-state, when documented! \begin{alsos}{standard-event-instance} \also[deleted-unit-instance] \also[print-instance-slots] \also[standard-event-instance] \also[standard-link-pointer] \also[standard-unit-instance] \end{alsos} \end{functiondoc} %% ------------------------------------------------------------------------ \begin{functiondoc}{Function}{trimmed-substring}% {\nobr{\var{character-bag string\/}} \nobr{\code{\&optional} \var{start end\/}} \nobr{\returns{} \var{trimmed-substring\/}}} \index{date!formatted}% \fnsyntax \fnpurpose Extract and trim a substring from \var{string}. \fnpackage \code{:gbbopen-tools} \fnmodule \code{:gbbopen-tools} \fnargs \begin{args}{character-bag} \arg[character-bag] A sequence containing characters \arg[string] A \glref{string~designator} \arg[start] Starting index into \var{string\/} (default is \code{0}) \arg[end] Ending index into \var{string\/} (default is \nil, meaning end of \var{string\/}) \arg[trimmed-substring] A string \end{args} \fnreturns The extracted, trimmed string \fnexamples % \W\supp \begin{example} > (trimmed-substring '(#\bkslash{}space #\bkslash{}tab) "xxx abc yyy" 3 12) "abc" > (trimmed-substring " " "xxx abc yyy" 3 12) "abc"\goodpagebreak > (trimmed-substring " " "xxx abc yyy" 3) "abc yyy"\goodpagebreak > (trimmed-substring " " "xxx abc yyy" 3 13) "abc y" > (trimmed-substring " " "xxx abc yyy" 2 12) "x abc" > (trimmed-substring " " " abc ") "abc" > \end{example} \fnnote % The function \nobr{\textbf{trimmed-substring}} is semantically equivalent to % \W\supp \begin{example} (string-trim \var{character-bag\/} (subseq \var{string start end\/})) \end{example} % but avoids allocating an intermediate substring. \end{functiondoc} %% ------------------------------------------------------------------------ \begin{functiondoc}{Macro}{undefmethod}{% \nobr{\var{function-name\/}} \nobr{\{\var{method-qualifier\/}\}\superstar{}} \nobr{\var{specialized-lambda-list\/}} \nobr{[[\var{declaration\/}\superstar{} \vbar{} \var{documentation\/}]]} \nobr{\var{form\/}\superstar}} \index{method!undefining}% \index{defmethod@\textbf{defmethod}!undoing}% \index{undefining!a method}% \fnsyntax \fnpurpose Locate and undefine a method. \fnpackage \code{:gbbopen-tools} \fnmodule \code{:gbbopen-tools} \fnargs \begin{args}{specialized-lambda-list} \arg[function-name] Either a symbol or \nobr{\code{(setf \var{symbol\/})}} \arg[method-qualifier] A non-list method qualifier object (such as \nobr{\code{:before}}, \nobr{\code{:after}}, or \nobr{\code{:around}}) \arg[specialized-lambda-list] A specialized lambda list (as per \nobr{\code{defmethod}}) \arg[declarations] A declare expression (not evaluated) \arg[documentation] A documentation string (not evaluated) \arg[forms] Zero or more \glref{forms} \end{args} \begin{alsos}{continue-patch} \also[continue-patch] \also[finish-patch] \also[patch] \also[start-patch] \end{alsos} \fnexample \bfindexit{instance-name-of}% \bfindexit{find-instance-by-name}% After creating an undesired method, use \nobr{\textbf{undefmethod}} to remove it: % \W\supp \begin{example} > (defmethod instance-name-of :before ((instance standard-unit-instance)) (print "Oops")) # > (\entlink{instance-name-of} (\entlink{find-instance-by-name} 112 'hyp)) "Oops" 112 > (undefmethod instance-name-of :before ((instance standard-unit-instance))) # > (\entlink{instance-name-of} (\entlink{find-instance-by-name} 112 'hyp)) 112 > \end{example} \fnnote % This macro may not be able to locate and undefine some methods with environment-specific eql specializers. \end{functiondoc} %% ------------------------------------------------------------------------ \begin{functiondoc}{Constant}{unbound-value-indicator}{}% \fnsyntax \fnpurpose Represent an unbound value. \fnpackage \code{:gbbopen-tools} \fnmodule \code{:gbbopen-tools} \fnvaluetype A \glref{keyword~symbol} \fnvalue \code{:-{}-{}-unbound-{}-{}-} \begin{alsos}{define-unit-class} \also[define-unit-class] \end{alsos} \fnexample Define a slot-reader \glref{function} that returns the value of \nobr{\code{my-slot}} or \nobr{\textbf{unbound-value-indicator}} if the slot is unbound: % \W\supp \begin{example} (defun safe-my-slot-of (instance) (if (slot-bound-p instance 'my-slot) (slot-value instance 'my-slot) unbound-value-indicator)) \end{example} \end{functiondoc} %% ------------------------------------------------------------------------ \begin{functiondoc}{Macro}{until}{\var{test-form\/} \nobr{\var{declaration\/}\superstar{}} \nobr{\var{form\/}\superstar}} \index{iteration!until@\textbf{until}}% \fnsyntax \fnpurpose Evaluates \nobr{\var{test-form\/}} and each \var{form\/} repeatedly, as long as \nobr{\var{test-form\/}} evaluates to \nil. \fnpackage \code{:gbbopen-tools} \fnmodule \code{:gbbopen-tools} \fnargs \begin{args}{test-form} \arg[test-form] A \glref{form} \arg[declaration] A declare expression (not evaluated) \arg[forms] An implicit \textbf{progn} of \glref{forms} to be evaluated \end{args} \begin{alsos}{do-while} \also[do-until] \also[do-while] \also[while] \end{alsos} \fnexamples % \W\supp \begin{example} > (let ((i 0)) (until (> (incf i) 3) (print i))) 1 2 3 nil\goodpagebreak > (until 't (print "No")) nil > \end{example} \end{functiondoc} %% ------------------------------------------------------------------------ \begin{functiondoc}{Macro}{while}{\var{test-form\/} \nobr{\var{declaration\/}\superstar{}} \nobr{\var{form\/}\superstar}} \index{iteration!while@\textbf{while}}% \fnsyntax \fnpurpose Evaluates \nobr{\var{test-form\/}} and each \var{form\/} repeatedly, until \nobr{\var{test-form\/}} evaluates to \nil. \fnpackage \code{:gbbopen-tools} \fnmodule \code{:gbbopen-tools} \fnargs \begin{args}{test-form} \arg[test-form] A \glref{form} \arg[declaration] A declare expression (not evaluated) \arg[forms] An implicit \textbf{progn} of \glref{forms} to be evaluated \end{args} \begin{alsos}{do-while} \also[do-until] \also[do-while] \also[until] \end{alsos} \fnexamples % \W\supp \begin{example} > (let ((i 0)) (while (<= (incf i) 3) (print i))) 1 2 3 nil\goodpagebreak > (while nil (print "No")) nil > \end{example} \end{functiondoc} %% ------------------------------------------------------------------------ \begin{functiondoc}{Macro}{with-error-handling}{% \nobr{[\var{form\/} \vbar{}} \nobr{\code{(}\var{form\/}} \nobr{[\code{(:conditions} \var{type\/}\code{)}]} \nobr{\var{handler-form\/}\superstar{}\code{)}} \nobr{\var{error-form\/}\superstar{}} \nobr{\returns{} \var{result\/}\superstar}} \index{ignoring errors}% \index{handling errors}% \index{error-condition@\textbf{error-condition}, in \textbf{with-error-handling}}% \index{error-message@\textbf{error-message}, in \textbf{with-error-handling}}% \fnsyntax \fnpurpose Evaluate each \nobr{\var{handler-form\/}} and each \nobr{\var{error-form\/}} if an error occurs while evaluating \var{form}. \fnpackage \code{:gbbopen-tools} \fnmodule \code{:gbbopen-tools} \fnargs \begin{args}{handler-forms} \arg[form] A \glref{form} \arg[type] A type specifier (default is \nobr{\code{(and error (not interrupt-signal))}} on \xsitelink{Allegro CL}{http://franz.com/products/allegrocl/}; otherwise \nobr{\code{error}}) \arg[handler-forms] Zero or more \glref{forms} \arg[error-forms] Zero or more \glref{forms} \arg[results] The values returned by evaluating \var{form}, the values returned by evaluating the last \nobr{\var{handler-form\/}} form or the last \nobr{\var{error-form\/}} form, or no values \end{args} \fnreturns The values returned by evaluating \var{form\/} unless an error occurs during that evaluation in which case: \begin{tightitemize} \item the values of evaluating the last \nobr{\var{error-form\/}} form, if specified, are returned \item otherwise, the values of evaluating the last \nobr{\var{handler-form\/}} form, if specified, are returned \item otherwise, no values are returned \end{tightitemize} \fndescription If an error occurs while evaluating \var{form}, each \nobr{\var{handler-form\/}} is evaluated in the dynamic context of the error, then the dynamic context is unwound to that in which \var{form\/} was evaluated and each \nobr{\var{error-form\/}} is evaluated. A lexical \glref{function}, \nobr{\textbf{error-message}}, is available for use within each \nobr{\var{handler-form\/}} and \nobr{\var{error-form}}. This lexical function accepts no arguments and returns a string describing the error that occurred during the evaluation of \var{form}. Another lexical \glref{function}, \nobr{\textbf{error-condition}}, is also available for use within each \nobr{\var{handler-form\/}} and nobr{\var{error-form}}. This lexical function accepts no arguments and returns the condition object that signaled the error. The conditions that are handled can be changed by using the \nobr{\code{(:conditions} \var{type\/}\code{)}} option. Unlike other Common Lisp implementations, \xsitelink{Allegro CL}{http://franz.com/products/allegrocl/} includes interrupt signals (typically generated by the user typing \nobr{\code{control-C}} characters in the REPL) as \nobr{\code{error}} conditions. Interrupt signals are excluded by default on Allegro CL. \begin{alsos}{*disable-with-error-handling*} \also[*disable-with-error-handling*] \end{alsos} \bfindexit{printv}% \fnexamples % \W\supp \begin{example} > (with-error-handling (values 1 2 3) ':error-occurred) 1 2 3 > (with-error-handling (values 1 2 (error "Bad")) ':error-occurred) :error-occurred > (with-error-handling (values 1 2 (/ 10 0)) (\entlink{printv} (error-message)) nil) ;; (error-message) => "Attempt to divide 10 by zero." nil\goodpagebreak > (defparameter *x* 0) *x* > (with-error-handling ((let ((*x* 1)) (error "A silly error has occurred.")) (\entlink{printv} "Handler form" (error-message) *x*) (values :c :b :a)) (\entlink{printv} "Error form" (error-message) *x*) (values :a :b :c)) ;; Handler form ;; (error-message) => "A silly error has occurred." ;; *x* => 1 ;; Error form ;; (error-message) => "A silly error has occurred." ;; *x* => 0 :a :b :c\goodpagebreak > (with-error-handling ((let ((*x* 1)) (error "A silly error has occurred.")) (\entlink{printv} "Handler form" (error-message) *x*) (values :c :b :a))) ; No error forms ;; Handler form ;; (error-message) => "A silly error has occurred." ;; *x* => 1 :c :b :a\goodpagebreak > (with-error-handling ;; No handler-forms: ((let ((*x* 1)) (error "A silly error has occurred."))) (\entlink{printv} "Error form" (error-message) *x*) (values :a :b :c)) ;; Error form ;; (error-message) => "A silly error has occurred." ;; *x* => 0 :a :b :c\goodpagebreak > (with-error-handling (warn "Not too bad") ':error-occurred) ;; Warning: Not too bad nil > (with-error-handling ((warn "Not too bad") (:conditions (or (and error #+allegro (not interrupt-signal)) warning))) :error-occurred) :error-occurred > \end{example} \end{functiondoc} %% ------------------------------------------------------------------------ \begin{functiondoc}{Macro}{with-full-optimization}% {\nobr{\code{(}\var{option\/}\superstar{}\code{)}} \nobr{\var{declaration\/}\superstar{}} \nobr{\var{form\/}\superstar{}} \nobr{\returns{} \var{result\/}\superstar}} \index{optimizations!declaring full}% \fnsyntax \fnpurpose Compile \var{forms\/} with \nobr{\code{(speed 3)}}, \nobr{\code{(safety 0)}}, \nobr{\code{(debug 0)}}, and \nobr{\code{(compilation-speed 0)}} optimization settings. \fnpackage \code{:gbbopen-tools} \fnmodule \code{:gbbopen-tools} \fnargs \begin{args}{options} \arg[option] No options are currently supported \arg[declaration] A declare expression (not evaluated) \arg[forms] An implicit \textbf{progn} of \glref{forms} to be evaluated \arg[results] The values returned by evaluating the last \var{form} \end{args} \fnreturns The values returned by evaluating \var{form}. \fndescription This macro provides a convenient means of declaring small code fragments for fastest (and least safe) compiler optimizations. If the \glref{feature} \nobr{\textbf{\entlinknoex{:full-safety}}} is present at compile time, this macro has no effect on optimization settings. \fnexamples Declare a \glref{function} definition, including argument checking, to be fully optimized for the fastest (and least safe) execution: % \W\supp \begin{example} (with-full-optimization () (defun extent-> (value) `(,value ,infinity))) \end{example} % Optimize the same \glref{function} definition, but this time without invocation and argument-checking optimizations: % \W\supp\notpretop \begin{example} (defun extent-> (value) (with-full-optimization () `(,value ,infinity))) \end{example} \end{functiondoc} %% ------------------------------------------------------------------------ \begin{functiondoc}{Macro}{with-generate-accessors-format}% {\nobr{(\var{format\/} [\var{prefix/suffix-name\/}])} \nobr{\var{form\/}\superstar{}} \nobr{\returns{} \var{result\/}\superstar{}}} \fnsyntax \fnpurpose Change the default for accessor names generated by \nobr{\textbf{\entlink{define-class}}}, \nobr{\textbf{\entlink{define-event-class}}}, \nobr{\textbf{\entlink{define-space-class}}}, and \nobr{\textbf{\entlink{define-unit-class}}} definitions appearing in \var{forms}. \fnpackage \code{:gbbopen-tools} \fnmodule \code{:gbbopen-tools} \fnargs \begin{args}{error-forms} \arg[format] Either the \glref{keyword} \nobr{\code{:prefix}} or \nobr{\code{:suffix}} \arg[prefix/suffix-name] One of the following (evaluated): \begin{tightitemize} \item A string \item A symbol \item A \glref{function~designator} specifying a \glref{function~object} accepting two arguments, class-name and slot-name, that returns the complete string to be used for the accessor name \end{tightitemize} \arg[forms] An implicit \textbf{progn} of \glref{forms} \arg[results] The values returned by evaluating the last \var{form} \end{args} \fnreturns The values returned by evaluating the last \var{form}. \fndescription If a \glref{function~object} \nobr{\var{prefix/suffix-name\/}} is specified, it is called to produce the complete accessor-name string, no matter which \nobr{\var{format\/}} value is provided. Otherwise, if \nobr{\code{:prefix}} is specified as the \var{format\/} value, a string or symbol \nobr{\var{prefix/suffix-name\/}} is concatenated in front of the slot name to generate the slot-accessor name. If \nobr{\code{:suffix}} is specified as the \nobr{\var{format\/}} value, a string or symbol \nobr{\var{prefix/suffix-name\/}} is concatenated after the slot name. The default \nobr{\var{prefix/suffix-name\/}} for \nobr{\code{:prefix}} is a \glref{function} that generates historical GBB-style \nobr{``\var{class-name}\code{.}\var{slot-name\/}''} slot accessors; the default for \nobr{\code{:suffix}} is \nobr{\code{'\#:-of}}. \begin{alsos}{define-space-class} \also[define-class] \also[define-event-class] \also[define-space-class] \also[define-unit-class] \end{alsos} \fnexamples Define three classes, \code{point}, \nobr{\code{circle}}, and \nobr{\code{rectangle}}, generating GBB-style \nobr{``\var{class-name}\code{.}\var{slot-name\/}''} slot accessors: % \W\supp \begin{example} > (with-generate-accessors-format (:prefix) (define-class point () (x y)) (define-class circle (point) (radius)) (define-class rectangle (point) (length width))) # > \end{example} % Re-define the classes, generating \nobr{``\var{slot-name\/}''-only} slot accessors: % \W\supp\notpretop \begin{example} > (with-generate-accessors-format (:suffix "") (define-class point () (x y)) (define-class circle (point) (radius)) (define-class rectangle (point) (length width))) # > \end{example} % Re-define the classes, generating ``\var{slot-name}\code{-of-}\var{class-name}'' slot accessors (note that the \nobr{\code{strange-name-string}} name-generation \glref{function} must be available at compile time): % \W\supp\notpretop \begin{example} > (eval-when (:compile-toplevel :load-toplevel :execute) (defun strange-name-string (class-name slot-name) (concatenate 'simple-string (symbol-name class-name) "-" (symbol-name '#:of) "-" (symbol-name slot-name)))) strange-name-string > (with-generate-accessors-format (:prefix (symbol-function 'strange-name-string)) (define-class point () (x y)) (define-class circle (point) (radius)) (define-class rectangle (point) (length width))) # > \end{example} \end{functiondoc} %% ------------------------------------------------------------------------ \begin{functiondoc}{Macro}{with-gensyms}{% \nobr{(\var{symbol\/}\superstar{})} \nobr{\var{declaration\/}\superstar{}} \nobr{\var{form\/}\superstar{}} \nobr{\returns{} \var{result\/}\superstar{}}} \fnsyntax \fnpurpose Bind each \var{symbol\/} to a gensym symbol. \fnpackage \code{:gbbopen-tools} \fnmodule \code{:gbbopen-tools} \fnargs \begin{args}{error-forms} \arg[symbols] Zero or more symbols to be bound to gensyms \arg[declaration] A declare expression (not evaluated) \arg[forms] An implicit \textbf{progn} of \glref{forms} to be evaluated \arg[results] The values returned by evaluating the last \var{form} \end{args} \fnreturns The values returned by evaluating the last \var{form}. \fnexamples % \W\supp \begin{example} > (pprint (macroexpand '(with-gensyms (a b) (form)))) (let ((a (gensym)) (b (gensym))) (form)) > \end{example} \end{functiondoc} %% ------------------------------------------------------------------------ \begin{functiondoc}{Macro}{with-once-only-bindings}{% \nobr{(\var{symbol\/}\superstar{})} \nobr{\var{declaration\/}\superstar{}} \nobr{\var{form\/}\superstar{}} \nobr{\returns{} \var{result\/}\superstar{}}} \fnsyntax \fnpurpose Evaluate, in order, each \nobr{\var{symbol\/}} and then make every reference to \nobr{\var{symbol\/}} inside each \var{form\/} refer to that value. \fnpackage \code{:gbbopen-tools} \fnmodule \code{:gbbopen-tools} \fnargs \begin{args}{error-forms} \arg[symbols] Zero or more symbols to be evaluated once only \arg[declaration] A declare expression (not evaluated) \arg[forms] An implicit \textbf{progn} of \glref{forms} to be evaluated \arg[results] The values returned by evaluating the last \var{form} \end{args} \fnreturns The values returned by evaluating the last \var{form}. \fndescription This is GBBopen's version of the ``once-only'' macro-writing macro that ensures that the forms associated with macro arguments are only evaluated once and in the specified order. \bfindexit{ensure-list}% \fnexample % \W\supp \begin{example} (define-compiler-macro \entlink{ensure-list} (x) (with-once-only-bindings (x) `(if (listp ,x) ,x (list ,x)))) \end{example} \end{functiondoc} %% ------------------------------------------------------------------------ \begin{functiondoc}{Function}{xor}{\nobr{\code{\&rest} \var{args\/}} \nobr{\returns{} \var{boolean\/}}} \fnsyntax \fnpurpose Return the exclusive or (XOR) of zero or more arguments. \fnpackage \code{:gbbopen-tools} \fnmodule \code{:gbbopen-tools} \fnargs \begin{args}{boolean} \arg[arg] A \glref{generalized~boolean} (an object) \arg[boolean] A \glref{generalized~boolean} \end{args} \fnreturns True if there are an even odd number of true arguments; \nil{} otherwise. \fnexamples % \W\supp \begin{example} > (xor) nil > (xor nil nil) nil > (xor 't 't) nil\goodpagebreak > (xor nil 't) t > (xor 't nil) t > (xor nil 't nil 't 't nil) t > \end{example} \end{functiondoc} %% ------------------------------------------------------------------------ % Set subsubentities indicator \W\renewcommand{\subsubentities}{1} \T\markright{}% \T\pagestyle{plain} \T\clearpage \W\xname{ref-clos-and-mop-entities} \T\pagestyle{fancy} \T\thispagestyle{fancybottom} \T\global\def\fnlastname{ }% \subsection{CLOS and MOP} \label{sec:CLOS}% \index{CLOS entities}% \index{MOP entities}% \codeindexit{accessor-method-slot-definition}% \codeindexit{add-dependent}% \codeindexit{add-direct-method}% \codeindexit{add-direct-subclass}% \codeindexit{class-default-initargs}% \codeindexit{class-direct-default-initargs}% \codeindexit{class-direct-slots}% \codeindexit{class-direct-subclasses}% \codeindexit{class-direct-superclasses}% \codeindexit{class-finalized-p}% \codeindexit{class-precedence-list}% \codeindexit{class-prototype}% \codeindexit{class-slots}% \codeindexit{compute-applicable-methods-using-classes}% \codeindexit{compute-class-precedence-list}% \codeindexit{compute-default-initargs}% \codeindexit{compute-discriminating-function}% \codeindexit{compute-effective-method}% \codeindexit{compute-effective-slot-definition}% \codeindexit{compute-slots}% \codeindexit{direct-slot-definition}% \codeindexit{direct-slot-definition-class}% \codeindexit{effective-slot-definition}% \codeindexit{effective-slot-definition-class}% \codeindexit{ensure-class}% \codeindexit{ensure-class-using-class}% \codeindexit{ensure-generic-function-using-class}% \codeindexit{eql-specializer}% \codeindexit{eql-specializer-object}% \codeindexit{extract-lambda-list}% \codeindexit{extract-specializer-names}% \codeindexit{finalize-inheritance}% \codeindexit{find-method-combination}% \codeindexit{forward-referenced-class}% \codeindexit{funcallable-standard-class}% \codeindexit{funcallable-standard-instance-access}% \codeindexit{funcallable-standard-object}% \codeindexit{generic-function-argument-precedence-order}% \codeindexit{generic-function-declarations}% \codeindexit{generic-function-lambda-list}% \codeindexit{generic-function-method-class}% \codeindexit{generic-function-method-combination}% \codeindexit{generic-function-methods}% \codeindexit{generic-function-name}% \codeindexit{intern-eql-specializer}% \codeindexit{make-method-lambda}% \codeindexit{map-dependents}% \codeindexit{metaobject}% \codeindexit{method-function}% \codeindexit{method-generic-function}% \codeindexit{method-lambda-list}% \codeindexit{method-specializers}% \codeindexit{reader-method-class}% \codeindexit{remove-dependent}% \codeindexit{remove-direct-method}% \codeindexit{remove-direct-subclass}% \codeindexit{set-funcallable-instance-function}% \codeindexit{slot-boundp-using-class}% \codeindexit{slot-definition}% \codeindexit{slot-definition-allocation}% \codeindexit{slot-definition-initargs}% \codeindexit{slot-definition-initform}% \codeindexit{slot-definition-initfunction}% \codeindexit{slot-definition-location}% \codeindexit{slot-definition-name}% \codeindexit{slot-definition-readers}% \codeindexit{slot-definition-type}% \codeindexit{slot-definition-writers}% \codeindexit{slot-makunbound-using-class}% \codeindexit{slot-value-using-class}% \codeindexit{specializer}% \codeindexit{specializer-direct-generic-functions}% \codeindexit{specializer-direct-methods}% \codeindexit{standard-accessor-method}% \codeindexit{standard-direct-slot-definition}% \codeindexit{standard-effective-slot-definition}% \codeindexit{standard-instance-access}% \codeindexit{standard-reader-method}% \codeindexit{standard-slot-definition}% \codeindexit{standard-writer-method}% \codeindexit{update-dependent}% \codeindexit{validate-superclass}% \codeindexit{writer-method-class}% % The GBBopen Tools \glref{module} imports commonly used CLOS and MOP symbols into the \nobr{\code{:gbbopen-tools}} package and then exports them, making it easy to use CLOS and MOP entities (without worrying about each Common Lisp implementation's package structure) by simply using the \nobr{\code{:gbbopen-tools}} package. The following CLOS and MOP symbols are exported by \nobr{\code{:gbbopen-tools}}: % \T\\[3pt] \W\supp\tabletop \T\begin{longtable}[l]{@{}l@{}l@{}} \W\begin{tabular}{@{}l@{}l@{}} ~~~~~ & \code{accessor-method-slot-definition} \\ & \code{add-dependent} \\ & \code{add-direct-method} \\ & \code{add-direct-subclass} \\ & \code{class-default-initargs} \\ & \code{class-direct-default-initargs} \\ & \code{class-direct-slots} \\ & \code{class-direct-subclasses} \\ & \code{class-direct-superclasses} \\ & \code{class-finalized-p} \\ & \code{class-precedence-list} \\ & \code{class-prototype} \\ & \code{class-slots} \\ & \code{compute-applicable-methods-using-classes} \\ & \code{compute-class-precedence-list} \\ & \code{compute-default-initargs} \\ & \code{compute-discriminating-function} \\ & \code{compute-effective-method} \\ & \code{compute-effective-slot-definition} \\ & \code{compute-slots} \\ \goodpagebreak & \code{direct-slot-definition} \\ & \code{direct-slot-definition-class} \\ & \code{effective-slot-definition} \\ & \code{effective-slot-definition-class} \\ & \code{ensure-class} \\ & \code{ensure-class-using-class} \\ & \code{ensure-generic-function-using-class} \\ & \code{eql-specializer} \\ & \code{eql-specializer-object} \\ & \code{extract-lambda-list} \\ & \code{extract-specializer-names} \\ \goodpagebreak & \code{finalize-inheritance} \\ & \code{find-method-combination} \\ & \code{forward-referenced-class} \\ & \code{funcallable-standard-class} \\ & \code{funcallable-standard-instance-access} \\ & \code{funcallable-standard-object} \\ \goodpagebreak & \code{generic-function-argument-precedence-order} \\ & \code{generic-function-declarations} \\ & \code{generic-function-lambda-list} \\ & \code{generic-function-method-class} \\ & \code{generic-function-method-combination} \\ & \code{generic-function-methods} \\ & \code{generic-function-name} \\ \goodpagebreak & \code{intern-eql-specializer} \\ & \code{make-method-lambda} \\ & \code{map-dependents} \\ & \code{metaobject} \\ & \code{method-function} \\ & \code{method-generic-function} \\ & \code{method-lambda-list} \\ & \code{method-specializers} \\ \goodpagebreak & \code{reader-method-class} \\ & \code{remove-dependent} \\ & \code{remove-direct-method} \\ & \code{remove-direct-subclass} \\ \goodpagebreak & \code{set-funcallable-instance-function} \\ & \code{slot-boundp-using-class} \\ & \code{slot-definition} \\ & \code{slot-definition-allocation} \\ & \code{slot-definition-initargs} \\ & \code{slot-definition-initform} \\ & \code{slot-definition-initfunction} \\ & \code{slot-definition-location} \\ & \code{slot-definition-name} \\ & \code{slot-definition-readers} \\ & \code{slot-definition-type} \\ & \code{slot-definition-writers} \\ & \code{slot-makunbound-using-class} \\ & \code{slot-value-using-class} \\ \goodpagebreak & \code{specializer} \\ & \code{specializer-direct-generic-functions} \\ & \code{specializer-direct-methods} \\ \goodpagebreak & \code{standard-accessor-method} \\ & \code{standard-direct-slot-definition} \\ & \code{standard-effective-slot-definition} \\ & \code{standard-instance-access} \\ & \code{standard-reader-method} \\ & \code{standard-slot-definition} \\ & \code{standard-writer-method} \\ & \code{update-dependent} \\ & \code{validate-superclass} \\ & \code{writer-method-class} \\ \T\end{longtable} \W\end{tabular} % Load-time warning messages are displayed if the Common Lisp implementation does not have one of these symbols in its CLOS or MOP implementation. %% ------------------------------------------------------------------------ \T\markright{}% \T\pagestyle{plain} \T\clearpage \W\xname{ref-declared-numerics} \T\pagestyle{fancy} \T\thispagestyle{fancybottom} \T\global\def\fnlastname{ }% \subsection{Declared Numerics} \label{sec:declared-numerics}% \label{ent:incfAMP}% \index{declared-numeric operators}% \index{fixnum!declared-numeric operators}% \index{single-float!declared-numeric operators}% \index{double-float!declared-numeric operators}% \index{module!:gbbopen-tools@\code{:gbbopen-tools}|itidx}% \index{:gbbopen-tools@\code{:gbbopen-tools} module|itidx}% % The \code{:gbbopen-tools} \glref{module} contains a set of declared-numeric and \reflink{pseudo probability}{sec:pprob} operators that provide convenient shorthands for declaring \code{\nobr{\glref{fixnum}}}, \nobr{\code{short-float}}, \nobr{\code{single-float}}, \nobr{\code{double-float}}, \nobr{\code{long-float}}, and \nobr{\code{pseudo-probability}} numeric operations. If the \glref{feature} \nobr{\textbf{\entlinknoex{:full-safety}}} is present at compile time, these operators do not make their \nobr{\code{fixnum}}, \nobr{\code{single-float}}, \nobr{\code{double-float}}, and \nobr{\code{long-float}} declarations. The names of the declared-numeric and \glref{pseudo-probability} operators include these ``type-indicator'' characters: % \T\\[3pt] \W\supp\tabletop \begin{tabular}{@{}l@{}l@{}l@{}l@{}} ~~~~~ & \textbf{Characters} & ~~~~~ & \textbf{Declared Type} \\ & \code{\&} & & \code{fixnum} \\ & \code{\$\&} & & \code{short-float} \\ & \code{\$} & & \code{single-float} \\ & \code{\$\$} & & \code{double-float} \\ & \code{\$\$\$} & & \code{long-float} \\ & \code{\%} & & \code{pseudo-probability} \\ \end{tabular} Thus, the declared-numeric \code{+} operators are: % \T\\[3pt] \W\supp\tabletop \begin{tabular}{@{}l@{}l@{}l@{}l@{}} ~~~~~ & \code{+\&} & ~~~~~ & \code{fixnum} addition \\ & \code{+\$\&} & & \code{short-float} addition \\ & \code{+\$} & & \code{single-float} addition \\ & \code{+\$\$} & & \code{double-float} addition \\ & \code{+\$\$\$} & & \code{long-float} addition \\ & \code{+\%} & & \code{pseudo-probability} addition \\ \end{tabular} \index{floating-point type declarations!Common Lisp implementation notes}% \index{floating-point formats!IEEE 754}% \index{single format!IEEE 754}% \index{double format!IEEE 754}% \index{IEEE 754 floating-point formats}% \index{Macintosh Common Lisp!floating-point type declarations}% \codeindexqual{:has-short-float}{feature}% \codeindexqual{:has-single-float}{feature}% \codeindexqual{:has-double-float}{feature}% \codeindexqual{:has-long-float}{feature}% Most Common Lisp implementations map double-float numbers to the 64-bit \xsitelink{IEEE 754}{http://www.psc.edu/general/software/packages/ieee/ieee.html} double format and single-float numbers to the 32-bit \xsitelink{IEEE 754}{http://www.psc.edu/general/software/packages/ieee/ieee.html} single format. The four types of floating-point declared numeric operators (\nobr{\code{short-float}}, \nobr{\code{single-float}}, \nobr{\code{double-float}}, and \nobr{\code{long-float}}) are always defined, even if the Common Lisp implementation provides fewer distinct internal \code{float} representations. The features \nobr{\code{:has-short-float}}, \nobr{\code{:has-single-float}}, \nobr{\code{:has-double-float}}, and \nobr{\code{:has-long-float}} are added when the implementation provides that distinct internal \code{float} representation. (The feature \nobr{\code{:has-single-float}} is always defined.) \codeindexqual{:fixnum-size-below-29}{feature}% \codeindexqual{:fixnum-size-supports-unsigned-byte-32}{feature}% The following two features related to \code{fixnum} capabilities are defined when appropriate: \nobr{\code{:fixnum-size-below-29}} and \nobr{\code{:fixnum-size-supports-unsigned-byte-32}}. Some examples of declared-numeric operators include: % \W\supp \begin{example} (\& x) \expands (the fixnum x) (+\& x y) \expands (the fixnum (+ (the fixnum x) (the fixnum y)) (>\$ a b) \expands (> (the single-float a) (the single-float b)) (minusp$$ value) \expands (minusp (the double-float value)) (truncate\& x y)) \expands (the (values fixnum fixnum) (truncate (\& x) (\& y))) \end{example} % The complete set of operators for each declared numeric type are listed in the following sections. (Pseudo probability operators are listed in the \reflink{Pseudo Probabilities section}{sec:pprob} of the manual.) \T\clearpage \W\xname{ref-fixnum-operators} \subsubsection{Fixnum operators} \bfindex{\&}% \bfindex{/\&}% \bfindex{$*$\&}% \bfindex{+\&}% \bfindex{-\&}% \bfindex{/=\&}% \bfindex{1+\&}% \bfindex{1-\&}% \bfindex{$<$\&}% \bfindex{$<$=\&}% \bfindex{=\&}% \bfindex{$>$\&}% \bfindex{$>$=\&}% \bfindexit{bounded-value\&}% \bfindex{ceiling\&}% \bfindex{decf\&}% \bfindex{decf\&-after}% \bfindexit{decf/delete\&-acons}% \bfindex{evenp\&}% \bfindex{fceiling\&}% \bfindex{ffloor\&}% \bfindex{floor\&}% \bfindex{fround\&}% \bfindex{ftruncate\&}% \bfindex{incf\&}% \bfindex{incf\&-after}% \bfindexit{pushnew/incf\&-acons}% \bfindex{max\&}% \bfindex{min\&}% \bfindex{minusp\&}% \bfindex{abs\&}% \bfindex{mod\&}% \bfindex{oddp\&}% \bfindex{plusp\&}% \bfindex{round\&}% \bfindex{truncate\&}% \bfindex{zerop\&}% % These \code{\glref{fixnum}} declared-numeric operators are defined in the \nobr{\code{:gbbopen-tools}} \glref{module}: % \T\\[6pt] \W\supp\tabletop \begin{tabular}{@{}l@{}l@{}l@{}l@{}l@{}l@{}} ~~~~~ & \textbf{Operator} & ~~~~~ & \textbf{Operation} & ~~~~~ & \textbf{Example} \\ \hline & \code{\&} & & \code{the fixnum} & & \code{(\& x)}\\ & \code{+\&} & & \code{+} & & \code{(+\& x y z)}\\ & \code{-\&} & & \code{-} & & \code{(-\& x y z)}\\ & \code{1+\&} & & \code{1+} & & \code{(1+\& x)}\\ & \code{1-\&} & & \code{1-} & & \code{(1-\& x)}\\ & \code{*\&} & & \code{*} & & \code{(*\& x y z)}\\ & \code{/\&} & & \code{/} & & \code{(/\& x y z)}\\ & \code{=\&} & & \code{=} & & \code{(=\& x y z)}\\ & \code{/=\&} & & \code{/=} & & \code{(/=\& x y z)}\\ & \code{<\&} & & \code{<} & & \code{(<\& x y z)}\\ & \code{<=\&} & & \code{<=} & & \code{(<=\& x y z)}\\ & \code{>\&} & & \code{>} & & \code{(>\& x y z)}\\ & \code{>=\&} & & \code{>=} & & \code{(>=\& x y z)}\\ & \code{abs\&} & & \code{abs} & & \code{(abs\& x)}\\ & \code{bounded-value\&} & & \code{\entlink{bounded-value}} & & \code{(bounded-value\& x y z)}\\ & \code{ceiling\&} & & \code{ceiling} & & \code{(ceiling\& x divisor)}\\ & \code{decf\&} & & \code{decf} & & \code{(decf\& x delta)}\\ & \code{decf-\&after} & & \code{\entlink{decf-after}} & & \code{(decf\&-after x delta)}\\ & \code{decf/delete\&-acons} & & \code{\entlink{decf/delete-acons}} & & \code{(decf/delete\&-acons}\\ & & & & & ~~~ \code{x delta alist)}\\ & \code{evenp\&} & & \code{evenp} & & \code{(evenp\& x)}\\ & \code{fceiling\&} & & \code{fceiling} & & \code{(fceiling\& x divisor)}\\ & \code{floor\&} & & \code{floor} & & \code{(floor\& x divisor)}\\ & \code{ffloor\&} & & \code{ffloor} & & \code{(ffloor\& x divisor)}\\ & \code{fround\&} & & \code{fround} & & \code{(fround\& x divisor)}\\ & \code{ftruncate\&} & & \code{ftruncate} & & \code{(ftruncate\& x divisor)}\\ & \code{incf\&} & & \code{incf} & & \code{(incf\& x delta)}\\ & \code{incf\&-after} & & \code{\entlink{incf-after}} & & \code{(incf\&-after x delta)}\\ & \code{max\&} & & \code{max} & & \code{(max\& x y z)}\\ & \code{min\&} & & \code{min} & & \code{(min\& x y z)}\\ & \code{minusp\&} & & \code{minusp} & & \code{(minusp\& x)}\\ & \code{mod\&} & & \code{mod} & & \code{(mod\& x divisor)}\\ & \code{oddp\&} & & \code{oddp} & & \code{(oddp\& x)}\\ & \code{plusp\&} & & \code{plusp} & & \code{(plusp\& x)}\\ & \code{pushnew/incf\&-acons} & & \code{\entlink{pushnew/incf-acons}} & & \code{(pushnew/incf\&-acons}\\ & & & & & ~~~ \code{'x delta alist)}\\ & \code{round\&} & & \code{round} & & \code{(round\& x divisor)}\\ & \code{truncate\&} & & \code{truncate} & & \code{(truncate\& x divisor)}\\ & \code{zerop\&} & & \code{zerop} & & \code{(zerop\& x)} \\[2pt] \hline \end{tabular} \T\medskip \bfindex{coerce\&}% The one-argument \glref{function} \nobr{\textbf{coerce\&}} provides convenient \nobr{\code{\glref{fixnum}}} coercion: % \W\supp \begin{example} (setf x (coerce& x)) \end{example} % Although \nobr{\code{(coerce x 'fixnum)}} is not permitted in Common Lisp, \nobr{\code{(coerce\& x)}} is equivalent to \nobr{\code{(truncate x)}} when the remainder is zero and the returned quotient is a \nobr{\code{\glref{fixnum}}}. Otherwise, \nobr{\code{(coerce\& x)}} signals an error. \T\clearpage \W\xname{ref-short-float-operators} \subsubsection{Short-float operators} \bfindex{\$\&}% \bfindex{/\$\&}% \bfindex{$*$\$\&}% \bfindex{+\$\&}% \bfindex{-\$\&}% \bfindex{/=\$\&}% \bfindex{1+\$\&}% \bfindex{1-\$\&}% \bfindex{$<$\$\&}% \bfindex{$<$=\$\&}% \bfindex{=\$\&}% \bfindex{$>$\$\&}% \bfindex{$>$=\$\&}% \bfindexit{bounded-value\$\&}% \bfindex{ceiling\$\&}% \bfindex{decf\$\&}% \bfindex{decf\$\&-after}% \bfindexit{decf/delete\$\&-acons}% \bfindex{evenp\$\&}% \bfindex{fceiling\$\&}% \bfindex{ffloor\$\&}% \bfindex{floor\$\&}% \bfindex{fround\$\&}% \bfindex{ftruncate\$\&}% \bfindex{incf\$\&}% \bfindex{incf\$\&-after}% \bfindexit{pushnew/incf\$\&-acons}% \bfindex{max\$\&}% \bfindex{min\$\&}% \bfindex{minusp\$\&}% \bfindex{abs\$\&}% \bfindex{mod\$\&}% \bfindex{oddp\$\&}% \bfindex{plusp\$\&}% \bfindex{round\$\&}% \bfindex{truncate\$\&}% \bfindex{zerop\$\&}% % These \code{short-float} declared-numeric operators are defined in the \nobr{\code{:gbbopen-tools}} \glref{module}: % \T\\[6pt] \W\supp\tabletop \begin{tabular}{@{}l@{}l@{}l@{}l@{}l@{}l@{}} ~~~~~ & \textbf{Operator} & ~~~~~ & \textbf{Operation} & ~~~~~ & \textbf{Example} \\ \hline & \code{\$\&} & & \code{the short-float} & & \code{(\$\& x)}\\ & \code{+\$\&} & & \code{+} & & \code{(+\$\& x y z)}\\ & \code{-\$\&} & & \code{-} & & \code{(-\$\& x y z)}\\ & \code{1+\$\&} & & \code{1+} & & \code{(1+\$\& x)}\\ & \code{1-\$\&} & & \code{1-} & & \code{(1-\$\& x)}\\ & \code{*\$\&} & & \code{*} & & \code{(*\$\& x y z)}\\ & \code{/\$\&} & & \code{/} & & \code{(/\$\& x y z)}\\ & \code{=\$\&} & & \code{=} & & \code{(=\$\& x y z)}\\ & \code{/=\$\&} & & \code{/=} & & \code{(/=\$\& x y z)}\\ & \code{<\$\&} & & \code{<} & & \code{(<\$\& x y z)}\\ & \code{<=\$\&} & & \code{<=} & & \code{(<=\$\& x y z)}\\ & \code{>\$\&} & & \code{>} & & \code{(>\$\& x y z)}\\ & \code{>=\$\&} & & \code{>=} & & \code{(>=\$\& x y z)}\\ & \code{abs\$\&} & & \code{abs} & & \code{(abs\$\& x)}\\ & \code{bounded-value\$\&} & & \code{\entlink{bounded-value}} & & \code{(bounded-value\$\& x y z)}\\ & \code{ceiling\$\&} & & \code{ceiling} & & \code{(ceiling\$\& x divisor)}\\ & \code{decf\$\&} & & \code{decf} & & \code{(decf\$\& x delta)}\\ & \code{decf-\$\&after} & & \code{\entlink{decf-after}} & & \code{(decf\$\&-after x delta)}\\ & \code{decf/delete\$\&-acons} & & \code{\entlink{decf/delete-acons}} & & \code{(decf/delete\$\&-acons}\\ & & & & & ~~~ \code{x delta alist)}\\ & \code{evenp\$\&} & & \code{evenp} & & \code{(evenp\$\& x)}\\ & \code{fceiling\$\&} & & \code{fceiling} & & \code{(fceiling\$\& x divisor)}\\ & \code{floor\$\&} & & \code{floor} & & \code{(floor\$\& x divisor)}\\ & \code{ffloor\$\&} & & \code{ffloor} & & \code{(ffloor\$\& x divisor)}\\ & \code{fround\$\&} & & \code{fround} & & \code{(fround\$\& x divisor)}\\ & \code{ftruncate\$\&} & & \code{ftruncate} & & \code{(ftruncate\$\& x divisor)}\\ & \code{incf\$\&} & & \code{incf} & & \code{(incf\$\& x delta)}\\ & \code{incf\$\&-after} & & \code{\entlink{incf-after}} & & \code{(incf\$\&-after x delta)}\\ & \code{max\$\&} & & \code{max} & & \code{(max\$\& x y z)}\\ & \code{min\$\&} & & \code{min} & & \code{(min\$\& x y z)}\\ & \code{minusp\$\&} & & \code{minusp} & & \code{(minusp\$\& x)}\\ & \code{mod\$\&} & & \code{mod} & & \code{(mod\$\& x divisor)}\\ & \code{oddp\$\&} & & \code{oddp} & & \code{(oddp\$\& x)}\\ & \code{plusp\$\&} & & \code{plusp} & & \code{(plusp\$\& x)}\\ & \code{pushnew/incf\$\&-acons} & & \code{\entlink{pushnew/incf-acons}} & & \code{(pushnew/incf\$\&-acons}\\ & & & & & ~~~ \code{'x delta alist)}\\ & \code{round\$\&} & & \code{round} & & \code{(round\$\& x divisor)}\\ & \code{truncate\$\&} & & \code{truncate} & & \code{(truncate\$\& x divisor)}\\ & \code{zerop\$\&} & & \code{zerop} & & \code{(zerop\$\& x)} \\[2pt] \hline \end{tabular} \T\medskip \bfindex{coerce\$\&}% The one-argument \glref{function} \nobr{\textbf{coerce\$\&}} provides convenient \nobr{\code{short-float}} coercion: % \W\supp \begin{example} (setf x (coerce\$& x)) \end{example} \T\clearpage \W\xname{ref-single-float-operators} \subsubsection{Single-float operators} \bfindex{\$}% \bfindex{/\$}% \bfindex{$*$\$}% \bfindex{+\$}% \bfindex{-\$}% \bfindex{/=\$}% \bfindex{1+\$}% \bfindex{1-\$}% \bfindex{$<$\$}% \bfindex{$<$=\$}% \bfindex{=\$}% \bfindex{$>$\$}% \bfindex{$>$=\$}% \bfindexit{bounded-value\$}% \bfindex{ceiling\$}% \bfindex{decf\$}% \bfindex{decf\$-after}% \bfindexit{decf/delete\$-acons}% \bfindex{evenp\$}% \bfindex{fceiling\$}% \bfindex{ffloor\$}% \bfindex{floor\$}% \bfindex{fround\$}% \bfindex{ftruncate\$}% \bfindex{incf\$}% \bfindex{incf\$-after}% \bfindexit{pushnew/incf\$-acons}% \bfindex{max\$}% \bfindex{min\$}% \bfindex{minusp\$}% \bfindex{abs\$}% \bfindex{mod\$}% \bfindex{oddp\$}% \bfindex{plusp\$}% \bfindex{round\$}% \bfindex{truncate\$}% \bfindex{zerop\$}% % These \code{single-float} declared-numeric operators are defined in the \nobr{\code{:gbbopen-tools}} \glref{module}: % \T\\[6pt] \W\supp\tabletop \begin{tabular}{@{}l@{}l@{}l@{}l@{}l@{}l@{}} ~~~~~ & \textbf{Operator} & ~~~~~ & \textbf{Operation} & ~~~~~ & \textbf{Example} \\ \hline & \code{\$} & & \code{the single-float} & & \code{(\$ x)}\\ & \code{+\$} & & \code{+} & & \code{(+\$ x y z)}\\ & \code{-\$} & & \code{-} & & \code{(-\$ x y z)}\\ & \code{1+\$} & & \code{1+} & & \code{(1+\$ x)}\\ & \code{1-\$} & & \code{1-} & & \code{(1-\$ x)}\\ & \code{*\$} & & \code{*} & & \code{(*\$ x y z)}\\ & \code{/\$} & & \code{/} & & \code{(/\$ x y z)}\\ & \code{=\$} & & \code{=} & & \code{(=\$ x y z)}\\ & \code{/=\$} & & \code{/=} & & \code{(/=\$ x y z)}\\ & \code{<\$} & & \code{<} & & \code{(<\$ x y z)}\\ & \code{<=\$} & & \code{<=} & & \code{(<=\$ x y z)}\\ & \code{>\$} & & \code{>} & & \code{(>\$ x y z)}\\ & \code{>=\$} & & \code{>=} & & \code{(>=\$ x y z)}\\ & \code{abs\$} & & \code{abs} & & \code{(abs\$ x)}\\ & \code{bounded-value\$} & & \code{\entlink{bounded-value}} & & \code{(bounded-value\$ x y z)}\\ & \code{ceiling\$} & & \code{ceiling} & & \code{(ceiling\$ x divisor)}\\ & \code{decf\$} & & \code{decf} & & \code{(decf\$ x delta)}\\ & \code{decf-\$after} & & \code{\entlink{decf-after}} & & \code{(decf\$-after x delta)}\\ & \code{decf/delete\$-acons} & & \code{\entlink{decf/delete-acons}} & & \code{(decf/delete\$-acons}\\ & & & & & ~~~ \code{x delta alist)}\\ & \code{evenp\$} & & \code{evenp} & & \code{(evenp\$ x)}\\ & \code{fceiling\$} & & \code{fceiling} & & \code{(fceiling\$ x divisor)}\\ & \code{floor\$} & & \code{floor} & & \code{(floor\$ x divisor)}\\ & \code{ffloor\$} & & \code{ffloor} & & \code{(ffloor\$ x divisor)}\\ & \code{fround\$} & & \code{fround} & & \code{(fround\$ x divisor)}\\ & \code{ftruncate\$} & & \code{ftruncate} & & \code{(ftruncate\$ x divisor)}\\ & \code{incf\$} & & \code{incf} & & \code{(incf\$ x delta)}\\ & \code{incf\$-after} & & \code{\entlink{incf-after}} & & \code{(incf\$-after x delta)}\\ & \code{max\$} & & \code{max} & & \code{(max\$ x y z)}\\ & \code{min\$} & & \code{min} & & \code{(min\$ x y z)}\\ & \code{minusp\$} & & \code{minusp} & & \code{(minusp\$ x)}\\ & \code{mod\$} & & \code{mod} & & \code{(mod\$ x divisor)}\\ & \code{oddp\$} & & \code{oddp} & & \code{(oddp\$ x)}\\ & \code{plusp\$} & & \code{plusp} & & \code{(plusp\$ x)}\\ & \code{pushnew/incf\$-acons} & & \code{\entlink{pushnew/incf-acons}} & & \code{(pushnew/incf\$-acons}\\ & & & & & ~~~ \code{'x delta alist)}\\ & \code{round\$} & & \code{round} & & \code{(round\$ x divisor)}\\ & \code{truncate\$} & & \code{truncate} & & \code{(truncate\$ x divisor)}\\ & \code{zerop\$} & & \code{zerop} & & \code{(zerop\$ x)} \\[2pt] \hline \end{tabular} \T\medskip \bfindex{coerce\$}% The one-argument \glref{function} \nobr{\textbf{coerce\$}} provides convenient \nobr{\code{single-float}} coercion: % \W\supp \begin{example} (setf x (coerce\$ x)) \end{example} \T\clearpage \W\xname{ref-double-float-operators} \subsubsection{Double-float operators} \bfindex{\$\$}% \bfindex{/\$\$}% \bfindex{$*$\$\$}% \bfindex{+\$\$}% \bfindex{-\$\$}% \bfindex{/=\$\$}% \bfindex{1+\$\$}% \bfindex{1-\$\$}% \bfindex{$<$\$\$}% \bfindex{$<$=\$\$}% \bfindex{=\$\$}% \bfindex{$>$\$\$}% \bfindex{$>$=\$\$}% \bfindexit{bounded-value\$\$}% \bfindex{ceiling\$\$}% \bfindex{decf\$\$}% \bfindex{decf\$\$-after}% \bfindexit{decf/delete\$\$-acons}% \bfindex{evenp\$\$}% \bfindex{fceiling\$\$}% \bfindex{ffloor\$\$}% \bfindex{floor\$\$}% \bfindex{fround\$\$}% \bfindex{ftruncate\$\$}% \bfindex{incf\$\$}% \bfindex{incf\$\$-after}% \bfindexit{pushnew/incf\$\$-acons}% \bfindex{max\$\$}% \bfindex{min\$\$}% \bfindex{minusp\$\$}% \bfindex{abs\$\$}% \bfindex{mod\$\$}% \bfindex{oddp\$\$}% \bfindex{plusp\$\$}% \bfindex{round\$\$}% \bfindex{truncate\$\$}% \bfindex{zerop\$\$}% % These \code{double-float} declared-numeric operators are defined in the \nobr{\code{:gbbopen-tools}} \glref{module}: % \T\\[6pt] \W\supp\tabletop \begin{tabular}{@{}l@{}l@{}l@{}l@{}l@{}l@{}} ~~~~~ & \textbf{Operator} & ~~~~~ & \textbf{Operation} & ~~~~~ & \textbf{Example} \\ \hline & \code{\$\$} & & \code{the double-float} & & \code{(\$\$ x)}\\ & \code{+\$\$} & & \code{+} & & \code{(+\$\$ x y z)}\\ & \code{-\$\$} & & \code{-} & & \code{(-\$\$ x y z)}\\ & \code{1+\$\$} & & \code{1+} & & \code{(1+\$\$ x)}\\ & \code{1-\$\$} & & \code{1-} & & \code{(1-\$\$ x)}\\ & \code{*\$\$} & & \code{*} & & \code{(*\$\$ x y z)}\\ & \code{/\$\$} & & \code{/} & & \code{(/\$\$ x y z)}\\ & \code{=\$\$} & & \code{=} & & \code{(=\$\$ x y z)}\\ & \code{/=\$\$} & & \code{/=} & & \code{(/=\$\$ x y z)}\\ & \code{<\$\$} & & \code{<} & & \code{(<\$\$ x y z)}\\ & \code{<=\$\$} & & \code{<=} & & \code{(<=\$\$ x y z)}\\ & \code{>\$\$} & & \code{>} & & \code{(>\$\$ x y z)}\\ & \code{>=\$\$} & & \code{>=} & & \code{(>=\$\$ x y z)}\\ & \code{abs\$\$} & & \code{abs} & & \code{(abs\$\$ x)}\\ & \code{bounded-value\$\$} & & \code{\entlink{bounded-value}} & & \code{(bounded-value\$\$ x y z)}\\ & \code{ceiling\$\$} & & \code{ceiling} & & \code{(ceiling\$\$ x divisor)}\\ & \code{decf\$\$} & & \code{decf} & & \code{(decf\$\$ x delta)}\\ & \code{decf-\$\$after} & & \code{\entlink{decf-after}} & & \code{(decf\$\$-after x delta)}\\ & \code{decf/delete\$\$-acons} & & \code{\entlink{decf/delete-acons}} & & \code{(decf/delete\$\$-acons}\\ & & & & & ~~~ \code{x delta alist)}\\ & \code{evenp\$\$} & & \code{evenp} & & \code{(evenp\$\$ x)}\\ & \code{fceiling\$\$} & & \code{fceiling} & & \code{(fceiling\$\$ x divisor)}\\ & \code{floor\$\$} & & \code{floor} & & \code{(floor\$\$ x divisor)}\\ & \code{ffloor\$\$} & & \code{ffloor} & & \code{(ffloor\$\$ x divisor)}\\ & \code{fround\$\$} & & \code{fround} & & \code{(fround\$\$ x divisor)}\\ & \code{ftruncate\$\$} & & \code{ftruncate} & & \code{(ftruncate\$\$ x divisor)}\\ & \code{incf\$\$} & & \code{incf} & & \code{(incf\$\$ x delta)}\\ & \code{incf\$\$-after} & & \code{\entlink{incf-after}} & & \code{(incf\$\$-after x delta)}\\ & \code{max\$\$} & & \code{max} & & \code{(max\$\$ x y z)}\\ & \code{min\$\$} & & \code{min} & & \code{(min\$\$ x y z)}\\ & \code{minusp\$\$} & & \code{minusp} & & \code{(minusp\$\$ x)}\\ & \code{mod\$\$} & & \code{mod} & & \code{(mod\$\$ x divisor)}\\ & \code{oddp\$\$} & & \code{oddp} & & \code{(oddp\$\$ x)}\\ & \code{plusp\$\$} & & \code{plusp} & & \code{(plusp\$\$ x)}\\ & \code{pushnew/incf\$\$-acons} & & \code{\entlink{pushnew/incf-acons}} & & \code{(pushnew/incf\$\$-acons}\\ & & & & & ~~~ \code{'x delta alist)}\\ & \code{round\$\$} & & \code{round} & & \code{(round\$\$ x divisor)}\\ & \code{truncate\$\$} & & \code{truncate} & & \code{(truncate\$\$ x divisor)}\\ & \code{zerop\$\$} & & \code{zerop} & & \code{(zerop\$\$ x)} \\[2pt] \hline \end{tabular} \T\medskip \bfindex{coerce\$\$}% The one-argument \glref{function} \nobr{\textbf{coerce\$\$}} provides convenient \nobr{\code{double-float}} coercion: % \W\supp \begin{example} (setf x (coerce\$\$ x)) \end{example} \T\clearpage \W\xname{ref-long-float-operators} \subsubsection{Long-float operators} \bfindex{\$\$\$}% \bfindex{/\$\$\$}% \bfindex{$*$\$\$\$}% \bfindex{+\$\$\$}% \bfindex{-\$\$\$}% \bfindex{/=\$\$\$}% \bfindex{1+\$\$\$}% \bfindex{1-\$\$\$}% \bfindex{$<$\$\$\$}% \bfindex{$<$=\$\$\$}% \bfindex{=\$\$\$}% \bfindex{$>$\$\$\$}% \bfindex{$>$=\$\$\$}% \bfindexit{bounded-value\$\$\$}% \bfindex{ceiling\$\$\$}% \bfindex{decf\$\$\$}% \bfindex{decf\$\$\$-after}% \bfindexit{decf/delete\$\$\$-acons}% \bfindex{evenp\$\$\$}% \bfindex{fceiling\$\$\$}% \bfindex{ffloor\$\$\$}% \bfindex{floor\$\$\$}% \bfindex{fround\$\$\$}% \bfindex{ftruncate\$\$\$}% \bfindex{incf\$\$\$}% \bfindex{incf\$\$\$-after}% \bfindexit{pushnew/incf\$\$\$-acons}% \bfindex{max\$\$\$}% \bfindex{min\$\$\$}% \bfindex{minusp\$\$\$}% \bfindex{abs\$\$\$}% \bfindex{mod\$\$\$}% \bfindex{oddp\$\$\$}% \bfindex{plusp\$\$\$}% \bfindex{round\$\$\$}% \bfindex{truncate\$\$\$}% \bfindex{zerop\$\$\$}% % These \code{long-float} declared-numeric operators are defined in the \nobr{\code{:gbbopen-tools}} \glref{module}: % \T\\[6pt] \W\supp\tabletop \begin{tabular}{@{}l@{}l@{}l@{}l@{}l@{}l@{}} ~~~~~ & \textbf{Operator} & ~~~~~ & \textbf{Operation} & ~~~~~ & \textbf{Example} \\ \hline & \code{\$\$\$} & & \code{the long-float} & & \code{(\$\$\$ x)}\\ & \code{+\$\$\$} & & \code{+} & & \code{(+\$\$\$ x y z)}\\ & \code{-\$\$\$} & & \code{-} & & \code{(-\$\$\$ x y z)}\\ & \code{1+\$\$\$} & & \code{1+} & & \code{(1+\$\$\$ x)}\\ & \code{1-\$\$\$} & & \code{1-} & & \code{(1-\$\$\$ x)}\\ & \code{*\$\$\$} & & \code{*} & & \code{(*\$\$\$ x y z)}\\ & \code{/\$\$\$} & & \code{/} & & \code{(/\$\$\$ x y z)}\\ & \code{=\$\$\$} & & \code{=} & & \code{(=\$\$\$ x y z)}\\ & \code{/=\$\$\$} & & \code{/=} & & \code{(/=\$\$\$ x y z)}\\ & \code{<\$\$\$} & & \code{<} & & \code{(<\$\$\$ x y z)}\\ & \code{<=\$\$\$} & & \code{<=} & & \code{(<=\$\$\$ x y z)}\\ & \code{>\$\$\$} & & \code{>} & & \code{(>\$\$\$ x y z)}\\ & \code{>=\$\$\$} & & \code{>=} & & \code{(>=\$\$\$ x y z)}\\ & \code{abs\$\$\$} & & \code{abs} & & \code{(abs\$\$\$ x)}\\ & \code{bounded-value\$\$\$} & & \code{\entlink{bounded-value}} & & \code{(bounded-value\$\$\$ x y z)}\\ & \code{ceiling\$\$\$} & & \code{ceiling} & & \code{(ceiling\$\$\$ x divisor)}\\ & \code{decf\$\$\$} & & \code{decf} & & \code{(decf\$\$\$ x delta)}\\ & \code{decf-\$\$\$after} & & \code{\entlink{decf-after}} & & \code{(decf\$\$\$-after x delta)}\\ & \code{decf/delete\$\$\$-acons} & & \code{\entlink{decf/delete-acons}} & & \code{(decf/delete\$\$\$-acons}\\ & & & & & ~~~ \code{x delta alist)}\\ & \code{evenp\$\$\$} & & \code{evenp} & & \code{(evenp\$\$\$ x)}\\ & \code{fceiling\$\$\$} & & \code{fceiling} & & \code{(fceiling\$\$\$ x divisor)}\\ & \code{floor\$\$\$} & & \code{floor} & & \code{(floor\$\$\$ x divisor)}\\ & \code{ffloor\$\$\$} & & \code{ffloor} & & \code{(ffloor\$\$\$ x divisor)}\\ & \code{fround\$\$\$} & & \code{fround} & & \code{(fround\$\$\$ x divisor)}\\ & \code{ftruncate\$\$\$} & & \code{ftruncate} & & \code{(ftruncate\$\$\$ x divisor)}\\ & \code{incf\$\$\$} & & \code{incf} & & \code{(incf\$\$\$ x delta)}\\ & \code{incf\$\$\$-after} & & \code{\entlink{incf-after}} & & \code{(incf\$\$\$-after x delta)}\\ & \code{max\$\$\$} & & \code{max} & & \code{(max\$\$\$ x y z)}\\ & \code{min\$\$\$} & & \code{min} & & \code{(min\$\$\$ x y z)}\\ & \code{minusp\$\$\$} & & \code{minusp} & & \code{(minusp\$\$\$ x)}\\ & \code{mod\$\$\$} & & \code{mod} & & \code{(mod\$\$\$ x divisor)}\\ & \code{oddp\$\$\$} & & \code{oddp} & & \code{(oddp\$\$\$ x)}\\ & \code{plusp\$\$\$} & & \code{plusp} & & \code{(plusp\$\$\$ x)}\\ & \code{pushnew/incf\$\$\$-acons} & & \code{\entlink{pushnew/incf-acons}} & & \code{(pushnew/incf\$\$\$-acons}\\ & & & & & ~~~ \code{'x delta alist)}\\ & \code{round\$\$\$} & & \code{round} & & \code{(round\$\$\$ x divisor)}\\ & \code{truncate\$\$\$} & & \code{truncate} & & \code{(truncate\$\$\$ x divisor)}\\ & \code{zerop\$\$\$} & & \code{zerop} & & \code{(zerop\$\$\$ x)} \\[2pt] \hline \end{tabular} \T\medskip \bfindex{coerce\$\$\$}% The one-argument \glref{function} \nobr{\textbf{coerce\$\$\$}} provides convenient \nobr{\code{long-float}} coercion: % \W\supp \begin{example} (setf x (coerce\$\$\$ x)) \end{example} %% ------------------------------------------------------------------------ \T\markright{}% \T\pagestyle{plain} \T\clearpage \W\xname{ref-pseudo-probability-entities} \T\pagestyle{fancy} \T\thispagestyle{fancybottom} \T\global\def\fnlastname{ }% \subsection{Pseudo Probabilities} \label{sec:pprob}% \index{pseudo-probability entities}% The \code{:gbbopen-tools} module provides a discretized \code{\glref{fixnum}} representation for probability values in which probability values in the range [0.0..1.0] are represented as the nearest integers in the range [0..1000]. The following \code{\glref{pseudo-probability}} operators are provided: % \bfindex{\%}% \bfindex{/\%}% \bfindex{$*$\%}% \bfindex{+\%}% \bfindex{-\%}% \bfindex{/=\%}% \bfindex{1+\%}% \bfindex{1-\%}% \bfindex{$<$\%}% \bfindex{$<$=\%}% \bfindex{=\%}% \bfindex{$>$\%}% \bfindex{$>$=\%}% \bfindexit{bounded-value\%}% \bfindex{ceiling\%}% \bfindex{decf\%}% \bfindex{decf\%-after}% \bfindexit{decf/delete\%-acons}% \bfindex{evenp\%}% \bfindex{fceiling\%}% \bfindex{ffloor\%}% \bfindex{floor\%}% \bfindex{fround\%}% \bfindex{ftruncate\%}% \bfindex{incf\%}% \bfindex{incf\%-after}% \bfindexit{pushnew/incf\%-acons}% \bfindex{max\%}% \bfindex{min\%}% \bfindex{minusp\%}% \bfindex{abs\%}% \bfindex{mod\%}% \bfindex{oddp\%}% \bfindex{plusp\%}% \bfindex{round\%}% \bfindex{truncate\%}% \bfindex{zerop\%}% % \T\\[6pt] \W\supp\tabletop \begin{tabular}{@{}l@{}l@{}l@{}l@{}l@{}l@{}} ~~~~~ & \textbf{Operator} & ~~~~~ & \textbf{Operation} & ~~~~~ & \textbf{Example} \\ \hline & \code{\%} & & \code{the pseudo-probability} & & \code{(\% x)}\\ & \code{+\%} & & \code{+\&} & & \code{(+\% x y z)}\\ & \code{-\%} & & \code{-\&} & & \code{(-\% x y z)}\\ & \code{1+\%} & & \code{1+\&} & & \code{(1+\% x)}\\ & \code{1-\%} & & \code{1-\&} & & \code{(1-\% x)}\\ & \code{\entlink{*\%}} & & normalizing \code{*\&} & & \code{(*\% x y z)}\\ & \code{\entlink{/\%}} & & normalizing \code{/\&} & & \code{(/\% x y z)}\\ & \code{=\%} & & \code{=\&} & & \code{(=\% x y z)}\\ & \code{/=\%} & & \code{/=\&} & & \code{(/=\% x y z)}\\ & \code{<\%} & & \code{<\&} & & \code{(<\% x y z)}\\ & \code{<=\%} & & \code{<=\&} & & \code{(<=\% x y z)}\\ & \code{>\%} & & \code{>\&} & & \code{(>\% x y z)}\\ & \code{>=\%} & & \code{>=\&} & & \code{(>=\% x y z)}\\ & \code{abs\%} & & \code{abs\&} & & \code{(abs\% x)}\\ & \code{bounded-value\%} & & \code{bounded-value\&} & & \code{(bounded-value\% x y z)}\\ & \code{ceiling\%} & & normalizing \code{ceiling\&} & & \code{(ceiling\% x divisor)}\\ & \code{decf\%} & & \code{decf\&} & & \code{(decf\% x delta)}\\ & \code{decf-\%after} & & \code{decf-after\&} & & \code{(decf\%-after x delta)}\\ & \code{decf/delete\%-acons} & & \code{decf/delete-acons\&} & & \code{(decf/delete\%-acons}\\ & & & & & ~~~ \code{x delta alist)}\\ & \code{evenp\%} & & \code{evenp\&} & & \code{(evenp\% x)}\\ & \code{fceiling\%} & & normalizing \code{fceiling\&} & & \code{(fceiling\% x divisor)}\\ & \code{floor\%} & & normalizing \code{floor\&} & & \code{(floor\% x divisor)}\\ & \code{ffloor\%} & & normalizing \code{ffloor\&} & & \code{(ffloor\% x divisor)}\\ & \code{fround\%} & & normalizing \code{fround\&} & & \code{(fround\% x divisor)}\\ & \code{ftruncate\%} & & normalizing \code{ftruncate\&} & & \code{(ftruncate\% x divisor)}\\ & \code{incf\%} & & \code{incf\&} & & \code{(incf\% x delta)}\\ & \code{incf\%-after} & & \code{incf-after\&} & & \code{(incf\%-after x delta)}\\ & \code{max\%} & & \code{max\&} & & \code{(max\% x y z)}\\ & \code{min\%} & & \code{min\&} & & \code{(min\% x y z)}\\ & \code{minusp\%} & & \code{minusp\&} & & \code{(minusp\% x)}\\ & \code{mod\%} & & \code{mod\&} & & \code{(mod\% x divisor)}\\ & \code{oddp\%} & & \code{oddp\&} & & \code{(oddp\% x)}\\ & \code{plusp\%} & & \code{plusp\&} & & \code{(plusp\% x)}\\ & \code{pushnew/incf\%-acons} & & \code{pushnew/incf-acons\&} & & \code{(pushnew/incf\%-acons}\\ & & & & & ~~~ \code{'x delta alist)}\\ & \code{round\%} & & normalizing \code{round\&} & & \code{(round\% x divisor)}\\ & \code{truncate\%} & & normalizing \code{truncate\&} & & \code{(truncate\% x divisor)}\\ & \code{zerop\%} & & \code{zerop\&} & & \code{(zerop\% x)} \\[2pt] \hline \end{tabular} \T\medskip \W\entities \T\clearpage %% ------------------------------------------------------------------------ \begin{functiondoc}[multiply-pprob]{Function}{*\%}% {\nobr{\var{pseudo-probability\/}\superstar{}} \nobr{\returns{} \var{pseudo-probability-product\/}}} \index{pseudo-probability!multiplication}% \fnsyntax \fnpurpose Returns the product of \nobr{\var{numbers}}, performing \glref{pseudo-probability}-normalization in the process. \fnpackage \code{:gbbopen-tools} \fnmodule \code{:gbbopen-tools} \fnargs \begin{args}{pseudo-probability-ln} \arg[pseudo-probability] A \code{\glref{fixnum}} \glref{pseudo-probability} \arg[pseudo-probability-product] A \nobr{\code{\glref{fixnum}}} \glref{pseudo-probability} \end{args} \fnreturns The \code{\glref{fixnum}} \glref{pseudo-probability} product of \nobr{\var{numbers\/}} or 1000 if no \nobr{\var{numbers\/}} are supplied. \begin{alsos}{pprob2prob} \also[/\%] \also[pprob2prob] \also[prob2pprob] \end{alsos} \fnexamples \begin{example} % \W\supp > (* 0.6 0.7) 0.42000002 > (*\% 600 700) 420 > (* 0.6 0.7 0.8) 0.33600003 > (*\% 600 700 800) 336 > (*\%) 1000 > \end{example} \end{functiondoc} %% ------------------------------------------------------------------------ \begin{functiondoc}[divide-pprob]{Function}{/\%}% {\var{\nobr{pseudo-probability-numerator} \nobr{pseudo-probability-denominator\/}\superstar{}} \nobr{\returns{} \var{quotient\/}}} \index{pseudo-probability!division}% \fnsyntax \fnpurpose Returns the quotient of dividing \nobr{\var{pseudo-probability-numerator\/}} by all of the \nobr{\var{pseudo-probability-denominators}}, performing \glref{pseudo-probability}-normalization in the process. \fnaltsyntax \fnalternate{/\%}% {\var{pseudo-probability-numerator\/} \returns{} \var{reciprocal\/}} \fnpackage \code{:gbbopen-tools} \fnmodule \code{:gbbopen-tools} \fnargs \begin{args}{pseudo-probability-ln} \arg[pseudo-probability-numerator] A \code{\glref{fixnum}} \glref{pseudo-probability} \arg[pseudo-probability-denominator] A \code{\glref{fixnum}} \glref{pseudo-probability} \arg[quotient] A \glref{pseudo-probability}-normalized \nobr{\code{\glref{fixnum}}} \arg[reciprocal] A \glref{pseudo-probability}-normalized \nobr{\code{\glref{fixnum}}} \end{args} \fnreturns The \glref{pseudo-probability}-normalized \nobr{\code{\glref{fixnum}}} quotient (if one or more \nobr{\var{pseudo-probability-denominators\/}} is specified; otherwise the \glref{pseudo-probability}-normalized \nobr{\code{\glref{fixnum}}} reciprocal of \nobr{\var{pseudo-probability-numerator}}. \fndescription % \glref{pseudo-probability}-normalization is performed by \textbf{/\%}, but the \nobr{\code{\glref{fixnum}}} result may not be a \glref{pseudo-probability}. It is an error to specify more than one \nobr{\var{pseudo-probability-denominator\/}} value that leads to an intermediate result that is larger than a \nobr{\code{\glref{fixnum}}}. \begin{alsos}{pprob2prob} \also[*\%] \also[pprob2prob] \also[prob2pprob] \end{alsos} \fnexamples \begin{example} % \W\supp > (/ 0.6 0.8) 0.75 > (/\% 600 800) 750 > (/ 0.6 0.8 0.9) 0.8333334 > (/\% 600 800 900) 833 > (/ 0.8 0.5) 1.6 ; not a probability > (/\% 800 500) 1600 ; not a \glref{pseudo-probability} > (/ 5.0) ; not a probability 0.2 > (/\% 5000) ; not a \glref{pseudo-probability} 200 > (/ 0.5) 2.0 ; not a probability > (/\% 500) 2000 ; not a \glref{pseudo-probability} > \end{example} \end{functiondoc} %% ------------------------------------------------------------------------ \begin{functiondoc}[exp-pprob]{Function}{exp\%}% {\nobr{\var{pseudo-probability-ln\/}} \nobr{\returns{} \var{pseudo-probability\/}}} %\index{pseudo-probability!ln (natural log)}% \fnsyntax \fnpurpose Return the ``pseudo natural logarithm'' (\glref{pseudo-probability-ln}) of a \glref{pseudo-probability} value. \fnpackage \code{:gbbopen-tools} \fnmodule \code{:gbbopen-tools} \fnargs \begin{args}{pseudo-probability-ln} \arg[pseudo-probability] A \code{\glref{fixnum}} \glref{pseudo-probability} \arg[pseudo-probability-ln] A \code{\glref{fixnum}} \glref{pseudo-probability-ln} \end{args} \fnreturns The \code{\glref{fixnum}} \glref{pseudo-probability-ln} of \nobr{\var{pseudo-probability}}. \begin{alsos}{prob2pprob} \also[ln\%] \also[pprob2prob] \also[prob2pprob] \end{alsos} \fnexamples \begin{example} % \W\supp > (exp 0.0) 1.0 > (exp\% 0) 1000 > (exp -6.907756) 9.999995e-4 > (exp\% -6907756) 1 > \end{example} \end{functiondoc} %% ------------------------------------------------------------------------ \begin{functiondoc}[ln-pprob]{Function}{ln\%}% {\nobr{\var{pseudo-probability\/}\superstar{}} \nobr{\returns{} \var{pseudo-probability-ln\/}}} \index{pseudo-probability!ln (natural log)}% \fnsyntax \fnpurpose Return the ``pseudo natural logarithm'' (\glref{pseudo-probability-ln}) of a \glref{pseudo-probability} value. \fnpackage \code{:gbbopen-tools} \fnmodule \code{:gbbopen-tools} \fnargs \begin{args}{pseudo-probability-ln} \arg[pseudo-probability] A \code{\glref{fixnum}} \glref{pseudo-probability} \arg[pseudo-probability-ln] A \code{\glref{fixnum}} \glref{pseudo-probability-ln} \end{args} \fnreturns The \code{\glref{fixnum}} \glref{pseudo-probability-ln} of \nobr{\var{pseudo-probability}}. \begin{alsos}{pprob2prob} \also[exp\%] \also[pprob2prob] \also[prob2pprob] \end{alsos} \fnexamples \begin{example} % \W\supp > (log 1.0) 0.0 > (ln\% 1000) 0 > (log 0.001) -6.9077554 > (ln\% 1) -6907756 > \end{example} \end{functiondoc} %% ------------------------------------------------------------------------ \begin{functiondoc}{Function}{pprob2prob}% {\nobr{\var{pseudo-probability\/}} \nobr{\returns{} \var{probability\/}}} \index{pseudo-probability!converting to a probability}% \index{probability!converting from a pseudo-probability}% \fnsyntax \fnpurpose Returns the value of \nobr{\var{pseudo-probability\/}} as a probability. \fnpackage \code{:gbbopen-tools} \fnmodule \code{:gbbopen-tools} \fnargs \begin{args}{pseudo-probability} \arg[pseudo-probability] A \code{\glref{fixnum}} \glref{pseudo-probability} \arg[probability] A [0.0..1.0] probability \end{args} \fnreturns The converted \nobr{\var{probability}}. \begin{alsos}{prob2pprob} \also[prob2pprob] \end{alsos} \fnexamples \begin{example} % \W\supp > (pprob2prob 0) 0.0 > (pprob2prob 1000) 1.0 > (pprob2prob 800) 0.8 > \end{example} \end{functiondoc} %% ------------------------------------------------------------------------ \begin{functiondoc}{Function}{prob2pprob}% {\var{probability\/} \nobr{\returns{} \var{pseudo-probability\/}}} \index{pseudo-probability!converting from a probability}% \index{probability!converting to a pseudo-probability}% \fnsyntax \fnpurpose Returns the value of \nobr{\var{probability\/}} as a \glref{pseudo-probability}. \fnpackage \code{:gbbopen-tools} \fnmodule \code{:gbbopen-tools} \fnargs \begin{args}{pseudo-probability} \arg[probability] A [0.0..1.0] probability \arg[pseudo-probability] A \code{\glref{fixnum}} \glref{pseudo-probability} \end{args} \fnreturns The converted \nobr{\var{pseudo-probability}}. \begin{alsos}{pprob2prob} \also[pprob2prob] \end{alsos} \fnexamples \begin{example} % \W\supp > (prob2pprob 0.0) 0 > (prob2pprob 1.0) 1000 > (prob2pprob 0.8) 800 > \end{example} \end{functiondoc} %% ------------------------------------------------------------------------ \T\markright{}% \T\pagestyle{plain} \T\clearpage \W\xname{ref-date-and-time-entities} \T\pagestyle{fancy} \T\thispagestyle{fancybottom} \T\global\def\fnlastname{ }% \subsection{Date and Time} \label{sec:dateandtime}% \index{date and time entities}% The \code{:gbbopen-tools} module includes useful date and time parsing and formatting entities. \index{time zone!abbreviations}% \index{abbreviations!time zone}% \label{ref:timezones}% In addition to UTC offsets, time-of-day entities support the following time-zone abbreviations for standard-time (non-daylight-savings) offsets: % \T\\[3pt] \W\supp\tabletop \small \begin{tabular}{c@{}c@{}c@{}c@{}l@{}} \textbf{Offset} & ~~~ & \textbf{Zone} & ~~~ & \textbf{Locations} \\ 1 && \code{WAT} && West Africa (also Cape Verdes Islands, Atlantic Ocean)\\ 2 && \code{AT} && Azores\\ 7/2 && \code{NST} && Newfoundland\\ 4 && \code{AST} && Atlantic\\ 5 && \code{EST} && Eastern (North America)\\ 6 && \code{CST} && Central (North America)\\ 7 && \code{MST} && Mountain (North America)\\ 8 && \code{PST} && Pacific (North America)\\ 9 && \code{AKST} && Alaska\\ 10 && \code{HAST} && Hawaii-Aleutian\\ 11 && \code{NT} && Nome\\ 12 && \code{IDLW} && International Dateline West\\ 0 && \code{GMT} && Greenwich (also Portugal, Reykjavik (Iceland), Western Africa)\\ -1 && \code{CET} && Central European (also Algeria, Nigeria, Angola)\\ -2 && \code{EET} && Eastern European (also Finland, Balkans, Libya, Egypt, South Africa)\\ -3 && \code{MSK} && Moscow (also Baghdad, Eastern Africa, Ethiopia, Kenya, Tanzania)\\ -4 && \code{ZP4} && Samara (Russia Zone 3)\\ -5 && \code{ZP5} && Yekaterinburg (Russia Zone 4)\\ -11/2 && \code{IST} && Indian\\ -6 && \code{ZP6} && Omsk (Russia Zone 5), Bangladesh)\\ -7 && \code{WAST} && West Austrailian Standard (also Christmas Island, Krasnoyarsk (Russia Zone 6), Western Indonesia) \\ -8 && \code{AWST} && Australian Western (also Irkutsk (Russia Zone 7), China, Hong Kong, Philippines, Central Indonesia)\\ -9 && \code{JST} && Japan (also Yakutsk (Russia Zone 8), Korea, Eastern Indonesia)\\ -19/2 && \code{ACST} && Australian Central\\ -10 && \code{AEST} && Australian Eastern (also Vladivostok (Russia Zone 9), Papua New Guinea)\\ -21/2 && \code{NFT} && Norfolk (Island)\\ -12 && \code{NZST} && New Zealand (also Kamchatka (Russia), Fiji, Marshall Islands) \\ \end{tabular} \normalsize \T\\[3pt] % and for daylight-savings-time offsets: % \T\\[3pt] \W\supp \small \begin{tabular}{c@{}c@{}c@{}c@{}l@{}} \textbf{Offset} & ~~~ & \textbf{Zone} & ~~~ & \textbf{Locations} \\ 5/2 && \code{NDT} && Newfoundland Daylight\\ 3 && \code{ADT} && Atlantic Daylight\\ 4 && \code{EDT} && Eastern Daylight (North America)\\ 5 && \code{CDT} && Central Daylight (North America)\\ 6 && \code{MDT} && Mountain Daylight (North America)\\ 7 && \code{PDT} && Pacific Daylight (North America)\\ 8 && \code{AKDT} && Alaska Daylight\\ 9 && \code{HADT} && Hawaii-Aleutian Daylight\\ -1 && \code{BST} && British Summer\\ -2 && \code{CEDT} && Central European Daylight\\ -3 && \code{EEDT} && Eastern European Daylight\\ -4 && \code{MSD} && Moscow Daylight\\ -9 && \code{AWDT} && Australian Western Daylight\\ -21/2 && \code{ACSD} && Australian Central Daylight\\ -11 && \code{AEDT} && Australian Eastern Daylight\\ \end{tabular} \normalsize Time-zone abbreviations used around the world are not unique or universal. The same hour offset can map onto multiple different zone abbreviations, and the same abbreviations are also used to refer to different zones. The above choices of supported abbreviations were made arbitrarily, and the use of UTC offsets is recommended for unambiguous textual representation of the time of day. \W\entities \T\clearpage %% ------------------------------------------------------------------------ \begin{functiondoc}[month-precedes-date-var]{Variable}% {*month-precedes-date*}{}% \fnsyntax \fnpurpose Control the default month and date ordering for GBBopen Tools date and time entities. \fnpackage \code{:gbbopen-tools} (home package is \nobr{\code{:module-manager}}) \fnmodule \code{:module-manager} \fnvaluetype A \glref{generalized~boolean} \fninitialvalue True \begin{alsos}{encode-date-and-time} \also[brief-date] \also[brief-date-and-time] \also[encode-date-and-time] \also[full-date-and-time] \also[parse-date] \also[parse-date-and-time] \also[parse-time] \also[very-brief-date] \end{alsos} \fnexamples Toggle between date formatting options: % \W\supp \begin{example} > (let ((*month-precedes-date* 't)) (brief-date-and-time)) "Feb 16 13:11" > (let ((*month-precedes-date* nil)) (brief-date-and-time)) "16 Feb 13:11" > \end{example} \fnnote \indexit{module!:module-manager@\code{:module-manager}}% \indexit{:module-manager@\code{:module-manager} module}% % This variable is defined in the \nobr{\code{:module-manager}} \glref{module} in order to make it available as early as possible. \end{functiondoc} %% ------------------------------------------------------------------------ \begin{functiondoc}[time-first-var]{Variable}% {*time-first*}{}% \fnsyntax \fnpurpose Control the default date and time ordering for GBBopen Tools date and time entities. \fnpackage \code{:gbbopen-tools} \fnmodule \code{:gbbopen-tools} \fnvaluetype A \glref{generalized~boolean} \fninitialvalue \nil \begin{alsos}{encode-date-and-time} \also[encode-date-and-time] \also[parse-date-and-time] \end{alsos} \fnexample Change the default date and time ordering to have the time precede the date: % \W\supp \begin{example} > (let ((*time-first* 't)) (parse-date-and-time "10:30pm 4/1/10")) 0 30 22 1 4 2010 nil nil 14 > \end{example} \end{functiondoc} %% ------------------------------------------------------------------------ \begin{functiondoc}[year-first-var]{Variable}% {*year-first*}{}% \fnsyntax \fnpurpose Control the default year positioning for GBBopen Tools date entities. \fnpackage \code{:gbbopen-tools} \fnmodule \code{:gbbopen-tools} \fnvaluetype A \glref{generalized~boolean} \fninitialvalue \nil \begin{alsos}{encode-date-and-time} \also[brief-date] \also[brief-date-and-time] \also[encode-date-and-time] \also[full-date-and-time] \also[parse-date] \also[parse-date-and-time] \also[very-brief-date] \end{alsos} \fnexample Change the default year positioning to have the year first: % \W\supp \begin{example} > (let ((*year-first* 't)) (full-date-and-time nil :all-numeric 't :year-first 't)) "2009/02/16 13:11" > (let ((*year-first* 't)) (parse-date "1-4-10" :year-first 't)) 10 4 2001 6 > \end{example} \end{functiondoc} %% ------------------------------------------------------------------------ \begin{functiondoc}{Function}{brief-date}{% \nobr{\code{\&optional} \var{universal-time\/}} \nobr{\code{\&key} \var{time-zone}} \var{\nobr{month-precedes-date} \nobr{year-first} \nobr{include-year} destination\/} \nobr{\returns{} \var{result\/}}} \index{date!formatted}% \index{time, formatted}% \fnsyntax \fnpurpose Generate a brief date description. \fnpackage \code{:gbbopen-tools} (home package is \nobr{\code{:module-manager}}) \fnmodule \code{:module-manager} \fnargs \begin{args}{universal-time} \arg[universal-time] A \glref{Universal~Time} (default is \nil, which is equivalent to the value returned by \nobr{\code{(get-universal-time)}}) \arg[time-zone] A \glref{time~zone} (default is \nil, which is equivalent to the current time zone adjusted for daylight saving time) \arg[month-precedes-date] A \glref{generalized~boolean} (default is \nobr{\textbf{\entlink{*month-precedes-date*}}}) \arg[year-first] A \glref{generalized~boolean} (default is \nobr{\textbf{\entlink{*year-first*}}}) \arg[include-year] A \glref{generalized~boolean} (default is \code{t}) \arg[destination] Either \nil, \code{t}, a stream, or a string with a fill pointer (default is \nil) \arg[result] A string or \nil{} \end{args} \fnreturns If \var{destination\/} is non-\nil, then \nil; otherwise, a string. \fndescription % A 12-character description is generated (6 characters, if \nobr{\var{include-year\/}} is non-\nil). \W\xml{p} \bfindexit{get-universal-time}% If \var{universal-time\/} is not supplied or is \nil, the current time (as returned by \nobr{\code{get-universal-time}} is used. \W\xml{p} % If \var{time-zone\/} is not supplied or is \nil, it defaults to the current time zone adjusted for daylight saving time. If \nobr{\var{time-zone\/}} is supplied, it is assumed to include any adjustment for daylight saving time. \W\xml{p} % If \var{month-precedes-date\/} is true, the month is presented in front of the date; otherwise the date precedes the month. \W\xml{p} % If \var{year-first\/} is supplied and is non-\nil, the year is presented in front of the month and date; otherwise the year follows the month and date. \W\xml{p} % If \var{include-year\/} is supplied and is non-\nil, the year is included in the presented time. \begin{alsos}{internet-text-date-and-time} \also[*month-precedes-date*] \also[brief-date-and-time] \also[full-date-and-time] \also[http-date-and-time] \also[internet-text-date-and-time] \also[iso8601-date-and-time] \also[message-log-date-and-time] \also[very-brief-date] \end{alsos} \fnexamples Display the current date (with and without the year): % \W\supp \begin{example} > (brief-date) "Feb 16, 2008" > (brief-date (get-universal-time) :include-year nil) "Feb 16" > \end{example} % Display the date 10 days ago: % \W\supp\notpretop \begin{example} > (brief-date (- (get-universal-time) (* 60 60 24 10))) "Feb 6, 2008" > \end{example} \fnnote \indexit{module!:module-manager@\code{:module-manager}}% \indexit{:module-manager@\code{:module-manager} module}% % This function is loaded with the \nobr{\code{:module-manager}} \glref{module} in order to to make it available as early as possible. \end{functiondoc} %% ------------------------------------------------------------------------ \begin{functiondoc}{Function}{brief-date-and-time}{% \nobr{\code{\&optional} \var{universal-time\/}} \nobr{\code{\&key} \var{time-zone}} \var{\nobr{month-precedes-date} \nobr{year-first} \nobr{include-seconds} destination\/} \nobr{\returns{} \var{result\/}}} \index{date!formatted}% \index{time, formatted}% \fnsyntax \fnpurpose Generate a brief date-and-time description. \fnpackage \code{:gbbopen-tools} (home package is \nobr{\code{:module-manager}}) \fnmodule \code{:module-manager} \fnargs \begin{args}{universal-time} \arg[universal-time] A \glref{Universal~Time} (default is \nil, which is equivalent to the value returned by \nobr{\code{(get-universal-time)}}) \arg[time-zone] A \glref{time~zone} (default is \nil, which is equivalent to the current time zone adjusted for daylight saving time) \arg[month-precedes-date] A \glref{generalized~boolean} (default is \nobr{\textbf{\entlink{*month-precedes-date*}}}) \arg[year-first] A \glref{generalized~boolean} (default is \nobr{\textbf{\entlink{*year-first*}}}) \arg[include-seconds] A \glref{generalized~boolean} (default is \nil) \arg[destination] Either \nil, \code{t}, a stream, or a string with a fill pointer (default is \nil) \arg[result] A string or \nil{} \end{args} \fnreturns If \var{destination\/} is non-\nil, then \nil; otherwise, a string. \fndescription A 12-character description (15 characters, if \nobr{\var{include-seconds\/}} is non-\nil{}) is generated. If the \nobr{\var{universal-time\/}} value is within 120 days of the current time, the result \nobr{\var{string\/}} includes the time of day but not the year; otherwise, the year is included but not the time of day. \W\xml{p} \bfindexit{get-universal-time}% % If \nobr{\var{universal-time\/}} is not supplied or is \nil, the current time (as returned by \nobr{\code{get-universal-time}} is used. \W\xml{p} % If \var{time-zone\/} is not supplied or is \nil, it defaults to the current time zone adjusted for daylight saving time. If \nobr{\var{time-zone\/}} is supplied, it is assumed to include any adjustment for daylight saving time. \W\xml{p} % If \var{month-precedes-date\/} is true, the month is presented in front of the date; otherwise the date precedes the month. \W\xml{p} % If \var{year-first\/} is supplied and is non-\nil, the year is presented in front of the month and date; otherwise the year follows the month and date. \W\xml{p} % If \var{include-seconds\/} is supplied and is non-\nil, seconds are included in the presented time. \begin{alsos}{internet-text-date-and-time} \also[*month-precedes-date*] \also[brief-date] \also[full-date-and-time] \also[http-date-and-time] \also[internet-text-date-and-time] \also[iso8601-date-and-time] \also[message-log-date-and-time] \also[very-brief-date] \end{alsos} \fnexamples Display the current date and time: % \W\supp \begin{example} > (brief-date-and-time) "Feb 16 13:11" > \end{example} % Display the current date and time (with seconds): % \W\supp\notpretop \begin{example} > (brief-date-and-time nil :include-seconds 't) "Feb 16 13:11:38" > \end{example} % Display the current date and time as GMT: % \W\supp\notpretop \begin{example} > (brief-date-and-time nil :time-zone 0) "Feb 16 18:11" > \end{example} % The date and time 10 days ago: % \W\supp\notpretop \begin{example} > (brief-date-and-time (- (get-universal-time) (* 60 60 24 10))) "Feb 6 13:11" > \end{example} % The date and time 125 days ago: % \W\supp\notpretop \begin{example} > (brief-date-and-time (- (get-universal-time) (* 60 60 24 125))) "Oct 12, 2004" > \end{example} % The date and time 125 days ago (with seconds, but ignored because no time of day is included for dates that are not within 120 days of the given time): % \W\supp\notpretop \begin{example} > (brief-date-and-time (- (get-universal-time) (* 60 60 24 125)) :include-seconds 't) "Oct 12, 2004 " > \end{example} \fnnote \indexit{module!:module-manager@\code{:module-manager}}% \indexit{:module-manager@\code{:module-manager} module}% % This function is loaded with the \nobr{\code{:module-manager}} \glref{module} in order to to make it available as early as possible. \end{functiondoc} %% ------------------------------------------------------------------------ \begin{functiondoc}{Function}{brief-duration}{% \var{seconds\/} \nobr{\code{\&optional} \var{maximum-fields destination\/}} \nobr{\returns{} \var{result\/}}} \index{time!duration, formatting}% \index{duration!formatting}% \fnsyntax \fnpurpose Format a numeric time duration (in \nobr{\var{seconds\/}}) into brief descriptive text. \fnpackage \code{:gbbopen-tools} \fnmodule \code{:gbbopen-tools} \fnargs \begin{args}{maximum-fields} \arg[seconds] A number \arg[maximum-fields] An integer from 1--5 indicating maximum number of fields to include in the descriptive \var{string\/} (default is 5, indicating all fields should be included) \arg[destination] Either \nil, \code{t}, a stream, or a string with a fill pointer (default is \nil) \arg[result] A string or \nil{} \end{args} \fnreturns If \var{destination\/} is non-\nil, then \nil; otherwise, a string. \fndescription The value of \var{seconds\/} is rounded to the nearest 100$^{th}$ of a second before conversion. Fields omitted by \nobr{\var{maximum-fields\/}} cause appropriate rounding of the generated description. \begin{alsos}{pretty-run-time-duration} \also[brief-run-time-duration] \also[parse-duration] \also[pretty-duration] \also[pretty-run-time-duration] \end{alsos} \fnexamples % \W\supp \begin{example} > (brief-duration 1000) "16m 40s" > (brief-duration -1000) "-16m 40s" > (brief-duration -1000.12345) "-16m 40.12s" > (brief-duration -1000.12543) "-16m 40.13s"\goodpagebreak > (brief-duration 166611.9) "1d 22h 16m 51.91s" > (brief-duration 166611.9 4) "1d 22h 16m 52s" > (brief-duration 166611.9 3) "1d 22h 17m" > (brief-duration 166611.9 2) "1d 22h" > (brief-duration 166611.9 1) "2d" > (brief-duration 31556952) "365d 5h 49m 12s" > \end{example} \end{functiondoc} %% ------------------------------------------------------------------------ \begin{functiondoc}{Function}{brief-run-time-duration}{% \nobr{\var{internal-time-units\/}} \nobr{\code{\&optional} \var{maximum-fields destination\/}} \nobr{\returns{} \var{result\/}}} \index{time!duration, formatting}% \index{duration!formatting}% \index{internal time units, formatting}% \fnsyntax \fnpurpose Format a run-time duration (in \nobr{\var{internal-time-units\/}}) into brief descriptive text. \fnpackage \code{:gbbopen-tools} \fnmodule \code{:gbbopen-tools} \fnargs \begin{args}{internal-time-units} \arg[internal-time-units] A number \arg[maximum-fields] An integer from 1--5 indicating maximum number of fields to include in the descriptive \var{string\/} (default is 5, indicating all fields should be included) \arg[destination] Either \nil, \code{t}, a stream, or a string with a fill pointer (default is \nil) \arg[result] A string or \nil{} \end{args} \fnreturns If \var{destination\/} is non-\nil, then \nil; otherwise, a string. \fndescription The \var{internal-time-units\/} run-time duration is rounded to the nearest 100$^{th}$ of a second before conversion. Fields omitted by \nobr{\var{maximum-fields\/}} cause appropriate rounding of the generated description. \begin{alsos}{brief-run-time-duration} \also[brief-duration] \also[parse-duration] \also[pretty-duration] \also[pretty-run-time-duration] \end{alsos} \fnexamples % \W\supp \begin{example} > internal-time-units-per-second 1000 > (brief-run-time-duration 1000) "1s" > (brief-run-time-duration 5) "0s" > (brief-run-time-duration 6) "0.01s" > most-positive-fixnum 536870911 > (brief-run-time-duration most-positive-fixnum) "6d 5h 7m 50.94s" > \end{example} \end{functiondoc} %% ------------------------------------------------------------------------ \begin{functiondoc}{Function}{encode-date-and-time}{% \var{string\/} \nobr{\code{\&key} \var{start end}} \var{\nobr{junk-allowed} \nobr{date-separators} \nobr{time-separators} \nobr{month-precedes-date} \nobr{year-first} \nobr{default-to-current-year} \nobr{time-first} \nobr{time-zone}\/} \nobr{\returns{} \nobr{\var{universal-time,} pos\/}}} \index{date!parsing}% \fnsyntax \fnpurpose Parse and then encode a date-and-time specification string to a \glref{Universal~Time}. \fnpackage \code{:gbbopen-tools} \fnmodule \code{:gbbopen-tools} \fnargs \begin{args}{default-to-current-year} \arg[string] A string \arg[start] Starting index into \var{string\/} (default is \code{0}) \arg[end] Ending index into \var{string\/} (default is \nil, meaning end of \var{string\/}) \arg[junk-allowed] A \glref{generalized~boolean} (default is \nil) \arg[date-separators] A sequence of characters that are skipped and separate the date, month, and year fields in \var{string}, if needed (default is \nobr{\code{"-/ ,"}}) \arg[time-separators] A sequence of characters that are skipped and separate the hour, minute, and second fields in \var{string}, if needed (default is \nobr{\code{" :"}}) \arg[month-precedes-date] A \glref{generalized~boolean} (default is \nobr{\textbf{\entlink{*month-precedes-date*}}}) \arg[year-first] A \glref{generalized~boolean} (default is \nobr{\textbf{\entlink{*year-first*}}}) \arg[default-to-current-year] A \glref{generalized~boolean} (default is \nil) \arg[time-first] A \glref{generalized~boolean} (default is \nobr{\textbf{\entlink{*time-first*}}}) \arg[time-zone] A \glref{time~zone} (default is \nil, which is equivalent to the current time zone adjusted for daylight saving time) \arg[universal-time] A \glref{Universal~Time} \arg[position] A index in \var{string\/} \end{args} \fnreturns Two values: \var{universal-time} and \nobr{\var{position}} \fnerrors % If \var{junk-allowed\/} is false, an error is signaled if a numeric field in \var{string\/} does not consist entirely of the representation of a integer, possibly surrounded on either side by characters in \nobr{\var{separators}}. \fndescription % Both the month and date must be specified in \var{string}, optionally followed by the year and the time of day. The month can be a numeric value (1--12), a three-letter abbreviation, or the full month name. If the month is specified numerically, then the value of \nobr{\var{month-precedes-date\/}} is used to determine the month and date ordering. If no year is specified in \var{string} and \nobr{\var{default-to-current-year\/}} is \nil, the current calendar year is assumed, unless the specified month and date have passed, in which case the next year is assumed. If no year is specified in \var{string} and \nobr{\var{default-to-current-year\/}} is true, the current calendar year is always assumed. If no hour, minute, or second values are specified, they default to zero. \W\xml{p} % If \var{month-precedes-date\/} is true, the month is expected before the date; otherwise the date is expected to follow the month. \W\xml{p} % If \var{year-first\/} is supplied and is non-\nil, the year must be provided and it is expected before the month and date; otherwise the year (if provided) is expected to follow the month and date. \W\xml{p} % If a time-zone is specified in \var{string}, it is used when encoding the \nobr{\var{universal-time\/}} value. Otherwise, if a non-\nil{} \nobr{\var{time-zone\/}} argument was supplied, it used for the encoding. Otherwise, the current time zone adjusted for daylight saving time is used. \W\xml{p} % If \var{time-first\/} is true, the time-of-day is expected before the date; otherwise the time-of-day is expected to follow the date. \W\xml{p} % The returned \var{position\/} is the index within \var{string\/} where the parse ended. \begin{alsos}{*month-precedes-date*} \also[*month-precedes-date*] \also[encode-date-and-time] \also[encode-time-of-day] \also[parse-date] \also[parse-date-and-time] \also[parse-duration] \also[parse-time] \end{alsos} \fnexamples % \W\supp \begin{example} > (encode-date-and-time "1 Apr 2010") 3479083200 10 > (encode-date-and-time "April 1, 2010 10:30") 3479121000 19\goodpagebreak > (encode-date-and-time "Thu 1 Apr 2010") 3479083200 14 > (encode-date-and-time "Thursday, April 1, 2010 10:30") 3479121000 29\goodpagebreak > (encode-date-and-time "4/1/10 10:30pm") 3479164200 14 > (encode-date-and-time "10:30pm 4/1/10" :time-first 't) 3479164200 14\goodpagebreak > (encode-date-and-time "Apr 1 2010 10:30 EDT") 3479121000 20\goodpagebreak > (encode-date-and-time "Apr 1 2010 10:30PM EDT") 3479164200 22\goodpagebreak > (encode-date-and-time "1 Apr 2010 10:30 IST") 3479086800 20\goodpagebreak > (encode-date-and-time "1 Apr 2010 10:30" :time-zone -11/2) 3479121000 20\goodpagebreak > (encode-date-and-time "1 Apr 2010 10:30 EDT" :time-zone -11/2) 3479086800 16\goodpagebreak > (encode-date-and-time "April 1, 2010 10:30 UTC-4") 3479121000 25 > \end{example} \replnote % \REPLindex{:ut}% % The equivalent of: % \W\supp \begin{example} (print (\entlink{encode-date-and-time} \var{string\/})) \end{example} % can be invoked using the \glref{REPL~command} \nobr{\code{:ut} \var{string\/}}. \end{functiondoc} %% ------------------------------------------------------------------------ \begin{functiondoc}{Function}{encode-time-of-day}% {\var{second minute hour\/} \nobr{\code{\&optional} \var{universal-time}\/} \nobr{\returns{} \var{\nobr{universal-time}\/}}} \fnsyntax \fnpurpose Return a \glref{Universal~Time} representing a specified time-of-day. \fnpackage \code{:gbbopen-tools} (or \code{:portable-threads} if Portable Threads is used without GBBopen Tools) \fnmodule \code{:gbbopen-tools} (or \code{:portable-threads} if Portable Threads is used without GBBopen Tools) \fnargs \begin{args}{universal-time} \arg[second] An integer between 0 and 59, inclusive \arg[minute] An integer between 0 and 59, inclusive \arg[hour] An integer between 0 and 23, inclusive \arg[universal-time] A \glref{Universal~Time} (default is \nil, which is equivalent to the value returned by \nobr{\code{(get-universal-time)}}) \end{args} \fndescription If the specified time-of-date has already passed (relative to the \nobr{\var{universal-time\/}} value), the next day is assumed. \begin{alsos}{encode-date-and-time} \also[encode-date-and-time] \end{alsos} \bfindexit{make-scheduled-function}% \bfindexit{schedule-function}% \fnexamples Schedule a \glref{scheduled~function} that prints \nobr{\code{"It's quitting time!"}} every day at 5pm: % \W\supp \begin{example} > (\entlink{schedule-function} (\entlink{make-scheduled-function} #'(lambda (scheduled-function) (declare (ignore scheduled-function)) (print "It's quitting time!")) :name 'quitting-time) (encode-time-of-day 0 0 17) :repeat-interval #.(* 24 60 60)) > \end{example} \bfindexit{schedule-function}% Verbosely change \nobr{\code{quitting-time}} to 5:30pm every day: % \W\supp \begin{example} > (\entlink{schedule-function} 'quitting-time (encode-time-of-day 0 30 17) :repeat-interval #.(* 24 60 60) :verbose 't) ;; Unscheduling #... ;; Scheduling # ;; as the next scheduled-function... > \end{example} \end{functiondoc} %% ------------------------------------------------------------------------ \begin{functiondoc}{Function}{full-date-and-time}{% \code{\&optional} \var{universal-time\/} \nobr{\code{\&key} \var{time-zone}} \var{\nobr{daylight-savings-p} \nobr{all-numeric} \nobr{separator} \nobr{full-names} \nobr{month-precedes-date} \nobr{year-first} \nobr{include-day} \nobr{include-seconds} \nobr{include-time-zone} \nobr{utc-offset-only} \nobr{12-hour} destination\/} \nobr{\returns{} \var{result\/}}} \index{date!formatted}% \index{time, formatted}% \fnsyntax \fnpurpose Generate a date-and-time description. \fnpackage \code{:gbbopen-tools} \fnmodule \code{:gbbopen-tools} \fnargs \begin{args}{daylight-savings-p} \arg[universal-time] A \glref{Universal~Time} (default is \nil, which is equivalent to the value returned by \nobr{\code{(get-universal-time)}}) \arg[time-zone] A \glref{time~zone} (default is \nil, which is equivalent to the current time zone adjusted for daylight saving time) \arg[daylight-savings-p] A \glref{generalized~boolean} (default is \nil) \arg[all-numeric] A \glref{generalized~boolean} (default is \nil) \arg[separator] A character (default is \code{\#\bkslash/}) \arg[full-names] A \glref{generalized~boolean} (default is \nil) \arg[month-precedes-date] A \glref{generalized~boolean} (default is \nobr{\textbf{\entlink{*month-precedes-date*}}}) \arg[year-first] A \glref{generalized~boolean} (default is \nobr{\textbf{\entlink{*year-first*}}}) \arg[include-day] A \glref{generalized~boolean} (default is \nil) \arg[include-time-zone] A \glref{generalized~boolean} (default is \nil) \arg[utc-offset-only] A \glref{generalized~boolean} (default is \nil) \arg[12-hour] A \glref{generalized~boolean} (default is \nil) \arg[destination] Either \nil, \code{t}, a stream, or a string with a fill pointer (default is \nil) \arg[result] A string or \nil{} \end{args} \fnreturns If \var{destination\/} is non-\nil, then \nil; otherwise, a string. \fndescription A 17-character description (longer if \nobr{\var{full-names\/}}, \nobr{\var{include-day\/}}, \nobr{\var{include-seconds\/}}, \nobr{\var{include-time-zone\/}}, or \nobr{\var{utc-offset-only\/}} are non-\nil{}) is generated. \W\xml{p} \bfindexit{get-universal-time}% % If \nobr{\var{universal-time\/}} is not supplied or is \nil, the current time (as returned by \nobr{\code{get-universal-time}} is used. \W\xml{p} % If \var{time-zone\/} is not supplied or is \nil, it defaults to the current time zone adjusted for daylight saving time. If a \nobr{\var{time-zone\/}} is supplied, it is assumed to include any adjustment for daylight saving time unless \nobr{\var{daylight-savings-p\/} is specified and is non-\nil}. \W\xml{p} % If \var{all-numeric\/} is supplied and is non-\nil, the month is indicated by its numeric value, and the date, month, and year are separated by the \var{separator\/} character. \W\xml{p} % If \var{full-names\/} is supplied and is non-\nil, the full name is generated rather than the abbreviated name for the month (if \var{include-day\/} is \nil) and for the day of the week, (if \var{include-day\/} is non-\nil). \W\xml{p} % If \var{month-precedes-date\/} is true, the month is presented in front of the date; otherwise the date precedes the month. \W\xml{p} % If \var{year-first\/} is supplied and is non-\nil, the year is presented in front of the month and date; otherwise the year follows the month and date. \W\xml{p} % If \var{include-day\/} is supplied and is non-\nil, the day of the week is included in front of the date and time. \W\xml{p} % If \var{include-seconds\/} is supplied and is non-\nil, seconds are included in the presented time. \W\xml{p} % If either \var{include-time-zone\/} or \var{utc-offset-only\/} is true, a time-zone specification is appended to the date-and-time presentation. If \var{utc-offset-only\/} is true, the time zone is presented as a UTC offset---even if a \link{{time-zone abbreviation}}{ref:timezones} supported by GBBopen Tools is available for the time zone. If a \nobr{\var{time-zone\/}} is supplied, the value of \nobr{\var{daylight-savings-p\/}} is used when generating a non-UTC time zone abbreviation; otherwise, the local daylight-savings setting for the \nobr{\var{universal-time\/}} value (as determined by \code{decode-universal-time}) is used, and the \nobr{\var{daylight-savings-p\/}} argument is ignored. \W\xml{p} % If \var{12-hour\/} is supplied and is non-\nil, the time-of-day is presented in AM/PM format. \begin{alsos}{internet-text-date-and-time} \also[*month-precedes-date*] \also[brief-date] \also[brief-date-and-time] \also[encode-date-and-time] \also[http-date-and-time] \also[internet-text-date-and-time] \also[iso8601-date-and-time] \also[message-log-date-and-time] \also[parse-date-and-time] \also[very-brief-date] \end{alsos} \fnexamples Display the current date and time: % \W\supp \begin{example} > (full-date-and-time) "Feb 16 2009 13:11" > \end{example} % Display the current date and time (with seconds): % \W\supp\notpretop \begin{example} > (full-date-and-time nil :include-seconds 't) "Feb 16 2009 13:11:38" > \end{example} % Display the current date and time (with the day of the week): % \W\supp\notpretop \begin{example} > (full-date-and-time nil :include-day 't) "Mon Feb 16 2009 13:11" > \end{example} % Display the current date and time (with no abbreviations and with the day of the week): % \W\supp\notpretop \begin{example} > (full-date-and-time nil :full-names 't :include-day 't) "Monday, February 16, 2009 13:11" > \end{example} % Display the current date and time (with no abbreviations, with the month following the date, and with the day of the week): % \W\supp\notpretop \begin{example} > (full-date-and-time nil :full-names 't :include-day 't :month-precedes-date nil) "Monday, 16 February, 2009 13:11" > \end{example} % Display the current date and time (with no abbreviations, with the year first and the month following the date, and with the day of the week): % \W\supp\notpretop \begin{example} > (full-date-and-time nil :full-names 't :include-day 't :year-first 't :month-precedes-date nil) "2009, 16 February, Monday 13:11" > \end{example} % Display the current date and time (all numeric, with the abbreviated day of the week): % \W\supp\notpretop \begin{example} > (full-date-and-time nil :all-numeric 't :include-day 't) "Mon 02/16/2009 13:11" > \end{example} % Display the current date and time (all numeric, with hyphen (minus-sign) separators): % \W\supp\notpretop \begin{example} > (full-date-and-time nil :all-numeric 't :separator #\-) "02-16-2009 13:11" > \end{example} % Display the current date and time (all numeric, with the year first and the abbreviated day of the week): % \W\supp\notpretop \begin{example} > (full-date-and-time nil :all-numeric 't :year-first 't :include-day 't) "2009/02/16 Mon 13:11" > \end{example} % Display the current date and time (all numeric, with the month following the date, and with the full day of the week): % \W\supp\notpretop \begin{example} > (full-date-and-time nil :all-numeric 't :include-day 't :full-names 't :month-precedes-date nil) "Monday, 16/02/2009 13:11" > \end{example} % Display the current date and time (with time zone): % \W\supp\notpretop \begin{example} > (full-date-and-time nil :include-time-zone 't) "Feb 16 2009 13:11 EST" > \end{example} % Display the current date and time (in 12-hour format with time zone): % \W\supp\notpretop \begin{example} > (full-date-and-time nil :12-hour 't :include-time-zone 't) "Feb 16 2009 1:11PM EST" > \end{example} % Display the current date and time (with UTC-offset time zone): % \W\supp\notpretop \begin{example} > (full-date-and-time nil :utc-offset-only 't) "Feb 16 2009 13:11 UTC-5" > \end{example} % Display the current date and time (with seconds and time zone): % \W\supp\notpretop \begin{example} > (full-date-and-time nil :include-seconds 't :include-time-zone 't) "Feb 16 2009 13:11:38 EST" > \end{example} % Display the current date and time as GMT: % \W\supp\notpretop \begin{example} > (full-date-and-time nil :time-zone 0) "Feb 16 2009 18:11" > \end{example} Display the current date and time as GMT (with time zone): % \W\supp\notpretop \begin{example} > (full-date-and-time nil :time-zone 0 :include-time-zone 't) "Feb 16 2009 18:11 GMT" > \end{example} % The date and time 10 days ago: % \bfindexit{parse-duration}% \W\supp\notpretop \begin{example} > (full-date-and-time (- (get-universal-time) (\entlink{parse-duration} "10 days"))) "Feb 6 2009 13:11" > \end{example} % The date and time 125 days ago: % \W\supp\notpretop \begin{example} > (full-date-and-time (- (get-universal-time) (\entlink{parse-duration} "125 days"))) "Oct 12 2008 13:11" > \end{example} % The date and time 125 days ago (with seconds): % \W\supp\notpretop \begin{example} > (full-date-and-time (- (get-universal-time) (\entlink{parse-duration} "125d")) :include-seconds 't) "Oct 12 2008 13:11:38" > \end{example} \replnote % \REPLindex{:ut}% % The equivalent of: % \W\supp \begin{example} (print (\entlink{full-date-and-time} \var{universal-time\/} :include-seconds 't)) \end{example} % can be invoked using the \glref{REPL~command} \nobr{\code{:ut} \var{universal-time\/}}. \end{functiondoc} %% ------------------------------------------------------------------------ \begin{functiondoc}{Function}{http-date-and-time}{% \nobr{\code{\&optional} \var{universal-time\/}} \nobr{\code{\&key} \var{destination\/}} \nobr{\returns{} \var{result\/}}} \index{time!formatting}% \fnsyntax \fnpurpose Convert a \glref{Universal~Time} value into HTTP/1.1 time-stamp format. \fnpackage \code{:gbbopen-tools} \fnmodule \code{:gbbopen-tools} \fnargs \begin{args}{universal-time} \arg[universal-time] A \glref{Universal~Time} (default is \nil, which is equivalent to the value returned by \nobr{\code{(get-universal-time)}}) \arg[destination] Either \nil, \code{t}, a stream, or a string with a fill pointer (default is \nil) \arg[result] A string or \nil{} \end{args} \fnreturns If \var{destination\/} is non-\nil, then \nil; otherwise, a string. \fndescription \bfindexit{get-universal-time}% % If \nobr{\var{universal-time\/}} is not supplied or is \nil, the current time (as returned by \nobr{\code{get-universal-time}} is used. \begin{alsos}{internet-text-date-and-time} \also[brief-date] \also[brief-date-and-time] \also[full-date-and-time] \also[http-date-and-time] \also[internet-text-date-and-time] \also[iso8601-date-and-time] \also[message-log-date-and-time] \also[very-brief-date] \end{alsos} \fnexample % \W\supp \begin{example} > (http-date-and-time) "Wed, 05 Aug 2009 17:29:26 GMT" > \end{example} \end{functiondoc} %% ------------------------------------------------------------------------ \begin{functiondoc}{Function}{internet-text-date-and-time}{% \nobr{\code{\&optional} \var{universal-time\/}} \nobr{\code{\&key} \var{time-zone}} \var{\nobr{daylight-savings-p} \nobr{utc-offset-only} destination\/} \nobr{\returns{} \var{result\/}}} \index{time!formatting}% \fnsyntax \fnpurpose Convert a \glref{Universal~Time} value into Internet Text Message format. \fnpackage \code{:gbbopen-tools} \fnmodule \code{:gbbopen-tools} \fnargs \begin{args}{daylight-savings-p} \arg[universal-time] A \glref{Universal~Time} (default is \nil, which is equivalent to the value returned by \nobr{\code{(get-universal-time)}}) \arg[time-zone] A \glref{time~zone} (default is \nil, which is equivalent to the current time zone adjusted for daylight saving time) \arg[daylight-savings-p] A \glref{generalized~boolean} (default is \nil) \arg[utc-offset-only] A \glref{generalized~boolean} (default is \nil) \arg[destination] Either \nil, \code{t}, a stream, or a string with a fill pointer (default is \nil) \arg[result] A string or \nil{} \end{args} \fnreturns If \var{destination\/} is non-\nil, then \nil; otherwise, a string. \fndescription \bfindexit{get-universal-time}% % If \nobr{\var{universal-time\/}} is not supplied or is \nil, the current time (as returned by \nobr{\code{get-universal-time}} is used. \W\xml{p} % If \var{utc-offset-only\/} is true, the time zone is represented as a UTC offset---even if a \link{{time-zone abbreviation}}{ref:timezones} supported by GBBopen Tools is available for the time zone. If a \nobr{\var{time-zone\/}} is supplied, the value of \nobr{\var{daylight-savings-p\/}} is used when generating a non-UTC time zone abbreviation; otherwise, the local daylight-savings setting for the \nobr{\var{universal-time\/}} value (as determined by \code{decode-universal-time}) is used, and the \nobr{\var{daylight-savings-p\/}} argument is ignored. \begin{alsos}{iso8601-date-and-time} \also[brief-date] \also[brief-date-and-time] \also[full-date-and-time] \also[http-date-and-time] \also[iso8601-date-and-time] \also[message-log-date-and-time] \also[very-brief-date] \end{alsos} \fnexamples % \W\supp \begin{example} > (internet-text-date-and-time) "Sat, 17 May 2008 04:02:49 -0400 (EDT)" > (internet-text-date-and-time nil :time-zone 0) "Sat, 17 May 2008 08:02:50 -0000 (GMT)" > \end{example} \end{functiondoc} %% ------------------------------------------------------------------------ \begin{functiondoc}{Function}{iso8601-date-and-time}{% \nobr{\code{\&optional} \var{universal-time\/}} \nobr{\code{\&key} \var{destination\/}} \nobr{\returns{} \var{result\/}}} \index{time!formatting}% \fnsyntax \fnpurpose Convert a \glref{Universal~Time} value into ISO8601 (XML dateTime) format. \fnpackage \code{:gbbopen-tools} \fnmodule \code{:gbbopen-tools} \fnargs \begin{args}{universal-time} \arg[universal-time] A \glref{Universal~Time} (default is \nil, which is equivalent to the value returned by \nobr{\code{(get-universal-time)}}) \arg[destination] Either \nil, \code{t}, a stream, or a string with a fill pointer (default is \nil) \arg[result] A string or \nil{} \end{args} \fnreturns If \var{destination\/} is non-\nil, then \nil; otherwise, a string. \fndescription \bfindexit{get-universal-time}% % If \nobr{\var{universal-time\/}} is not supplied or is \nil, the current time (as returned by \nobr{\code{get-universal-time}} is used. \begin{alsos}{internet-text-date-and-time} \also[brief-date] \also[brief-date-and-time] \also[full-date-and-time] \also[http-date-and-time] \also[internet-text-date-and-time] \also[message-log-date-and-time] \also[very-brief-date] \end{alsos} \fnexample % \W\supp \begin{example} > (iso8601-date-and-time) "2008-05-17T08:02:49Z" > \end{example} \end{functiondoc} %% ------------------------------------------------------------------------ \begin{functiondoc}{Function}{message-log-date-and-time}{% \nobr{\code{\&optional} \var{universal-time\/}} \nobr{\code{\&key} \var{destination\/}} \nobr{\returns{} \var{result\/}}} \index{time!formatting}% \fnsyntax \fnpurpose Convert a \glref{Universal~Time} value into ``message log'' \nobr{(\code{MMM DD HH:MM:SS})} format. \fnpackage \code{:gbbopen-tools} \fnmodule \code{:gbbopen-tools} \fnargs \begin{args}{universal-time} \arg[universal-time] A \glref{Universal~Time} (default is \nil, which is equivalent to the value returned by \nobr{\code{(get-universal-time)}} \arg[destination] Either \nil, \code{t}, a stream, or a string with a fill pointer (default is \nil) \arg[result] A string or \nil{} \end{args} \fnreturns If \var{destination\/} is non-\nil, then \nil; otherwise, a string. \fndescription \bfindexit{get-universal-time}% % If \nobr{\var{universal-time\/}} is not supplied or is \nil, the current time (as returned by \nobr{\code{get-universal-time}} is used. \begin{alsos}{internet-text-date-and-time} \also[brief-date] \also[brief-date-and-time] \also[full-date-and-time] \also[http-date-and-time] \also[internet-text-date-and-time] \also[iso8601-date-and-time] \also[very-brief-date] \end{alsos} \fnexample % \W\supp \begin{example} > (message-log-date-and-time) "May 17 04:02:49" > \end{example} \end{functiondoc} %% ------------------------------------------------------------------------ \begin{functiondoc}{Function}{parse-date}{% \var{string\/} \code{\&key} \var{start end \nobr{junk-allowed} \nobr{separators} \nobr{month-precedes-date} \nobr{year-first} \nobr{default-to-current-year}\/} \nobr{\returns{} \var{date, month, year, position\/}}} \index{date!parsing}% \fnsyntax \fnpurpose Parse a date-specification string. \fnpackage \code{:gbbopen-tools} (home package is \nobr{\code{:module-manager}}) \fnmodule \code{:module-manager} \fnargs \begin{args}{default-to-current-year} \arg[string] A simple string \arg[start] Starting index into \var{string\/} (default is \code{0}) \arg[end] Ending index into \var{string\/} (default is \nil, meaning end of \var{string\/}) \arg[junk-allowed] A \glref{generalized~boolean} (default is \nil) \arg[separators] A sequence of characters that are skipped and separate the date, month, and year fields in \var{string}, if needed (default is \nobr{\code{"-/ ,"}}) \arg[month-precedes-date] A \glref{generalized~boolean} (default is \nobr{\textbf{\entlink{*month-precedes-date*}}}) \arg[year-first] A \glref{generalized~boolean} (default is \nobr{\textbf{\entlink{*year-first*}}}) \arg[default-to-current-year] A \glref{generalized~boolean} (default is \nil) \arg[date] An integer between 1 and up to 31, inclusive, depending on the month and year \arg[month] An integer between 1 and 12, inclusive \arg[year] An integer \arg[position] A index in \var{string\/} \end{args} \fnreturns Four values: \var{date}, \var{month}, \var{year}, and \nobr{\var{position}} \fnerrors % If \var{junk-allowed\/} is false, an error is signaled if a numeric field in \var{string\/} does not consist entirely of the representation of a integer, possibly surrounded on either side by characters in \nobr{\var{separators}}. \fndescription % Both the month and date must be specified in \var{string}, optionally followed by the year and the time of day. The month can be a numeric value (1--12), a three-letter abbreviation, or the full month name. If the month is specified numerically, then the value of \nobr{\var{month-precedes-date\/}} is used to determine the month and date ordering. If no year is specified in \var{string} and \nobr{\var{default-to-current-year\/}} is \nil, the current calendar year is assumed, unless the specified month and date have passed, in which case the next year is assumed. If no year is specified in \var{string} and \nobr{\var{default-to-current-year\/}} is true, the current calendar year is always assumed. The returned \var{position\/} is the index within \var{string\/} where the parse ended. \begin{alsos}{*month-precedes-date*} \also[*month-precedes-date*] \also[encode-date-and-time] \also[encode-time-of-day] \also[parse-date-and-time] \also[parse-duration] \also[parse-time] \end{alsos} \fnexamples % \W\supp \begin{example} > (parse-date "1 Apr 2010") 1 4 2010 10 > (parse-date "April 1, 2010") 1 4 2010 13 > (parse-date "Thu 1 Apr 2010") 1 4 2010 14 > (parse-date "Thursday, April 1, 2010") 1 4 2010 23\goodpagebreak > (parse-date "1-4-10" :month-precedes-date 't) 4 1 2010 6 > (parse-date "1-4-10" :month-precedes-date nil) 1 4 2010 6\goodpagebreak > (parse-date "1-4-10" :month-precedes-date 't :year-first 't) 10 4 2001 6 > (parse-date "1-4-10" :month-precedes-date nil :year-first 't) 4 10 2001 6\goodpagebreak > (parse-date "4 Jul") \textcolor{darkergray}{;; entered May 1, 2008} 4 7 2008 5 > (parse-date "4 Jul") \textcolor{darkergray}{;; entered August 1, 2008} 4 7 2009 5 > (parse-date "4 Jul" \textcolor{darkergray}{;; entered August 1, 2008} :default-to-current-year 't) 4 7 2008 5 > (parse-date "4/7 " :month-precedes-date nil) 4 7 2008 5\goodpagebreak > (parse-date "4/7 junk" :junk-allowed 't) 7 4 2008 5 > \end{example} \fnnote \indexit{module!:module-manager@\code{:module-manager}}% \indexit{:module-manager@\code{:module-manager} module}% % This function is loaded with the \nobr{\code{:module-manager}} \glref{module} in order to to make it available as early as possible. \end{functiondoc} %% ------------------------------------------------------------------------ \begin{functiondoc}{Function}{parse-date-and-time}{% \var{string\/} \code{\&key} \var{start end \nobr{junk-allowed} \nobr{date-separators} \nobr{time-separators} \nobr{month-precedes-date} \nobr{year-first} \nobr{default-to-current-year} \nobr{time-first}\/} \nobr{\returns{} \var{second, minute, hour,}} \var{date, month, year, \nobr{time-zone,} \nobr{daylight-savings-p,} pos\/}} \index{date!parsing}% \fnsyntax \fnpurpose Parse a date-and-time specification string. \fnpackage \code{:gbbopen-tools} \fnmodule \code{:gbbopen-tools} \fnargs \begin{args}{default-to-current-year} \arg[string] A simple string \arg[start] Starting index into \var{string\/} (default is \code{0}) \arg[end] Ending index into \var{string\/} (default is \nil, meaning end of \var{string\/}) \arg[junk-allowed] A \glref{generalized~boolean} (default is \nil) \arg[date-separators] A sequence of characters that are skipped and separate the date, month, and year fields in \var{string}, if needed (default is \nobr{\code{"-/ ,"}}) \arg[time-separators] A sequence of characters that are skipped and separate the hour, minute, and second fields in \var{string}, if needed (default is \nobr{\code{" :"}}) \arg[month-precedes-date] A \glref{generalized~boolean} (default is \nobr{\textbf{\entlink{*month-precedes-date*}}}) \arg[year-first] A \glref{generalized~boolean} (default is \nobr{\textbf{\entlink{*year-first*}}}) \arg[default-to-current-year] A \glref{generalized~boolean} (default is \nil) \arg[time-first] A \glref{generalized~boolean} (default is \nobr{\textbf{\entlink{*time-first*}}}) \arg[second] An integer between 0 and up to 59, inclusive \arg[minute] An integer between 0 and up to 59, inclusive \arg[hour] An integer between 0 and up to 23, inclusive \arg[date] An integer between 1 and up to 31, inclusive, depending on the month and year \arg[month] An integer between 1 and 12, inclusive \arg[year] An integer \arg[time-zone] A time zone: a rational multiple of 1/3600 between -24 and 24 that represents the number of hours offset from GMT \arg[daylight-savings-p] A \glref{generalized~boolean} \arg[position] A index in \var{string\/} \end{args} \fnreturns Nine values: \var{second}, \var{minute}, \var{hour}, \var{date}, \var{month}, \var{year}, \nobr{\var{time-zone}}, \nobr{\var{daylight-savings-p}}, and \nobr{\var{position}} \fnerrors % If \var{junk-allowed\/} is false, an error is signaled if a numeric field in \var{string\/} does not consist entirely of the representation of a integer, possibly surrounded on either side by characters in \nobr{\var{separators}}. \fndescription % Both the month and date must be specified in \var{string}, optionally followed by the year and the time of day. The month can be a numeric value (1--12), a three-letter abbreviation, or the full month name. If the month is specified numerically, then the value of \nobr{\var{month-precedes-date\/}} is used to determine the month and date ordering. If no year is specified in \var{string} and \nobr{\var{default-to-current-year\/}} is \nil, the current calendar year is assumed, unless the specified month and date have passed, in which case the next year is assumed. If no year is specified in \var{string} and \nobr{\var{default-to-current-year\/}} is true, the current calendar year is always assumed. If no hour, minute, or second values are specified, they default to zero. The values returned for \nobr{\var{time-zone}} and \nobr{\var{daylight-savings-p}} will be \nil{} unless a time-zone is specified in \var{string}. \W\xml{p} % If \var{month-precedes-date\/} is true, the month is expected before the date; otherwise the date is expected to follow the month. \W\xml{p} % If \var{year-first\/} is supplied and is non-\nil, the year must be provided and it is expected before the month and date; otherwise the year (if provided) is expected to follow the month and date. \W\xml{p} % If a time-zone is specified in \var{string}, it is used when encoding the \nobr{\var{universal-time\/}} value. Otherwise, if a non-\nil{} \nobr{\var{time-zone\/}} argument was supplied, it used for the encoding. Otherwise, the current time zone adjusted for daylight saving time is used. \W\xml{p} % If \var{time-first\/} is true, the time-of-day is expected before the date; otherwise the time-of-day is expected to follow the date. \W\xml{p} % The returned \var{position\/} is the index within \var{string\/} where the parse ended. \begin{alsos}{*month-precedes-date*} \also[*month-precedes-date*] \also[encode-date-and-time] \also[encode-time-of-day] \also[full-date-and-time] \also[parse-date] \also[parse-duration] \also[parse-time] \end{alsos} \fnexamples % \W\supp \begin{example} > (parse-date-and-time "1 Apr 2010") 0 0 0 1 4 2010 nil nil 10\goodpagebreak > (parse-date-and-time "April 1, 2010 10:30") 0 30 10 1 4 2010 nil nil 19\goodpagebreak > (parse-date-and-time "4/1/10 10:30pm") 0 30 22 1 4 2010 nil nil 14 > (parse-date-and-time "10:30pm 4/1/10" :time-first 't) 0 30 22 1 4 2010 nil nil 14\goodpagebreak > (parse-date-and-time "Apr 1 2010 10:30 EDT") 0 30 10 1 4 2010 4 t 20\goodpagebreak > (parse-date-and-time "1 Apr 2010 10:30 IST") 0 30 10 1 4 2010 -11/2 nil 20\goodpagebreak > (parse-date-and-time "April 1, 2010 10:30 UTC-7") 0 30 10 1 4 2010 7 nil 25 > \end{example} \end{functiondoc} %% ------------------------------------------------------------------------ \begin{functiondoc}{Function}{parse-duration}{% \var{string\/} %% units keyword is not documented: \nobr{\code{\&key} \var{start end separators\/}} \nobr{\returns{} \var{seconds\/}}} \index{duration!parsing}% \fnsyntax \fnpurpose Parse a time-duration-specification string. \fnpackage \code{:gbbopen-tools} \fnmodule \code{:gbbopen-tools} \fnargs \begin{args}{month-precedes-date} \arg[string] A simple string \arg[start] Starting index into \var{string\/} (default is \code{0}) \arg[end] Ending index into \var{string\/} (default is \nil, meaning end of \var{string\/}) \arg[separators] A sequence of characters that are skipped between specification items (default is \nobr{\code{" ,"}}) \end{args} \fnreturns The duration, in seconds \fndescription % The following time-duration-unit specifiers are recognized (both singular and plural): \W\supp\tabletop \begin{tabular}{@{}llll@{}} ~~~~~ & \code{"second"} & ~~ & (or \code{"sec"} or \code{"s"}) \\ & \code{"minute"} & & (or \code{"min"} or \code{"m"}) \\ & \code{"hour"} & & (or \code{"hr"} or \code{"h"}) \\ & \code{"day"} & & (or \code{"d"}) \\ & \code{"week"} & & (or \code{"wk"}) \\ & \code{"month"} & & (or \code{"mon"}) \\ & \code{"year"} & & (or \code{"yr"}) \\ \end{tabular} \T\\ A \code{"month"} is interpreted as exactly 30 days; a \nobr{\code{"year"}} as 365 days. \begin{alsos}{encode-date-and-time} \also[brief-duration] \also[encode-date-and-time] \also[encode-time-of-day] \also[parse-date] \also[parse-date-and-time] \also[pretty-duration] \also[parse-time] \end{alsos} \fnexamples % \W\supp \begin{example} > (parse-duration "2 minutes") 60 > (parse-duration "-2min") -60 > (parse-duration "2m") 60\goodpagebreak > (parse-duration "365 days, 5 hours, 49 minutes, 12 seconds" 31556952 > (parse-duration "365d 5h 49m 12s") 31556952 > (parse-duration "365d5h49m12s") 31556952\goodpagebreak > (parse-duration "1min -2secs") 58 > (parse-duration "1m-2s") 58\goodpagebreak > (parse-duration "1/2hr") 1800 > (parse-duration "0.5hr") 1800.0\goodpagebreak > (parse-duration "2 months") 5184000 > (parse-duration "3 wks") 1814400 \end{example} \end{functiondoc} %% ------------------------------------------------------------------------ \begin{functiondoc}{Function}{parse-time}{% \var{string\/} \nobr{\code{\&key} \var{start end junk-allowed separators\/}} \nobr{\returns{} \var{second, minute, hour,}} \var{\nobr{time-zone,} \nobr{daylight-savings-p,} pos\/}} \index{date!parsing}% \fnsyntax \fnpurpose Parse a time-of-day specification string. \fnpackage \code{:gbbopen-tools} \fnmodule \code{:gbbopen-tools} \fnargs \begin{args}{daylight-savings-p} \arg[string] A simple string \arg[start] Starting index into \var{string\/} (default is \code{0}) \arg[end] Ending index into \var{string\/} (default is \nil, meaning end of \var{string\/}) \arg[junk-allowed] A \glref{generalized~boolean} (default is \nil) \arg[separators] A sequence of characters that are skipped and separate the hour, minute, and second fields in \var{string}, if needed (default is \nobr{\code{" :"}}) \arg[second] An integer between 0 and up to 59, inclusive \arg[minute] An integer between 0 and up to 59, inclusive \arg[hour] An integer between 0 and up to 23, inclusive \arg[time-zone] A time zone: a rational multiple of 1/3600 between -24 and 24 that represents the number of hours offset from GMT \arg[daylight-savings-p] A \glref{generalized~boolean} \arg[position] A index in \var{string\/} \end{args} \fnreturns Six values: \var{second}, \var{minute}, \var{hour}, \nobr{\var{time-zone}}, \nobr{\var{daylight-savings-p}}, and \nobr{\var{position}} \fnerrors % If \var{junk-allowed\/} is false, an error is signaled if a numeric field in \var{string\/} does not consist entirely of the representation of a integer, possibly surrounded on either side by characters in \nobr{\var{separators}}. \fndescription % If no hour, minute, or second values are specified in \var{string}, they default to zero. The values returned for \nobr{\var{time-zone}} and \nobr{\var{daylight-savings-p}} will be \nil{} unless a time-zone is specified in \var{string}. The returned \var{position\/} is the index within \var{string\/} where the parse ended. \begin{alsos}{encode-date-and-time} \also[encode-date-and-time] \also[encode-time-of-day] \also[parse-date] \also[parse-date-and-time] \also[parse-duration] \also[parse-time] \end{alsos} \fnexamples % \W\supp \begin{example} > (parse-time "10:30") 0 30 10 nil nil 5\goodpagebreak > (parse-time "10:30pm") 0 30 22 nil nil 7\goodpagebreak > (parse-time "10:30 EDT") 0 30 10 4 t 9\goodpagebreak > (parse-time "10:30 IST") 0 30 10 -11/2 nil 9\goodpagebreak > (parse-time "10:30 UTC-7") 0 30 10 7 nil 11 > \end{example} \end{functiondoc} %% ------------------------------------------------------------------------ \begin{functiondoc}{Function}{pretty-duration}{% \var{seconds\/} \nobr{\code{\&optional} \var{maximum-fields destination\/}} \nobr{\returns{} \var{result\/}}} \index{time!duration, formatting}% \index{duration!formatting}% \fnsyntax \fnpurpose Format a numeric time duration (in \nobr{\var{seconds\/}}) into descriptive text. \fnpackage \code{:gbbopen-tools} \fnmodule \code{:gbbopen-tools} \fnargs \begin{args}{maximum-fields} \arg[seconds] A number \arg[maximum-fields] An integer from 1--5 indicating maximum number of fields to include in the descriptive \var{string\/} (default is 5, indicating all fields should be included) \arg[destination] Either \nil, \code{t}, a stream, or a string with a fill pointer (default is \nil) \arg[result] A string or \nil{} \end{args} \fnreturns If \var{destination\/} is non-\nil, then \nil; otherwise, a string. \fndescription The value of \var{seconds\/} is rounded to the nearest 100$^{th}$ of a second before conversion. Fields omitted by \nobr{\var{maximum-fields\/}} cause appropriate rounding of the generated description. \begin{alsos}{pretty-run-time-duration} \also[brief-duration] \also[brief-run-time-duration] \also[parse-duration] \also[pretty-run-time-duration] \end{alsos} \fnexamples % \W\supp \begin{example} > (pretty-duration 1000) "16 minutes, 40 seconds" > (pretty-duration -1000) "minus 16 minutes, 40 seconds" > (pretty-duration -1000.12345) "minus 16 minutes, 40.12 seconds" > (pretty-duration -1000.12543) "minus 16 minutes, 40.13 seconds"\goodpagebreak > (pretty-duration 166611.9) "1 day, 22 hours, 16 minutes, 51.91 seconds" > (pretty-duration 166611.9 4) "1 day, 22 hours, 16 minutes, 52 seconds" > (pretty-duration 166611.9 3) "1 day, 22 hours, 17 minutes" > (pretty-duration 166611.9 2) "1 day, 22 hours" > (pretty-duration 166611.9 1) "2 days"\goodpagebreak > (pretty-duration 31556952) "365 days, 5 hours, 49 minutes, 12 seconds" > \end{example} \end{functiondoc} %% ------------------------------------------------------------------------ \begin{functiondoc}{Function}{pretty-run-time-duration}{% \nobr{\var{internal-time-units\/}} \nobr{\code{\&optional} \var{maximum-fields destination\/}} \nobr{\returns{} \var{result\/}}} \index{time!duration, formatting}% \index{duration!formatting}% \index{internal time units, formatting}% \fnsyntax \fnpurpose Format a run-time duration (in \nobr{\var{internal-time-units\/}}) into descriptive text. \fnpackage \code{:gbbopen-tools} \fnmodule \code{:gbbopen-tools} \fnargs \begin{args}{internal-time-units} \arg[internal-time-units] A number \arg[maximum-fields] An integer from 1--5 indicating maximum number of fields to include in the descriptive \var{string\/} (default is 5, indicating all fields should be included) \arg[destination] Either \nil, \code{t}, a stream, or a string with a fill pointer (default is \nil) \arg[result] A string or \nil{} \end{args} \fnreturns If \var{destination\/} is non-\nil, then \nil; otherwise, a string. \fndescription The \var{internal-time-units\/} run-time duration is rounded to the nearest 100$^{th}$ of a second before conversion. Fields omitted by \nobr{\var{maximum-fields\/}} cause appropriate rounding of the generated description. \begin{alsos}{brief-run-time-duration} \also[brief-duration] \also[brief-run-time-duration] \also[parse-duration] \also[pretty-duration] \end{alsos} \fnexamples % \W\supp \begin{example} > internal-time-units-per-second 1000 > (pretty-run-time-duration 1000) "1 second" > (pretty-run-time-duration 5) "0 seconds" > (pretty-run-time-duration 6) "0.01 seconds"\goodpagebreak > most-positive-fixnum 536870911 > (pretty-run-time-duration most-positive-fixnum) "6 days, 5 hours, 7 minutes, 50.94 seconds" > \end{example} \end{functiondoc} %% ------------------------------------------------------------------------ \begin{functiondoc}{Function}{very-brief-date}{% \nobr{\code{\&optional} \var{universal-time\/}} \nobr{\code{\&key} \var{time-zone}} \var{\nobr{month-precedes-date} \nobr{year-first} \nobr{include-year} \nobr{separator} destination\/} \nobr{\returns{} \var{result\/}}} \index{date!formatted}% \index{time, formatted}% \fnsyntax \fnpurpose Generate a very brief date description. \fnpackage \code{:gbbopen-tools} \fnmodule \code{:gbbopen-tools} \fnargs \begin{args}{universal-time} \arg[universal-time] A \glref{Universal~Time} (default is \nil, which is equivalent to the value returned by \nobr{\code{(get-universal-time)}}) \arg[time-zone] A \glref{time~zone} (default is \nil, which is equivalent to the current time zone adjusted for daylight saving time) \arg[month-precedes-date] A \glref{generalized~boolean} (default is \nobr{\textbf{\entlink{*month-precedes-date*}}}) \arg[year-first] A \glref{generalized~boolean} (default is \nobr{\textbf{\entlink{*year-first*}}}) \arg[include-year] A \glref{generalized~boolean} (default is \code{t}) \arg[separator] A character (default is \code{\#\bkslash/}) \arg[destination] Either \nil, \code{t}, a stream, or a string with a fill pointer (default is \nil) \arg[result] A string or \nil{} \end{args} \fnreturns If \var{destination\/} is non-\nil, then \nil; otherwise, a string. \fndescription % \bfindexit{get-universal-time}% If \var{universal-time\/} is not supplied or is \nil, the current time (as returned by \nobr{\code{get-universal-time}} is used. \W\xml{p} % If \var{time-zone\/} is not supplied or is \nil, it defaults to the current time zone adjusted for daylight saving time. If \nobr{\var{time-zone\/}} is supplied, it is assumed to include any adjustment for daylight saving time. \W\xml{p} % If \var{month-precedes-date\/} is true, the month is presented in front of the date; otherwise the date precedes the month. \W\xml{p} % If \var{year-first\/} is supplied and is non-\nil, the year is presented in front of the month and date; otherwise the year follows the month and date. \W\xml{p} % If \var{include-year\/} is supplied and is non-\nil, the year is included in the presented time. \begin{alsos}{internet-text-date-and-time} \also[*month-precedes-date*] \also[brief-date-and-time] \also[full-date-and-time] \also[http-date-and-time] \also[internet-text-date-and-time] \also[iso8601-date-and-time] \also[message-log-date-and-time] \end{alsos} \fnexamples Display the current date (with and without the year): % \W\supp \begin{example} > (very-brief-date) "2/16/2008" > (very-brief-date (get-universal-time) :include-year nil) "2/16" > \end{example} \end{functiondoc} %% ------------------------------------------------------------------------ \T\markright{}% \T\pagestyle{plain} \T\clearpage \W\xname{ref-offset-universal-time-entities} \T\pagestyle{fancy} \T\thispagestyle{fancybottom} \T\global\def\fnlastname{ }% \subsection{Offset Universal Time} \label{sec:offsettime}% \index{offset universal time}% Common Lisp has three time representations: Decoded Time, Universal Time, and Internal Time. \glref{Universal~Time} (UT) allows specific points in time from the beginning of 1900 to be represented with one-second resolution (ignoring leap seconds). The disadvantage of absolute Universal Time values is that they are bignums in most Common Lisp implementations. To reduce computation and storage requirements, a fourth time representation, \glref{Offset~Universal~Time} (OT), can be used. Offset Universal Time is Universal Time that is offset by an integer time-base value so that the most often used Offset Universal Time values in an application are \glref{fixnums}. Nearly all Common Lisp implementations provide fixnums of at least 30 bits (34 years of time range) or more, but CLISP on 32-bit machines provides only 25 bits (388 days). The ANSI standard requires an implementation to provide fixnums with at least 16 bits (only 18 hours), but fortunately Common Lisp implementations are considerably more generous! When developing applications that must represent time values that exceed the fixnum range, it is important to choose the best time-base offset value to reduce bignum costs. Of course, existing Offset Universal Time values will appear shifted if the time-base offset value is changed. \W\entities \T\clearpage %% ------------------------------------------------------------------------ \begin{functiondoc}[ot-base-var]{Variable}{*ot-base*}{}% \fnsyntax \fnpurpose Holds the \glref{Offset~Universal~Time} time-base value. \fnpackage \code{:gbbopen-tools} \fnmodule \code{:gbbopen-tools} \fnvaluetype An \glref{Offset~Universal~Time} time-base value \fninitialvalue Must be set by using \nobr{\textbf{\entlink{set-ot-base}}} \begin{alsos}{check-ot-base} \also[check-ot-base] \also[ot2ut] \also[set-ot-base] \also[ut2ot] \end{alsos} \end{functiondoc} %% ------------------------------------------------------------------------ \begin{functiondoc}{Function}{check-ot-base}{% \nobr{\code{\&optional} \var{suppress-warning\/}} \nobr{\returns{} \var{boolean\/}}} \index{universal time!setting the time base value}% \fnsyntax \fnpurpose Check if the current time can be represented as a \nobr{\code{\glref{fixnum}}} given the current \glref{Offset~Universal~Time} time-base value. \fnpackage \code{:gbbopen-tools} \fnmodule \code{:gbbopen-tools} \fnargs \begin{args}{suppress-warning} \arg[suppress-warning] A \glref{generalized~boolean} (default is \nil) \arg[boolean] A \glref{generalized~boolean} \end{args} \fnreturns True if the current time can be represented as a \nobr{\code{\glref{fixnum}}} \glref{Offset~Universal~Time} value; nil otherwise. \fnerrors The \glref{Offset~Universal~Time} time-base value has not been set. \begin{alsos}{set-ot-base} \also[*ot-base*] \also[ot2ut] \also[set-ot-base] \also[ut2ot] \end{alsos} \fnexamples Set the time base for \glref{Offset~Universal~Time} to today and check: % \W\supp \begin{example} > (\entlink{set-ot-base}) 3410655616 > (check-ot-base) t > \end{example} % Set the time base for \glref{Offset~Universal~Time} to January 1, 1900 and check: % \W\supp\notpretop \begin{example} > (\entlink{set-ot-base} 1 1 1900) 16777216 > (check-ot-base) ;; Warning: The current time represented as an \glref{Offset~Universal~Time} is not a fixnum. nil > (check-ot-base 't) nil > \end{example} \end{functiondoc} %% ------------------------------------------------------------------------ \begin{functiondoc}{Function}{ot2ut}{\var{offset-universal-time\/} \nobr{\returns{} \var{universal-time\/}}} \index{offset universal time!converting to universal time}% \fnsyntax \fnpurpose Convert an \glref{Offset~Universal~Time} value to a \glref{Universal~Time} value. \fnpackage \code{:gbbopen-tools} \fnmodule \code{:gbbopen-tools} \fnargs \begin{args}{offset-universal-time} \arg[offset-universal-time] An \glref{Offset~Universal~Time} value \arg[universal-time] A \glref{Universal~Time} \end{args} \fnreturns The equivalent \glref{Universal~Time} value \fnerrors The \glref{Offset~Universal~Time} time-base value has not been set. \begin{alsos}{check-ot-base} \also[*ot-base*] \also[check-ot-base] \also[ut2ot] \also[set-ot-base] \end{alsos} \fnexample % \W\supp \begin{example} > (\entlink{set-ot-base} 1 7 2007) 3409014016 > (ot2ut -15071348) 3393942668 > \end{example} \replnote % \REPLindex{:ot}% % The equivalent of: % \W\supp \begin{example} (\entlink{full-date-and-time} (ot2ut \var{offset-universal-time\/}) :include-seconds 't :destination *standard-output*) \end{example} % can be invoked using the \glref{REPL~command} \nobr{\code{:ot} \var{offset-universal-time\/}}. \end{functiondoc} %% ------------------------------------------------------------------------ \begin{functiondoc}{Macro}{printvot}{% \nobr{\var{form\/}\superstar{}} \nobr{\returns{} \var{result\/}\superstar}} \index{debugging, using printvot@using \textbf{printvot}}% \fnsyntax \fnpurpose Assist debugging involving \nobr{\glref{Offset~Universal~Time}} values by printing forms and the results of evaluating them to \nobr{\code{*trace-output*}}. Any form producing a single-valued integer result is assumed to be an \nobr{\glref{Offset~Universal~Time}} value and a convenient \nobr{\textbf{\entlink{full-date-and-time}}} format (including seconds) is printed as the result value. \fnpackage \code{:gbbopen-tools} \fnmodule \code{:gbbopen-tools} \fnargs \begin{args}{results} \arg[forms] An implicit \nobr{\code{progn}} of \glref{forms} to be evaluated and printed \arg[results] The values returned by evaluating the last \var{form} that is not the keyword symbol \code{:hr} \end{args} \fnreturns The values returned by evaluating the last \var{form} that is not the keyword symbol \code{:hr} \fndescription The following is performed for each form in \var{forms}: \begin{tightitemize} \item if the form is the keyword symbol \code{:hr}, a dashed separator line printed to \nobr{\code{*trace-output*}} \item if the form is a string (before evaluation), it is treated as a label and printed to \nobr{\code{*trace-output*}} without enclosing double-quote characters \item if the form is a self-evaluating object, it is printed to \nobr{\code{*trace-output*}} \item otherwise, the form is printed to \nobr{\code{*trace-output*}}, then the form is evaluated and the result values are printed to \nobr{\code{*trace-output*}}. Unlike \textbf{\entlink{printv}}, a single-valued integer result is assumed to be an \nobr{\glref{Offset~Universal~Time}} value and when that result is printed by \textbf{printvot}, it is first converted to \glref{Universal~Time} and then to \nobr{\textbf{\entlink{full-date-and-time}}} format (including seconds). \end{tightitemize} \begin{alsos}{full-date-and-time} \also[full-date-and-time] \also[printv] \end{alsos} \bfindexit{ut2ot}% \fnexamples % \W\supp \begin{example} > (printvot "PRINTVOV example" *ot-base* (ut2ot) :hr) ;; PRINTVOV example ;; *ot-base* => "Oct 22 2117 04:40:32" ;; (ut2ot) => "Jun 4 2008 13:51:08" ;; ------------------------------------------------------------ -15071348 > \end{example} \end{functiondoc} %% ------------------------------------------------------------------------ \begin{functiondoc}{Function}{set-ot-base}{\code{\&optional} \var{date month year time-zone\/} \nobr{\returns{} \var{ot-base\/}}} \index{universal time!setting the time base value}% \fnsyntax \fnpurpose Set the \glref{Offset~Universal~Time} time-base value. \fnpackage \code{:gbbopen-tools} \fnmodule \code{:gbbopen-tools} \fnargs \begin{args}{universal-time} \arg[date] An integer between 1 and up to 31, inclusive, depending on the month and year or \nil, indicating the current date (default is \nil) \arg[month] An integer between 1 and 12, inclusive or \nil, indicating the current month (default is \nil) \arg[year] An integer indicating the year A.D. or \nil, indicating the current year (default is \nil); if the \var{year\/} integer is between 0 and 99, the ``obvious'' year is assumed. \arg[time-zone] A time zone: a rational multiple of 1/3600 between -24 and 24 that represents the number of hours offset from GMT (default is zero) \end{args} \fnreturns The \glref{Offset~Universal~Time} time-base value \fndescription Without any arguments, \nobr{\textbf{set-ot-base}} sets the time-base value to the current date. Setting the time base to the current date can be used in applications that do not need to represent historical dates and that do not save or communicate \glref{Offset~Universal~Time} values. However, setting the time base to a specific date is recommended for most applications. \begin{alsos}{check-ot-base} \also[*ot-base*] \also[check-ot-base] \also[ot2ut] \also[ut2ot] \end{alsos} \fnexamples Set the time base for \glref{Offset~Universal~Time} to today: % \W\supp \begin{example} > (set-ot-base) 3436662016 > \end{example} Note that the returned \glref{Offset~Universal~Time} time-base value (above) is not the current \glref{Universal~Time} value: % \W\supp\notpretop \begin{example} > (get-universal-time) 3419947437 > \end{example} Set the time base for \glref{Offset~Universal~Time} to July 1, 2007: % \W\supp \begin{example} > (set-ot-base 1 7 2007) 3409014016 > \end{example} \end{functiondoc} %% ------------------------------------------------------------------------ \begin{functiondoc}{Function}{ut2ot}{% \nobr{\code{\&optional} \var{universal-time\/}} \nobr{\returns{} \var{offset-universal-time\/}}} \index{universal time!converting to offset universal time}% \fnsyntax \fnpurpose Convert a \glref{Universal~Time} value to an \glref{Offset~Universal~Time} value. \fnpackage \code{:gbbopen-tools} \fnmodule \code{:gbbopen-tools} \fnargs \begin{args}{offset-universal-time} \arg[universal-time] A \glref{Universal~Time} value (default is the current \glref{Universal~Time}) \arg[offset-universal-time] An \glref{Offset~Universal~Time} value \end{args} \fnreturns The equivalent \glref{Offset~Universal~Time} value \fnerrors The \glref{Offset~Universal~Time} time-base value has not been set. \begin{alsos}{check-ot-base} \also[*ot-base*] \also[check-ot-base] \also[ot2ut] \also[set-ot-base] \end{alsos} \fnexamples % codeindexit{multiple-value-call}% codeindexit{encode-universal-time}% % \W\supp \begin{example} > (\entlink{set-ot-base} 1 7 2007) 3409014016 > (ut2ot) -15071348 > (ut2ot 3393942668) -15071348 > (ut2ot (multiple-value-call #'encode-universal-time ;; noon on the Fourth of July, 2008: 0 0 12 (parse-date "July 4, 2008"))) 15161984 > \end{example} \end{functiondoc} %% ------------------------------------------------------------------------ \T\markright{}% \T\pagestyle{plain} \T\clearpage \W\xname{ref-atable-entities} \T\pagestyle{fancy} \T\thispagestyle{fancybottom} \T\global\def\fnlastname{ }% \subsection{Transitioning Sets and Tables} \label{sec:atable}% \index{set, auto-transitioning}% \index{table, auto-transitioning}% \index{ESET}% \index{ET}% % Ideally, native Common Lisp hash tables operations should always be very fast. On some Common Lisp implementations, however, a small amount of time (and space) can be saved by using list-based representations for hash tables with small entry counts. These list-based representations transition automatically to regular hash tables as the entry count grows beyond the performance-advantage threshold (and back to the list representation as the count shrinks). These auto-transitioning representations add a small overhead to normal hash table operations, so their use should be considered very carefully (and restricted to situations where the counts tend to remain low). \psubpar{ESETs} \index{ESET}% % An ESET (short for \code{eq}-set) is a keys-only table that automatically transitions between list and hash-table implementations. The keys are used to represent elements of the ESET and are compared using \code{eq}. \psubpar{ETs} \index{ET}% % An ET (short for \code{eq}-table) is a key-and-value table that automatically transitions between list and hash-table implementations. The keys are compared using \code{eq}. %% ------------------------------------------------------------------------ \begin{functiondoc}{Function}{add-to-eset}{\var{item eset\/} \nobr{\returns{} \var{item\/}}} \fnsyntax \fnpurpose Add \var{item\/} to \var{eset\/} if it is not already present using \code{eq} as the comparison function. \fnpackage \code{:gbbopen-tools} \fnmodule \code{:gbbopen-tools} \fnargs \begin{args}{symbol} \arg[item] An object \arg[eset] An \glref{ESET} \end{args} \fnreturns The \var{item} \begin{alsos}{delete-from-eset} \also[in-eset] \also[make-eset] \also[delete-from-eset] \end{alsos} \fnexamples \bfindexit{make-eset}% \bfindexit{in-eset}% % \W\supp \begin{example} > (defparameter *eset* (\entlink{make-eset})) *eset > (\entlink{in-eset} 'x *eset*) nil nil > (add-to-eset 'x *eset*) x > (\entlink{in-eset} 'x *eset*) x t\goodpagebreak > (\entlink{in-eset} nil *eset*) nil nil > (add-to-eset nil *eset*) nil > (in-eset nil *eset*) nil t > \end{example} \end{functiondoc} %% ------------------------------------------------------------------------ \begin{functiondoc}{Function}{delete-from-eset}{\var{item eset\/} \nobr{\returns{} \var{deleted-p\/}}} \fnsyntax \fnpurpose Delete \var{item\/} from \var{eset\/} if it is present using \code{eq} as the comparison function. \fnpackage \code{:gbbopen-tools} \fnmodule \code{:gbbopen-tools} \fnargs \begin{args}{symbol} \arg[item] An object \arg[eset] An \glref{ESET} \arg[deleted-p] A \glref{generalized~boolean} \end{args} \fnreturns True, if \var{item\/} was deleted from \var{eset}; \nil{} otherwise \begin{alsos}{add-to-eset} \also[add-to-eset] \also[in-eset] \also[make-eset] \end{alsos} \fnexamples \bfindexit{add-to-eset}% \bfindexit{make-eset}% \bfindexit{in-eset}% % \W\supp \begin{example} > (defparameter *eset* (\entlink{make-eset})) *eset > (\entlink{add-to-eset} 'x *eset*) x > (\entlink{in-eset} 'x *eset*) x t\goodpagebreak > (delete-from-eset 'x *eset*) t > (\entlink{in-eset} 'x *eset*) nil nil > (delete-from-eset 'x *eset*) nil > \end{example} \end{functiondoc} %% ------------------------------------------------------------------------ \begin{functiondoc}{Function}{delete-et}{\var{item et\/} \nobr{\returns{} \var{deleted-p\/}}} \fnsyntax \fnpurpose Delete \var{item\/} from \var{et\/} if it is present using \code{eq} as the comparison function. \fnpackage \code{:gbbopen-tools} \fnmodule \code{:gbbopen-tools} \fnargs \begin{args}{symbol} \arg[item] An object \arg[et] An \glref{ET} \arg[deleted-p] A \glref{generalized~boolean} \end{args} \fnreturns True, if \var{item\/} was deleted from \var{et}; \nil{} otherwise \begin{alsos}{make-et} \also[get-et] \also[make-et] \end{alsos} \fnexamples \bfindexit{make-et}% \bfindexit{get-et}% % \W\supp \begin{example} > (defparameter *et* (\entlink{make-et})) *et > (setf (\entlink{get-et} 'x *et*) 3) 3 > (\entlink{get-et} 'x *et*) 3 t\goodpagebreak > (delete-et 'x *et*) t > (\entlink{get-et} 'x *et*) nil nil > (delete-et 'x *et*) nil > \end{example} \end{functiondoc} %% ------------------------------------------------------------------------ \begin{functiondoc}{Function}{get-et}{\var{key et\/} \nobr{\code{\&optional} \var{default\/}} \nobr{\returns{} \var{value, present-p\/}}} \index{searching!for an value in an et}% \fnsyntax \fnpurpose Return the value associated with \var{key\/} in \var{et\/} using \code{eq} as the key-comparison function. \fnsetf \fnsetfsyntax{get-et}{\var{key et\/} \nobr{\code{\&optional} \var{default\/}}}% {\var{value\/}} \fnpackage \code{:gbbopen-tools} \fnmodule \code{:gbbopen-tools} \fnargs \begin{args}{symbol} \arg[key] An object \arg[et] An \glref{ET} \arg[value] An object \arg[present-p] A \glref{generalized~boolean} \end{args} \fnreturns Two values: \begin{tightitemize} \item The value associated with the given \var{key\/} or \var{default\/} if no entry is associated with \var{key} \item True, if an entry was found; \nil{} if there is no such entry \end{tightitemize} % When \code{setf} is used with \nobr{\textbf{get-et}}, the supplied \var{value\/} is returned as a single value. \fndescription % \code{Setf} may be used with \nobr{\textbf{get-et}} to replace the value associated with the given \var{key}, or to add a new entry. When a \nobr{\textbf{get-et}} form is used as a setf place, any \var{default\/} which is supplied is evaluated, but its value is ignored. \begin{alsos}{delete-et} \also[make-et] \also[assq] \also[delete-et] \end{alsos} \fnexamples \bfindexit{make-et}% % \W\supp \begin{example} > (defparameter *e* (\entlink{make-et})) *et > (get-et 'x *et*) nil nil > (get-et 'x *et* ':missing) :missing nil > (setf (get-et 'x *et*) 1) 1 > (get-et 'x *et*) 1 t\goodpagebreak > (get-et nil *et*) nil nil > (setf (get-et nil *et*) nil) nil > (get-et nil *et*) nil t > \end{example} \end{functiondoc} %% ------------------------------------------------------------------------ \begin{functiondoc}{Function}{in-eset}{\var{item eset\/} \nobr{\returns{} \var{item-or-nil, present-p\/}}} \index{searching!for an item in an eset}% \fnsyntax \fnpurpose Determine if \var{item\/} is in \var{eset\/} using \code{eq} as the comparison function. \fnpackage \code{:gbbopen-tools} \fnmodule \code{:gbbopen-tools} \fnargs \begin{args}{symbol} \arg[item] An object \arg[eset] An \glref{ESET} \arg[item-or-nil] An object or \nil{} \arg[present-p] A \glref{generalized~boolean} \end{args} \fnreturns Two values: \begin{tightitemize} \item \var{item}, if \var{item\/} is a member of \var{eset}; otherwise \nil{} \item True, if an entry was found; \nil{} if there is no such entry \end{tightitemize} \begin{alsos}{delete-from-eset} \also[add-to-eset] \also[make-eset] \also[memq] \also[delete-from-eset] \end{alsos} \fnexamples \bfindexit{add-to-eset}% \bfindexit{make-eset}% % \W\supp \begin{example} > (defparameter *eset* (\entlink{make-eset})) *eset > (in-eset 'x *eset*) nil nil > (\entlink{add-to-eset} 'x *eset*) x > (in-eset 'x *eset*) x t\goodpagebreak > (in-eset nil *eset*) nil nil > (\entlink{add-to-eset} nil *eset*) nil > (in-eset nil *eset*) nil t > \end{example} \end{functiondoc} %% ------------------------------------------------------------------------ \begin{functiondoc}{Function}{make-eset}{\noargs \nobr{\returns{} \var{eset\/}}} \index{creating!an ESET}% \index{making!an ESET}% \fnsyntax \fnpurpose Create an empty \glref{ESET}. \fnpackage \code{:gbbopen-tools} \fnmodule \code{:gbbopen-tools} \fnargs \begin{args}{symbol} \arg[eset] An \glref{ESET} \end{args} \fnreturns An empty ESET \begin{alsos}{delete-from-eset} \also[add-to-eset] \also[in-eset] \also[delete-from-eset] \end{alsos} \fnexamples % \W\supp \begin{example} > (make-eset) (0) > \end{example} \end{functiondoc} %% ------------------------------------------------------------------------ \begin{functiondoc}{Function}{make-et}{\noargs \nobr{\returns{} \var{et\/}}} \index{creating!an ET}% \index{making!an ET}% \fnsyntax \fnpurpose Create an empty \glref{ET}. \fnpackage \code{:gbbopen-tools} \fnmodule \code{:gbbopen-tools} \fnargs \begin{args}{symbol} \arg[et] An \glref{ET} \end{args} \fnreturns An empty ET \begin{alsos}{delete-et} \also[get-et] \also[delete-et] \end{alsos} \fnexamples % \W\supp \begin{example} > (make-et) (0) > \end{example} \end{functiondoc} %% ------------------------------------------------------------------------ \T\markright{}% \T\pagestyle{plain} \T\clearpage \W\xname{ref-search-tree-entities} \T\pagestyle{fancy} \T\thispagestyle{fancybottom} \T\global\def\fnlastname{ }% \subsection{Search Trees} \label{sec:trees}% \index{search trees}% \index{left-leaning red-black trees}% % A red-black tree is binary search tree that is roughly balanced, keeping the worst-case time values for operations such as inserting, deleting, and searching proportional to the height of the tree. Left-leaning red-black (\glref{LLRB}) trees are a simpler version of red-black trees in which all red links must ``lean'' left except during inserts and deletes. LLRB trees have good worst-case running time for their operations and are efficient in general use. \indexit{module!:gbbopen-tools@\code{:gbbopen-tools}}% \indexit{:gbbopen-tools@\code{:gbbopen-tools} module}% \W\entities \T\clearpage %% ------------------------------------------------------------------------ \begin{functiondoc}{Function}{llrb-tree-count}{\var{llrb-tree\/} \nobr{\returns{} \var{count\/}}} \index{LLRB tree!entities count}% \fnsyntax \fnpurpose Return number of entries stored in \var{llrb-tree}. \fnpackage \code{:gbbopen-tools} \fnmodule \code{:gbbopen-tools} \fnargs \begin{args}{llrb-tree} \arg[llrb-tree] An \glref{LLRB~tree} \arg[count] A non-negative integer \end{args} \fnreturns The number of entries stored in \var{llrb-tree} \begin{alsos}{llrb-tree-delete} \also[llrb-tree-delete] \also[llrb-tree-p] \also[llrb-tree-test] \also[llrb-tree-value] \also[make-llrb-tree] \also[map-llrb-tree] \end{alsos} \fnexample % \W\supp \begin{example} > (llrb-tree-count *tree*) 3 > \end{example} \end{functiondoc} %% ------------------------------------------------------------------------ \begin{functiondoc}{Function}{llrb-tree-delete}{% \var{key \nobr{llrb-tree\/}} \nobr{\returns{} \var{deleted-p\/}}} \index{LLRB tree!deleting}% \fnsyntax \fnpurpose Delete the entry associated with a given key. \fnpackage \code{:gbbopen-tools} \fnmodule \code{:gbbopen-tools} \fnargs \begin{args}{llrb-tree} \arg[key] An object \arg[llrb-tree] An \glref{LLRB~tree} \arg[deleted-p] A \glref{generalized~boolean} \end{args} \fnreturns True if the entry was deleted; \nil{} if it was not found \begin{alsos}{llrb-tree-count} \also[llrb-tree-count] \also[llrb-tree-p] \also[llrb-tree-test] \also[llrb-tree-value] \also[make-llrb-tree] \also[map-llrb-tree] \end{alsos} \fnexample % Delete the entry stored under \code{1} in the LLRB-tree \code{*tree*}, then try deleting it a second time: \W\supp \begin{example} > (llrb-tree-delete 1 *tree*) t > (llrb-tree-delete 1 *tree*) nil \end{example} \end{functiondoc} %% ------------------------------------------------------------------------ \begin{functiondoc}{Function}{llrb-tree-p}{\var{object\/} \nobr{\returns{} \var{boolean\/}}} \index{LLRB tree!predicate}% \fnsyntax \fnpurpose Determine if an object is an LLRB tree. \fnpackage \code{:gbbopen-tools} \fnmodule \code{:gbbopen-tools} \fnargs \begin{args}{boolean} \arg[object] An object \arg[boolean] A \glref{generalized~boolean} \end{args} \fnreturns True if \var{object\/} is an LLRB tree; \nil{} otherwise. \begin{alsos}{llrb-tree-delete} \also[llrb-tree-count] \also[llrb-tree-delete] \also[llrb-tree-test] \also[llrb-tree-value] \also[make-llrb-tree] \also[map-llrb-tree] \end{alsos} \fnexample % \W\supp \begin{example} > (llrb-tree-p *tree*) t > \end{example} \end{functiondoc} %% ------------------------------------------------------------------------ \begin{functiondoc}{Function}{llrb-tree-test}{\var{llrb-tree\/} \nobr{\returns{} \var{comparison-test\/}}} \index{LLRB tree!entities count}% \fnsyntax \fnpurpose Return the \glref{three-way~comparison~test} function used in \var{llrb-tree}. \fnpackage \code{:gbbopen-tools} \fnmodule \code{:gbbopen-tools} \fnargs \begin{args}{comparison-test} \arg[llrb-tree] An \glref{LLRB~tree} \arg[comparison-test] A \glref{function~designator} specifying the \glref{three-way~comparison~test} \glref{function~object} used in \var{llrb-tree} \end{args} \fnreturns The comparison test used in \var{llrb-tree} \begin{alsos}{llrb-tree-delete} \also[llrb-tree-count] \also[llrb-tree-delete] \also[llrb-tree-p] \also[llrb-tree-value] \also[make-llrb-tree] \also[map-llrb-tree] \end{alsos} \fnexample % \W\supp \begin{example} > (llrb-tree-test *tree*) compare\& > \end{example} \end{functiondoc} %% ------------------------------------------------------------------------ \begin{functiondoc}{Function}{llrb-tree-value}{\var{key llrb-tree\/} \nobr{\code{\&optional} \var{default\/}} \nobr{\returns{} \var{value, present-p\/}}} \index{LLRB tree!retrieval}% \index{LLRB tree!inserting}% \fnsyntax \fnpurpose Return the value associated with a given key. \fnsetf \fnsetfsyntax{llrb-tree-value}{\var{key llrb-tree\/} \nobr{\code{\&optional} \var{default\/}}}{\var{value\/}}% {\returns{} \var{value, present-p\/}} \fnpackage \code{:gbbopen-tools} \fnmodule \code{:gbbopen-tools} \fnargs \begin{args}{present-p} \arg[key] An object \arg[llrb-tree] An \glref{LLRB~tree} \arg[default] An object (default is \nil) \arg[value] An object \arg[present-p] A \glref{generalized~boolean} \end{args} \fnreturns Two values: \begin{tightitemize} \item The value associated with the given \var{key\/} or \var{default\/} if no entry is associated with \var{key} \item True, if an entry was found; \nil{} if there is no such entry \end{tightitemize} \fndescription % \code{Setf} may be used with \nobr{\textbf{llrb-tree-value}} to replace the value associated with the given \var{key}, or to add a new entry. When a \nobr{\textbf{llrb-tree-value}} form is used as a setf place, any \var{default\/} which is supplied is evaluated, but its value is ignored. \begin{alsos}{llrb-tree-delete} \also[llrb-tree-count] \also[llrb-tree-delete] \also[llrb-tree-p] \also[llrb-tree-test] \also[make-llrb-tree] \also[map-llrb-tree] \end{alsos} \fnexample % \W\supp \begin{example} > (defparameter *tree* (\entlink{make-llrb-tree} #'compare\&)) *tree* > (llrb-tree-value 1 *tree*) nil > (setf (llrb-tree-value 1 *tree*) 'a) a > (llrb-tree-value 1 *tree*) a t > \end{example} \end{functiondoc} %% ------------------------------------------------------------------------ \begin{functiondoc}{Function}{make-llrb-tree}{\var{comparison-test\/} \nobr{\returns{} \var{llrb-tree\/}}} \index{LLRB tree!creating}% \fnsyntax \fnpurpose Create an empty left-leaning red-black tree. \fnpackage \code{:gbbopen-tools} \fnmodule \code{:gbbopen-tools} \fnargs \begin{args}{comparison-test} \arg[comparison-test] A \glref{three-way~comparison~test} \arg[llrb-tree] An \glref{LLRB~tree} \end{args} \fnreturns An empty left-leaning red-black tree \begin{alsos}{llrb-tree-delete} \also[llrb-tree-count] \also[llrb-tree-delete] \also[llrb-tree-p] \also[llrb-tree-test] \also[llrb-tree-value] \also[map-llrb-tree] \end{alsos} \fnexample % \W\supp \begin{example} > (make-llrb-tree #'compare\&) # > \end{example} \end{functiondoc} %% ------------------------------------------------------------------------ \begin{functiondoc}{Function}{map-llrb-tree}{% \var{function \nobr{llrb-tree\/}}} \index{LLRB tree!applying a function to entries of}% \fnsyntax \fnpurpose Apply a \glref{function} once to the key and value of each entry in an LLRB tree. \fnpackage \code{:gbbopen-tools} \fnmodule \code{:gbbopen-tools} \fnargs \begin{args}{comparison-test} \arg[function] A \glref{function~designator} specifying a \glref{function~object} of two arguments \arg[llrb-tree] An \glref{LLRB~tree} \end{args} \begin{alsos}{llrb-tree-delete} \also[llrb-tree-count] \also[llrb-tree-delete] \also[llrb-tree-p] \also[llrb-tree-test] \also[llrb-tree-value] \also[make-llrb-tree] \end{alsos} \fnexample % \W\supp \begin{example} > (map-llrb-tree #'(lambda (key value) (\entlink{printv} key value)) *tree*) ;; key => 1 ;; value => a ;; key => 2 ;; value => b ;; key => 3 ;; value => c nil > \end{example} \end{functiondoc} %% ======================================================================== %% Additional Tools \T\markright{}% \T\pagestyle{plain} \T\cleardoublepage \W\xname{ref-additional-tools-entities} \T\pagestyle{fancy} \T\thispagestyle{fancybottom} \T\global\def\fnlastname{ }% \T\renewcommand{\headrulewidth}{0pt} \section{Additional GBBopen Tools} \label{sec:additional-tools}% % Additional GBBopen Tool entities are grouped into \glref{modules} that can be loaded as appropriate. Documentation for these additional-tool entities is arranged according to the following modules: % \begin{tightitemize} % \item uniform interfaces to implementation-specific thread (multiprocessing) capabilities are provided by the \reflink{\nobr{\code{:portable-threads}} module}{sec:portablethreads} % \item polling functions for Common Lisp implementations that do not provide thread capabilities are provided by the \reflink{\nobr{\code{:polling-functions}} module}{sec:pollingfunctions} % \item uniform socket interfaces are provided by the \reflink{\nobr{\code{:portable-sockets}} module}{sec:portablesockets} % \item uniform interfaces to the operating system are provided by the \reflink{\nobr{\code{:os-interface}} module}{sec:os-interface} % \item Double Metaphone phonetic-code computation is provided by the \reflink{\nobr{\code{:double-metaphone}} module}{sec:double-metaphone} module. % \end{tightitemize} \T\clearpage \T\renewcommand{\headrulewidth}{0.01pt} %% ------------------------------------------------------------------------ \T\markright{}% \T\pagestyle{plain} \T\clearpage \W\xname{ref-portable-thread-entities} \T\pagestyle{fancy} \T\thispagestyle{fancybottom} \T\global\def\fnlastname{ }% \subsection{Portable Threads} \label{sec:portablethreads}% \index{module!:portable-threads@\code{:portable-threads}}% \index{:portable-threads@\code{:portable-threads} module}% GBBopen's Portable Threads provides a uniform interface to commonly used \glref{thread} (multiprocessing) entities. Wherever possible, these entities do something reasonable in Common Lisp implementations that do not provide threads. However, entities that make no sense without threads signal errors in non-threaded implementations (as noted with each entity). The \glref{feature} \nobr{\code{:threads-not-available}} is added on Common Lisp implementations without thread support, and the \glref{feature} \nobr{\code{:with-timeout-not-available}} is added on implementations that do not support \nobr{\textbf{\entlink{with-timeout}}}. Portable Threads entities are provided by the \nobr{\code{:portable-threads}} module in GBBopen. Stand-alone use of the Portable Threads interface is also easy, requiring only the \xsitelink{\nobr{\code{portable-threads.lisp}}}{http://gbbopen.org/svn/GBBopen/trunk/source/tools/portable-threads.lisp} file for the portable-interface layer and, if desired, \xsitelink{\nobr{\code{scheduled-periodic-functions.lisp}}}{http://gbbopen.org/svn/GBBopen/trunk/source/tools/scheduled-periodic-functions.lisp} for the \glref{scheduled} and \glref{periodic} function \reflink{entities}{sec:scheduledfunctions}. \psubpar{Threads and Processes} Common Lisp implementations that provide multiprocessing capabilities use one of two approaches: \begin{tightitemize} \item \textit{Application-level threads\/} (also called ``Lisp processes'') which are created, deleted, and scheduled internally by the Common Lisp implementation \item \textit{Operating-system threads\/} (or ``native threads'') which are lightweight, operating-system threads that are created, deleted, and scheduled by the operating system \end{tightitemize} There are advantages and complexities associated with each approach, and the Portable Threads Interface is designed to provide a uniform abstraction over them that can be used to code applications that perform consistently and efficiently on any supported Common Lisp implementation. \psubpar{Locks} Common Lisp implementations provide differing semantics for the behavior of mutual-exclusion locks that are acquired recursively by the same \glref{thread}: some always allow recursive use, others provide special ``recursive'' lock objects in addition to non-recursive locks, and still others allow recursive use to be specified at the time that a lock is being acquired. To enable behavioral consistency in all Common Lisp implementations, the \nobr{\code{:portable-threads}} interface module provides (non-recursive) \glref{locks} and \glref{recursive~locks} and a single acquisition form, \nobr{\textbf{\entlink{with-lock-held}}}, that behaves appropriately for each lock type. \psubpar{Condition Variables} POSIX-style \glref{condition~variables} provide an atomic means for a \glref{thread} to release a lock that it holds and go to sleep until it is awakened by another thread. Once awakened, the lock that it was holding is reacquired atomically before the thread is allowed to do anything else. A condition variable must always be associated with a \glref{lock} (or \glref{recursive~lock}) in order to avoid a race condition created when one thread signals a condition while another thread is preparing to wait on it. In this situation, the second thread would be perpetually waiting for the signal that has already been sent. In the POSIX model, there is no explicit link between the lock used to control access to the condition variable and the condition variable. The Portable Threads Interface makes this association explicit by bundling the lock with the \nobr{\textbf{\entlink{condition-variable}}} CLOS object instance and allowing the \nobr{\textbf{\entlink{condition-variable}}} object to be used directly in lock entities. \psubpar{Hibernation} Sometimes it is desirable to put a thread to sleep (perhaps for a long time) until some event has occurred. The Portable Threads Interface provides two entities that make this situation easy to code: \nobr{\textbf{\entlink{hibernate-thread}}} and \nobr{\textbf{\entlink{awaken-thread}}}. Thread hibernation can only be performed by the thread on itself, eliminating issues of a thread being hibernated at an undesirable time. Note that there is the potential for a hibernate/awaken race condition if a thread hibernates itself again soon after being awakened (when a second \nobr{\textbf{\entlink{awaken-thread}}} intended for the original hiberation is applied to the second hibernation rather than being ignored because the target thread is not hibernating). Using a \nobr{\textbf{\entlink{condition-variable}}} is preferable in this situation. When a thread is hibernating, it remains available to respond to \nobr{\textbf{\entlink{run-in-thread}}} and \nobr{\textbf{\entlink{symbol-value-in-thread}}} operations as well as to be awakened by a dynamically surrounding \nobr{\textbf{\entlink{with-timeout}}}. \psubpar{What about Process Wait?} Thread coordination functions, such as \nobr{\code{process-wait}}, are expensive to implement with operating-system threads. Such functions stop the executing thread until a Common Lisp \glref{predicate~function} returns a true value. With application-level threads, the Lisp-based scheduler evaluates the \glref{predicate~function} periodically when looking for other threads that can be run. With operating-system threads, however, thread scheduling is performed by the operating system and evaluating a Common Lisp \glref{predicate~function} requires complex and expensive interaction between the operating-system thread scheduling and the Common Lisp implementation. Given this cost and complexity, many Common Lisp implementations that use operating-system threads have elected not to provide \nobr{\code{process-wait}}-style coordination functions, and this issue extends to the Portable Threads Interface as well. Fortunately, most uses of \nobr{\code{process-wait}} can be replaced by a different strategy that relies on the producer of a change that would affect the \nobr{\code{process-wait}} \glref{predicate~function} to signal the event rather than having the consumers of the change use predicate functions to poll for it. Condition variables, the Portable Threads \nobr{\textbf{\entlink{hibernate-thread}}} and \nobr{\textbf{\entlink{awaken-thread}}} mechanism, or blocking I/O functions cover most of the typical uses of \nobr{\code{process-wait}}. \W\entities \T\psubpar{Portable Threads entities} \T Descriptions of the Portable Threads entities follow. \T\clearpage %% ------------------------------------------------------------------------ \begin{functiondoc}{Function}{all-threads}{\noargs{} \nobr{\returns{} \var{list-of-threads\/}}} \index{thread!obtaining all}% \fnsyntax \fnpurpose Return a list of all known \glref{threads}. \fnpackage \code{:portable-threads} \fnmodule \code{:portable-threads} \fnargs \begin{args}{list-of-threads} \arg[list-of-threads] A proper list \end{args} \fnreturns A list of objects representing the \glref{threads}. \fndescription The returned list of \glref{threads} is accurate only at the precise instant the \nobr{\textbf{all-threads}} function is called. New threads may be created or existing threads killed at any time, so the returned list is always potentially outdated. \begin{alsos}{thread-alive-p} \also[current-thread] \also[thread-alive-p] \also[threadp] \also[spawn-form] \also[spawn-thread] \end{alsos} \fnexample % \W\supp \begin{example} > (all-threads) (#) > \end{example} \fnnotes % On Common Lisp implementations without threads, \nil{} is returned. The returned list of \glref{threads} should not be destructively altered. \end{functiondoc} %% ------------------------------------------------------------------------ \begin{functiondoc}{Macro}{as-atomic-operation}% {\nobr{\var{form\/}\superstar{}} \nobr{\returns{} \var{primary-value\/}}} \fnsyntax \fnpurpose Execute \var{forms\/} as an atomic operation. \fnpackage \code{:portable-threads} \fnmodule \code{:portable-threads} \fnargs \begin{args}{form} \arg[primary-value] The first value returned by evaluating the last \var{form} \end{args} \fnreturns The primary value returned by evaluating the last \nobr{\var{form}}. \fndescription This macro provides atomicity in the following entities (when the Common Lisp implementation does not support them directly): % \nobr{\textbf{\entlink{atomic-decf}}}, \nobr{\textbf{\entlink{atomic-decf\&}}}, \nobr{\textbf{\entlink{atomic-delete}}}, \nobr{\textbf{\entlink{atomic-flush}}}, \nobr{\textbf{\entlink{atomic-incf}}}, \nobr{\textbf{\entlink{atomic-incf\&}}}, \nobr{\textbf{\entlink{atomic-push}}}, \nobr{\textbf{\entlink{atomic-pushnew}}}, and \nobr{\textbf{\entlink{atomic-pop}}}. % It is intended only for implementing very brief atomic operations and should not be used for long computations or computations that wait or block. Note that \nobr{\textbf{as-atomic-operation}} is only guaranteed to return a single value, not multiple values. \begin{alsos}{browse-hyperdoc} \also[atomic-decf] \also[atomic-decf\&] \also[atomic-delete] \also[atomic-flush] \also[atomic-incf] \also[atomic-incf\&] \also[atomic-push] \also[atomic-pushnew] \also[atomic-pop] \end{alsos} \fnexample Define an atomic \nobr{\textbf{\entlink{nsorted-insert}}}: % \W\supp \begin{example} (defun atomic-nsorted-insert (\&rest args) (declare (dynamic-extent args)) (as-atomic-operation (apply #'\entlink{nsorted-insert} args))) \end{example} \end{functiondoc} %% ------------------------------------------------------------------------ \begin{functiondoc}{Macro}{atomic-decf}{\var{place\/} \nobr{[\var{delta-form\/}]} \nobr{\returns{} \var{new-place-value\/}}} \index{atomic operations!decf@\textbf{decf}}% \fnsyntax \fnpurpose Decrement the value stored in \nobr{\var{place\/}} as an \glref{atomic~operation}. \fnpackage \code{:portable-threads} \fnmodule \code{:portable-threads} \fnargs \begin{args}{place} \arg[place] A \glref{form} which is suitable for use as a \glref{generalized~reference} \arg[delta-form] A \glref{form} that is evaluated to produce a delta value (default is 1) \arg[new-place-value] A number \end{args} \fnreturns The new value of \var{place}. \begin{alsos}{as-atomic-operation} \also[as-atomic-operation] \also[atomic-decf\&] \also[atomic-delete] \also[atomic-flush] \also[atomic-incf] \also[atomic-incf\&] \also[atomic-pop] \also[atomic-pushnew] \end{alsos} \fnexamples % \W\supp \begin{example} > x 5 > (atomic-decf x) 4 > (atomic-decf x 1.5) 2.5 > \end{example} \end{functiondoc} %% ------------------------------------------------------------------------ \begin{functiondoc}[atomic-decf-amp]{Macro}{atomic-decf\&}{\var{place\/} \nobr{[\var{delta-form\/}]} \nobr{\returns{} \var{new-place-value\/}}} \index{atomic operations!decf\&@\textbf{decf\&}}% \fnsyntax \fnpurpose Decrement the \glref{fixnum} value stored in \nobr{\var{place\/}} as an \glref{atomic~operation}. \fnpackage \code{:portable-threads} \fnmodule \code{:portable-threads} \fnargs \begin{args}{place} \arg[place] A \glref{form} which is suitable for use as a \glref{generalized~reference} containing a fixnum value \arg[delta-form] A \glref{form} that is evaluated to produce a fixnum delta value (default is 1) \arg[new-place-value] A fixnum \end{args} \fnreturns The new fixnum value of \var{place}. \begin{alsos}{as-atomic-operation} \also[as-atomic-operation] \also[atomic-decf] \also[atomic-delete] \also[atomic-flush] \also[atomic-incf] \also[atomic-incf\&] \also[atomic-pop] \also[atomic-pushnew] \end{alsos} \fnexamples % \W\supp \begin{example} > x 5 > (atomic-decf\& x) 4 > (atomic-decf\& x 2) 2 > \end{example} \end{functiondoc} %% ------------------------------------------------------------------------ \begin{functiondoc}{Macro}{atomic-delete}{\var{item place\/} \nobr{\code{\&key} \var{from-end test test-not start end count key\/}} \nobr{\returns{} \var{sequence\/}}} \index{atomic operations!delete@\textbf{delete}}% \fnsyntax \fnpurpose As an \glref{atomic~operation}, set \nobr{\var{place\/}} to the sequence in \nobr{\var{place\/}} from which the elements that satisfy the \nobr{\var{test\/}} have been removed. \fnpackage \code{:portable-threads} \fnmodule \code{:portable-threads} \fnargs \begin{args}{from-end} \arg[item] An object \arg[place] A \glref{form} which is suitable for use as a \glref{generalized~reference} that contains a proper sequence \arg[from-end] A \glref{generalized~boolean} (default is \nil) \arg[test] A \glref{function~designator} specifying a \glref{function~object} of two arguments that returns a \glref{generalized~boolean} (default is \nobr{\code{\#'eql}}) \arg[test-not] A \glref{function~designator} specifying a \glref{function~object} of two arguments that returns a \glref{generalized~boolean} (use of \nobr{\code{:test-not}} is deprecated) \arg[start] Starting index into \nobr{\var{sequence\/}} (default is \code{0}) \arg[end] Ending index into \nobr{\var{sequence\/}} (default is \nil, meaning end of \nobr{\var{sequence\/}}) \arg[count] An integer or \nil{} (default is \nil) \arg[key] A \glref{function~designator} specifying a \glref{function~object} of one argument, or \nil{} (default is \nil) \arg[sequence] A sequence \end{args} \fnreturns The sequence in \var{place\/} from which the elements that satisfy the test have been removed. \fndescription Replaces \var{place\/} with the sequence in \nobr{\var{place\/}} from which elements that satisfy the \nobr{\var{test\/}} have been deleted. The supplied \nobr{\var{place\/}} sequence may be modified in constructing the result; however, modification of the sequence itself is not guaranteed. Specifying a \nobr{\var{from-end\/}} value of true matters only when the \nobr{\var{count\/}} is provided, and in that case only the rightmost \nobr{\var{count\/}} elements satisfying the \nobr{\var{test\/}} are deleted. \begin{alsos}{as-atomic-operation} \also[as-atomic-operation] \also[atomic-flush] \also[atomic-pop] \also[atomic-push] \also[atomic-pushnew] \also[counted-delete] \also[delq] \also[delq-one] \end{alsos} \fnexample % \W\supp \begin{example} > list (1 2 3) > (atomic-delete 2 list) (2 3) > list (2 3) > \end{example} \end{functiondoc} %% ------------------------------------------------------------------------ \begin{functiondoc}{Macro}{atomic-flush}{\var{place\/} \nobr{\returns{} \var{old-place-value\/}}} \index{atomic operations!flush}% \fnsyntax \fnpurpose As an \glref{atomic~operation}, set the value of \nobr{\var{place\/}} to \nil, and return the value \nobr{\var{place\/}} had prior to being set. \fnpackage \code{:portable-threads} \fnmodule \code{:portable-threads} \fnargs \begin{args}{old-place-value} \arg[place] A \glref{form} which is suitable for use as a \glref{generalized~reference} \arg[old-place-value] An object \end{args} \fnreturns The \var{place\/} value prior to being set to \nil. \begin{alsos}{as-atomic-operation} \also[as-atomic-operation] \also[atomic-delete] \also[atomic-pop] \also[atomic-push] \also[atomic-pushnew] \end{alsos} \fnexample % \W\supp \begin{example} > list (1 2 3) > (atomic-flush list) (1 2 3) > list nil > \end{example} \end{functiondoc} %% ------------------------------------------------------------------------ \begin{functiondoc}{Macro}{atomic-incf}{\var{place\/} \nobr{[\var{delta-form\/}]} \nobr{\returns{} \var{new-place-value\/}}} \index{atomic operations!incf@\textbf{incf}}% \fnsyntax \fnpurpose Increment the value stored in \nobr{\var{place\/}} as an \glref{atomic~operation}. \fnpackage \code{:portable-threads} \fnmodule \code{:portable-threads} \fnargs \begin{args}{new-place-value} \arg[place] A \glref{form} which is suitable for use as a \glref{generalized~reference} \arg[delta-form] A \glref{form} that is evaluated to produce a delta value (default is 1) \arg[new-place-value] A number \end{args} \fnreturns The new value of \var{place}. \begin{alsos}{as-atomic-operation} \also[as-atomic-operation] \also[atomic-decf] \also[atomic-decf\&] \also[atomic-delete] \also[atomic-flush] \also[atomic-incf\&] \also[atomic-pop] \also[atomic-pushnew] \end{alsos} \fnexamples % \W\supp \begin{example} > x 2 > (atomic-incf x) 3 > (atomic-incf x 1.5) 4.5 > \end{example} \end{functiondoc} %% ------------------------------------------------------------------------ \begin{functiondoc}[atomic-incf-amp]{Macro}{atomic-incf\&}{\var{place\/} \nobr{[\var{delta-form\/}]} \nobr{\returns{} \var{new-place-value\/}}} \index{atomic operations!incf\&@\textbf{incf\&}}% \fnsyntax \fnpurpose Increment the \glref{fixnum} value stored in \nobr{\var{place\/}} as an \glref{atomic~operation}. \fnpackage \code{:portable-threads} \fnmodule \code{:portable-threads} \fnargs \begin{args}{new-place-value} \arg[place] A \glref{form} which is suitable for use as a \glref{generalized~reference} containing a fixnum value \arg[delta-form] A \glref{form} that is evaluated to produce a fixnum delta value (default is 1) \arg[new-place-value] A fixnum \end{args} \fnreturns The new fixnum value of \var{place}. \begin{alsos}{as-atomic-operation} \also[as-atomic-operation] \also[atomic-decf] \also[atomic-decf\&] \also[atomic-delete] \also[atomic-flush] \also[atomic-incf] \also[atomic-pop] \also[atomic-pushnew] \end{alsos} \fnexamples % \W\supp \begin{example} > x 2 > (atomic-incf\& x) 3 > (atomic-incf\& x 2) 5 > \end{example} \end{functiondoc} %% ------------------------------------------------------------------------ \begin{functiondoc}{Macro}{atomic-pop}{\var{place\/} \nobr{\returns{} \var{element\/}}} \index{atomic operations!pop@\textbf{pop}}% \fnsyntax \fnpurpose As an \glref{atomic~operation}, remove the first element from the list stored in \nobr{\var{place}}, store the updated list in \nobr{\var{place}}, and return the removed first element. \fnpackage \code{:portable-threads} \fnmodule \code{:portable-threads} \fnargs \begin{args}{element} \arg[place] A \glref{form} which is suitable for use as a \glref{generalized~reference} that contains a \glref{proper~list} or a \glref{dotted~list} \arg[element] An object \end{args} \fnreturns The first element (the \glref{car}) of the list stored in \nobr{\var{place}}. \begin{alsos}{as-atomic-operation} \also[as-atomic-operation] \also[atomic-delete] \also[atomic-flush] \also[atomic-push] \also[atomic-pushnew] \end{alsos} \fnexample % \W\supp \begin{example} > list (1 2 3) > (atomic-pop list) 1 > list (2 3) > \end{example} \end{functiondoc} %% ------------------------------------------------------------------------ \begin{functiondoc}{Macro}{atomic-push}{\var{item place\/} \nobr{\returns{} \var{new-place-value\/}}} \index{atomic operations!push@\textbf{push}}% \fnsyntax \fnpurpose As an \glref{atomic~operation}, prepend \var{item\/} to the list stored in \nobr{\var{place\/}} and store the updated list in \nobr{\var{place}}. \fnpackage \code{:portable-threads} \fnmodule \code{:portable-threads} \fnargs \begin{args}{new-place-value} \arg[item] An object \arg[place] A \glref{form} which is suitable for use as a \glref{generalized~reference} \arg[new-place-value] A proper list \end{args} \fnreturns The new value of \var{place}. \begin{alsos}{as-atomic-operation} \also[as-atomic-operation] \also[atomic-delete] \also[atomic-flush] \also[atomic-pop] \also[atomic-pushnew] \end{alsos} \fnexample % \W\supp \begin{example} > list (1 2 3) > (atomic-push 10 list) (10 1 2 3) > \end{example} \end{functiondoc} %% ------------------------------------------------------------------------ \begin{functiondoc}{Macro}{atomic-pushnew}{\var{item place\/} \nobr{\code{\&key} \var{key test test-not\/}} \nobr{\returns{} \var{new-place-value\/}}} \index{atomic operations!pushnew@\textbf{pushnew}}% \fnsyntax \fnpurpose As an \glref{atomic~operation}, when \var{item\/} is not the same as any element in the list stored in \nobr{\var{place}}, prepend \var{item\/} to the list and store the updated list in \nobr{\var{place}}. \fnpackage \code{:portable-threads} \fnmodule \code{:portable-threads} \fnargs \begin{args}{new-place-value} \arg[item] An object \arg[place] A \glref{form} which is suitable for use as a \glref{generalized~reference} that contains a \glref{proper~list} \arg[key] A \glref{function~designator} specifying a \glref{function~object} of one argument, or \nil{} (default is \nil) \arg[test] A \glref{function~designator} specifying a \glref{function~object} of two arguments that returns a \glref{generalized~boolean} (default is \nobr{\code{\#'eql}}) \arg[test-not] A \glref{function~designator} specifying a \glref{function~object} of two arguments that returns a \glref{generalized~boolean} (use of \nobr{\code{:test-not}} is deprecated) \arg[new-place-value] A proper list \end{args} \fnreturns The new value of \var{place}. \begin{alsos}{as-atomic-operation} \also[as-atomic-operation] \also[atomic-delete] \also[atomic-flush] \also[atomic-pop] \also[atomic-push] \end{alsos} \fnexamples % \W\supp \begin{example} > list (1 2 3) > (atomic-pushnew 2 list) (1 2 3) > (atomic-pushnew 10 list) (10 1 2 3) > \end{example} \end{functiondoc} %% ------------------------------------------------------------------------ \begin{functiondoc}{Function}{awaken-thread}{\var{thread\/}} \index{thread!awakening}% \index{awakening a thread}% \fnsyntax \fnpurpose Awaken a hibernating \glref{thread}. \fnpackage \code{:portable-threads} \fnmodule \code{:portable-threads} \fnargs \begin{args}{thread} \arg[thread] A \glref{thread} \end{args} \fnerrors \nothreads{} \fndescription An attempt to awaken a non-hibernating thread is ignored. \begin{alsos}{hibernate-thread} \also[hibernate-thread] \end{alsos} \fnexample % \W\supp \begin{example} (awaken-thread thread) \end{example} \end{functiondoc} %% ------------------------------------------------------------------------ \begin{functiondoc}{Class}{condition-variable}{} \index{class!condition-variable@\textbf{condition-variable}}% \fnsyntax \fnpackage \code{:portable-threads} \fnmodule \code{:portable-threads} \fndescription The class \nobr{\textbf{condition-variable}} is a subclass of \nobr{\code{standard-object}}. Instances of \nobr{\textbf{condition-variable}} include an associated lock, which can be either a \glref{lock} (the default) or a \glref{recursive~lock}. \begin{alsos}{make-condition-variable} \also[make-condition-variable] \also[define-class] \end{alsos} \end{functiondoc} %% ------------------------------------------------------------------------ \begin{functiondoc}{Function}{condition-variable-broadcast}% {\var{condition-variable}} \index{signaling, condition variable!all blocked threads}% \fnsyntax \fnpurpose Unblock all \glref{threads} that are blocked on \nobr{\var{condition-variable}}. \fnpackage \code{:portable-threads} \fnmodule \code{:portable-threads} \fnargs \begin{args}{condition-variable} \arg[condition-variable] A \glref{condition~variable} \end{args} \fnerrors \nocvlock{} \fndescription If no threads are blocked on \nobr{\var{condition-variable}}, this function is a no-op. \begin{alsos}{condition-variable-wait-with-timeout} \also[condition-variable-signal] \also[condition-variable-wait] \also[condition-variable-wait-with-timeout] \also[make-condition-variable] \also[with-lock-held] \also[without-lock-held] \end{alsos} \bfindexit{with-lock-held}% \fnexample Acquire the \glref{lock} associated with \nobr{\code{condition-variable}} and then signal all blocked \glref{threads} that are waiting on it: % \W\supp \begin{example} (\entlink{with-lock-held} (condition-variable) (condition-variable-broadcast condition-variable)) \end{example} \fnnote % On Common Lisp implementations without threads, this function does nothing. \end{functiondoc} %% ------------------------------------------------------------------------ \begin{functiondoc}{Function}{condition-variable-signal}% {\var{condition-variable}} \index{signaling, condition variable!one blocked thread}% \fnsyntax \fnpurpose Unblock one \glref{thread} that is blocked on \nobr{\var{condition-variable}}. \fnpackage \code{:portable-threads} \fnmodule \code{:portable-threads} \fnargs \begin{args}{condition-variable} \arg[condition-variable] A \glref{condition~variable} \end{args} \fnerrors \nocvlock{} \fndescription If no threads are blocked on \nobr{\var{condition-variable}}, this function is a no-op. \begin{alsos}{condition-variable-wait-with-timeout} \also[condition-variable-broadcast] \also[condition-variable-wait] \also[condition-variable-wait-with-timeout] \also[make-condition-variable] \also[with-lock-held] \also[without-lock-held] \end{alsos} \bfindexit{with-lock-held}% \fnexample Acquire the \glref{lock} associated with \nobr{\code{condition-variable}} and then signal one blocked \glref{thread} that is waiting on it: % \W\supp \begin{example} (\entlink{with-lock-held} (condition-variable) (condition-variable-signal condition-variable)) \end{example} \fnnote % On Common Lisp implementations without threads, this function does nothing. \end{functiondoc} %% ------------------------------------------------------------------------ \begin{functiondoc}{Function}{condition-variable-wait}% {\var{condition-variable}} \index{waiting, on condition variable}% \fnsyntax \fnpurpose Block the current \glref{thread} on \nobr{\var{condition-variable}}. \fnpackage \code{:portable-threads} \fnmodule \code{:portable-threads} \fnargs \begin{args}{condition-variable} \arg[condition-variable] A \glref{condition~variable} \end{args} \fnerrors \nocvlock{} \par \nothreads{} \begin{alsos}{condition-variable-wait-with-timeout} \also[condition-variable-broadcast] \also[condition-variable-signal] \also[condition-variable-wait-with-timeout] \also[make-condition-variable] \also[with-lock-held] \also[without-lock-held] \end{alsos} \bfindexit{with-lock-held}% \fnexample Acquire the condition-variable \glref{lock} and then wait until signaled by another \glref{thread}: % \W\supp \begin{example} (\entlink{with-lock-held} (condition-variable) (condition-variable-wait condition-variable)) \end{example} \end{functiondoc} %% ------------------------------------------------------------------------ \begin{functiondoc}{Function}{condition-variable-wait-with-timeout}% {\var{condition-variable seconds} \nobr{\returns{} \var{boolean\/}}} \index{waiting, on condition variable, time limited}% \fnsyntax \fnpurpose Block the current \glref{thread} on \nobr{\var{condition-variable\/}} or until \nobr{\var{seconds\/}} seconds have elapsed. \fnpackage \code{:portable-threads} \fnmodule \code{:portable-threads} \fnargs \begin{args}{condition-variable} \arg[condition-variable] A \glref{condition~variable} \arg[seconds] A number \arg[boolean] A \glref{generalized~boolean} \end{args} \fnreturns True if \nobr{\var{condition-variable\/}} is unblocked before \nobr{\var{seconds\/}} seconds have elapsed; \nil{} if the timeout has occurred. \fnerrors \nocvlock{} \par \nothreads{} \begin{alsos}{condition-variable-broadcast} \also[condition-variable-broadcast] \also[condition-variable-signal] \also[condition-variable-wait] \also[make-condition-variable] \also[with-lock-held] \also[without-lock-held] \end{alsos} \bfindexit{with-lock-held}% \fnexample Acquire the condition-variable \glref{lock} and then wait until signaled by another \glref{thread} or until 5 seconds have elapsed: % \W\supp \begin{example} (\entlink{with-lock-held} (condition-variable) (condition-variable-wait-with-timeout condition-variable 5)) \end{example} \end{functiondoc} %% ------------------------------------------------------------------------ \begin{functiondoc}{Function}{current-thread}{\noargs{} \nobr{\returns{} \var{thread\/}}} \index{thread!obtaining the current}% \fnsyntax \fnpurpose Return the object representing the current \glref{thread}. \fnpackage \code{:portable-threads} \fnmodule \code{:portable-threads} \fnargs \begin{args}{thread} \arg[thread] A \glref{thread} \end{args} \fnreturns The object representing the current \glref{thread}. \begin{alsos}{spawn-thread} \also[all-threads] \also[spawn-form] \also[spawn-thread] \end{alsos} \fnexample % \W\supp \begin{example} > (current-thread) # > \end{example} \fnnote % On Common Lisp implementations without threads, the keyword symbol \nobr{\code{:threads-not-available}} is returned. \end{functiondoc} %% ------------------------------------------------------------------------ \begin{functiondoc}{Function}{hibernate-thread}{\noargs{}} \index{thread!hibernating}% \fnsyntax \fnpurpose Hibernate the current \glref{thread}. \fnpackage \code{:portable-threads} \fnmodule \code{:portable-threads} \fnerrors \nothreads{} \begin{alsos}{awaken-thread} \also[awaken-thread] \end{alsos} \fnexample Hibernate the current \glref{thread}: % \W\supp \begin{example} (hibernate-thread) \end{example} \end{functiondoc} %% ------------------------------------------------------------------------ \begin{functiondoc}{Function}{kill-thread}{\var{thread\/}} \index{thread!killing}% \index{killing a thread}% \fnsyntax \fnpurpose Kill a \glref{thread}. \fnpackage \code{:portable-threads} \fnmodule \code{:portable-threads} \fnargs \begin{args}{thread} \arg[thread] A \glref{thread} \end{args} \fnerrors \nothreads{} \begin{alsos}{thread-alive-p} \also[spawn-form] \also[spawn-thread] \also[thread-alive-p] \end{alsos} \fnexample % \W\supp \begin{example} (kill-thread thread) \end{example} \end{functiondoc} %% ------------------------------------------------------------------------ \begin{functiondoc}{Function}{make-condition-variable}% {\nobr{\code{\&rest} \var{initargs\/}} \nobr{\code{\&key} \var{class lock\/}} \nobr{\returns{} \var{condition-variable\/}}} \index{creating!a condition variable}% \index{making!a condition variable}% \index{condition variable!creating}% \fnsyntax \fnpurpose Create a new \glref{condition~variable}. \fnpackage \code{:portable-threads} \fnmodule \code{:portable-threads} \fnargs \begin{args}{condition-variable} \arg[initargs] An \glref{initialization~argument~list} \arg[class] The name of the \glref{class} for the created \glref{condition-variable} instance (default is \nobr{\code{condition-variable}}) \arg[lock] A \glref{lock}, a \glref{recursive~lock}, or a \glref{condition~variable} (default is a non-recursive lock) \arg[condition-variable] A \glref{condition~variable} \end{args} \fnreturns The created \nobr{\textbf{\entlink{condition-variable}}}. \begin{alsos}{make-recursive-lock} \also[make-instance] \also[make-lock] \also[make-recursive-lock] \also[with-lock-held] \also[without-lock-held] \end{alsos} \fnexamples Make a \nobr{\textbf{condition-variable}} instance with a non-recursive \glref{lock}: % \W\supp \begin{example} > (make-condition-variable) # > \end{example} % Make a \nobr{\textbf{condition-variable}} instance with a \glref{recursive~lock}: % \W\supp\notpretop \begin{example} > (make-condition-variable :lock (\entlink{make-recursive-lock})) # > \end{example} % Define a subclass of \nobr{\textbf{condition-variable}} that includes a \nobr{\code{state}} slot: % \W\supp\notpretop \begin{example} (defclass state-cv (condition-variable) ((state :initarg :state :initform nil :accessor state-of))) \end{example} % and then create a \nobr{\code{state-cv}} instance with a \glref{recursive~lock}: % \W\supp\notpretop \begin{example} > (make-condition-variable :class 'state-cv :lock (\entlink{make-recursive-lock})) # > \end{example} \fnnote % The \textbf{make-condition-variable} function is equivalent to using \nobr{\textbf{\entlinknoex{make-instance}}} with the desired \glref{class} for the created \glref{condition-variable} instance. However, using \nobr{\textbf{make-condition-variable}} is preferable stylistically. \end{functiondoc} %% ------------------------------------------------------------------------ \begin{functiondoc}{Function}{make-lock}{% \nobr{\code{\&key} \var{name\/}} \nobr{\returns{} \var{lock\/}}} \index{lock!creating}% \index{creating!a lock}% \index{making!a lock}% \fnsyntax \fnpurpose Create a \glref{lock}. \fnpackage \code{:portable-threads} \fnmodule \code{:portable-threads} \fnargs \begin{args}{name} \arg[name] A string. \arg[lock] A \glref{lock} \end{args} \fnreturns The newly created \glref{lock}. \begin{alsos}{make-condition-variable} \also[make-condition-variable] \also[make-recursive-lock] \also[thread-holds-lock-p] \also[with-lock-held] \also[without-lock-held] \end{alsos} \fnexample % \W\supp \begin{example} > (make-lock :name "Priority Queue") # > \end{example} \fnnote % On Common Lisp implementations without threads, a ``pseudo-lock'' object is returned. \end{functiondoc} %% ------------------------------------------------------------------------ \begin{functiondoc}{Function}{make-recursive-lock}{% \nobr{\code{\&key} \var{name\/}} \nobr{\returns{} \var{recursive-lock\/}}} \index{lock!creating}% \index{creating!a lock}% \index{making!a lock}% \fnsyntax \fnpurpose Create a \glref{recursive~lock}. \fnpackage \code{:portable-threads} \fnmodule \code{:portable-threads} \fnargs \begin{args}{name} \arg[name] A string. \arg[lock] A \glref{recursive~lock} \end{args} \fnreturns The newly created \glref{recursive~lock}. \begin{alsos}{make-condition-variable} \also[make-condition-variable] \also[make-lock] \also[thread-holds-lock-p] \also[with-lock-held] \also[without-lock-held] \end{alsos} \fnexample % \W\supp \begin{example} > (make-recursive-lock :name "Priority Queue") # > \end{example} \fnnote % On Common Lisp implementations without threads, a ``pseudo-recursive-lock'' object is returned. \end{functiondoc} %% ------------------------------------------------------------------------ \begin{functiondoc}{Constant}{nearly-forever-seconds}{}% \codeindexit{sleep}% \bfindexit{nearly-forever-seconds}% \fnsyntax \fnpurpose The maximum number of seconds supported by \code{sleep}. \fnpackage \code{:portable-threads} \fnmodule \code{:portable-threads} \fnvaluetype A \glref{fixnum} \fnvalue Implementation dependent \begin{alsos}{sleep-nearly-forever} \also[sleep-nearly-forever] \end{alsos} \end{functiondoc} %% ------------------------------------------------------------------------ \begin{functiondoc}{Function}{run-in-thread}{\var{thread function\/} \nobr{\code{\&rest} \var{args\/}}} \index{thread!running a function in}% \fnsyntax \fnpurpose Force \var{thread\/} to apply \nobr{\var{function\/}} to \nobr{\var{args\/}}. \fnpackage \code{:portable-threads} \fnmodule \code{:portable-threads} \fnargs \begin{args}{function} \arg[thread] A \glref{thread} \arg[function] A \glref{function~designator} \arg[args] Arguments to the function \end{args} \fnerrors \nothreads{} \begin{alsos}{spawn-thread} \also[spawn-form] \also[spawn-thread] \end{alsos} \fnexample % \W\supp \begin{example} (run-in-thread thread #'(lambda (result) (throw ':exit result)) result) \end{example} \end{functiondoc} %% ------------------------------------------------------------------------ \begin{functiondoc}{Function}{sleep-nearly-forever}{% \nobr{\code{\&optional} \var{seconds\/}}} \fnsyntax \fnpurpose A maximum-time-bounded \code{sleep}. \fnpackage \code{:portable-threads} \fnmodule \code{:portable-threads} \fnargs \begin{args}{function} \arg[seconds] An integer (default is \nobr{\textbf{\entlink{nearly-forever-seconds}}}) \end{args} \fndescription % \codeindexit{sleep}% \bfindexit{nearly-forever-seconds}% % Calls \code{sleep} with \var{seconds\/} or \nobr{\textbf{\entlink{nearly-forever-seconds}}}, whichever is less. Using \nobr{\textbf{nearly-forever-seconds}} protects against exceeding the duration limit of the Common Lisp implementation's \code{sleep} function for very long duration sleeping, by truncating the duration to \nobr{\textbf{\entlink{nearly-forever-seconds}}}. \begin{alsos}{nearly-forever-seconds} \also[nearly-forever-seconds] \end{alsos} \bfindexit{nearly-forever-seconds}% \fnexamples % \W\supp \begin{example} > (sleep-nearly-forever) ; sleep for a very long time \textrm{\ldots{}} > (sleep-nearly-forever ; sleep as long as the above (* 2 \entlink{nearly-forever-seconds})) \textrm{\ldots{}} > \end{example} \end{functiondoc} %% ------------------------------------------------------------------------ \begin{functiondoc}{Macro}{spawn-form}{\var{form\/}\superstar \nobr{\returns{} \var{thread\/}}} \index{thread!spawning}% \index{creating!a thread}% \index{making!a thread}% \fnsyntax \fnpurpose Evaluate \var{forms\/} in a new \glref{thread}. \fnpackage \code{:portable-threads} \fnmodule \code{:portable-threads} \fnargs \begin{args}{function} \arg[form] A \glref{form} \arg[thread] A \glref{thread} \end{args} \fnreturns The object representing the new \glref{thread}. \fnerrors \nothreads{} \begin{alsos}{symbol-value-in-thread} \also[all-threads] \also[awaken-thread] \also[current-thread] \also[hibernate-thread] \also[kill-thread] \also[spawn-thread] \also[thread-alive-p] \also[thread-name] \also[thread-whostate] \also[threadp] \also[run-in-thread] \also[symbol-value-in-thread] \end{alsos} \fnexample % \W\supp \begin{example} > (spawn-form (sleep 60)) # > \end{example} \end{functiondoc} %% ------------------------------------------------------------------------ \begin{functiondoc}{Function}{spawn-thread}{\var{name function\/} \nobr{\code{\&rest} \var{args\/}} \nobr{\returns{} \var{thread\/}}} \index{thread!spawning}% \index{creating!a thread}% \index{making!a thread}% \fnsyntax \fnpurpose Spawn a new \glref{thread}. \fnpackage \code{:portable-threads} \fnmodule \code{:portable-threads} \fnargs \begin{args}{function} \arg[name] A string \arg[function] A \glref{function~designator} \arg[args] Arguments to the function \arg[thread] A \glref{thread} \end{args} \fnreturns The object representing the new \glref{thread}. \fnerrors \nothreads{} \begin{alsos}{symbol-value-in-thread} \also[all-threads] \also[awaken-thread] \also[current-thread] \also[hibernate-thread] \also[kill-thread] \also[spawn-form] \also[thread-alive-p] \also[thread-name] \also[thread-whostate] \also[threadp] \also[run-in-thread] \also[symbol-value-in-thread] \end{alsos} \fnexample % \W\supp \begin{example} > (spawn-thread "Sleepy" #'sleep 60) # > \end{example} \end{functiondoc} %% ------------------------------------------------------------------------ \begin{functiondoc}{Function}{symbol-value-in-thread}{% \var{symbol thread\/} \nobr{\returns{} \nobr{\var{object, boundp\/}}}} \index{thread!symbol value in}% \index{value, of a symbol in a thread}% \fnsyntax \fnpurpose Return the value of \var{symbol\/} in a \glref{thread}. \fnpackage \code{:portable-threads} \fnmodule \code{:portable-threads} \fnargs \begin{args}{function} \arg[symbol] A symbol \arg[thread] A \glref{thread} \arg[object] An object \arg[boundp] A \glref{generalized~boolean} \end{args} \fnreturns Two values: \begin{tightitemize} \item the value of \var{symbol\/} in \nobr{\var{thread\/}} or nil if no value is bound \item \code{t} if \var{symbol\/} is specially or globally bound in \nobr{\var{thread}}; otherwise \nil \end{tightitemize} \fndescription The global symbol value is returned as the first value if no thread-local value is bound. \begin{alsos}{spawn-thread} \also[spawn-form] \also[spawn-thread] \end{alsos} \fnexamples % \W\supp \begin{example} > (symbol-value-in-thread '*x* thread) 33 t > (symbol-value-in-thread 'pi thread) 3.141592653589793d0 t > (symbol-value-in-thread '*unbound* thread) nil nil > \end{example} \fnnote % On Common Lisp implementations without threads, this function obtains the global symbol value. \end{functiondoc} %% ------------------------------------------------------------------------ \begin{functiondoc}{Function}{thread-alive-p}{\var{thread\/} \nobr{\returns{} \var{boolean\/}}} \fnsyntax \fnpurpose Determine if a \glref{thread} is alive. \fnpackage \code{:portable-threads} \fnmodule \code{:portable-threads} \fnargs \begin{args}{thread} \arg[thread] A \glref{thread} \arg[boolean] A \glref{generalized~boolean} \end{args} \fnreturns True if \var{thread\/} is alive; \nil{} otherwise. \fnerrors \nothreads{} \begin{alsos}{spawn-thread} \also[all-threads] \also[kill-thread] \also[spawn-form] \also[spawn-thread] \end{alsos} \bfindexit{spawn-thread}% \bfindexit{kill-thread}% \fnexamples % \W\supp \begin{example} > (defparameter *silly-thread* (\entlink{spawn-thread} "Sleeper" 'sleep 10000)) *silly-thread* > (thread-alive-p *silly-thread*) t > (\entlink{kill-thread} *silly-thread*) t > (thread-alive-p *silly-thread*) nil > \end{example} \end{functiondoc} %% ------------------------------------------------------------------------ \begin{functiondoc}{Function}{thread-name}{\var{thread\/} \nobr{\returns{} \var{name-string\/}}} \fnsyntax \fnpurpose Return the name of a \glref{thread}. \fnsetf \fnsetfsyntax{thread-name}{\var{thread\/}}{\var{name-string\/}} \fnpackage \code{:portable-threads} \fnmodule \code{:portable-threads} \fnargs \begin{args}{thread} \arg[thread] A \glref{thread} \arg[name-string] A string \end{args} \fnreturns The name of \var{thread}. \fnerrors \nothreads{} \begin{alsos}{spawn-thread} \also[spawn-form] \also[spawn-thread] \end{alsos} \fnexamples % \W\supp \begin{example} > (thread-name thread) "Initial" > (setf (thread-name thread) "Version 2") "Version 2" > (thread-name thread) "Version 2" > \end{example} \fnnote % Digitool's \xsitelink{Macintosh Common Lisp}{http://www.digitool.com} does not support changing the thread name via \nobr{\textbf{setf}}. \end{functiondoc} %% ------------------------------------------------------------------------ \begin{functiondoc}{Function}{thread-whostate}{\var{thread\/} \nobr{\returns{} \var{whostate\/}}} \fnsyntax \fnpurpose Return a string that describes the current state of a \glref{thread}. \fnsetf \fnsetfsyntax{thread-whostate}% {\var{thread\/}}{\var{whostate\/}} \fnpackage \code{:portable-threads} \fnmodule \code{:portable-threads} \fnargs \begin{args}{whostate} \arg[thread] A \glref{thread} \arg[whostate] A string or \nil{} \end{args} \fnreturns The whostate string of the \glref{thread} or \nil. \fnerrors \nothreads{} \begin{alsos}{without-lock-held} \also[spawn-form] \also[spawn-thread] \also[with-lock-held] \also[without-lock-held] \end{alsos} \fnexample % \W\supp \begin{example} > (thread-whostate thread) "Running" > \end{example} \fnnote % Although the \var{whostate\/} value can provide helpful information when debugging, specific \nobr{\var{whostate\/}} values and their meanings vary among Common Lisp implementations and should not be used programmatically. Only \xsitelink{Allegro CL}{http://franz.com/products/allegrocl/}, \xsitelink{Clozure CL}{http://trac.clozure.com/ccl}, and Digitool's \xsitelink{Macintosh Common Lisp}{http://www.digitool.com} support user-settable whostates; \nobr{\textbf{(setf~whostate)}} is a no-op on other Common Lisp implementations. \end{functiondoc} %% ------------------------------------------------------------------------ \begin{functiondoc}{Function}{thread-yield}{\noargs{}} \index{thread!yielding to other threads}% \index{yielding to other threads}% \fnsyntax \fnpurpose Give other \glref{threads} a chance to execute. \fnpackage \code{:portable-threads} \fnmodule \code{:portable-threads} \fnexample % \W\supp \begin{example} (thread-yield) \end{example} \fnnote % On Common Lisp implementations without thread support, this function executes \nobr{\textbf{\entlink{run-polling-functions}}} if the \nobr{\code{:polling-functions}} module has been loaded. Otherwise, it is a no-op on non-threaded implementations. \end{functiondoc} %% ------------------------------------------------------------------------ \begin{functiondoc}{Function}{threadp}{\var{object\/} \nobr{\returns{} \var{boolean\/}}} \index{thread!checking state}% \fnsyntax \fnpurpose Check if \var{object\/} is an object representing a \glref{thread}. \fnpackage \code{:portable-threads} \fnmodule \code{:portable-threads} \fnargs \begin{args}{object} \arg[object] An object \arg[boolean] A \glref{generalized~boolean} \end{args} \fnreturns True if \var{object\/} is an object representing a \glref{thread}; \nil{} otherwise. \begin{alsos}{thread-alive-p} \also[all-threads] \also[spawn-form] \also[spawn-thread] \also[thread-alive-p] \end{alsos} \bfindexit{all-threads}% \fnexample % \W\supp \begin{example} > (threadp (car (\entlink{all-threads}))) t > \end{example} \end{functiondoc} %% ------------------------------------------------------------------------ \begin{functiondoc}{Function}{thread-holds-lock-p}{\var{lock\/} \nobr{\returns{} \var{boolean\/}}} \index{lock, held by current thread}% \fnsyntax \fnpurpose Determine if \var{lock\/} is held by the current \glref{thread}. \fnpackage \code{:portable-threads} \fnmodule \code{:portable-threads} \fnargs \begin{args}{boolean} \arg[lock] A \glref{lock}, a \glref{recursive~lock}, or a \glref{condition~variable} \arg[boolean] A \glref{generalized~boolean} \end{args} \fnreturns True if the current thread holds \var{lock}; \nil{} otherwise. \begin{alsos}{make-condition-variable} \also[make-condition-variable] \also[make-lock] \also[make-recursive-lock] \also[with-lock-held] \also[without-lock-held] \end{alsos} \bfindexit{with-lock-held}% \fnexamples Two simple examples using a \glref{lock}: % \W\supp \begin{example} > (thread-holds-lock-p lock) nil > (\entlink{with-lock-held} (lock) (thread-holds-lock-p lock)) t > \end{example} % Two more simple examples using a \glref{condition~variable}: % \W\supp\notpretop \begin{example} > (thread-holds-lock-p condition-variable) nil > (\entlink{with-lock-held} (condition-variable) (thread-holds-lock-p condition-variable)) t > \end{example} \end{functiondoc} %% ------------------------------------------------------------------------ \begin{functiondoc}{Macro}{with-lock-held}{% \nobr{\code{(}\var{lock\/} \code{\&key} \var{whostate\/}\code{)}} \nobr{\var{form\/}\superstar{}} \nobr{\returns{} \var{result\/}\superstar}} \index{lock!acquiring}% \index{acquiring!a lock}% \index{recursive lock!acquiring}% \index{acquiring!a recursive lock}% \fnsyntax \fnpurpose After acquiring a \glref{lock} or a \glref{recursive~lock}, execute forms and then release the lock. \fnpackage \code{:portable-threads} \fnmodule \code{:portable-threads} \fnargs \begin{args}{whostate} \arg[lock] A \glref{lock}, a \glref{recursive~lock}, or a \glref{condition~variable} \arg[whostate] A string (default \nobr{\code{"With Lock Held"}}) \arg[forms] An implicit \nobr{\textbf{progn}} of \glref{forms} to be evaluated \arg[results] The values returned by evaluating the last \var{form} \end{args} \fnreturns The values returned by evaluating the last \var{form}. \fnerrors A \glref{thread} attempts to re-acquire a (non-recursive) \glref{lock} that it holds. \fndescription If a \glref{thread} executes a \nobr{\textbf{with-lock-held}} that is dynamically inside another \nobr{\textbf{with-lock-held}} involving the same \glref{recursive~lock}, the inner \nobr{\textbf{with-lock-held}} simply proceeds as if it had acquired the lock. \begin{alsos}{thread-holds-lock-p} \also[make-condition-variable] \also[make-lock] \also[make-recursive-lock] \also[thread-holds-lock-p] \also[thread-whostate] \also[without-lock-held] \end{alsos} \fnexamples Acquire the lock controlling access to a critical section of code: % \W\supp \begin{example} (with-lock-held (lock :whostate "Waiting for Critical Lock") (critical-section)) \end{example} % A silly example showing a recursive re-acquisition of a \glref{recursive~lock}: % \W\supp\notpretop \begin{example} (with-lock-held (recursive-lock :whostate "Waiting for Critical Lock") (with-lock-held (recursive-lock :whostate "Again Waiting for Critical Lock") (critical-section))) \end{example} % \bfindexit{condition-variable-signal}% % Acquire the \glref{lock} associated with \nobr{\code{condition-variable}} and then signal all blocked \glref{threads} that are waiting on it: % \W\supp\notpretop \begin{example} (with-lock-held (condition-variable) (\entlink{condition-variable-signal} condition-variable)) \end{example} \fnnote % The \var{whostate\/} value is ignored by \xsitelink{SBCL}{http://sbcl.sourceforge.net}. \end{functiondoc} %% ------------------------------------------------------------------------ \begin{functiondoc}{Macro}{with-timeout}{% \nobr{\code{(}\var{seconds\/} \var{timeout-form\/}\superstar{}\code{)}} \nobr{\var{form\/}\superstar{}} \nobr{\returns{} \var{result\/}\superstar}} \fnsyntax \fnpurpose Bound the time allowed to evaluate \nobr{\var{forms\/}} to \nobr{\var{seconds}}, evaluating \nobr{\var{timeout-forms\/}} if the time limit is reached. \fnpackage \code{:portable-threads} \fnmodule \code{:portable-threads} \fnargs \begin{args}{whostate} \arg[seconds] A number \arg[timeout-forms] An implicit \nobr{\textbf{progn}} of \glref{forms} to be evaluated if the timed \nobr{\var{forms\/}} do not complete before \nobr{\var{seconds\/}} seconds have elapsed \arg[forms] An implicit \nobr{\textbf{progn}} of \glref{forms} to be evaluated \arg[results] The values returned by evaluating the last \var{form\/} or the last \nobr{\var{timeout-form\/}} \end{args} \fnreturns The values returned by evaluating the last \var{form\/} if completed in less than \nobr{\var{seconds\/}} seconds; otherwise the values returned by evaluating the last \nobr{\var{timeout-form\/}} \fnerrors \nothreads{} However, \nobr{\textbf{with-timeout}} is also supported on non-threaded \xsitelink{SBCL}{http://sbcl.sourceforge.net}. \fndescription If the evaluation of \nobr{\var{forms\/}} does not complete within \nobr{\var{seconds\/}} seconds, execution of \nobr{\var{forms\/}} is terminated and the \nobr{\var{timeout-forms\/}} are evaluated, returning the result of the last \nobr{\var{timeout-form}}. The \nobr{\var{timeout-forms\/}} are not evaluated if the \nobr{\var{forms\/}} complete within \nobr{\var{seconds\/}} seconds, in which case the result of the last \var{form\/} is returned. \begin{alsos}{condition-variable-wait-with-timeout} \also[condition-variable-wait-with-timeout] \end{alsos} \fnexamples Evaluate a simple form, with a one-second time out: % \W\supp \begin{example} > (with-timeout (1 ':timed-out) ':did-not-time-out) :did-not-time-out > \end{example} % Again, but this time sleep for two seconds to cause a time out: % \W\supp\notpretop \begin{example} > (with-timeout (1 ':timed-out) (sleep 2) ':did-not-time-out) :timed-out \textrm{\textcolor{green}{; (after 1 second)}} > \end{example} % Uses of \nobr{\textbf{with-timeout}} can be nested: % \W\supp\notpretop \begin{example} > (with-timeout (1 ':timed-out-outer) (with-timeout (2 ':timed-out-inner) (sleep 3) ':did-not-time-out)) :timed-out-outer \textrm{\textcolor{green}{; (after 1 second)}} > (with-timeout (2 ':timed-out-outer) (with-timeout (1 ':timed-out-inner) (sleep 3) ':did-not-time-out)) :timed-out-inner \textrm{\textcolor{green}{; (after 1 second)}} > \end{example} \end{functiondoc} %% ------------------------------------------------------------------------ \begin{functiondoc}{Macro}{without-lock-held}{\code{(}\var{lock\/} \code{\&key} \var{whostate\/}\code{)} \var{form\/}\superstar{} \returns{} \var{result\/}\superstar} \index{lock!releaseing temporarily}% \index{releasing!a lock, temporarily}% \index{recursive lock!releasing temporarily}% \index{releasing!a recursive lock, temporarily}% \fnsyntax \fnpurpose Temporarily release a \glref{lock} or a \glref{recursive~lock}, execute forms and then reacquire the lock. \fnpackage \code{:portable-threads} \fnmodule \code{:portable-threads} \fnargs \begin{args}{whostate} \arg[lock] A \glref{lock}, a \glref{recursive~lock}, or a \glref{condition~variable} \arg[whostate] A string (default \nobr{\code{"Without Lock Held"}}) \arg[forms] An implicit \nobr{\textbf{progn}} of \glref{forms} to be evaluated \arg[results] The values returned by evaluating the last \var{form} \end{args} \fnreturns The values returned by evaluating the last \var{form}. \fnerrors A \glref{thread} attempts to release a \glref{lock} that it does not hold. \begin{alsos}{thread-holds-lock-p} \also[make-condition-variable] \also[make-lock] \also[make-recursive-lock] \also[thread-holds-lock-p] \also[thread-whostate] \also[with-lock-held] \end{alsos} \fnexample % \bfindexit{with-lock-held}% % Acquire and temporarily release a lock controlling access to several critical sections of code: % \W\supp \begin{example} (\entlink{with-lock-held} (lock :whostate "Waiting for Critical Lock") (critical-section-1) (without-lock-held (lock :whostate "Doing non-critical stuff") (non-critical-section)) (critical-section-2)) \end{example} \fnnote % The \var{whostate\/} value is ignored by \xsitelink{SBCL}{http://sbcl.sourceforge.net}. \end{functiondoc} %% ------------------------------------------------------------------------ \T\markright{}% \T\pagestyle{plain} \T\clearpage \W\xname{ref-scheduled-function-entities} \T\pagestyle{fancy} \T\thispagestyle{fancybottom} \T\global\def\fnlastname{ }% \subsection{Scheduled and Periodic Functions} \label{sec:scheduledfunctions}% \indexit{module!:portable-threads@\code{:portable-threads}}% \indexit{:portable-threads@\code{:portable-threads} module}% GBBopen provides two forms of time-scheduled functions: \glref{scheduled~functions} and \glref{periodic~functions}, both built using \reflink{Portable Threads}{sec:portablethreads}. These time-scheduled-function entities are provided by the \nobr{\code{:portable-threads}} module. \psubpar{Scheduled Functions} A \glref{scheduled~function} is an object that contains a \glref{function} to be run at a specified time. When that specified time arrives, the \glref{function} is invoked with a single argument: the \glref{scheduled~function} object. A repeat interval (in seconds) can also be specified for the \glref{scheduled~function}. This value is used whenever the \glref{scheduled~function} is invoked to schedule itself again at a new time relative to the current invocation. \glref{Scheduled~functions} can be scheduled to a resolution of one second. \glref{Scheduled~functions} are scheduled and invoked by a separate \nobr{\code{"Scheduled-Function Scheduler"}} \glref{thread}. Unless the run time of the invoked function is brief, the invoked function should spawn a new thread in which to perform its activities so as to avoid delaying the invocation of a subsequent \glref{scheduled~function}. \psubpar{Periodic Functions} \codeindexit{sleep}% % A \glref{periodic~function} is a \glref{function} to be run repeatedly at a specified interval. Unlike \glref{scheduled~functions}, which can be scheduled only to a resolution of one second, a \glref{periodic~function} can be repeated at intervals as brief as is supported by the \nobr{\code{sleep}} function of the Common Lisp implementation. A \glref{periodic~function} is scheduled and executed in its own \glref{thread}. As with \glref{scheduled~functions}, the invoked function should spawn a new thread in which to perform its activities, unless its run time is brief. \W\entities \T\psubpar{Portable Threads entities} \T Descriptions of the Portable Threads entities follow. \T\clearpage %% ------------------------------------------------------------------------ \begin{functiondoc}[periodic-function-verbose-var]{Variable}% {*periodic-function-verbose*}{}% \fnsyntax \fnpurpose Controls whether initiation and termination of \glref{periodic-function} \glref{threads} are printed as comments. \fnpackage \code{:portable-threads} \fnmodule \code{:portable-threads} \fnvaluetype A \glref{generalized~boolean} \fninitialvalue \nil \fndescription The value of \nobr{\textbf{*periodic-function-verbose*}} can be changed globally to display the management of \glref{periodic~functions}. \begin{alsos}{spawn-periodic-function} \also[kill-periodic-function] \also[spawn-periodic-function] \end{alsos} \bfindexit{spawn-periodic-function}% \fnexample Schedule a simple \glref{periodic~function} with verbose printing enabled: % \W\supp \begin{example} > (setf *periodic-function-verbose* 't) t > (\entlink{spawn-periodic-function} #'(lambda () (print "Hello!")) 0.1 :name 'hello :count 2) ;; Spawning periodic-function thread for hello... # > "Hello!" "Hello!" ;; Exiting periodic-function thread hello > \end{example} \end{functiondoc} %% ------------------------------------------------------------------------ \begin{functiondoc}[schedule-function-verbose-var]{Variable}% {*schedule-function-verbose*}{}% \fnsyntax \fnpurpose Controls whether scheduling changes made to \glref{scheduled~functions} are printed as comments. \fnpackage \code{:portable-threads} \fnmodule \code{:portable-threads} \fnvaluetype A \glref{generalized~boolean} \fninitialvalue \nil \fndescription The value of \nobr{\textbf{*schedule-function-verbose*}} can be changed globally to display the activities of the \glref{scheduled~function} scheduler. \begin{alsos}{schedule-function-relative} \also[schedule-function] \also[schedule-function-relative] \also[unschedule-function] \end{alsos} \bfindexit{encode-time-of-day}% \fnexample Change the invocation time of \glref{scheduled~function} \nobr{\code{quitting-time}} from 5pm to 5:30pm with verbose printing enabled: % \W\supp \begin{example} > (setf *schedule-function-verbose* 't) t > (schedule-function 'quitting-time (\entlink{encode-time-of-day} 17 30 0) :repeat-interval #.(* 24 60 60)) ;; Unscheduling #... ;; Scheduling # ;; as the next scheduled-function... > \end{example} \end{functiondoc} %% ------------------------------------------------------------------------ \begin{functiondoc}{Function}{all-scheduled-functions}{\noargs{} \nobr{\returns{} \var{list-of-scheduled-functions\/}}} \index{scheduled functions!obtaining all}% \index{function!scheduled, obtaining all}% \fnsyntax \fnpurpose Return the list of all \glref{scheduled~functions} that are currently scheduled. \fnpackage \code{:portable-threads} \fnmodule \code{:portable-threads} \fnargs \begin{args}{list-of-scheduled-functions} \arg[list-of-scheduled-functions] A proper list \end{args} \fnreturns A list of \nobr{\code{scheduled-function}} objects. \begin{alsos}{schedule-function-relative} \also[make-scheduled-function] \also[schedule-function] \also[schedule-function-relative] \also[unschedule-function] \end{alsos} \fnexample % \W\supp \begin{example} > (all-threads) (#) > \end{example} \fnnotes % On Common Lisp implementations without threads, \nil{} is returned. \bfindexit{schedule-function}% \bfindexit{unschedule-function}% % The returned list of \glref{scheduled~functions} should not be destructively altered. In particular, unscheduling a scheduled function (using \nobr{\textbf{\entlink{unschedule-function}}}) or changing a scheduled function's invocation time (using \nobr{\textbf{\entlink{schedule-function}}}) may modify the list of scheduled functions, so a copy of the returned list of scheduled functions should be used for any iteration that involves these operations. \end{functiondoc} %% ------------------------------------------------------------------------ \begin{functiondoc}{Function}{kill-periodic-function}{\noargs{}} \index{periodic function!terminating}% \index{function!periodic, terminating}% \fnsyntax \fnpurpose Terminate the thread invoking a \glref{periodic~function}. \fnpackage \code{:portable-threads} \fnmodule \code{:portable-threads} \fnerrors \nothreads{} \textbf{Kill-periodic-function} called outside the dynamic scope of a \glref{periodic~function}. \begin{alsos}{*periodic-function-verbose*} \also[*periodic-function-verbose*] \also[all-threads] \also[kill-thread] \also[spawn-periodic-function] \end{alsos} \bfindexit{define-event-class}% \bfindexit{signal-event}% \bfindexit{control-shell-running-p}% \bfindexit{spawn-periodic-function}% % \fnexample Define and spawn a \glref{periodic~function} that is invoked every 0.5 seconds to signal a \nobr{\code{half-second-interrupt-event}}, continuing as long as the control shell is running: % \W\supp \begin{example} > (\entlink{define-event-class} half-second-timer-event (timer-interrupt-event) ()) half-second-timer-event > (defun half-second-timer () (unless (\entlink{control-shell-running-p}) (kill-periodic-function)) (\entlink{signal-event} 'half-second-timer-event)) half-second-timer > (\entlink{spawn-periodic-function} 'half-second-timer 0.5) # > \end{example} \end{functiondoc} %% ------------------------------------------------------------------------ \begin{functiondoc}{Function}{make-scheduled-function}{\var{function\/} \nobr{\code{\&key} \var{name name-test marker marker-test\/}} \nobr{\returns{} \var{scheduled-function\/}}} \index{scheduled function!creating}% \index{function!scheduled, creating}% \index{creating!a scheduled function}% \index{making!a scheduled function}% \fnsyntax \fnpurpose Create a \glref{scheduled~function}. \fnpackage \code{:portable-threads} \fnmodule \code{:portable-threads} \fnargs \begin{args}{scheduled-function} \arg[function] A \glref{function~designator} specifying a \glref{function~object} of one argument \arg[name] An object (typically a string or a symbol; default is \nobr{\var{function}}, if \nobr{\var{function\/}} is a symbol, otherwise \nil) \arg[name-test] A \glref{function~designator} specifying a \glref{function~object} of two arguments that returns a \glref{generalized~boolean} (default is \nobr{\code{\#'eql}}) \arg[marker] An object (default is \nil) \arg[marker-test] A \glref{function~designator} specifying a \glref{function~object} of two arguments that returns a \glref{generalized~boolean} (default is \nobr{\code{\#'eql}}) \arg[scheduled-function] A \glref{scheduled~function} \end{args} \fnreturns The newly created \glref{scheduled~function}. \fnerrors \nothreads{} \fndescription Unless the run time to perform \nobr{\var{function\/}} is brief, it should spawn a new \glref{thread} in which to perform its activities so as to avoid delaying the invocation of a subsequent \glref{scheduled~function}. The optional \var{marker\/} and associated comparison \var{marker-test\/} can be specified to distinguish \glref{scheduled~functions} with the same \var{name} in calls to \nobr{\textbf{\entlink{schedule-function}}}, \nobr{\textbf{\entlink{schedule-function-relative}}}, and \nobr{\textbf{\entlink{unschedule-function}}}. \begin{alsos}{scheduled-function-scheduler-running-p} \also[*schedule-function-verbose*] \also[all-scheduled-functions] \also[pause-scheduled-function-scheduler] \also[restart-scheduled-function-scheduler] \also[resume-scheduled-function-scheduler] \also[schedule-function] \also[schedule-function-relative] \also[scheduled-function-marker] \also[scheduled-function-marker-test] \also[scheduled-function-name] \also[scheduled-function-name-test] \also[scheduled-function-repeat-interval] \also[scheduled-function-scheduler-paused-p] \also[scheduled-function-scheduler-running-p] \also[spawn-periodic-function] \also[unschedule-function] \end{alsos} \fnexamples % Create a \glref{scheduled~function} that simply prints \nobr{\code{"Hello"}} when invoked: % \W\supp \begin{example} > (make-scheduled-function #'(lambda (scheduled-function) (declare (ignore scheduled-function)) (print "Hello")) :name 'hello) # > \end{example} \bfindexit{scheduled-function-repeat-interval}% \bfindexit{spawn-thread}% % A more complex \glref{scheduled~function} that spawns a new \glref{thread} to do its work and randomly sets whether to reschedule itself (and at what interval): % \W\supp \begin{example} > (defun complex-function (scheduled-function) (let ((interval (random 100))) (setf (\entlink{scheduled-function-repeat-interval} scheduled-function) (if (plusp interval) ;; repeat 1-99 seconds from now: interval ;; don't repeat 1\% of the time: nil))) (\entlink{spawn-thread} "Lots of stuff doer" #'do-lots-of-stuff)) complex-function > (make-scheduled-function 'complex-function) # > \end{example} \end{functiondoc} %% ------------------------------------------------------------------------ \begin{functiondoc}{Function}{pause-scheduled-function-scheduler}% {\noargs{}} \index{scheduled function!scheduler, pausing}% \fnsyntax \fnpurpose Pause \glref{scheduled-function} scheduling. \fnpackage \code{:portable-threads} \fnmodule \code{:portable-threads} \fnerrors \nothreads{} \fndescription Pausing the \glref{scheduled-function} scheduler causes all scheduled functions whose invocation time arrives to be held pending until the scheduled-function scheduler is resumed. \begin{alsos}{scheduled-function-scheduler-running-p} \also[resume-scheduled-function-scheduler] \also[scheduled-function-scheduler-paused-p] \also[scheduled-function-scheduler-running-p] \end{alsos} \bfindexit{scheduled-function-scheduler-paused-p}% \fnexample Pause the \glref{scheduled-function} scheduler: % \W\supp \begin{example} > (\entlink{scheduled-function-scheduler-paused-p}) nil > (pause-scheduled-function-scheduler) > (\entlink{scheduled-function-scheduler-paused-p}) t > \end{example} \end{functiondoc} %% ------------------------------------------------------------------------ \begin{functiondoc}{Function}{restart-scheduled-function-scheduler}% {\noargs{} \nobr{\returns{} \var{thread\/}}} \index{scheduled function!scheduler, restarting}% \fnsyntax \fnpurpose Restart the \glref{scheduled-function} scheduling thread. \fnpackage \code{:portable-threads} \fnmodule \code{:portable-threads} \fnargs \begin{args}{thread} \arg[thread] A \glref{thread} or \nil{} \end{args} \fnreturns The object representing the newly spawned \glref{scheduled-function} scheduler \glref{thread} or \nil{} if the \glref{scheduled-function} scheduler was already running. \fnerrors \nothreads{} \fndescription If the \glref{scheduled-function} scheduler \glref{thread} has been killed accidentally, this function can be used to start a new scheduler \glref{thread}. \begin{alsos}{scheduled-function-scheduler-running-p} \also[resume-scheduled-function-scheduler] \also[schedule-function] \also[scheduled-function-repeat-interval] \also[scheduled-function-scheduler-paused-p] \also[scheduled-function-scheduler-running-p] \also[unschedule-function] \end{alsos} \fnexamples Restart the \glref{scheduled-function} scheduler: % \W\supp \begin{example} > (restart-scheduled-function-scheduler) # > \end{example} % Restarting a \glref{scheduled-function} scheduler that is already running has no effect: % \W\supp\notpretop \begin{example} > (restart-scheduled-function-scheduler) ;; The scheduled-function scheduler is already running. nil > \end{example} \end{functiondoc} %% ------------------------------------------------------------------------ \begin{functiondoc}{Function}{resume-scheduled-function-scheduler}% {\noargs{}} \index{scheduled function!scheduler, resuming}% \fnsyntax \fnpurpose Resume \glref{scheduled-function} scheduling. \fnpackage \code{:portable-threads} \fnmodule \code{:portable-threads} \fnerrors \nothreads{} \fndescription Resuming the \glref{scheduled-function} scheduler causes all scheduled functions that have been held pending while the scheduled-function scheduler was paused to be invoked as if their invocation time had just occurred. \begin{alsos}{scheduled-function-scheduler-running-p} \also[pause-scheduled-function-scheduler] \also[scheduled-function-scheduler-paused-p] \also[scheduled-function-scheduler-running-p] \end{alsos} \bfindexit{scheduled-function-scheduler-paused-p}% \fnexample Resume the \glref{scheduled-function} scheduler: % \W\supp \begin{example} > (\entlink{scheduled-function-scheduler-paused-p}) t > (resume-scheduled-function-scheduler) > (\entlink{scheduled-function-scheduler-paused-p}) nil > \end{example} \end{functiondoc} %% ------------------------------------------------------------------------ \begin{functiondoc}{Function}{schedule-function}% {\var{\nobr{name-or-scheduled-function} \nobr{invocation-time\/}} \nobr{\code{\&key} \var{marker repeat-interval verbose\/}}} \index{scheduled function!scheduling}% \index{function!scheduled, scheduling}% \index{scheduling!a scheduled function}% \fnsyntax \fnpurpose Schedule a \glref{scheduled~function} at an absolute invocation time. \fnpackage \code{:portable-threads} \fnmodule \code{:portable-threads} \fnargs \begin{args}{name-or-scheduled-function} \arg[name-or-scheduled-function] An object (typically a string or a symbol) naming a currently scheduled \glref{scheduled~function} or a \nobr{\code{scheduled-function}} object \arg[invocation-time] A \glref{Universal~Time} \arg[marker] An object (default is \nil) \arg[repeat-interval] A positive integer (representing seconds) or \nil{} (default is \nil) \arg[verbose] A \glref{generalized~boolean} (default is \nobr{\textbf{\entlink{*schedule-function-verbose*}}}) \end{args} \fnerrors \nothreads{} \fndescription If the \nobr{\glref{scheduled~function}} is unscheduled, the \nobr{\code{scheduled-function}} object must be specified as the \nobr{\var{name-or-scheduled-function\/}} value. In this case, the \nobr{\glref{scheduled~function}} it is added to the list of currently scheduled \nobr{\glref{scheduled~functions}} with the specified \nobr{\var{invocation-time\/}} and optional \nobr{\var{repeat-interval}}, if specified. If the \nobr{\var{scheduled-function\/}} object is currently scheduled, either the \nobr{\code{scheduled-function}} object or the optional \var{name\/} value that was specified when the \nobr{\code{scheduled-function}} object was created with \nobr{\textbf{\entlink{make-scheduled-function}}} can be specified as the \nobr{\var{name-or-scheduled-function\/}} value. If a name is specified as the \nobr{\var{name-or-scheduled-function\/}} value and more than one \nobr{\glref{scheduled~function}} with the specified \var{name\/} is currently scheduled, the \nobr{\glref{scheduled~function}} with the earliest invocation time is selected. If an optional \var{marker\/} value was specified along with \var{name\/} when the \nobr{\code{scheduled-function}} object was created with \nobr{\textbf{\entlink{make-scheduled-function}}}, the \var{marker\/} value can also be specified to restrict the selected \nobr{\glref{scheduled~function}} to the one with the earliest invocation time that matches both the \var{name\/} and \var{marker} values. The selected \nobr{\glref{scheduled~function}} is first unscheduled and then rescheduled with the specified \nobr{\var{invocation-time\/}} and optional \nobr{\var{repeat-interval}}, if specified. \begin{alsos}{scheduled-function-scheduler-running-p} \also[*schedule-function-verbose*] \also[all-scheduled-functions] \also[encode-time-of-day] \also[make-scheduled-function] \also[restart-scheduled-function-scheduler] \also[schedule-function-relative] \also[scheduled-function-repeat-interval] \also[scheduled-function-scheduler-paused-p] \also[scheduled-function-scheduler-running-p] \also[spawn-periodic-function] \also[unschedule-function] \end{alsos} \bfindexit{make-scheduled-function}% \fnexamples Schedule a \glref{scheduled~function} that simply prints \nobr{\code{"Happy New Year!"}} at midnight (local time) on January 1, 2010: % \W\supp \begin{example} > (schedule-function (\entlink{make-scheduled-function} #'(lambda (scheduled-function) (declare (ignore scheduled-function)) (print "Happy New Year!"))) (encode-universal-time 0 0 0 1 1 2010)) > (all-scheduled-functions) (#) > \end{example} % \bfindexit{make-scheduled-function}% \bfindexit{encode-time-of-day}% % Schedule a \glref{scheduled~function} that prints \nobr{\code{"It's quitting time!"}} every day at 5pm: % \W\supp\notpretop \begin{example} > (schedule-function (\entlink{make-scheduled-function} #'(lambda (scheduled-function) (declare (ignore scheduled-function)) (print "It's quitting time!")) :name 'quitting-time) (\entlink{encode-time-of-day} 17 0 0) :repeat-interval #.(* 24 60 60)) > \end{example} % \bfindexit{encode-time-of-day}% % Verbosely change \nobr{\code{quitting-time}} to 5:30pm every day: % \W\supp\notpretop \begin{example} > (schedule-function 'quitting-time (\entlink{encode-time-of-day} 17 30 0) :repeat-interval #.(* 24 60 60) :verbose 't) ;; Unscheduling #... ;; Scheduling # ;; as the next scheduled-function... > \end{example} \end{functiondoc} %% ------------------------------------------------------------------------ \begin{functiondoc}{Function}{schedule-function-relative}% {\var{\nobr{name-or-scheduled-function} seconds\/} \nobr{\code{\&key} \var{marker repeat-interval verbose\/}}} \index{scheduled function!scheduling}% \index{function!scheduled, scheduling}% \index{scheduling!a scheduled function}% \fnsyntax \fnpurpose Schedule a \glref{scheduled~function} a specified number of seconds from now. \fnpackage \code{:portable-threads} \fnmodule \code{:portable-threads} \fnargs \begin{args}{name-or-scheduled-function} \arg[name-or-scheduled-function] An object (typically a string or a symbol) naming a currently scheduled \glref{scheduled~function} or a \nobr{\code{scheduled-function}} object \arg[seconds] A positive integer \arg[marker] An object (default is \nil) \arg[repeat-interval] A positive integer (representing seconds) or \nil{} (default is \nil) \arg[verbose] A \glref{generalized~boolean} (default is \nobr{\textbf{\entlink{*schedule-function-verbose*}}}) \end{args} \fnerrors \nothreads{} \fndescription If the \nobr{\glref{scheduled~function}} is unscheduled, the \nobr{\code{scheduled-function}} object must be specified as the \nobr{\var{name-or-scheduled-function\/}} value. In this case, the \nobr{\glref{scheduled~function}} it is added to the list of currently scheduled \nobr{\glref{scheduled~functions}} with an invocation time of \nobr{\var{interval\/}} seconds from the current time and optional \nobr{\var{repeat-interval}}, if specified. If the \nobr{\var{scheduled-function\/}} object is currently scheduled, either the \nobr{\code{scheduled-function}} object or the optional \var{name\/} value that was specified when the \nobr{\code{scheduled-function}} object was created with \nobr{\textbf{\entlink{make-scheduled-function}}} can be specified as the \nobr{\var{name-or-scheduled-function\/}} value. If a name is specified as the \nobr{\var{name-or-scheduled-function\/}} value and more than one \nobr{\glref{scheduled~function}} with the specified \var{name\/} is currently scheduled, the \nobr{\glref{scheduled~function}} with the earliest invocation time is selected. If an optional \var{marker\/} value was specified along with \var{name\/} when the \nobr{\code{scheduled-function}} object was created with \nobr{\textbf{\entlink{make-scheduled-function}}}, the \var{marker\/} value can also be specified to restrict the selected \nobr{\glref{scheduled~function}} to the one with the earliest invocation time that matches both the \var{name\/} and \var{marker} values. The selected \nobr{\glref{scheduled~function}} is first unscheduled and then rescheduled with an invocation time of \nobr{\var{interval\/}} seconds from the current time and optional \nobr{\var{repeat-interval}}, if specified. \begin{alsos}{scheduled-function-scheduler-running-p} \also[*schedule-function-verbose*] \also[all-scheduled-functions] \also[make-scheduled-function] \also[restart-scheduled-function-scheduler] \also[schedule-function] \also[scheduled-function-invocation-time] \also[scheduled-function-marker] \also[scheduled-function-marker-test] \also[scheduled-function-name] \also[scheduled-function-name-test] \also[scheduled-function-repeat-interval] \also[scheduled-function-scheduler-paused-p] \also[scheduled-function-scheduler-running-p] \also[spawn-periodic-function] \also[unschedule-function] \end{alsos} \bfindexit{make-scheduled-function}% \fnexamples % Schedule a \glref{scheduled~function} that simply prints \nobr{\code{"Hello!"}} 5 seconds from now: % \W\supp \begin{example} > (schedule-function-relative (\entlink{make-scheduled-function} #'(lambda (scheduled-function) (declare (ignore scheduled-function)) (print "Hello!"))) 5) > \end{example} % \bfindexit{make-scheduled-function}% \bfindexit{signal-event}% % Schedule a \glref{scheduled~function} that signals a GBBopen \nobr{\code{timer-interrupt-event}} every 30 seconds: % \W\supp\notpretop \begin{example} > (schedule-function-relative (\entlink{make-scheduled-function} #'(lambda (scheduled-function) (declare (ignore scheduled-function)) (\entlink{signal-event} 'timer-interrupt-event))) 30 :repeat-interval 30) > \end{example} \fnnote % The form \nobr{\code{(schedule-function-relative} \nobr{\var{scheduled-function\/}} \code{10)}} is equivalent to \nobr{\code{(\entlink{schedule-function}} \var{scheduled-function\/} \code{(+ (get-universal-time) 10))}}. \end{functiondoc} %% ------------------------------------------------------------------------ \begin{functiondoc}{Function}{scheduled-function-invocation-time}% {\nobr{\var{scheduled-function\/}} \nobr{\returns{} \var{invocation-time\/}}} \index{function!scheduled, invocation time}% \fnsyntax \fnpurpose Return the invocation time of a \glref{scheduled~function}. \fnpackage \code{:portable-threads} \fnmodule \code{:portable-threads} \fnargs \begin{args}{scheduled-function} \arg[scheduled-function] A \glref{scheduled~function} \arg[invocation-time] A \glref{Universal~Time} \end{args} \fnreturns The invocation time of \var{scheduled-function}. \begin{alsos}{schedule-function-relative} \also[all-scheduled-functions] \also[make-scheduled-function] \also[schedule-function] \also[schedule-function-relative] \also[scheduled-function-marker] \also[scheduled-function-marker-test] \also[scheduled-function-name] \also[scheduled-function-name-test] \also[scheduled-function-repeat-interval] \end{alsos} \fnexample % Return the invocation-time of \glref{scheduled~function} \nobr{\code{scheduled-function}}: % \W\supp \begin{example} > (scheduled-function-invocation-time scheduled-function) 3465679813 > \end{example} \end{functiondoc} %% ------------------------------------------------------------------------ \begin{functiondoc}{Function}{scheduled-function-marker}% {\nobr{\var{scheduled-function\/}} \nobr{\returns{} \var{marker\/}}} \index{function!scheduled, marker}% \fnsyntax \fnpurpose Return the marker of a \glref{scheduled~function}. \fnpackage \code{:portable-threads} \fnmodule \code{:portable-threads} \fnargs \begin{args}{scheduled-function} \arg[scheduled-function] A \glref{scheduled~function} \arg[marker] An object \end{args} \fnreturns The marker of \var{scheduled-function}. \begin{alsos}{schedule-function-relative} \also[all-scheduled-functions] \also[make-scheduled-function] \also[schedule-function] \also[schedule-function-relative] \also[scheduled-function-marker-test] \also[scheduled-function-name] \also[scheduled-function-name-test] \also[scheduled-function-repeat-interval] \end{alsos} \bfindexit{all-scheduled-functions}% \fnexample % Return a list of the markers of all currently scheduled \glref{scheduled~functions}: % \W\supp \begin{example} > (mapcar #'scheduled-function-marker (\entlink{all-scheduled-functions})) (nil) > \end{example} \end{functiondoc} %% ------------------------------------------------------------------------ \begin{functiondoc}{Function}{scheduled-function-marker-test}% {\nobr{\var{scheduled-function\/}} \nobr{\returns{} \var{marker-predicate\/}}} \index{function!scheduled, test}% \fnsyntax \fnpurpose Return the marker-comparison predicate of a \glref{scheduled~function}. \fnpackage \code{:portable-threads} \fnmodule \code{:portable-threads} \fnargs \begin{args}{scheduled-function} \arg[scheduled-function] A \glref{scheduled~function} \arg[marker-predicate] A \glref{function~designator} specifying a \glref{function~object} of two arguments that returns a \glref{generalized~boolean} \end{args} \fnreturns The marker-comparison predicate of \var{scheduled-function}. \begin{alsos}{schedule-function-relative} \also[all-scheduled-functions] \also[make-scheduled-function] \also[schedule-function] \also[schedule-function-relative] \also[scheduled-function-invocation-time] \also[scheduled-function-marker] \also[scheduled-function-name] \also[scheduled-function-name-test] \end{alsos} \bfindexit{all-scheduled-functions}% \fnexample % Return a list of the marker-comparison predicates of all currently scheduled \glref{scheduled~functions}: % \W\supp \begin{example} > (mapcar #'scheduled-function-marker-test (\entlink{all-scheduled-functions})) (#'eql) > \end{example} \end{functiondoc} %% ------------------------------------------------------------------------ \begin{functiondoc}{Function}{scheduled-function-name}% {\nobr{\var{scheduled-function\/}} \nobr{\returns{} \var{name\/}}} \index{function!scheduled, name}% \fnsyntax \fnpurpose Return the name of a \glref{scheduled~function}. \fnpackage \code{:portable-threads} \fnmodule \code{:portable-threads} \fnargs \begin{args}{scheduled-function} \arg[scheduled-function] A \glref{scheduled~function} \arg[name] An object (typically a string or a symbol) \end{args} \fnreturns The name of \var{scheduled-function}. \begin{alsos}{schedule-function-relative} \also[all-scheduled-functions] \also[make-scheduled-function] \also[schedule-function] \also[schedule-function-relative] \also[scheduled-function-marker] \also[scheduled-function-marker-test] \also[scheduled-function-name-test] \also[scheduled-function-repeat-interval] \end{alsos} \bfindexit{all-scheduled-functions}% \fnexample % Return the names of all currently scheduled \glref{scheduled~functions}: % \W\supp \begin{example} > (mapcar #'scheduled-function-name (\entlink{all-scheduled-functions})) (quitting-time) > \end{example} \end{functiondoc} %% ------------------------------------------------------------------------ \begin{functiondoc}{Function}{scheduled-function-name-test}% {\nobr{\var{scheduled-function\/}} \nobr{\returns{} \var{name-predicate\/}}} \index{function!scheduled, test}% \fnsyntax \fnpurpose Return the name-comparison predicate of a \glref{scheduled~function}. \fnpackage \code{:portable-threads} \fnmodule \code{:portable-threads} \fnargs \begin{args}{scheduled-function} \arg[scheduled-function] A \glref{scheduled~function} \arg[name-predicate] A \glref{function~designator} specifying a \glref{function~object} of two arguments that returns a \glref{generalized~boolean} \end{args} \fnreturns The name-comparison predicate of \var{scheduled-function}. \begin{alsos}{schedule-function-relative} \also[all-scheduled-functions] \also[make-scheduled-function] \also[schedule-function] \also[schedule-function-relative] \also[scheduled-function-invocation-time] \also[scheduled-function-marker] \also[scheduled-function-name] \also[scheduled-function-name-test] \end{alsos} \bfindexit{all-scheduled-functions}% \fnexample % Return a list of the name-comparison predicates of all currently scheduled \glref{scheduled~functions}: % \W\supp \begin{example} > (mapcar #'scheduled-function-name-test (\entlink{all-scheduled-functions})) (#'eql) > \end{example} \end{functiondoc} %% ------------------------------------------------------------------------ \begin{functiondoc}{Function}{scheduled-function-repeat-interval}% {\nobr{\var{scheduled-function\/}} \nobr{\returns{} \var{repeat-interval\/}}} \index{function!scheduled, repeat-interval value}% \index{changing!repeat-interval, of a scheduled function}% \fnsyntax \fnpurpose Return the repeat interval of a \glref{scheduled~function}. \fnsetf \fnsetfsyntax{scheduled-function-repeat-interval}% {\var{scheduled-function\/}}{\var{repeat-interval\/}} \fnpackage \code{:portable-threads} \fnmodule \code{:portable-threads} \fnargs \begin{args}{scheduled-function} \arg[scheduled-function] A \glref{scheduled~function} \arg[repeat-interval] A positive integer (representing seconds) or \nil \end{args} \fnreturns The repeat interval of \var{scheduled-function}. \begin{alsos}{schedule-function-relative} \also[all-scheduled-functions] \also[make-scheduled-function] \also[schedule-function] \also[schedule-function-relative] \also[scheduled-function-marker] \also[scheduled-function-marker-test] \also[scheduled-function-name] \also[scheduled-function-name-test] \end{alsos} \bfindexit{all-scheduled-functions}% \fnexamples % Display the \nobr{\code{scheduled-function}} object and its repeat interval for each currently scheduled \glref{scheduled~function}: % \W\supp \begin{example} > (dolist (scheduled-function (\entlink{all-scheduled-functions})) (format t "~&;; ~s ~s~\%" scheduled-function (scheduled-function-repeat-interval scheduled-function))) ;; # 86400 nil > \end{example} Define a \glref{function} to be used as a \glref{scheduled~function} that randomly sets whether to reschedule itself (and at what interval): % \W\supp \begin{example} (defun complex-function (scheduled-function) (let ((interval (random 100))) (setf (scheduled-function-repeat-interval scheduled-function) (if (plusp interval) ;; repeat 1-99 seconds from now: interval ;; don't repeat 1\% of the time: nil))) (do-some-stuff)) \end{example} \end{functiondoc} %% ------------------------------------------------------------------------ \begin{functiondoc}{Function}{scheduled-function-scheduler-paused-p}% {\noargs{} \nobr{\returns{} \var{boolean\/}}} \index{scheduled function!scheduler, checking paused status}% \fnsyntax \fnpurpose Determine if \glref{scheduled-function} scheduling is paused. \fnpackage \code{:portable-threads} \fnmodule \code{:portable-threads} \fnargs \begin{args}{boolean} \arg[boolean] A \glref{generalized~boolean} \end{args} \fnreturns True if the \glref{scheduled-function} scheduler is paused; \nil{} otherwise. \fnerrors \nothreads{} \begin{alsos}{scheduled-function-scheduler-running-p} \also[pause-scheduled-function-scheduler] \also[resume-scheduled-function-scheduler] \also[scheduled-function-scheduler-running-p] \end{alsos} \bfindexit{pause-scheduled-function-scheduler}% \fnexample Pause the \glref{scheduled-function} scheduler: % \W\supp \begin{example} > (scheduled-function-scheduler-paused-p) nil > (\entlink{pause-scheduled-function-scheduler}) > (scheduled-function-scheduler-paused-p) t > \end{example} \end{functiondoc} %% ------------------------------------------------------------------------ \begin{functiondoc}{Function}{scheduled-function-scheduler-running-p}% {\noargs{} \nobr{\returns{} \var{boolean\/}}} \index{scheduled function!scheduler, checking running status}% \fnsyntax \fnpurpose Determine if the \glref{scheduled-function} scheduler is running. \fnpackage \code{:portable-threads} \fnmodule \code{:portable-threads} \fnargs \begin{args}{boolean} \arg[boolean] A \glref{generalized~boolean} \end{args} \fnreturns True if the \glref{scheduled-function} scheduler is running; \nil{} otherwise. \fnerrors \nothreads{} \begin{alsos}{scheduled-function-scheduler-paused-p} \also[pause-scheduled-function-scheduler] \also[restart-scheduled-function-scheduler] \also[resume-scheduled-function-scheduler] \also[scheduled-function-scheduler-paused-p] \end{alsos} \fnexample Check that the \glref{scheduled-function} scheduler is running: % \W\supp \begin{example} > (scheduled-function-scheduler-running-p) t > \end{example} \end{functiondoc} %% ------------------------------------------------------------------------ \begin{functiondoc}{Function}{spawn-periodic-function}% {\var{function \nobr{repeat-interval\/}} \nobr{\code{\&key} \var{count name verbose\/}} \nobr{\returns{} \var{thread\/}}} \index{periodic function!spawning}% \index{function!periodic, spawning}% \fnsyntax \fnpurpose Spawn a thread invoking \nobr{\var{function\/}} every \nobr{\var{repeat-interval\/}} seconds. \fnpackage \code{:portable-threads} \fnmodule \code{:portable-threads} \fnargs \begin{args}{repeat-interval} \arg[function] A \glref{function~designator} specifying a \glref{function~object} of no arguments \arg[repeat-interval] A number (representing seconds) \arg[count] A number or \nil{} (default is \nil) \arg[name] An object (typically a string or a symbol; default is \nobr{\var{function}}, if \nobr{\var{function\/}} is a symbol, otherwise \nil) \arg[verbose] A \glref{generalized~boolean} (default is \nobr{\textbf{\entlink{*periodic-function-verbose*}}}) \arg[thread] A \glref{thread} \end{args} \fnreturns The object representing the \glref{thread} associated with the \glref{periodic~function}. \fnerrors \nothreads{} \fndescription If \var{count\/} is \nil, \nobr{\var{function\/}} will continue to be invoked every \nobr{\var{repeat-interval\/}} seconds until the \glref{periodic-function} \glref{thread} is killed or until \nobr{\var{function\/}} calls \nobr{\textbf{\entlink{kill-periodic-function}}}. Otherwise, \nobr{\var{count\/}} is decremented by one prior to each invocation of \nobr{\var{function\/}} and, if it is negative, the \glref{periodic~function} is terminated. \begin{alsos}{*periodic-function-verbose*} \also[*periodic-function-verbose*] \also[all-threads] \also[kill-periodic-function] \also[kill-thread] \also[make-scheduled-function] \also[schedule-function] \also[schedule-function-relative] \end{alsos} \fnexamples Spawn a simple \glref{periodic~function} that is invoked every 0.1 seconds, but that only runs twice: % \W\supp \begin{example} > (spawn-periodic-function #'(lambda () (print "Hello!")) 0.1 :name 'hello :count 2) # > "Hello!" "Hello!" \end{example} % \bfindexit{kill-periodic-function}% % Spawn a simple \glref{periodic~function} that is invoked every 0.1 seconds that runs up to 20 times, but with a 10\% chance on each invocation of terminating early: % \W\supp\notpretop \begin{example} > (spawn-periodic-function #'(lambda () (when (zerop (random 10)) (kill-periodic-function)) (print "Hello!")) 0.1 :count 20 :verbose 't) ;; Spawning periodic-function thread for... # > "Hello!" "Hello!" "Hello!" "Hello!" ;; Killing periodic-function... ;; Exiting periodic-function thread \end{example} % \bfindexit{define-event-class}% \bfindexit{signal-event}% \bfindexit{control-shell-running-p}% \bfindexit{kill-periodic-function}% % Define and spawn a \glref{periodic~function} that is invoked every 0.5 seconds to signal a \nobr{\code{half-second-interrupt-event}}, continuing as long as the control shell is running: % \W\supp\notpretop \begin{example} > (\entlink{define-event-class} half-second-timer-event (timer-interrupt-event) ()) half-second-timer-event > (defun half-second-timer () (unless (\entlink{control-shell-running-p}) (\entlink{kill-periodic-function})) (\entlink{signal-event} 'half-second-timer-event)) half-second-timer > (spawn-periodic-function 'half-second-timer 0.5) # > \end{example} \end{functiondoc} %% ------------------------------------------------------------------------ \begin{functiondoc}{Function}{unschedule-function}% {\nobr{\var{name-or-scheduled-function\/}} \nobr{\code{\&key} \var{marker warnp verbose\/}} \nobr{\returns{} \var{boolean\/}}} \index{scheduled function!canceling scheduling}% \index{function!scheduled, canceling scheduling}% \index{scheduling!canceling a scheduled function}% \index{unscheduling!a scheduled function}% \fnsyntax \fnpurpose Cancel the upcoming invocation (and subsequent repeat-interval scheduling) of a currently scheduled \glref{scheduled~function}. \fnpackage \code{:portable-threads} \fnmodule \code{:portable-threads} \fnargs \begin{args}{name-or-scheduled-function} \arg[name-or-scheduled-function] An object (typically a string or a symbol) naming a currently scheduled \glref{scheduled~function} or a \nobr{\code{scheduled-function}} object \arg[marker] An object (default is \nil) \arg[verbose] A \glref{generalized~boolean} (default is \nobr{\textbf{\entlink{*schedule-function-verbose*}}}) \arg[warnp] A \glref{generalized~boolean} (default is \code{t}) \arg[boolean] A \glref{generalized~boolean} \end{args} \fnreturns The \glref{scheduled~function} if it was unscheduled; \nil{} if the \glref{scheduled~function} was not currently scheduled or was not found. \fnerrors \nothreads{} \fndescription If the \nobr{\var{scheduled-function\/}} object is currently scheduled, either the \nobr{\code{scheduled-function}} object or the optional \var{name\/} value that was specified when the \nobr{\code{scheduled-function}} object was created with \nobr{\textbf{\entlink{make-scheduled-function}}} can be specified as the \nobr{\var{name-or-scheduled-function\/}} value. If a name is specified as the \nobr{\var{name-or-scheduled-function\/}} value and more than one \nobr{\glref{scheduled~function}} with the specified \var{name\/} is currently scheduled, the \nobr{\glref{scheduled~function}} with the earliest invocation time is selected. If an optional \var{marker\/} value was specified along with \var{name\/} when the \nobr{\code{scheduled-function}} object was created with \nobr{\textbf{\entlink{make-scheduled-function}}}, the \var{marker\/} value can also be specified to restrict the selected \nobr{\glref{scheduled~function}} to the one with the earliest invocation time that matches both the \var{name\/} and \var{marker} values. The selected \nobr{\glref{scheduled~function}} is removed from the list of currently scheduled \glref{scheduled~functions}. If \var{warnp} is true, a warning is issued if the \glref{scheduled~function} was not currently scheduled or was not found. \begin{alsos}{restart-scheduled-function-scheduler} \also[*schedule-function-verbose*] \also[all-scheduled-functions] \also[make-scheduled-function] \also[schedule-function] \also[schedule-function-relative] \end{alsos} \fnexamples Unschedule the \nobr{\code{quitting-time}} \glref{scheduled~function}: % \W\supp \begin{example} > (unschedule-function 'quitting-time) # > \end{example} % \bfindexit{all-scheduled-functions}% % Unschedule all currently scheduled \glref{scheduled~functions}: % \W\supp\notpretop \begin{example} > (\entlink{all-scheduled-functions}) (#) > (mapc #'unschedule-function (\entlink{all-scheduled-functions})) (#) > (\entlink{all-scheduled-functions}) nil > \end{example} % Unschedule a non-existent \glref{scheduled~function}: % \W\supp\notpretop \begin{example} > (unschedule-function 'non-existent) ;; Warning: Scheduled-function non-existent was not scheduled; no action taken. nil > \end{example} \end{functiondoc} %% ------------------------------------------------------------------------ \T\markright{}% \T\pagestyle{plain} \T\clearpage \W\xname{ref-polling-function-entities} \T\pagestyle{fancy} \T\thispagestyle{fancybottom} \T\global\def\fnlastname{ }% \subsection{Polling Functions} \label{sec:pollingfunctions}% \index{module!:polling-functions@\code{:polling-functions}}% \index{:polling-functions@\code{:polling-functions} module}% % The \code{:polling-functions} \glref{module} provides a set of \textit{polling functions\/} that can be used to support ``event-loop'' processing on Common Lisp implementations that do not provide threads. These functions are available for use with all Common Lisp implementations. \W\entities \T\clearpage %% ------------------------------------------------------------------------ \begin{functiondoc}{Function}{add-polling-function}% {\var{function\/} \nobr{\code{\&key} \var{priority\/}}} \index{polling function!adding a}% \fnsyntax \fnpurpose Add a polling \glref{function} to the list of polling functions at the position indicated by \nobr{\var{priority}}. \fnpackage \code{:gbbopen-tools} \fnmodule \code{:polling-functions} \fnargs \begin{args}{priority} \arg[function] A \glref{function~designator} specifying a \glref{function~object} of no arguments \arg[priority] A \code{\glref{fixnum}} (default is \code{0}) \end{args} \fndescription \bfindexit{*standard-output*}% The description is printed to the {\bf *standard-output*} stream. \begin{alsos}{describe-all-polling-functions} \also[describe-all-polling-functions] \also[remove-all-polling-functions] \also[remove-polling-function] \also[run-polling-functions] \end{alsos} \fnexample Add the \glref{function} \nobr{\code{check-for-new-connection}} to the list of polling functions (with priority -10): % \W\supp \begin{example} (add-polling-function #'check-for-new-connection :priority -10) \end{example} \end{functiondoc} %% ------------------------------------------------------------------------ \begin{functiondoc}{Function}{describe-all-polling-functions}{\noargs} \index{polling function!printing information about}% \index{printing!information about!polling functions}% \fnsyntax \fnpurpose Describe the polling functions in the list of polling functions. \fnpackage \code{:gbbopen-tools} \fnmodule \code{:polling-functions} \fndescription \bfindexit{*standard-output*}% The description is printed to the {\bf *standard-output*} stream. \begin{alsos}{remove-all-polling-functions} \also[add-polling-function] \also[remove-all-polling-functions] \also[remove-polling-function] \also[run-polling-functions] \end{alsos} \fnexample Describe list of polling functions: % \W\supp \begin{example} > (describe-all-polling-functions) ;; Polling functions: ;; -10 # > \end{example} \end{functiondoc} %% ------------------------------------------------------------------------ \begin{functiondoc}{Function}{remove-polling-function}{\var{function\/}} \index{polling function!removing a}% \fnsyntax \fnpurpose Remove a polling \glref{function} from the list of polling functions. \fnpackage \code{:gbbopen-tools} \fnmodule \code{:polling-functions} \fnargs \begin{args}{function} \arg[function] A \glref{function~designator} \end{args} \begin{alsos}{describe-all-polling-functions} \also[add-polling-function] \also[describe-all-polling-functions] \also[remove-all-polling-functions] \also[run-polling-functions] \end{alsos} \fnexample Remove the \glref{function} \nobr{\code{check-for-new-connection}} from the list of polling functions: % \W\supp \begin{example} (remove-polling-function #'check-for-new-connection) \end{example} \end{functiondoc} %% ------------------------------------------------------------------------ \begin{functiondoc}{Function}{remove-all-polling-functions}{\noargs} \index{polling function!removing every}% \fnsyntax \fnpurpose Remove all polling functions from the list of polling functions. \fnpackage \code{:gbbopen-tools} \fnmodule \code{:polling-functions} \begin{alsos}{describe-all-polling-functions} \also[add-polling-function] \also[describe-all-polling-functions] \also[remove-polling-function] \also[run-polling-functions] \end{alsos} \fnexample Remove all functions from the list of polling functions: % \W\supp \begin{example} (remove-all-polling-functions) \end{example} \end{functiondoc} %% ------------------------------------------------------------------------ \begin{functiondoc}{Function}{run-polling-functions}{\noargs} \index{polling function!running}% \fnsyntax \fnpurpose Run every polling \glref{function} in the list of polling functions. \fnpackage \code{:gbbopen-tools} \fnmodule \code{:polling-functions} \begin{alsos}{describe-all-polling-functions} \also[add-polling-function] \also[describe-all-polling-functions] \also[remove-all-polling-functions] \also[remove-polling-function] \also[start-control-shell] \end{alsos} \fnexample Run the polling functions (once, in sequence): % \W\supp \begin{example} (run-polling-functions) \end{example} \bfindexit{start-control-shell}% \index{polling function!called by the control shell}% \fnnote \pollingnote \end{functiondoc} %% ------------------------------------------------------------------------ \T\markright{}% \T\pagestyle{plain} \T\clearpage \W\xname{ref-portable-socket-entities} \T\pagestyle{fancy} \T\thispagestyle{fancybottom} \T\global\def\fnlastname{ }% \subsection{Portable Sockets} \label{sec:portablesockets}% \index{module!:portable-sockets@\code{:portable-sockets}}% \index{:portable-sockets@\code{:portable-sockets} module}% % The \code{:portable-sockets} \glref{module} provides a uniform interface to commonly used socket entities. \W\entities \T\clearpage %% ------------------------------------------------------------------------ \begin{functiondoc}{Function}{accept-connection}{\var{passive-socket\/} \nobr{\code{\&key} \var{wait\/}} \nobr{\returns{} \var{socket-stream\/}}} \index{connection!accepting}% \index{socket stream!accept connection}% \index{accept a socket stream connection}% \fnsyntax \fnpurpose Accept a socket-stream connection. \fnpackage \code{:portable-sockets} \fnmodule \code{:portable-sockets} \fnargs \begin{args}{passive-socket} \arg[passive-socket] A \glref{passive~socket} \arg[wait] A \glref{generalized~boolean} (default is \code{t}) \arg[socket-stream] A socket stream \end{args} \fnreturns A socket stream. \begin{alsos}{shutdown-socket-stream} \also[shutdown-socket-stream] \also[start-connection-server] \end{alsos} \bfindexit{make-passive-socket}% \bfindexit{close-passive-socket}% \fnexample Accept a connection made to a newly created passive socket: % \W\supp \begin{example} > (let* ((passive-socket (\entlink{make-passive-socket} 5555)) (connection (accept-connection passive-socket))) (\entlink{close-passive-socket} passive-socket) connection) # > \end{example} \fnnote % Connections should always be closed using \nobr{\textbf{close}} (from both sides) to free up operating-system resources when they are no longer needed. \end{functiondoc} %% ------------------------------------------------------------------------ \begin{functiondoc}{Function}{close-passive-socket}{\var{passive-socket\/}} \index{socket!passive, closing}% \index{passive socket, closing}% \fnsyntax \fnpurpose Close a passive socket. \fnpackage \code{:portable-sockets} \fnmodule \code{:portable-sockets} \fnargs \begin{args}{passive-socket} \arg[passive-socket] A \glref{passive~socket} \end{args} \begin{alsos}{make-passive-socket} \also[make-passive-socket] \end{alsos} \fnexample Close a passive socket: % \W\supp \begin{example} (close-passive-socket passive-socket) \end{example} \end{functiondoc} %% ------------------------------------------------------------------------ \begin{functiondoc}{Function}{local-hostname-and-port}% {\nobr{\var{socket-stream\/}} \nobr{\code{\&optional} \var{do-not-resolve\/}} \nobr{\returns{} \var{hostname, port}}} \index{socket stream!local hostname}% \index{socket stream!local port}% \index{local hostname!of an open socket stream}% \index{local port!of an open socket stream}% \fnsyntax \fnpurpose Return the name of the host on the local side of the \nobr{\var{socket-stream\/}} connection and its port number. \fnpackage \code{:portable-sockets} \fnmodule \code{:portable-sockets} \fnargs \begin{args}{socket-stream} \arg[socket-stream] A socket stream \arg[do-not-resolve] A \glref{generalized~boolean} (default is \nil) \arg[hostname] A string \arg[port] An integer \end{args} \fnreturns Two values: \begin{tightitemize} \item a string containing the name of the local host \item the integer port number at the local host \end{tightitemize} \begin{alsos}{remote-hostname-and-port} \also[open-connection] \also[remote-hostname-and-port] \also[with-open-connection] \end{alsos} \fnexamples Return the local hostname and port of an open socket-stream connection to the \nobr{\code{wiki.alu.org}} web server: % \W\supp \begin{example} > (local-hostname-and-port connection) "192.168.240.104 (ruby.gbbopen.org)" 56833 > \end{example} % Return the local hostname and port of the open socket-stream connection, but without hostname resolution: % \W\supp\notpretop \begin{example} > (local-hostname-and-port connection 't) "192.168.240.104" 56833 > \end{example} \end{functiondoc} %% ------------------------------------------------------------------------ \begin{functiondoc}{Function}{make-passive-socket}% {\var{port\/} \nobr{\code{\&key} \var{backlog interface reuse-address\/}} \nobr{\returns{} \var{passive-socket\/}}} \index{socket!passive, making}% \index{passive socket, making}% \fnsyntax \fnpurpose Create a \glref{passive~socket} that can accept connections. \fnpackage \code{:portable-sockets} \fnmodule \code{:portable-sockets} \fnargs \begin{args}{reuse-address} \arg[port] An integer or a string specifying the service port \arg[backlog] An integer (default is 5) \arg[interface] A 32-bit internet address or a string specifying a network interface on the local machine or \nil \arg[reuse-address] A \glref{generalized~boolean} (default is \nil) \arg[passive-socket] A \glref{passive~socket} \end{args} \fnreturns The new \glref{passive~socket}. \fndescription An \var{interface\/} string can be either a host name, such as \nobr{\code{"localhost"}} or a ``dotted'' IP address, such as \nobr{\code{"127.0.0.1"}}. The value of \nobr{\var{backlog\/}} tells the operating system how many unprocessed connections can be held pending (connected but still awaiting an \nobr{\textbf{\entlink{accept-connection}}}). \begin{alsos}{start-connection-server} \also[accept-connection] \also[start-connection-server] \end{alsos} \fnexample Create a passive socket, listening on port 5555: % \W\supp \begin{example} > (make-passive-socket 5555) # > \end{example} \bfindexit{close-passive-socket}% \fnnote % The passive socket should be closed using \nobr{\textbf{\entlink{close-passive-socket}}} when the service is no longer needed in order to free up operating system resources. \end{functiondoc} %% ------------------------------------------------------------------------ \begin{functiondoc}{Generic~Function}{open-connection}{\var{host port\/} \nobr{\returns{} \var{socket-stream\/}}} \index{connection!opening}% \index{socket stream connection!opening}% \index{opening!a socket stream connection}% \fnsyntax \fnpurpose Open a socket-stream connection to server \var{host}. \fnmethods \fnalternate{open-connection}{\code{(}\var{host\/} \code{integer)} \var{port\/} \returns{} \var{socket-stream\/}} \fnalternate{open-connection}{\code{(}\var{host\/} \code{string)} \var{port\/} \returns{} \var{socket-stream\/}} \fnpackage \code{:portable-sockets} \fnmodule \code{:portable-sockets} \fnargs \begin{args}{socket-stream} \arg[host] A 32-bit internet address or a string specifying the remote host \arg[port] An integer or a string specifying the service port \arg[socket-stream] A socket stream \end{args} \fnreturns A socket stream. \fndescription A \var{host\/} string can be either a host name or a ``dotted'' IP address, such as \nobr{\code{"127.0.0.1"}}. String values available for specifying \var{port\/} are found in the operating system's services file and labeled as being \code{tcp} services. On Unix systems, the services file is \nobr{\code{/etc/services}}. On Windows, it is the file \nobr{\code{services}} in the \nobr{\code{Windows}} directory. \begin{alsos}{shutdown-socket-stream} \also[shutdown-socket-stream] \also[with-open-connection] \end{alsos} \fnexample Open a socket connection to the GBBopen Project web server: % \W\supp \begin{example} > (open-connection "GBBopen.org" 80) # > \end{example} \fnnote % Connections should always be closed using \nobr{\textbf{close}} (from both sides) when they are no longer needed to free up operating-system resources. \end{functiondoc} %% ------------------------------------------------------------------------ \begin{functiondoc}{Function}{remote-hostname-and-port}% {\var{socket-stream\/} \nobr{\code{\&optional} \var{do-not-resolve\/}} \nobr{\returns{} \var{hostname, port}}} \index{socket stream!remote hostname}% \index{socket stream!remote port}% \index{remote hostname!of an open socket stream}% \index{remote port!of an open socket stream}% \fnsyntax \fnpurpose Return the name of the host on the remote side of the \nobr{\var{socket-stream\/}} connection and its port number. \fnpackage \code{:portable-sockets} \fnmodule \code{:portable-sockets} \fnargs \begin{args}{socket-stream} \arg[socket-stream] A socket stream \arg[do-not-resolve] A \glref{generalized~boolean} (defaulto is \nil) \arg[hostname] A string \arg[port] An integer \end{args} \fnreturns Two values: \begin{tightitemize} \item a string containing the name of the remote host \item the integer port number at the remote host \end{tightitemize} \begin{alsos}{local-hostname-and-port} \also[open-connection] \also[local-hostname-and-port] \also[with-open-connection] \end{alsos} \fnexamples Return the remote hostname and port of an open socket-stream connection to the \nobr{\code{wiki.alu.org}} web server: % \W\supp \begin{example} > (remote-hostname-and-port connection) "206.169.106.4 (bibop.alu.org)" 80 > \end{example} % Return the remote hostname and port of the open socket-stream connection, but without hostname resolution: % \W\supp\notpretop \begin{example} > (remote-hostname-and-port connection 't) "206.169.106.4" 80 > \end{example} \end{functiondoc} %% ------------------------------------------------------------------------ \begin{functiondoc}{Function}{shutdown-socket-stream}% {\var{socket-stream direction\/}} \index{socket stream!shutdown}% \index{close one direction of an open socket stream}% \fnsyntax \fnpurpose Shut down (close) one direction of an open connection. \fnpackage \code{:portable-sockets} \fnmodule \code{:portable-sockets} \fnargs \begin{args}{socket-stream} \arg[socket-stream] A socket stream \arg[direction] The \glref{keyword~symbol} \nobr{\code{:input}} or \nobr{\code{:output}} specifying the direction to be closed \end{args} \begin{alsos}{start-connection-server} \also[start-connection-server] \also[open-connection] \also[with-open-connection] \end{alsos} \fnexample Tell the other end of a socket connection that we are done sending output on the socket stream (send an end-of-file indication): % \W\supp \begin{example} (shutdown-socket-stream socket-stream ':output) \end{example} \fnnote % Connections should always be closed using \nobr{\textbf{close}} (from both sides) when they are no longer needed to free up operating-system resources. \end{functiondoc} %% ------------------------------------------------------------------------ \begin{functiondoc}{Function}{start-connection-server}% {\var{function port\/} \nobr{\code{\&key} \var{backlog interface name reuse-address\/}} \nobr{\returns{} \var{thread\/}}} \index{socket!accepting connections}% \index{socket!connection server}% \index{connection server!starting}% \index{starting!a connection server}% \fnsyntax \fnpurpose Create a connection-server thread that accepts connections and processes them according to \nobr{\var{function}}. \fnpackage \code{:portable-sockets} \fnmodule \code{:portable-sockets} \fnargs \begin{args}{reuse-address} \arg[function] A \glref{function~designator} specifying a \glref{function~object} of one argument \arg[port] An integer or a string specifying the service port \arg[backlog] An integer (default is 5) \arg[interface] A 32-bit internet address or a string specifying a network interface on the local machine or \nil \arg[name] A string (default is \nobr{\code{"Connection Server"}}) \arg[reuse-address] A \glref{generalized~boolean} (default is \nil) \arg[thread] A \glref{thread} \end{args} \fnreturns The new connection-server \glref{thread}. \fnerrors \nothreads{} \bfindexit{accept-connection}% \fndescription The connection server will not accept another connection until \nobr{\var{function\/}} returns, so normally \nobr{\var{function\/}} should spawn another thread to handle the connection. An \var{interface\/} string can be either a host name, such as \nobr{\code{"localhost"}} or a ``dotted'' IP address, such as \nobr{\code{"127.0.0.1"}}. The value of \nobr{\var{backlog\/}} tells the operating system how many unprocessed connections can be held pending (connected but still awaiting an \nobr{\textbf{\entlink{accept-connection}}}). \begin{alsos}{with-open-connection} \also[kill-thread] \also[open-connection] \also[with-open-connection] \end{alsos} \fnexample Start a simple connection server that accepts connections on port 5555, reads one line of input, and closes the connection: % \W\supp \begin{verbatim} > (start-connection-server #'(lambda (connection) (let ((line (read-line connection nil))) (format t "~&;; New Connection: ~a~%" line) (close connection))) 5555) # \end{verbatim} \bfindexit{kill-thread}% \fnnote % Use \nobr{\textbf{\entlink{kill-thread}}} to kill the connection-server thread. \end{functiondoc} %% ------------------------------------------------------------------------ \begin{functiondoc}{Macro}{with-open-connection}% {\code{(}\var{var host port\/}\code{)} \nobr{\var{declaration\/}\superstar{}} \nobr{\var{form\/}\superstar{}}} \index{connection!opening}% \index{socket stream!opening}% \index{opening!a socket stream connection}% \fnsyntax \fnpurpose Open a socket-stream connection to server \var{host}, perform a series of operations on the connection, and then close the connection. \fnpackage \code{:portable-sockets} \fnmodule \code{:portable-sockets} \fnargs \begin{args}{host} \arg[var] A \glref{variable~symbol} \arg[host] A 32-bit internet address or a string specifying the remote host \arg[port] An integer or a string specifying the service port \arg[declaration] A declare expression (not evaluated) \arg[forms] An implicit \nobr{\textbf{progn}} of \glref{forms} to be evaluated \end{args} \fndescription This macro ensures that the opened connection is closed when control leaves the body of the macro. A \var{host\/} string can be either a host name or a ``dotted'' IP address, such as \nobr{\code{"127.0.0.1"}}. String values available for specifying \var{port\/} are found in the operating system's services file and labeled as being \code{tcp} services. On Unix systems, the services file is \nobr{\code{/etc/services}}. On Windows, it is the file \nobr{\code{services}} in the \nobr{\code{Windows}} directory. \begin{alsos}{shutdown-socket-stream} \also[open-connection] \also[shutdown-socket-stream] \end{alsos} \fnexample Open a socket connection to the GBBopen Project web server: % \W\supp \begin{verbatim} > (with-open-connection (connection "GBBopen.org" 80) (flet ((write-crlf (stream) ;; HTTP requires CR/LF line termination: (write-char #\return stream) (write-char #\linefeed stream))) (format connection "GET / HTTP/1.1") (write-crlf connection) (format connection "Host: ~a:~a" host port) (write-crlf connection) (write-crlf connection) (force-output connection) (let ((line (read-line connection))) (format t "~&;; Received: ~a~%" line)))) ;; Received: HTTP/1.1 200 OK > \end{verbatim} \end{functiondoc} %% ------------------------------------------------------------------------ \T\markright{}% \T\pagestyle{plain} \T\clearpage \W\xname{ref-double-metaphone-entities} \T\pagestyle{fancy} \T\thispagestyle{fancybottom} \T\global\def\fnlastname{ }% \subsection{Double Metaphone} \label{sec:double-metaphone}% \index{module!:double-metaphone@\code{:double-metaphone}}% \index{:double-metaphone@\code{:double-metaphone} module}% % The \nobr{\code{:double-metaphone}} \glref{module} provides Double Metaphone phonetic-code generation. The Metaphone algorithm, published by Lawrence Philips in 1990, improved early phonetic approaches, such as Soundex, by attempting to correctly code cases where ``gh'' is pronounced as ``f'' as in ``laugh'' and when it is silent, as in ``dough,'' or where ``t,'' ``c,'' and ``s'' are pronounced as ``sh'' (or ``ch,'' which is treated as a sound that is similar enough to ``sh'' to be mapped to the same encoding value) as in ``ratio,'' ``ciao,'' and ``erosion.'' Although Metaphone was an improvement, it failed to encode many common words accurately, including the silent ``l'' in ``lincoln,'' and the case of ``school'' where ``ch'' is pronounced as ``k.'' Also, by using the Soundex style of encoding an initial vowel as it appears, Metaphone results in different encodings for ``Otto'' and ``auto,'' which sound similar enough to match. Double Metaphone was published by Lawrence Philips in 2000 to improve accuracy further than was achieved by Metaphone. It maps all initial vowels to ``A,'' matching ``Otto'' to ``auto.'' It attempts to correctly encode a number of common words and names commonly found in the United States that are of non-english origin and are usually pronounced correctly according to their non-english spellings, by Americans, such as ``Jose'' or ``pizza.'' It also attempts to account for cases where more than one pronunciation may be common in the United States, such as the Spanish name ``Cabrillo'' which might be plausibly pronounced as ``cabreeyo'' or ``cabrillo.'' Double Metaphone addresses exceptions in regular English pronunciation, such as the many cases of silent consonants, such as the silent ``l'' in ``lincoln'' or the silent ``s'' in ``island,'' as well as the pronunciation of ``s'' as ``sh'' in ``sugar,'' or an anomaly like ``caesar,'' an unusual case of a ``c'' followed by an ``a'' where the ``c'' is pronounced as ``s.'' Even with this more detailed treatment, Double Metaphone still misses a number of common exceptions, such as the silent ``p'' in ``receipt,'' many cases where ``ch'' is pronounced as ``k'' instead of ``ch'' as in ``monarch,'' many cases where Americans pronounce words of non-English origin according to their non-English pronunciations, such as ``chutzpah,'' and exceptions such as ``colonel,'' pronounced ``kernal,'' and ``tucson,'' pronounced ``tooson.'' In addition to providing strict adherence to the Double Metaphone algorithm, this Common Lisp implementation also supports an extended-encoding option that activates additional encoding rules that separate the sounds used for ``B'' and ``P,'' for ``D'' and ``T,'' for ``F'' and ``V,'' and for ``S'' and ``Z.'' The extended-encoding option often produces phonetic-code results that are more natural and intuitive. \W\entities \T\clearpage %% ------------------------------------------------------------------------ \begin{functiondoc}{Function}{double-metaphone}{\var{string\/ \nobr{\code{\&optional} \var{extended-p\/}}} \nobr{\returns{} \var{primary-index [, secondary-index]\/}}} \index{string!double-metaphone indexes}% \fnsyntax \fnpurpose Compute the primary and secondary Double Metaphone phonetic-code strings of \var{string}. \fnpackage \code{:gbbopen-tools} \fnmodule \code{:double-metaphone} \fnargs \begin{args}{boolean} \arg[string] A string \arg[extended-p] A \glref{generalized~boolean} (default is \nil) \arg[primary-index] A string \arg[secondary-index] A string \end{args} \fnreturns One or two values: the primary and secondary phonetic-code strings. If there is no secondary code for \var{string}, only the primary string is returned. \fndescription % If \var{extended-p} is \nil{}, strict Double Metaphone encoding is used. If \var{extended-p} is true, additional encoding rules that separate sounds are used for ``B'' and ``P,'' for ``D'' and ``T,'' for ``F'' and ``V,'' and for ``S'' and ``Z.'' \fnexamples % \W\supp \begin{example} > (double-metaphone "testing") "TSTN" > (double-metaphone "Smith") "SM0" "XMT" > (double-metaphone "Schmidt") "XMT" "SMT"\goodpagebreak > (double-metaphone "batboy") "PTP" > (double-metaphone "batboy" 't) "BTB"\goodpagebreak > (double-metaphone "Barlow") "PRL" "PRLF" > (double-metaphone "Barlow" 't) "BRL" "BRLF"\goodpagebreak > (double-metaphone "buzz") "PS" > (double-metaphone "buzz" 't) "BZ" > \end{example} \end{functiondoc} %% ------------------------------------------------------------------------ \T\markright{}% \T\pagestyle{plain} \T\clearpage \W\xname{ref-os-interface-entities} \T\pagestyle{fancy} \T\thispagestyle{fancybottom} \T\global\def\fnlastname{ }% \subsection{OS Interface} \label{sec:os-interface}% \index{module!:os-interface@\code{:os-interface}}% \index{:os-interface@\code{:os-interface} module}% % The \nobr{\code{:os-interface}} \glref{module} provides a uniform interface to commonly used operating-system entities. \W\entities \T\clearpage %% ------------------------------------------------------------------------ \begin{functiondoc}{Function}{browse-hyperdoc}{\var{symbol\/} \nobr{\returns{} \var{boolean\/}}} \index{GBBopen!Hyperdoc!displaying an entity}% \index{Hyperdoc, on line!displaying an entity}% \index{documentation, GBBopen Hyperdoc access}% \fnsyntax \fnpurpose Display the GBBopen Hyperdoc page for \var{symbol\/} in a browser window. \fnpackage \code{:gbbopen-tools} \fnmodule \code{:os-interface} \fnargs \begin{args}{boolean} \arg[symbol] A symbol \arg[boolean] A \glref{generalized~boolean} \end{args} \fnreturns True if the Hyperdoc file associated with \var{symbol\/} is available and has been passed to the preferred browser; no value otherwise. \bfindexit{*preferred-browser*}% \fndescription The desired browser can be specified in \nobr{\code{\entlink{*preferred-browser*}}} (see the discussion in \reflink{GBBopen hyperdoc}{sec:hyperdoc} for details). \begin{alsos}{*preferred-browser*} \also[*preferred-browser*] \end{alsos} \fnexample % \W\supp \begin{example} > (browse-hyperdoc 'standard-event-instance) t > \end{example} \end{functiondoc} %% ------------------------------------------------------------------------ \begin{functiondoc}{Function}{close-external-program-stream}{\var{stream\/}} \index{external-program!closing associated stream}% \index{stream, closing external program}% \fnsyntax \bfindexit{run-external-program}% \fnpurpose Close a stream created by \nobr{\textbf{\entlinknoex{run-external-program}}}. \fnpackage \code{:gbbopen-tools} \fnmodule \code{:os-interface} \fnargs \begin{args}{stream} \arg[stream] The stream to be closed \end{args} \begin{alsos}{run-external-program} \also[run-external-program] \end{alsos} \bfindexit{run-external-program}% \fnexample % \W\supp \begin{example} > (let ((stream (\entlink{run-external-program} "date" nil))) (print (read-line stream)) (close-external-program-stream stream)) "Mon Jul 4 14:06:04 EDT 2005" > \end{example} \end{functiondoc} %% ------------------------------------------------------------------------ \begin{functiondoc}{Function}{kill-external-program}{\var{os-process\/} \nobr{\code{\&optional} \var{signal-number\/}}} \index{external-program!terminating}% \index{external-program!signaling}% \index{signaling an external program}% \index{terminating an external program}% \fnsyntax \fnpurpose Terminate or signal an external program. \fnpackage \code{:gbbopen-tools} \fnmodule \code{:os-interface} \fnargs \begin{args}{signal-number} \arg[os-process] An implementation-dependent process representation or \nil{} \arg[signal-number] A small integer (default is \code{15}, the software termination signal) \end{args} \fnerrors This function is not supported on Windows platforms. \begin{alsos}{run-external-program} \also[run-external-program] \end{alsos} \bfindexit{run-external-program}% \fnexample % \W\supp \begin{example} > (multiple-value-bind (stream os-process) (\entlink{run-external-program} "sleep" '("120")) (sleep 10) (kill-external-program os-process)) t > \end{example} \end{functiondoc} %% ------------------------------------------------------------------------ \begin{functiondoc}{Function}{run-external-program}{\var{program args\/} \nobr{\&key \var{input output wait\/}} \nobr{\returns{} \var{bidirectional-stream, os-process}}} \index{external-program!running}% \index{invoking an external program}% \fnsyntax \fnpurpose Run an external program. \fnpackage \code{:gbbopen-tools} \fnmodule \code{:os-interface} \fnargs \begin{args}{bidirectional-stream} \arg[program] A string specifying the name of the program to be run \arg[args] A list of strings passed to \var{program\/} as arguments \arg[input] A stream specification (default is \nobr{\code{:stream}}, see below) \arg[output] A stream specification (default is \nobr{\code{:stream}}, see below) \arg[wait] A \glref{generalized~boolean} (default is \nil) \arg[bidirectional-stream] A stream or \nil{} \arg[os-process] An implementation-dependent process representation or \nil{} \end{args} \fnreturns Two values: \begin{tightitemize} \item an input, output, or bi-directional stream or \nil{} \item an operating-system process representation, if available, or \nil{} \end{tightitemize} \fnerrors Use of a true value for \var{wait\/} and a \nobr{\code{:stream}} value for \var{input\/} or \var{output\/} is problematic or an error in most Common Lisp implementations. \fndescription The values of \var{input\/} and \var{output\/} can be: \begin{tightitemize} \item \code{:stream} (the default) which creates a stream that is returned as the first result value; if both \var{input\/} and \var{output\/} are specified as \nobr{\code{:stream}}, a bi-directional stream is created and returned \item a string specifying a file to be used as input or output \end{tightitemize} \xsitelink{LispWorks}{http://www.lispworks.com} (non-Windows platforms) and \xsitelink{SBCL}{http://sbcl.sourceforge.net} do not use a search path for locating \var{program}, the full path must be specified in the \var{program\/} string. \begin{alsos}{close-external-program-stream} \also[close-external-program-stream] \end{alsos} \bfindexit{close-external-program-stream}% \fnexample % \W\supp \begin{example} > (let ((stream (run-external-program "date" nil))) (print (read-line stream)) (\entlink{close-external-program-stream} stream)) "Mon Jul 4 14:06:04 EDT 2005" > \end{example} \end{functiondoc} %% ------------------------------------------------------------------------ \begin{functiondoc}{Function}{svn-version}{% \nobr{\code{\&key} \var{directory program\/}} \nobr{\returns{} \var{version-string-or-nil}}} \index{subversion!obtain working-copy version number}% \fnsyntax \fnpurpose Obtain the \xsitelink{Subversion}{http://subversion.tigris.org} compact version number of a working copy. \fnpackage \code{:gbbopen-tools} \fnmodule \code{:os-interface} \fnargs \begin{args}{version-string-or-nil} \arg[directory] One of the following: \begin{tightitemize} \item A string specifying a directory \item A pathname specifying a directory \item A \glref{keyword} naming a \glref{root~directory} \end{tightitemize} (default is the GBBopen install directory) \arg[program] A string specifying the name of the program to be run (default is \nobr{\code{"svnversion"}}) \arg[version-string-or-nil] A string or \nil{} \end{args} \fnreturns A string containing the compact version number or \nil{} if the program \nobr{\code{svnversion}} cannot be found or the specified directory is not in a Subversion working copy. \fndescription % \xsitelink{LispWorks}{http://www.lispworks.com} (non-Windows platforms) and \xsitelink{SBCL}{http://sbcl.sourceforge.net} do not use a search path for locating \var{program}, the full path must be specified in the \var{program\/} string. \fnexamples % \W\supp \begin{example} > (svn-version) "525" > (svn-version :program "/usr/bin/svnversion") "525" > (svn-version :directory ':my-app-root) "73:76M" > \end{example} \end{functiondoc} %% ======================================================================== %% GBBopen Core % Clear subsubentities indicator \W\renewcommand{\subsubentities}{} \T\markright{}% \T\pagestyle{plain} \T\cleardoublepage \W\xname{ref-GBBopen-core-entities} \T\pagestyle{fancy} \T\thispagestyle{fancybottom} \T\global\def\fnlastname{ }% \T\renewcommand{\headrulewidth}{0pt} \section{GBBopen Core} \label{sec:gbbopen-core}% \index{module!:gbbopen-core@\code{:gbbopen-core}}% \index{:gbbopen-core@\code{:gbbopen-core} module}% % The GBBopen Core \glref{module}, \nobr{\code{:gbbopen-core}}, provides support for the \glref{blackboard~repository}, \glref{unit} and \glref{space} classes and instances, inter-instance \glref{links}, and \glref{event} signaling. Documentation for \glref{unit-class} and \glref{unit-instance} entities, as well as general-purpose \nobr{\code{:gbbopen-core}} entities, is \texorhtml{included in this section}{available below}. Documentation for the remaining \nobr{\code{:gbbopen-core}} entities is arranged into the following \texorhtml{sections}{groups}: \begin{tightitemize} \item \refsectionlink{link entities}{sec:links} \item \refsectionlink{event, event function, event printing, and event signaling entities}{sec:events} \item \refsectionlink{interval manipulation entities}{sec:interval} \item \refsectionlink{space-instance and blackboard-rep